#pragma once #include #include #include 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(code)), message)), code(static_cast(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