I’ve been working on a device type for the Particle platform. The idea is an extension of my Smart Room Controller project I developed for the ThingShield.
I’m making great progress in how the Particle receives commands from SmartThings, but I’m finding that my lack of coding experience is impeding my progress in getting published events from the Particle into SmartThings. The key first step I’m looking to do is add a local switch to the Photon. I was planning to use httpGet and point it at my particle device’s API output, but I can’t get it working.
@juano2310, do you have any advice?
Device type code:
/**
* SmartThings/Particle Automation Node
* powered by Particle
*
* Author: @dome
* Big credit to: juano23@gmail.com
* Date: 2014-01-23
*/
preferences {
input("deviceId", "text", title: "Device ID")
input("token", "text", title: "Access Token")
}
// for the UI
metadata {
// Automatically generated. Make future change here.
definition (name: "SPAN", author: "dome") {
capability "Switch"
capability "Valve"
capability "Alarm"
capability "Water Sensor"
capability "Temperature Measurement"
command "red"
command "green"
command "blue"
command "dark"
command "white"
command "redalert"
command "flashgreen"
command "flashred"
command "flashblue"
command "flashorange"
command "flashyellow"
command "flashpurple"
command "flashwhite"
command "fadered"
command "fadegreen"
command "fadeblue"
command "fadeorange"
command "fadeyellow"
command "fadepurple"
command "fadewhite"
command "strobered"
command "strobegreen"
command "strobeblue"
command "strobewhite"
command "strobeorange"
command "strobeyellow"
command "strobepurple"
command "persistred"
command "persistgreen"
command "persistblue"
command "persistwhite"
command "persistorange"
command "persistyellow"
command "persistpurple"
command "dimred"
command "dimgreen"
command "dimblue"
command "dimwhite"
command "dimorange"
command "dimyellow"
command "dimpurple"
command "alertred"
command "alertgreen"
command "alertblue"
command "alertwhite"
command "alertorange"
command "alertyellow"
command "alertpurple"
command "beep1"
command "beep2"
command "beep3"
command "beep4"
command "siren1"
command "siren2"
command "siren3"
command "siren4"
command "modehome"
command "modeaway"
command "modenight"
command "modeguest"
command "modedebug"
}
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
standardTile("valve", "device.valve", width: 1, height: 1, canChangeIcon: true) {
state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0"
state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
}
standardTile("alarm", "device.alarm", canChangeIcon: false) {
state "off", label:'off', action:'alarm.both', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
}
main "switch"
details "switch","alarm","valve"
}
}
def parse(String description) {
if(message == "switch.on") {
sendEvent(name: "switch", value: "on")
descriptionText = "${device.displayName} is switched on"
}
log.error "This device does not support incoming events"
return null
}
def on() {
put '1'
sendEvent(name: "switch", value: "on")
log.debug "${device.displayName} is on"
}
def off() {
put '0'
sendEvent(name: "switch", value: "off")
sendEvent(name: "valve", value: "closed")
sendEvent(name: "alarm", value: "off")
log.debug "${device.displayName} is off"
}
def both() {
put '9'
sendEvent(name: "switch", value: "on")
sendEvent(name: "alarm", value: "both")
log.debug "${device.displayName} is in alarm"
}
def open() {
put '2'
sendEvent(name: "valve", value: "open")
log.debug "${device.displayName} has begun watering"
}
def close() {
put '3'
sendEvent(name: "valve", value: "closed")
log.debug "${device.displayName} has ceased watering"
}
def modehome() {
put '41'
log.debug "${device.displayName} has changed mode to Home"
}
def modenight() {
put '42'
log.debug "${device.displayName} has changed mode to Night"
}
def modeaway() {
put '43'
log.debug "${device.displayName} has changed mode to Away"
}
def modeguest() {
put '44'
log.debug "${device.displayName} has changed mode to Guest"
}
def modedebug() {
put '45'
log.debug "${device.displayName} has changed mode to Debug"
}
private put(span) {
//Spark Core API Call
httpPost(
uri: "https://api.particle.io/v1/devices/${deviceId}/spancommand",
body: [access_token: token, command: span],
) {response -> log.debug (response.data)}
}
private get() {
//Spark Core API Call
log.debug "get invoked"
httpGet("https://api.spark.io/v1/devices?access_token=${token}", spansend) { resp ->
resp.headers.each {
log.debug "${it.name} : ${it.value}"
}
}
}
def poll() {
log.debug "Executing 'poll'"
get()
checkSpark()
}
def refresh() {
log.debug "Executing 'refresh'"
get()
checkSpark()
}
// Get the sensor reading
private getReading() {
//Spark Core API Call
def readingClosure = { response ->
log.debug "Reading request was successful, $response.data.result"
sendEvent(name: "rssi", value: response.data.result)
}
httpGet("https://api.spark.io/v1/devices/${deviceId}/${sparkVar}?access_token=${token}", readingClosure)
}
// Check the Spark status on the polling schedule so not realtime unless refreshed
private checkStatus() {
int stat = 0
//Spark Core API Call
def readingClosure = { response -> response.data.each { core ->
if (core.id == deviceId) {
log.debug "Spark status check was successful, $core.connected"
sendEvent(name: "switch", value: core.connected ? "on" : "off")
stat = core.connected ? 1 : 0
}
}
}
httpGet("https://api.spark.io/v1/devices?access_token=${token}", readingClosure)
stat
}
/*
def params = [
uri: "https://api.particle.io",
path: "/v1/devices/events?access_token=${token}"
]
*/
void spanget() {
// httpGet(params) { resp ->
log.debug "spanget invoked"
httpGet("https://api.spark.io/v1/devices?access_token=${token}", spansend) { resp ->
resp.headers.each {
log.debug "${it.name} : ${it.value}"
}
log.debug "response contentType: ${resp.contentType}"
log.debug "response data: ${resp.data}"
if (resp == 1) {
log.debug "home"
}
}
}
def checkSpark() {
if (checkStatus()) {
getReading()
}
else {
sendEvent(name: "rssi", value: "-200")
}
}
Particle code:
int SPANcommand(String command);
int V1 = 7;
int sirenPin = 1;
bool test = FALSE;
bool light = FALSE;
String deviceType = "SRC";
//Options: SRC, SYC
String watering = "false";
String alarm = "false";
int startCountdown = 20; //In minutes
//Before conversion, 40000 = 1 minute
int countdown = 0;
void setup()
{
Particle.function("spancommand", SPANcommand);
// Particle.variable("watering", watering, STRING);
pinMode(V1, OUTPUT);
pinMode(sirenPin, OUTPUT);
digitalWrite(V1, LOW);
delay(10);
RGB.control(true);
//RGB.brightness();
RGB.color(0, 0, 255);
delay(500);
beep1();
//Particle.publish("restart");
Particle.publish("spansend", "restart");
Particle.publish("deviceType", deviceType);
RGB.color(0, 0, 0);
//TODO: set valve and switch to closed and off
}
void loop()
{
if (watering == "true")
{
countdown = countdown - 10;
if (countdown <= 0)
{
digitalWrite(V1, LOW);
watering = "false";
Particle.publish("spansend","closed");
RGB.color(0, 0, 0);
beep4();
}
}
delay(10);
if (test == TRUE)
{
if (light == TRUE) {
delay(10000);
RGB.color(0, 0, 0);
light = FALSE;
}
else if (light == FALSE) {
delay(10000);
RGB.color(255, 255, 255);
light = TRUE;
}
}
}
int SPANcommand(String command)
{
if (command == "1") {
digitalWrite(V1, HIGH);
watering = "true";
RGB.color(0, 255, 0);
countdown = startCountdown * 40000;
beep3();
beep3();
Particle.publish("spansend","open");
return 1;
}
else if (command == "0") {
digitalWrite(V1, LOW);
watering = "false";
beep4();
beep4();
Particle.publish("spansend","closed");
RGB.color(0, 0, 0);
return 0;
}
else if (command == "9") {
//alarm activation protocol
digitalWrite(V1, HIGH);
watering = "false";
beep4();
beep4();
Particle.publish("spansend","alarm");
RGB.color(255, 0, 0);
return 0;
}
else if (command == "41") {
Particle.publish("Mode","home");
RGB.color(0, 255, 0);
delay(500);
RGB.color(0, 0, 0);
return 0;
}
else if (command == "42") {
Particle.publish("Mode","night");
RGB.color(0, 0, 255);
delay(500);
RGB.color(0, 0, 0);
return 0;
}
else if (command == "43") {
Particle.publish("Mode","away");
RGB.color(255, 0, 0);
delay(500);
RGB.color(0, 0, 0);
return 0;
}
else if (command == "44") {
Particle.publish("Mode","guest");
RGB.color(0, 255, 100);
delay(500);
RGB.color(0, 0, 0);
return 0;
}
else if (command == "45") {
Particle.publish("Mode","debug");
RGB.color(255, 0, 255);
delay(500);
RGB.color(0, 0, 0);
return 0;
}
else {
beep2();
}
}
void beep1()
{
beep(4000, 50, 50);
beep(4000, 50, 0);
}
void beep2()
{
beep(4000, 50, 50);
beep(4000, 1000, 0);
}
void beep3()
{
beep(4000, 200, 50);
beep(4650, 500, 0);
}
void beep4()
{
beep(4125, 100, 50);
beep(4000, 500, 0);
}
void beep(int freq, int duration, int wait)
{
tone(sirenPin, freq);
delay(duration);
noTone(sirenPin);
delay(wait);
}