Page 1 of 1

32 bit modbus data with MQTT

Posted: 01 Jun 2019, 04:21
by KoenW
Hi guys,

First of all, thank you for the RevpiModio and PyPLCControl - great job.

I have a project with 32 bit data retrieved over Modbus RTU. This comes in on 2 Modbus registers, with two bytes in each. I am trying to publish this by MQTT, but the problem is that the MQTT publishes this as 2 messages - 1 per modbus word. Putting these back together afterwards is risky - I can never guarantee that the two messages belong together. Perhaps 1 message was lost or delayed and I recombine two messages from a different original 32bit datapoint, which leads to wrong outputs.

If I wanted to publish the 32 bit data as a single MQTT message, how would I do that? Do I need to write my own script in PyControl? Can I modify your MQTT script?

Many thanks,
Koen

Re: 32 bit modbus data with MQTT

Posted: 01 Jun 2019, 21:05
by RevPiModIO
Hi Koen!

I like your idea! Our MQTT-Server is based on RevPiModIO2 and in that library you can define own IOs via .replace_io(...). But I did not implement that in RevPiPyLoad till now ;) !

Maybe it would be cool, if the user can define such IOs in a config file. All the work is done by RevPiModIO2 (it is already implementet), which spans the new 4 Byte long IO across 4 Bytes / or 2 Words. RevPiPyLoad could load that information and will publish this IOs how ever you define them (size / byteorder)... Another interesting thing would be, that RevPiPyControl (our GUI) loads the same data and would display that value in the IO-Watch-List...

If you have some time, I will work on that and it would be nice, if you could test that new Software ??? I try to build a beta till Tuesday! :D

Regards, Sven

---------------------------------------
Of course you could modify our "revpipyload/mqttserver.py" and use .replace_io(...), but that will be very static and would fail if the IO names changed in piCtory.
Check out our documentation: https://revpimodio.org/doku2/io/#replace_io

Code: Select all

# (...) line 134
        try:
            # Lesend und Eventüberwachung
            self._rpi = revpimodio2.RevPiModIO(
                autorefresh=self._send_events,
                monitoring=True,
                configrsc=proginit.pargs.configrsc,
                procimg=proginit.pargs.procimg
            )
            
            # ADD THIS FOR 32 BIT INTEGER BYTEORDER BIG / OR USE byteorder="little"
            self._rpi.io.MODBUS_IO_NAME.replace_io("new_name", "i", byteorder="big")

            # Schreibenen Zugriff
            if self._write_outputs:
                self._rpi_write = revpimodio2.RevPiModIO(
                    configrsc=proginit.pargs.configrsc,
                    procimg=proginit.pargs.procimg
                )
                
                # DO THE SAME WITH self._rpi_write !!!
                self._rpi_write.io.MODBUS_IO_NAME.replace_io("new_name", "i", byteorder="big")

        except Exception as e:
# (...)

Re: 32 bit modbus data with MQTT

Posted: 02 Jun 2019, 12:40
by KoenW
Hi Sven,

I will try with the modification of the MQTT py script. Although I am not a top gun with python.

Your idea with a configurable mqtt server sounds great. If you make a beta, I will happily test it. ;)

Vielen dank,
Koen

Re: 32 bit modbus data with MQTT

Posted: 05 Jun 2019, 10:24
by KoenW
Hi Sven,

I tried modifying "revpipyload/mqttserver.py" per your recommendation - but no success. I added your suggestion - see below. I tried to combine modbus words MRTU_IW81 and MRTU_IW82 into MRTU_IWnew. Once I did the modification of mqttserver.py, I rebooted the RevPi and used piTest -v MRTU_IWnew to see if it knew the variable - no success. I also had a look at any MQTT message with MRTU_IWnew in the topic - no luck. MQTT gets published every 10sec, so something should be there if it existed.

What could I be doing wrong?

Code: Select all

# (...) line 134
        try:
            # Lesend und Eventüberwachung
            self._rpi = revpimodio2.RevPiModIO(
                autorefresh=self._send_events,
                monitoring=True,
                configrsc=proginit.pargs.configrsc,
                procimg=proginit.pargs.procimg
            )
            
            # ADD THIS FOR 32 BIT INTEGER BYTEORDER BIG / OR USE byteorder="little"
            self._rpi.io.MRTU_IW81.replace_io("MRTU_IWnew", "i", byteorder="big")

            # Schreibenen Zugriff
            if self._write_outputs:
                self._rpi_write = revpimodio2.RevPiModIO(
                    configrsc=proginit.pargs.configrsc,
                    procimg=proginit.pargs.procimg
                )
                
                # DO THE SAME WITH self._rpi_write !!!
                self._rpi_write.io.MRTU_IW81.replace_io("MRTU_IWnew", "i", byteorder="big")

        except Exception as e:
# (...)

UPDATE:
I found this in the log and the MQTT publisher is not running :
2019-06-05 19:18:14 [WARNING ] can not load revpimodio2 module. maybe its not installed or an old version (required at least 2.5.0). if you like to use the mqtt feature, update/install revpimodio2: 'apt-get install python3-revpimodio2'
I wonder what is the issue?
I tried using the .io_replace function in a python shell, and that seems to work well. Somehow modifying the mqttserver.py file is throwing errors.
I also did the recommendation from the error: sudo apt-get install python3-revpimodiuo2, but that made no difference.

:?:

UPDATE-2:
I have now added a modified version a bit lower in the mqttserver.py, and that seems to work - see below.

That will get me out of trouble - still very keen to see the GUI with this functionality if you have time!

Code: Select all

# (...) line 191

        # Add modbus 32bit data
        try:
            self._rpi.io.MRTU_IW81.replace_io("MRTU_IWnew", "i", byteorder="little")
            self._rpi.io.MRTU_IWnew.reg_event(self._evt_io)
            self._exported_ios.append(self._rpi.io.MRTU_IWnew)

        except Exception as e:
            proginit.logger.error(
                "32bit configuration not loadable for MQTT"
            )
            raise e

        proginit.logger.debug("created revpimodio2 object")
        
# (...)

Thank you,
Koen



RevPiModIO wrote: 01 Jun 2019, 21:05 Hi Koen!

I like your idea! Our MQTT-Server is based on RevPiModIO2 and in that library you can define own IOs via .replace_io(...). But I did not implement that in RevPiPyLoad till now ;) !

Maybe it would be cool, if the user can define such IOs in a config file. All the work is done by RevPiModIO2 (it is already implementet), which spans the new 4 Byte long IO across 4 Bytes / or 2 Words. RevPiPyLoad could load that information and will publish this IOs how ever you define them (size / byteorder)... Another interesting thing would be, that RevPiPyControl (our GUI) loads the same data and would display that value in the IO-Watch-List...

If you have some time, I will work on that and it would be nice, if you could test that new Software ??? I try to build a beta till Tuesday! :D

Regards, Sven

---------------------------------------
Of course you could modify our "revpipyload/mqttserver.py" and use .replace_io(...), but that will be very static and would fail if the IO names changed in piCtory.
Check out our documentation: https://revpimodio.org/doku2/io/#replace_io

Code: Select all

# (...) line 134
        try:
            # Lesend und Eventüberwachung
            self._rpi = revpimodio2.RevPiModIO(
                autorefresh=self._send_events,
                monitoring=True,
                configrsc=proginit.pargs.configrsc,
                procimg=proginit.pargs.procimg
            )
            
            # ADD THIS FOR 32 BIT INTEGER BYTEORDER BIG / OR USE byteorder="little"
            self._rpi.io.MODBUS_IO_NAME.replace_io("new_name", "i", byteorder="big")

            # Schreibenen Zugriff
            if self._write_outputs:
                self._rpi_write = revpimodio2.RevPiModIO(
                    configrsc=proginit.pargs.configrsc,
                    procimg=proginit.pargs.procimg
                )
                
                # DO THE SAME WITH self._rpi_write !!!
                self._rpi_write.io.MODBUS_IO_NAME.replace_io("new_name", "i", byteorder="big")

        except Exception as e:
# (...)

Re: 32 bit modbus data with MQTT

Posted: 16 Jun 2019, 17:15
by RevPiModIO
Hi KoenW!

I am so sorry about the long time till my response! Nice to hear, that you have a first solution to work with MQTT.

I started to implement some new features to RevPiModIO2 and the RevPiPyLoad system. If it all worked together you should be able to create/edit a file with the replace_io definition, for example:

Code: Select all

# Replace IO

[MRTU_IW81]
replace = MRTU_IW81
frm = i
byteorder = little

[p_online]
replace = p_byte1
frm = ?
bit = 0

[p_onoff]
replace = p_byte1
frm = ?
bit = 1

RevPiModIO will be able to use this file and replace the IOs in the Python program. Of course RevPiPyLoad will also use this data, it's based on RevPiModIO. So everything is working with the same replaced_ios, the python program, the MQTT System, die RevPiPyControl System to watch the data aaaaaand so on :D

I have an early beta, which is working, BUT you have to restart the revpipyload service after editing the replace_io.conf file... I'm sill working on that ;)

First (stable): https://revpimodio.org/dnl/python3-revp ... -1_all.deb
Second (beta): https://revpimodio.org/dnl/revpipyload_0.7.6-1_all.deb

For RevPiPyLoad, there is a modified config file, if you use your old one, you have to add this to the DEFAULT section - and enter you replace_io stuff to the replace_ios.conf:

Code: Select all

[DEFAULT]
replace_ios = /etc/revpipyload/replace_ios.conf

Sven

Re: 32 bit modbus data with MQTT

Posted: 21 Jun 2019, 02:43
by KoenW
Thank you Sven,

I will have a look at the beta one of these days. We are just implementing a project with a client and I will also be on holiday for a few weeks - so I might not get back to you until late July.

Many many thanks again - Vielen dank.

Koen