Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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}')
Exemple #4
0
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}')
Exemple #5
0
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
Exemple #6
0
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}')