Modbus Reply Script

Hello. I'm evaluating IO Ninja to see if I can use it to simulate some Modbus RTU devices. What I'm currently trying to do is write a simple script that will reply to a particular Modbus Master request of Read Holding Registers. Is there a script example for using the ModbusRtuReadReplyPacket template to send a response to a Read Holding Registers request?

Hello,

Here's a script that receives Read Holding Register (or Read Input Register) requests and replies with ever-increasing values (1, 2, 3,...):

import "io_Modbus.jnc"
import "crc16.jnc"

pragma(Alignment, 1)

struct Request:
	io.ModbusRtuAduHdr,
	io.ModbusReadPdu {
	uint16_t m_crc;
}
	
struct Reply: 
	io.ModbusRtuAduHdr,
	io.ModbusReadReplyPdu {
	uint16_t m_data[128]; // big enough
}

void main() {
	Request request;
	Reply reply;	

	int value = 0;

	for (;;) {
		receiveAll(&request, sizeof(request)); // read request

		// prepare reply

		size_t dataSize = request.m_count * sizeof(uint16_t);
		reply.m_func = request.m_func;
		reply.m_deviceAddress = request.m_deviceAddress;
		reply.m_size = dataSize;

		bigendian uint16_t* p = reply.m_data; // Modbus values are bigendian
		for (size_t i = 0; i < request.m_count; i++)
			p[i] = ++value; // adjust values accordingly

		size_t size = offsetof(Reply.m_data) + dataSize; // not including Modbus checksum
		reply.m_data[request.m_count] = crc16_ansi(reply, size, 0xffff); 

		// transmit reply
		
		transmit(reply, size + sizeof(uint16_t)); // including Modbus checksum
	}
}

The result might look like this:

f7d227b6-48f0-4e34-9f61-13aafaf1b018-image.png

Above, I used a pair of TCP Server and TCP Connection sessions to issue sample Read Holding Register requests, but in your case, you most likely want to use a Serial session to talk to a real device.

Thank you for the example. This is exactly what I was looking for.