I have started to get into the hobby of building some personal IOT devices that started when I got bit by the bug after building a brewpi homebrew fermentation controller from a raspberry pi and an arduino. Realizing the potential of these devices has thrown me further down the rabbit hole. I however like to create a concept and wire it up but the programming is all greek to me. Sometimes if I struggle my way through the comments I can understand what is happening with someone elses code but for all practical purposes I am a complete stranger to code. Guess I should pick a new hobby haha. Now on to where I need help… Essentially what I designed was some speakers that I mounted to my hottub pergola in my backyard detached from my house. I didn’t want to have to run speaker wire out to the location so I used a setup that I have had a ton of success with in other areas of my home for a whole home audio setup which is basically a raspberry pi with a hifiberry amp+ on top. For anyone looking into audio I love this setup the software I use is called max2play and its awesome. I didn’t want to mess with any mains wiring by the hottub due to the dangers of water and electricity so I currently have solar powered cafe lights on the pergola that run off a double A battery I beefed up the solar panels from the stock and now they work great and keeping up with the spirit of the solar hottub area I wanted the speaker system to be solar powered as well. The raspberry pi and amp I knew used alot of juice when sitting at idle and I only need the speakers to play a couple of hours a night. I wanted the solar panel and battery to be small so this is where the particle photon comes in. I basically uses this battery https://www.amazon.com/gp/product/B00ME3ZH7C/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1 it has 12 volt output and a 5 volt output and supports through charging via the 12 volt port. My pi and amp combination runs off the 12 volt port and my particle photon from the 5 volt usb. I modified some code that I found where someone was controlling an 8 channel relay and integrating this with a smartthings home automation controller to just control a one channel relay which I use to switch on and off the pi. Success my code works I can turn on and off the speakers from my smartthings controller. They sound great and when synced with my patio speakers they deliver a way more even sound to my pool area so multiple success! My battery and solar panel is seeming to keep up with these super sunny phoenix summer days but I want to make dead sure it keeps up in the winter or days with weather. I don’t want to have interruptions or Id deem the project a failure… currently im using my backpacking solar panel (goal zero namad 7) to power my project for proof of concept and it has been stellar the last few weeks. Im currently waiting for the solar panel I plan to permanently install to arrive from a slow boat coming from China. The panel I plan on installing is a little smaller than my hiking one. What I want is to create some even more power saving code into my photon to make sure this thing runs smoothly. Currently the photon is running full speed 24 hours a day. I tried reading about the different modes and just ended up ultimately confused. For instance I definitely do not need for any reason to be able to play music after 2 am for instance that would be horrible for the neighbors so I would be fine if my particle went into a deep sleep mode from say 2 am to 9 am to save even more juice. Or I even had some confusion is there a mode that it could be put into that would keep looking for my on command but sleep all other functions that were unnecessary that I could use all the time for my daytime function? Currently the only battery saving option I have in my code is I saw how someone controlled the color of the led and I just changed the values to zero turning off the photons led. The battery pack has some leds that I cant shutoff but Im sure it doesn’t use that much. I will attach my code here and some pictures of my project. Id appreciate input or suggestions on what should be in there to achieve what I want to achieve. Thanks in advance for your patients and help just rememeber I’m a total noob to code.
Photon Code
// A Spark function to parse the commands
int relay4(String command);
// We name pins
int r4 = D3;
// This routine runs only once upon reset
void setup()
{
//Register Spark functions
Spark.function("strelay4", relay4);
// Initialize output pins
pinMode(r4, OUTPUT);
// take control of the LED
RGB.control(true);
// the following sets the RGB LED to light green:
RGB.color(0, 0, 0);
}
// This routine loops forever
void loop()
{
// nothing here
}
//acts based on messages from spark cloud
int relay1(String command)
{
int relay4(String command)
{
if (command == "1")
{
digitalWrite(r4, HIGH); // Turn ON the relay
return 1;
}
else
{
digitalWrite(r4, LOW); // Turn OFF the relay
return 0;
}
}
Smarththings Groovy Code
/*
* Particle.io Device Example
*
*
*/
definition(
name: "Particle.io Device",
namespace: "rhworkshop",
author: "Andy Rawson",
description: "Allows a Particle.io device to be used with SmartThings",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
// Preferences and setup pages
preferences {
page(name: "page1", title: "Particle Device", nextPage: "page2", uninstall: true) {
section("Username and Password") {
input "particleUsername", "text", title: "Your Particle.io Username", required: true
input "particlePassword", "password", title: "Your Particle.io Password", required: true
}
}
}
page(name: "page2", title: "Check Auth", nextPage: "page3", install: false, uninstall: false)
page(name: "page3", title: "Pick Device", install: true, uninstall: false)
def page2() {
dynamicPage(name: "page2") {
section("Generate Token") {
if (loginToParticle()) {
paragraph title: "Success logging in to Particle.io", "Auth Token generated"
}
else {
paragraph title: "Error logging in to Particle.io", "Check your username and password or check the log for other errors"
}
}
}
}
def page3() {
dynamicPage(name: "page3") {
section("Particle Device to use"){
def particleDevices = getDevices()
input(name: "particleDevice", type: "enum", title: "Select the particle Device", required: true, multiple: false, options: particleDevices)
}
section {
label title: "Assign a name", required: false
}
}
}
// -----------------------------------------------------------
// Setup functions
// -----------------------------------------------------------
def installed() {
state.webhookName = "dev${particleDevice[-6..-1]}"
state.appURL = "https://graph.api.smartthings.com/api/smartapps/installations/${app.id}/stdata/${state.webhookName}/{{pin}}/{{data}}?access_token=${state.accessToken}"
//log.debug "Installed with settings: ${settings}"
checkWebhook()
//setupSensors()
}
def updated() {
//log.debug "Updated with settings: ${settings}"
unsubscribe()
checkWebhook()
//setupSensors()
}
// Log in to Particle.io
def loginToParticle() {
if (!state.particleToken){
def clientAuth = "particle:particle"
clientAuth = "Basic " + clientAuth.encodeAsBase64().toString()
def params = [
headers: [Authorization: clientAuth],
uri: "https://api.particle.io/oauth/token",
body: [grant_type: "password",
username: particleUsername,
password: particlePassword
]
]
try {
httpPost(params) {response ->
state.particleToken = response.data.access_token
}
log.debug "Created new Particle.io token"
//log.debug "Particle Token ${state.particleToken}"
checkToken()
return true
} catch (e) {
log.error "error: $e"
return false
}
}
else {
return true
}
}
// Check to see if we need to make the webhook or if it is there already
void checkWebhook() {
int foundHook = 0
try {
httpGet(uri:"https://api.particle.io/v1/webhooks?access_token=${state.particleToken}",
) {response -> response.data.each {
hook ->
//log.debug hook.event
if (hook.event == state.webhookName) {
foundHook = 1
log.debug "Found existing webhook id: ${hook.id}"
}
}
if (!foundHook) {
createWebhook()
}
else {
}
}
}
catch (e) {
log.error "error: $e"
}
}
// Create a new particle webhook for this app to use
void createWebhook() {
log.debug "Creating a Particle webhook "
try {
httpPost(uri: "https://api.particle.io/v1/webhooks",
body: [access_token: state.particleToken,
event: state.webhookName,
url: state.appURL,
requestType: "GET",
mydevices: true]
) {response -> log.debug (response.data)}
}
catch (e) {
log.error "error: $e"
}
}
// get a list of the particle devices from the account
def getDevices() {
def particleDevices = [:]
//Particle API Call
try {
def readingClosure = { response -> response.data.each { core ->
particleDevices.put(core.id, core.name)
}
}
httpGet("https://api.particle.io/v1/devices?access_token=${state.particleToken}", readingClosure)
}
catch (e) {
log.error "error: $e"
}
return particleDevices
}
// Is there an accessToken yet?
def checkToken() {
if (!state.accessToken) {
createAccessToken()
}
}
// api mappings for the Particle.io API to talk to the SmartThings API
mappings {
path("/stdata/:webhookName/:pin/:data") {
action: [
GET: "setDeviceState"
]
}
}
// -----------------------------------------------------------
// Send and receive commands with the Particle device
// -----------------------------------------------------------
// send an on command to the particle device
def switchOnHandler(evt) {
evt.getProperties().each {e -> log.debug "${e}" }
log.debug "switch turned on!"
def pinToSet = "D0"
try {
httpPost("https://api.particle.io/v1/devices/${particleDevice}/setOn?access_token=${state.particleToken}","command=${pinToSet}",) {response -> log.debug (response.data)}
}
catch (e) {
log.error "error: $e"
}
}
// send an off command to the particle device
def switchOffHandler(evt) {
log.debug "switch turned off!"
def pinToSet = "D0"
try {
httpPost("https://api.particle.io/v1/devices/${particleDevice}/setOff?access_token=${state.particleToken}","command=${pinToSet}",) {response -> log.debug (response.data)}
}
catch (e) {
log.error "error: $e"
}
}
// send a value to particle device
def switchValueHandler(evt) {
log.debug "switch dimmed to ${evt.value}!"
def pinToSet = "D0"
def pinValue = "101"
try {
httpPost("https://api.particle.io/v1/devices/${particleDevice}/setValue?access_token=${state.particleToken}","command=${pinToSet}:${pinValue}",) {response -> log.debug (response.data)}
}
catch (e) {
log.error "error: $e"
}
}
// got the webhook from the particle device now do something with the information
def setDeviceState() {
log.debug "Got webhook - pin: ${params.pin} data: ${params.data}"
//return [Respond: "OK"]
}
// -----------------------------------------------------------
// Uninstall Section
// -----------------------------------------------------------
def uninstalled() {
log.debug "Uninstalling ParticleThings"
deleteWebhook()
deleteAccessToken()
log.debug "ParticleThings Uninstalled"
}
// Cleanup on uninstall - remove the particle webhook for this app
void deleteWebhook() {
try{
httpGet(uri:"https://api.particle.io/v1/webhooks?access_token=${state.particleToken}",
) {response -> response.data.each {
hook ->
//log.debug hook.event
if (hook.event == state.webhookName) {
httpDelete(uri:"https://api.particle.io/v1/webhooks/${hook.id}?access_token=${state.particleToken}")
log.debug "Deleted the existing webhook with the id: ${hook.id} and the event name: ${state.webhookName}"
}
}
}
} catch (all) {log.debug "Couldn't delete webhook, moving on"}
}
// Cleanup on uninstall - remove the particle access token
void deleteAccessToken() {
try{
def clientAuth = "${particleUsername}:${particlePassword}"
clientAuth = "Basic " + clientAuth.encodeAsBase64().toString()
def params = [
headers: [Authorization: clientAuth],
uri: "https://api.particle.io/v1/access_tokens/${state.particleToken}"
]
httpDelete(params) //uri:"https://${particleUsername}:${particlePassword}@api.particle.io/v1/access_tokens/${state.particleToken}")
log.debug "Deleted the existing Particle Access Token"
} catch (e) {log.debug "Couldn't delete Particle Token, moving on: $e"}
}
Project Pictures
originally I had a pi3 powering it but i switched it for the zero w thinking this would save even more power while its on and accomplish the same thing.