I'm trying to design a protocol for sending/receiving serial data.
The basic plan is to allow for text data to be entered in the command prompt, translate that to a hex string and send it out over the serial connection.
The hex protocol with the serial device is as follows:
byte[0]: address of the serial device peripheral we are interested in
byte[1]: command to send
byte[2]: optional parameter
byte[3]: optional parameter
I like the idea of dictionaries to do that command line translation so that I can do something like this.
commands = {
...
'ping': [0x01, 0x01, 0x00, 0x00],
...
}
input = raw_input("<< ")
if input in commands:
serial.write(commands[input])
else:
print "Unknown command" + input
This seems fine for simple commands like ping but I'm not sure what to do when it comes to implementing more complex commands like pinging a specified peripheral
>> ping host
My first idea is to tokenize the input and use nested dictionaries to hold the commands.
commands = {
'ping': {
'default': [0x01, 0x01, 0x00, 0x00],
'host': [0x01, 0x01, 0x00, 0x00],
'sensor': [0x02, 0x01, 0x00, 0x00]
}
}
I haven't looked up how to tokenize a string yet so I'll use pseudo for that here.
input = raw_input(">> ")
tokens = tokenize(input)
if tokens[0] in commands:
if tokens[1] is not '':
if tokens[1] in commands[tokens[0]]:
if tokens[2] is not '':
...
else:
serial.write(commands[tokens[0]][tokens[1]])
else:
print "Unknown Address" + tokens[1]
else:
serial.write(commands[token[0]]['default']
else:
print "Unknown command" + tokens[0]
I feel like I may be headed in the wrong direction here though, I'm worried the dictionary will become somewhat unwieldy, any thoughts? How would you do a lookup table of this sort?
I've somewhat implemented what would be the final solution for this style of lookup.
First I define my protocol dictionary
myProtocol.py
class MyProtocol:
''' Handshaking '''
_zero = 0x00
_start = 0xA9
_stop = 0x9A
_ack = 0xB8
_nack = 0x8B
_err = 0xEE
handshake = {
'zero' : _zero,
'start' : _start,
'stop' : _stop,
'ack' : _ack,
'nack' : _nack,
'err' : _err
}
''' Address '''
_host = 0x01 # target device
_sdcard = 0x03
addresses = {
'host' : _host
}
''' Common Commands '''
_ping = 0x01 # request an ack
_get = 0x02 # retrieve data
_set = 0x03 # modify settings
''' Command Strings '''
command = {
# default ping
'ping' : [_host, _ping, _zero, _zero],
# commands issued to the device itself
'host' : {
'ping' : [_host, _ping, _zero, _zero],
'get' : {
'date' : [_host, _get, 0x01, _zero]
},
'set' : {
'date' : [_host, _set, 0x01, 0x01], # to be followed by a message with the date
}
}
};
Next, the program to read user input and transform it into a hex command. This code is ignoring the actual serial communication for now, just receiving input and printing out the associated command (for valid input).
serialCom.py
def processInput(inList, dictionary):
# recursively process a list of input
head = inList[0]
tail = inList[1:]
if head == 'exit':
print "received exit command"
ser.close()
exit()
# is this a valid token?
if head in dictionary:
print head + " ",
# are there more commands to process?
if len(tail) > 0:
processInput(tail, dictionary[head])
else:
# have we found a command
if isinstance(dictionary[head], list):
print "\n command found:",
for i in dictionary[head]:
print "%#04X" % i,
print
elif isinstance(dictionary[head], dict):
print ":: insufficient arguments"
print " requires:"
for i in sorted(dictionary.keys()): #dictionary[head].keys():
# print the possible arguments
print " " + i
else:
# this shouldn't happen, the command dictionary is corrupt
print ":: invalid command dictionary"
else:
print ":: invalid command[" + head + "]"
print " possible commands:"
for i in sorted(dictionary.keys()):
# print the possible commands
print " " + i
while 1:
# get keyboard input
command = raw_input("<< ")
token = command.split()
processInput(token, MyProtocol.command)
-
2\$\begingroup\$ Welcome to Code Review! It looks like you have the beginnings of an interesting question, but first you must have a version of the code that works. \$\endgroup\$200_success– 200_success2014年09月24日 22:10:28 +00:00Commented Sep 24, 2014 at 22:10
1 Answer 1
Maybe my approach is crude, but the first thought I had was to use a simple dictionary with key as "ping host". If user separates command and parameters with multiple spaces or tabs, that too can be handled by preprocessing the command before indexing the dictionary.
Another approach that may be more pythonic would be to convert the input into a tuple and use that tuple to index the dictionary.
Maybe there is a specific reason why you require hierarchy, which is not obvious to me.
-
\$\begingroup\$ Thanks for the answer. It actually never occurred to me to use spaces within the key. \$\endgroup\$user3817250– user38172502014年11月03日 14:51:32 +00:00Commented Nov 3, 2014 at 14:51
Explore related questions
See similar questions with these tags.