/* Kasa Device Driver Series Copyright Dave Gutheinz License: https://github.com/DaveGut/HubitatActive/blob/master/KasaDevices/License.md ===== Link to list of changes ===== https://github.com/DaveGut/HubitatActive/blob/master/KasaDevices/Changes.pdf ===== Link to Documentation ===== https://github.com/DaveGut/HubitatActive/blob/master/KasaDevices/Documentation.pdf ===================================================================================================*/ def driverVer() { return "2.3.6" } metadata { definition (name: "Kasa Color Bulb", namespace: nameSpace(), author: "Dave Gutheinz", importUrl: "https://raw.githubusercontent.com/DaveGut/HubitatActive/master/KasaDevices/DeviceDrivers/ColorBulb.groovy" ) { capability "Light" capability "Switch" capability "Switch Level" capability "Change Level" capability "Refresh" capability "Actuator" capability "Configuration" command "setCircadian" attribute "circadianState", "string" capability "Color Temperature" capability "Color Mode" capability "Color Control" command "setRGB", [[ name: "red,green,blue", type: "STRING"]] command "bulbPresetCreate", [[ name: "Name for preset.", type: "STRING"]] command "bulbPresetDelete", [[ name: "Name for preset.", type: "STRING"]] command "bulbPresetSet", [[ name: "Name for preset.", type: "STRING"],[ name: "Transition Time (seconds).", type: "STRING"]] command "setPollInterval", [[ name: "Poll Interval in seconds", constraints: ["default", "1 minute", "5 minutes", "10 minutes", "30 minutes"], type: "ENUM"]] capability "Power Meter" capability "Energy Meter" attribute "currMonthTotal", "number" attribute "currMonthAvg", "number" attribute "lastMonthTotal", "number" attribute "lastMonthAvg", "number" attribute "connection", "string" attribute "commsError", "string" } preferences { input ("textEnable", "bool", title: "Enable descriptionText logging", defaultValue: true) input ("logEnable", "bool", title: "Enable debug logging", defaultValue: false) input ("transition_Time", "number", title: "Default Transition time (seconds)", defaultValue: 1) input ("syncBulbs", "bool", title: "Sync Bulb Preset Data", defaultValue: false) input ("emFunction", "bool", title: "Enable Energy Monitor", defaultValue: false) if (emFunction) { input ("energyPollInt", "enum", title: "Energy Poll Interval (minutes)", options: ["1 minute", "5 minutes", "30 minutes"], defaultValue: "30 minutes") } input ("bind", "bool", title: "Kasa Cloud Binding", defalutValue: true) input ("useCloud", "bool", title: "Use Kasa Cloud for device control", defaultValue: false) input ("nameSync", "enum", title: "Synchronize Names", defaultValue: "none", options: ["none": "Don't synchronize", "device" : "Kasa device name master", "Hubitat" : "Hubitat label master"]) input ("manualIp", "string", title: "Manual IP Update [Caution]", defaultValue: getDataValue("deviceIP")) input ("manualPort", "string", title: "Manual Port Update [Caution]", defaultValue: getDataValue("devicePort")) input ("rebootDev", "bool", title: "Reboot device [Caution]", defaultValue: false) } } def installed() { def instStatus= installCommon() state.bulbPresets = [:] logInfo("installed: ${instStatus}") } def updated() { def updStatus = updateCommon() if (syncBulbs) { updStatus << [syncBulbs: syncBulbPresets()] } updStatus << [emFunction: setupEmFunction()] def transTime = transition_Time if (transTime == null) { transTime = 1 device.updateSetting("transition_Time", [type:"number", value: 1]) } updStatus << [transition_Time: transTime] if (!state.bulbPresets) { state.bulbPresets = [:] } logInfo("updated: ${updStatus}") refresh() } def setColorTemperature(colorTemp, level = device.currentValue("level"), transTime = transition_Time) { def lowCt = 2500 def highCt = 9000 if (colorTemp < lowCt) { colorTemp = lowCt } else if (colorTemp > highCt) { colorTemp = highCt } setLightColor(level, colorTemp, 0, 0, transTime) } def distResp(response) { if (response.system) { if (response.system.get_sysinfo) { setSysInfo(response.system.get_sysinfo) if (nameSync == "device") { updateName(response.system.get_sysinfo) } } else if (response.system.set_dev_alias) { updateName(response.system.set_dev_alias) } else { logWarn("distResp: Unhandled response = ${response}") } } else if (response["smartlife.iot.smartbulb.lightingservice"]) { setSysInfo([light_state:response["smartlife.iot.smartbulb.lightingservice"].transition_light_state]) } else if (response["smartlife.iot.common.emeter"]) { distEmeter(response["smartlife.iot.common.emeter"]) } else if (response["smartlife.iot.common.cloud"]) { setBindUnbind(response["smartlife.iot.common.cloud"]) } else if (response["smartlife.iot.common.system"]) { if (response["smartlife.iot.common.system"].reboot) { logWarn("distResp: Rebooting device") } else { logDebug("distResp: Unhandled reboot response: ${response}") } } else { logWarn("distResp: Unhandled response = ${response}") } } def setSysInfo(status) { def lightStatus = status.light_state if (state.lastStatus != lightStatus) { state.lastStatus = lightStatus logInfo("setSysinfo: [status: ${lightStatus}]") def onOff if (lightStatus.on_off == 0) { onOff = "off" } else { onOff = "on" int level = lightStatus.brightness if (device.currentValue("level") != level) { sendEvent(name: "level", value: level, unit: "%") } if (device.currentValue("circadianState") != lightStatus.mode) { sendEvent(name: "circadianState", value: lightStatus.mode) } int colorTemp = lightStatus.color_temp int hue = lightStatus.hue int hubHue = (hue / 3.6).toInteger() int saturation = lightStatus.saturation def colorMode def colorName = " " def rgb = "" def color = "" if (colorTemp > 0) { colorMode = "CT" colorName = convertTemperatureToGenericColorName(colorTemp.toInteger()) } else { colorMode = "RGB" colorName = convertHueToGenericColorName(hubHue.toInteger()) color = "[hue: ${hubHue}, saturation: ${saturation}, level: ${level}]" rgb = hubitat.helper.ColorUtils.hsvToRGB([hubHue, saturation, level]) } if (device.currentValue("colorTemperature") != colorTemp) { sendEvent(name: "colorTemperature", value: colorTemp) sendEvent(name: "colorName", value: colorName) } if (device.currentValue("color") != color) { sendEvent(name: "colorName", value: colorName) sendEvent(name: "color", value: color) sendEvent(name: "hue", value: hubHue) sendEvent(name: "saturation", value: saturation) sendEvent(name: "colorMode", value: colorMode) sendEvent(name: "RGB", value: rgb) } } sendEvent(name: "switch", value: onOff, type: "digital") } runIn(1, getPower) } // ~~~~~ start include (1359) davegut.kasaCommon ~~~~~ library ( // library marker davegut.kasaCommon, line 1 name: "kasaCommon", // library marker davegut.kasaCommon, line 2 namespace: "davegut", // library marker davegut.kasaCommon, line 3 author: "Dave Gutheinz", // library marker davegut.kasaCommon, line 4 description: "Kasa Device Common Methods", // library marker davegut.kasaCommon, line 5 category: "utilities", // library marker davegut.kasaCommon, line 6 documentationLink: "" // library marker davegut.kasaCommon, line 7 ) // library marker davegut.kasaCommon, line 8 def nameSpace() { return "davegut" } // library marker davegut.kasaCommon, line 10 def installCommon() { // library marker davegut.kasaCommon, line 12 pauseExecution(3000) // library marker davegut.kasaCommon, line 13 def instStatus = [:] // library marker davegut.kasaCommon, line 14 if (getDataValue("deviceIP") == "CLOUD") { // library marker davegut.kasaCommon, line 15 sendEvent(name: "connection", value: "CLOUD") // library marker davegut.kasaCommon, line 16 device.updateSetting("useCloud", [type:"bool", value: true]) // library marker davegut.kasaCommon, line 17 instStatus << [useCloud: true, connection: "CLOUD"] // library marker davegut.kasaCommon, line 18 } else { // library marker davegut.kasaCommon, line 19 sendEvent(name: "connection", value: "LAN") // library marker davegut.kasaCommon, line 20 device.updateSetting("useCloud", [type:"bool", value: false]) // library marker davegut.kasaCommon, line 21 instStatus << [useCloud: false, connection: "LAN"] // library marker davegut.kasaCommon, line 22 } // library marker davegut.kasaCommon, line 23 sendEvent(name: "commsError", value: "false") // library marker davegut.kasaCommon, line 25 state.errorCount = 0 // library marker davegut.kasaCommon, line 26 state.pollInterval = "30 minutes" // library marker davegut.kasaCommon, line 27 runIn(1, updated) // library marker davegut.kasaCommon, line 28 return instStatus // library marker davegut.kasaCommon, line 29 } // library marker davegut.kasaCommon, line 30 def updateCommon() { // library marker davegut.kasaCommon, line 32 def updStatus = [:] // library marker davegut.kasaCommon, line 33 if (rebootDev) { // library marker davegut.kasaCommon, line 34 updStatus << [rebootDev: rebootDevice()] // library marker davegut.kasaCommon, line 35 return updStatus // library marker davegut.kasaCommon, line 36 } // library marker davegut.kasaCommon, line 37 unschedule() // library marker davegut.kasaCommon, line 38 updStatus << [bind: bindUnbind()] // library marker davegut.kasaCommon, line 39 if (nameSync != "none") { // library marker davegut.kasaCommon, line 40 updStatus << [nameSync: syncName()] // library marker davegut.kasaCommon, line 41 } // library marker davegut.kasaCommon, line 42 if (logEnable) { runIn(1800, debugLogOff) } // library marker davegut.kasaCommon, line 43 updStatus << [textEnable: textEnable, logEnable: logEnable] // library marker davegut.kasaCommon, line 44 if (manualIp != getDataValue("deviceIP")) { // library marker davegut.kasaCommon, line 45 updateDataValue("deviceIP", manualIp) // library marker davegut.kasaCommon, line 46 updStatus << [ipUpdate: manualIp] // library marker davegut.kasaCommon, line 47 } // library marker davegut.kasaCommon, line 48 if (manualPort != getDataValue("devicePort")) { // library marker davegut.kasaCommon, line 49 updateDataValue("devicePort", manualPort) // library marker davegut.kasaCommon, line 50 updStatus << [portUpdate: manualPort] // library marker davegut.kasaCommon, line 51 } // library marker davegut.kasaCommon, line 52 state.errorCount = 0 // library marker davegut.kasaCommon, line 53 sendEvent(name: "commsError", value: "false") // library marker davegut.kasaCommon, line 54 def pollInterval = state.pollInterval // library marker davegut.kasaCommon, line 55 if (pollInterval == null) { pollInterval = "30 minutes" } // library marker davegut.kasaCommon, line 56 updStatus << [pollInterval: setPollInterval(pollInterval)] // library marker davegut.kasaCommon, line 57 state.remove("UPDATE_AVAILABLE") // library marker davegut.kasaCommon, line 58 state.remove("releaseNotes") // library marker davegut.kasaCommon, line 59 removeDataValue("driverVersion") // library marker davegut.kasaCommon, line 60 if (emFunction) { // library marker davegut.kasaCommon, line 61 scheduleEnergyAttrs() // library marker davegut.kasaCommon, line 62 state.getEnergy = "This Month" // library marker davegut.kasaCommon, line 63 updStatus << [emFunction: "scheduled"] // library marker davegut.kasaCommon, line 64 } // library marker davegut.kasaCommon, line 65 runIn(5, listAttributes) // library marker davegut.kasaCommon, line 66 return updStatus // library marker davegut.kasaCommon, line 67 } // library marker davegut.kasaCommon, line 68 def configure() { // library marker davegut.kasaCommon, line 70 if (parent == null) { // library marker davegut.kasaCommon, line 71 logWarn("configure: No Parent Detected. Configure function ABORTED. Use Save Preferences instead.") // library marker davegut.kasaCommon, line 72 } else { // library marker davegut.kasaCommon, line 73 def confStatus = parent.updateConfigurations() // library marker davegut.kasaCommon, line 74 logInfo("configure: ${confStatus}") // library marker davegut.kasaCommon, line 75 } // library marker davegut.kasaCommon, line 76 } // library marker davegut.kasaCommon, line 77 def refresh() { poll() } // library marker davegut.kasaCommon, line 79 def poll() { getSysinfo() } // library marker davegut.kasaCommon, line 81 def setPollInterval(interval = state.pollInterval) { // library marker davegut.kasaCommon, line 83 if (interval == "default" || interval == "off" || interval == null) { // library marker davegut.kasaCommon, line 84 interval = "30 minutes" // library marker davegut.kasaCommon, line 85 } else if (useCloud || altLan || getDataValue("altComms") == "true") { // library marker davegut.kasaCommon, line 86 if (interval.contains("sec")) { // library marker davegut.kasaCommon, line 87 interval = "1 minute" // library marker davegut.kasaCommon, line 88 logWarn("setPollInterval: Device using Cloud or rawSocket. Poll interval reset to minimum value of 1 minute.") // library marker davegut.kasaCommon, line 89 } // library marker davegut.kasaCommon, line 90 } // library marker davegut.kasaCommon, line 91 state.pollInterval = interval // library marker davegut.kasaCommon, line 92 def pollInterval = interval.substring(0,2).toInteger() // library marker davegut.kasaCommon, line 93 if (interval.contains("sec")) { // library marker davegut.kasaCommon, line 94 def start = Math.round((pollInterval-1) * Math.random()).toInteger() // library marker davegut.kasaCommon, line 95 schedule("${start}/${pollInterval} * * * * ?", "poll") // library marker davegut.kasaCommon, line 96 logWarn("setPollInterval: Polling intervals of less than one minute " + // library marker davegut.kasaCommon, line 97 "can take high resources and may impact hub performance.") // library marker davegut.kasaCommon, line 98 } else { // library marker davegut.kasaCommon, line 99 def start = Math.round(59 * Math.random()).toInteger() // library marker davegut.kasaCommon, line 100 schedule("${start} */${pollInterval} * * * ?", "poll") // library marker davegut.kasaCommon, line 101 } // library marker davegut.kasaCommon, line 102 logDebug("setPollInterval: interval = ${interval}.") // library marker davegut.kasaCommon, line 103 return interval // library marker davegut.kasaCommon, line 104 } // library marker davegut.kasaCommon, line 105 def rebootDevice() { // library marker davegut.kasaCommon, line 107 device.updateSetting("rebootDev", [type:"bool", value: false]) // library marker davegut.kasaCommon, line 108 reboot() // library marker davegut.kasaCommon, line 109 pauseExecution(10000) // library marker davegut.kasaCommon, line 110 return "REBOOTING DEVICE" // library marker davegut.kasaCommon, line 111 } // library marker davegut.kasaCommon, line 112 def bindUnbind() { // library marker davegut.kasaCommon, line 114 def message // library marker davegut.kasaCommon, line 115 if (getDataValue("deviceIP") == "CLOUD") { // library marker davegut.kasaCommon, line 116 device.updateSetting("bind", [type:"bool", value: true]) // library marker davegut.kasaCommon, line 117 device.updateSetting("useCloud", [type:"bool", value: true]) // library marker davegut.kasaCommon, line 118 message = "No deviceIp. Bind not modified." // library marker davegut.kasaCommon, line 119 } else if (bind == null || getDataValue("feature") == "lightStrip") { // library marker davegut.kasaCommon, line 120 message = "Getting current bind state" // library marker davegut.kasaCommon, line 121 getBind() // library marker davegut.kasaCommon, line 122 } else if (bind == true) { // library marker davegut.kasaCommon, line 123 if (!parent.kasaToken || parent.userName == null || parent.userPassword == null) { // library marker davegut.kasaCommon, line 124 message = "Username/pwd not set." // library marker davegut.kasaCommon, line 125 getBind() // library marker davegut.kasaCommon, line 126 } else { // library marker davegut.kasaCommon, line 127 message = "Binding device to the Kasa Cloud." // library marker davegut.kasaCommon, line 128 setBind(parent.userName, parent.userPassword) // library marker davegut.kasaCommon, line 129 } // library marker davegut.kasaCommon, line 130 } else if (bind == false) { // library marker davegut.kasaCommon, line 131 message = "Unbinding device from the Kasa Cloud." // library marker davegut.kasaCommon, line 132 setUnbind() // library marker davegut.kasaCommon, line 133 } // library marker davegut.kasaCommon, line 134 pauseExecution(5000) // library marker davegut.kasaCommon, line 135 return message // library marker davegut.kasaCommon, line 136 } // library marker davegut.kasaCommon, line 137 def setBindUnbind(cmdResp) { // library marker davegut.kasaCommon, line 139 def bindState = true // library marker davegut.kasaCommon, line 140 if (cmdResp.get_info) { // library marker davegut.kasaCommon, line 141 if (cmdResp.get_info.binded == 0) { bindState = false } // library marker davegut.kasaCommon, line 142 logInfo("setBindUnbind: Bind status set to ${bindState}") // library marker davegut.kasaCommon, line 143 setCommsType(bindState) // library marker davegut.kasaCommon, line 144 } else if (cmdResp.bind.err_code == 0){ // library marker davegut.kasaCommon, line 145 getBind() // library marker davegut.kasaCommon, line 146 } else { // library marker davegut.kasaCommon, line 147 logWarn("setBindUnbind: Unhandled response: ${cmdResp}") // library marker davegut.kasaCommon, line 148 } // library marker davegut.kasaCommon, line 149 } // library marker davegut.kasaCommon, line 150 def setCommsType(bindState) { // library marker davegut.kasaCommon, line 152 def commsType = "LAN" // library marker davegut.kasaCommon, line 153 def cloudCtrl = false // library marker davegut.kasaCommon, line 154 if (bindState == false && useCloud == true) { // library marker davegut.kasaCommon, line 155 logWarn("setCommsType: Can not use cloud. Device is not bound to Kasa cloud.") // library marker davegut.kasaCommon, line 156 } else if (bindState == true && useCloud == true && parent.kasaToken) { // library marker davegut.kasaCommon, line 157 commsType = "CLOUD" // library marker davegut.kasaCommon, line 158 cloudCtrl = true // library marker davegut.kasaCommon, line 159 } else if (altLan == true) { // library marker davegut.kasaCommon, line 160 commsType = "AltLAN" // library marker davegut.kasaCommon, line 161 state.response = "" // library marker davegut.kasaCommon, line 162 } // library marker davegut.kasaCommon, line 163 def commsSettings = [bind: bindState, useCloud: cloudCtrl, commsType: commsType] // library marker davegut.kasaCommon, line 164 device.updateSetting("bind", [type:"bool", value: bindState]) // library marker davegut.kasaCommon, line 165 device.updateSetting("useCloud", [type:"bool", value: cloudCtrl]) // library marker davegut.kasaCommon, line 166 sendEvent(name: "connection", value: "${commsType}") // library marker davegut.kasaCommon, line 167 logInfo("setCommsType: ${commsSettings}") // library marker davegut.kasaCommon, line 168 if (getDataValue("plugNo") != null) { // library marker davegut.kasaCommon, line 169 def coordData = [:] // library marker davegut.kasaCommon, line 170 coordData << [bind: bindState] // library marker davegut.kasaCommon, line 171 coordData << [useCloud: cloudCtrl] // library marker davegut.kasaCommon, line 172 coordData << [connection: commsType] // library marker davegut.kasaCommon, line 173 coordData << [altLan: altLan] // library marker davegut.kasaCommon, line 174 parent.coordinate("commsData", coordData, getDataValue("deviceId"), getDataValue("plugNo")) // library marker davegut.kasaCommon, line 175 } // library marker davegut.kasaCommon, line 176 pauseExecution(1000) // library marker davegut.kasaCommon, line 177 } // library marker davegut.kasaCommon, line 178 def syncName() { // library marker davegut.kasaCommon, line 180 def message // library marker davegut.kasaCommon, line 181 if (nameSync == "Hubitat") { // library marker davegut.kasaCommon, line 182 message = "Hubitat Label Sync" // library marker davegut.kasaCommon, line 183 setDeviceAlias(device.getLabel()) // library marker davegut.kasaCommon, line 184 } else if (nameSync == "device") { // library marker davegut.kasaCommon, line 185 message = "Device Alias Sync" // library marker davegut.kasaCommon, line 186 } else { // library marker davegut.kasaCommon, line 187 message = "Not Syncing" // library marker davegut.kasaCommon, line 188 } // library marker davegut.kasaCommon, line 189 device.updateSetting("nameSync",[type:"enum", value:"none"]) // library marker davegut.kasaCommon, line 190 return message // library marker davegut.kasaCommon, line 191 } // library marker davegut.kasaCommon, line 192 def updateName(response) { // library marker davegut.kasaCommon, line 194 def name = device.getLabel() // library marker davegut.kasaCommon, line 195 if (response.alias) { // library marker davegut.kasaCommon, line 196 name = response.alias // library marker davegut.kasaCommon, line 197 device.setLabel(name) // library marker davegut.kasaCommon, line 198 } else if (response.err_code != 0) { // library marker davegut.kasaCommon, line 199 def msg = "updateName: Name Sync from Hubitat to Device returned an error." // library marker davegut.kasaCommon, line 200 msg+= "\n\rNote: Some devices do not support syncing name from the hub.\n\r" // library marker davegut.kasaCommon, line 201 logWarn(msg) // library marker davegut.kasaCommon, line 202 return // library marker davegut.kasaCommon, line 203 } // library marker davegut.kasaCommon, line 204 logInfo("updateName: Hubitat and Kasa device name synchronized to ${name}") // library marker davegut.kasaCommon, line 205 } // library marker davegut.kasaCommon, line 206 def getSysinfo() { // library marker davegut.kasaCommon, line 208 if (getDataValue("altComms") == "true") { // library marker davegut.kasaCommon, line 209 sendTcpCmd("""{"system":{"get_sysinfo":{}}}""") // library marker davegut.kasaCommon, line 210 } else { // library marker davegut.kasaCommon, line 211 sendCmd("""{"system":{"get_sysinfo":{}}}""") // library marker davegut.kasaCommon, line 212 } // library marker davegut.kasaCommon, line 213 } // library marker davegut.kasaCommon, line 214 def bindService() { // library marker davegut.kasaCommon, line 216 def service = "cnCloud" // library marker davegut.kasaCommon, line 217 def feature = getDataValue("feature") // library marker davegut.kasaCommon, line 218 if (feature.contains("Bulb") || feature == "lightStrip") { // library marker davegut.kasaCommon, line 219 service = "smartlife.iot.common.cloud" // library marker davegut.kasaCommon, line 220 } // library marker davegut.kasaCommon, line 221 return service // library marker davegut.kasaCommon, line 222 } // library marker davegut.kasaCommon, line 223 def getBind() { // library marker davegut.kasaCommon, line 225 if (getDataValue("deviceIP") == "CLOUD") { // library marker davegut.kasaCommon, line 226 logDebug("getBind: [status: notRun, reason: [deviceIP: CLOUD]]") // library marker davegut.kasaCommon, line 227 } else { // library marker davegut.kasaCommon, line 228 sendLanCmd("""{"${bindService()}":{"get_info":{}}}""") // library marker davegut.kasaCommon, line 229 } // library marker davegut.kasaCommon, line 230 } // library marker davegut.kasaCommon, line 231 def setBind(userName, password) { // library marker davegut.kasaCommon, line 233 if (getDataValue("deviceIP") == "CLOUD") { // library marker davegut.kasaCommon, line 234 logDebug("setBind: [status: notRun, reason: [deviceIP: CLOUD]]") // library marker davegut.kasaCommon, line 235 } else { // library marker davegut.kasaCommon, line 236 sendLanCmd("""{"${bindService()}":{"bind":{"username":"${userName}",""" + // library marker davegut.kasaCommon, line 237 """"password":"${password}"}},""" + // library marker davegut.kasaCommon, line 238 """"${bindService()}":{"get_info":{}}}""") // library marker davegut.kasaCommon, line 239 } // library marker davegut.kasaCommon, line 240 } // library marker davegut.kasaCommon, line 241 def setUnbind() { // library marker davegut.kasaCommon, line 243 if (getDataValue("deviceIP") == "CLOUD") { // library marker davegut.kasaCommon, line 244 logDebug("setUnbind: [status: notRun, reason: [deviceIP: CLOUD]]") // library marker davegut.kasaCommon, line 245 } else { // library marker davegut.kasaCommon, line 246 sendLanCmd("""{"${bindService()}":{"unbind":""},""" + // library marker davegut.kasaCommon, line 247 """"${bindService()}":{"get_info":{}}}""") // library marker davegut.kasaCommon, line 248 } // library marker davegut.kasaCommon, line 249 } // library marker davegut.kasaCommon, line 250 def sysService() { // library marker davegut.kasaCommon, line 252 def service = "system" // library marker davegut.kasaCommon, line 253 def feature = getDataValue("feature") // library marker davegut.kasaCommon, line 254 if (feature.contains("Bulb") || feature == "lightStrip") { // library marker davegut.kasaCommon, line 255 service = "smartlife.iot.common.system" // library marker davegut.kasaCommon, line 256 } // library marker davegut.kasaCommon, line 257 return service // library marker davegut.kasaCommon, line 258 } // library marker davegut.kasaCommon, line 259 def reboot() { // library marker davegut.kasaCommon, line 261 sendCmd("""{"${sysService()}":{"reboot":{"delay":1}}}""") // library marker davegut.kasaCommon, line 262 } // library marker davegut.kasaCommon, line 263 def setDeviceAlias(newAlias) { // library marker davegut.kasaCommon, line 265 if (getDataValue("plugNo") != null) { // library marker davegut.kasaCommon, line 266 sendCmd("""{"context":{"child_ids":["${getDataValue("plugId")}"]},""" + // library marker davegut.kasaCommon, line 267 """"system":{"set_dev_alias":{"alias":"${device.getLabel()}"}}}""") // library marker davegut.kasaCommon, line 268 } else { // library marker davegut.kasaCommon, line 269 sendCmd("""{"${sysService()}":{"set_dev_alias":{"alias":"${device.getLabel()}"}}}""") // library marker davegut.kasaCommon, line 270 } // library marker davegut.kasaCommon, line 271 } // library marker davegut.kasaCommon, line 272 // ~~~~~ end include (1359) davegut.kasaCommon ~~~~~ // ~~~~~ start include (1360) davegut.kasaCommunications ~~~~~ library ( // library marker davegut.kasaCommunications, line 1 name: "kasaCommunications", // library marker davegut.kasaCommunications, line 2 namespace: "davegut", // library marker davegut.kasaCommunications, line 3 author: "Dave Gutheinz", // library marker davegut.kasaCommunications, line 4 description: "Kasa Communications Methods", // library marker davegut.kasaCommunications, line 5 category: "communications", // library marker davegut.kasaCommunications, line 6 documentationLink: "" // library marker davegut.kasaCommunications, line 7 ) // library marker davegut.kasaCommunications, line 8 import groovy.json.JsonSlurper // library marker davegut.kasaCommunications, line 10 import org.json.JSONObject // library marker davegut.kasaCommunications, line 11 def getPort() { // library marker davegut.kasaCommunications, line 13 def port = 9999 // library marker davegut.kasaCommunications, line 14 if (getDataValue("devicePort")) { // library marker davegut.kasaCommunications, line 15 port = getDataValue("devicePort") // library marker davegut.kasaCommunications, line 16 } // library marker davegut.kasaCommunications, line 17 return port // library marker davegut.kasaCommunications, line 18 } // library marker davegut.kasaCommunications, line 19 def sendCmd(command) { // library marker davegut.kasaCommunications, line 21 state.lastCommand = command // library marker davegut.kasaCommunications, line 22 def connection = device.currentValue("connection") // library marker davegut.kasaCommunications, line 23 if (connection == "LAN") { // library marker davegut.kasaCommunications, line 24 sendLanCmd(command) // library marker davegut.kasaCommunications, line 25 } else if (connection == "CLOUD") { // library marker davegut.kasaCommunications, line 26 sendKasaCmd(command) // library marker davegut.kasaCommunications, line 27 } else if (connection == "AltLAN") { // library marker davegut.kasaCommunications, line 28 sendTcpCmd(command) // library marker davegut.kasaCommunications, line 29 } else { // library marker davegut.kasaCommunications, line 30 logWarn("sendCmd: attribute connection is not set.") // library marker davegut.kasaCommunications, line 31 } // library marker davegut.kasaCommunications, line 32 } // library marker davegut.kasaCommunications, line 33 /////////////////////////////////// // library marker davegut.kasaCommunications, line 35 def sendLanCmd(command) { // library marker davegut.kasaCommunications, line 36 logDebug("sendLanCmd: [ip: ${getDataValue("deviceIP")}, cmd: ${command}]") // library marker davegut.kasaCommunications, line 37 def myHubAction = new hubitat.device.HubAction( // library marker davegut.kasaCommunications, line 38 outputXOR(command), // library marker davegut.kasaCommunications, line 39 hubitat.device.Protocol.LAN, // library marker davegut.kasaCommunications, line 40 [type: hubitat.device.HubAction.Type.LAN_TYPE_UDPCLIENT, // library marker davegut.kasaCommunications, line 41 destinationAddress: "${getDataValue("deviceIP")}:${getPort()}", // library marker davegut.kasaCommunications, line 42 encoding: hubitat.device.HubAction.Encoding.HEX_STRING, // library marker davegut.kasaCommunications, line 43 parseWarning: true, // library marker davegut.kasaCommunications, line 44 timeout: 9, // library marker davegut.kasaCommunications, line 45 ignoreResponse: false, // library marker davegut.kasaCommunications, line 46 callback: "parseUdp"]) // library marker davegut.kasaCommunications, line 47 try { // library marker davegut.kasaCommunications, line 48 sendHubCommand(myHubAction) // library marker davegut.kasaCommunications, line 49 } catch (e) { // library marker davegut.kasaCommunications, line 50 handleCommsError() // library marker davegut.kasaCommunications, line 51 logWarn("sendLanCmd: LAN Error = ${e}.\n\rNo retry on this error.") // library marker davegut.kasaCommunications, line 52 } // library marker davegut.kasaCommunications, line 53 } // library marker davegut.kasaCommunications, line 54 def parseUdp(message) { // library marker davegut.kasaCommunications, line 55 def resp = parseLanMessage(message) // library marker davegut.kasaCommunications, line 56 if (resp.type == "LAN_TYPE_UDPCLIENT") { // library marker davegut.kasaCommunications, line 57 def clearResp = inputXOR(resp.payload) // library marker davegut.kasaCommunications, line 58 if (clearResp.length() > 1023) { // library marker davegut.kasaCommunications, line 59 if (clearResp.contains("preferred")) { // library marker davegut.kasaCommunications, line 60 clearResp = clearResp.substring(0,clearResp.indexOf("preferred")-2) + "}}}" // library marker davegut.kasaCommunications, line 61 } else if (clearResp.contains("child_num")) { // library marker davegut.kasaCommunications, line 62 clearResp = clearResp.substring(0,clearResp.indexOf("child_num") -2) + "}}}" // library marker davegut.kasaCommunications, line 63 } else { // library marker davegut.kasaCommunications, line 64 logWarn("parseUdp: [status: converting to altComms, error: udp msg can not be parsed]") // library marker davegut.kasaCommunications, line 65 logDebug("parseUdp: [messageData: ${clearResp}]") // library marker davegut.kasaCommunications, line 66 updateDataValue("altComms", "true") // library marker davegut.kasaCommunications, line 67 sendTcpCmd(state.lastCommand) // library marker davegut.kasaCommunications, line 68 return // library marker davegut.kasaCommunications, line 69 } // library marker davegut.kasaCommunications, line 70 } // library marker davegut.kasaCommunications, line 71 def cmdResp = new JsonSlurper().parseText(clearResp) // library marker davegut.kasaCommunications, line 72 logDebug("parseUdp: ${cmdResp}") // library marker davegut.kasaCommunications, line 73 distResp(cmdResp) // library marker davegut.kasaCommunications, line 74 setCommsError(false) // library marker davegut.kasaCommunications, line 75 } else { // library marker davegut.kasaCommunications, line 76 logDebug("parseUdp: [error: error, reason: not LAN_TYPE_UDPCLIENT, respType: ${resp.type}]") // library marker davegut.kasaCommunications, line 77 handleCommsError() // library marker davegut.kasaCommunications, line 78 } // library marker davegut.kasaCommunications, line 79 } // library marker davegut.kasaCommunications, line 80 def sendKasaCmd(command) { // library marker davegut.kasaCommunications, line 82 logDebug("sendKasaCmd: ${command}") // library marker davegut.kasaCommunications, line 83 def cmdResponse = "" // library marker davegut.kasaCommunications, line 84 def cmdBody = [ // library marker davegut.kasaCommunications, line 85 method: "passthrough", // library marker davegut.kasaCommunications, line 86 params: [ // library marker davegut.kasaCommunications, line 87 deviceId: getDataValue("deviceId"), // library marker davegut.kasaCommunications, line 88 requestData: "${command}" // library marker davegut.kasaCommunications, line 89 ] // library marker davegut.kasaCommunications, line 90 ] // library marker davegut.kasaCommunications, line 91 if (!parent.kasaCloudUrl || !parent.kasaToken) { // library marker davegut.kasaCommunications, line 92 logWarn("sendKasaCmd: Cloud interface not properly set up.") // library marker davegut.kasaCommunications, line 93 return // library marker davegut.kasaCommunications, line 94 } // library marker davegut.kasaCommunications, line 95 def sendCloudCmdParams = [ // library marker davegut.kasaCommunications, line 96 uri: "${parent.kasaCloudUrl}/?token=${parent.kasaToken}", // library marker davegut.kasaCommunications, line 97 requestContentType: 'application/json', // library marker davegut.kasaCommunications, line 98 contentType: 'application/json', // library marker davegut.kasaCommunications, line 99 headers: ['Accept':'application/json; version=1, */*; q=0.01'], // library marker davegut.kasaCommunications, line 100 timeout: 10, // library marker davegut.kasaCommunications, line 101 body : new groovy.json.JsonBuilder(cmdBody).toString() // library marker davegut.kasaCommunications, line 102 ] // library marker davegut.kasaCommunications, line 103 try { // library marker davegut.kasaCommunications, line 104 asynchttpPost("cloudParse", sendCloudCmdParams) // library marker davegut.kasaCommunications, line 105 } catch (e) { // library marker davegut.kasaCommunications, line 106 def msg = "sendKasaCmd: Error in Cloud Communications. The Kasa Cloud is unreachable." // library marker davegut.kasaCommunications, line 107 msg += "\nAdditional Data: Error = ${e}\n\n" // library marker davegut.kasaCommunications, line 108 logWarn(msg) // library marker davegut.kasaCommunications, line 109 } // library marker davegut.kasaCommunications, line 110 } // library marker davegut.kasaCommunications, line 111 def cloudParse(resp, data = null) { // library marker davegut.kasaCommunications, line 112 try { // library marker davegut.kasaCommunications, line 113 response = new JsonSlurper().parseText(resp.data) // library marker davegut.kasaCommunications, line 114 } catch (e) { // library marker davegut.kasaCommunications, line 115 response = [error_code: 9999, data: e] // library marker davegut.kasaCommunications, line 116 } // library marker davegut.kasaCommunications, line 117 if (resp.status == 200 && response.error_code == 0 && resp != []) { // library marker davegut.kasaCommunications, line 118 def cmdResp = new JsonSlurper().parseText(response.result.responseData) // library marker davegut.kasaCommunications, line 119 logDebug("cloudParse: ${cmdResp}") // library marker davegut.kasaCommunications, line 120 distResp(cmdResp) // library marker davegut.kasaCommunications, line 121 } else { // library marker davegut.kasaCommunications, line 122 def msg = "cloudParse:\nError from the Kasa Cloud. Most common cause is " // library marker davegut.kasaCommunications, line 123 msg += "your Kasa Token has expired. Run Kasa Login and Token update and try again." // library marker davegut.kasaCommunications, line 124 msg += "\nAdditional Data: Error = ${resp.data}\n\n" // library marker davegut.kasaCommunications, line 125 logDebug(msg) // library marker davegut.kasaCommunications, line 126 } // library marker davegut.kasaCommunications, line 127 } // library marker davegut.kasaCommunications, line 128 def sendTcpCmd(command) { // library marker davegut.kasaCommunications, line 130 logDebug("sendTcpCmd: ${command}") // library marker davegut.kasaCommunications, line 131 try { // library marker davegut.kasaCommunications, line 132 interfaces.rawSocket.connect("${getDataValue("deviceIP")}", // library marker davegut.kasaCommunications, line 133 getPort().toInteger(), byteInterface: true) // library marker davegut.kasaCommunications, line 134 } catch (error) { // library marker davegut.kasaCommunications, line 135 logDebug("SendTcpCmd: [connectFailed: [ip: ${getDataValue("deviceIP")}, Error = ${error}]]") // library marker davegut.kasaCommunications, line 136 } // library marker davegut.kasaCommunications, line 137 state.response = "" // library marker davegut.kasaCommunications, line 138 interfaces.rawSocket.sendMessage(outputXorTcp(command)) // library marker davegut.kasaCommunications, line 139 } // library marker davegut.kasaCommunications, line 140 def close() { interfaces.rawSocket.close() } // library marker davegut.kasaCommunications, line 141 def socketStatus(message) { // library marker davegut.kasaCommunications, line 142 if (message != "receive error: Stream closed.") { // library marker davegut.kasaCommunications, line 143 logDebug("socketStatus: Socket Established") // library marker davegut.kasaCommunications, line 144 } else { // library marker davegut.kasaCommunications, line 145 logWarn("socketStatus = ${message}") // library marker davegut.kasaCommunications, line 146 } // library marker davegut.kasaCommunications, line 147 } // library marker davegut.kasaCommunications, line 148 def parse(message) { // library marker davegut.kasaCommunications, line 149 if (message != null || message != "") { // library marker davegut.kasaCommunications, line 150 def response = state.response.concat(message) // library marker davegut.kasaCommunications, line 151 state.response = response // library marker davegut.kasaCommunications, line 152 extractTcpResp(response) // library marker davegut.kasaCommunications, line 153 } // library marker davegut.kasaCommunications, line 154 } // library marker davegut.kasaCommunications, line 155 def extractTcpResp(response) { // library marker davegut.kasaCommunications, line 156 def cmdResp // library marker davegut.kasaCommunications, line 157 def clearResp = inputXorTcp(response) // library marker davegut.kasaCommunications, line 158 if (clearResp.endsWith("}}}")) { // library marker davegut.kasaCommunications, line 159 interfaces.rawSocket.close() // library marker davegut.kasaCommunications, line 160 try { // library marker davegut.kasaCommunications, line 161 cmdResp = parseJson(clearResp) // library marker davegut.kasaCommunications, line 162 distResp(cmdResp) // library marker davegut.kasaCommunications, line 163 } catch (e) { // library marker davegut.kasaCommunications, line 164 logWarn("extractTcpResp: [length: ${clearResp.length()}, clearResp: ${clearResp}, comms error: ${e}]") // library marker davegut.kasaCommunications, line 165 } // library marker davegut.kasaCommunications, line 166 } else if (clearResp.length() > 2000) { // library marker davegut.kasaCommunications, line 167 interfaces.rawSocket.close() // library marker davegut.kasaCommunications, line 168 } // library marker davegut.kasaCommunications, line 169 } // library marker davegut.kasaCommunications, line 170 //////////////////////////////////////// // library marker davegut.kasaCommunications, line 175 def handleCommsError() { // library marker davegut.kasaCommunications, line 176 Map logData = [:] // library marker davegut.kasaCommunications, line 177 if (state.lastCommand != "") { // library marker davegut.kasaCommunications, line 178 def count = state.errorCount + 1 // library marker davegut.kasaCommunications, line 179 state.errorCount = count // library marker davegut.kasaCommunications, line 180 def retry = true // library marker davegut.kasaCommunications, line 181 def cmdData = new JSONObject(state.lastCmd) // library marker davegut.kasaCommunications, line 182 def cmdBody = parseJson(cmdData.cmdBody.toString()) // library marker davegut.kasaCommunications, line 183 logData << [count: count, command: state.lastCommand] // library marker davegut.kasaCommunications, line 184 switch (count) { // library marker davegut.kasaCommunications, line 185 case 1: // library marker davegut.kasaCommunications, line 186 case 2: // library marker davegut.kasaCommunications, line 187 if (getDataValue("altComms") == "true") { // library marker davegut.kasaCommunications, line 188 sendTcpCmd(state.lastCommand) // library marker davegut.kasaCommunications, line 189 } else { // library marker davegut.kasaCommunications, line 190 sendCmd(state.lastCommand) // library marker davegut.kasaCommunications, line 191 } // library marker davegut.kasaCommunications, line 192 logDebug("handleCommsError: ${logData}") // library marker davegut.kasaCommunications, line 193 break // library marker davegut.kasaCommunications, line 194 case 3: // library marker davegut.kasaCommunications, line 195 logData << [setCommsError: setCommsError(true), status: "retriesDisabled"] // library marker davegut.kasaCommunications, line 196 logError("handleCommsError: ${logData}") // library marker davegut.kasaCommunications, line 197 break // library marker davegut.kasaCommunications, line 198 default: // library marker davegut.kasaCommunications, line 199 break // library marker davegut.kasaCommunications, line 200 } // library marker davegut.kasaCommunications, line 201 } // library marker davegut.kasaCommunications, line 202 } // library marker davegut.kasaCommunications, line 203 ///////////////////////////////////////////// // library marker davegut.kasaCommunications, line 204 def setCommsError(status) { // library marker davegut.kasaCommunications, line 205 if (!status) { // library marker davegut.kasaCommunications, line 206 sendEvent(name: "commsError", value: "false") // library marker davegut.kasaCommunications, line 207 state.errorCount = 0 // library marker davegut.kasaCommunications, line 208 } else { // library marker davegut.kasaCommunications, line 209 sendEvent(name: "commsError", value: "false") // library marker davegut.kasaCommunications, line 210 return "commsErrorSet" // library marker davegut.kasaCommunications, line 211 } // library marker davegut.kasaCommunications, line 212 } // library marker davegut.kasaCommunications, line 213 //////////////////////////////////////////////////////////////////// // library marker davegut.kasaCommunications, line 216 def xxhandleCommsError() { // library marker davegut.kasaCommunications, line 217 if (state.lastCommand == "") { return } // library marker davegut.kasaCommunications, line 218 def count = state.errorCount + 1 // library marker davegut.kasaCommunications, line 219 state.errorCount = count // library marker davegut.kasaCommunications, line 220 def retry = true // library marker davegut.kasaCommunications, line 221 def status = [count: count, command: state.lastCommand] // library marker davegut.kasaCommunications, line 222 if (count == 3) { // library marker davegut.kasaCommunications, line 223 def attemptFix = parent.fixConnection() // library marker davegut.kasaCommunications, line 224 status << [attemptFixResult: [attemptFix]] // library marker davegut.kasaCommunications, line 225 } else if (count >= 4) { // library marker davegut.kasaCommunications, line 226 retry = false // library marker davegut.kasaCommunications, line 227 } // library marker davegut.kasaCommunications, line 228 if (retry == true) { // library marker davegut.kasaCommunications, line 229 if (state.lastCommand != null) { // library marker davegut.kasaCommunications, line 230 if (getDataValue("altComms") == "true") { // library marker davegut.kasaCommunications, line 231 sendTcpCmd(state.lastCommand) // library marker davegut.kasaCommunications, line 232 } else { // library marker davegut.kasaCommunications, line 233 sendCmd(state.lastCommand) // library marker davegut.kasaCommunications, line 234 } // library marker davegut.kasaCommunications, line 235 } // library marker davegut.kasaCommunications, line 236 } else { // library marker davegut.kasaCommunications, line 237 setCommsError() // library marker davegut.kasaCommunications, line 238 } // library marker davegut.kasaCommunications, line 239 status << [retry: retry] // library marker davegut.kasaCommunications, line 240 if (status.count > 2) { // library marker davegut.kasaCommunications, line 241 logWarn("handleCommsError: ${status}") // library marker davegut.kasaCommunications, line 242 } else { // library marker davegut.kasaCommunications, line 243 logDebug("handleCommsError: ${status}") // library marker davegut.kasaCommunications, line 244 } // library marker davegut.kasaCommunications, line 245 } // library marker davegut.kasaCommunications, line 246 /////////////////////////////////////////////////////// // library marker davegut.kasaCommunications, line 247 def xxsetCommsError() { // library marker davegut.kasaCommunications, line 248 if (device.currentValue("commsError") == "false") { // library marker davegut.kasaCommunications, line 249 def message = "Can't connect to your device at ${getDataValue("deviceIP")}:${getPort()}. " // library marker davegut.kasaCommunications, line 250 message += "Refer to troubleshooting guide commsError section." // library marker davegut.kasaCommunications, line 251 sendEvent(name: "commsError", value: "true") // library marker davegut.kasaCommunications, line 252 state.COMMS_ERROR = message // library marker davegut.kasaCommunications, line 253 logWarn("setCommsError: ${message}") // library marker davegut.kasaCommunications, line 254 runIn(15, limitPollInterval) // library marker davegut.kasaCommunications, line 255 } // library marker davegut.kasaCommunications, line 256 } // library marker davegut.kasaCommunications, line 257 ///////////////////////////////////////////////////////////////// // library marker davegut.kasaCommunications, line 258 def xxlimitPollInterval() { // library marker davegut.kasaCommunications, line 259 state.nonErrorPollInterval = state.pollInterval // library marker davegut.kasaCommunications, line 260 setPollInterval("30 minutes") // library marker davegut.kasaCommunications, line 261 } // library marker davegut.kasaCommunications, line 262 //////////////////////////////////////////////////////////////// // library marker davegut.kasaCommunications, line 263 def xxresetCommsError() { // library marker davegut.kasaCommunications, line 264 state.errorCount = 0 // library marker davegut.kasaCommunications, line 265 if (device.currentValue("commsError") == "true") { // library marker davegut.kasaCommunications, line 266 sendEvent(name: "commsError", value: "false") // library marker davegut.kasaCommunications, line 267 setPollInterval(state.nonErrorPollInterval) // library marker davegut.kasaCommunications, line 268 state.remove("nonErrorPollInterval") // library marker davegut.kasaCommunications, line 269 state.remove("COMMS_ERROR") // library marker davegut.kasaCommunications, line 270 logInfo("resetCommsError: Comms error cleared!") // library marker davegut.kasaCommunications, line 271 } // library marker davegut.kasaCommunications, line 272 } // library marker davegut.kasaCommunications, line 273 private outputXOR(command) { // library marker davegut.kasaCommunications, line 277 def str = "" // library marker davegut.kasaCommunications, line 278 def encrCmd = "" // library marker davegut.kasaCommunications, line 279 def key = 0xAB // library marker davegut.kasaCommunications, line 280 for (int i = 0; i < command.length(); i++) { // library marker davegut.kasaCommunications, line 281 str = (command.charAt(i) as byte) ^ key // library marker davegut.kasaCommunications, line 282 key = str // library marker davegut.kasaCommunications, line 283 encrCmd += Integer.toHexString(str) // library marker davegut.kasaCommunications, line 284 } // library marker davegut.kasaCommunications, line 285 return encrCmd // library marker davegut.kasaCommunications, line 286 } // library marker davegut.kasaCommunications, line 287 private inputXOR(encrResponse) { // library marker davegut.kasaCommunications, line 289 String[] strBytes = encrResponse.split("(?<=\\G.{2})") // library marker davegut.kasaCommunications, line 290 def cmdResponse = "" // library marker davegut.kasaCommunications, line 291 def key = 0xAB // library marker davegut.kasaCommunications, line 292 def nextKey // library marker davegut.kasaCommunications, line 293 byte[] XORtemp // library marker davegut.kasaCommunications, line 294 for(int i = 0; i < strBytes.length; i++) { // library marker davegut.kasaCommunications, line 295 nextKey = (byte)Integer.parseInt(strBytes[i], 16) // could be negative // library marker davegut.kasaCommunications, line 296 XORtemp = nextKey ^ key // library marker davegut.kasaCommunications, line 297 key = nextKey // library marker davegut.kasaCommunications, line 298 cmdResponse += new String(XORtemp) // library marker davegut.kasaCommunications, line 299 } // library marker davegut.kasaCommunications, line 300 return cmdResponse // library marker davegut.kasaCommunications, line 301 } // library marker davegut.kasaCommunications, line 302 private outputXorTcp(command) { // library marker davegut.kasaCommunications, line 304 def str = "" // library marker davegut.kasaCommunications, line 305 def encrCmd = "000000" + Integer.toHexString(command.length()) // library marker davegut.kasaCommunications, line 306 def key = 0xAB // library marker davegut.kasaCommunications, line 307 for (int i = 0; i < command.length(); i++) { // library marker davegut.kasaCommunications, line 308 str = (command.charAt(i) as byte) ^ key // library marker davegut.kasaCommunications, line 309 key = str // library marker davegut.kasaCommunications, line 310 encrCmd += Integer.toHexString(str) // library marker davegut.kasaCommunications, line 311 } // library marker davegut.kasaCommunications, line 312 return encrCmd // library marker davegut.kasaCommunications, line 313 } // library marker davegut.kasaCommunications, line 314 private inputXorTcp(resp) { // library marker davegut.kasaCommunications, line 316 String[] strBytes = resp.substring(8).split("(?<=\\G.{2})") // library marker davegut.kasaCommunications, line 317 def cmdResponse = "" // library marker davegut.kasaCommunications, line 318 def key = 0xAB // library marker davegut.kasaCommunications, line 319 def nextKey // library marker davegut.kasaCommunications, line 320 byte[] XORtemp // library marker davegut.kasaCommunications, line 321 for(int i = 0; i < strBytes.length; i++) { // library marker davegut.kasaCommunications, line 322 nextKey = (byte)Integer.parseInt(strBytes[i], 16) // could be negative // library marker davegut.kasaCommunications, line 323 XORtemp = nextKey ^ key // library marker davegut.kasaCommunications, line 324 key = nextKey // library marker davegut.kasaCommunications, line 325 cmdResponse += new String(XORtemp) // library marker davegut.kasaCommunications, line 326 } // library marker davegut.kasaCommunications, line 327 return cmdResponse // library marker davegut.kasaCommunications, line 328 } // library marker davegut.kasaCommunications, line 329 // ~~~~~ end include (1360) davegut.kasaCommunications ~~~~~ // ~~~~~ start include (1357) davegut.commonLogging ~~~~~ library ( // library marker davegut.commonLogging, line 1 name: "commonLogging", // library marker davegut.commonLogging, line 2 namespace: "davegut", // library marker davegut.commonLogging, line 3 author: "Dave Gutheinz", // library marker davegut.commonLogging, line 4 description: "Common Logging Methods", // library marker davegut.commonLogging, line 5 category: "utilities", // library marker davegut.commonLogging, line 6 documentationLink: "" // library marker davegut.commonLogging, line 7 ) // library marker davegut.commonLogging, line 8 // Logging during development // library marker davegut.commonLogging, line 10 def listAttributes(trace = false) { // library marker davegut.commonLogging, line 11 def attrs = device.getSupportedAttributes() // library marker davegut.commonLogging, line 12 def attrList = [:] // library marker davegut.commonLogging, line 13 attrs.each { // library marker davegut.commonLogging, line 14 def val = device.currentValue("${it}") // library marker davegut.commonLogging, line 15 attrList << ["${it}": val] // library marker davegut.commonLogging, line 16 } // library marker davegut.commonLogging, line 17 if (trace == true) { // library marker davegut.commonLogging, line 18 logInfo("Attributes: ${attrList}") // library marker davegut.commonLogging, line 19 } else { // library marker davegut.commonLogging, line 20 logDebug("Attributes: ${attrList}") // library marker davegut.commonLogging, line 21 } // library marker davegut.commonLogging, line 22 } // library marker davegut.commonLogging, line 23 // 6.7.2 Change B. Remove driverVer() // library marker davegut.commonLogging, line 25 def logTrace(msg){ // library marker davegut.commonLogging, line 26 log.trace "${device.displayName}-${driverVer()}: ${msg}" // library marker davegut.commonLogging, line 27 } // library marker davegut.commonLogging, line 28 def logInfo(msg) { // library marker davegut.commonLogging, line 30 if (textEnable || infoLog) { // library marker davegut.commonLogging, line 31 log.info "${device.displayName}-${driverVer()}: ${msg}" // library marker davegut.commonLogging, line 32 } // library marker davegut.commonLogging, line 33 } // library marker davegut.commonLogging, line 34 def debugLogOff() { // library marker davegut.commonLogging, line 36 if (logEnable) { // library marker davegut.commonLogging, line 37 device.updateSetting("logEnable", [type:"bool", value: false]) // library marker davegut.commonLogging, line 38 } // library marker davegut.commonLogging, line 39 logInfo("debugLogOff") // library marker davegut.commonLogging, line 40 } // library marker davegut.commonLogging, line 41 def logDebug(msg) { // library marker davegut.commonLogging, line 43 if (logEnable || debugLog) { // library marker davegut.commonLogging, line 44 log.debug "${device.displayName}-${driverVer()}: ${msg}" // library marker davegut.commonLogging, line 45 } // library marker davegut.commonLogging, line 46 } // library marker davegut.commonLogging, line 47 def logWarn(msg) { log.warn "${device.displayName}-${driverVer()}: ${msg}" } // library marker davegut.commonLogging, line 49 // ~~~~~ end include (1357) davegut.commonLogging ~~~~~ // ~~~~~ start include (1362) davegut.kasaLights ~~~~~ library ( // library marker davegut.kasaLights, line 1 name: "kasaLights", // library marker davegut.kasaLights, line 2 namespace: "davegut", // library marker davegut.kasaLights, line 3 author: "Dave Gutheinz", // library marker davegut.kasaLights, line 4 description: "Kasa Bulb and Light Common Methods", // library marker davegut.kasaLights, line 5 category: "utilities", // library marker davegut.kasaLights, line 6 documentationLink: "" // library marker davegut.kasaLights, line 7 ) // library marker davegut.kasaLights, line 8 def on() { setLightOnOff(1, transition_Time) } // library marker davegut.kasaLights, line 10 def off() { setLightOnOff(0, transition_Time) } // library marker davegut.kasaLights, line 12 def setLevel(level, transTime = transition_Time) { // library marker davegut.kasaLights, line 14 setLightLevel(level, transTime) // library marker davegut.kasaLights, line 15 } // library marker davegut.kasaLights, line 16 def startLevelChange(direction) { // library marker davegut.kasaLights, line 18 unschedule(levelUp) // library marker davegut.kasaLights, line 19 unschedule(levelDown) // library marker davegut.kasaLights, line 20 if (direction == "up") { levelUp() } // library marker davegut.kasaLights, line 21 else { levelDown() } // library marker davegut.kasaLights, line 22 } // library marker davegut.kasaLights, line 23 def stopLevelChange() { // library marker davegut.kasaLights, line 25 unschedule(levelUp) // library marker davegut.kasaLights, line 26 unschedule(levelDown) // library marker davegut.kasaLights, line 27 } // library marker davegut.kasaLights, line 28 def levelUp() { // library marker davegut.kasaLights, line 30 def curLevel = device.currentValue("level").toInteger() // library marker davegut.kasaLights, line 31 if (curLevel == 100) { return } // library marker davegut.kasaLights, line 32 def newLevel = curLevel + 4 // library marker davegut.kasaLights, line 33 if (newLevel > 100) { newLevel = 100 } // library marker davegut.kasaLights, line 34 setLevel(newLevel, 0) // library marker davegut.kasaLights, line 35 runIn(1, levelUp) // library marker davegut.kasaLights, line 36 } // library marker davegut.kasaLights, line 37 def levelDown() { // library marker davegut.kasaLights, line 39 def curLevel = device.currentValue("level").toInteger() // library marker davegut.kasaLights, line 40 if (curLevel == 0 || device.currentValue("switch") == "off") { return } // library marker davegut.kasaLights, line 41 def newLevel = curLevel - 4 // library marker davegut.kasaLights, line 42 if (newLevel < 0) { off() } // library marker davegut.kasaLights, line 43 else { // library marker davegut.kasaLights, line 44 setLevel(newLevel, 0) // library marker davegut.kasaLights, line 45 runIn(1, levelDown) // library marker davegut.kasaLights, line 46 } // library marker davegut.kasaLights, line 47 } // library marker davegut.kasaLights, line 48 def service() { // library marker davegut.kasaLights, line 50 def service = "smartlife.iot.smartbulb.lightingservice" // library marker davegut.kasaLights, line 51 if (getDataValue("feature") == "lightStrip") { service = "smartlife.iot.lightStrip" } // library marker davegut.kasaLights, line 52 return service // library marker davegut.kasaLights, line 53 } // library marker davegut.kasaLights, line 54 def method() { // library marker davegut.kasaLights, line 56 def method = "transition_light_state" // library marker davegut.kasaLights, line 57 if (getDataValue("feature") == "lightStrip") { method = "set_light_state" } // library marker davegut.kasaLights, line 58 return method // library marker davegut.kasaLights, line 59 } // library marker davegut.kasaLights, line 60 def checkTransTime(transTime) { // library marker davegut.kasaLights, line 62 if (transTime == null || transTime < 0) { transTime = 0 } // library marker davegut.kasaLights, line 63 transTime = 1000 * transTime.toInteger() // library marker davegut.kasaLights, line 64 if (transTime > 8000) { transTime = 8000 } // library marker davegut.kasaLights, line 65 return transTime // library marker davegut.kasaLights, line 66 } // library marker davegut.kasaLights, line 67 def checkLevel(level) { // library marker davegut.kasaLights, line 69 if (level == null || level < 0) { // library marker davegut.kasaLights, line 70 level = device.currentValue("level") // library marker davegut.kasaLights, line 71 logWarn("checkLevel: Entered level null or negative. Level set to ${level}") // library marker davegut.kasaLights, line 72 } else if (level > 100) { // library marker davegut.kasaLights, line 73 level = 100 // library marker davegut.kasaLights, line 74 logWarn("checkLevel: Entered level > 100. Level set to ${level}") // library marker davegut.kasaLights, line 75 } // library marker davegut.kasaLights, line 76 return level // library marker davegut.kasaLights, line 77 } // library marker davegut.kasaLights, line 78 def setLightOnOff(onOff, transTime = 0) { // library marker davegut.kasaLights, line 80 transTime = checkTransTime(transTime) // library marker davegut.kasaLights, line 81 sendCmd("""{"${service()}":{"${method()}":{"on_off":${onOff},""" + // library marker davegut.kasaLights, line 82 """"transition_period":${transTime}}}}""") // library marker davegut.kasaLights, line 83 } // library marker davegut.kasaLights, line 84 def setLightLevel(level, transTime = 0) { // library marker davegut.kasaLights, line 86 level = checkLevel(level) // library marker davegut.kasaLights, line 87 if (level == 0) { // library marker davegut.kasaLights, line 88 setLightOnOff(0, transTime) // library marker davegut.kasaLights, line 89 } else { // library marker davegut.kasaLights, line 90 transTime = checkTransTime(transTime) // library marker davegut.kasaLights, line 91 sendCmd("""{"${service()}":{"${method()}":{"ignore_default":1,"on_off":1,""" + // library marker davegut.kasaLights, line 92 """"brightness":${level},"transition_period":${transTime}}}}""") // library marker davegut.kasaLights, line 93 } // library marker davegut.kasaLights, line 94 } // library marker davegut.kasaLights, line 95 // ~~~~~ end include (1362) davegut.kasaLights ~~~~~ // ~~~~~ start include (1358) davegut.kasaColorLights ~~~~~ library ( // library marker davegut.kasaColorLights, line 1 name: "kasaColorLights", // library marker davegut.kasaColorLights, line 2 namespace: "davegut", // library marker davegut.kasaColorLights, line 3 author: "Dave Gutheinz", // library marker davegut.kasaColorLights, line 4 description: "Kasa Color/CT Bulb and Light Common Methods", // library marker davegut.kasaColorLights, line 5 category: "utilities", // library marker davegut.kasaColorLights, line 6 documentationLink: "" // library marker davegut.kasaColorLights, line 7 ) // library marker davegut.kasaColorLights, line 8 def setCircadian() { // library marker davegut.kasaColorLights, line 10 sendCmd("""{"${service()}":{"${method()}":{"mode":"circadian"}}}""") // library marker davegut.kasaColorLights, line 11 } // library marker davegut.kasaColorLights, line 12 def setHue(hue) { setColor([hue: hue]) } // library marker davegut.kasaColorLights, line 14 def setSaturation(saturation) { setColor([saturation: saturation]) } // library marker davegut.kasaColorLights, line 16 def setColor(Map color, transTime = transition_Time) { // library marker davegut.kasaColorLights, line 18 if (color == null) { // library marker davegut.kasaColorLights, line 19 LogWarn("setColor: Color map is null. Command not executed.") // library marker davegut.kasaColorLights, line 20 } else { // library marker davegut.kasaColorLights, line 21 def level = device.currentValue("level") // library marker davegut.kasaColorLights, line 22 if (color.level) { level = color.level } // library marker davegut.kasaColorLights, line 23 def hue = device.currentValue("hue") // library marker davegut.kasaColorLights, line 24 if (color.hue || color.hue == 0) { hue = color.hue.toInteger() } // library marker davegut.kasaColorLights, line 25 def saturation = device.currentValue("saturation") // library marker davegut.kasaColorLights, line 26 if (color.saturation || color.saturation == 0) { saturation = color.saturation } // library marker davegut.kasaColorLights, line 27 hue = Math.round(0.49 + hue * 3.6).toInteger() // library marker davegut.kasaColorLights, line 28 if (hue < 0 || hue > 360 || saturation < 0 || saturation > 100 || level < 0 || level > 100) { // library marker davegut.kasaColorLights, line 29 logWarn("setColor: Entered hue, saturation, or level out of range! (H:${hue}, S:${saturation}, L:${level}") // library marker davegut.kasaColorLights, line 30 } else { // library marker davegut.kasaColorLights, line 31 setLightColor(level, 0, hue, saturation, transTime) // library marker davegut.kasaColorLights, line 32 } // library marker davegut.kasaColorLights, line 33 } // library marker davegut.kasaColorLights, line 34 } // library marker davegut.kasaColorLights, line 35 def setRGB(rgb) { // library marker davegut.kasaColorLights, line 37 logDebug("setRGB: ${rgb}") // library marker davegut.kasaColorLights, line 38 def rgbArray = rgb.split('\\,') // library marker davegut.kasaColorLights, line 39 def hsvData = hubitat.helper.ColorUtils.rgbToHSV([rgbArray[0].toInteger(), rgbArray[1].toInteger(), rgbArray[2].toInteger()]) // library marker davegut.kasaColorLights, line 40 def hue = (0.5 + hsvData[0]).toInteger() // library marker davegut.kasaColorLights, line 41 def saturation = (0.5 + hsvData[1]).toInteger() // library marker davegut.kasaColorLights, line 42 def level = (0.5 + hsvData[2]).toInteger() // library marker davegut.kasaColorLights, line 43 def Map hslData = [ // library marker davegut.kasaColorLights, line 44 hue: hue, // library marker davegut.kasaColorLights, line 45 saturation: saturation, // library marker davegut.kasaColorLights, line 46 level: level // library marker davegut.kasaColorLights, line 47 ] // library marker davegut.kasaColorLights, line 48 setColor(hslData) // library marker davegut.kasaColorLights, line 49 } // library marker davegut.kasaColorLights, line 50 def setLightColor(level, colorTemp, hue, saturation, transTime = 0) { // library marker davegut.kasaColorLights, line 52 level = checkLevel(level) // library marker davegut.kasaColorLights, line 53 if (level == 0) { // library marker davegut.kasaColorLights, line 54 setLightOnOff(0, transTime) // library marker davegut.kasaColorLights, line 55 } else { // library marker davegut.kasaColorLights, line 56 transTime = checkTransTime(transTime) // library marker davegut.kasaColorLights, line 57 sendCmd("""{"${service()}":{"${method()}":{"ignore_default":1,"on_off":1,""" + // library marker davegut.kasaColorLights, line 58 """"brightness":${level},"color_temp":${colorTemp},""" + // library marker davegut.kasaColorLights, line 59 """"hue":${hue},"saturation":${saturation},"transition_period":${transTime}}}}""") // library marker davegut.kasaColorLights, line 60 } // library marker davegut.kasaColorLights, line 61 } // library marker davegut.kasaColorLights, line 62 def bulbPresetCreate(psName) { // library marker davegut.kasaColorLights, line 64 if (!state.bulbPresets) { state.bulbPresets = [:] } // library marker davegut.kasaColorLights, line 65 psName = psName.trim().toLowerCase() // library marker davegut.kasaColorLights, line 66 logDebug("bulbPresetCreate: ${psName}") // library marker davegut.kasaColorLights, line 67 def psData = [:] // library marker davegut.kasaColorLights, line 68 psData["hue"] = device.currentValue("hue") // library marker davegut.kasaColorLights, line 69 psData["saturation"] = device.currentValue("saturation") // library marker davegut.kasaColorLights, line 70 psData["level"] = device.currentValue("level") // library marker davegut.kasaColorLights, line 71 def colorTemp = device.currentValue("colorTemperature") // library marker davegut.kasaColorLights, line 72 if (colorTemp == null) { colorTemp = 0 } // library marker davegut.kasaColorLights, line 73 psData["colTemp"] = colorTemp // library marker davegut.kasaColorLights, line 74 state.bulbPresets << ["${psName}": psData] // library marker davegut.kasaColorLights, line 75 } // library marker davegut.kasaColorLights, line 76 def bulbPresetDelete(psName) { // library marker davegut.kasaColorLights, line 78 psName = psName.trim() // library marker davegut.kasaColorLights, line 79 logDebug("bulbPresetDelete: ${psName}") // library marker davegut.kasaColorLights, line 80 def presets = state.bulbPresets // library marker davegut.kasaColorLights, line 81 if (presets.toString().contains(psName)) { // library marker davegut.kasaColorLights, line 82 presets.remove(psName) // library marker davegut.kasaColorLights, line 83 } else { // library marker davegut.kasaColorLights, line 84 logWarn("bulbPresetDelete: ${psName} is not a valid name.") // library marker davegut.kasaColorLights, line 85 } // library marker davegut.kasaColorLights, line 86 } // library marker davegut.kasaColorLights, line 87 def syncBulbPresets() { // library marker davegut.kasaColorLights, line 89 device.updateSetting("syncBulbs", [type:"bool", value: false]) // library marker davegut.kasaColorLights, line 90 parent.syncBulbPresets(state.bulbPresets) // library marker davegut.kasaColorLights, line 91 return "Syncing" // library marker davegut.kasaColorLights, line 92 } // library marker davegut.kasaColorLights, line 93 def updatePresets(bulbPresets) { // library marker davegut.kasaColorLights, line 95 logInfo("updatePresets: ${bulbPresets}") // library marker davegut.kasaColorLights, line 96 state.bulbPresets = bulbPresets // library marker davegut.kasaColorLights, line 97 } // library marker davegut.kasaColorLights, line 98 def bulbPresetSet(psName, transTime = transition_Time) { // library marker davegut.kasaColorLights, line 100 psName = psName.trim() // library marker davegut.kasaColorLights, line 101 if (state.bulbPresets."${psName}") { // library marker davegut.kasaColorLights, line 102 def psData = state.bulbPresets."${psName}" // library marker davegut.kasaColorLights, line 103 def hue = Math.round(0.49 + psData.hue.toInteger() * 3.6).toInteger() // library marker davegut.kasaColorLights, line 104 setLightColor(psData.level, psData.colTemp, hue, psData.saturation, transTime) // library marker davegut.kasaColorLights, line 105 } else { // library marker davegut.kasaColorLights, line 106 logWarn("bulbPresetSet: ${psName} is not a valid name.") // library marker davegut.kasaColorLights, line 107 } // library marker davegut.kasaColorLights, line 108 } // library marker davegut.kasaColorLights, line 109 // ~~~~~ end include (1358) davegut.kasaColorLights ~~~~~ // ~~~~~ start include (1361) davegut.kasaEnergyMonitor ~~~~~ library ( // library marker davegut.kasaEnergyMonitor, line 1 name: "kasaEnergyMonitor", // library marker davegut.kasaEnergyMonitor, line 2 namespace: "davegut", // library marker davegut.kasaEnergyMonitor, line 3 author: "Dave Gutheinz", // library marker davegut.kasaEnergyMonitor, line 4 description: "Kasa Device Energy Monitor Methods", // library marker davegut.kasaEnergyMonitor, line 5 category: "energyMonitor", // library marker davegut.kasaEnergyMonitor, line 6 documentationLink: "" // library marker davegut.kasaEnergyMonitor, line 7 ) // library marker davegut.kasaEnergyMonitor, line 8 def setupEmFunction() { // library marker davegut.kasaEnergyMonitor, line 10 if (emFunction && device.currentValue("currMonthTotal") > 0) { // library marker davegut.kasaEnergyMonitor, line 11 state.getEnergy = "This Month" // library marker davegut.kasaEnergyMonitor, line 12 return "Continuing EM Function" // library marker davegut.kasaEnergyMonitor, line 13 } else if (emFunction) { // library marker davegut.kasaEnergyMonitor, line 14 zeroizeEnergyAttrs() // library marker davegut.kasaEnergyMonitor, line 15 state.response = "" // library marker davegut.kasaEnergyMonitor, line 16 state.getEnergy = "This Month" // library marker davegut.kasaEnergyMonitor, line 17 // Run order / delay is critical for successful operation. // library marker davegut.kasaEnergyMonitor, line 18 getEnergyThisMonth() // library marker davegut.kasaEnergyMonitor, line 19 runIn(10, getEnergyLastMonth) // library marker davegut.kasaEnergyMonitor, line 20 return "Initialized" // library marker davegut.kasaEnergyMonitor, line 21 } else if (emFunction && device.currentValue("power") != null) { // library marker davegut.kasaEnergyMonitor, line 22 // for power != null, EM had to be enabled at one time. Set values to 0. // library marker davegut.kasaEnergyMonitor, line 23 zeroizeEnergyAttrs() // library marker davegut.kasaEnergyMonitor, line 24 state.remove("getEnergy") // library marker davegut.kasaEnergyMonitor, line 25 return "Disabled" // library marker davegut.kasaEnergyMonitor, line 26 } else { // library marker davegut.kasaEnergyMonitor, line 27 return "Not initialized" // library marker davegut.kasaEnergyMonitor, line 28 } // library marker davegut.kasaEnergyMonitor, line 29 } // library marker davegut.kasaEnergyMonitor, line 30 def scheduleEnergyAttrs() { // library marker davegut.kasaEnergyMonitor, line 32 schedule("10 0 0 * * ?", getEnergyThisMonth) // library marker davegut.kasaEnergyMonitor, line 33 schedule("15 2 0 1 * ?", getEnergyLastMonth) // library marker davegut.kasaEnergyMonitor, line 34 switch(energyPollInt) { // library marker davegut.kasaEnergyMonitor, line 35 case "1 minute": // library marker davegut.kasaEnergyMonitor, line 36 runEvery1Minute(getEnergyToday) // library marker davegut.kasaEnergyMonitor, line 37 break // library marker davegut.kasaEnergyMonitor, line 38 case "5 minutes": // library marker davegut.kasaEnergyMonitor, line 39 runEvery5Minutes(getEnergyToday) // library marker davegut.kasaEnergyMonitor, line 40 break // library marker davegut.kasaEnergyMonitor, line 41 default: // library marker davegut.kasaEnergyMonitor, line 42 runEvery30Minutes(getEnergyToday) // library marker davegut.kasaEnergyMonitor, line 43 } // library marker davegut.kasaEnergyMonitor, line 44 } // library marker davegut.kasaEnergyMonitor, line 45 def zeroizeEnergyAttrs() { // library marker davegut.kasaEnergyMonitor, line 47 sendEvent(name: "power", value: 0, unit: "W") // library marker davegut.kasaEnergyMonitor, line 48 sendEvent(name: "energy", value: 0, unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 49 sendEvent(name: "currMonthTotal", value: 0, unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 50 sendEvent(name: "currMonthAvg", value: 0, unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 51 sendEvent(name: "lastMonthTotal", value: 0, unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 52 sendEvent(name: "lastMonthAvg", value: 0, unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 53 } // library marker davegut.kasaEnergyMonitor, line 54 def getDate() { // library marker davegut.kasaEnergyMonitor, line 56 def currDate = new Date() // library marker davegut.kasaEnergyMonitor, line 57 int year = currDate.format("yyyy").toInteger() // library marker davegut.kasaEnergyMonitor, line 58 int month = currDate.format("M").toInteger() // library marker davegut.kasaEnergyMonitor, line 59 int day = currDate.format("d").toInteger() // library marker davegut.kasaEnergyMonitor, line 60 return [year: year, month: month, day: day] // library marker davegut.kasaEnergyMonitor, line 61 } // library marker davegut.kasaEnergyMonitor, line 62 def distEmeter(emeterResp) { // library marker davegut.kasaEnergyMonitor, line 64 def date = getDate() // library marker davegut.kasaEnergyMonitor, line 65 logDebug("distEmeter: ${emeterResp}, ${date}, ${state.getEnergy}") // library marker davegut.kasaEnergyMonitor, line 66 def lastYear = date.year - 1 // library marker davegut.kasaEnergyMonitor, line 67 if (emeterResp.get_realtime) { // library marker davegut.kasaEnergyMonitor, line 68 setPower(emeterResp.get_realtime) // library marker davegut.kasaEnergyMonitor, line 69 } else if (emeterResp.get_monthstat) { // library marker davegut.kasaEnergyMonitor, line 70 def monthList = emeterResp.get_monthstat.month_list // library marker davegut.kasaEnergyMonitor, line 71 if (state.getEnergy == "Today") { // library marker davegut.kasaEnergyMonitor, line 72 setEnergyToday(monthList, date) // library marker davegut.kasaEnergyMonitor, line 73 } else if (state.getEnergy == "This Month") { // library marker davegut.kasaEnergyMonitor, line 74 setThisMonth(monthList, date) // library marker davegut.kasaEnergyMonitor, line 75 } else if (state.getEnergy == "Last Month") { // library marker davegut.kasaEnergyMonitor, line 76 setLastMonth(monthList, date) // library marker davegut.kasaEnergyMonitor, line 77 } else if (monthList == []) { // library marker davegut.kasaEnergyMonitor, line 78 logDebug("distEmeter: monthList Empty. No data for year.") // library marker davegut.kasaEnergyMonitor, line 79 } // library marker davegut.kasaEnergyMonitor, line 80 } else { // library marker davegut.kasaEnergyMonitor, line 81 logWarn("distEmeter: Unhandled response = ${emeterResp}") // library marker davegut.kasaEnergyMonitor, line 82 } // library marker davegut.kasaEnergyMonitor, line 83 } // library marker davegut.kasaEnergyMonitor, line 84 def getPower() { // library marker davegut.kasaEnergyMonitor, line 86 if (emFunction) { // library marker davegut.kasaEnergyMonitor, line 87 if (device.currentValue("switch") == "on") { // library marker davegut.kasaEnergyMonitor, line 88 getRealtime() // library marker davegut.kasaEnergyMonitor, line 89 } else if (device.currentValue("power") != 0) { // library marker davegut.kasaEnergyMonitor, line 90 sendEvent(name: "power", value: 0, descriptionText: "Watts", unit: "W", type: "digital") // library marker davegut.kasaEnergyMonitor, line 91 } // library marker davegut.kasaEnergyMonitor, line 92 } // library marker davegut.kasaEnergyMonitor, line 93 } // library marker davegut.kasaEnergyMonitor, line 94 def setPower(response) { // library marker davegut.kasaEnergyMonitor, line 96 logDebug("setPower: ${response}") // library marker davegut.kasaEnergyMonitor, line 97 def power = response.power // library marker davegut.kasaEnergyMonitor, line 98 if (power == null) { power = response.power_mw / 1000 } // library marker davegut.kasaEnergyMonitor, line 99 power = (power + 0.5).toInteger() // library marker davegut.kasaEnergyMonitor, line 100 def curPwr = device.currentValue("power") // library marker davegut.kasaEnergyMonitor, line 101 def pwrChange = false // library marker davegut.kasaEnergyMonitor, line 102 if (curPwr != power) { // library marker davegut.kasaEnergyMonitor, line 103 if (curPwr == null || (curPwr == 0 && power > 0)) { // library marker davegut.kasaEnergyMonitor, line 104 pwrChange = true // library marker davegut.kasaEnergyMonitor, line 105 } else { // library marker davegut.kasaEnergyMonitor, line 106 def changeRatio = Math.abs((power - curPwr) / curPwr) // library marker davegut.kasaEnergyMonitor, line 107 if (changeRatio > 0.03) { // library marker davegut.kasaEnergyMonitor, line 108 pwrChange = true // library marker davegut.kasaEnergyMonitor, line 109 } // library marker davegut.kasaEnergyMonitor, line 110 } // library marker davegut.kasaEnergyMonitor, line 111 } // library marker davegut.kasaEnergyMonitor, line 112 if (pwrChange == true) { // library marker davegut.kasaEnergyMonitor, line 113 sendEvent(name: "power", value: power, descriptionText: "Watts", unit: "W", type: "digital") // library marker davegut.kasaEnergyMonitor, line 114 } // library marker davegut.kasaEnergyMonitor, line 115 } // library marker davegut.kasaEnergyMonitor, line 116 def getEnergyToday() { // library marker davegut.kasaEnergyMonitor, line 118 if (device.currentValue("switch") == "on") { // library marker davegut.kasaEnergyMonitor, line 119 state.getEnergy = "Today" // library marker davegut.kasaEnergyMonitor, line 120 def year = getDate().year // library marker davegut.kasaEnergyMonitor, line 121 logDebug("getEnergyToday: ${year}") // library marker davegut.kasaEnergyMonitor, line 122 runIn(5, getMonthstat, [data: year]) // library marker davegut.kasaEnergyMonitor, line 123 } // library marker davegut.kasaEnergyMonitor, line 124 } // library marker davegut.kasaEnergyMonitor, line 125 def setEnergyToday(monthList, date) { // library marker davegut.kasaEnergyMonitor, line 127 logDebug("setEnergyToday: ${date}, ${monthList}") // library marker davegut.kasaEnergyMonitor, line 128 def data = monthList.find { it.month == date.month && it.year == date.year} // library marker davegut.kasaEnergyMonitor, line 129 def status = [:] // library marker davegut.kasaEnergyMonitor, line 130 def energy = 0 // library marker davegut.kasaEnergyMonitor, line 131 if (data == null) { // library marker davegut.kasaEnergyMonitor, line 132 status << [msgError: "Return Data Null"] // library marker davegut.kasaEnergyMonitor, line 133 } else { // library marker davegut.kasaEnergyMonitor, line 134 energy = data.energy // library marker davegut.kasaEnergyMonitor, line 135 if (energy == null) { energy = data.energy_wh/1000 } // library marker davegut.kasaEnergyMonitor, line 136 energy = Math.round(100*energy)/100 - device.currentValue("currMonthTotal") // library marker davegut.kasaEnergyMonitor, line 137 } // library marker davegut.kasaEnergyMonitor, line 138 if (device.currentValue("energy") != energy) { // library marker davegut.kasaEnergyMonitor, line 139 sendEvent(name: "energy", value: energy, descriptionText: "KiloWatt Hours", unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 140 status << [energy: energy] // library marker davegut.kasaEnergyMonitor, line 141 } // library marker davegut.kasaEnergyMonitor, line 142 if (status != [:]) { logInfo("setEnergyToday: ${status}") } // library marker davegut.kasaEnergyMonitor, line 143 if (!state.getEnergy) { // library marker davegut.kasaEnergyMonitor, line 144 schedule("10 0 0 * * ?", getEnergyThisMonth) // library marker davegut.kasaEnergyMonitor, line 145 schedule("15 2 0 1 * ?", getEnergyLastMonth) // library marker davegut.kasaEnergyMonitor, line 146 state.getEnergy = "This Month" // library marker davegut.kasaEnergyMonitor, line 147 getEnergyThisMonth() // library marker davegut.kasaEnergyMonitor, line 148 runIn(10, getEnergyLastMonth) // library marker davegut.kasaEnergyMonitor, line 149 } // library marker davegut.kasaEnergyMonitor, line 150 } // library marker davegut.kasaEnergyMonitor, line 151 def getEnergyThisMonth() { // library marker davegut.kasaEnergyMonitor, line 153 state.getEnergy = "This Month" // library marker davegut.kasaEnergyMonitor, line 154 def year = getDate().year // library marker davegut.kasaEnergyMonitor, line 155 logDebug("getEnergyThisMonth: ${year}") // library marker davegut.kasaEnergyMonitor, line 156 runIn(5, getMonthstat, [data: year]) // library marker davegut.kasaEnergyMonitor, line 157 } // library marker davegut.kasaEnergyMonitor, line 158 def setThisMonth(monthList, date) { // library marker davegut.kasaEnergyMonitor, line 160 logDebug("setThisMonth: ${date} // ${monthList}") // library marker davegut.kasaEnergyMonitor, line 161 def data = monthList.find { it.month == date.month && it.year == date.year} // library marker davegut.kasaEnergyMonitor, line 162 def status = [:] // library marker davegut.kasaEnergyMonitor, line 163 def totEnergy = 0 // library marker davegut.kasaEnergyMonitor, line 164 def avgEnergy = 0 // library marker davegut.kasaEnergyMonitor, line 165 if (data == null) { // library marker davegut.kasaEnergyMonitor, line 166 status << [msgError: "Return Data Null"] // library marker davegut.kasaEnergyMonitor, line 167 } else { // library marker davegut.kasaEnergyMonitor, line 168 status << [msgError: "OK"] // library marker davegut.kasaEnergyMonitor, line 169 totEnergy = data.energy // library marker davegut.kasaEnergyMonitor, line 170 if (totEnergy == null) { totEnergy = data.energy_wh/1000 } // library marker davegut.kasaEnergyMonitor, line 171 if (date.day == 1) { // library marker davegut.kasaEnergyMonitor, line 172 avgEnergy = 0 // library marker davegut.kasaEnergyMonitor, line 173 } else { // library marker davegut.kasaEnergyMonitor, line 174 avgEnergy = totEnergy /(date.day - 1) // library marker davegut.kasaEnergyMonitor, line 175 } // library marker davegut.kasaEnergyMonitor, line 176 } // library marker davegut.kasaEnergyMonitor, line 177 totEnergy = Math.round(100*totEnergy)/100 // library marker davegut.kasaEnergyMonitor, line 178 avgEnergy = Math.round(100*avgEnergy)/100 // library marker davegut.kasaEnergyMonitor, line 179 sendEvent(name: "currMonthTotal", value: totEnergy, // library marker davegut.kasaEnergyMonitor, line 180 descriptionText: "KiloWatt Hours", unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 181 status << [currMonthTotal: totEnergy] // library marker davegut.kasaEnergyMonitor, line 182 sendEvent(name: "currMonthAvg", value: avgEnergy, // library marker davegut.kasaEnergyMonitor, line 183 descriptionText: "KiloWatt Hours per Day", unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 184 status << [currMonthAvg: avgEnergy] // library marker davegut.kasaEnergyMonitor, line 185 getEnergyToday() // library marker davegut.kasaEnergyMonitor, line 186 logInfo("setThisMonth: ${status}") // library marker davegut.kasaEnergyMonitor, line 187 } // library marker davegut.kasaEnergyMonitor, line 188 def getEnergyLastMonth() { // library marker davegut.kasaEnergyMonitor, line 190 state.getEnergy = "Last Month" // library marker davegut.kasaEnergyMonitor, line 191 def date = getDate() // library marker davegut.kasaEnergyMonitor, line 192 def year = date.year // library marker davegut.kasaEnergyMonitor, line 193 if (date.month == 1) { // library marker davegut.kasaEnergyMonitor, line 194 year = year - 1 // library marker davegut.kasaEnergyMonitor, line 195 } // library marker davegut.kasaEnergyMonitor, line 196 logDebug("getEnergyLastMonth: ${year}") // library marker davegut.kasaEnergyMonitor, line 197 runIn(5, getMonthstat, [data: year]) // library marker davegut.kasaEnergyMonitor, line 198 } // library marker davegut.kasaEnergyMonitor, line 199 def setLastMonth(monthList, date) { // library marker davegut.kasaEnergyMonitor, line 201 logDebug("setLastMonth: ${date} // ${monthList}") // library marker davegut.kasaEnergyMonitor, line 202 def lastMonthYear = date.year // library marker davegut.kasaEnergyMonitor, line 203 def lastMonth = date.month - 1 // library marker davegut.kasaEnergyMonitor, line 204 if (date.month == 1) { // library marker davegut.kasaEnergyMonitor, line 205 lastMonthYear -+ 1 // library marker davegut.kasaEnergyMonitor, line 206 lastMonth = 12 // library marker davegut.kasaEnergyMonitor, line 207 } // library marker davegut.kasaEnergyMonitor, line 208 def data = monthList.find { it.month == lastMonth } // library marker davegut.kasaEnergyMonitor, line 209 def status = [:] // library marker davegut.kasaEnergyMonitor, line 210 def totEnergy = 0 // library marker davegut.kasaEnergyMonitor, line 211 def avgEnergy = 0 // library marker davegut.kasaEnergyMonitor, line 212 if (data == null) { // library marker davegut.kasaEnergyMonitor, line 213 status << [msgError: "Return Data Null"] // library marker davegut.kasaEnergyMonitor, line 214 } else { // library marker davegut.kasaEnergyMonitor, line 215 status << [msgError: "OK"] // library marker davegut.kasaEnergyMonitor, line 216 def monthLength // library marker davegut.kasaEnergyMonitor, line 217 switch(lastMonth) { // library marker davegut.kasaEnergyMonitor, line 218 case 4: // library marker davegut.kasaEnergyMonitor, line 219 case 6: // library marker davegut.kasaEnergyMonitor, line 220 case 9: // library marker davegut.kasaEnergyMonitor, line 221 case 11: // library marker davegut.kasaEnergyMonitor, line 222 monthLength = 30 // library marker davegut.kasaEnergyMonitor, line 223 break // library marker davegut.kasaEnergyMonitor, line 224 case 2: // library marker davegut.kasaEnergyMonitor, line 225 monthLength = 28 // library marker davegut.kasaEnergyMonitor, line 226 if (lastMonthYear == 2020 || lastMonthYear == 2024 || lastMonthYear == 2028) { // library marker davegut.kasaEnergyMonitor, line 227 monthLength = 29 // library marker davegut.kasaEnergyMonitor, line 228 } // library marker davegut.kasaEnergyMonitor, line 229 break // library marker davegut.kasaEnergyMonitor, line 230 default: // library marker davegut.kasaEnergyMonitor, line 231 monthLength = 31 // library marker davegut.kasaEnergyMonitor, line 232 } // library marker davegut.kasaEnergyMonitor, line 233 totEnergy = data.energy // library marker davegut.kasaEnergyMonitor, line 234 if (totEnergy == null) { totEnergy = data.energy_wh/1000 } // library marker davegut.kasaEnergyMonitor, line 235 avgEnergy = totEnergy / monthLength // library marker davegut.kasaEnergyMonitor, line 236 } // library marker davegut.kasaEnergyMonitor, line 237 totEnergy = Math.round(100*totEnergy)/100 // library marker davegut.kasaEnergyMonitor, line 238 avgEnergy = Math.round(100*avgEnergy)/100 // library marker davegut.kasaEnergyMonitor, line 239 sendEvent(name: "lastMonthTotal", value: totEnergy, // library marker davegut.kasaEnergyMonitor, line 240 descriptionText: "KiloWatt Hours", unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 241 status << [lastMonthTotal: totEnergy] // library marker davegut.kasaEnergyMonitor, line 242 sendEvent(name: "lastMonthAvg", value: avgEnergy, // library marker davegut.kasaEnergyMonitor, line 243 descriptionText: "KiloWatt Hoursper Day", unit: "KWH") // library marker davegut.kasaEnergyMonitor, line 244 status << [lastMonthAvg: avgEnergy] // library marker davegut.kasaEnergyMonitor, line 245 logInfo("setLastMonth: ${status}") // library marker davegut.kasaEnergyMonitor, line 246 } // library marker davegut.kasaEnergyMonitor, line 247 def getRealtime() { // library marker davegut.kasaEnergyMonitor, line 249 def feature = getDataValue("feature") // library marker davegut.kasaEnergyMonitor, line 250 if (getDataValue("plugNo") != null) { // library marker davegut.kasaEnergyMonitor, line 251 sendCmd("""{"context":{"child_ids":["${getDataValue("plugId")}"]},""" + // library marker davegut.kasaEnergyMonitor, line 252 """"emeter":{"get_realtime":{}}}""") // library marker davegut.kasaEnergyMonitor, line 253 } else if (feature.contains("Bulb") || feature == "lightStrip") { // library marker davegut.kasaEnergyMonitor, line 254 sendCmd("""{"smartlife.iot.common.emeter":{"get_realtime":{}}}""") // library marker davegut.kasaEnergyMonitor, line 255 } else { // library marker davegut.kasaEnergyMonitor, line 256 sendCmd("""{"emeter":{"get_realtime":{}}}""") // library marker davegut.kasaEnergyMonitor, line 257 } // library marker davegut.kasaEnergyMonitor, line 258 } // library marker davegut.kasaEnergyMonitor, line 259 def getMonthstat(year) { // library marker davegut.kasaEnergyMonitor, line 261 def feature = getDataValue("feature") // library marker davegut.kasaEnergyMonitor, line 262 if (getDataValue("plugNo") != null) { // library marker davegut.kasaEnergyMonitor, line 263 sendCmd("""{"context":{"child_ids":["${getDataValue("plugId")}"]},""" + // library marker davegut.kasaEnergyMonitor, line 264 """"emeter":{"get_monthstat":{"year": ${year}}}}""") // library marker davegut.kasaEnergyMonitor, line 265 } else if (feature.contains("Bulb") || feature == "lightStrip") { // library marker davegut.kasaEnergyMonitor, line 266 sendCmd("""{"smartlife.iot.common.emeter":{"get_monthstat":{"year": ${year}}}}""") // library marker davegut.kasaEnergyMonitor, line 267 } else { // library marker davegut.kasaEnergyMonitor, line 268 sendCmd("""{"emeter":{"get_monthstat":{"year": ${year}}}}""") // library marker davegut.kasaEnergyMonitor, line 269 } // library marker davegut.kasaEnergyMonitor, line 270 } // library marker davegut.kasaEnergyMonitor, line 271 // ~~~~~ end include (1361) davegut.kasaEnergyMonitor ~~~~~