Particle httpGet help?


(Dome) #1

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);
}

(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #2

Check out a few other Photon projects already posted for clues, perhaps?

Search :mag: “Photon”.


(Dome) #3

Thanks, I have been doing that all along… as far as I’ve seen, no one else is using httpGet, instead relying on devices that only communicate one way. I want two way communication.


(Juan Risso) #4

Hi Dome,
Some time ago I helped posting this library on Particle platform “HTTPCLIENT” whit this library you can make http calls directly from the Photon.
If you enable Oauth and endpoints on your SmartApp you would be able to send values directly from the Photon to the SmartApp without having to query the Photon regularly.


(Justin Wurth) #5

I am very interested in this myself. I currently don’t use this much as I am using an enerwave 7 button controller with one setup of lights and I don’t really look in the app to see status. I would like this for the spark/photon blinds project I had setup as it would allow me to create a smart app that is a little more intuitive.

I think what you are looking for is here:
https://docs.particle.io/reference/javascript/#publishing-event

I would think you would need to publish an event (var) to the particle cloud and then do an httpGet to grab that variable.


(Dome) #6

@juano2310 @jjhtpc Thanks, I will keep hacking at it. I’m a self-taught coder and am much more comfortable developing hardware than software. Java is not in my comfort zone but maybe this is my incentive to branch out and learn something new (or at least fail spectacularly!).


(Justin Wurth) #7

Oh and I thought of something else. I don’t know if you use IFTTT, but I find that it is often a great first step to prototype integration as direct connection sometimes requires coding and that is not always intuitive. IFTTT can look for a published event or look for a variable change and you can setup to trigger an event off that and then make something happen on ST or send yourself a text message.

This will help you at least determine if your publish is working properly.


(Dome) #8

I might just do that. When I developed my first Spark/Particle device I did use IFTTT as an intermediary for ST->P events, but did not see the need for the other direction at the time. I developed further and was able to remove the IFTTT segment for a direct link between ST and Particle. As for why I didn’t think to try this for the other direction, that’s beyond me. I guess I didn’t eat my Wheaties this morning.


(Dome) #9

Thank you for your suggestion. I think I got lost in the forest and couldn’t find the trees! I got it working with IFTTT. I would eventually like to take off those training wheels but this at least gets me moving with a workable solution today.


(Justin Wurth) #10

Ha that is exactly how I look at IFTTT training wheels, because all IFTTT is, is a simplified in between for two separate entities that need to be coded. If you can get it working that way there is a way through the API to directly code it.


(Jeff) #11

@juano2310 any chance you could point me in the direction of this library?
thanks!


(Juan Risso) #12

Hi @jdetmold,
If you go to https://build.particle.io/build after you log in, in the left hand column there is a one option that is libraries. Use the search tool to spot “HTTPCLIENT”. There are examples there too.
Also you can find it here. https://github.com/nmattisson/HttpClient


(Jeff) #13

Thanks a ton!
20char


(Justin Wurth) #14

@dome
Hey dome by chance could you post the code that worked both on spark and on smartthings.

I am planning on adding something similar to the blinds project and possibly the rgb solution and I am not one to reinvent the wheel. Any help is appreciated.

Thanks,

jjhtpc


(Jeff) #15

I agree if anyone has a demo of this working that would be very helpful!


(Justin Wurth) #16

OK I worked this out. I talk about it here.


(Jeff) #17

I have thus far had no luck getting this working with oauth and smartthings, any change you have or have seen any example code with this working with smart things?