Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ffc72b1

Browse files
committedJul 3, 2023
Add Zizm ZM194-D9Y power meter
1 parent 1362318 commit ffc72b1

File tree

3 files changed

+397
-0
lines changed

3 files changed

+397
-0
lines changed
 
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Zizm ZM194-D9Y
2+
3+
This [Enapter Device Blueprint](https://go.enapter.com/marketplace-readme) integrates **Zizm ZM194-D9Y** - 3-Phase Multi-function Power Meter with [ModBus RTU](https://go.enapter.com/developers-enapter-modbus) over [RS-485 communication interface](https://go.enapter.com/developers-enapter-rs485).
4+
5+
## Connect to Enapter
6+
7+
- Sign up to the Enapter Cloud using the [Web](https://cloud.enapter.com/) or mobile app ([iOS](https://apps.apple.com/app/id1388329910), [Android](https://play.google.com/store/apps/details?id=com.enapter&hl=en)).
8+
- Use the [Enapter ENP-RS485](https://go.enapter.com/handbook-enp-rs485) module for physical connection. See [connection instructions](https://go.enapter.com/handbook-enp-rs485-conn) in the module manual.
9+
- [Add ENP-RS485 to your site](https://go.enapter.com/handbook-mobile-app) using the mobile app.
10+
- [Upload](https://go.enapter.com/developers-upload-blueprint) this blueprint to ENP-RS485.
11+
- Use the `Set Up Connection` command in the Enapter mobile or Web app to set up Modbus RTU communication parameters:
12+
- Baudrate;
13+
- Modbus address;
14+
- Parity.
+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
local config = require('enapter.ucm.config')
2+
3+
BAUDRATE = 'baudrate'
4+
ADDRESS = 'address'
5+
PARITY = 'parity'
6+
7+
-- Default RS485 communication interface parameters
8+
DATA_BITS = 8
9+
STOP_BITS = 1
10+
11+
function main()
12+
config.init({
13+
[BAUDRATE] = { type = 'number', required = true, default = 9600 },
14+
[ADDRESS] = { type = 'number', required = true, default = 1 },
15+
[PARITY] = { type = 'string', required = true, default = 'N' },
16+
})
17+
18+
local values, err = config.read_all()
19+
if err then
20+
enapter.log('cannot read config: ' .. tostring(err), 'error')
21+
return nil, 'cannot_read_config'
22+
else
23+
local baudrate, parity = values[BAUDRATE], values[PARITY]
24+
25+
local result = rs485.init(baudrate, DATA_BITS, parity, STOP_BITS)
26+
if result ~= 0 then
27+
enapter.log('RS485 init error: ' .. rs485.err_to_str(result), error, true)
28+
end
29+
end
30+
31+
scheduler.add(30000, send_properties)
32+
scheduler.add(1000, send_telemetry)
33+
end
34+
35+
function send_properties()
36+
enapter.send_properties({
37+
vendor = 'Zizm',
38+
model = 'ZM194-D9Y',
39+
})
40+
end
41+
42+
function send_telemetry()
43+
local telemetry = {}
44+
local status = 'ok'
45+
46+
local all_metrics = {
47+
voltage_a = {
48+
register_address = 0x0000,
49+
register_count = 2,
50+
fn = touint32,
51+
},
52+
voltage_b = {
53+
register_address = 0x0002,
54+
register_count = 2,
55+
fn = touint32,
56+
},
57+
voltage_c = {
58+
register_address = 0x0004,
59+
register_count = 2,
60+
fn = touint32,
61+
},
62+
line_voltage_ab = {
63+
register_address = 0x0006,
64+
register_count = 2,
65+
fn = touint32,
66+
},
67+
line_voltage_bc = {
68+
register_address = 0x0008,
69+
register_count = 2,
70+
fn = touint32,
71+
},
72+
line_voltage_ca = {
73+
register_address = 0x000A,
74+
register_count = 2,
75+
fn = touint32,
76+
},
77+
current_a = {
78+
register_address = 0x000C,
79+
register_count = 2,
80+
fn = touint32,
81+
},
82+
current_b = {
83+
register_address = 0x000E,
84+
register_count = 2,
85+
fn = touint32,
86+
},
87+
current_c = {
88+
register_address = 0x0010,
89+
register_count = 2,
90+
fn = touint32,
91+
},
92+
active_power_a = {
93+
register_address = 0x0012,
94+
register_count = 2,
95+
fn = touint32,
96+
},
97+
active_power_b = {
98+
register_address = 0x0014,
99+
register_count = 2,
100+
fn = touint32,
101+
},
102+
active_power_c = {
103+
register_address = 0x0016,
104+
register_count = 2,
105+
fn = touint32,
106+
},
107+
total_active_power = {
108+
register_address = 0x0018,
109+
register_count = 2,
110+
fn = touint32,
111+
},
112+
reactive_power_a = {
113+
register_address = 0x001A,
114+
register_count = 2,
115+
fn = touint32,
116+
},
117+
reactive_power_b = {
118+
register_address = 0x001C,
119+
register_count = 2,
120+
fn = touint32,
121+
},
122+
reactive_power_c = {
123+
register_address = 0x001E,
124+
register_count = 2,
125+
fn = touint32,
126+
},
127+
total_reactive_power = {
128+
register_address = 0x0020,
129+
register_count = 2,
130+
fn = touint32,
131+
},
132+
frequency = {
133+
register_address = 0x0032,
134+
register_count = 2,
135+
fn = touint32,
136+
},
137+
total_active_electric_energy = {
138+
register_address = 0x0038,
139+
register_count = 2,
140+
fn = touint32,
141+
},
142+
forward_active_electric_energy = {
143+
register_address = 0x003A,
144+
register_count = 2,
145+
fn = touint32,
146+
},
147+
reverse_active_electric_energy = {
148+
register_address = 0x003C,
149+
register_count = 2,
150+
fn = touint32,
151+
},
152+
}
153+
154+
for name, metric in pairs(all_metrics) do
155+
if
156+
not add_to_telemetry(
157+
name,
158+
telemetry,
159+
metric.register_address,
160+
metric.register_count,
161+
metric.fn
162+
)
163+
then
164+
status = 'read_error'
165+
end
166+
end
167+
168+
telemetry['status'] = status
169+
enapter.send_telemetry(telemetry)
170+
end
171+
172+
function add_to_telemetry(metric_name, tbl, register_address, registers_count, fn)
173+
local address, err = config.read(ADDRESS)
174+
if err == nil then
175+
local data, result = modbus.read_holdings(address, register_address, registers_count, 1000)
176+
if data then
177+
tbl[metric_name] = fn(data) / 1000.0 -- coefficient 0.001 for all metrics
178+
else
179+
enapter.log(
180+
'Register ' .. register_address .. ' reading failed: ' .. modbus.err_to_str(result)
181+
)
182+
end
183+
return true
184+
end
185+
return false
186+
end
187+
188+
function touint32(register)
189+
local raw_str =
190+
string.pack('BBBB', register[1] >> 8, register[1] & 0xff, register[2] >> 8, register[2] & 0xff)
191+
return string.unpack('>I2', raw_str)
192+
end
193+
194+
main()
+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
blueprint_spec: device/1.0
2+
display_name: Zizm ZM194-D9Y
3+
description: 3-Phase Multi-function Power Meter.
4+
icon: enapter-power-meter
5+
vendor: zizm
6+
author: enapter
7+
support:
8+
url: https://go.enapter.com/enapter-blueprint-support
9+
email: support@enapter.com
10+
license: MIT
11+
verification_level: verified
12+
13+
communication_module:
14+
product: ENP-RS485
15+
lua:
16+
file: firmware.lua
17+
dependencies:
18+
- enapter-ucm
19+
20+
properties:
21+
vendor:
22+
type: string
23+
display_name: Vendor
24+
model:
25+
type: string
26+
display_name: Model
27+
28+
telemetry:
29+
status:
30+
display_name: Modbus status
31+
type: string
32+
enum:
33+
- ok
34+
- read_error
35+
total_active_power:
36+
type: float
37+
unit: kwatt
38+
display_name: Total Active Power
39+
total_active_electric_energy:
40+
type: float
41+
unit: kwatth
42+
display_name: Total Active Electric Energy
43+
active_power_a:
44+
type: float
45+
unit: kwatt
46+
display_name: Active Power A
47+
active_power_b:
48+
type: float
49+
unit: watt
50+
display_name: Active Power B
51+
active_power_c:
52+
type: float
53+
unit: kwatt
54+
display_name: Active Power C
55+
voltage_a:
56+
type: float
57+
unit: volt
58+
display_name: Phase A Voltage
59+
voltage_b:
60+
type: float
61+
unit: volt
62+
display_name: Phase B Voltage
63+
voltage_c:
64+
type: float
65+
unit: volt
66+
display_name: Phase C Voltage
67+
line_voltage_ab:
68+
type: float
69+
unit: volt
70+
display_name: Line Voltage AB
71+
line_voltage_bc:
72+
type: float
73+
unit: volt
74+
display_name: Line Voltage BC
75+
line_voltage_ca:
76+
type: float
77+
unit: volt
78+
display_name: Line Voltage CA
79+
current_a:
80+
type: float
81+
unit: amp
82+
display_name: Phase A Current
83+
current_b:
84+
type: float
85+
unit: amp
86+
display_name: Phase B Current
87+
current_c:
88+
type: float
89+
unit: amp
90+
display_name: Phase C Current
91+
frequency:
92+
type: float
93+
unit: hertz
94+
display_name: Frequency
95+
total_reactive_power:
96+
type: float
97+
unit: watt
98+
display_name: Total Reactive Power
99+
reactive_power_a:
100+
type: float
101+
unit: watt
102+
display_name: Reactive Power A
103+
reactive_power_b:
104+
type: float
105+
unit: watt
106+
display_name: Reactive Power B
107+
reactive_power_c:
108+
type: float
109+
unit: watt
110+
display_name: Reactive Power C
111+
forward_active_electric_energy:
112+
type: float
113+
unit: kwatth
114+
display_name: Forward Active Electric Energy
115+
reverse_active_electric_energy:
116+
type: float
117+
unit: kwatth
118+
display_name: Reverse Active Electric Energy
119+
120+
command_groups:
121+
connection:
122+
display_name: Connection
123+
124+
commands:
125+
# TODO: mark commands containing secrets
126+
write_configuration:
127+
display_name: Set Up Connection
128+
description: Set Modbus RTU connection
129+
group: connection
130+
populate_values_command: read_configuration
131+
ui:
132+
icon: file-document-edit-outline
133+
arguments:
134+
baudrate:
135+
display_name: Baudrate
136+
type: number
137+
required: true
138+
enum:
139+
- 2400
140+
- 4800
141+
- 9600
142+
address:
143+
display_name: Modbus address
144+
type: number
145+
required: true
146+
min: 1
147+
max: 247
148+
parity:
149+
display_name: Parity
150+
type: string
151+
required: true
152+
enum:
153+
- N
154+
- E
155+
- O
156+
read_configuration:
157+
display_name: Read Connection Parameters
158+
group: connection
159+
ui:
160+
icon: file-check-outline
161+
.cloud:
162+
category: power_meters
163+
mobile_main_chart: total_active_power
164+
mobile_telemetry:
165+
- total_active_electric_energy
166+
- total_active_power
167+
- active_power_a
168+
- active_power_b
169+
- active_power_c
170+
- voltage_a
171+
- voltage_b
172+
- voltage_c
173+
- current_a
174+
- current_b
175+
- current_c
176+
- frequency
177+
mobile_charts:
178+
- total_active_electric_energy
179+
- total_active_power
180+
- active_power_a
181+
- active_power_b
182+
- active_power_c
183+
- voltage_a
184+
- voltage_b
185+
- voltage_c
186+
- current_a
187+
- current_b
188+
- current_c
189+
- frequency

0 commit comments

Comments
 (0)
Please sign in to comment.