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.
IotMeterMsgCodec.cpp
- Committer:
- RobMeades
- Date:
- 2015-05-22
- Revision:
- 0:5c46cb3be899
File content as of revision 0:5c46cb3be899:
/* C027N/water-meter interface for Water Meter Demo * * Copyright (C) u-blox Melbourn Ltd * u-blox Melbourn Ltd, Melbourn, UK * * All rights reserved. * * This source file is the sole property of u-blox Melbourn Ltd. * Reproduction or utilization of this source in whole or part is * forbidden without the written consent of u-blox Melbourn Ltd. */ /** * @file iot_meter_msg_handler.cpp * This file implements the API to the C027N/water-meter device * for the MWC demo 2015. */ #include <stdint.h> #include <stdio.h> #include <stdarg.h> // for va_... #include <string.h> // for memcpy() #include <IotMeterApi.hpp> #ifdef DEBUG #define MESSAGE_CODEC_LOGMSG(...) MessageCodec::logMsg(__VA_ARGS__) #else #define MESSAGE_CODEC_LOGMSG(...) #endif // ---------------------------------------------------------------- // GENERAL COMPILE-TIME CONSTANTS // ---------------------------------------------------------------- /// The max size of a debug message (including terminator) #define MAX_DEBUG_MESSAGE_LEN 128 // ---------------------------------------------------------------- // PRIVATE VARIABLES // ---------------------------------------------------------------- void (*MessageCodec::mp_guiPrintToConsole) (const char*) = NULL; // ---------------------------------------------------------------- // ON-AIR MESSAGE IDs // ---------------------------------------------------------------- /// The message IDs in the downlink direction (i.e. to the // C027/water-meter device). Note that 'over the air' these // are cast into an uint8_t. typedef enum MsgIdDlTag_t { REBOOT_REQ_DL_MSG, //!< Reboot the C027N/water-meter //! device. SERIAL_NUMBER_GET_REQ_DL_MSG, //!< Get the serial number of the //! water-meter. READING_INTERVAL_SET_REQ_DL_MSG, //!< Set the rate at which readings //! are returned by the C027N/water-meter //! device. READING_INTERVAL_GET_REQ_DL_MSG, //!< Get the rate at which readings //! are returned by the C027N/water-meter //! device. GPIO_SET_REQ_DL_MSG, //!< Set the state of a GPIO on the //! C027N board. GPIO_GET_REQ_DL_MSG, //!< Get the state of a GPIO on the //! C027N board. LED_SET_REQ_DL_MSG, //!< Set the steady state of the red //! LED on the C027 board. LED_GET_REQ_DL_MSG, //!< Get the steady state of the red //! LED on the C027 board. FLASH_SET_REQ_DL_MSG, //!< Set the LED on the C027/water-meter //! device to flash when a reading is //! being sent (or not). FLASH_GET_REQ_DL_MSG, //!< Get whether the LED on the C027/ //! flashes when a mesage is //! being sent/received (or not). MAX_NUM_DL_MSGS //!< The maximum number of downlink //! messages. } MsgIdDl_t; /// The message IDs in the uplink direction (i.e. from the // C027N/water-meter device). Note that 'over the air' these are // cast into an uint8_t. typedef enum MsgIdUlTag_t { INIT_IND_UL_MSG, //!< Power on of the C027N/water meter //! device has completed. SERIAL_NUMBER_IND_UL_MSG, //!< The serial number of the water meter. VOLUME_IND_UL_MSG, //!< The current water meter reading. RSSI_IND_UL_MSG, //!< The current RSSI reading from the //! radio module. SERIAL_NUMBER_GET_CNF_UL_MSG, //!< The serial number of the water-meter. READING_INTERVAL_SET_CNF_UL_MSG, //!< The rate at which readings are //! returned by the C027/water-meter device. READING_INTERVAL_GET_CNF_UL_MSG, //!< The rate at which readings are //! returned by the C027/water-meter device. GPIO_SET_CNF_UL_MSG, //!< The state of a GPIO on the C027 board. GPIO_GET_CNF_UL_MSG, //!< The state of a GPIO on the C027 board. LED_SET_CNF_UL_MSG, //!< The steady state of the red LED on //! the C027/water-meter device. LED_GET_CNF_UL_MSG, //!< The steady state of the red LED on //! the C027/water-meter device. FLASH_SET_CNF_UL_MSG, //!< Whether the LED on the C027/water //! meter device is set to flash when a //! message is being sent/received (or not). FLASH_GET_CNF_UL_MSG, //!< Whether the LED on the C027/water //! meter device is set to flash when a //! message is being sent/received (or not). MAX_NUM_UL_MSGS //!< The maximum number of uplink messages. } MsgIdUl_t; // ---------------------------------------------------------------- // GENERIC PRIVATE FUNCTIONS // ---------------------------------------------------------------- /// Encode a boolean value, noting that this is contained // in a 32 bytes coded value. uint32_t MessageCodec::encodeBool (char * pBuffer, bool value) { uint32_t numBytesEncoded = 4; memset (pBuffer, 0, 4); pBuffer[3] = value; return numBytesEncoded; } /// Decode a boolean value, noting that this is contained // in a 32 bytes coded value. bool MessageCodec::decodeBool (const char ** ppBuffer) { uint32_t value = 0; bool boolValue = false; value += ((**ppBuffer) & 0xFF) << 24; (*ppBuffer)++; value += ((**ppBuffer) & 0xFF) << 16; (*ppBuffer)++; value += ((**ppBuffer) & 0xFF) << 8; (*ppBuffer)++; value += ((**ppBuffer) & 0xFF) ; (*ppBuffer)++; if (value) { boolValue = true; } return boolValue; } /// Encode an int32 uint32_t MessageCodec::encodeUint32 (char * pBuffer, uint32_t value) { uint32_t numBytesEncoded = 4; pBuffer[0] = 0xff & (value >> 24); pBuffer[1] = 0xff & (value >> 16); pBuffer[2] = 0xff & (value >> 8); pBuffer[3] = 0xff & value; return numBytesEncoded; } /// Decode an int32 uint32_t MessageCodec::decodeUint32 (const char ** ppBuffer) { uint32_t value = 0; value += ((**ppBuffer) & 0xFF) << 24; (*ppBuffer)++; value += ((**ppBuffer) & 0xFF) << 16; (*ppBuffer)++; value += ((**ppBuffer) & 0xFF) << 8; (*ppBuffer)++; value += ((**ppBuffer) & 0xFF); (*ppBuffer)++; return value; } /// Encode GpioState uint32_t MessageCodec::encodeGpioState (char * pBuffer, GpioState_t *pGpioState) { uint32_t numBytesEncoded = 0; pBuffer[numBytesEncoded] = 0; numBytesEncoded++; pBuffer[numBytesEncoded] = pGpioState->gpio; numBytesEncoded++; pBuffer[numBytesEncoded] = pGpioState->inputNotOutput; numBytesEncoded++; pBuffer[numBytesEncoded] = pGpioState->onNotOff; numBytesEncoded++; return numBytesEncoded; } // Decode GpioState void MessageCodec::decodeGpioState (GpioState_t * pGpioState, const char ** ppBuffer) { // Ignore the first byte as it's empty (*ppBuffer)++; pGpioState->gpio = (uint8_t) ((**ppBuffer) & 0xFF); (*ppBuffer)++; pGpioState->inputNotOutput = (bool) ((**ppBuffer) & 0xFF); (*ppBuffer)++; pGpioState->onNotOff = (bool) ((**ppBuffer) & 0xFF); (*ppBuffer)++; } // ---------------------------------------------------------------- // MESSAGE ENCODING FUNCTIONS // ---------------------------------------------------------------- uint32_t MessageCodec::encodeInitIndUlMsg (char * pBuffer, InitIndUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding InitIndUlMsg, ID 0x%.2x, ", INIT_IND_UL_MSG); pBuffer[numBytesEncoded] = INIT_IND_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), (uint32_t) pMsg->wakeUpCode); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeRebootReqDlMsg (char * pBuffer, RebootReqDlMsg_t *pMsg) { uint32_t numBytesEncoded = 0; pBuffer[numBytesEncoded] = REBOOT_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->devModeOnNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeSerialNumberIndUlMsg (char * pBuffer, SerialNumberIndUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding SerialNumberIndUlMsg, ID 0x%.2x, ", SERIAL_NUMBER_IND_UL_MSG); pBuffer[numBytesEncoded] = SERIAL_NUMBER_IND_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->serialNumber); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeVolumeIndUlMsg (char * pBuffer, VolumeIndUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding VolumeIndUlMsg, ID 0x%.2x, ", VOLUME_IND_UL_MSG); pBuffer[numBytesEncoded] = VOLUME_IND_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->volumeLitres); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeRssiIndUlMsg (char * pBuffer, RssiIndUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding RssiIndUlMsg, ID 0x%.2x, ", RSSI_IND_UL_MSG); pBuffer[numBytesEncoded] = RSSI_IND_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->rssi); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeSerialNumberGetReqDlMsg (char * pBuffer) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding SerialNumberGetReqDlMsg, ID 0x%.2x, ", SERIAL_NUMBER_GET_REQ_DL_MSG); pBuffer[numBytesEncoded] = SERIAL_NUMBER_GET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), 0); // Encode packing as all // messages must have a body MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeSerialNumberGetCnfUlMsg (char * pBuffer, SerialNumberGetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding SerialNumberGetCnfUlMsg, ID 0x%.2x, ", SERIAL_NUMBER_GET_CNF_UL_MSG); pBuffer[numBytesEncoded] = SERIAL_NUMBER_GET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->serialNumber); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeReadingIntervalSetReqDlMsg (char * pBuffer, ReadingIntervalSetReqDlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding ReadingIntervalSetReqDlMsg, ID 0x%.2x, ", READING_INTERVAL_SET_REQ_DL_MSG); pBuffer[numBytesEncoded] = READING_INTERVAL_SET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->readingIntervalSeconds); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeReadingIntervalSetCnfUlMsg (char * pBuffer, ReadingIntervalSetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding ReadingIntervalSetCnfUlMsg, ID 0x%.2x, ", READING_INTERVAL_SET_CNF_UL_MSG); pBuffer[numBytesEncoded] = READING_INTERVAL_SET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->readingIntervalSeconds); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeReadingIntervalGetReqDlMsg (char * pBuffer) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding ReadingIntervalGetReqDlMsg, ID 0x%.2x, ", READING_INTERVAL_GET_REQ_DL_MSG); pBuffer[numBytesEncoded] = READING_INTERVAL_GET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), 0); // Encode packing as all // messages must have a body MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeReadingIntervalGetCnfUlMsg (char * pBuffer, ReadingIntervalGetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding ReadingIntervalGetCnfUlMsg, ID 0x%.2x, ", READING_INTERVAL_GET_CNF_UL_MSG); pBuffer[numBytesEncoded] = READING_INTERVAL_GET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), pMsg->readingIntervalSeconds); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeGpioSetReqDlMsg (char * pBuffer, GpioSetReqDlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding GpioSetReqDlMsg, ID 0x%.2x, ", GPIO_SET_REQ_DL_MSG); pBuffer[numBytesEncoded] = GPIO_SET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeGpioState (&(pBuffer[numBytesEncoded]), &(pMsg->gpioState)); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeGpioSetCnfUlMsg (char * pBuffer, GpioSetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding GpioSetCnfUlMsg, ID 0x%.2x, ", GPIO_SET_CNF_UL_MSG); pBuffer[numBytesEncoded] = GPIO_SET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeGpioState (&(pBuffer[numBytesEncoded]), &(pMsg->gpioState)); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeGpioGetReqDlMsg (char * pBuffer, GpioGetReqDlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding GpioGetReqDlMsg, ID 0x%.2x, ", LED_GET_REQ_DL_MSG); pBuffer[numBytesEncoded] = GPIO_GET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeUint32 (&(pBuffer[numBytesEncoded]), (uint32_t) pMsg->gpio); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeGpioGetCnfUlMsg (char * pBuffer, GpioGetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding GpioGetCnfUlMsg, ID 0x%.2x, ", LED_GET_CNF_UL_MSG); pBuffer[numBytesEncoded] = GPIO_GET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeGpioState (&(pBuffer[numBytesEncoded]), &(pMsg->gpioState)); return numBytesEncoded; } uint32_t MessageCodec::encodeLedSetReqDlMsg (char * pBuffer, LedSetReqDlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding LedSetReqDlMsg, ID 0x%.2x, ", LED_SET_REQ_DL_MSG); pBuffer[numBytesEncoded] = LED_SET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->onNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeLedSetCnfUlMsg (char * pBuffer, LedSetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding LedSetCnfUlMsg, ID 0x%.2x, ", LED_SET_CNF_UL_MSG); pBuffer[numBytesEncoded] = LED_SET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->onNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeLedGetReqDlMsg (char * pBuffer) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding LedGetReqDlMsg, ID 0x%.2x, ", LED_GET_REQ_DL_MSG); pBuffer[numBytesEncoded] = LED_GET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), 0); // Encode packing as all // messages must have a body MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeLedGetCnfUlMsg (char * pBuffer, LedGetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding LedGetCnfUlMsg, ID 0x%.2x, ", LED_GET_CNF_UL_MSG); pBuffer[numBytesEncoded] = LED_GET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->onNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeFlashSetReqDlMsg (char * pBuffer, FlashSetReqDlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding FlashSetReqDlMsg, ID 0x%.2x, ", FLASH_SET_REQ_DL_MSG); pBuffer[numBytesEncoded] = FLASH_SET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->onNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeFlashSetCnfUlMsg (char * pBuffer, FlashSetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding FlashSetCnfUlMs, ID 0x%.2x, ", FLASH_SET_CNF_UL_MSG); pBuffer[numBytesEncoded] = FLASH_SET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->onNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeFlashGetReqDlMsg (char * pBuffer) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding FlashGetReqDlMsg, ID 0x%.2x, ", FLASH_GET_REQ_DL_MSG); pBuffer[numBytesEncoded] = FLASH_GET_REQ_DL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), 0); // Encode packing as all // messages must have a body MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } uint32_t MessageCodec::encodeFlashGetCnfUlMsg (char * pBuffer, FlashGetCnfUlMsg_t * pMsg) { uint32_t numBytesEncoded = 0; MESSAGE_CODEC_LOGMSG ("Encoding FlashGetCnfUlMs, ID 0x%.2x, ", FLASH_GET_CNF_UL_MSG); pBuffer[numBytesEncoded] = FLASH_GET_CNF_UL_MSG; numBytesEncoded++; numBytesEncoded += encodeBool (&(pBuffer[numBytesEncoded]), pMsg->onNotOff); MESSAGE_CODEC_LOGMSG ("%d bytes encoded.\n", numBytesEncoded); return numBytesEncoded; } // ---------------------------------------------------------------- // MESSAGE DECODING FUNCTIONS // ---------------------------------------------------------------- MessageCodec::DecodeResult_t MessageCodec::decodeDlMsg (const char ** ppInBuffer, uint32_t sizeInBuffer, DlMsgUnion_t * pOutBuffer) { MsgIdDl_t msgId; DecodeResult_t decodeResult = DECODE_RESULT_FAILURE; if (sizeInBuffer < MAX_MESSAGE_SIZE) { decodeResult = DECODE_RESULT_INPUT_TOO_SHORT; } else { decodeResult = DECODE_RESULT_UNKNOWN_MSG_ID; // First byte should be a valid DL message ID msgId = (MsgIdDl_t) **ppInBuffer; (*ppInBuffer)++; if (msgId < MAX_NUM_DL_MSGS) { switch (msgId) { case REBOOT_REQ_DL_MSG: decodeResult = DECODE_RESULT_REBOOT_REQ_DL_MSG; pOutBuffer->rebootReqDlMsg.devModeOnNotOff = decodeBool (ppInBuffer); break; case SERIAL_NUMBER_GET_REQ_DL_MSG: decodeResult = DECODE_RESULT_SERIAL_NUMBER_GET_REQ_DL_MSG; decodeUint32 (ppInBuffer); // Must decode the rest of the dummy message; break; case READING_INTERVAL_SET_REQ_DL_MSG: decodeResult = DECODE_RESULT_READING_INTERVAL_SET_REQ_DL_MSG; pOutBuffer->readingIntervalSetReqDlMsg.readingIntervalSeconds = decodeUint32 (ppInBuffer); break; case READING_INTERVAL_GET_REQ_DL_MSG: decodeResult = DECODE_RESULT_READING_INTERVAL_GET_REQ_DL_MSG; decodeUint32 (ppInBuffer); // Must decode the rest of the dummy message; break; case GPIO_SET_REQ_DL_MSG: decodeResult = DECODE_RESULT_GPIO_SET_REQ_DL_MSG; decodeGpioState (&(pOutBuffer->gpioSetReqDlMsg.gpioState), ppInBuffer); break; case GPIO_GET_REQ_DL_MSG: decodeResult = DECODE_RESULT_GPIO_GET_REQ_DL_MSG; pOutBuffer->gpioGetReqDlMsg.gpio = (uint8_t) decodeUint32 (ppInBuffer); break; case LED_SET_REQ_DL_MSG: decodeResult = DECODE_RESULT_LED_SET_REQ_DL_MSG; pOutBuffer->ledSetReqDlMsg.onNotOff = decodeBool (ppInBuffer); break; case LED_GET_REQ_DL_MSG: decodeResult = DECODE_RESULT_LED_GET_REQ_DL_MSG; decodeUint32 (ppInBuffer); // Must decode the rest of the dummy message; break; case FLASH_SET_REQ_DL_MSG: decodeResult = DECODE_RESULT_FLASH_SET_REQ_DL_MSG; pOutBuffer->flashSetReqDlMsg.onNotOff = decodeBool (ppInBuffer); break; case FLASH_GET_REQ_DL_MSG: decodeResult = DECODE_RESULT_FLASH_GET_REQ_DL_MSG; decodeUint32 (ppInBuffer); // Must decode the rest of the dummy message; break; default: // The decodeResult will be left as Unknown message break; } } } return decodeResult; } MessageCodec::DecodeResult_t MessageCodec::decodeUlMsg (const char ** ppInBuffer, uint32_t sizeInBuffer, UlMsgUnion_t * pOutBuffer) { MsgIdUl_t msgId; DecodeResult_t decodeResult = DECODE_RESULT_FAILURE; if (sizeInBuffer < MAX_MESSAGE_SIZE) { decodeResult = DECODE_RESULT_INPUT_TOO_SHORT; } else { decodeResult = DECODE_RESULT_UNKNOWN_MSG_ID; // First byte should be a valid UL message ID msgId = (MsgIdUl_t) **ppInBuffer; (*ppInBuffer)++; if (msgId < MAX_NUM_UL_MSGS) { switch (msgId) { case INIT_IND_UL_MSG: decodeResult = DECODE_RESULT_INIT_IND_UL_MSG; pOutBuffer->initIndUlMsg.wakeUpCode = (WakeUpCode_t) decodeUint32 (ppInBuffer); break; case SERIAL_NUMBER_IND_UL_MSG: decodeResult = DECODE_RESULT_SERIAL_NUMBER_IND_UL_MSG; pOutBuffer->serialNumberIndUlMsg.serialNumber = decodeUint32 (ppInBuffer); break; case VOLUME_IND_UL_MSG: decodeResult = DECODE_RESULT_VOLUME_IND_UL_MSG; pOutBuffer->volumeIndUlMsg.volumeLitres = decodeUint32 (ppInBuffer); break; case RSSI_IND_UL_MSG: decodeResult = DECODE_RESULT_RSSI_IND_UL_MSG; pOutBuffer->rssiIndUlMsg.rssi = decodeUint32 (ppInBuffer); break; case SERIAL_NUMBER_GET_CNF_UL_MSG: decodeResult = DECODE_RESULT_SERIAL_NUMBER_GET_CNF_UL_MSG; pOutBuffer->serialNumberCnfUlMsg.serialNumber = decodeUint32 (ppInBuffer); break; case READING_INTERVAL_SET_CNF_UL_MSG: decodeResult = DECODE_RESULT_READING_INTERVAL_SET_CNF_UL_MSG; pOutBuffer->readingIntervalSetCnfUlMsg.readingIntervalSeconds = decodeUint32 (ppInBuffer); break; case READING_INTERVAL_GET_CNF_UL_MSG: decodeResult = DECODE_RESULT_READING_INTERVAL_GET_CNF_UL_MSG; pOutBuffer->readingIntervalGetCnfUlMsg.readingIntervalSeconds = decodeUint32 (ppInBuffer); break; case GPIO_SET_CNF_UL_MSG: decodeResult = DECODE_RESULT_GPIO_SET_CNF_UL_MSG; pOutBuffer->gpioSetCnfUlMsg = decodeUint32 (ppInBuffer); // Decode as an int32 for later unpacking break; case GPIO_GET_CNF_UL_MSG: decodeResult = DECODE_RESULT_GPIO_GET_CNF_UL_MSG; pOutBuffer->gpioGetCnfUlMsg = decodeUint32 (ppInBuffer); // Decode as an int32 for later unpacking break; case LED_SET_CNF_UL_MSG: decodeResult = DECODE_RESULT_LED_SET_CNF_UL_MSG; pOutBuffer->ledSetCnfUlMsg.onNotOff = decodeBool (ppInBuffer); break; case LED_GET_CNF_UL_MSG: decodeResult = DECODE_RESULT_LED_GET_CNF_UL_MSG; pOutBuffer->ledGetCnfUlMsg.onNotOff = decodeBool (ppInBuffer); break; case FLASH_SET_CNF_UL_MSG: decodeResult = DECODE_RESULT_FLASH_SET_CNF_UL_MSG; pOutBuffer->flashSetCnfUlMsg.onNotOff = decodeBool (ppInBuffer); break; case FLASH_GET_CNF_UL_MSG: decodeResult = DECODE_RESULT_FLASH_GET_CNF_UL_MSG; pOutBuffer->flashGetCnfUlMsg.onNotOff = decodeBool (ppInBuffer); break; default: // The decodeResult will be left as Unknown message break; } } } return decodeResult; } // ---------------------------------------------------------------- // MISC FUNCTIONS // ---------------------------------------------------------------- // Log debug messages void MessageCodec::logMsg (const char * pFormat, ...) { char buffer[MAX_DEBUG_MESSAGE_LEN]; va_list args; va_start (args, pFormat); vsnprintf (buffer, sizeof (buffer), pFormat, args); va_end (args); #ifdef WIN32 if (MessageCodec::mp_guiPrintToConsole) { (*MessageCodec::mp_guiPrintToConsole) (buffer); } #else // Must be on ARM printf (buffer); #endif } void MessageCodec::initDll (void (*guiPrintToConsole) (const char *)) { #ifdef WIN32 mp_guiPrintToConsole = guiPrintToConsole; // This is the signal to the GUI that we're done with initialisation logMsg ("MessageCodec::ready.\n"); #endif } // End Of File