SpacebrewYun: added new example

This commit is contained in:
Federico Fissore 2013-07-18 14:07:39 +02:00
parent 36cc2c89e7
commit 92cb63b843
4 changed files with 591 additions and 0 deletions

View File

@ -0,0 +1,98 @@
#include <Bridge.h>
#include <SpacebrewYun.h>
/**
* Arduino Yun Spacebrew Library Example
*
* This example code is in the public domain.
*
* @date July 16, 2013
* @author Julio Terra
*
*/
SpacebrewYun sb = SpacebrewYun("aYun", "Arduino Yun spacebrew test");
int counter = 0;
long last = 0;
int interval = 2000;
void setup() {
Serial.begin(57600);
delay(4000);
while (!Serial) { Serial.println("connecting"); }
//Initialize Console and wait for port to open:
Bridge.begin();
Serial.println("Bridge Started");
Serial.println("Configuring Spacebrew Client");
sb.verbose(true);
sb.addPublish("string test", "string");
sb.addPublish("range test", "range");
sb.addPublish("boolean test", "boolean");
sb.addPublish("custom test", "crazy");
sb.addSubscribe("string test", "string");
sb.addSubscribe("range test", "range");
sb.addSubscribe("boolean test", "boolean");
sb.addSubscribe("custom test", "crazy");
sb.onRangeMessage(handleRange);
sb.onStringMessage(handleString);
sb.onBooleanMessage(handleBoolean);
sb.onCustomMessage(handleCustom);
sb.connect("sandbox.spacebrew.cc");
}
void loop() {
sb.monitor();
if ( sb.connected() ) {
if ( (millis() - last) > interval ) {
String test_str_msg = "testing, testing, ";
test_str_msg += counter;
counter ++;
sb.send("string test", test_str_msg);
sb.send("range test", 500);
sb.send("boolean test", true);
sb.send("custom test", "youre loco");
last = millis();
}
}
}
void handleRange (String route, int value) {
Serial.print("Range msg ");
Serial.print(route);
Serial.print(", value ");
Serial.println(value);
}
void handleString (String route, String value) {
Serial.print("String msg ");
Serial.print(route);
Serial.print(", value ");
Serial.println(value);
}
void handleBoolean (String route, boolean value) {
Serial.print("Boolen msg ");
Serial.print(route);
Serial.print(", value ");
Serial.println(value ? "true" : "false");
}
void handleCustom (String route, String value, String type) {
Serial.print("Custom msg ");
Serial.print(route);
Serial.print(" of type ");
Serial.print(type);
Serial.print(", value ");
Serial.println(value);
}

View File

@ -0,0 +1,356 @@
#include "SpacebrewYun.h"
SpacebrewYun::SpacebrewYun(const String& _name, const String& _description) {
name = _name;
description = _description;
server = "sandbox.spacebrew.cc";
port = 9000;
_connected = false;
_verbose = false;
_error_msg = false;
sub_name = "";
sub_msg = "";
sub_type = "";
read_name = false;
read_msg = false;
sub_name_max = 25;
sub_msg_max = 50;
for ( int i = 0; i < pidLength; i++ ) {
pid [i] = '\0';
}
for ( int i = 0; i < sbPidsLen; i++ ) {
sbPids [i] = '\0';
}
Console.buffer(64);
}
// boolean SpacebrewYun::_connected = false;
SpacebrewYun::OnBooleanMessage SpacebrewYun::_onBooleanMessage = NULL;
SpacebrewYun::OnRangeMessage SpacebrewYun::_onRangeMessage = NULL;
SpacebrewYun::OnStringMessage SpacebrewYun::_onStringMessage = NULL;
SpacebrewYun::OnCustomMessage SpacebrewYun::_onCustomMessage = NULL;
SpacebrewYun::OnSBOpen SpacebrewYun::_onOpen = NULL;
SpacebrewYun::OnSBClose SpacebrewYun::_onClose = NULL;
SpacebrewYun::OnSBError SpacebrewYun::_onError = NULL;
void SpacebrewYun::onOpen(OnSBOpen function){
_onOpen = function;
}
void SpacebrewYun::onClose(OnSBClose function){
_onClose = function;
}
void SpacebrewYun::onRangeMessage(OnRangeMessage function){
_onRangeMessage = function;
}
void SpacebrewYun::onStringMessage(OnStringMessage function){
_onStringMessage = function;
}
void SpacebrewYun::onBooleanMessage(OnBooleanMessage function){
_onBooleanMessage = function;
}
void SpacebrewYun::onCustomMessage(OnCustomMessage function){
_onCustomMessage = function;
}
void SpacebrewYun::onError(OnSBError function){
_onError = function;
}
void SpacebrewYun::addPublish(const String& name, const String& type) {
Publisher *p = new Publisher();
p->name = createString(name.length() + 1);
p->type = createString(type.length() + 1);
name.toCharArray(p->name, name.length() + 1);
type.toCharArray(p->type, type.length() + 1);
if (publishers == NULL){
publishers = p;
} else {
Publisher *curr = publishers;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = p;
}
}
void SpacebrewYun::addSubscribe(const String& name, const String& type) {
Subscriber *p = new Subscriber();
p->name = createString(name.length() + 1);
p->type = createString(type.length() + 1);
name.toCharArray(p->name, name.length() + 1);
type.toCharArray(p->type, type.length() + 1);
if (subscribers == NULL){
subscribers = p;
}
else {
Subscriber *curr = subscribers;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = p;
}
}
void SpacebrewYun::connect(String _server, int _port) {
server = _server;
port = _port;
killPids();
brew.begin("python"); // Process should launch the "curl" command
brew.addParameter("/usr/lib/python2.7/spacebrew/spacebrew.py"); // Process should launch the "curl" command
brew.addParameter("--server");
brew.addParameter(server);
brew.addParameter("--port");
brew.addParameter(String(port));
brew.addParameter("-n");
brew.addParameter(name);
brew.addParameter("-d");
brew.addParameter(description);
if (subscribers != NULL) {
Subscriber *curr = subscribers;
while(curr != NULL){
if (_verbose) {
Serial.print(F("Creating subcribers: "));
Serial.println(curr->name);
}
brew.addParameter("-s"); // Add the URL parameter to "curl"
brew.addParameter(curr->name); // Add the URL parameter to "curl"
brew.addParameter(","); // Add the URL parameter to "curl"
brew.addParameter(curr->type); // Add the URL parameter to "curl"
if (curr->next == NULL) curr = NULL;
else curr = curr->next;
}
}
if (publishers != NULL) {
Publisher *curr = publishers;
while(curr != NULL){
if (_verbose) {
Serial.print(F("Creating publishers: "));
Serial.println(curr->name);
}
brew.addParameter("-p"); // Add the URL parameter to "curl"
brew.addParameter(curr->name); // Add the URL parameter to "curl"
brew.addParameter(","); // Add the URL parameter to "curl"
brew.addParameter(curr->type); // Add the URL parameter to "curl"
if (curr->next == NULL) curr = NULL;
else curr = curr->next;
}
}
Console.begin();
brew.runAsynchronously();
while (!Console) { ; }
}
void SpacebrewYun::monitor() {
while (Console.available() > 0) {
char c = Console.read();
if (c == char(CONNECTION_START) && !_connected) {
_connected = true;
if (_verbose) {
Serial.print(F("Connected to spacebrew server at: "));
Serial.println(server);
Serial.print(F("Application name set to: "));
Serial.println(name);
}
if (_onOpen != NULL){
_onOpen();
}
}
else if (c == char(CONNECTION_END) && _connected) {
_connected = false;
if (_verbose) {
Serial.print(F("Disconnected from spacebrew server at: "));
Serial.println(server);
}
if (_onClose != NULL){
_onClose();
}
}
if (_verbose) {
if (c == char(CONNECTION_ERROR)) {
_error_msg = true;
Serial.println(F("ERROR :: with Spacebrew.py Connection ::"));
}
else if (_error_msg && c == char(MSG_END)) {
_error_msg = false;
Serial.println();
}
if (_error_msg) {
Serial.print(c);
}
}
if (_connected) {
if (c == char(MSG_START)) {
read_name = true;
} else if (c == char(MSG_DIV) || sub_name.length() > sub_name_max) {
read_name = false;
read_msg = true;
} else if (c == char(MSG_END) || sub_msg.length() > sub_msg_max) {
read_msg = false;
onMessage();
} else {
if (read_name == true) {
sub_name += c;
} else if (read_msg == true) {
sub_msg += c;
}
else if (_verbose) {
Serial.print(c);
}
}
}
}
}
boolean SpacebrewYun::connected() {
return SpacebrewYun::_connected;
}
void SpacebrewYun::verbose(boolean verbose = true) {
_verbose = verbose;
}
void SpacebrewYun::onMessage() {
if (subscribers != NULL) {
Subscriber *curr = subscribers;
while((curr != NULL) && (sub_type == "")){
if (sub_name.equals(curr->name) == true) {
sub_type = curr->type;
}
if (curr->next == NULL) curr = NULL;
else curr = curr->next;
}
}
if ( sub_type.equals("range") ) {
if (_onRangeMessage != NULL) {
_onRangeMessage( sub_name, int(sub_msg.toInt()) );
} else {
Serial.println(F("ERROR :: Range message received, no callback method is registered"));
}
} else if ( sub_type.equals("boolean") ) {
if (_onBooleanMessage != NULL) {
_onBooleanMessage( sub_name, ( sub_msg.equals("false") ? false : true ) );
} else {
Serial.println(F("ERROR :: Boolean message received, no callback method is registered"));
}
} else if ( sub_type.equals("string") ) {
if (_onStringMessage != NULL) {
_onStringMessage( sub_name, sub_msg );
} else {
Serial.println(F("ERROR :: String message received, no callback method is registered"));
}
} else {
if (_onCustomMessage != NULL) {
_onCustomMessage( sub_name, sub_msg, sub_type );
} else {
Serial.println(F("ERROR :: Custom message received, no callback method is registered"));
}
}
sub_name = "";
sub_msg = "";
sub_type = "";
}
void SpacebrewYun::send(const String& name, const String& value){
Console.print(char(29));
Console.print(name);
Console.print(char(30));
Console.print(value);
Console.print(char(31));
Console.flush();
true;
}
/**
* method that gets the pid of all spacebrew.py instances running on the linino.
*/
void SpacebrewYun::getPids() {
// request the pid of all python processes
pids.begin("python");
pids.addParameter("/usr/lib/python2.7/spacebrew/getProcPid.py"); // Process should launch the "curl" command
pids.run();
if (_verbose) {
Serial.println(F("Checking if spacebrew process already running"));
}
int sbPidsIndex = 0;
int pidCharIndex = 0;
char c = '\0';
while ( pids.available() > 0 ) {
c = pids.read();
if ( c >= '0' && c <= '9' ) {
pid[pidCharIndex] = c;
pidCharIndex = (pidCharIndex + 1) % pidLength;
}
else if ( (c == ' ' || c == '\n') && pidCharIndex > 0) {
sbPids[sbPidsIndex] = atoi(pid);
if ( sbPidsIndex < (sbPidsLen - 1) ) sbPidsIndex = (sbPidsIndex + 1);
for( int i = 0; i < pidLength; i++ ){
pid[i] = '\0';
pidCharIndex = 0;
}
}
}
}
/**
* method that kills all of the spacebrew.py instances that are running
* on the linino.
*/
void SpacebrewYun::killPids() {
getPids();
delay(400);
for (int i = 0; i < sbPidsLen; i ++) {
if (sbPids[i] > 0) {
char * newPID = itoa(sbPids[i], pid, 10);
if (_verbose) {
Serial.print(F("Stopping existing spacebrew processes with pids: "));
Serial.println(newPID);
}
Process p;
p.begin("kill");
p.addParameter("-9");
p.addParameter(newPID); // Process should launch the "curl" command
p.run(); // Run the process and wait for its termination
delay(400);
}
}
}

View File

@ -0,0 +1,122 @@
#ifndef YUNSPACEBREW_H
#define YUNSPACEBREW_H
#include "Arduino.h"
#include <Bridge.h>
#include <Console.h>
#include <Process.h>
enum SBmsg {
CONNECTION_START = char(28),
CONNECTION_END = char(27),
CONNECTION_ERROR = char(26),
MSG_START = char(29),
MSG_DIV = char(30),
MSG_END = char(31)
};
struct Publisher {
char *name;
char *type;
char *defaultValue;
Publisher * next;
};
struct Subscriber{
char *name;
char *type;
Subscriber * next;
};
int const pidLength = 6;
int const sbPidsLen = 4;
class SpacebrewYun {
public:
SpacebrewYun(const String&, const String&);
void addPublish(const String&, const String&);
void addSubscribe(const String&, const String&);
void connect(String, int);
void connect() { connect(server, port); };
void connect(String _server) { connect(String(_server), port); };
void monitor();
void onMessage();
boolean connected();
void send(const String&, const String&);
void send(const String& name, char * value) { send(name, String(value)); }
void send(const String& name, bool value){ send(name, (value ? "true" : "false")); };
void send(const String& name, int value) { send(name, String(value)); };
void send(const String& name, long value) { send(name, String(value)); };
void send(const String& name, float value) { send(name, String(value)); };
void verbose(boolean);
typedef void (*OnBooleanMessage)(String name, boolean value);
typedef void (*OnRangeMessage)(String name, int value);
typedef void (*OnStringMessage)(String name, String value);
typedef void (*OnCustomMessage)(String name, String value, String type);
typedef void (*OnSBOpen)();
typedef void (*OnSBClose)();
typedef void (*OnSBError)(int code, String message);
void onOpen(OnSBOpen function);
void onClose(OnSBClose function);
void onRangeMessage(OnRangeMessage function);
void onStringMessage(OnStringMessage function);
void onBooleanMessage(OnBooleanMessage function);
void onCustomMessage(OnCustomMessage function);
void onError(OnSBError function);
private:
Process brew;
String name;
String server;
String description;
boolean _connected;
boolean _error_msg;
boolean _verbose;
int port;
/**Output should be at least 5 cells**/
static OnBooleanMessage _onBooleanMessage;
static OnRangeMessage _onRangeMessage;
static OnStringMessage _onStringMessage;
static OnCustomMessage _onCustomMessage;
static OnSBOpen _onOpen;
static OnSBClose _onClose;
static OnSBError _onError;
Subscriber * subscribers;
Publisher * publishers;
String sub_name;
String sub_msg;
String sub_type;
boolean read_name;
boolean read_msg;
int sub_name_max;
int sub_msg_max;
Process pids;
char pid [6];
int sbPids [4];
void killPids();
void getPids();
static char * createString(int len){
char * out = ( char * )malloc( len + 1 );
return out;
}
};
#endif

View File

@ -0,0 +1,15 @@
SpacebrewYun KEYWORD1
addPublish KEYWORD2
addSubscribe KEYWORD2
connect KEYWORD2
verbose KEYWORD2
monitor KEYWORD2
onMessage KEYWORD2
send KEYWORD2
onRangeMessage KEYWORD2
onStringMessage KEYWORD2
onBooleanMessage KEYWORD2
onCustomMessage KEYWORD2
onOpen KEYWORD2
onClose KEYWORD2
onError KEYWORD2