1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::error::Error;
use thiserror::Error;
use crate::{DecodeError, InvalidPointData, Model};
/// This error is returned if a communication fails because of a timeout
/// or underlying modbus error.
#[derive(Debug, Error)]
pub enum ModbusError {
/// A timeout occured
#[error("Timeout")]
Timeout,
/// The requested device does not implement modbus correctly and the
/// underlying modbus implementation reported an error.
#[error(transparent)]
Protocol(Box<dyn Error + Send + Sync>),
/// I/O error
#[error("I/O error")]
IO(#[from] std::io::Error),
/// The function code received in the query is not an allowable action for
/// the server (or slave). This may be because the function code is only
/// applicable to newer devices, and was not implemented in the unit
/// selected. It could also indicate that the server (or slave) is in the
/// wrong state to process a request of this type, for example because it is
/// unconfigured and is being asked to return register values.
#[error("Illegal function")]
IllegalFunction,
/// The data address received in the query is not an allowable address for
/// the server (or slave). More specifically, the combination of reference
/// number and transfer length is invalid. For a controller with 100
/// registers, the PDU addresses the first register as 0, and the last one
/// as 99. If a request is submitted with a starting register address of 96
/// and a quantity of registers of 4, then this request will successfully
/// operate (address-wise at least) on registers 96, 97, 98, 99. If a
/// request is submitted with a starting register address of 96 and a
/// quantity of registers of 5, then this request will fail with Exception
/// Code 0x02 “Illegal Data Address” since it attempts to operate on
/// registers 96, 97, 98, 99 and 100, and there is no register with address
/// 100.
#[error("Illegal data address")]
IllegalDataAddress,
/// A value contained in the query data field is not an allowable value for
/// server (or slave). This indicates a fault in the structure of the
/// remainder of a complex request, such as that the implied length is
/// incorrect. It specifically does NOT mean that a data item submitted for
/// storage in a register has a value outside the expectation of the
/// application program, since the MODBUS protocol is unaware of the
/// significance of any particular value of any particular register.
#[error("Illegal data value")]
IllegalDataValue,
/// An unrecoverable error occurred while the server (or slave) was
/// attempting to perform the requested action.
#[error("Server device failure")]
ServerDeviceFailure,
/// Specialized use in conjunction with programming
/// commands. The server (or slave) has accepted the request and is
/// processing it, but a long duration of time will be required to do so.
/// This response is returned to prevent a timeout error from occurring in
/// the client (or master). The client (or master) can next issue a Poll
/// Program Complete message to determine if processing is completed.
#[error("Acknowledge")]
Acknowledge,
/// Specialized use in conjunction with programming commands. The server (or
/// slave) is engaged in processing a long–duration program command. The
/// client (or master) should retransmit the message later when the server
/// (or slave) is free.
#[error("Server device busy")]
ServerDeviceBusy,
/// Specialized use in conjunction with function codes 20 and 21 and
/// reference type 6, to indicate that the extended file area failed to pass
/// a consistency check. The server (or slave) attempted to read record
/// file, but detected a parity error in the memory. The client (or master)
/// can retry the request, but service may be required on the server (or
/// slave) device.
#[error("Memory parity error")]
MemoryParityError,
/// Specialized use in conjunction with gateways, indicates that the gateway
/// was unable to allocate an internal communication path from the input
/// port to the output port for processing the request. Usually means that
/// the gateway is misconfigured or overloaded.
#[error("Gateway path unavailable")]
GatewayPathUnavailable,
/// Specialized use in conjunction with gateways, indicates that no response
/// was obtained from the target device. Usually means that the device is
/// not present on the network.
#[error("Gateway target device")]
GatewayTargetDevice,
/// Custom modbus error
#[error("Custom: {0}")]
Custom(u8),
}
/// This error is returned if there was an error loading the
/// requested model.
#[derive(Debug, Error)]
pub enum ReadModelError<M: Model> {
/// Some error occured while communicating via the modbus. This
/// error is implementation specific.
#[error("Modbus error: {0}")]
Modbus(#[from] ModbusError),
/// The decoding of the point data failed.
#[error("Decode error: {0}")]
DecodeError(#[from] DecodeError),
/// The model decoded but contains invalid point data.
#[error(transparent)]
InvalidPointData(#[from] InvalidPointData<M>),
}
/// This error is returned if there was an error while
/// reading data from a point.
#[derive(Debug, Error)]
pub enum ReadPointError {
/// Communication error.
#[error("Modbus error: {0}")]
Modbus(#[from] ModbusError),
/// The decoding of the point data failed.
#[error("Decode error: {0}")]
DecodeError(#[from] DecodeError),
/// The point is mandatory but value is missing.
#[error("Missing mandatory value")]
MissingMandatoryValue,
}
/// This error is returned if there was an error while
/// writing data to a point.
#[derive(Debug, Error)]
pub enum WritePointError {
/// Communication error.
#[error("Modbus error: {0}")]
Modbus(#[from] ModbusError),
/// The encoded value was too large for the point.
#[error("Encoded value too large for point")]
ValueTooLarge,
}