blob: 9498a1c91665d5373d982ac2290a6cc67b9366cc [file] [log] [blame]
#pragma once
#include <format>
#include <stdexcept>
#include <string>
namespace phosphor::modbus::rtu
{
enum class ModbusExceptionCode
{
// The Modbus function code in the request is not supported or is an invalid
// action for the server.
illegalFunctionCode = 1,
// The requested data address is not valid or authorized for the server.
illegalDataAddress = 2,
// The value provided in the request is not an allowable value for the
// server, or the data field is structured incorrectly.
illegalDataValue = 3,
// The server encountered an internal error and cannot perform the requested
// operation.
slaveDeviceFailure = 4,
// The server has accepted the request but needs more time to process it.
acknowledge = 5,
// The server is currently busy and cannot respond to the request.
slaveDeviceBusy = 6,
// The server cannot perform the program function received in the query.
// This code is returned for an unsuccessful programming request using
// function code 13 or 14 decimal. The client should request diagnostic or
// error information from the server.
negativeAcknowledge = 7,
// The server attempted to read extended memory, but detected a parity error
// in the memory. The client can retry the request, but service may be
// required on the server device.
memoryParityError = 8,
unknownError = 255,
};
class ModbusException : public std::runtime_error
{
public:
const ModbusExceptionCode code;
explicit ModbusException(uint8_t code, const std::string& message = "") :
std::runtime_error(std::format(
"{} ({})", toString(static_cast<ModbusExceptionCode>(code)),
message)),
code(static_cast<ModbusExceptionCode>(code))
{}
static auto toString(ModbusExceptionCode code) -> std::string
{
switch (code)
{
case ModbusExceptionCode::illegalFunctionCode:
return "Illegal Function Code";
case ModbusExceptionCode::illegalDataAddress:
return "Illegal Data Address";
case ModbusExceptionCode::illegalDataValue:
return "Illegal Data Value";
case ModbusExceptionCode::slaveDeviceFailure:
return "Slave Device Failure";
case ModbusExceptionCode::acknowledge:
return "Acknowledge";
case ModbusExceptionCode::slaveDeviceBusy:
return "Slave Device Busy";
case ModbusExceptionCode::negativeAcknowledge:
return "Negative Acknowledge";
case ModbusExceptionCode::memoryParityError:
return "Memory Parity Error";
default:
return "Unknown Modbus Error";
}
}
};
class ModbusCRCException : public std::runtime_error
{
public:
explicit ModbusCRCException(uint16_t expectedCRC, uint16_t crc) :
std::runtime_error(
"CRC mismatch, expected: " + std::to_string(expectedCRC) +
" received: " + std::to_string(crc))
{}
};
class ModbusBadResponseException : public std::runtime_error
{
public:
explicit ModbusBadResponseException(const std::string& fieldName,
uint32_t expectedValue,
uint32_t currentValue) :
std::runtime_error(
"Value mismatch for " + fieldName +
", expected value: " + std::to_string(expectedValue) +
", current value: " + std::to_string(currentValue))
{}
};
} // namespace phosphor::modbus::rtu