Skip to content

Commit c8db597

Browse files
committed
Shelly Pro 3EM, EM-50 and 3CT63 support for dbus-modbus-client 1.58+
1 parent c2fbd6f commit c8db597

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

dbus-modbus-client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import ev_charger
3535
import smappee
3636
import victron_em
37+
import shelly
3738

3839
import logging
3940
log = logging.getLogger()

shelly.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import device
2+
import probe
3+
from register import *
4+
5+
# This Python script adds support for Modbus enabled Shelly devices in dbus-modbus-client version 1.58 and later.
6+
#
7+
8+
# This is just a helper class to make life a bit easier with the Modbus registers.
9+
#
10+
class Reg_shelly(Reg_f32l):
11+
def __init__(self, base, name=None, scale=1, text=None, write=False, invalid=[], **kwargs):
12+
super().__init__(base - 30000, name, scale, text, write, invalid, **kwargs)
13+
14+
# Shelly Pro 3EM
15+
# https://shelly-api-docs.shelly.cloud/gen2/Devices/Gen2/ShellyPro3EM
16+
#
17+
# Triphase (defualt)
18+
# https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/EM/
19+
# https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/EMData/
20+
#
21+
# Monophase
22+
# https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/EM1/
23+
# https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/EM1Data/
24+
#
25+
# Modbus
26+
# https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Modbus
27+
#
28+
class Shelly_Pro_Meter(device.CustomName, device.EnergyMeter):
29+
vendor_id = 'shelly'
30+
vendor_name = 'Shelly'
31+
min_timeout = 0.5
32+
33+
# Shelly uses input registers!
34+
default_access = 'input'
35+
36+
# Subclasses must set the following three properties!
37+
# productname
38+
# productmodel
39+
# productid
40+
41+
def device_init(self):
42+
self.info_regs = [
43+
Reg_text(0, 6, '/Serial', little=True),
44+
]
45+
46+
if self.monophase():
47+
# As far as I can tell there is no elegant way of mapping Shelly Pro 3EM's Monophase profile. Shelly
48+
# has modeled the Monophase profile as three virtual devices under the same IP:Port whereas
49+
# dbus-modbus-client makes the strong assumption that an IP:Port is an unique identifier for a single
50+
# device. Our only option is to go truly Monophase and disregard the Phase B and C meters. *shrug*
51+
#
52+
nr_phases = 1
53+
54+
self.data_regs += [
55+
Reg_shelly(32302, '/Ac/Energy/Forward', 1000, '%.1f kWh'),
56+
Reg_shelly(32304, '/Ac/Energy/Reverse', 1000, '%.1f kWh'),
57+
Reg_shelly(32007, '/Ac/Power', 1, '%.1f W'),
58+
59+
Reg_shelly(32003, '/Ac/L1/Voltage', 1, '%.1f V'),
60+
Reg_shelly(32005, '/Ac/L1/Current', 1, '%.1f A'),
61+
Reg_shelly(32310, '/Ac/L1/Energy/Forward', 1000, '%.1f kWh'),
62+
Reg_shelly(32312, '/Ac/L1/Energy/Reverse', 1000, '%.1f kWh'),
63+
Reg_shelly(32007, '/Ac/L1/Power', 1, '%.1f W'),
64+
]
65+
66+
else:
67+
# Triphase (default)
68+
#
69+
nr_phases = 3
70+
71+
self.data_regs += [
72+
Reg_shelly(31162, '/Ac/Energy/Forward', 1000, '%.1f kWh'),
73+
Reg_shelly(31164, '/Ac/Energy/Reverse', 1000, '%.1f kWh'),
74+
Reg_shelly(31013, '/Ac/Power', 1, '%.1f W'),
75+
76+
Reg_shelly(31020, '/Ac/L1/Voltage', 1, '%.1f V'),
77+
Reg_shelly(31022, '/Ac/L1/Current', 1, '%.1f A'),
78+
Reg_shelly(31182, '/Ac/L1/Energy/Forward', 1000, '%.1f kWh'),
79+
Reg_shelly(31184, '/Ac/L1/Energy/Reverse', 1000, '%.1f kWh'),
80+
Reg_shelly(31024, '/Ac/L1/Power', 1, '%.1f W'),
81+
82+
Reg_shelly(31040, '/Ac/L2/Voltage', 1, '%.1f V'),
83+
Reg_shelly(31042, '/Ac/L2/Current', 1, '%.1f A'),
84+
Reg_shelly(31202, '/Ac/L2/Energy/Forward', 1000, '%.1f kWh'),
85+
Reg_shelly(31204, '/Ac/L2/Energy/Reverse', 1000, '%.1f kWh'),
86+
Reg_shelly(31044, '/Ac/L2/Power', 1, '%.1f W'),
87+
88+
Reg_shelly(31060, '/Ac/L3/Voltage', 1, '%.1f V'),
89+
Reg_shelly(31062, '/Ac/L3/Current', 1, '%.1f A'),
90+
Reg_shelly(31222, '/Ac/L3/Energy/Forward', 1000, '%.1f kWh'),
91+
Reg_shelly(31224, '/Ac/L3/Energy/Reverse', 1000, '%.1f kWh'),
92+
Reg_shelly(31064, '/Ac/L3/Power', 1, '%.1f W'),
93+
]
94+
95+
#
96+
# Returns true if the Shelly Pro appears to run in the Monophase profile.
97+
#
98+
def monophase(self):
99+
try:
100+
self.read_register(Reg_shelly(32000))
101+
return True
102+
except Exception as err:
103+
self.log.info("The device appears to be in Triphase (default) mode.", err)
104+
return False
105+
106+
# Shelly Pro 3EM
107+
# https://www.shelly.com/products/shelly-pro-3em-x1
108+
#
109+
class Shelly_Pro_3EM(Shelly_Pro_Meter):
110+
productname = 'Shelly Pro 3EM'
111+
productmodel = 'SPEM-003CEBEU'
112+
# P120
113+
productid = 0x50313230
114+
115+
# Shelly Pro EM-50
116+
# https://www.shelly.com/products/shelly-pro-em-50
117+
#
118+
class Shelly_Pro_EM50(Shelly_Pro_Meter):
119+
productname = 'Shelly Pro EM-50'
120+
productmodel = 'SPEM-002CEBEU50'
121+
# P050
122+
productid = 0x50303530
123+
124+
# Shelly Pro 3EM 3CT63
125+
# https://www.shelly.com/products/shelly-pro-3em-3ct63
126+
#
127+
class Shelly_Pro_3EM_3CT63(Shelly_Pro_Meter):
128+
productname = 'Shelly Pro 3EM 3CT63'
129+
productmodel = 'SPEM-003CEBEU63'
130+
# P063
131+
productid = 0x50303633
132+
133+
models = {
134+
Shelly_Pro_3EM.productmodel: {
135+
'model': Shelly_Pro_3EM.productmodel,
136+
'handler': Shelly_Pro_3EM,
137+
},
138+
Shelly_Pro_EM50.productmodel: {
139+
'model': Shelly_Pro_EM50.productmodel,
140+
'handler': Shelly_Pro_EM50,
141+
},
142+
Shelly_Pro_3EM_3CT63.productmodel: {
143+
'model': Shelly_Pro_3EM_3CT63.productmodel,
144+
'handler': Shelly_Pro_3EM_3CT63,
145+
},
146+
}
147+
148+
probe.add_handler(probe.ModelRegister(Reg_text(6, 10, 'model', little=True), models,
149+
methods=['tcp'],
150+
units=[1]))

0 commit comments

Comments
 (0)