Temboo: removing ControlBySMS and SendDataToMySQL examples, as per Temboo request

This commit is contained in:
Federico Fissore 2014-11-12 17:55:54 +01:00
parent 8815806540
commit e52b4edd6f
4 changed files with 0 additions and 780 deletions

View File

@ -1,443 +0,0 @@
/*
ControlBySMS
Demonstrates using an SMS message to a Twilio account to turn an LED
on the Yún board on and off using the Temboo Arduino Yún SDK.
Sending a SMS with the text "LED ON" to your Twilio phone number
will turn on the LED on the Yún. Sending "LED OFF" will turn it off.
Check out the latest Arduino & Temboo examples and support docs at http://www.temboo.com/arduino
A Temboo account and application key are necessary to run all Temboo examples.
If you don't already have one, you can register for a free Temboo account at
http://www.temboo.com
Since this sketch uses Twilio to retrieve the SMS, you'll also need a valid
Twilio account. You can create one for free at https://www.twilio.com.
The sketch needs your Twilio Account SID and Auth Token you get when you
register with Twilio. Make sure to use the Account SID and Auth Token from
your Twilio Dashboard (not your test credentials from the Dev Tools panel).
Normally, Twilio expects to contact a web site you provide to get a response
when an SMS message is received for your Twilio number. In this case, we
don't want to send any response (and we don't want to have to set up a web
site just to receive SMS messages.) You can use a URL that Twilio provides
for this purpose. When a message is received and sent to the Twilio "twimlets"
URL, it returns a code meaning "no response required." To set this up:
1. Log in to your Twilio account and go to this URL:
https://www.twilio.com/user/account/phone-numbers/incoming
2. Select the Twilio number you want to receive SMS messages at.
3. Put this URL in the "SMS Request URL" field:
http://twimlets.com/echo?Twiml=%3CResponse%3E%3C%2FResponse%3E
See this link to Twilio's FAQ for details:
https://www.twilio.com/help/faq/sms/how-can-i-receive-sms-messages-without-responding
4. Click the "Save Changes" button at the bottom of the page.
Your account will now receive SMS messages, but won't send any responses.
This example assumes basic familiarity with Arduino sketches, and that your Yún is connected
to the Internet.
Looking for another API? We've got over 100 in our Library!
This example code is in the public domain.
*/
#include <Bridge.h>
#include <Temboo.h>
#include "TembooAccount.h" // contains Temboo account information
// as described in the footer comment below
/*** SUBSTITUTE YOUR VALUES BELOW: ***/
// Note that for additional security and reusability, you could
// use #define statements to specify these values in a .h file.
// the Account SID from your Twilio account
const String TWILIO_ACCOUNT_SID = "xxxxxxxxxxxxxxxxxx";
// the Auth Token from your Twilio account
const String TWILIO_AUTH_TOKEN = "xxxxxxxxxxxxxxxxx";
// only act on messages sent from this phone number. (e.g. 15415551212)
const String FROM_PHONE_NUMBER = "xxxxxxxxxxx";
// how often (in milliseconds) to check for new SMS messages.
const unsigned long SMS_CHECK_PERIOD = 60000;
// keep track of when we last checked for new messages
// (initialize it to SMS_CHECK_PERIOD seconds ago so
// we do the first check as soon as the sketch starts.)
unsigned long lastSMSCheckTime = -SMS_CHECK_PERIOD;
// keep track of the ID of the last SMS message we processed.
// (we only need to process newer messages)
String lastSid;
// we'll be turning the LED built in to the Yún on and off
// to simulate controlling some device. That LED is on pin 13.
int LED_PIN = 13;
int numRuns = 1; // execution count, so this doesn't run forever
int maxRuns = 10; // the max number of times the Twitter HomeTimeline Choreo should run
void setup() {
Serial.begin(9600);
// for debugging, wait until a serial console is connected
delay(4000);
while(!Serial);
// tell the board to treat the LED pin as an output.
pinMode(LED_PIN, OUTPUT);
// start with the LED off
digitalWrite(LED_PIN, LOW);
// initialize the connection to Linux.
Bridge.begin();
// Twilio will report old SMS messages. We want to
// ignore any existing control messages when we start.
Serial.println("Ignoring any existing control messages...");
checkForMessages(true);
}
void loop()
{
// get the number of milliseconds the CPU has been running.
unsigned long now = millis();
// see if it's time to check for new SMS messages.
if (now - lastSMSCheckTime >= SMS_CHECK_PERIOD) {
// it's time to check for new messages
// save this time so we know when to check next
lastSMSCheckTime = now;
if (numRuns <= maxRuns) {
Serial.println("Checking for new SMS messages - Run #" + String(numRuns++));
// execute the choreo and don't ignore control messages.
checkForMessages(false);
} else {
Serial.println("Already ran " + String(maxRuns) + " times.");
}
}
}
/*
This function executes the Twilio > SMSMessages > ListMessages choreo
and processes the results.
If ignoreCommands is 'true', this function will read and process messages
updating 'lastSid', but will not actually take any action on any commands
found. This is so we can ignore any old control messages when we start.
If ignoreCommands is 'false', control messages WILL be acted on.
*/
void checkForMessages(bool ignoreCommands) {
// we need a TembooChoreo object to send a Choreo request to Temboo
TembooChoreo ListMessagesChoreo;
ListMessagesChoreo.begin();
// set Temboo account credentials
ListMessagesChoreo.setAccountName(TEMBOO_ACCOUNT);
ListMessagesChoreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
ListMessagesChoreo.setAppKey(TEMBOO_APP_KEY);
// identify the Temboo Library choreo to run (Twilio > SMSMessages > ListMessages)
ListMessagesChoreo.setChoreo("/Library/Twilio/SMSMessages/ListMessages");
// set the choreo inputs
// see https://www.temboo.com/library/Library/Twilio/SMSMessages/ListMessages/
// for complete details about the inputs for this Choreo
// the first input is a your Twilio AccountSID
ListMessagesChoreo.addInput("AccountSID", TWILIO_ACCOUNT_SID);
// next is your Twilio Auth Token
ListMessagesChoreo.addInput("AuthToken", TWILIO_AUTH_TOKEN);
// we only want to know about messages sent from our designated phone number
ListMessagesChoreo.addInput("From", FROM_PHONE_NUMBER);
// Twilio can return information about up to 1000 messages at a time.
// we're only interested in the 3 most recent ones. Note that if
// this account receives lots of messages in quick succession,
// (more than 3 per minute in this case), we might miss some control
// messages. But if we request too many messages, we might run out of
// memory on the Arduino side of the Yún.
ListMessagesChoreo.addInput("PageSize", "3");
// We want the response in XML format to process with our
// XPath output filters.
ListMessagesChoreo.addInput("ResponseFormat", "xml");
// we don't want everything from the output, just the
// message IDs (the Sids) and the message texts
ListMessagesChoreo.addOutputFilter("sid", "Sid", "Response");
ListMessagesChoreo.addOutputFilter("text", "Body", "Response");
// tell the Choreo to run and wait for the results. The
// return code (returnCode) will tell us whether the Temboo client
// was able to send our request to the Temboo servers
unsigned int returnCode = ListMessagesChoreo.run();
// a return code of zero (0) means success
if (returnCode == 0) {
// Need a string to hold the list of message IDs.
String messageSids;
// Need a string to hold the texts of the messages.
String messageTexts;
// when the choreo results are available, process them.
// the output filters we specified will return comma delimited
// lists containing the Sids and texts of the messages
// from our designated phone number.
while(ListMessagesChoreo.available()) {
// output names are terminated with '\x1F' characters.
String name = ListMessagesChoreo.readStringUntil('\x1F');
name.trim();
//Serial.println(name);
// output values are terminated with '\x1E' characters.
String data = ListMessagesChoreo.readStringUntil('\x1E');
data.trim();
//Serial.println(data);
// assign the data to the appropriate string based on the name
if (name == "sid") {
messageSids = data;
} else if (name == "text") {
messageTexts = data;
}
}
// done reading output, close the Choreo to free up resources.
ListMessagesChoreo.close();
// parse the comma delimited lists of messages and Sids
processMessages(messageTexts, messageSids, ignoreCommands);
} else {
// a non-zero return code means there was an error
// read and print the error message
while(ListMessagesChoreo.available()) {
char c = ListMessagesChoreo.read();
Serial.print(c);
}
}
}
/*
This function processes the lists of message texts and Sids.
If a message contains a comma as part of the
message text, that message will be enclosed in double quotes
(") in the list. Example:
A message,"Hey, now",Another message text
If the message contains double quotes, it will be enclosed in
double quotes AND the internal quotes will be doubled.
Example:
"Hi ""Sam"" the man", Led on
NOTE! We are assuming that Twilio returns more recent messages
first. This isn't officially documented by Twilio, but we've
not seen any other case.
'messageTexts' is a String containing a comma separated list of
message texts with commas and quotes escaped as described above.
'messageSids' is a String containing a comma separated list of
message Sids. Sids should not contain embedded commas or quotes.
'ignoreCommands' is a boolean. 'true' means and control messages
will not be acted upon. 'false' means control messages will be
acted upon in the usual way.
*/
void processMessages(String messageTexts, String messageSids, bool ignoreCommands) {
// proceed if we received at least one message
if (messageSids.length() > 0) {
int i = -1;
int sidsStart = 0;
int textsStart = 0;
String sid;
String text;
bool ledUpdated = false;
// go through the list until we run out of items
// or otherwise know we can stop
do {
// Output filter list items are separated by commas
// find the start of the next item in the list
i = messageSids.indexOf(',', sidsStart);
if (i >= 0) {
//extract a single Sid from the list.
sid = messageSids.substring(sidsStart, i);
sidsStart = i + 1;
// find the start of the next text in the list.
// Note that we have to be prepared to handle embedded
// quotes and commans in the message texts.
// The standard Arduino String class doesn't handle
// this, so we have to write our own function to do it.
i = quotedIndexOf(messageTexts, ',', textsStart);
if (i >= 0) {
// extract a single message text from the list.
text = messageTexts.substring(textsStart, i);
textsStart = i + 1;
// process the Sid and text to see if it's a
// control message.
ledUpdated = processMessage(sid, text, ignoreCommands);
}
} else {
// the last item in the lists won't have a comma at the end,
// so we have to handle them specially.
// Since we know this is the last item, we can just
// take the rest of the string for the Sid and text.
sid = messageSids.substring(sidsStart);
text = messageTexts.substring(textsStart);
// process the last item.
ledUpdated = processMessage(sid, text, ignoreCommands);
}
// keep going until either we run out of list items
// or we run into a message we processed on a previous run.
} while ((i >=0) && (sid != lastSid));
// print what we've found to the serial monitor,
// just so we can see what's going on.
if (sid == lastSid) {
if (ledUpdated)
Serial.println("Control message processed.");
else
Serial.println("No new control messages received.");
} else {
Serial.println("No control messages received.");
}
} else {
Serial.println("No messages found");
}
}
/*
This function knows how to tell if a message is a control message
or not. It also knows know to control whatever it is we're controlling
(the state of the LED on pin 13 in this case.)
A message with the text "LED ON" turns the LED on.
A message with the text "LED OFF" turns the LED off.
(Case is ignored.)
If 'ignoreCommands' is true, the actions described above will NOT
take place.
It also updates the 'lastSid' global variable when
a control message is processed.
It returns 'true' if the message was a control message, and
'false' if it wasn't or if we've already processed this message.
*/
bool processMessage(String sid, String text, bool ignoreCommands) {
// a flag to indicate whether this was a control message or not
bool ledUpdated = false;
// if we haven't already processed this message
if (sid != lastSid) {
if (text.equalsIgnoreCase("LED ON")) {
if (!ignoreCommands) {
//turn on the LED
digitalWrite(LED_PIN, HIGH);
Serial.println("LED ON");
}
ledUpdated = true;
} else if (text.equalsIgnoreCase("LED OFF")) {
if (!ignoreCommands) {
//turn off the LED
digitalWrite(LED_PIN, LOW);
Serial.println("LED OFF");
}
ledUpdated = true;
}
// If the LED state was updated, remember the Sid if this message.
if (ledUpdated)
lastSid = sid;
}
return ledUpdated;
}
/*
This function finds the index of a delimiter character in a String,
ignoring delimiters that appear inside double-quotes.
*/
int quotedIndexOf(String s, char delim, int start) {
bool inQuotes = false;
char c;
int index = -1;
const char QUOTE = '"';
do {
c = s[start++];
if (c == QUOTE)
inQuotes = !inQuotes;
else if (c == delim && !inQuotes)
index = --start;
} while ((c != '\0') && (index < 0));
return index;
}
/*
IMPORTANT NOTE: TembooAccount.h:
TembooAccount.h is a file referenced by this sketch that contains your Temboo account information.
You'll need to edit the placeholder version of TembooAccount.h included with this example sketch,
by inserting your own Temboo account name and app key information. The contents of the file should
look like:
#define TEMBOO_ACCOUNT "myTembooAccountName" // your Temboo account name
#define TEMBOO_APP_KEY_NAME "myFirstApp" // your Temboo app key name
#define TEMBOO_APP_KEY "xxx-xxx-xxx-xx-xxx" // your Temboo app key
You can find your Temboo App Key information on the Temboo website,
under My Account > Application Keys
The same TembooAccount.h file settings can be used for all Temboo SDK sketches.
Keeping your account information in a separate file means you can save it once,
then just distribute the main .ino file without worrying that you forgot to delete your credentials.
*/

View File

@ -1,5 +0,0 @@
#define TEMBOO_ACCOUNT "myTembooAccountName" // your Temboo account name
#define TEMBOO_APP_KEY_NAME "myFirstApp" // your Temboo app key name
#define TEMBOO_APP_KEY "xxx-xxx-xxx-xx-xxx" // your Temboo app key

View File

@ -1,328 +0,0 @@
/*
SendDataToMySQL
Demonstrates storing and reading values in a MySQL database using
the Temboo Arduino Yún SDK. This example will periodically
update a MySQL instance with dummy sensor values from the Yún, and
then read those values back from the database.
Check out the latest Arduino & Temboo examples and support docs at http://www.temboo.com/arduino
A Temboo account and application key are necessary to run all Temboo examples.
If you don't already have one, you can register for a free Temboo account at
http://www.temboo.com
To use this example, you'll need a MySQL instance. These instructions
assume that you are using an Amazon RDS instance in the "US East"
region. For details on how to use a database hosted elsewhere, see
http://temboo.com/library/Library/MySQL
To configure an RDS MySQL instance for Temboo connectivity:
1. If you don't already have one, create an Amazon AWS account and
a new MySQL RDS instance. The instructions at
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.html
will guide you through this process. Be sure to select the "US East (N. Virginia)"
region in the dropdown menu in the upper right side of the RDS Management Console
before creating the new instance.
2. Configure your RDS instance by adding a security rule to allow access
by Temboo. If you're familiar with the RDS command line tools,
you can do so using the instructions at https://www.temboo.com/library/Library/MySQL/
If you're not familiar with the RDS command line tools, the following steps
will guide you through this process using a Temboo Choreo:
-Obtain your AWS Access Key ID and Secret Access Key from the "Security Credentials"
pane of the AWS management console. If you haven't yet created an Access Key, you
will be able to do so from this interface.
-Log in to your Temboo account at https://www.temboo.com/login
-Navigate to https://www.temboo.com/library/Library/Amazon/RDS/AuthorizeDBSecurityGroupIngress/
-Turn on Run Mode, and enter the following inputs:
AWSAccessKeyId: your AWS access key
AWSSecretKeyId: your AWS secret key
CIDRIP: (leave empty)
DBSecurityGroupName: your RDS DBSecurityGroup name
EC2SecurityGroupName: Temboo Access
EC2SecurityGroupOwnerId: 114370834540
-Click the "Try it Out" button. If all went well, you should see an XML document
in the "Output" section of the Choreo description page listing the access permissions
in your RDS security group. Temboo should now have access to your RDS database.
3. To run the SendDataToMySQL sketch, you'll need the following information
about your database. These values can be found on the RDS Management Console:
-The address of the DB server (eg, somename.abc3xy6ijklmn.us-east-1.rds.amazonaws.com)
-The database name
-A username for a user with read, write, and create access to the DB
-The password for that user
Substitute these values into the DATABASE_SERVER, DATABASE_NAME, DATABASE_USERNAME,
and DATABASE_PASSWORD constants in the sketch.
When you run the sketch, it will attempt to create a new table named "readings" in the
database if it doesn't already exist. The table contains two columns: an unsigned INT
column named "cpu_time" and an INT column named "sensor_value".
This example assumes basic familiarity with Arduino sketches, and that your Yún is connected
to the Internet.
Looking for another API to use with your Arduino Yún? We've got over 100 in our Library!
This example code is in the public domain.
*/
#include <Bridge.h>
#include <Temboo.h>
#include "TembooAccount.h" // contains Temboo account information,
// as described in the footer comment below
/*** SUBSTITUTE YOUR VALUES BELOW: ***/
// Note that for additional security and reusability, you could
// use #define statements to specify these values in a .h file.
const String DATABASE_SERVER = "server-address-of-your-MySQL-instance";
const String DATABASE_NAME = "your-MySQL-database-name";
const String DATABASE_USERNAME = "your-MySQL-user-name";
const String DATABASE_PASSWORD = "your-MySQL-user-password";
// the name of the table to write to and read from
const String DATABASE_TABLE_NAME = "readings";
// how often to run the Choreo (in milliseconds)
const unsigned long RUN_INTERVAL_MILLIS = 60000;
// the last time we ran the Choreos (initialized to 60 seconds ago,
// so the Choreos are run immediately when we start up)
unsigned long lastRun = (unsigned long)-60000;
// a flag to indicate if we were able to create the table
// (or that it already existed)
bool haveTable = false;
void setup() {
// for debugging, wait until a serial console is connected
Serial.begin(9600);
delay(4000);
while(!Serial);
Serial.print("Initializing the bridge...");
Bridge.begin();
Serial.println("OK");
// make sure the table we need exists or create it if it doesn't
// (see the comments in the createTable function for details)
unsigned int result = createTable();
// set the 'haveTable' flag to true on success,
// or false if there was a problem creating the table
haveTable = (result == 0);
}
void loop()
{
// get the number of milliseconds this sketch has been running
unsigned long now = millis();
// run again if it's been RUN_INTERVAL_MILLIS milliseconds since we last ran
if (now - lastRun >= RUN_INTERVAL_MILLIS) {
// remember 'now' as the last time we ran the choreo
lastRun = now;
// do the database write/read only if we have the table.
if (haveTable) {
// get the value we want to add to our table
int sensorValue = getSensorValue();
// add a record containing the cpu time and sensor value
appendRow(now, sensorValue);
// Read the values just written to verify that they really
// did get sent to the database. (Not necessary in a real
// sketch, but done here to demonstrate retrieving data.)
retrieveRow(now);
} else {
Serial.println("Table creation failed, not appending row.");
}
}
}
/*
* createTable is a function that executes a SQL statement to
* create a table with the correct columns needed for this sketch.
*/
unsigned int createTable() {
Serial.print("Creating table '" + DATABASE_TABLE_NAME + "' (if needed)...");
// We need a table with columns to contain the cpu time and the sensor value.
// cpu time is an 'unsigned long' which is 4 bytes on the Yún,
// so an INT UNSIGNED in MySQL will hold any possible value.
// Our sensor values are 'int' values on the Yún,
// so an INT in MySQL will hold all possible values.
// Create a String containing the SQL statement to create the table.
String sql = "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE_NAME + " (cpu_time INT UNSIGNED, sensor_value INT);";
// Send the SQL to Temboo so it can forward it to your database.
unsigned int result = executeSQLCommand(sql, false);
// If there was an error, the executeSQLCommand function will have
// printed it to the Serial console. Otherwise, print OK.
if (result == 0) {
Serial.println("OK");
}
return result;
}
/*
* appendRow is a function that executes a SQL statement to
* insert a new row of data into the database.
* cpuTime is the value to be inserted into the cpu_time column
* value is the value wot be inserted into the sensor_value column
*/
unsigned int appendRow(unsigned long cpuTime, int value) {
Serial.print("Inserting row " + String(cpuTime) + ", " + String(value) + "...");
// Create a String containing the SQL statement to insert a row.
String sql = "INSERT " + DATABASE_TABLE_NAME + " VALUES (" + cpuTime + "," + value + ");";
// Send the SQL to Temboo so it can forward it to your database.
unsigned int result = executeSQLCommand(sql, false);
// If there was an error, the executeSQLCommand function will have
// printed it to the Serial console. Otherwise, print OK.
if (result == 0) {
Serial.println("OK");
}
return result;
}
/*
* retrieveRow is a function that executes a SQL statement to
* retrieve a row of data from the database.
* cpuTime is the cpu_time value of the row to be retrieved.
* (note that it must exactly match the value stored.)
*/
unsigned int retrieveRow(unsigned long cpuTime) {
Serial.println("Retrieving row with time " + String(cpuTime) + "...");
// Create a String containing the SQL statement to retrieve a row.
String sql = "SELECT * FROM " + DATABASE_TABLE_NAME + " WHERE cpu_time = '" + cpuTime + "';";
// Send the SQL to Temboo so it can forward it to your database.
// In this case, we want to print the raw output we get from
// Temboo. This is just to demonstrate that the data really did
// get written to the database.
unsigned int result = executeSQLCommand(sql, true);
return result;
}
/*
* executeSQLCommand is a function for sending SQL statements to
* Temboo for execution on your database.
* sql is a String containing the SQL statement to be executed.
* showOutput is a boolean flag which if set to 'true' will cause
* the raw Choreo results to be printed to the Serial console.
*/
unsigned int executeSQLCommand(String sql, bool showOutput) {
// Create a TembooChoreo object
TembooChoreo choreo;
// Initialize the Choreo object.
choreo.begin();
// set Temboo account credentials
choreo.setAccountName(TEMBOO_ACCOUNT);
choreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
choreo.setAppKey(TEMBOO_APP_KEY);
// specify the Choreo to be run
choreo.setChoreo("/Library/MySQL/RunCommand");
// add inputs specifying the RDS endpoint address
// and the database name within that RDS instance
choreo.addInput("Server", DATABASE_SERVER);
choreo.addInput("DatabaseName", DATABASE_NAME);
// add inputs for the MySQL user credentials
choreo.addInput("Username", DATABASE_USERNAME);
choreo.addInput("Password", DATABASE_PASSWORD);
// add the SQL command to be executed
choreo.addInput("SQL", sql);
// run the Choreo and wait for the results
// The return code (returnCode) will indicate success or failure
unsigned int returnCode = choreo.run();
// return code of zero (0) means success
if (returnCode == 0) {
// print the raw output if requested.
if (showOutput) {
while (choreo.available()) {
char c = choreo.read();
Serial.print(c);
}
}
} else {
// return code of anything other than zero means failure
// read and display any error messages
while (choreo.available()) {
char c = choreo.read();
Serial.print(c);
}
Serial.println("");
}
choreo.close();
return returnCode;
}
/*
* getSensorValue is a function to simulates reading the value of a sensor
*/
int getSensorValue() {
Serial.print("Reading sensor value...");
int value = analogRead(A0);
Serial.println("OK");
return value;
}
/*
IMPORTANT NOTE: TembooAccount.h:
TembooAccount.h is a file referenced by this sketch that contains your Temboo account information.
You'll need to edit the placeholder version of TembooAccount.h included with this example sketch,
by inserting your own Temboo account name and app key information. The contents of the file should
look like:
#define TEMBOO_ACCOUNT "myTembooAccountName" // your Temboo account name
#define TEMBOO_APP_KEY_NAME "myFirstApp" // your Temboo app key name
#define TEMBOO_APP_KEY "xxx-xxx-xxx-xx-xxx" // your Temboo app key
You can find your Temboo App Key information on the Temboo website,
under My Account > Application Keys
The same TembooAccount.h file settings can be used for all Temboo SDK sketches.
Keeping your account information in a separate file means you can share the main .ino file without worrying
that you forgot to delete your credentials.
*/

View File

@ -1,4 +0,0 @@
#define TEMBOO_ACCOUNT "myTembooAccountName" // your Temboo account name
#define TEMBOO_APP_KEY_NAME "myFirstApp" // your Temboo app key name
#define TEMBOO_APP_KEY "xxx-xxx-xxx-xx-xxx" // your Temboo app key