BERG Cloud / BERGCloud

Dependents:   LittleCounter-Example

Revision:
6:79100379d4b4
Parent:
5:2e04a8b3fc25
diff -r 2e04a8b3fc25 -r 79100379d4b4 BERGCloudBase.cpp
--- a/BERGCloudBase.cpp	Tue Nov 26 17:45:12 2013 +0000
+++ b/BERGCloudBase.cpp	Wed Apr 16 14:38:12 2014 +0000
@@ -28,7 +28,7 @@
 #define __STDC_LIMIT_MACROS /* Include C99 stdint defines in C++ code */
 #include <stdint.h>
 #include <stddef.h>
-#include <string.h> /* For memcpy() */
+#include <string.h> /* For memset() */
 
 #include "BERGCloudBase.h"
 
@@ -37,6 +37,11 @@
 
 #define CONNECT_POLL_RATE_MS 250
 
+/* MessagePack for named commands and events */
+#define _MP_FIXRAW_MIN      0xa0
+#define _MP_FIXRAW_MAX      0xbf
+#define _MAX_FIXRAW         (_MP_FIXRAW_MAX - _MP_FIXRAW_MIN)
+
 uint8_t BERGCloudBase::nullKey[BC_KEY_SIZE_BYTES] = {0};
 
 bool BERGCloudBase::_transaction(_BC_SPI_TRANSACTION *tr)
@@ -276,6 +281,8 @@
 {
   /* Returns TRUE if a valid command has been received */
 
+  _LOG("pollForCommand() methods returning a command ID number have been deprecated.\r\n");
+
   _BC_SPI_TRANSACTION tr;
   uint8_t cmdID[2] = {0};
   uint16_t cmdIDSize = 0;
@@ -303,11 +310,80 @@
   return false;
 }
 
+bool BERGCloudBase::pollForCommand(uint8_t *commandBuffer, uint16_t commandBufferSize, uint16_t& commandSize, char *commandName, uint8_t commandNameMaxSize)
+{
+  /* Returns TRUE if a valid command has been received */
+
+  _BC_SPI_TRANSACTION tr;
+  uint8_t cmdID[2] = {0};
+  uint16_t cmdIDSize = 0;
+  uint8_t commandNameSize;
+  uint8_t originalCommandNameSize;
+  uint8_t msgPackByte;
+  uint16_t command;
+
+  if ((commandName == NULL) || (commandNameMaxSize < 2))
+  {
+    return false;
+  }
+
+  initTransaction(&tr);
+
+  tr.command = SPI_CMD_POLL_FOR_COMMAND;
+
+  tr.rx[0].buffer = cmdID;
+  tr.rx[0].bufferSize = sizeof(cmdID);
+  tr.rx[0].dataSize = &cmdIDSize;
+
+  tr.rx[1].buffer = commandBuffer;
+  tr.rx[1].bufferSize = commandBufferSize;
+  tr.rx[1].dataSize = &commandSize;
+
+  if (transaction(&tr))
+  {
+    command = (cmdID[0] << 8) | cmdID[1];
+    if (command == BC_COMMAND_NAMED_PACKED)
+    {
+      /* Get command name string size */
+      msgPackByte = *commandBuffer;
+
+      if ((msgPackByte <_MP_FIXRAW_MIN) || (msgPackByte > _MP_FIXRAW_MAX))
+      {
+        /* Invalid */
+        return false;
+      }
+
+      commandNameSize = originalCommandNameSize = msgPackByte - _MP_FIXRAW_MIN;
+
+      /* Limit to the size of the buffer provided */
+      if (commandNameSize > (commandNameMaxSize-1)) /* -1 for null terminator */
+      {
+        commandNameSize = (commandNameMaxSize-1);
+      }
+
+      /* Copy command name string as a null-terminated C string */
+      bytecpy((uint8_t *)commandName, (commandBuffer+1), commandNameSize); /* +1 for messagePack fixraw byte */
+      commandName[commandNameSize] = '\0';
+
+      /* Move up remaining packed data, update size */
+      commandSize -= (originalCommandNameSize + 1); /* +1 for messagePack fixraw byte */
+      bytecpy(commandBuffer, commandBuffer + (originalCommandNameSize + 1), commandSize);
+      return true;
+    }
+  }
+
+  *commandName = '\0';
+  commandSize = 0;
+  return false;
+}
+
 #ifdef BERGCLOUD_PACK_UNPACK
 bool BERGCloudBase::pollForCommand(BERGCloudMessageBuffer& buffer, uint8_t& commandID)
 {
   /* Returns TRUE if a valid command has been received */
 
+  _LOG("pollForCommand() methods returning a command ID number have been deprecated.\r\n");
+
   _BC_SPI_TRANSACTION tr;
   uint8_t cmdID[2] = {0};
   uint16_t cmdIDSize = 0;
@@ -337,12 +413,85 @@
   buffer.used(0);
   return false;
 }
+
+bool BERGCloudBase::pollForCommand(BERGCloudMessageBuffer& buffer, char *commandName, uint8_t commandNameMaxSize)
+{
+  /* Returns TRUE if a valid command has been received */
+
+  _BC_SPI_TRANSACTION tr;
+  uint8_t cmdID[2] = {0};
+  uint16_t cmdIDSize = 0;
+  uint16_t dataSize = 0;
+  uint8_t commandNameSize;
+  uint8_t originalCommandNameSize;
+  uint8_t msgPackByte;
+  uint16_t command;
+
+  if ((commandName == NULL) || (commandNameMaxSize < 2))
+  {
+    return false;
+  }
+
+  initTransaction(&tr);
+  buffer.clear();
+
+  tr.command = SPI_CMD_POLL_FOR_COMMAND;
+
+  tr.rx[0].buffer = cmdID;
+  tr.rx[0].bufferSize = sizeof(cmdID);
+  tr.rx[0].dataSize = &cmdIDSize;
+
+  tr.rx[1].buffer = buffer.ptr();
+  tr.rx[1].bufferSize = buffer.size();
+  tr.rx[1].dataSize = &dataSize;
+
+  if (transaction(&tr))
+  {
+    command = (cmdID[0] << 8) | cmdID[1];
+    if (command == BC_COMMAND_NAMED_PACKED)
+    {
+      /* Get command name string size */
+      msgPackByte = *buffer.ptr();
+
+      if ((msgPackByte <_MP_FIXRAW_MIN) || (msgPackByte > _MP_FIXRAW_MAX))
+      {
+        /* Invalid */
+        return false;
+      }
+
+      commandNameSize = originalCommandNameSize = msgPackByte - _MP_FIXRAW_MIN;
+
+      /* Limit to the size of the buffer provided */
+      if (commandNameSize > (commandNameMaxSize-1)) /* -1 for null terminator */
+      {
+        commandNameSize = (commandNameMaxSize-1);
+      }
+
+      /* Copy command name string as a null-terminated C string */
+      bytecpy((uint8_t *)commandName, (buffer.ptr()+1), commandNameSize); /* +1 for messagePack fixraw byte */
+      commandName[commandNameSize] = '\0';
+
+      /* Move up remaining packed data, update size */
+      dataSize -= (originalCommandNameSize + 1); /* +1 for messagePack fixraw byte */
+      bytecpy(buffer.ptr(), buffer.ptr() + (originalCommandNameSize + 1), dataSize);
+
+      buffer.used(dataSize);
+      return true;
+    }
+  }
+
+  buffer.used(0);
+  *commandName = '\0';
+  return false;
+}
 #endif
 
 bool BERGCloudBase::_sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, uint8_t command)
 {
   /* Returns TRUE if the event is sent successfully */
 
+  _LOG("sendEvent() methods using an eventCode number have been deprecated.\r\n");
+
   _BC_SPI_TRANSACTION tr;
   uint8_t header[4] = {0};
 
@@ -367,9 +516,62 @@
 
 bool BERGCloudBase::sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, bool packed)
 {
+
   return _sendEvent(eventCode, eventBuffer, eventSize, packed ? SPI_CMD_SEND_EVENT_PACKED : SPI_CMD_SEND_EVENT_RAW);
 }
 
+bool BERGCloudBase::sendEvent(const char *eventName, uint8_t *eventBuffer, uint16_t eventSize, bool packed)
+{
+  /* Returns TRUE if the event is sent successfully */
+
+  _BC_SPI_TRANSACTION tr;
+  uint8_t headerSize = 5; /* Four bytes of SPI header, one byte of messagePack type */
+  uint8_t header[5 + _MAX_FIXRAW] = {0}; /* Header size plus maximum name string size */
+
+  if (!packed)
+  {
+    /* We only support packed data now */
+    return false;
+  }
+
+  if ((eventName == NULL) || (eventName[0] == '\0'))
+  {
+    _LOG("Event name must be at least one character.\r\n");
+    return false;
+  }
+
+  /* Create SPI header */
+  header[0] = BC_EVENT_NAMED_PACKED & BC_EVENT_ID_MASK;
+  header[1] = 0;
+  header[2] = 0;
+  header[3] = 0;
+
+  /* Create string header in messagePack format */
+  header[4] = _MP_FIXRAW_MIN;
+  while ((*eventName != '\0') && (headerSize < sizeof(header)))
+  {
+    /* Copy string, update messagePack byte */
+    header[4]++;
+    header[headerSize++] = *eventName++;
+  }
+
+  if (eventSize > ((uint16_t)SPI_MAX_PAYLOAD_SIZE_BYTES - headerSize))
+  {
+    _LOG("Event is too big.\r\n");
+    return false;
+  }
+
+  initTransaction(&tr);
+
+  tr.command = SPI_CMD_SEND_EVENT_PACKED;
+  tr.tx[0].buffer = (uint8_t *)header;
+  tr.tx[0].dataSize = headerSize;
+  tr.tx[1].buffer = eventBuffer;
+  tr.tx[1].dataSize = eventSize;
+
+  return transaction(&tr);
+}
+
 #ifdef BERGCLOUD_PACK_UNPACK
 bool BERGCloudBase::sendEvent(uint8_t eventCode, BERGCloudMessageBuffer& buffer)
 {
@@ -380,6 +582,52 @@
   buffer.clear();
   return result;
 }
+
+bool BERGCloudBase::sendEvent(const char *eventName, BERGCloudMessageBuffer& buffer)
+{
+  /* Returns TRUE if the event is sent successfully */
+
+  _BC_SPI_TRANSACTION tr;
+  uint8_t headerSize = 5; /* Four bytes of SPI header, one byte of messagePack type */
+  uint8_t header[5 + _MAX_FIXRAW] = {0}; /* Header size plus maximum name string size */
+
+  if ((eventName == NULL) || (eventName[0] == '\0'))
+  {
+    _LOG("Event name must be at least one character.\r\n");
+    return false;
+  }
+
+  /* Create SPI header */
+  header[0] = BC_EVENT_NAMED_PACKED & BC_EVENT_ID_MASK;
+  header[1] = 0;
+  header[2] = 0;
+  header[3] = 0;
+
+  /* Create string header in messagePack format */
+  header[4] = _MP_FIXRAW_MIN;
+  while ((*eventName != '\0') && (headerSize < sizeof(header)))
+  {
+    /* Copy string, update messagePack byte */
+    header[4]++;
+    header[headerSize++] = *eventName++;
+  }
+
+  if (buffer.used() > ((uint16_t)SPI_MAX_PAYLOAD_SIZE_BYTES - headerSize))
+  {
+    _LOG("Event is too big.\r\n");
+    return false;
+  }
+
+  initTransaction(&tr);
+
+  tr.command = SPI_CMD_SEND_EVENT_PACKED;
+  tr.tx[0].buffer = (uint8_t *)header;
+  tr.tx[0].dataSize = headerSize;
+  tr.tx[1].buffer = buffer.ptr();
+  tr.tx[1].dataSize = buffer.used();
+
+  return transaction(&tr);
+}
 #endif
 
 bool BERGCloudBase::getConnectionState(uint8_t& state)
@@ -479,6 +727,31 @@
   return true;
 }
 
+bool BERGCloudBase::connect(const char *key, uint16_t version, bool waitForConnected)
+{
+  unsigned int tmp_key[BC_KEY_SIZE_BYTES] = {0};
+  uint8_t _key[BC_KEY_SIZE_BYTES] = {0};
+  uint8_t i;
+
+  /* Convert key from ASCII */
+  if (key != NULL)
+  {
+    if (sscanf(key, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+      &tmp_key[0],  &tmp_key[1],  &tmp_key[2],  &tmp_key[3],
+      &tmp_key[4],  &tmp_key[5],  &tmp_key[6],  &tmp_key[7],
+      &tmp_key[8],  &tmp_key[9],  &tmp_key[10], &tmp_key[11],
+      &tmp_key[12], &tmp_key[13], &tmp_key[14], &tmp_key[15]) == 16)
+    {
+      for (i=0; i<sizeof(_key); i++)
+      {
+        _key[i] = (uint8_t)tmp_key[i];
+      }
+    }
+  }
+
+  return connect(_key, version, waitForConnected);
+}
+
 bool BERGCloudBase::getClaimingState(uint8_t& state)
 {
   _BC_SPI_TRANSACTION tr;
@@ -610,9 +883,25 @@
 {
   synced = false;
   lastResponse = SPI_RSP_SUCCESS;
+
+  /* Print library version */
+  _LOG("\r\nBERGCloud library version ");
+  _LOG_HEX(BERGCLOUD_LIB_VERSION >> 8);
+  _LOG(".");
+  _LOG_HEX(BERGCLOUD_LIB_VERSION & 0xff);
+  _LOG("\r\n");
 }
 
 void BERGCloudBase::end(void)
 {
 }
+
+void BERGCloudBase::bytecpy(uint8_t *dst, uint8_t *src, uint16_t size)
+{
+  /* memcpy() cannot be used when buffers overlap */
+  while (size-- > 0)
+  {
+    *dst++ = *src++;
+  }
+}