/* 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 Dimming Switch", namespace: nameSpace(), author: "Dave Gutheinz", importUrl: "https://raw.githubusercontent.com/DaveGut/HubitatActive/master/KasaDevices/DeviceDrivers/DimmingSwitch.groovy" ) { capability "Switch" capability "Actuator" capability "Refresh" capability "Configuration" capability "Switch Level" capability "Level Preset" capability "Change Level" command "ledOn" command "ledOff" attribute "led", "string" command "setPollInterval", [[ name: "Poll Interval in seconds", constraints: ["default", "5 seconds", "10 seconds", "15 seconds", "30 seconds", "1 minute", "5 minutes", "10 minutes", "30 minutes"], type: "ENUM"]] 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 ("gentleOn", "number", title: "Gentle On (max 7000 msec)", defaultValue:5000, range: 0 .. 7100) input ("gentleOff", "number", title: "Gentle Off (max 7000 msec)", defaultValue:5000, range: 0 .. 7100) def fadeOpts = [0: "Instant", 1000: "Fast", 2000: "Medium", 3000: "Slow"] input ("fadeOn", "enum", title: "Fade On", defaultValue:"Fast", options: fadeOpts) input ("fadeOff", "enum", title: "Fade Off", defaultValue:"Fast", options: fadeOpts) def pressOpts = ["none", "instant_on_off", "gentle_on_off", "Preset 0", "Preset 1", "Preset 2", "Preset 3"] input ("longPress", "enum", title: "Long Press Action", defaultValue: "gentle_on_off", options: pressOpts) input ("doubleClick", "enum", title: "Double Tap Action", defaultValue: "Preset 1", options: pressOpts) 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() pauseExecution(3000) getDimmerConfiguration() logInfo("installed: ${instStatus}") } def updated() { def updStatus = updateCommon() configureDimmer() logInfo("updated: ${updStatus}") refresh() } def configureDimmer() { logDebug("configureDimmer") if (longPress == null || doubleClick == null || gentleOn == null || gentleOff == null || fadeOff == null || fadeOn == null) { def dimmerSet = getDimmerConfiguration() pauseExecution(2000) } sendCmd("""{"smartlife.iot.dimmer":{"set_gentle_on_time":{"duration": ${gentleOn}}, """ + """"set_gentle_off_time":{"duration": ${gentleOff}}, """ + """"set_fade_on_time":{"fadeTime": ${fadeOn}}, """ + """"set_fade_off_time":{"fadeTime": ${fadeOff}}}}""") pauseExecution(2000) def action1 = """{"mode":"${longPress}"}""" if (longPress.contains("Preset")) { action1 = """{"mode":"customize_preset","index":${longPress[-1].toInteger()}}""" } def action2 = """{"mode":"${doubleClick}"}""" if (doubleClick.contains("Preset")) { action2 = """{"mode":"customize_preset","index":${doubleClick[-1].toInteger()}}""" } sendCmd("""{"smartlife.iot.dimmer":{"set_double_click_action":${action2}, """ + """"set_long_press_action":${action1}}}""") runIn(1, getDimmerConfiguration) } def setDimmerConfig(response) { logDebug("setDimmerConfiguration: ${response}") def params def dimmerConfig = [:] if (response["get_dimmer_parameters"]) { params = response["get_dimmer_parameters"] if (params.err_code == "0") { logWarn("setDimmerConfig: Error in getDimmerParams: ${params}") } else { def fadeOn = getFade(params.fadeOnTime.toInteger()) def fadeOff = getFade(params.fadeOffTime.toInteger()) device.updateSetting("fadeOn", [type:"integer", value: fadeOn]) device.updateSetting("fadeOff", [type:"integer", value: fadeOff]) device.updateSetting("gentleOn", [type:"integer", value: params.gentleOnTime]) device.updateSetting("gentleOff", [type:"integer", value: params.gentleOffTime]) dimmerConfig << [fadeOn: fadeOn, fadeOff: fadeOff, genleOn: gentleOn, gentleOff: gentleOff] } } if (response["get_default_behavior"]) { params = response["get_default_behavior"] if (params.err_code == "0") { logWarn("setDimmerConfig: Error in getDefaultBehavior: ${params}") } else { def longPress = params.long_press.mode if (params.long_press.index != null) { longPress = "Preset ${params.long_press.index}" } device.updateSetting("longPress", [type:"enum", value: longPress]) def doubleClick = params.double_click.mode if (params.double_click.index != null) { doubleClick = "Preset ${params.double_click.index}" } device.updateSetting("doubleClick", [type:"enum", value: doubleClick]) dimmerConfig << [longPress: longPress, doubleClick: doubleClick] } } logInfo("setDimmerConfig: ${dimmerConfig}") } def getFade(fadeTime) { def fadeSpeed = "Instant" if (fadeTime == 1000) { fadeSpeed = "Fast" } else if (fadeTime == 2000) { fadeSpeed = "Medium" } else if (fadeTime == 3000) { fadeSpeed = "Slow" } return fadeSpeed } def setLevel(level, transTime = gentleOn/1000) { setDimmerTransition(level, transTime) def updates = [:] updates << [switch: "on", level: level] sendEvent(name: "switch", value: "on", type: "digital") sendEvent(name: "level", value: level, type: "digital") logInfo("setLevel: ${updates}") runIn(9, getSysinfo) } def presetLevel(level) { presetBrightness(level) } def startLevelChange(direction) { logDebug("startLevelChange: [level: ${device.currentValue("level")}, direction: ${direction}]") if (device.currentValue("switch") == "off") { setRelayState(1) pauseExecution(1000) } if (direction == "up") { levelUp() } else { levelDown() } } def stopLevelChange() { logDebug("startLevelChange: [level: ${device.currentValue("level")}]") unschedule(levelUp) unschedule(levelDown) } def levelUp() { def curLevel = device.currentValue("level").toInteger() if (curLevel == 100) { return } def newLevel = curLevel + 4 if (newLevel > 100) { newLevel = 100 } presetBrightness(newLevel) runIn(1, levelUp) } def levelDown() { def curLevel = device.currentValue("level").toInteger() if (curLevel == 0 || device.currentValue("switch") == "off") { return } def newLevel = curLevel - 4 if (newLevel <= 0) { off() } else { presetBrightness(newLevel) runIn(1, levelDown) } } def setSysInfo(status) { def switchStatus = status.relay_state def logData = [:] def onOff = "on" if (switchStatus == 0) { onOff = "off" } if (device.currentValue("switch") != onOff) { sendEvent(name: "switch", value: onOff, type: "digital") logData << [switch: onOff] } if (device.currentValue("level") != status.brightness) { sendEvent(name: "level", value: status.brightness, type: "digital") logData << [level: status.brightness] } def ledStatus = status.led_off def ledOnOff = "on" if (ledStatus == 1) { ledOnOff = "off" } if (device.currentValue("led") != ledOnOff) { sendEvent(name: "led", value: ledOnOff) logData << [led: ledOnOff] } if (logData != [:]) { logInfo("setSysinfo: ${logData}") } if (nameSync == "device") { updateName(status) } } def checkTransTime(transTime) { if (transTime == null || transTime < 0.001) { transTime = gentleOn } else if (transTime == 0) { transTime = 50 } else { transTime = transTime * 1000 } if (transTime > 8000) { transTime = 8000 } return transTime.toInteger() } def checkLevel(level) { if (level == null || level < 0) { level = device.currentValue("level") logWarn("checkLevel: Entered level null or negative. Level set to ${level}") } else if (level > 100) { level = 100 logWarn("checkLevel: Entered level > 100. Level set to ${level}") } return level } def setDimmerTransition(level, transTime) { level = checkLevel(level) transTime = checkTransTime(transTime) logDebug("setDimmerTransition: [level: ${level}, transTime: ${transTime}]") if (level == 0) { setRelayState(0) } else { sendCmd("""{"smartlife.iot.dimmer":{"set_dimmer_transition":{"brightness":${level},""" + """"duration":${transTime}}}}""") } } def presetBrightness(level) { level = checkLevel(level) logDebug("presetLevel: [level: ${level}]") sendCmd("""{"smartlife.iot.dimmer":{"set_brightness":{"brightness":${level}}},""" + """"system" :{"get_sysinfo" :{}}}""") } def getDimmerConfiguration() { logDebug("getDimmerConfiguration") sendCmd("""{"smartlife.iot.dimmer":{"get_dimmer_parameters":{}, """ + """"get_default_behavior":{}}}""") } // ~~~~~ 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 (1363) davegut.kasaPlugs ~~~~~ library ( // library marker davegut.kasaPlugs, line 1 name: "kasaPlugs", // library marker davegut.kasaPlugs, line 2 namespace: "davegut", // library marker davegut.kasaPlugs, line 3 author: "Dave Gutheinz", // library marker davegut.kasaPlugs, line 4 description: "Kasa Plug and Switches Common Methods", // library marker davegut.kasaPlugs, line 5 category: "utilities", // library marker davegut.kasaPlugs, line 6 documentationLink: "" // library marker davegut.kasaPlugs, line 7 ) // library marker davegut.kasaPlugs, line 8 def on() { setRelayState(1) } // library marker davegut.kasaPlugs, line 10 def off() { setRelayState(0) } // library marker davegut.kasaPlugs, line 12 def ledOn() { setLedOff(0) } // library marker davegut.kasaPlugs, line 14 def ledOff() { setLedOff(1) } // library marker davegut.kasaPlugs, line 16 def distResp(response) { // library marker davegut.kasaPlugs, line 18 if (response.system) { // library marker davegut.kasaPlugs, line 19 if (response.system.get_sysinfo) { // library marker davegut.kasaPlugs, line 20 setSysInfo(response.system.get_sysinfo) // library marker davegut.kasaPlugs, line 21 } else if (response.system.set_relay_state || // library marker davegut.kasaPlugs, line 22 response.system.set_led_off) { // library marker davegut.kasaPlugs, line 23 if (getDataValue("model") == "HS210") { // library marker davegut.kasaPlugs, line 24 runIn(2, getSysinfo) // library marker davegut.kasaPlugs, line 25 } else { // library marker davegut.kasaPlugs, line 26 getSysinfo() // library marker davegut.kasaPlugs, line 27 } // library marker davegut.kasaPlugs, line 28 } else if (response.system.reboot) { // library marker davegut.kasaPlugs, line 29 logWarn("distResp: Rebooting device.") // library marker davegut.kasaPlugs, line 30 } else if (response.system.set_dev_alias) { // library marker davegut.kasaPlugs, line 31 updateName(response.system.set_dev_alias) // library marker davegut.kasaPlugs, line 32 } else { // library marker davegut.kasaPlugs, line 33 logDebug("distResp: Unhandled response = ${response}") // library marker davegut.kasaPlugs, line 34 } // library marker davegut.kasaPlugs, line 35 } else if (response["smartlife.iot.dimmer"]) { // library marker davegut.kasaPlugs, line 36 if (response["smartlife.iot.dimmer"].get_dimmer_parameters) { // library marker davegut.kasaPlugs, line 37 setDimmerConfig(response["smartlife.iot.dimmer"]) // library marker davegut.kasaPlugs, line 38 } else { // library marker davegut.kasaPlugs, line 39 logDebug("distResp: Unhandled response: ${response["smartlife.iot.dimmer"]}") // library marker davegut.kasaPlugs, line 40 } // library marker davegut.kasaPlugs, line 41 } else if (response.emeter) { // library marker davegut.kasaPlugs, line 42 distEmeter(response.emeter) // library marker davegut.kasaPlugs, line 43 } else if (response.cnCloud) { // library marker davegut.kasaPlugs, line 44 setBindUnbind(response.cnCloud) // library marker davegut.kasaPlugs, line 45 } else { // library marker davegut.kasaPlugs, line 46 logDebug("distResp: Unhandled response = ${response}") // library marker davegut.kasaPlugs, line 47 } // library marker davegut.kasaPlugs, line 48 } // library marker davegut.kasaPlugs, line 49 def setRelayState(onOff) { // library marker davegut.kasaPlugs, line 51 logDebug("setRelayState: [switch: ${onOff}]") // library marker davegut.kasaPlugs, line 52 if (getDataValue("plugNo") == null) { // library marker davegut.kasaPlugs, line 53 sendCmd("""{"system":{"set_relay_state":{"state":${onOff}}}}""") // library marker davegut.kasaPlugs, line 54 } else { // library marker davegut.kasaPlugs, line 55 sendCmd("""{"context":{"child_ids":["${getDataValue("plugId")}"]},""" + // library marker davegut.kasaPlugs, line 56 """"system":{"set_relay_state":{"state":${onOff}}}}""") // library marker davegut.kasaPlugs, line 57 } // library marker davegut.kasaPlugs, line 58 } // library marker davegut.kasaPlugs, line 59 def setLedOff(onOff) { // library marker davegut.kasaPlugs, line 61 logDebug("setLedOff: [ledOff: ${onOff}]") // library marker davegut.kasaPlugs, line 62 sendCmd("""{"system":{"set_led_off":{"off":${onOff}}}}""") // library marker davegut.kasaPlugs, line 63 } // library marker davegut.kasaPlugs, line 64 // ~~~~~ end include (1363) davegut.kasaPlugs ~~~~~