예제 #1
0
 def shortPoll(self):
     LOGGER.debug('')
     self.save_custom_data()
     self.set_hosts_connected()
     # Call shortpoll on the camect hosts
     for id,node in self.nodes_by_id.items():
         node.shortPoll()
예제 #2
0
    def refresh(self):
        if not self.isStarted:
            return

        for entry in self.calendars:
            calendar = entry.calendar
            LOGGER.debug('Checking calendar %s', calendar['summary'])
            todayDate = datetime.datetime.now(
                pytz.timezone(calendar['timeZone']))
            todayDate = todayDate.replace(hour=0,
                                          minute=0,
                                          second=0,
                                          microsecond=0)
            tomorrowDate = todayDate + datetime.timedelta(days=1)
            endDate = todayDate + datetime.timedelta(days=2)
            entry.todayNode.setDate(todayDate)
            entry.tomorrowNode.setDate(tomorrowDate)
            result = self.service.events().list(
                calendarId=calendar['id'],
                timeMin=todayDate.isoformat(),
                singleEvents=True,
                timeMax=endDate.isoformat()).execute()
            for event in result.get('items', []):
                if self.is_holiday(event):
                    LOGGER.debug('Event found %s', event['summary'])
                    date = dateutil.parser.parse(event['start']['date']).date()

                    if date == todayDate.date():
                        entry.todayNode.setFutureState()
                    else:
                        entry.tomorrowNode.setFutureState()
            entry.todayNode.refresh()
            entry.tomorrowNode.refresh()
예제 #3
0
 def start(self):
     if 'remoteSensors' in self.tstat:
         #LOGGER.debug("{}:remoteSensors={}".format(self.address,json.dumps(self.tstat['remoteSensors'], sort_keys=True, indent=2)))
         for sensor in self.tstat['remoteSensors']:
             if 'id' in sensor and 'name' in sensor:
                 sensorAddress = self.getSensorAddress(sensor)
                 if sensorAddress is not None:
                     # Delete the old one if it exists
                     sensorAddressOld = self.getSensorAddressOld(sensor)
                     try:
                         fonode = self.controller.poly.getNode(
                             sensorAddressOld)
                     except TypeError:
                         fonode = False
                         LOGGER.debug(
                             "caught fnode fail due to polyglot cloud bug? assuming old node not found"
                         )
                     if fonode is not False:
                         self.controller.addNotice({
                             fnode['address']:
                             "Sensor created with new name, please delete old sensor with address '{}' in the Polyglot UI."
                             .format(fnode['address'])
                         })
                     addS = False
                     # Add Sensor is necessary
                     # Did the nodedef id change?
                     nid = self.get_sensor_nodedef(sensor)
                     sensorName = get_valid_node_name('Ecobee - {}'.format(
                         sensor['name']))
                     self.controller.addNode(
                         Sensor(self.controller, self.address,
                                sensorAddress, sensorName, nid, self))
     self.check_weather()
     self.update(self.revData, self.fullData)
     self.query()
예제 #4
0
    def send_msg(self, zone):
        data = bytearray(36)
        data[0] = 0xf0
        self.setIDs(data, 4, 0, 0, 0x70)
        data[7] = 0
        data[21] = ord('a')
        data[22] = ord(' ')
        data[23] = ord('m')
        data[24] = ord('e')
        data[25] = ord('s')
        data[26] = ord('s')
        data[27] = ord('a')
        data[28] = ord('g')
        data[29] = ord('e')
        self.setIDs(data, 1, 0x7f, 0, 0)
        self.setPath(data, 8, [0x01, 0x01], [])
        data[12] = 0x00
        data[13] = 0x00
        data[14] = 0x01
        data[15] = 0x00
        data[16] = 0x10
        data[17] = 0x00

        data[34] = self.checksum(data, 34)
        data[35] = 0xf7

        LOGGER.debug('sending message: ' + ' '.join('{:02x}'.format(x)
                                                    for x in data))
        self.Send(data)
예제 #5
0
    def volume(self, zone, level):
        data = bytearray(22)

        data[0] = 0xf0
        self.setIDs(data, 1, 0, 0, 0x7f)
        self.setIDs(data, 4, 0, zone, 0x70)
        data[7] = 0x05
        data[8] = 0x02
        data[9] = 0x02
        data[10] = 0x00
        data[11] = 0x00
        data[12] = 0xf1
        data[13] = 0x21
        data[14] = 0x00
        data[15] = level
        data[16] = 0x00
        data[17] = zone
        data[18] = 0x00
        data[19] = 0x01
        data[20] = self.checksum(data, 20)
        data[21] = 0xf7

        LOGGER.debug('sending volume: ' + ''.join('{:02x}'.format(x)
                                                  for x in data))
        self.Send(data)
예제 #6
0
    def __russound_loop_tcp(self, processCommand):
        buf = bytearray(50)
        st = 0

        while self.connected:
            try:
                data = self.sock.recv(4096)
                #LOGGER.debug(data)

                for b in data:
                    if st == 0:  # looking for start byte
                        if b == 0xf0:
                            buf[st] = b
                            st += 1
                    else:  # looking for end byte
                        if b == 0xf7:
                            buf[st] = b
                            st = 0
                            LOGGER.debug('recv: ' + ' '.join('{:02x}'.format(x)
                                                             for x in data))
                            msg = rnet_message.RNetMessage(buf)
                            processCommand(msg)
                        else:
                            buf[st] = b
                            st += 1

            except BlockingIOError:
                LOGGER.info('waiting on data')
                pass
            except ConnectionResetError as msg:
                LOGGER.error('Connection error: ' + str(msg))
                self.connected = False
예제 #7
0
    def get_info(self, zone, info_type):
        path_len = (info_type & 0xff00) >> 8
        if path_len == 5:
            data = bytearray(18)
        else:
            data = bytearray(17)

        data[0] = 0xf0
        self.setIDs(data, 1, 0, 0, 0x7f)
        self.setIDs(data, 4, 0, zone, 0x70)
        data[7] = 0x01

        if path_len == 5:
            self.setPath(data, 8,
                         [0x02, 0x00, zone, 0x00, (info_type & 0x00ff)])
            data[15] = 0x00
            data[16] = self.checksum(data, 16)
            data[17] = 0xf7
        else:
            self.setPath(data, 8, [0x02, 0x00, zone, (info_type & 0x00ff)])
            data[14] = 0x00
            data[15] = self.checksum(data, 15)
            data[16] = 0xf7

        LOGGER.debug('sending get_info: ' + ''.join('{:02x}'.format(x)
                                                    for x in data))
        self.Send(data)
예제 #8
0
 def set_param(self, rioZone, param, level):
     LOGGER.debug('sending Zone:' + rioZone + ' level:' + str(level))
     if param == 0:
         data = 'SET ' + rioZone + '.bass="' + str(level - 10) + '"\r\n'
     if param == 1:
         data = 'SET ' + rioZone + '.treble="' + str(level - 10) + '"\r\n'
     if param == 2:
         if level == 0:
             data = 'SET ' + rioZone + '.loudness="OFF"\r\n'
         else:
             data = 'SET ' + rioZone + '.loudness="ON"\r\n'
     if param == 3:
         data = 'SET ' + rioZone + '.balance="' + str(level - 10) + '"\r\n'
     if param == 4:
         data = 'SET ' + rioZone + '.turnOnVolume="' + str(level) + '"\r\n'
     if param == 5:
         if level == 0:
             data = 'EVENT ' + rioZone + '!ZoneMuteOff\r\n'
         else:
             data = 'EVENT ' + rioZone + '!ZoneMuteOn\r\n'
     if param == 6:
         if level == 0:
             data = 'EVENT ' + rioZone + '!DoNotDisturb OFF\r\n'
         else:
             data = 'EVENT ' + rioZone + '!doNotDisturb ON\r\n'
     if param == 7:
         if level == 0:
             data = 'EVENT ' + rioZone + '!PartyMode OFF\r\n'
         else:
             data = 'EVENT ' + rioZone + '!PartyMode ON\r\n'
     self.Send(data)
예제 #9
0
 def set_logical_status(self, val=None, force=False):
     LOGGER.debug(f'{self.lpfx} val={val}')
     if val is None:
         val = self.elk.logical_status
     else:
         val = int(val)
     self._set_logical_status(val, force=force)
예제 #10
0
 def set_debug_level(self, level):
     LOGGER.debug('set_debug_level: {}'.format(level))
     if level is None:
         level = 10
     level = int(level)
     if level == 0:
         level = 30
     LOGGER.info('set_debug_level: Set GV1 to {}'.format(level))
     self.set_driver('GV1', level)
     # 0=All 10=Debug are the same because 0 (NOTSET) doesn't show everything.
     if level <= 10:
         LOGGER.setLevel(logging.DEBUG)
     elif level == 20:
         LOGGER.setLevel(logging.INFO)
     elif level == 30:
         LOGGER.setLevel(logging.WARNING)
     elif level == 40:
         LOGGER.setLevel(logging.ERROR)
     elif level == 50:
         LOGGER.setLevel(logging.CRITICAL)
     else:
         LOGGER.debug("set_debug_level: Unknown level {}".format(level))
     if level < 10:
         LOG_HANDLER.set_basic_config(True, logging.DEBUG)
     else:
         # This is the polyinterface default
         LOG_HANDLER.set_basic_config(True, logging.WARNING)
 def start(self):
     """
     Optional.
     Polyglot v2 Interface startup done. Here is where you start your integration.
     This will run, once the NodeServer connects to Polyglot and gets it's config.
     In this example I am calling a discovery method. While this is optional,
     this is where you should start. No need to Super this method, the parent
     version does nothing.
     """
     # This grabs the server.json data and checks profile_version is up to
     # date based on the profile_version in server.json as compared to the
     # last time run which is stored in the DB.  When testing just keep
     # changing the profile_version to some fake string to reload on restart
     # Only works on local currently..
     serverdata = self.poly.get_server_data(check_profile=True)
     #serverdata['version'] = "testing"
     LOGGER.info('Started Template NodeServer {}'.format(
         serverdata['version']))
     # Show values on startup if desired.
     LOGGER.debug('ST=%s', self.getDriver('ST'))
     self.setDriver('ST', 1)
     self.heartbeat(0)
     self.check_params()
     self.set_debug_level(self.getDriver('GV1'))
     self.discover()
     self.poly.add_custom_config_docs(
         "<b>This is some custom config docs data</b>")
예제 #12
0
def RmZoneCtrl(url, access_token, command):
    #extract the zone number from the command string
    zone = ''.join(filter(lambda i: i.isdigit(), command['address']))
    if command['cmd'] == 'STOP':
        try:
            response = requests.post(url + 'api/4/zone/' + str(zone) +
                                     "/stop" + access_token,
                                     data=None,
                                     json=None,
                                     verify=False)
            LOGGER.debug(response)
            LOGGER.debug('Received Stop Command')
        except:
            LOGGER.error('Unable to stop zone {} watering'.format(zone))

    elif command['cmd'] == 'RUN':
        #extract the run duration from the command string and convert it to minutes
        zone_duration = '{"time":' + str(int(command['value']) * 60) + '}'
        LOGGER.debug("Zone duration: {}".format(zone_duration))
        #'{"time":60}'
        try:
            response = requests.post(url + 'api/4/zone/' + str(zone) +
                                     "/start" + access_token,
                                     data=zone_duration,
                                     json=None,
                                     verify=False)
            LOGGER.debug('Received Run Command')
            LOGGER.debug(response.url)
        except:
            LOGGER.error('Unable to start zone watering')
예제 #13
0
 def set_force_off(self, command):
     LOGGER.debug("Setting %s to force off", self.key)
     self.is_day_off = False
     self.is_force_off = True
     self.setDriver('ST', self.get_state())
     time.sleep(1)
     self.controller.set_force_off(self.dateProvider.dates[self.key])
예제 #14
0
 def is_weekend(self, key):
     result = self.weekend.get(calendar.day_name[self.dates[key].weekday()])
     if result is not None:
         LOGGER.debug('Weekend found for Key %s, Date %s', key,
                      self.dates[key])
         return True
     return False
예제 #15
0
def rmHeartBeat(host, timeout):

    try:
        response, result = sp.getstatusoutput("ping -c1 -w" + str(timeout) +
                                              " " + host)
        LOGGER.debug("rmHeartBeat response: {}".format(response))
        if response == 0:
            LOGGER.debug('Running on RPi')
            return response

    except OSError as err:
        LOGGER.error('Ping Error - No Heartbeat')
        LOGGER.debug(err)
        return None

    if response == 127:
        try:
            response = sp.call(
                ['/sbin/ping', '-c1', '-W' + str(timeout), host], shell=False)
            LOGGER.debug("rmHeartBeat response: {}".format(response))
            if response == 0:
                LOGGER.debug('Running on Polisy')
                return response
        except OSError as err:
            LOGGER.error(err)
            return None
    else:
        LOGGER.error('Ping Error - No Heartbeat')
        return None
예제 #16
0
    def tuyaPlatform(self, apiRegion, apiKey, apiSecret, uri, token=None):
        request = "https://openapi.tuya%s.com/v1.0/%s" % (apiRegion, uri)
        now = int(time.time() * 1000)
        if (token == None):
            payload = apiKey + str(now)
        else:
            payload = apiKey + token + str(now)

        # Sign Payload
        signature = hmac.new(apiSecret.encode('utf-8'),
                             msg=payload.encode('utf-8'),
                             digestmod=hashlib.sha256).hexdigest().upper()

        # Create Header Data
        headers = {}
        headers['client_id'] = apiKey
        headers['sign_method'] = 'HMAC-SHA256'
        headers['t'] = str(now)
        headers['sign'] = signature
        if (token != None):
            headers['access_token'] = token

        # Get Token
        response = requests.get(request, headers=headers)
        try:
            response_dict = json.loads(response.content.decode())
        except:
            try:
                response_dict = json.loads(response.content)
            except:
                LOGGER.debug("Failed to get valid JSON response")
예제 #17
0
 def setSwOn(self, command):
     self.setDriver('GV2', 1)
     payload1 = None
     payload1 = d.generate_payload(tinytuya.CONTROL, {'1': False, '2': 50})
     d = tinytuya.OutletDevice
     LOGGER.debug(("\nTest Cycle Switch by def on"))
     d._send_receive(payload1)
 def set_debug_level(self, level):
     LOGGER.debug('set_debug_level: {}'.format(level))
     if level is None:
         level = 30
     level = int(level)
     if level == 0:
         level = 30
     LOGGER.info('set_debug_level: Set GV1 to {}'.format(level))
     self.setDriver('GV1', level)
     # 0=All 10=Debug are the same because 0 (NOTSET) doesn't show everything.
     if level <= 10:
         LOGGER.setLevel(logging.DEBUG)
     elif level == 20:
         LOGGER.setLevel(logging.INFO)
     elif level == 30:
         LOGGER.setLevel(logging.WARNING)
     elif level == 40:
         LOGGER.setLevel(logging.ERROR)
     elif level == 50:
         LOGGER.setLevel(logging.CRITICAL)
     else:
         LOGGER.debug("set_debug_level: Unknown level {}".format(level))
     # this is the best way to control logging for modules, so you can
     # still see warnings and errors
     #if level < 10:
     #    self.set_module_logs(logging.DEBUG)
     #else:
     #    # Just warnigns for the modules unless in module debug mode
     #    self.set_module_logs(logging.WARNING)
     # Or you can do this and you will never see mention of module logging
     if level < 10:
         LOG_HANDLER.set_basic_config(True, logging.DEBUG)
     else:
         # This is the polyinterface default
         LOG_HANDLER.set_basic_config(True, logging.WARNING)
예제 #19
0
 def _startRefresh(self,test=False):
     # See if someone else already refreshed it?  Very small chance of this happening on PGC, but it could.
     if 'tokenData' in self.polyConfig['customData']:
         if 'refresh_token' in self.polyConfig['customData']['tokenData']:
             LOGGER.debug("{}= {}".format(self._data_tag,self.polyConfig['customData'][self._data_tag]))
             LOGGER.debug("_last_dtns={}".format(self._last_dtns))
             if self._last_dtns is not False:
                 # Check that it was ours
                 if not self._last_dtns == self.polyConfig['customData'][self._data_tag]:
                     LOGGER.error("Someone changed the db?")
                     LOGGER.error("{}= {}".format(self._data_tag,self.polyConfig['customData'][self._data_tag]))
                     LOGGER.error("_last_dtns={}".format(self._last_dtns))
                     try:
                         l_dt = datetime.fromtimestamp(self._last_dtns).strftime(self._lock_fmt)
                         c_dt = datetime.fromtimestamp(self.polyConfig['customData'][self._data_tag]).strftime(self._lock_fmt)
                         if c_dt < l_dt:
                             LOGGER.error("But it is older than what we wrote, so will ignore it...")
                         else:
                             LOGGER.error("And it's newer than what we wrote so will use it?")
                             LOGGER.error(" Mine:    {}".format(self.tokenData))
                             LOGGER.error(" Current: {}".format(self.polyConfig['customData']['tokenData']))
                             LOGGER.error("We will use the new tokens...")
                             self.tokenData = deepcopy(self.polyConfig['customData']['tokenData'])
                             return False
                     except:
                         LOGGER.error("Failed determing age of last db write by someone else, will ignore it.",exc_info=True)
     rval = self.lockCustomData()
     if (rval):
         self.refreshingTokens = True
     return rval
예제 #20
0
 def set_driver(self, mdrv, val, default=0, force=False, report=True):
     #LOGGER.debug(f'{self.lpfx} {mdrv},{val} default={default} force={force},report={report}')
     if val is None:
         # Restore from DB for existing nodes
         try:
             val = self.getDriver(mdrv)
             LOGGER.info(f'{self.lpfx} {val}')
         except:
             LOGGER.warning(
                 f'{self.lpfx} getDriver({mdrv}) failed which can happen on new nodes, using {default}'
             )
     val = default if val is None else int(val)
     try:
         if not mdrv in self.__my_drivers or val != self.__my_drivers[
                 mdrv] or force:
             self.setDriver(mdrv, val, report=report)
             info = ''
             if self.id in NODE_DEF_MAP and mdrv in NODE_DEF_MAP[self.id]:
                 info += f"'{NODE_DEF_MAP[self.id][mdrv]['name']}' = "
                 info += f"'{NODE_DEF_MAP[self.id][mdrv]['keys'][val]}'" if val in NODE_DEF_MAP[
                     self.id][mdrv]['keys'] else "'NOT IN NODE_DEF_MAP'"
             self.__my_drivers[mdrv] = val
             LOGGER.debug(f'{self.lpfx} set_driver({mdrv},{val}) {info}')
         #else:
         #    LOGGER.debug(f'{self.lpfx} not necessary')
     except:
         LOGGER.error(f'{self.lpfx} set_driver({mdrv},{val}) failed')
         return None
     return val
예제 #21
0
 def get_listen(self):
     LOGGER.debug('')
     val = self.getDriver('GV2')
     if val is None:
         val = 1
     LOGGER.debug(val)
     return int(val)
예제 #22
0
 def set_physical_status(self, val=None, force=False, reportCmd=True):
     LOGGER.debug(f'{self.lpfx} val={val}')
     if val is None:
         val = self.elk.physical_status
     else:
         val = int(val)
     self._set_physical_status(val, force=force, reportCmd=reportCmd)
예제 #23
0
 def add_saved(self):
     LOGGER.info('{self.lpfx}: Adding saved cameras...')
     for cam in self.controller.get_saved_cameras(self):
         LOGGER.debug(
             f"{self.lpfx}: Adding cam {cam['node_address']} {cam['name']}")
         self.cams_by_id[cam['id']] = self.controller.addNode(
             Camera(self.controller, self, cam['node_address'], cam))
예제 #24
0
 def _shortPoll(self):
     while (True):
         self.short_event.wait()
         LOGGER.debug('start')
         for an in self._area_nodes:
             self._area_nodes[an].shortPoll()
         self.short_event.clear()
         LOGGER.debug('done')
예제 #25
0
 def heartbeat(self):
     LOGGER.debug(f"{self.lpfx} hb={self.hb}")
     if self.hb == 0:
         self.reportCmd("DON", 2)
         self.hb = 1
     else:
         self.reportCmd("DOF", 2)
         self.hb = 0
예제 #26
0
 def stop(self):
     LOGGER.debug(f"{self.lpfx} NodeServer stopping...")
     if self.elk is not None:
         self.elk.disconnect()
     if self.elk_thread is not None:
         # Wait for actual termination (if needed)
         self.elk_thread.join()
     LOGGER.debug(f"{self.lpfx} NodeServer stopping complete...")
예제 #27
0
 def _longPoll(self):
     while (True):
         self.long_event.wait()
         LOGGER.debug('start')
         self.heartbeat()
         self.check_connection()
         self.long_event.clear()
         LOGGER.debug('done')
예제 #28
0
 def update_status(self,cam):
     """
     Given a cam dict from the Camcect API update all our drivers
     """
     LOGGER.debug(f"{self.lpfx}: disabled={cam['disabled']} is_alert_disabled={cam['is_alert_disabled']} is_streaming={cam['is_streaming']}")
     self.set_driver('ST',0   if cam['disabled']           else 1)
     self.set_driver('MODE',0 if cam['is_alert_disabled']  else 1)
     self.set_driver('GPV', 1 if cam['is_streaming']       else 0)
예제 #29
0
 def execute_command(self, command):
     LOGGER.debug('executing %s', command)
     try:
         self.deviceDriver.executeCommand(command['cmd'],
                                          command.get('value'))
         self.refresh_state()
     except:
         LOGGER.exception('Error sending command to ' + self.name)
예제 #30
0
 def heartbeat(self):
     LOGGER.debug('heartbeat hb={}'.format(self.hb))
     if self.hb == 0:
         self.reportCmd("DON",2)
         self.hb = 1
     else:
         self.reportCmd("DOF",2)
         self.hb = 0