Compare commits

..

1 Commits

Author SHA1 Message Date
Richard Goldberg
b63f07ab42 MSA-1818: Yamaha Receiver and Zones 2017-03-04 07:54:50 -08:00
4 changed files with 436 additions and 859 deletions

View File

@@ -0,0 +1,282 @@
/**
* SmartThings Device Handler: Yamaha Zone
*
* Author: redloro@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*/
metadata {
definition (name: "Yamaha Zone", namespace: "redloro-smartthings", author: "redloro@gmail.com") {
/**
* List our capabilties. Doing so adds predefined command(s) which
* belong to the capability.
*/
capability "Music Player"
capability "Switch"
capability "Switch Level"
capability "Refresh"
capability "Polling"
/**
* Define all commands, ie, if you have a custom action not
* covered by a capability, you NEED to define it here or
* the call will not be made.
*
* To call a capability function, just prefix it with the name
* of the capability, for example, refresh would be "refresh.refresh"
*/
command "source0"
command "source1"
command "source2"
command "source3"
command "source4"
command "source5"
command "mutedOn"
command "mutedOff"
command "partyModeOn"
command "partyModeOff"
command "zone"
}
/**
* Define the various tiles and the states that they can be in.
* The 2nd parameter defines an event which the tile listens to,
* if received, it tries to map it to a state.
*
* You can also use ${currentValue} for the value of the event
* or ${name} for the name of the event. Just make SURE to use
* single quotes, otherwise it will only be interpreted at time of
* launch, instead of every time the event triggers.
*/
tiles(scale: 2) {
multiAttributeTile(name:"state", type:"lighting", width:6, height:4) {
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'On', action:"switch.off", icon:"st.Electronics.electronics16", backgroundColor:"#79b821", nextState:"off"
attributeState "off", label:'Off', action:"switch.on", icon:"st.Electronics.electronics16", backgroundColor:"#ffffff", nextState:"on"
}
tileAttribute ("source", key: "SECONDARY_CONTROL") {
attributeState "source", label:'${currentValue}'
}
}
// row
//controlTile("volume", "device.volume", "slider", height: 1, width: 6, range:"(0..100)") {
controlTile("volume", "device.volume", "slider", height: 1, width: 6, range:"(-80..16)") {
state "volume", label: "Volume", action:"music Player.setLevel", backgroundColor:"#00a0dc"
}
// row
standardTile("0", "device.source0", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV1", action:"source0", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV1", action:"source0", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("1", "device.source1", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV2", action:"source1", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV2", action:"source1", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("2", "device.source2", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV3", action:"source2", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV3", action:"source2", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("3", "device.source3", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV4", action:"source3", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV4", action:"source3", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("4", "device.source4", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV5", action:"source4", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV5", action:"source4", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("5", "device.source5", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV6", action:"source5", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV6", action:"source5", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
// row
standardTile("muted", "device.muted", decoration: "flat", width: 2, height: 2) {
state("off", label:'Muted', action:"mutedOn", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff", nextState:"on")
state("on", label:'Muted', action:"mutedOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-mute.png", backgroundColor:"#ffffff", nextState:"off")
}
standardTile("partyMode", "device.partyMode", decoration: "flat", width: 2, height: 2, inactiveLabel: false) {
state("off", label:'Party Mode', action:"partyModeOn", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff", nextState:"on")
state("on", label:'Party Mode', action:"partyModeOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-party.png", backgroundColor:"#ffffff", nextState:"off")
}
standardTile("refresh", "device.status", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:"Refresh", action:"refresh.refresh", icon:"st.secondary.refresh-icon", backgroundColor:"#ffffff"
}
// Defines which tile to show in the overview
main "state"
// Defines which tile(s) to show when user opens the detailed view
details([
"state",
"volume",
"0","1","2","3","4","5",
"muted", "partyMode","refresh"
])
}
preferences {
input name: "source0", type: "text", title: "Source 1", defaultValue: "AV1"
input name: "source1", type: "text", title: "Source 2", defaultValue: "AV2"
input name: "source2", type: "text", title: "Source 3", defaultValue: "AV3"
input name: "source3", type: "text", title: "Source 4", defaultValue: "AV4"
input name: "source4", type: "text", title: "Source 5", defaultValue: "AV5"
input name: "source5", type: "text", title: "Source 6", defaultValue: "AV6"
}
}
/**************************************************************************
* The following section simply maps the actions as defined in
* the metadata into onAction() calls.
*
* This is preferred since some actions can be dealt with more
* efficiently this way. Also keeps all user interaction code in
* one place.
*
*/
def on() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Power_Control><Power>On</Power></Power_Control></${getZone()}></YAMAHA_AV>")
sendEvent(name: "switch", value: "on")
}
def off() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Power_Control><Power>Standby</Power></Power_Control></${getZone()}></YAMAHA_AV>")
sendEvent(name: "switch", value: "off")
}
def setLevel(value) {
//sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Lvl><Val>${(Math.round(value * 9 / 5) * 5 - 800).intValue()}</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></${getZone()}></YAMAHA_AV>")
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Lvl><Val>${(value * 10).intValue()}</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></${getZone()}></YAMAHA_AV>")
sendEvent(name: "volume", value: value)
}
def source0() {
setSource(0)
}
def source1() {
setSource(1)
}
def source2() {
setSource(2)
}
def source3() {
setSource(3)
}
def source4() {
setSource(4)
}
def source5() {
setSource(5)
}
def mutedOn() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Mute>On</Mute></Volume></${getZone()}></YAMAHA_AV>")
sendEvent(name: "muted", value: "on")
}
def mutedOff() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Mute>Off</Mute></Volume></${getZone()}></YAMAHA_AV>")
sendEvent(name: "muted", value: "off")
}
def partyModeOn() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Mode>On</Mode></Party_Mode></System></YAMAHA_AV>")
sendEvent(name: "partyMode", value: "on")
}
def partyModeOff() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Mode>Off</Mode></Party_Mode></System></YAMAHA_AV>")
sendEvent(name: "partyMode", value: "off")
}
def refresh() {
sendCommand("<YAMAHA_AV cmd=\"GET\"><${getZone()}><Basic_Status>GetParam</Basic_Status></${getZone()}></YAMAHA_AV>")
sendCommand("<YAMAHA_AV cmd=\"GET\"><System><Party_Mode><Mode>GetParam</Mode></Party_Mode></System></YAMAHA_AV>")
}
/**************************************************************************/
/**
* Called every so often (every 5 minutes actually) to refresh the
* tiles so the user gets the correct information.
*/
def poll() {
refresh()
}
def parse(String description) {
return
}
def setSource(id) {
//log.debug "source: "+getSourceName(id)
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Input><Input_Sel>"+getSourceName(id)+"</Input_Sel></Input></${getZone()}></YAMAHA_AV>")
setSourceTile(getSourceName(id))
}
def getSourceName(id) {
if (settings) {
return settings."source${id}"
} else {
return ['AV1', 'AV2', 'AV3', 'AV4', 'AV5', 'AV6'].get(id)
}
}
def setSourceTile(name) {
sendEvent(name: "source", value: "Source: ${name}")
for (def i = 0; i < 6; i++) {
if (name == getSourceName(i)) {
sendEvent(name: "source${i}", value: "on")
}
else {
sendEvent(name: "source${i}", value: "off")
}
}
}
def zone(evt) {
/*
* Zone On/Off
*/
if (evt.Basic_Status.Power_Control.Power.text()) {
sendEvent(name: "switch", value: (evt.Basic_Status.Power_Control.Power.text() == "On") ? "on" : "off")
}
/*
* Zone Volume
*/
if (evt.Basic_Status.Volume.Lvl.Val.text()) {
def int volLevel = evt.Basic_Status.Volume.Lvl.Val.toInteger() ?: -250
//sendEvent(name: "volume", value: ((volLevel + 800) / 9).intValue())
sendEvent(name: "volume", value: (volLevel / 10).intValue())
}
/*
* Zone Muted
*/
if (evt.Basic_Status.Volume.Mute.text()) {
sendEvent(name: "muted", value: (evt.Basic_Status.Volume.Mute.text() == "On") ? "on" : "off")
}
/*
* Zone Source
*/
if (evt.Basic_Status.Input.Input_Sel.text()) {
setSourceTile(evt.Basic_Status.Input.Input_Sel.text())
}
/*
* Party Mode
*/
if (evt.Party_Mode.Mode.text()) {
sendEvent(name: "partyMode", value: (evt.Party_Mode.Mode.text() == "On") ? "on" : "off")
}
}
private sendCommand(body) {
parent.sendCommand(body)
}
private getZone() {
return new String(device.deviceNetworkId).tokenize('|')[2]
}

View File

@@ -1,794 +0,0 @@
/**
* Gideon
*
* Copyright 2016 Nicola Russo
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "Gideon Smart Home",
namespace: "gideon.api",
author: "Braindrain Solutions ltd",
description: "Gideon Smart Home SmartApp allows you to connect and control all of your SmartThings devices through the Gideon app, making your SmartThings devices even smarter.",
category: "Family",
iconUrl: "http://s33.postimg.org/t77u7y7v3/logo.png",
iconX2Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
iconX3Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
oauth: [displayName: "Gideon Smart Home API app", displayLink: "gideon.ai"])
preferences {
section("Control these contact sensors...") {
input "contact", "capability.contactSensor", multiple:true, required:false
}
section("Control these switch levels...") {
input "switchlevels", "capability.switchLevel", multiple:true, required:false
}
/* section("Control these thermostats...") {
input "thermostats", "capability.thermostat", multiple:true, required:false
}*/
section("Control the color for these devices...") {
input "colors", "capability.colorControl", multiple:true, required:false
}
section("Control the color temperature for these devices...") {
input "kelvin", "capability.colorTemperature", multiple:true, required:false
}
section("Control these switches...") {
input "switches", "capability.switch", multiple:true, required:false
}
section("Control these smoke alarms...") {
input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false
}
section("Control these window shades...") {
input "shades", "capability.windowShade", multiple:true, required:false
}
section("Control these garage doors...") {
input "garage", "capability.garageDoorControl", multiple:true, required:false
}
section("Control these water sensors...") {
input "water_sensors", "capability.waterSensor", multiple:true, required:false
}
section("Control these motion sensors...") {
input "motions", "capability.motionSensor", multiple:true, required:false
}
section("Control these presence sensors...") {
input "presence_sensors", "capability.presenceSensor", multiple:true, required:false
}
section("Control these outlets...") {
input "outlets", "capability.outlet", multiple:true, required:false
}
section("Control these power meters...") {
input "meters", "capability.powerMeter", multiple:true, required:false
}
section("Control these locks...") {
input "locks", "capability.lock", multiple:true, required:false
}
section("Control these temperature sensors...") {
input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false
}
section("Control these batteries...") {
input "batteries", "capability.battery", multiple:true, required:false
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
}
private device(it, type) {
it ? [id: it.id, label: it.label, type: type] : null
}
//API Mapping
mappings {
path("/getalldevices") {
action: [
GET: "getAllDevices"
]
}
/*
path("/thermostat/setcool/:id/:temp") {
action: [
GET: "setCoolTemp"
]
}
path("/thermostat/setheat/:id/:temp") {
action: [
GET: "setHeatTemp"
]
}
path("/thermostat/setfanmode/:id/:mode") {
action: [
GET: "setFanMode"
]
}
path("/thermostat/setmode/:id/:mode") {
action: [
GET: "setThermostatMode"
]
}
path("/thermostat/:id") {
action: [
GET: "getThermostatStatus"
]
}
*/
path("/light/dim/:id/:dim") {
action: [
GET: "setLevelStatus"
]
}
path("/light/kelvin/:id/:kelvin") {
action: [
GET: "setKelvin"
]
}
path("/colorlight/:id/:hue/:sat") {
action: [
GET: "setColor"
]
}
path("/light/status/:id") {
action: [
GET: "getLightStatus"
]
}
path("/light/on/:id") {
action: [
GET: "turnOnLight"
]
}
path("/light/off/:id") {
action: [
GET: "turnOffLight"
]
}
path("/doorlocks/lock/:id") {
action: [
GET: "lockDoorLock"
]
}
path("/doorlocks/unlock/:id") {
action: [
GET: "unlockDoorLock"
]
}
path("/doorlocks/:id") {
action: [
GET: "getDoorLockStatus"
]
}
path("/contacts/:id") {
action: [
GET: "getContactStatus"
]
}
path("/smoke/:id") {
action: [
GET: "getSmokeStatus"
]
}
path("/shades/open/:id") {
action: [
GET: "openShade"
]
}
path("/shades/preset/:id") {
action: [
GET: "presetShade"
]
}
path("/shades/close/:id") {
action: [
GET: "closeShade"
]
}
path("/shades/:id") {
action: [
GET: "getShadeStatus"
]
}
path("/garage/open/:id") {
action: [
GET: "openGarage"
]
}
path("/garage/close/:id") {
action: [
GET: "closeGarage"
]
}
path("/garage/:id") {
action: [
GET: "getGarageStatus"
]
}
path("/watersensors/:id") {
action: [
GET: "getWaterSensorStatus"
]
}
path("/tempsensors/:id") {
action: [
GET: "getTempSensorsStatus"
]
}
path("/meters/:id") {
action: [
GET: "getMeterStatus"
]
}
path("/batteries/:id") {
action: [
GET: "getBatteryStatus"
]
}
path("/presences/:id") {
action: [
GET: "getPresenceStatus"
]
}
path("/motions/:id") {
action: [
GET: "getMotionStatus"
]
}
path("/outlets/:id") {
action: [
GET: "getOutletStatus"
]
}
path("/outlets/turnon/:id") {
action: [
GET: "turnOnOutlet"
]
}
path("/outlets/turnoff/:id") {
action: [
GET: "turnOffOutlet"
]
}
path("/switches/turnon/:id") {
action: [
GET: "turnOnSwitch"
]
}
path("/switches/turnoff/:id") {
action: [
GET: "turnOffSwitch"
]
}
path("/switches/:id") {
action: [
GET: "getSwitchStatus"
]
}
}
//API Methods
def getAllDevices() {
def locks_list = locks.collect{device(it,"Lock")}
/*def thermo_list = thermostats.collect{device(it,"Thermostat")}*/
def colors_list = colors.collect{device(it,"Color")}
def kelvin_list = kelvin.collect{device(it,"Kelvin")}
def contact_list = contact.collect{device(it,"Contact Sensor")}
def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")}
def shades_list = shades.collect{device(it,"Window Shade")}
def garage_list = garage.collect{device(it,"Garage Door")}
def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")}
def presences_list = presence_sensors.collect{device(it,"Presence")}
def motions_list = motions.collect{device(it,"Motion")}
def outlets_list = outlets.collect{device(it,"Outlet")}
def switches_list = switches.collect{device(it,"Switch")}
def switchlevels_list = switchlevels.collect{device(it,"Switch Level")}
def temp_list = temperature_sensors.collect{device(it,"Temperature")}
def meters_list = meters.collect{device(it,"Power Meters")}
def battery_list = batteries.collect{device(it,"Batteries")}
return outlets_list + kelvin_list + colors_list + switchlevels_list + smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + switches_list + temp_list + meters_list + battery_list
}
//thermostat
/*
def setCoolTemp() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setCoolingSetpoint")) {
device.setCoolingSetpoint(params.temp.toInteger());
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def setHeatTemp() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setHeatingSetpoint")) {
device.setHeatingSetpoint(params.temp.toInteger());
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def setFanMode() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setThermostatFanMode")) {
device.setThermostatFanMode(params.mode);
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def setThermostatMode() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setThermostatMode")) {
device.setThermostatMode(params.mode);
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def getThermostatStatus() {
def device = thermostats.find{ it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [ThermostatOperatingState: device.currentValue('thermostatOperatingState'), ThermostatSetpoint: device.currentValue('thermostatSetpoint'),
ThermostatFanMode: device.currentValue('thermostatFanMode'), ThermostatMode: device.currentValue('thermostatMode')]
}
}
*/
//light
def turnOnLight() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
return [Device_id: params.id, result_action: "200"]
}
}
def turnOffLight() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.off();
return [Device_id: params.id, result_action: "200"]
}
}
def getLightStatus() {
def device = switches.find{ it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)]
}
}
//color control
def setColor() {
def device = colors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()]
device.setColor(map);
return [Device_id: params.id, result_action: "200"]
}
}
def getColorStatus(id) {
def device = colors.find { it.id == id }
if (!device) {
return [Color: "none"]
} else {
return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')]
}
}
//kelvin control
def setKelvin() {
def device = kelvin.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.setColorTemperature(params.kelvin.toInteger());
return [Device_id: params.id, result_action: "200"]
}
}
def getKelvinStatus(id) {
def device = kelvin.find { it.id == id }
if (!device) {
return [kelvin: "none"]
} else {
return [kelvin: device.currentValue('colorTemperature')]
}
}
//switch level
def getLevelStatus() {
def device = switchlevels.find { it.id == params.id }
if (!device) {
[Level: "No dimmer"]
} else {
return [Level: device.currentValue('level')]
}
}
def getLevelStatus(id) {
def device = switchlevels.find { it.id == id }
if (!device) {
[Level: "No dimmer"]
} else {
return [Level: device.currentValue('level')]
}
}
def setLevelStatus() {
def device = switchlevels.find { it.id == params.id }
def level = params.dim
if (!device) {
httpError(404, "Device not found")
} else {
device.setLevel(level.toInteger())
return [result_action: "200", Level: device.currentValue('level')]
}
}
//contact sensors
def getContactStatus() {
def device = contact.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def args = getTempSensorsStatus(device.id)
return [Device_state: device.currentValue('contact')] + args
}
}
//smoke detectors
def getSmokeStatus() {
def device = smoke_alarms.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('smoke')] + bat
}
}
//garage
def getGarageStatus() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('door')]
}
}
def openGarage() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.open();
return [Device_id: params.id, result_action: "200"]
}
}
def closeGarage() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.close();
return [Device_id: params.id, result_action: "200"]
}
}
//shades
def getShadeStatus() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('windowShade')]
}
}
def openShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.open();
return [Device_id: params.id, result_action: "200"]
}
}
def presetShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.presetPosition();
return [Device_id: params.id, result_action: "200"]
}
}
def closeShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.close();
return [Device_id: params.id, result_action: "200"]
}
}
//water sensor
def getWaterSensorStatus() {
def device = water_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('water')] + bat
}
}
//batteries
def getBatteryStatus() {
def device = batteries.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.latestValue("battery")]
}
}
def getBatteryStatus(id) {
def device = batteries.find { it.id == id }
if (!device) {
return []
} else {
return [battery_state: device.latestValue("battery")]
}
}
//LOCKS
def getDoorLockStatus() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('lock')] + bat
}
}
def lockDoorLock() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.lock();
return [Device_id: params.id, result_action: "200"]
}
}
def unlockDoorLock() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.unlock();
return [Device_id: params.id, result_action: "200"]
}
}
//PRESENCE
def getPresenceStatus() {
def device = presence_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('presence')] + bat
}
}
//MOTION
def getMotionStatus() {
def device = motions.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def args = getTempSensorsStatus(device.id)
return [Device_state: device.currentValue('motion')] + args
}
}
//OUTLET
def getOutletStatus() {
def device = outlets.find { it.id == params.id }
if (!device) {
device = switches.find { it.id == params.id }
if(!device) {
httpError(404, "Device not found")
}
}
def watt = getMeterStatus(device.id)
return [Device_state: device.currentValue('switch')] + watt
}
def getMeterStatus() {
def device = meters.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
}
}
def getMeterStatus(id) {
def device = meters.find { it.id == id }
if (!device) {
return []
} else {
return [Current_watt: device.currentValue("power")]
}
}
def turnOnOutlet() {
def device = outlets.find { it.id == params.id }
if (!device) {
device = switches.find { it.id == params.id }
if(!device) {
httpError(404, "Device not found")
}
}
device.on();
return [Device_id: params.id, result_action: "200"]
}
def turnOffOutlet() {
def device = outlets.find { it.id == params.id }
if (!device) {
device = switches.find { it.id == params.id }
if(!device) {
httpError(404, "Device not found")
}
}
device.off();
return [Device_id: params.id, result_action: "200"]
}
//SWITCH
def getSwitchStatus() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)]
}
}
def turnOnSwitch() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
return [Device_id: params.id, result_action: "200"]
}
}
def turnOffSwitch() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.off();
return [Device_id: params.id, result_action: "200"]
}
}
//TEMPERATURE
def getTempSensorsStatus() {
def device = temperature_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
def scale = [Scale: location.temperatureScale]
return [Device_state: device.currentValue('temperature')] + scale + bat
}
}
def getTempSensorsStatus(id) {
def device = temperature_sensors.find { it.id == id }
if (!device) {
return []
} else {
def bat = getBatteryStatus(device.id)
return [temperature: device.currentValue('temperature')] + bat
}
}

View File

@@ -0,0 +1,154 @@
/**
* SmartThings SmartApp: Yamaha Network Receiver
*
* Author: redloro@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* https://github.com/PSeitz/yamaha-nodejs
* http://<RECEIVER_IP_ADDRESS>/YamahaRemoteControl/desc.xml
*/
import groovy.util.XmlSlurper
definition(
name: "Yamaha Receiver",
namespace: "redloro-smartthings",
author: "redloro@gmail.com",
description: "Yamaha SmartApp",
category: "My Apps",
iconUrl: "https://raw.githubusercontent.com/redloro/smartthings/master/images/yamaha-receiver.png",
iconX2Url: "https://raw.githubusercontent.com/redloro/smartthings/master/images/yamaha-receiver.png",
iconX3Url: "https://raw.githubusercontent.com/redloro/smartthings/master/images/yamaha-receiver.png"
)
preferences {
section("SmartThings Hub") {
input "hostHub", "hub", title: "Select Hub", multiple: false, required: true
}
section("Yamaha Receiver") {
input name: "receiverName", type: "text", title: "Name", required: true, defaultValue: "Yamaha"
input name: "receiverIp", type: "text", title: "IP", required: true
input name: "receiverZones", type: "enum", title: "Zones", required: true, multiple: true, options: ["Main_Zone","Zone_B","Zone_2","Zone_3","Zone_4"]
}
}
def installed() {
subscribeToEvents()
}
def subscribeToEvents() {
subscribe(location, null, lanResponseHandler, [filterEvents:false])
}
def updated() {
addChildDevices()
}
def uninstalled() {
removeChildDevices()
}
def lanResponseHandler(evt) {
def map = stringToMap(evt.stringValue)
//verify that this message is from Yamaha Receiver IP
if (!map.ip || map.ip != convertIPtoHex(settings.receiverIp)) {
return
}
def headers = getHttpHeaders(map.headers);
def body = getHttpBody(map.body);
//log.trace "Headers: ${headers}"
//log.trace "Body: ${body}"
updateZoneDevices(body.children()[0])
}
private updateZoneDevices(evt) {
//log.debug "updateZoneDevices: ${evt.toString()}"
if (evt.name() == "System") {
//log.debug "Update all zones"
childDevices*.zone(evt)
return
}
def zonedevice = getChildDevice(getDeviceId(evt.name()))
if (zonedevice) {
zonedevice.zone(evt)
}
//check for Zone_B
zonedevice = getChildDevice(getDeviceId("Zone_B"))
if (zonedevice && evt.name() == "Main_Zone") {
zonedevice.zone(evt)
}
}
private addChildDevices() {
// add yamaha device
settings.receiverZones.each {
def deviceId = getDeviceId(it)
if (!getChildDevice(deviceId)) {
addChildDevice("redloro-smartthings", "Yamaha Zone", deviceId, hostHub.id, ["name": it, label: "${settings.receiverName}: ${it}", completedSetup: true])
log.debug "Added Yamaha zone: ${deviceId}"
}
}
childDevices*.refresh()
}
private removeChildDevices() {
getAllChildDevices().each { deleteChildDevice(it.deviceNetworkId) }
}
private sendCommand(body) {
//log.debug "Yamaha Network Receiver send command: ${body}"
def hubAction = new physicalgraph.device.HubAction(
headers: [HOST: getReceiverAddress()],
method: "POST",
path: "/YamahaRemoteControl/ctrl",
body: body
)
sendHubCommand(hubAction)
}
private getHttpHeaders(headers) {
def obj = [:]
new String(headers.decodeBase64()).split("\r\n").each {param ->
def nameAndValue = param.split(":")
obj[nameAndValue[0]] = (nameAndValue.length == 1) ? "" : nameAndValue[1].trim()
}
return obj
}
private getHttpBody(body) {
def obj = null;
if (body) {
obj = new XmlSlurper().parseText(new String(body.decodeBase64()))
}
return obj
}
private getDeviceId(zone) {
return "yamaha|${settings.receiverIp}|${zone}"
}
private getReceiverAddress() {
return settings.receiverIp + ":80"
}
private String convertIPtoHex(ipAddress) {
return ipAddress.tokenize( '.' ).collect { String.format( '%02x', it.toInteger() ) }.join().toUpperCase()
}
private String convertPortToHex(port) {
return port.toString().format( '%04x', port.toInteger() ).toUpperCase()
}

View File

@@ -1,65 +0,0 @@
/**
* Copyright 2015 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* Monitors a switch for ON condition and switches OFF after time delay.
*
* Author: SmartThings modified by TC Hayes
*
* This app detects the ON status of a switch, waits X seconds, then switches off.
* May be used anywhere a short on/off condition of a few seconds is needed, for example:
* --- An automatic doorbell where a motion sensor switches ON a buzzer. This app terminates the buzz after X seconds.
* --- An automated pet/fish feeder where a separate timer app turns on the feed switch. This app turns off the flow after X seconds. Use along
* with a delay timer between feeds eg (Home Monitor / Custom / New Monitoring Rule ...).
* --- A garage door opener actuator where an on/off pulse of X seconds is needed to either open or close. Any other app can trigger
* the ON condition by detecting motion, button operation of a button, or elapsed time. This app will teminate the pulse with an OFF signal. Use
* ST Smart Home Monitor (Custom / New Monitoring Rule ... ) with this app to close a door left open.
* --- Use with app 'Switch ON After Delay' to create a continuing on/off flashing sequence. (Lighthouse.)
**/
definition(
name: "Switch OFF After Delay",
namespace: "tchayes57",
author: "tchayes57",
description: "Monitor switch and respond to an ON condition with OFF after X seconds.",
category: "Convenience",
)
preferences {
section("Switch to be monitored ...") {
input "switch1", "capability.switch", required: true
}
section("Set Delay") {
input "openTimer", "number", title: "Number of seconds delay", required: true
}
}
def installed() {
subscribe(app, appTouchHandler)
subscribeToCommand(switch1, "on", onCommand)
}
def updated() {
unsubscribe()
subscribe(app, appTouchHandler)
subscribeToCommand(switch1, "on", onCommand)
}
// identify transition to ON
def appTouch(evt) {
log.debug "appTouch: $evt.value, $evt"
switch1?.on()
}
// initiate OFF after delay
def onCommand(evt) {
log.debug "onCommand: $evt.value, $evt"
switch1?.off(delay: openTimer * 1000)
}