Пример #1
0
    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.threaddebug(u"%s multiPlug is %s" %
                                (dev.name, self.multiPlug))

        self.logger.threaddebug(
            u"Starting data refresh for %s :%s:%s: with %s" %
            (dev.name, devType, devAddr, self.offPoll))

        tplink_dev_states = tplink_relay_protocol(devAddr, devPort)
        lastState = 2
        lastStateMulti = {}
        firstRun = False
        self.exceptCount = 0
        self.pollErrors = 0

        while True:
            try:
                self.logger.threaddebug(
                    u"%s: Starting polling loop with interval %s\n" %
                    (self.name, self.pollFreq))
                try:
                    result = tplink_dev_states.send('info')
                    self.logger.threaddebug("%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.threaddebug(
                    u"%s: finished state data collection with %s" %
                    (self.name, data))

                # Check if we got an error back
                if 'error' in data:
                    self.pollErrors += 1
                    if self.pollErrors == 5:
                        self.logger.error(
                            u"5 consecutive polling error for device \"%s\": %s"
                            % (self.name, data['error']))
                        self.pollFreq += 1
                    elif self.pollErrors == 10:
                        self.logger.error(
                            u"8 consecutive polling error for device \"%s\": %s"
                            % (self.name, data['error']))
                        self.pollFreq += 1
                    elif self.pollErrors >= 15:
                        self.logger.error(
                            u"Unable to poll device \"%s\": %s after 15 attempts. Polling for this device will now shut down."
                            % (self.name, data['error']))
                        indigo.device.enable(dev.id, value=False)
                        return

                else:
                    if self.pollErrors > 0:
                        self.pollErrors = 0
                        # reset pollFreq in case increaded due to errors
                        if self.onOffState:
                            self.pollFreq = self.onPoll
                        else:
                            self.pollFreq = self.offPoll
                    # check the onOff state of each plug
                    if self.multiPlug:
                        self.logger.threaddebug(
                            u"%s: entered multiPlug state block" % (self.name))
                        multiPlugOnCount = 0
                        elements = data['system']['get_sysinfo']['children']

                        self.logger.threaddebug(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.threaddebug(
                                u"%s: Starting new element... id=%s, outletNum=%s, element=%s"
                                % (outletName, element['id'], outletNum,
                                   element))
                            for outlet in self.outlets:
                                self.logger.threaddebug(
                                    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.threaddebug(
                                        u"%s: YES %s" %
                                        (outletName, outletNum))
                                    # self.logger.threaddebug(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.threaddebug(
                                            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.threaddebug(
                                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.threaddebug(
                                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.threaddebug(u"%s: Got Here 0 with %s" % (self.name, data))
                        devState = data['system']['get_sysinfo']['relay_state']
                        self.logger.threaddebug(
                            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.threaddebug(
                                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.threaddebug(
                                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.threaddebug(
                                u"Polling found %s set to %s" %
                                (self.name, logState))
                            self.logger.threaddebug(
                                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.threaddebug(
                                u"Starting energy query for devices at %s" %
                                (devAddr))
                            deviceId = self.deviceId

                            for element in elements:
                                # self.logger.threaddebug(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.threaddebug(
                                        u"Found entry for outlet %s devId is %s"
                                        % (childId, indigoDevice.id))

                                    state = element['state']
                                    self.logger.threaddebug(
                                        u"Ready to check energy for outlet %s, state %s"
                                        % (childId, state))
                                    if bool(state):
                                        self.logger.threaddebug(
                                            u"Getting energy for %s %s %s %s state %s"
                                            % (devAddr, devPort, deviceId,
                                               childId, state))
                                        tplink_dev_energy = tplink_relay_protocol(
                                            devAddr, devPort, deviceId,
                                            childId)
                                        result = tplink_dev_energy.send(
                                            'energy')
                                        data = json.loads(result)
                                        self.logger.threaddebug(
                                            "%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_relay_protocol(
                                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.threaddebug(
                                "Received results for %s @ %s secs: %s, %s, %s: change = %s"
                                % (dev.name, self.pollFreq, curWatts, curVolts,
                                   curAmps, self.changed))
                indigo.debugger()
                self.logger.threaddebug(
                    u"%s: In the loop - finished data gathering. Will now pause for %s"
                    % (self.name, self.pollFreq))
                pTime = 0.5
                cTime = float(self.pollFreq)

                self.exceptCount = 0
                while cTime > 0:
                    # self.logger.threaddebug(u"%s: Looping Timer = %s" % (self.name, cTime) )
                    if self.changed or not self._is_running:
                        # self.logger.threaddebug(u"Device change for %s" % (self.name))
                        self.changed = False
                        cTime = 0
                    else:
                        # self.logger.threaddebug(u"starting mini sleep for %6.4f" % (pTime))
                        sleep(pTime)
                        cTime = cTime - pTime
                        # self.logger.threaddebug(u"Timer = %6.4f" % (cTime))

                    # self.logger.threaddebug(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 self.exceptCount == 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:
                    self.exceptCount += 1
                    self.logger.error(
                        "Error attempting to update %s: %s. Will try again in %s seconds"
                        % (self.name, str(e), self.pollFreq))
Пример #2
0
    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))
Пример #3
0
  def run(self):
    self.logger.debug(u"called for: %s." % (self.dev, ))
    dev = self.dev
    devType = dev.deviceTypeId
    devAddr = dev.address
    devPort = 9999

    self.logger.threaddebug(u"Starting data refresh for %s :%s:%s: with %s" % (dev.name, devType, devAddr, self.offPoll))

    tplink_dev_states = tplink_dimmer_protocol(devAddr, devPort, self.deviceId)
    lastState = 2
    lastStateMulti = {}
    firstRun = False
    self.exceptCount = 0
    self.pollErrors = 0

    while True:
      try:
        self.logger.threaddebug(u"%s: Starting polling loop with interval %s\n" % (self.name, self.pollFreq) )
        try:
          result = tplink_dev_states.send('info',"","")
          self.logger.threaddebug("%s connection 1 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.threaddebug(u"%s: finished state data collection with %s" % (self.name, data))

        # Check if we got an error back
        if 'error' in data or 'error' in data1:
          self.pollErrors += 1
          if self.pollErrors == 5:
            self.logger.error(u"5 consecutive polling error for device \"%s\": %s" % (self.name, data['error']))
            self.pollFreq += 1
          elif self.pollErrors == 10:
            self.logger.error(u"8 consecutive polling error for device \"%s\": %s" % (self.name, data['error']))
            self.pollFreq += 1
          elif self.pollErrors >= 15:
            self.logger.error(u"Unable to poll device \"%s\": %s after 15 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
          if self.pollErrors > 0:
            self.pollErrors = 0
            # reset pollFreq in case increaded due to errors
            if self.onOffState:
              self.pollFreq = self.onPoll
            else:
              self.pollFreq = self.offPoll
          # self.logger.threaddebug(u"%s: Got Here 0 with %s" % (self.name, data))
          devState = data['system']['get_sysinfo']['light_state']['on_off']
          self.logger.threaddebug(u"%s: smartBulb 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:
            # the device state changed; update indigo states
            if devState == 0:
              state = False
              logState = "Off"
              # self.interupt(state=True, action='state')
            else: # on or dimmed
              state = True
              logState = "On"
              # self.interupt(state=False, action='state')
            lastState = devState

            self.logger.threaddebug(u"%s: state= %s, lastState=%s : %s" % (self.name, devState, lastState, state))

            alias = data['system']['get_sysinfo']['alias']
            rssi = data['system']['get_sysinfo']['rssi']
            bright = data['system']['get_sysinfo']['brightness']

            data1 = data1['smartlife.iot.dimmer']['get_dimmer_parameters']
            state_update_list = [
                {'key':'onOffState', 'value':state, 'uiValue':logState},
                {'key':'brightnessLevel', 'value':bright},
                {'key':'rssi',  'value':rssi},
                {'key':'alias', 'value':alias},
              ]
            dev.updateStatesOnServer(state_update_list)
            self.logger.debug(u"{}, updated state on server: onOff={}, alias={}".format(self.name, state, alias))

            self.logger.threaddebug(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))

            if state:
              # only get HSV parameters from the device if the bulb is on (or dimmed)
              # the data returned by 'info' has several different formats...
              if "dft_on_state" in  data['system']['get_sysinfo']['light_state']:
                brightness = data['system']['get_sysinfo']['light_state']["dft_on_state"]['brightness']
                hue        = data['system']['get_sysinfo']['light_state']["dft_on_state"]['hue']
                sat        = data['system']['get_sysinfo']['light_state']["dft_on_state"]['saturation']
                temp       = data['system']['get_sysinfo']['light_state']["dft_on_state"]['color_temp']
                fromObject = 'dft_on_state'
              elif "brightness" in  data['system']['get_sysinfo']['light_state']:
                brightness = data['system']['get_sysinfo']['light_state']['brightness']
                hue        = data['system']['get_sysinfo']['light_state']['hue']
                sat        = data['system']['get_sysinfo']['light_state']['saturation']
                temp       = data['system']['get_sysinfo']['light_state']['color_temp']
                fromObject = 'light_state'
              else:
                self.logger.debug(u"{}, brightness not in light_state data: {}".format(self.name, data['system']['get_sysinfo']['light_state']))
                brightness = None

              if brightness is not None:
                state_update_list = [
                    {'key':'brightnessLevel', 'value':brightness},
                    {'key':'Hue',        'value':hue},
                    {'key':'Saturation', 'value':sat},
                    {'key':'colorTemp',  'value':temp},
                  ]
                dev.updateStatesOnServer(state_update_list)
                self.logger.debug(u"{}, updated state on server: Dimmer States={} from {}".format(self.name, state_update_list, fromObject))

            else:
                # if the bulb is off, just set to 0
                state_update_list = [
                    {'key':'brightnessLevel', 'value':0},
                    # leave other parameters alone
                  ]
                dev.updateStatesOnServer(state_update_list)

            self.interupt(state=state, action='state')
            self.localOnOff = False

            self.logger.threaddebug(u"Polling %s %s set to %s" % ((self.name, foundMsg, logState)) )

          elif devState and "dft_on_state" in data['system']['get_sysinfo']['light_state']:
            # if the device is on, update the brighness - maybe we didn't get it last time
            brightness = data['system']['get_sysinfo']['light_state']["dft_on_state"]['brightness']
            hue        = data['system']['get_sysinfo']['light_state']["dft_on_state"]['hue']
            sat        = data['system']['get_sysinfo']['light_state']["dft_on_state"]['saturation']
            temp       = data['system']['get_sysinfo']['light_state']["dft_on_state"]['color_temp']

            state_update_list = [
                {'key':'brightnessLevel', 'value':brightness},
                {'key':'Hue',        'value':hue},
                {'key':'Saturation', 'value':sat},
                {'key':'colorTemp',  'value':temp},
              ]
            dev.updateStatesOnServer(state_update_list)
            self.logger.debug(u"{}, no state change; update state on server: Dimmer States={}".format(self.name, state_update_list))

          self.logger.debug(u"%s: finished state update %s" % (self.name, data))

        indigo.debugger()
        self.logger.threaddebug(u"%s: In the loop - finished data gathering. Will now pause for %s" % (self.name, self.pollFreq))
        pTime = 0.5
        cTime = float(self.pollFreq)

        self.exceptCount = 0
        while cTime > 0:
          # self.logger.threaddebug(u"%s: Looping Timer = %s" % (self.name, cTime) )
          if self.changed or not self._is_running:
            # self.logger.threaddebug(u"Device change for %s" % (self.name))
            self.changed = False
            cTime = 0
          else:
            # self.logger.threaddebug(u"starting mini sleep for %6.4f" % (pTime))
            sleep(pTime)
            cTime = cTime - pTime
            # self.logger.threaddebug(u"Timer = %6.4f" % (cTime))

          # self.logger.threaddebug(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 self.exceptCount == 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:
          self.exceptCount += 1
          self.logger.error("Error attempting to update %s: %s. Will try again in %s seconds" % (self.name, str(e), self.pollFreq))
  def run(self):
    self.logger.debug(u"called for: %s." % (self.dev, ))
    dev = self.dev
    devType = dev.deviceTypeId
    devAddr = dev.address
    devPort = 9999

    self.logger.threaddebug(u"Starting data refresh for %s :%s:%s: with %s" % (dev.name, devType, devAddr, self.offPoll))

    tplink_dev_states = tplink_relayswitch_protocol(devAddr, devPort)
    lastState = 2
    firstRun = False
    self.exceptCount = 0
    self.pollErrors = 0

    while True:
      try:
        self.logger.threaddebug(u"%s: Starting polling loop with interval %s\n" % (self.name, self.pollFreq) )
        try:
          result = tplink_dev_states.send('info',"","")
          self.logger.threaddebug("%s connection 1 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)))

        try:
          result = tplink_dev_states.send('getParam',"","")
          self.logger.threaddebug("%s connection 2 received (%s)" % (self.name, result))
          data1 = json.loads(result)
          result = tplink_dev_states.send('getBehave',"","")
          self.logger.threaddebug("%s connection 3 received (%s)" % (self.name, result))
          data2 = json.loads(result)
        except Exception as e:
          self.logger.error("{} error getting RelaySwitch data. Is this the right device type?".format(self.name))
          self.logger.error("    error was '{}'".format(str(e)))
          self.logger.error("    Polling for this device will now shut down.")
          indigo.device.enable(dev.id, value=False)
          return

        self.logger.threaddebug(u"%s: finished state data collection with %s" % (self.name, data))

        # Check if we got an error back
        if 'error' in data or 'error' in data1 or 'error' in data2:
          self.pollErrors += 1
          # put the error in one place no matter which command failed
          if 'error' in data:
            error = data['error']
          elif 'error' in data1:
            error = data1['error']
          elif 'error' in data2:
            error = data2['error']

          if self.pollErrors == 5:
            self.logger.error(u"5 consecutive polling error for device \"%s\": %s" % (self.name, error))
            self.pollFreq += 1
          elif self.pollErrors == 10:
            self.logger.error(u"10 consecutive polling error for device \"%s\": %s" % (self.name, error))
            self.pollFreq += 1
          elif self.pollErrors >= 15:
            self.logger.error(u"Unable to poll device \"%s\": %s after 15 attempts. Polling for this device will now shut down." % (self.name, error))
            indigo.device.enable(dev.id, value=False)
            return

        else:
            if self.pollErrors > 0:
              self.pollErrors = 0
              # reset pollFreq in case increaded due to errors
              if self.onOffState:
                self.pollFreq = self.onPoll
              else:
                self.pollFreq = self.offPoll
            # self.logger.threaddebug(u"%s: Got Here 0 with %s" % (self.name, data))
            devState = data['system']['get_sysinfo']['relay_state']
            bright = data['system']['get_sysinfo']['brightness']
            self.logger.threaddebug(u"%s: switch state= %s, lastState=%s, brightness=%s" % (self.name, devState, lastState, str(bright)))
            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.threaddebug(u"%s: state= %s, lastState=%s : %s" % (self.name, devState, lastState, state))
#            indigo.server.log(u"%s: state= %s, lastState=%s : %s" % (self.name, devState, lastState, state))
            try:
              alias = data['system']['get_sysinfo']['alias']
              rssi = data['system']['get_sysinfo']['rssi']
              data1 = data1['smartlife.iot.dimmer']['get_dimmer_parameters']
              fadeOnTime = data1['fadeOnTime']
              fadeOffTime = data1['fadeOffTime']
              minThreshold = data1['minThreshold']
              gentleOnTime = data1['gentleOnTime']
              gentleOffTime = data1['gentleOffTime']
              rampRate = data1['rampRate']
              data2 = data2['smartlife.iot.dimmer']['get_default_behavior']
              hardOn=data2['hard_on']['mode']
              softOn=data2['soft_on']['mode']
              longPress=data2['long_press']['mode']
              doubleClick=data2['double_click']['mode']
            except:
              self.logger.error("{} error parsing RelaySwitch data. Is this the right device type?".format(self.name))
              self.logger.error("    error was '{}'".format(str(e)))
              self.logger.error("    Polling for this device will now shut down.")
              indigo.device.enable(dev.id, value=False)
              return

#           indigo,server.log("update state:"+str(state))
            if state==False:
                  bright=0

            state_update_list = [
                  {'key':'onOffState', 'value':state},
                  {'key':'brightnessLevel', 'value':bright},
                  {'key':'rssi', 'value':rssi},
                  {'key':'alias', 'value':alias},
                  {'key':'fadeOnTime', 'value':fadeOnTime},
                  {'key':'fadeOffTime', 'value':fadeOffTime},
                  {'key':'minThreshold', 'value':minThreshold},
                  {'key':'gentleOnTime', 'value':gentleOnTime},
                  {'key':'gentleOffTime', 'value':gentleOffTime},
                  {'key':'hardOn', 'value':hardOn},
                  {'key':'softOn', 'value':softOn},
                  {'key':'longPress', 'value':longPress},
                  {'key':'doubleClick', 'value':doubleClick},
                ]
            dev.updateStatesOnServer(state_update_list)

            self.logger.threaddebug(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.threaddebug(u"Polling found %s set to %s" % (self.name, logState) )
            self.logger.threaddebug(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))

        indigo.debugger()
        self.logger.threaddebug(u"%s: In the loop - finished data gathering. Will now pause for %s" % (self.name, self.pollFreq))
        pTime = 0.5
        cTime = float(self.pollFreq)

        self.exceptCount = 0
        while cTime > 0:
          # self.logger.threaddebug(u"%s: Looping Timer = %s" % (self.name, cTime) )
          if self.changed or not self._is_running:
            # self.logger.threaddebug(u"Device change for %s" % (self.name, ))
            self.changed = False
            cTime = 0
          else:
            # self.logger.threaddebug(u"starting mini sleep for %6.4f" % (pTime, ))
            sleep(pTime)
            cTime = cTime - pTime
            # self.logger.threaddebug(u"Timer = %6.4f" % (cTime, ))

          # self.logger.threaddebug(u"Timer loop finished for %s" % (self.name, ))

        self.logger.debug(u"%s: Back in the loop - timer ended" % (self.name, ))

      except Exception as e:
        if self.exceptCount == 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:
          self.exceptCount += 1
          self.logger.error("Error attempting to update %s: %s. Will try again in %s seconds" % (self.name, str(e), self.pollFreq))