@@ -286,8 +286,8 @@ def __init__(self, panda, tx_addr, rx_addr=None, bus=0, timeout=10, debug=False)
286
286
287
287
def _isotp_thread (self , debug ):
288
288
try :
289
- rx_frame = {"size" : 0 , "data" : "" , "idx" : 0 , "done" : True }
290
- tx_frame = {"size" : 0 , "data" : "" , "idx" : 0 , "done" : True }
289
+ rx_frame = {"size" : 0 , "data" : b "" , "idx" : 0 , "done" : True }
290
+ tx_frame = {"size" : 0 , "data" : b "" , "idx" : 0 , "done" : True }
291
291
292
292
# allow all output
293
293
self .panda .set_safety_mode (0x1337 )
@@ -333,9 +333,16 @@ def _isotp_thread(self, debug):
333
333
self .rx_queue .put (rx_frame ["data" ])
334
334
elif rx_data [0 ] >> 4 == 0x3 :
335
335
# flow control
336
- assert tx_frame ["done" ] == False , "tx: no active frame"
337
- # TODO: support wait/overflow
338
- assert rx_data [0 ] == 0x30 , "tx: flow-control requires: continue"
336
+ if tx_frame ["done" ] != False :
337
+ tx_frame ["done" ] = True
338
+ self .rx_queue .put (b"\x7F \xFF \xFF tx: no active frame" )
339
+ # TODO: support wait
340
+ if rx_data [0 ] == 0x31 :
341
+ tx_frame ["done" ] = True
342
+ self .rx_queue .put (b"\x7F \xFF \xFF tx: flow-control error - wait not supported" )
343
+ if rx_data [0 ] == 0x32 :
344
+ tx_frame ["done" ] = True
345
+ self .rx_queue .put (b"\x7F \xFF \xFF tx: flow-control error - overflow/abort" )
339
346
delay_ts = rx_data [2 ] & 0x7F
340
347
# scale is 1 milliseconds if first bit == 0, 100 micro seconds if first bit == 1
341
348
delay_div = 1000. if rx_data [2 ] & 0x80 == 0 else 10000.
@@ -346,7 +353,7 @@ def _isotp_thread(self, debug):
346
353
for i in range (start , end , 7 ):
347
354
tx_frame ["idx" ] += 1
348
355
# consecutive tx frames
349
- msg = (chr (0x20 | (tx_frame ["idx" ] & 0xF )).encode ("utf8" ) + tx_frame ["data" ][i :i + 7 ]).ljust (8 , b"\x00 " )
356
+ msg = (chr (0x20 | (tx_frame ["idx" ] & 0xF )).encode () + tx_frame ["data" ][i :i + 7 ]).ljust (8 , b"\x00 " )
350
357
if (debug ): print ("S: {} {}" .format (hex (self .tx_addr ), hexlify (msg )))
351
358
self .panda .can_send (self .tx_addr , msg , self .bus )
352
359
if delay_ts > 0 :
@@ -357,12 +364,12 @@ def _isotp_thread(self, debug):
357
364
if not self .tx_queue .empty ():
358
365
req = self .tx_queue .get (block = False )
359
366
# reset rx and tx frames
360
- rx_frame = {"size" : 0 , "data" : "" , "idx" : 0 , "done" : True }
367
+ rx_frame = {"size" : 0 , "data" : b "" , "idx" : 0 , "done" : True }
361
368
tx_frame = {"size" : len (req ), "data" : req , "idx" : 0 , "done" : False }
362
369
if tx_frame ["size" ] < 8 :
363
370
# single frame
364
371
tx_frame ["done" ] = True
365
- msg = (chr (tx_frame ["size" ]).encode ("utf8" ) + tx_frame ["data" ]).ljust (8 , b"\x00 " )
372
+ msg = (chr (tx_frame ["size" ]).encode () + tx_frame ["data" ]).ljust (8 , b"\x00 " )
366
373
if (debug ): print ("S: {} {}" .format (hex (self .tx_addr ), hexlify (msg )))
367
374
self .panda .can_send (self .tx_addr , msg , self .bus )
368
375
else :
@@ -379,9 +386,9 @@ def _isotp_thread(self, debug):
379
386
380
387
# generic uds request
381
388
def _uds_request (self , service_type , subfunction = None , data = None ):
382
- req = chr (service_type ).encode ("utf8" )
389
+ req = chr (service_type ).encode ()
383
390
if subfunction is not None :
384
- req += chr (subfunction ).encode ("utf8" )
391
+ req += chr (subfunction ).encode ()
385
392
if data is not None :
386
393
req += data
387
394
self .tx_queue .put (req )
@@ -407,7 +414,7 @@ def _uds_request(self, service_type, subfunction=None, data=None):
407
414
try :
408
415
error_desc = _negative_response_codes [error_code ]
409
416
except Exception :
410
- error_desc = 'unknown error'
417
+ error_desc = resp [ 3 :]
411
418
# wait for another message if response pending
412
419
if error_code == 0x78 :
413
420
time .sleep (0.1 )
@@ -452,7 +459,7 @@ def security_access(self, access_type, security_key=None):
452
459
return security_seed
453
460
454
461
def communication_control (self , control_type , message_type ):
455
- data = chr (message_type ).encode ("utf8" )
462
+ data = chr (message_type ).encode ()
456
463
self ._uds_request (SERVICE_TYPE .COMMUNICATION_CONTROL , subfunction = control_type , data = data )
457
464
458
465
def tester_present (self , ):
@@ -505,7 +512,7 @@ def response_on_event(self, response_event_type, store_event, window_time, event
505
512
def link_control (self , link_control_type , baud_rate_type = None ):
506
513
if link_control_type == LINK_CONTROL_TYPE .VERIFY_BAUDRATE_TRANSITION_WITH_FIXED_BAUDRATE :
507
514
# baud_rate_type = BAUD_RATE_TYPE
508
- data = chr (baud_rate_type ).encode ("utf8" )
515
+ data = chr (baud_rate_type ).encode ()
509
516
elif link_control_type == LINK_CONTROL_TYPE .VERIFY_BAUDRATE_TRANSITION_WITH_SPECIFIC_BAUDRATE :
510
517
# baud_rate_type = custom value (3 bytes big-endian)
511
518
data = struct .pack ('!I' , baud_rate_type )[1 :]
@@ -527,7 +534,7 @@ def read_memory_by_address(self, memory_address, memory_size, memory_address_byt
527
534
raise ValueError ('invalid memory_address_bytes: {}' .format (memory_address_bytes ))
528
535
if memory_size_bytes < 1 or memory_size_bytes > 4 :
529
536
raise ValueError ('invalid memory_size_bytes: {}' .format (memory_size_bytes ))
530
- data = chr (memory_size_bytes << 4 | memory_address_bytes ).encode ("utf8" )
537
+ data = chr (memory_size_bytes << 4 | memory_address_bytes ).encode ()
531
538
532
539
if memory_address >= 1 << (memory_address_bytes * 8 ):
533
540
raise ValueError ('invalid memory_address: {}' .format (memory_address ))
@@ -549,7 +556,7 @@ def read_scaling_data_by_identifier(self, data_identifier_type):
549
556
550
557
def read_data_by_periodic_identifier (self , transmission_mode_type , periodic_data_identifier ):
551
558
# TODO: support list of identifiers
552
- data = chr (transmission_mode_type ).encode ("utf8" ) + chr (periodic_data_identifier ).encode ("utf8" )
559
+ data = chr (transmission_mode_type ).encode () + chr (periodic_data_identifier ).encode ()
553
560
self ._uds_request (SERVICE_TYPE .READ_DATA_BY_PERIODIC_IDENTIFIER , subfunction = None , data = data )
554
561
555
562
def dynamically_define_data_identifier (self , dynamic_definition_type , dynamic_data_identifier , source_definitions , memory_address_bytes = 4 , memory_size_bytes = 1 ):
@@ -561,9 +568,9 @@ def dynamically_define_data_identifier(self, dynamic_definition_type, dynamic_da
561
568
data = struct .pack ('!H' , dynamic_data_identifier )
562
569
if dynamic_definition_type == DYNAMIC_DEFINITION_TYPE .DEFINE_BY_IDENTIFIER :
563
570
for s in source_definitions :
564
- data += struct .pack ('!H' , s ["data_identifier" ]) + chr (s ["position" ]).encode ("utf8" ) + chr (s ["memory_size" ]).encode ("utf8" )
571
+ data += struct .pack ('!H' , s ["data_identifier" ]) + chr (s ["position" ]).encode () + chr (s ["memory_size" ]).encode ()
565
572
elif dynamic_definition_type == DYNAMIC_DEFINITION_TYPE .DEFINE_BY_MEMORY_ADDRESS :
566
- data += chr (memory_size_bytes << 4 | memory_address_bytes ).encode ("utf8" )
573
+ data += chr (memory_size_bytes << 4 | memory_address_bytes ).encode ()
567
574
for s in source_definitions :
568
575
if s ["memory_address" ] >= 1 << (memory_address_bytes * 8 ):
569
576
raise ValueError ('invalid memory_address: {}' .format (s ["memory_address" ]))
@@ -589,7 +596,7 @@ def write_memory_by_address(self, memory_address, memory_size, data_record, memo
589
596
raise ValueError ('invalid memory_address_bytes: {}' .format (memory_address_bytes ))
590
597
if memory_size_bytes < 1 or memory_size_bytes > 4 :
591
598
raise ValueError ('invalid memory_size_bytes: {}' .format (memory_size_bytes ))
592
- data = chr (memory_size_bytes << 4 | memory_address_bytes ).encode ("utf8" )
599
+ data = chr (memory_size_bytes << 4 | memory_address_bytes ).encode ()
593
600
594
601
if memory_address >= 1 << (memory_address_bytes * 8 ):
595
602
raise ValueError ('invalid memory_address: {}' .format (memory_address ))
@@ -606,15 +613,15 @@ def clear_diagnostic_information(self, dtc_group_type):
606
613
self ._uds_request (SERVICE_TYPE .CLEAR_DIAGNOSTIC_INFORMATION , subfunction = None , data = data )
607
614
608
615
def read_dtc_information (self , dtc_report_type , dtc_status_mask_type = DTC_STATUS_MASK_TYPE .ALL , dtc_severity_mask_type = DTC_SEVERITY_MASK_TYPE .ALL , dtc_mask_record = 0xFFFFFF , dtc_snapshot_record_num = 0xFF , dtc_extended_record_num = 0xFF ):
609
- data = ''
616
+ data = b ''
610
617
# dtc_status_mask_type
611
618
if dtc_report_type == DTC_REPORT_TYPE .NUMBER_OF_DTC_BY_STATUS_MASK or \
612
619
dtc_report_type == DTC_REPORT_TYPE .DTC_BY_STATUS_MASK or \
613
620
dtc_report_type == DTC_REPORT_TYPE .MIRROR_MEMORY_DTC_BY_STATUS_MASK or \
614
621
dtc_report_type == DTC_REPORT_TYPE .NUMBER_OF_MIRROR_MEMORY_DTC_BY_STATUS_MASK or \
615
622
dtc_report_type == DTC_REPORT_TYPE .NUMBER_OF_EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK or \
616
623
dtc_report_type == DTC_REPORT_TYPE .EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK :
617
- data += chr (dtc_status_mask_type ).encode ("utf8" )
624
+ data += chr (dtc_status_mask_type ).encode ()
618
625
# dtc_mask_record
619
626
if dtc_report_type == DTC_REPORT_TYPE .DTC_SNAPSHOT_IDENTIFICATION or \
620
627
dtc_report_type == DTC_REPORT_TYPE .DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER or \
@@ -630,26 +637,26 @@ def read_dtc_information(self, dtc_report_type, dtc_status_mask_type=DTC_STATUS_
630
637
# dtc_extended_record_num
631
638
if dtc_report_type == DTC_REPORT_TYPE .DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \
632
639
dtc_report_type == DTC_REPORT_TYPE .MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER :
633
- data += chr (dtc_extended_record_num ).encode ("utf8" )
640
+ data += chr (dtc_extended_record_num ).encode ()
634
641
# dtc_severity_mask_type
635
642
if dtc_report_type == DTC_REPORT_TYPE .NUMBER_OF_DTC_BY_SEVERITY_MASK_RECORD or \
636
643
dtc_report_type == DTC_REPORT_TYPE .DTC_BY_SEVERITY_MASK_RECORD :
637
- data += chr (dtc_severity_mask_type ).encode ("utf8" ) + chr (dtc_status_mask_type ).encode ("utf8" )
644
+ data += chr (dtc_severity_mask_type ).encode () + chr (dtc_status_mask_type ).encode ()
638
645
639
646
resp = self ._uds_request (SERVICE_TYPE .READ_DTC_INFORMATION , subfunction = dtc_report_type , data = data )
640
647
641
648
# TODO: parse response
642
649
return resp
643
650
644
- def input_output_control_by_identifier (self , data_identifier_type , control_option_record , control_enable_mask_record = '' ):
651
+ def input_output_control_by_identifier (self , data_identifier_type , control_option_record , control_enable_mask_record = b '' ):
645
652
data = struct .pack ('!H' , data_identifier_type ) + control_option_record + control_enable_mask_record
646
653
resp = self ._uds_request (SERVICE_TYPE .INPUT_OUTPUT_CONTROL_BY_IDENTIFIER , subfunction = None , data = data )
647
654
resp_id = struct .unpack ('!H' , resp [0 :2 ])[0 ] if len (resp ) >= 2 else None
648
655
if resp_id != data_identifier_type :
649
656
raise ValueError ('invalid response data identifier: {}' .format (hex (resp_id )))
650
657
return resp [2 :]
651
658
652
- def routine_control (self , routine_control_type , routine_identifier_type , routine_option_record = '' ):
659
+ def routine_control (self , routine_control_type , routine_identifier_type , routine_option_record = b '' ):
653
660
data = struct .pack ('!H' , routine_identifier_type ) + routine_option_record
654
661
resp = self ._uds_request (SERVICE_TYPE .ROUTINE_CONTROL , subfunction = routine_control_type , data = data )
655
662
resp_id = struct .unpack ('!H' , resp [0 :2 ])[0 ] if len (resp ) >= 2 else None
@@ -658,13 +665,13 @@ def routine_control(self, routine_control_type, routine_identifier_type, routine
658
665
return resp [2 :]
659
666
660
667
def request_download (self , memory_address , memory_size , memory_address_bytes = 4 , memory_size_bytes = 4 , data_format = 0x00 ):
661
- data = chr (data_format ).encode ("utf8" )
668
+ data = chr (data_format ).encode ()
662
669
663
670
if memory_address_bytes < 1 or memory_address_bytes > 4 :
664
671
raise ValueError ('invalid memory_address_bytes: {}' .format (memory_address_bytes ))
665
672
if memory_size_bytes < 1 or memory_size_bytes > 4 :
666
673
raise ValueError ('invalid memory_size_bytes: {}' .format (memory_size_bytes ))
667
- data += chr (memory_size_bytes << 4 | memory_address_bytes ).encode ("utf8" )
674
+ data += chr (memory_size_bytes << 4 | memory_address_bytes ).encode ()
668
675
669
676
if memory_address >= 1 << (memory_address_bytes * 8 ):
670
677
raise ValueError ('invalid memory_address: {}' .format (memory_address ))
@@ -683,13 +690,13 @@ def request_download(self, memory_address, memory_size, memory_address_bytes=4,
683
690
return max_num_bytes # max number of bytes per transfer data request
684
691
685
692
def request_upload (self , memory_address , memory_size , memory_address_bytes = 4 , memory_size_bytes = 4 , data_format = 0x00 ):
686
- data = chr (data_format ).encode ("utf8" )
693
+ data = chr (data_format ).encode ()
687
694
688
695
if memory_address_bytes < 1 or memory_address_bytes > 4 :
689
696
raise ValueError ('invalid memory_address_bytes: {}' .format (memory_address_bytes ))
690
697
if memory_size_bytes < 1 or memory_size_bytes > 4 :
691
698
raise ValueError ('invalid memory_size_bytes: {}' .format (memory_size_bytes ))
692
- data += chr (memory_size_bytes << 4 | memory_address_bytes ).encode ("utf8" )
699
+ data += chr (memory_size_bytes << 4 | memory_address_bytes ).encode ()
693
700
694
701
if memory_address >= 1 << (memory_address_bytes * 8 ):
695
702
raise ValueError ('invalid memory_address: {}' .format (memory_address ))
@@ -707,8 +714,8 @@ def request_upload(self, memory_address, memory_size, memory_address_bytes=4, me
707
714
708
715
return max_num_bytes # max number of bytes per transfer data request
709
716
710
- def transfer_data (self , block_sequence_count , data = '' ):
711
- data = chr (block_sequence_count ).encode ("utf8" ) + data
717
+ def transfer_data (self , block_sequence_count , data = b '' ):
718
+ data = chr (block_sequence_count ).encode () + data
712
719
resp = self ._uds_request (SERVICE_TYPE .TRANSFER_DATA , subfunction = None , data = data )
713
720
resp_id = resp [0 ] if len (resp ) > 0 else None
714
721
if resp_id != block_sequence_count :
0 commit comments