mirror of https://github.com/noisymime/Arduino.git
Merge pull request #2215 from temboo/ide-1.5.x-temboo
Updated Temboo library
This commit is contained in:
commit
378fa904c5
|
@ -0,0 +1,31 @@
|
|||
Temboo Library for Arduino
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
For installation instructions, please visit:
|
||||
|
||||
http://temboo.com/arduino/others/library-installation
|
||||
|
||||
Examples, Tutorials & More
|
||||
--------------------------
|
||||
|
||||
You can find lots of examples, tutorials and info about Device Coder (Temboo's tool for automatically generating internet-connected sketch code) at the link below:
|
||||
|
||||
http://temboo.com/arduino/
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
This library has been tested with the following Arduino boards:
|
||||
|
||||
* TRE
|
||||
* Yún
|
||||
* Due
|
||||
* Mega
|
||||
* Uno
|
||||
|
||||
And the following internet shields:
|
||||
|
||||
* Arduino Wifi Shield
|
||||
* Arduino Ethernet Shield
|
|
@ -24,6 +24,7 @@ setAppKeyName KEYWORD2
|
|||
setAppKey KEYWORD2
|
||||
setChoreo KEYWORD2
|
||||
setCredential KEYWORD2
|
||||
setSavedInputs KEYWORD2
|
||||
addInput KEYWORD2
|
||||
addOutputFilter KEYWORD2
|
||||
setSettingsFileToWrite KEYWORD2
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
name=Temboo
|
||||
author=Temboo
|
||||
email=support@temboo.com
|
||||
sentence=Allows any Arduino with Internet access to connect to web-based resources and services APIs.
|
||||
paragraph=Temboo is a platform that provides normalized access to 100+ APIs, databases, code utilities and more. This library enables the Yún to connect to Temboo, making it simple to interact with a vast array of web-based resources and services.
|
||||
url=http://www.temboo.com
|
||||
architectures=avr
|
||||
version=1.0
|
||||
dependencies=
|
||||
core-dependencies=arduino (>=1.5.0)
|
||||
sentence=This library enables calls to Temboo, a platform that connects Arduino boards to 100+ APIs, databases, code utilities and more.
|
||||
paragraph=Use this library to connect your Arduino board to Temboo, making it simple to interact with a vast array of web-based resources and services.
|
||||
url=http://www.temboo.com/arduino
|
||||
architectures=*
|
||||
version=1.1
|
||||
core-dependencies=arduino (>=1.5.0)
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino Yún library
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2013, Temboo Inc.
|
||||
# Copyright 2014, Temboo Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -20,6 +20,13 @@
|
|||
###############################################################################
|
||||
*/
|
||||
|
||||
|
||||
#if defined (ARDUINO_AVR_YUN) || defined (ARDUINO_AVR_TRE)
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// BEGIN ARDUINO YUN AND TRE SUPPORT
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
#include <Temboo.h>
|
||||
|
||||
void TembooChoreo::begin() {
|
||||
|
@ -46,6 +53,14 @@ void TembooChoreo::setCredential(const String& credentialName) {
|
|||
addParameter("-e" + credentialName);
|
||||
}
|
||||
|
||||
void TembooChoreo::setSavedInputs(const String& savedInputsName) {
|
||||
addParameter("-e" + savedInputsName);
|
||||
}
|
||||
|
||||
void TembooChoreo::setProfile(const String& profileName) {
|
||||
addParameter("-e" + profileName);
|
||||
}
|
||||
|
||||
void TembooChoreo::addInput(const String& inputName, const String& inputValue) {
|
||||
addParameter("-i" + inputName + ":" + inputValue);
|
||||
}
|
||||
|
@ -62,3 +77,319 @@ void TembooChoreo::setSettingsFileToRead(const String& filePath) {
|
|||
addParameter("-r" + filePath);
|
||||
}
|
||||
|
||||
|
||||
#else //ARDUINO_AVR_YUN
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// BEGIN ARDUINO NON-YUN SUPPORT
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
#include <string.h>
|
||||
#include <Client.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <Temboo.h>
|
||||
#include "utility/TembooGlobal.h"
|
||||
#include "utility/TembooSession.h"
|
||||
|
||||
static const char HTTP_CODE[] PROGMEM = "HTTP_CODE\x0A\x1F";
|
||||
|
||||
TembooChoreo::TembooChoreo(Client& client) : m_client(client) {
|
||||
m_accountName = NULL;
|
||||
m_appKeyName = NULL;
|
||||
m_appKeyValue = NULL;
|
||||
m_path = NULL;
|
||||
m_nextChar = NULL;
|
||||
m_nextState = END;
|
||||
}
|
||||
|
||||
void TembooChoreo::setAccountName(const String& accountName) {
|
||||
m_accountName = accountName.c_str();
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setAccountName(const char* accountName) {
|
||||
m_accountName = accountName;
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setAppKeyName(const String& appKeyName) {
|
||||
m_appKeyName = appKeyName.c_str();
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setAppKeyName(const char* appKeyName) {
|
||||
m_appKeyName = appKeyName;
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setAppKey(const String& appKeyValue) {
|
||||
m_appKeyValue = appKeyValue.c_str();
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setAppKey(const char* appKeyValue) {
|
||||
m_appKeyValue = appKeyValue;
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setChoreo(const String& path) {
|
||||
m_path = path.c_str();
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setChoreo(const char* path) {
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setSavedInputs(const String& savedInputsName) {
|
||||
m_preset.put(savedInputsName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setSavedInputs(const char* savedInputsName) {
|
||||
m_preset.put(savedInputsName);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setCredential(const String& credentialName) {
|
||||
m_preset.put(credentialName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setCredential(const char* credentialName) {
|
||||
m_preset.put(credentialName);
|
||||
}
|
||||
|
||||
void TembooChoreo::setProfile(const String& profileName) {
|
||||
m_preset.put(profileName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::setProfile(const char* profileName) {
|
||||
m_preset.put(profileName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TembooChoreo::addInput(const String& inputName, const String& inputValue) {
|
||||
m_inputs.put(inputName.c_str(), inputValue.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addInput(const char* inputName, const char* inputValue) {
|
||||
m_inputs.put(inputName, inputValue);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addInput(const char* inputName, const String& inputValue) {
|
||||
m_inputs.put(inputName, inputValue.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addInput(const String& inputName, const char* inputValue) {
|
||||
m_inputs.put(inputName.c_str(), inputValue);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const char* outputName, const char* filterPath, const char* variableName) {
|
||||
m_outputs.put(outputName, filterPath, variableName);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const String& outputName, const char* filterPath, const char* variableName) {
|
||||
m_outputs.put(outputName.c_str(), filterPath, variableName);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const char* outputName, const String& filterPath, const char* variableName) {
|
||||
m_outputs.put(outputName, filterPath.c_str(), variableName);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const String& outputName, const String& filterPath, const char* variableName) {
|
||||
m_outputs.put(outputName.c_str(), filterPath.c_str(), variableName);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const char* outputName, const char* filterPath, const String& variableName) {
|
||||
m_outputs.put(outputName, filterPath, variableName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const String& outputName, const char* filterPath, const String& variableName) {
|
||||
m_outputs.put(outputName.c_str(), filterPath, variableName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const char* outputName, const String& filterPath, const String& variableName) {
|
||||
m_outputs.put(outputName, filterPath.c_str(), variableName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::addOutputFilter(const String& outputName, const String& filterPath, const String& variableName) {
|
||||
m_outputs.put(outputName.c_str(), filterPath.c_str(), variableName.c_str());
|
||||
}
|
||||
|
||||
|
||||
int TembooChoreo::run() {
|
||||
return run(INADDR_NONE, 80);
|
||||
}
|
||||
|
||||
|
||||
int TembooChoreo::run(IPAddress addr, uint16_t port) {
|
||||
|
||||
m_nextChar = NULL;
|
||||
|
||||
if (m_accountName == NULL || *m_accountName == '\0') {
|
||||
return TEMBOO_ERROR_ACCOUNT_MISSING;
|
||||
}
|
||||
|
||||
if (m_path == NULL || *m_path == '\0') {
|
||||
return TEMBOO_ERROR_CHOREO_MISSING;
|
||||
}
|
||||
|
||||
if (m_appKeyName == NULL || *m_appKeyName == '\0') {
|
||||
return TEMBOO_ERROR_APPKEY_NAME_MISSING;
|
||||
}
|
||||
|
||||
if (m_appKeyValue == NULL || *m_appKeyValue == '\0') {
|
||||
return TEMBOO_ERROR_APPKEY_MISSING;
|
||||
}
|
||||
|
||||
|
||||
TembooSession session(m_client, addr, port);
|
||||
uint16_t httpCode = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (0 != session.executeChoreo(m_accountName, m_appKeyName, m_appKeyValue, m_path, m_inputs, m_outputs, m_preset)) {
|
||||
httpCode = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
while(!m_client.available()) {
|
||||
if (!m_client.connected()) {
|
||||
TEMBOO_TRACELN("Disconnected");
|
||||
return TEMBOO_ERROR_HTTP_ERROR;
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
|
||||
if (!m_client.find("HTTP/1.1 ")) {
|
||||
TEMBOO_TRACELN("No HTTP");
|
||||
return TEMBOO_ERROR_HTTP_ERROR;
|
||||
}
|
||||
|
||||
httpCode = (uint16_t)m_client.parseInt();
|
||||
|
||||
// We expect HTTP response codes to be <= 599, but
|
||||
// we need to be prepared for anything.
|
||||
if (httpCode >= 600) {
|
||||
TEMBOO_TRACELN("Invalid HTTP");
|
||||
httpCode = 0;
|
||||
}
|
||||
|
||||
// if we get an auth error AND there was an x-temboo-time header,
|
||||
// update the session timeOffset
|
||||
if ((httpCode == 401) && (i == 0)) {
|
||||
if (m_client.find("x-temboo-time:")) {
|
||||
TembooSession::setTime((unsigned long)m_client.parseInt());
|
||||
while(m_client.available()) {
|
||||
m_client.read();
|
||||
}
|
||||
m_client.stop();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16toa(httpCode, m_httpCodeStr);
|
||||
strcat_P(m_httpCodeStr, PSTR("\x0A\x1E"));
|
||||
m_nextState = START;
|
||||
m_nextChar = HTTP_CODE;
|
||||
|
||||
if (httpCode < 200 || httpCode >= 300) {
|
||||
return TEMBOO_ERROR_HTTP_ERROR;
|
||||
}
|
||||
|
||||
if (!m_client.find("\x0D\x0A\x0D\x0A")) {
|
||||
return TEMBOO_ERROR_HTTP_ERROR;
|
||||
}
|
||||
|
||||
return TEMBOO_ERROR_OK;
|
||||
}
|
||||
|
||||
void TembooChoreo::close() {
|
||||
m_client.stop();
|
||||
}
|
||||
|
||||
int TembooChoreo::available() {
|
||||
// If we're still sending the HTTP response code,
|
||||
// report at least one character available.
|
||||
if (m_nextChar != NULL) {
|
||||
return m_client.available() + 1;
|
||||
}
|
||||
|
||||
// Otherwise, return however many characters the client has.
|
||||
return m_client.available();
|
||||
}
|
||||
|
||||
|
||||
int TembooChoreo::peek() {
|
||||
// If we're still sending the HTTP response code,
|
||||
// return the next character in that sequence.
|
||||
if (m_nextChar != NULL) {
|
||||
return (int)*m_nextChar;
|
||||
}
|
||||
|
||||
// Otherwise, return whatever is in the client buffer.
|
||||
return m_client.peek();
|
||||
}
|
||||
|
||||
|
||||
int TembooChoreo::read() {
|
||||
|
||||
int c = 0;
|
||||
switch(m_nextState) {
|
||||
case START:
|
||||
m_nextChar = HTTP_CODE;
|
||||
c = (int)pgm_read_byte(m_nextChar++);
|
||||
m_nextState = HTTP_CODE_TAG;
|
||||
break;
|
||||
|
||||
case HTTP_CODE_TAG:
|
||||
c = (int)pgm_read_byte(m_nextChar++);
|
||||
if (pgm_read_byte(m_nextChar) == '\0') {
|
||||
m_nextState = HTTP_CODE_VALUE;
|
||||
m_nextChar = m_httpCodeStr;
|
||||
}
|
||||
break;
|
||||
|
||||
case HTTP_CODE_VALUE:
|
||||
c = (int)(*m_nextChar++);
|
||||
if (*m_nextChar == '\0') {
|
||||
m_nextState = END;
|
||||
m_nextChar = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
c = m_client.read();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
size_t TembooChoreo::write(uint8_t data) {
|
||||
return m_client.write(data);
|
||||
}
|
||||
|
||||
|
||||
void TembooChoreo::flush() {
|
||||
m_nextChar = NULL;
|
||||
m_nextState = END;
|
||||
m_client.flush();
|
||||
}
|
||||
|
||||
#endif //ARDUINO_AVR_YUN
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino Yún library
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2013, Temboo Inc.
|
||||
# Copyright 2014, Temboo Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -20,9 +20,16 @@
|
|||
###############################################################################
|
||||
*/
|
||||
|
||||
#ifndef _TEMBOO_H
|
||||
#define _TEMBOO_H
|
||||
#ifndef TEMBOO_H_
|
||||
#define TEMBOO_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined (ARDUINO_AVR_YUN) || defined (ARDUINO_AVR_TRE)
|
||||
///////////////////////////////////////////////////////
|
||||
// BEGIN ARDUINO YUN AND TRE SUPPORT
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
#include <Process.h>
|
||||
|
||||
class TembooChoreo : public Process {
|
||||
|
@ -34,6 +41,8 @@ class TembooChoreo : public Process {
|
|||
void setAppKey(const String& appKey);
|
||||
void setChoreo(const String& choreo);
|
||||
void setCredential(const String& credentialName);
|
||||
void setSavedInputs(const String& saveInputsName);
|
||||
void setProfile(const String& profileName);
|
||||
void addInput(const String& inputName, const String& inputValue);
|
||||
void addOutputFilter(const String& filterName, const String& filterPath, const String& variableName);
|
||||
void setSettingsFileToWrite(const String& filePath);
|
||||
|
@ -41,4 +50,122 @@ class TembooChoreo : public Process {
|
|||
|
||||
};
|
||||
|
||||
#endif
|
||||
#else //ARDUINO_AVR_YUN
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// BEGIN ARDUINO NON-YUN SUPPORT
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
#include <Stream.h>
|
||||
#include <Client.h>
|
||||
#include <IPAddress.h>
|
||||
#include "utility/ChoreoInputSet.h"
|
||||
#include "utility/ChoreoOutputSet.h"
|
||||
#include "utility/ChoreoPreset.h"
|
||||
|
||||
#define TEMBOO_ERROR_OK (0)
|
||||
#define TEMBOO_ERROR_ACCOUNT_MISSING (201)
|
||||
#define TEMBOO_ERROR_CHOREO_MISSING (203)
|
||||
#define TEMBOO_ERROR_APPKEY_NAME_MISSING (205)
|
||||
#define TEMBOO_ERROR_APPKEY_MISSING (207)
|
||||
#define TEMBOO_ERROR_HTTP_ERROR (223)
|
||||
|
||||
class TembooChoreo : public Stream {
|
||||
public:
|
||||
|
||||
// Constructor.
|
||||
// client - an instance of an Arduino Client, usually an EthernetClient
|
||||
// or a WiFiClient. Used to communicate with Temboo.
|
||||
TembooChoreo(Client& client);
|
||||
|
||||
// Does nothing. Just for source compatibility with Yun code.
|
||||
void begin() {};
|
||||
|
||||
// Sets the account name to use when communicating with Temboo.
|
||||
// (required)
|
||||
void setAccountName(const String& accountName);
|
||||
void setAccountName(const char* accountName);
|
||||
|
||||
// Sets the application key name to use with choreo execution requests.
|
||||
// (required)
|
||||
void setAppKeyName(const String& appKeyName);
|
||||
void setAppKeyName(const char* appKeyName);
|
||||
|
||||
// Sets the application key value to use with choreo execution requests
|
||||
// (required)
|
||||
void setAppKey(const String& appKey);
|
||||
void setAppKey(const char* appKey);
|
||||
|
||||
// sets the name of the choreo to be executed.
|
||||
// (required)
|
||||
void setChoreo(const String& choreoPath);
|
||||
void setChoreo(const char* choreoPath);
|
||||
|
||||
// sets the name of the saved inputs to use when executing the choreo
|
||||
// (optional)
|
||||
void setSavedInputs(const String& savedInputsName);
|
||||
void setSavedInputs(const char* savedInputsName);
|
||||
|
||||
void setCredential(const String& credentialName);
|
||||
void setCredential(const char* credentialName);
|
||||
|
||||
void setProfile(const String& profileName);
|
||||
void setProfile(const char* profileName);
|
||||
|
||||
// sets an input to be used when executing a choreo.
|
||||
// (optional or required, depending on the choreo being executed.)
|
||||
void addInput(const String& inputName, const String& inputValue);
|
||||
void addInput(const char* inputName, const char* inputValue);
|
||||
void addInput(const char* inputName, const String& inputValue);
|
||||
void addInput(const String& inputName, const char* inputValue);
|
||||
|
||||
// sets an output filter to be used to process the choreo output
|
||||
// (optional)
|
||||
void addOutputFilter(const char* filterName, const char* filterPath, const char* variableName);
|
||||
void addOutputFilter(const String& filterName, const char* filterPath, const char* variableName);
|
||||
void addOutputFilter(const char* filterName, const String& filterPath, const char* variableName);
|
||||
void addOutputFilter(const String& filterName, const String& filterPath, const char* variableName);
|
||||
void addOutputFilter(const char* filterName, const char* filterPath, const String& variableName);
|
||||
void addOutputFilter(const String& filterName, const char* filterPath, const String& variableName);
|
||||
void addOutputFilter(const char* filterName, const String& filterPath, const String& variableName);
|
||||
void addOutputFilter(const String& filterName, const String& filterPath, const String& variableName);
|
||||
|
||||
// run the choreo using the current input info
|
||||
int run();
|
||||
|
||||
// run the choreo on the Temboo server at the given IP address and port
|
||||
// (used only when instructed by Temboo customer support.)
|
||||
int run(IPAddress addr, uint16_t port);
|
||||
|
||||
void close();
|
||||
|
||||
// Stream interface - see the Arduino library documentation.
|
||||
int available();
|
||||
int read();
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
//Print interface - see the Arduino library documentation
|
||||
size_t write(uint8_t data);
|
||||
|
||||
|
||||
protected:
|
||||
ChoreoInputSet m_inputs;
|
||||
ChoreoOutputSet m_outputs;
|
||||
ChoreoPreset m_preset;
|
||||
|
||||
const char* m_accountName;
|
||||
const char* m_appKeyValue;
|
||||
const char* m_appKeyName;
|
||||
const char* m_path;
|
||||
Client& m_client;
|
||||
char m_httpCodeStr[6];
|
||||
const char* m_nextChar;
|
||||
enum State {START, HTTP_CODE_TAG, HTTP_CODE_VALUE, END};
|
||||
State m_nextState;
|
||||
|
||||
};
|
||||
|
||||
#endif //ARDUINO_AVR_YUN
|
||||
|
||||
#endif //TEMBOO_H_
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 "BaseFormatter.h"
|
||||
|
||||
char BaseFormatter::escape(char c) {
|
||||
char outChar = c;
|
||||
switch(c) {
|
||||
case '\\':
|
||||
case '"':
|
||||
outChar = '\\';
|
||||
m_escapedChar = c;
|
||||
break;
|
||||
case '\b':
|
||||
outChar = '\\';
|
||||
m_escapedChar = 'b';
|
||||
break;
|
||||
case '\f':
|
||||
outChar = '\\';
|
||||
m_escapedChar = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
outChar = '\\';
|
||||
m_escapedChar = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
outChar = '\\';
|
||||
m_escapedChar = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
outChar = '\\';
|
||||
m_escapedChar = 't';
|
||||
break;
|
||||
default:
|
||||
m_escapedChar = '\0';
|
||||
}
|
||||
return outChar;
|
||||
}
|
||||
|
||||
char BaseFormatter::finishEscape() {
|
||||
char c = m_escapedChar;
|
||||
m_escapedChar = '\0';
|
||||
return c;
|
||||
}
|
||||
|
||||
char BaseFormatter::readTagChar(int nextState) {
|
||||
char c = pgm_read_byte(m_nextChar++);
|
||||
if (pgm_read_byte(m_nextChar) == '\0') {
|
||||
m_nextState = nextState;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
char BaseFormatter::readValueChar(int nextState) {
|
||||
char c;
|
||||
if (isEscaping()) {
|
||||
c = finishEscape();
|
||||
if (*m_nextChar == '\0') {
|
||||
m_nextState = nextState;
|
||||
}
|
||||
} else {
|
||||
c = escape(*m_nextChar++);
|
||||
if (!isEscaping()) {
|
||||
if(*m_nextChar == '\0') {
|
||||
m_nextState = nextState;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
char BaseFormatter::readStartTagChar(const char* tag, int nextState) {
|
||||
m_nextChar = tag;
|
||||
char c = pgm_read_byte(m_nextChar++);
|
||||
m_nextState = nextState;
|
||||
return c;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 BASEFORMATTER_H_
|
||||
#define BASEFORMATTER_H_
|
||||
#include "TembooGlobal.h"
|
||||
|
||||
class BaseFormatter {
|
||||
public:
|
||||
BaseFormatter() {m_escapedChar = '\0';}
|
||||
|
||||
protected:
|
||||
const char* m_nextChar;
|
||||
int m_nextState;
|
||||
char m_escapedChar;
|
||||
|
||||
char escape(char c);
|
||||
bool isEscaping() {return m_escapedChar != '\0';}
|
||||
char finishEscape();
|
||||
|
||||
char readTagChar(int nextState);
|
||||
char readValueChar(int nextState);
|
||||
char readStartTagChar(const char* tag, int nextState);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <stddef.h>
|
||||
#include "ChoreoInput.h"
|
||||
|
||||
ChoreoInput::ChoreoInput(ChoreoInput* prev, const char* name, const char* value) {
|
||||
if (prev != NULL) {
|
||||
prev->m_next = this;
|
||||
}
|
||||
m_next = NULL;
|
||||
m_name = name;
|
||||
m_value = value;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOINPUT_H_
|
||||
#define CHOREOINPUT_H_
|
||||
#include "TembooGlobal.h"
|
||||
class ChoreoInput {
|
||||
public:
|
||||
ChoreoInput(ChoreoInput* prev, const char* name, const char* value);
|
||||
const char* getName() const {return m_name;}
|
||||
const char* getValue() const {return m_value;}
|
||||
void setValue(const char* value) {m_value = value;}
|
||||
ChoreoInput* getNext() const {return m_next;}
|
||||
|
||||
private:
|
||||
ChoreoInput* m_next;
|
||||
const char* m_name;
|
||||
const char* m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "ChoreoInputFormatter.h"
|
||||
#include "ChoreoInputSet.h"
|
||||
|
||||
static const char TAG_INPUTS_START[] PROGMEM = "\"inputs\":{";
|
||||
|
||||
ChoreoInputFormatter::ChoreoInputFormatter(const ChoreoInputSet* inputSet) {
|
||||
m_inputSet = inputSet;
|
||||
reset();
|
||||
}
|
||||
|
||||
void ChoreoInputFormatter::reset() {
|
||||
m_currentInput = NULL;
|
||||
m_nextChar = NULL;
|
||||
if (m_inputSet == NULL || m_inputSet->isEmpty()) {
|
||||
m_nextState = END;
|
||||
} else {
|
||||
m_nextState = START;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChoreoInputFormatter::hasNext() {
|
||||
return m_nextState != END;
|
||||
}
|
||||
|
||||
char ChoreoInputFormatter::next() {
|
||||
char c;
|
||||
switch(m_nextState) {
|
||||
case START:
|
||||
c = readStartTagChar(TAG_INPUTS_START, INPUTS_TAG);
|
||||
break;
|
||||
|
||||
case INPUTS_TAG:
|
||||
c = readTagChar(NAME_START);
|
||||
if (m_nextState == NAME_START) {
|
||||
m_currentInput= m_inputSet->getFirstInput();
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_START:
|
||||
c = '"';
|
||||
m_nextChar = m_currentInput->getName();
|
||||
if ((NULL == m_nextChar) || ('\0' == *m_nextChar)) {
|
||||
m_nextState = NAME_END;
|
||||
} else {
|
||||
m_nextState = NAME;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
c = readValueChar(NAME_END);
|
||||
break;
|
||||
|
||||
case NAME_END:
|
||||
c = '"';
|
||||
m_nextState = NAME_VALUE_SEPARATOR;
|
||||
break;
|
||||
|
||||
case NAME_VALUE_SEPARATOR:
|
||||
c = ':';
|
||||
m_nextState = VALUE_START;
|
||||
break;
|
||||
|
||||
case VALUE_START:
|
||||
c = '"';
|
||||
m_nextChar = m_currentInput->getValue();
|
||||
if ((NULL == m_nextChar) || ('\0' == *m_nextChar)) {
|
||||
m_nextState = VALUE_END;
|
||||
} else {
|
||||
m_nextState = VALUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case VALUE:
|
||||
c = readValueChar(VALUE_END);
|
||||
break;
|
||||
|
||||
case VALUE_END:
|
||||
c = '"';
|
||||
m_currentInput = m_currentInput->getNext();
|
||||
if (m_currentInput != NULL) {
|
||||
m_nextState = NEXT_INPUT;
|
||||
} else {
|
||||
m_nextState = INPUTS_END;
|
||||
}
|
||||
break;
|
||||
case NEXT_INPUT:
|
||||
c = ',';
|
||||
m_nextChar = m_currentInput->getName();
|
||||
m_nextState = NAME_START;
|
||||
break;
|
||||
|
||||
case INPUTS_END:
|
||||
c = '}';
|
||||
m_nextState = END;
|
||||
break;
|
||||
case END:
|
||||
default:
|
||||
c = '\0';
|
||||
}
|
||||
return c;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOINPUTFORMATTER_H_
|
||||
#define CHOREOINPUTFORMATTER_H_
|
||||
#include "TembooGlobal.h"
|
||||
#include "BaseFormatter.h"
|
||||
#include "ChoreoInputSet.h"
|
||||
|
||||
class ChoreoInputFormatter : public BaseFormatter {
|
||||
|
||||
public:
|
||||
ChoreoInputFormatter(const ChoreoInputSet* inputSet);
|
||||
bool hasNext();
|
||||
char next();
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
const ChoreoInputSet* m_inputSet;
|
||||
const ChoreoInput* m_currentInput;
|
||||
|
||||
|
||||
enum State {
|
||||
START,
|
||||
INPUTS_TAG,
|
||||
NAME_START,
|
||||
NAME,
|
||||
NAME_END,
|
||||
NAME_VALUE_SEPARATOR,
|
||||
VALUE_START,
|
||||
VALUE,
|
||||
VALUE_END,
|
||||
NEXT_INPUT,
|
||||
INPUTS_END,
|
||||
END
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <string.h>
|
||||
#include "ChoreoInputSet.h"
|
||||
|
||||
ChoreoInputSet::ChoreoInputSet() {
|
||||
m_first = NULL;
|
||||
}
|
||||
|
||||
ChoreoInputSet::~ChoreoInputSet() {
|
||||
ChoreoInput* i = m_first;
|
||||
ChoreoInput* next = NULL;
|
||||
while (i != NULL) {
|
||||
next = i->getNext();
|
||||
delete i;
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
void ChoreoInputSet::put(const char* name, const char* value) {
|
||||
|
||||
// Haven't set ANY inputs yet?
|
||||
// Just create a new one.
|
||||
if (m_first == NULL) {
|
||||
m_first = new ChoreoInput(NULL, name, value);
|
||||
} else {
|
||||
// Some inputs already set.
|
||||
// See if we already have this input.
|
||||
ChoreoInput* last = NULL;
|
||||
ChoreoInput* i = m_first;
|
||||
while(i != NULL) {
|
||||
if (strcmp(i->getName(), name) == 0) {
|
||||
// We already have an input with this name.
|
||||
// Just update the value.
|
||||
i->setValue(value);
|
||||
break;
|
||||
}
|
||||
last = i;
|
||||
i = i->getNext();
|
||||
}
|
||||
|
||||
// We don't have an input with this name
|
||||
// So we need to create a new one.
|
||||
if (i == NULL) {
|
||||
new ChoreoInput(last, name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* ChoreoInputSet::get(const char* name) const {
|
||||
ChoreoInput* i = m_first;
|
||||
while(i != NULL) {
|
||||
if (strcmp(i->getName(), name) == 0) {
|
||||
return i->getValue();
|
||||
}
|
||||
i = i->getNext();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOINPUTSET_H_
|
||||
#define CHOREOINPUTSET_H_
|
||||
#include <stddef.h>
|
||||
#include "TembooGlobal.h"
|
||||
#include "ChoreoInput.h"
|
||||
|
||||
class ChoreoInputSet {
|
||||
|
||||
public:
|
||||
ChoreoInputSet();
|
||||
~ChoreoInputSet();
|
||||
void put(const char* name, const char* value);
|
||||
const char* get(const char* name) const;
|
||||
bool isEmpty() const {return m_first == NULL;}
|
||||
const ChoreoInput* getFirstInput() const {return m_first;}
|
||||
|
||||
protected:
|
||||
ChoreoInput* m_first;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <stddef.h>
|
||||
#include "ChoreoOutput.h"
|
||||
|
||||
|
||||
ChoreoOutput::ChoreoOutput(ChoreoOutput* prev, const char* name, const char* path, const char* var) {
|
||||
if (prev != NULL) {
|
||||
prev->m_next = this;
|
||||
}
|
||||
m_next = NULL;
|
||||
m_name = name;
|
||||
m_path = path;
|
||||
m_var = var;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOOUTPUT_H_
|
||||
#define CHOREOOUTPUT_H_
|
||||
#include "TembooGlobal.h"
|
||||
|
||||
class ChoreoOutput {
|
||||
public:
|
||||
ChoreoOutput(ChoreoOutput* prev, const char* name, const char* path, const char* var);
|
||||
const char* getName() const {return m_name;}
|
||||
const char* getPath() const {return m_path;}
|
||||
const char* getVariable() const {return m_var;}
|
||||
void setPath(const char* path) {m_path = path;}
|
||||
void setVariable(const char* variable) {m_var = variable;}
|
||||
ChoreoOutput* getNext() const {return m_next;}
|
||||
|
||||
private:
|
||||
ChoreoOutput* m_next;
|
||||
const char* m_name;
|
||||
const char* m_path;
|
||||
const char* m_var;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "ChoreoOutputFormatter.h"
|
||||
#include "ChoreoOutputSet.h"
|
||||
|
||||
static const char TAG_OUTPUTS_START[] PROGMEM = "\"outputs\":[";
|
||||
static const char TAG_NAME[] PROGMEM = "\"name\":";
|
||||
static const char TAG_PATH[] PROGMEM = "\"path\":";
|
||||
static const char TAG_VAR[] PROGMEM = "\"variable\":";
|
||||
|
||||
|
||||
ChoreoOutputFormatter::ChoreoOutputFormatter(const ChoreoOutputSet* outputSet) {
|
||||
m_outputSet = outputSet;
|
||||
reset();
|
||||
}
|
||||
|
||||
void ChoreoOutputFormatter::reset() {
|
||||
m_currentOutput = NULL;
|
||||
m_nextChar = NULL;
|
||||
if (m_outputSet == NULL || m_outputSet->isEmpty()) {
|
||||
m_nextState = END;
|
||||
} else {
|
||||
m_nextState = START;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChoreoOutputFormatter::hasNext() {
|
||||
return m_nextState != END;
|
||||
}
|
||||
|
||||
char ChoreoOutputFormatter::next() {
|
||||
char c = '\0';
|
||||
switch(m_nextState) {
|
||||
case START:
|
||||
c = readStartTagChar(TAG_OUTPUTS_START, OUTPUTS_TAG);
|
||||
break;
|
||||
|
||||
case OUTPUTS_TAG:
|
||||
c = readTagChar(OUTPUT_START);
|
||||
if (m_nextState == OUTPUT_START) {
|
||||
m_currentOutput = m_outputSet->getFirstOutput();
|
||||
}
|
||||
break;
|
||||
|
||||
case OUTPUT_START:
|
||||
c = '{';
|
||||
m_nextChar = TAG_NAME;
|
||||
m_nextState = NAME_TAG;
|
||||
break;
|
||||
|
||||
case NAME_TAG:
|
||||
c = readTagChar(NAME_START);
|
||||
break;
|
||||
|
||||
case NAME_START:
|
||||
c = '"';
|
||||
m_nextChar = m_currentOutput->getName();
|
||||
if ((NULL == m_nextChar) || ('\0' == *m_nextChar)) {
|
||||
m_nextState = NAME_END;
|
||||
} else {
|
||||
m_nextState = NAME;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
c = readValueChar(NAME_END);
|
||||
break;
|
||||
|
||||
case NAME_END:
|
||||
c = '"';
|
||||
m_nextState = NAME_PATH_SEPARATOR;
|
||||
break;
|
||||
|
||||
case NAME_PATH_SEPARATOR:
|
||||
c = ',';
|
||||
m_nextState = PATH_TAG;
|
||||
m_nextChar = TAG_PATH;
|
||||
break;
|
||||
|
||||
case PATH_TAG:
|
||||
c = readTagChar(PATH_START);
|
||||
break;
|
||||
|
||||
case PATH_START:
|
||||
c = '"';
|
||||
m_nextChar = m_currentOutput->getPath();
|
||||
if ((NULL == m_nextChar) || ('\0' == *m_nextChar)) {
|
||||
m_nextState = PATH_END;
|
||||
} else {
|
||||
m_nextState = PATH;
|
||||
}
|
||||
break;
|
||||
|
||||
case PATH:
|
||||
c = readValueChar(PATH_END);
|
||||
break;
|
||||
|
||||
case PATH_END:
|
||||
c = '"';
|
||||
m_nextState = PATH_VAR_SEPARATOR;
|
||||
break;
|
||||
|
||||
case PATH_VAR_SEPARATOR:
|
||||
c = ',';
|
||||
m_nextState = VAR_TAG;
|
||||
m_nextChar = TAG_VAR;
|
||||
break;
|
||||
|
||||
case VAR_TAG:
|
||||
c = readTagChar(VAR_START);
|
||||
break;
|
||||
|
||||
case VAR_START:
|
||||
c = '"';
|
||||
m_nextChar = m_currentOutput->getVariable();
|
||||
if ((NULL == m_nextChar) || ('\0' == *m_nextChar)) {
|
||||
m_nextState = VAR_END;
|
||||
} else {
|
||||
m_nextState = VAR;
|
||||
}
|
||||
break;
|
||||
|
||||
case VAR:
|
||||
c = readValueChar(VAR_END);
|
||||
break;
|
||||
|
||||
case VAR_END:
|
||||
c = '"';
|
||||
m_nextState = OUTPUT_END;
|
||||
break;
|
||||
|
||||
case OUTPUT_END:
|
||||
c = '}';
|
||||
m_currentOutput = m_currentOutput->getNext();
|
||||
if (m_currentOutput != NULL) {
|
||||
m_nextState = NEXT_OUTPUT;
|
||||
} else {
|
||||
m_nextState = OUTPUTS_END;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEXT_OUTPUT:
|
||||
c = ',';
|
||||
m_nextChar = m_currentOutput->getName();
|
||||
m_nextState = OUTPUT_START;
|
||||
break;
|
||||
|
||||
case OUTPUTS_END:
|
||||
c = ']';
|
||||
m_nextState = END;
|
||||
break;
|
||||
case END:
|
||||
default:
|
||||
c = '\0';
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOOUTPUTFORMATTER_H_
|
||||
#define CHOREOOUTPUTFORMATTER_H_
|
||||
#include "TembooGlobal.h"
|
||||
#include "BaseFormatter.h"
|
||||
#include "ChoreoOutputSet.h"
|
||||
|
||||
class ChoreoOutputFormatter : public BaseFormatter {
|
||||
|
||||
public:
|
||||
ChoreoOutputFormatter(const ChoreoOutputSet* outputSet);
|
||||
bool hasNext();
|
||||
char next();
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
const ChoreoOutputSet* m_outputSet;
|
||||
const ChoreoOutput* m_currentOutput;
|
||||
|
||||
enum State {
|
||||
START,
|
||||
OUTPUTS_TAG,
|
||||
OUTPUT_START,
|
||||
NAME_TAG,
|
||||
NAME_START,
|
||||
NAME,
|
||||
NAME_END,
|
||||
NAME_PATH_SEPARATOR,
|
||||
PATH_TAG,
|
||||
PATH_START,
|
||||
PATH,
|
||||
PATH_END,
|
||||
PATH_VAR_SEPARATOR,
|
||||
VAR_TAG,
|
||||
VAR_START,
|
||||
VAR,
|
||||
VAR_END,
|
||||
OUTPUT_END,
|
||||
NEXT_OUTPUT,
|
||||
OUTPUTS_END,
|
||||
END
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <stddef.h>
|
||||
#include <string.h>
|
||||
#include "ChoreoOutputSet.h"
|
||||
|
||||
|
||||
ChoreoOutputSet::ChoreoOutputSet() {
|
||||
m_first = NULL;
|
||||
}
|
||||
|
||||
ChoreoOutputSet::~ChoreoOutputSet() {
|
||||
ChoreoOutput* i = m_first;
|
||||
ChoreoOutput* next = NULL;
|
||||
while(i != NULL) {
|
||||
next = i->getNext();
|
||||
delete i;
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
void ChoreoOutputSet::put(const char* name, const char* path, const char* variable) {
|
||||
if (m_first == NULL) {
|
||||
m_first = new ChoreoOutput(NULL, name, path, variable);
|
||||
} else {
|
||||
ChoreoOutput* last = NULL;
|
||||
ChoreoOutput* i = m_first;
|
||||
while(i != NULL) {
|
||||
if (strcmp(i->getName(), name) == 0) {
|
||||
i->setPath(path);
|
||||
i->setVariable(variable);
|
||||
break;
|
||||
}
|
||||
last = i;
|
||||
i = i->getNext();
|
||||
}
|
||||
|
||||
if (i == NULL) {
|
||||
new ChoreoOutput(last, name, path, variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ChoreoOutput* ChoreoOutputSet::get(const char* name) const {
|
||||
ChoreoOutput* i = m_first;
|
||||
while(i != NULL) {
|
||||
if (strcmp(i->getName(), name) == 0) {
|
||||
return i;
|
||||
}
|
||||
i = i->getNext();
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOOUTPUTSET_H_
|
||||
#define CHOREOOUTPUTSET_H_
|
||||
#include <stddef.h>
|
||||
#include "TembooGlobal.h"
|
||||
#include "ChoreoOutput.h"
|
||||
|
||||
class ChoreoOutputSet {
|
||||
|
||||
public:
|
||||
ChoreoOutputSet();
|
||||
~ChoreoOutputSet();
|
||||
void put(const char* name, const char* path, const char* variable);
|
||||
const ChoreoOutput* get(const char* name) const;
|
||||
bool isEmpty() const {return m_first == NULL;}
|
||||
const ChoreoOutput* getFirstOutput() const {return m_first;}
|
||||
|
||||
protected:
|
||||
ChoreoOutput* m_first;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 "ChoreoPreset.h"
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOPRESET_H_
|
||||
#define CHOREOPRESET_H_
|
||||
#include <stddef.h>
|
||||
#include "TembooGlobal.h"
|
||||
|
||||
class ChoreoPreset {
|
||||
public:
|
||||
ChoreoPreset() {m_name = NULL;}
|
||||
ChoreoPreset(const char* name) {put(name);}
|
||||
const char* getName() const {return m_name;}
|
||||
void put(const char* name) {m_name = name;}
|
||||
bool isEmpty() const {return m_name == NULL || *m_name == '\0';}
|
||||
|
||||
private:
|
||||
const char* m_name;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "ChoreoPresetFormatter.h"
|
||||
#include "ChoreoPreset.h"
|
||||
|
||||
static const char TAG_PRESET[] PROGMEM = "\"preset\":";
|
||||
|
||||
ChoreoPresetFormatter::ChoreoPresetFormatter(const ChoreoPreset* preset) {
|
||||
m_preset = preset;
|
||||
reset();
|
||||
}
|
||||
|
||||
void ChoreoPresetFormatter::reset() {
|
||||
m_nextChar = NULL;
|
||||
if (m_preset == NULL || m_preset->isEmpty()) {
|
||||
m_nextState = END;
|
||||
} else {
|
||||
m_nextState = START;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChoreoPresetFormatter::hasNext() {
|
||||
return m_nextState != END;
|
||||
}
|
||||
|
||||
char ChoreoPresetFormatter::next() {
|
||||
char c = '\0';
|
||||
switch(m_nextState) {
|
||||
case START:
|
||||
c = readStartTagChar(TAG_PRESET, PRESET_TAG);
|
||||
break;
|
||||
|
||||
case PRESET_TAG:
|
||||
c = readTagChar(NAME_START);
|
||||
break;
|
||||
|
||||
case NAME_START:
|
||||
c = '"';
|
||||
m_nextChar = m_preset->getName();
|
||||
if ((NULL == m_nextChar) || ('\0' == *m_nextChar)) {
|
||||
m_nextState = NAME_END;
|
||||
} else {
|
||||
m_nextState = NAME;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
c = readValueChar(NAME_END);
|
||||
break;
|
||||
|
||||
case NAME_END:
|
||||
c = '"';
|
||||
m_nextState = END;
|
||||
break;
|
||||
|
||||
case END:
|
||||
default:
|
||||
c = '\0';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 CHOREOPROFILEFORMATTER_H_
|
||||
#define CHOREOPROFILEFORMATTER_H_
|
||||
#include "TembooGlobal.h"
|
||||
#include "BaseFormatter.h"
|
||||
#include "ChoreoPreset.h"
|
||||
|
||||
class ChoreoPresetFormatter : public BaseFormatter {
|
||||
|
||||
public:
|
||||
ChoreoPresetFormatter(const ChoreoPreset* preset);
|
||||
bool hasNext();
|
||||
char next();
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
const ChoreoPreset* m_preset;
|
||||
|
||||
enum State {
|
||||
START,
|
||||
PRESET_TAG,
|
||||
NAME_START,
|
||||
NAME,
|
||||
NAME_END,
|
||||
END
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 "DataFormatter.h"
|
||||
|
||||
|
||||
DataFormatter::DataFormatter(
|
||||
const ChoreoInputSet* inputSet,
|
||||
const ChoreoOutputSet* outputSet,
|
||||
const ChoreoPreset* preset) :
|
||||
m_inputFormatter(inputSet),
|
||||
m_outputFormatter(outputSet),
|
||||
m_presetFormatter(preset) {
|
||||
|
||||
m_inputSet = inputSet;
|
||||
m_outputSet = outputSet;
|
||||
m_preset = preset;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void DataFormatter::reset() {
|
||||
m_nextState = DATA_START;
|
||||
m_inputFormatter.reset();
|
||||
m_outputFormatter.reset();
|
||||
m_presetFormatter.reset();
|
||||
}
|
||||
|
||||
bool DataFormatter::hasNext() {
|
||||
return m_nextState != DATA_END;
|
||||
}
|
||||
|
||||
char DataFormatter::next() {
|
||||
char c;
|
||||
switch(m_nextState) {
|
||||
case DATA_START:
|
||||
c = '{';
|
||||
if (m_inputFormatter.hasNext()) {
|
||||
m_nextState = FORMATTING_INPUTS;
|
||||
} else if (m_outputFormatter.hasNext()) {
|
||||
m_nextState = FORMATTING_OUTPUTS;
|
||||
} else if (m_presetFormatter.hasNext()) {
|
||||
m_nextState = FORMATTING_PRESET;
|
||||
} else {
|
||||
m_nextState = FORMATTING_EMPTY;
|
||||
}
|
||||
break;
|
||||
case FORMATTING_INPUTS:
|
||||
if (m_inputFormatter.hasNext()) {
|
||||
c = m_inputFormatter.next();
|
||||
} else if (m_outputFormatter.hasNext()) {
|
||||
c = ',';
|
||||
m_nextState = FORMATTING_OUTPUTS;
|
||||
} else if (m_presetFormatter.hasNext()) {
|
||||
c = ',';
|
||||
m_nextState = FORMATTING_PRESET;
|
||||
} else {
|
||||
c = '}';
|
||||
m_nextState = DATA_END;
|
||||
}
|
||||
break;
|
||||
case FORMATTING_OUTPUTS:
|
||||
if (m_outputFormatter.hasNext()) {
|
||||
c = m_outputFormatter.next();
|
||||
} else if (m_presetFormatter.hasNext()) {
|
||||
c = ',';
|
||||
m_nextState = FORMATTING_PRESET;
|
||||
} else {
|
||||
c = '}';
|
||||
m_nextState = DATA_END;
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMATTING_PRESET:
|
||||
if (m_presetFormatter.hasNext()) {
|
||||
c = m_presetFormatter.next();
|
||||
} else {
|
||||
c = '}';
|
||||
m_nextState = DATA_END;
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMATTING_EMPTY:
|
||||
c = '}';
|
||||
m_nextState = DATA_END;
|
||||
break;
|
||||
|
||||
case DATA_END:
|
||||
default:
|
||||
c = '\0';
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 DATAFORMATTER_H_
|
||||
#define DATAFORMATTER_H_
|
||||
#include "TembooGlobal.h"
|
||||
#include "ChoreoInputSet.h"
|
||||
#include "ChoreoOutputSet.h"
|
||||
#include "ChoreoPreset.h"
|
||||
#include "ChoreoInputFormatter.h"
|
||||
#include "ChoreoOutputFormatter.h"
|
||||
#include "ChoreoPresetFormatter.h"
|
||||
|
||||
|
||||
class DataFormatter {
|
||||
|
||||
public:
|
||||
DataFormatter(const ChoreoInputSet* inputSet, const ChoreoOutputSet* outputSet, const ChoreoPreset* preset);
|
||||
bool hasNext();
|
||||
char next();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
const ChoreoInputSet* m_inputSet;
|
||||
const ChoreoOutputSet* m_outputSet;
|
||||
const ChoreoPreset* m_preset;
|
||||
|
||||
ChoreoInputFormatter m_inputFormatter;
|
||||
ChoreoOutputFormatter m_outputFormatter;
|
||||
ChoreoPresetFormatter m_presetFormatter;
|
||||
|
||||
enum State {
|
||||
DATA_START,
|
||||
FORMATTING_INPUTS,
|
||||
FORMATTING_OUTPUTS,
|
||||
FORMATTING_PRESET,
|
||||
FORMATTING_EMPTY,
|
||||
DATA_END
|
||||
};
|
||||
|
||||
State m_nextState;
|
||||
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 "TembooGlobal.h"
|
||||
|
||||
char* uint16toa(uint16_t value, char* dest) {
|
||||
return uint32toa(value, dest);
|
||||
}
|
||||
|
||||
char* uint32toa(uint32_t value, char* dest) {
|
||||
char* end = dest;
|
||||
do {
|
||||
*end++ = (value % 10) + '0';
|
||||
} while (value /= 10);
|
||||
*end = '\0';
|
||||
end--;
|
||||
|
||||
char c;
|
||||
char* begin = dest;
|
||||
while(end > begin) {
|
||||
c = *end;
|
||||
*end = *begin;
|
||||
*begin = c;
|
||||
end--;
|
||||
begin++;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 TEMBOOGLOBAL_H_
|
||||
#define TEMBOOGLOBAL_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define TEMBOO_VERBOSE
|
||||
|
||||
#ifdef TEMBOO_VERBOSE
|
||||
#define TEMBOO_TRACE(x) Serial.print(x)
|
||||
#define TEMBOO_TRACE_BYTES(x,c) Serial.write((const uint8_t*)x,c)
|
||||
#define TEMBOO_TRACELN(x) Serial.println(x)
|
||||
#else
|
||||
#define TEMBOO_TRACE(x)
|
||||
#define TEMBOO_TRACE_BYTES(x,c)
|
||||
#define TEMBOO_TRACELN(x)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char* uint16toa(uint16_t value, char* dest);
|
||||
char* uint32toa(uint32_t value, char* dest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "TembooSession.h"
|
||||
#include "tmbhmac.h"
|
||||
#include "DataFormatter.h"
|
||||
|
||||
static const char EOL[] PROGMEM = "\r\n";
|
||||
static const char POST[] PROGMEM = "POST ";
|
||||
static const char POSTAMBLE[] PROGMEM = " HTTP/1.0"; // Prevent host from using chunked encoding in response.
|
||||
static const char HEADER_HOST[] PROGMEM = "Host: ";
|
||||
static const char HEADER_ACCEPT[] PROGMEM = "Accept: application/xml";
|
||||
static const char HEADER_ORG[] PROGMEM = "x-temboo-domain: /";
|
||||
static const char HEADER_DOM[] PROGMEM = "/master";
|
||||
static const char HEADER_CONTENT_LENGTH[] PROGMEM = "Content-Length: ";
|
||||
static const char HEADER_TIME[] PROGMEM = "x-temboo-time: ";
|
||||
static const char BASE_CHOREO_URI[] PROGMEM = "/arcturus-web/api-1.0/ar";
|
||||
static const char HEADER_AUTH[] PROGMEM = "x-temboo-authentication: ";
|
||||
static const char HEADER_CONTENT_TYPE[] PROGMEM = "Content-Type: text/plain";
|
||||
static const char TEMBOO_DOMAIN[] PROGMEM = ".temboolive.com";
|
||||
static const char SDK_ID[] PROGMEM = "?source_id=arduinoSDK1";
|
||||
|
||||
unsigned long TembooSession::s_timeOffset = 0;
|
||||
|
||||
TembooSession::TembooSession(Client& client,
|
||||
IPAddress serverAddr,
|
||||
uint16_t port) : m_client(client) {
|
||||
m_addr = serverAddr;
|
||||
m_port = port;
|
||||
m_sendQueueDepth = 0;
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::setTime(unsigned long currentTime) {
|
||||
s_timeOffset = currentTime - (millis()/1000);
|
||||
}
|
||||
|
||||
|
||||
unsigned long TembooSession::getTime() {
|
||||
return s_timeOffset + (millis()/1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int TembooSession::executeChoreo(
|
||||
const char* accountName,
|
||||
const char* appKeyName,
|
||||
const char* appKeyValue,
|
||||
const char* path,
|
||||
const ChoreoInputSet& inputSet,
|
||||
const ChoreoOutputSet& outputSet,
|
||||
const ChoreoPreset& preset) {
|
||||
|
||||
DataFormatter fmt(&inputSet, &outputSet, &preset);
|
||||
char auth[HMAC_HEX_SIZE_BYTES + 1];
|
||||
char buffer[11];
|
||||
|
||||
// We use the current time-of-day as salt on the app key.
|
||||
// We keep track of time-of-day by getting the current time
|
||||
// from the server and applying an offset (the length of time
|
||||
// we've been running.)
|
||||
uint32toa((uint32_t)TembooSession::getTime(), buffer);
|
||||
|
||||
uint16_t contentLength = getAuth(fmt, appKeyValue, buffer, auth);
|
||||
|
||||
m_client.stop();
|
||||
m_client.flush();
|
||||
|
||||
int connected = 0;
|
||||
TEMBOO_TRACE("Connecting: ");
|
||||
|
||||
// reserve space for the "host" string sufficient to hold either the
|
||||
// (dotted-quad) IP address + port, or the default <account>.temboolive.com
|
||||
// host string.
|
||||
int hostLen = (m_addr == INADDR_NONE ? (strlen_P(TEMBOO_DOMAIN) + strlen(accountName) + 1):21);
|
||||
char host[hostLen];
|
||||
|
||||
// If no explicit IP address was specified (the normal case), construct
|
||||
// the "host" string from the account name and the temboo domain name.
|
||||
if (m_addr == INADDR_NONE) {
|
||||
strcpy(host, accountName);
|
||||
strcat_P(host, TEMBOO_DOMAIN);
|
||||
TEMBOO_TRACELN(host);
|
||||
connected = m_client.connect(host, m_port);
|
||||
} else {
|
||||
|
||||
// If an IP address was explicitly specified (presumably for testing purposes),
|
||||
// convert it to a dotted-quad text string.
|
||||
host[0] = '\0';
|
||||
for(int i = 0; i < 4; i++) {
|
||||
uint16toa(m_addr[i], &host[strlen(host)]);
|
||||
strcat(host, ".");
|
||||
}
|
||||
|
||||
// replace the last '.' with ':'
|
||||
host[strlen(host)-1] = ':';
|
||||
|
||||
// append the port number
|
||||
uint16toa(m_port, &host[strlen(host)]);
|
||||
|
||||
TEMBOO_TRACELN(host);
|
||||
connected = m_client.connect(m_addr, m_port);
|
||||
}
|
||||
|
||||
if (connected) {
|
||||
|
||||
TEMBOO_TRACELN("OK. req:");
|
||||
qsendProgmem(POST);
|
||||
qsendProgmem(BASE_CHOREO_URI);
|
||||
qsend(path);
|
||||
qsendProgmem(SDK_ID);
|
||||
qsendlnProgmem(POSTAMBLE);
|
||||
|
||||
// Send our custom authentication header
|
||||
// (app-key-name:hmac)
|
||||
qsendProgmem(HEADER_AUTH);
|
||||
qsend(appKeyName);
|
||||
qsend(":");
|
||||
qsendln(auth);
|
||||
|
||||
// send the standard host header
|
||||
qsendProgmem(HEADER_HOST);
|
||||
qsendln(host);
|
||||
|
||||
// send the standard accept header
|
||||
qsendlnProgmem(HEADER_ACCEPT);
|
||||
|
||||
// send our custom account name neader
|
||||
qsendProgmem(HEADER_ORG);
|
||||
qsend(accountName);
|
||||
qsendlnProgmem(HEADER_DOM);
|
||||
|
||||
// send the standard content type header
|
||||
qsendlnProgmem(HEADER_CONTENT_TYPE);
|
||||
|
||||
// send our custom client time header
|
||||
qsendProgmem(HEADER_TIME);
|
||||
qsendln(buffer);
|
||||
|
||||
// send the standard content length header
|
||||
qsendProgmem(HEADER_CONTENT_LENGTH);
|
||||
qsendln(uint16toa(contentLength, buffer));
|
||||
|
||||
qsendProgmem(EOL);
|
||||
|
||||
// Format and send the body of the request
|
||||
fmt.reset();
|
||||
while(fmt.hasNext()) {
|
||||
qsend(fmt.next());
|
||||
}
|
||||
|
||||
qsendProgmem(EOL);
|
||||
qflush();
|
||||
return 0;
|
||||
} else {
|
||||
TEMBOO_TRACELN("FAIL");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t TembooSession::getAuth(DataFormatter& fmt, const char* appKeyValue, const char* salt, char* result) const {
|
||||
|
||||
// We need the length of the data for other things, and
|
||||
// this method is a convenient place to calculate it.
|
||||
uint16_t len = 0;
|
||||
|
||||
HMAC hmac;
|
||||
|
||||
//combine the salt and the key and give it to the HMAC calculator
|
||||
size_t keyLength = strlen(appKeyValue) + strlen(salt);
|
||||
char key[keyLength + 1];
|
||||
strcpy(key, salt);
|
||||
strcat(key, appKeyValue);
|
||||
hmac.init((uint8_t*)key, keyLength);
|
||||
|
||||
// process the data a block at a time.
|
||||
uint8_t buffer[HMAC_BLOCK_SIZE_BYTES];
|
||||
int blockCount = 0;
|
||||
fmt.reset();
|
||||
while(fmt.hasNext()) {
|
||||
uint8_t c = fmt.next();
|
||||
len++;
|
||||
buffer[blockCount++] = c;
|
||||
if (blockCount == HMAC_BLOCK_SIZE_BYTES) {
|
||||
hmac.process(buffer, blockCount);
|
||||
blockCount = 0;
|
||||
}
|
||||
}
|
||||
hmac.process(buffer, blockCount);
|
||||
|
||||
// Finalize the HMAC calculation and store the (ASCII HEX) value in *result.
|
||||
hmac.finishHex(result);
|
||||
|
||||
// Return the number of characters processed.
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::qsend(const char* s) {
|
||||
char c = *s++;
|
||||
while(c != '\0') {
|
||||
qsend(c);
|
||||
c = *s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::qsendProgmem(const char* s) {
|
||||
char c = pgm_read_byte(s++);
|
||||
while(c != '\0') {
|
||||
qsend(c);
|
||||
c = pgm_read_byte(s++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::qsend(char c) {
|
||||
m_sendQueue[m_sendQueueDepth++] = c;
|
||||
if (m_sendQueueDepth >= TEMBOO_SEND_QUEUE_SIZE) {
|
||||
qflush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::qflush() {
|
||||
m_client.write((const uint8_t*)m_sendQueue, m_sendQueueDepth);
|
||||
TEMBOO_TRACE_BYTES(m_sendQueue, m_sendQueueDepth);
|
||||
m_sendQueueDepth = 0;
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::qsendln(const char* s) {
|
||||
qsend(s);
|
||||
qsendProgmem(EOL);
|
||||
}
|
||||
|
||||
|
||||
void TembooSession::qsendlnProgmem(const char* s) {
|
||||
qsendProgmem(s);
|
||||
qsendProgmem(EOL);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 TEMBOOSESSIONCLASS_H_
|
||||
#define TEMBOOSESSIONCLASS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
#include <Client.h>
|
||||
#include "TembooGlobal.h"
|
||||
|
||||
#ifndef TEMBOO_SEND_QUEUE_SIZE
|
||||
|
||||
// Some network interfaces (i.e. ethernet or WiFi shields) can only accept
|
||||
// a limited amount of data. If you try to send more than the limit, the excess
|
||||
// is just lost. However, sending one character at a time is very inefficient.
|
||||
// To deal with this situation, we queue up TEMBOO_SEND_QUEUE_SIZE bytes to send
|
||||
// to the network device at one time. This is a compromise between RAM usage
|
||||
// and performance.
|
||||
#define TEMBOO_SEND_QUEUE_SIZE (32)
|
||||
#endif
|
||||
|
||||
class ChoreoInputSet;
|
||||
class ChoreoOutputSet;
|
||||
class ChoreoPreset;
|
||||
class DataFormatter;
|
||||
|
||||
class TembooSession {
|
||||
public:
|
||||
|
||||
//TembooSession constructor
|
||||
//client: REQUIRED TCP/IP client object. Usually either an EthernetClient or a WiFiClient
|
||||
//IPAddress: OPTIONAL IP address of the server to connect to. Usually only used for testing.
|
||||
//port: OPTIONAL port number to use with the IPAddress. Usually only used for testing.
|
||||
TembooSession(Client& client, IPAddress serverAddr=INADDR_NONE, uint16_t port=80);
|
||||
|
||||
//executeChoreo sends a choreo execution request to the Temboo system.
|
||||
// Does not wait for a response (that's a job for whoever owns the Client.)
|
||||
//accountName: the name of the user's account at Temboo.
|
||||
//appKeyName: the name of an application key in the user's account to use
|
||||
// for this execution (analogous to a user name).
|
||||
//appKeyValue: the value of the application key named in appKeyName.
|
||||
// Used to authenticate the user (analogous to a password)
|
||||
//path: The full path to the choreo to be executed (relative to the root of the
|
||||
// user's account.)
|
||||
//inputSet: the set of inputs needed by the choreo.
|
||||
// May be an empty ChoreoInputSet.
|
||||
//outputSet: the set of output filters to be applied to the choreo results.
|
||||
// May be an empty ChoreoOutputSet
|
||||
//preset: the ChoreoPreset to be used with the choreo execution.
|
||||
// May be an empty ChoreoPreset.
|
||||
int executeChoreo(const char* accountName,
|
||||
const char* appKeyName,
|
||||
const char* appKeyValue,
|
||||
const char* path,
|
||||
const ChoreoInputSet& inputSet,
|
||||
const ChoreoOutputSet& outputSet,
|
||||
const ChoreoPreset& preset);
|
||||
|
||||
// setTime sets the current time in Unix timestamp format. Needed for execution request authentication.
|
||||
// NOTE: This method is usually called by TembooChoreo.run() with the current time returned by
|
||||
// an error response from the Temboo system, thus automatically setting the time. However, it
|
||||
// MAY be called from user code if the particular board has a way of determining the current
|
||||
// time in the proper format.
|
||||
// currentTime: the number of seconds since 1970-01-01 00:00:00 UTC.
|
||||
static void setTime(unsigned long currentTime);
|
||||
|
||||
//getTime returns the current time in Unix timestamp format (seconds since 1970-01-01 00:00:00 UTC).
|
||||
// Only valid after setTime has been called.
|
||||
static unsigned long getTime();
|
||||
|
||||
private:
|
||||
static unsigned long s_timeOffset;
|
||||
|
||||
IPAddress m_addr;
|
||||
uint16_t m_port;
|
||||
|
||||
Client& m_client;
|
||||
char m_sendQueue[TEMBOO_SEND_QUEUE_SIZE];
|
||||
size_t m_sendQueueDepth;
|
||||
|
||||
// calculate the authentication code value of the formatted request body
|
||||
// using the salted application key value as the key.
|
||||
// Returns the number of characters processed (i.e. the length of the request body)
|
||||
uint16_t getAuth(DataFormatter& fmt, const char* appKeyValue, const char* salt, char* hexAuth) const;
|
||||
|
||||
|
||||
// queue an entire nul-terminated char array
|
||||
// from RAM followed by a newline.
|
||||
void qsendln(const char* str);
|
||||
|
||||
// queue an entire nul-terminated char array
|
||||
// from flash memory (PROGMEM) one byte at a time,
|
||||
// followed by a newline.
|
||||
void qsendlnProgmem(const char* str);
|
||||
|
||||
// queue an entire nul-terminated char array
|
||||
// from RAM one byte at a time.
|
||||
void qsend(const char*);
|
||||
|
||||
// queue an entire nul-terminated char array
|
||||
// from flash memory (PROGMEM) one byte at a time.
|
||||
void qsendProgmem(const char*);
|
||||
|
||||
// queue a single character to be sent when the queue is full.
|
||||
void qsend(char);
|
||||
|
||||
// send the current contents of the send queue to the client.
|
||||
void qflush();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <string.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "tmbhmac.h"
|
||||
|
||||
HMAC::HMAC() {
|
||||
}
|
||||
|
||||
HMAC::HMAC(const uint8_t* key, uint32_t keyLength) {
|
||||
init(key, keyLength);
|
||||
}
|
||||
|
||||
void HMAC::init(const uint8_t* key, uint32_t keyLength) {
|
||||
|
||||
m_key = key;
|
||||
m_keyLength = keyLength;
|
||||
|
||||
uint8_t iKeyPad[HMAC_BLOCK_SIZE_BYTES];
|
||||
|
||||
constructKeyPad(iKeyPad, key, keyLength, (uint8_t)0x36);
|
||||
|
||||
m_md5.init();
|
||||
m_md5.process(iKeyPad, HMAC_BLOCK_SIZE_BYTES);
|
||||
}
|
||||
|
||||
void HMAC::process(const uint8_t* msg, uint32_t msgLength) {
|
||||
// hmac = hash(o_key_pad + hash(i_key_pad + message))
|
||||
// continue hashing the message
|
||||
m_md5.process(msg, msgLength);
|
||||
}
|
||||
|
||||
void HMAC::finish(uint8_t* dest) {
|
||||
//hmac = hash(o_key_pad + hash(i_key_pad + message))
|
||||
//
|
||||
// Construct the o_key_pad
|
||||
uint8_t finalBlock[HMAC_BLOCK_SIZE_BYTES + HMAC_HASH_SIZE_BYTES];
|
||||
constructKeyPad(finalBlock, m_key, m_keyLength, (uint8_t)0x5C);
|
||||
m_md5.finish(finalBlock + HMAC_BLOCK_SIZE_BYTES);
|
||||
|
||||
m_md5.init();
|
||||
m_md5.process(finalBlock, HMAC_BLOCK_SIZE_BYTES + HMAC_HASH_SIZE_BYTES);
|
||||
m_md5.finish(dest);
|
||||
}
|
||||
|
||||
void HMAC::finishHex(char* dest) {
|
||||
uint8_t binDest[HMAC_HASH_SIZE_BYTES];
|
||||
finish(binDest);
|
||||
toHex(binDest, dest);
|
||||
}
|
||||
|
||||
void HMAC::toHex(uint8_t* hmac, char* dest) {
|
||||
static const char hex[17] PROGMEM = "0123456789abcdef";
|
||||
uint16_t i;
|
||||
for (i = 0; i < HMAC_HASH_SIZE_BYTES; i++) {
|
||||
dest[i*2] = pgm_read_byte(&hex[hmac[i] >> 4]);
|
||||
dest[(i*2) + 1] = pgm_read_byte(&hex[hmac[i] & 0x0F]);
|
||||
}
|
||||
dest[HMAC_HASH_SIZE_BYTES * 2] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* dest MUST be big enough to hold HMAC_BLOCK_SIZE_BYTES
|
||||
*/
|
||||
void HMAC::constructKeyPad(uint8_t* dest, const uint8_t* key, uint32_t keyLength, uint8_t padByte) {
|
||||
|
||||
if (keyLength > HMAC_BLOCK_SIZE_BYTES) {
|
||||
// If the key is bigger than 1 block,
|
||||
// replace the key with the hash of the key.
|
||||
MD5 md5;
|
||||
md5.process(key, keyLength);
|
||||
md5.finish(dest);
|
||||
keyLength = HMAC_HASH_SIZE_BYTES;
|
||||
} else {
|
||||
// If the key length is <= to the HMAC block length,
|
||||
// just use the key as-is.
|
||||
memcpy(dest, key, keyLength);
|
||||
}
|
||||
// pad the remaining space with 0s
|
||||
if (keyLength < HMAC_BLOCK_SIZE_BYTES) {
|
||||
memset(dest + keyLength, 0, HMAC_BLOCK_SIZE_BYTES-keyLength);
|
||||
}
|
||||
|
||||
for (int i = 0; i < HMAC_BLOCK_SIZE_BYTES; i++) {
|
||||
dest[i] ^= padByte;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 TMBHMAC_H_
|
||||
#define TMBHMAC_H_
|
||||
#include "tmbmd5.h"
|
||||
#include "TembooGlobal.h"
|
||||
|
||||
#define HMAC_HASH_SIZE_BYTES (MD5_HASH_SIZE_BYTES)
|
||||
#define HMAC_BLOCK_SIZE_BYTES (MD5_BLOCK_SIZE_BYTES)
|
||||
|
||||
#define HMAC_HEX_SIZE_BYTES (HMAC_HASH_SIZE_BYTES * 2)
|
||||
|
||||
class HMAC
|
||||
{
|
||||
public:
|
||||
HMAC();
|
||||
HMAC(const uint8_t* key, uint32_t keyLength);
|
||||
void init(const uint8_t* key, uint32_t keyLength);
|
||||
void process(const uint8_t* msg, uint32_t msgLength);
|
||||
void finish(uint8_t* dest);
|
||||
void finishHex(char* dest);
|
||||
enum {
|
||||
HMAC_OK = 0,
|
||||
HMAC_ERROR,
|
||||
HMAC_FAIL_TESTVECTOR
|
||||
};
|
||||
|
||||
private:
|
||||
MD5 m_md5;
|
||||
const uint8_t* m_key;
|
||||
uint32_t m_keyLength;
|
||||
|
||||
void constructKeyPad(uint8_t* dest, const uint8_t* key, uint32_t keyLength, uint8_t padByte);
|
||||
void toHex(uint8_t* hmac, char* dest);
|
||||
};
|
||||
#endif
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 <string.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "tmbmd5.h"
|
||||
|
||||
|
||||
static const uint8_t Worder[64] PROGMEM = {
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
|
||||
1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
|
||||
5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
|
||||
0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
|
||||
};
|
||||
|
||||
static const uint8_t Rorder[64] PROGMEM = {
|
||||
7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
|
||||
5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
|
||||
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
|
||||
6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
|
||||
};
|
||||
|
||||
static const uint32_t Korder[64] PROGMEM = {
|
||||
0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
|
||||
0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
|
||||
0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
|
||||
0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
|
||||
0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
|
||||
0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
|
||||
0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
|
||||
0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
|
||||
};
|
||||
|
||||
|
||||
MD5::MD5() {
|
||||
init();
|
||||
}
|
||||
|
||||
void MD5::init() {
|
||||
m_state[0] = 0x67452301UL;
|
||||
m_state[1] = 0xefcdab89UL;
|
||||
m_state[2] = 0x98badcfeUL;
|
||||
m_state[3] = 0x10325476UL;
|
||||
m_bufLength = 0;
|
||||
m_msgLengthBits = 0;
|
||||
}
|
||||
|
||||
int MD5::compress(const uint8_t* buf) {
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
uint32_t c;
|
||||
uint32_t d;
|
||||
uint32_t i;
|
||||
uint32_t W[16];
|
||||
uint32_t t;
|
||||
|
||||
// Copy data into W[0..15] in an endian-agnostic way
|
||||
for (i = 0; i < 16; i++) {
|
||||
W[i] = ((uint32_t)(buf[3])) << 24
|
||||
| ((uint32_t)(buf[2])) << 16
|
||||
| ((uint32_t)(buf[1])) << 8
|
||||
| ((uint32_t)(buf[0]));
|
||||
buf += 4;
|
||||
}
|
||||
|
||||
// copy current state
|
||||
a = m_state[0];
|
||||
b = m_state[1];
|
||||
c = m_state[2];
|
||||
d = m_state[3];
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
FF(&a,b,c,d,W[pgm_read_byte(&Worder[i])],pgm_read_byte(&Rorder[i]),pgm_read_dword(&Korder[i]));
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 32; ++i) {
|
||||
GG(&a,b,c,d,W[pgm_read_byte(&Worder[i])],pgm_read_byte(&Rorder[i]),pgm_read_dword(&Korder[i]));
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 48; ++i) {
|
||||
HH(&a,b,c,d,W[pgm_read_byte(&Worder[i])],pgm_read_byte(&Rorder[i]),pgm_read_dword(&Korder[i]));
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 64; ++i) {
|
||||
II(&a,b,c,d,W[pgm_read_byte(&Worder[i])],pgm_read_byte(&Rorder[i]),pgm_read_dword(&Korder[i]));
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
m_state[0] = m_state[0] + a;
|
||||
m_state[1] = m_state[1] + b;
|
||||
m_state[2] = m_state[2] + c;
|
||||
m_state[3] = m_state[3] + d;
|
||||
|
||||
return MD5::MD5_OK;
|
||||
}
|
||||
|
||||
int MD5::process (const uint8_t* msg, uint32_t msgLengthBytes) {
|
||||
uint32_t n;
|
||||
int err;
|
||||
|
||||
if (m_bufLength >= sizeof(m_buf)) {
|
||||
return MD5::MD5_INVALID_ARG;
|
||||
}
|
||||
|
||||
while (msgLengthBytes > 0) {
|
||||
|
||||
// Process the input msg in 64 byte chunks
|
||||
if (m_bufLength == 0 && msgLengthBytes >= 64) {
|
||||
err = compress (msg);
|
||||
if (err != MD5::MD5_OK) {
|
||||
return err;
|
||||
}
|
||||
m_msgLengthBits += 64 * 8;
|
||||
msg += 64;
|
||||
msgLengthBytes -= 64;
|
||||
} else {
|
||||
n = 64 - m_bufLength;
|
||||
if (msgLengthBytes < n) {
|
||||
n = msgLengthBytes;
|
||||
}
|
||||
memcpy(m_buf + m_bufLength, msg, (size_t)n);
|
||||
m_bufLength += n;
|
||||
msg += n;
|
||||
msgLengthBytes -= n;
|
||||
if (m_bufLength == 64) {
|
||||
err = compress (m_buf);
|
||||
if (err != MD5::MD5_OK) {
|
||||
return err;
|
||||
}
|
||||
m_msgLengthBits += 64 * 8;
|
||||
m_bufLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MD5::MD5_OK;
|
||||
}
|
||||
|
||||
|
||||
int MD5::finish(uint8_t* out) {
|
||||
int i;
|
||||
|
||||
if (m_bufLength >= sizeof(m_buf)) {
|
||||
return MD5::MD5_INVALID_ARG;
|
||||
}
|
||||
|
||||
m_msgLengthBits += m_bufLength * 8;
|
||||
|
||||
// append a '1' bit (right-padded with zeros)
|
||||
m_buf[m_bufLength++] = (uint8_t)0x80;
|
||||
|
||||
// if the bufLength is > 56 bytes, pad with zeros then compress.
|
||||
// Then fall back to padding with zeros and length encoding like normal.
|
||||
if (m_bufLength > 56) {
|
||||
while (m_bufLength < 64) {
|
||||
m_buf[m_bufLength++] = (uint8_t)0;
|
||||
}
|
||||
compress(m_buf);
|
||||
m_bufLength = 0;
|
||||
}
|
||||
|
||||
// pad with zeroes up to 56 bytes.
|
||||
// (Why 56? because we store the 8-byte length at the end.)
|
||||
// (What if bufLength == 56? Perfect! No padding prior to 8-byte length needed.)
|
||||
while (m_bufLength < 56) {
|
||||
m_buf[m_bufLength++] = (uint8_t)0;
|
||||
}
|
||||
|
||||
// add the length in an endian-agnostic way
|
||||
m_buf[56] = (uint8_t)((m_msgLengthBits ) & 255);
|
||||
m_buf[57] = (uint8_t)((m_msgLengthBits >> 8) & 255);
|
||||
m_buf[58] = (uint8_t)((m_msgLengthBits >> 16) & 255);
|
||||
m_buf[59] = (uint8_t)((m_msgLengthBits >> 24) & 255);
|
||||
m_buf[60] = (uint8_t)((m_msgLengthBits >> 32) & 255);
|
||||
m_buf[61] = (uint8_t)((m_msgLengthBits >> 40) & 255);
|
||||
m_buf[62] = (uint8_t)((m_msgLengthBits >> 48) & 255);
|
||||
m_buf[63] = (uint8_t)((m_msgLengthBits >> 56) & 255);
|
||||
|
||||
compress(m_buf);
|
||||
|
||||
// copy the state to the output in an endian-agnostic way
|
||||
for (i = 0; i < 4; i++) {
|
||||
out[0] = m_state[i] & 255;
|
||||
out[1] = (m_state[i] >> 8) & 255;
|
||||
out[2] = (m_state[i] >> 16) & 255;
|
||||
out[3] = (m_state[i] >> 24) & 255;
|
||||
out += 4;
|
||||
}
|
||||
return MD5::MD5_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
###############################################################################
|
||||
#
|
||||
# Temboo Arduino library
|
||||
#
|
||||
# Copyright 2014, 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 TMBMD5_H_
|
||||
#define TMBMD5_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "TembooGlobal.h"
|
||||
|
||||
#define MD5_HASH_SIZE_BITS (128)
|
||||
#define MD5_HASH_SIZE_BYTES (MD5_HASH_SIZE_BITS/8)
|
||||
|
||||
#define MD5_BLOCK_SIZE_BITS (512)
|
||||
#define MD5_BLOCK_SIZE_BYTES (MD5_BLOCK_SIZE_BITS/8)
|
||||
|
||||
|
||||
#define ROL(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
class MD5 {
|
||||
|
||||
public:
|
||||
MD5();
|
||||
void init();
|
||||
int process(const uint8_t* in, uint32_t inlen);
|
||||
int finish(uint8_t* hash);
|
||||
enum {
|
||||
MD5_OK = 0,
|
||||
MD5_ERROR,
|
||||
MD5_INVALID_ARG,
|
||||
MD5_FAIL_TESTVECTOR
|
||||
};
|
||||
|
||||
private:
|
||||
uint64_t m_msgLengthBits;
|
||||
uint32_t m_state[4];
|
||||
uint32_t m_bufLength;
|
||||
uint8_t m_buf[64];
|
||||
|
||||
int compress(const uint8_t* buf);
|
||||
|
||||
inline uint32_t F_(uint32_t x, uint32_t y, uint32_t z) { return (z ^ (x & (y ^ z))); }
|
||||
inline uint32_t G_(uint32_t x, uint32_t y, uint32_t z) { return (y ^ (z & (y ^ x))); }
|
||||
inline uint32_t H_(uint32_t x, uint32_t y, uint32_t z) { return (x^y^z); }
|
||||
inline uint32_t I_(uint32_t x, uint32_t y, uint32_t z) { return (y^(x|(~z))); }
|
||||
|
||||
|
||||
inline void FF(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t M, uint32_t s, uint32_t t) { *a = (*a + F_(b,c,d) + M + t); *a = ROL(*a, s) + b; }
|
||||
inline void GG(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t M, uint32_t s, uint32_t t) { *a = (*a + G_(b,c,d) + M + t); *a = ROL(*a, s) + b; }
|
||||
inline void HH(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t M, uint32_t s, uint32_t t) { *a = (*a + H_(b,c,d) + M + t); *a = ROL(*a, s) + b; }
|
||||
inline void II(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t M, uint32_t s, uint32_t t) { *a = (*a + I_(b,c,d) + M + t); *a = ROL(*a, s) + b; }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue