Verify Zwave parameter settings


(Niall Loftus ) #1

I am trying to verify the zwave parameter settings and I have used the following command to set them in the configure() function for a Fibaro Motion Sensor ( parameter 42 is the lux report interval)

cmds << zwave.configurationV1.configurationSet(configurationValue: [0,220], parameterNumber: 42, size: 2).format()

My problem is trying to read the value to verify it was set correctly. I have tried using the following, but I get the same value reported regardless of the value set.

log.debug "Value: ${zwave.configurationV1.configurationGet(parameterNumber: 42).format()}

I know there are reported problem with lux reporting, but I have just used parameter 42 as an example.


(Kevin) #2

The Get command doesn’t return the value, it’s used the same way as the Set command. After you call the Get command it will send the requested parameter as a Report command.

I believe you would need to put something like the following below your Set line.

cmds << zwave.configurationV1.configurationGet(parameterNumber: 42).format()

And add the method below to retrieve the value.

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {	 
	log.debug "${cmd.configurationValue}"	
}

(Niall Loftus ) #3

Kevin - Thank you for the reply.
I forgot to mention is the original post I had tried what you had suggested and was not getting any debug output so I assume I was not calling the method correctly so I went down another track.
I am not familiar with the groovy syntax.
Any suggestions?


(Kevin) #4

The cmds object needs to be the last line of the method so if you put a log statement below it, nothing would have shown in the log. Without seeing the rest of your code, I can’t really help identify a syntax problem, but the code should have looked something like this:

def someMethod() {
	def cmds = []

	cmds << zwave.configurationV1.configurationSet(configurationValue: [0,220], parameterNumber: 42, size: 2).format()
	
	cmds << zwave.configurationV1.configurationGet(parameterNumber: 42).format()
	
	cmds
}

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {	 
	log.debug "${cmd.configurationValue}"	
}

(Niall Loftus ) #5

Appreciate the help. Thank you.


(the rooms manager guy) #6

having a similar problem. in my configure method trying to get the configuration settings after they are set. but none of the configurationGet seem to actually generate an event at least none that gets received by the parse method.

any help would be much appreciated.

thank you.

delayBetween([
	zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: settings.ReportTime).format(),	//send meter report every x minutes.
	zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: settings.ReportTime).format(),	//accumulated energy report meter interval
	zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 1).format(),	//send only meter report when wattage change 1=meter, 2=multilevel , 3=both, 0=none 
	zwave.configurationV1.configurationSet(parameterNumber: 12, size: 1, scaledConfigurationValue: wattageadjust).format(),//Minimum change in wattage 0-255
	zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: 0).format(),// dont send multilevel report
	zwave.configurationV1.configurationGet(parameterNumber: 8).format(),
	zwave.configurationV1.configurationGet(parameterNumber: 9).format(),
	zwave.configurationV1.configurationGet(parameterNumber: 10).format(),
	zwave.configurationV1.configurationGet(parameterNumber: 11).format(),
	zwave.configurationV1.configurationGet(parameterNumber: 12).format(),
])

EDIT: here is the method i was hoping that would recieve the value and log it.

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug "in config report cmd = $cmd "

[name: "indicatorStatus", value: state.currentIndicatorStatus, display: true]

}


(Kevin) #7

How are you executing the configure command?

If you’re doing it from the updated method or a zwave event you need to wrap delayBetween with response().

I’ve run into some devices that only execute the first few zwave commands if they’re sent to the device too quickly so changing delayBetween([…]) to delayBetween([…], 250) might solve the problem.

By having all the gets at the end, you have no way of knowing if any of the commands made it to the device so I usually put each get command below the set command.


(the rooms manager guy) #8

that delaybetween is the last thing in the configure method which is called from the updated method.

ok. let me try the delay and alternating the sets and gets and see if that works.

thank you.


(the rooms manager guy) #9

EDIT: i think you meant this:

   cmds += configure()
		
	if (cmds) {
		cmds << "delay 1200"
	}
	
	cmds << wakeUpNoMoreInfoCmd()
	return response(cmds)

you mean like this?

def updated() {		
	if (!isDuplicateCommand(state.lastUpdated, 5000)) {
		state.lastUpdated = new Date().time

		logTrace "Executing updated()"
		
		def cmds = configure()
		return cmds ? sendResponse(cmds) : []
	}
}

private sendResponse(cmds) {
	def actions = []
	cmds?.each { cmd ->
		actions << new physicalgraph.device.HubAction(cmd)
	}	
	sendHubCommand(actions)
	return []
}

(the rooms manager guy) #10

this is the DH. none of the zwave commands seem to be going thru, like the configuration set and get. if you dont mind giving it a quick review and share your feedback that would be much appreciated.

thank you.

/**
 *  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.
 * modified by lgkahn v1 for control of the on/off light
 * the lite when on/off is not the normal parameter settings of the config class and there also
 * is no never lite option.. So custom code for this device only.
 *
 */
metadata {
	definition (name: "Enerwave ZW15SM Metering Switch", namespace: "smartthings", author: "LGKahn") {
		capability "Energy Meter"
		capability "Actuator"
		capability "Switch"
		capability "Power Meter"
		capability "Polling"
		capability "Refresh"
		capability "Configuration"
		capability "Sensor"
        capability "Indicator"
        

// bangali - added the next 3 line
//		attribute "power", "string"
//		attribute "energy", "string"
//		attribute "indicatorStatus", "string"
       
		fingerprint inClusters: "0x25,0x32"
	}


preferences {
   input("ReportTime", "number", title: "Report Timeout Interval?", description: "The time in minutes after which an update is sent?", defaultValue: 3, required: false)
   input("WattageChange", "number", title: "Wattage change before reporting: 1-25?", description: "The minimum wattage change before reporting?",defaultValue: 15, required: false)
   }

	// simulator metadata
	simulator {
		status "on":  "command: 2003, payload: FF"
		status "off": "command: 2003, payload: 00"

		for (int i = 0; i <= 10000; i += 1000) {
			status "power  ${i} W": new physicalgraph.zwave.Zwave().meterV1.meterReport(
				scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
		}
		for (int i = 0; i <= 100; i += 10) {
			status "energy  ${i} kWh": new physicalgraph.zwave.Zwave().meterV1.meterReport(
				scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
		}

		// reply messages
		reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
		reply "200100,delay 100,2502": "command: 2503, payload: 00"

	}

	// tile definitions
	tiles {
		standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
			state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
			state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
		}
		valueTile("power", "device.power", inactiveLabel: false, decoration: "flat") {
			state "default", label:'${currentValue} W'
		}
		valueTile("energy", "device.energy") {
			state "default", label:'${currentValue} kWh'
		}
		standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat") {
			state "default", label:'reset kWh', action:"reset"
		}
		standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		standardTile("indicatorStatus", "device.indicatorStatus", width: 1, height: 1, inactiveLabel: false, decoration: "flat") {
			state "when off", action:"indicator.indicatorWhenOn", icon:"st.indicators.lit-when-off"
			state "when on", action:"indicator.indicatorWhenOff", icon:"st.indicators.lit-when-on"
		
		}
		main(["switch","power","energy"])
		details(["switch","power","energy","indicatorStatus","refresh","reset"])
	}
}


def parse(String description) {
	def result = null
log.debug "in parse desc = $description"

	if(description == "updated") return 
	def cmd = zwave.parse(description, [0x20: 1, 0x32: 1, 0x70: 1, 0x72: 2])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	return result
}



def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
log.debug "in meter report cmd = $cmd "

// bangali - commented the following block and changed them to sendEvent from createEvent
	if (cmd.scale == 0) {
		createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kWh")
	} 
    else if (cmd.scale == 1) {
		createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kVAh")
	} 
    else if (cmd.scale == 2) {
		createEvent(name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W")
	}
}


def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
// bangali
log.debug "in basic report cmd = $cmd "

	def evt = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "physical")
	if (evt.isStateChange) {
		[evt, response(["delay 3000", zwave.meterV2.meterGet(scale: 2).format()])]
	}
    else {
		evt
	}
}


def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
// bangali
log.debug "in switch report cmd = $cmd "

	createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
}


def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
// log.debug "in config report  got indicatorstatus = $state.currentIndicatorStatus"	
// bangali
log.debug "in config report cmd = $cmd "

	[name: "indicatorStatus", value: state.currentIndicatorStatus, display: true]
}


def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
log.debug "in manuf specific report cmd = $cmd "

	def result = []
	
	result << response(delayBetween([
		zwave.meterV2.meterGet(scale: 0).format(),
		zwave.meterV2.meterGet(scale: 2).format(),
	]))

	result
}


def zwaveEvent(physicalgraph.zwave.Command cmd) {
// bangali
log.debug "in unhandled report cmd = $cmd"

log.debug "$device.displayName: Unhandled: $cmd"
	[:]
}


def on() {
log.debug "in on"

// bangali - everything originally worked fine except there was no reporting of 
// energy usage unless the refresh button is clicked in the ST app.
// to fix that, this schedules the poll() method to be executed on a recurring 
// schedule when switch is turned on. after this device handler is installed,
// turn on and off the switch for this polling to get scheduled.
// this one is every n minutes where n = reporting interval in settings.
//	schedule("0 */$settings.ReportTime * * * ?", refresh)

// bangali - to change reporting of energy usage to every 30 seconds,
// uncomment the following line and comment the schedule line before this.
//	schedule("0/30 0/1 0 ? * * *", poll)

	[
		zwave.basicV1.basicSet(value: 0xFF).format(),
		zwave.switchBinaryV1.switchBinaryGet().format(),
		"delay 3000",
		zwave.meterV2.meterGet(scale: 2).format()
	]
}


def off() {
log.debug "in off"

// bangali - this unschedules the poll() method when switch is turned off.
//	unschedule(refresh)

	[
    	zwave.basicV1.basicSet(value: 0x00).format(),
		zwave.switchBinaryV1.switchBinaryGet().format(),
		"delay 3000",
		zwave.meterV2.meterGet(scale: 2).format()
	]
}


def poll() {
// bangali - added next 2 lines and commented the remaining lines
log.debug "in poll"
    refresh()
    
//	delayBetween([
//		zwave.switchBinaryV1.switchBinaryGet().format(),
//		zwave.meterV2.meterGet(scale: 0).format(),
//        zwave.meterV2.meterGet(scale: 2).format()
//	])
}


// bangali - added PING is used by Device-Watch in attempt to reach the Device
def ping() {
// bangali
log.debug "in ping"
	refresh()
}


def refresh() {
log.debug "in refresh"

	def value = "when off"
//  log.debug "in refresh for when on got indicatorstatus = $state.currentIndicatorStatus"
	sendEvent(name: "indicatorStatus", value: state.currentIndicatorStatus, display: true)
	
	delayBetween([
		zwave.switchBinaryV1.switchBinaryGet().format(),
		zwave.meterV2.meterGet(scale: 0).format(),
        zwave.meterV2.meterGet(scale: 2).format(),
	], 1000)
}


def updated() {
log.debug "in updated"

	def cmds = []
//bangali - added next 3 lights
    // Device-Watch simply pings if no device events received for 32min(checkInterval)
	sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
    
	cmds = configure()
    unschedule(refresh)
	schedule("0 */$settings.ReportTime * * * ?", refresh)
	return response(cmds)
}


def configure() {
// bangali
log.debug "in configure"

	if (settings.WattageChange < 1 || settings.WattageChange > 25) {
		settings.WattageChange = 5;
	}
 
log.debug "In configure timeout value = $settings.ReportTime"
log.debug "Wattage change = $settings.WattageChange"
def wattageadjust = settings.WattageChange * 10;
log.debug "Wattage change = $settings.WattageChange adjusted: $wattageadjust "

	delayBetween([
		zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: settings.ReportTime).format(),	//send meter report every x minutes.
		zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: settings.ReportTime).format(),	//accumulated energy report meter interval
		zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 1).format(),	//send only meter report when wattage change 1=meter, 2=multilevel , 3=both, 0=none 
		zwave.configurationV1.configurationSet(parameterNumber: 12, size: 1, scaledConfigurationValue: wattageadjust).format(),//Minimum change in wattage 0-255
		zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: 0).format(),// dont send multilevel report
// bangali - added the following
		zwave.configurationV1.configurationGet(parameterNumber: 8).format(),
		zwave.configurationV1.configurationGet(parameterNumber: 9).format(),
		zwave.configurationV1.configurationGet(parameterNumber: 10).format(),
		zwave.configurationV1.configurationGet(parameterNumber: 11).format(),
		zwave.configurationV1.configurationGet(parameterNumber: 12).format(),
    ], 1000)
}


def reset() {
log.debug "in reset"
	state.currentIndicatorStatus = "when on"
	return [
		zwave.meterV2.meterReset().format(),
		zwave.meterV2.meterGet(scale: 0).format()
	]
}


def indicatorWhenOn() {
log.debug "in when on"
	state.currentIndicatorStatus = "when on"
	sendEvent(name: "indicatorStatus", value: "when on", display: true)
	zwave.configurationV1.configurationSet(parameterNumber: 0x01, size: 1, scaledConfigurationValue: 1).format()
}


def indicatorWhenOff() {
log.debug "in when off"
	state.currentIndicatorStatus = "when off"
	sendEvent(name: "indicatorStatus", value: "when off", display: true)	  
	zwave.configurationV1.configurationSet(parameterNumber: 0x01, size: 1, scaledConfigurationValue: 0).format()
}

(Kevin) #11

Yes, that code segment was taken from the wakeupnotification zwave event so cmds had to be wrapped with response.

Nope. That code segment appears to be taken from one of my DTHs which has a workaround I had to put in when a ST Update broke the response command, but they fixed the bug shortly after.

There are a lot of issues unrelated to the configuration commands not making it to the device, but the most poorly written DTHs I’ve seen were written by SmartThings so some of them may have already been there…

You have a comment stating you added 3 attributes, but the attributes are already commeted out so I’m assuming you’re aware that those lines shouldn’t be there because their already declared by the corresponding capabilities.

You also have a comment stating you changed the createEvents into sendEVents in the PowerMeterReport event handler, but that wasn’t necessary.

I’m not sure if the Health Check related code was left over from the original DTH or if you implemented it, but it has several issues. The main one being that it’s not included in the capability list.

The ConfigurationReport event handler is returning a map instead of creatEvent so the indicatorStatus attribute won’t get updated.

The best way to troubleshoot the configuration problem is to add config get after config set in the indicatorWhenOn/off commands because the delay won’t matter since only 2 commands are being sent. I also recommend removing sendEvent from those commands and letting the ConfigurationReport method create it instead.

If that works, then change the configure method so that each config get is under the corresponding config set which will allow you to see if any of the commands are making it to the device.

If adding config get to the indicatorWhenon/off commands didn’t work, check the device’s fingerprint. If you see “sec:” and 70 is in the list then the device most likely only supports configuration commands that have been encapsulated.

If you don’t see “sec:” in the fingerprint then the only other thing I can think of is to try switching to configuration V2. Device’s are supposed to be backwards compatible, but at least one of the devices I’ve worked with wasn’t. To use v2 you have to change the number in your version get/set commands, configurationreport event, and change “0x70: 1” to “0x70: 2” in your parse method.

If I misunderstood the configuration problem and the configuration reports were coming back, but the values weren’t changing then switching to configuration v2 will most likely fix that.


(the rooms manager guy) #12

@krlaframboise thank you much. i am going to parse through each line of your response and go back to work on this one. yes, i did take the examples i posted from your DHs.

thank you again.


(the rooms manager guy) #13

still working through this, this device seems almost flaky. parts will work, then stop working and rework only if i unplug and replug-in the device.

one mystery i am trying to find a clue to is these 2 methods. the poll method seems to get called by ST every ~10 mins and returns the right meter data. the updateWatts method which is scheduled to run every 1 minute, gets called because i see the log output, but the meter data is never returned. given those methods are exactly the same that doesnt seem to make any sense.

any hints? :slight_smile:

def poll()	{
log.debug "in poll()"
	return	[
    	zwave.meterV2.meterGet(scale: 2).format()
    ]
}

def updateWatts()	{
log.debug "in updateWatts()"
	return [
		zwave.meterV2.meterGet(scale: 2).format()
	]
}

thanks!


(Kevin) #14

Commands returned from a method executed by a schedule won’t get sent to the device so you have to use sendHubAction.

If you use that “sendResponse” method of mine, that you previously posted, in your updateWatts method it should solve your problem.


(the rooms manager guy) #15

that fixed it. :slight_smile: thank you.