Create a gist now

Instantly share code, notes, and snippets.

anonymous /cowbell.agent.nut
Created Apr 4, 2015

What would you like to do?
Internet of Cowbell
#require "Bullwinkle.class.nut:1.0.0"
#require "Twitter.class.nut:1.0.0"
const CONSUMER_KEY = ""
const CONSUMER_SECRET = ""
const ACCESS_TOKEN = ""
const ACCESS_SECRET = ""
const PROJURL = "http://hackaday.io/project/5089";
class Persist {
cache = null;
function read(key = null, def = null) {
if (cache == null) {
cache = server.load();
}
return (key in cache) ? cache[key] : def;
}
function write(key, value) {
if (cache == null) {
cache = server.load();
}
if (key in cache) {
if (cache[key] != value) {
cache[key] <- value;
server.save(cache);
}
} else {
cache[key] <- value;
server.save(cache);
}
return value;
}
}
twitter <- Twitter(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET);
bullwinkle <- Bullwinkle(); // create bullwinkle object
bullwinkle.set_timeout(10); // set default timeout (seconds)
bullwinkle.set_retries(3); // set default number of retries
p <- Persist();
cnt <- p.read("cnt", 0);
script <- ["th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"];
twitter.stream("#morecowbell", function(tweetData){
bullwinkle.send("ring", null);
p.write("cnt", ++cnt);
local tweetString;
local roll = (math.rand() % 10);
switch ( roll ) {
case 0:
tweetString = format("@%s Somewhere in Los Altos, CA a Cowbell just rang for the %i%s time because of you. Checkout %s", tweetData.user.screen_name, cnt, script[cnt % 10], PROJURL);
break;
case 1:
tweetString = format("@%s I rang my Cowbell for the %i%s time, but that one was just for you. Checkout %s", tweetData.user.screen_name, cnt, script[cnt % 10], PROJURL);
break;
case 2:
tweetString = format("@%s You're the %i%s person to ask for more cowbell since April 2nd, 2015. Checkout %s", tweetData.user.screen_name, cnt, script[cnt % 10], PROJURL);
break;
case 3:
tweetString = format("@%s You asked for Cowbell. I delivered Cowbell. Checkout %s", tweetData.user.screen_name, PROJURL);
break;
case 4:
tweetString = format("@%s Cowbell persciption filled. If you experience fever, seek medical attention. Checkout %s", tweetData.user.screen_name, PROJURL);
break;
case 5:
tweetString = format("@%s What is the Internet of Cowbell? Checkout %s", tweetData.user.screen_name, PROJURL);
break;
case 6:
tweetString = format("@%s You just rung an Internet connected Cowbell. The future is here. Checkout %s", tweetData.user.screen_name, PROJURL);
break;
case 7:
tweetString = format("@%s I literally just rung a Cowbell for you. You're welcome. Checkout %s", tweetData.user.screen_name, PROJURL);
break;
case 8:
tweetString = format("@%s Do you ring or hit a Cowbell? Either way I just did it for you. Checkout %s", tweetData.user.screen_name, PROJURL);
break;
case 9:
default:
tweetString = format("@%s By the power of the Internet, I rung a Cowbell just for you. Checkout %s", tweetData.user.screen_name, PROJURL);
break;
}
// Log the Tweet, and who tweeted it (there is a LOT more info in tweetData)
server.log(format("%s - %s\n%s", tweetData.text, tweetData.user.screen_name,tweetString))
twitter.tweet(tweetString);
});
#require "Bullwinkle.class.nut:1.0.0"
// Use the Connection Class to stay online all the time
class Connection {
static CONNECTION_TIMEOUT = 30;
static CHECK_TIMEOUT = 5;
static MAX_LOGS = 100;
connected = null;
connecting = false;
stayconnected = true;
reason = null;
callbacks = null;
blinkup_timer = null;
logs = null;
// .........................................................................
constructor(_do_connect = true) {
callbacks = {};
logs = [];
server.setsendtimeoutpolicy(RETURN_ON_ERROR, WAIT_TIL_SENT, CONNECTION_TIMEOUT);
connected = server.isconnected();
imp.wakeup(CHECK_TIMEOUT, _check.bindenv(this));
if (_do_connect && !connected) imp.wakeup(0, connect.bindenv(this));
else if (connected) imp.wakeup(0, _reconnect.bindenv(this));
}
// .........................................................................
function _check() {
imp.wakeup(CHECK_TIMEOUT, _check.bindenv(this));
if (!server.isconnected() && !connecting && stayconnected) {
// We aren't connected or connecting, so we should try
_disconnected(NOT_CONNECTED, true);
}
}
// .........................................................................
function _disconnected(_reason, _do_reconnect = false) {
local fireevent = connected;
connected = false;
connecting = false;
reason = _reason;
if (fireevent && "disconnected" in callbacks) callbacks.disconnected();
if (_do_reconnect) connect();
}
// .........................................................................
function _reconnect(_state = null) {
if (_state == SERVER_CONNECTED || _state == null) {
connected = true;
connecting = false;
// Dump the logs
while (logs.len() > 0) {
local logo = logs[0];
logs.remove(0);
local d = date(logo.ts);
local msg = format("%04d-%02d-%02d %02d:%02d:%02d UTC %s", d.year, d.month+1, d.day, d.hour, d.min, d.sec, logo.msg);
if (logo.err) server.error(msg);
else server.log(msg);
}
if ("connected" in callbacks) callbacks.connected(SERVER_CONNECTED);
} else {
connected = false;
connecting = false;
connect();
}
}
// .........................................................................
function connect(withblinkup = true) {
stayconnected = true;
if (!connected && !connecting) {
server.connect(_reconnect.bindenv(this), CONNECTION_TIMEOUT);
connecting = true;
}
if (withblinkup) {
// Enable BlinkUp for 60 seconds
imp.enableblinkup(true);
if (blinkup_timer) imp.cancelwakeup(blinkup_timer);
blinkup_timer = imp.wakeup(60, function() {
blinkup_timer = null;
imp.enableblinkup(false);
}.bindenv(this))
}
}
// .........................................................................
function disconnect() {
stayconnected = false;
server.disconnect();
_disconnected(NOT_CONNECTED, false);
}
// .........................................................................
function isconnected() {
return connected == true;
}
// .........................................................................
function ondisconnect(_disconnected = null) {
if (_disconnected == null) delete callbacks["disconnected"];
else callbacks["disconnected"] <- _disconnected;
}
// .........................................................................
function onconnect(_connected = null) {
if (_connected == null) delete callbacks["connected"];
else callbacks["connected"] <- _connected;
}
// .........................................................................
function log(msg, err=false) {
if (server.isconnected()) server.log(msg);
else logs.push({msg=msg, err=err, ts=time()})
if (logs.len() > MAX_LOGS) logs.remove(0);
}
// .........................................................................
function error(msg) {
log(msg, true);
}
}
cm <- Connection();
cm.onconnect(function(reason=null) { cm.log("Connected") });
cm.ondisconnect(function(reason=null) { cm.error("Disconnected") });
/******* Cowbell Code **************************/
cowbell <- hardware.pin7;
cowbell.configure(DIGITAL_OUT, 0);
bullwinkle <- Bullwinkle(); // create bullwinkle object
bullwinkle.set_timeout(10); // set default timeout (seconds)
bullwinkle.set_retries(3); // set default number of retries
bullwinkle.on("ring", function(context) {
cowbell.write(1);
imp.sleep(0.01);
cowbell.write(0);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment