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

Python and python framework

Moderator: leecollings

User avatar
Domoberry
Posts: 116
Joined: Tuesday 30 May 2017 19:00
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.7
Contact:

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

Post by Domoberry »

Just for the record. My current setup:
- Bullseye on RPI 3B (upgraded from Buster)
- Domoticz 2023.1 (upgraded from 2022.1)
- Python Version: 3.9.2 (no python2)
- pip3 (no pip2)
- pymodbus 2.5.3
- pyModbusTCP 0.1.10
- modbus plugin read v2021.7 (and write 2021.7)
and, read works OK with poll rate of 30 seconds for 5 registers from the same device using RTU (serial).
Yet, to avoid the "Modbus error decoding or received no data" I need to restart the 5 clients with a notable interval each after reboot.
So, not there yet, following some posts above specifically on this issue (which I did not have in Domoticz 2022.1 and Buster).
User avatar
Domoberry
Posts: 116
Joined: Tuesday 30 May 2017 19:00
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.7
Contact:

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

Post by Domoberry »

Update
Observations (I'm using 5 modbus client in Domoticz to read 5 values from the same device using RTU over USB):
(1)
- after a Domoticz restart, the 'onHeartbeat' calls in the log are all within a few hundred milliseconds
- this seems to cause the Modbus Read script to throw two errors (for each of the Modbus read attempts):
- Error: EVSE-voltage-B: Modbus error decoding or received no data (RTU/ASCII/RTU over TCP)!, check your settings!
originating from the section 'DECODE DATA TYPE' in the Modbus Read script
- Error: EVSE-voltage-B: Modbus error decoding or received no data!, check your settings!
originating from the section 'DECODE DATA VALUE' in the Modbus Read script
- as suggested by T1NKB, the Modbus script receiving None or Null (from calling pymodbus) can cause this, which in turn could be caused by the virtually simultaneous onHeartbeat calls
- if the onHeartbeat calls are at least 1 second apart, things seem to work ok
- I did not observe the problem when previously using Domoticz 2022.2 and Buster
(2)
- if I restart the 5 Modbus Clients in the Domoticz setup/hardware screen (by clicking 'Update') with an interval of say 5 seconds each, all works fine
- however, it seems that after some 3 days the Domoticz web UI stops working - this could have another cause
(3)
- adding a random delay between 1 and 3 seconds in the 'OnStartUp' sections of the Modbus Read script does not help
(and this is likely violating a basic rule for Domoticz plugins: do not code any delays)
(4)
- adding a random delay between 1 and 3 seconds in the 'OnHeartbeat' sections of the Modbus Read script does not help and in fact causes issues with Domoticz (probably because I'm violating a basic rule for Domoticz plugins: do not code any delays)
(5)
- changing the polling interval for each of the 5 Modbus Read clients with 2 seconds difference does what you would expect: the number of errors drops an more or less randomly appears when two of the Modbus Read onHeartbeat call coincidentally are within a few hundred milliseconds
- I did not check if in this case Domoticz UI also fails after ~3 days

I'm currently without any ideas and wonder if there was anything changed in the Domoticz plugin framework from 2022.2 to 2023.1 which could be related. Underlying question: why is the Modbus Read client not working as before?
Anyone who can recommend an alternative Domoticz - Modbus solution (which would be within my limited technical reach)?
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

I can confirm that 2023.1 on Buster still has this issue, disabling the hardware and re-enabling one at a time resolves this until the next reboot. I guess me restarting them put them several seconds apart. I can't blame the python version or the modbus script as it works without error. It must be the way Domoticz is handling these scripts that is the problem


2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/plugin.py", line 134, in onHeartbeat
2023-03-30 19:48:40.073 Error: SDM120M-ID7: _plugin.onHeartbeat()
2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/plugin.py", line 85, in onHeartbeat
2023-03-30 19:48:40.073 Error: SDM120M-ID7: Total_System_Power = self.rs485.read_float(12, functioncode=4, numberOfRegisters=2)
2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/minimalmodbus.py", line 392, in read_float
2023-03-30 19:48:40.073 Error: SDM120M-ID7: return self._genericCommand(functioncode, registeraddress, numberOfRegisters=numberOfRegisters, payloadformat='float')
2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/minimalmodbus.py", line 697, in _genericCommand
2023-03-30 19:48:40.073 Error: SDM120M-ID7: payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/minimalmodbus.py", line 795, in _performCommand
2023-03-30 19:48:40.073 Error: SDM120M-ID7: response = self._communicate(request, number_of_bytes_to_read)
2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/minimalmodbus.py", line 857, in _communicate
2023-03-30 19:48:40.073 Error: SDM120M-ID7: self.serial.open()
2023-03-30 19:48:40.073 Error: SDM120M-ID7: File "/home/pi/domoticz/plugins/SDM120Modbus/serial/serialposix.py", line 261, in open
2023-03-30 19:48:40.073 Error: SDM120M-ID7: raise SerialException("Port is already open.")
2023-03-30 19:48:40.073 Error: SDM120M-ID7: serial.serialutil.SerialException: Port is already open.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
User avatar
Domoberry
Posts: 116
Joined: Tuesday 30 May 2017 19:00
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.7
Contact:

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

Post by Domoberry »

Thanks Simat for your update!
Do I understand correctly that you have multiple instances of the https://github.com/bbossink/SDM72D-Modb ... /plugin.py plugin running and that this worked OK in a pre-2023.1 Domoticz release? If so, out of curiosity, which Domoticz version handled the plugin still ok in your case?
That would move the focus to 'something' which has changed in Domoticz (in the plugin framework?).
(I moved from 2022.1 to 2023.1 and from Buster to Bullseye at virtually the same time, so could not conclude on which change caused the issue)
Also, since the issue you posted is based on a plugin using the 'minimalmodbus' library, whereas in my case the 'pymodbus' library is used, it seems to rule out the pymodbus library as main cause of the problem.
I'm currently using only one pymodbus based plugin in Domoticz, which is running OK for 4 days now. This plugin reads only one modbus register per Domoticz plugin, hence I normally use several to read the various values from my energy meter (pwr, energy, voltage L1, voltage L2, voltage L3, etc.)

:?: Any Domoticz expert (on the plugin framework) able to chime in? Am I looking at a potential bug or a breaking change I missed out on?
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

Hi,

Yes, actually this one https://github.com/remcovanvugt/SDM120M ... icz-plugin I have 5 instances running to several Eastron SDM120M. I started having problems in 2022 and the date on the plugin.py file that I made several edits to is December 2021, so the version will be around then. I think 2021.1 was the last working version maybe 2022.1, certainly 2022.2 had the issue. This is on a Rasp Pi 4 with Buster and the plugin stopped working correctly on startup after an upgrade of Domoticz only.

I'm pretty sure its not the python version as this code works onces you've disabled all of modbus plugins and then started them one at a time.

Someone in another post had mentioned maybe Domoticz now runs the plugsin in paraellel which would explain the serial port getting locked and then not getting locked once you'd started them in a staggered manner.

I'd modified my SDM120 plug to display both the Energy Usage and Power Usage on the same chart.

Cheers

S.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
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 »

Yes, 2021.1 was the last working version. I had the above issues too and although I looked into it to try and find out why this was happening, I just decided to run a 2021.1 version of Domoticz. In my case this is possible because I run this plugin on a dedicated remote server. It doesn't influence the running of any other plugins of which you want the latest versions.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

I'd like to go back to 2021.1 but I'm on the latest version now and i think a migration of the database back to 2021.1 would be very difficult. I have a lot of useful historical data in Domoticz so starting again isn't an attractive option. I wonder if the energy tables have changed structure, i only have energy and temperature data, might be do able but fixing the latest version is the better option.

S.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

Going back to a previous version might be possible, from what I can see only the following tables have changed / are new between 2021.1 and 2023.1

Applications
Cameras
EnOceanNodes
Notifications
UserVariables

S.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

Hi all,

I have gone back to Domoticz 2021.1, this is with 32 bit Bullseye Lite with Python 3.9.2, OWFS, PHP 7.4.33, Influx 1.8.10, Grafana 9.4.7 on a Pi4 4GB with a 32GB Sandisk Industrial SLC SDcard.

All works fine now, the Modbus plugin based on this https://github.com/remcovanvugt/SDM120M ... icz-plugin works fine.
I have 6 x SDM120M connected to a USB FTDI to RS485 Modbus adapter, all plugin instances start without problem.

As i had to build Domoticz 2021.1 from the source as a compiled executable isn't included, I took the time to edit 1Wire.cpp and 1WireByOWFS.cpp so it didn't return a zero if it read a null.

I didn't mess around with the Database, only reduced the version number in preference table to 148.

Does anyone know if its possible to get those edits made in the main distro ? I guess no one is maintaining the 1-wire side as its so old now. :(

OWFS also works fine without having to do a modprobe fuse.

Cheers

Simon.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
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 »

Good work Simon. I too had to change the preference table in the database with SQlite. Changed it back to 148 too. Seeing as you are using a different Modbus plugin than I am (a repo from user Domoticx), it seems the problems I was having with Modbus and the latest Domoticz version wasn't to blame on the plugin (which is where I was initially looking for the problem until I decided to downgrade Domoticz). For some reason Domoticz isn't friendly with one of the Python modules for Modbus anymore.
Hue | Zigbee2Mqtt | MQTT | P1 | Xiaomi | RFXCom | Modbus | Qlima | Solaredge
TP-Link | Plugwise | Thermosmart | Node-Red | Grafana | Master and 5 remote servers
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

BUG submitted to Github under - https://github.com/domoticz/domoticz/issues/5671 as there is no further action this forum can take.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

After i wee bit a fiddling around, i've found a bodge maybe. On my own build of 2023.1 i've added a 1 second delay in CPlugin::StartHardware() within hardware/Plugins.cpp

`bool CPlugin::StartHardware()
{
if (m_bIsStarted)
StopHardware();

RequestStart();

// Flush the message queue (should already be empty)
{
std::lock_guard<std::mutex> l(m_QueueMutex);
while (!m_MessageQueue.empty())
{
m_MessageQueue.pop_front();
}
}

// Start worker thread
try
{
std::lock_guard<std::mutex> l(m_QueueMutex);

sleep_milliseconds(1000); // ** LOAD PLUGINS 1sec APART **

m_thread = std::make_shared<std::thread>(&CPlugin::Do_Work, this);
if (!m_thread)
{
Log(LOG_ERROR, "Failed start interface worker thread.");
}
else
{
SetThreadName(m_thread->native_handle(), m_Name.c_str());
Log(LOG_NORM, "Worker thread started.");
}
}`
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

Updated and tested plugin now available on

https://github.com/simat-git/SDM120-Modbus

Works with Domoticz 2023.1, now just takes a few minutes to initially allocate each instance to its own timeslot, will also recover from bus disconnection and re-time itself. The previous plugin would error until manual intervention / reset.

Not sure how much interest there is to fix the Modbus RTU / ASCII / TCP/IP Plugin ?? that would have to use either a variable in shared memory to form a lock, or a file in a tmpfs mount.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

Regarding the missing module pymodbus.client.sync when using this plugin on Bullseye with Python > 3.7 (3.9.2 in my case )and Domoticz 2023.1 - just edit the plugin.py and change

pymodbus.client.sync to pymodbus.client

Code: Select all

from pymodbus.client import ModbusSerialClient # RTU
from pymodbus.client import ModbusTcpClient    # RTU over TCP
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
marcin81233
Posts: 3
Joined: Saturday 06 May 2023 20:54
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

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

Post by marcin81233 »

Can someone help me convert the plugin so that it downloads data from the deye inverter?
simat
Posts: 33
Joined: Thursday 04 November 2021 21:17
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.1
Location: UK
Contact:

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

Post by simat »

Is your inverter Modbus RTU or Modbus TCP ?

Someone suggested that the Deye Inverter is the same as Sol-Ark ?

https://diysolarforum.com/threads/sol-a ... ing.23717/

Either way the Modbus RTU/ASCI/TCP plugin mentioned in this thread should do the trick without modification, you just need to know the modbus slave ID, register address and data type for starters.
Raspberry Pi4, Sunny Boy 4000TL, Victron Multiplus II 10kw ESS, 44kWh LiFEPO4, Batrium BMS, NodeRED on Cerbo GX
User avatar
Domoberry
Posts: 116
Joined: Tuesday 30 May 2017 19:00
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.7
Contact:

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

Post by Domoberry »

Update: I have created a "derivative" plugin for the Sinotimer DDS024MR 3 phase energy meter, based on the plugin here https://github.com/MFxMF/SDM630-Modbus. This plugin uses the modbus library from https://github.com/pyhys/minimalmodbus. This "solves" the problem I had with the DomoticX based version as it this plugin downloads all required data in one Heartbeat.
A disadvantage is that this plugin does not have all the features and flexibility the DomoticX one offers, but in my case it does the job perfectly.
If your device is Modbus RTU and you want to read only from the device, it is probably reasonable straightforward to create another derivative plugin for it.
The approach is similar to what simat has done here: https://github.com/simat-git/SDM120-Modbus

This is the 1.0.7 plugin (working, but in progress), please be warned that I have limited Python/plugin experience... Kudos for MFxMF for the source!
Edit: minor tweaks, runInterval now in 10 sec increments. Updated plugin code v1.0.8 below.
I'm using Domoticz 2023.1, Bullseye, Python 3.9.2

Code: Select all

#!/usr/bin/env python
#changelog
# 230511 1.0.7 Device name corrected to DDS024MR
# 230518 1.0.8 improved description and implemented 'reading interval' in seconds, default 60
#todo
# 230511 are the '+' operators in the update of the current devices really needed? (Copied from SDM630 plugin)
# 230518 need some extra spaces in the <description> below &nbsp; and &#160; do not seem to work, I use a dash (-) instead for now.
"""
Sinotimer DDS024MR Modbus Smart Meter Three Phase Electrical System. The Python plugin for Domoticz
Original author: MFxMF and modified by: Domoberry
Requirements: 
    1.python module minimalmodbus -> http://minimalmodbus.readthedocs.io/en/master/
        (pi@raspberrypi:~$ sudo pip3 install minimalmodbus)
    2.Communication hardware module Modbus USB to RS485 converter module
"""
"""
<plugin key="DDS024MR" name="Sinotimer DDS024MR-Modbus v1.0.8" version="1.0.8" author="Domoberry">
    <description>
        <h3>Modbus plugin for Sinotimer DDS024MR energy meter v1.0.8</h3>
        This plug in will read the most relevant data from this din-rail 3-phase energy meter.<br/>
        It is based on the 'minimalmodbus' and 'pyserial' Python libraries.
        See -<a href="https://github.com/pyhys/minimalmodbus">Minimalmodbus Github</a>- and -<a href="https://minimalmodbus.readthedocs.io/">Minimalmodbus Read the Docs</a>- for more information.<br/>
        This plugin is derived from the -<a href="https://github.com/MFxMF/SDM630-Modbus">SDM630 energy meter plugin</a>- by MFxMF<br/>
        <br/>
        <h4>Some details</h4>
        Data obtained from the DDS024MR includes:
        <ul><li>Voltage, current, and power for each phase</li>
        <li>Total power</li>
        <li>Mains frequency</li>
        <li>Accumulated energy used</li></ul>
        <br/>
        <h4>Limitations</h4>
        <ul><li>The DDS024MR provides some additional values which can be added by modifying the plugin.</li>
        <li>Reading interval is set in seconds, yet interpreted as multiple of 10 seconds (the "heartbeat" interval).</li>
        <li>A reading interval 0 will result in updates every "heartbeat" of the system.</li>
        <li>Only -<b>one</b>- of these plugins can be active at any given time to avoid a possible conflict using the serial port.</li></ul>
    </description>
    <params>
        <param field="SerialPort" label="Modbus Port" width="400px" required="true" default="/dev/ttyUSB0" />
        <param field="Mode1" label="Baud rate" width="40px" required="true" default="9600" />
        <param field="Mode2" label="Device ID" width="40px" required="true" default="1" />
        <param field="Mode3" label="Reading Interval (seconds)" width="40px" required="true" default="60" />
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>

"""

import minimalmodbus
import serial
import Domoticz #this is hence a 'legacy' Domoticz plugin


class BasePlugin:
    def __init__(self):
        self.runInterval = 1 #read modbus every n time(s) onHeartbeat is called
        self.rs485 = "" 
        return
    
    def onStart(self):
        self.rs485 = minimalmodbus.Instrument(Parameters["SerialPort"], int(Parameters["Mode2"])) #Mode2 = modbus device ID
        self.rs485.serial.baudrate = Parameters["Mode1"] #DDS024MR: supports max 9600 baud
        self.rs485.serial.bytesize = 8 #DDS024MR: bytesize = 8
        self.rs485.serial.parity = minimalmodbus.serial.PARITY_EVEN #DDS024MR: parity even
        self.rs485.serial.stopbits = 1 #DDS024MR: stopbits 1
        self.rs485.serial.timeout = 0.2 #200 msecs
        self.rs485.debug = False
        self.rs485.mode = minimalmodbus.MODE_RTU #DDS024MR: uses RTU
        devicecreated = []
        Domoticz.Log("Sinotimer DDS024MR Modbus plugin start")
        
        if Parameters["Mode6"] == 'Debug':
            Domoticz.Log(self.rs485) # show current settings in log
        
        self.runInterval = int(Parameters["Mode3"])//10 #onHeartbeat runs every 10 secs
        
        if 1 not in Devices:
            Domoticz.Device(Name="Voltage L1", Unit=1,TypeName="Voltage",Used=0).Create()
        if 2 not in Devices:
            Domoticz.Device(Name="Voltage L2", Unit=2,TypeName="Voltage",Used=0).Create()
        if 3 not in Devices:
            Domoticz.Device(Name="Voltage L3", Unit=3,TypeName="Voltage",Used=0).Create()
        if 4 not in Devices:
            Domoticz.Device(Name="Current L1,2,3", Unit=4,TypeName="Current/Ampere",Used=0).Create()
        if 5 not in Devices:
            Domoticz.Device(Name="Power L1", Unit=5,TypeName="Usage",Used=0).Create()
        if 6 not in Devices:
            Domoticz.Device(Name="Power L2", Unit=6,TypeName="Usage",Used=0).Create()
        if 7 not in Devices:
            Domoticz.Device(Name="Power L3", Unit=7,TypeName="Usage",Used=0).Create()
        if 8 not in Devices:
            Domoticz.Device(Name="Total Power", Unit=8,TypeName="Usage",Used=0).Create()
        Options = { "Custom" : "1;Hz"}
        if 9 not in Devices:
            Domoticz.Device(Name="Mains Frequency", Unit=9,TypeName="Custom",Used=0,Options=Options).Create()
        if 10 not in Devices:
            Domoticz.Device(Name="Total Energy", Unit=10,Type=0x71,Subtype=0x0,Used=0).Create()
    
    def onStop(self):
        Domoticz.Log("Sinotimer DDS024MR Modbus plugin stop")
    
    def onHeartbeat(self):
        self.runInterval -=1; #WH decrease runInterval by 1; modbus will be read as soon as <= 0
        if self.runInterval <= 0:
            # Get data from DDS024MR
            try:
                Domoticz.Log("Reading Modbus data from Sinotimer DDS024MR...")
                # WH since minimalmodbus V1.00 "numberOfRegisters" shall be replaced with "number_of_registers"
                Volts_L1 = self.rs485.read_float(0, functioncode=4, number_of_registers=2)
                Volts_L2 = self.rs485.read_float(2, functioncode=4, number_of_registers=2)
                Volts_L3 = self.rs485.read_float(4, functioncode=4, number_of_registers=2)
                Current_L1 = self.rs485.read_float(8, functioncode=4, number_of_registers=2)
                Current_L2 = self.rs485.read_float(10, functioncode=4, number_of_registers=2)
                Current_L3 = self.rs485.read_float(12, functioncode=4, number_of_registers=2)
                Active_Power_L1 = self.rs485.read_float(18, functioncode=4, number_of_registers=2)
                Active_Power_L2 = self.rs485.read_float(20, functioncode=4, number_of_registers=2)
                Active_Power_L3 = self.rs485.read_float(22, functioncode=4, number_of_registers=2)
                Total_System_Active_Power = self.rs485.read_float(16, functioncode=4,number_of_registers=2)
                Frequency_Of_Supply_Voltages = self.rs485.read_float(54, functioncode=4, number_of_registers=2)
                Total_kwh = self.rs485.read_float(256, functioncode=4, number_of_registers=2)
            except: #WH in case any code in 'try' raises an exception, below is executed:
                Domoticz.Log("Connection problem");
            else: #WH: in case no exception, below is executed
                
                #Update Domoticz devices. Using ("%0.2f" % variable) to limit number of decimals and convert to string
                Domoticz.Log("Updating devices with Sinotimer DDS024MR data...")
                Devices[1].Update(0,("%0.1f" % Volts_L1))
                Devices[2].Update(0,("%0.1f" % Volts_L2))
                Devices[3].Update(0,("%0.1f" % Volts_L3))
                Devices[4].Update(0,("%0.1f" % Current_L1)+";"+("%0.1f" % Current_L2)+";"+("%0.1f" % Current_L3))
                Devices[5].Update(0,("%0.1f" % Active_Power_L1))
                Devices[6].Update(0,("%0.1f" % Active_Power_L2))
                Devices[7].Update(0,("%0.1f" % Active_Power_L3))
                Devices[8].Update(0,("%0.1f" % Total_System_Active_Power))
                Devices[9].Update(0,("%0.2f" % Frequency_Of_Supply_Voltages))
                Devices[10].Update(0,str(Total_kwh*1000))
                
            if Parameters["Mode6"] == 'Debug':
                Domoticz.Log("Sinotimer DDS024MR Modbus Data:")
                Domoticz.Log('Voltage L1: {0:.3f} V'.format(Volts_L1))
                Domoticz.Log('Voltage L2: {0:.3f} V'.format(Volts_L2))
                Domoticz.Log('Voltage L3: {0:.3f} V'.format(Volts_L3))
                Domoticz.Log('Current L1: {0:.3f} A'.format(Current_L1))
                Domoticz.Log('Current L2: {0:.3f} A'.format(Current_L2))
                Domoticz.Log('Current L3: {0:.3f} A'.format(Current_L3))
                Domoticz.Log('Power L1: {0:.3f} W'.format(Active_Power_L1))
                Domoticz.Log('Power L2: {0:.3f} W'.format(Active_Power_L2))
                Domoticz.Log('Power L3: {0:.3f} W'.format(Active_Power_L3))
                Domoticz.Log('Total power: {0:.3f} W'.format(Total_System_Active_Power))
                Domoticz.Log('Frequency of supply voltages: {0:.3f} Hz'.format(Frequency_Of_Supply_Voltages))
                Domoticz.Log('Total kWh: {0:.3f} kWh'.format(Total_kwh))
                
            self.runInterval = int(Parameters["Mode3"])//10 # reset runInterval after reading modbus

global _plugin
_plugin = BasePlugin()

def onStart():
    global _plugin
    _plugin.onStart()

def onStop():
    global _plugin
    _plugin.onStop()

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
marcin81233
Posts: 3
Joined: Saturday 06 May 2023 20:54
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

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

Post by marcin81233 »

simat wrote: Sunday 07 May 2023 9:57 Is your inverter Modbus RTU or Modbus TCP ?

Someone suggested that the Deye Inverter is the same as Sol-Ark ?



Either way the Modbus RTU/ASCI/TCP plugin mentioned in this thread should do the trick without modification, you just need to know the modbus slave ID, register address and data type for starters.
I'm a novice in such matters. Could you write what I should enter in the appropriate fields in domoticz from this frame?
Attachments
Zrzut ekranu z 2023-06-11 12-07-02.png
Zrzut ekranu z 2023-06-11 12-07-02.png (274.68 KiB) Viewed 2597 times
Bez tytułu 1.pdf
(241.15 KiB) Downloaded 75 times
PieterS
Posts: 195
Joined: Wednesday 31 May 2017 16:06
Target OS: NAS (Synology & others)
Domoticz version: 2024.7
Location: NL
Contact:

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

Post by PieterS »

Alain wrote: Saturday 08 April 2023 8:59 Yes, 2021.1 was the last working version. I had the above issues too and although I looked into it to try and find out why this was happening, I just decided to run a 2021.1 version of Domoticz. In my case this is possible because I run this plugin on a dedicated remote server. It doesn't influence the running of any other plugins of which you want the latest versions.
I investigate the posibility of buying a kWh-meter with Modbus. Especialy a Eastron SDM 630 V2. Goal is to read how much energy is loaded into my EV. But reading this thread it seems not that easy with Domoticz.

@Alain:
Can you explain how you configure it to run the plugin on a remote server?
How do you export the results of the measurements to Domoticz?

I am very interested. Thanks in advance.
Synology with Domoticz build (V2024.7) in Docker
User avatar
Domoberry
Posts: 116
Joined: Tuesday 30 May 2017 19:00
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.7
Contact:

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

Post by Domoberry »

Hi PieterS,
I'm currently using a 3 phase energy meter from Sinotimer, model DDS024MR (about 50-60E) with Domoticz to read data from my EV wallbox. It uses minimalmodbus (v2.0.1) and Python (v3.9.2) on Domoticz v2023.1 running on an Bullseye/RPI3B. It provides Domoticz devices for line voltages, currents and power, as well as total power, total energy and main frequency, all obtained from the DDS024MR. For the interface between DDS024MR modbus and RPI USB, I used a simple Modbus/RS485 to USB dongle.
I derived the plugin from the nice work done by others for the Eastron SDM630 https://github.com/MFxMF/SDM630-Modbus and Eastron SDM120 https://github.com/remcovanvugt/SDM120M ... icz-plugin. This was a good learning experience :-)
Originally I used the (much more sophisticated) plugins from DomoticX https://github.com/DomoticX/domoticz-modbus, but with the introduction of Domoticz 2023.1, some issue emerged which rendered this plugin problematic on Domoticz 2023.1 (see above for more details).
The Eastron SDM630 plugin on Github is by now some 4 years old and some small changes are needed as for example minimalmodbus has introduced a breaking change post v1.0.0. By comparing the SDM630 plugin with the DDS024MS one (see post in May), one should be able to revive the SDM630 plugin. Obviously, you can also revert to the DSS024MR energy meter. This is a less featured device compared to the SDM630, but could perhaps already provides the data you need. I can share some documentation if you want. Disclaimer: this is my first plugin ever ...
Note that there are also different approaches to solve the DomoticX 'problem', see https://github.com/domoticz/domoticz/issues/5671
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest