xref: /openbmc/phosphor-modbus/rtu/modbus/modbus_exception.hpp (revision 9695bd284570b51677c11529103929c8e51da6b6)
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 
ModbusException(uint8_t code,const std::string & message="")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 
toString(ModbusExceptionCode code)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:
ModbusCRCException(uint16_t expectedCRC,uint16_t crc)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:
ModbusBadResponseException(const std::string & fieldName,uint32_t expectedValue,uint32_t currentValue)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
108