-
Notifications
You must be signed in to change notification settings - Fork 0
/
Modbus.cpp
253 lines (217 loc) · 8.43 KB
/
Modbus.cpp
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#pragma hdrstop
#include <memory>
#include "Modbus.h"
//---------------------------------------------------------------------------
namespace Modbus {
//---------------------------------------------------------------------------
void DebugBytesToHex( String Prologue, TBytes Data )
{
#if defined( _DEBUG )
auto SB = std::make_unique<TStringBuilder>( Prologue );
for ( auto Val : Data ) {
SB->AppendFormat( _T( "%.2X " ), ARRAYOFCONST( ( Val ) ) );
}
::OutputDebugString( SB->ToString().c_str() );
#endif
}
static const String ExceptionCodeText[8] = {
_T( "Illegal Function" ),
_T( "Illegal Data Address" ),
_T( "Illegal Data Value" ),
_T( "Slave Device Failure" ),
_T( "Acknowledge" ),
_T( "Slave Device Busy" ),
_T( "Negative Acknowledge" ),
_T( "Memory Parity Error" ),
};
static const String ExceptionCodeDescription[8] = {
_T( "The function code received in the query "
"is not an allowable action for the slave. "
"If a Poll Program Complete command "
"was issued, this code indicates that no "
"program function preceded it." ),
_T( "The data address received in the query "
"is not an allowable address for the "
"slave." ),
_T( "A value contained in the query data "
"field is not an allowable value for the "
"slave." ),
_T( "An unrecoverable error occurred while "
"the slave was attempting to perform the "
"requested action." ),
_T( "The 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 "
"master. The master can next issue a "
"Poll Program Complete message to "
"determine if processing is completed." ),
_T( "The slave is engaged in processing a "
"long–duration program command. The "
"master should retransmit the message "
"later when the slave is free." ),
_T( "The slave 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 master "
"should request diagnostic or error "
"information from the slave." ),
_T( "The slave attempted to read extended "
"memory, but detected a parity error in "
"the memory. The master can retry the "
"request, but service may be required on "
"the slave device." ),
};
//---------------------------------------------------------------------------
String GetExceptionCodeText( ExceptionCode Code )
{
return ExceptionCodeText[static_cast<size_t>( Code ) - 1];
}
//---------------------------------------------------------------------------
String GetExceptionCodeDescription( ExceptionCode Code )
{
return ExceptionCodeDescription[static_cast<size_t>( Code ) - 1];
}
//---------------------------------------------------------------------------
void RaiseFunctionCodeNotImplementedException( FunctionCode Code )
{
throw EBaseException(
Format(
_T( "Function code %.2Xh not implemented" )
, ARRAYOFCONST( ( static_cast<int>( Code ) ) )
)
);
/*
throw EBaseException( String( _T( "Function code " ) ) +
IntToHex( static_cast<int>( Code ), 2 ) +
String( _T( "H not implemented!" ) ) );
*/
}
//---------------------------------------------------------------------------
void RaiseStandardException( Context const & Context, ExceptionCode Code,
String Prefix )
{
switch ( Code ) {
case ExceptionCode::IllegalFunction: throw EIllegalFunction( Context, Prefix );
case ExceptionCode::IllegalDataAddress: throw EIllegalDataAddress( Context, Prefix );
case ExceptionCode::IllegalDataValue: throw EIllegalDataValue( Context, Prefix );
case ExceptionCode::SlaveDeviceFailure: throw ESlaveDeviceFailure( Context, Prefix );
case ExceptionCode::Acknowledge: throw EAcknowledge( Context, Prefix );
case ExceptionCode::SlaveDeviceBusy: throw ESlaveDeviceBusy( Context, Prefix );
case ExceptionCode::NegativeAcknowledge: throw ENegativeAcknowledge( Context, Prefix );
case ExceptionCode::MemoryParityError: throw EMemoryParityError( Context, Prefix );
default:
throw EProtocolException(
Context, Code, _T( "Unknown Modbus exception code" )
);
}
}
//---------------------------------------------------------------------------
namespace Master {
//---------------------------------------------------------------------------
Protocol::Protocol()
{
}
//---------------------------------------------------------------------------
Protocol::~Protocol()
{
}
//---------------------------------------------------------------------------
void Protocol::Open()
{
if ( !IsConnected() ) {
//RaiseExceptionIfIsConnected( _T( "connection already open" ) );
DoOpen();
}
}
//---------------------------------------------------------------------------
void Protocol::Close()
{
if ( IsConnected() ) {
//RaiseExceptionIfIsNotConnected( _T( "connection already closed" ) );
DoClose();
}
}
//---------------------------------------------------------------------------
// DoReadCoilStatus
// DoReadInputStatus
void Protocol::DoReadHoldingRegisters( Context const & /* Context */,
RegAddrType /*StartAddr*/,
RegCountType /*PointCount*/,
RegDataType* /*Data*/ )
{
RaiseFunctionCodeNotImplementedException( FunctionCode::ReadHoldingRegisters );
}
//---------------------------------------------------------------------------
// DoReadInputRegisters
// DoForceSingleCoil
void Protocol::DoPresetSingleRegister( Context const & /* Context */,
RegAddrType /* Addr */,
RegDataType /* Data */ )
{
RaiseFunctionCodeNotImplementedException( FunctionCode::PresetSingleRegister );
}
//---------------------------------------------------------------------------
// DoReadExceptionStatus
// DoDiagnostics
// DoProgram484
// DoPoll484
// DoFetchCommEventCtr
// DoFetchCommEventLog
// DoProgramController
// DoPollController
// DoForceMultipleCoils
void Protocol::DoPresetMultipleRegisters( Context const & /* Context */,
RegAddrType /*StartAddr*/,
RegCountType /*PointCount*/,
RegDataType const * /*Data*/ )
{
RaiseFunctionCodeNotImplementedException( FunctionCode::PresetMultipleRegisters );
}
//---------------------------------------------------------------------------
// ReportSlave
// Program884_M84
// ResetCommLink
// ReadGeneralReference
// WriteGeneralReference
// MaskWrite4XRegister
void Protocol::DoMaskWrite4XRegister( Context const & Context,
RegAddrType Addr,
RegDataType AndMask,
RegDataType OrMask )
{
RaiseFunctionCodeNotImplementedException( FunctionCode::PresetMultipleRegisters );
}
// ReadWrite4XRegisters
// ReadFIFOQueue
//---------------------------------------------------------------------------
void Protocol::RaiseExceptionIfIsConnected( String Msg ) const
{
if ( IsConnected() ) {
throw EBaseException(
Format(
_T( "The connection is already estabilished: %s" )
, ARRAYOFCONST( ( Msg ) )
)
);
}
}
//---------------------------------------------------------------------------
void Protocol::RaiseExceptionIfIsNotConnected( String Msg ) const
{
if ( !IsConnected() ) {
throw EBaseException(
Format(
_T( "The connection was already previously close: %s" )
, ARRAYOFCONST( ( Msg ) )
)
);
}
}
//---------------------------------------------------------------------------
}; // End of namespace Master
//---------------------------------------------------------------------------
}; // End of namespace Modbus
//---------------------------------------------------------------------------