Advertisement
eSbek

Domoticz plugin Mbus Read v2019.04.20 update

Apr 20th, 2019
411
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 28.23 KB | None | 0 0
  1. # Modbus RTU/ASCII/TCP - Universal READ Plugin for Domoticz
  2. #
  3. # Author: Sebastiaan Ebeltjes / domoticx.nl
  4. # Serial HW: USB RS485-Serial Stick, like: http://domoticx.nl/webwinkel/index.php?route=product/product&product_id=386
  5. #
  6. # Dependancies:
  7. # - pymodbus AND pymodbusTCP:
  8. #   - Install for python 3.x with: sudo pip3 install -U pymodbus pymodbusTCP
  9. #
  10. # NOTE: Some "name" fields are abused to put in more options ;-)
  11. #
  12. # Sandolution: Removed debug option due to implementation of sensor type.
  13. # Added more options for data type (swapping of low/high byte/word).
  14. # Adjusted dividing settings to include 10000.
  15. #
  16. """
  17. <plugin key="Modbus" name="Modbus RTU/ASCII/TCP - READ v1.1.4" author="S. Ebeltjes / domoticx.nl" version="1.1.3" externallink="" wikilink="https://github.com/DomoticX/domoticz-modbus/">
  18.   <params>
  19.       <param field="Mode1" label="Method" width="120px" required="true">
  20.           <options>
  21.               <option label="RTU" value="rtu" default="true"/>
  22.               <option label="ASCII" value="ascii"/>
  23.               <option label="RTU over TCP" value="rtutcp"/>
  24.               <option label="TCP/IP" value="tcpip"/>
  25.           </options>
  26.       </param>
  27.       <param field="SerialPort" label="Serial Port" width="120px" required="true"/>
  28.       <param field="Mode2" label="Baudrate" width="70px" required="true">
  29.           <options>
  30.               <option label="1200" value="1200"/>
  31.               <option label="2400" value="2400"/>
  32.               <option label="4800" value="4800"/>
  33.               <option label="9600" value="9600" default="true"/>
  34.               <option label="14400" value="14400"/>
  35.               <option label="19200" value="19200"/>
  36.               <option label="38400" value="38400"/>
  37.               <option label="57600" value="57600"/>
  38.               <option label="115200" value="115200"/>
  39.           </options>
  40.       </param>
  41.       <param field="Mode3" label="Port settings" width="260px" required="true">
  42.           <options>
  43.               <option label="StopBits 1 / ByteSize 7 / Parity: None" value="S1B7PN"/>
  44.               <option label="StopBits 1 / ByteSize 7 / Parity: Even" value="S1B7PE"/>
  45.               <option label="StopBits 1 / ByteSize 7 / Parity: Odd" value="S1B7PO"/>
  46.               <option label="StopBits 1 / ByteSize 8 / Parity: None" value="S1B8PN" default="true"/>
  47.               <option label="StopBits 1 / ByteSize 8 / Parity: Even" value="S1B8PE"/>
  48.               <option label="StopBits 1 / ByteSize 8 / Parity: Odd" value="S1B8PO"/>
  49.               <option label="StopBits 2 / ByteSize 7 / Parity: None" value="S2B7PN"/>
  50.               <option label="StopBits 2 / ByteSize 7 / Parity: Even" value="S2B7PE"/>
  51.               <option label="StopBits 2 / ByteSize 7 / Parity: Odd" value="S2B7PO"/>
  52.               <option label="StopBits 2 / ByteSize 8 / Parity: None" value="S2B8PN"/>
  53.               <option label="StopBits 2 / ByteSize 8 / Parity: Even" value="S2B8PE"/>
  54.               <option label="StopBits 2 / ByteSize 8 / Parity: Odd" value="S2B8PO"/>
  55.           </options>
  56.       </param>
  57.       <param field="Address" label="Device address /ID(TCP)" width="120px" required="true"/>
  58.       <param field="Port" label="Port (TCP)" value="502" width="75px"/>
  59.       <param field="Username" label="Modbus Function" width="280px" required="true">
  60.           <options>
  61.               <option label="Read Coil (Function 1)" value="1"/>
  62.               <option label="Read Discrete Input (Function 2)" value="2"/>
  63.               <option label="Read Holding Registers (Function 3)" value="3"/>
  64.               <option label="Read Input Registers (Function 4)" value="4" default="true"/>
  65.           </options>
  66.       </param>
  67.       <param field="Password" label="Register number" width="75px" required="true"/>
  68.       <param field="Mode6" label="Data type" width="180px" required="true">
  69.           <options>
  70.               <option label="No conversion (1 register)" value="noco"/>
  71.               <option label="INT 8-Bit LSB" value="int8LSB"/>
  72.               <option label="INT 8-Bit MSB" value="int8MSB"/>
  73.               <option label="INT 16-Bit" value="int16"/>
  74.               <option label="INT 16-Bit Swapped" value="int16s"/>
  75.               <option label="INT 32-Bit" value="int32"/>
  76.               <option label="INT 32-Bit Swapped" value="int32s"/>
  77.               <option label="INT 64-Bit" value="int64"/>
  78.               <option label="INT 64-Bit Swapped" value="int64s"/>
  79.               <option label="UINT 8-Bit LSB" value="uint8LSB"/>
  80.               <option label="UINT 8-Bit MSB" value="uint8MSB"/>
  81.               <option label="UINT 16-Bit" value="uint16" default="true"/>
  82.               <option label="UINT 16-Bit Swapped" value="uint16s"/>
  83.               <option label="UINT 32-Bit" value="uint32"/>
  84.               <option label="UINT 32-Bit Swapped" value="uint32s"/>
  85.               <option label="UINT 64-Bit" value="uint64"/>
  86.               <option label="UINT 64-Bit Swapped" value="uint64s"/>
  87.               <option label="FLOAT 32-Bit" value="float32"/>
  88.               <option label="FLOAT 32-Bit Swapped" value="float32"/>
  89.               <option label="FLOAT 64-Bit" value="float64"/>
  90.               <option label="FLOAT 64-Bit Swapped" value="float64s"/>
  91.               <option label="STRING 2-byte" value="string2"/>
  92.               <option label="STRING 4-byte" value="string4"/>
  93.               <option label="STRING 6-byte" value="string6"/>
  94.               <option label="STRING 8-byte" value="string8"/>
  95.           </options>
  96.       </param>
  97.       <param field="Mode5" label="Divide value" width="100px" required="true">
  98.           <options>
  99.               <option label="No" value="div0" default="true"/>
  100.               <option label="Divide /10" value="div10"/>
  101.               <option label="Divide /100" value="div100"/>
  102.               <option label="Divide /1000" value="div1000"/>
  103.               <option label="Divide /10000" value="div10000"/>
  104.           </options>
  105.       </param>
  106.    <param field="Mode4" label="Sensor type" width="180px" required="true" value="Custom">
  107.           <options>
  108.               <option label="Air Quality" value="Air Quality"/>
  109.        <option label="Alert" value="Alert"/>
  110.        <option label="Barometer" value="Barometer"/>
  111.        <option label="Counter Incremental" value="Counter Incremental"/>
  112.        <option label="Current/Ampere" value="Current/Ampere"/>
  113.        <option label="Current (Single)" value="Current (Single)"/>
  114.        <option label="Custom" value="Custom" default="true"/>
  115.        <option label="Distance" value="Distance"/>
  116.        <option label="Gas" value="Gas"/>
  117.        <option label="Humidity" value="Humidity"/>
  118.        <option label="Illumination" value="Illumination"/>
  119.        <option label="kWh" value="kWh"/>
  120.        <option label="Leaf Wetness" value="Leaf Wetness"/>
  121.        <option label="Percentage" value="Percentage"/>
  122.        <option label="Pressure" value="Pressure"/>
  123.        <option label="Rain" value="Rain"/>
  124.        <option label="Selector Switch" value="Selector Switch"/>
  125.        <option label="Soil Moisture" value="Soil Moisture"/>
  126.        <option label="Solar Radiation" value="Solar Radiation"/>
  127.        <option label="Sound Level" value="Sound Level"/>
  128.        <option label="Switch" value="Switch"/>
  129.        <option label="Temperature" value="Temperature"/>
  130.        <option label="Temp+Hum" value="Temp+Hum"/>
  131.        <option label="Temp+Hum+Baro" value="Temp+Hum+Baro"/>
  132.        <option label="Text" value="Text"/>
  133.        <option label="Usage" value="Usage"/>
  134.        <option label="UV" value="UV"/>
  135.        <option label="Visibility" value="Visibility"/>
  136.        <option label="Voltage" value="Voltage"/>
  137.        <option label="Waterflow" value="Waterflow"/>
  138.        <option label="Wind" value="Wind"/>
  139.        <option label="Wind+Temp+Chill" value="Wind+Temp+Chill"/>
  140.           </options>
  141.       </param>
  142.   </params>
  143. </plugin>
  144. """
  145. import Domoticz
  146.  
  147. import sys
  148.  
  149. #DSM 6.2 python 3.5.1
  150. sys.path.append('/usr/local/lib/python3.5/site-packages')
  151. #sys.path.append('/volume1/@appstore/py3k/usr/local/lib/python3.5/site-packages')
  152.  
  153. #Windows 10 Python 3.5.1
  154. sys.path.append("C:\Program Files (x86)\Python35-32\Lib\site-packages")
  155.  
  156. #Linux
  157. #sys.path.append('/usr/local/lib/python3.4/dist-packages')
  158. #sys.path.append('/usr/local/lib/python3.5/dist-packages')
  159.  
  160. from pymodbus.client.sync import ModbusSerialClient
  161. from pymodbus.client.sync import ModbusTcpClient
  162. from pymodbus.transaction import ModbusRtuFramer
  163. from pymodbus.client.sync import ModbusTcpClient as ModbusClient
  164.  
  165. from pymodbus.constants import Endian
  166. from pymodbus.payload import BinaryPayloadDecoder
  167.  
  168.  
  169. from pymodbus.compat import iteritems
  170. from collections import OrderedDict
  171. from pymodbus.exceptions import ParameterException
  172.  
  173. # Declare internal variables
  174. result = ""
  175. value = 0
  176. ignored = 0
  177. data = []
  178.  
  179. class BasePlugin:
  180.     enabled = False
  181.     def __init__(self):
  182.         return
  183.  
  184.     def onStart(self):
  185.         Domoticz.Log("onStart called")
  186.         #if Parameters["Mode4"] == "debug": Domoticz.Debugging(1)
  187.         Domoticz.Debugging(0)   #Enable debugging by default, mode 4 is used for sensor mode
  188.         Domoticz.Log("Sensor Type: "+Parameters["Mode4"])
  189.         #Removed the full name parameter
  190.         #Due to the lack of more parameter posibility, the name will be the hardware name
  191.         if (len(Devices) == 0): Domoticz.Device(Name=" ",  Unit=1, TypeName=Parameters["Mode4"], Image=0, Used=1).Create() #Added sensor type
  192.         DumpConfigToLog()
  193.         Domoticz.Log("Modbus RTU/ASCII/TCP - Universal READ loaded.")
  194.         return
  195.  
  196.     def onStop(self):
  197.         Domoticz.Log("onStop called")
  198.  
  199.     def onConnect(self, Connection, Status, Description):
  200.         Domoticz.Log("onConnect called")
  201.         return
  202.  
  203.     def onMessage(self, Connection, Data, Status, Extra):
  204.         Domoticz.Log("onMessage called")
  205.  
  206.     def onCommand(self, Unit, Command, Level, Hue):
  207.         Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
  208.  
  209.     def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
  210.         Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)
  211.  
  212.     def onDisconnect(self, Connection):
  213.         Domoticz.Log("onDisconnect called")
  214.  
  215.     def onHeartbeat(self):
  216.         #Domoticz.Log("onHeartbeat called")
  217.  
  218.         # Wich serial port settings to use?
  219.         if (Parameters["Mode3"] == "S1B7PN"): StopBits, ByteSize, Parity = 1, 7, "N"
  220.         if (Parameters["Mode3"] == "S1B7PE"): StopBits, ByteSize, Parity = 1, 7, "E"
  221.         if (Parameters["Mode3"] == "S1B7PO"): StopBits, ByteSize, Parity = 1, 7, "O"
  222.         if (Parameters["Mode3"] == "S1B8PN"): StopBits, ByteSize, Parity = 1, 8, "N"
  223.         if (Parameters["Mode3"] == "S1B8PE"): StopBits, ByteSize, Parity = 1, 8, "E"
  224.         if (Parameters["Mode3"] == "S1B8PO"): StopBits, ByteSize, Parity = 1, 8, "O"
  225.         if (Parameters["Mode3"] == "S2B7PN"): StopBits, ByteSize, Parity = 2, 7, "N"
  226.         if (Parameters["Mode3"] == "S2B7PE"): StopBits, ByteSize, Parity = 2, 7, "E"
  227.         if (Parameters["Mode3"] == "S2B7PO"): StopBits, ByteSize, Parity = 2, 7, "O"
  228.         if (Parameters["Mode3"] == "S2B8PN"): StopBits, ByteSize, Parity = 2, 8, "N"
  229.         if (Parameters["Mode3"] == "S2B8PE"): StopBits, ByteSize, Parity = 2, 8, "E"
  230.         if (Parameters["Mode3"] == "S2B8PO"): StopBits, ByteSize, Parity = 2, 8, "O"
  231.  
  232.         # How many registers to read (depending on data type)?
  233.     # Added additional options for byte/word swapping
  234.         registercount = 1 # Default
  235.         if (Parameters["Mode6"] == "noco"): registercount = 1
  236.         if (Parameters["Mode6"] == "int8LSB"): registercount = 1
  237.         if (Parameters["Mode6"] == "int8MSB"): registercount = 1
  238.         if (Parameters["Mode6"] == "int16"): registercount = 1
  239.         if (Parameters["Mode6"] == "int16s"): registercount = 1
  240.         if (Parameters["Mode6"] == "int32"): registercount = 2
  241.         if (Parameters["Mode6"] == "int32s"): registercount = 2
  242.         if (Parameters["Mode6"] == "int64"): registercount = 4
  243.         if (Parameters["Mode6"] == "int64s"): registercount = 4
  244.         if (Parameters["Mode6"] == "uint8LSB"): registercount = 1
  245.         if (Parameters["Mode6"] == "uint8MSB"): registercount = 1
  246.         if (Parameters["Mode6"] == "uint16"): registercount = 1
  247.         if (Parameters["Mode6"] == "uint16s"): registercount = 1
  248.         if (Parameters["Mode6"] == "uint32"): registercount = 2
  249.         if (Parameters["Mode6"] == "uint32s"): registercount = 2
  250.         if (Parameters["Mode6"] == "uint64"): registercount = 4
  251.         if (Parameters["Mode6"] == "uint64s"): registercount = 4
  252.         if (Parameters["Mode6"] == "float32"): registercount = 2
  253.         if (Parameters["Mode6"] == "float32s"): registercount = 2
  254.         if (Parameters["Mode6"] == "float64"): registercount = 4
  255.         if (Parameters["Mode6"] == "float64s"): registercount = 4
  256.         if (Parameters["Mode6"] == "string2"): registercount = 2
  257.         if (Parameters["Mode6"] == "string4"): registercount = 4
  258.         if (Parameters["Mode6"] == "string6"): registercount = 6
  259.         if (Parameters["Mode6"] == "string8"): registercount = 8
  260.  
  261.     # Split address to support TCP/IP device ID
  262.  
  263.         AddressData = Parameters['Address'].split('/')  # Split on "/"
  264.         UnitAddress = AddressData[0]
  265.  
  266.     # Is there a unit ID given after the IP? (e.g. 192.168.2.100/56)
  267.  
  268.         UnitIdForIp = 1  # Default
  269.         if len(AddressData) > 1:
  270.           UnitIdForIp = AddressData[1]
  271.  
  272.         ###################################
  273.         # pymodbus: RTU / ASCII
  274.         ###################################
  275.         if (Parameters["Mode1"] == "rtu" or Parameters["Mode1"] == "ascii"):
  276.           Domoticz.Debug("MODBUS DEBUG USB SERIAL HW - Port="+Parameters["SerialPort"]+", BaudRate="+Parameters["Mode2"]+", StopBits="+str(StopBits)+", ByteSize="+str(ByteSize)+" Parity="+Parity)
  277.           Domoticz.Debug("MODBUS DEBUG USB SERIAL CMD - Method="+Parameters["Mode1"]+", Address="+UnitAddress+", Register="+Parameters["Password"]+", Function="+Parameters["Username"]+", Data type="+Parameters["Mode6"])
  278.           try:
  279.             client = ModbusSerialClient(method=Parameters["Mode1"], port=Parameters["SerialPort"], stopbits=StopBits, bytesize=ByteSize, parity=Parity, baudrate=int(Parameters["Mode2"]), timeout=1, retries=2)
  280.           except:
  281.             Domoticz.Log("Error opening Serial interface on "+Parameters["SerialPort"])
  282.             Devices[1].Update(0, "0") # Update device in Domoticz
  283.  
  284.         ###################################
  285.         # pymodbus: RTU over TCP
  286.         ###################################
  287.         if (Parameters["Mode1"] == "rtutcp"):
  288.           Domoticz.Debug("MODBUS DEBUG TCP CMD - Method="+Parameters["Mode1"]+", Address="+UnitAddress+", Port="+Parameters["Port"]+", Register="+Parameters["Password"]+", Data type="+Parameters["Mode6"])
  289.           try:
  290.             client = ModbusTcpClient(host=UnitAddress, port=int(Parameters["Port"]), framer=ModbusRtuFramer, auto_open=True, auto_close=True, timeout=5)
  291.           except:
  292.             Domoticz.Log("Error opening TCP interface on address: "+UnitAddress)
  293.             Devices[1].Update(0, "0") # Update device in Domoticz
  294.  
  295.         ###################################
  296.         # pymodbusTCP: TCP/IP
  297.         ###################################
  298.         if (Parameters["Mode1"] == "tcpip"):
  299.           Domoticz.Debug("MODBUS DEBUG TCP CMD - Method="+Parameters["Mode1"]+", Address="+UnitAddress+", Port="+Parameters["Port"]+", Unit ID="+UnitIdForIp+", Register="+Parameters["Password"]+", Data type="+Parameters["Mode6"])
  300.           try:
  301.             client = ModbusClient(host=UnitAddress, port=int(Parameters["Port"]), unit_id=UnitIdForIp, auto_open=True, auto_close=True, timeout=5)
  302.           except:
  303.             Domoticz.Log("Error opening TCP/IP interface on address: "+UnitAddress)
  304.             Devices[1].Update(0, "0") # Update device in Domoticz
  305.  
  306.         ###################################
  307.         # pymodbus section
  308.         ###################################
  309.         if (Parameters["Mode1"] == "rtu" or Parameters["Mode1"] == "ascii" or Parameters["Mode1"] == "rtutcp"):
  310.           try:
  311.             # Which function to execute? RTU/ASCII/RTU over TCP
  312.             if (Parameters["Username"] == "1"):
  313.               data = client.read_coils(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp))
  314.             if (Parameters["Username"] == "2"):
  315.               data = client.read_discrete_inputs(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp))
  316.             if (Parameters["Username"] == "3"):
  317.               data = client.read_holding_registers(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp))
  318.             if (Parameters["Username"] == "4"):
  319.               data = client.read_input_registers(int(Parameters["Password"]), registercount, unit=int(UnitIdForIp))
  320.             Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data))
  321.           except:
  322.             Domoticz.Log("Modbus error communicating! (RTU/ASCII/RTU over TCP), check your settings!")
  323.             Devices[1].Update(0, "0") # Update device to OFF in Domoticz
  324.  
  325.           try:
  326.             # How to decode the input?
  327.             # Added option to swap bytes (little endian)
  328.             if (Parameters["Mode6"] == "int16s" or Parameters["Mode6"] == "uint16s"):
  329.               decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Little, wordorder=Endian.Big)
  330.             # Added option to swap words (little endian)
  331.             elif (Parameters["Mode6"] == "int32s" or Parameters["Mode6"] == "uint32s" or Parameters["Mode6"] == "int64s" or Parameters["Mode6"] == "uint64s"
  332.                   or Parameters["Mode6"] == "float32s" or Parameters["Mode6"] == "float64s"):
  333.               decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Big, wordorder=Endian.Little)
  334.             # Otherwise always big endian
  335.             else:
  336.               decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Big, wordorder=Endian.Big)
  337.  
  338.             if (Parameters["Mode6"] == "noco"): value = data.registers[0]
  339.             if (Parameters["Mode6"] == "int8LSB"):
  340.               ignored = decoder.skip_bytes(1)
  341.               value = decoder.decode_8bit_int()
  342.             if (Parameters["Mode6"] == "int8MSB"): value = decoder.decode_8bit_int()
  343.             if (Parameters["Mode6"] == "int16"): value = decoder.decode_16bit_int()
  344.             if (Parameters["Mode6"] == "int16s"): value = decoder.decode_16bit_int()
  345.             if (Parameters["Mode6"] == "int32"): value = decoder.decode_32bit_int()
  346.             if (Parameters["Mode6"] == "int32s"): value = decoder.decode_32bit_int()
  347.             if (Parameters["Mode6"] == "int64"): value = decoder.decode_64bit_int()
  348.             if (Parameters["Mode6"] == "int64s"): value = decoder.decode_64bit_int()
  349.             if (Parameters["Mode6"] == "uint8LSB"):
  350.               ignored = decoder.skip_bytes(1)
  351.               value = decoder.decode_8bit_uint()
  352.             if (Parameters["Mode6"] == "uint8MSB"): value = decoder.decode_8bit_uint()
  353.             if (Parameters["Mode6"] == "uint16"): value = decoder.decode_16bit_uint()
  354.             if (Parameters["Mode6"] == "uint16s"): value = decoder.decode_16bit_uint()
  355.             if (Parameters["Mode6"] == "uint32"): value = decoder.decode_32bit_uint()
  356.             if (Parameters["Mode6"] == "uint32s"): value = decoder.decode_32bit_uint()
  357.             if (Parameters["Mode6"] == "uint64"): value = decoder.decode_64bit_uint()
  358.             if (Parameters["Mode6"] == "uint64s"): value = decoder.decode_64bit_uint()
  359.             if (Parameters["Mode6"] == "float32"): value = decoder.decode_32bit_float()
  360.             if (Parameters["Mode6"] == "float32s"): value = decoder.decode_32bit_float()
  361.             if (Parameters["Mode6"] == "float64"): value = decoder.decode_64bit_float()
  362.             if (Parameters["Mode6"] == "float64s"): value = decoder.decode_64bit_float()
  363.             if (Parameters["Mode6"] == "string2"): value = decoder.decode_string(2)
  364.             if (Parameters["Mode6"] == "string4"): value = decoder.decode_string(4)
  365.             if (Parameters["Mode6"] == "string6"): value = decoder.decode_string(6)
  366.             if (Parameters["Mode6"] == "string8"): value = decoder.decode_string(8)
  367.             Domoticz.Debug("MODBUS DEBUG VALUE: " + str(value))
  368.  
  369.             # Divide the value (decimal)?
  370.             # Added 10000 option
  371.             if (Parameters["Mode5"] == "div0"): value = str(value)
  372.             if (Parameters["Mode5"] == "div10"): value = str(round(value / 10, 1))
  373.             if (Parameters["Mode5"] == "div100"): value = str(round(value / 100, 2))
  374.             if (Parameters["Mode5"] == "div1000"): value = str(round(value / 1000, 3))
  375.             if (Parameters["Mode5"] == "div10000"): value = str(round(value / 10000, 4))
  376.            
  377.             Devices[1].Update(0, value) # Update value in Domoticz
  378.  
  379.           except:
  380.             Domoticz.Log("Modbus error decoding or received no data (RTU/ASCII/RTU over TCP)!, check your settings!")
  381.             Devices[1].Update(0, "0") # Update value in Domoticz
  382.  
  383.         ###################################
  384.         # pymodbusTCP section
  385.         ###################################
  386.         if (Parameters["Mode1"] == "tcpip"):
  387.           try:
  388.             # Which function to execute? TCP/IP
  389.             if (Parameters["Username"] == "1"): data = client.read_coils(int(Parameters["Password"]), registercount)
  390.             if (Parameters["Username"] == "2"): data = client.read_discrete_inputs(int(Parameters["Password"]), registercount)
  391.             if (Parameters["Username"] == "3"): data = client.read_holding_registers(int(Parameters["Password"]), registercount)
  392.             if (Parameters["Username"] == "4"): data = client.read_input_registers(int(Parameters["Password"]), registercount)
  393.             Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data))
  394.            
  395.           except:
  396.             Domoticz.Log("Modbus error communicating! (TCP/IP), check your settings!")
  397.             Devices[1].Update(0, "0") # Update device to OFF in Domoticz
  398.  
  399.           try:
  400.             # How to decode the input?
  401.             # Added option to swap bytes (little endian)
  402.             if (Parameters["Mode6"] == "int16s" or Parameters["Mode6"] == "uint16s"):
  403.               decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Little, wordorder=Endian.Big)
  404.             # Added option to swap words (little endian)
  405.             elif (Parameters["Mode6"] == "int32s" or Parameters["Mode6"] == "uint32s" or Parameters["Mode6"] == "int64s" or Parameters["Mode6"] == "uint64s"
  406.                   or Parameters["Mode6"] == "float32s" or Parameters["Mode6"] == "float64s"):
  407.               decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Big, wordorder=Endian.Little)
  408.             # Otherwise always big endian
  409.             else:
  410.               decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=Endian.Big, wordorder=Endian.Big)
  411.  
  412.             if (Parameters["Mode6"] == "noco"): value = data.registers[0]
  413.             if (Parameters["Mode6"] == "int8LSB"):
  414.               ignored = decoder.skip_bytes(1)
  415.               value = decoder.decode_8bit_int()
  416.             if (Parameters["Mode6"] == "int8MSB"): value = decoder.decode_8bit_int()
  417.             if (Parameters["Mode6"] == "int16"): value = decoder.decode_16bit_int()
  418.             if (Parameters["Mode6"] == "int16s"): value = decoder.decode_16bit_int()
  419.             if (Parameters["Mode6"] == "int32"): value = decoder.decode_32bit_int()
  420.             if (Parameters["Mode6"] == "int32s"): value = decoder.decode_32bit_int()
  421.             if (Parameters["Mode6"] == "int64"): value = decoder.decode_64bit_int()
  422.             if (Parameters["Mode6"] == "int64s"): value = decoder.decode_64bit_int()
  423.             if (Parameters["Mode6"] == "uint8LSB"):
  424.               ignored = decoder.skip_bytes(1)
  425.               value = decoder.decode_8bit_uint()
  426.             if (Parameters["Mode6"] == "uint8MSB"): value = decoder.decode_8bit_uint()  
  427.             if (Parameters["Mode6"] == "uint16"): value = decoder.decode_16bit_uint()
  428.             if (Parameters["Mode6"] == "uint16s"): value = decoder.decode_16bit_uint()
  429.             if (Parameters["Mode6"] == "uint32"): value = decoder.decode_32bit_uint()
  430.             if (Parameters["Mode6"] == "uint32s"): value = decoder.decode_32bit_uint()
  431.             if (Parameters["Mode6"] == "uint64"): value = decoder.decode_64bit_uint()
  432.             if (Parameters["Mode6"] == "uint64s"): value = decoder.decode_64bit_uint()
  433.             if (Parameters["Mode6"] == "float32"): value = decoder.decode_32bit_float()
  434.             if (Parameters["Mode6"] == "float32s"): value = decoder.decode_32bit_float()
  435.             if (Parameters["Mode6"] == "float64"): value = decoder.decode_64bit_float()
  436.             if (Parameters["Mode6"] == "float64s"): value = decoder.decode_64bit_float()
  437.             if (Parameters["Mode6"] == "string2"): value = decoder.decode_string(2)
  438.             if (Parameters["Mode6"] == "string4"): value = decoder.decode_string(4)
  439.             if (Parameters["Mode6"] == "string6"): value = decoder.decode_string(6)
  440.             if (Parameters["Mode6"] == "string8"): value = decoder.decode_string(8)
  441.             Domoticz.Debug("MODBUS DEBUG VALUE: " + str(value))
  442.  
  443.             # Divide the value (decimal)?
  444.             # Added 10000 option
  445.             if (Parameters["Mode5"] == "div0"): value = str(value)
  446.             if (Parameters["Mode5"] == "div10"): value = str(round(value / 10, 1))
  447.             if (Parameters["Mode5"] == "div100"): value = str(round(value / 100, 2))
  448.             if (Parameters["Mode5"] == "div1000"): value = str(round(value / 1000, 3))
  449.             if (Parameters["Mode5"] == "div10000"): value = str(round(value / 10000, 4))
  450.  
  451.             if (Parameters["Username"] == "1") and (value != "0"): Devices[1].Update(1, value) # Update value in Domoticz
  452.  
  453.             Devices[1].Update(0, value) # Update value in Domoticz
  454.           except:
  455.             Domoticz.Log("Modbus error decoding or received no data (TCP/IP)!, check your settings!")
  456.             Devices[1].Update(0, "0") # Update value in Domoticz
  457.  
  458.     def UpdateDevice(Unit, nValue, sValue):
  459.         # Make sure that the Domoticz device still exists (they can be deleted) before updating it
  460.         if (Unit in Devices):
  461.           if (Devices[Unit].nValue != nValue) or (Devices[Unit].sValue != sValue):
  462.             Devices[Unit].Update(nValue, str(sValue))
  463.             Domoticz.Log("Update "+str(nValue)+":'"+str(sValue)+"' ("+Devices[Unit].Name+")")
  464.         return
  465.  
  466. global _plugin
  467. _plugin = BasePlugin()
  468.  
  469. def onStart():
  470.     global _plugin
  471.     _plugin.onStart()
  472.  
  473. def onStop():
  474.     global _plugin
  475.     _plugin.onStop()
  476.  
  477. def onConnect(Connection, Status, Description):
  478.     global _plugin
  479.     _plugin.onConnect(Connection, Status, Description)
  480.  
  481. def onMessage(Connection, Data, Status, Extra):
  482.     global _plugin
  483.     _plugin.onMessage(Connection, Data, Status, Extra)
  484.  
  485. def onCommand(Unit, Command, Level, Hue):
  486.     global _plugin
  487.     _plugin.onCommand(Unit, Command, Level, Hue)
  488.  
  489. def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
  490.     global _plugin
  491.     _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)
  492.  
  493. def onDisconnect(Connection):
  494.     global _plugin
  495.     _plugin.onDisconnect(Connection)
  496.  
  497. def onHeartbeat():
  498.     global _plugin
  499.     _plugin.onHeartbeat()
  500.  
  501.     # Generic helper functions
  502. def DumpConfigToLog():
  503.     for x in Parameters:
  504.         if Parameters[x] != "":
  505.             Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
  506.     Domoticz.Debug("Device count: " + str(len(Devices)))
  507.     for x in Devices:
  508.         Domoticz.Debug("Device:           " + str(x) + " - " + str(Devices[x]))
  509.         Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
  510.         Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
  511.         Domoticz.Debug("Device nValue:    " + str(Devices[x].nValue))
  512.         Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
  513.         Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
  514.     return
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement