Skip to content

Commit

Permalink
responseLength method
Browse files Browse the repository at this point in the history
  • Loading branch information
pkubanek committed Sep 28, 2024
1 parent 9372fb0 commit f4b9c24
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 18 deletions.
11 changes: 11 additions & 0 deletions include/Modbus/BusList.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,17 @@ class BusList : public std::vector<CommandRecord> {
emplace(end(), CommandRecord(Buffer(address, func, params...), timing));
}

/**
* Returns number of expected bytes, given the reply so far received. Child
* subclasses shall overwrite the method.
*
* @param response received response data.
*
* @return Total size of the response expected. If the passed response doesn't contain
* all data needed to calculate its length, returns -1.
*/
virtual int responseLength(const std::vector<uint8_t> &response);

/**
* Process @glos{ILC} response. Address and function of the response are checked if
*
Expand Down
2 changes: 2 additions & 0 deletions include/cRIO/MPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class MPU : public Modbus::BusList {
*/
MPU(uint8_t bus, uint8_t node_address);

int responseLength(const std::vector<uint8_t> &response) override;

/**
* Returns bus number (internal FPGA identifier).
*
Expand Down
26 changes: 26 additions & 0 deletions src/LSST/cRIO/MPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,32 @@ MPU::MPU(uint8_t bus, uint8_t node_address) : _bus(bus), _node_address(node_addr
0x90);
}

int MPU::responseLength(const std::vector<uint8_t> &response) {
if (response.size() < 2) {
return -1;
}

// Modbus error response. 5 bytes total - address, function, error code, CRC checksum
switch (response[1]) {
case READ_INPUT_STATUS:
case READ_HOLDING_REGISTERS:
if (response.size() < 3) {
return -1;
}
return 5 + response[2];

case PRESET_HOLDING_REGISTER:
case PRESET_HOLDING_REGISTERS:
return 8;

default:
if ((response[1] & 0x80) == 0x80) {
return 5;
}
return -1;
}
}

void MPU::readInputStatus(uint16_t start_register_address, uint16_t count, uint32_t timing) {
callFunction(_node_address, READ_INPUT_STATUS, timing, start_register_address, count);
_commanded_info.push_back(CommandedInfo(start_register_address, count));
Expand Down
2 changes: 2 additions & 0 deletions src/Modbus/BusList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ using namespace Modbus;

BusList::BusList() {}

int BusList::responseLength(const std::vector<uint8_t> &response) { return -1; }

void BusList::parse(Parser parser) {
auto exp_address = at(_parsed_index).buffer.address();
auto exp_func = at(_parsed_index).buffer.func();
Expand Down
18 changes: 18 additions & 0 deletions tests/test_MPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,21 @@ TEST_CASE("Test MPU preset holding registers by simplymodbus.ca", "[MPU]") {

CHECK_NOTHROW(mpu.parse(std::vector<uint8_t>({0x11, 0x10, 0x00, 0x01, 0x00, 0x02, 0x12, 0x98})));
}

TEST_CASE("Test responseLength calculations", "[ResponseLength]") {
TestMPU mpu(5, 0x11);

CHECK(mpu.responseLength({0x11, 0x83}) == 5);

CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::READ_INPUT_STATUS}) == -1);
CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::READ_INPUT_STATUS, 0x02}) == 7);

CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::READ_HOLDING_REGISTERS}) == -1);
CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::READ_HOLDING_REGISTERS, 0x08}) == 13);

CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::PRESET_HOLDING_REGISTER}) == 8);
CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::PRESET_HOLDING_REGISTER, 0x11, 0x22, 0x33, 0x44}) == 8);

CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::PRESET_HOLDING_REGISTERS}) == 8);
CHECK(mpu.responseLength({0x11, MPU::MODBUS_CMD::PRESET_HOLDING_REGISTERS, 0x11, 0x22, 0x33, 0x44}) == 8);
}
43 changes: 25 additions & 18 deletions tests/test_Modbus_BusList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ TestList::TestList(uint8_t _expectedAddress) : expectedAddress(_expectedAddress)
uint16_t reg1 = parser.read<uint16_t>();
uint16_t reg2 = parser.read<uint16_t>();
uint16_t reg3 = parser.read<uint16_t>();
REQUIRE_NOTHROW(parser.checkCRC());
CHECK_NOTHROW(parser.checkCRC());
processReadRegister(parser.address(), reg1, reg2, reg3);
},
131);
Expand All @@ -66,9 +66,9 @@ TEST_CASE("Call functions", "[Calls]") {
buslist.callFunction(43, 86, 200, static_cast<float>(0.1122), static_cast<int16_t>(-1234),
static_cast<uint64_t>(0x0123456789abcdef));

REQUIRE(buslist.size() == 2);
CHECK(buslist.size() == 2);

REQUIRE(buslist[0].buffer.size() == 11);
CHECK(buslist[0].buffer.size() == 11);
CHECK(buslist[0].buffer[0] == 0x7b);
CHECK(buslist[0].buffer[1] == 0x11);
CHECK(buslist[0].buffer[2] == 0xfe);
Expand All @@ -81,7 +81,7 @@ TEST_CASE("Call functions", "[Calls]") {
CHECK(buslist[0].buffer[9] == 0x4b);
CHECK(buslist[0].buffer[10] == 0xa7);

REQUIRE(buslist[1].buffer.size() == 18);
CHECK(buslist[1].buffer.size() == 18);
CHECK(buslist[1].buffer[0] == 0x2b);
CHECK(buslist[1].buffer[1] == 0x56);
CHECK(buslist[1].buffer[2] == 0x3d);
Expand Down Expand Up @@ -109,7 +109,7 @@ TEST_CASE("Call function, parser return", "[Parsing]") {

std::vector<uint8_t> data({0x11, 0x03, 0x06, 0xAE, 0x41, 0x56, 0x52, 0x43, 0x40, 0x49, 0xAD});

REQUIRE_NOTHROW(buslist.parse(data));
CHECK_NOTHROW(buslist.parse(data));
}

TEST_CASE("Call 10 functions, parser return", "[Parsing]") {
Expand All @@ -127,7 +127,7 @@ TEST_CASE("Call 10 functions, parser return", "[Parsing]") {

for (int address = 1; address < 10; address++) {
buslist.expectedAddress = address;
REQUIRE_NOTHROW(buslist.parse(generateReply(address)));
CHECK_NOTHROW(buslist.parse(generateReply(address)));
}
}

Expand All @@ -146,38 +146,45 @@ TEST_CASE("Missing response", "[BusListErrors]") {

for (uint8_t address = 1; address < 10; address++) {
buslist.expectedAddress = address;
REQUIRE_NOTHROW(buslist.parse(generateReply(address)));
CHECK_NOTHROW(buslist.parse(generateReply(address)));
}

buslist.reset();

for (uint8_t address = 1; address < 10; address++) {
buslist.expectedAddress = address;
REQUIRE_THROWS_AS(buslist.parse(generateReply(address + 1)), MissingResponse);
CHECK_THROWS_AS(buslist.parse(generateReply(address + 1)), MissingResponse);
}

buslist.reset();

// test MissingResponse is thrown properly in expected processing sequences

buslist.expectedAddress = 1;
REQUIRE_THROWS_AS(buslist.parse(generateReply(2)), MissingResponse);
CHECK_THROWS_AS(buslist.parse(generateReply(2)), MissingResponse);
buslist.expectedAddress = 2;
REQUIRE_NOTHROW(buslist.parse(generateReply(2)));
CHECK_NOTHROW(buslist.parse(generateReply(2)));
buslist.expectedAddress = 3;
REQUIRE_NOTHROW(buslist.parse(generateReply(3)));
CHECK_NOTHROW(buslist.parse(generateReply(3)));
buslist.expectedAddress = 4;
REQUIRE_NOTHROW(buslist.parse(generateReply(4)));
CHECK_NOTHROW(buslist.parse(generateReply(4)));
buslist.expectedAddress = 5;
REQUIRE_THROWS_AS(buslist.parse(generateReply(7)), MissingResponse);
CHECK_THROWS_AS(buslist.parse(generateReply(7)), MissingResponse);
buslist.expectedAddress = 6;
REQUIRE_THROWS_AS(buslist.parse(generateReply(7)), MissingResponse);
CHECK_THROWS_AS(buslist.parse(generateReply(7)), MissingResponse);
buslist.expectedAddress = 7;
REQUIRE_NOTHROW(buslist.parse(generateReply(7)));
CHECK_NOTHROW(buslist.parse(generateReply(7)));
buslist.expectedAddress = 8;
REQUIRE_NOTHROW(buslist.parse(generateReply(8)));
CHECK_NOTHROW(buslist.parse(generateReply(8)));
buslist.expectedAddress = 9;
REQUIRE_NOTHROW(buslist.parse(generateReply(9)));
CHECK_NOTHROW(buslist.parse(generateReply(9)));
buslist.expectedAddress = 9;
REQUIRE_THROWS_AS(buslist.parse(generateReply(10)), std::out_of_range);
CHECK_THROWS_AS(buslist.parse(generateReply(10)), std::out_of_range);
}

TEST_CASE("Response length calculations", "[ResponseLength]") {
TestList buslist(1);

CHECK(buslist.responseLength({}) == -1);
CHECK(buslist.responseLength({0x01, 0x02}) == -1);
}

0 comments on commit f4b9c24

Please sign in to comment.