@@ -27,6 +27,11 @@ class SinricProClass : public SinricProInterface {
27
27
void handle ();
28
28
void stop ();
29
29
bool isConnected ();
30
+
31
+ typedef std::function<void (void )> connectCallbackHandler;
32
+ void onConnected (connectCallbackHandler cb) { _websocketListener.onConnected (cb); }
33
+ void onDisconnected (connectCallbackHandler cb) { _websocketListener.onDisconnected (cb); }
34
+
30
35
void restoreDeviceStates (bool flag) { _websocketListener.setRestoreDeviceStates (flag); }
31
36
32
37
DynamicJsonDocument prepareResponse (JsonDocument& requestMessage);
@@ -58,16 +63,18 @@ class SinricProClass : public SinricProInterface {
58
63
void disconnect ();
59
64
void reconnect ();
60
65
61
- void onConnect () { DEBUG_SINRIC (" [SinricPro:onConnect() ]\r\n " ); }
62
- void onDisconnect () { DEBUG_SINRIC (" [SinricPro:onDisconnect()] \r\n " ); }
66
+ void onConnect () { DEBUG_SINRIC (" [SinricPro]: Connected to \" %s \" ! ]\r\n " , serverURL. c_str () ); }
67
+ void onDisconnect () { DEBUG_SINRIC (" [SinricPro]: Disconnect \r\n " ); }
63
68
64
- bool checkDeviceId (String deviceId);
69
+ bool verifyDeviceId (const char * id);
70
+ bool verifyAppKey (const char * key);
71
+ bool verifyAppSecret (const char * secret);
65
72
void extractTimestamp (JsonDocument &message);
66
73
67
74
SinricProDeviceInterface* getDevice (String deviceId);
68
75
69
76
template <typename DeviceType>
70
- DeviceType& getDeviceInstance (String deviceId) { return (DeviceType&) * getDevice (deviceId); }
77
+ DeviceType& getDeviceInstance (String deviceId);
71
78
72
79
std::vector<SinricProDeviceInterface*> devices;
73
80
String socketAuthToken;
@@ -81,6 +88,8 @@ class SinricProClass : public SinricProInterface {
81
88
82
89
unsigned long getTimestamp () { return baseTimestamp + (millis ()/1000 ); }
83
90
unsigned long baseTimestamp = 0 ;
91
+
92
+ bool _begin = false ;
84
93
};
85
94
86
95
SinricProDeviceInterface* SinricProClass::getDevice (String deviceId) {
@@ -90,37 +99,86 @@ SinricProDeviceInterface* SinricProClass::getDevice(String deviceId) {
90
99
return nullptr ;
91
100
}
92
101
102
+ template <typename DeviceType>
103
+ DeviceType& SinricProClass::getDeviceInstance (String deviceId) {
104
+ DeviceType* tmp_device = (DeviceType*) getDevice (deviceId);
105
+ if (tmp_device) return *tmp_device;
106
+
107
+ DEBUG_SINRIC (" [SinricPro]: Device \" %s\" does not exist. Creating new device\r\n " , deviceId.c_str ());
108
+ DeviceType& tmp_deviceInstance = add<DeviceType>(deviceId.c_str ());
109
+
110
+ if (isConnected ()) {
111
+ DEBUG_SINRIC (" [SinricPro]: Reconnecting to server.\r\n " );
112
+ reconnect ();
113
+ }
114
+
115
+ return tmp_deviceInstance;
116
+ }
117
+
93
118
void SinricProClass::begin (String socketAuthToken, String signingKey, String serverURL) {
119
+ bool success = true ;
120
+ if (!verifyAppKey (socketAuthToken.c_str ())) {
121
+ DEBUG_SINRIC (" [SinricPro:begin()]: App-Key \" %s\" is invalid!! Please check your app-key!! SinricPro will not work!\r\n " , socketAuthToken.c_str ());
122
+ success = false ;
123
+ }
124
+ if (!verifyAppSecret (signingKey.c_str ())) {
125
+ DEBUG_SINRIC (" [SinricPro:begin()]: App-Secret \" %s\" is invalid!! Please check your app-secret!! SinricPro will not work!\r\n " , signingKey.c_str ());
126
+ success = false ;
127
+ return ;
128
+ }
129
+
130
+ if (!success) {
131
+ _begin = false ;
132
+ return ;
133
+ }
134
+
94
135
this ->socketAuthToken = socketAuthToken;
95
136
this ->signingKey = signingKey;
96
137
this ->serverURL = serverURL;
138
+ _begin = true ;
97
139
}
98
140
99
141
template <typename DeviceType>
100
142
DeviceType& SinricProClass::add (const char * deviceId, unsigned long eventWaitTime) {
101
143
DeviceType* newDevice = new DeviceType (deviceId, eventWaitTime);
102
- if (checkDeviceId (String (deviceId))){
144
+ if (verifyDeviceId (deviceId)){
145
+ DEBUG_SINRIC (" [SinricPro:add()]: Adding device with id \" %s\" .\r\n " , deviceId);
103
146
newDevice->begin (this );
104
- devices.push_back (newDevice);
147
+ if (verifyAppKey (socketAuthToken.c_str ()) && verifyAppSecret (signingKey.c_str ())) _begin = true ;
148
+ } else {
149
+ DEBUG_SINRIC (" [SinricPro:add()]: DeviceId \" %s\" is invalid!! Device will be ignored and will NOT WORK!\r\n " , deviceId);
105
150
}
151
+ devices.push_back (newDevice);
106
152
return *newDevice;
107
153
}
108
154
109
155
__attribute__ ((deprecated(" Please use DeviceType& myDevice = SinricPro.add<DeviceType>(DeviceId);" )))
110
156
void SinricProClass::add(SinricProDeviceInterface* newDevice) {
111
- if (!checkDeviceId ( String ( newDevice->getDeviceId () ))) return ;
157
+ if (!verifyDeviceId ( newDevice->getDeviceId ())) return ;
112
158
newDevice->begin (this );
113
159
devices.push_back (newDevice);
114
160
}
115
161
116
162
__attribute__ ((deprecated(" Please use DeviceType& myDevice = SinricPro.add<DeviceType>(DeviceId);" )))
117
163
void SinricProClass::add(SinricProDeviceInterface& newDevice) {
118
- if (!checkDeviceId ( String ( newDevice.getDeviceId () ))) return ;
164
+ if (!verifyDeviceId ( newDevice.getDeviceId ())) return ;
119
165
newDevice.begin (this );
120
166
devices.push_back (&newDevice);
121
167
}
122
168
123
169
void SinricProClass::handle () {
170
+ static bool begin_error = false ;
171
+ if (!_begin) {
172
+ if (!begin_error) { // print this only once!
173
+ DEBUG_SINRIC (" [SinricPro:handle()]: ERROR! SinricPro.begin() failed or was not called prior to event handler\r\n " );
174
+ DEBUG_SINRIC (" [SinricPro:handle()]: -Reasons include an invalid app-key, invalid app-secret or no valid deviceIds)\r\n " );
175
+ DEBUG_SINRIC (" [SinricPro:handle()]: -SinricPro is disabled! Check earlier log messages for details.\r\n " );
176
+ begin_error = true ;
177
+ }
178
+ return ;
179
+ }
180
+
181
+
124
182
if (!isConnected ()) connect ();
125
183
_websocketListener.handle ();
126
184
_udpListener.handle ();
@@ -201,12 +259,12 @@ void SinricProClass::handleReceiveQueue() {
201
259
String messageType = jsonMessage[" payload" ][" type" ];
202
260
203
261
if (sigMatch) { // signature is valid process message
204
- DEBUG_SINRIC (" [SinricPro.handleReceiveQueue()]: Signature is valid! Processing message.\r\n " );
262
+ DEBUG_SINRIC (" [SinricPro.handleReceiveQueue()]: Signature is valid. Processing message.. .\r\n " );
205
263
extractTimestamp (jsonMessage);
206
264
if (messageType == " response" ) handleResponse (jsonMessage);
207
265
if (messageType == " request" ) handleRequest (jsonMessage, rawMessage->getInterface ());
208
266
} else {
209
- DEBUG_SINRIC (" [SinricPro.handleReceiveQueue()]: Signature is invalid...sending messsage to [dev/null] ;)\r\n " );
267
+ DEBUG_SINRIC (" [SinricPro.handleReceiveQueue()]: Signature is invalid! Sending messsage to [dev/null] ;)\r\n " );
210
268
}
211
269
delete rawMessage;
212
270
}
@@ -248,12 +306,20 @@ void SinricProClass::connect() {
248
306
String deviceList;
249
307
int i = 0 ;
250
308
for (auto & device : devices) {
251
- if (i>0 ) deviceList += " ;" ;
252
- deviceList += String (device->getDeviceId ());
253
- i++;
309
+ const char * deviceId = device->getDeviceId ();
310
+ if (verifyDeviceId (deviceId)) {
311
+ if (i>0 ) deviceList += ' ;' ;
312
+ deviceList += String (deviceId);
313
+ i++;
314
+ }
315
+ }
316
+ if (i==0 ) { // no device have been added! -> do not connect!
317
+ _begin = false ;
318
+ DEBUG_SINRIC (" [SinricPro]: ERROR! No valid devices available. Please add a valid device first!\r\n " );
319
+ return ;
254
320
}
255
321
256
- _websocketListener.begin (serverURL, socketAuthToken, deviceList. c_str () , &receiveQueue);
322
+ _websocketListener.begin (serverURL, socketAuthToken, deviceList, &receiveQueue);
257
323
}
258
324
259
325
@@ -268,31 +334,34 @@ bool SinricProClass::isConnected() {
268
334
269
335
270
336
void SinricProClass::reconnect () {
271
- DEBUG_SINRIC (" SinricProClass. reconnect(): disconnecting\r\n " );
337
+ DEBUG_SINRIC (" SinricPro: reconnect(): disconnecting\r\n " );
272
338
stop ();
273
- DEBUG_SINRIC (" SinricProClass.reconnect(): wait 1second\r\n " );
274
- delay (1000 );
275
- DEBUG_SINRIC (" SinricProClass.reconnect(): connecting\r\n " );
339
+ DEBUG_SINRIC (" SinricPro:reconnect(): connecting\r\n " );
276
340
connect ();
277
341
}
278
342
279
- bool SinricProClass::checkDeviceId (String deviceId) {
280
- if (deviceId.length () != 24 ) {
281
- DEBUG_SINRIC (" [SinricPro.add()]: Invalid deviceId \" %s\" ! Device will be ignored!\r\n " , deviceId.c_str ());
282
- return false ;
283
- }
343
+ bool SinricProClass::verifyDeviceId (const char * id) {
344
+ if (strlen (id) != 24 ) return false ;
345
+ int tmp; char tmp_c;
346
+ return sscanf (id, " %4x%4x%4x%4x%4x%4x%c" ,
347
+ &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp_c) == 6 ;
348
+ }
284
349
285
- for (size_t i = 0 ; i < deviceId.length (); i++) {
286
- char current = deviceId[i];
287
- if (current >= ' 0' && current <= ' 9' ) continue ;
288
- if (current >= ' A' && current <= ' F' ) continue ;
289
- if (current >= ' a' && current <= ' f' ) continue ;
290
- DEBUG_SINRIC (" [SinricPro.add()]: Invalid deviceId \" %s\" ! Device will be ignored!\r\n " , deviceId.c_str ());
291
- return false ;
292
- }
293
- return true ;
350
+ bool SinricProClass::verifyAppKey (const char * key) {
351
+ if (strlen (key) != 36 ) return false ;
352
+ int tmp; char tmp_c;
353
+ return sscanf (key, " %4x%4x-%4x-%4x-%4x-%4x%4x%4x%c" ,
354
+ &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp_c) == 8 ;
294
355
}
295
356
357
+ bool SinricProClass::verifyAppSecret (const char * secret) {
358
+ if (strlen (secret) != 73 ) return false ;
359
+ int tmp; char tmp_c;
360
+ return sscanf (secret, " %4x%4x-%4x-%4x-%4x-%4x%4x%4x-%4x%4x-%4x-%4x-%4x-%4x%4x%4x%c" ,
361
+ &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp_c) == 16 ;
362
+ }
363
+
364
+
296
365
void SinricProClass::extractTimestamp (JsonDocument &message) {
297
366
unsigned long tempTimestamp = 0 ;
298
367
// extract timestamp from timestamp message right after websocket connection is established
0 commit comments