Check out the details at our website: biffshocker.com
What?
During a Hackathon weekend, we got a chance to hack the DeLorean. Our teammate, Piers Ridyard had the idea for Biff Shocker combining SmartThings, Softlayer, Spark.io and IFTTT into a homebrew security system.
Prerequisites:
* SmartThings Starter Kit and Docs
* Spark io Core and SparkButton
* Dropcam
* Sonos Player
For SmartThings integration with Dropcam, Sonos, check out these (Connect) App:
* https://support.smartthings.com/hc/en-us/articles/201788114-Controlling-Dropcam-with-SmartThings
*https://support.smartthings.com/hc/en-us/articles/200927220-Connecting-Sonos-to-SmartThings
We used a simple ZigBee contact sensor on the SmartThings platform to tell us when the door is open or closed.
But how do we know if its us opening or Biff opening?
A Dropcam can also be integrated and be triggered by a SmartThings event.
Although there isn't recording done at the SmartThings platform, we can use the Dropcam alerts to setup zone alarm detections:
Untitled file
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
/**
* Big Turn ON
*
* Author: SmartThings
*/
definition(
name: "Big Turn ON",
namespace: "smartthings",
author: "SmartThings",
description: "Turn your lights on when the SmartApp is tapped or activated.",
category: "Convenience",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet@2x.png"
)
preferences {
section("When I touch the app, turn on...") {
input "switches", "capability.switch", multiple: true
}
}
def installed()
{
subscribe(location, changedLocationMode)
subscribe(app, appTouch)
}
def updated()
{
unsubscribe()
subscribe(location, changedLocationMode)
subscribe(app, appTouch)
}
def changedLocationMode(evt) {
log.debug "changedLocationMode: $evt"
switches?.on()
}
def appTouch(evt) {
def params = [
uri: 'https://api.spark.io/v1/devices/54ff6c066672524821281167/shockBiff',
headers: ['Authorization': 'Bearer 0fc47112a9191876ff0193170aaf3687b9a28557'],
body: 'command',
requestContentType: "application/x-www-form-urlencoded",
body: ["args":"blue"]
]
httpPost(params){ response ->
log.debug "Response Received: Status [$response.status]"
}
log.debug "appTouch: $evt"
switches?.on()
}
controlling Spark devices with node.js — Read More
Latest commit to the master branch on 3-16-2015
Download as zipUntitled file
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
// This #include statement was automatically added by the Spark IDE.
#include "SparkButton/SparkButton.h"
SparkButton b = SparkButton();
uint8_t button1 = 0;
uint8_t button2 = 0;
uint8_t button3 = 0;
uint8_t button4 = 0;
uint8_t buttonAll = 0;
int gaugeCount = 0;
int shockPin = D0;
int rainbowRemote(String command);
int ledOnRemote(String command);
int ledOffRemote(String command);
int ledAllOnRemote(String command);
int ledAllOffRemote(String command);
int gaugeRemote(String command);
// The code in setup() runs once when the device is powered on or reset. Used for setting up states, modes, etc
void setup() {
pinMode( shockPin, OUTPUT );
// Tell b to get everything ready to go
b.begin();
//Spark.function("ledOn", ledOnRemote);
//Spark.function("ledOff", ledOffRemote);
Spark.function("shockBiff", shockBiff);
Spark.function("allLedsOn", ledAllOnRemote);
Spark.function("allLedsOff", ledAllOffRemote);
Spark.function("rainbow", rainbowRemote);
Spark.function("gauge",gaugeRemote);
Spark.subscribe("buttonGauge",gaugeRemoteSub);
Spark.subscribe("gaugeCount",gaugeCounter);
// Spark.subscribe("shockBiff", shockBiff);
Spark.function("trigger",trigger);
//Spark.function("readX")
}
/* loop(), in contrast to setup(), runs all the time. Over and over again.
Remember this particularly if there are things you DON'T want to run a lot. Like Spark.publish() */
void loop() {
// shockBiff();
// delay(1000);
if(b.allButtonsOn()){
if(!buttonAll){
buttonAll = 1;
Spark.publish("allbuttons","all buttons pressed!", 60, PRIVATE);
b.rainbow(10);
delay(100);
b.allLedsOff();
}
}
else {buttonAll = 0;}
if(b.buttonOn(1)){
if(!button1){
button1 = 1;
Spark.publish("button1","button 1 pressed!", 60, PRIVATE);
b.ledOn(12,50,0,0);
delay(100);
b.ledOff(12);
}
}
else {button1 = 0;}
if(b.buttonOn(2)){
shockBiff("blah");
if(!button2){
button2 = 1;
Spark.publish("button2","button 2 pressed!", 60, PRIVATE);
b.ledOn(3,0,50,0);
delay(100);
b.ledOff(3);
}
}
else {button2 = 0;}
if(b.buttonOn(3)){
shockBiff("blah");
if(!button3){
button3 = 1;
Spark.publish("button3","button 3 pressed!", 60, PRIVATE);
b.ledOn(6,0,0,50);
delay(100);
b.ledOff(6);
}
}
else {button3 = 0;}
if(b.buttonOn(4)){
shockBiff("blah");
if(!button4){
button4 = 1;
Spark.publish("button4","button 4 pressed!", 60, PRIVATE);
b.ledOn(9,30,30,30);
delay(100);
b.ledOff(9);
}
}
else {button4 = 0;}
}
int rainbowRemote(String command)
{
if(command.equals("rainbow"))
{
// b.allLedsOn(150,0,0);
b.rainbow(10);
delay(100);
b.allLedsOff();
}
return 1;
}
// {
// b.rainbow(10);
// // char inputStr[64];
// // command.toCharArray(inputStr,64);
// // int i = atoi(inputStr);
// // long startMillis = millis();
// // while(millis() < startMillis + i*5000){
// // b.rainbow(30);
// // }
// return 1;
// }
int ledOnRemote(String command){
int i = 0;
char inputStr[64];
command.toCharArray(inputStr,64);
char *p = strtok(inputStr,",");
i = atoi(p);
p = strtok(NULL,",");
if(String(p).equals("red")){
b.ledOn(i,150,0,0);
}
else if(String(p).equals("green")){
b.ledOn(i,0,150,0);
}
else if(String(p).equals("blue")){
b.ledOn(i,0,0,150);
}
else if(String(p).equals("white")){
b.ledOn(i,150,150,150);
}
else {
//parse out CSV colors
uint8_t red = atoi(p);
p = strtok(NULL,",");
uint8_t grn = atoi(p);
p = strtok(NULL,",");
uint8_t blu = atoi(p);
b.ledOn(i,red,grn,blu);
}
return 1;
}
int ledOffRemote(String command){
char inputStr[64];
command.toCharArray(inputStr,64);
char *p = strtok(inputStr,",");
int i = atoi(p);
b.ledOff(i);
return 1;
}
int ledAllOnRemote(String command){
if(command.equals("red")){
b.allLedsOn(150,0,0);
}
else if(command.equals("green")){
b.allLedsOn(0,150,0);
}
else if(command.equals("blue")){
b.allLedsOn(0,0,150);
}
else if(command.equals("white")){
b.allLedsOn(150,150,150);
}
else if(command.equals("rainbow")){
b.rainbow(10);
}
else {
char inputStr[64];
command.toCharArray(inputStr,64);
char *p = strtok(inputStr,",");
int red = atoi(p);
p = strtok(NULL,",");
int grn = atoi(p);
p = strtok(NULL,",");
int blu = atoi(p);
p = strtok(NULL,",");
b.allLedsOn(red,grn,blu);
}
return 1;
}
int ledAllOffRemote(String command){
b.allLedsOff();
return 1;
}
int gaugeRemote(String command){
char temp[5];
command.toCharArray(temp,5);
//int level = map(atoi(temp),1,100,1,33);
int level = atoi(temp);
b.allLedsOff();
for(int i = 0; i < level+1; i++){
if(i < 12){
b.ledOn(i,0,40,0);
}
else if(i < 23){
b.ledOn(i-11,0,90,10);
}
else if(i < 34){
b.ledOn(i-22,20,20,0);
}
else if(i < 45){
b.ledOn(i-33,80,80,10);
}
else if(i < 56){
b.ledOn(i-44,30,0,0);
}
else if(i < 67){
b.ledOn(i-55,90,0,5);
}
delay(100);
}
return 1;
}
void gaugeRemoteSub(const char *event, const char *data)
{
gaugeRemote(String(data));
}
void gaugeCounter(const char *event, const char *data)
{
gaugeCount++;
gaugeRemote(String(gaugeCount));
}
int shockBiff(String command)
{
digitalWrite( shockPin, HIGH );
delay(3000);
digitalWrite( shockPin, LOW );
return 1;
}
int trigger(String command)
{
b.rainbow(10);
delay(100);
b.allLedsOff();
return 1;
}
Then all kinds of unsuspecting people started walking up:
We also used IFTTT to trigger cloud-enabled services
/**
* Big Turn ON
*
* Author: SmartThings
*/
definition(
name: "Big Turn ON",
namespace: "smartthings",
author: "SmartThings",
description: "Turn your lights on when the SmartApp is tapped or activated.",
category: "Convenience",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet@2x.png"
)
preferences {
section("When I touch the app, turn on...") {
input "switches", "capability.switch", multiple: true
}
}
def installed()
{
subscribe(location, changedLocationMode)
subscribe(app, appTouch)
}
def updated()
{
unsubscribe()
subscribe(location, changedLocationMode)
subscribe(app, appTouch)
}
def changedLocationMode(evt) {
log.debug "changedLocationMode: $evt"
switches?.on()
}
def appTouch(evt) {
def params = [
uri: 'https://api.spark.io/v1/devices/54ff6c066672524821281167/shockBiff',
headers: ['Authorization': 'Bearer 0fc47112a9191876ff0193170aaf3687b9a28557'],
body: 'command',
requestContentType: "application/x-www-form-urlencoded",
body: ["args":"blue"]
]
httpPost(params){ response ->
log.debug "Response Received: Status [$response.status]"
}
log.debug "appTouch: $evt"
switches?.on()
}
// This #include statement was automatically added by the Spark IDE.
#include "SparkButton/SparkButton.h"
SparkButton b = SparkButton();
uint8_t button1 = 0;
uint8_t button2 = 0;
uint8_t button3 = 0;
uint8_t button4 = 0;
uint8_t buttonAll = 0;
int gaugeCount = 0;
int shockPin = D0;
int rainbowRemote(String command);
int ledOnRemote(String command);
int ledOffRemote(String command);
int ledAllOnRemote(String command);
int ledAllOffRemote(String command);
int gaugeRemote(String command);
// The code in setup() runs once when the device is powered on or reset. Used for setting up states, modes, etc
void setup() {
pinMode( shockPin, OUTPUT );
// Tell b to get everything ready to go
b.begin();
//Spark.function("ledOn", ledOnRemote);
//Spark.function("ledOff", ledOffRemote);
Spark.function("shockBiff", shockBiff);
Spark.function("allLedsOn", ledAllOnRemote);
Spark.function("allLedsOff", ledAllOffRemote);
Spark.function("rainbow", rainbowRemote);
Spark.function("gauge",gaugeRemote);
Spark.subscribe("buttonGauge",gaugeRemoteSub);
Spark.subscribe("gaugeCount",gaugeCounter);
// Spark.subscribe("shockBiff", shockBiff);
Spark.function("trigger",trigger);
//Spark.function("readX")
}
/* loop(), in contrast to setup(), runs all the time. Over and over again.
Remember this particularly if there are things you DON'T want to run a lot. Like Spark.publish() */
void loop() {
// shockBiff();
// delay(1000);
if(b.allButtonsOn()){
if(!buttonAll){
buttonAll = 1;
Spark.publish("allbuttons","all buttons pressed!", 60, PRIVATE);
b.rainbow(10);
delay(100);
b.allLedsOff();
}
}
else {buttonAll = 0;}
if(b.buttonOn(1)){
if(!button1){
button1 = 1;
Spark.publish("button1","button 1 pressed!", 60, PRIVATE);
b.ledOn(12,50,0,0);
delay(100);
b.ledOff(12);
}
}
else {button1 = 0;}
if(b.buttonOn(2)){
shockBiff("blah");
if(!button2){
button2 = 1;
Spark.publish("button2","button 2 pressed!", 60, PRIVATE);
b.ledOn(3,0,50,0);
delay(100);
b.ledOff(3);
}
}
else {button2 = 0;}
if(b.buttonOn(3)){
shockBiff("blah");
if(!button3){
button3 = 1;
Spark.publish("button3","button 3 pressed!", 60, PRIVATE);
b.ledOn(6,0,0,50);
delay(100);
b.ledOff(6);
}
}
else {button3 = 0;}
if(b.buttonOn(4)){
shockBiff("blah");
if(!button4){
button4 = 1;
Spark.publish("button4","button 4 pressed!", 60, PRIVATE);
b.ledOn(9,30,30,30);
delay(100);
b.ledOff(9);
}
}
else {button4 = 0;}
}
int rainbowRemote(String command)
{
if(command.equals("rainbow"))
{
// b.allLedsOn(150,0,0);
b.rainbow(10);
delay(100);
b.allLedsOff();
}
return 1;
}
// {
// b.rainbow(10);
// // char inputStr[64];
// // command.toCharArray(inputStr,64);
// // int i = atoi(inputStr);
// // long startMillis = millis();
// // while(millis() < startMillis + i*5000){
// // b.rainbow(30);
// // }
// return 1;
// }
int ledOnRemote(String command){
int i = 0;
char inputStr[64];
command.toCharArray(inputStr,64);
char *p = strtok(inputStr,",");
i = atoi(p);
p = strtok(NULL,",");
if(String(p).equals("red")){
b.ledOn(i,150,0,0);
}
else if(String(p).equals("green")){
b.ledOn(i,0,150,0);
}
else if(String(p).equals("blue")){
b.ledOn(i,0,0,150);
}
else if(String(p).equals("white")){
b.ledOn(i,150,150,150);
}
else {
//parse out CSV colors
uint8_t red = atoi(p);
p = strtok(NULL,",");
uint8_t grn = atoi(p);
p = strtok(NULL,",");
uint8_t blu = atoi(p);
b.ledOn(i,red,grn,blu);
}
return 1;
}
int ledOffRemote(String command){
char inputStr[64];
command.toCharArray(inputStr,64);
char *p = strtok(inputStr,",");
int i = atoi(p);
b.ledOff(i);
return 1;
}
int ledAllOnRemote(String command){
if(command.equals("red")){
b.allLedsOn(150,0,0);
}
else if(command.equals("green")){
b.allLedsOn(0,150,0);
}
else if(command.equals("blue")){
b.allLedsOn(0,0,150);
}
else if(command.equals("white")){
b.allLedsOn(150,150,150);
}
else if(command.equals("rainbow")){
b.rainbow(10);
}
else {
char inputStr[64];
command.toCharArray(inputStr,64);
char *p = strtok(inputStr,",");
int red = atoi(p);
p = strtok(NULL,",");
int grn = atoi(p);
p = strtok(NULL,",");
int blu = atoi(p);
p = strtok(NULL,",");
b.allLedsOn(red,grn,blu);
}
return 1;
}
int ledAllOffRemote(String command){
b.allLedsOff();
return 1;
}
int gaugeRemote(String command){
char temp[5];
command.toCharArray(temp,5);
//int level = map(atoi(temp),1,100,1,33);
int level = atoi(temp);
b.allLedsOff();
for(int i = 0; i < level+1; i++){
if(i < 12){
b.ledOn(i,0,40,0);
}
else if(i < 23){
b.ledOn(i-11,0,90,10);
}
else if(i < 34){
b.ledOn(i-22,20,20,0);
}
else if(i < 45){
b.ledOn(i-33,80,80,10);
}
else if(i < 56){
b.ledOn(i-44,30,0,0);
}
else if(i < 67){
b.ledOn(i-55,90,0,5);
}
delay(100);
}
return 1;
}
void gaugeRemoteSub(const char *event, const char *data)
{
gaugeRemote(String(data));
}
void gaugeCounter(const char *event, const char *data)
{
gaugeCount++;
gaugeRemote(String(gaugeCount));
}
int shockBiff(String command)
{
digitalWrite( shockPin, HIGH );
delay(3000);
digitalWrite( shockPin, LOW );
return 1;
}
int trigger(String command)
{
b.rainbow(10);
delay(100);
b.allLedsOff();
return 1;
}
Comments
Please log in or sign up to comment.