async def test_accessory_with_hardware_revision(hass, hk_driver):
    """Test HomeAccessory class with hardware revision."""
    entity_id = "sensor.accessory"
    hass.states.async_set(entity_id, "on")
    acc = HomeAccessory(
        hass,
        hk_driver,
        "Home Accessory",
        entity_id,
        3,
        {
            ATTR_MODEL: None,
            ATTR_MANUFACTURER: None,
            ATTR_SW_VERSION: None,
            ATTR_HW_VERSION: "1.2.3",
            ATTR_INTEGRATION: None,
        },
    )
    acc.driver = hk_driver
    serv = acc.get_service(SERV_ACCESSORY_INFO)
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == "Home Assistant Sensor"
    assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == entity_id
    assert hass_version.startswith(
        serv.get_characteristic(CHAR_FIRMWARE_REVISION).value
    )
    assert serv.get_characteristic(CHAR_HARDWARE_REVISION).value == "1.2.3"
    assert isinstance(acc.to_HAP(), dict)
예제 #2
0
    def test_home_accessory(self):
        """Test HomeAccessory class."""
        hass = get_test_home_assistant()

        acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2, '')
        self.assertEqual(acc.hass, hass)
        self.assertEqual(acc.display_name, 'Home Accessory')
        self.assertEqual(acc.category, 1)  # Category.OTHER
        self.assertEqual(len(acc.services), 1)
        serv = acc.services[0]  # SERV_ACCESSORY_INFO
        self.assertEqual(
            serv.get_characteristic(CHAR_MODEL).value, 'homekit.accessory')

        hass.states.set('homekit.accessory', 'on')
        hass.block_till_done()
        acc.run()
        hass.states.set('homekit.accessory', 'off')
        hass.block_till_done()

        acc = HomeAccessory('hass', 'test_name', 'test_model', 2, '')
        self.assertEqual(acc.display_name, 'test_name')
        self.assertEqual(acc.aid, 2)
        self.assertEqual(len(acc.services), 1)
        serv = acc.services[0]  # SERV_ACCESSORY_INFO
        self.assertEqual(
            serv.get_characteristic(CHAR_MODEL).value, 'test_model')

        hass.stop()
async def test_accessory_with_missing_basic_service_info(hass, hk_driver):
    """Test HomeAccessory class."""
    entity_id = "sensor.accessory"
    hass.states.async_set(entity_id, "on")
    acc = HomeAccessory(
        hass,
        hk_driver,
        "Home Accessory",
        entity_id,
        3,
        {
            ATTR_MODEL: None,
            ATTR_MANUFACTURER: None,
            ATTR_SW_VERSION: None,
            ATTR_INTEGRATION: None,
        },
    )
    serv = acc.get_service(SERV_ACCESSORY_INFO)
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(
        CHAR_MANUFACTURER).value == "Home Assistant Sensor"
    assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == entity_id
    assert serv.get_characteristic(
        CHAR_FIRMWARE_REVISION).value == hass_version
예제 #4
0
async def test_missing_linked_battery_sensor(hass, hk_driver, caplog):
    """Test battery service with mising linked_battery_sensor."""
    entity_id = "homekit.accessory"
    linked_battery = "sensor.battery"
    hass.states.async_set(entity_id, "open")
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_SENSOR: linked_battery},
    )
    acc.update_state = lambda x: None
    assert not acc.linked_battery_sensor

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()

    assert not acc.linked_battery_sensor
    assert not hasattr(acc, "_char_battery")
    assert not hasattr(acc, "_char_low_battery")
    assert not hasattr(acc, "_char_charging")
예제 #5
0
async def test_linked_battery_charging_sensor(hass, hk_driver, caplog):
    """Test battery service with linked_battery_charging_sensor."""
    entity_id = "homekit.accessory"
    linked_battery_charging_sensor = "binary_sensor.battery_charging"
    hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 100})
    hass.states.async_set(linked_battery_charging_sensor, STATE_ON, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_CHARGING_SENSOR: linked_battery_charging_sensor},
    )
    acc.update_state = lambda x: None
    assert acc.linked_battery_charging_sensor == linked_battery_charging_sensor

    await acc.run_handler()
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 1

    hass.states.async_set(linked_battery_charging_sensor, STATE_OFF, None)
    await acc.run_handler()
    await hass.async_block_till_done()
    assert acc._char_charging.value == 0

    hass.states.async_set(linked_battery_charging_sensor, STATE_ON, None)
    await acc.run_handler()
    await hass.async_block_till_done()
    assert acc._char_charging.value == 1
async def test_call_service(hass, hk_driver, events):
    """Test call_service method."""
    entity_id = "homekit.accessory"
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Home Accessory", entity_id, 2, {})
    call_service = async_mock_service(hass, "cover", "open_cover")

    test_domain = "cover"
    test_service = "open_cover"
    test_value = "value"

    acc.async_call_service(
        test_domain, test_service, {ATTR_ENTITY_ID: entity_id}, test_value
    )
    await hass.async_block_till_done()

    assert len(events) == 1
    assert events[0].data == {
        ATTR_ENTITY_ID: acc.entity_id,
        ATTR_DISPLAY_NAME: acc.display_name,
        ATTR_SERVICE: test_service,
        ATTR_VALUE: test_value,
    }

    assert len(call_service) == 1
    assert call_service[0].domain == test_domain
    assert call_service[0].service == test_service
    assert call_service[0].data == {ATTR_ENTITY_ID: entity_id}
예제 #7
0
async def test_battery_service(hass, hk_driver, caplog):
    """Test battery service."""
    entity_id = 'homekit.accessory'
    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 50})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Battery Service', entity_id, 2, None)
    acc.update_state = lambda x: None
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 50
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2

    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 'error'})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2
    assert 'ERROR' not in caplog.text

    # Test charging
    hass.states.async_set(entity_id, None, {
        ATTR_BATTERY_LEVEL: 10, ATTR_BATTERY_CHARGING: True})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Battery Service', entity_id, 2, None)
    acc.update_state = lambda x: None
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 1

    hass.states.async_set(entity_id, None, {
        ATTR_BATTERY_LEVEL: 100, ATTR_BATTERY_CHARGING: False})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0
예제 #8
0
async def test_accessory_cancels_track_state_change_on_stop(hass, hk_driver):
    """Ensure homekit state changed listeners are unsubscribed on reload."""
    entity_id = "sensor.accessory"
    hass.states.async_set(entity_id, None)
    acc = HomeAccessory(hass, hk_driver, "Home Accessory", entity_id, 2,
                        {"platform": "isy994"})
    with patch(
            "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        await acc.run_handler()
    assert len(hass.data[TRACK_STATE_CHANGE_CALLBACKS][entity_id]) == 1
    acc.async_stop()
    assert entity_id not in hass.data[TRACK_STATE_CHANGE_CALLBACKS]
예제 #9
0
async def test_battery_service(hass, hk_driver):
    """Test battery service."""
    entity_id = 'homekit.accessory'
    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 50})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Battery Service', entity_id, 2, None)
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 50
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2

    # Test charging
    hass.states.async_set(entity_id, None, {
        ATTR_BATTERY_LEVEL: 10,
        ATTR_BATTERY_CHARGING: True
    })
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Battery Service', entity_id, 2, None)
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 1

    hass.states.async_set(entity_id, None, {
        ATTR_BATTERY_LEVEL: 100,
        ATTR_BATTERY_CHARGING: False
    })
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0
예제 #10
0
async def test_call_service(hass, hk_driver, events):
    """Test call_service method."""
    entity_id = 'homekit.accessory'
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Home Accessory', entity_id, 2, None)
    call_service = async_mock_service(hass, 'cover', 'open_cover')

    test_domain = 'cover'
    test_service = 'open_cover'
    test_value = 'value'

    await acc.async_call_service(test_domain, test_service,
                                 {ATTR_ENTITY_ID: entity_id}, test_value)
    await hass.async_block_till_done()

    assert len(events) == 1
    assert events[0].data == {
        ATTR_ENTITY_ID: acc.entity_id,
        ATTR_DISPLAY_NAME: acc.display_name,
        ATTR_SERVICE: test_service,
        ATTR_VALUE: test_value
    }

    assert len(call_service) == 1
    assert call_service[0].domain == test_domain
    assert call_service[0].service == test_service
    assert call_service[0].data == {ATTR_ENTITY_ID: entity_id}
async def test_battery_appears_after_startup(hass, hk_driver, caplog):
    """Test battery level appears after homekit is started."""
    entity_id = "homekit.accessory"
    hass.states.async_set(entity_id, None, {})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Accessory without battery", entity_id, 2, {})
    assert acc._char_battery is None

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_battery is None

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
        await hass.async_block_till_done()
    assert acc._char_battery is None

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        hass.states.async_remove(entity_id)
        await hass.async_block_till_done()
    assert acc._char_battery is None
예제 #12
0
async def test_missing_linked_battery_sensor(hass, hk_driver, caplog):
    """Test battery service with missing linked_battery_sensor."""
    entity_id = "homekit.accessory"
    linked_battery = "sensor.battery"
    hass.states.async_set(entity_id, "open")
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_SENSOR: linked_battery},
    )
    assert not acc.linked_battery_sensor

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run_handler()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

    assert not acc.linked_battery_sensor
    assert acc._char_battery is None
    assert acc._char_low_battery is None
    assert acc._char_charging is None
async def test_missing_linked_battery_charging_sensor(hass, hk_driver, caplog):
    """Test battery service with linked_battery_charging_sensor that is mapping to a missing entity."""
    entity_id = "homekit.accessory"
    linked_battery_charging_sensor = "binary_sensor.battery_charging"
    hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 100})
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_CHARGING_SENSOR: linked_battery_charging_sensor},
    )
    assert acc.linked_battery_charging_sensor is None

    # Make sure we don't throw if the linked_battery_charging_sensor
    # is removed
    hass.states.async_remove(linked_battery_charging_sensor)
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        await acc.run()
        await hass.async_block_till_done()

    # Make sure we don't throw if the entity_id
    # is removed
    hass.states.async_remove(entity_id)
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        await acc.run()
        await hass.async_block_till_done()
예제 #14
0
    def test_home_accessory(self):
        """Test HomeAccessory class."""
        acc = HomeAccessory()
        self.assertEqual(acc.display_name, ACCESSORY_NAME)
        self.assertEqual(acc.category, 1)  # Category.OTHER
        self.assertEqual(len(acc.services), 1)
        serv = acc.services[0]  # SERV_ACCESSORY_INFO
        self.assertEqual(
            serv.get_characteristic(CHAR_MODEL).value, ACCESSORY_MODEL)

        acc = HomeAccessory('test_name', 'test_model', 'FAN', aid=2)
        self.assertEqual(acc.display_name, 'test_name')
        self.assertEqual(acc.category, 3)  # Category.FAN
        self.assertEqual(acc.aid, 2)
        self.assertEqual(len(acc.services), 1)
        serv = acc.services[0]  # SERV_ACCESSORY_INFO
        self.assertEqual(
            serv.get_characteristic(CHAR_MODEL).value, 'test_model')
예제 #15
0
async def test_battery_appears_after_startup(hass, hk_driver, caplog):
    """Test battery level appears after homekit is started."""
    entity_id = "homekit.accessory"
    hass.states.async_set(entity_id, None, {})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Accessory without battery",
                        entity_id, 2, None)
    acc.update_state = lambda x: None
    assert acc._char_battery is None

    await acc.run_handler()
    await hass.async_block_till_done()
    assert acc._char_battery is None

    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
    await hass.async_block_till_done()
    assert acc._char_battery is None
async def test_linked_battery_charging_sensor(hass, hk_driver, caplog):
    """Test battery service with linked_battery_charging_sensor."""
    entity_id = "homekit.accessory"
    linked_battery_charging_sensor = "binary_sensor.battery_charging"
    hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 100})
    hass.states.async_set(linked_battery_charging_sensor, STATE_ON, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_CHARGING_SENSOR: linked_battery_charging_sensor},
    )
    assert acc.linked_battery_charging_sensor == linked_battery_charging_sensor

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 1

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        hass.states.async_set(linked_battery_charging_sensor, STATE_OFF, None)
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_charging.value == 0

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        hass.states.async_set(linked_battery_charging_sensor, STATE_ON, None)
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_charging.value == 1

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        hass.states.async_remove(linked_battery_charging_sensor)
        await acc.run()
        await hass.async_block_till_done()
    assert acc._char_charging.value == 1
async def test_home_accessory(hass, hk_driver):
    """Test HomeAccessory class."""
    entity_id = 'homekit.accessory'
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Home Accessory', entity_id, 2, None)
    assert acc.hass == hass
    assert acc.display_name == 'Home Accessory'
    assert acc.aid == 2
    assert acc.category == 1  # Category.OTHER
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.display_name == SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == 'Home Accessory'
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == MANUFACTURER
    assert serv.get_characteristic(CHAR_MODEL).value == 'Homekit'
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == \
        'homekit.accessory'

    hass.states.async_set(entity_id, 'on')
    await hass.async_block_till_done()
    with patch('homeassistant.components.homekit.accessories.'
               'HomeAccessory.update_state') as mock_update_state:
        await hass.async_add_job(acc.run)
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_update_state.assert_called_with(state)

        hass.states.async_remove(entity_id)
        await hass.async_block_till_done()
        assert mock_update_state.call_count == 1

    with pytest.raises(NotImplementedError):
        acc.update_state('new_state')

    # Test model name from domain
    entity_id = 'test_model.demo'
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()
    acc = HomeAccessory(hass, hk_driver, 'test_name', entity_id, 2, None)
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_MODEL).value == 'Test Model'
예제 #18
0
def test_home_accessory(mock_pre_serv):
    """Test initializing a HomeAccessory object."""
    acc = HomeAccessory('TestAccessory', 'test.accessory', 'WINDOW')

    assert acc.display_name == 'TestAccessory'
    assert acc.category == 13  # Category.WINDOW
    assert len(acc.services) == 1

    serv = acc.services[0]
    assert serv.display_name == SERV_ACCESSORY_INFO
    char_model = serv.get_characteristic(CHAR_MODEL)
    assert char_model.get_value() == 'test.accessory'
예제 #19
0
    def test_home_accessory(self):
        """Test HomeAccessory class."""
        hass = get_test_home_assistant()

        acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2)
        self.assertEqual(acc.hass, hass)
        self.assertEqual(acc.display_name, 'Home Accessory')
        self.assertEqual(acc.category, 1)  # Category.OTHER
        self.assertEqual(len(acc.services), 1)
        serv = acc.services[0]  # SERV_ACCESSORY_INFO
        self.assertEqual(serv.display_name, SERV_ACCESSORY_INFO)
        self.assertEqual(
            serv.get_characteristic(CHAR_NAME).value, 'Home Accessory')
        self.assertEqual(
            serv.get_characteristic(CHAR_MANUFACTURER).value, MANUFACTURER)
        self.assertEqual(serv.get_characteristic(CHAR_MODEL).value, 'Homekit')
        self.assertEqual(
            serv.get_characteristic(CHAR_SERIAL_NUMBER).value,
            'homekit.accessory')

        hass.states.set('homekit.accessory', 'on')
        hass.block_till_done()
        acc.run()
        hass.states.set('homekit.accessory', 'off')
        hass.block_till_done()

        acc = HomeAccessory('hass', 'test_name', 'test_model.demo', 2)
        self.assertEqual(acc.display_name, 'test_name')
        self.assertEqual(acc.aid, 2)
        self.assertEqual(len(acc.services), 1)
        serv = acc.services[0]  # SERV_ACCESSORY_INFO
        self.assertEqual(
            serv.get_characteristic(CHAR_MODEL).value, 'Test Model')

        hass.stop()
예제 #20
0
async def test_battery_service(hass, hk_driver, caplog):
    """Test battery service."""
    entity_id = "homekit.accessory"
    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 50})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
    acc.update_state = lambda x: None
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 50
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2

    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: "error"})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2
    assert "ERROR" not in caplog.text

    # Test charging
    hass.states.async_set(entity_id, None, {
        ATTR_BATTERY_LEVEL: 10,
        ATTR_BATTERY_CHARGING: True
    })
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
    acc.update_state = lambda x: None
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 1

    hass.states.async_set(entity_id, None, {
        ATTR_BATTERY_LEVEL: 100,
        ATTR_BATTERY_CHARGING: False
    })
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0
예제 #21
0
async def test_home_accessory(hass):
    """Test HomeAccessory class."""
    entity_id = 'homekit.accessory'
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, 'Home Accessory', entity_id, 2, None)
    assert acc.hass == hass
    assert acc.display_name == 'Home Accessory'
    assert acc.aid == 2
    assert acc.category == 1  # Category.OTHER
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.display_name == SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == 'Home Accessory'
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == MANUFACTURER
    assert serv.get_characteristic(CHAR_MODEL).value == 'Homekit'
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == \
        'homekit.accessory'

    hass.states.async_set('homekit.accessory', 'on')
    await hass.async_block_till_done()
    await hass.async_add_job(acc.run)
    hass.states.async_set('homekit.accessory', 'off')
    await hass.async_block_till_done()

    entity_id = 'test_model.demo'
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory('hass', 'test_name', entity_id, 2, None)
    assert acc.display_name == 'test_name'
    assert acc.aid == 2
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_MODEL).value == 'Test Model'
예제 #22
0
    def test_set_accessory_info(self):
        """Test setting the basic accessory information."""
        # Test HomeAccessory
        acc = HomeAccessory('HA', 'Home Accessory', 'homekit.accessory', 2, '')
        set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000')

        serv = acc.get_service(SERV_ACCESSORY_INFO)
        self.assertEqual(serv.get_characteristic(CHAR_NAME).value, 'name')
        self.assertEqual(serv.get_characteristic(CHAR_MODEL).value, 'model')
        self.assertEqual(
            serv.get_characteristic(CHAR_MANUFACTURER).value, 'manufacturer')
        self.assertEqual(
            serv.get_characteristic(CHAR_SERIAL_NUMBER).value, '0000')

        # Test HomeBridge
        acc = HomeBridge('hass')
        set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000')

        serv = acc.get_service(SERV_ACCESSORY_INFO)
        self.assertEqual(serv.get_characteristic(CHAR_MODEL).value, 'model')
        self.assertEqual(
            serv.get_characteristic(CHAR_MANUFACTURER).value, 'manufacturer')
        self.assertEqual(
            serv.get_characteristic(CHAR_SERIAL_NUMBER).value, '0000')
예제 #23
0
async def test_missing_linked_battery_charging_sensor(hass, hk_driver, caplog):
    """Test battery service with linked_battery_charging_sensor that is mapping to a missing entity."""
    entity_id = "homekit.accessory"
    linked_battery_charging_sensor = "binary_sensor.battery_charging"
    hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 100})
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_CHARGING_SENSOR: linked_battery_charging_sensor},
    )
    assert acc.linked_battery_charging_sensor is None
예제 #24
0
async def test_linked_battery_sensor(hass, hk_driver, caplog):
    """Test battery service with linked_battery_sensor."""
    entity_id = 'homekit.accessory'
    linked_battery = 'sensor.battery'
    hass.states.async_set(entity_id, 'open', {ATTR_BATTERY_LEVEL: 100})
    hass.states.async_set(linked_battery, 50, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Battery Service', entity_id, 2,
                        {CONF_LINKED_BATTERY_SENSOR: linked_battery})
    acc.update_state = lambda x: None
    assert acc.linked_battery_sensor == linked_battery

    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 50
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    hass.states.async_set(linked_battery, 10, None)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert acc._char_low_battery.value == 1

    # Ignore battery change on entity if it has linked_battery
    hass.states.async_set(entity_id, 'open', {ATTR_BATTERY_LEVEL: 90})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10

    # Test none numeric state for linked_battery
    hass.states.async_set(linked_battery, 'error', None)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert 'ERROR' not in caplog.text

    # Test charging & low battery threshold
    hass.states.async_set(linked_battery, 20, {ATTR_BATTERY_CHARGING: True})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, 'Battery Service', entity_id, 2,
                        {CONF_LINKED_BATTERY_SENSOR: linked_battery,
                         CONF_LOW_BATTERY_THRESHOLD: 50})
    acc.update_state = lambda x: None
    await hass.async_add_job(acc.run)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 20
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 1

    hass.states.async_set(linked_battery, 100, {ATTR_BATTERY_CHARGING: False})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0
예제 #25
0
async def test_home_accessory(hass, hk_driver):
    """Test HomeAccessory class."""
    entity_id = "homekit.accessory"
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Home Accessory", entity_id, 2, None)
    assert acc.hass == hass
    assert acc.display_name == "Home Accessory"
    assert acc.aid == 2
    assert acc.category == 1  # Category.OTHER
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.display_name == SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == MANUFACTURER
    assert serv.get_characteristic(CHAR_MODEL).value == "Homekit"
    assert serv.get_characteristic(
        CHAR_SERIAL_NUMBER).value == "homekit.accessory"

    hass.states.async_set(entity_id, "on")
    await hass.async_block_till_done()
    with patch(
            "homeassistant.components.homekit.accessories.HomeAccessory.update_state"
    ) as mock_update_state:
        await acc.run_handler()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_update_state.assert_called_with(state)

        hass.states.async_remove(entity_id)
        await hass.async_block_till_done()
        assert mock_update_state.call_count == 1

    with pytest.raises(NotImplementedError):
        acc.update_state("new_state")

    # Test model name from domain
    entity_id = "test_model.demo"
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()
    acc = HomeAccessory(hass, hk_driver, "test_name", entity_id, 2, None)
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_MODEL).value == "Test Model"
예제 #26
0
async def test_home_accessory(hass):
    """Test HomeAccessory class."""
    entity_id = 'homekit.accessory'
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, 'Home Accessory', entity_id, 2, None)
    assert acc.hass == hass
    assert acc.display_name == 'Home Accessory'
    assert acc.aid == 2
    assert acc.category == 1  # Category.OTHER
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.display_name == SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == 'Home Accessory'
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == MANUFACTURER
    assert serv.get_characteristic(CHAR_MODEL).value == 'Homekit'
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == \
        'homekit.accessory'

    hass.states.async_set(entity_id, 'on')
    await hass.async_block_till_done()
    with patch('homeassistant.components.homekit.accessories.'
               'HomeAccessory.update_state') as mock_update_state:
        await hass.async_add_job(acc.run)
        state = hass.states.get(entity_id)
        mock_update_state.assert_called_with(state)

        hass.states.async_remove(entity_id)
        await hass.async_block_till_done()
        assert mock_update_state.call_count == 1

    with pytest.raises(NotImplementedError):
        acc.update_state('new_state')

    # Test model name from domain
    acc = HomeAccessory('hass', 'test_name', 'test_model.demo', 2, None)
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_MODEL).value == 'Test Model'
async def test_home_accessory(hass, hk_driver):
    """Test HomeAccessory class."""
    entity_id = "sensor.accessory"
    entity_id2 = "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum_maximum_maximum_maximum_allowed_length"

    hass.states.async_set(entity_id, None)
    hass.states.async_set(entity_id2, STATE_UNAVAILABLE)

    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass, hk_driver, "Home Accessory", entity_id, 2, {"platform": "isy994"}
    )
    assert acc.hass == hass
    assert acc.display_name == "Home Accessory"
    assert acc.aid == 2
    assert acc.available is True
    assert acc.category == 1  # Category.OTHER
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.display_name == SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == "Isy994"
    assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == "sensor.accessory"

    acc2 = HomeAccessory(hass, hk_driver, "Home Accessory", entity_id2, 3, {})
    serv = acc2.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == f"{MANUFACTURER} Light"
    assert serv.get_characteristic(CHAR_MODEL).value == "Light"
    assert (
        serv.get_characteristic(CHAR_SERIAL_NUMBER).value
        == "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum"
    )

    acc3 = HomeAccessory(
        hass,
        hk_driver,
        "Home Accessory that exceeds the maximum maximum maximum maximum maximum maximum length",
        entity_id2,
        3,
        {
            ATTR_MODEL: "Awesome Model that exceeds the maximum maximum maximum maximum maximum maximum length",
            ATTR_MANUFACTURER: "Lux Brands that exceeds the maximum maximum maximum maximum maximum maximum length",
            ATTR_SW_VERSION: "0.4.3 that exceeds the maximum maximum maximum maximum maximum maximum length",
            ATTR_INTEGRATION: "luxe that exceeds the maximum maximum maximum maximum maximum maximum length",
        },
    )
    assert acc3.available is False
    serv = acc3.services[0]  # SERV_ACCESSORY_INFO
    assert (
        serv.get_characteristic(CHAR_NAME).value
        == "Home Accessory that exceeds the maximum maximum maximum maximum "
    )
    assert (
        serv.get_characteristic(CHAR_MANUFACTURER).value
        == "Lux Brands that exceeds the maximum maximum maximum maximum maxi"
    )
    assert (
        serv.get_characteristic(CHAR_MODEL).value
        == "Awesome Model that exceeds the maximum maximum maximum maximum m"
    )
    assert (
        serv.get_characteristic(CHAR_SERIAL_NUMBER).value
        == "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum"
    )
    assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == "0.4.3"

    acc4 = HomeAccessory(
        hass,
        hk_driver,
        "Home Accessory that exceeds the maximum maximum maximum maximum maximum maximum length",
        entity_id2,
        3,
        {
            ATTR_MODEL: "Awesome Model that exceeds the maximum maximum maximum maximum maximum maximum length",
            ATTR_MANUFACTURER: "Lux Brands that exceeds the maximum maximum maximum maximum maximum maximum length",
            ATTR_SW_VERSION: "will_not_match_regex",
            ATTR_INTEGRATION: "luxe that exceeds the maximum maximum maximum maximum maximum maximum length",
        },
    )
    assert acc4.available is False
    serv = acc4.services[0]  # SERV_ACCESSORY_INFO
    assert (
        serv.get_characteristic(CHAR_NAME).value
        == "Home Accessory that exceeds the maximum maximum maximum maximum "
    )
    assert (
        serv.get_characteristic(CHAR_MANUFACTURER).value
        == "Lux Brands that exceeds the maximum maximum maximum maximum maxi"
    )
    assert (
        serv.get_characteristic(CHAR_MODEL).value
        == "Awesome Model that exceeds the maximum maximum maximum maximum m"
    )
    assert (
        serv.get_characteristic(CHAR_SERIAL_NUMBER).value
        == "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum"
    )
    assert hass_version.startswith(
        serv.get_characteristic(CHAR_FIRMWARE_REVISION).value
    )

    hass.states.async_set(entity_id, "on")
    await hass.async_block_till_done()
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

        hass.states.async_remove(entity_id)
        await hass.async_block_till_done()
        assert mock_async_update_state.call_count == 1

    with pytest.raises(NotImplementedError):
        acc.async_update_state("new_state")

    # Test model name from domain
    entity_id = "test_model.demo"
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()
    acc = HomeAccessory(hass, hk_driver, "test_name", entity_id, 2, None)
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_MODEL).value == "Test Model"
예제 #28
0
async def test_home_accessory(hass, hk_driver):
    """Test HomeAccessory class."""
    entity_id = "sensor.accessory"
    entity_id2 = "light.accessory"

    hass.states.async_set(entity_id, None)
    hass.states.async_set(entity_id2, None)

    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass, hk_driver, "Home Accessory", entity_id, 2, {"platform": "isy994"}
    )
    assert acc.hass == hass
    assert acc.display_name == "Home Accessory"
    assert acc.aid == 2
    assert acc.category == 1  # Category.OTHER
    assert len(acc.services) == 1
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.display_name == SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == "Isy994"
    assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == "sensor.accessory"

    acc2 = HomeAccessory(hass, hk_driver, "Home Accessory", entity_id2, 3, {})
    serv = acc2.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == f"{MANUFACTURER} Light"
    assert serv.get_characteristic(CHAR_MODEL).value == "Light"
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == "light.accessory"

    acc3 = HomeAccessory(
        hass,
        hk_driver,
        "Home Accessory",
        entity_id2,
        3,
        {
            ATTR_MODEL: "Awesome",
            ATTR_MANUFACTURER: "Lux Brands",
            ATTR_SOFTWARE_VERSION: "0.4.3",
            ATTR_INTERGRATION: "luxe",
        },
    )
    serv = acc3.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
    assert serv.get_characteristic(CHAR_MANUFACTURER).value == "Lux Brands"
    assert serv.get_characteristic(CHAR_MODEL).value == "Awesome"
    assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == "light.accessory"

    hass.states.async_set(entity_id, "on")
    await hass.async_block_till_done()
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run_handler()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

        hass.states.async_remove(entity_id)
        await hass.async_block_till_done()
        assert mock_async_update_state.call_count == 1

    with pytest.raises(NotImplementedError):
        acc.async_update_state("new_state")

    # Test model name from domain
    entity_id = "test_model.demo"
    hass.states.async_set(entity_id, None)
    await hass.async_block_till_done()
    acc = HomeAccessory(hass, hk_driver, "test_name", entity_id, 2, None)
    serv = acc.services[0]  # SERV_ACCESSORY_INFO
    assert serv.get_characteristic(CHAR_MODEL).value == "Test Model"
async def test_battery_service(hass, hk_driver, caplog):
    """Test battery service."""
    entity_id = "homekit.accessory"
    hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 50})
    await hass.async_block_till_done()

    acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
    assert acc._char_battery.value == 0
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

    assert acc._char_battery.value == 50
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: 15})
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        hass.states.async_set(entity_id, None, {ATTR_BATTERY_LEVEL: "error"})
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

    assert acc._char_battery.value == 15
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 2
    assert "ERROR" not in caplog.text

    # Test charging
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        hass.states.async_set(
            entity_id, None, {ATTR_BATTERY_LEVEL: 10, ATTR_BATTERY_CHARGING: True}
        )
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        acc = HomeAccessory(hass, hk_driver, "Battery Service", entity_id, 2, None)
        assert acc._char_battery.value == 0
        assert acc._char_low_battery.value == 0
        assert acc._char_charging.value == 2

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_battery.value == 10
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 1

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        hass.states.async_set(
            entity_id, None, {ATTR_BATTERY_LEVEL: 100, ATTR_BATTERY_CHARGING: False}
        )
        await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0
async def test_linked_battery_sensor(hass, hk_driver, caplog):
    """Test battery service with linked_battery_sensor."""
    entity_id = "homekit.accessory"
    linked_battery = "sensor.battery"
    hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 100})
    hass.states.async_set(linked_battery, 50, None)
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_SENSOR: linked_battery},
    )
    assert acc.linked_battery_sensor == linked_battery

    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_battery.value == 50
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 2

    hass.states.async_set(linked_battery, 10, None)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert acc._char_low_battery.value == 1

    # Ignore battery change on entity if it has linked_battery
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        hass.states.async_set(entity_id, "open", {ATTR_BATTERY_LEVEL: 90})
        await hass.async_block_till_done()
    assert acc._char_battery.value == 10

    # Test none numeric state for linked_battery
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ):
        hass.states.async_set(linked_battery, "error", None)
        await hass.async_block_till_done()
    assert acc._char_battery.value == 10
    assert "ERROR" not in caplog.text

    # Test charging & low battery threshold
    hass.states.async_set(linked_battery, 20, {ATTR_BATTERY_CHARGING: True})
    await hass.async_block_till_done()

    acc = HomeAccessory(
        hass,
        hk_driver,
        "Battery Service",
        entity_id,
        2,
        {CONF_LINKED_BATTERY_SENSOR: linked_battery, CONF_LOW_BATTERY_THRESHOLD: 50},
    )
    with patch(
        "homeassistant.components.homekit.accessories.HomeAccessory.async_update_state"
    ) as mock_async_update_state:
        await acc.run()
        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        mock_async_update_state.assert_called_with(state)
    assert acc._char_battery.value == 20
    assert acc._char_low_battery.value == 1
    assert acc._char_charging.value == 1

    hass.states.async_set(linked_battery, 100, {ATTR_BATTERY_CHARGING: False})
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0

    hass.states.async_remove(linked_battery)
    await hass.async_block_till_done()
    assert acc._char_battery.value == 100
    assert acc._char_low_battery.value == 0
    assert acc._char_charging.value == 0