| Jagpal Singh Gill | 9695bd2 | 2025-10-01 14:38:17 -0700 | [diff] [blame^] | 1 | #pragma once |
| 2 | |
| 3 | #include <format> |
| 4 | #include <stdexcept> |
| 5 | #include <string> |
| 6 | |
| 7 | namespace phosphor::modbus::rtu |
| 8 | { |
| 9 | |
| 10 | enum class ModbusExceptionCode |
| 11 | { |
| 12 | // The Modbus function code in the request is not supported or is an invalid |
| 13 | // action for the server. |
| 14 | illegalFunctionCode = 1, |
| 15 | |
| 16 | // The requested data address is not valid or authorized for the server. |
| 17 | illegalDataAddress = 2, |
| 18 | |
| 19 | // The value provided in the request is not an allowable value for the |
| 20 | // server, or the data field is structured incorrectly. |
| 21 | illegalDataValue = 3, |
| 22 | |
| 23 | // The server encountered an internal error and cannot perform the requested |
| 24 | // operation. |
| 25 | slaveDeviceFailure = 4, |
| 26 | |
| 27 | // The server has accepted the request but needs more time to process it. |
| 28 | acknowledge = 5, |
| 29 | |
| 30 | // The server is currently busy and cannot respond to the request. |
| 31 | slaveDeviceBusy = 6, |
| 32 | |
| 33 | // The server cannot perform the program function received in the query. |
| 34 | // This code is returned for an unsuccessful programming request using |
| 35 | // function code 13 or 14 decimal. The client should request diagnostic or |
| 36 | // error information from the server. |
| 37 | negativeAcknowledge = 7, |
| 38 | |
| 39 | // The server attempted to read extended memory, but detected a parity error |
| 40 | // in the memory. The client can retry the request, but service may be |
| 41 | // required on the server device. |
| 42 | memoryParityError = 8, |
| 43 | unknownError = 255, |
| 44 | }; |
| 45 | |
| 46 | class ModbusException : public std::runtime_error |
| 47 | { |
| 48 | public: |
| 49 | const ModbusExceptionCode code; |
| 50 | |
| 51 | explicit ModbusException(uint8_t code, const std::string& message = "") : |
| 52 | std::runtime_error(std::format( |
| 53 | "{} ({})", toString(static_cast<ModbusExceptionCode>(code)), |
| 54 | message)), |
| 55 | code(static_cast<ModbusExceptionCode>(code)) |
| 56 | {} |
| 57 | |
| 58 | static auto toString(ModbusExceptionCode code) -> std::string |
| 59 | { |
| 60 | switch (code) |
| 61 | { |
| 62 | case ModbusExceptionCode::illegalFunctionCode: |
| 63 | return "Illegal Function Code"; |
| 64 | case ModbusExceptionCode::illegalDataAddress: |
| 65 | return "Illegal Data Address"; |
| 66 | case ModbusExceptionCode::illegalDataValue: |
| 67 | return "Illegal Data Value"; |
| 68 | case ModbusExceptionCode::slaveDeviceFailure: |
| 69 | return "Slave Device Failure"; |
| 70 | case ModbusExceptionCode::acknowledge: |
| 71 | return "Acknowledge"; |
| 72 | case ModbusExceptionCode::slaveDeviceBusy: |
| 73 | return "Slave Device Busy"; |
| 74 | case ModbusExceptionCode::negativeAcknowledge: |
| 75 | return "Negative Acknowledge"; |
| 76 | case ModbusExceptionCode::memoryParityError: |
| 77 | return "Memory Parity Error"; |
| 78 | default: |
| 79 | return "Unknown Modbus Error"; |
| 80 | } |
| 81 | } |
| 82 | }; |
| 83 | |
| 84 | class ModbusCRCException : public std::runtime_error |
| 85 | { |
| 86 | public: |
| 87 | explicit ModbusCRCException(uint16_t expectedCRC, uint16_t crc) : |
| 88 | std::runtime_error( |
| 89 | "CRC mismatch, expected: " + std::to_string(expectedCRC) + |
| 90 | " received: " + std::to_string(crc)) |
| 91 | {} |
| 92 | }; |
| 93 | |
| 94 | class ModbusBadResponseException : public std::runtime_error |
| 95 | { |
| 96 | public: |
| 97 | explicit ModbusBadResponseException(const std::string& fieldName, |
| 98 | uint32_t expectedValue, |
| 99 | uint32_t currentValue) : |
| 100 | std::runtime_error( |
| 101 | "Value mismatch for " + fieldName + |
| 102 | ", expected value: " + std::to_string(expectedValue) + |
| 103 | ", current value: " + std::to_string(currentValue)) |
| 104 | {} |
| 105 | }; |
| 106 | |
| 107 | } // namespace phosphor::modbus::rtu |