Fix bond device state with v3 firmwares (#72516)
This commit is contained in:
parent
3537fa1dab
commit
c1f62d03a0
20 changed files with 59 additions and 31 deletions
|
@ -5,7 +5,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp import ClientError, ClientResponseError, ClientTimeout
|
from aiohttp import ClientError, ClientResponseError, ClientTimeout
|
||||||
from bond_api import Bond, BPUPSubscriptions, start_bpup
|
from bond_async import Bond, BPUPSubscriptions, start_bpup
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
|
|
@ -5,7 +5,7 @@ from dataclasses import dataclass
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from bond_api import Action, BPUPSubscriptions
|
from bond_async import Action, BPUPSubscriptions
|
||||||
|
|
||||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
|
|
@ -6,7 +6,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp import ClientConnectionError, ClientResponseError
|
from aiohttp import ClientConnectionError, ClientResponseError
|
||||||
from bond_api import Bond
|
from bond_async import Bond
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries, exceptions
|
from homeassistant import config_entries, exceptions
|
||||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from bond_api import Action, BPUPSubscriptions, DeviceType
|
from bond_async import Action, BPUPSubscriptions, DeviceType
|
||||||
|
|
||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
ATTR_POSITION,
|
ATTR_POSITION,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp import ClientError
|
from aiohttp import ClientError
|
||||||
from bond_api import BPUPSubscriptions
|
from bond_async import BPUPSubscriptions
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_HW_VERSION,
|
ATTR_HW_VERSION,
|
||||||
|
@ -156,9 +156,13 @@ class BondEntity(Entity):
|
||||||
self._apply_state(state)
|
self._apply_state(state)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_bpup_callback(self, state: dict) -> None:
|
def _async_bpup_callback(self, json_msg: dict) -> None:
|
||||||
"""Process a state change from BPUP."""
|
"""Process a state change from BPUP."""
|
||||||
self._async_state_callback(state)
|
topic = json_msg["t"]
|
||||||
|
if topic != f"devices/{self._device_id}/state":
|
||||||
|
return
|
||||||
|
|
||||||
|
self._async_state_callback(json_msg["b"])
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
|
|
|
@ -6,7 +6,7 @@ import math
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp.client_exceptions import ClientResponseError
|
from aiohttp.client_exceptions import ClientResponseError
|
||||||
from bond_api import Action, BPUPSubscriptions, DeviceType, Direction
|
from bond_async import Action, BPUPSubscriptions, DeviceType, Direction
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.fan import (
|
from homeassistant.components.fan import (
|
||||||
|
|
|
@ -5,7 +5,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp.client_exceptions import ClientResponseError
|
from aiohttp.client_exceptions import ClientResponseError
|
||||||
from bond_api import Action, BPUPSubscriptions, DeviceType
|
from bond_async import Action, BPUPSubscriptions, DeviceType
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
"name": "Bond",
|
"name": "Bond",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/bond",
|
"documentation": "https://www.home-assistant.io/integrations/bond",
|
||||||
"requirements": ["bond-api==0.1.18"],
|
"requirements": ["bond-async==0.1.20"],
|
||||||
"zeroconf": ["_bond._tcp.local."],
|
"zeroconf": ["_bond._tcp.local."],
|
||||||
"codeowners": ["@bdraco", "@prystupa", "@joshs85", "@marciogranzotto"],
|
"codeowners": ["@bdraco", "@prystupa", "@joshs85", "@marciogranzotto"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["bond_api"]
|
"loggers": ["bond_async"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp.client_exceptions import ClientResponseError
|
from aiohttp.client_exceptions import ClientResponseError
|
||||||
from bond_api import Action, BPUPSubscriptions, DeviceType
|
from bond_async import Action, BPUPSubscriptions, DeviceType
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
|
|
|
@ -5,7 +5,7 @@ import logging
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from aiohttp import ClientResponseError
|
from aiohttp import ClientResponseError
|
||||||
from bond_api import Action, Bond
|
from bond_async import Action, Bond
|
||||||
|
|
||||||
from homeassistant.util.async_ import gather_with_concurrency
|
from homeassistant.util.async_ import gather_with_concurrency
|
||||||
|
|
||||||
|
|
|
@ -417,7 +417,7 @@ blockchain==1.4.4
|
||||||
# bluepy==1.3.0
|
# bluepy==1.3.0
|
||||||
|
|
||||||
# homeassistant.components.bond
|
# homeassistant.components.bond
|
||||||
bond-api==0.1.18
|
bond-async==0.1.20
|
||||||
|
|
||||||
# homeassistant.components.bosch_shc
|
# homeassistant.components.bosch_shc
|
||||||
boschshcpy==0.2.30
|
boschshcpy==0.2.30
|
||||||
|
|
|
@ -318,7 +318,7 @@ blebox_uniapi==1.3.3
|
||||||
blinkpy==0.19.0
|
blinkpy==0.19.0
|
||||||
|
|
||||||
# homeassistant.components.bond
|
# homeassistant.components.bond
|
||||||
bond-api==0.1.18
|
bond-async==0.1.20
|
||||||
|
|
||||||
# homeassistant.components.bosch_shc
|
# homeassistant.components.bosch_shc
|
||||||
boschshcpy==0.2.30
|
boschshcpy==0.2.30
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import Any
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from aiohttp.client_exceptions import ClientResponseError
|
from aiohttp.client_exceptions import ClientResponseError
|
||||||
from bond_api import DeviceType
|
from bond_async import DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.bond.const import DOMAIN as BOND_DOMAIN
|
from homeassistant.components.bond.const import DOMAIN as BOND_DOMAIN
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Tests for the Bond button device."""
|
"""Tests for the Bond button device."""
|
||||||
|
|
||||||
from bond_api import Action, DeviceType
|
from bond_async import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.bond.button import STEP_SIZE
|
from homeassistant.components.bond.button import STEP_SIZE
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Tests for the Bond cover device."""
|
"""Tests for the Bond cover device."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from bond_api import Action, DeviceType
|
from bond_async import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
|
|
|
@ -3,7 +3,8 @@ import asyncio
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from bond_api import BPUPSubscriptions, DeviceType
|
from bond_async import BPUPSubscriptions, DeviceType
|
||||||
|
from bond_async.bpup import BPUP_ALIVE_TIMEOUT
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components import fan
|
from homeassistant.components import fan
|
||||||
|
@ -44,24 +45,47 @@ async def test_bpup_goes_offline_and_recovers_same_entity(hass: core.HomeAssista
|
||||||
bpup_subs.notify(
|
bpup_subs.notify(
|
||||||
{
|
{
|
||||||
"s": 200,
|
"s": 200,
|
||||||
"t": "bond/test-device-id/update",
|
"t": "devices/test-device-id/state",
|
||||||
"b": {"power": 1, "speed": 3, "direction": 0},
|
"b": {"power": 1, "speed": 3, "direction": 0},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 100
|
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 100
|
||||||
|
|
||||||
|
# Send a message for the wrong device to make sure its ignored
|
||||||
|
# we should never get this callback
|
||||||
|
bpup_subs.notify(
|
||||||
|
{
|
||||||
|
"s": 200,
|
||||||
|
"t": "devices/other-device-id/state",
|
||||||
|
"b": {"power": 1, "speed": 1, "direction": 0},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 100
|
||||||
|
|
||||||
|
# Test we ignore messages for the wrong topic
|
||||||
|
bpup_subs.notify(
|
||||||
|
{
|
||||||
|
"s": 200,
|
||||||
|
"t": "devices/test-device-id/other_topic",
|
||||||
|
"b": {"power": 1, "speed": 1, "direction": 0},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 100
|
||||||
|
|
||||||
bpup_subs.notify(
|
bpup_subs.notify(
|
||||||
{
|
{
|
||||||
"s": 200,
|
"s": 200,
|
||||||
"t": "bond/test-device-id/update",
|
"t": "devices/test-device-id/state",
|
||||||
"b": {"power": 1, "speed": 1, "direction": 0},
|
"b": {"power": 1, "speed": 1, "direction": 0},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 33
|
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 33
|
||||||
|
|
||||||
bpup_subs.last_message_time = 0
|
bpup_subs.last_message_time = -BPUP_ALIVE_TIMEOUT
|
||||||
with patch_bond_device_state(side_effect=asyncio.TimeoutError):
|
with patch_bond_device_state(side_effect=asyncio.TimeoutError):
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=230))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=230))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -75,7 +99,7 @@ async def test_bpup_goes_offline_and_recovers_same_entity(hass: core.HomeAssista
|
||||||
bpup_subs.notify(
|
bpup_subs.notify(
|
||||||
{
|
{
|
||||||
"s": 200,
|
"s": 200,
|
||||||
"t": "bond/test-device-id/update",
|
"t": "devices/test-device-id/state",
|
||||||
"b": {"power": 1, "speed": 2, "direction": 0},
|
"b": {"power": 1, "speed": 2, "direction": 0},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -106,7 +130,7 @@ async def test_bpup_goes_offline_and_recovers_different_entity(
|
||||||
bpup_subs.notify(
|
bpup_subs.notify(
|
||||||
{
|
{
|
||||||
"s": 200,
|
"s": 200,
|
||||||
"t": "bond/test-device-id/update",
|
"t": "devices/test-device-id/state",
|
||||||
"b": {"power": 1, "speed": 3, "direction": 0},
|
"b": {"power": 1, "speed": 3, "direction": 0},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -116,14 +140,14 @@ async def test_bpup_goes_offline_and_recovers_different_entity(
|
||||||
bpup_subs.notify(
|
bpup_subs.notify(
|
||||||
{
|
{
|
||||||
"s": 200,
|
"s": 200,
|
||||||
"t": "bond/test-device-id/update",
|
"t": "devices/test-device-id/state",
|
||||||
"b": {"power": 1, "speed": 1, "direction": 0},
|
"b": {"power": 1, "speed": 1, "direction": 0},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 33
|
assert hass.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 33
|
||||||
|
|
||||||
bpup_subs.last_message_time = 0
|
bpup_subs.last_message_time = -BPUP_ALIVE_TIMEOUT
|
||||||
with patch_bond_device_state(side_effect=asyncio.TimeoutError):
|
with patch_bond_device_state(side_effect=asyncio.TimeoutError):
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=230))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=230))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -133,7 +157,7 @@ async def test_bpup_goes_offline_and_recovers_different_entity(
|
||||||
bpup_subs.notify(
|
bpup_subs.notify(
|
||||||
{
|
{
|
||||||
"s": 200,
|
"s": 200,
|
||||||
"t": "bond/not-this-device-id/update",
|
"t": "devices/not-this-device-id/state",
|
||||||
"b": {"power": 1, "speed": 2, "direction": 0},
|
"b": {"power": 1, "speed": 2, "direction": 0},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import call
|
from unittest.mock import call
|
||||||
|
|
||||||
from bond_api import Action, DeviceType, Direction
|
from bond_async import Action, DeviceType, Direction
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
|
|
|
@ -3,7 +3,7 @@ import asyncio
|
||||||
from unittest.mock import MagicMock, Mock
|
from unittest.mock import MagicMock, Mock
|
||||||
|
|
||||||
from aiohttp import ClientConnectionError, ClientResponseError
|
from aiohttp import ClientConnectionError, ClientResponseError
|
||||||
from bond_api import DeviceType
|
from bond_async import DeviceType
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.bond.const import DOMAIN
|
from homeassistant.components.bond.const import DOMAIN
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Tests for the Bond light device."""
|
"""Tests for the Bond light device."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from bond_api import Action, DeviceType
|
from bond_async import Action, DeviceType
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Tests for the Bond switch device."""
|
"""Tests for the Bond switch device."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from bond_api import Action, DeviceType
|
from bond_async import Action, DeviceType
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
|
|
Loading…
Add table
Reference in a new issue