pzem016 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +0 -0
- data/PZEM016-bench.jpg +0 -0
- data/README.md +102 -0
- data/Rakefile +4 -0
- data/exe/pzem016.rb +139 -0
- data/lib/pzem016/pzem016.rb +182 -0
- data/lib/pzem016/version.rb +5 -0
- data/lib/pzem016.rb +11 -0
- data/sampleoutput.png +0 -0
- data/sig/pzem016.rbs +4 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '030915a891a9651cde14fcecdca0c8aec9683b3a58fbe36d20913ac5e4603935'
|
4
|
+
data.tar.gz: b1d4db0b9982a05e173420f63056272ef298eee1bbf3b01a120800589785c50a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 72d7704b3335514d3c011c2211022b676c4dd5f5764a4a5a581835fdf714c175b0c5bdc7cbe09b9fc11a2410528f77e09487b18d669304f36654df6a279c96a2
|
7
|
+
data.tar.gz: 26eeb29d6d1893b83145d791d1c0241af11cacf9679d2878d207732be418713935bbcc15e8489fb9fc0a54f00141b2dbc26d96051a5911bcc26ed6c27cfa995d
|
data/CHANGELOG
ADDED
File without changes
|
data/PZEM016-bench.jpg
ADDED
Binary file
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Pzem016
|
2
|
+
|
3
|
+
Pzem016 is some Ruby support for some very cheap but decent power monitors you can get from AliExpress
|
4
|
+
|
5
|
+
These things: https://www.aliexpress.com/w/wholesale-pzem%2525252d016.html?spm=a2g0o.best.search.0
|
6
|
+
|
7
|
+
This gem provides a library to wrap some of the modbus details, and a cli so you can interact
|
8
|
+
with them right away without having to write code.
|
9
|
+
|
10
|
+
You'll need an RS-485 adapter of some sort - I have had good luck with https://www.amazon.com/dp/B076WVFXN8?ref=ppx_yo2ov_dt_b_product_details&th=1
|
11
|
+
|
12
|
+
Wiring is very simple. For a single point to point it's just A<->A, B<->B, GND<->GND. You can have more than one node on the bus. If you intend
|
13
|
+
to do that you'll need to look at doing some impedance matching with terminating resistors at both ends.
|
14
|
+
|
15
|
+
![RS-485 wiring](PZEM016-bench.jpg)
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
20
|
+
|
21
|
+
Install the gem and add to the application's Gemfile by executing:
|
22
|
+
|
23
|
+
$ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
24
|
+
|
25
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
26
|
+
|
27
|
+
$ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Library documentation is here: [TODO]
|
32
|
+
|
33
|
+
Example of output:
|
34
|
+
![sample usage](sampleoutput.png)
|
35
|
+
|
36
|
+
The command line tool's cli syntax uses subcommands:
|
37
|
+
|
38
|
+
```
|
39
|
+
pzem016.rb --help
|
40
|
+
PZEM-016 power measurement module utility.
|
41
|
+
|
42
|
+
Syntax: pzem016.rb [global options] <command> [options]
|
43
|
+
|
44
|
+
Commands: ["read", "readconfig", "setconfig", "resetenergy", "scanbus"]
|
45
|
+
|
46
|
+
Global options:
|
47
|
+
-p, --port=<s> Serial port (default: /dev/ttyUSB0)
|
48
|
+
-s, --speed=<i> Port speed (default: 9600)
|
49
|
+
-t, --timeout=<i> Retry timeout (default: 1)
|
50
|
+
-r, --retries=<i> Number of times to retry ModBus command (default: 1)
|
51
|
+
-n, --name=<s> Device name (default: PZEM-016 Device)
|
52
|
+
-d, --debug Extra noise
|
53
|
+
-h, --help Show this message
|
54
|
+
```
|
55
|
+
|
56
|
+
```
|
57
|
+
pzem016.rb read --help
|
58
|
+
Read power values from specified device
|
59
|
+
-s, --sladdr=<i> Slave address (default: 1)
|
60
|
+
-j, --json Output JSON
|
61
|
+
-h, --help Show this message
|
62
|
+
```
|
63
|
+
|
64
|
+
```
|
65
|
+
pzem016.rb readconfig --help
|
66
|
+
Read config values from specified device
|
67
|
+
-s, --sladdr=<i> Slave address (default: 1)
|
68
|
+
-j, --json Output JSON
|
69
|
+
-h, --help Show this message
|
70
|
+
```
|
71
|
+
|
72
|
+
```
|
73
|
+
pzem016.rb setconfig --help
|
74
|
+
Set device address and/or alarm threshold: pzem016.rb setconfig <addr|alarm> <value>
|
75
|
+
-s, --sladdr=<i> Slave address (default: 1)
|
76
|
+
-h, --help Show this message
|
77
|
+
```
|
78
|
+
|
79
|
+
```
|
80
|
+
pzem016.rb resetenergy --help
|
81
|
+
Reset (clear) the energy counter (KWH) on the specified device
|
82
|
+
-s, --sladdr=<i> Slave address (default: 1)
|
83
|
+
-h, --help Show this message
|
84
|
+
```
|
85
|
+
|
86
|
+
```
|
87
|
+
pzem016.rb scanbus --help
|
88
|
+
Scan ModBus for nodes/addrs
|
89
|
+
-r, --read Try to read values when node is found
|
90
|
+
-h, --help Show this message
|
91
|
+
```
|
92
|
+
|
93
|
+
|
94
|
+
## Development
|
95
|
+
|
96
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
97
|
+
|
98
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
99
|
+
|
100
|
+
## Contributing
|
101
|
+
|
102
|
+
Bug reports and pull requests are welcome on GitLab at https://gitlab.com/svdasein/pzem016
|
data/Rakefile
ADDED
data/exe/pzem016.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/pzem016'
|
5
|
+
require 'optimist'
|
6
|
+
require 'ruby-progressbar'
|
7
|
+
|
8
|
+
progname = File.basename($PROGRAM_NAME)
|
9
|
+
commands = %w[read readconfig setconfig resetenergy scanbus]
|
10
|
+
|
11
|
+
global_opts = Optimist.options do
|
12
|
+
banner "PZEM-016 power measurement module utility.\n\nSyntax: #{progname} [global options] <command> [options]\n\nCommands: #{commands}\n\nGlobal options:"
|
13
|
+
opt :port, 'Serial port', type: :string, default: '/dev/ttyUSB0'
|
14
|
+
opt :speed, 'Port speed', type: :integer, default: 9600
|
15
|
+
opt :timeout, 'Retry timeout', type: :integer, default: 1
|
16
|
+
opt :retries, 'Number of times to retry ModBus command', default: 1
|
17
|
+
opt :name, 'Device name', type: :string, default: 'PZEM-016 Device'
|
18
|
+
opt :debug, 'Extra noise', type: :boolean
|
19
|
+
stop_on commands
|
20
|
+
end
|
21
|
+
|
22
|
+
cmd = ARGV.empty? ? '(not given)' : ARGV.shift.downcase.to_sym
|
23
|
+
|
24
|
+
cmd_opts = case cmd
|
25
|
+
when :read, :readconfig # parse delete options
|
26
|
+
Optimist.options do
|
27
|
+
banner "Read #{cmd == :read ? "power" : "config"} values from specified device"
|
28
|
+
opt :sladdr, 'Slave address', type: :integer, default: 1
|
29
|
+
opt :json, 'Output JSON', type: :boolean, default: false
|
30
|
+
end
|
31
|
+
when :setconfig
|
32
|
+
opts = Optimist.options do
|
33
|
+
banner "Set device address and/or alarm threshold: #{progname} setconfig <addr|alarm> <value>"
|
34
|
+
opt :sladdr, 'Slave address', type: :integer, default: 1
|
35
|
+
end
|
36
|
+
if ARGV.size == 2
|
37
|
+
setting = ARGV.shift.downcase.to_sym
|
38
|
+
Optimist.die "Specify one of 'addr' or 'alarm'; you gave '#{setting}'" unless %i[addr alarm].include?(setting)
|
39
|
+
value = ARGV.shift.to_i
|
40
|
+
else
|
41
|
+
Optimist.die "syntax #{progname} setconfig <addr|alarm> <value>"
|
42
|
+
end
|
43
|
+
opts
|
44
|
+
when :resetenergy
|
45
|
+
Optimist.options do
|
46
|
+
banner 'Reset (clear) the energy counter (KWH) on the specified device'
|
47
|
+
opt :sladdr, 'Slave address', type: :integer, default: 1
|
48
|
+
end
|
49
|
+
when :scanbus
|
50
|
+
Optimist.options do
|
51
|
+
banner 'Scan ModBus for nodes/addrs'
|
52
|
+
opt :read, 'Try to read values when node is found', type: :boolean
|
53
|
+
end
|
54
|
+
else
|
55
|
+
puts "Valid commands: #{commands}"
|
56
|
+
Optimist.die "unknown command: #{cmd}"
|
57
|
+
end
|
58
|
+
|
59
|
+
if global_opts[:debug]
|
60
|
+
puts "Global options: #{global_opts.inspect}"
|
61
|
+
puts "Subcommand: #{cmd.inspect}"
|
62
|
+
puts "Subcommand options: #{cmd_opts.inspect}"
|
63
|
+
puts "Remaining arguments: #{ARGV.inspect}"
|
64
|
+
end
|
65
|
+
|
66
|
+
bus = ModBus::RTUClient.connect(global_opts[:port], global_opts[:speed])
|
67
|
+
|
68
|
+
begin
|
69
|
+
case cmd
|
70
|
+
when :read
|
71
|
+
bus.with_slave(cmd_opts[:sladdr]).tap do |slave|
|
72
|
+
slave.read_retry_timeout = global_opts[:timeout]
|
73
|
+
slave.read_retries = global_opts[:retries]
|
74
|
+
input = Pzem016::InputRegisters.new(global_opts[:name], slave)
|
75
|
+
input.read
|
76
|
+
if cmd_opts[:json]
|
77
|
+
puts input.to_json
|
78
|
+
else
|
79
|
+
input.report
|
80
|
+
end
|
81
|
+
end
|
82
|
+
when :readconfig
|
83
|
+
bus.with_slave(cmd_opts[:sladdr]).tap do |slave|
|
84
|
+
slave.read_retry_timeout = global_opts[:timeout]
|
85
|
+
slave.read_retries = global_opts[:retries]
|
86
|
+
holding = Pzem016::HoldingRegisters.new(global_opts[:name], slave)
|
87
|
+
holding.read
|
88
|
+
if cmd_opts[:json]
|
89
|
+
puts holding.to_json
|
90
|
+
else
|
91
|
+
holding.report
|
92
|
+
end
|
93
|
+
end
|
94
|
+
when :setconfig
|
95
|
+
slave = bus.with_slave(cmd_opts[:sladdr])
|
96
|
+
slave.read_retry_timeout = global_opts[:timeout]
|
97
|
+
slave.read_retries = global_opts[:retries]
|
98
|
+
device = Pzem016::HoldingRegisters.new(global_opts[:name], slave)
|
99
|
+
case setting
|
100
|
+
when :addr
|
101
|
+
device.set_address(value)
|
102
|
+
puts "Address of slave at '#{cmd_opts[:sladdr]}' has been changed to '#{value}'"
|
103
|
+
when :alarm
|
104
|
+
device.set_alarm(value)
|
105
|
+
puts "Alarm threshold value for slave at #{cmd_opts[:sladdr]} has been set to #{value} watts"
|
106
|
+
end
|
107
|
+
when :resetenergy
|
108
|
+
puts "Slave at addr #{cmd_opts[:sladdr]} energy counter reset: #{Pzem016::HoldingRegisters.new(global_opts[:name],
|
109
|
+
bus.with_slave(cmd_opts[:sladdr])).reset_energy}"
|
110
|
+
when :scanbus
|
111
|
+
begin
|
112
|
+
(1..247).each do |address|
|
113
|
+
bus.with_slave(address) do |slave|
|
114
|
+
slave.read_retry_timeout = global_opts[:timeout]
|
115
|
+
slave.read_retries = global_opts[:retries]
|
116
|
+
begin
|
117
|
+
value = slave.read_holding_registers(0, 3)
|
118
|
+
puts "\nDevice found at address #{value[2]}\n"
|
119
|
+
if cmd_opts[:read]
|
120
|
+
input = Pzem016::InputRegisters.new(global_opts[:name], slave)
|
121
|
+
input.read
|
122
|
+
input.report
|
123
|
+
puts
|
124
|
+
end
|
125
|
+
rescue StandardError
|
126
|
+
print '.'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
puts "\n"
|
131
|
+
rescue Interrupt
|
132
|
+
puts "\nscan interrupted\n"
|
133
|
+
end
|
134
|
+
else
|
135
|
+
puts "Command required, one of #{commands}"
|
136
|
+
end
|
137
|
+
rescue ModBus::Errors::ModBusTimeout
|
138
|
+
puts 'ModBus timed out - are you sure you specified the correct --sladdr?'
|
139
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# This module is a container for a few classes that wrap a bunch
|
5
|
+
# of ModBus related stuff
|
6
|
+
#
|
7
|
+
module Pzem016
|
8
|
+
require 'json'
|
9
|
+
require 'awesome_print'
|
10
|
+
|
11
|
+
##
|
12
|
+
# Some abstract behavior for the register parser classes
|
13
|
+
#
|
14
|
+
class ModbusRegisters
|
15
|
+
attr_reader :raw, :slave
|
16
|
+
|
17
|
+
##
|
18
|
+
# This takes two params: name and slave. Name is a descriptive string
|
19
|
+
# for the slave. Slave is an instance of a ModBus::RTUClient slave
|
20
|
+
# that you've previously set up.
|
21
|
+
#
|
22
|
+
def initialize(name, slave)
|
23
|
+
@slave = slave
|
24
|
+
@name = name
|
25
|
+
@raw = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Stub for read logic
|
30
|
+
#
|
31
|
+
def read
|
32
|
+
@raw = []
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Simple basic behavior for turning the data read into a hash
|
37
|
+
#
|
38
|
+
def to_hash
|
39
|
+
{ raw: @raw }
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Returns the sample data as a json string
|
44
|
+
#
|
45
|
+
def to_json(*_args)
|
46
|
+
to_hash.to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Outputs a pretty dump of the readings to STDOUT
|
51
|
+
#
|
52
|
+
def report
|
53
|
+
ap to_hash
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Parsing logic for the "holding registers", also
|
59
|
+
# known as read/write. PZEM-016 is configured via these
|
60
|
+
#
|
61
|
+
class HoldingRegisters < ModbusRegisters
|
62
|
+
##
|
63
|
+
# Specific holding register read logic for PZEM-016
|
64
|
+
#
|
65
|
+
def read
|
66
|
+
@raw = @slave.holding_registers[0..6]
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Sets the address of the slave to the new address addr
|
71
|
+
#
|
72
|
+
def set_address(addr)
|
73
|
+
@slave.write_single_register(2, addr)
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Sets the alarm threshold to the given number of watts
|
78
|
+
def set_alarm(watts)
|
79
|
+
@slave.write_single_register(1, watts)
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Clears / resets the KWH (energy) counter on the PZEM-016
|
84
|
+
#
|
85
|
+
def reset_energy
|
86
|
+
@slave.query("\x42")
|
87
|
+
rescue ModBus::Errors::IllegalFunction
|
88
|
+
# the units respond with an error but in fact do reset the counter
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Specific logic for generating a hash of the holding registers in a PZEM-016
|
94
|
+
#
|
95
|
+
def to_hash
|
96
|
+
{
|
97
|
+
"DeviceName": @name,
|
98
|
+
"Address": @raw[2],
|
99
|
+
"AlarmWatts": @raw[1]
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Parsing logic for the "input registers", also
|
106
|
+
# known as readonly. This is where the sample data
|
107
|
+
# shows up
|
108
|
+
#
|
109
|
+
class InputRegisters < ModbusRegisters
|
110
|
+
##
|
111
|
+
# Specific input register read logic for PZEM-016
|
112
|
+
#
|
113
|
+
def read
|
114
|
+
@raw = @slave.input_registers[0..9]
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Extracts measured volts from the sample data
|
119
|
+
#
|
120
|
+
def volts
|
121
|
+
(@raw[0] * 0.1).round(3)
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Extracts measured amps from the sample data
|
126
|
+
#
|
127
|
+
def amps
|
128
|
+
(((@raw[2] << 16) | @raw[1]) * 0.001).round(3)
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Extracts measured watts from the sample data
|
133
|
+
#
|
134
|
+
def watts
|
135
|
+
(((@raw[4] << 16) | @raw[3]) * 0.1).round(3)
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# Extracts cumulative watt-hours from the sample data
|
140
|
+
#
|
141
|
+
def wattHours
|
142
|
+
(((@raw[6] << 16) | @raw[5]) * 0.1).round(3)
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# Extracts measured frequency from the sample data
|
147
|
+
#
|
148
|
+
def hz
|
149
|
+
(@raw[7] * 0.1).round(3)
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Extracts measured power factor from the sample data
|
154
|
+
#
|
155
|
+
def powerFactor
|
156
|
+
(@raw[8] * 0.01).round(3)
|
157
|
+
end
|
158
|
+
|
159
|
+
##
|
160
|
+
# Returns true of power consumption has reached the alarm number of watts
|
161
|
+
#
|
162
|
+
def alarm?
|
163
|
+
@raw[9] == 0xFFFF
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Specific logic for generating a hash of the input registers in a PZEM-016
|
168
|
+
#
|
169
|
+
def to_hash
|
170
|
+
{
|
171
|
+
"DeviceName": @name,
|
172
|
+
"Volts": volts,
|
173
|
+
"Amps": amps,
|
174
|
+
"Watts": watts,
|
175
|
+
"WH": wattHours,
|
176
|
+
"HZ": hz,
|
177
|
+
"PF": powerFactor,
|
178
|
+
"Alarm": alarm?
|
179
|
+
}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
data/lib/pzem016.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rmodbus'
|
4
|
+
require 'pry' if ENV['RUBY_ENV'] == 'development'
|
5
|
+
require_relative 'pzem016/version'
|
6
|
+
require_relative 'pzem016/pzem016'
|
7
|
+
|
8
|
+
module Pzem016
|
9
|
+
class Error < StandardError; end
|
10
|
+
# Your code goes here...
|
11
|
+
end
|
data/sampleoutput.png
ADDED
Binary file
|
data/sig/pzem016.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pzem016
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dave Parker
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-03-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: awesome_print
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: optimist
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rmodbus
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: ruby-progressbar
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: PZEM-016 is a cheap power monitoring thing you can get from aliexpress
|
70
|
+
for usually very little money https://www.aliexpress.com/w/wholesale-pzem%2525252d016.html?spm=a2g0o.best.search.0. This
|
71
|
+
gem provides a library to talk to them with and some cli utils
|
72
|
+
email:
|
73
|
+
- dparker@svdasein.org
|
74
|
+
executables:
|
75
|
+
- pzem016.rb
|
76
|
+
extensions: []
|
77
|
+
extra_rdoc_files: []
|
78
|
+
files:
|
79
|
+
- CHANGELOG
|
80
|
+
- PZEM016-bench.jpg
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- exe/pzem016.rb
|
84
|
+
- lib/pzem016.rb
|
85
|
+
- lib/pzem016/pzem016.rb
|
86
|
+
- lib/pzem016/version.rb
|
87
|
+
- sampleoutput.png
|
88
|
+
- sig/pzem016.rbs
|
89
|
+
homepage: https://gitlab.com/svdasein/pzem016
|
90
|
+
licenses: []
|
91
|
+
metadata:
|
92
|
+
allowed_push_host: https://rubygems.org
|
93
|
+
source_code_uri: https://gitlab.com/svdasein/pzem016
|
94
|
+
changelog_uri: https://gitlab.com/svdasein/pzem016/-/blob/master/CHANGELOG
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.0.0
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.5.7
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Library and cli utils to interact with PZEM-016 power monitoring units
|
114
|
+
test_files: []
|