Skip to content

Commit

Permalink
Modbus::BusList::set_error_response method
Browse files Browse the repository at this point in the history
  • Loading branch information
pkubanek committed Nov 4, 2024
1 parent 71bc23d commit 22743c2
Show file tree
Hide file tree
Showing 14 changed files with 292 additions and 281 deletions.
30 changes: 18 additions & 12 deletions include/Modbus/BusList.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,20 @@ class WrongResponse : public std::runtime_error {
exp_func, exp_address, called, address)) {}
};

/**
* Thrown when function error response (in Modbus, that's the function code |
* 0x80). Not thrown when the error handling function was provided
*/
class ErrorResponse : public std::runtime_error {
public:
ErrorResponse(uint8_t address, uint8_t func);
};

/**
* Error thrown when response action for the function received in response is
* undefined.
*
* @see BusList::addResponse
* @see BusList::add_response
*/
class UnexpectedResponse : public std::runtime_error {
public:
Expand Down Expand Up @@ -119,18 +128,13 @@ class ResponseRecord {
/**
* Construct callback entry.
*
* @param _func Function code
* @param _action Action to execute when function code is encountered
* @param _error_reply Error reply. That's usually 0x80 | _func
* @param _error_action Error action
*/
ResponseRecord(uint8_t _func, std::function<void(Parser)> _action, uint8_t _error_reply,
std::function<void(uint8_t, uint8_t)> _error_action)
: func(_func), action(_action), error_reply(_error_reply), error_action(_error_action) {}
ResponseRecord(std::function<void(Parser)> _action, std::function<void(uint8_t, uint8_t)> _error_action)
: action(_action), error_action(_error_action) {}

const uint8_t func; ///< sucessfull response function code
std::function<void(Parser)> action; ///< action to call on sucessfull response
const uint8_t error_reply; ///< error response code
std::function<void(uint8_t, uint8_t)> error_action; ///< action to call on the error response. Arguments
///< are address and error /< code received from ILC
};
Expand Down Expand Up @@ -273,7 +277,7 @@ class BusList : public std::vector<CommandRecord> {
* safe) disable the failing @glos{ILC}.
*
* @throw UnexpectedResponse Throwed when the bus list action for the
* address/function (set with the addResponse call) wasn't set.
* address/function (set with the add_response call) wasn't set.
*/
void parse(Parser parser);

Expand Down Expand Up @@ -302,8 +306,10 @@ class BusList : public std::vector<CommandRecord> {
*
* @see checkCached
*/
void addResponse(uint8_t func, std::function<void(Parser)> action, uint8_t error_reply,
std::function<void(uint8_t, uint8_t)> error_action = nullptr);
void add_response(uint8_t func, std::function<void(Parser)> action,
std::function<void(uint8_t, uint8_t)> error_action = nullptr);

void set_error_response(uint8_t func, std::function<void(uint8_t, uint8_t)> error_action);

ErrorRecord get_error_record(uint8_t address) { return _errors[address]; }

Expand All @@ -314,7 +320,7 @@ class BusList : public std::vector<CommandRecord> {
static constexpr uint8_t MODBUS_ERROR_MASK = 0x80;

private:
std::list<ResponseRecord> _functions;
std::map<uint8_t, ResponseRecord> _functions;

std::map<uint8_t, ErrorRecord> _errors;

Expand Down
2 changes: 1 addition & 1 deletion include/cRIO/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class Application {
* Prints preamble for commands help. Can include tips which commands to
* use,..
*/
virtual void printGenericHelp(){};
virtual void printGenericHelp() {};

/**
* Process option from command line parsing.
Expand Down
4 changes: 2 additions & 2 deletions include/cRIO/ModbusBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,13 @@ class ModbusBuffer {
* Called before responses are processed (before processXX methods are
* called).
*/
virtual void preProcess(){};
virtual void preProcess() {};

/**
* Called after responses are processed (after processXX methods are
* called).
*/
virtual void postProcess(){};
virtual void postProcess() {};

/**
* Thrown when an unknown response function is received. As unknown function
Expand Down
2 changes: 1 addition & 1 deletion include/cRIO/Task.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Task {
*
* @param ex exception raised during processing
*/
virtual void reportException(const std::exception &ex){};
virtual void reportException(const std::exception &ex) {};

static constexpr task_return_t DONT_RESCHEDULE = 0xFFFFFFFF;

Expand Down
93 changes: 40 additions & 53 deletions src/ILC/ILCBusList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,72 +27,59 @@
using namespace ILC;

ILCBusList::ILCBusList(uint8_t bus) : _bus(bus) {
addResponse(
ILC_CMD::SERVER_ID,
[this](Modbus::Parser parser) {
uint8_t fnLen = parser.read<uint8_t>();
if (fnLen < 12) {
throw std::runtime_error(fmt::format(
"invalid ILC function 17 response length - expect at least 12, got {}", fnLen));
}
fnLen -= 12;

uint64_t uniqueID = parser.readU48();
uint8_t ilcAppType = parser.read<uint8_t>();
uint8_t networkNodeType = parser.read<uint8_t>();
uint8_t ilcSelectedOptions = parser.read<uint8_t>();
uint8_t networkNodeOptions = parser.read<uint8_t>();
uint8_t majorRev = parser.read<uint8_t>();
uint8_t minorRev = parser.read<uint8_t>();
std::string fwName = parser.readString(fnLen);
parser.checkCRC();
processServerID(parser.address(), uniqueID, ilcAppType, networkNodeType, ilcSelectedOptions,
networkNodeOptions, majorRev, minorRev, fwName);
},
BusList::MODBUS_ERROR_MASK | ILC_CMD::SERVER_ID);

addResponse(
ILC_CMD::SERVER_STATUS,
[this](Modbus::Parser parser) {
uint8_t mode = parser.read<uint8_t>();
uint16_t status = parser.read<uint16_t>();
uint16_t faults = parser.read<uint16_t>();
parser.checkCRC();
_lastMode[parser.address()] = mode;
processServerStatus(parser.address(), mode, status, faults);
},
BusList::MODBUS_ERROR_MASK | ILC_CMD::SERVER_STATUS);

addResponse(
add_response(ILC_CMD::SERVER_ID, [this](Modbus::Parser parser) {
uint8_t fnLen = parser.read<uint8_t>();
if (fnLen < 12) {
throw std::runtime_error(fmt::format(
"invalid ILC function 17 response length - expect at least 12, got {}", fnLen));
}
fnLen -= 12;

uint64_t uniqueID = parser.readU48();
uint8_t ilcAppType = parser.read<uint8_t>();
uint8_t networkNodeType = parser.read<uint8_t>();
uint8_t ilcSelectedOptions = parser.read<uint8_t>();
uint8_t networkNodeOptions = parser.read<uint8_t>();
uint8_t majorRev = parser.read<uint8_t>();
uint8_t minorRev = parser.read<uint8_t>();
std::string fwName = parser.readString(fnLen);
parser.checkCRC();
processServerID(parser.address(), uniqueID, ilcAppType, networkNodeType, ilcSelectedOptions,
networkNodeOptions, majorRev, minorRev, fwName);
});

add_response(ILC_CMD::SERVER_STATUS, [this](Modbus::Parser parser) {
uint8_t mode = parser.read<uint8_t>();
uint16_t status = parser.read<uint16_t>();
uint16_t faults = parser.read<uint16_t>();
parser.checkCRC();
_lastMode[parser.address()] = mode;
processServerStatus(parser.address(), mode, status, faults);
});

add_response(
ILC_CMD::CHANGE_MODE,
[this](Modbus::Parser parser) {
uint16_t mode = parser.read<uint16_t>();
parser.checkCRC();
_lastMode[parser.address()] = mode;
processChangeILCMode(parser.address(), mode);
},
BusList::MODBUS_ERROR_MASK | ILC_CMD::CHANGE_MODE,
[this](uint8_t address, uint8_t error) {
SPDLOG_WARN("Cannot change mode of ILC with address {0} - response {1} ({1:02x})", address,
error);
});

addResponse(
ILC_CMD::SET_TEMP_ADDRESS,
[this](Modbus::Parser parser) {
uint8_t newAddress = parser.read<uint8_t>();
parser.checkCRC();
processSetTempILCAddress(parser.address(), newAddress);
},
BusList::MODBUS_ERROR_MASK | ILC_CMD::SET_TEMP_ADDRESS);
add_response(ILC_CMD::SET_TEMP_ADDRESS, [this](Modbus::Parser parser) {
uint8_t newAddress = parser.read<uint8_t>();
parser.checkCRC();
processSetTempILCAddress(parser.address(), newAddress);
});

addResponse(
ILC_CMD::RESET_SERVER,
[this](Modbus::Parser parser) {
parser.checkCRC();
processResetServer(parser.address());
},
BusList::MODBUS_ERROR_MASK | ILC_CMD::RESET_SERVER);
add_response(ILC_CMD::RESET_SERVER, [this](Modbus::Parser parser) {
parser.checkCRC();
processResetServer(parser.address());
});
}

ILCBusList::~ILCBusList() {}
Expand Down
29 changes: 13 additions & 16 deletions src/ILC/SensorMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,19 @@
using namespace ILC;

SensorMonitor::SensorMonitor(uint8_t bus) : ILCBusList(bus) {
addResponse(
SENSOR_VALUES,
[this](Modbus::Parser parser) {
std::vector<float> values;
// there should be 2 bytes (address, function), 4 bytes floats and 2 bytes CRC - so the size()
// shall be multiple of 4
if (parser.size() % 4 != 0) {
throw std::runtime_error(
fmt::format("Invalid reponse length - expected 4*x, received {}", parser.size()));
}
add_response(SENSOR_VALUES, [this](Modbus::Parser parser) {
std::vector<float> values;
// there should be 2 bytes (address, function), 4 bytes floats and 2 bytes CRC - so the size()
// shall be multiple of 4
if (parser.size() % 4 != 0) {
throw std::runtime_error(
fmt::format("Invalid reponse length - expected 4*x, received {}", parser.size()));
}

for (int i = 1; i < static_cast<int>(parser.size()) / 4; i++) {
values.push_back(parser.read<float>());
}
for (int i = 1; i < static_cast<int>(parser.size()) / 4; i++) {
values.push_back(parser.read<float>());
}

processSensorValues(parser.address(), values);
},
SENSOR_VALUES | MODBUS_ERROR_MASK);
processSensorValues(parser.address(), values);
});
}
24 changes: 11 additions & 13 deletions src/LSST/cRIO/ElectromechanicalPneumaticILC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,26 +99,24 @@ ElectromechanicalPneumaticILC::ElectromechanicalPneumaticILC(uint8_t bus) : ILC:
processMezzaninePressure(parser.address(), primaryPush, primaryPull, secondaryPush, secondaryPull);
};

addResponse(ILC_EM_CMD::SET_STEPPER_STEPS, stepperForceStatus, 194);
add_response(ILC_EM_CMD::SET_STEPPER_STEPS, stepperForceStatus);

addResponse(ILC_EM_CMD::STEPPER_FORCE_STATUS, stepperForceStatus, 195);
add_response(ILC_EM_CMD::STEPPER_FORCE_STATUS, stepperForceStatus);

addResponse(
ILC_EM_CMD::SET_DCA_GAIN, [this](Modbus::Parser parser) { parser.checkCRC(); }, 201);
add_response(ILC_EM_CMD::SET_DCA_GAIN, [this](Modbus::Parser parser) { parser.checkCRC(); });

addResponse(ILC_EM_CMD::REPORT_DCA_GAIN, dcaGain, 202);
add_response(ILC_EM_CMD::REPORT_DCA_GAIN, dcaGain);

addResponse(ILC_EM_CMD::SET_FORCE_OFFSET, forceActuatorForceStatus, 210);
add_response(ILC_EM_CMD::SET_FORCE_OFFSET, forceActuatorForceStatus);

addResponse(ILC_EM_CMD::REPORT_FA_FORCE_STATUS, forceActuatorForceStatus, 220);
add_response(ILC_EM_CMD::REPORT_FA_FORCE_STATUS, forceActuatorForceStatus);

addResponse(
ILC_EM_CMD::SET_OFFSET_AND_SENSITIVITY, [this](Modbus::Parser parser) { parser.checkCRC(); },
235);
add_response(ILC_EM_CMD::SET_OFFSET_AND_SENSITIVITY,
[this](Modbus::Parser parser) { parser.checkCRC(); });

addResponse(ILC_EM_CMD::REPORT_CALIBRATION_DATA, calibrationData, 238);
add_response(ILC_EM_CMD::REPORT_CALIBRATION_DATA, calibrationData);

addResponse(ILC_EM_CMD::REPORT_MEZZANINE_PRESSURE, pressureData, 247);
add_response(ILC_EM_CMD::REPORT_MEZZANINE_PRESSURE, pressureData);

addResponse(ILC_EM_CMD::REPORT_HARDPOINT_LVDT, hardpointLVDT, 250);
add_response(ILC_EM_CMD::REPORT_HARDPOINT_LVDT, hardpointLVDT);
}
9 changes: 3 additions & 6 deletions src/LSST/cRIO/FPGACliApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@ FPGACliApp::FPGACliApp(const char* name, const char* description)
"Temporary disable given ILC in * commands");
addILCCommand("@enable", std::bind(&FPGACliApp::enableILC, this, std::placeholders::_1),
"Re-enable given ILC in * commands");
addILCCommand(
"info", [](ILCUnit u) { u.first->reportServerID(u.second); }, "Print ILC info");
addILCCommand(
"status", [](ILCUnit u) { u.first->reportServerStatus(u.second); }, "Print ILC status");
addILCCommand("info", [](ILCUnit u) { u.first->reportServerID(u.second); }, "Print ILC info");
addILCCommand("status", [](ILCUnit u) { u.first->reportServerStatus(u.second); }, "Print ILC status");
addILCCommand(
"standby", [](ILCUnit u) { u.first->changeILCMode(u.second, ILC::Mode::Standby); },
"Change ILC mode to standby");
Expand All @@ -63,8 +61,7 @@ FPGACliApp::FPGACliApp(const char* name, const char* description)
addILCCommand(
"clear-faults", [](ILCUnit u) { u.first->changeILCMode(u.second, ILC::Mode::ClearFaults); },
"Clear ILC faults");
addILCCommand(
"reset", [](ILCUnit u) { u.first->resetServer(u.second); }, "Reset server");
addILCCommand("reset", [](ILCUnit u) { u.first->resetServer(u.second); }, "Reset server");

addCommand("program-ilc", std::bind(&FPGACliApp::programILC, this, std::placeholders::_1), "FS?",
NEED_FPGA, "<firmware hex file> <ILC...>", "Program ILC with new firmware.");
Expand Down
Loading

0 comments on commit 22743c2

Please sign in to comment.