Merge pull request #2215 from temboo/ide-1.5.x-temboo

Updated Temboo library
This commit is contained in:
Cristian Maglie 2014-08-01 12:48:06 +02:00
commit 378fa904c5
33 changed files with 2794 additions and 14 deletions

View File

@ -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

View File

@ -24,6 +24,7 @@ setAppKeyName KEYWORD2
setAppKey KEYWORD2
setChoreo KEYWORD2
setCredential KEYWORD2
setSavedInputs KEYWORD2
addInput KEYWORD2
addOutputFilter KEYWORD2
setSettingsFileToWrite KEYWORD2

View File

@ -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)

View File

@ -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

View File

@ -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_

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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