Zwave Power Strip from AEON

I can’t seem to get any of these to clean compile. They generate many syntax errors. Is there a different development environment to compile these? Also I would like to identify each switch and also use them separately from triggers. Is any of this possible?

@Sorapp They don’t compile, you just place the device handler code into the SmartThings IDE and apply it to the device in the same place.

Bad choice of words. The bottom line is that they get multiple errors which prevents it from saving. On the plus side, I figured out what I was doing wrong. I was not stripping the line numbers when I copied the code. I also have difficulty figuring out which is a device handler and which is the smart app. I am a long time software developer and I tend to try to understand based on my previous experience. I finally got it right and I am very pleased with the results for the Aeon SmartStrip. I also want to thank everyone for their work, I could not have figured this out on my own.
I do still have a question, what happened to the energy usage stats, they are missing in my setup? This is not a show stopper, just curious.

@Sorapp I have a device type that is a work in progress, but there are currently bugs in the Android app that make the formatting look funky. It looks great in iOS so I’m just waiting for the SmartThings team to fix the Android app before pushing it out. If you are using iOS you might want to use it as it works really well. It shows all the energy usage info, even for the two outlets that are not controlled by a switch.

3 Likes

HA didn’t even know these had temp sensors in them, awesome!

Even though I’m on android I tried it on both of my strips.

Seems to be working fine so far. The UI glitch is easily worked around, scroll below first half of the screen, turn the display off then back on, it refreshes and looks, mostly, normal.

@michaelahess Don’t get too excited about the temp sensor. The device rarely reports a change in temperature. It is more of an internal temperature to see if anything is overheating inside I believe.

Good enough for me, both are in a cabinet rack so any temp is a good indicator for my other gear’s health. Assuming it has a nice stable baseline to it. :grin:

Thanks erocm1231 for the code, yes I am using IOS. This is very close to what I am looking for. I would like to suggest 2 small, I hope, changes. First, display the switch Number in each of the 4 switches. Second, display the outlet numbers in each of the 2 fixed outlets. I have looked at the code, but I am not experienced enough to do it myself.

Thanks cooperglee.
I noticed that if I change the state of the individual switches in the SmartStrip thing, the state does not track to the corresponding virtual switch. I installed both the device type and the smartapp and everything seemed to work OK. Am I missing something?

@Sorapp I have posted an updated device type with some of your suggestions. iOS isn’t displaying the label for the outlets, so I am still looking into that.

If you are looking for a SmartApp to sync the Aeon SmartStrip with Virtual Switches, you may want to try my sync app:

If you set the device type of your virtual switches to my “Simulated Energy Switch”, then the virtual switches will have energy and power reported.


6 Likes

Just swapped all my VS’s over to these, seems ok so far, thanks for all this effort Eric!

I can’t remove the Cooper Lee virtual switches smartapp, just says An Unexpected Error Occurred. I’ve tried from the IDE as well. I was able to unassign all the virtual switches so it’s only got a link to the actual aeon smartstrips, which I can’t remove.

Anyone have any thoughts on how to fully remove this?

@michaelahess Can you see if there is an error in the IDE logs when you try to remove it? We might be able to fix it so it removes correctly.

Also, I think SmartThings support can remove it, but it might take them a few days.

No error’s get logged. I’ll open a support ticket, maybe it’s related to my github integration being broken, thanks for the suggestion!

I also have a issue with A Power Strip maybe someone here can help me with it. The issue is that in de simulator it works all fine, I can power the node’s on and off seperatly. But on my app i can only switch the node’s off.

metadata {
	definition (name: "GreenWave", namespace: "greenwave", author: "Smartthings") {
		capability "Switch"
		capability "Energy Meter"
		capability "Power Meter"
		capability "Refresh"
		capability "Configuration"
		capability "Actuator"
		capability "Sensor"

		command "reset"

		(1..6).each { n ->
			attribute "switch$n", "enum", ["on", "off"]
			attribute "power$n", "number"
			attribute "energy$n", "number"
			command "on$n"
			command "off$n"
			command "reset$n"
		}

		fingerprint deviceId: "0x1001", inClusters: "0x25,0x32,0x27,0x70,0x85,0x72,0x86,0x60", outClusters: "0x82"
	}

	// simulator metadata
	simulator {
		status "on":  "command: 2003, payload: FF"
		status "off":  "command: 2003, payload: 00"
		status "switch1 on": "command: 600D, payload: 01 00 25 03 FF"
		status "switch1 off": "command: 600D, payload: 01 00 25 03 00"
		status "switch6 on": "command: 600D, payload: 06 00 25 03 FF"
		status "switch6 off": "command: 600D, payload: 06 00 25 03 00"
		status "power": new physicalgraph.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 30, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
		status "energy": new physicalgraph.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 200, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
		status "power1": "command: 600D, payload: 0100" + new physicalgraph.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 30, precision: 3, meterType: 4, scale: 2, size: 4).format()
		status "energy2": "command: 600D, payload: 0200" + new physicalgraph.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 200, precision: 3, meterType: 0, scale: 0, size: 4).format()

		// 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", decoration: "flat") {
			state "default", label:'${currentValue} W'
		}
		valueTile("energy", "device.energy", decoration: "flat") {
			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"
		}


		(1..6).each { n ->
			standardTile("switch$n", "switch$n", canChangeIcon: true) {
            	state "off", label: '${name}', action: "on$n", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
				state "on", label: '${name}', action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#79b821"
			}
			valueTile("power$n", "power$n", decoration: "flat") {
				state "default", label:'${currentValue} W'
			}
			valueTile("energy$n", "energy$n", decoration: "flat") {
				state "default", label:'${currentValue} kWh'
			}
		}

		main(["switch", "power", "energy", "switch1", "switch2", "switch3", "switch4", "switch5", "switch6"])
		details(["switch","power","energy",
				 "switch1","power1","energy1",
				 "switch2","power2","energy2",
				 "switch3","power3","energy3",
				 "switch4","power4","energy4",
                 "switch5","power5","energy5",
                 "switch6","power6","energy6",
				 "refresh","reset"])
	}
}


def parse(String description) {
	def result = null
	if (description.startsWith("Err")) {
		result = createEvent(descriptionText:description, isStateChange:true)
	} else if (description != "updated") {
		def cmd = zwave.parse(description, [0x60: 3, 0x32: 3, 0x25: 1, 0x20: 1])
		if (cmd) {
			result = zwaveEvent(cmd, null)
		}
	}
	log.debug "parsed '${description}' to ${result.inspect()}"
	result
}

def endpointEvent(endpoint, map) {
	if (endpoint) {
		map.name = map.name + endpoint.toString()
	}
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd, ep) {
	def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 3, 0x25: 1, 0x20: 1])
	if (encapsulatedCommand) {
		if (encapsulatedCommand.commandClassId == 0x32) {
			// Metered outlets are numbered differently than switches
			Integer endpoint = cmd.sourceEndPoint
			if (endpoint > 2) {
				zwaveEvent(encapsulatedCommand, endpoint - 2)
			} else if (endpoint == 0) {
				zwaveEvent(encapsulatedCommand, 0)
			} else {
				log.debug("Ignoring metered outlet $endpoint msg: $encapsulatedCommand")
				[]
			}
		} else {
			zwaveEvent(encapsulatedCommand, cmd.sourceEndPoint as Integer)
		}
	}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, endpoint) {
	def map = [name: "switch", type: "physical", value: (cmd.value ? "on" : "off")]
	def events = [endpointEvent(endpoint, map)]
	def cmds = []
	if (endpoint) {
		cmds += delayBetween([2,0].collect { s -> encap(zwave.meterV3.meterGet(scale: s), endpoint) }, 1000)
		if(endpoint < 4) cmds += ["delay 1500", encap(zwave.basicV1.basicGet(), endpoint + 1)]
	} else if (events[0].isStateChange) {
		events += (1..4).collect { ep -> endpointEvent(ep, map.clone()) }
		cmds << "delay 3000"
		cmds += delayBetween((0..4).collect { ep -> encap(zwave.meterV3.meterGet(scale: 2), ep) }, 800)
	}
	if(cmds) events << response(cmds)
	events
}

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd, endpoint) {
	def map = [name: "switch", value: (cmd.value ? "on" : "off")]
	def events = [endpointEvent(endpoint, map)]
	def cmds = []
	if (!endpoint && events[0].isStateChange) {
		events += (1..4).collect { ep -> endpointEvent(ep, map.clone()) }
		cmds << "delay 3000"
		cmds += delayBetween((1..4).collect { ep -> encap(zwave.meterV3.meterGet(scale: 2), ep) })
	}
	if(cmds) events << response(cmds)
	events
}

def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd, ep) {
	def event = [:]
	def cmds = []
	if (cmd.scale < 2) {
		def val = Math.round(cmd.scaledMeterValue*100)/100.0
		event = endpointEvent(ep, [name: "energy", value: val, unit: ["kWh", "kVAh"][cmd.scale]])
	} else {
		event = endpointEvent(ep, [name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"])
	}
	if (!ep && event.isStateChange && event.name == "energy") {
		// Total strip energy consumption changed, check individual outlets
		(1..4).each { endpoint ->
			cmds << encap(zwave.meterV2.meterGet(scale: 0), endpoint)
			cmds << "delay 400"
		}
	}
	cmds ? [event, response(cmds)] : event
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, ep) {
	updateDataValue("MSR", String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId))
	null
}

def zwaveEvent(physicalgraph.zwave.Command cmd, ep) {
	log.debug "${device.displayName}: Unhandled ${cmd}" + (ep ? " from endpoint $ep" : "")
}

def onOffCmd(value, endpoint = null) {
	[
		encap(zwave.basicV1.basicSet(value: value), endpoint),
		"delay 500",
		encap(zwave.switchBinaryV1.switchBinaryGet(), endpoint),
		"delay 3000",
		encap(zwave.meterV3.meterGet(scale: 2), endpoint)
	]
}

def on() { onOffCmd(0xFF) }
def off() { onOffCmd(0x0) }

def on1() { onOffCmd(0xFF, 1) }
def on2() { onOffCmd(0xFF, 2) }
def on3() { onOffCmd(0xFF, 3) }
def on4() { onOffCmd(0xFF, 4) }
def on5() { onOffCmd(0xFF, 5) }
def on6() { onOffCmd(0xFF, 6) }

def off1() { onOffCmd(0x0, 1) }
def off2() { onOffCmd(0x0, 2) }
def off3() { onOffCmd(0x0, 3) }
def off4() { onOffCmd(0x0, 4) }
def off5() { onOffCmd(0x0, 5) }
def off6() { onOffCmd(0x0, 6) }

def refresh() {
	delayBetween([
		zwave.basicV1.basicGet().format(),
		zwave.meterV3.meterGet(scale: 0).format(),
		zwave.meterV3.meterGet(scale: 2).format(),
		encap(zwave.basicV1.basicGet(), 1)  // further gets are sent from the basic report handler
	])
}

def resetCmd(endpoint = null) {
	delayBetween([
		encap(zwave.meterV2.meterReset(), endpoint),
		encap(zwave.meterV2.meterGet(scale: 0), endpoint)
	])
}

def reset() {
	delayBetween([resetCmd(null), reset1(), reset2(), reset3(), reset4(), reset5(), reset6()])
}

def reset1() { resetCmd(1) }
def reset2() { resetCmd(2) }
def reset3() { resetCmd(3) }
def reset4() { resetCmd(4) }
def reset5() { resetCmd(5) }
def reset6() { resetCmd(6) }
def configure() {
	def cmds = [
		zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, configurationValue: [0, 0, 0, 1]).format(),
		zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, configurationValue: [0, 0, 0x79, 0]).format(),
		zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 90).format(),
	]
	[5, 8, 9, 10, 11].each { p ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: p, size: 2, scaledConfigurationValue: 5).format()
	}
	[12, 15, 16, 17, 18].each { p ->
		cmds << zwave.configurationV1.configurationSet(parameterNumber: p, size: 1, scaledConfigurationValue: 50).format()
	}
	cmds += [
		zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 15*60).format(),
		zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, configurationValue: [1]).format(),
	]
	delayBetween(cmds) + "delay 5000" + refresh()
}

private encap(cmd, endpoint) {
	if (endpoint) {
		if (cmd.commandClassId == 0x32) {
			// Metered outlets are numbered differently than switches
			if (endpoint < 0x80) {
				endpoint += 2
			} else {
				endpoint = ((endpoint & 0x7F) << 2) | 0x80
			}
		}
		zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:endpoint).encapsulate(cmd).format()
	} else {
		cmd.format()
	}
}

@WEBNAR Try my device handler. It is posted a few posts up. You can also use the SmartApp if you want to have individual virtual switches that correspond to the physical switches.

I tried it but that didn’t do a thing for me also i am new to Smartthings since a couple of hours. So i don’t see the screen Virtual or Physical Switch.

How can i create a virtual switch? i don’t see the option in the app.

@WEBNAR FAQ: Creating a virtual Device

1 Like

With your app i get the following error:
java.lang.NullPointerException