165 lines
5.9 KiB
Python
165 lines
5.9 KiB
Python
#!/usr/bin/env python
|
|
"""
|
|
Hiking DDS238-2 ZN/S Energy Meter
|
|
Author: Xavier Beaudouin
|
|
Requirements:
|
|
1. modbus over TCP adapter like PW21
|
|
2. pymodbus AND pymodbusTCP
|
|
"""
|
|
"""
|
|
<plugin key="DS238_ModbusTCP" name="DS238-2 D/ZN ModbusTCP" author="Xavier Beaudouin" version="0.0.1" externallink="https://github.com/xbeaudouin/domoticz-ds238-modbus-tcp">
|
|
<params>
|
|
<param field="Address" label="IP Address" width="150px" required="true" />
|
|
<param field="Port" label="Port Number" width="100px" required="true" default="502" />
|
|
<param field="Mode1" label="Add missing devices" width="100px" required="true" default="Yes" >
|
|
<options>
|
|
<option label="Yes" value="Yes" default="true" />
|
|
<option label="No" value="No" />
|
|
</options>
|
|
</param>
|
|
<param field="Mode3" label="Modbus address" width="100px" required="true" default="1" />
|
|
<param field="Mode6" label="Debug" width="100px">
|
|
<options>
|
|
<option label="True" value="Debug"/>
|
|
<option label="False" value="Normal" default="true" />
|
|
</options>
|
|
</param>
|
|
</params>
|
|
</plugin>
|
|
"""
|
|
|
|
import Domoticz
|
|
import sys
|
|
|
|
sys.path.append('/usr/local/lib/python3.4/dist-packages')
|
|
sys.path.append('/usr/local/lib/python3.5/dist-packages')
|
|
sys.path.append('/usr/local/lib/python3.6/dist-packages')
|
|
sys.path.append('/usr/local/lib/python3.7/dist-packages')
|
|
sys.path.append('/usr/local/lib/python3.8/dist-packages')
|
|
|
|
import pymodbus
|
|
|
|
from pyModbusTCP.client import ModbusClient
|
|
from pymodbus.constants import Endian
|
|
from pymodbus.payload import BinaryPayloadDecoder
|
|
|
|
class BasePlugin:
|
|
#enabled = False
|
|
def __init__(self):
|
|
return
|
|
|
|
def onStart(self):
|
|
try:
|
|
Domoticz.Log("DS238-2 ZN/S Energy Meter TCP loaded!, using python v" + sys.version[:6] + " and pymodbus v" + pymodbus.__version__)
|
|
except:
|
|
Domoticz.Log("DS238-2 ZN/S Energy Meter TCP loaded!")
|
|
|
|
# Check dependancies
|
|
try:
|
|
if (float(Parameters["DomoticzVersion"][:6]) < float("2020.2")): Domoticz.Error("WARNING: Domoticz version is outdated or not supported. Please update!")
|
|
if (float(sys.version[:1]) < 3): Domoticz.Error("WARNING: Python3 should be used !")
|
|
if (float(pymodbus.__version__[:3]) < float("2.3")): Domoticz.Error("WARNING: pymodbus version is outdated, please update!")
|
|
except:
|
|
Domoticz.Error("Warning ! Dependancies could not be checked !")
|
|
|
|
Domoticz.Log("Started !")
|
|
# Parse parameters
|
|
|
|
# Debug
|
|
if Parameters["Mode6"] == "Debug":
|
|
Domoticz.Debugging(1)
|
|
else:
|
|
Domoticz.Debugging(0)
|
|
|
|
self.IPAddress = Parameters["Address"]
|
|
self.IPPort = Parameters["Port"]
|
|
if Parameters["Mode1"] == "1":
|
|
self.AddMissing = 1
|
|
else:
|
|
self.AddMissing = 0
|
|
|
|
self.MBAddr = int(Parameters["Mode3"])
|
|
|
|
Domoticz.Debug("Query IP " + self.IPAddress + ":" + str(self.IPPort) +" on device : "+str(self.MBAddr))
|
|
|
|
# Create the Domoticz.Devices() here.
|
|
|
|
|
|
def onStop(self):
|
|
Domoticz.Log("onStop called")
|
|
|
|
def onConnect(self, Connection, Status, Description):
|
|
Domoticz.Log("onConnect called")
|
|
|
|
def onMessage(self, Connection, Data):
|
|
Domoticz.Log("onMessage called")
|
|
|
|
def onCommand(self, Unit, Command, Level, Hue):
|
|
Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
|
|
|
|
def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
|
|
Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)
|
|
|
|
def onDisconnect(self, Connection):
|
|
Domoticz.Log("onDisconnect called")
|
|
|
|
def onHeartbeat(self):
|
|
Domoticz.Log("onHeartbeat called")
|
|
Domoticz.Debug(" Interface : IP="+self.IPAddress +", Port="+str(self.IPPort)+" ID="+str(self.MBAddr))
|
|
try:
|
|
client = ModbusClient(host=self.IPAddress, port=self.IPPort, unit_id=self.MBAddr, auto_open=True, auto_close=True, timeout=2)
|
|
except:
|
|
Domoticz.Error("Error connecting to TCP/Interface on address : "+self.IPaddress+":"+str(self.IPPort))
|
|
# TODO: add for each devices
|
|
#Devices[1].Update(1, "0") # Set value to 0 (error)
|
|
|
|
global _plugin
|
|
_plugin = BasePlugin()
|
|
|
|
def onStart():
|
|
global _plugin
|
|
_plugin.onStart()
|
|
|
|
def onStop():
|
|
global _plugin
|
|
_plugin.onStop()
|
|
|
|
def onConnect(Connection, Status, Description):
|
|
global _plugin
|
|
_plugin.onConnect(Connection, Status, Description)
|
|
|
|
def onMessage(Connection, Data):
|
|
global _plugin
|
|
_plugin.onMessage(Connection, Data)
|
|
|
|
def onCommand(Unit, Command, Level, Hue):
|
|
global _plugin
|
|
_plugin.onCommand(Unit, Command, Level, Hue)
|
|
|
|
def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
|
|
global _plugin
|
|
_plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)
|
|
|
|
def onDisconnect(Connection):
|
|
global _plugin
|
|
_plugin.onDisconnect(Connection)
|
|
|
|
def onHeartbeat():
|
|
global _plugin
|
|
_plugin.onHeartbeat()
|
|
|
|
# Generic helper functions
|
|
def DumpConfigToLog():
|
|
for x in Parameters:
|
|
if Parameters[x] != "":
|
|
Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
|
|
Domoticz.Debug("Device count: " + str(len(Devices)))
|
|
for x in Devices:
|
|
Domoticz.Debug("Device: " + str(x) + " - " + str(Devices[x]))
|
|
Domoticz.Debug("Device ID: '" + str(Devices[x].ID) + "'")
|
|
Domoticz.Debug("Device Name: '" + Devices[x].Name + "'")
|
|
Domoticz.Debug("Device nValue: " + str(Devices[x].nValue))
|
|
Domoticz.Debug("Device sValue: '" + Devices[x].sValue + "'")
|
|
Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
|
|
return
|