-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
Summary
In the Modbus server implementation, the interface doesn't allow for more than one Modbus unit to be defined.
In my use case, I had a number of I²C devices (TI INA219s) that I wanted to expose via Modbus/RTU so I could poll them over a serial link from collectd
. However, when I went to implement the callback functions for the Modbus server, I observed that they only provide a register number and a pointer for the result. There was no way for me to know which unit ID was being accessed.
It would appear that struct modbus_iface_param
only makes provision for a single server.
This is quite limiting. I've had to kludge it by jamming everything into a single logical Modbus "unit" and using register offsets to identify which device the data is coming from.
Describe the solution you'd like
It'd be much more flexible if the struct modbus_iface_param
could take an array of struct modbus_server_param
s, each optionally passing a void *
context pointer; passing the pointer to the struct modbus_server_param
to callback functions as the first argument.
i.e.
struct modbus_user_callbacks {
int (*coil_rd)(const struct modbus_server_param *server, uint16_t addr, bool *state);
int (*coil_wr)(const struct modbus_server_param *server, uint16_t addr, bool state);
int (*discrete_input_rd)(const struct modbus_server_param *server, uint16_t addr, bool *state);
int (*input_reg_rd)(const struct modbus_server_param *server, uint16_t addr, uint16_t *reg);
int (*input_reg_rd_fp)(const struct modbus_server_param *server, uint16_t addr, float *reg);
int (*holding_reg_rd)(const struct modbus_server_param *server, uint16_t addr, uint16_t *reg);
int (*holding_reg_wr)(const struct modbus_server_param *server, uint16_t addr, uint16_t reg);
int (*holding_reg_rd_fp)(const struct modbus_server_param *server, uint16_t addr, float *reg);
int (*holding_reg_wr_fp)(const struct modbus_server_param *server, uint16_t addr, float reg);
};
struct modbus_server_param {
modbus_user_callbacks *user_cb;
void *user_ctx;
uint8_t unit_id;
};
struct modbus_iface_param {
enum modbus_mode mode;
union {
struct modbus_server_param *server;
uint32_t rx_timeout;
};
union {
struct modbus_serial_param serial;
struct modbus_raw_cb rawcb;
};
};
The array could be terminated by a struct modbus_server_param
with a unit_id
of 0; since that is a "reserved" address used for broadcasts to "all slave devices". Alternatively, a NULL
user_cb
pointer could indicate "the end".
This would make it possible to define homogenous or even heterogenous arrays of arbitrary Modbus units that would then be exposed on the Modbus/RTU or Modbus/TCP interface.
Alternatives
No response
Additional Context
No response