Modbus data to iDigi

Has anyone connected a modbus rtu device to capture data in iDigi? Basically, I want to upload a power meter’s data up through a Digi rs485 to zigbee adaptor into a connectport X4 gateway and have the data available in iDigi. I understand how to receive the data into the connectport, but need help on how to configure dia to send it up to iDigi.

Any suggestions would be appreciated.

It is moving along - I have my code reading two Modbus/TCP (ethernet-based) servers from an X4 every few seconds, which creates float or int channels named things like motor01_current, or motor02_speed.

Since the Dia Code talks via the normal Digi Modbus bridge/engine, it will work with Modbus/TCP in TCP or UDP, plus Modbus/RTU or Modbus/ASCII in TCP, UDP, serial or Xbee.

I am gearing it more towards normal cellular (less at Xbee) since combined with my ‘filter-device’ it would make a great report-by-exception tool for waste-water, lift pumps etc - only moving changes and perhaps a daily ‘refresh’ via cellular.

(Should have sample code to share by Thu or Fri this week)

I have complex experimental code which does some of this, but what piece are you actually needing? If you are already pulling Modbus data into the CP, how is that being done? Have you written Dia drivers before?

Thanks

  • Lynn

What is the volume of data that you anticipate? In particular, at what frequency do you expect to obtain new samples? Is the most recent sample the only thing that is interesting to be available from iDigi, or is there a desire to support some form of change tracking directly from iDigi?

I’m curious how you hope to map the data to services that can be provided by iDigi.

To be more specific, I want to link up a Conzerv EM 6433 power meter using a Digi rs485 Adapter to the ConnectPort X4. I don’t have any code yet, I was referring to the ModBus serial settings on the CX4 that already exist. It appears that the CX4 can map the ZigBee links to pass the ModBus registers through the serial port interface to a python driver that I have to write.

Ideally, I would like to get 5 second samples of certain registers, such as Voltage, Amps, and KwH at a minimum. I only plan to have the latest reading on iDigi. I can store the data elsewhere if I need to keep track of it over time. The end result is a sort of web virtual meter that gets updated by requesting the latest record from iDigi via the web service.
There is a Modbus Register mapping sample on the Wiki, but I would still have to write a DIA driver to poll the Meter, I presume, but have not written a driver from scratch.

So, I think what I need is a DIA driver that polls the meter via the RS485 adapter and retrieves the needed register data. That data becomes a “channel” like some of the examples that I can configure for the cws-exist upload.

I see, I’ll try to clean up one of my code samples to allow a serial Modbus poll (which returns a word array) to be parsed/chopped up into “Published Dia channels”.

You are correct that the X4 can manage Modbus external to Python, however I’d probably ‘de-couple’ the poll. So on some schedule a driver would send a poll and time-stamp the send but not wait for a response, then any response which seemed to match the outstanding request could be parsed into published channels.

Do you desire allow a remote Modbus/TCP master to query the power meter freely “in parallel” to the Python? If yes, then we need to allow the Modbus engine to “own” the raw serial channel (end-point 232) out of the X4. Otherwise we can allow Python to manage that.

Awesome! Sounds like you’ve done this before. Due to my lack of ModBus experience, I need to ask a question:
Can the Slave RTU (Meter) be set to just transmit the register values periodically? This would be a “push” rather than a “pull” via a poll. If so, then I would just have to send a command initially to set the push timing.

If not, then your suggestion sounds fine to allow the Python driver to send the poll based on a programmable schedule.

I was thinking of using RCI to set/get values from the slave device for diagnostics. Having direct remote Modbus TCP control sounds easier. Although I expect the meter to be passive, it has several features that would be nice to set/get remotely without having to write python code, I could then connect to the Cx4 via a ModBus program on my computer (seems to be many available) and have direct access to the meter. I think the iDigi TCP/IP mapping would allow me to do that correct?

What do you think is better from a flexibility standpoint, RCI or Remote Modbus?

Thanks again for all your help!

Generally, Modbus ‘server/slaves’ can never create messages so must be polled by brute-force, for example every few seconds. Big users shift to DNP3 or BACNET or other newer protocols when ‘report-by-exception’ data comms are desired. Keep in mind there is no graceful way to mix push/pull on the same serial line - however some higher-end Ethernet-based devices can be both master and slave. Also, many users use small local “operator-panels” to both display the local device info polled by brute-force via Modbus, and also to push data up-stream by other protocols or as a Modbus master.

My code would start as read-only, writing to control systems can be a dangerous task & generally requires a direct write-then-readback in realtime which isn’t so easy in widely dispursed, abstracted networks.

Personally I’d rather use iDigi to upload periodic data long-term in cyclic, less-than-realtime and use Modbus/TCP direct via cellular/DSL/broadband to “set” things in real-time & confirm the effect.

OK,
Thank makes sense. Let me know when you have a version I can start testing.
Regards,
Andy

Hi Lynn,

No hurry, just checking in on the code you mentioned. It would be great to be able to test this weekend :slight_smile:

Regards,
Andy

Sorry - was distracted.

It’s been running fine since last Friday importing some solar inverter data via Modbus/TCP into Dia for upload to iDigi (a remote host uses RCI to pull the data actually).

Open the ZIP and see if the readme and the file placement makes sense. Hopefully all the right files are there.

  • Lynn

FYI - here is a trace output on the YML included in the ZIP. You see the Modbus poll and response, plus the update of the Dia channels. At the moment ‘both’ inverters are the same one, so the data matches. Plus the inverters don’t return floats - only ‘fixed point’ so you’ll see things like 5993 for Hz, which means 59.93 Hz.

  • Lynn

MBusUdpPoller(mbus): Cyclic Process at 2009-10-28 15:54:30
> Poll(in01) req [12] 26 8F 00 00 00 06 0A 03 00 00 00 14
> Poll(in01) rsp [49]
[0000]: 26 8F 00 00 00 2B 0A 03 28 43 D7 00 00 27 A3 00 00 00 17 04 AA 17 69 01
0E 00 1B 03 EC 01 0E 00
[0032]: 53 00 F0 01 03 00 00 00 00 00 00 00 00 00 00 00 00
(in01_acTotalEnergy)
(in01_uptime)
(in01_acCurrent)
(in01_acVoltage)
(in01_acFrequency)
(in01_acPower)
(in01_dcCurrent)
(in01_dcVoltage)
(in01_dcPower)
(in01_airTemp)
(in01_devTemp1)
(in01_devTemp2)
> Poll(in02) req [12] 26 90 00 00 00 06 0B 03 00 00 00 14
> Poll(in02) rsp [49]
[0000]: 26 90 00 00 00 2B 0B 03 28 43 D7 00 00 27 A3 00 00 00 17 04 AA 17 69 01
0E 00 1B 03 EC 01 0E 00
[0032]: 53 00 F0 01 03 00 00 00 00 00 00 00 00 00 00 00 00
(in02_acTotalEnergy)
(in02_uptime)
(in02_acCurrent)
(in02_acVoltage)
(in02_acFrequency)
(in02_acPower)
(in02_dcCurrent)
(in02_dcVoltage)
(in02_dcPower)
(in02_airTemp)
(in02_devTemp1)
(in02_devTemp2)
process slipped - adjusting for 2.00 lag

Thanks, I will start working on this over the weekend. However, I have a question. If I run this code, will I be able to also run DIA.py to collect data from Analog and digital adaptors as well as the temperature and light sensors that I have? Sounds like this code is mutually exclusive with the standard DIA.py code. Hope not.

It is pure Dia - you can run it along with any other drivers.

The ONLY point at which “Modbus Bridge” and “Dia” are mutually exclusive is when binding to the serial-encap channel/end-point of 0xe8 (232). That channel is NOT used for the AIO/DIO. You would only have a conflict with something like the Massa M300 ‘serial’ driver, which also expects to bind on end-point 0xe8.

Were you planing to fetch Modbus via XBee 232/485 adapters? Or is the Modbus from direct RS-232 serial or Ethernet to X4?

In the future I will enable direct Dia->XBee polling for Modbus, but that gets very complex to defragment Modbus and handle timeouts, stale response etc. The Modbus Bridge has 6 years of experience doing that & handles up to 60 threads at a fraction of the RAM that Python would cost to repeat. Someday that will be required, I’m just hoping to delay that someday.

That is great news. I am still learning so that is why I asked. All of the Modbus data gathering will be via the RS485 Adapter (XBee link) into the CX4. I am toying with using the CX2 for smaller sites. Have you had any positive / negative experience with the ConnectPort X2 pulling ModBus data? I read in the WIKI that it requires a firmware update to work. I don’t need this right away, I will experiment later on with the CX2 as it is a lower cost gateway.

Are you always polling 25 words or less of Modbus data?

I could create a direct (non-Modbus bridge) driver more quickly if the response always fits within a single RF packet - this would make it a more event-driven system. In fact the “query” could be pre-cooked and the Dia would instead see the responses as-if unsolicited.

The X2 can’t run both Python and Modbus bridge at the same time. However, and X4 could use Ethernet to pull Modbus data via the X2. So you could use several X2 around a facility to feed xbee/mesh into Ethernet.

Well, you warned me about the possible conflict but I did not think that there would be an issue with a Digi light sensor. I tried adding in a Wall plug light / temperature sensor and got a nasty error:
#> python dia.py

Determining platform type…Digi Python environment found.

Attempting to read “dia.pyr” in “WEB/python/dia.zip”…
iDigi Device Integration Application Version 1.2.19
Using settings file: dia.pyr
Core: initial garbage collection of 0 objects.
Core: post-settings garbage collection of 10 objects.
Starting Scheduler…
Starting Channel Manager…
Starting Device Driver Manager…
turning all debug output OFF
MBusUdpPoller(MBUS): UDP connection to peer(‘127.0.0.1’, 502)
XBeeDeviceManager(xbee_device_manager): retrieving node list
XBeeDeviceManager(xbee_device_manager): node ‘00:13:a2:00:40:55:90:55!’ moved to CONFIGURE state.
XBeeDeviceManagerConfigurator: request to configure node ‘00:13:a2:00:40:55:90:55!’
XBeeDeviceManagerConfigurator: worker assigned to ‘00:13:a2:00:40:55:90:55!’
XBeeDeviceManager(xbee_device_manager): configuration done for node ‘00:13:a2:00:40:55:90:55!’ promoting to RUNNING state.
XBeeGPIOClient: Discovery request sent: 1262110404.0
receive_info: io_count: 28
requesting names: (‘<28B’, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27) from endpoint 41

Exception during core initialization:
Traceback (most recent call last):
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\core\core_services.py”, line 235, in epoch
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\devices\device_driver_manager.py”, line 57, in init
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\common\abstract_service_manager.py”, line 105, in init
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\settings\settings_base.py”, line 175, in init
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\common\abstract_service_manager.py”, line 121, in apply_settings
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\common\abstract_service_manager.py”, line 151, in _reenumerate_services
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\common\abstract_service_manager.py”, line 274, in instance_start
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\devices\xbee\xbee_devices\xbee_sensor.py”, line 254, in start
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\devices\xbee\xbee_device_manager\xbee_device_manager.py”, line 591, in xbee_device_event_spec_add
File “C:\Users\apineda\Documents_DIGI\dia_pkg_1.2.19\src\devices\xbee\xbee_device_manager\xbee_device_manager.py”, line 222, in __endpoint_add
Exception: Unable to bind endpoint 0xe8! Check that no other programs are running or are set to run on the device.
CoreServices: fatal exception caught! Halting execution.
++++++++++++++++++++

Here is the YML for the sensor:

  • name: LT1
    driver: devices.xbee.xbee_devices.xbee_sensor:XBeeSensor
    settings:
    xbee_device_manager: “xbee_device_manager”
    extended_address: “00:13:a2:00:40:32:64:24!”
    sleep: False
    sample_rate_ms: 10000

Is there a way I can run the temp/light sensors on the same gateway?

Regards,
Andy

Hi Lynn,

I am probably not placing a file in the right place, but I get an error after making the code and uploading it to the CX4.

Here is what I did:

  1. copied over the files into their respective directory in the DIA folder.
  2. Executed a python make.py cfg/mbus_poller.yml(no errors)
  3. Uploaded the dia.zip file to the CX4
  4. rebooted
  5. Telented in and executed python dia.py.

I captured the error below:
++++++++++++++++++++++++++++++++++++++++++++++++++++++
Determining platform type…Digi Python environment found.

iDigi Device Integration Application Version 1.1.15
Using settings file: dia.yml
Core: initial garbage collection of 0 objects.
Attempting to read “dia.yml” in “WEB/python/dia.zip”…
Core: post-settings garbage collection of 25 objects.
Starting Channel Manager…
Starting Device Driver Manager…

Exception during dynamic class load:
Traceback (most recent call last):
File “src\devices\device_driver_manager.py”, line 134, in driver_load
File “src\common\classloader.py”, line 52, in classloader
ImportError: No module named experimental.alarm_clock_device
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Which is odd, because I see that the experimental.alarm_clock_device is in the device folder.

Also,
I don’t have the following driver:
driver: presentations.idigi_db.idigi_db:iDigi_DB
but I commented that out to see if that made a difference and it did not. I can use the driver: presentations.cwm_exist.cwm_exist:CWMExist after I get the main code working.

I moved the code out from under experimental directory and adjusted the references and it now works fine!

Is the db driver:
“driver: presentations.idigi_db.idigi_db:iDigi_DB”
something you devised? Can you send that to me?

Thanks a lot! So far, this code works great.

With regards to the X2 question, I only need to read a few Words from the modbus devices, so the 30 word max (to prevent multiple packets) is not a problem.

The ‘presentations.idigi_db.idigi_db:iDigi_DB’ is the old cwm_exist renamed (because ‘iDigi’ term has displaced the old ‘CWM’ term). You should be able to just swap out those terms until the Dia 1.2 is released and you see the new name.

I am working on the pure mesh version for Modbus - but I see the second short-fall in the direct DIA->mesh is you will not have direct/raw Modbus/TCP access to the xbee/mesh device from local Ethernet - trying to ‘bridge’ raw Modbus & mix it with the data productions from Dia is a big job (the existing IA Modbus bridge is a transaction processor, not data processor so shrugs that task off as breakfast :slight_smile: