示例#1
0
async def test_homekit_too_many_accessories(opp, hk_driver, caplog,
                                            mock_zeroconf):
    """Test adding too many accessories to HomeKit."""
    entry = await async_init_integration(opp)

    entity_filter = generate_filter(["cover", "light"], ["demo.test"], [], [])

    homekit = _mock_homekit(opp, entry, HOMEKIT_MODE_BRIDGE, entity_filter)

    def _mock_bridge(*_):
        mock_bridge = HomeBridge(opp, hk_driver, "mock_bridge")
        # The bridge itself counts as an accessory
        mock_bridge.accessories = range(MAX_DEVICES)
        return mock_bridge

    homekit.driver = hk_driver
    homekit.driver.accessory = Accessory(hk_driver, "any")

    opp.states.async_set("light.demo", "on")
    opp.states.async_set("light.demo2", "on")
    opp.states.async_set("light.demo3", "on")

    with patch("pyhap.accessory_driver.AccessoryDriver.async_start"), patch(
            f"{PATH_HOMEKIT}.show_setup_message"), patch(
                f"{PATH_HOMEKIT}.HomeBridge", _mock_bridge):
        await homekit.async_start()
        await opp.async_block_till_done()
        assert "would exceed" in caplog.text
示例#2
0
    def __init__(
        self,
        opp: OpenPeerPower,
        keep_days: int,
        purge_interval: int,
        uri: str,
        include: Dict,
        exclude: Dict,
    ) -> None:
        """Initialize the recorder."""
        threading.Thread.__init__(self, name="Recorder")

        self.opp = opp
        self.keep_days = keep_days
        self.purge_interval = purge_interval
        self.queue: Any = queue.Queue()
        self.recording_start = dt_util.utcnow()
        self.db_url = uri
        self.async_db_ready = asyncio.Future()
        self.engine: Any = None
        self.run_info: Any = None

        self.entity_filter = generate_filter(
            include.get(CONF_DOMAINS, []),
            include.get(CONF_ENTITIES, []),
            exclude.get(CONF_DOMAINS, []),
            exclude.get(CONF_ENTITIES, []),
        )
        self.exclude_t = exclude.get(CONF_EVENT_TYPES, [])

        self.get_session = None
示例#3
0
def test_no_filters_case_1():
    """If include and exclude not included, pass everything."""
    incl_dom = {}
    incl_ent = {}
    excl_dom = {}
    excl_ent = {}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent)

    for value in ("sensor.test", "sun.sun", "light.test"):
        assert testfilter(value)
示例#4
0
def test_excludes_only_case_3():
    """If exclude specified, pass all but specified (Case 3)."""
    incl_dom = {}
    incl_ent = {}
    excl_dom = {"light", "sensor"}
    excl_ent = {"binary_sensor.working"}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent)

    assert testfilter("sensor.test") is False
    assert testfilter("light.test") is False
    assert testfilter("binary_sensor.working") is False
    assert testfilter("binary_sensor.another")
    assert testfilter("sun.sun") is True
示例#5
0
def test_includes_only_case_2():
    """If include specified, only pass if specified (Case 2)."""
    incl_dom = {"light", "sensor"}
    incl_ent = {"binary_sensor.working"}
    excl_dom = {}
    excl_ent = {}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent)

    assert testfilter("sensor.test")
    assert testfilter("light.test")
    assert testfilter("binary_sensor.working")
    assert testfilter("binary_sensor.notworking") is False
    assert testfilter("sun.sun") is False
示例#6
0
def _mock_homekit(opp, entry, homekit_mode, entity_filter=None):
    return HomeKit(
        opp=opp,
        name=BRIDGE_NAME,
        port=DEFAULT_PORT,
        ip_address=None,
        entity_filter=entity_filter or generate_filter([], [], [], []),
        exclude_accessory_mode=False,
        entity_config={},
        homekit_mode=homekit_mode,
        advertise_ip=None,
        entry_id=entry.entry_id,
        entry_title=entry.title,
    )
示例#7
0
def test_with_include_domain_case4a():
    """Test case 4a - include and exclude specified, with included domain."""
    incl_dom = {"light", "sensor"}
    incl_ent = {"binary_sensor.working"}
    excl_dom = {}
    excl_ent = {"light.ignoreme", "sensor.notworking"}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent)

    assert testfilter("sensor.test")
    assert testfilter("sensor.notworking") is False
    assert testfilter("light.test")
    assert testfilter("light.ignoreme") is False
    assert testfilter("binary_sensor.working")
    assert testfilter("binary_sensor.another") is False
    assert testfilter("sun.sun") is False
示例#8
0
async def async_setup(opp, config):
    """Set up the MQTT state feed."""
    conf = config.get(DOMAIN, {})
    base_topic = conf.get(CONF_BASE_TOPIC)
    pub_include = conf.get(CONF_INCLUDE, {})
    pub_exclude = conf.get(CONF_EXCLUDE, {})
    publish_attributes = conf.get(CONF_PUBLISH_ATTRIBUTES)
    publish_timestamps = conf.get(CONF_PUBLISH_TIMESTAMPS)
    publish_filter = generate_filter(
        pub_include.get(CONF_DOMAINS, []),
        pub_include.get(CONF_ENTITIES, []),
        pub_exclude.get(CONF_DOMAINS, []),
        pub_exclude.get(CONF_ENTITIES, []),
    )
    if not base_topic.endswith("/"):
        base_topic = base_topic + "/"

    @callback
    def _state_publisher(entity_id, old_state, new_state):
        if new_state is None:
            return

        if not publish_filter(entity_id):
            return

        payload = new_state.state

        mybase = base_topic + entity_id.replace(".", "/") + "/"
        opp.components.mqtt.async_publish(mybase + "state", payload, 1, True)

        if publish_timestamps:
            if new_state.last_updated:
                opp.components.mqtt.async_publish(
                    mybase + "last_updated",
                    new_state.last_updated.isoformat(), 1, True)
            if new_state.last_changed:
                opp.components.mqtt.async_publish(
                    mybase + "last_changed",
                    new_state.last_changed.isoformat(), 1, True)

        if publish_attributes:
            for key, val in new_state.attributes.items():
                encoded_val = json.dumps(val, cls=JSONEncoder)
                opp.components.mqtt.async_publish(mybase + key, encoded_val, 1,
                                                  True)

    async_track_state_change(opp, MATCH_ALL, _state_publisher)
    return True
示例#9
0
def _generate_filter_from_config(config):
    excluded_entities = []
    excluded_domains = []
    included_entities = []
    included_domains = []

    exclude = config.get(CONF_EXCLUDE)
    if exclude:
        excluded_entities = exclude.get(CONF_ENTITIES, [])
        excluded_domains = exclude.get(CONF_DOMAINS, [])
    include = config.get(CONF_INCLUDE)
    if include:
        included_entities = include.get(CONF_ENTITIES, [])
        included_domains = include.get(CONF_DOMAINS, [])

    return generate_filter(included_domains, included_entities,
                           excluded_domains, excluded_entities)
示例#10
0
async def test_homekit_entity_filter(opp, mock_zeroconf):
    """Test the entity filter."""
    entry = await async_init_integration(opp)

    entity_filter = generate_filter(["cover"], ["demo.test"], [], [])
    homekit = _mock_homekit(opp, entry, HOMEKIT_MODE_BRIDGE, entity_filter)

    homekit.bridge = Mock()
    homekit.bridge.accessories = {}
    opp.states.async_set("cover.test", "open")
    opp.states.async_set("demo.test", "on")
    opp.states.async_set("light.demo", "on")

    filtered_states = await homekit.async_configure_accessories()
    assert opp.states.get("cover.test") in filtered_states
    assert opp.states.get("demo.test") in filtered_states
    assert opp.states.get("light.demo") not in filtered_states
示例#11
0
def test_excludes_only_with_glob_case_3():
    """If exclude specified, pass all but specified (Case 3)."""
    incl_dom = {}
    incl_glob = {}
    incl_ent = {}
    excl_dom = {"light", "sensor"}
    excl_glob = {"cover.*_window"}
    excl_ent = {"binary_sensor.working"}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent,
                                 incl_glob, excl_glob)

    assert testfilter("sensor.test") is False
    assert testfilter("light.test") is False
    assert testfilter("cover.bedroom_window") is False
    assert testfilter("binary_sensor.working") is False
    assert testfilter("binary_sensor.another")
    assert testfilter("sun.sun") is True
    assert testfilter("cover.garage_door")
示例#12
0
def test_includes_only_with_glob_case_2():
    """If include specified, only pass if specified (Case 2)."""
    incl_dom = {"light", "sensor"}
    incl_glob = {"cover.*_window"}
    incl_ent = {"binary_sensor.working"}
    excl_dom = {}
    excl_glob = {}
    excl_ent = {}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent,
                                 incl_glob, excl_glob)

    assert testfilter("sensor.test")
    assert testfilter("light.test")
    assert testfilter("cover.bedroom_window")
    assert testfilter("binary_sensor.working")
    assert testfilter("binary_sensor.notworking") is False
    assert testfilter("sun.sun") is False
    assert testfilter("cover.garage_door") is False
示例#13
0
def test_exclude_glob_case4b():
    """Test case 4b - include and exclude specified, with excluded glob."""
    incl_dom = {}
    incl_glob = {}
    incl_ent = {"binary_sensor.working"}
    excl_dom = {}
    excl_glob = {"binary_sensor.*"}
    excl_ent = {"light.ignoreme", "sensor.notworking"}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent,
                                 incl_glob, excl_glob)

    assert testfilter("sensor.test")
    assert testfilter("sensor.notworking") is False
    assert testfilter("light.test")
    assert testfilter("light.ignoreme") is False
    assert testfilter("binary_sensor.working")
    assert testfilter("binary_sensor.another") is False
    assert testfilter("sun.sun") is True
示例#14
0
def test_with_include_domain_glob_filtering_case4a():
    """Test case 4a - include and exclude specified, both have domains and globs."""
    incl_dom = {"light"}
    incl_glob = {"*working"}
    incl_ent = {}
    excl_dom = {"binary_sensor"}
    excl_glob = {"*notworking"}
    excl_ent = {"light.ignoreme"}
    testfilter = generate_filter(incl_dom, incl_ent, excl_dom, excl_ent,
                                 incl_glob, excl_glob)

    assert testfilter("sensor.working")
    assert testfilter("sensor.notworking") is False
    assert testfilter("light.test")
    assert testfilter("light.notworking") is False
    assert testfilter("light.ignoreme") is False
    assert testfilter("binary_sensor.not_working") is False
    assert testfilter("binary_sensor.another") is False
    assert testfilter("sun.sun") is False
示例#15
0
async def test_homekit_start_with_a_broken_accessory(opp, hk_driver,
                                                     mock_zeroconf):
    """Test HomeKit start method."""
    entry = MockConfigEntry(domain=DOMAIN,
                            data={
                                CONF_NAME: "mock_name",
                                CONF_PORT: 12345
                            })
    entity_filter = generate_filter(["cover", "light"], ["demo.test"], [], [])

    await async_init_entry(opp, entry)
    homekit = _mock_homekit(opp, entry, HOMEKIT_MODE_BRIDGE, entity_filter)

    homekit.bridge = Mock()
    homekit.bridge.accessories = []
    homekit.driver = hk_driver
    homekit.driver.accessory = Accessory(hk_driver, "any")

    opp.states.async_set("light.demo", "on")
    opp.states.async_set("light.broken", "on")

    with patch(f"{PATH_HOMEKIT}.get_accessory", side_effect=Exception), patch(
            f"{PATH_HOMEKIT}.show_setup_message") as mock_setup_msg, patch(
                "pyhap.accessory_driver.AccessoryDriver.async_start"
            ) as hk_driver_start:
        await homekit.async_start()

    await opp.async_block_till_done()
    mock_setup_msg.assert_called_with(opp, entry.entry_id,
                                      "Mock Title (Open Peer Power Bridge)",
                                      ANY, ANY)
    assert hk_driver_start.called
    assert homekit.status == STATUS_RUNNING

    # Test start() if already started
    hk_driver_start.reset_mock()
    await homekit.async_start()
    await opp.async_block_till_done()
    assert not hk_driver_start.called
示例#16
0
def _get_events(
    opp,
    start_day,
    end_day,
    entity_ids=None,
    filters=None,
    entities_filter=None,
    entity_matches_only=False,
    context_id=None,
):
    """Get events for a period of time."""
    assert not (entity_ids
                and context_id), "can't pass in both entity_ids and context_id"

    entity_attr_cache = EntityAttributeCache(opp)
    context_lookup = {None: None}

    def yield_events(query):
        """Yield Events that are not filtered away."""
        for row in query.yield_per(1000):
            event = LazyEventPartialState(row)
            context_lookup.setdefault(event.context_id, event)
            if event.event_type == EVENT_CALL_SERVICE:
                continue
            if event.event_type == EVENT_STATE_CHANGED or _keep_event(
                    opp, event, entities_filter):
                yield event

    if entity_ids is not None:
        entities_filter = generate_filter([], entity_ids, [], [])

    with session_scope(opp=opp) as session:
        old_state = aliased(States, name="old_state")

        if entity_ids is not None:
            query = _generate_events_query_without_states(session)
            query = _apply_event_time_filter(query, start_day, end_day)
            query = _apply_event_types_filter(
                opp, query, ALL_EVENT_TYPES_EXCEPT_STATE_CHANGED)
            if entity_matches_only:
                # When entity_matches_only is provided, contexts and events that do not
                # contain the entity_ids are not included in the logbook response.
                query = _apply_event_entity_id_matchers(query, entity_ids)

            query = query.union_all(
                _generate_states_query(session, start_day, end_day, old_state,
                                       entity_ids))
        else:
            query = _generate_events_query(session)
            query = _apply_event_time_filter(query, start_day, end_day)
            query = _apply_events_types_and_states_filter(
                opp, query,
                old_state).filter((States.last_updated == States.last_changed)
                                  | (Events.event_type != EVENT_STATE_CHANGED))
            if filters:
                query = query.filter(filters.entity_filter() | (
                    Events.event_type != EVENT_STATE_CHANGED))

            if context_id is not None:
                query = query.filter(Events.context_id == context_id)

        query = query.order_by(Events.time_fired)

        return list(
            humanify(opp, yield_events(query), entity_attr_cache,
                     context_lookup))