A simple CIoT message protocol, used in the Water Meter Demos.
This library provides a small messaging protocol for a CIoT device, intended for use with the Water Meter Demo. As well as building for the C027 target, files are included for building a C DLL and, from that, a C Sharp DLL which can be linked into the PC-end of the Water Meter Demo (see the .ZIP file stored in the Wiki of the Water Meter Demo project) to provide end-to-end messaging with complete transparency. Since these PC files cannot be built inside mbed the source files are post-fixed with a ".txt" extension to keep them out of the way.
If a water pump is to be switched on/off as part of the demo, an interface circuit is required, which is described on the Wiki of the WaterMeterSupport library.
IotMeterDllWrapper.cs.txt
- Committer:
- RobMeades
- Date:
- 2015-05-22
- Revision:
- 0:5c46cb3be899
File content as of revision 0:5c46cb3be899:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; using System.Threading; namespace MessageCodec { /// <summary> /// This is a wrapper around the native dll for MessageCodec calls /// </summary> public class MessageCodec_dll { [DllImport ("Kernel32.dll")] extern static SafeFileHandle GetStdHandle(Int32 nStdHandle); /// <summary> /// Windows specific calls to load a library at runtime /// </summary> [DllImport ("kernel32.dll")] internal static extern IntPtr LoadLibrary(String dllname); /// <summary> /// Windows specific call to get the address of a entry in a dll /// </summary> [DllImport ("kernel32.dll")] internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname); /// The outcome of message decoding. // !!! ORDER IS IMPORTANT AND THIS MUST align with the generic // and UL (but not DL as the C# DLL is not intended to decode // a DL message) portions of the C typedef DecodeResult_t. public enum CSDecodeResult { DECODE_RESULT_FAILURE = 0, //!< Generic failed decode. DECODE_RESULT_INPUT_TOO_SHORT, //!< Not enough input bytes. DECODE_RESULT_OUTPUT_TOO_SHORT, //!< Not enough room in the //! output. DECODE_RESULT_UNKNOWN_MSG_ID, //!< Rogue message ID. DECODE_RESULT_UL_MSG_BASE = 0x80, //!< From here on are the //! uplink messages. DECODE_RESULT_INIT_IND_UL_MSG = DECODE_RESULT_UL_MSG_BASE, DECODE_RESULT_SERIAL_NUMBER_IND_UL_MSG, DECODE_RESULT_SERIAL_NUMBER_CNF_UL_MSG, DECODE_RESULT_VOLUME_IND_UL_MSG, DECODE_RESULT_RSSI_IND_UL_MSG, DECODE_RESULT_READING_INTERVAL_SET_CNF_UL_MSG, DECODE_RESULT_READING_INTERVAL_GET_CNF_UL_MSG, DECODE_RESULT_GPIO_SET_CNF_UL_MSG, DECODE_RESULT_GPIO_GET_CNF_UL_MSG, DECODE_RESULT_LED_SET_CNF_UL_MSG, DECODE_RESULT_LED_GET_CNF_UL_MSG, DECODE_RESULT_FLASH_SET_CNF_UL_MSG, DECODE_RESULT_FLASH_GET_CNF_UL_MSG, // !!! If you add one here update // the next line !!! MAX_UL_REQ_MSG = DECODE_RESULT_FLASH_GET_CNF_UL_MSG, MAX_NUM_DECODE_RESULTS //!< The maximum number of //! decode results. }; // uint32_t __cdecl maxDatagramSizeRaw (void); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _maxDatagramSizeRaw (); public _maxDatagramSizeRaw maxDatagramSizeRaw; // uint32_t __cdecl gpioWaterPump (void); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _gpioWaterPump(); public _gpioWaterPump gpioWaterPump; // uint32_t __cdecl encodeRebootReqDlMsg (char * pBuffer, // bool devModeOnNotOff); [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeRebootReqDlMsg(byte* pBuffer, Boolean devModeOnNotOff); public _encodeRebootReqDlMsg encodeRebootReqDlMsg; // uint32_t __cdecl encodeSerialNumberGetReqDlMsg (char * pBuffer); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeSerialNumberGetReqDlMsg(byte* pBuffer); public _encodeSerialNumberGetReqDlMsg encodeSerialNumberGetReqDlMsg; // uint32_t __cdecl encodeReadingIntervalSetReqDlMsg (char * pBuffer, // UInt32 readingIntervalSeconds); [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeReadingIntervalSetReqDlMsg(byte* pBuffer, UInt32 readingIntervalSeconds); public _encodeReadingIntervalSetReqDlMsg encodeReadingIntervalSetReqDlMsg; // uint32_t __cdecl encodeReadingIntervalGetReqDlMsg (char * pBuffer); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeReadingIntervalGetReqDlMsg(byte* pBuffer); public _encodeReadingIntervalGetReqDlMsg encodeReadingIntervalGetReqDlMsg; // uint32_t __cdecl encodeGpioSetReqDlMsg (char * pBuffer, // uint8_t gpio, // bool inputNotOutput, // bool onNotOff); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeGpioSetReqDlMsg(byte* pBuffer, UInt32 gpio, Boolean inputNotOutput, Boolean onNotOff); public _encodeGpioSetReqDlMsg encodeGpioSetReqDlMsg; // uint32_t __cdecl encodeGpioGetReqDlMsg (char * pBuffer, // uint8_t gpio); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeGpioGetReqDlMsg(byte* pBuffer, UInt32 gpio); public _encodeGpioGetReqDlMsg encodeGpioGetReqDlMsg; // uint32_t __cdecl encodeLedSetReqDlMsg (char * pBuffer, // bool onNotOff); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeLedSetReqDlMsg(byte* pBuffer, Boolean onNotOff); public _encodeLedSetReqDlMsg encodeLedSetReqDlMsg; // uint32_t __cdecl encodeLedGetReqDlMsg (char * pBuffer); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeLedGetReqDlMsg(byte* pBuffer); public _encodeLedGetReqDlMsg encodeLedGetReqDlMsg; // uint32_t __cdecl encodeFlashSetReqDlMsg (char * pBuffer, // bool onNotOff); [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeFlashSetReqDlMsg(byte * pBuffer, Boolean onNotOff); public _encodeFlashSetReqDlMsg encodeFlashSetReqDlMsg; // uint32_t __cdecl encodeFlashGetReqDlMsg (char * pBuffer); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate UInt32 _encodeFlashGetReqDlMsg(byte* pBuffer); public _encodeFlashGetReqDlMsg encodeFlashGetReqDlMsg; // void __cdecl unpackGpioState (uint32_t value, // uint32_t *pGpio, // bool * pInputNotOutput, // bool * pOnNotOff); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate void _unpackGpioState(UInt32 value, UInt32* pGpio, Boolean *pInputNotOutput, Boolean *pOnNotOff); public _unpackGpioState unpackGpioState; // CsDecodeResult_t __cdecl decodeUlMsg (const char ** ppInBuffer, // uint32_t sizeInBuffer, // uint32_t * pContents); [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public unsafe delegate CSDecodeResult _decodeUlMsg(byte** ppInBuffer, UInt32 sizeInBuffer, UInt32* pContents); public _decodeUlMsg decodeUlMsg; [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public delegate void guiPrintToConsoleCallback(StringBuilder data); [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public delegate void _initDll([MarshalAs (UnmanagedType.FunctionPtr)] guiPrintToConsoleCallback callbackPointer); public _initDll initDll; void guiPrintToConsole(StringBuilder data) { if (onConsoleTrace != null) { onConsoleTrace (data.ToString ()); } } /// <summary> /// Load the dll and do the bindings /// </summary> /// <param name="dllLocation">location of dll</param> public void bindDll(string dllLocation) { IntPtr ptrDll = LoadLibrary (dllLocation); if (ptrDll == IntPtr.Zero) throw new Exception (String.Format ("Cannot find {0}", dllLocation)); maxDatagramSizeRaw = (_maxDatagramSizeRaw)bindItem(ptrDll, "maxDatagramSizeRaw", typeof(_maxDatagramSizeRaw)); gpioWaterPump = (_gpioWaterPump)bindItem(ptrDll, "gpioWaterPump", typeof(_gpioWaterPump)); encodeRebootReqDlMsg = (_encodeRebootReqDlMsg)bindItem(ptrDll, "encodeRebootReqDlMsg", typeof(_encodeRebootReqDlMsg)); encodeSerialNumberGetReqDlMsg = (_encodeSerialNumberGetReqDlMsg)bindItem(ptrDll, "encodeSerialNumberGetReqDlMsg", typeof(_encodeSerialNumberGetReqDlMsg)); encodeReadingIntervalSetReqDlMsg = (_encodeReadingIntervalSetReqDlMsg)bindItem(ptrDll, "encodeReadingIntervalSetReqDlMsg", typeof(_encodeReadingIntervalSetReqDlMsg)); encodeReadingIntervalGetReqDlMsg = (_encodeReadingIntervalGetReqDlMsg)bindItem(ptrDll, "encodeReadingIntervalGetReqDlMsg", typeof(_encodeReadingIntervalGetReqDlMsg)); encodeGpioSetReqDlMsg = (_encodeGpioSetReqDlMsg)bindItem(ptrDll, "encodeGpioSetReqDlMsg", typeof(_encodeGpioSetReqDlMsg)); encodeGpioGetReqDlMsg = (_encodeGpioGetReqDlMsg)bindItem(ptrDll, "encodeGpioGetReqDlMsg", typeof(_encodeGpioGetReqDlMsg)); encodeLedSetReqDlMsg = (_encodeLedSetReqDlMsg)bindItem(ptrDll, "encodeLedSetReqDlMsg", typeof(_encodeLedSetReqDlMsg)); encodeLedGetReqDlMsg = (_encodeLedGetReqDlMsg)bindItem(ptrDll, "encodeLedGetReqDlMsg", typeof(_encodeLedGetReqDlMsg)); encodeFlashSetReqDlMsg = (_encodeFlashSetReqDlMsg)bindItem(ptrDll, "encodeFlashSetReqDlMsg", typeof(_encodeFlashSetReqDlMsg)); encodeFlashGetReqDlMsg = (_encodeFlashGetReqDlMsg)bindItem(ptrDll, "encodeFlashGetReqDlMsg", typeof(_encodeFlashGetReqDlMsg)); unpackGpioState = (_unpackGpioState)bindItem(ptrDll, "unpackGpioState", typeof(_unpackGpioState)); decodeUlMsg = (_decodeUlMsg)bindItem(ptrDll, "decodeUlMsg", typeof(_decodeUlMsg)); initDll = (_initDll)bindItem (ptrDll, "initDll", typeof (_initDll)); initDll (guiPrintToConsole); } public object bindItem(IntPtr ptrDll, string dllFuncName, Type type) { // Get pointer to dllexport function IntPtr procaddr = GetProcAddress (ptrDll, dllFuncName); if (procaddr == IntPtr.Zero) throw new Exception (String.Format ("Cannot find {0}", dllFuncName)); // Bind it to the function Object result = Marshal.GetDelegateForFunctionPointer (procaddr, type); if (result == null) throw new Exception (String.Format ("Cannot bind to {0}", dllFuncName)); return result; } public delegate void ConsoleTrace(string data); public event ConsoleTrace onConsoleTrace; } }