Senet Packet API
Revision 0:08689149c8e3, committed 2016-03-05
- Comitter:
- shaunkrnelson
- Date:
- Sat Mar 05 21:56:20 2016 +0000
- Child:
- 1:c4435fed9eb9
- Commit message:
- Initial commit
Changed in this revision
| senet_packet.cpp | Show annotated file Show diff for this revision Revisions of this file |
| senet_packet.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/senet_packet.cpp Sat Mar 05 21:56:20 2016 +0000
@@ -0,0 +1,268 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: senet_packet.cpp
+ *
+ * Description: Senet Packet Types implementation file
+ *
+ * Version: 1.0
+ * Created: 03/05/2016 04:23:40 PM
+ *
+ * Author: S. Nelson
+ * Company: Senet, Inc
+ *
+ * =====================================================================================
+ */
+
+
+#include "senet_packet.h"
+// #include <cstddef>
+
+
+int32_t SenetLoRaPacket::
+PacketHeader::serialize(uint8_t *frame, int32_t len)
+{
+ ASSERT(len > 2);
+
+ frame[0] = version;
+ frame[1] = type;
+
+ return 2;
+}
+
+bool SenetLoRaPacket::
+PacketHeader::deserialize(uint8_t *frame, int32_t len)
+{
+ if((frame != NULL) && (len >= 2))
+ {
+ version = frame[0];
+ type = frame[1];
+ return true;
+ }
+ return false;
+}
+
+bool SensorPacket::addSensorValue(uint8_t position, uint8_t type, uint16_t value)
+{
+ if (position < MAX_SENSOR_VALUES)
+ {
+ sensorValue[position].type = type;
+ sensorValue[position].value = value;
+ sensorValue[position].isSet = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+int32_t SensorPacket::serializeData(uint8_t *buffer, int32_t len)
+{
+ int32_t bytes = 0;
+ int32_t dataLen = 0;
+
+ for(int32_t i = 0; i < MAX_SENSOR_VALUES; i++)
+ {
+ if(sensorValue[i].isSet == true)
+ {
+ dataLen = sensorValue[i].serialize(buffer+bytes, len - bytes);
+ if(dataLen == -1)
+ return -1;
+ bytes += dataLen;
+ }
+ }
+ return bytes;
+}
+
+bool SelfIdPacket::setDeviceType(uint32_t model, uint8_t revision)
+{
+ if((model & 0x00FFFFFF) != model)
+ return false;
+
+ deviceType = (model<<8)|revision;
+ return true;
+}
+
+bool SelfIdPacket::setSwVersion(uint8_t major, uint8_t minor, uint8_t point, uint16_t build, uint8_t developerId)
+{
+ uint8_t _major = major & 0xf;
+ uint8_t _minor = minor & 0xf;
+ uint8_t _point = point & 0x3f;
+ uint16_t _build = build & 0x3ff;
+ uint8_t _devid = developerId & 0xff;
+
+ if((_major != major) || (_minor != minor) || (_point != point) || (_build != build) || (_devid != developerId))
+ return false;
+
+ swVersion = (_major << 28) | (_minor << 24) | (_point << 18) | (_build << 8) | _devid;
+ return true;
+}
+
+void SelfIdPacket::setBatteryFailState(bool failed)
+{
+ if(failed == true)
+ powerMask |= 1 << 3;
+ else
+ powerMask &= ~(1 << 3);
+}
+
+bool SelfIdPacket::setBatteryLevel(uint8_t level)
+{
+ uint8_t _level = level & 0x7;
+
+ if(level != _level)
+ return false;
+
+ powerMask &= 0xf8;
+ powerMask |= _level;
+
+ return true;
+}
+
+bool SelfIdPacket::setExtPowerSupplyState(uint8_t id, bool isPresent)
+{
+ bool retVal = false;
+ if(id == EXT_POWER_SUPPLY_1)
+ {
+ powerMask &= 0x7F;
+ if(isPresent)
+ powerMask |= 0x80;
+ retVal = true;
+ }
+ else if(id == EXT_POWER_SUPPLY_2)
+ {
+ powerMask &= 0xBF;
+ if(isPresent)
+ powerMask |= 0x40;
+ retVal = true;
+ }
+ return retVal;
+}
+
+int32_t SelfIdPacket::serializeData(uint8_t *frame, int32_t len)
+{
+#define SELFID_PACKET_LEN 8
+
+ ASSERT(SELFID_PACKET_LEN <= len);
+
+ frame[0] = (deviceType>>16) & 0xff;
+ frame[1] = (deviceType>>8) & 0xff;
+ frame[2] = deviceType & 0xff;
+
+ frame[3] = (swVersion >> 24) & 0xff;
+ frame[4] = (swVersion >> 16) & 0xff;
+ frame[5] = (swVersion >> 8) & 0xff;
+ frame[6] = swVersion & 0xff;
+
+ frame[7] = powerMask;
+
+ return SELFID_PACKET_LEN;
+}
+
+int32_t ConfigWordPacket::serializeData(uint8_t *frame, int32_t len)
+{
+#define CONTROL_PACKET_LENGTH 9
+
+ ASSERT(CONTROL_PACKET_LENGTH <= len);
+
+ frame[0] = (config>>24) & 0xff;
+ frame[1] = (config>>16) & 0xff;
+ frame[2] = (config>>8) & 0xff;
+ frame[3] = config & 0xff;
+
+ frame[4] = (mask>>24) & 0xff;
+ frame[5] = (mask>>16) & 0xff;
+ frame[6] = (mask>>8) & 0xff;
+ frame[7] = mask & 0xff;
+
+ frame[8] = authKey;
+
+ return CONTROL_PACKET_LENGTH;
+
+}
+
+int32_t BootInfoPacket::serializeData(uint8_t *frame, int32_t len)
+{
+#define BOOT_PACKET_LENGTH 8
+
+ ASSERT(BOOT_PACKET_LENGTH <= len);
+
+ frame[0] = (bootCount<<8) & 0xff;
+ frame[1] = bootCount & 0xff;
+
+ frame[2] = (resetCount<<8) & 0xff;
+ frame[3] = resetCount & 0xff;
+
+ frame[4] = (lastBootReason<<24) & 0xff;
+ frame[5] = (lastBootReason<<16) & 0xff;
+ frame[6] = (lastBootReason<<8) & 0xff;
+
+ return BOOT_PACKET_LENGTH;
+}
+
+bool GpsPacket::setCoordinates(uint32_t _latitude, uint32_t _longitude, uint16_t _elevation)
+{
+
+ if(((_latitude & 0x00ffffff) != _latitude) || ((_longitude & 0x00ffffff) != _longitude))
+ return false;
+
+ latitude = _latitude;
+ longitude = _longitude;
+ elevation = _elevation;
+}
+
+int32_t GpsPacket::serializeData(uint8_t *frame, int32_t len)
+{
+#define GPS_PACKET_LENGTH 7
+
+ if(len < GPS_PACKET_LENGTH )
+ return -1;
+
+ frame[0] = (latitude>>16) & 0xff;
+ frame[1] = (latitude>>8) & 0xff;
+ frame[2] = latitude & 0xff;
+
+ frame[3] = (longitude>>16) & 0xff;
+ frame[4] = (longitude>>8) & 0xff;
+ frame[5] = longitude & 0xff;
+
+ frame[6] = txPower;
+
+ return GPS_PACKET_LENGTH;
+}
+
+int32_t RFDataPacket::serializeData(uint8_t *frame, int32_t len)
+{
+#define RFDATA_PACKET_LEN 8
+
+ ASSERT(len > RFDATA_PACKET_LEN);
+
+ frame[0] = channel;
+ frame[1] = txpower;
+ frame[2] = datarate;
+ frame[3] = snr;
+ frame[4] = rssi;
+ frame[5] = (timestamp >> 16)& 0xff;
+ frame[6] = (timestamp >> 8)& 0xff;
+ frame[7] = timestamp & 0xff;
+ return RFDATA_PACKET_LEN;
+
+}
+
+bool OctetStringPacket::setOctetString(uint8_t *os, uint8_t len)
+{
+ if(len > maxSize)
+ return false;
+
+ memcpy(osptr, os, len);
+ oslen = len;
+ return true;
+}
+
+int32_t OctetStringPacket::serializeData(uint8_t *frame, int32_t len)
+{
+ if(len < oslen)
+ oslen = len;
+ memcpy(frame, osptr, oslen);
+ return oslen;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/senet_packet.h Sat Mar 05 21:56:20 2016 +0000
@@ -0,0 +1,355 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: senet_packet.h
+ *
+ * Description: Senet Packet types
+ *
+ * Version: 1.0
+ * Created: 03/05/2016 03:13:20 PM
+ * Revision: 1
+ *
+ * Author: Shaun Nelson, coder extraodinaire
+ * Company: Senet, Inc
+ *
+ * =====================================================================================
+ */
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#define ASSERT(_expr) assert(_expr)
+
+// Senet packet types
+enum SenetPacketT
+{
+ SELF_ID_PACKET = 0,
+ RF_PACKET = 1,
+ GPS_PACKET = 2,
+ CONTROL_PACKET = 3,
+ BOOT_INFO_PACKET = 4,
+ SENSOR_PACKET = 8,
+ OCTET_STRING_PACKET = 126,
+ UTF_8_STRING = 127
+};
+
+
+/*
+ * =====================================================================================
+ * Class: SenetLoRaPacket
+ * Description: Senet Packet Base class
+ * =====================================================================================
+ */
+struct SenetLoRaPacket
+{
+ static const uint32_t MAX_FRAME_SIZE = 242;
+ static const uint8_t VERSION = 1;
+
+
+ // Common packet header
+ struct PacketHeader
+ {
+ uint8_t version; // packet format versioni
+ uint8_t type; // Senet packet type
+
+ PacketHeader(uint8_t _type=0)
+ {
+ version = VERSION;
+ type = _type;
+ }
+
+ int32_t serialize (uint8_t *frame, int32_t len);
+ bool deserialize(uint8_t *frame, int32_t len);
+ } header;
+
+ uint8_t pkt[MAX_FRAME_SIZE]; // serialized packet buffer
+ uint8_t pktLen; // serialized packet length
+
+ SenetLoRaPacket(uint8_t senetPktType)
+ {
+ header.type = senetPktType;
+ header.version = VERSION;
+ pktLen = 0;
+ }
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: SenetLoRaPacket
+ * Method: serialize
+ * Description: Packet serializer
+ *--------------------------------------------------------------------------------------
+ */
+ virtual int32_t serialize()
+ {
+ pktLen = header.serialize(pkt, MAX_FRAME_SIZE);
+
+ int32_t payloadLen = serializeData(pkt + pktLen, MAX_FRAME_SIZE - pktLen);
+ if(payloadLen > 0)
+ {
+ pktLen += payloadLen;
+ return pktLen;
+ }
+ return -1;
+ }
+
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: SenetLoRaPacket
+ * Method: serializeData
+ * Description: Each unique packet type implements this to serialize its data
+ *--------------------------------------------------------------------------------------
+ */
+ virtual int32_t serializeData(uint8_t *frame, int32_t len) {return 0;}
+
+};
+
+
+/*
+ * =====================================================================================
+ * Class: BootInfoPacket
+ * Description: Device Boot information packet
+ * =====================================================================================
+ */
+struct BootInfoPacket : public SenetLoRaPacket
+{
+ uint16_t bootCount; // number of device boots
+ uint16_t resetCount; // number of device resets
+ uint32_t lastBootReason; // last boot reason
+
+ BootInfoPacket() :
+ SenetLoRaPacket(BOOT_INFO_PACKET)
+ {
+ bootCount = 0;
+ resetCount = 0;
+ lastBootReason = 0;
+ }
+
+ protected:
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: BootInfoPacket
+ * Method: serializeData
+ * Description: Serialize packet data
+ *--------------------------------------------------------------------------------------
+ */
+ int32_t serializeData(uint8_t *frame, int32_t len);
+};
+
+
+/*
+ * =====================================================================================
+ * Class: ControlWordPacket
+ * Description: Packet to configure device
+ * =====================================================================================
+ */
+struct ConfigWordPacket : public SenetLoRaPacket
+{
+ ConfigWordPacket() :
+ SenetLoRaPacket(CONTROL_PACKET) { config = 0; mask = 0; authKey = 0; }
+
+ uint32_t config; // configuration word
+ uint32_t mask; // valid bit mask applied to configuration word
+ uint8_t authKey; // Downlink authentication key
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: ConfigWordPacket
+ * Method: serializeData
+ * Description: Serialize packet data
+ *--------------------------------------------------------------------------------------
+ */
+ int32_t serializeData(uint8_t *frame, int32_t len);
+};
+
+
+/*
+ * =====================================================================================
+ * Class: GpsPacket
+ * Description: Transmit device location in Decimal degress (http://www.en.wikipedia.org/wiki/Decimal_degrees)
+ * =====================================================================================
+ */
+struct GpsPacket : public SenetLoRaPacket
+{
+ bool setCoordinates(uint32_t latitude, uint32_t longitude, uint16_t elevation);
+ inline void setTxPower(uint8_t dBm) { txPower = dBm; }
+
+ GpsPacket():
+ SenetLoRaPacket(GPS_PACKET)
+ {
+ latitude = 0;
+ longitude = 0;
+ elevation = 0;
+ txPower = 0;
+ }
+
+ protected:
+ uint32_t latitude;
+ uint32_t longitude;
+ uint16_t elevation;
+ uint8_t txPower;
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: GpsPacket
+ * Method: serializeData
+ * Description: Serialize the data
+ *--------------------------------------------------------------------------------------
+ */
+ int32_t serializeData(uint8_t *frame, int32_t len);
+};
+
+
+/*
+ * =====================================================================================
+ * Class: OctetStringPacket
+ * Description: Variable length Octet String packet
+ * =====================================================================================
+ */
+struct OctetStringPacket : public SenetLoRaPacket
+{
+ bool setOctetString(uint8_t *os, uint8_t len);
+
+ OctetStringPacket(uint8_t size)
+ : SenetLoRaPacket(OCTET_STRING_PACKET)
+ {
+ osptr = new uint8_t[size];
+ ASSERT(osptr != NULL);
+ maxSize = size;
+ oslen = 0;
+ }
+
+ protected:
+ uint8_t *osptr;
+ uint8_t maxSize;
+ uint8_t oslen;
+
+ virtual int32_t serializeData(uint8_t *frame, int32_t len);
+};
+
+
+/*
+ * =====================================================================================
+ * Class: RFDataPacket
+ * Description: Radio Data packet
+ * =====================================================================================
+ */
+struct RFDataPacket : public SenetLoRaPacket
+{
+ uint8_t channel; // The channel the device sent on
+ uint8_t txpower; // The transmit power in dBm used by the device
+ uint8_t datarate; // The datarate used by the device
+ uint8_t snr; // Signal to Noise ratio of the last frame received
+ uint8_t rssi; // RSSI of the last frame received
+ uint32_t timestamp; // The device's current timestamp
+
+ RFDataPacket():
+ SenetLoRaPacket(RF_PACKET)
+ {
+ channel = 0;
+ txpower = 0;
+ datarate = 0;
+ snr = 0;
+ rssi = 0;
+ timestamp = 0;
+ }
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: RFDataPacket
+ * Method: serializeData
+ * Description: Serialize the data
+ *--------------------------------------------------------------------------------------
+ */
+ int32_t serializeData(uint8_t *frame, int32_t len);
+};
+
+
+/*
+ * =====================================================================================
+ * Class: SelfIdPacket
+ * Description:
+ * =====================================================================================
+ */
+struct SelfIdPacket : public SenetLoRaPacket
+{
+ const static uint8_t EXT_POWER_SUPPLY_ID_MAX = 2;
+ const static uint8_t EXT_POWER_SUPPLY_1 = 1;
+ const static uint8_t EXT_POWER_SUPPLY_2 = 2;
+ const static uint8_t BATTERY_LEVEL_MAX = 7;
+
+ bool setDeviceType (uint32_t model, uint8_t revision);
+ bool setSwVersion (uint8_t major, uint8_t minor, uint8_t point, uint16_t build, uint8_t developer);
+ void setBatteryFailState (bool failed);
+ bool setBatteryLevel (uint8_t level);
+ bool setExtPowerSupplyState (uint8_t id, bool isPresent);
+
+ SelfIdPacket() :
+ SenetLoRaPacket(SELF_ID_PACKET) { deviceType = 0; swVersion = 0; powerMask = 0; }
+
+ protected:
+ uint32_t deviceType;
+ uint32_t swVersion;
+ uint8_t powerMask;
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: SelfIdPacket
+ * Method: serializeData
+ * Description: Serialize the data
+ *--------------------------------------------------------------------------------------
+ */
+ virtual int32_t serializeData(uint8_t *frame, int32_t len);
+};
+
+
+/*
+ * =====================================================================================
+ * Class: SensorPacket
+ * Description:
+ * =====================================================================================
+ */
+struct SensorPacket : public SenetLoRaPacket
+{
+ bool setPrimarySensor(uint16_t value) { return addSensorValue(0,1, value);};
+ bool setTemperature (uint16_t value) { return addSensorValue(1,2, value);}
+ void reset();
+
+ SensorPacket() :
+ SenetLoRaPacket(SENSOR_PACKET) {}
+
+ protected:
+ static const uint8_t MAX_SENSOR_VALUES = 2;
+
+ struct SensorValue
+ {
+ uint8_t type;
+ uint16_t value;
+ bool isSet;
+
+ SensorValue() { type = 0; value = 0; isSet = false;}
+
+ int32_t serialize(uint8_t *frame, int32_t len)
+ {
+ if(len < 3)
+ return -1;
+
+ frame[0] = type;
+ frame[1] = (value >> 8) & 0xff;
+ frame[2] = value & 0xff;
+ return 3;
+ }
+ } sensorValue[MAX_SENSOR_VALUES];
+
+ bool addSensorValue(uint8_t position, uint8_t type, uint16_t value);
+
+ /*
+ *--------------------------------------------------------------------------------------
+ * Class: SelfIdPacket
+ * Method: serializeData
+ * Description: Serialize the data
+ *--------------------------------------------------------------------------------------
+ */
+ virtual int32_t serializeData(uint8_t *frame, int32_t len);
+
+};