def getInfo(self, pluginAction, dev): self.logger.info("sent '{}' status request".format(dev.name)) addr = dev.address port = 9999 self.logger.debug("getInfo name={}, addr={}".format( dev.name, addr, )) tplink_dev = tplink_smartplug(addr, port) result = tplink_dev.send("info") try: # pretty print the json result json_result = json.loads(result) # Get the device state from the JSON if json_result["system"]["get_sysinfo"]["relay_state"] == 1: state = "on" else: state = "off" # Update Indigo's device state dev.updateStateOnServer("onOffState", state) self.logger.debug("getInfo result JSON:\n{}".format( json.dumps(json_result, sort_keys=True, indent=2, separators=(',', ': ')))) except ValueError as e: self.logger.error("JSON value error: {} on {}".format(e, result))
def getTpDevice(self, filter="", valuesDict=None, typeId="", targetId=0): self.logger.debug(u"called for: %s, %s, %s." % (filter, typeId, targetId)) self.logger.threaddebug(u"called for: %s, %s, %s, %s." % (filter, typeId, targetId, valuesDict)) deviceArray = [] if indigo.devices[targetId].configured: return deviceArray else: tplink_discover = tplink_smartplug(None, None) try: self.deviceSearchResults = tplink_discover.discover() except Exception as e: self.logger.error("Discovery connection failed with (%s)" % (str(e))) self.logger.debug(u"received %s" % (self.deviceSearchResults)) for address in self.deviceSearchResults: model = self.deviceSearchResults[address]['system'][ 'get_sysinfo']['model'] menuText = model + " @ " + address menuEntry = (address, menuText) deviceArray.append(menuEntry) menuEntry = ('manual', 'manual entry') deviceArray.append(menuEntry) return deviceArray
def actionControlDimmerRelay(self, action, dev): if dev.model == "SmartPlug": addr = dev.address childID = None deviceID = None else: addr = dev.ownerProps['addr'] childID = dev.ownerProps['outlet'] deviceID = dev.ownerProps['deviceID'] port = 9999 self.logger.debug("TPlink name={}, addr={}, action={}".format(dev.name, addr, action)) tplink_dev = tplink_smartplug (addr, port, deviceID, childID) ###### TURN ON ###### if action.deviceAction == indigo.kDimmerRelayAction.TurnOn: # Command hardware module (dev) to turn ON here: cmd = "on" ###### TURN OFF ###### elif action.deviceAction == indigo.kDimmerRelayAction.TurnOff: # Command hardware module (dev) to turn OFF here: cmd = "off" ###### TOGGLE ###### elif action.deviceAction == indigo.kDimmerRelayAction.Toggle: # Command hardware module (dev) to toggle here: if dev.onState: cmd = "off" else: cmd = "on" newOnState = not dev.onState else: self.logger.error("Unknown command: {}".format(indigo.kDimmerRelayAction)) return result = tplink_dev.send(cmd) sendSuccess = False try: result_dict = json.loads(result) error_code = result_dict["system"]["set_relay_state"]["err_code"] if error_code == 0: sendSuccess = True else: self.logger.error("turn {} command failed (error code: {})".format(cmd, error_code)) except: pass if sendSuccess: # If success then log that the command was successfully sent. self.logger.info(u'sent "{}" {}'.format(dev.name, cmd)) # And then tell the Indigo Server to update the state. dev.updateStateOnServer("onOffState", cmd) else: # Else log failure but do NOT update state on Indigo Server. self.logger.error(u'send "{}" {} failed with result "{}"'.format(dev.name, cmd, result))
def getInfo(self, pluginAction, dev): self.logger.debug("sent '{}' status request".format(dev.name)) if dev.model == "SmartPlug": addr = dev.address else: addr = dev.ownerProps['addr'] port = 9999 self.logger.debug("getInfo name={}, addr={}".format(dev.name, addr, ) ) tplink_dev = tplink_smartplug (addr, port) if dev.model == "SmartPlug": result = tplink_dev.send("info") try: # pretty print the json result json_result = json.loads(result) # Get the device state from the JSON # Parse JSON for device state if json_result["system"]["get_sysinfo"]["relay_state"] == 1: state = "on" else: state = "off" # Update Indigo's device state dev.updateStateOnServer("onOffState", state) self.logger.debug("getInfo result JSON:\n{}".format(json.dumps(json_result, sort_keys=True, indent=2, separators=(',', ': ')))) except ValueError as e: self.logger.error("JSON value error: {} on {}".format(e, result)) # If a SmartStrip or DualPlug else: result = tplink_dev.send("info") try: # pretty print the json result json_result = json.loads(result) # Parse JSON for device state plug_num = dev.ownerProps['outlet'] target_plug = [plug for plug in json_result["system"]["get_sysinfo"]['children'] if plug['id'] == dev.ownerProps['deviceID'] + str(int(plug_num)).zfill(2)] state_val = target_plug[0]['state'] if state_val == 1: state = "on" else: state = "off" # Update Indigo's device state dev.updateStateOnServer("onOffState", state) self.logger.debug("getInfo result JSON:\n{}".format(json.dumps(json_result, sort_keys=True, indent=2, separators=(',', ': ')))) except ValueError as e: self.logger.error("JSON value error: {} on {}".format(e, result)) if dev.model == "SmartStrip" : self.getEnergyInfo("", dev)
def initializeDev(self, valuesDict): self.logger.debug(u"called for: %s." % (valuesDict)) self.logger.debug(u"2 called for: %s." % (valuesDict)) devAddr = valuesDict['address'] devName = "new device at " + devAddr devPort = 9999 deviceId = None childId = None tplink_dev = tplink_smartplug(devAddr, devPort, deviceId, childId) result = tplink_dev.send('info') self.deviceSearchResults[devAddr] = result self.logger.debug(u"%s: InitializeDev 3 got %s" % (devName, result)) data = json.loads(result) self.deviceSearchResults[devAddr] = data self.logger.debug(u"%s: InitializeDev 4 got %s" % (devName, data)) valuesDict['deviceId'] = data['system']['get_sysinfo']['deviceId'] valuesDict['childId'] = str(deviceId) + valuesDict['outletNum'] valuesDict['mac'] = data['system']['get_sysinfo']['mac'] valuesDict['model'] = data['system']['get_sysinfo']['model'] if 'child_num' in data['system']['get_sysinfo']: self.logger.debug(u"%s has child_id", devName) valuesDict['multiPlug'] = True valuesDict['outletsAvailable'] = data['system']['get_sysinfo'][ 'child_num'] else: self.logger.debug(u"%s does not have child_id", devName) valuesDict['multiPlug'] = False valuesDict['outletsAvailable'] = 1 if 'ENE' in data['system']['get_sysinfo']['feature']: valuesDict['energyCapable'] = True else: valuesDict['energyCapable'] = False valuesDict['initialize'] = False return valuesDict
def getAlias(self, dev): self.logger.debug("sent '{}' status request".format(dev.name)) if dev.model == "SmartPlug": addr = dev.address else: addr = dev.ownerProps['addr'] port = 9999 self.logger.debug("Getting alias for ={}, addr={}".format(dev.name, addr, ) ) tplink_dev = tplink_smartplug (addr, port) if dev.model == "SmartPlug": result = tplink_dev.send("info") try: # pretty print the json result json_result = json.loads(result) # Parse JSON for Alias alias = json_result["system"]["get_sysinfo"]['alias'] except ValueError as e: self.logger.error("Error updating device alias.") # If a SmartStrip or DualPlug else: result = tplink_dev.send("info") try: # pretty print the json result json_result = json.loads(result) # Parse JSON for Alias plug_num = dev.ownerProps['outlet'] target_plug = [plug for plug in json_result["system"]["get_sysinfo"]['children'] if plug['id'] == str(int(plug_num)).zfill(2)] alias = target_plug[0]['alias'] except ValueError as e: self.logger.error("Error updating device alias.") # Update Indigo's device description/Notes field self.logger.debug("Updating device description with " + alias) dev.description = str(alias) dev.replaceOnServer()
def getEnergyInfo(self, pluginAction, dev): keyValueList = [] self.logger.debug("sent '{}' status request".format(dev.name)) if dev.model == "SmartPlug": addr = dev.address else: addr = dev.ownerProps['addr'] port = 9999 self.logger.debug("getInfo name={}, addr={}".format(dev.name, addr, ) ) tplink_dev = tplink_smartplug (addr, port, dev.ownerProps['deviceID'], dev.ownerProps['outlet']) result = tplink_dev.send("energy") try: # pretty print the json result json_result = json.loads(result) power_mw = json_result["emeter"]["get_realtime"]['power_mw'] self.logger.debug("Power in MW is " + str(power_mw)) # Set curEnergyLevel value curEnergyLevel = power_mw / float(1000) self.logger.debug("Current energy is " + str(curEnergyLevel)) keyValueList.append ({'key':"curEnergyLevel", 'value':curEnergyLevel, 'uiValue':str(curEnergyLevel) + "w"}) dev.updateStatesOnServer(keyValueList) except ValueError as e: self.logger.error("JSON value error: {} on {}".format(e, result))
def smartStripInit(self, device): self.logger.debug("Top of smartStripInit") port = 9999 addr = device.address.split(":")[0] childID = int(device.address.split(":")[1]) - 1 self.logger.debug("Smart strip or plug found. IP Address is: " + str(addr) + " and Outlet index ID is " + str(childID)) self.update_device_property(device, "addr", addr) self.update_device_property(device, "outlet", str(childID)) tplink_dev = tplink_smartplug (addr, port) json_result = tplink_dev.send("info") json_result = json.loads(json_result) deviceID = json_result["system"]["get_sysinfo"]["deviceId"] self.logger.debug("DeviceID is detected "+ deviceID) self.update_device_property(device, "deviceID", deviceID) if device.model == "SmartStrip" : keyValueList = [ {'key':'curEnergyLevel', 'value':''}] device.updateStatesOnServer(keyValueList)
def run(self): self.logger.debug(u"called for: %s." % (self.dev)) dev = self.dev devType = dev.deviceTypeId energyCapable = dev.pluginProps['energyCapable'] devAddr = dev.address devPort = 9999 self.logger.debug(u"%s multiPlug is %s" % (dev.name, self.multiPlug)) self.logger.debug(u"Starting data refresh for %s :%s:%s: with %s" % (dev.name, devType, devAddr, self.offPoll)) tplink_dev_states = tplink_smartplug(devAddr, devPort) lastState = 2 lastStateMulti = {} firstRun = False error_counter = 0 pollErrors = 0 while True: try: self.logger.debug( u"%s: Starting polling loop with interval %s\n", self.name, self.pollFreq) try: result = tplink_dev_states.send('info') self.logger.debug("%s connection received (%s)" % (self.name, result)) data = json.loads(result) except Exception as e: self.logger.error("%s connection failed with (%s)" % (self.name, str(e))) self.logger.debug( u"%s: finished state data collection with %s" % (self.name, data)) # Check if we got an error back if 'error' in data: pollErrors += 1 if pollErrors == 2: self.logger.error( u"2 consecutive polling error for device \"%s\": %s" % (self.name, data['error'])) elif pollErrors == 5: self.logger.error( u"5 consecutive polling error for device \"%s\": %s" % (self.name, data['error'])) elif pollErrors == 8: self.logger.error( u"8 consecutive polling error for device \"%s\": %s" % (self.name, data['error'])) elif pollErrors >= 10: self.logger.error( u"Unable to poll device \"%s\": %s after 10 attempts. Polling for this device will now shut down." % (self.name, data['error'])) indigo.device.enable(dev.id, value=False) return else: # First, we check the onOff state of each plug pollErrors = 0 if self.multiPlug: self.logger.debug( u"%s: entered multiPlug state block" % (self.name)) multiPlugOnCount = 0 elements = data['system']['get_sysinfo']['children'] self.logger.debug(u"%s: Elements %s" % (self.name, elements)) for element in elements: multiPlugOnCount += int(element['state']) outletName = element['alias'] outletNum = element['id'][-2:] # self.logger.error(u"on count = %s last on count was %s for %s" % (multiPlugOnCount, self.lastMultiPlugOnCount, self.dev.address)) devState = bool(element['state']) self.logger.debug( u"%s: Starting new element... id=%s, outletNum=%s, element=%s" % (outletName, element['id'], outletNum, element)) for outlet in self.outlets: self.logger.debug( u"%s: Outlet=%s and id=%s id=%s" % (outletName, outlet, element['id'], element['id'][-2:])) if outlet == outletNum: #element['id'][-2:] == outlet: self.logger.debug(u"%s: YES %s" % (outletName, outletNum)) # self.logger.debug(u"%s: indigo device onOffState is %s, actual is %s", outletName, lastStateMulti[outletNum], devState) if not outletNum in lastStateMulti: lastStateMulti[outletNum] = 2 foundMsg = 'found' else: foundMsg = 'remotely' if devState != lastStateMulti[outletNum]: if devState: state = True logState = "On" else: state = False logState = "Off" lastStateMulti[outletNum] = devState alias = element['alias'] rssi = data['system']['get_sysinfo'][ 'rssi'] state_update_list = [{ 'key': 'onOffState', 'value': state }, { 'key': 'rssi', 'value': rssi }, { 'key': 'alias', 'value': alias }] self.outlets[ outlet].updateStatesOnServer( state_update_list) if not self.localOnOff: if self.logOnOff: self.logger.info( u"%s -%s %s set to %s", self.name, outletName, foundMsg, logState) self.logger.debug( u"Polling found %s set to %s", self.name, logState) # Before we go, check to see if we need to update the polling interval if self.lastMultiPlugOnCount == 0 and multiPlugOnCount > 0: # we have transitioned from all plugs off to at least one plug on self.logger.debug( u"Changing polling interval to on for %s" % (self.dev.address)) self.interupt(state=True, action='state') elif self.lastMultiPlugOnCount > 0 and multiPlugOnCount == 0: # we have transitioned from at least one plug on to all plugs off self.logger.debug( u"Changing polling interval to on for %s" % (self.dev.address)) self.interupt(state=False, action='state') self.lastMultiPlugOnCount = multiPlugOnCount self.localOnOff = False else: # we have a single outlet device # self.logger.debug(u"%s: Got Here 0 with %s" % (self.name, data)) devState = data['system']['get_sysinfo']['relay_state'] self.logger.debug( u"%s: single outlet device 1 state= %s, lastState=%s" % (self.name, devState, lastState)) if not firstRun: # set the logOnOff msg to reflect a first pass in the poll firstRun = True foundMsg = 'found' else: foundMsg = 'remotely' if devState != lastState: if devState: state = True logState = "On" # self.interupt(state=True, action='state') else: state = False logState = "Off" # self.interupt(state=False, action='state') lastState = devState self.logger.debug( u"%s: state= %s, lastState=%s : %s" % (self.name, devState, lastState, state)) alias = data['system']['get_sysinfo']['alias'] rssi = data['system']['get_sysinfo']['rssi'] state_update_list = [{ 'key': 'onOffState', 'value': state }, { 'key': 'rssi', 'value': rssi }, { 'key': 'alias', 'value': alias }] dev.updateStatesOnServer(state_update_list) self.logger.debug( u"%s is now %s: localOnOff=%s, logOnOff=%s", self.name, logState, self.localOnOff, self.logOnOff) if not self.localOnOff: if self.logOnOff: self.logger.info(u"{} {} set to {}".format( self.name, foundMsg, logState)) self.interupt(state=state, action='state') self.localOnOff = False self.logger.debug(u"Polling found %s set to %s", self.name, logState) self.logger.debug( u"%s, updated state on server to %s (%s, %s)", self.name, state, rssi, alias) self.logger.debug(u"%s: finished state update %s" % (self.name, data)) # Now we start looking for energy data... if the plug is capable if energyCapable: if self.multiPlug: self.logger.debug( u"Starting energy query for devices at %s", devAddr) deviceId = self.deviceId for element in elements: # self.logger.debug(u"Starting energy update for %s: id=%s, element:%s" % (self.name, element['id'], element)) childId = element['id'][-2:] if childId in self.outlets: indigoDevice = self.outlets[childId] # totAccuUsage = float(indigoDevice.pluginProps['totAccuUsage']) self.logger.debug( u"Found entry for outlet %s devId is %s", childId, indigoDevice.id) state = element['state'] self.logger.debug( u"Ready to check energy for outlet %s, state %s" % (childId, state)) if bool(state): self.logger.debug( u"Getting energy for %s %s %s %s state %s" % (devAddr, devPort, deviceId, childId, state)) tplink_dev_energy = tplink_smartplug( devAddr, devPort, deviceId, childId) result = tplink_dev_energy.send( 'energy') data = json.loads(result) self.logger.debug("%s: data=%s" % (self.name, data)) curWatts = data['emeter'][ 'get_realtime']['power_mw'] / 1000 curVolts = data['emeter'][ 'get_realtime']['voltage_mv'] / 1000 curAmps = data['emeter'][ 'get_realtime']['current_ma'] / 1000 # totWattHrs = round( float( (data['emeter']['get_realtime']['total_wh'])/100) - totAccuUsage, 1) totWattHrs = round( float( (data['emeter']['get_realtime'] ['total_wh']) / 100), 1) state_update_list = [{ 'key': 'curWatts', 'value': curWatts }, { 'key': 'totWattHrs', 'value': totWattHrs }, { 'key': 'curVolts', 'value': curVolts }, { 'key': 'curAmps', 'value': curAmps }, { 'key': "curEnergyLevel", 'value': curWatts, 'uiValue': str(curWatts) + " w" }, { 'key': 'accumEnergyTotal', 'value': totWattHrs, 'uiValue': str(totWattHrs) + " kwh" }] indigoDevice.updateStatesOnServer( state_update_list) else: self.logger.debug( "Outlet %s:%s was off. No data collected", self.name, childId) state_update_list = [{ 'key': 'curWatts', 'value': 0 }, { 'key': 'curVolts', 'value': 0 }, { 'key': 'curAmps', 'value': 0 }, { 'key': "curEnergyLevel", 'value': 0, 'uiValue': str(0) + " w" }] indigoDevice.updateStatesOnServer( state_update_list) else: self.logger.debug( u"Outlet %s: outlet=%s not configured. No energy usage collected" % (self.name, childId)) else: # we have a single outlet device tplink_dev_energy = tplink_smartplug( devAddr, devPort, None, None) result = tplink_dev_energy.send('energy') data = json.loads(result) self.logger.debug("Received result: |%s|" % (result)) # totAccuUsage = float(dev.pluginProps['totAccuUsage']) curWatts = data['emeter']['get_realtime'][ 'power_mw'] / 1000 curVolts = data['emeter']['get_realtime'][ 'voltage_mv'] / 1000 curAmps = data['emeter']['get_realtime'][ 'current_ma'] / 1000 totWattHrs = round( float( data['emeter']['get_realtime']['total_wh']) / 100, 1) # totWattHrs = round( float( (data['emeter']['get_realtime']['total_wh'])/100) - totAccuUsage, 1) state_update_list = [{ 'key': 'curWatts', 'value': curWatts }, { 'key': 'totWattHrs', 'value': totWattHrs }, { 'key': 'curEnergyLevel', 'value': curWatts, 'uiValue': str(curWatts) + " w" }, { 'key': 'accumEnergyTotal', 'value': totWattHrs, 'uiValue': str(totWattHrs) + " kwh" }, { 'key': 'curVolts', 'value': curVolts }, { 'key': 'curAmps', 'value': curAmps }] dev.updateStatesOnServer(state_update_list) self.logger.debug( "Received results for %s @ %s secs: %s, %s, %s: change = %s" % (dev.name, self.pollFreq, curWatts, curVolts, curAmps, self.changed)) indigo.debugger() self.logger.debug( u"%s: In the loop - finished data gathering. Will now pause for %s" % (self.name, self.pollFreq)) pTime = 0.5 cTime = float(self.pollFreq) error_counter = 0 while cTime > 0: # self.logger.debug(u"%s: Looping Timer = %s", self.name, cTime) if self.changed or not self._is_running: # self.logger.debug(u"Device change for %s" % (self.name)) self.changed = False cTime = 0 else: # self.logger.debug(u"starting mini sleep for %6.4f" % (pTime)) sleep(pTime) cTime = cTime - pTime # self.logger.debug(u"Timer = %6.4f" % (cTime)) # self.logger.debug(u"Timer loop finished for %s", self.name) if not self._is_running: break self.logger.debug(u"%s: Back in the loop - timer ended" % (self.name)) except Exception as e: if error_counter == 10: self.logger.error( "Unable to update %s: after 10 attempts. Polling for this device will now shut down. (%s)" % (self.name, str(e))) indigo.device.enable(dev.id, value=False) return else: error_counter += 1 self.logger.error( "Error attempting to update %s: %s. Will try again in %s seconds" % (self.name, str(e), self.pollFreq))
def actionControlDimmerRelay(self, action, dev): self.logger.debug(u"called with: %s for %s." % (action, dev.name)) addr = dev.address port = 9999 if dev.pluginProps['multiPlug']: deviceId = dev.pluginProps['deviceId'] childId = dev.pluginProps['outletNum'] else: deviceId = None childId = None tplink_dev = tplink_smartplug(addr, port, deviceId, childId) self.logger.debug(u"tplink_dev set with: %s, %s, %s, %s." % (addr, port, deviceId, childId)) ###### TURN ON ###### if action.deviceAction == indigo.kDimmerRelayAction.TurnOn: cmd = "on" if dev.pluginProps['devPoll']: self.tpThreads[dev.address].interupt(state=True, action='state') ###### TURN OFF ###### elif action.deviceAction == indigo.kDimmerRelayAction.TurnOff: cmd = "off" if dev.pluginProps['devPoll']: self.tpThreads[dev.address].interupt(state=False, action='state') ###### TOGGLE ###### elif action.deviceAction == indigo.kDimmerRelayAction.Toggle: if dev.onState: cmd = "off" if dev.pluginProps['devPoll']: self.tpThreads[dev.address].interupt(state=False, action='state') else: cmd = "on" if dev.pluginProps['devPoll']: self.tpThreads[dev.address].interupt(state=True, action='state') else: self.logger.error("Unknown command: {}".format( indigo.kDimmerRelayAction)) return result = tplink_dev.send(cmd) sendSuccess = False try: result_dict = json.loads(result) error_code = result_dict["system"]["set_relay_state"]["err_code"] if error_code == 0: sendSuccess = True else: self.logger.error( "turn {} command failed (error code: {})".format( cmd, error_code)) except: pass indigo.debugger() if sendSuccess: # If success then log that the command was successfully sent. self.logger.debug(u'sent "{}" {}'.format(dev.name, cmd)) # And then tell the Indigo Server to update the state. if cmd == "on": state = True else: state = False dev.updateStateOnServer(key="onOffState", value=state) if self.logOnOff: self.logger.info(u"%s set to %s", dev.name, cmd) #self.tpThreads[dev.address].interupt(dev=dev, action='status') else: # Else log failure but do NOT update state on Indigo Server. self.logger.error(u'send "{}" {} failed with result "{}"'.format( dev.name, cmd, result))