mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +00:00
Added component named switcher_kis switcher water heater integration. (#22325)
* Added component named switcher_kis switcher water heater integration. * Fixed conflicts. * Updated requirements. * Added manifest.json file and updated CODEOWNERS. * Fixed requirements_all.txt. * Better component tests. * Removed unnecessary parameter from fixture function. * Removed tests section from mypy.ini. * Remove unused ENTITY_ID_FORMAT. * Stop udp bridge when failed to setup the component. * Replace DISCOVERY_ constants prefix with DATA_. * Various change requests. * Fixed constant name change remifications. * Added explicit name to fixture. * Various change requests. * More various change requests. * Added EventType for homeassistant.core.Event. * Switched from event driven data distribution to dispatcher type plus clean-ups. * Removed name and icon keys from the component configuration. * Various change requests. * Various change reqeusts and clean-ups. * Removed unnecessary DEPENDENCIES constant from swith platform. * Replaced configuration data guard with assert. * Removed unused constants. * Removed confusing type casting for mypy sake. * Refactor property device_name to name. * Removed None guard effecting mypy only. * Removed unnecessary function from switch entity. * Removed None guard in use by mypy only. * Removed unused constant. * Removed unnecessary context manager. * Stopped messing around with mypy.ini. * Referring to typing.TYPE_CHECKING for non-runtime imports. * Added test requierment correctyly. * Replaced queue.get() with queue.get_nowait() to avoid backing up intervals requests. * Revert changes in mypy.ini. * Changed attributes content to device properties instead of entity properties. * Fixed typo in constant name. * Remove unnecessary async keyword from callable. * Waiting for tasks on event loop to end. * Added callback decorator to callable.
This commit is contained in:
parent
31e514ec15
commit
9d8d8afa82
@ -562,6 +562,7 @@ omit =
|
||||
homeassistant/components/swiss_public_transport/sensor.py
|
||||
homeassistant/components/swisscom/device_tracker.py
|
||||
homeassistant/components/switchbot/switch.py
|
||||
homeassistant/components/switcher_kis/switch.py
|
||||
homeassistant/components/switchmate/switch.py
|
||||
homeassistant/components/syncthru/sensor.py
|
||||
homeassistant/components/synology/camera.py
|
||||
|
@ -206,6 +206,7 @@ homeassistant/components/supla/* @mwegrzynek
|
||||
homeassistant/components/swiss_hydrological_data/* @fabaff
|
||||
homeassistant/components/swiss_public_transport/* @fabaff
|
||||
homeassistant/components/switchbot/* @danielhiversen
|
||||
homeassistant/components/switcher_kis/* @tomerfi
|
||||
homeassistant/components/switchmate/* @danielhiversen
|
||||
homeassistant/components/synology_srm/* @aerialls
|
||||
homeassistant/components/syslog/* @fabaff
|
||||
|
93
homeassistant/components/switcher_kis/__init__.py
Normal file
93
homeassistant/components/switcher_kis/__init__.py
Normal file
@ -0,0 +1,93 @@
|
||||
"""Home Assistant Switcher Component."""
|
||||
|
||||
from asyncio import QueueEmpty, TimeoutError as Asyncio_TimeoutError, wait_for
|
||||
from datetime import datetime, timedelta
|
||||
from logging import getLogger
|
||||
from typing import Dict, Optional
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.discovery import async_load_platform
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.helpers.typing import EventType, HomeAssistantType
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
DOMAIN = 'switcher_kis'
|
||||
|
||||
CONF_DEVICE_ID = 'device_id'
|
||||
CONF_DEVICE_PASSWORD = 'device_password'
|
||||
CONF_PHONE_ID = 'phone_id'
|
||||
|
||||
DATA_DEVICE = 'device'
|
||||
|
||||
SIGNAL_SWITCHER_DEVICE_UPDATE = 'switcher_device_update'
|
||||
|
||||
ATTR_AUTO_OFF_SET = 'auto_off_set'
|
||||
ATTR_ELECTRIC_CURRENT = 'electric_current'
|
||||
ATTR_REMAINING_TIME = 'remaining_time'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_PHONE_ID): cv.string,
|
||||
vol.Required(CONF_DEVICE_ID): cv.string,
|
||||
vol.Required(CONF_DEVICE_PASSWORD): cv.string
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistantType, config: Dict) -> bool:
|
||||
"""Set up the switcher component."""
|
||||
from aioswitcher.bridge import SwitcherV2Bridge
|
||||
|
||||
phone_id = config[DOMAIN][CONF_PHONE_ID]
|
||||
device_id = config[DOMAIN][CONF_DEVICE_ID]
|
||||
device_password = config[DOMAIN][CONF_DEVICE_PASSWORD]
|
||||
|
||||
v2bridge = SwitcherV2Bridge(
|
||||
hass.loop, phone_id, device_id, device_password)
|
||||
|
||||
await v2bridge.start()
|
||||
|
||||
async def async_stop_bridge(event: EventType) -> None:
|
||||
"""On homeassistant stop, gracefully stop the bridge if running."""
|
||||
await v2bridge.stop()
|
||||
|
||||
hass.async_add_job(hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_STOP, async_stop_bridge))
|
||||
|
||||
try:
|
||||
device_data = await wait_for(
|
||||
v2bridge.queue.get(), timeout=5.0, loop=hass.loop)
|
||||
except (Asyncio_TimeoutError, RuntimeError):
|
||||
_LOGGER.exception("failed to get response from device")
|
||||
await v2bridge.stop()
|
||||
return False
|
||||
|
||||
hass.data[DOMAIN] = {
|
||||
DATA_DEVICE: device_data
|
||||
}
|
||||
|
||||
hass.async_create_task(async_load_platform(
|
||||
hass, SWITCH_DOMAIN, DOMAIN, None, config))
|
||||
|
||||
@callback
|
||||
def device_updates(timestamp: Optional[datetime]) -> None:
|
||||
"""Use for updating the device data from the queue."""
|
||||
if v2bridge.running:
|
||||
try:
|
||||
device_new_data = v2bridge.queue.get_nowait()
|
||||
if device_new_data:
|
||||
async_dispatcher_send(
|
||||
hass, SIGNAL_SWITCHER_DEVICE_UPDATE, device_new_data)
|
||||
except QueueEmpty:
|
||||
pass
|
||||
|
||||
async_track_time_interval(hass, device_updates, timedelta(seconds=4))
|
||||
|
||||
return True
|
12
homeassistant/components/switcher_kis/manifest.json
Normal file
12
homeassistant/components/switcher_kis/manifest.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"domain": "switcher_kis",
|
||||
"name": "Switcher",
|
||||
"documentation": "https://www.home-assistant.io/components/switcher_kis/",
|
||||
"codeowners": [
|
||||
"@tomerfi"
|
||||
],
|
||||
"requirements": [
|
||||
"aioswitcher==2019.3.21"
|
||||
],
|
||||
"dependencies": []
|
||||
}
|
142
homeassistant/components/switcher_kis/switch.py
Normal file
142
homeassistant/components/switcher_kis/switch.py
Normal file
@ -0,0 +1,142 @@
|
||||
"""Home Assistant Switcher Component Switch platform."""
|
||||
|
||||
from logging import getLogger
|
||||
from typing import Callable, Dict, TYPE_CHECKING
|
||||
|
||||
from homeassistant.components.switch import ATTR_CURRENT_POWER_W, SwitchDevice
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from . import (
|
||||
ATTR_AUTO_OFF_SET, ATTR_ELECTRIC_CURRENT, ATTR_REMAINING_TIME,
|
||||
DATA_DEVICE, DOMAIN, SIGNAL_SWITCHER_DEVICE_UPDATE)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aioswitcher.devices import SwitcherV2Device
|
||||
from aioswitcher.api.messages import SwitcherV2ControlResponseMSG
|
||||
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
DEVICE_PROPERTIES_TO_HA_ATTRIBUTES = {
|
||||
'power_consumption': ATTR_CURRENT_POWER_W,
|
||||
'electric_current': ATTR_ELECTRIC_CURRENT,
|
||||
'remaining_time': ATTR_REMAINING_TIME,
|
||||
'auto_off_set': ATTR_AUTO_OFF_SET
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_platform(hass: HomeAssistantType, config: Dict,
|
||||
async_add_entities: Callable,
|
||||
discovery_info: Dict) -> None:
|
||||
"""Set up the switcher platform for the switch component."""
|
||||
assert DOMAIN in hass.data
|
||||
async_add_entities([SwitcherControl(hass.data[DOMAIN][DATA_DEVICE])])
|
||||
|
||||
|
||||
class SwitcherControl(SwitchDevice):
|
||||
"""Home Assistant switch entity."""
|
||||
|
||||
def __init__(self, device_data: 'SwitcherV2Device') -> None:
|
||||
"""Initialize the entity."""
|
||||
self._self_initiated = False
|
||||
self._device_data = device_data
|
||||
self._state = device_data.state
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the device's name."""
|
||||
return self._device_data.name
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
"""Return False, entity pushes its state to HA."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID."""
|
||||
return "{}-{}".format(
|
||||
self._device_data.device_id, self._device_data.mac_addr)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if entity is on."""
|
||||
from aioswitcher.consts import STATE_ON as SWITCHER_STATE_ON
|
||||
return self._state == SWITCHER_STATE_ON
|
||||
|
||||
@property
|
||||
def current_power_w(self) -> int:
|
||||
"""Return the current power usage in W."""
|
||||
return self._device_data.power_consumption
|
||||
|
||||
@property
|
||||
def device_state_attributes(self) -> Dict:
|
||||
"""Return the optional state attributes."""
|
||||
from aioswitcher.consts import WAITING_TEXT
|
||||
|
||||
attribs = {}
|
||||
|
||||
for prop, attr in DEVICE_PROPERTIES_TO_HA_ATTRIBUTES.items():
|
||||
value = getattr(self._device_data, prop)
|
||||
if value and value is not WAITING_TEXT:
|
||||
attribs[attr] = value
|
||||
|
||||
return attribs
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
from aioswitcher.consts import (STATE_OFF as SWITCHER_STATE_OFF,
|
||||
STATE_ON as SWITCHER_STATE_ON)
|
||||
return self._state in [SWITCHER_STATE_ON, SWITCHER_STATE_OFF]
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Run when entity about to be added to hass."""
|
||||
async_dispatcher_connect(
|
||||
self.hass, SIGNAL_SWITCHER_DEVICE_UPDATE, self.async_update_data)
|
||||
|
||||
async def async_update_data(self, device_data: 'SwitcherV2Device') -> None:
|
||||
"""Update the entity data."""
|
||||
if device_data:
|
||||
if self._self_initiated:
|
||||
self._self_initiated = False
|
||||
else:
|
||||
self._device_data = device_data
|
||||
self._state = self._device_data.state
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
async def async_turn_on(self, **kwargs: Dict) -> None:
|
||||
"""Turn the entity on.
|
||||
|
||||
This method must be run in the event loop and returns a coroutine.
|
||||
"""
|
||||
await self._control_device(True)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Dict) -> None:
|
||||
"""Turn the entity off.
|
||||
|
||||
This method must be run in the event loop and returns a coroutine.
|
||||
"""
|
||||
await self._control_device(False)
|
||||
|
||||
async def _control_device(self, send_on: bool) -> None:
|
||||
"""Turn the entity on or off."""
|
||||
from aioswitcher.api import SwitcherV2Api
|
||||
from aioswitcher.consts import (COMMAND_OFF, COMMAND_ON,
|
||||
STATE_OFF as SWITCHER_STATE_OFF,
|
||||
STATE_ON as SWITCHER_STATE_ON)
|
||||
|
||||
response = None # type: SwitcherV2ControlResponseMSG
|
||||
async with SwitcherV2Api(
|
||||
self.hass.loop, self._device_data.ip_addr,
|
||||
self._device_data.phone_id, self._device_data.device_id,
|
||||
self._device_data.device_password) as swapi:
|
||||
response = await swapi.control_device(
|
||||
COMMAND_ON if send_on else COMMAND_OFF)
|
||||
|
||||
if response and response.successful:
|
||||
self._self_initiated = True
|
||||
self._state = \
|
||||
SWITCHER_STATE_ON if send_on else SWITCHER_STATE_OFF
|
||||
self.async_schedule_update_ha_state()
|
@ -7,6 +7,7 @@ import homeassistant.core
|
||||
|
||||
GPSType = Tuple[float, float]
|
||||
ConfigType = Dict[str, Any]
|
||||
EventType = homeassistant.core.Event
|
||||
HomeAssistantType = homeassistant.core.HomeAssistant
|
||||
ServiceDataType = Dict[str, Any]
|
||||
TemplateVarsType = Optional[Dict[str, Any]]
|
||||
|
@ -145,6 +145,9 @@ aiolifx_effects==0.2.1
|
||||
# homeassistant.components.hunterdouglas_powerview
|
||||
aiopvapi==1.6.14
|
||||
|
||||
# homeassistant.components.switcher_kis
|
||||
aioswitcher==2019.3.21
|
||||
|
||||
# homeassistant.components.unifi
|
||||
aiounifi==4
|
||||
|
||||
|
@ -51,6 +51,9 @@ aiohttp_cors==0.7.0
|
||||
# homeassistant.components.hue
|
||||
aiohue==1.9.1
|
||||
|
||||
# homeassistant.components.switcher_kis
|
||||
aioswitcher==2019.3.21
|
||||
|
||||
# homeassistant.components.unifi
|
||||
aiounifi==4
|
||||
|
||||
|
@ -48,6 +48,7 @@ TEST_REQUIREMENTS = (
|
||||
'aiohttp_cors',
|
||||
'aiohue',
|
||||
'aiounifi',
|
||||
'aioswitcher',
|
||||
'apns2',
|
||||
'av',
|
||||
'axis',
|
||||
|
1
tests/components/switcher_kis/__init__.py
Normal file
1
tests/components/switcher_kis/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Test cases and object for the Switcher integration tests."""
|
110
tests/components/switcher_kis/conftest.py
Normal file
110
tests/components/switcher_kis/conftest.py
Normal file
@ -0,0 +1,110 @@
|
||||
"""Common fixtures and objects for the Switcher integration tests."""
|
||||
|
||||
from asyncio import Queue
|
||||
from datetime import datetime
|
||||
from typing import Any, Generator, Optional
|
||||
|
||||
from asynctest import CoroutineMock, patch
|
||||
from pytest import fixture
|
||||
|
||||
from .consts import (
|
||||
DUMMY_AUTO_OFF_SET, DUMMY_DEVICE_ID, DUMMY_DEVICE_NAME,
|
||||
DUMMY_DEVICE_STATE, DUMMY_ELECTRIC_CURRENT, DUMMY_IP_ADDRESS,
|
||||
DUMMY_MAC_ADDRESS, DUMMY_PHONE_ID, DUMMY_POWER_CONSUMPTION,
|
||||
DUMMY_REMAINING_TIME)
|
||||
|
||||
|
||||
@patch('aioswitcher.devices.SwitcherV2Device')
|
||||
class MockSwitcherV2Device:
|
||||
"""Class for mocking the aioswitcher.devices.SwitcherV2Device object."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the object."""
|
||||
self._last_state_change = datetime.now()
|
||||
|
||||
@property
|
||||
def device_id(self) -> str:
|
||||
"""Return the device id."""
|
||||
return DUMMY_DEVICE_ID
|
||||
|
||||
@property
|
||||
def ip_addr(self) -> str:
|
||||
"""Return the ip address."""
|
||||
return DUMMY_IP_ADDRESS
|
||||
|
||||
@property
|
||||
def mac_addr(self) -> str:
|
||||
"""Return the mac address."""
|
||||
return DUMMY_MAC_ADDRESS
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the device name."""
|
||||
return DUMMY_DEVICE_NAME
|
||||
|
||||
@property
|
||||
def state(self) -> str:
|
||||
"""Return the device state."""
|
||||
return DUMMY_DEVICE_STATE
|
||||
|
||||
@property
|
||||
def remaining_time(self) -> Optional[str]:
|
||||
"""Return the time left to auto-off."""
|
||||
return DUMMY_REMAINING_TIME
|
||||
|
||||
@property
|
||||
def auto_off_set(self) -> str:
|
||||
"""Return the auto-off configuration value."""
|
||||
return DUMMY_AUTO_OFF_SET
|
||||
|
||||
@property
|
||||
def power_consumption(self) -> int:
|
||||
"""Return the power consumption in watts."""
|
||||
return DUMMY_POWER_CONSUMPTION
|
||||
|
||||
@property
|
||||
def electric_current(self) -> float:
|
||||
"""Return the power consumption in amps."""
|
||||
return DUMMY_ELECTRIC_CURRENT
|
||||
|
||||
@property
|
||||
def phone_id(self) -> str:
|
||||
"""Return the phone id."""
|
||||
return DUMMY_PHONE_ID
|
||||
|
||||
@property
|
||||
def last_data_update(self) -> datetime:
|
||||
"""Return the timestamp of the last update."""
|
||||
return datetime.now()
|
||||
|
||||
@property
|
||||
def last_state_change(self) -> datetime:
|
||||
"""Return the timestamp of the state change."""
|
||||
return self._last_state_change
|
||||
|
||||
|
||||
@fixture(name='mock_bridge')
|
||||
def mock_bridge_fixture() -> Generator[None, Any, None]:
|
||||
"""Fixture for mocking aioswitcher.bridge.SwitcherV2Bridge."""
|
||||
queue = Queue() # type: Queue
|
||||
|
||||
async def mock_queue():
|
||||
"""Mock asyncio's Queue."""
|
||||
await queue.put(MockSwitcherV2Device())
|
||||
return await queue.get()
|
||||
|
||||
mock_bridge = CoroutineMock()
|
||||
|
||||
patchers = [
|
||||
patch('aioswitcher.bridge.SwitcherV2Bridge.start', new=mock_bridge),
|
||||
patch('aioswitcher.bridge.SwitcherV2Bridge.stop', new=mock_bridge),
|
||||
patch('aioswitcher.bridge.SwitcherV2Bridge.queue', get=mock_queue)
|
||||
]
|
||||
|
||||
for patcher in patchers:
|
||||
patcher.start()
|
||||
|
||||
yield
|
||||
|
||||
for patcher in patchers:
|
||||
patcher.stop()
|
26
tests/components/switcher_kis/consts.py
Normal file
26
tests/components/switcher_kis/consts.py
Normal file
@ -0,0 +1,26 @@
|
||||
"""Constants for the Switcher integration tests."""
|
||||
|
||||
from homeassistant.components.switcher_kis import (
|
||||
CONF_DEVICE_ID, CONF_DEVICE_PASSWORD, CONF_PHONE_ID, DOMAIN)
|
||||
|
||||
DUMMY_AUTO_OFF_SET = '01:30:00'
|
||||
DUMMY_DEVICE_ID = 'a123bc'
|
||||
DUMMY_DEVICE_NAME = "Device Name"
|
||||
DUMMY_DEVICE_PASSWORD = '12345678'
|
||||
DUMMY_DEVICE_STATE = 'on'
|
||||
DUMMY_ELECTRIC_CURRENT = 12.8
|
||||
DUMMY_ICON = 'mdi:dummy-icon'
|
||||
DUMMY_IP_ADDRESS = '192.168.100.157'
|
||||
DUMMY_MAC_ADDRESS = 'A1:B2:C3:45:67:D8'
|
||||
DUMMY_NAME = 'boiler'
|
||||
DUMMY_PHONE_ID = '1234'
|
||||
DUMMY_POWER_CONSUMPTION = 2780
|
||||
DUMMY_REMAINING_TIME = '01:29:32'
|
||||
|
||||
MANDATORY_CONFIGURATION = {
|
||||
DOMAIN: {
|
||||
CONF_PHONE_ID: DUMMY_PHONE_ID,
|
||||
CONF_DEVICE_ID: DUMMY_DEVICE_ID,
|
||||
CONF_DEVICE_PASSWORD: DUMMY_DEVICE_PASSWORD
|
||||
}
|
||||
}
|
49
tests/components/switcher_kis/test_init.py
Normal file
49
tests/components/switcher_kis/test_init.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""Test cases for the switcher_kis component."""
|
||||
|
||||
from typing import Any, Generator
|
||||
|
||||
from homeassistant.components.switcher_kis import (DOMAIN, DATA_DEVICE)
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .consts import (
|
||||
DUMMY_AUTO_OFF_SET, DUMMY_DEVICE_ID, DUMMY_DEVICE_NAME,
|
||||
DUMMY_DEVICE_STATE, DUMMY_ELECTRIC_CURRENT, DUMMY_IP_ADDRESS,
|
||||
DUMMY_MAC_ADDRESS, DUMMY_PHONE_ID, DUMMY_POWER_CONSUMPTION,
|
||||
DUMMY_REMAINING_TIME, MANDATORY_CONFIGURATION)
|
||||
|
||||
|
||||
async def test_failed_config(hass: HomeAssistantType) -> None:
|
||||
"""Test failed configuration."""
|
||||
assert await async_setup_component(
|
||||
hass, DOMAIN, MANDATORY_CONFIGURATION) is False
|
||||
|
||||
|
||||
async def test_minimal_config(hass: HomeAssistantType,
|
||||
mock_bridge: Generator[None, Any, None]
|
||||
) -> None:
|
||||
"""Test setup with configuration minimal entries."""
|
||||
assert await async_setup_component(hass, DOMAIN, MANDATORY_CONFIGURATION)
|
||||
|
||||
|
||||
async def test_discovery_data_bucket(
|
||||
hass: HomeAssistantType,
|
||||
mock_bridge: Generator[None, Any, None]
|
||||
) -> None:
|
||||
"""Test the event send with the updated device."""
|
||||
assert await async_setup_component(
|
||||
hass, DOMAIN, MANDATORY_CONFIGURATION)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = hass.data[DOMAIN].get(DATA_DEVICE)
|
||||
assert device.device_id == DUMMY_DEVICE_ID
|
||||
assert device.ip_addr == DUMMY_IP_ADDRESS
|
||||
assert device.mac_addr == DUMMY_MAC_ADDRESS
|
||||
assert device.name == DUMMY_DEVICE_NAME
|
||||
assert device.state == DUMMY_DEVICE_STATE
|
||||
assert device.remaining_time == DUMMY_REMAINING_TIME
|
||||
assert device.auto_off_set == DUMMY_AUTO_OFF_SET
|
||||
assert device.power_consumption == DUMMY_POWER_CONSUMPTION
|
||||
assert device.electric_current == DUMMY_ELECTRIC_CURRENT
|
||||
assert device.phone_id == DUMMY_PHONE_ID
|
Loading…
x
Reference in New Issue
Block a user