Hello!
I'm converting my home from ST to HE, and first off, man, Loving HE! So fast, and so easy! Everything just works! = )
But I'm having issues porting a driver over from ST. I wrote it for a App I wrote "Smart Room". My App ported over just fine, but when I try to save the Driver, I get the error:
Cannot get property 'label' on null object on line 19
I searched the forum for that error, but wasn't able to pull anything applicable from what I read. Line 19 is the 'metadata' line in the below code.
Does anyone have any insights into what I'm doing wrong?
Thanks for your time,
Nick
/**
* Smart Room
*
* Copyright 2015 Nick Albright
*
* 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.
*
*/
public static String version() { return "v1.0.0" }
metadata {
definition (name: "Smart Room", namespace: "albrnick", author: "Nick Albright") {
capability "Presence Sensor" // For Occupied
capability "Switch" // For Lights auto on and off
capability "Motion Sensor" // For triggering the room externally
capability "Thermostat Mode" // Hack for displaying the tile
capability "ContactSensor" // For communicating ligths on or off to room app
attribute "lights", "enum", ["on", "off"]
command "on" // Turn on Lights auto on and off
command "off" // Turn off Lights auto on and off
command "active"
command "inactive"
command "isOccupied" // Is the room occupied?
command "lightsOn" // Turn the room's lights on
command "lightsOff" // Turn the room's lights off
}
simulator {
// TODO: define status and reply messages here
}
// hack
// heat -> Lights Changable & Occupied
// cool -> Lights Changable & UnOccupied
// emergency heat -> Lights Not Changable & UnOccupied
// auto -> Lights Not Changable & Occupied
tiles {
standardTile("thermostatMode", "device.thermostatMode", width: 2, height: 2, canChangeIcon: true ) {
state("heat", label: "occ heat", action: "auto", icon: "st.doors.garage.garage-closed", backgroundColor: "#ffffff", nextState: "auto")
state("cool", label: "${device.label}", action: "emergencyHeat", icon: "st.doors.garage.garage-open", backgroundColor: "#ffffff", nextState: "emergency heat", defaultState: true)
state("emergency heat", label: "c", action: "cool", icon: "st.doors.garage.garage-open", backgroundColor: "#bbbbbb", nextState: "cool")
state("auto", label: "occ auto", action: "heat", icon: "st.doors.garage.garage-closed", backgroundColor: "#bbbbbb", nextState: "heat")
}
standardTile("state", "device.state", width: 2, height: 2, canChangeIcon: true ) {
state("on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "off")
state("off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on")
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state("default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh")
}
main "thermostatMode"
details(["thermostatMode", "state", "refresh"])
}
}
// parse events into attributes
def parse(String description) {
log.debug "xParsing '${description}'"
// TODO: handle 'presence' attribute
// TODO: handle 'switch' attribute
}
def poll() {
log.debug('polled!')
}
def set_state( occupied, no_trigger_lights ) {
log.debug("${device.label} set_state")
def s = null
if (no_trigger_lights) {
if ( occupied ) {
s = 'auto'
} else {
s = 'emergency heat'
}
} else { // Triggerable lights!
if ( occupied ) {
s = 'heat'
} else {
s = 'cool'
}
}
if (s) {
sendEvent( name: 'thermostatMode', value: s, isStateChange: true )
}
log.debug("${device.label} set state to ${s}")
}
def tell_parent_auto_lights() {
log.debug('allowing lights 2')
// Seems to fix a bug where the parent doesn't get like the first event
log.debug("${parent.state.occupied}")
sendEvent(name: 'state', value: 'on')
}
def tell_parent_no_auto_lights() {
log.debug('disallowing lights 2')
// Seems to fix a bug where the parent doesn't get like the first event
log.debug("${parent.state.occupied}")
sendEvent(name: 'state', value: 'off')
}
def lightsOn() {
log.debug( 'Sending lights on')
sendEvent(name: 'lights', value: "on", isStateChange: true )
}
def lightsOff() {
log.debug( 'Sending lights off')
sendEvent(name: 'lights', value: "off", isStateChange: true )
}
// handle commands
// Switch - turn on/off auto lights
def on() {
log.debug("on")
log.debug("state ${state}")
tell_parent_auto_lights()
}
def off() {
log.debug("off")
tell_parent_no_auto_lights()
}
//
def isOccupied() {
return( parent.state.occupied )
}
// Motion sensing
def active() {
log.trace "active() 2"
sendEvent(name: "motion", value: "active")
runIn(1, inactive)
}
def inactive() {
log.trace "inactive() 2"
sendEvent(name: "motion", value: "inactive")
}
def emergencyHeat() {
log.debug("emergencyHeat..2")
tell_parent_no_auto_lights()
sendEvent(name: 'thermostatMode', value: 'emergency heat', isStateChange: true)
}
def auto() {
log.debug('auto..2')
tell_parent_no_auto_lights()
sendEvent(name: 'thermostatMode', value: 'auto', isStateChange: true)
}
def heat() {
log.debug('heat..2')
tell_parent_auto_lights()
sendEvent(name: 'thermostatMode', value: 'heat', isStateChange: true)
}
def cool() {
log.debug('cool..2')
tell_parent_auto_lights()
sendEvent(name: 'thermostatMode', value: 'cool', isStateChange: true)
}