async def on_connect_function(self):
        data = await async_get_items(disconnect_on_error=True,
                                     all_metadata=True)
        if data is None:
            return None

        fresh_item_sync()

        found_items = len(data)
        for _dict in data:
            item_name = _dict['name']
            new_item = map_item(
                item_name, _dict['type'], _dict['state'],
                frozenset(_dict['tags']), frozenset(_dict['groupNames']),
                _dict.get('metadata',
                          {}))  # type: HABApp.openhab.items.OpenhabItem
            if new_item is None:
                continue
            add_to_registry(new_item, True)

        # remove items which are no longer available
        ist = set(Items.get_all_item_names())
        soll = {k['name'] for k in data}
        for k in ist - soll:
            if isinstance(Items.get_item(k), HABApp.openhab.items.OpenhabItem):
                Items.pop_item(k)

        log.info(f'Updated {found_items:d} Items')

        # try to update things, too
        data = await async_get_things(disconnect_on_error=True)
        if data is None:
            return None

        Thing = HABApp.openhab.items.Thing
        for t_dict in data:
            name = t_dict['UID']
            try:
                thing = Items.get_item(name)
                if not isinstance(thing, Thing):
                    log.warning(
                        f'Item {name} has the wrong type ({type(thing)}), expected Thing'
                    )
                    thing = Thing(name)
            except Items.ItemNotFoundException:
                thing = Thing(name)

            thing.status = t_dict['statusInfo']['status']
            Items.add_item(thing)

        # remove things which were deleted
        ist = set(Items.get_all_item_names())
        soll = {k['UID'] for k in data}
        for k in ist - soll:
            if isinstance(Items.get_item(k), Thing):
                Items.pop_item(k)

        log.info(f'Updated {len(data):d} Things')
        return None
def on_sse_event(event_dict: dict):
    try:
        # Lookup corresponding OpenHAB event
        event = get_event(event_dict)

        # Update item in registry BEFORE posting to the event bus
        # so the items have the correct state when we process the event in a rule
        try:
            if isinstance(event, ValueUpdateEvent):
                __item = Items.get_item(
                    event.name
                )  # type: HABApp.core.items.base_item.BaseValueItem
                __item.set_value(event.value)
                EventBus.post_event(event.name, event)
                return None

            if isinstance(event, ThingStatusInfoEvent):
                __thing = Items.get_item(
                    event.name)  # type: HABApp.openhab.items.Thing
                __thing.process_event(event)
                EventBus.post_event(event.name, event)
                return None

            # Workaround because there is no GroupItemStateEvent
            if isinstance(event, GroupItemStateChangedEvent):
                __item = Items.get_item(
                    event.name)  # type: HABApp.openhab.items.GroupItem
                __item.set_value(event.value)
                EventBus.post_event(event.name, event)
                return None
        except ItemNotFoundException:
            log_warning(
                log,
                f'Received {event.__class__.__name__} for {event.name} but item does not exist!'
            )

            # Post the event anyway
            EventBus.post_event(event.name, event)
            return None

        if isinstance(event, ItemRemovedEvent):
            remove_from_registry(event.name)
            EventBus.post_event(event.name, event)
            return None

        # These events require that we query openhab because of the metadata so we have to do it in a task
        # They also change the item registry
        if isinstance(event, (ItemAddedEvent, ItemUpdatedEvent)):
            create_task(item_event(event))
            return None

        HABApp.core.EventBus.post_event(event.name, event)
    except Exception as e:
        process_exception(func=on_sse_event, e=e)
        return None
Exemple #3
0
def on_sse_event(event_dict: dict):

    # Lookup corresponding OpenHAB event
    event = get_event(event_dict)

    # Update item in registry BEFORE posting to the event bus
    # so the items have the correct state when we process the event in a rule
    try:
        if isinstance(event, HABApp.core.events.ValueUpdateEvent):
            __item = Items.get_item(
                event.name)  # type: HABApp.core.items.base_item.BaseValueItem
            __item.set_value(event.value)
            HABApp.core.EventBus.post_event(event.name, event)
            return None
        elif isinstance(event, HABApp.openhab.events.ThingStatusInfoEvent):
            __thing = Items.get_item(
                event.name)  # type: HABApp.openhab.items.Thing
            __thing.process_event(event)
            HABApp.core.EventBus.post_event(event.name, event)
            return None
    except HABApp.core.Items.ItemNotFoundException:
        pass

    # Events which change the ItemRegistry
    if isinstance(event, (HABApp.openhab.events.ItemAddedEvent,
                          HABApp.openhab.events.ItemUpdatedEvent)):
        item = map_item(event.name, event.type, 'NULL')
        if item is None:
            return None

        # check already existing item so we can print a warning if something changes
        try:
            existing_item = Items.get_item(item.name)
            if isinstance(existing_item, item.__class__):
                # it's the same item class so we don't replace it!
                item = existing_item
            else:
                log.warning(
                    f'Item changed type from {existing_item.__class__} to {item.__class__}'
                )
        except Items.ItemNotFoundException:
            pass

        # always overwrite with new definition
        Items.set_item(item)

    elif isinstance(event, HABApp.openhab.events.ItemRemovedEvent):
        Items.pop_item(event.name)

    # Send Event to Event Bus
    HABApp.core.EventBus.post_event(event.name, event)
    return None
    def get_create_item(cls,
                        name: str,
                        write_topic: Optional[str] = None,
                        initial_value=None) -> 'MqttPairItem':
        """Creates a new item in HABApp and returns it or returns the already existing one with the given name.
        HABApp tries to automatically derive the write topic from the item name. In cases where this does not
        work it can be specified manually.

        :param name: item name (topic that reports the state)
        :param write_topic: topic that is used to write values or ``None`` (default) to build it automatically
        :param initial_value: state the item will have if it gets created
        :return: item
        """
        assert isinstance(name, str), type(name)

        # try to build write topic
        if write_topic is None:
            write_topic = build_write_topic(name)

        try:
            item = Items.get_item(name)
        except Items.ItemNotFoundException:
            item = cls(name,
                       write_topic=write_topic,
                       initial_value=initial_value)
            Items.add_item(item)

        assert isinstance(item, cls), f'{cls} != {type(item)}'
        return item
Exemple #5
0
def process_msg(client, userdata, message: mqtt.MQTTMessage):

    topic, payload = get_msg_payload(message)
    if topic is None:
        return None

    _item = None  # type: typing.Optional[HABApp.mqtt.items.MqttBaseItem]
    try:
        _item = Items.get_item(topic)  # type: HABApp.mqtt.items.MqttBaseItem
    except HABApp.core.Items.ItemNotFoundException:
        # only create items for if the message has the retain flag
        if message.retain:
            _item = Items.create_item(
                topic,
                HABApp.mqtt.items.MqttItem)  # type: HABApp.mqtt.items.MqttItem

    # we don't have an item -> we process only the event
    if _item is None:
        HABApp.core.EventBus.post_event(topic,
                                        MqttValueUpdateEvent(topic, payload))
        return None

    # Remember state and update item before doing callbacks
    _old_state = _item.value
    _item.set_value(payload)

    # Post events
    HABApp.core.EventBus.post_event(topic,
                                    MqttValueUpdateEvent(topic, payload))
    if _old_state != payload:
        HABApp.core.EventBus.post_event(
            topic, MqttValueChangeEvent(topic, payload, _old_state))
def add_to_registry(item: 'HABApp.openhab.items.OpenhabItem', set_value=False):
    name = item.name
    for grp in item.groups:
        MEMBERS.setdefault(grp, set()).add(name)

    if not Items.item_exists(name):
        return Items.add_item(item)

    existing = Items.get_item(name)
    if isinstance(existing, item.__class__):
        # If we load directly through the API and not through an event we have to set the value
        if set_value:
            existing.set_value(item.value)

        # remove old groups
        for grp in set(existing.groups) - set(item.groups):
            MEMBERS.get(grp, set()).discard(name)

        # same type - it was only an item update (e.g. label)!
        existing.tags = item.tags
        existing.groups = item.groups
        return None

    log_warning(
        log,
        f'Item type changed from {existing.__class__} to {item.__class__}')

    # Replace existing item with the updated definition
    Items.pop_item(name)
    Items.add_item(item)
Exemple #7
0
    def check(self, now):
        if self.is_canceled:
            return None

        try:
            item = Items.get_item(self.name)
        except Items.ItemNotFoundException:
            return None

        timestamp = item._last_change if self.__watch_only_changes else item._last_update
        duration = now - timestamp
        if duration < self.duration_const:
            self.executed = False
            return None

        if self.executed:
            return None

        EventBus.post_event(
            self.name,
            (ValueNoChangeEvent if self.__watch_only_changes else ValueNoUpdateEvent)(
                self.name, item.value, int(duration.total_seconds())
            )
        )
        self.executed = True
Exemple #8
0
def test_retain_create():
    topic = '/test/creation'

    assert not Items.item_exists(topic)
    process_msg(None, None, MqttDummyMsg(topic, 'aaa', retain=False))
    assert not Items.item_exists(topic)

    # Retain True will create the item
    process_msg(None, None, MqttDummyMsg(topic, 'adsf123', retain=True))
    assert Items.item_exists(topic)
    assert Items.get_item(topic).value == 'adsf123'

    Items.pop_item(topic)
def remove_from_registry(name: str):
    if not Items.item_exists(name):
        return None

    item = Items.get_item(name)  # type: HABApp.openhab.items.OpenhabItem
    for grp in item.groups:
        MEMBERS.get(grp, set()).discard(name)

    if isinstance(item, HABApp.openhab.items.GroupItem):
        MEMBERS.pop(name, None)

    Items.pop_item(name)
    return None
    def test_item(self):

        NAME = 'test'
        created_item = Item(NAME)
        Items.add_item(created_item)

        self.assertTrue(Items.item_exists(NAME))
        self.assertIs(created_item, Items.get_item(NAME))

        self.assertEqual(Items.get_all_item_names(), [NAME])
        self.assertEqual(Items.get_all_items(), [created_item])

        self.assertIs(created_item, Items.pop_item(NAME))
        self.assertEqual(Items.get_all_items(), [])
Exemple #11
0
    def get_create_item(cls, name: str, initial_value=None) -> 'MqttItem':
        """Creates a new item in HABApp and returns it or returns the already existing one with the given name

        :param name: item name
        :param initial_value: state the item will have if it gets created
        :return: item
        """
        assert isinstance(name, str), type(name)

        try:
            item = Items.get_item(name)
        except Items.ItemNotFoundException:
            item = cls(name, initial_value)
            Items.add_item(item)

        assert isinstance(item, cls), f'{cls} != {type(item)}'
        return item
    async def on_connect_function(self):
        data = await async_get_items()
        if data is None:
            return None

        found_items = len(data)
        for _dict in data:
            item_name = _dict['name']
            new_item = map_item(item_name, _dict['type'], _dict['state'])
            if new_item is None:
                continue

            try:
                # if the item already exists and it has the correct type just update its state
                # Since we load the items before we load the rules this should actually never happen
                existing_item = Items.get_item(
                    item_name)  # type: HABApp.core.items.BaseValueItem
                if isinstance(existing_item, new_item.__class__):
                    existing_item.set_value(
                        new_item.value
                    )  # use the converted state from the new item here
                    new_item = existing_item
            except Items.ItemNotFoundException:
                pass

            # create new item or change item type
            Items.set_item(new_item)

        # remove items which are no longer available
        ist = set(Items.get_all_item_names())
        soll = {k['name'] for k in data}
        for k in ist - soll:
            if isinstance(Items.get_item(k), HABApp.openhab.items.OpenhabItem):
                Items.pop_item(k)

        log.info(f'Updated {found_items:d} Items')

        # try to update things, too
        data = await async_get_things()
        if data is None:
            return None

        Thing = HABApp.openhab.items.Thing
        for t_dict in data:
            name = t_dict['UID']
            try:
                thing = HABApp.core.Items.get_item(name)
                if not isinstance(thing, Thing):
                    log.warning(
                        f'Item {name} has the wrong type ({type(thing)}), expected Thing'
                    )
                    thing = Thing(name)
            except HABApp.core.Items.ItemNotFoundException:
                thing = Thing(name)

            thing.status = t_dict['statusInfo']['status']
            HABApp.core.Items.set_item(thing)

        # remove things which were deleted
        ist = set(HABApp.core.Items.get_all_item_names())
        soll = {k['UID'] for k in data}
        for k in ist - soll:
            if isinstance(HABApp.core.Items.get_item(k), Thing):
                HABApp.core.Items.pop_item(k)

        log.info(f'Updated {len(data):d} Things')
        return None
def get_members(
        group_name: str) -> Tuple['HABApp.openhab.items.OpenhabItem', ...]:
    ret = []
    for name in MEMBERS.get(group_name, []):
        ret.append(Items.get_item(name))
    return tuple(sorted(ret))