1 #include "modbus_commands.hpp"
2
3 #include "modbus_exception.hpp"
4
5 #include <phosphor-logging/lg2.hpp>
6
7 namespace phosphor::modbus::rtu
8 {
9
ReadHoldingRegistersRequest(uint8_t deviceAddress,uint16_t registerOffset,uint16_t registerCount)10 ReadHoldingRegistersRequest::ReadHoldingRegistersRequest(
11 uint8_t deviceAddress, uint16_t registerOffset, uint16_t registerCount) :
12 deviceAddress(deviceAddress), registerOffset(registerOffset),
13 registerCount(registerCount)
14 {}
15
encode()16 auto ReadHoldingRegistersRequest::encode() -> void
17 {
18 *this << deviceAddress << commandCode << registerOffset << registerCount;
19 appendCRC();
20 }
21
ReadHoldingRegistersResponse(uint8_t deviceAddress,std::vector<uint16_t> & registers)22 ReadHoldingRegistersResponse::ReadHoldingRegistersResponse(
23 uint8_t deviceAddress, std::vector<uint16_t>& registers) :
24 expectedDeviceAddress(deviceAddress), registers(registers)
25 {
26 if (registers.empty())
27 {
28 throw std::underflow_error("Response registers are empty");
29 }
30 // addr(1), func(1), bytecount(1), <2 * count regs>, crc(2)
31 len = 5 + (2 * registers.size());
32 }
33
decode()34 auto Response::decode() -> void
35 {
36 validate();
37
38 // Error response is structured as:
39 // addr(1), errorFunctionCode(1), exceptionCode(1)
40 // Where errorFunctionCode is the response function with
41 // MSB set to 1, hence mask of 0x80.
42 bool isError = (len == 3 && (functionCode & 0x80) != 0);
43 if (isError)
44 {
45 throw ModbusException(raw[2]);
46 }
47 }
48
decode()49 auto ReadHoldingRegistersResponse::decode() -> void
50 {
51 Response::decode();
52 uint8_t byteCount, responseCode, deviceAddress;
53 *this >> registers >> byteCount >> responseCode >> deviceAddress;
54 verifyValue("Device Address", deviceAddress, expectedDeviceAddress);
55 verifyValue("Response Function Code", responseCode, expectedCommandCode);
56 verifyValue("Byte Count", byteCount, registers.size() * 2);
57 }
58
59 } // namespace phosphor::modbus::rtu
60