async def async_get_things() -> Optional[List[Dict[str, Any]]]: try: resp = await get('things') return load_json(await resp.text(encoding='utf-8')) except Exception as e: # sometimes uuid and items already works but things not - so we ignore these errors here, too if not isinstance(e, (OpenhabDisconnectedError, OpenhabNotReadyYet)): for line in traceback.format_exc().splitlines(): log.error(line) return None
async def async_get_items(include_habapp_meta=False) -> Optional[List[Dict[str, Any]]]: params = None if include_habapp_meta: params = {'metadata': 'HABApp'} try: resp = await get('items', params=params) return load_json(await resp.text(encoding='utf-8')) except Exception as e: # sometimes uuid already works but items not - so we ignore these errors here, too if not isinstance(e, (OpenhabDisconnectedError, OpenhabNotReadyYet)): for line in traceback.format_exc().splitlines(): log.error(line) return None
async def start_sse_event_listener(): try: # cache so we don't have to look up every event call = ON_SSE_EVENT options = {} if HABApp.CONFIG.openhab.connection.user or HABApp.CONFIG.openhab.connection.password: options['with_credentials'] = True event_prefix = 'openhab' if not IS_OH2 else 'smarthome' async with sse_client.EventSource( url=f'{HTTP_PREFIX}/rest/events?topics=' f'{event_prefix}/items/,' # Item updates f'{event_prefix}/channels/,' # Channel update f'{event_prefix}/things/*/status,' # Thing status updates f'{event_prefix}/things/*/statuschanged' # Thing status changes , option=options, session=HTTP_SESSION) as event_source: async for event in event_source: try: event = load_json(event.data) except ValueError: continue except TypeError: continue # Log sse event if log_events.isEnabledFor(logging.DEBUG): log_events._log(logging.DEBUG, event, []) # process call(event) except asyncio.CancelledError: # This exception gets raised if we cancel the coroutine # since this is normal behaviour we ignore this exception pass except Exception as e: disconnect = is_disconnect_exception(e) lvl = logging.WARNING if disconnect else logging.ERROR log.log(lvl, f'SSE request Error: {e}') for line in traceback.format_exc().splitlines(): log.log(lvl, line) # reconnect even if we have an unexpected error if not disconnect: set_offline(f'Uncaught error in process_sse_events: {e}')
def get_event(_in_dict: dict) -> OpenhabEvent: event_type: str = _in_dict['type'] topic: str = _in_dict['topic'] # Workaround for None values in the payload str p_str: str = _in_dict['payload'] if '"NONE"' in p_str: p_str = p_str.replace('"NONE"', 'null') payload = load_json(p_str) # Find event from implemented events try: return __event_lookup[event_type].from_dict(topic, payload) except KeyError: raise ValueError(f'Unknown Event: {event_type:s} for {_in_dict}')
def get_msg_payload(msg: MQTTMessage) -> Tuple[Optional[str], Any]: try: topic = msg._topic.decode('utf-8') raw = msg.payload try: val = raw.decode("utf-8") except UnicodeDecodeError: # Payload ist a byte stream if log.isEnabledFor(logging.DEBUG): log._log(logging.DEBUG, f'{topic} ({msg.qos}): {raw[:20]}...', []) return topic, raw if log.isEnabledFor(logging.DEBUG): log._log(logging.DEBUG, f'{topic} ({msg.qos}): {val}', []) # None if val == 'none' or val == 'None': return topic, None # bool if val == 'true' or val == 'True': return topic, True if val == 'false' or val == 'False': return topic, False # int if val.isdecimal(): return topic, int(val) # json list/dict if val.startswith('{') and val.endswith('}') or val.startswith('[') and val.endswith(']'): try: return topic, load_json(val) except ValueError: return topic, val # float or str try: return topic, float(val) except ValueError: return topic, val except Exception as e: process_exception('get_msg_payload', e, logger=log) return None, None
async def start_sse_event_listener(): try: # cache so we don't have to look up every event call = ON_SSE_EVENT async with sse_client.EventSource( url=f'{HTTP_PREFIX}/rest/' "events?topics=smarthome/items/," # Item updates "smarthome/channels/," # Channel update "smarthome/things/*/status," # Thing status updates "smarthome/things/*/statuschanged" # Thing status changes , session=HTTP_SESSION) as event_source: async for event in event_source: try: event = load_json(event.data) except ValueError: continue except TypeError: continue # Log sse event if log_events.isEnabledFor(logging.DEBUG): log_events._log(logging.DEBUG, event, []) # process call(event) except asyncio.CancelledError: # This exception gets raised if we cancel the coroutine # since this is normal behaviour we ignore this exception pass except Exception as e: disconnect = is_disconnect_exception(e) lvl = logging.WARNING if disconnect else logging.ERROR log.log(lvl, f'SSE request Error: {e}') for line in traceback.format_exc().splitlines(): log.log(lvl, line) # reconnect even if we have an unexpected error if not disconnect: set_offline(f'Uncaught error in process_sse_events: {e}')