2020-09-21 01:58:32 +02:00
/ * *
* OpenHabAppV2
*
* Description
* Provides two way communications between a Smartthings Hub and OpenHAB
* Messages from OpenHAB with the following paths are supported and perform the following functions
* / state - returns the state of the specified device and attribute , i . e . on , off , 95
* / update - Updates the state of the specified device and attribute
* / discovery - Returns a list of the devices
* / error - Returns error messages to OpenHAB for logging
* Messages are sent to OpenHAB with the following paths
* /smartthings/ push - When an event occurs on a monitored device the new value is sent to OpenHAB
*
* Authors
* - rjraker @gmail.com - 1 /30/ 17 - Modified for use with Smartthings
* - st . john . johnson @gmail.com and jeremiah . wuenschel @gmail.com - original code for interface with another device
*
2021-01-02 22:03:14 +01:00
* Copyright 2016 - 2021
2020-09-21 01:58:32 +02:00
*
* 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 .
* /
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovy.json.JsonBuilder
import groovy.transform.Field
// Massive lookup tree
@Field CAPABILITY_MAP = [
"accelerationSensor" : [
name: "Acceleration Sensor" ,
capability: "capability.accelerationSensor" ,
attributes: [
"acceleration"
]
] ,
"airConditionerMode" : [
name: "Air Conditioner Mode" ,
capability: "capability.airConditionerMode" ,
attributes: [
"airConditionerMode"
] ,
action: actionAirConditionerMode
] ,
"alarm" : [
name: "Alarm" ,
capability: "capability.alarm" ,
attributes: [
"alarm"
] ,
action: "actionAlarm"
] ,
"battery" : [
name: "Battery" ,
capability: "capability.battery" ,
attributes: [
"battery"
]
] ,
"beacon" : [
name: "Beacon" ,
capability: "capability.beacon" ,
attributes: [
"presence"
]
] ,
"bulb" : [
name: "Bulb" ,
capability: "capability.bulb" ,
attributes: [
"switch"
] ,
action: "actionOnOff"
] ,
"button" : [
name: "Button" ,
capability: "capability.button" ,
attributes: [
"button"
]
] ,
"carbonDioxideMeasurement" : [
name: "Carbon Dioxide Measurement" ,
capability: "capability.carbonDioxideMeasurement" ,
attributes: [
"carbonDioxide"
]
] ,
"carbonMonoxideDetector" : [
name: "Carbon Monoxide Detector" ,
capability: "capability.carbonMonoxideDetector" ,
attributes: [
"carbonMonoxide"
]
] ,
"colorControl" : [
name: "Color Control" ,
capability: "capability.colorControl" ,
attributes: [
"hue" ,
"saturation" ,
"color"
] ,
action: "actionColorControl"
] ,
"color" : [
name: "Color (proposed)" ,
capability: "capability.color" ,
attributes: [
"colorValue"
] ,
action: "actionColor"
] ,
"colorTemperature" : [
name: "Color Temperature" ,
capability: "capability.colorTemperature" ,
attributes: [
"colorTemperature"
] ,
action: "actionColorTemperature"
] ,
"consumable" : [
name: "Consumable" ,
capability: "capability.consumable" ,
attributes: [
"consumable"
] ,
action: "actionConsumable"
] ,
"contactSensor" : [
name: "Contact Sensor" ,
capability: "capability.contactSensor" ,
attributes: [
"contact"
]
] ,
"doorControl" : [
name: "Door Control" ,
capability: "capability.doorControl" ,
attributes: [
"door"
] ,
action: "actionOpenClosed"
] ,
"energyMeter" : [
name: "Energy Meter" ,
capability: "capability.energyMeter" ,
attributes: [
"energy"
]
] ,
"dryerMode" : [
name: "Dryer Mode" ,
capability: "capability.dryerMode" ,
attributes: [
"dryerMode"
] ,
action: "actionApplianceMode"
] ,
"dryerOperatingState" : [
name: "Dryer Operating State" ,
capability: "capability.dryerOperatingState" ,
attributes: [
"machineState" ,
"dryerJobState"
] ,
action: "actionMachineState"
] ,
"estimatedTimeOfArrival" : [
name: "Estimated Time Of Arrival" ,
capability: "capability.estimatedTimeOfArrival" ,
attributes: [
"eta"
]
] ,
"garageDoorControl" : [
name: "Garage Door Control" ,
capability: "capability.garageDoorControl" ,
attributes: [
"door"
] ,
action: "actionOpenClosed"
] ,
"holdableButton" : [
name: "Holdable Button" ,
capability: "capability.holdableButton" ,
attributes: [
"button" ,
"numberOfButtons"
] ,
action: "actionOpenClosed"
] ,
"illuminanceMeasurement" : [
name: "Illuminance Measurement" ,
capability: "capability.illuminanceMeasurement" ,
attributes: [
"illuminance"
]
] ,
"imageCapture" : [
name: "Image Capture" ,
capability: "capability.imageCapture" ,
attributes: [
"image"
]
] ,
"indicator" : [
name: "Indicator" ,
capability: "capability.indicator" ,
attributes: [
"indicatorStatus"
] ,
action: indicator
] ,
"infraredLevel" : [
name: "Infrared Level" ,
capability: "capability.infraredLevel" ,
attributes: [
"infraredLevel"
] ,
action: "actionLevel"
] ,
"lock" : [
name: "Lock" ,
capability: "capability.lock" ,
attributes: [
"lock"
] ,
action: "actionLock"
] ,
"lockOnly" : [
name: "Lock Only" ,
capability: "capability.lockOnly" ,
attributes: [
"lock"
] ,
action: "actionLockOnly"
] ,
"mediaController" : [
name: "Media Controller" ,
capability: "capability.mediaController" ,
attributes: [
"activities" ,
"currentActivity"
]
] ,
"motionSensor" : [
name: "Motion Sensor" ,
capability: "capability.motionSensor" ,
attributes: [
"motion"
] ,
action: "actionActiveInactive"
] ,
"musicPlayer" : [
name: "Music Player" ,
capability: "capability.musicPlayer" ,
attributes: [
"status" ,
"level" ,
"trackDescription" ,
"trackData" ,
"mute"
] ,
action: "actionMusicPlayer"
] ,
"outlet" : [
name: "Outlet" ,
capability: "capability.outlet" ,
attributes: [
"switch"
] ,
action: "actionOnOff"
] ,
"pHMeasurement" : [
name: "pH Measurement" ,
capability: "capability.pHMeasurement" ,
attributes: [
"pH"
]
] ,
"powerMeter" : [
name: "Power Meter" ,
capability: "capability.powerMeter" ,
attributes: [
"power"
]
] ,
"powerSource" : [
name: "Power Source" ,
capability: "capability.powerSource" ,
attributes: [
"powerSource"
]
] ,
"presenceSensor" : [
name: "Presence Sensor" ,
capability: "capability.presenceSensor" ,
attributes: [
"presence"
]
] ,
"relativeHumidityMeasurement" : [
name: "Relative Humidity Measurement" ,
capability: "capability.relativeHumidityMeasurement" ,
attributes: [
"humidity"
]
] ,
"relaySwitch" : [
name: "Relay Switch" ,
capability: "capability.relaySwitch" ,
attributes: [
"switch"
] ,
action: "actionOnOff"
] ,
"shockSensor" : [
name: "Shock Sensor" ,
capability: "capability.shockSensor" ,
attributes: [
"shock"
]
] ,
"signalStrength" : [
name: "Signal Strength" ,
capability: "capability.signalStrength" ,
attributes: [
"lqi" ,
"rssi"
]
] ,
"sleepSensor" : [
name: "Sleep Sensor" ,
capability: "capability.sleepSensor" ,
attributes: [
"sleeping"
]
] ,
"smokeDetector" : [
name: "Smoke Detector" ,
capability: "capability.smokeDetector" ,
attributes: [
"smoke" ,
"carbonMonoxide"
]
] ,
"soundPressureLevel" : [
name: "Sound Pressure Level" ,
capability: "capability.soundPressureLevel" ,
attributes: [
"soundPressureLevel"
]
] ,
"soundSensor" : [
name: "Sound Sensor" ,
capability: "capability.soundSensor" ,
attributes: [
"phraseSpoken"
]
] ,
"speechRecognition" : [
name: "Speech Recognition" ,
capability: "capability.speechRecognition" ,
action: [
"speak"
]
] ,
"stepSensor" : [
name: "Step Sensor" ,
capability: "capability.stepSensor" ,
attributes: [
"steps" ,
"goal"
]
] ,
"switch" : [
name: "Switch" ,
capability: "capability.switch" ,
attributes: [
"switch"
] ,
action: "actionOnOff"
] ,
"switchLevel" : [
name: "Dimmer Switch" ,
capability: "capability.switchLevel" ,
attributes: [
"level"
] ,
action: "actionLevel"
] ,
"soundPressureLevel" : [
name: "Sound Pressure Level" ,
capability: "capability.soundPressureLevel" ,
attributes: [
"soundPressureLevel"
]
] ,
"tamperAlert" : [
name: "Tamper Alert" ,
capability: "capability.tamperAlert" ,
attributes: [
"tamper"
]
] ,
"temperatureMeasurement" : [
name: "Temperature Measurement" ,
capability: "capability.temperatureMeasurement" ,
attributes: [
"temperature"
]
] ,
"thermostat" : [
name: "Thermostat" ,
capability: "capability.thermostat" ,
attributes: [
"temperature" ,
"heatingSetpoint" ,
"coolingSetpoint" ,
"thermostatSetpoint" ,
"thermostatMode" ,
"thermostatFanMode" ,
"thermostatOperatingState"
] ,
action: "actionThermostat"
] ,
"thermostatCoolingSetpoint" : [
name: "Thermostat Cooling Setpoint" ,
capability: "capability.thermostatCoolingSetpoint" ,
attributes: [
"coolingSetpoint"
] ,
action: "actionThermostat"
] ,
"thermostatFanMode" : [
name: "Thermostat Fan Mode" ,
capability: "capability.thermostatFanMode" ,
attributes: [
"thermostatFanMode"
] ,
action: "actionThermostat"
] ,
"thermostatHeatingSetpoint" : [
name: "Thermostat Heating Setpoint" ,
capability: "capability.thermostatHeatingSetpoint" ,
attributes: [
"heatingSetpoint"
] ,
action: "actionThermostat"
] ,
"thermostatMode" : [
name: "Thermostat Mode" ,
capability: "capability.thermostatMode" ,
attributes: [
"thermostatMode"
] ,
action: "actionThermostat"
] ,
"thermostatOperatingState" : [
name: "Thermostat Operating State" ,
capability: "capability.thermostatOperatingState" ,
attributes: [
"thermostatOperatingState"
]
] ,
"thermostatSetpoint" : [
name: "Thermostat Setpoint" ,
capability: "capability.thermostatSetpoint" ,
attributes: [
"thermostatSetpoint"
]
] ,
"threeAxis" : [
name: "Three Axis" ,
capability: "capability.threeAxis" ,
attributes: [
"threeAxis"
]
] ,
"timedSession" : [
name: "Timed Session" ,
capability: "capability.timedSession" ,
attributes: [
"timeRemaining" ,
"sessionStatus"
] ,
action: "actionTimedSession"
] ,
"touchSensor" : [
name: "Touch Sensor" ,
capability: "capability.touchSensor" ,
attributes: [
"touch"
]
] ,
"valve" : [
name: "Valve" ,
capability: "capability.valve" ,
attributes: [
"valve"
] ,
action: "actionOpenClosed"
] ,
"voltageMeasurement" : [
name: "Voltage Measurement" ,
capability: "capability.voltageMeasurement" ,
attributes: [
"voltage"
]
] ,
"washerMode" : [
name: "Washer Mode" ,
capability: "capability.washerMode" ,
attributes: [
"washerMode"
] ,
action: "actionApplianceMode"
] ,
"washerOperatingState" : [
name: "Washer Operating State" ,
capability: "capability.washerOperatingState" ,
attributes: [
"machineState" ,
"washerJobState"
] ,
action: "actionMachineState"
] ,
"waterSensor" : [
name: "Water Sensor" ,
capability: "capability.waterSensor" ,
attributes: [
"water"
]
] ,
"windowShade" : [
name: "Window Shade" ,
capability: "capability.windowShade" ,
attributes: [
"windowShade"
] ,
action: "actionOpenClosed"
]
]
definition (
name: "OpenHabAppV2" ,
namespace: "bobrak" ,
author: "Bob Raker" ,
description: "Provides two way communications between a Smartthings Hub and OpenHAB" ,
category: "My Apps" ,
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Connections/Cat-Connections.png" ,
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Connections/Cat-Connections@2x.png" ,
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Connections/Cat-Connections@3x.png"
)
preferences {
section ( "Send Notifications?" ) {
input ( "recipients" , "contact" , title: "Send notifications to" , multiple: true , required: false )
}
section ( "Input" ) {
CAPABILITY_MAP . each { key , capability - >
input key , capability [ "capability" ] , title: capability [ "name" ] , description: capability [ "key" ] , multiple: true , required: false
}
}
section ( "Device" ) {
input "openhabDevice" , "capability.notification" , title: "Notify this virtual device" , required: true , multiple: false
}
}
def installed ( ) {
log . debug "Installed with settings: ${settings}"
initialize ( )
}
def updated ( ) {
log . debug "Updated with settings: ${settings}"
// Unsubscribe from all events
unsubscribe ( )
// Subscribe to stuff
initialize ( )
}
def initialize ( ) {
// Subscribe to new events from devices
CAPABILITY_MAP . each { key , capability - >
capability [ "attributes" ] . each { attribute - >
if ( settings [ key ] ! = null ) {
subscribe ( settings [ key ] , attribute , inputHandler )
log . debug "Subscribing inputHandler to device \"${settings[key]}\" with attribute \"${attribute}\""
}
}
}
// Subscribe to events from the openhabDevice
log . debug "Subscribing to event handler ${openHabDevice}"
subscribe ( openhabDevice , "message" , openhabMessageHandler )
}
// Receive an event from OpenHAB via the openhabDevice
def openhabMessageHandler ( evt ) {
def json = new JsonSlurper ( ) . parseText ( evt . value )
log . debug "Received device event from Message : ${json}"
switch ( json . path ) {
case "update" :
openhabUpdateHandler ( evt )
break
case "state" :
openhabStateHandler ( evt )
break
case "discovery" :
openhabDiscoveryHandler ( evt )
break
default :
log . debug "Received device event from Message **** UNEXPECTED **** : ${json}"
}
}
// Handler for "current" state requests
def openhabStateHandler ( evt ) {
def mapIn = new JsonSlurper ( ) . parseText ( evt . value )
log . debug "Received state event from openhabDevice: ${mapIn}"
// Get the CAPABILITY_MAP entry for this device type
def capability = CAPABILITY_MAP [ mapIn . capabilityKey ]
if ( capability = = null ) {
log . error "No capability: \"${mapIn.capabilityKey}\" exists, make sure there is a CAPABILITY_MAP entry for this capability."
sendErrorResponse "Requested current state information for CAPABILITY: \"${mapIn.capabilityKey}\" but this is not defined in the SmartApp"
return
}
// Verify the attribute is on this capability
if ( ! capability . attributes . contains ( mapIn . capabilityAttribute ) ) {
log . error "Capability \"${mapIn.capabilityKey}\" does NOT contain the expected attribute: \"${mapIn.capabilityAttribute}\", make sure the a CAPABILITY_MAP for this capability contains the missing attribte."
sendErrorResponse "Requested current state information for CAPABILITY: \"${mapIn.capabilityKey}\" with attribute: \"${mapIn.capabilityAttribute}\" but this is attribute not defined for this capability in the SmartApp"
return
}
// Look for the device associated with this capability and return the value of the specified attribute
settings [ mapIn . capabilityKey ] . each { device - >
if ( device . displayName = = mapIn . deviceDisplayName ) {
// Have the device, get the value and return the correct message
def currentState = device . currentValue ( mapIn . capabilityAttribute )
// Have to handle special values. Ones that are not numeric or string
// This switch statement should just be considered a beginning. There are other cases that I dont have devices to test
def capabilityAttr = mapIn . capabilityAttribute
switch ( capabilityAttr ) {
case 'threeAxis' :
currentState = "${currentState}"
break
default :
break
}
def jsonOut = new JsonOutput ( ) . toJson ( [
path: "/smartthings/state" ,
body: [
deviceDisplayName: device . displayName ,
capabilityAttribute: capabilityAttr ,
value: currentState
]
] )
log . debug "State Handler is returning ${jsonOut}"
openhabDevice . deviceNotification ( jsonOut )
}
}
}
// Update a device when requested from OpenHAB
def openhabUpdateHandler ( evt ) {
def json = new JsonSlurper ( ) . parseText ( evt . value )
// log.debug "Received update event from openhabDevice: ${json}"
// printSettings()
if ( json . type = = "notify" ) {
if ( json . name = = "Contacts" ) {
sendNotificationToContacts ( "${json.value}" , recipients )
} else {
sendNotificationEvent ( "${json.value}" )
}
return
}
// Get the CAPABILITY_MAP entry for this device type
def capability = CAPABILITY_MAP [ json . capabilityKey ]
if ( capability = = null ) {
//log.error "No capability: \"${json.capabilityKey}\" exists, make sure there is a CAPABILITY_MAP entry for this capability."
sendErrorResponse "Update failed device displayName of: \"${json.deviceDisplayName}\" with CAPABILITY: \"${json.capabilityKey}\" because that CAPABILTY does not exist in the SmartApp"
return
}
// Look for the device associated with this capability and perform the requested action
settings [ json . capabilityKey ] . each { device - >
// log.debug "openhabUpdateHandler - looking at devices with capabilityKey ${json.capabilityKey} and device{ ${device.displayName}."
if ( device . displayName = = json . deviceDisplayName ) {
log . debug "openhabUpdateHandler - found device for ${json.deviceDisplayName}"
if ( capability . containsKey ( "action" ) ) {
// log.debug "openhabUpdateHandler - Capability ${capability.name} with device name ${device.displayName} changed to ${json.value} using action ${capability.action}"
def action = capability [ "action" ]
// Yes, this is calling the method dynamically
try {
"$action" ( device , json . capabilityAttribute , json . value )
} catch ( e ) {
sendErrorResponse "Error occured while calling action: {$action} for Capability: ${capability.name} with device name: ${device.displayName} changed to: ${json.value}. Exception ${e}"
// log.error "Error occured while calling action: {$action} for Capability: ${capability.name} with device name: ${device.displayName} changed to: ${json.value}. Exception ${e}"
}
}
}
}
}
// Debug method
def printSettings ( ) {
log . debug "**** printSettings() ****"
String out
settings . each { key , device - >
out + = " *** ${key} *** \n"
device . each { d - >
out + = "[ key: ${key}, deviceName: ${d.name}, deviceLabel: ${d.label}, deviceValue: ${d.currentValue} "
/ * The following does work for showing attributes bug significantly expands the output
def attributes = d . getSupportedAttributes ( )
out + = ", attrLen: ${attributes.size()}"
attributes . each { a - >
out + = ", ${a}"
}
out + = "], \n"
* /
}
}
log . debug "*** printSettings() done ***"
}
def sendErrorResponse ( msg ) {
def jsonOut = new JsonOutput ( ) . toJson ( [
path: "/smartthings/error" ,
body: [
message: msg
]
] )
openhabDevice . deviceNotification ( jsonOut )
log . error msg
}
// Send a list of all devices to OpenHAB - used during OpenHAB's discovery process
// The hub is only capable of sending back a buffer of ~40,000 bytes. This routine
// will send multiple responses anytime the buffer exceeds 30,000 bytes
def openhabDiscoveryHandler ( evt ) {
def mapIn = new JsonSlurper ( ) . parseText ( evt . value )
log . debug "Entered discovery handler with mapIn: ${mapIn}"
def results = [ ]
def bufferLength = 0
def deviceCount = 0
CAPABILITY_MAP . each { key , capability - >
capability [ "attributes" ] . each { attribute - >
settings [ key ] . each { device - >
// The device info has to be returned as a string. It will be parsed into device data on the OpenHAB side
def deviceInfo = "{\"capability\": \"${key}\", \"attribute\": \"${attribute}\", \"name\": \"${device.displayName}\", \"id\": \"${device.id}\" }"
results . push ( deviceInfo )
deviceCount + +
bufferLength + = deviceInfo . length ( )
// Check if we have close to a full buffer and if so send it
if ( bufferLength > 30000 ) {
def json = new groovy . json . JsonOutput ( ) . toJson ( [
path: "/smartthings/discovery" ,
body: results
] )
log . debug "Discovery is returning JSON: ${json}"
openhabDevice . deviceNotification ( json )
results = [ ]
bufferLength = 0
}
}
}
}
if ( bufferLength > 0 ) {
def json = new groovy . json . JsonOutput ( ) . toJson ( [
path: "/smartthings/discovery" ,
body: results
] )
log . debug "Discovery is returning FINAL JSON: ${json}"
openhabDevice . deviceNotification ( json )
}
log . debug "Discovery returned data for ${deviceCount} devices."
}
// Receive an event from a device and send it onto OpenHAB
def inputHandler ( evt ) {
def device = evt . device
def capabilities = device . capabilities
def json = new JsonOutput ( ) . toJson ( [
path: "/smartthings/state" ,
body: [
deviceDisplayName: evt . displayName ,
value: evt . value ,
capabilityAttribute: evt . name ,
]
] )
log . debug "Forwarding device event to openhabDevice: ${json}"
openhabDevice . deviceNotification ( json )
}
// +---------------------------------+
// | WARNING, BEYOND HERE BE DRAGONS |
// +---------------------------------+
// These are the functions that handle incoming messages from OpenHAB.
// I tried to put them in closures but apparently SmartThings Groovy sandbox
// restricts you from running closures from an object (it's not safe).
// This handles the basic case where there is one attribute and one action that sets the attribute.
// And, the value is always an ENUM
def actionEnum ( device , attribute , value ) {
log . debug "actionEnum: Setting device \"${device}\" with attribute \"${attribute}\" to value \"${value}\""
//device."${value}"() // I can't figure out why this doesn't work, but it doesn't
def converted = "set" + attribute . capitalize ( )
device . "$converted" ( value )
}
def actionAirConditionerMode ( device , attribute , value ) {
log . debug "actionAirConditionerMode: Setting device \"${device}\" with attribute \"${attribute}\" to value \"${value}\""
device . setAirConditionerMode ( value )
}
def actionAlarm ( device , attribute , value ) {
switch ( value ) {
case "strobe" :
device . strobe ( )
break
case "siren" :
device . siren ( )
break
case "off" :
device . off ( )
break
case "both" :
device . both ( )
break
}
}
// This is the original color control
2021-02-04 09:48:15 +01:00
// 1-19-2021 The color values of on and off were added in response to issue https://github.com/BobRak/OpenHAB-Smartthings/issues/102
// These changes were made because OH 3.0 uses color values of on/off. OH 2 and 3.1 don't seem to need this.
2020-09-21 01:58:32 +02:00
def actionColorControl ( device , attribute , value ) {
log . debug "actionColor: attribute \"${attribute}\", value \"${value}\""
switch ( attribute ) {
case "hue" :
device . setHue ( value as int )
break
case "saturation" :
device . setSaturation ( value as int )
break
case "color" :
2021-02-04 09:48:15 +01:00
if ( value = = "off" ) {
device . off ( )
} else if ( value = = "on" ) {
device . on ( )
} else {
def colormap = [ "hue" : value [ 0 ] as int , "saturation" : value [ 1 ] as int ]
log . debug "actionColorControl: Setting device \"${device}\" with attribute \"${attribute}\" to colormap \"${colormap}\""
device . setColor ( colormap )
device . setLevel ( value [ 2 ] as int )
}
2020-09-21 01:58:32 +02:00
break
}
}
// This is the new "proposed" color. Here hue is 0-360
2021-02-04 09:48:15 +01:00
// 1-19-2021 The attributes of on and off were added in response to issue https://github.com/BobRak/OpenHAB-Smartthings/issues/102
// These changes were made because OH 3.0 uses color values of on/off. OH 2 and 3.1 don't seem to need this.
2020-09-21 01:58:32 +02:00
def actionColor ( device , attribute , value ) {
log . debug "actionColor: attribute \"${attribute}\", value \"${value}\""
switch ( attribute ) {
case "hue" :
device . setHue ( value as int )
break
case "saturation" :
device . setSaturation ( value as int )
break
case "colorValue" :
def colormap = [ "hue" : value [ 0 ] as int , "saturation" : value [ 1 ] as int ]
// log.debug "actionColor: Setting device \"${device}\" with attribute \"${attribute}\" to colormap \"${colormap}\""
device . setColor ( colormap )
device . setLevel ( value [ 2 ] as int )
break
2021-02-04 09:48:15 +01:00
case "off" :
// log.debug "actionColor: Setting device \"${device}\" with attribute \"${attribute}\" to off"
device . off ( )
break
case "on" :
// log.debug "actionColor: Setting device \"${device}\" with attribute \"${attribute}\" to on"
device . on ( )
break
2020-09-21 01:58:32 +02:00
}
}
def actionOpenClosed ( device , attribute , value ) {
if ( value = = "open" ) {
device . open ( )
} else if ( value = = "close" ) {
device . close ( )
}
}
def actionOnOff ( device , attribute , value ) {
if ( value = = "off" ) {
device . off ( )
} else if ( value = = "on" ) {
device . on ( )
}
}
def actionActiveInactive ( device , attribute , value ) {
if ( value = = "active" ) {
device . active ( )
} else if ( value = = "inactive" ) {
device . inactive ( )
}
}
def actionThermostat ( device , attribute , value ) {
log . debug "actionThermostat: Setting device \"${device}\" with attribute \"${attribute}\" to value \"${value}\""
switch ( attribute ) {
case "heatingSetpoint" :
device . setHeatingSetpoint ( value )
break
case "coolingSetpoint" :
device . setCoolingSetpoint ( value )
break
case "thermostatMode" :
device . setThermostatMode ( value )
break
case "thermostatFanMode" :
device . setThermostatFanMode ( value )
break
}
}
def actionMusicPlayer ( device , attribute , value ) {
switch ( attribute ) {
case "level" :
device . setLevel ( value )
break
case "mute" :
if ( value = = "muted" ) {
device . mute ( )
} else if ( value = = "unmuted" ) {
device . unmute ( )
}
break
}
}
def actionColorTemperature ( device , attribute , value ) {
device . setColorTemperature ( value as int )
}
def actionLevel ( device , attribute , value ) {
//log.debug "actionLevel: Setting device \"${device}\" with attribute \"${attribute}\" to value \"${value}\""
// OpenHAB will send on / off or a number for the percent. See what we got and acct accordingly
if ( value = = "off" ) {
device . off ( )
} else if ( value = = "on" ) {
device . on ( )
} else {
device . setLevel ( value as int )
// And, set the switch to on if level > 0 otherwise off
if ( value > 0 ) {
device . on ( )
} else {
device . off ( )
}
}
}
def actionConsumable ( device , attribute , value ) {
device . setConsumableStatus ( value )
}
def actionLock ( device , attribute , value ) {
// log.debug "actionLock: Setting device \"${device}\" with attribute \"${attribute}\" to value \"${value}\""
if ( value = = "locked" ) {
device . lock ( )
} else if ( value = = "unlocked" ) {
device . unlock ( )
}
}
def actionLockOnly ( device , attribute , value ) {
// log.debug "actionLockOnly: Setting device \"${device}\" with attribute \"${attribute}\" to value \"${value}\""
if ( value = = "locked" ) {
device . lock ( )
}
}
def actionTimedSession ( device , attribute , value ) {
if ( attribute = = "timeRemaining" ) {
device . setTimeRemaining ( value )
}
}
def actionApplianceMode ( device , attribute , value ) {
//log.debug "actionDryeMode: attribute: ${attribute} value: ${value}"
// Through trial and error I figured out that changing the dryerMode requires the following code
// Originally this was called actionDryerMode but then the washer was added I renamed and added washer modes
switch ( value ) {
// Modes used by both washer and dryer
case "regular" :
device . regular ( )
break
// Dryer modes
case "lowHeat" :
device . lowHeat ( )
break
case "highHeat" :
device . highHeat ( )
break
// washer modes
case "heavy" :
device . heavy ( )
break
case "rinse" :
device . rinse ( )
break
case "spinDry" :
device . spinDry ( )
break
}
}
def actionMachineState ( device , attribute , value ) {
//log.debug "actionMachineState: attribute: ${attribute} value: ${value}"
// Through trial and error I figured out that changing the machineState requires the following code
switch ( value ) {
case "run" :
device . start ( )
break
case "stop" :
device . stop ( )
break
case "pause" :
device . pause ( )
break
// I'm not sure if unpause() is valid. I saw an error message that included unpause as a valid command but it is not included in the Capabilities for MachineState
case "unpause" :
device . unpause ( )
break
}
}
// The following functions return the current state of a device
def switchState ( device , attribute ) {
device . currentValue ( attribute ) ;
}