Can Groov Rio be used as a ModBus server?


Can the Groov Rio be used as a ModBus server? I have looked through a lot of the documentation and I see a lot about acting as a client, but not as a server. I want to to use Node-Red to collect info from the built in inputs and gather some values from other ModBus Servers, then present it as needed in a comprehensive block as called upon from some other Client.

New user to the Rio here, so I hope this is not a silly question. Thanks.


Sure, Node-RED has the server nodes you seek.
So, it’s all done via a flow that you build out with the IP address, Modbus device ID, and registers of your other devices.
For the RIOs internal I/O, use the Node-RED groov IO nodes.

Once you have all your data, you can either use MQTT or perhaps move all the data into MMP and then you can move that block of data to what the other client can ingest.

There are lots of flows and examples on the forums here. The search can guide you but hit the forums with any specific questions you have.

Or even easier, just use the built-in Modbus server on the RIO if you just need the RIO I/O points.

Thank you. I read through 1678 and it doesn’t really discuss the Rio at all. I’d like to have the device use both I/O values from itself in ModBus as well as some other data gathered from Node-Red. Is this possible for the Rio?

In short. Yes.

The reason we don’t talk about it much in the docs is that you need to use Node-RED, which is not an Opto-developed platform.

As I said, just install the Modbus Nodes and get started. Its pretty straight forward if you have the Modbus manual and register details for the devices you are going to poll.

Thanks all. I will jump right in and give it a shot. I have been writing ModBus apps in .Net for a while, so this is just different / easier?

I appreciate the guidance.


The memory map is mostly the same on all the different controllers, the document has plenty of notes for when there are exceptions regarding the RIO. If you have data you have retrieved in Node-Red, you can use the groov IO nodes to write them to the RIO scratchpad, then you can retrieve that via the built-in Modbus on the RIO (at port 8502).

Once you figure out the address of the value you want in the memory map, go into groov manage on the RIO to the I/O Services, Modbus Calculator where you can cross reference the MMP address to a Modbus unit ID and address.

1 Like

Thank you Philip for the detailed response. I am sure it is straight forward once you get used to it. I will dig into it in a few days.

Thanks again.


You’re welcome, let us know what you end up doing.

If you want to make your scratchpad data and your IO data all contiguous in memory (so you can make one modbus call) - check out the “Custom Configuration Area” of the memory map (document 1465 explains it). It is normally used to “stream” data, but it can be used for this purpose as well.

Hello all. Thanks for the advice. I am muddling through the process of understanding how everything fits together. I have spent a fair amount of time reading the Modbus and Opto MMP Protocol guides as well as the Memory Maps provided.

So far, using Node-Red, I have figured out how to read the various channels on the RIO and write them to MMP locations. I am struggling with ModBus accessing of these locations from a different machine on the network. This comes down to the basic fact that a given MMP location (0xFoDA 0014) has a Unit ID of 111 and a Register ID of 10. I don’t know how to access that from a different machine. There were a couple of lines in the reams of documents that hinted at the Unit ID being an internal method of accessing all the available memory. I’ve looked at the Custom Data Access and Streaming sections in 1465, but I don’t know how those present to a ModBus client polling for Holding Registers.

In 1678 it shows the RIO as having Holding Registers from number 1031 to 3078, with the first 10 being assigned to the I/O as appropriate. How are the other 2K registers accessed or written to in Node-Red? I feel that I am simply missing something extremely obvious.

What I really need to do is gather the various I/O values from the RIO and in addition, read some values from one or two ModBus servers on the network, saving these values to the RIO ModBus server. Then, on a timed basis, a network ModBus client will poll the RIO and collect all the data at once.

Thank you in advance for any guidance at all.


I’ve re-read this thread a few times just now and I’m still a bit hazy on exactly what your end goal is here.
I wonder if it’s worth drawing a block diagram out and posting a picture of it here so we can see where you are headed.

One thing that is odd to me is to use Node-RED running on the RIO to read the RIO I/O and write it to an MMP address.
That’s sort of like saying “Lets read the modbus register and write it to a modbus register so we can read the value of the modbus register”.
Since every RIO / EPIC / SNAP I/O point has a Modbus register address, it is unnecessary to move it anywhere before you read it.

Most other Modbus devices have, say, a few dozen registers, so they can use just one device ID, and that’s all you need: the IP address, device ID, and the actual register address…
Opto devices can be loaded up (RIO not quite as much - on the I/O side), so we quickly ran out of register address space.
The way we got around that was to break up the Modbus address register space into different device IDs.
Some Modbus software cannot handle this. They have only ONE device ID allowed per IP address. In this case, you often have to put in the groov IP address a few times, each with a different device ID to read all the data you need, but in the case of the RIO I/O, you should be fine with just the one IP and device ID setting in the other software you mentioned.

This forum post might help show the different device IDs in play:

It seemed like your first post wanted to read a remote ModbusTCP device from Node-RED running on the RIO, but your last post seems to suggest that you want to do that but also expose that data to a third-party software application?

Thanks again for the response. Let me take a step back and describe the project.

I have a factory full of equipment (furnaces, compressors, solvent degreasers, forming machines, presses, etc…). Some of it has PLC’s or other modern controllers to drive the main component, but a lot of it is comprised of “dumb” electronics that just runs 24/7 for decades. Since 2010 I have been collecting Process Data on various portions and storing it into specific tables in an onsite MS SQL Database. Each table is pretty much either Machine or Process focused, and each record in the database provides a snapshot of the machines condition at that moment. Interval ranges from 5 seconds to 1 minute, depending on the machine. The data is easily accessed by a web site and is used as part of trouble shooting and predictive/preventative maintenance. Over time, I am continually expanding the scope and penetration of the system. I also collect machine faults and some user inputs, but that is not related to this issue.

The data acquisition components being used are varied. I have three Opto panels with SNAP PAC brains and I/O cards from about 2010 or so that do about 50% of the work. On other systems, I have installed some LabJack boxes to acquire primarily thermocouple and analog I/O from various things. I have a few MOXA boxes that seem to do well with a couple of furnace atmosphere controllers that use serial ModBus. The key here is the aggregation and curation of data points to make a single, time stamped database record that descries the condition at a point in time.

Currently, this aggregation is getting a bit complex and difficult to work with in a flexible manner. I have written a DataLink program that generates threads at a prescribed interval. These threads act as ModBus clients, reading from the various ModBus servers, be it a LabJack, a Eurotherm furnace controller, or a PLC with a ModBus server node running in it. This thread acquires the information, builds the parameter array, and adds it to the appropriate database table. It works very well, but it is getting difficult to update and maintain. I am currently hitting about 100 data points on the shop floor now, and it will likely double before the year end. It is also going to expand to three other locations I have next year.

My objective in evaluating the Opto RIO was to push some of the data aggregation out to the shop floor, probably some form of Edge computing. I would envision the RIO gathering some of the data itself, and as appropriate, read from some of the pertinent other ModBus servers it needs data from. The RIO would then have all the data it would need and could either append a database row itself (if I could get the node-red-contrib-mssql node to work), or it could simply hold the entire data package in local ModBus registers, all prepared, for the DataLink program to simply read and append.

I have an immediate need that I am using as an evaluation of the groov RIO. I need to read two thermocouples and two analog inputs (0-10VDC), There are also four data points I want to collect from two PLC’s and hold. This will provide a complete data package for two centrifuges, telling me the fluid temperature, actual rotation speed and setpoint, and the program used.

So, that is where I am. In regards to the reading from one ModBus register and putting it into a different one is relatively simple. I was working with a thermocouple readings on channel 0 and 1. If I read the register directly from an external ModBus client, the data read is stored in IEEE float32 format, which while very accurate, is much more difficult to work with. If I read from the channels’ register (1032?) using the Opto I/O node and store it into a normal Holding Register, it is stored in a much more typical integer format using the four bytes. While it is truncated and stored as an integer, that is more than accurate enough for me. If necessary I pre-multiply by 100 and divide by 100 upon reading.

So, I hope that helps. My primary question is can I put all my ModBus data from various sources into Holding Registers and Coils on the RIO and make them accessible to a remote ModBus client?

Again, I hope this is the right venue for questions like this, and thank you for your time.




I just went through the .NET software I use for ModBus work, and there is a property for a a connection called UnitIdentifier. This probably relates to the Unit ID used for the MMP registers.

Never too old to learn something new. Ancora imparo.


1 Like

Yes, that sounds correct. The official terminology from the specification on modbus is “Slave Address” for serial devices and “Unit Identifier” for Modbus TCP devices.


Thanks for your support, Philip. I am able to get the Rio to do what I wanted in terms of curating data from various sources. I am struggling to get Node-Red on the Rio to connect to an MS SQL Server due to the version of node.js on the Rio and the complexity of our network on site. Easy work around, and it fits in with a philosophical debate I have with myself:
Should the Field unit curate and push the data, or simply curate and make available?

Both sides have positives and negatives in a harsh, industrial environment with many units in the field configured in different ways. Either way, I like the Rio.

Thanks again.


Use whichever way is easiest/simplest. If you are having trouble with the sql node, then pull the data instead. On a local network it probably doesn’t matter which way. There could be an argument to using your data link program to get the data from all your RIOs and push to your database. If you need to change database servers, then you only need to update one thing.

Since you are connecting to so many different types of devices, you may consider a SCADA system (Ignition) to manage it all as well - could end up saving you time to make the cost worth it.