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.

IotMeterMsgs.hpp

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

File content as of revision 0:5c46cb3be899:

/* C027N/water-meter message definitions 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_MSGS_HPP
#define IOT_METER_MSGS_HPP

/**
 * @file iot_meter_msgs.h
 * This file defines the messages sent between the
 * C027N/water-meter device and a PC app for the MWC demo
 * 2015.
 *
 * The message format is as follows:
 *
 * uint8_t   id
 * uint32_t  value
 *
 * The IDs are defined in an enumerated type and there are
 * separately defined ID sets for the downlink and uplink
 * directions (i.e. they may overlap).  When transmitted the
 * messages are packed such that the 32-bit content byte
 * immediately follows the 8-bit ID with no packing, resulting
 * in a fixed message length of 5 bytes.  Multiple fixed
 * length messages may be packed into a datagram, hence it can
 * be assumed that a datagram of length < 10 bytes contains
 * one message, a datagram of length < 15 bytes contains two
 * messages, etc.
 *
 * Boolean values are expressed as uint32_t zero (false) or
 * uint32_t one (true).  For multibyte values the highest
 * value bytes is stored first, so a message with ID 0xa5 and
 * value 0x12345678 would be stored in the datagram as:
 *
 * Location: 0 1 2 3 4
 * Contents: a512345678
 *
 * There are some messages (Gpio setters for instance) which
 * encode more than a single value into the value field.  See
 * the individual encode/decode functions for how these values
 * are packed.
 */
 
// ----------------------------------------------------------------
// GENERAL COMPILE-TIME CONSTANTS
// ----------------------------------------------------------------

/// The maximum length of a single messages in bytes
#define MAX_MESSAGE_SIZE 5
 
/// The default meter reading interval.
#define DEFAULT_READING_INTERVAL_SECONDS 10


// ----------------------------------------------------------------
// TYPES
// ----------------------------------------------------------------

/// The wake up code sent from the device
typedef enum WakeUpCodeTag_t
{
    WAKE_UP_CODE_OK,                   //!< A good wake-up, no problems.
    WAKE_UP_CODE_WATER_METER_PROBLEM,  //!< Wake-up after assert due to
                                       //! problems reading the water meter.
    WAKE_UP_CODE_AT_COMMAND_PROBLEM,   //!< Wake-up after assert due to
                                       //! problems with AT commands.
    WAKE_UP_CODE_NETWORK_SEND_PROBLEM, //!< Wake-up after assert due to
                                       //! problems sending to the network.
    WAKE_UP_CODE_MEMORY_ALLOC_PROBLEM, //!< Wake-up after assert due to
                                       //! memory allocation issues.
    WAKE_UP_CODE_PROTOCOL_PROBLEM,     //!< Wake-up after assert due to
                                       //! a protocol problem.
    WAKE_UP_CODE_GENERIC_FAILURE,      //!< Wake-up after a generic failure.
    WAKE_UP_CODE_REBOOT,               //!< Waking up after a commanded reboot.
    MAX_NUM_WAKE_UP_CODES              //!< The maximum number of
                                       //! decode results.
} WakeUpCode_t;

// ----------------------------------------------------------------
// MESSAGE BODIES
// ----------------------------------------------------------------
 
/// InitIndUlMsg_t. 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 requested rate (or DEFAULT_READING_INTERVAL_SECONDS if no
// InitReqDlMsg_t has been received by the device).
typedef struct InitIndUlMsgTag_t
{
    WakeUpCode_t wakeUpCode; //!< A wake-up code from the device.
} InitIndUlMsg_t;

/// RebootReqDlMsg_t. Sent to reboot the device and set the development
// mode on or off.  By default development mode is OFF.
typedef struct RebootReqDlMsgTag_t
{
    bool devModeOnNotOff; //!< If true development mode is on, else it is off.
} RebootReqDlMsg_t;

/// SerialNumberGetCnfUlMsg_t. Sent in response to a SerialNumberGetReqDlMsg_t (which
// is empty and so not represented here).
typedef struct SerialNumberGetCnfUlMsgTag_t
{
  uint32_t serialNumber; //!< The serial number of the meter.
} SerialNumberGetCnfUlMsg_t;

/// SerialNumberIndUlMsg_t. Sent at power-on of the device and in response to
// an InitReqDlMsg_t. Indicates the serial number of the device.
typedef struct SerialNumberIndUlMsgTag_t
{
  uint32_t serialNumber; //!< The serial number of the meter.
} SerialNumberIndUlMsg_t;

/// VolumeIndUlMsg_t. The current meter reading.
typedef struct VolumeIndUlMsgTag_t
{
  uint32_t volumeLitres;
} VolumeIndUlMsg_t;

/// RssiIndUlMsg_t. The current RSSI reading.
typedef struct RssiIndUlMsgTag_t
{
  uint32_t rssi; //!< The RSSI reading in arbitrary units, range 0 to 255.
} RssiIndUlMsg_t;

/// ReadingIntervalSetReqDlMsg_t. Set the meter reading interval.
typedef struct ReadingIntervalSetReqDlMsgTag_t
{
  uint32_t readingIntervalSeconds; //!< The interval at which the device
                                   //! should send readings.
} ReadingIntervalSetReqDlMsg_t;

/// ReadingIntervalSetCnfUlMsg_t. Sent in response to a
// ReadingIntervalSetReqDlMsg_t.
// After transmission of this message meter readings will be returned
// at the requested rate (or DEFAULT_READING_INTERVAL_SECONDS if no
// command setting it otherwise has been received by the device).
typedef struct ReadingIntervalSetCnfUlMsgTag_t
{
  uint32_t readingIntervalSeconds; //!< The interval at which readings are sent.
} ReadingIntervalSetCnfUlMsg_t;

/// ReadingIntervalGetCnfUlMsg_t. Sent in response to a
// ReadingIntervalGetReqDlMsg_t (which is empty and so not represented
// here).
// After transmission of this message meter readings will be returned
// at the requested rate (or DEFAULT_READING_INTERVAL_SECONDS if no
// command setting it otherwise has been received by the device).
typedef struct ReadingIntervalGetCnfUlMsgTag_t
{
    uint32_t readingIntervalSeconds; //!< The interval at which readings are sent.
} ReadingIntervalGetCnfUlMsg_t;

/// GpioState_t.  Data concerning how a GPIO is set up.
typedef struct GpioStateTag_t
{
    uint8_t gpio;        //!< The GPIO in question: 0 for D0, 1 for D1, etc.
    bool inputNotOutput; //!< true if this is an input, else it is an output.
    bool onNotOff;       //!< If the GPIO is an output then this gives its state.
                         //! If the GPIO is an input this is not set.
} GpioState_t;

/// GpioSetReqDlMsg_t. Set the state of a GPIO on the C027N board.
typedef struct GpioSetReqDlMsgTag_t
{
    GpioState_t gpioState; //!< The state of the GPIO.
} GpioSetReqDlMsg_t;

/// GpioSetCnfUlMsg_t.  Response to GpioSetReqDlMsg_t.
typedef struct GpioSetCnfUlMsgTag_t
{
    GpioState_t gpioState; //!< The state of the GPIO.
} GpioSetCnfUlMsg_t;

/// GpioGetReqDlMsg_t. Gets the state of a GPIO on the C027N board.
typedef struct GpioGetReqDlMsgTag_t
{
    uint8_t gpio;        //!< The GPIO to get.
} GpioGetReqDlMsg_t;

/// GpioGetCnfUlMsg_t. Sent in response to a GpioGetReqDlMsg.
typedef struct GpioGetCnfUlMsgTag_t
{
    GpioState_t gpioState; //!< The state of the GPIO.
} GpioGetCnfUlMsg_t;

/// LedSetReqDlMsg_t. Set the steady state of the red LED on
// the C027N board.
typedef struct LedSetReqDlMsgTag_t
{
    bool onNotOff; //!< Make the steady state ON if true, otherwise OFF.
                   //! OFF is the default state.
} LedSetReqDlMsg_t;

/// LedSetCnfUlMsg_t.  Response to LedSetReqDlMsg_t.
typedef struct LedSetCnfUlMsgTag_t
{
    bool onNotOff; //!< The LED is steady-state ON if true, otherwise
                   //! OFF.
} LedSetCnfUlMsg_t;

/// LedGetCnfUlMsg_t. Sent in response to an LedGetReqDlMsg
// (which is an empty ID and so not represented here).
typedef struct LedGetCnfUlMsgTag_t
{
    bool onNotOff; //!< The steady state is ON if true, otherwise OFF.
} LedGetCnfUlMsg_t;

/// FlashSetReqDlMsg_t. Set the red LED to flash when a reading is
// being sent (or not).  If LedSetReqDlMsg_t has been set to ON the
// flash will be 'inverted', i.e. the red LED will blink off when a
// reading is being transmitted instead.
typedef struct FlashSetReqDlMsgTag_t
{
    bool onNotOff; //!< If true then the red LED will flash when a
                   //! reading is being sent, else it will remain in
                   //! steady state. The default is to flash when a
                   //! reading is being sent.
} FlashSetReqDlMsg_t;

/**
 * FlashSetCnfUlMsg_t. Response to FlashSetReqDlMsg_t.
 */
typedef struct FlashSetCnfUlMsgTag_t
{
    bool onNotOff; //!< If true then the red LED flashes when a
                   //! reading is being sent, else it will remain in
                   //! steady state.
} FlashSetCnfUlMsg_t;

/// FlashGetCnfUlMsg_t. Sent in response to a FlashGetReqDlMsg
// (which is an empty ID and so not represented here).
typedef struct FlashGetCnfUlMsgTag_t
{
    bool onNotOff; //!< The steady state is ON if true, otherwise OFF.
} FlashGetCnfUlMsg_t;

// ----------------------------------------------------------------
// MESSAGE UNIONS
// ----------------------------------------------------------------

/// Union of all downlink messages.
typedef union DlMsgUnionTag_t
{
    RebootReqDlMsg_t rebootReqDlMsg;
    ReadingIntervalSetReqDlMsg_t readingIntervalSetReqDlMsg;
    GpioSetReqDlMsg_t gpioSetReqDlMsg;
    GpioGetReqDlMsg_t gpioGetReqDlMsg;
    LedSetReqDlMsg_t ledSetReqDlMsg;
    FlashSetReqDlMsg_t flashSetReqDlMsg;
} DlMsgUnion_t;

/// Union of all uplink messages.
typedef union UlMsgUnionTag_t
{
    InitIndUlMsg_t initIndUlMsg;
    VolumeIndUlMsg_t volumeIndUlMsg;
    RssiIndUlMsg_t rssiIndUlMsg;
    SerialNumberIndUlMsg_t serialNumberIndUlMsg;
    SerialNumberGetCnfUlMsg_t serialNumberCnfUlMsg;
    ReadingIntervalSetCnfUlMsg_t readingIntervalSetCnfUlMsg;
    ReadingIntervalGetCnfUlMsg_t readingIntervalGetCnfUlMsg;
    uint32_t gpioSetCnfUlMsg; // These are left packed inside a uint32_t so that
    uint32_t gpioGetCnfUlMsg; // they can be passed to C# without a struct.
    LedSetCnfUlMsg_t ledSetCnfUlMsg;
    LedGetCnfUlMsg_t ledGetCnfUlMsg;
    FlashSetCnfUlMsg_t flashSetCnfUlMsg;
    FlashGetCnfUlMsg_t flashGetCnfUlMsg;
} UlMsgUnion_t;

#endif

// End Of File