Particle Photon DH and Apps

My understanding is:

The Xenon is simply a Mesh "player" -- it adds to a mesh, but it doesn't connect elsewhere.

The Argon and Boron are also Mesh "players" - but they have an additional radio to connect to somewhere else. Argon is WiFi and Boron uses cellular.

You could create a mesh of 10 Argons, but then you'd have paid more. You could have a mesh of 10 Xenons, but they wouldn't be wirelessly reachable.

In other words, the mesh portion is the same on all of them, with Xenon not having any external wireless portion.

I have a hacked together driver based on a device driver by Justin Wurth. Here is my bastardized version that is working for me.

// Copyright (c) <year>, <copyright holder>
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//     * Redistribution of this software in source or binary forms shall be free
//       of all charges or fees to the recipient of this software.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/**

 *  Spark Core

 *

 *  Author: Justin Wurth

 *  Date: 2014-09-19
/**
 * 
 *
 
 *
 */

 preferences {

    input("deviceId", "text", title: "Device ID")

    input("token", "text", title: "Access Token")

}


    metadata {
	   definition (name: "Spark/Photon WS2812b", namespace: "jjhtpc", author: "Justin Wurth") 
		{capability "Switch Level"
		capability "Color Control"
		capability "Color Temperature"
		capability "Switch"
        capability "Refresh"
        capability "Polling"
        attribute "colorName", "string"
	}
}

	// tile definitions
	
command "Red"

command "Green"

command "Brown"

command "Gigem"

command "Broncos"

command "effect6"


tiles {
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: false) {
			
	state "off", label: '${name}', action: "switch.on", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#ffffff"
			
	state "on", label: '${name}', action: "switch.off", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#79b821", iconColor: "#ffffff"
		
}

standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
        
	state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}		
     	
standardTile("Red", "device.Red") {
			
	state "Red", label: '${name}', action: "Red", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#d3ffd3", iconColor: "#ffffff"
}

standardTile("Green", "device.Green") {

	state "Green", label: '${name}', action: "Green", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#d3ffd3", iconColor: "#ffffff"
}

standardTile("Brown", "device.Brown") {
			
	state "Brown", label: '${name}', action: "Brown", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#d3ffd3", iconColor: "#ffffff"
}

standardTile("Gigem", "device.gigem") {
			
	state "Gigem", label: '${name}', action: "Gigem", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#d3ffd3", iconColor: "#ffffff"
}
       
standardTile("Broncos", "device.Broncos") {
			
	state "Broncos", label: '${name}', action: "Broncos", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#d3ffd3", iconColor: "#ffffff"
}

standardTile("effect6", "device.effect6") {
			
	state "effect6", label: '${name}', action: "effect6", icon: "st.Seasonal Winter.seasonal-winter-011", backgroundColor: "#d3ffd3", iconColor: "#ffffff"
}
       

//standardTile("color", "device.color") {
        	
//state "alert", label: '${name}', action: "tvdim", icon: "st.Lighting.light13", backgroundColor: "#ff0000", iconColor: "#ffffff"
       
//state "tvdim", label: '${name}', action: "moviedim", icon: "st.Lighting.light13", backgroundColor: "#d3d3d3", iconColor: "#ffffff"
 
//state "moviedim", label: '${name}', action: "alerts", icon: "st.Lighting.light13", backgroundColor: "#ffffff", iconColor: "#ffffff"
//}



controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 1, inactiveLabel: false, range:"(0..100)") {
		state "level", action:"switch level.setLevel"
	}

controlTile("rgbSelector", "device.color", "color", height: 3, width: 3, inactiveLabel: false) {
		state "color", action:"setColor"
    }


                
main(["switch"])   
details(["switch", "Red", "Green", "Brown", "Gigem", "Broncos", "effect6","levelSliderControl", "refresh", "rgbSelector"])
	
}




def parse(String description) {
	log.debug "This device does not support incoming events"
	return null
}
def off(){
	put '0'
    sendEvent(name: "switch", value: "off" )
    log.debug "switch is off"
}

def on() {
	put '1'
	sendEvent(name: "switch", value: "on" )
    log.debug "switch is on"
}

def Red() {
	put '2'
    sendEvent(name: "switch", value: "on" )
    log.debug "this device is on Red"
}

def Green() {
	put '3'
    sendEvent(name: "switch", value: "on" )
    log.debug "this device is on Green"
}


def Brown() {
	put '4'
    sendEvent(name: "switch", value: "on" )
    log.debug "this device is on Brown"
}

def Gigem() {
	put '5'
    sendEvent(name: "switch", value: "on" )
    log.debug "this device is on Gigem"
}

def Broncos() {
	put '6'
    sendEvent(name: "switch", value: "on" )
    log.debug "this device is on Broncos"
}

def effect6() {
	put '7'
    sendEvent(name: "switch", value: "on" )
    log.debug "this device is on effect6"
}

def setColor(value) {
	log.debug "setColor: ${value.hue} and setSaturation: ${value.saturation}"
    def rgb = rgbToShieldRgb(value.red, value.green, value.blue);
}

def rgbToShieldRgb(r,g,b){
	r = r
    b = b
    g = g
    put "$r,$g,$b"
    log.debug "Switch set to $r,$g,$b"
}

def setLevel(value){
	call "$value"
    log.debug "$value"
    
}



def poll() {
	log.debug "Executing 'poll'"
	 checkStatus ()	
}

def refresh() {
	log.debug "executing 'refresh'"
	checkStatus()

}
def checkStatus(){
	
	httpGet(uri: "https://api.particle.io/v1/devices/${deviceId}/checkStatus1?access_token=${token}",
    	contentType: 'application/json',)
    {resp ->           
            log.debug "resp data: ${resp.data}"
            log.debug "result: ${resp.data.result}"
		sendEvent(name: "switch", value: "${resp.data.result}" )
	}
}


private put(led) {

    //Spark Core API Call

    httpPost(

        uri: "https://api.particle.io/v1/devices/${deviceId}/led",

        body: [access_token: token, command: led],  

    )

}

private call(dim) {

    //Spark Core API Call

    httpPost(

        uri: "https://api.particle.io/v1/devices/${deviceId}/dim",

        body: [access_token: token, command: dim],  

    )

}
1 Like

Very interesting...and apparently brand new.

Argon Dev Kit - WiFi - Gateway - $35
Boron Dev Kit - LTE - Gateway - $59
Xenon Dev Kit - WiFi - Repeater/Endpoint - $25

These mesh are brand new. But the photon and electron are a few years old. When paired with the hardware from control everything it seems fairly powerful and robust. They ate actually shooting for the enterprise market more than home. But they work for home as well

Control Everything has some interesting hardware...but very pricey for most DIY users.

This guy is a photon in case someone wanted to browse the code.

I did a project with the Photon and got it to work with HE. It's just a distance sensor mounted to my garage door opener pointing down to measure the distance between the sensor and the car below. Depending on that distance, my DH in HE updates which "presence sensor" is parked in the stall.

I agree, but price is relative, if I can use a Hubitat as the local hub and all of these low power devices/sensors/processors to make a kit for the RV segment to use it would be great. Having lived in mine for over 5 years, jst being able to monitor/control things would be fantastic.

When you say RV, I assume you mean Recreational Vehicle?

Yes.

I went back and looked, and you are correct, since the partnered with NCD, they have raised the prices tremendously. When I was purchasing direct a year or two ago, the prices were no where near what they are now. I can make my own pcbs and populate them cheaper than that.

1 Like

So this code is for a photon that is connected to a LED controller? Would it be loaded as a DH? Or an APP?

Yeah. It's individually addressable LED's I have on my patio. And the Photon is the LED controller. You load it as a device. All it does is Pass a value to the photon which runs that part of the program. If you are interested I can share my photon code as well.

1 Like

Yes, I am very interested. I would like to know what board your using for the LEDs also. I bought one of the I2C boards

So the code here is the DH? which when someone places their device id and tokens into it, they can load it as a device correct?

Correct. It still requires your photon program to accept those values to do something.

Ok, I will try to load it here in a bit and see if I can get it to see it as a device. It jst looked like to me, it had "app" functions, so I wasn't sure which area to load it.

I have some drivers that can call particle functions. “Basic switches button controllers etc” they can also go receive particle variables via a refresh command. However I’ve found the best way to receive sensor data from the photon is to have the photon directly send sensor data to hubitat via http to the hubitat maker Api. Far less jumps and cloud complexity.

would you mind sharing those drivers?

1 Like

you got it!

heres one simple example where you give the device your particle device id access token via the input fields created as well as the particle function name you want to access. This passes a simple 1 or 0 to the function like an on off switch to for instance turn on and off a relay

// input options
preferences {
    input name: "deviceId", type: "text", title: "Device ID", required: true
    input name: "token", type: "password", title: "Access Token", required: true
    input name: "PFuncName", type: "text", title: "Particle Function Name", required: true, defaultValue: "SayMyName"
    }

// name the capabilities Attributes and author
metadata {
	definition (name: "Photon Switch", namespace: "brennonsapps", author: "bscuderi") {
        capability "Switch"

// register the custom commands
        //command "getWATT"
	}
}

// on
def on() {
	send(1)
    sendEvent(name: 'switch', value: 'on')
}
// off
def off() {
	send(0)
    sendEvent(name: 'switch', value: 'off')
}

private send(relaystate) {
    //Photon Cloud Call
	httpPost(
        uri: "https://api.particle.io/v1/devices/${deviceId}/${PFuncName}",
        body: [access_token: token, command: relaystate],  
	) {response -> log.debug (response.data)}
}

Heres one that refreshing will cause it to go get a particle variable data.. this is good for sensors. you can make a rule in rule machine for a refresh interval or I have however now for most of my particle photon sensor data now I am using a virtual device in hubitat that my photons are pushing data directly to by making an http call to the hubitat maker API.

/**
 * Particle Photon Temp Sensor
 *
 * Author: Brennon Scuderi
 *
 * 
 *
 * 
 */

preferences {
    input name: "deviceId", type: "text", title: "Device ID", required: true
    input name: "token", type: "password", title: "Access Token", required: true
    input name: "TemperatureVar", type: "text", title: "Temperature Variable", required: true, defaultValue: "InsertYourVariableHere"
    }

metadata {
    definition (name: "Particle Photon Temp Sensor", namespace: "brennonsapps", author: "Brennon Scuderi") {
        capability "Sensor"
        capability "Refresh"
        capability "Temperature Measurement"
        attribute "temperature", "number"
    }
}

// handle commands
def refresh() {
    log.debug "Executing 'refresh'"
    getTemperature()
}

private getTemperature() {
    def closure = { response ->
        log.debug "Temperature request was successful, $response.data"
        sendEvent(name: "temperature", value: response.data.result.toInteger())
    }
    httpGet("https://api.particle.io/v1/devices/${deviceId}/${TemperatureVar}?access_token=${token}", closure)
}

I have other examples that are more complex but they are basically variations of this such as my pool pump controller that works kind of like a button controller sending multiple speeds valve settings as well as multiple sensor values like rpm watts etc.. I could post that too if it helps but they all stem from these two simple ideas.

1 Like