Python plugin: Modbus RTU / ASCII / TCP/IP Topic is solved

Python and python framework

Moderator: leecollings

KrisWp
Posts: 2
Joined: Saturday 17 April 2021 17:55
Target OS: Linux
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by KrisWp »

andrehj wrote: Saturday 17 April 2021 20:16
KrisWp wrote: Saturday 17 April 2021 19:37 I find out that the reason of this is because the 2 devices are polling simultanious and my Modbus is overloaded.
...
But because of the slight differences of the pollingrate, in a few days the calls are on the same moment and the Modbus flips...
What error do you get when "the modbus flips"?
I also had many unexplained modbus errors. Sometimes there were hours without them, and then they would reappear at 12 minute intervals. Could not find an explanation, but all of these errors disappeared when I installed a 120 Ohm resistor on both ends of the RS485 bus, even though my bus is only 6 meters long (I use AWG23 twisted pair).
Everywhere you read that these resistors are only needed for very long lengths, but in my case they solved all modbus errors.
No specific error. But the values I received are sometimes 0.
With another commandline tool (sdm120c), also bad results at the moment Domoticz return zero’s.
Resistors are also in place...
Is there a way to tune the polling? Or to disable autopolling and initiate it from script?
magicduck
Posts: 36
Joined: Sunday 11 February 2018 13:25
Target OS: -
Domoticz version:
Location: Longwy, France
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by magicduck »

Hi there

I see there 3 modules in this project : modbus-read/modbus-write, but there is modbus-device. Since @domoticX is the maintainer of this project, does modbus-device is ready for usage, or it is dead project?
Regards,
Xavier
magicduck
Posts: 36
Joined: Sunday 11 February 2018 13:25
Target OS: -
Domoticz version:
Location: Longwy, France
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by magicduck »

Fireflies wrote: Thursday 08 October 2020 17:04 Thanks for developing this nice plugin. I am trying to use this plugin with an EASTRON SDM120M Modbus coupled to an RS485 USB stick on a Raspberry PI in Domoticz. I am able to read the values from the device directly in the commandline with a tool, leading me to the conclusion that the hardware configuration is correct. However, the plugin seems to crash when I make a device in Domoticz. I cannot figure out what is going wrong. This is what the Domoticz log shows:

Code: Select all

2020-10-08 16:54:09.306 Error: (Modbus2) failed to load 'plugin.py', Python Path used was '/home/pi/domoticz/plugins/modbus-device/:/usr/lib/python37.zip:/usr/lib/python3.7:/usr/lib/python3.7/lib-dynload:/usr/local/lib/python3.7/dist-packages:/usr/lib/python3/dist-packages:/usr/lib/python3.7/dist-packages'.
2020-10-08 16:54:09.306 Error: (Test) Module Import failed, exception: 'SyntaxError'
2020-10-08 16:54:09.306 Error: (Test) Import detail: File: /home/pi/domoticz/plugins/modbus-device/modbusregister.py, Line: 19, offset: 19
2020-10-08 16:54:09.307 Error: (Test) Error Line ' if devide<>"":
2020-10-08 16:54:09.307 '
2020-10-08 16:55:17.009 Error: Test hardware (11) thread seems to have ended unexpectedly
Is there anybody that can help me to sort this issue?
Well seem the modbus-device plugin is using old Python code.
I am trying to fix it. But so far no luck... Maybe if someone have some ideas: code is in https://github.com/xbeaudouin/domoticz- ... bus-device
Alain
Posts: 164
Joined: Sunday 26 April 2020 5:27
Target OS: Linux
Domoticz version: 2022.1
Location: Netherlands
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Alain »

eSbek wrote: Saturday 12 September 2020 12:13 Hey developers of the plugin,
Some time ago I modded v1.0.9 for my house ventilation system to use different values of the fan speeds whenever I need (not using fixed payload value). So I decided to read a dedicated domoticz user variable inside the python script and write the value by Modbus to my ventilation system (eg. hi humidity detected in the bathroom -> speed goes on higher values).
Please find the mod if you want to develop same approach in your latest plugins:
https://pastebin.com/5zwiepyu
I'm trying to use your modification to write values to a "read register". I have two heatpumps and in the register table supplied by the manufacturer, the setpoints are in modbus address 40002. The address tells me this is a holding register (function 3) and if I use the modbus READ plugin, I can see the current value. How can I use/modify the WRITE python script to write to this address? It should be possible because when I tried this with a simple modbus testing tool, I could actually write a value to this address and I saw the value change on the heatpump lcd controller.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
Alain
Posts: 164
Joined: Sunday 26 April 2020 5:27
Target OS: Linux
Domoticz version: 2022.1
Location: Netherlands
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Alain »

I got it working. I modified the Write file to create a thermostat instead of a switch when creating the device. I also changed it to write the thermostat value to de heat pump and it works. I only changed it for RTU because I'm not using TCP. Shouldn't be too hard to copy to the rest of the script. Here's the code as I use it now:

Code: Select all

# Modbus RTU / ASCII / TCP/IP - Universal READ Plugin for Domoticz
#
# Tested on domoticz 2020.2 (stable) with Python v3.7.3 and pymodbus v2.3.0
#
# Author: Sebastiaan Ebeltjes / DomoticX.nl
# RTU Serial HW: USB RS485-Serial Stick, like https://webshop.domoticx.nl/index.php?route=product/search&search=RS485%20RTU%20USB
#
# Dependancies:
# - pymodbus AND pymodbusTCP:
#   - Install for python3 with: sudo pip3 install -U pymodbus pymodbusTCP
#

"""
<plugin key="ModbusWRITE" name="Modbus RTU / ASCII / TCP/IP - WRITE v2021.2" author="S. Ebeltjes / DomoticX.nl" version="2021.2" externallink="http://domoticx.nl" wikilink="https://github.com/DomoticX/domoticz-modbus">
    <description>
        <h3>Modbus RTU / ASCII / TCP/IP - WRITE</h3>
        With this plugin you can write to RS485 Modbus devices with methods RTU/ASCII/TCP<br/>
        <br/>
        <h4>RTU</h4>
        The serial binary communication protocol. It is the communication standard that<br/>
        became widely used and all series of PLC's and other device producers support it.<br/>
        It goes about the network protocol of the 1Master x nSlave type. The Slave devices can be 254 at the most.<br/>
        <h4>ASCII</h4>
        This protocol is similar to Modbus RTU, but the binary content is transformed to common ASCII characters.<br/>
        It is not used as frequently as Modbus RTU.<br/>
        <h4>RTU over TCP</h4> 
        Means a MODBUS RTU packet wrapped in a TCP packet. The message bytes are modified to add the 6 byte MBAP header and remove the two byte CRC.
        <h4>TCP/IP</h4>
        It is a network protocol - classic Ethernet TCP/IP with the 10/100 Mbit/s speed rate, a standard net HW Ethernet card is sufficient.<br/>
        The communication principle (1Master x nSlave) is the same as for Modbus RTU. used port is most likely: 502<br/>
        <br/>
        <h3>Set-up and Configuration:</h3>
        See wiki link above.<br/> 
    </description>
    <params>
        <param field="Mode1" label="Communication Mode" width="160px" required="true">
            <options>
                <option label="RTU" value="rtu:rtu" default="true"/>
                <option label="RTU (+DEBUG)" value="rtu:debug"/>
                <option label="RTU ASCII" value="ascii:ascii"/>
                <option label="RTU ASCII (+DEBUG)" value="ascii:debug"/>
                <option label="RTU over TCP" value="rtutcp:rtutcp"/>
                <option label="RTU over TCP (+DEBUG)" value="rtutcp:debug"/>
                <option label="TCP/IP" value="tcpip:tcpip"/>
                <option label="TCP/IP (+DEBUG)" value="tcpip:debug"/>
            </options>
        </param>
        <param field="SerialPort" label="RTU - Serial Port" width="120px"/>
        <param field="Mode3" label="RTU - Port settings" width="260px">
            <options>
                <option label="StopBits 1 / ByteSize 7 / Parity: None" value="S1B7PN"/>
                <option label="StopBits 1 / ByteSize 7 / Parity: Even" value="S1B7PE"/>
                <option label="StopBits 1 / ByteSize 7 / Parity: Odd" value="S1B7PO"/>
                <option label="StopBits 1 / ByteSize 8 / Parity: None" value="S1B8PN" default="true"/>
                <option label="StopBits 1 / ByteSize 8 / Parity: Even" value="S1B8PE"/>
                <option label="StopBits 1 / ByteSize 8 / Parity: Odd" value="S1B8PO"/>
                <option label="StopBits 2 / ByteSize 7 / Parity: None" value="S2B7PN"/>
                <option label="StopBits 2 / ByteSize 7 / Parity: Even" value="S2B7PE"/>
                <option label="StopBits 2 / ByteSize 7 / Parity: Odd" value="S2B7PO"/>
                <option label="StopBits 2 / ByteSize 8 / Parity: None" value="S2B8PN"/>
                <option label="StopBits 2 / ByteSize 8 / Parity: Even" value="S2B8PE"/>
                <option label="StopBits 2 / ByteSize 8 / Parity: Odd" value="S2B8PO"/>
            </options>
        </param>
        <param field="Mode2" label="RTU - Baudrate" width="70px">
            <options>
                <option label="1200" value="1200"/>
                <option label="2400" value="2400"/>
                <option label="4800" value="4800"/>
                <option label="9600" value="9600" default="true"/>
                <option label="14400" value="14400"/>
                <option label="19200" value="19200"/>
                <option label="38400" value="38400"/>
                <option label="57600" value="57600"/>
                <option label="115200" value="115200"/>
            </options>
        </param>
        <param field="Address" label="TCP/IP - IP:Port" width="140px" default="192.168.2.1:502"/>
        <param field="Password" label="Device ID" width="50px" default="1" required="true"/>
        <param field="Username" label="Modbus Function" width="280px" required="true">
             <options>
                <option label="Write Single Coil (Function 5)" value="5"/>
                <option label="Write Single Holding Register (Function 6)" value="6" default="true"/>
                <option label="Write Multiple Coils (Function 15)" value="15"/>
                <option label="Write Registers (Function 16)" value="16"/>
            </options>
        </param>
        <param field="Port" label="Register number" width="50px" default="1" required="true"/>
     </params>
</plugin>
"""

import Domoticz
import sys
import pymodbus
import requests
import json

from pymodbus.client.sync import ModbusSerialClient # RTU
from pymodbus.client.sync import ModbusTcpClient    # RTU over TCP
from pymodbus.transaction import ModbusRtuFramer    # RTU over TCP
from pyModbusTCP.client import ModbusClient         # TCP/IP
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
result=""

class BasePlugin:
    enabled = False
    def __init__(self):
        return

    def onStart(self):
        Domoticz.Log("onStart called")
        try:
          Domoticz.Log("Modbus RTU/ASCII/TCP - Universal WRITE loaded!, using python v" + sys.version[:6] + " and pymodbus v" + pymodbus.__version__)
        except:
          Domoticz.Log("Modbus RTU/ASCII/TCP - Universal WRITE loaded!")

        # Dependancies notification
        try:
          if (float(Parameters["DomoticzVersion"][:6]) < float("2020.2")): Domoticz.Error("WARNING: Domoticz version is outdated/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!")

        ########################################
        # READ-IN OPTIONS AND SETTINGS
        ########################################
        # Convert "option names" to variables for easy reading and debugging.
        # Note: Parameters["Port"] cannot accept other value then int! (e.g. 192.168.0.0 will result in 192)

        Domoticz_Setting_Communication_MODDEB = Parameters["Mode1"].split(":") # Split MODE and DEBUG setting MODE:DEBUG
        self.Domoticz_Setting_Communication_Mode = Domoticz_Setting_Communication_MODDEB[0]
        self.Domoticz_Setting_Serial_Port = Parameters["SerialPort"]
        self.Domoticz_Setting_Baudrate = Parameters["Mode2"]
        self.Domoticz_Setting_Port_Mode = Parameters["Mode3"]
        self.Domoticz_Setting_Modbus_Function = Parameters["Username"]
        self.Domoticz_Setting_Register_Number = Parameters["Port"]
#        self.Domoticz_Setting_Payload_ON = Parameters["Mode4"]
#        self.Domoticz_Setting_Payload_OFF = Parameters["Mode5"]
        self.Domoticz_Setting_Device_ID = Parameters["Password"]

        self.Domoticz_Setting_TCP_IPPORT = Parameters["Address"].split(":") # Split address and port setting TCP:IP
        self.Domoticz_Setting_TCP_IP = 0 # Default
        if len(self.Domoticz_Setting_TCP_IPPORT) > 0: self.Domoticz_Setting_TCP_IP = self.Domoticz_Setting_TCP_IPPORT[0]
        self.Domoticz_Setting_TCP_PORT = 0 # Default
        if len(self.Domoticz_Setting_TCP_IPPORT) > 1: self.Domoticz_Setting_TCP_PORT = self.Domoticz_Setting_TCP_IPPORT[1]

        # Set debug yes/no
        if (Domoticz_Setting_Communication_MODDEB[1] == "debug"):
          Domoticz.Debugging(1) # Enable debugging
          DumpConfigToLog()
          Domoticz.Debug("***** NOTIFICATION: Debug enabled!")
        else:
          Domoticz.Debugging(0) # Disable debugging

        # RTU - Serial port settings
        if (self.Domoticz_Setting_Port_Mode == "S1B7PN"): self.StopBits, self.ByteSize, self.Parity = 1, 7, "N"
        if (self.Domoticz_Setting_Port_Mode == "S1B7PE"): self.StopBits, self.ByteSize, self.Parity = 1, 7, "E"
        if (self.Domoticz_Setting_Port_Mode == "S1B7PO"): self.StopBits, self.ByteSize, self.Parity = 1, 7, "O"
        if (self.Domoticz_Setting_Port_Mode == "S1B8PN"): self.StopBits, self.ByteSize, self.Parity = 1, 8, "N"
        if (self.Domoticz_Setting_Port_Mode == "S1B8PE"): self.StopBits, self.ByteSize, self.Parity = 1, 8, "E"
        if (self.Domoticz_Setting_Port_Mode == "S1B8PO"): self.StopBits, self.ByteSize, self.Parity = 1, 8, "O"
        if (self.Domoticz_Setting_Port_Mode == "S2B7PN"): self.StopBits, self.ByteSize, self.Parity = 2, 7, "N"
        if (self.Domoticz_Setting_Port_Mode == "S2B7PE"): self.StopBits, self.ByteSize, self.Parity = 2, 7, "E"
        if (self.Domoticz_Setting_Port_Mode == "S2B7PO"): self.StopBits, self.ByteSize, self.Parity = 2, 7, "O"
        if (self.Domoticz_Setting_Port_Mode == "S2B8PN"): self.StopBits, self.ByteSize, self.Parity = 2, 8, "N"
        if (self.Domoticz_Setting_Port_Mode == "S2B8PE"): self.StopBits, self.ByteSize, self.Parity = 2, 8, "E"
        if (self.Domoticz_Setting_Port_Mode == "S2B8PO"): self.StopBits, self.ByteSize, self.Parity = 2, 8, "O"

        if (len(Devices) == 0): Domoticz.Device(Name="Thermostat", Unit=1, Type=242, Subtype=1, Used=1).Create() # Used=1 to add a switch immediatly!

    def onStop(self):
        Domoticz.Log("onStop called")

    def onConnect(self, Connection, Status, Description):
        Domoticz.Log("onConnect called")
        return

    def onMessage(self, Connection, Data, Status, Extra):
        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))

        # ON/OFF payload value
        payload = str(Level) # Set payload from Thermostat
        if Level > 58:
            Level = 58
        elif Level < 25:
            Level = 25
        percentage = Level*10
        Devices[1].Update(nValue=0, sValue=str(Level))
        
  
        ########################################
        # SET HARDWARE - pymodbus: RTU / ASCII
        ########################################
        if (self.Domoticz_Setting_Communication_Mode == "rtu" or self.Domoticz_Setting_Communication_Mode == "ascii"):
          Domoticz.Debug("MODBUS DEBUG - INTERFACE: Port="+self.Domoticz_Setting_Serial_Port+", BaudRate="+self.Domoticz_Setting_Baudrate+", StopBits="+str(self.StopBits)+", ByteSize="+str(self.ByteSize)+" Parity="+self.Parity)
          Domoticz.Debug("MODBUS DEBUG - SETTINGS: Method="+self.Domoticz_Setting_Communication_Mode+", Device ID="+self.Domoticz_Setting_Device_ID+", Register="+self.Domoticz_Setting_Register_Number+", Function="+self.Domoticz_Setting_Modbus_Function+", Payload="+payload)
          try:
            client = ModbusSerialClient(method=self.Domoticz_Setting_Communication_Mode, port=self.Domoticz_Setting_Serial_Port, stopbits=self.StopBits, bytesize=self.ByteSize, parity=self.Parity, baudrate=int(self.Domoticz_Setting_Baudrate), timeout=2, retries=2)
          except:
            Domoticz.Error("Error opening Serial interface on "+self.Domoticz_Setting_Serial_Port)
            Devices[1].Update(1, "0") # Set value to 0 (error)

        ########################################
        # SET HARDWARE - pymodbus: RTU over TCP
        ########################################
        if (self.Domoticz_Setting_Communication_Mode == "rtutcp"):
          Domoticz.Debug("MODBUS DEBUG - INTERFACE: IP="+self.Domoticz_Setting_TCP_IP+", Port="+self.Domoticz_Setting_TCP_PORT)
          Domoticz.Debug("MODBUS DEBUG - SETTINGS: Method="+self.Domoticz_Setting_Communication_Mode+", Device ID="+self.Domoticz_Setting_Device_ID+", Register="+self.Domoticz_Setting_Register_Number+", Function="+self.Domoticz_Setting_Modbus_Function+", Payload="+payload)
          try:
            client = ModbusTcpClient(host=self.Domoticz_Setting_TCP_IP, port=int(self.Domoticz_Setting_TCP_PORT), framer=ModbusRtuFramer, auto_open=True, auto_close=True, timeout=2)
          except:
            Domoticz.Error("Error opening RTU over TCP interface on address: "+self.Domoticz_Setting_TCP_IPPORT)
            Devices[1].Update(1, "0") # Set value to 0 (error)

        ########################################
        # SET HARDWARE - pymodbusTCP: TCP/IP
        ########################################
        if (self.Domoticz_Setting_Communication_Mode == "tcpip"):
          Domoticz.Debug("MODBUS DEBUG - INTERFACE: IP="+self.Domoticz_Setting_TCP_IP+", Port="+self.Domoticz_Setting_TCP_PORT)
          Domoticz.Debug("MODBUS DEBUG - SETTINGS: Method="+self.Domoticz_Setting_Communication_Mode+", Device ID="+self.Domoticz_Setting_Device_ID+", Register="+self.Domoticz_Setting_Register_Number+", Function"+self.Domoticz_Setting_Modbus_Function+", Payload="+payload)
          try:
            client = ModbusClient(host=self.Domoticz_Setting_TCP_IP, port=int(self.Domoticz_Setting_TCP_PORT), unit_id=int(self.Domoticz_Setting_Device_ID), auto_open=True, auto_close=True, timeout=2)
          except:
            Domoticz.Error("Error opening TCP/IP interface on address: "+self.Domoticz_Setting_TCP_IPPORT)
            Devices[1].Update(1, "0") # Set value to 0 (error)

        ########################################
        # WRITE PAYLOAD - pymodbus: RTU / ASCII / RTU over TCP
        ########################################
        if (self.Domoticz_Setting_Communication_Mode == "rtu" or self.Domoticz_Setting_Communication_Mode == "ascii" or self.Domoticz_Setting_Communication_Mode == "rtutcp"):
          try:
            # Function to execute
            if (self.Domoticz_Setting_Modbus_Function == "5"): result = client.write_coil(int(self.Domoticz_Setting_Register_Number), int(percentage), unit=int(self.Domoticz_Setting_Device_ID))
            if (self.Domoticz_Setting_Modbus_Function == "6"): result = client.write_register(int(self.Domoticz_Setting_Register_Number), int(percentage), unit=int(self.Domoticz_Setting_Device_ID))
            if (self.Domoticz_Setting_Modbus_Function == "15"): result = client.write_coils(int(self.Domoticz_Setting_Register_Number), int(percentage), unit=int(self.Domoticz_Setting_Device_ID))
            if (self.Domoticz_Setting_Modbus_Function == "16"): result = client.write_registers(int(self.Domoticz_Setting_Register_Number), int(percentage), unit=int(self.Domoticz_Setting_Device_ID))
            client.close()

            Domoticz.Debug("MODBUS DEBUG - RESULT: " + str(result))
            if (str(Command) == "On"): Devices[1].Update(1, "1") # Update device to ON
            if (str(Command) == "Off"): Devices[1].Update(0, "0") # Update device to OFF
          except:
            Domoticz.Error("Modbus error communicating! (RTU/ASCII/RTU over TCP), check your settings!")
            Devices[1].Update(1, "0") # Set value to 0 (error)

        ########################################
        # SET PAYLOAD - pymodbusTCP: TCP/IP
        ########################################
        if (self.Domoticz_Setting_Communication_Mode == "tcpip"):
          try:
            # Function to execute
            if (self.Domoticz_Setting_Modbus_Function == "5"): result = client.write_single_coil(int(self.Domoticz_Setting_Register_Number), int(payload))
            if (self.Domoticz_Setting_Modbus_Function == "6"): result = client.write_single_register(int(self.Domoticz_Setting_Register_Number), int(payload))
            if (self.Domoticz_Setting_Modbus_Function == "15"): result = client.write_multiple_coils(int(self.Domoticz_Setting_Register_Number), [payload])     # TODO split up multiple bytes to proper array.
            if (self.Domoticz_Setting_Modbus_Function == "16"): result = client.write_multiple_registers(int(self.Domoticz_Setting_Register_Number), [payload]) # TODO split up multiple bytes to proper array.
            client.close()

            Domoticz.Debug("MODBUS DEBUG - RESULT: " + str(result))
            if (str(Command) == "On"): Devices[1].Update(1, "1") # Update device to ON
            if (str(Command) == "Off"): Devices[1].Update(0, "0") # Update device to OFF
          except:
            Domoticz.Error("Modbus error communicating! (TCP/IP), check your settings!")
            Devices[1].Update(1, "0") # Set value to 0 (error)

    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")
        return

    def UpdateDevice(Unit, nValue, sValue):
        # Make sure that the Domoticz device still exists (they can be deleted) before updating it 
        if (Unit in Devices):
          if (Devices[Unit].nValue != nValue) or (Devices[Unit].sValue != sValue):
            Devices[Unit].Update(nValue, str(sValue))
            Domoticz.Log("Update "+str(nValue)+":'"+str(sValue)+"' ("+Devices[Unit].Name+")")
        return

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, Status, Extra):
    global _plugin
    _plugin.onMessage(Connection, Data, Status, Extra)

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
Last edited by Alain on Thursday 01 July 2021 2:01, edited 1 time in total.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
Alain
Posts: 164
Joined: Sunday 26 April 2020 5:27
Target OS: Linux
Domoticz version: 2022.1
Location: Netherlands
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Alain »

KrisWp wrote: Saturday 17 April 2021 21:38
andrehj wrote: Saturday 17 April 2021 20:16
KrisWp wrote: Saturday 17 April 2021 19:37 I find out that the reason of this is because the 2 devices are polling simultanious and my Modbus is overloaded.
...
But because of the slight differences of the pollingrate, in a few days the calls are on the same moment and the Modbus flips...
What error do you get when "the modbus flips"?
I also had many unexplained modbus errors. Sometimes there were hours without them, and then they would reappear at 12 minute intervals. Could not find an explanation, but all of these errors disappeared when I installed a 120 Ohm resistor on both ends of the RS485 bus, even though my bus is only 6 meters long (I use AWG23 twisted pair).
Everywhere you read that these resistors are only needed for very long lengths, but in my case they solved all modbus errors.
No specific error. But the values I received are sometimes 0.
With another commandline tool (sdm120c), also bad results at the moment Domoticz return zero’s.
Resistors are also in place...
Is there a way to tune the polling? Or to disable autopolling and initiate it from script?
I'm getting these errors too (at least every day at random times). I have already set the polling rate to different intervals for each hardware device and I just added a 120 ohm resistor (although the lengths are short), but that didn't help either. I'm thinking about disabling the autopolling (disable the heartbeat part in the script) too and calling from a separate script. I currently have 15 devices reading from 2 different heat pumps.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
User avatar
andrehj
Posts: 44
Joined: Sunday 06 January 2019 14:26
Target OS: -
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by andrehj »

andrehj wrote: Saturday 17 April 2021 20:16 Could not find an explanation, but all of these errors disappeared when I installed a 120 Ohm resistor on both ends of the RS485 bus, even though my bus is only 6 meters long (I use AWG23 twisted pair).
I have to correct myself on this one. Even though I have far less errors with the resistors in place, they still appear now and then. Next step is to install shielded cable. To be continued...
Beksinski
Posts: 2
Joined: Monday 18 October 2021 12:31
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Beksinski »

Hello, i have problem with WRITE module. When i send Windows PC with ModbusMat1.1 to send some data to my modbus rtu 16ch relay board vis usb-serial adapter - everything is working correctly. When i would like to send the same data from domoticz to the module it don’t react - there is No communication I think. In my opiniom i could make some mistakes in domoticz configuration/settings. Would you Please look on it?
Attachments
4BA379F4-1D30-48B2-9019-71A81C5AA492.jpeg
4BA379F4-1D30-48B2-9019-71A81C5AA492.jpeg (389.07 KiB) Viewed 2917 times
672273F4-F30C-48CF-8749-8AF570C5A793.jpeg
672273F4-F30C-48CF-8749-8AF570C5A793.jpeg (387.4 KiB) Viewed 2917 times
D9FC9057-7881-4656-BB0A-25513A30CA5E.jpeg
D9FC9057-7881-4656-BB0A-25513A30CA5E.jpeg (371.25 KiB) Viewed 2917 times
Beksinski
Posts: 2
Joined: Monday 18 October 2021 12:31
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Beksinski »

More photos…
Attachments
9EC65A01-F829-4E82-97A0-12EB9BD025D4.jpeg
9EC65A01-F829-4E82-97A0-12EB9BD025D4.jpeg (340.25 KiB) Viewed 2917 times
0C40FDBA-1B5A-4CDD-A683-A5CD08A80EEB.jpeg
0C40FDBA-1B5A-4CDD-A683-A5CD08A80EEB.jpeg (356.68 KiB) Viewed 2917 times
62199B47-32AB-445A-B583-1565D869D5D6.jpeg
62199B47-32AB-445A-B583-1565D869D5D6.jpeg (372.64 KiB) Viewed 2917 times
Mazzokun
Posts: 89
Joined: Thursday 28 April 2016 23:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Milan, Italy
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Mazzokun »

Hi all!
I'm trying to read a value from a PLC with Modbus TCP and with this windows app I have success (RESULTS FIELD)
IMG_4248.JPG
IMG_4248.JPG (180.7 KiB) Viewed 2787 times
But when I try to use the plugin with the same options it does't work and says: "Modbus error decoding or received no data (TCP/IP)!, check your settings!"
Script version: 2020.2F
Any Idea/advice?
Thank you :)
IMG_4249.JPG
IMG_4249.JPG (291.71 KiB) Viewed 2787 times
Alain
Posts: 164
Joined: Sunday 26 April 2020 5:27
Target OS: Linux
Domoticz version: 2022.1
Location: Netherlands
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Alain »

Mazzokun wrote: Sunday 14 November 2021 22:26 Hi all!
I'm trying to read a value from a PLC with Modbus TCP and with this windows app I have success (RESULTS FIELD)

But when I try to use the plugin with the same options it does't work and says: "Modbus error decoding or received no data (TCP/IP)!, check your settings!"
Script version: 2020.2F
Any Idea/advice?
Thank you :)
I think you have filled an incorrect register number in. You only need to fill in 31. The module fills in the rest, because you select what you are trying to do (i.e. Read Holding Register 40***). If you donb't get the correct value, try filling in 30. I can't recall if this plugin starts at 0 or 1.

You may also need to select a divider to get the correct value, but that will be apparent to you when you see the value you receive.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
Mazzokun
Posts: 89
Joined: Thursday 28 April 2016 23:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Milan, Italy
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Mazzokun »

8-) :D :D :D
TY SO MUCH NOW WORKS!!! 8-)
It was only register 30 8-)
A Last tip; there is a way that the script round the value After 2 digits after the comma?
Alain
Posts: 164
Joined: Sunday 26 April 2020 5:27
Target OS: Linux
Domoticz version: 2022.1
Location: Netherlands
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Alain »

You'll need to change the script for that if you are not dividing the result.

Go to line 487 in the plugin.py
At the end of the line it says: value = str(value)
Change that to: value = str(round(value, 2))
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
Alain
Posts: 164
Joined: Sunday 26 April 2020 5:27
Target OS: Linux
Domoticz version: 2022.1
Location: Netherlands
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Alain »

Don't forget to restart Domoticz for the change in the script to take effect.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
Mazzokun
Posts: 89
Joined: Thursday 28 April 2016 23:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Milan, Italy
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Mazzokun »

:P PERFECT
Really thank you ;)
Mazzokun
Posts: 89
Joined: Thursday 28 April 2016 23:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Milan, Italy
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Mazzokun »

Today harder questions:
1) I have a 16 bit WORD value so 0101010100101000 where each 1 or 0 is the status of a 16input/output card.
I tried Data type "no conversion" and "sensor type" text, to record the string of values, but it does't work.
2) I don't want the value 0 in the domoticz sensor if there is an error in reading/conversion, so i commented the pyton script where it says

Code: Select all

  # Devices[1].Update(1, "0") # Set value to 0 (error)
The script itself works and updates corretly the temperature values, but into the log I have an error each time the plugin read modbus value
2021-11-16 18:03:02.794 Error: CELLA 1_T hardware (14) thread seems to have ended unexpectedly
2021-11-16 18:03:02.795 Error: CELLA 2_T hardware (15) thread seems to have ended unexpectedly
Any advice?
Thany you a lot :)
User avatar
andrehj
Posts: 44
Joined: Sunday 06 January 2019 14:26
Target OS: -
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by andrehj »

If you want to read such a value, simply use MBRTU in a script (I use PHP scripts). It is much more flexible.
Since I'm familiar with MBRTU, I only use this Python plugin for Modbus over TCP/IP.
Allras82
Posts: 20
Joined: Thursday 26 October 2017 19:47
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Allras82 »

Hi,

A week ago I've added a modbus rtu to my setup for communication with a ventilation system.
Everything is working, except that I have to restart my domoticz a couple of times each day. It simply freezing.
This I have not seen before the modbus was added.

Anyone experience that too?

I'm at a raspberry pi3 and latest stable of domoticz.


Additionally, is there any way to group the messages? For each value I read from the slave, a new HW is created in domoticz. So this modbus have added 17 new hardware...
Is this maybe a problem, relates to the freezing of domoticz?
User avatar
andrehj
Posts: 44
Joined: Sunday 06 January 2019 14:26
Target OS: -
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by andrehj »

I also had freezes every few days, which have disappeared since I changed to mbrtu (see message above).
Allras82
Posts: 20
Joined: Thursday 26 October 2017 19:47
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Modbus RTU / ASCII / TCP/IP

Post by Allras82 »

Do you have a link to where I can find info about this?
I'm not familiar with it.

Thanks
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest