@@ -109,7 +109,15 @@ def set_log_level(self, log_level):
109
109
110
110
111
111
class AbstractClient :
112
- def __init__ (self , device_id , scope_id , cred_type , key_or_cert , storage = None , max_connection_attempts = 5 ):
112
+ def __init__ (
113
+ self ,
114
+ device_id ,
115
+ scope_id ,
116
+ cred_type ,
117
+ key_or_cert ,
118
+ storage = None ,
119
+ max_connection_attempts = 5 ,
120
+ ):
113
121
self ._device_id = device_id
114
122
self ._scope_id = scope_id
115
123
self ._cred_type = cred_type
@@ -168,8 +176,7 @@ def set_content_encoding(self, content_encoding):
168
176
self ._content_encoding = content_encoding
169
177
170
178
def _prepare_message (self , payload , properties ):
171
- msg = Message (payload , uuid .uuid4 (),
172
- self ._content_encoding , self ._content_type )
179
+ msg = Message (payload , uuid .uuid4 (), self ._content_encoding , self ._content_type )
173
180
if bool (properties ):
174
181
for prop in properties :
175
182
msg .custom_properties [prop ] = properties [prop ]
@@ -186,34 +193,43 @@ def on(self, eventname, callback):
186
193
187
194
def _sync_twin (self ):
188
195
try :
189
- desired = self ._twin [' desired' ]
190
- desired_version = self ._twin [' desired' ][ ' $version' ]
196
+ desired = self ._twin [" desired" ]
197
+ desired_version = self ._twin [" desired" ][ " $version" ]
191
198
except KeyError :
192
199
return
193
200
try :
194
- reported = self ._twin [' reported' ]
201
+ reported = self ._twin [" reported" ]
195
202
except KeyError :
196
203
return
197
204
patch = {}
198
205
for desired_prop in desired :
199
206
print ("Syncing property '{}'" .format (desired_prop ))
200
- if desired_prop == ' $version' :
207
+ if desired_prop == " $version" :
201
208
continue
202
209
# is a component
203
- if str (type (desired [desired_prop ])) == "<class 'dict'>" and '__t' in desired [desired_prop ]:
210
+ if (
211
+ str (type (desired [desired_prop ])) == "<class 'dict'>"
212
+ and "__t" in desired [desired_prop ]
213
+ ):
204
214
desired_prop_component = desired_prop
205
215
for desired_prop_name in desired [desired_prop_component ]:
206
216
if desired_prop_name == "__t" :
207
217
continue
208
218
has_reported = False
209
219
try :
210
- has_reported = reported [desired_prop_component ][desired_prop_name ]
220
+ has_reported = reported [desired_prop_component ][
221
+ desired_prop_name
222
+ ]
211
223
except KeyError :
212
224
pass
213
225
if not has_reported : # no reported yet. send desired
214
226
patch [desired_prop_component ] = desired [desired_prop_component ]
215
227
# desired is more recent
216
- if has_reported and 'av' in has_reported and has_reported ['av' ] < desired_version :
228
+ if (
229
+ has_reported
230
+ and "av" in has_reported
231
+ and has_reported ["av" ] < desired_version
232
+ ):
217
233
patch [desired_prop_component ] = desired [desired_prop_component ]
218
234
else : # default component
219
235
has_reported = False
@@ -224,22 +240,39 @@ def _sync_twin(self):
224
240
if not has_reported : # no reported yet. send desired
225
241
patch [desired_prop ] = desired [desired_prop ]
226
242
# desired is more recent
227
- if has_reported and 'av' in has_reported and has_reported ['av' ] < desired_version :
243
+ if (
244
+ has_reported
245
+ and "av" in has_reported
246
+ and has_reported ["av" ] < desired_version
247
+ ):
228
248
patch [desired_prop ] = desired [desired_prop ]
229
249
230
250
if patch : # there are desired to ack
231
- patch [' $version' ] = desired_version
251
+ patch [" $version" ] = desired_version
232
252
return patch
233
253
else :
234
254
return None
235
255
236
256
237
257
class IoTCClient (AbstractClient ):
238
258
def __init__ (
239
- self , device_id , scope_id , cred_type , key_or_cert , logger = None , storage = None , max_connection_attempts = 5
259
+ self ,
260
+ device_id ,
261
+ scope_id ,
262
+ cred_type ,
263
+ key_or_cert ,
264
+ logger = None ,
265
+ storage = None ,
266
+ max_connection_attempts = 5 ,
240
267
):
241
268
AbstractClient .__init__ (
242
- self , device_id , scope_id , cred_type , key_or_cert , storage , max_connection_attempts
269
+ self ,
270
+ device_id ,
271
+ scope_id ,
272
+ cred_type ,
273
+ key_or_cert ,
274
+ storage ,
275
+ max_connection_attempts ,
243
276
)
244
277
if logger is None :
245
278
self ._logger = ConsoleLogger (IOTCLogLevel .IOTC_LOGGING_API_ONLY )
@@ -281,8 +314,8 @@ def _handle_property_ack(
281
314
"value" : property_value ,
282
315
"ac" : 200 ,
283
316
"ad" : "Completed" ,
284
- "av" : property_version
285
- }
317
+ "av" : property_version ,
318
+ },
286
319
}
287
320
}
288
321
)
@@ -311,8 +344,9 @@ def _update_properties(self, patch, prop_cb):
311
344
312
345
# check if component
313
346
try :
314
- is_component = str (
315
- type (patch [prop ])) == "<class 'dict'>" and patch [prop ]["__t" ]
347
+ is_component = (
348
+ str (type (patch [prop ])) == "<class 'dict'>" and patch [prop ]["__t" ]
349
+ )
316
350
except KeyError :
317
351
pass
318
352
if is_component :
@@ -332,9 +366,7 @@ def _update_properties(self, patch, prop_cb):
332
366
prop ,
333
367
)
334
368
else :
335
- self ._handle_property_ack (
336
- prop_cb , prop , patch [prop ], patch ["$version" ]
337
- )
369
+ self ._handle_property_ack (prop_cb , prop , patch [prop ], patch ["$version" ])
338
370
339
371
def _on_properties (self , patch ):
340
372
self ._logger .debug ("Setup properties listener" )
@@ -435,7 +467,9 @@ def connect(self, force_dps=False):
435
467
Connects the device.
436
468
:raises exception: If connection fails
437
469
"""
438
- if self ._connection_attempts_count > self ._max_connection_attempts : # max number of retries. exit
470
+ if (
471
+ self ._connection_attempts_count > self ._max_connection_attempts
472
+ ): # max number of retries. exit
439
473
self ._terminate = True
440
474
self ._connecting = False
441
475
return
@@ -459,8 +493,7 @@ def connect(self, force_dps=False):
459
493
self ._key_or_cert = self ._compute_derived_symmetric_key (
460
494
self ._key_or_cert , self ._device_id
461
495
)
462
- self ._logger .debug (
463
- "Device key: {}" .format (self ._key_or_cert ))
496
+ self ._logger .debug ("Device key: {}" .format (self ._key_or_cert ))
464
497
465
498
self ._provisioning_client = (
466
499
ProvisioningDeviceClient .create_from_symmetric_key (
@@ -475,8 +508,7 @@ def connect(self, force_dps=False):
475
508
self ._cert_file = self ._key_or_cert ["cert_file" ]
476
509
try :
477
510
self ._cert_phrase = self ._key_or_cert ["cert_phrase" ]
478
- x509 = X509 (self ._cert_file , self ._key_file ,
479
- self ._cert_phrase )
511
+ x509 = X509 (self ._cert_file , self ._key_file , self ._cert_phrase )
480
512
except :
481
513
self ._logger .debug (
482
514
"No passphrase available for certificate. Trying without it"
@@ -494,7 +526,8 @@ def connect(self, force_dps=False):
494
526
495
527
if self ._model_id :
496
528
self ._provisioning_client .provisioning_payload = {
497
- "iotcModelId" : self ._model_id
529
+ "iotcModelId" : self ._model_id ,
530
+ "modelId" : self ._model_id ,
498
531
}
499
532
try :
500
533
registration_result = self ._provisioning_client .register ()
@@ -535,19 +568,25 @@ def connect(self, force_dps=False):
535
568
IOTCConnectType .IOTC_CONNECT_SYMM_KEY ,
536
569
):
537
570
self ._device_client = IoTHubDeviceClient .create_from_connection_string (
538
- _credentials .connection_string
571
+ _credentials .connection_string , product_info = self . _model_id
539
572
)
540
573
else :
541
- if ' cert_phrase' in _credentials .certificate :
574
+ if " cert_phrase" in _credentials .certificate :
542
575
x509 = X509 (
543
- _credentials .certificate ['cert_file' ], _credentials .certificate ['key_file' ], _credentials .certificate ['cert_phrase' ])
576
+ _credentials .certificate ["cert_file" ],
577
+ _credentials .certificate ["key_file" ],
578
+ _credentials .certificate ["cert_phrase" ],
579
+ )
544
580
else :
545
581
x509 = X509 (
546
- _credentials .certificate ['cert_file' ], _credentials .certificate ['key_file' ])
582
+ _credentials .certificate ["cert_file" ],
583
+ _credentials .certificate ["key_file" ],
584
+ )
547
585
self ._device_client = IoTHubDeviceClient .create_from_x509_certificate (
548
586
x509 = x509 ,
549
587
hostname = _credentials .hub_name ,
550
588
device_id = _credentials .device_id ,
589
+ product_info = self ._model_id ,
551
590
)
552
591
self ._device_client .connect ()
553
592
self ._logger .debug ("Device connected" )
@@ -561,14 +600,18 @@ def connect(self, force_dps=False):
561
600
except : # connection to hub failed. hub can be down or connection string expired. fallback to dps
562
601
t , v , tb = sys .exc_info ()
563
602
self ._logger .info ("ERROR: Failed to connect to Hub" )
564
- if force_dps is True : # don't fallback to dps as we already using it for connecting
603
+ if (
604
+ force_dps is True
605
+ ): # don't fallback to dps as we already using it for connecting
565
606
sys .exit (1 )
566
607
self ._connection_attempts_count += 1
567
608
self .connect (True )
568
609
569
610
# setup listeners
570
611
571
- self ._device_client .on_twin_desired_properties_patch_received = self ._on_properties
612
+ self ._device_client .on_twin_desired_properties_patch_received = (
613
+ self ._on_properties
614
+ )
572
615
self ._device_client .on_method_request_received = self ._on_commands
573
616
self ._device_client .on_message_received = self ._on_enqueued_commands
574
617
@@ -602,8 +645,7 @@ def _compute_derived_symmetric_key(self, secret, reg_id):
602
645
try :
603
646
secret = base64 .b64decode (secret )
604
647
except :
605
- self ._logger .debug (
606
- "ERROR: broken base64 secret => `" + secret + "`" )
648
+ self ._logger .debug ("ERROR: broken base64 secret => `" + secret + "`" )
607
649
sys .exit ()
608
650
609
651
return base64 .b64encode (
0 commit comments