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()
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()
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()
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)
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)
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
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)
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)
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)
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>")
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')
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])
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
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
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")
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)
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
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
def get_listen(self): LOGGER.debug('') val = self.getDriver('GV2') if val is None: val = 1 LOGGER.debug(val) return int(val)
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)
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))
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')
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
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...")
def _longPoll(self): while (True): self.long_event.wait() LOGGER.debug('start') self.heartbeat() self.check_connection() self.long_event.clear() LOGGER.debug('done')
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)
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)
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