From 0e19f41ae4ba7e0435bb52707204588d5cef2b2e Mon Sep 17 00:00:00 2001 From: kevinbuck-temboo Date: Mon, 22 Aug 2016 16:19:31 -0400 Subject: [PATCH] Version 1.1.7 update --- .../CloudControlsConfig.ino | 97 +++++ keywords.txt | 4 + library.properties | 2 +- src/Temboo.h | 8 +- src/TembooCoAPEdgeDevice.cpp | 8 +- src/TembooMonitoring.cpp | 334 ++++++++++++++++++ src/TembooMonitoring.h | 82 +++++ src/TembooYunShield.h | 7 +- src/utility/TembooWebSocketRequestHandles.c | 209 +++++++++++ src/utility/TembooWebSocketRequestHandles.h | 66 ++++ 10 files changed, 809 insertions(+), 8 deletions(-) create mode 100644 examples/ArduinoYun/CloudControlsConfig/CloudControlsConfig.ino create mode 100644 src/TembooMonitoring.cpp create mode 100644 src/TembooMonitoring.h create mode 100644 src/utility/TembooWebSocketRequestHandles.c create mode 100644 src/utility/TembooWebSocketRequestHandles.h diff --git a/examples/ArduinoYun/CloudControlsConfig/CloudControlsConfig.ino b/examples/ArduinoYun/CloudControlsConfig/CloudControlsConfig.ino new file mode 100644 index 0000000..562cb85 --- /dev/null +++ b/examples/ArduinoYun/CloudControlsConfig/CloudControlsConfig.ino @@ -0,0 +1,97 @@ +// Copyright 2016, Temboo Inc. + +#include + +void setup() { + // initialize the Bridge + Bridge.begin(); + Serial.begin(9600); + Process p; + + //intro message + Serial.println("**** Temboo Cloud Controls ****\n"); + + // update the package list + Serial.print("Updating package listings..."); + p.runShellCommand("opkg update"); + int returnCode = p.exitValue(); + if (returnCode == 0) { + Serial.println("Success!"); + } else { + Serial.println("Failed. Make sure your device is connected to the internet properly."); + while(p.available()) { + char c = p.read(); + Serial.print(c); + } + return; + } + Serial.println(); + // upgrade the Temboo package + Serial.print("Updating Temboo..."); + p.runShellCommand("opkg install http://downloads.arduino.cc/openwrtyun/1/packages/temboo_1.3.1-1_ar71xx.ipk"); + returnCode = p.exitValue(); + if (returnCode == 0) { + Serial.println("Success!"); + } else { + Serial.println("Failed."); + while(p.available()) { + char c = p.read(); + Serial.print(c); + } + return; + } + Serial.println(); + + // install python openssl to allow for for ssl connections + Serial.print("Installing python-openssl..."); + p.runShellCommand("opkg install python-openssl"); + returnCode = p.exitValue(); + if (returnCode == 0) { + Serial.println("Success!"); + } else { + Serial.println("Failed."); + while(p.available()) { + char c = p.read(); + Serial.print(c); + } + return; + } + Serial.println(); + + // Installing twisted web to work with CoAP gateway + Serial.print("Installing twisted-web..."); + p.runShellCommand("opkg install twisted-web"); + returnCode = p.exitValue(); + if (returnCode == 0) { + Serial.println("Success!"); + } else { + Serial.println("Failed."); + while(p.available()) { + char c = p.read(); + Serial.print(c); + } + return; + } + Serial.println(); + + // Configuring zope + Serial.print("Configuring zope..."); + p.runShellCommand("touch /usr/lib/python2.7/site-packages/zope/__init__.py"); + returnCode = p.exitValue(); + if (returnCode == 0) { + Serial.println("Success!"); + } else { + Serial.println("Failed."); + while(p.available()) { + char c = p.read(); + Serial.print(c); + } + return; + } + + Serial.println("Update Complete - your Yun is ready for Cloud Controls!"); +} + +void loop() { + // do nothing +} diff --git a/keywords.txt b/keywords.txt index 8d0ab82..d6bff6a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -33,6 +33,10 @@ setCredential KEYWORD2 setSavedInputs KEYWORD2 addInput KEYWORD2 addOutputFilter KEYWORD2 +addSensorInput KEYWORD2 +addInputExpression KEYWORD2 +setDeviceName KEYWORD2 +setDeviceType KEYWORD2 setSettingsFileToWrite KEYWORD2 setSettingsFileToRead KEYWORD2 setGatewayAddress KEYWORD2 diff --git a/library.properties b/library.properties index 239e1f2..0377a8c 100644 --- a/library.properties +++ b/library.properties @@ -6,5 +6,5 @@ paragraph=Use this library to connect your Arduino or Genuino board to Temboo, m category=Communication url=http://www.temboo.com/arduino architectures=* -version=1.1.6 +version=1.1.7 core-dependencies=arduino (>=1.5.0) diff --git a/src/Temboo.h b/src/Temboo.h index cd69e59..930a036 100644 --- a/src/Temboo.h +++ b/src/Temboo.h @@ -48,8 +48,12 @@ class TembooChoreo : public Process { void setSettingsFileToWrite(const String& filePath) { addParameter("-w" + filePath);} void setSettingsFileToRead(const String& filePath) { addParameter("-r" + filePath);} void setGatewayAddress(const String& addr) { addParameter("-s" + addr);} - - + void addInputExpression(const String& inputName, const String& inputValue) { addParameter("-f" + inputName + ":" + inputValue);} + void addSensorInput(const String& sensorName, long sensorValue, const String& conversion) {addParameter("-n" + sensorName + ":" + String(sensorValue) + ":" + conversion);} + void addSensorInput(const String& sensorName, long sensorValue) {addParameter("-v" + sensorName + ":" + String(sensorValue));} + void addSensorInput(const String& sensorName, long sensorValue, const String& rawLow, const String& rawHigh, const String& scaleLow, const String& scaleHigh) {addParameter("-m" + sensorName + ":" + String(sensorValue) + ":" + rawLow+ ":" + rawHigh+ ":" + scaleLow+ ":" + scaleHigh);} + void setDeviceName(const String& deviceName) {addParameter("-d" + deviceName);} + void setDeviceType(const String& deviceType) {addParameter("-t" + deviceType);} }; #else //ARDUINO_AVR_YUN diff --git a/src/TembooCoAPEdgeDevice.cpp b/src/TembooCoAPEdgeDevice.cpp index 098dea9..d323597 100644 --- a/src/TembooCoAPEdgeDevice.cpp +++ b/src/TembooCoAPEdgeDevice.cpp @@ -41,6 +41,7 @@ const char HTTP_CODE_PREFIX[] = "HTTP_CODE\x0A\x1F"; const char HTTP_CODE_SUFFIX[] = "\x0A\x1E"; const char TembooCoAPClient::URI_PATH[] = "exec"; const char TIME_URI_PATH[] = "time"; +static char HEADER_TIME[] = "x-temboo-time:"; uint16_t TembooCoAPChoreo::s_nextRequestId = 0; @@ -54,8 +55,8 @@ TembooCoAPClient::TembooCoAPClient(TembooCoAPIPStack& ipStack, IPAddress gateway m_blockSize(MAX_BLOCK_SIZE), m_lastError(NO_ERROR), m_dataLen(0), - m_respLen(0), m_txIndex(0), + m_respLen(0), m_txByteCount(0), m_respHttpCode(0) { @@ -551,7 +552,6 @@ bool TembooCoAPClient::moreBlocksToSend() { TembooCoAPClient::Result TembooCoAPClient::sendChoreoRequest() { uint16_t payloadLength = 0; - int16_t blockNum = 0; generateToken(); @@ -828,7 +828,7 @@ int TembooCoAPChoreo::run(uint16_t timeoutSecs) { //Unauthroized, need to update the time if (httpCode == 401 && i == 0) { - find("x-temboo-time:"); + find(HEADER_TIME); TembooCoAPSession::setTime((unsigned long)this->parseInt()); } else { TEMBOO_TRACE("DBG: "); @@ -922,7 +922,7 @@ int TembooCoAPChoreo::read() { } -size_t TembooCoAPChoreo::write(uint8_t data) { +size_t TembooCoAPChoreo::write(uint8_t __attribute__ ((unused)) data) { return 0; } diff --git a/src/TembooMonitoring.cpp b/src/TembooMonitoring.cpp new file mode 100644 index 0000000..247d2a9 --- /dev/null +++ b/src/TembooMonitoring.cpp @@ -0,0 +1,334 @@ +/* +############################################################################### +# +# Temboo Arduino library +# +# Copyright 2016, Temboo Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +# +############################################################################### +*/ + + +#include +#include +#include "utility/TembooGlobal.h" +#include "TembooMonitoring.h" + +const int MAX_MAILBOX_MESSAGE_SIZE = 128; + +const unsigned long POLL_TIMEOUT = 50; +const unsigned long INITIATE_TIMEOUT_MS = 5000; +const unsigned long MCU_PING_PERIOD_MS = 5000; + +void logTembooDebug(const char *c) { + Console.print("Debug: "); + Console.println(c); +} + +void addWebSocketPinData(int pin, int pinVal, bool requestResponse) { + TembooMessaging::sendData(pin, pinVal, requestResponse); +} + +void updateIntervalTime(int intervalTime) { + uint8_t msg[MAX_MAILBOX_MESSAGE_SIZE] = {0}; + int messageSize = snprintf((char*)msg, MAX_MAILBOX_MESSAGE_SIZE, "Mi|V%i", intervalTime); + Mailbox.writeMessage(msg, messageSize); +} + +static void tembooDigitalWrite(uint32_t pin, int val) { + digitalWrite(pin, val); +} + +uint32_t tembooDigitalRead(uint32_t pin) { + return digitalRead(pin); +} + +static void tembooAnalogWrite(uint32_t pin, int val) { + analogWrite(pin, val); +} + +uint32_t tembooAnalogRead(uint32_t pin) { + return analogRead(pin); +} + +TembooMessaging::TembooMessaging(TembooPinTable* pinTable, int pinTableSize) { + m_accountName = NULL; + m_appKey = NULL; + m_appKeyName = NULL; + m_deviceID = NULL; + m_connectionStatus = false; + m_pinTable = pinTable; + m_pinTableSize = pinTableSize; + m_pinTableDepth = 0; + m_connectionAttemptTime = millis(); + m_lastPingTime = millis(); + // init array + int i = 0; + for (i = 0; i < m_pinTableSize; i++) { + m_pinTable[i].pin = -1; + m_pinTable[i].pinRead = NULL; + m_pinTable[i].pinWrite = NULL; + } +} + +void TembooMessaging::startMessaging() { + if (!running()) { + TEMBOO_TRACELN("starting messanger"); + m_connectionStatus = false; + Process::begin("tembooMessaging"); + runAsynchronously(); + } +} + +void TembooMessaging::setPinsToDefaultState() { + int i = 0; + for (; i < m_pinTableDepth; i++) { + if (m_pinTable[i].pinWrite != NULL) { + m_pinTable[i].pinWrite(m_pinTable[i].pin, m_pinTable[i].defaultValue); + m_pinTable[i].currentPinValue = m_pinTable[i].defaultValue; + } + } +} + +void TembooMessaging::addPinConfig(int pin, const char* type, int mode, int defaultValue) { + // check if there is room to add new pin information + if (m_pinTableDepth == m_pinTableSize) { + return; + } + bool success = true; + // check if pin has already been added, if it has + // edit the config/mode, else, add to config + int i = 0; + for (; i < m_pinTableDepth; i++) { + if (m_pinTable[i].pin == pin) { + break; + } + } + if (mode == INPUT) { + if (!strcasecmp(type, "analog")) { + pinMode(pin, INPUT); + m_pinTable[i].pinRead = tembooAnalogRead; + m_pinTable[i].pinWrite = NULL; + m_pinTable[i].pin = pin; + m_pinTable[i].currentPinValue = tembooAnalogRead(pin); + m_pinTable[i].defaultValue = defaultValue; + } else if (!strcasecmp(type, "digital")) { + pinMode(pin, INPUT); + m_pinTable[i].pinRead = tembooDigitalRead; + m_pinTable[i].pinWrite = NULL; + m_pinTable[i].pin = pin; + m_pinTable[i].currentPinValue = tembooDigitalRead(pin); + m_pinTable[i].defaultValue = defaultValue; + } else { + success = false; + } + } else if (mode == OUTPUT) { + if (!strcasecmp(type, "analog")) { + pinMode(pin, OUTPUT); + m_pinTable[i].pinRead = NULL; + m_pinTable[i].pinWrite = tembooAnalogWrite; + m_pinTable[i].pin = pin; + m_pinTable[i].currentPinValue = defaultValue; + m_pinTable[i].defaultValue = defaultValue; + tembooAnalogWrite(pin, defaultValue); + } else if (!strcasecmp(type, "digital")) { + pinMode(pin, OUTPUT); + m_pinTable[i].pinRead = NULL; + m_pinTable[i].pinWrite = tembooDigitalWrite; + m_pinTable[i].pin = pin; + m_pinTable[i].currentPinValue = defaultValue; + m_pinTable[i].defaultValue = defaultValue; + tembooDigitalWrite(pin, defaultValue); + } else { + success = false; + } + } else { + success = false; + } + if (success) { + if (i >= m_pinTableDepth) { + // if we needed to add a new pin, increment depth + m_pinTableDepth++; + } + } +} + +void TembooMessaging::begin() { + Mailbox.begin(); + startMessaging(); +} + +void TembooMessaging::setAccountName(const String& accountName) { + m_accountName = accountName.c_str(); +} +void TembooMessaging::setAccountName(const char* accountName) { + m_accountName = accountName; +} + +void TembooMessaging::setAppKeyName(const String& appKeyName) { + m_appKeyName = appKeyName.c_str(); +} +void TembooMessaging::setAppKeyName(const char* appKeyName) { + m_appKeyName = appKeyName; +} + +void TembooMessaging::setAppKey(const String& appKey) { + m_appKey = appKey.c_str(); +} +void TembooMessaging::setAppKey(const char* appKey) { + m_appKey = appKey; +} + +void TembooMessaging::setDeviceID(const String& deviceID) { + m_deviceID = deviceID.c_str(); +} +void TembooMessaging::setDeviceID(const char* deviceID) { + m_deviceID = deviceID; +} + +void TembooMessaging::initiateConnection() { + unsigned long now = millis(); + if (now - m_connectionAttemptTime < INITIATE_TIMEOUT_MS) { + poll(); + return; + } + if (m_accountName == NULL || *m_accountName == '\0') { + logTembooDebug("Account name invalid or not set"); + return; + } + if (m_appKeyName == NULL || *m_appKeyName == '\0') { + logTembooDebug("Appkey name invalid or not set"); + return; + } + if (m_deviceID == NULL || *m_deviceID == '\0') { + logTembooDebug("DeviceID invalid or not set"); + return; + } + if (m_appKey == NULL || *m_appKey == '\0') { + logTembooDebug("Appkey invalid or not set"); + return; + } + startMessaging(); + int messageSize = strlen(m_accountName) + strlen(m_appKey) + strlen(m_appKeyName) + strlen(m_deviceID) + 11; + uint8_t msg[messageSize]; + if (messageSize < MAX_MAILBOX_MESSAGE_SIZE) { + Console.println("Attempting to connect to Temboo"); + messageSize = snprintf((char*)msg, messageSize, "MI|N%s|K%s|B%s|A%s", m_accountName, m_appKeyName, m_deviceID, m_appKey); + Mailbox.writeMessage(msg, messageSize); + m_connectionAttemptTime = now; + } else { + logTembooDebug("Initiation request too large"); + return; + } +} + +WSMessageRequest TembooMessaging::poll() { + startMessaging(); + long int now = millis(); + WSMessageRequest rc = WS_NO_MESSAGE; + while (millis() - now < POLL_TIMEOUT) { + if (millis() - m_lastPingTime >= MCU_PING_PERIOD_MS) { + m_lastPingTime = millis(); + sendPing(); + } + if (Mailbox.messageAvailable()) { + uint8_t msg[MAX_MAILBOX_MESSAGE_SIZE] = {0}; + int recvLen = Mailbox.readMessage(msg, MAX_MAILBOX_MESSAGE_SIZE); + if (recvLen > 0) { + rc = handleResponse(msg, m_pinTable, m_pinTableDepth, m_connectionStatus); + if (rc == WS_UPDATE_CONNECTED) { + logTembooDebug("Connected to Temboo"); + m_connectionStatus = true; + } else if (rc == WS_UPDATE_DISCONNECTED) { + logTembooDebug("Disconnected from Temboo"); + m_connectionStatus = false; + } else if (rc == WS_REQUEST_ERROR) { + // disconnect + sendError("Message request error"); + } + } + } + } + return rc; +} + +void TembooMessaging::updatePinValue(int pinNum, int pinVal) { + // save the data to the strcuture and then send to Temboo + int i = 0; + for (; i < m_pinTableDepth; i++) { + if (m_pinTable[i].pin == pinNum) { + m_pinTable[i].currentPinValue = pinVal; + // if pin has pinWrite as NULL, it is an input + // pin and needs to be stored. If not NULL, + // pin is an actuator and should not be stored + if(m_pinTable[i].pinWrite == NULL){ + sendData(pinNum, pinVal, false); + } else { + sendData(pinNum, pinVal, true); + } + return; + } + } + logTembooDebug("Pin not found, unable to update"); +} + +int TembooMessaging::retrievePinValue(int pinNum) { + // search through pin structure and return the pin value + int i = 0; + for (; i < m_pinTableDepth; i++) { + if (m_pinTable[i].pin == pinNum) { + return m_pinTable[i].currentPinValue; + } + } + logTembooDebug("Pin not found, unable to obtain value"); + return 0; +} + +void TembooMessaging::sendError(const char* errorText) { + uint8_t msg[MAX_MAILBOX_MESSAGE_SIZE] = {0}; + int messageSize = snprintf((char*)msg, MAX_MAILBOX_MESSAGE_SIZE, "ME|T%s", errorText); + Mailbox.writeMessage(msg, messageSize); +} + +void TembooMessaging::disconnectWSConnection(int closeCode, const char* closeReason) { + int messageSize = strlen(closeReason) + 11; + uint8_t msg[messageSize]; + messageSize = snprintf((char*)msg, messageSize, "MF|O%i|r%s", closeCode, closeReason); + Mailbox.writeMessage(msg, messageSize); +} + +void TembooMessaging::sendData(int pin, int pinVal, bool requestResponse) { + uint8_t msg[MAX_MAILBOX_MESSAGE_SIZE] = {0}; + int messageSize = snprintf((char*)msg, MAX_MAILBOX_MESSAGE_SIZE, "MD|P%i|V%i%s", pin, pinVal, requestResponse ? "|Q" : ""); + Mailbox.writeMessage(msg, messageSize); +} +void TembooMessaging::sendData(int pin, float pinVal) { + uint8_t msg[MAX_MAILBOX_MESSAGE_SIZE] = {0}; + char floatStr[12] = {0}; + dtostrf(pinVal, 4, 2, floatStr); + int messageSize = snprintf((char*)msg, MAX_MAILBOX_MESSAGE_SIZE, "MD|P%i|V%s", pin, floatStr); + Mailbox.writeMessage(msg, messageSize); +} + +bool TembooMessaging::isConnected() { + if (running()) { + return m_connectionStatus; + } + return false; +} + +void TembooMessaging::sendPing() { + Mailbox.writeMessage((uint8_t*)"P",1); +} diff --git a/src/TembooMonitoring.h b/src/TembooMonitoring.h new file mode 100644 index 0000000..1cdc461 --- /dev/null +++ b/src/TembooMonitoring.h @@ -0,0 +1,82 @@ +/* +############################################################################### +# +# Temboo Arduino library +# +# Copyright 2016, Temboo Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +# +############################################################################### +*/ + +#ifndef TEMBOOMESSAGING_H_ +#define TEMBOOMESSAGING_H_ + +#include +#include + +#include "utility/TembooWebSocketRequestHandles.h" + +class TembooMessaging : public Process { + +public: + TembooMessaging(TembooPinTable* pinTable, int pinTableSize); + void begin(); + + void setAccountName(const String& accountName); + void setAccountName(const char* accountName); + + void setAppKeyName(const String& appKeyName); + void setAppKeyName(const char* appKeyName); + + void setAppKey(const String& appKey); + void setAppKey(const char* appKey); + + void setDeviceID(const String& appKey); + void setDeviceID(const char* appKey); + + void addPinConfig(int pin, const char* type, int mode, int defaultValue); + + void initiateConnection(); + + WSMessageRequest poll(); + + static void sendData(int pin, int pinVal, bool requestResponse=false); + void sendData(int pin, float pinVal); + void updatePinValue(int pinNum, int pinVal); + int retrievePinValue(int pinNum); + void setPinsToDefaultState(); + + bool isConnected(); + +private: + const char* m_accountName; + const char* m_appKey; + const char* m_appKeyName; + const char* m_deviceID; + bool m_connectionStatus; + int m_pinTableSize; + int m_pinTableDepth; + long int m_connectionAttemptTime; + TembooPinTable* m_pinTable; + unsigned long m_lastPingTime; + + void startMessaging(); + void disconnectWSConnection(int closeCode, const char* closeReason); + void sendError(const char* errorText); + void sendPing(); + +}; + +#endif \ No newline at end of file diff --git a/src/TembooYunShield.h b/src/TembooYunShield.h index c297efb..ff00dbe 100644 --- a/src/TembooYunShield.h +++ b/src/TembooYunShield.h @@ -47,7 +47,12 @@ class TembooYunShieldChoreo : public Process { void setSettingsFileToWrite(const String& filePath) { addParameter("-w" + filePath);} void setSettingsFileToRead(const String& filePath) { addParameter("-r" + filePath);} void setGatewayAddress(const String& addr) { addParameter("-s" + addr);} - + void addInputExpression(const String& inputName, const String& inputValue) { addParameter("-f" + inputName + ":" + inputValue);} + void addSensorInput(const String& sensorName, long sensorValue, const String& conversion) {addParameter("-n" + sensorName + ":" + String(sensorValue) + ":" + conversion);} + void addSensorInput(const String& sensorName, long sensorValue) {addParameter("-v" + sensorName + ":" + String(sensorValue));} + void addSensorInput(const String& sensorName, long sensorValue, const String& rawLow, const String& rawHigh, const String& scaleLow, const String& scaleHigh) {addParameter("-m" + sensorName + ":" + String(sensorValue) + ":" + rawLow+ ":" + rawHigh+ ":" + scaleLow+ ":" + scaleHigh);} + void setDeviceName(const String& deviceName) {addParameter("-d" + deviceName);} + void setDeviceType(const String& deviceType) {addParameter("-t" + deviceType);} }; diff --git a/src/utility/TembooWebSocketRequestHandles.c b/src/utility/TembooWebSocketRequestHandles.c new file mode 100644 index 0000000..113c6c9 --- /dev/null +++ b/src/utility/TembooWebSocketRequestHandles.c @@ -0,0 +1,209 @@ +/* +############################################################################### +# +# Temboo library +# +# Copyright 2016, Temboo Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +# +############################################################################### +*/ + +#include + +#include "TembooWebSocketRequestHandles.h" +#include "TembooGlobal.h" + +static WSMessageRequest handleMessageRequest(char** saveptr); +static WSMessageRequest handleIntervalRequest(char** saveptr); +static WSMessageRequest handleSetRequest(char** saveptr, TembooPinTable* pinTable, int pinTableDepth); +static WSMessageRequest handleGetRequest(char** saveptr, TembooPinTable* pinTable, int pinTableDepth); +static WSMessageRequest handleMonitoringUpdateRequest(char**saveptr); + +static const uint16_t WS_MAX_PAYLOAD_SIZE = 126; + + + +WSMessageRequest handleGetRequest(char** saveptr, TembooPinTable* pinTable, int pinTableDepth) { + char* textField = strtok_r(NULL, "|", &(*saveptr)); + int pinNum = -1; + int pinVal = -1; + WSMessageRequest rc = WS_REQUEST_ERROR; + // strlen should catch the + sign + while (textField != NULL && strlen(textField) >= 2) { + if (*textField == 'P') { + if (isdigit(textField[1]) && strlen(&textField[1]) < 4) { + pinNum = atoi(&textField[1]); + } + } else if (*textField == '+') { + break; + } + textField = strtok_r(NULL, "|", &(*saveptr)); + } + + if (pinNum >= 0) { + //obtain the data and send to Temboo + int i = 0; + for (i = 0; i < pinTableDepth; i++) { + if (pinTable[i].pin == pinNum) { + if (pinTable[i].pinRead != NULL) { + // input pin + pinVal = pinTable[i].pinRead(pinNum); + } else { + // output pin/actuator, use saved value + pinVal = pinTable[i].currentPinValue; + } + rc = WS_GET_REQUEST; + break; + } + } + } + if (rc != WS_REQUEST_ERROR) { + // Send pinVal + addWebSocketPinData(pinNum, pinVal, true); + } + return rc; +} + +WSMessageRequest handleSetRequest(char** saveptr, TembooPinTable* pinTable, int pinTableDepth) { + int pinNum = -1; + int pinVal = -1; + bool pinValSet = false; + WSMessageRequest rc = WS_REQUEST_ERROR; + char* textField = strtok_r(NULL, "|", &(*saveptr)); + while (textField != NULL && strlen(textField) >= 2) { + if (*textField == 'P') { + if (isdigit(textField[1]) && strlen(&textField[1]) < 4) { + pinNum = atoi(&textField[1]); + } + } else if (*textField == 'V') { + if (isdigit(textField[1]) && strlen(&textField[1]) < 7) { + pinVal = atoi(&textField[1]); + pinValSet = true; + } + + } else if (*textField == '+') { + break; + } + textField = strtok_r(NULL, "|", &(*saveptr)); + } + + if (pinNum >= 0 && pinValSet) { + int i = 0; + for (; i < pinTableDepth; i++) { + if (pinTable[i].pin == pinNum) { + if (pinTable[i].pinWrite != NULL) { + pinTable[i].currentPinValue = pinVal; + pinTable[i].pinWrite(pinNum, pinVal); + rc = WS_SET_REQUEST; + } + break; + } + } + } + if (rc != WS_REQUEST_ERROR) { + // with pinval found, send the data to Temboo + addWebSocketPinData(pinNum, pinVal, true); + } + return rc; +} + +WSMessageRequest handleMessageRequest(char** saveptr) { + char* textField = strtok_r(NULL, "|", &(*saveptr)); + WSMessageRequest rc = WS_REQUEST_ERROR; + if (textField != NULL && strlen(textField) >= 2) { + if (*textField == 'T') { + logTembooDebug(&textField[1]); + rc = WS_MESSAGE_REQUEST; + } + } + return rc; +} + +WSMessageRequest handleMonitoringUpdateRequest(char** saveptr) { + char* textField = strtok_r(NULL, "|", &(*saveptr)); + WSMessageRequest rc = WS_REQUEST_ERROR; + if (textField != NULL && strlen(textField) >= 2) { + if (*textField == 'T') { + if (!strcmp(&textField[1], "true")) { + rc = WS_UPDATE_CONNECTED; + } else if (!strcmp(&textField[1], "false")) { + rc = WS_UPDATE_DISCONNECTED; + } else { + rc = WS_REQUEST_ERROR; + } + } + } + return rc; +} + +WSMessageRequest handleIntervalRequest(char** saveptr) { + char* textField = strtok_r(NULL, "|", &(*saveptr)); + WSMessageRequest rc = WS_REQUEST_ERROR; + if (textField != NULL && strlen(textField) >= 2) { + if (*textField == 'V') { + if (isdigit(textField[1]) && strlen(&textField[1]) < 6) { + updateIntervalTime(atoi(&textField[1])); + rc = WS_INTERVAL_REQUEST; + } + } + } + return rc; +} + +WSMessageRequest handleResponse(uint8_t* request, TembooPinTable* pinTable, int pinTableDepth, bool connectionStatus) { + // parse response to find request type + char* saveptr = NULL; + char* requestField = strtok_r((char*)request, "|", &saveptr); + WSMessageRequest rc = WS_REQUEST_ERROR; + while (requestField != NULL) { + if (*requestField == 'M') { + switch (requestField[1]) { + // only read web socket messages if device is connected + // to the web socket + case 'G': + // send pin data to Temboo + if (connectionStatus) { + rc = handleGetRequest(&saveptr, pinTable, pinTableDepth); + } + break; + case 'S': + // change state of a pin + if (connectionStatus) { + rc = handleSetRequest(&saveptr, pinTable, pinTableDepth); + } + break; + case 'E': + // print message + rc = handleMessageRequest(&saveptr); + break; + case 'U': + rc = handleMonitoringUpdateRequest(&saveptr); + break; + case 'I': + rc = handleIntervalRequest(&saveptr); + break; + default: + // return error + rc = WS_REQUEST_ERROR; + break; + } + } + if (rc == WS_REQUEST_ERROR) { + break; + } + requestField = strtok_r(NULL, "|", &saveptr); + } + return rc; +} diff --git a/src/utility/TembooWebSocketRequestHandles.h b/src/utility/TembooWebSocketRequestHandles.h new file mode 100644 index 0000000..0223f5f --- /dev/null +++ b/src/utility/TembooWebSocketRequestHandles.h @@ -0,0 +1,66 @@ +/* +############################################################################### +# +# Temboo Arduino library +# +# Copyright 2016, Temboo Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +# +############################################################################### +*/ + +#ifndef __TembooWebSocketRequestHandles__ +#define __TembooWebSocketRequestHandles__ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef enum { + WS_GET_REQUEST = 0, + WS_SET_REQUEST, + WS_DATA_REQUEST, + WS_MESSAGE_REQUEST, + WS_RR_REQUEST, + WS_SESSION_ID_REQUEST, + WS_REQUEST_ERROR, + WS_UPDATE_CONNECTED, + WS_UPDATE_DISCONNECTED, + WS_NO_MESSAGE, + WS_INTERVAL_REQUEST +} WSMessageRequest; + +typedef struct TembooPinTable { + uint8_t pin; + uint32_t (*pinRead)(uint32_t pin); + void (*pinWrite)(uint32_t pin, int val); + int currentPinValue; + int defaultValue; +} TembooPinTable; + +void addWebSocketPinData(int pin, int pinVal, bool requestResponse); +void updateIntervalTime(int intervalTime); + +// Send frame +WSMessageRequest handleResponse(uint8_t* request, TembooPinTable* pinTable, int pinTableDepth, bool connectionStatus); +void logTembooDebug(const char *c); +#if defined(__cplusplus) +} +#endif + + + +#endif /* defined(__TembooWebSocketRequestHandles__) */