def test_search_oh(): item1 = OpenhabItem('oh_item_1', tags=frozenset(['tag1', 'tag2', 'tag3']), groups=frozenset(['grp1', 'grp2']), metadata={'meta1': MetaData('meta_v1')}) item2 = SwitchItem('oh_item_2', tags=frozenset(['tag1', 'tag2', 'tag4']), groups=frozenset(['grp2', 'grp3']), metadata={'meta2': MetaData('meta_v2', config={'a': 'b'})}) item3 = Item('item_2') assert Rule.get_items() == [] Items.add_item(item1) Items.add_item(item2) Items.add_item(item3) assert Rule.get_items() == [item1, item2, item3] assert Rule.get_items(tags='tag2') == [item1, item2] assert Rule.get_items(tags='tag4') == [item2] assert Rule.get_items(groups='grp1') == [item1] assert Rule.get_items(groups='grp2') == [item1, item2] assert Rule.get_items(groups='grp1', tags='tag1') == [item1] assert Rule.get_items(groups='grp2', tags='tag4') == [item2] assert Rule.get_items(metadata='meta1') == [item1] assert Rule.get_items(metadata='meta2') == [item2] assert Rule.get_items(metadata=r'meta\d') == [item1, item2] assert Rule.get_items(metadata_value='meta_v1') == [item1] assert Rule.get_items(metadata_value='meta_v2') == [item2] assert Rule.get_items(metadata_value=r'meta_v\d') == [item1, item2] assert Rule.get_items(groups='grp1', metadata_value=r'meta_v\d') == [item1]
def test_group_update(self): item1 = SwitchItem.get_item(self.item1.name) item2 = SwitchItem.get_item(self.item2.name) group = GroupItem.get_item(self.group.name) with ItemWaiter(group) as waiter: waiter.wait_for_state(None) item1.oh_post_update('ON') waiter.wait_for_state('ON') item1.oh_post_update('OFF') waiter.wait_for_state('OFF') item2.oh_post_update('ON') waiter.wait_for_state('ON')
def item_state_change(self, event): assert isinstance(event, ValueChangeEvent) print( f'{event}') # interaction is available through self.openhab or self.oh self.openhab.send_command('TestItemCommand', 'ON') # example for interaction with openhab item type switch_item = SwitchItem.get_item('TestSwitch') if switch_item.is_on(): switch_item.off()
def __init__(self): super().__init__() # get items test_contact = ContactItem.get_item('TestContact') test_date_time = DatetimeItem.get_item('TestDateTime') test_switch = SwitchItem.get_item('TestSwitch') # Trigger on item updates test_contact.listen_event(self.item_state_update, ItemStateEvent) test_date_time.listen_event(self.item_state_update, ValueUpdateEvent) # Trigger on item changes test_contact.listen_event(self.item_state_change, ItemStateChangedEvent) test_date_time.listen_event(self.item_state_change, ValueChangeEvent) # Trigger on item commands test_switch.listen_event(self.item_command, ItemCommandEvent)
def map_items(name, openhab_type: str, openhab_value: str): assert isinstance(openhab_type, str), type(openhab_type) assert isinstance(openhab_value, str), type(openhab_value) value: typing.Optional[str] = openhab_value if openhab_value == 'NULL' or openhab_value == 'UNDEF': value = None # Quantity types are like this: Number:Temperature and have a unit set: "12.3 °C". # We have to remove the dimension from the type and remove the unit from the value if ':' in openhab_type: openhab_type = openhab_type[:openhab_type.find(':')] # if the item is not initialized its None and has no dimension if value is not None: value, _ = QuantityValue.split_unit(value) # Specific classes if openhab_type == "Switch": return SwitchItem(name, value) if openhab_type == "String": return StringItem(name, value) if openhab_type == "Contact": return ContactItem(name, value) if openhab_type == "Rollershutter": if value is None: return RollershutterItem(name, value) return RollershutterItem(name, float(value)) if openhab_type == "Dimmer": return DimmerItem(name, value) if openhab_type == "Number": if value is None: return NumberItem(name, value) # Number items can be int or float try: return NumberItem(name, int(value)) except ValueError: return NumberItem(name, float(value)) if openhab_type == "DateTime": if value is None: return DatetimeItem(name, value) dt = datetime.datetime.strptime(value.replace('+', '000+'), '%Y-%m-%dT%H:%M:%S.%f%z') # all datetimes from openhab have a timezone set so we can't easily compare them # --> TypeError: can't compare offset-naive and offset-aware datetimes dt = dt.astimezone( tz=None) # Changes datetime object so it uses system timezone dt = dt.replace(tzinfo=None) # Removes timezone awareness return DatetimeItem(name, dt) if openhab_type == "Color": if value is None: return ColorItem(name) return ColorItem(name, *(float(k) for k in value.split(','))) if openhab_type == "Location": return LocationItem(name, value) if openhab_type == "Player": return PlayerItem(name, value) if openhab_type == "Group": return GroupItem(name, value) if openhab_type == "Image": img = ImageItem(name) if value is None: return img img.set_value(RawValue(value)) return img raise ValueError(f'Unknown Openhab type: {openhab_type}')
def map_item(name: str, type: str, value: Optional[str], tags: FrozenSet[str], groups: FrozenSet[str], metadata: Optional[Dict[str, Dict[str, Any]]]) -> \ Optional['HABApp.openhab.items.OpenhabItem']: try: assert isinstance(type, str) assert value is None or isinstance(value, str) if value == 'NULL' or value == 'UNDEF': value = None # map Metadata if metadata is not None: meta = Map({k: MetaData(v['value'], Map(v.get('config', {}))) for k, v in metadata.items()}) else: meta = Map() # Quantity types are like this: Number:Temperature and have a unit set: "12.3 °C". # We have to remove the dimension from the type and remove the unit from the value if ':' in type: type, dimension = type.split(':') # if the item is not initialized its None and has no dimension if value is not None: value, _ = QuantityValue.split_unit(value) # Specific classes if type == "Switch": return SwitchItem(name, value, tags=tags, groups=groups, metadata=meta) if type == "String": return StringItem(name, value, tags=tags, groups=groups, metadata=meta) if type == "Contact": return ContactItem(name, value, tags=tags, groups=groups, metadata=meta) if type == "Rollershutter": if value is None: return RollershutterItem(name, value, tags=tags, groups=groups, metadata=meta) return RollershutterItem(name, float(value), tags=tags, groups=groups, metadata=meta) if type == "Dimmer": if value is None: return DimmerItem(name, value, tags=tags, groups=groups, metadata=meta) return DimmerItem(name, float(value), tags=tags, groups=groups, metadata=meta) if type == "Number": if value is None: return NumberItem(name, value, tags=tags, groups=groups, metadata=meta) # Number items can be int or float try: return NumberItem(name, int(value), tags=tags, groups=groups, metadata=meta) except ValueError: return NumberItem(name, float(value), tags=tags, groups=groups, metadata=meta) if type == "DateTime": if value is None: return DatetimeItem(name, value, tags=tags, groups=groups, metadata=meta) # Todo: remove this once we go >= OH3.1 # Previous OH versions used a datetime string like this: # 2018-11-19T09:47:38.284+0100 # OH 3.1 uses # 2021-04-10T22:00:43.043996+0200 if len(value) == 28: value = value.replace('+', '000+') dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f%z') # all datetimes from openhab have a timezone set so we can't easily compare them # --> TypeError: can't compare offset-naive and offset-aware datetimes dt = dt.astimezone(tz=None) # Changes datetime object so it uses system timezone dt = dt.replace(tzinfo=None) # Removes timezone awareness return DatetimeItem(name, dt, tags=tags, groups=groups, metadata=meta) if type == "Color": if value is None: return ColorItem(name, tags=tags, groups=groups, metadata=meta) return ColorItem(name, *(float(k) for k in value.split(',')), tags=tags, groups=groups, metadata=meta) if type == "Image": img = ImageItem(name, tags=tags, groups=groups, metadata=meta) if value is None: return img img.set_value(RawValue(value)) return img if type == "Group": return GroupItem(name, value, tags=tags, groups=groups, metadata=meta) if type == "Location": return LocationItem(name, value, tags=tags, groups=groups, metadata=meta) if type == "Player": return PlayerItem(name, value, tags=tags, groups=groups, metadata=meta) raise ValueError(f'Unknown Openhab type: {type} for {name}') except Exception as e: process_exception('map_items', e, logger=log) return None