1
+ # pylint: skip-file
2
+
1
3
### COMMAND FORMATS
2
4
3
5
__description__ = \
4
6
"""
5
7
PyCmdMessenger
6
8
7
9
Class for communication with an arduino using the CmdMessenger serial
8
- communication library.
10
+ communication library.
9
11
"""
10
12
__author__ = "Michael J. Harms"
11
13
__date__ = "2016-05-20"
15
17
16
18
class CmdMessenger :
17
19
"""
18
- Basic interface for interfacing over a serial connection to an arduino
20
+ Basic interface for interfacing over a serial connection to an arduino
19
21
using the CmdMessenger library.
20
22
"""
21
-
23
+
22
24
def __init__ (self ,
23
25
board_instance ,
24
26
commands ,
@@ -29,7 +31,7 @@ def __init__(self,
29
31
"""
30
32
Input:
31
33
board_instance:
32
- instance of ArduinoBoard initialized with correct serial
34
+ instance of ArduinoBoard initialized with correct serial
33
35
connection (points to correct serial with correct baud rate) and
34
36
correct board parameters (float bytes, etc.)
35
37
@@ -46,19 +48,19 @@ def __init__(self,
46
48
47
49
command_separator:
48
50
character that separates messages (commands) from each other
49
- Default: ";"
50
-
51
+ Default: ";"
52
+
51
53
escape_separator:
52
54
escape character to allow separators within messages.
53
55
Default: "/"
54
56
55
57
warnings:
56
58
warnings for user
57
59
Default: True
58
-
60
+
59
61
The separators and escape_separator should match what's
60
62
in the arduino code that initializes the CmdMessenger. The default
61
- separator values match the default values as of CmdMessenger 4.0.
63
+ separator values match the default values as of CmdMessenger 4.0.
62
64
"""
63
65
64
66
self .board = board_instance
@@ -79,7 +81,7 @@ def __init__(self,
79
81
self ._cmd_name_to_int [c [0 ]] = i
80
82
self ._int_to_cmd_name [i ] = c [0 ]
81
83
self ._cmd_name_to_format [c [0 ]] = c [1 ]
82
-
84
+
83
85
self ._byte_field_sep = self .field_separator .encode ("ascii" )
84
86
self ._byte_command_sep = self .command_separator .encode ("ascii" )
85
87
self ._byte_escape_sep = self .escape_separator .encode ("ascii" )
@@ -119,13 +121,13 @@ def __init__(self,
119
121
120
122
def send (self ,cmd ,* args ,arg_formats = None ):
121
123
"""
122
- Send a command (which may or may not have associated arguments) to an
124
+ Send a command (which may or may not have associated arguments) to an
123
125
arduino using the CmdMessage protocol. The command and any parameters
124
- should be passed as direct arguments to send.
126
+ should be passed as direct arguments to send.
125
127
126
128
arg_formats is an optional string that specifies the formats to use for
127
129
each argument when passed to the arduino. If specified here,
128
- arg_formats supercedes formats specified on initialization.
130
+ arg_formats supercedes formats specified on initialization.
129
131
"""
130
132
131
133
# Turn the command into an integer.
@@ -135,7 +137,7 @@ def send(self,cmd,*args,arg_formats=None):
135
137
err = "Command '{}' not recognized.\n " .format (cmd )
136
138
raise ValueError (err )
137
139
138
- # Figure out what formats to use for each argument.
140
+ # Figure out what formats to use for each argument.
139
141
arg_format_list = []
140
142
if arg_formats != None :
141
143
@@ -150,8 +152,8 @@ def send(self,cmd,*args,arg_formats=None):
150
152
except KeyError :
151
153
# if not, guess for all arguments
152
154
arg_format_list = ["g" for i in range (len (args ))]
153
-
154
- # Deal with "*" format
155
+
156
+ # Deal with "*" format
155
157
arg_format_list = self ._treat_star_format (arg_format_list ,args )
156
158
157
159
if len (args ) > 0 :
@@ -160,7 +162,7 @@ def send(self,cmd,*args,arg_formats=None):
160
162
raise ValueError (err )
161
163
162
164
# Go through each argument and create a bytes representation in the
163
- # proper format to send. Escape appropriate characters.
165
+ # proper format to send. Escape appropriate characters.
164
166
fields = ["{}" .format (command_as_int ).encode ("ascii" )]
165
167
for i , a in enumerate (args ):
166
168
fields .append (self ._send_methods [arg_format_list [i ]](a ))
@@ -174,15 +176,15 @@ def send(self,cmd,*args,arg_formats=None):
174
176
175
177
def receive (self ,arg_formats = None ):
176
178
"""
177
- Recieve commands coming off the serial port.
179
+ Recieve commands coming off the serial port.
178
180
179
181
arg_formats is an optimal keyword that specifies the formats to use to
180
182
parse incoming arguments. If specified here, arg_formats supercedes
181
- the formats specified on initialization.
183
+ the formats specified on initialization.
182
184
"""
183
185
184
186
# Read serial input until a command separator or empty character is
185
- # reached
187
+ # reached
186
188
msg = [[]]
187
189
raw_msg = []
188
190
escaped = False
@@ -218,26 +220,26 @@ def receive(self,arg_formats=None):
218
220
command_sep_found = True
219
221
break
220
222
221
- # or any empty characater
223
+ # or any empty characater
222
224
elif tmp == b'' :
223
225
break
224
226
225
227
# okay, must be something
226
228
else :
227
229
msg [- 1 ].append (tmp )
228
-
230
+
229
231
# No message received given timeouts
230
232
if len (msg ) == 1 and len (msg [0 ]) == 0 :
231
233
return None
232
234
233
235
# Make sure the message terminated properly
234
236
if not command_sep_found :
235
-
236
- # empty message (likely from line endings being included)
237
- joined_raw = b'' .join (raw_msg )
237
+
238
+ # empty message (likely from line endings being included)
239
+ joined_raw = b'' .join (raw_msg )
238
240
if joined_raw .strip () == b'' :
239
241
return None
240
-
242
+
241
243
err = "Incomplete message ({})" .format (joined_raw .decode ())
242
244
raise EOFError (err )
243
245
@@ -254,8 +256,8 @@ def receive(self,arg_formats=None):
254
256
cmd_name = "unknown"
255
257
w = "Recieved unrecognized command ({})." .format (cmd )
256
258
warnings .warn (w ,Warning )
257
-
258
- # Figure out what formats to use for each argument.
259
+
260
+ # Figure out what formats to use for each argument.
259
261
arg_format_list = []
260
262
if arg_formats != None :
261
263
@@ -271,7 +273,7 @@ def receive(self,arg_formats=None):
271
273
# if not, guess for all arguments
272
274
arg_format_list = ["g" for i in range (len (fields [1 :]))]
273
275
274
- # Deal with "*" format
276
+ # Deal with "*" format
275
277
arg_format_list = self ._treat_star_format (arg_format_list ,fields [1 :])
276
278
277
279
if len (fields [1 :]) > 0 :
@@ -282,7 +284,7 @@ def receive(self,arg_formats=None):
282
284
received = []
283
285
for i , f in enumerate (fields [1 :]):
284
286
received .append (self ._recv_methods [arg_format_list [i ]](f ))
285
-
287
+
286
288
# Record the time the message arrived
287
289
message_time = time .time ()
288
290
@@ -314,7 +316,7 @@ def _treat_star_format(self,arg_format_list,args):
314
316
err = "'*' format must occur only once, be at end of string, and be preceded by at least one other format."
315
317
raise ValueError (err )
316
318
317
- return arg_format_list
319
+ return arg_format_list
318
320
319
321
def _send_char (self ,value ):
320
322
"""
@@ -367,7 +369,7 @@ def _send_int(self,value):
367
369
bounds for signed int.
368
370
"""
369
371
370
- # Coerce to int. This will throw a ValueError if the value can't
372
+ # Coerce to int. This will throw a ValueError if the value can't
371
373
# actually be converted.
372
374
if type (value ) != int :
373
375
new_value = int (value )
@@ -381,15 +383,15 @@ def _send_int(self,value):
381
383
if value > self .board .int_max or value < self .board .int_min :
382
384
err = "Value {} exceeds the size of the board's int." .format (value )
383
385
raise OverflowError (err )
384
-
386
+
385
387
return struct .pack (self .board .int_type ,value )
386
-
388
+
387
389
def _send_unsigned_int (self ,value ):
388
390
"""
389
391
Convert a numerical value into an integer, then to a bytes object. Check
390
392
bounds for unsigned int.
391
393
"""
392
- # Coerce to int. This will throw a ValueError if the value can't
394
+ # Coerce to int. This will throw a ValueError if the value can't
393
395
# actually be converted.
394
396
if type (value ) != int :
395
397
new_value = int (value )
@@ -403,7 +405,7 @@ def _send_unsigned_int(self,value):
403
405
if value > self .board .unsigned_int_max or value < self .board .unsigned_int_min :
404
406
err = "Value {} exceeds the size of the board's unsigned int." .format (value )
405
407
raise OverflowError (err )
406
-
408
+
407
409
return struct .pack (self .board .unsigned_int_type ,value )
408
410
409
411
def _send_long (self ,value ):
@@ -412,11 +414,11 @@ def _send_long(self,value):
412
414
bounds for signed long.
413
415
"""
414
416
415
- # Coerce to int. This will throw a ValueError if the value can't
417
+ # Coerce to int. This will throw a ValueError if the value can't
416
418
# actually be converted.
417
419
if type (value ) != int :
418
420
new_value = int (value )
419
-
421
+
420
422
if self .give_warnings :
421
423
w = "Coercing {} into int ({})" .format (value ,new_value )
422
424
warnings .warn (w ,Warning )
@@ -426,16 +428,16 @@ def _send_long(self,value):
426
428
if value > self .board .long_max or value < self .board .long_min :
427
429
err = "Value {} exceeds the size of the board's long." .format (value )
428
430
raise OverflowError (err )
429
-
431
+
430
432
return struct .pack (self .board .long_type ,value )
431
-
433
+
432
434
def _send_unsigned_long (self ,value ):
433
435
"""
434
- Convert a numerical value into an integer, then to a bytes object.
436
+ Convert a numerical value into an integer, then to a bytes object.
435
437
Check bounds for unsigned long.
436
438
"""
437
439
438
- # Coerce to int. This will throw a ValueError if the value can't
440
+ # Coerce to int. This will throw a ValueError if the value can't
439
441
# actually be converted.
440
442
if type (value ) != int :
441
443
new_value = int (value )
@@ -449,15 +451,15 @@ def _send_unsigned_long(self,value):
449
451
if value > self .board .unsigned_long_max or value < self .board .unsigned_long_min :
450
452
err = "Value {} exceeds the size of the board's unsigned long." .format (value )
451
453
raise OverflowError (err )
452
-
454
+
453
455
return struct .pack (self .board .unsigned_long_type ,value )
454
456
455
457
def _send_float (self ,value ):
456
458
"""
457
459
Return a float as a IEEE 754 format bytes object.
458
460
"""
459
461
460
- # convert to float. this will throw a ValueError if the type is not
462
+ # convert to float. this will throw a ValueError if the type is not
461
463
# readily converted
462
464
if type (value ) != float :
463
465
value = float (value )
@@ -468,13 +470,13 @@ def _send_float(self,value):
468
470
raise OverflowError (err )
469
471
470
472
return struct .pack (self .board .float_type ,value )
471
-
473
+
472
474
def _send_double (self ,value ):
473
475
"""
474
476
Return a float as a IEEE 754 format bytes object.
475
477
"""
476
478
477
- # convert to float. this will throw a ValueError if the type is not
479
+ # convert to float. this will throw a ValueError if the type is not
478
480
# readily converted
479
481
if type (value ) != float :
480
482
value = float (value )
@@ -489,7 +491,7 @@ def _send_double(self,value):
489
491
def _send_string (self ,value ):
490
492
"""
491
493
Convert a string to a bytes object. If value is not a string, it is
492
- be converted to one with a standard string.format call.
494
+ be converted to one with a standard string.format call.
493
495
"""
494
496
495
497
if type (value ) != bytes :
@@ -513,8 +515,8 @@ def _send_guess(self,value):
513
515
"""
514
516
Send the argument as a string in a way that should (probably, maybe!) be
515
517
processed properly by C++ calls like atoi, atof, etc. This method is
516
- NOT RECOMMENDED, particularly for floats, because values are often
517
- mangled silently. Instead, specify a format (e.g. "f") and use the
518
+ NOT RECOMMENDED, particularly for floats, because values are often
519
+ mangled silently. Instead, specify a format (e.g. "f") and use the
518
520
CmdMessenger::readBinArg<CAST> method (e.g. c.readBinArg<float>();) to
519
521
read the values on the arduino side.
520
522
"""
@@ -584,7 +586,7 @@ def _recv_double(self,value):
584
586
"""
585
587
586
588
return struct .unpack (self .board .double_type ,value )[0 ]
587
-
589
+
588
590
def _recv_string (self ,value ):
589
591
"""
590
592
Recieve a binary (bytes) string, returning a python string.
@@ -604,13 +606,13 @@ def _recv_bool(self,value):
604
606
"""
605
607
Receive a binary bool, return as python bool.
606
608
"""
607
-
609
+
608
610
return struct .unpack ("?" ,value )[0 ]
609
611
610
612
def _recv_guess (self ,value ):
611
613
"""
612
- Take the binary spew and try to make it into a float or integer. If
613
- that can't be done, return a string.
614
+ Take the binary spew and try to make it into a float or integer. If
615
+ that can't be done, return a string.
614
616
615
617
Note: this is generally a bad idea, as values can be seriously mangled
616
618
by going from float -> string -> float. You'll generally be better off
@@ -638,5 +640,3 @@ def _recv_guess(self,value):
638
640
639
641
# Return as string
640
642
return self ._recv_string (value )
641
-
642
-
0 commit comments