Handling messages from an Arduino with MEF
In this post I will demonstrate how to design a decoupled message processing application that can be easily extended for future projects. This decoupled application will use the Managed Extensibility Framework (MEF) which is part of .Net 4.0. The goal is to be able to orchestrate simple messages that originate from the Arduino that can be wired up easily into a .Net application. Another goal will be to reduce the number of messages that are sent from the Arduino.
Once you start interfacing your Arduino to your PC you might have a tendency to use the Arduino as a dumb IO extension of your PC. This usually ends up being some code in the Arduino that reads a sensor value and blindly sends it to the serial port of the PC then the PC usually has to decipher the raw data. This certainly is a valid approach in a lot of cases but I also like to use some logic in the Arduino to determine what and when to send information to the PC. A good example of this might be if I have a light sensor on the Arduino and I want to know when it is dark or light in a room I wouldn't want to have the raw sensor data being sent over to the PC and then the PC making the decision of if it is light or dark. I would rather have the Arduino determine this and just send a message to the PC once it becomes dark or light.
Lets get started. First lets define what the message looks like that will be sent from the Arduino over the serial port. Each message will consist of a single line of text that is terminated by a carriage return. Each element of the message will be delimited by a space character. A message will consist of 1 to N elements. The very first element of the message defines what message processor will handle the message. The first message I want to define will tell the PC that an Analog Input has reached a thresh hold.
The message looks like this: AT 1 200 201
- AT is the unique code that determines the message processor.
- 1 is the analog pin.
- 200 was the thresh hold.
- 201 was the actual reading that triggered the thresh hold message.
A second message exists that is called the Heart Beat Message and it looks like: HB 20
- HB is the unique code that determines the message processor.
- 20 is the number of beats that have occurred.
Here is the code for the Arduino that reads the sensor and sends the message when the threshold is reached. It also sends a heartbeat message to the PC every 5 seconds. This code is could be expanded to only send the thresh hold message once until the sensor value dropped below the thresh hold. You might also want to have the thresh hold be exceeded for something like 30 seconds before the message is sent in order to prevent firing the message too frequently when the thresh hold is on the edge.
Next we need to create the .Net code to parse the message and do something with it. Keep in mind I want to have a decoupled infrastructure for processing this message and also make it easy to extend in support of other messages. MEF makes this real easy to do.
So I knew I wanted to have 4 C# projects. Here are the projects:
- Arduino.Contract - Defines the concrete interfaces that must be implemented.
- Auduino.Services - Defines the code that communicates with the Arduino.
- Auduino.Processors - This holds all the message processors that parse data from the Arduino.
- Auduino.Console - A simple console application that shows the results of the messages coming from the Communication Service.
The Contract project has the ICommunicationService and the IMessageProcessor
The Services project references the Contract project and has a RS232CommunicationService that implements the ICommunicationService. It’s job is to connect to the Arduino over RS232 and intercept any messages coming from the Arduino and match up these messages with the appropriate Message Processor.
As you can see the Data Received Handler iterates over the message processors until a match is found. Once it is found it processes the message by calling the Execute method.
As mentioned before Message Processors must implement the IMessageProcessor interface and they must be exported as IMessageProcessor. This creates a plugin infrastructure that allows you to later add new message processors without changing the RS232CommunicationService. Since MEF can also discover assemblies on disk you can easily have message processors written by other Arduino fans and simply place their DLL in your working directory.
Here is the first have of the AnalogThreshholdProcessor
Here is the second half of the processor that shows the Execute method and how the processor Sends the message using MEF’s named import on a property. This effectively decouples the message processor from anyone that is listening for the message. I specifically use .Net native types in any import so that no other dependencies on complex types are required.
Here is the HeartBeatProcessor:
So once the message is processed where does it go?
As you can see in the Console project there are named exports that MEF uses to wire up Message Processors to the Program class.
Conclusion
Connecting PC’s and Arduinos together to expose your .Net Applications to the external world can be a lot of fun and as you can see we can easily make a re-usable extensible library of strongly typed messages. These messages are easily consumable by any .Net program. You can even write some nice unit tests around the message processors to be sure they parse the data as expected without even hooking up an Arduino. Making the Arduino program process sensor data in a more meaningful way will cut down on IO as well as offload some of the processing needs onto the Arduino.
In a future post I will show you how you might replace the RS232CommunicationService with a service that can receive the messages over your network and there will be very little changes to the .Net application to accomplish this.