diff --git a/devicetypes/astralink/philio-smart-energy-plug-in-switch.src/philio-smart-energy-plug-in-switch.groovy b/devicetypes/astralink/philio-smart-energy-plug-in-switch.src/philio-smart-energy-plug-in-switch.groovy new file mode 100644 index 0000000..66098fb --- /dev/null +++ b/devicetypes/astralink/philio-smart-energy-plug-in-switch.src/philio-smart-energy-plug-in-switch.groovy @@ -0,0 +1,198 @@ +/** + * Copyright 2015 Astralink + * + * 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: "Philio Smart Energy Plug in Switch", namespace: "astralink", author: "AstraLink"){ + capability "Relay Switch" + capability "Power Meter" + capability "Energy Meter" + capability "Actuator" + capability "Switch" + capability "Configuration" + capability "Polling" + capability "Refresh" + capability "Sensor" + + attribute "ManufacturerCode", "string" + attribute "ProductCode", "string" + attribute "ProduceTypeCode", "string" + attribute "WirelessConfig", "string" + attribute "WakeUp", "string" + + fingerprint deviceId: "0x1001", inClusters: "0x5E, 0x86, 0x72, 0x98, 0x5A, 0x85, 0x59, 0x73, 0x25, 0x20, 0x27, 0x32, 0x70, 0x71, 0x75, 0x7A" + } + + // simulator metadata + simulator { + status "on": "command: 2003, payload: FF" + status "off": "command: 2003, payload: 00" + + // 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("configure", "device.power", inactiveLabel: false, decoration: "flat") { + state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" + } + standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") { + state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" + } + + main "switch" + details(["switch","power","energy","refresh","configure"]) + } +} + +def installed() { + zwave.manufacturerSpecificV1.manufacturerSpecificGet().format() +} + +def parse(String description) { + def result = null + def cmd = zwave.parse(description, [0x20: 1, 0x70: 1]) + + log.debug cmd + + if (cmd) { + result = createEvent(zwaveEvent(cmd)) + } + if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) { + result = [result, response(zwave.basicV1.basicGet())] + log.debug "Was hailed: requesting state update" + } else { + log.debug "Parse returned ${result?.descriptionText}" + } + return result +} + +def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { + [name: "switch", value: cmd.value ? "on" : "off", type: "physical"] +} + +def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { + [name: "switch", value: cmd.value ? "on" : "off", type: "digital"] +} + +def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { + log.debug "MeterReport ${cmd}" + + if (cmd.scale == 0) { + [name: "energy", value: cmd.scaledMeterValue, unit: "kWh"] + } else if (cmd.scale == 1) { + [name: "energy", value: cmd.scaledMeterValue, unit: "kVAh"] + } + else { + [name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"] + } +} + +def configure() { + delayBetween([ + zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(), + zwave.associationV2.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format(), + zwave.configurationV1.configurationSet(parameterNumber: 1, size: 2, scaledConfigurationValue: 12).format(), // Watt Meter report 5s per unit + zwave.configurationV1.configurationSet(parameterNumber: 2, size: 2, scaledConfigurationValue: 2).format() // KWH report 10mins per unit + ]) +} + + + +def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { + def value = "when off" + if (cmd.configurationValue[0] == 1) {value = "when on"} + if (cmd.configurationValue[0] == 2) {value = "never"} + [name: "indicatorStatus", value: value, display: false] +} + +def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { + [name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false] +} + +def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { + def result = [] + + def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) + def ManufacturerCode = String.format("%04X", cmd.manufacturerId) + def ProductCode = String.format("%04X", cmd.productId) + def ProduceTypeCode = String.format("%04X", cmd.productTypeId) + def WirelessConfig = "ZWP" + + sendEvent(name: "ManufacturerCode", value: ManufacturerCode) + sendEvent(name: "ProductCode", value: ProductCode) + sendEvent(name: "ProduceTypeCode", value: ProduceTypeCode) + sendEvent(name: "WirelessConfig", value: WirelessConfig) + + result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false) + return result +} + +def zwaveEvent(physicalgraph.zwave.Command cmd) { + return createEvent(descriptionText: "$device.displayName: $cmd", displayed: false) + +} + +def on() { + delayBetween([ + zwave.basicV1.basicSet(value: 0xFF).format(), + zwave.switchBinaryV1.switchBinaryGet().format() + ]) +} + +def off() { + delayBetween([ + zwave.basicV1.basicSet(value: 0x00).format(), + zwave.switchBinaryV1.switchBinaryGet().format() + ]) +} + +def poll() { + zwave.switchBinaryV1.switchBinaryGet().format() +} + +def refresh() { + delayBetween([ + zwave.switchBinaryV1.switchBinaryGet().format(), + zwave.manufacturerSpecificV1.manufacturerSpecificGet().format() + ]) +} +def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { + def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1]) + log.debug "encapsulated: $encapsulatedCommand" + if (encapsulatedCommand) { + state.sec = 1 + zwaveEvent(encapsulatedCommand) + } +} + + +private secure(physicalgraph.zwave.Command cmd) { + zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() +} + +private secureSequence(commands, delay=200) { + delayBetween(commands.collect{ secure(it) }, delay) +} \ No newline at end of file