19 #include <uuid/modbus.h>
28 #include <make_unique.cpp>
35 uint16_t device, uint16_t address, uint16_t size, uint16_t timeout_ms) {
36 auto response = std::make_shared<RegisterDataResponse>();
38 if (device < DeviceAddressType::MIN_UNICAST
39 || device > DeviceAddressType::MAX_UNICAST
40 || size < 1 || size > 0x007D) {
41 response->status(ResponseStatus::FAILURE_INVALID);
43 if (timeout_ms == 0) {
47 requests_.push_back(std::make_unique<RegisterRequest>(device,
48 FunctionCode::READ_HOLDING_REGISTERS, timeout_ms, address, size,
56 uint16_t device, uint16_t address, uint16_t size, uint16_t timeout_ms) {
57 auto response = std::make_shared<RegisterDataResponse>();
59 if (device < DeviceAddressType::MIN_UNICAST
60 || device > DeviceAddressType::MAX_UNICAST
61 || size < 1 || size > 0x007D) {
62 response->status(ResponseStatus::FAILURE_INVALID);
64 if (timeout_ms == 0) {
68 requests_.push_back(std::make_unique<RegisterRequest>(device,
69 FunctionCode::READ_INPUT_REGISTERS, timeout_ms, address, size,
77 uint16_t device, uint16_t address, uint16_t value, uint16_t timeout_ms) {
78 auto response = std::make_shared<RegisterWriteResponse>();
80 if (device > DeviceAddressType::MAX_UNICAST) {
81 response->status(ResponseStatus::FAILURE_INVALID);
83 if (timeout_ms == 0) {
84 if (device == DeviceAddressType::BROADCAST) {
91 requests_.push_back(std::make_unique<RegisterRequest>(device,
92 FunctionCode::WRITE_SINGLE_REGISTER, timeout_ms, address, value,
100 uint16_t timeout_ms, uint16_t address, uint16_t data,
101 const std::shared_ptr<Response> &response)
102 :
Request(device, function_code, timeout_ms, response),
103 address_(address), data_(data) {
111 frame[4] =
data() >> 8;
112 frame[5] =
data() & 0xFF;
118 logger.
err(F(
"Incomplete message for function %02X from device %u, expected 3+ received %u"),
119 frame[1], frame[0], len);
120 return ResponseStatus::FAILURE_LENGTH;
122 return ResponseStatus::FAILURE_LENGTH;
123 }
else if (frame[2] & 1) {
124 logger.
err(F(
"Invalid message for function %02X from device %u, byte count %u is not a multiple of 2"),
125 frame[1], frame[0], frame[2]);
126 return ResponseStatus::FAILURE_LENGTH;
129 for (uint16_t i = 0; i < frame[2]; i += 2) {
130 data_.emplace_back((frame[3 + i] << 8) | frame[4 + i]);
133 return ResponseStatus::SUCCESS;
138 return ResponseStatus::FAILURE_LENGTH;
141 address_ = (frame[2] << 8) | frame[3];
142 data_.emplace_back((frame[4] << 8) | frame[5]);
144 return ResponseStatus::SUCCESS;
void err(const char *format,...) const
Log a message at level Level::ERR.
ResponseStatus parse(frame_buffer_t &frame, uint16_t len) override
Parse a message frame buffer and store the outcome in this response.
std::vector< uint16_t > data_
uint16_t data() const
Get the register size or value.
uint16_t address() const
Get the register address.
RegisterRequest(uint16_t device, uint8_t function_code, uint16_t timeout_ms, uint16_t address, uint16_t data, const std::shared_ptr< Response > &response)
Create a new register request message (not directly useful).
uint16_t encode(frame_buffer_t &frame) override
Encode this request and store it in a message frame buffer.
ResponseStatus parse(frame_buffer_t &frame, uint16_t len) override
Parse a message frame buffer and store the outcome in this response.
uint8_t function_code() const
Get the function code of the request.
uint16_t device() const
Get the destination device address.
bool check_length(frame_buffer_t &frame, uint16_t actual, uint16_t expected)
Check the length of the message frame is correct and log an error if it is not.
uint16_t default_broadcast_timeout_ms_
uint16_t default_unicast_timeout_ms_
std::shared_ptr< const RegisterDataResponse > read_input_registers(uint16_t device, uint16_t address, uint16_t size, uint16_t timeout_ms=0)
Read a contiguous block of input registers from a remote device.
std::shared_ptr< const RegisterWriteResponse > write_holding_register(uint16_t device, uint16_t address, uint16_t value, uint16_t timeout_ms=0)
Write to a single holding register in a remote device.
std::shared_ptr< const RegisterDataResponse > read_holding_registers(uint16_t device, uint16_t address, uint16_t size, uint16_t timeout_ms=0)
Read a contiguous block of holding registers from a remote device.
std::deque< std::unique_ptr< Request > > requests_
const uuid::log::Logger logger
ResponseStatus
Status of response messages.
std::array< uint8_t, MAX_MESSAGE_SIZE+1 > frame_buffer_t