-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathJSONclasses.cs
556 lines (436 loc) · 16.9 KB
/
JSONclasses.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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Encrypt;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Remootio
{
public partial class Remootio
{
/// <summary>
/// Message types
/// </summary>
public enum type
{
NOTSET,
// The API client sends this to keep the connection alive. It is recommended to send one PING frame to the
// Remootio device every 60-90 seconds and also check for the PONG response to detect a broken connection.
// Direction: API client → Remootio device
PING,
// Response: Remootio device → API client
PONG,
// The Remootio device sends error frames to the API client to indicate various errors
// Direction: Remootio device → API client
ERROR,
// Note: not documented
INPUT_ERROR,
// The API client can send this frame to check the version of the Websocket API running on the Remootio device
// Direction: API client → Remootio device
HELLO,
// Response: Remootio device → API client
SERVER_HELLO,
// The API client sends the AUTH frame to start the authentication flow
// Direction: API client → Remootio device
AUTH,
//
ENCRYPTED,
// The API client sends this action to get the current state of the gate or garage door (open/closed)
// Direction: API client → Remootio device
QUERY,
// The API client sends this action to trigger the control output of the Remootio device
// and thus operate the gate or garage door
// Direction: API client → Remootio device
TRIGGER,
// The API client sends this action to open the gate or the garage door.
// This will trigger Remootio's control output only if the gate or garage door status is "closed"
// Direction: API client → Remootio device
OPEN,
// The API client sends this action to close the gate or the garage door.
// This will trigger Remootio's control output only if the gate or garage door status is "open"
// Direction: API client → Remootio device
CLOSE,
// The API client sends this action to restart the Remootio device. The UNENCRYPTED_PAYLOAD of the
// action is shown below (the action id also needs to be calculated id = lastActionId % 0x7FFFFFFF)
// Direction: API client → Remootio device
RESTART,
// Remootio sends the following event if the status of the gate or garage door has changed
// (from "open" to "closed" or from "closed" to "open").
// This is the only event that is sent if the API is enabled without logging.
// It is also sent if the API is enabled with logging.
// Direction: Remootio device → API client
StateChange,
// Remootio sends the following event if it any key has operated the Remootio device
// (triggered the control output)
// Direction: Remootio device → API client
RelayTrigger,
// Remootio sends the following event if any key has connected to the Remootio device.
// Direction: Remootio device → API client
Connected,
// Remootio sends the following event if the gate or garage door has been left open for some time
// Direction: Remootio device → API client
LeftOpen,
// Remootio sends the following event if the access rights or notification settings for any key have been changed
// Direction: Remootio device → API client
KeyManagement,
// Remootio sends the following event if it was restarted
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
Restart,
// Remootio sends the following event if the manual button was pushed
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
ManualButtonPushed,
// Remootio sends the following event if the manual button was enabled
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
ManualButtonEnabled,
// Remootio sends the following event if the manual button was disabled.
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
ManualButtonDisabled,
// Remootio sends the following event if the doorbell was pushed.
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
DoorbellPushed,
// Remootio sends the following event if the doorbell was enabled
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
DoorbellEnabled,
// Remootio sends the following event if the doorbell was disabled
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
DoorbellDisabled,
// Remootio sends the following event if the status sensor was enabled.
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
SensorEnabled,
// Remootio sends the following event if the logic of the status sensor was flipped
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
SensorFlipped,
// Remootio sends the following event if the status sensor was disabled
// This is only sent if the API is enabled with logging
// Direction: Remootio device → API client
SensorDisabled,
}
#region Messages
[Serializable]
public class BASE
{
// setting the order to 1 will only work if you set an order greater than 1 on all other properties.
// By default any property without an Order setting will be given an order of -1.
// So you must either give all serialized properties and order, or set your first item to -2
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty(Order = -10)]
public type type;
[JsonConstructor]
protected BASE()
{
}
protected BASE(type type)
{
this.type = type;
}
}
#region Responses / Events
public class _Challenge
{
public string sessionKey { get; set; }
public int initialActionId { get; set; }
}
/// <summary>
/// Received from device in response to "AUTH"
/// </summary>
public class Challenge
{
public _Challenge challenge { get; set; }
}
protected class ERROR : BASE
{
[JsonConstructor]
public ERROR() : base(type.ERROR) { }
public string errorMessage;
}
protected class SERVER_HELLO : BASE
{
[JsonConstructor]
public SERVER_HELLO() : base(type.SERVER_HELLO) { }
public int apiVersion;
public string message;
}
/// <summary>
/// Which key caused an event (Connected, RelayTrigger, etc?)
/// </summary>
public class KeyData
{
/// <summary>
/// shows which key has operated the device
/// </summary>
public int? keyNr { get; set; }
/// <summary>
/// "master key" - the key of the Remootio device's owner who has set it up
/// "unique key" - the unique keys the owner has shared with other people
/// "guest key" - the guest key that can be shared with an unlimited amount of people
/// "api key" - "keyType" is "api key" if the event was triggered by this websocket API client
/// "smart home" - if the event was triggered by the smart home key used for Alexa, Google Home etc
/// </summary>
public string keyType { get; set; }
/// <summary>
/// "bluetooth" - event was triggered via Bluetooth
/// "wifi" - event was triggered via Wi-Fi
/// "internet" - event was triggered via the Internet (EasyConnect)
/// "autoopen" - event was triggered by the auto-open feature
/// "unknown" - this should normally not happen at all
/// </summary>
public string via { get; set; }
}
public class RESPONSE : BASE
{
[JsonConstructor]
protected RESPONSE()
{
}
protected RESPONSE(type type) : base(type)
{
}
/// <summary>
/// Raw json data
/// </summary>
public string raw { get; set; }
/// <summary>
/// State open/closed (or no sensor)
/// </summary>
public string state { get; set; }
public string errorCode { get; set; }
/// <summary>
/// shows the time passed since the last restart of the Remootio device in 100ms units
/// </summary>
public int t100ms { get; set; }
/// <summary>
/// LastActionId
/// Only used for replies to the actions, hense Nullable
/// </summary>
public int? id { get; set; }
/// <summary>
/// Some events have counter
/// Only used for replies to the actions, hense Nullable
/// </summary>
public int? cnt { get; set; }
/// <summary>
/// Only used for replies to the actions, hense Nullable
/// </summary>
public bool? success { get; set; }
/// <summary>
/// The field "relayTriggered" shows if Remootio's output relay was triggered during the action
/// Only used for replies to the actions, hense Nullable
/// </summary>
public bool? relayTriggered { get; set; }
}
/// <summary>
/// Used for the following types:
/// Connected, RelayTrigger, KeyManagement
/// </summary>
public class RESPONSE_WITH_KEY : RESPONSE
{
[JsonConstructor]
RESPONSE_WITH_KEY()
{
}
protected RESPONSE_WITH_KEY(type type) : base(type)
{
}
/// <summary>
/// Which key caused an event (Connected, RelayTrigger, etc?)
/// </summary>
public KeyData data { get; set; }
}
public class LeftOpenData
{
/// <summary>
/// The field "timeOpen100ms" shows how long the gate has been left open in multiples of 100 ms
/// </summary>
public int timeOpen100ms { get; set; }
}
/// <summary>
/// Used for the following types:
/// Connected, RelayTrigger, KeyManagement
/// </summary>
public class LeftOpen : RESPONSE
{
[JsonConstructor]
LeftOpen() : base(type.LeftOpen)
{
}
/// <summary>
/// Which key caused an event (Connected, RelayTrigger, etc?)
/// </summary>
public LeftOpenData data { get; set; }
}
// protected class QUERY_RESPONSE : RESPONSE
// {
// [JsonConstructor]
// public QUERY_RESPONSE() : base(type.QUERY) { }
// }
//
//
// protected class TRIGGER_RESPONSE : RESPONSE
// {
// [JsonConstructor]
// public TRIGGER_RESPONSE() : base(type.TRIGGER) { }
// }
//
//
// protected class OPEN_RESPONSE : RESPONSE
// {
// [JsonConstructor]
// public OPEN_RESPONSE() : base(type.OPEN) { }
// }
//
//
// protected class CLOSE_RESPONSE : RESPONSE
// {
// [JsonConstructor]
// public CLOSE_RESPONSE() : base(type.CLOSE) { }
// }
//
//
// /// <summary>
// /// Remootio sends the following event if it any key has operated
// /// the Remootio device (triggered the control output)
// /// </summary>
// protected class RelayTrigger : RESPONSE
// {
// [JsonConstructor]
// public RelayTrigger() : base(type.RelayTrigger) { }
// }
//
//
// /// <summary>
// /// Remootio sends the following event if any key has connected to the Remootio device
// /// </summary>
// protected class Connected : RESPONSE
// {
// [JsonConstructor]
// public Connected() : base(type.Connected) { }
// }
#endregion Responses
#region Requests
protected class PING : BASE
{
public PING() : base(type.PING) { }
}
protected class AUTH : BASE
{
public AUTH() : base(type.AUTH) { }
}
protected class HELLO : BASE
{
public HELLO() : base(type.HELLO) { }
}
/// <summary>
/// Both Request and Response
/// </summary>
public class ENCRYPTED : BASE
{
[JsonConstructor]
public ENCRYPTED() : base(type.ENCRYPTED) { }
[JsonProperty(Order = -9)]
public encr data;
[JsonProperty(Order = -8)]
public string mac;
}
public class encr
{
public string iv;
public string payload;
}
#endregion Requests
#region ACTIONS
protected class QUERY : E_ACTION
{
[JsonConstructor]
public QUERY(int id, AesEncryption aes, string sIV = null)
: base(type.QUERY, id, aes, sIV)
{
}
}
protected class TRIGGER : E_ACTION
{
[JsonConstructor]
public TRIGGER(int id, AesEncryption aes, string sIV = null)
: base(type.TRIGGER, id, aes, sIV)
{
}
}
protected class OPEN : E_ACTION
{
[JsonConstructor]
public OPEN(int id, AesEncryption aes, string sIV = null)
: base(type.OPEN, id, aes, sIV)
{
}
}
protected class CLOSE : E_ACTION
{
[JsonConstructor]
public CLOSE(int id, AesEncryption aes, string sIV = null)
: base(type.CLOSE, id, aes, sIV)
{
}
}
/// <summary>
/// ACTION.action field definition
/// {"action":{"type":"QUERY","id":1836946866}}
/// </summary>
public class _ACTION : BASE
{
[JsonConstructor]
public _ACTION(type type, int id)
: base(type)
{
//this.type = type;
this.id = id;
}
// Action ID
public int id;
}
/// <summary>
/// Unencrypted data.payload of the frame
/// {"action":{"type":"QUERY","id":1836946866}}
/// </summary>
public class ACTION
{
[JsonConstructor]
public ACTION(type type, int id)
{
Console.WriteLine($"\nACTION: '{type}', id {id}");
this.action = new _ACTION(type, id);
}
public _ACTION action;
}
/// <summary>
/// Encrypted wrapper for Action
/// </summary>
public class E_ACTION : ENCRYPTED
{
/// <summary>
/// Ctor - create encr data field
/// </summary>
/// <param name="type"></param>
/// <param name="id">Action ID</param>
/// <param name="aes">AesEncryption</param>
/// <param name="sIV">Only for testing, normally pass null to generate</param>
public E_ACTION(type type, int id, AesEncryption aes, string sIV = null)
{
ACTION action = new ACTION(type, id);
this.data = MakeEncr(action, aes, sIV);
this.mac = hmac(data, aes);
}
}
#endregion ACTIONS
#endregion Messages
}
}