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.

IotMeterApi.hpp

Committer:
RobMeades
Date:
2015-05-22
Revision:
0:5c46cb3be899

File content as of revision 0:5c46cb3be899:

/* C027N/water-meter interface definition 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.
 */

#ifndef IOT_METER_API_HPP
#define IOT_METER_API_HPP

/**
 * @file iot_meter_api.h
 * This file defines the API to the C027N/water-meter device
 * for the MWC demo 2015.
 */

#include <IotMeterMsgs.hpp>

// ----------------------------------------------------------------
// HARDWARE
// The code in this library is setup to expect a Water Pump Relay,
// a Crydom D2425, to be connected through this circuit:
//
// C027N board                     D2425 (Water Pump Relay)
//
//    5V   o------------o 
//                      | 
//                     | |
//                     | |  180 Ohm
//                     | |
//                      |
//                      o--------------o '+3' pin
//            10k Ohm   |
//              ___    / 
//     D7   o--|___|--| (transistor)
//                    _\/
//                      |
//                      |
//                      |
//    Gnd   o-----------o--------------o '4' pin
//                      
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// GENERAL COMPILE-TIME CONSTANTS
// ----------------------------------------------------------------

/// The maximum length of a raw datagram in bytes
#define MAX_DATAGRAM_SIZE_RAW 20

// The GPIO that the water pump is connected to on the C027N board
#define GPIO_WATER_PUMP 7

// ----------------------------------------------------------------
// CLASSES
// ----------------------------------------------------------------

class MessageCodec {
public:

    // ----------------------------------------------------------------
    // MESSAGE ENCODING FUNCTIONS
    // ----------------------------------------------------------------

    /// Encode an uplink message that is sent at power-on of the
    // device.  Indicates that the device has been initialised.  After
    // transmission of this message meter readings will be returned
    // at the indicated rate.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeInitIndUlMsg (char * pBuffer,
                                 InitIndUlMsg_t * pMsg);

    /// Encode a downlink message that reboots the device.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeRebootReqDlMsg (char * pBuffer,
                                   RebootReqDlMsg_t *pMsg);

    /// Encode an uplink message containing the current meter reading.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeVolumeIndUlMsg (char * pBuffer,
                                   VolumeIndUlMsg_t * pMsg);

    /// Encode an uplink message containing the current RSSI reading.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeRssiIndUlMsg (char * pBuffer,
                                 RssiIndUlMsg_t * pMsg);

    /// Encode a downlink message that sets the reading interval
    // of the water meter.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \return  The number of bytes encoded.
    uint32_t encodeSerialNumberGetReqDlMsg (char * pBuffer);

    /// Encode an uplink message that is sent as a response to a
    // SerialNumberGetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeSerialNumberGetCnfUlMsg (char * pBuffer,
                                            SerialNumberGetCnfUlMsg_t * pMsg);

    /// Encode an uplink message that is sent at power-on of the
    // device and in response to an InitReqDlMsg.  Indicates the
    // serial number of the device.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeSerialNumberIndUlMsg (char * pBuffer,
                                         SerialNumberIndUlMsg_t * pMsg);

    /// Encode a downlink message that retrieves the reading interval.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeReadingIntervalGetReqDlMsg (char * pBuffer);

    /// Encode an uplink message that is sent as a response to a
    // ReadingIntervalGetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeReadingIntervalGetCnfUlMsg (char * pBuffer,
                                               ReadingIntervalGetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that sets the reading interval.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \return  The number of bytes encoded.
    uint32_t encodeReadingIntervalSetReqDlMsg (char * pBuffer,
                                               ReadingIntervalSetReqDlMsg_t * pMsg);

    /// Encode an uplink message that is sent as a response to a
    // ReadingIntervalSetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeReadingIntervalSetCnfUlMsg (char * pBuffer,
                                               ReadingIntervalSetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that gets the state of a GPIO
    // on the C027N board.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \return  The number of bytes encoded.
    uint32_t encodeGpioGetReqDlMsg (char * pBuffer,
                                    GpioGetReqDlMsg_t *pMsg);

    /// Encode an uplink message that is sent as a response to a
    // GpioGetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeGpioGetCnfUlMsg (char * pBuffer,
                                    GpioGetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that sets the state of a GPIO
    // on the C027N board.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeGpioSetReqDlMsg (char * pBuffer,
                                    GpioSetReqDlMsg_t * pMsg);

    /// Encode an uplink message that is sent as a response to a
    // GpioSetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeGpioSetCnfUlMsg (char * pBuffer,
                                    GpioSetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that gets the steady state of the
    // red LED on the C027N board.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \return  The number of bytes encoded.
    uint32_t encodeLedGetReqDlMsg (char * pBuffer);

    /// Encode an uplink message that is sent as a response to an
    // LedGetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeLedGetCnfUlMsg (char * pBuffer,
                                   LedGetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that sets the steady state of
    // the red LED.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeLedSetReqDlMsg (char * pBuffer,
                                   LedSetReqDlMsg_t * pMsg);

    /// Encode an uplink message that is sent as a response to an
    // LedSetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeLedSetCnfUlMsg (char * pBuffer,
                                   LedSetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that sets the red LED to flash when
    // a message is being sent/received (or not).  If LedSetReqDlMsg
    // has set the LED to ON the flash will be 'inverted', i.e. the
    // red LED will blink off when a message is being transmitted
    // or received instead.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeFlashSetReqDlMsg (char * pBuffer,
                                     FlashSetReqDlMsg_t * pMsg);

    /// Encode an uplink message that is sent as a response to a
    // FlashSetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeFlashSetCnfUlMsg (char * pBuffer,
                                     FlashSetCnfUlMsg_t * pMsg);

    /// Encode a downlink message that gets the red LED to flash when
    // a message is being sent/received (or not).  If LedSetReqDlMsg
    // has set the LED to ON the flash will be 'inverted', i.e. the
    // red LED will blink off when a message is being transmitted
    // or received instead.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeFlashGetReqDlMsg (char * pBuffer);

    /// Encode an uplink message that is sent as a response to a
    // FlashGetReqDlMsg.
    // \param pBuffer  A pointer to the buffer to encode into.  The
    // buffer length must be at least MAX_MESSAGE_SIZE long
    // \param pMsg  A pointer to the message to send.
    // \return  The number of bytes encoded.
    uint32_t encodeFlashGetCnfUlMsg (char * pBuffer,
                                     FlashGetCnfUlMsg_t * pMsg);

    // ----------------------------------------------------------------
    // MESSAGE DECODING FUNCTIONS
    // ----------------------------------------------------------------

    /// The outcome of message decoding.
    //
    // !!! When you add anything to the generic of UL sections
    // here (but not the DL bits as C# never decodes a DL thing),
    // align it with the DLL exported version in the dll wrapper files
    // so that the C# application can decode it.
    typedef enum DecodeResultTag_t
    {
      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_DL_MSG_BASE = 0x40,  //!< From here on are the
                                         //! downlink messages.
                                         // !!! If you add one here
                                         // update the next line !!!
      DECODE_RESULT_REBOOT_REQ_DL_MSG = DECODE_RESULT_DL_MSG_BASE,
      DECODE_RESULT_SERIAL_NUMBER_GET_REQ_DL_MSG,
      DECODE_RESULT_READING_INTERVAL_SET_REQ_DL_MSG,
      DECODE_RESULT_READING_INTERVAL_GET_REQ_DL_MSG,
      DECODE_RESULT_GPIO_SET_REQ_DL_MSG,
      DECODE_RESULT_GPIO_GET_REQ_DL_MSG,
      DECODE_RESULT_LED_SET_REQ_DL_MSG,
      DECODE_RESULT_LED_GET_REQ_DL_MSG,
      DECODE_RESULT_FLASH_SET_REQ_DL_MSG,
      DECODE_RESULT_FLASH_GET_REQ_DL_MSG,  // !!! If you add one here
                                           // update the next line !!!
      MAX_DL_REQ_MSG = DECODE_RESULT_FLASH_GET_REQ_DL_MSG,
      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_GET_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.
    } DecodeResult_t;

    /// Decode a downlink message. When a datagram has been received
    // this function should be called iteratively to decode all the
    // messages contained within it.  The result, in pOutputBuffer,
    // should be cast by the calling function to DlMsgUnion_t and
    // the relevant member selected according to the
    // DecodeResult_t code.
    // \param ppInBuffer  A pointer to the pointer to decode from.
    // On completion this is pointing to the next byte that
    // could be decoded, after the currently decoded message,
    // in the buffer.
    // \param sizeInBuffer  The number of bytes left to decode.
    // \param pOutBuffer  A pointer to the buffer to write the
    // result into.
    // \param pBytesDecoded A pointer to a place to write the number
    // of bytes decoded.
    // \return  The result of the decoding, which hopefully says
    // what message has been decoded.
    DecodeResult_t decodeDlMsg (const char ** ppInBuffer,
                                uint32_t sizeInBuffer,
                                DlMsgUnion_t * pOutBuffer);

    /// Decode an uplink message. When a datagram has been received
    // this function should be called iteratively to decode all the
    // messages contained within it.  The result, in pOutputBuffer,
    // should be cast by the calling function to UlMsgUnion_t and
    // the relevant member selected according to the
    // DecodeResult_t code.
    // \param ppInBuffer  A pointer to the pointer to decode from.
    // On completion this is pointing to the next byte that
    // could be decoded, after the currently decoded message,
    // in the buffer.
    // \param sizeInBuffer  The number of bytes left to decode.
    // \param pOutBuffer  A pointer to the buffer to write the
    // result into.
    // \return  The result of the decoding, which hopefully says
    // what message has been decoded.
    DecodeResult_t decodeUlMsg (const char ** ppInBuffer,
                                uint32_t sizeInBuffer,
                                UlMsgUnion_t * pOutBuffer);

    // ----------------------------------------------------------------
    // MISC FUNCTIONS
    // ----------------------------------------------------------------

    /// Only used in the DLL form, sets up the "printf()" function
    // for logging.
    // \param guiPrintToConsole  the printf function.
    void initDll (void (*guiPrintToConsole) (const char *));

    /// User callback function for "printf()" logging.  
    static void (*mp_guiPrintToConsole) (const char *);

private:
    /// Encode a boolean value.
    // \param pBuffer  A pointer to where the encoded
    // value should be placed.
    // \param value The Boolean value.
    // \return  The number of bytes encoded.
    uint32_t encodeBool (char * pBuffer, bool value);
    /// Decode a Boolean value.
    // \param ppBuffer  A pointer to the pointer to decode.
    // On completion this points to the location after the
    // bool in the input buffer.
    // \return  The decoded value.
    bool decodeBool (const char ** ppBuffer);
    /// Encode a uint32_t value.
    // \param pBuffer  A pointer to the value to decode.
    // \param value The value.
    // \return  The number of bytes encoded.
    uint32_t encodeUint32 (char * pBuffer, uint32_t value);
    /// Decode a uint32_t value.
    // \param ppBuffer  A pointer to the pointer to decode.
    // On completion this points to the location after the
    // uint32 in the input buffer.
    uint32_t decodeUint32 (const char ** ppBuffer);
    /// Encode GpioState.
    // \param pBuffer  A pointer to the value to decode.
    // \param gGpioState A pointer to the place to put the
    // GPIO Sate.
    // \return  The number of bytes encoded.
    uint32_t encodeGpioState (char * pBuffer, GpioState_t *pGpioState);
    /// Decode Gpio_State_t.
    // \param gGpioState_t a pointer to a place to put the
    // decoded GPIO state.
    // \param ppBuffer  A pointer to the pointer to decode.
    // On completion this points to the location after the
    // uint32 in the input buffer.
    void decodeGpioState (GpioState_t * pGpioState,
                          const char ** ppBuffer);
    /// Log a message for debugging, "printf()" style.
    // \param pFormat The printf() stle parameters.
    void logMsg (const char * pFormat, ...);
};

#endif

// End Of File