« back

Command Parser - Part 1

30 Nov 2012

It's time to parse some commands.

Taking a cue from the Arduino CmdMessenger Library, Doug suggested we use the "id, message;" syntax for the parsing of our messages. Let's take a look at creating a structured message from a single string and then at decoding a single message.

We are going to create a function that takes a command_id and a message. The command_id should be a number. The message should be a string. We will want to check the data in several ways to make sure that it matches our criteria, so we will use cond with several cases.

The first thing we will do in the function is check if the command_id is a string. If it is, we will throw an exception. If not, we will move forward.

Once we know that the command_id is in fact an integer, we will want to know that it is an 8 bit unsigned integer. If it is not, we will throw an exception. If it is, we will move forward.

Next, we will want to make sure that our message is a string and not a number. If it is a number, we will throw an exception. If it is a string, we will move on.

The last condition verifies that the command_id is within the proper range and that the message is a string. If so, which is really what we want, we will format the message and then return it. Nice!

1     (defn create-structured-message [command-id, message]
2     		(cond 
3     			(string? command-id)(throw (Exception. "The command id needs to be a number."))
4     			(or(< command-id 0) (> command-id 255))(throw (Exception. "The number needs to be within range of 0 - 255."))
5     			(integer? message)(throw (Exception. "The message needs to be a string."))
6     			(and(and (>= command-id 0) (<= command-id 255)) (string? message))(apply str [command_id,","" "message ";"])))
7     

Now let's take a look at decoding a single message.

When we create the function to decode a single message, it will take a string. We need to get access to the id and the message. We want to remove the formatting so the first thing we will do is replace the ; with nothing.Then we will use let and set each portion of the structured message to a variable while removing the ','.

Next we will check that the id is in fact an integer. If it is not, we will throw an exception, if it is, we will move forward.

Then, we will check that the number is between 0 and 255. If it is not, we will throw an exception, if it is, we will move forward.

Then, confirming that the number we have is in range, we will return our id and message.

1     (defn decode-structured-message [structured_message]
2     	(let [stripped-message (replace structured_message #";" "") ]
3     		(let [id (read-string (first(split stripped-message #", "))) message (first (rest (split stripped-message #", ")))]
4     			(cond
5     				(not(integer? id))(throw (Exception. "The command id needs to be a number."))
6     				(or(< id 0) (> id 255))(throw (Exception. "The number needs to be within range of 0 - 255."))
7     				(and(>= id 0) (<= id 255)) (vector id message)))))
comments powered by Disqus