-
Notifications
You must be signed in to change notification settings - Fork 1
/
ICiiClient.cs
295 lines (244 loc) · 10.5 KB
/
ICiiClient.cs
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TAInstruments.CommonInstrumentInterface
{
/// <summary>
/// Mercury Trios comm specified Access Levels.
/// </summary>
public enum CiiAccessLevel
{
AlInvalid = 0,
AlViewOnly = 1,
AlMaster = 2,
AlLocalUI = 3,
AlEngineering = 1000
}
/// <summary>
/// Mercury Trios comm specified message statuses.
/// </summary>
public enum CiiMsgStatus
{
MsSuccess = 0, /** It worked. */
MsFailed = 1, /** It didn't work. */
MsUnknownCommand = 2, /** Unknown command message. */
MsMalformedMessage = 3, /** Trouble parsing the message at the protocol level */
MsBusy = 4, /** Try again later... */
MsNotLoggedIn = 5, /** Try again later... */
MsAccessDenied = 6, /** Try again later... */
MsOperationTimedOut = 7, /** Internal Timeout */
MsUserSpecific = 256, /** Everything past this is custom */
}
/// <summary>
/// The callback used for receiving status messages.
/// </summary>
/// <param name="substatus"></param>
/// <param name="buffer"></param>
/// <param name="startingOffset"></param>
/// <param name="dataLength"></param>
/// <remarks>
/// We pass you the actual received buffer as an optimization.
/// You need to pay attention to where to start to deserialize the
/// buffer based on StartingOffset and DataLength.
/// </remarks>
public delegate void ReceiveStatusHandler(uint substatus, byte[] buffer, int startingOffset, int dataLength);
public delegate void ReceiveAckHandler(object userData, uint sequenceNumber);
public delegate void ReceiveNakHandler(object userData, uint sequenceNumber, uint errorCode);
public delegate void ReceiveResponseHandler( object userData,
uint sequenceNumber,
uint subcommand,
uint statusCode,
byte[] data,
int startingOffset,
int dataLength);
public class CiiAsyncErrorEventArgs : EventArgs
{
public string ErrorDescription {get; private set; }
public CiiAsyncErrorEventArgs(string errorDescription)
{
ErrorDescription = errorDescription;
}
}
/// <summary>
/// If something goes wrong, this is called.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// FYI - These callbacks are made on a different thread.
/// </remarks>
public delegate void AsyncErrorEventHandler(object sender, CiiAsyncErrorEventArgs e);
/// <summary>
/// This is called when you become connected.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// These callbacks can be made on your thread or a different one.
/// </remarks>
public delegate void ConnectEventHandler(object sender, EventArgs e);
/// <summary>
/// This is called when you become disconnected.
/// </summary>
/// When this is called, you are out of sync with the Instrument.
/// This will always be called first:
/// 1) DisconnectEventHandler
/// 2) DisconnectWarningEventHandler
/// 3) DisconnectErrorEventHandler
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// FYI - These callbacks are made on a different thread.
/// </remarks>
public delegate void DisconnectEventHandler(object sender, EventArgs e);
/// <summary>
/// This is called after you've been disconnected for warningDelay seconds.
/// </summary>
/// This will always be called second:
/// 1) DisconnectEventHandler
/// 2) DisconnectWarningEventHandler
/// 3) DisconnectErrorEventHandler
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// FYI - These callbacks are made on a different thread.
/// </remarks>
public delegate void DisconnectWarningEventHandler(object sender, EventArgs e);
/// <summary>
/// This is called after you've been disconnected for errorDelay seconds.
/// </summary>
/// This will always be called third:
/// 1) DisconnectEventHandler
/// 2) DisconnectWarningEventHandler
/// 3) DisconnectErrorEventHandler
/// After this is called, the comms layer aborts further communications
/// attempts. There will be no more retries.
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// FYI - These callbacks are made on a different thread.
/// </remarks>
public delegate void DisconnectErrorEventHandler(object sender, EventArgs e);
/// <summary>
/// The interface to get information resulting from a SendActionCommand() or SendGetCommand().
/// </summary>
public class CommandCompletion
{
public CommandCompletion()
{
AckHandler = null;
NakHandler = null;
ResponseHandler = null;
UserData = null;
}
public CommandCompletion(ReceiveAckHandler receiveAck,
ReceiveNakHandler receiveNak,
ReceiveResponseHandler receiveResponse)
{
AckHandler = receiveAck;
NakHandler = receiveNak;
ResponseHandler = receiveResponse;
UserData = null;
}
public CommandCompletion(ReceiveAckHandler receiveAck,
ReceiveNakHandler receiveNak,
ReceiveResponseHandler receiveResponse,
object userData)
{
AckHandler = receiveAck;
NakHandler = receiveNak;
ResponseHandler = receiveResponse;
UserData = userData;
}
// OPAQUE REFERENCE TO USER DATA
public object UserData { get; private set; }
public ReceiveAckHandler AckHandler { get; private set; }
public ReceiveNakHandler NakHandler { get; private set; }
public ReceiveResponseHandler ResponseHandler { get; private set; }
}
/// <summary>
/// This is the Client interface to the Mercury communications API.
/// </summary>
/// <remarks>
/// Application code should confine itself to this interface,
/// after it has made the apropriate unique CiiClient.
/// </remarks>
public interface ICiiClient
{
bool Connect(CiiAccessLevel requestedAccess);
void Disconnect();
bool IsConnected { get; }
/// <summary>
/// This allows you to get a specific status message delivered to you.
/// </summary>
/// <param name="statusMessage"></param>
/// <param name="statusDelegate"></param>
/// <returns></returns>
bool RegisterStatusHandler(uint statusMessage, ReceiveStatusHandler statusDelegate);
/// <summary>
/// If a message is not consumed by a registered status handler (above),
/// and there is an unhandled status handler, it will be called.
/// </summary>
/// <param name="statusDelegate"></param>
/// <returns></returns>
/// <remarks>
/// There can only be one of these registered.
/// </remarks>
bool RegisterUnhandledStatusHandler(ReceiveStatusHandler statusDelegate);
event AsyncErrorEventHandler AsyncErrorEvent;
event ConnectEventHandler ConnectEvent;
event DisconnectEventHandler DisconnectEvent;
event DisconnectWarningEventHandler DisconnectWarning;
event DisconnectErrorEventHandler DisconnectError;
/// <summary>
/// Allows you to change the defaults of when the comms library
/// will send you a DisconnectWarningEventHandler event and a
/// DisconnectErrorEventHandler.
/// </summary>
/// When the OS tells the comms layer that the socket is
/// disconnected, we send the DisconnectEvent right then.
/// When warningDelay seconds have elapsed after this point,
/// we send the DisconnectWarningEventHandler event.
/// When errorDelay seconds have from the disconnect, we send the
/// DisconnectErrorEventHandler event, and we stop retrying.
/// If the math is wrong we just ignore the invalid parameter(s).
/// The following must be true:
/// errorDelay > warningDelay > 0
/// <param name="warningDelay">Delay in seconds from Disconnect to callback.
/// Default value = 5 seconds.</param>
/// <param name="errorDelay">Delay in seconds from Disconnect to callback
/// Default value = 30 seconds.</param>
void SetCommFailureTimeouts(int warningDelay, int errorDelay);
CiiAccessLevel GrantedAccess { get; }
#region Send Message API
bool SendActionCommand( uint subcommand,
byte[] data,
CommandCompletion completion,
out uint sequenceNumber);
bool SendActionCommand(uint subcommand,
byte[] data,
CommandCompletion completion
);
bool SendGetCommand( uint subcommand,
byte[] data,
CommandCompletion completion,
out uint sequenceNumber);
bool SendGetCommand( uint subcommand,
byte[] data,
CommandCompletion completion
);
#endregion
/// <summary>
/// This allows you to cancel a Get or Action command while it is being worked on.
/// </summary>
/// <param name="sequenceNumber"></param>
/// <remarks>
/// Calling this does "NOT" guarantee that your callbacks won't be called.
/// There are implicit race conditions with this type of operation.
/// You need to be ready to handle callbacks you cancelled even AFTER
/// you have called this.
/// </remarks>
void DeleteCommandInProgress(uint sequenceNumber);
}
}