I originally started building my own Low Power Protocol(LPP) encoder because I could only find one other Github repository with a C# implementation. There hadn’t been any updates for a while and I wasn’t confident that I could make the code work on my nanoFramework and TinyCLR devices.
I started with the sample Mbed C code and did a largely mechanical conversion to C#. I then revisited some of the mathematics where floating point values were converted to an integer.
The original C++ code (understandably) had some language specific approaches which didn’t map well into C#. I then translated the code to C#
public void TemperatureAdd(byte channel, float celsius)
{
if ((index + TemperatureSize) > buffer.Length)
{
throw new ApplicationException("TemperatureAdd insufficent buffer capacity");
}
short val = (short)(celsius * 10);
buffer[index++] = channel;
buffer[index++] = (byte)DataType.Temperature;
buffer[index++] = (byte)(val >> 8);
buffer[index++] = (byte)val;
}
One of my sensors was sending values with more decimal places than LPP supported and I noticed the value was not getting rounded e.g. 2.99 ->2.9 not 3.0 etc. So I revised my implementation to use Math.Round (which is supported by the nanoFramework and TinyCLR).
public void DigitalInputAdd(byte channel, bool value)
{
#region Guard conditions
if ((channel < Constants.ChannelMinimum) || (channel > Constants.ChannelMaximum))
{
throw new ArgumentException($"channel must be between {Constants.ChannelMinimum} and {Constants.ChannelMaximum}", "channel");
}
if ((index + Constants.DigitalInputSize) > buffer.Length)
{
throw new ApplicationException($"Datatype DigitalInput insufficent buffer capacity, {buffer.Length - index} bytes available");
}
#endregion
buffer[index++] = channel;
buffer[index++] = (byte)Enumerations.DataType.DigitalInput;
// I know this is fugly but it works on all platforms
if (value)
{
buffer[index++] = 1;
}
else
{
buffer[index++] = 0;
}
}
I then extracted out the channel and buffer size validation but I’m not certain this makes the code anymore readable/understandable
public void DigitalInputAdd(byte channel, bool value)
{
IsChannelNumberValid(channel);
IsBufferSizeSufficient(Enumerations.DataType.DigitalInput);
buffer[index++] = channel;
buffer[index++] = (byte)Enumerations.DataType.DigitalInput;
// I know this is fugly but it works on all platforms
if (value)
{
buffer[index++] = 1;
}
else
{
buffer[index++] = 0;
}
}
The code runs on netCore, nanoFramework, and TinyCLRV2 just needs a few more unit tests and it will be ready for production. I started with an LPP encoder which I needed for one of my applications. I’m also working an approach for a decoder which will run on all my target platforms with minimal modification or compile time directives.