mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 08:07:45 +00:00
2022.9.3 (#78410)
This commit is contained in:
commit
896955e4df
19
.github/workflows/ci.yaml
vendored
19
.github/workflows/ci.yaml
vendored
@ -169,7 +169,6 @@ jobs:
|
||||
uses: actions/setup-python@v4.1.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
cache: "pip"
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.8
|
||||
@ -484,7 +483,7 @@ jobs:
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Restore pip wheel cache
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
@ -492,10 +491,10 @@ jobs:
|
||||
with:
|
||||
path: ${{ env.PIP_CACHE }}
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
steps.generate-pip-key.outputs.key }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-pip-${{ env.PIP_CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}-
|
||||
${{ runner.os }}-${{ matrix.python-version }}-pip-${{ env.PIP_CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}-
|
||||
- name: Install additional OS dependencies
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
@ -542,7 +541,7 @@ jobs:
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
@ -574,7 +573,7 @@ jobs:
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
@ -607,7 +606,7 @@ jobs:
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
@ -651,7 +650,7 @@ jobs:
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
@ -699,7 +698,7 @@ jobs:
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
@ -752,7 +751,7 @@ jobs:
|
||||
uses: actions/cache@v3.0.8
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "blink",
|
||||
"name": "Blink",
|
||||
"documentation": "https://www.home-assistant.io/integrations/blink",
|
||||
"requirements": ["blinkpy==0.19.0"],
|
||||
"requirements": ["blinkpy==0.19.2"],
|
||||
"codeowners": ["@fronzbot"],
|
||||
"dhcp": [
|
||||
{
|
||||
|
@ -5,9 +5,11 @@
|
||||
"dependencies": ["usb"],
|
||||
"quality_scale": "internal",
|
||||
"requirements": [
|
||||
"bleak==0.16.0",
|
||||
"bleak==0.17.0",
|
||||
"bleak-retry-connector==1.15.1",
|
||||
"bluetooth-adapters==0.4.1",
|
||||
"bluetooth-auto-recovery==0.3.2"
|
||||
"bluetooth-auto-recovery==0.3.3",
|
||||
"dbus-fast==1.4.0"
|
||||
],
|
||||
"codeowners": ["@bdraco"],
|
||||
"config_flow": true,
|
||||
|
@ -17,7 +17,7 @@ from bleak.backends.bluezdbus.advertisement_monitor import OrPattern
|
||||
from bleak.backends.bluezdbus.scanner import BlueZScannerArgs
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
from dbus_next import InvalidMessageError
|
||||
from dbus_fast import InvalidMessageError
|
||||
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import (
|
||||
|
@ -47,7 +47,7 @@ SERVICE_CONFIGURE = "configure"
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_INITIAL, default=DEFAULT_INITIAL): cv.positive_int,
|
||||
vol.Required(CONF_NAME): vol.All(cv.string, vol.Length(min=1)),
|
||||
@ -57,16 +57,6 @@ CREATE_FIELDS = {
|
||||
vol.Optional(CONF_STEP, default=DEFAULT_STEP): cv.positive_int,
|
||||
}
|
||||
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_INITIAL): cv.positive_int,
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_MAXIMUM): vol.Any(None, vol.Coerce(int)),
|
||||
vol.Optional(CONF_MINIMUM): vol.Any(None, vol.Coerce(int)),
|
||||
vol.Optional(CONF_RESTORE): cv.boolean,
|
||||
vol.Optional(CONF_STEP): cv.positive_int,
|
||||
}
|
||||
|
||||
|
||||
def _none_to_empty_dict(value):
|
||||
if value is None:
|
||||
@ -128,7 +118,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
component.async_register_entity_service(SERVICE_INCREMENT, {}, "async_increment")
|
||||
@ -152,12 +142,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
class CounterStorageCollection(collection.StorageCollection):
|
||||
"""Input storage based collection."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(CREATE_FIELDS)
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS)
|
||||
|
||||
async def _process_create_data(self, data: dict) -> dict:
|
||||
"""Validate the config is valid."""
|
||||
return self.CREATE_SCHEMA(data)
|
||||
return self.CREATE_UPDATE_SCHEMA(data)
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict) -> str:
|
||||
@ -166,8 +155,8 @@ class CounterStorageCollection(collection.StorageCollection):
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return {**data, **update_data}
|
||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
class Counter(RestoreEntity):
|
||||
|
@ -43,6 +43,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
except AuthenticationRequired as err:
|
||||
raise ConfigEntryAuthFailed from err
|
||||
|
||||
if not hass.data[DOMAIN]:
|
||||
async_setup_services(hass)
|
||||
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id] = DeconzGateway(
|
||||
hass, config_entry, api
|
||||
)
|
||||
@ -53,9 +56,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
await async_setup_events(gateway)
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||
|
||||
if len(hass.data[DOMAIN]) == 1:
|
||||
async_setup_services(hass)
|
||||
|
||||
api.start()
|
||||
|
||||
config_entry.async_on_unload(
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "dhcp",
|
||||
"name": "DHCP Discovery",
|
||||
"documentation": "https://www.home-assistant.io/integrations/dhcp",
|
||||
"requirements": ["scapy==2.4.5", "aiodiscover==1.4.11"],
|
||||
"requirements": ["scapy==2.4.5", "aiodiscover==1.4.13"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"quality_scale": "internal",
|
||||
"iot_class": "local_push",
|
||||
|
@ -44,6 +44,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
|
||||
|
||||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
|
@ -20,6 +20,7 @@ from homeassistant.const import (
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
ENERGY_MEGA_WATT_HOUR,
|
||||
ENERGY_WATT_HOUR,
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
@ -44,7 +45,7 @@ SUPPORTED_STATE_CLASSES = [
|
||||
SensorStateClass.TOTAL_INCREASING,
|
||||
]
|
||||
VALID_ENERGY_UNITS = [ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR, ENERGY_MEGA_WATT_HOUR]
|
||||
VALID_ENERGY_UNITS_GAS = [VOLUME_CUBIC_METERS] + VALID_ENERGY_UNITS
|
||||
VALID_ENERGY_UNITS_GAS = [VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS] + VALID_ENERGY_UNITS
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "frontend",
|
||||
"name": "Home Assistant Frontend",
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"requirements": ["home-assistant-frontend==20220907.0"],
|
||||
"requirements": ["home-assistant-frontend==20220907.1"],
|
||||
"dependencies": [
|
||||
"api",
|
||||
"auth",
|
||||
|
@ -17,6 +17,11 @@
|
||||
"service_uuid": "00008351-0000-1000-8000-00805f9b34fb",
|
||||
"connectable": false
|
||||
},
|
||||
{
|
||||
"manufacturer_id": 57391,
|
||||
"service_uuid": "00008351-0000-1000-8000-00805f9b34fb",
|
||||
"connectable": false
|
||||
},
|
||||
{
|
||||
"manufacturer_id": 18994,
|
||||
"service_uuid": "00008551-0000-1000-8000-00805f9b34fb",
|
||||
@ -53,7 +58,7 @@
|
||||
"connectable": false
|
||||
}
|
||||
],
|
||||
"requirements": ["govee-ble==0.17.2"],
|
||||
"requirements": ["govee-ble==0.17.3"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"iot_class": "local_push"
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "HomeKit Controller",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/homekit_controller",
|
||||
"requirements": ["aiohomekit==1.5.6"],
|
||||
"requirements": ["aiohomekit==1.5.7"],
|
||||
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."],
|
||||
"bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }],
|
||||
"dependencies": ["bluetooth", "zeroconf"],
|
||||
|
@ -37,20 +37,25 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_INITIAL = "initial"
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
|
||||
vol.Optional(CONF_INITIAL): cv.boolean,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
}
|
||||
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_INITIAL): cv.boolean,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{DOMAIN: cv.schema_with_slug_keys(vol.Any(UPDATE_FIELDS, None))},
|
||||
{
|
||||
DOMAIN: cv.schema_with_slug_keys(
|
||||
vol.Any(
|
||||
{
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_INITIAL): cv.boolean,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
},
|
||||
None,
|
||||
)
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
@ -62,12 +67,11 @@ STORAGE_VERSION = 1
|
||||
class InputBooleanStorageCollection(collection.StorageCollection):
|
||||
"""Input boolean collection stored in storage."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(CREATE_FIELDS)
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS)
|
||||
|
||||
async def _process_create_data(self, data: dict) -> dict:
|
||||
"""Validate the config is valid."""
|
||||
return self.CREATE_SCHEMA(data)
|
||||
return self.CREATE_UPDATE_SCHEMA(data)
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict) -> str:
|
||||
@ -76,8 +80,8 @@ class InputBooleanStorageCollection(collection.StorageCollection):
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return {**data, **update_data}
|
||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
@bind_hass
|
||||
@ -118,7 +122,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
|
@ -30,18 +30,23 @@ DOMAIN = "input_button"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
}
|
||||
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{DOMAIN: cv.schema_with_slug_keys(vol.Any(UPDATE_FIELDS, None))},
|
||||
{
|
||||
DOMAIN: cv.schema_with_slug_keys(
|
||||
vol.Any(
|
||||
{
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
},
|
||||
None,
|
||||
)
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
@ -53,12 +58,11 @@ STORAGE_VERSION = 1
|
||||
class InputButtonStorageCollection(collection.StorageCollection):
|
||||
"""Input button collection stored in storage."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(CREATE_FIELDS)
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS)
|
||||
|
||||
async def _process_create_data(self, data: dict) -> vol.Schema:
|
||||
"""Validate the config is valid."""
|
||||
return self.CREATE_SCHEMA(data)
|
||||
return self.CREATE_UPDATE_SCHEMA(data)
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict) -> str:
|
||||
@ -67,8 +71,8 @@ class InputButtonStorageCollection(collection.StorageCollection):
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return {**data, **update_data}
|
||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
@ -103,7 +107,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
|
@ -61,20 +61,13 @@ def validate_set_datetime_attrs(config):
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
|
||||
vol.Optional(CONF_HAS_DATE, default=False): cv.boolean,
|
||||
vol.Optional(CONF_HAS_TIME, default=False): cv.boolean,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_INITIAL): cv.string,
|
||||
}
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_HAS_DATE): cv.boolean,
|
||||
vol.Optional(CONF_HAS_TIME): cv.boolean,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_INITIAL): cv.string,
|
||||
}
|
||||
|
||||
|
||||
def has_date_or_time(conf):
|
||||
@ -167,7 +160,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
@ -213,12 +206,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
class DateTimeStorageCollection(collection.StorageCollection):
|
||||
"""Input storage based collection."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, has_date_or_time))
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, has_date_or_time))
|
||||
|
||||
async def _process_create_data(self, data: dict) -> dict:
|
||||
"""Validate the config is valid."""
|
||||
return self.CREATE_SCHEMA(data)
|
||||
return self.CREATE_UPDATE_SCHEMA(data)
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict) -> str:
|
||||
@ -227,8 +219,8 @@ class DateTimeStorageCollection(collection.StorageCollection):
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return has_date_or_time({**data, **update_data})
|
||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
class InputDatetime(RestoreEntity):
|
||||
|
@ -65,7 +65,7 @@ def _cv_input_number(cfg):
|
||||
return cfg
|
||||
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
|
||||
vol.Required(CONF_MIN): vol.Coerce(float),
|
||||
vol.Required(CONF_MAX): vol.Coerce(float),
|
||||
@ -76,17 +76,6 @@ CREATE_FIELDS = {
|
||||
vol.Optional(CONF_MODE, default=MODE_SLIDER): vol.In([MODE_BOX, MODE_SLIDER]),
|
||||
}
|
||||
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_MIN): vol.Coerce(float),
|
||||
vol.Optional(CONF_MAX): vol.Coerce(float),
|
||||
vol.Optional(CONF_INITIAL): vol.Coerce(float),
|
||||
vol.Optional(CONF_STEP): vol.All(vol.Coerce(float), vol.Range(min=1e-9)),
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||
vol.Optional(CONF_MODE): vol.In([MODE_BOX, MODE_SLIDER]),
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: cv.schema_with_slug_keys(
|
||||
@ -148,7 +137,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
@ -184,22 +173,37 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
class NumberStorageCollection(collection.StorageCollection):
|
||||
"""Input storage based collection."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, _cv_input_number))
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_number))
|
||||
|
||||
async def _process_create_data(self, data: dict) -> dict:
|
||||
"""Validate the config is valid."""
|
||||
return self.CREATE_SCHEMA(data)
|
||||
return self.SCHEMA(data)
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict) -> str:
|
||||
"""Suggest an ID based on the config."""
|
||||
return info[CONF_NAME]
|
||||
|
||||
async def _async_load_data(self) -> dict | None:
|
||||
"""Load the data.
|
||||
|
||||
A past bug caused frontend to add initial value to all input numbers.
|
||||
This drops that.
|
||||
"""
|
||||
data = await super()._async_load_data()
|
||||
|
||||
if data is None:
|
||||
return data
|
||||
|
||||
for number in data["items"]:
|
||||
number.pop(CONF_INITIAL, None)
|
||||
|
||||
return data
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return _cv_input_number({**data, **update_data})
|
||||
update_data = self.SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
class InputNumber(RestoreEntity):
|
||||
|
@ -56,7 +56,7 @@ def _unique(options: Any) -> Any:
|
||||
raise HomeAssistantError("Duplicate options are not allowed") from exc
|
||||
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
|
||||
vol.Required(CONF_OPTIONS): vol.All(
|
||||
cv.ensure_list, vol.Length(min=1), _unique, [cv.string]
|
||||
@ -64,14 +64,6 @@ CREATE_FIELDS = {
|
||||
vol.Optional(CONF_INITIAL): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
}
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_OPTIONS): vol.All(
|
||||
cv.ensure_list, vol.Length(min=1), _unique, [cv.string]
|
||||
),
|
||||
vol.Optional(CONF_INITIAL): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
}
|
||||
|
||||
|
||||
def _remove_duplicates(options: list[str], name: str | None) -> list[str]:
|
||||
@ -172,7 +164,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
@ -238,12 +230,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
class InputSelectStorageCollection(collection.StorageCollection):
|
||||
"""Input storage based collection."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, _cv_input_select))
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_select))
|
||||
|
||||
async def _process_create_data(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Validate the config is valid."""
|
||||
return cast(dict[str, Any], self.CREATE_SCHEMA(data))
|
||||
return cast(dict[str, Any], self.CREATE_UPDATE_SCHEMA(data))
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict[str, Any]) -> str:
|
||||
@ -254,8 +245,8 @@ class InputSelectStorageCollection(collection.StorageCollection):
|
||||
self, data: dict[str, Any], update_data: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return _cv_input_select({**data, **update_data})
|
||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
class InputSelect(SelectEntity, RestoreEntity):
|
||||
|
@ -51,7 +51,7 @@ SERVICE_SET_VALUE = "set_value"
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
|
||||
vol.Optional(CONF_MIN, default=CONF_MIN_VALUE): vol.Coerce(int),
|
||||
vol.Optional(CONF_MAX, default=CONF_MAX_VALUE): vol.Coerce(int),
|
||||
@ -61,16 +61,6 @@ CREATE_FIELDS = {
|
||||
vol.Optional(CONF_PATTERN): cv.string,
|
||||
vol.Optional(CONF_MODE, default=MODE_TEXT): vol.In([MODE_TEXT, MODE_PASSWORD]),
|
||||
}
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_MIN): vol.Coerce(int),
|
||||
vol.Optional(CONF_MAX): vol.Coerce(int),
|
||||
vol.Optional(CONF_INITIAL): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||
vol.Optional(CONF_PATTERN): cv.string,
|
||||
vol.Optional(CONF_MODE): vol.In([MODE_TEXT, MODE_PASSWORD]),
|
||||
}
|
||||
|
||||
|
||||
def _cv_input_text(cfg):
|
||||
@ -147,7 +137,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
@ -177,12 +167,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
class InputTextStorageCollection(collection.StorageCollection):
|
||||
"""Input storage based collection."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, _cv_input_text))
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_text))
|
||||
|
||||
async def _process_create_data(self, data: dict) -> dict:
|
||||
"""Validate the config is valid."""
|
||||
return self.CREATE_SCHEMA(data)
|
||||
return self.CREATE_UPDATE_SCHEMA(data)
|
||||
|
||||
@callback
|
||||
def _get_suggested_id(self, info: dict) -> str:
|
||||
@ -191,8 +180,8 @@ class InputTextStorageCollection(collection.StorageCollection):
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
update_data = self.UPDATE_SCHEMA(update_data)
|
||||
return _cv_input_text({**data, **update_data})
|
||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
return {CONF_ID: data[CONF_ID]} | update_data
|
||||
|
||||
|
||||
class InputText(RestoreEntity):
|
||||
|
@ -1,19 +1,61 @@
|
||||
"""Component for the Portuguese weather service - IPMA."""
|
||||
import logging
|
||||
|
||||
import async_timeout
|
||||
from pyipma import IPMAException
|
||||
from pyipma.api import IPMA_API
|
||||
from pyipma.location import Location
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .config_flow import IpmaFlowHandler # noqa: F401
|
||||
from .const import DOMAIN # noqa: F401
|
||||
from .const import DATA_API, DATA_LOCATION, DOMAIN
|
||||
|
||||
DEFAULT_NAME = "ipma"
|
||||
|
||||
PLATFORMS = [Platform.WEATHER]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
||||
async def async_get_api(hass):
|
||||
"""Get the pyipma api object."""
|
||||
websession = async_get_clientsession(hass)
|
||||
return IPMA_API(websession)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Set up IPMA station as config entry."""
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
latitude = config_entry.data[CONF_LATITUDE]
|
||||
longitude = config_entry.data[CONF_LONGITUDE]
|
||||
|
||||
api = await async_get_api(hass)
|
||||
try:
|
||||
async with async_timeout.timeout(30):
|
||||
location = await Location.get(api, float(latitude), float(longitude))
|
||||
|
||||
_LOGGER.debug(
|
||||
"Initializing for coordinates %s, %s -> station %s (%d, %d)",
|
||||
latitude,
|
||||
longitude,
|
||||
location.station,
|
||||
location.id_station,
|
||||
location.global_id_local,
|
||||
)
|
||||
except IPMAException as err:
|
||||
raise ConfigEntryNotReady(
|
||||
f"Could not get location for ({latitude},{longitude})"
|
||||
) from err
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][config_entry.entry_id] = {DATA_API: api, DATA_LOCATION: location}
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||
return True
|
||||
|
||||
|
||||
|
@ -6,3 +6,6 @@ DOMAIN = "ipma"
|
||||
HOME_LOCATION_NAME = "Home"
|
||||
|
||||
ENTITY_ID_SENSOR_FORMAT_HOME = f"{WEATHER_DOMAIN}.ipma_{HOME_LOCATION_NAME}"
|
||||
|
||||
DATA_LOCATION = "location"
|
||||
DATA_API = "api"
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Instituto Portugu\u00eas do Mar e Atmosfera (IPMA)",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/ipma",
|
||||
"requirements": ["pyipma==3.0.2"],
|
||||
"requirements": ["pyipma==3.0.4"],
|
||||
"codeowners": ["@dgomes", "@abmantis"],
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["geopy", "pyipma"]
|
||||
|
@ -48,11 +48,12 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv, entity_registry
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.sun import is_up
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
from .const import DATA_API, DATA_LOCATION, DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTRIBUTION = "Instituto Português do Mar e Atmosfera"
|
||||
@ -95,13 +96,10 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Add a weather entity from a config_entry."""
|
||||
latitude = config_entry.data[CONF_LATITUDE]
|
||||
longitude = config_entry.data[CONF_LONGITUDE]
|
||||
api = hass.data[DOMAIN][config_entry.entry_id][DATA_API]
|
||||
location = hass.data[DOMAIN][config_entry.entry_id][DATA_LOCATION]
|
||||
mode = config_entry.data[CONF_MODE]
|
||||
|
||||
api = await async_get_api(hass)
|
||||
location = await async_get_location(hass, api, latitude, longitude)
|
||||
|
||||
# Migrate old unique_id
|
||||
@callback
|
||||
def _async_migrator(entity_entry: entity_registry.RegistryEntry):
|
||||
@ -127,29 +125,6 @@ async def async_setup_entry(
|
||||
async_add_entities([IPMAWeather(location, api, config_entry.data)], True)
|
||||
|
||||
|
||||
async def async_get_api(hass):
|
||||
"""Get the pyipma api object."""
|
||||
websession = async_get_clientsession(hass)
|
||||
return IPMA_API(websession)
|
||||
|
||||
|
||||
async def async_get_location(hass, api, latitude, longitude):
|
||||
"""Retrieve pyipma location, location name to be used as the entity name."""
|
||||
async with async_timeout.timeout(30):
|
||||
location = await Location.get(api, float(latitude), float(longitude))
|
||||
|
||||
_LOGGER.debug(
|
||||
"Initializing for coordinates %s, %s -> station %s (%d, %d)",
|
||||
latitude,
|
||||
longitude,
|
||||
location.station,
|
||||
location.id_station,
|
||||
location.global_id_local,
|
||||
)
|
||||
|
||||
return location
|
||||
|
||||
|
||||
class IPMAWeather(WeatherEntity):
|
||||
"""Representation of a weather condition."""
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "LED BLE",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/ble_ble",
|
||||
"requirements": ["led-ble==0.9.1"],
|
||||
"requirements": ["led-ble==0.10.0"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"bluetooth": [
|
||||
|
@ -99,4 +99,11 @@ class RainMachineUpdateEntity(RainMachineEntity, UpdateEntity):
|
||||
UpdateStates.UPGRADING,
|
||||
UpdateStates.REBOOT,
|
||||
)
|
||||
self._attr_latest_version = data["packageDetails"]["newVersion"]
|
||||
|
||||
# The RainMachine API docs say that multiple "packages" can be updated, but
|
||||
# don't give details on what types exist (which makes it impossible to have
|
||||
# update entities per update type); so, we use the first one (with the idea that
|
||||
# after it succeeds, the entity will show the next update):
|
||||
package_details = data["packageDetails"][0]
|
||||
self._attr_latest_version = package_details["newVersion"]
|
||||
self._attr_title = package_details["packageName"]
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "switchbot",
|
||||
"name": "SwitchBot",
|
||||
"documentation": "https://www.home-assistant.io/integrations/switchbot",
|
||||
"requirements": ["PySwitchbot==0.19.5"],
|
||||
"requirements": ["PySwitchbot==0.19.8"],
|
||||
"config_flow": true,
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": [
|
||||
|
@ -61,18 +61,12 @@ SERVICE_FINISH = "finish"
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
|
||||
CREATE_FIELDS = {
|
||||
STORAGE_FIELDS = {
|
||||
vol.Required(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_DURATION, default=DEFAULT_DURATION): cv.time_period,
|
||||
vol.Optional(CONF_RESTORE, default=DEFAULT_RESTORE): cv.boolean,
|
||||
}
|
||||
UPDATE_FIELDS = {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_DURATION): cv.time_period,
|
||||
vol.Optional(CONF_RESTORE): cv.boolean,
|
||||
}
|
||||
|
||||
|
||||
def _format_timedelta(delta: timedelta):
|
||||
@ -137,7 +131,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
await storage_collection.async_load()
|
||||
|
||||
collection.StorageCollectionWebsocket(
|
||||
storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS
|
||||
storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS
|
||||
).async_setup(hass)
|
||||
|
||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||
@ -171,12 +165,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
class TimerStorageCollection(collection.StorageCollection):
|
||||
"""Timer storage based collection."""
|
||||
|
||||
CREATE_SCHEMA = vol.Schema(CREATE_FIELDS)
|
||||
UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS)
|
||||
CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS)
|
||||
|
||||
async def _process_create_data(self, data: dict) -> dict:
|
||||
"""Validate the config is valid."""
|
||||
data = self.CREATE_SCHEMA(data)
|
||||
data = self.CREATE_UPDATE_SCHEMA(data)
|
||||
# make duration JSON serializeable
|
||||
data[CONF_DURATION] = _format_timedelta(data[CONF_DURATION])
|
||||
return data
|
||||
@ -188,7 +181,7 @@ class TimerStorageCollection(collection.StorageCollection):
|
||||
|
||||
async def _update_data(self, data: dict, update_data: dict) -> dict:
|
||||
"""Return a new updated data object."""
|
||||
data = {**data, **self.UPDATE_SCHEMA(update_data)}
|
||||
data = {CONF_ID: data[CONF_ID]} | self.CREATE_UPDATE_SCHEMA(update_data)
|
||||
# make duration JSON serializeable
|
||||
if CONF_DURATION in update_data:
|
||||
data[CONF_DURATION] = _format_timedelta(data[CONF_DURATION])
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Viessmann ViCare",
|
||||
"documentation": "https://www.home-assistant.io/integrations/vicare",
|
||||
"codeowners": ["@oischinger"],
|
||||
"requirements": ["PyViCare==2.16.2"],
|
||||
"requirements": ["PyViCare==2.17.0"],
|
||||
"iot_class": "cloud_polling",
|
||||
"config_flow": true,
|
||||
"dhcp": [
|
||||
|
@ -9,7 +9,7 @@
|
||||
"service_data_uuid": "0000fe95-0000-1000-8000-00805f9b34fb"
|
||||
}
|
||||
],
|
||||
"requirements": ["xiaomi-ble==0.9.0"],
|
||||
"requirements": ["xiaomi-ble==0.10.0"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@Jc2k", "@Ernst79"],
|
||||
"iot_class": "local_push"
|
||||
|
@ -3,10 +3,15 @@
|
||||
"name": "Yale Access Bluetooth",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/yalexs_ble",
|
||||
"requirements": ["yalexs-ble==1.8.1"],
|
||||
"requirements": ["yalexs-ble==1.9.0"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@bdraco"],
|
||||
"bluetooth": [{ "manufacturer_id": 465 }],
|
||||
"bluetooth": [
|
||||
{
|
||||
"manufacturer_id": 465,
|
||||
"service_uuid": "0000fe24-0000-1000-8000-00805f9b34fb"
|
||||
}
|
||||
],
|
||||
"iot_class": "local_push",
|
||||
"supported_brands": {
|
||||
"august_ble": "August Bluetooth"
|
||||
|
@ -84,7 +84,7 @@ PARALLEL_UPDATES = 0
|
||||
SIGNAL_LIGHT_GROUP_STATE_CHANGED = "zha_light_group_state_changed"
|
||||
SIGNAL_LIGHT_GROUP_TRANSITION_START = "zha_light_group_transition_start"
|
||||
SIGNAL_LIGHT_GROUP_TRANSITION_FINISHED = "zha_light_group_transition_finished"
|
||||
DEFAULT_MIN_TRANSITION_MANUFACTURERS = {"Sengled"}
|
||||
DEFAULT_MIN_TRANSITION_MANUFACTURERS = {"sengled"}
|
||||
|
||||
COLOR_MODES_GROUP_LIGHT = {ColorMode.COLOR_TEMP, ColorMode.XY}
|
||||
SUPPORT_GROUP_LIGHT = (
|
||||
|
@ -7,7 +7,7 @@ from .backports.enum import StrEnum
|
||||
|
||||
MAJOR_VERSION: Final = 2022
|
||||
MINOR_VERSION: Final = 9
|
||||
PATCH_VERSION: Final = "2"
|
||||
PATCH_VERSION: Final = "3"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
||||
|
@ -62,6 +62,12 @@ BLUETOOTH: list[dict[str, bool | str | int | list[int]]] = [
|
||||
"service_uuid": "00008351-0000-1000-8000-00805f9b34fb",
|
||||
"connectable": False
|
||||
},
|
||||
{
|
||||
"domain": "govee_ble",
|
||||
"manufacturer_id": 57391,
|
||||
"service_uuid": "00008351-0000-1000-8000-00805f9b34fb",
|
||||
"connectable": False
|
||||
},
|
||||
{
|
||||
"domain": "govee_ble",
|
||||
"manufacturer_id": 18994,
|
||||
@ -281,6 +287,7 @@ BLUETOOTH: list[dict[str, bool | str | int | list[int]]] = [
|
||||
},
|
||||
{
|
||||
"domain": "yalexs_ble",
|
||||
"manufacturer_id": 465
|
||||
"manufacturer_id": 465,
|
||||
"service_uuid": "0000fe24-0000-1000-8000-00805f9b34fb"
|
||||
}
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
PyJWT==2.4.0
|
||||
PyNaCl==1.5.0
|
||||
aiodiscover==1.4.11
|
||||
aiodiscover==1.4.13
|
||||
aiohttp==3.8.1
|
||||
aiohttp_cors==0.7.0
|
||||
astral==2.2
|
||||
@ -10,16 +10,18 @@ atomicwrites-homeassistant==1.4.1
|
||||
attrs==21.2.0
|
||||
awesomeversion==22.8.0
|
||||
bcrypt==3.1.7
|
||||
bleak==0.16.0
|
||||
bleak-retry-connector==1.15.1
|
||||
bleak==0.17.0
|
||||
bluetooth-adapters==0.4.1
|
||||
bluetooth-auto-recovery==0.3.2
|
||||
bluetooth-auto-recovery==0.3.3
|
||||
certifi>=2021.5.30
|
||||
ciso8601==2.2.0
|
||||
cryptography==37.0.4
|
||||
dbus-fast==1.4.0
|
||||
fnvhash==0.1.0
|
||||
hass-nabucasa==0.55.0
|
||||
home-assistant-bluetooth==1.3.0
|
||||
home-assistant-frontend==20220907.0
|
||||
home-assistant-frontend==20220907.1
|
||||
httpx==0.23.0
|
||||
ifaddr==0.1.7
|
||||
jinja2==3.1.2
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2022.9.2"
|
||||
version = "2022.9.3"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
readme = "README.rst"
|
||||
|
@ -37,7 +37,7 @@ PyRMVtransport==0.3.3
|
||||
PySocks==1.7.1
|
||||
|
||||
# homeassistant.components.switchbot
|
||||
PySwitchbot==0.19.5
|
||||
PySwitchbot==0.19.8
|
||||
|
||||
# homeassistant.components.transport_nsw
|
||||
PyTransportNSW==0.1.1
|
||||
@ -47,7 +47,7 @@ PyTransportNSW==0.1.1
|
||||
PyTurboJPEG==1.6.7
|
||||
|
||||
# homeassistant.components.vicare
|
||||
PyViCare==2.16.2
|
||||
PyViCare==2.17.0
|
||||
|
||||
# homeassistant.components.xiaomi_aqara
|
||||
PyXiaomiGateway==0.13.4
|
||||
@ -134,7 +134,7 @@ aiobafi6==0.7.2
|
||||
aiobotocore==2.1.0
|
||||
|
||||
# homeassistant.components.dhcp
|
||||
aiodiscover==1.4.11
|
||||
aiodiscover==1.4.13
|
||||
|
||||
# homeassistant.components.dnsip
|
||||
# homeassistant.components.minecraft_server
|
||||
@ -171,7 +171,7 @@ aioguardian==2022.07.0
|
||||
aioharmony==0.2.9
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==1.5.6
|
||||
aiohomekit==1.5.7
|
||||
|
||||
# homeassistant.components.emulated_hue
|
||||
# homeassistant.components.http
|
||||
@ -408,13 +408,16 @@ bimmer_connected==0.10.2
|
||||
bizkaibus==0.1.1
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak==0.16.0
|
||||
bleak-retry-connector==1.15.1
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak==0.17.0
|
||||
|
||||
# homeassistant.components.blebox
|
||||
blebox_uniapi==2.0.2
|
||||
|
||||
# homeassistant.components.blink
|
||||
blinkpy==0.19.0
|
||||
blinkpy==0.19.2
|
||||
|
||||
# homeassistant.components.blinksticklight
|
||||
blinkstick==1.2.0
|
||||
@ -433,7 +436,7 @@ bluemaestro-ble==0.2.0
|
||||
bluetooth-adapters==0.4.1
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bluetooth-auto-recovery==0.3.2
|
||||
bluetooth-auto-recovery==0.3.3
|
||||
|
||||
# homeassistant.components.bond
|
||||
bond-async==0.1.22
|
||||
@ -534,6 +537,9 @@ datadog==0.15.0
|
||||
# homeassistant.components.metoffice
|
||||
datapoint==0.9.8
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
dbus-fast==1.4.0
|
||||
|
||||
# homeassistant.components.debugpy
|
||||
debugpy==1.6.3
|
||||
|
||||
@ -772,7 +778,7 @@ googlemaps==2.5.1
|
||||
goslide-api==0.5.1
|
||||
|
||||
# homeassistant.components.govee_ble
|
||||
govee-ble==0.17.2
|
||||
govee-ble==0.17.3
|
||||
|
||||
# homeassistant.components.remote_rpi_gpio
|
||||
gpiozero==1.6.2
|
||||
@ -851,7 +857,7 @@ hole==0.7.0
|
||||
holidays==0.14.2
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20220907.0
|
||||
home-assistant-frontend==20220907.1
|
||||
|
||||
# homeassistant.components.home_connect
|
||||
homeconnect==0.7.2
|
||||
@ -968,7 +974,7 @@ lakeside==0.12
|
||||
laundrify_aio==1.1.2
|
||||
|
||||
# homeassistant.components.led_ble
|
||||
led-ble==0.9.1
|
||||
led-ble==0.10.0
|
||||
|
||||
# homeassistant.components.foscam
|
||||
libpyfoscam==1.0
|
||||
@ -1608,7 +1614,7 @@ pyinsteon==1.2.0
|
||||
pyintesishome==1.8.0
|
||||
|
||||
# homeassistant.components.ipma
|
||||
pyipma==3.0.2
|
||||
pyipma==3.0.4
|
||||
|
||||
# homeassistant.components.ipp
|
||||
pyipp==0.11.0
|
||||
@ -2522,7 +2528,7 @@ xbox-webapi==2.0.11
|
||||
xboxapi==2.0.1
|
||||
|
||||
# homeassistant.components.xiaomi_ble
|
||||
xiaomi-ble==0.9.0
|
||||
xiaomi-ble==0.10.0
|
||||
|
||||
# homeassistant.components.knx
|
||||
xknx==1.0.2
|
||||
@ -2542,7 +2548,7 @@ xs1-api-client==3.0.0
|
||||
yalesmartalarmclient==0.3.9
|
||||
|
||||
# homeassistant.components.yalexs_ble
|
||||
yalexs-ble==1.8.1
|
||||
yalexs-ble==1.9.0
|
||||
|
||||
# homeassistant.components.august
|
||||
yalexs==1.2.1
|
||||
|
@ -33,7 +33,7 @@ PyRMVtransport==0.3.3
|
||||
PySocks==1.7.1
|
||||
|
||||
# homeassistant.components.switchbot
|
||||
PySwitchbot==0.19.5
|
||||
PySwitchbot==0.19.8
|
||||
|
||||
# homeassistant.components.transport_nsw
|
||||
PyTransportNSW==0.1.1
|
||||
@ -43,7 +43,7 @@ PyTransportNSW==0.1.1
|
||||
PyTurboJPEG==1.6.7
|
||||
|
||||
# homeassistant.components.vicare
|
||||
PyViCare==2.16.2
|
||||
PyViCare==2.17.0
|
||||
|
||||
# homeassistant.components.xiaomi_aqara
|
||||
PyXiaomiGateway==0.13.4
|
||||
@ -121,7 +121,7 @@ aiobafi6==0.7.2
|
||||
aiobotocore==2.1.0
|
||||
|
||||
# homeassistant.components.dhcp
|
||||
aiodiscover==1.4.11
|
||||
aiodiscover==1.4.13
|
||||
|
||||
# homeassistant.components.dnsip
|
||||
# homeassistant.components.minecraft_server
|
||||
@ -155,7 +155,7 @@ aioguardian==2022.07.0
|
||||
aioharmony==0.2.9
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==1.5.6
|
||||
aiohomekit==1.5.7
|
||||
|
||||
# homeassistant.components.emulated_hue
|
||||
# homeassistant.components.http
|
||||
@ -329,13 +329,16 @@ bellows==0.33.1
|
||||
bimmer_connected==0.10.2
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak==0.16.0
|
||||
bleak-retry-connector==1.15.1
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak==0.17.0
|
||||
|
||||
# homeassistant.components.blebox
|
||||
blebox_uniapi==2.0.2
|
||||
|
||||
# homeassistant.components.blink
|
||||
blinkpy==0.19.0
|
||||
blinkpy==0.19.2
|
||||
|
||||
# homeassistant.components.bluemaestro
|
||||
bluemaestro-ble==0.2.0
|
||||
@ -344,7 +347,7 @@ bluemaestro-ble==0.2.0
|
||||
bluetooth-adapters==0.4.1
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bluetooth-auto-recovery==0.3.2
|
||||
bluetooth-auto-recovery==0.3.3
|
||||
|
||||
# homeassistant.components.bond
|
||||
bond-async==0.1.22
|
||||
@ -411,6 +414,9 @@ datadog==0.15.0
|
||||
# homeassistant.components.metoffice
|
||||
datapoint==0.9.8
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
dbus-fast==1.4.0
|
||||
|
||||
# homeassistant.components.debugpy
|
||||
debugpy==1.6.3
|
||||
|
||||
@ -573,7 +579,7 @@ google-nest-sdm==2.0.0
|
||||
googlemaps==2.5.1
|
||||
|
||||
# homeassistant.components.govee_ble
|
||||
govee-ble==0.17.2
|
||||
govee-ble==0.17.3
|
||||
|
||||
# homeassistant.components.gree
|
||||
greeclimate==1.3.0
|
||||
@ -628,7 +634,7 @@ hole==0.7.0
|
||||
holidays==0.14.2
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20220907.0
|
||||
home-assistant-frontend==20220907.1
|
||||
|
||||
# homeassistant.components.home_connect
|
||||
homeconnect==0.7.2
|
||||
@ -706,7 +712,7 @@ lacrosse-view==0.0.9
|
||||
laundrify_aio==1.1.2
|
||||
|
||||
# homeassistant.components.led_ble
|
||||
led-ble==0.9.1
|
||||
led-ble==0.10.0
|
||||
|
||||
# homeassistant.components.foscam
|
||||
libpyfoscam==1.0
|
||||
@ -1121,7 +1127,7 @@ pyicloud==1.0.0
|
||||
pyinsteon==1.2.0
|
||||
|
||||
# homeassistant.components.ipma
|
||||
pyipma==3.0.2
|
||||
pyipma==3.0.4
|
||||
|
||||
# homeassistant.components.ipp
|
||||
pyipp==0.11.0
|
||||
@ -1729,7 +1735,7 @@ wolf_smartset==0.1.11
|
||||
xbox-webapi==2.0.11
|
||||
|
||||
# homeassistant.components.xiaomi_ble
|
||||
xiaomi-ble==0.9.0
|
||||
xiaomi-ble==0.10.0
|
||||
|
||||
# homeassistant.components.knx
|
||||
xknx==1.0.2
|
||||
@ -1746,7 +1752,7 @@ xmltodict==0.13.0
|
||||
yalesmartalarmclient==0.3.9
|
||||
|
||||
# homeassistant.components.yalexs_ble
|
||||
yalexs-ble==1.8.1
|
||||
yalexs-ble==1.9.0
|
||||
|
||||
# homeassistant.components.august
|
||||
yalexs==1.2.1
|
||||
|
@ -7,7 +7,7 @@ from bleak.backends.scanner import (
|
||||
AdvertisementDataCallback,
|
||||
BLEDevice,
|
||||
)
|
||||
from dbus_next import InvalidMessageError
|
||||
from dbus_fast import InvalidMessageError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import bluetooth
|
||||
|
@ -591,17 +591,15 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup):
|
||||
async def test_update_min_max(hass, hass_ws_client, storage_setup):
|
||||
"""Test updating min/max updates the state."""
|
||||
|
||||
items = [
|
||||
{
|
||||
"id": "from_storage",
|
||||
"initial": 15,
|
||||
"name": "from storage",
|
||||
"maximum": 100,
|
||||
"minimum": 10,
|
||||
"step": 3,
|
||||
"restore": True,
|
||||
}
|
||||
]
|
||||
settings = {
|
||||
"initial": 15,
|
||||
"name": "from storage",
|
||||
"maximum": 100,
|
||||
"minimum": 10,
|
||||
"step": 3,
|
||||
"restore": True,
|
||||
}
|
||||
items = [{"id": "from_storage"} | settings]
|
||||
assert await storage_setup(items)
|
||||
|
||||
input_id = "from_storage"
|
||||
@ -618,16 +616,18 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = settings | {"minimum": 19}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"minimum": 19,
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert int(state.state) == 19
|
||||
@ -635,18 +635,18 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup):
|
||||
assert state.attributes[ATTR_MAXIMUM] == 100
|
||||
assert state.attributes[ATTR_STEP] == 3
|
||||
|
||||
updated_settings = settings | {"maximum": 5, "minimum": 2, "step": 5}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 7,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"maximum": 5,
|
||||
"minimum": 2,
|
||||
"step": 5,
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert int(state.state) == 5
|
||||
@ -654,18 +654,18 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup):
|
||||
assert state.attributes[ATTR_MAXIMUM] == 5
|
||||
assert state.attributes[ATTR_STEP] == 5
|
||||
|
||||
updated_settings = settings | {"maximum": None, "minimum": None, "step": 6}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 8,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"maximum": None,
|
||||
"minimum": None,
|
||||
"step": 6,
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert int(state.state) == 5
|
||||
|
@ -20,6 +20,7 @@ from homeassistant.const import (
|
||||
ENERGY_MEGA_WATT_HOUR,
|
||||
ENERGY_WATT_HOUR,
|
||||
STATE_UNKNOWN,
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@ -841,10 +842,13 @@ async def test_cost_sensor_handle_price_units(
|
||||
assert state.state == "20.0"
|
||||
|
||||
|
||||
async def test_cost_sensor_handle_gas(hass, hass_storage, setup_integration) -> None:
|
||||
@pytest.mark.parametrize("unit", (VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS))
|
||||
async def test_cost_sensor_handle_gas(
|
||||
hass, hass_storage, setup_integration, unit
|
||||
) -> None:
|
||||
"""Test gas cost price from sensor entity."""
|
||||
energy_attributes = {
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_UNIT_OF_MEASUREMENT: unit,
|
||||
ATTR_STATE_CLASS: SensorStateClass.TOTAL_INCREASING,
|
||||
}
|
||||
energy_data = data.EnergyManager.default_preferences()
|
||||
|
@ -40,7 +40,11 @@ def storage_setup(hass, hass_storage):
|
||||
"data": {"items": [{"id": "from_storage", "name": "from storage"}]},
|
||||
}
|
||||
else:
|
||||
hass_storage[DOMAIN] = items
|
||||
hass_storage[DOMAIN] = {
|
||||
"key": DOMAIN,
|
||||
"version": 1,
|
||||
"data": {"items": items},
|
||||
}
|
||||
if config is None:
|
||||
config = {DOMAIN: {}}
|
||||
return await async_setup_component(hass, DOMAIN, config)
|
||||
@ -332,6 +336,89 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup):
|
||||
assert ent_reg.async_get_entity_id(DOMAIN, DOMAIN, input_id) is None
|
||||
|
||||
|
||||
async def test_ws_update(hass, hass_ws_client, storage_setup):
|
||||
"""Test update WS."""
|
||||
|
||||
settings = {
|
||||
"name": "from storage",
|
||||
}
|
||||
items = [{"id": "from_storage"} | settings]
|
||||
assert await storage_setup(items)
|
||||
|
||||
input_id = "from_storage"
|
||||
input_entity_id = f"{DOMAIN}.{input_id}"
|
||||
ent_reg = er.async_get(hass)
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state is not None
|
||||
assert state.state
|
||||
assert ent_reg.async_get_entity_id(DOMAIN, DOMAIN, input_id) is not None
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = settings | {"name": "new_name", "icon": "mdi:blah"}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state.attributes["icon"] == "mdi:blah"
|
||||
assert state.attributes["friendly_name"] == "new_name"
|
||||
|
||||
updated_settings = settings | {"name": "new_name_2"}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 7,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert "icon" not in state.attributes
|
||||
assert state.attributes["friendly_name"] == "new_name_2"
|
||||
|
||||
|
||||
async def test_ws_create(hass, hass_ws_client, storage_setup):
|
||||
"""Test create WS."""
|
||||
assert await storage_setup(items=[])
|
||||
|
||||
input_id = "new_input"
|
||||
input_entity_id = f"{DOMAIN}.{input_id}"
|
||||
ent_reg = er.async_get(hass)
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state is None
|
||||
assert ent_reg.async_get_entity_id(DOMAIN, DOMAIN, input_id) is None
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/create",
|
||||
"name": "New Input",
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state.state
|
||||
|
||||
|
||||
async def test_setup_no_config(hass, hass_admin_user):
|
||||
"""Test component setup with no config."""
|
||||
count_start = len(hass.states.async_entity_ids())
|
||||
|
@ -305,6 +305,7 @@ async def test_ws_create_update(hass, hass_ws_client, storage_setup):
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "new", "name": "newer"}
|
||||
|
||||
state = hass.states.get(f"{DOMAIN}.new")
|
||||
assert state is not None
|
||||
|
@ -583,17 +583,23 @@ async def test_update(hass, hass_ws_client, storage_setup):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = {
|
||||
CONF_NAME: "even newer name",
|
||||
CONF_HAS_DATE: False,
|
||||
CONF_HAS_TIME: True,
|
||||
CONF_INITIAL: INITIAL_DATETIME,
|
||||
}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
ATTR_NAME: "even newer name",
|
||||
CONF_HAS_DATE: False,
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state.state == INITIAL_TIME
|
||||
|
@ -416,7 +416,7 @@ async def test_load_from_storage(hass, storage_setup):
|
||||
"""Test set up from storage."""
|
||||
assert await storage_setup()
|
||||
state = hass.states.get(f"{DOMAIN}.from_storage")
|
||||
assert float(state.state) == 10
|
||||
assert float(state.state) == 0 # initial is not supported when loading from storage
|
||||
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "from storage"
|
||||
assert state.attributes.get(ATTR_EDITABLE)
|
||||
|
||||
@ -438,7 +438,7 @@ async def test_editable_state_attribute(hass, storage_setup):
|
||||
)
|
||||
|
||||
state = hass.states.get(f"{DOMAIN}.from_storage")
|
||||
assert float(state.state) == 10
|
||||
assert float(state.state) == 0
|
||||
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "from storage"
|
||||
assert state.attributes.get(ATTR_EDITABLE)
|
||||
|
||||
@ -507,16 +507,14 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup):
|
||||
async def test_update_min_max(hass, hass_ws_client, storage_setup):
|
||||
"""Test updating min/max updates the state."""
|
||||
|
||||
items = [
|
||||
{
|
||||
"id": "from_storage",
|
||||
"name": "from storage",
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"step": 1,
|
||||
"mode": "slider",
|
||||
}
|
||||
]
|
||||
settings = {
|
||||
"name": "from storage",
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"step": 1,
|
||||
"mode": "slider",
|
||||
}
|
||||
items = [{"id": "from_storage"} | settings]
|
||||
assert await storage_setup(items)
|
||||
|
||||
input_id = "from_storage"
|
||||
@ -530,26 +528,34 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = settings | {"min": 9}
|
||||
await client.send_json(
|
||||
{"id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", "min": 9}
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert float(state.state) == 9
|
||||
|
||||
updated_settings = settings | {"max": 5}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 7,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"max": 5,
|
||||
"min": 0,
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert float(state.state) == 5
|
||||
|
@ -628,13 +628,11 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup):
|
||||
async def test_update(hass, hass_ws_client, storage_setup):
|
||||
"""Test updating options updates the state."""
|
||||
|
||||
items = [
|
||||
{
|
||||
"id": "from_storage",
|
||||
"name": "from storage",
|
||||
"options": ["yaml update 1", "yaml update 2"],
|
||||
}
|
||||
]
|
||||
settings = {
|
||||
"name": "from storage",
|
||||
"options": ["yaml update 1", "yaml update 2"],
|
||||
}
|
||||
items = [{"id": "from_storage"} | settings]
|
||||
assert await storage_setup(items)
|
||||
|
||||
input_id = "from_storage"
|
||||
@ -647,28 +645,36 @@ async def test_update(hass, hass_ws_client, storage_setup):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = settings | {
|
||||
"options": ["new option", "newer option"],
|
||||
CONF_INITIAL: "newer option",
|
||||
}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"options": ["new option", "newer option"],
|
||||
CONF_INITIAL: "newer option",
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state.attributes[ATTR_OPTIONS] == ["new option", "newer option"]
|
||||
|
||||
# Should fail because the initial state is now invalid
|
||||
updated_settings = settings | {
|
||||
"options": ["new option", "no newer option"],
|
||||
CONF_INITIAL: "newer option",
|
||||
}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 7,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"options": ["new option", "no newer option"],
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
@ -678,13 +684,11 @@ async def test_update(hass, hass_ws_client, storage_setup):
|
||||
async def test_update_duplicates(hass, hass_ws_client, storage_setup, caplog):
|
||||
"""Test updating options updates the state."""
|
||||
|
||||
items = [
|
||||
{
|
||||
"id": "from_storage",
|
||||
"name": "from storage",
|
||||
"options": ["yaml update 1", "yaml update 2"],
|
||||
}
|
||||
]
|
||||
settings = {
|
||||
"name": "from storage",
|
||||
"options": ["yaml update 1", "yaml update 2"],
|
||||
}
|
||||
items = [{"id": "from_storage"} | settings]
|
||||
assert await storage_setup(items)
|
||||
|
||||
input_id = "from_storage"
|
||||
@ -697,13 +701,16 @@ async def test_update_duplicates(hass, hass_ws_client, storage_setup, caplog):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = settings | {
|
||||
"options": ["new option", "newer option", "newer option"],
|
||||
CONF_INITIAL: "newer option",
|
||||
}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
"options": ["new option", "newer option", "newer option"],
|
||||
CONF_INITIAL: "newer option",
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
|
@ -432,19 +432,24 @@ async def test_update(hass, hass_ws_client, storage_setup):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = {
|
||||
ATTR_NAME: "even newer name",
|
||||
CONF_INITIAL: "newer option",
|
||||
ATTR_MAX: TEST_VAL_MAX,
|
||||
ATTR_MIN: 6,
|
||||
ATTR_MODE: "password",
|
||||
}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{input_id}",
|
||||
ATTR_NAME: "even newer name",
|
||||
CONF_INITIAL: "newer option",
|
||||
ATTR_MIN: 6,
|
||||
ATTR_MODE: "password",
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {"id": "from_storage"} | updated_settings
|
||||
|
||||
state = hass.states.get(input_entity_id)
|
||||
assert state.state == "loaded from storage"
|
||||
|
@ -168,7 +168,7 @@ async def test_config_entry_migration(hass):
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ipma.weather.async_get_location",
|
||||
"pyipma.location.Location.get",
|
||||
return_value=MockLocation(),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
|
@ -19,7 +19,6 @@ from homeassistant.components.weather import (
|
||||
ATTR_WEATHER_TEMPERATURE,
|
||||
ATTR_WEATHER_WIND_BEARING,
|
||||
ATTR_WEATHER_WIND_SPEED,
|
||||
DOMAIN as WEATHER_DOMAIN,
|
||||
)
|
||||
from homeassistant.const import STATE_UNKNOWN
|
||||
|
||||
@ -181,7 +180,8 @@ async def test_setup_config_flow(hass):
|
||||
return_value=MockLocation(),
|
||||
):
|
||||
entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG)
|
||||
await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("weather.hometown")
|
||||
@ -203,7 +203,8 @@ async def test_daily_forecast(hass):
|
||||
return_value=MockLocation(),
|
||||
):
|
||||
entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG)
|
||||
await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("weather.hometown")
|
||||
@ -227,7 +228,8 @@ async def test_hourly_forecast(hass):
|
||||
return_value=MockLocation(),
|
||||
):
|
||||
entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG_HOURLY)
|
||||
await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("weather.hometown")
|
||||
@ -248,7 +250,8 @@ async def test_failed_get_observation_forecast(hass):
|
||||
return_value=MockBadLocation(),
|
||||
):
|
||||
entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG)
|
||||
await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("weather.hometown")
|
||||
|
@ -41,7 +41,7 @@ def find_log(logs, level):
|
||||
if not isinstance(level, tuple):
|
||||
level = (level,)
|
||||
log = next(
|
||||
(log for log in logs if log["level"] in level),
|
||||
(log for log in logs if log["level"] in level and log["name"] != "asyncio"),
|
||||
None,
|
||||
)
|
||||
assert log is not None
|
||||
|
@ -585,17 +585,27 @@ async def test_update(hass, hass_ws_client, storage_setup):
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
updated_settings = {
|
||||
CONF_NAME: "timer from storage",
|
||||
CONF_DURATION: 33,
|
||||
CONF_RESTORE: True,
|
||||
}
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 6,
|
||||
"type": f"{DOMAIN}/update",
|
||||
f"{DOMAIN}_id": f"{timer_id}",
|
||||
CONF_DURATION: 33,
|
||||
CONF_RESTORE: True,
|
||||
**updated_settings,
|
||||
}
|
||||
)
|
||||
resp = await client.receive_json()
|
||||
assert resp["success"]
|
||||
assert resp["result"] == {
|
||||
"id": "from_storage",
|
||||
CONF_DURATION: "0:00:33",
|
||||
CONF_NAME: "timer from storage",
|
||||
CONF_RESTORE: True,
|
||||
}
|
||||
|
||||
state = hass.states.get(timer_entity_id)
|
||||
assert state.attributes[ATTR_DURATION] == _format_timedelta(cv.time_period(33))
|
||||
|
@ -45,10 +45,10 @@ async def test_smoke_sensor(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
smoke_sensor = hass.states.get("binary_sensor.thermometer_e39cbc_smoke")
|
||||
smoke_sensor = hass.states.get("binary_sensor.thermometer_9cbc_smoke")
|
||||
smoke_sensor_attribtes = smoke_sensor.attributes
|
||||
assert smoke_sensor.state == "on"
|
||||
assert smoke_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Thermometer E39CBC Smoke"
|
||||
assert smoke_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Thermometer 9CBC Smoke"
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -90,10 +90,10 @@ async def test_moisture(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
sensor = hass.states.get("binary_sensor.smart_flower_pot_6a3e7a_moisture")
|
||||
sensor = hass.states.get("binary_sensor.smart_flower_pot_3e7a_moisture")
|
||||
sensor_attr = sensor.attributes
|
||||
assert sensor.state == "on"
|
||||
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Moisture"
|
||||
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Moisture"
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -39,7 +39,7 @@ async def test_async_step_bluetooth_valid_device(hass):
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Baby Thermometer DD6FC1 (MMC-T201-1)"
|
||||
assert result2["title"] == "Baby Thermometer 6FC1 (MMC-T201-1)"
|
||||
assert result2["data"] == {}
|
||||
assert result2["result"].unique_id == "00:81:F9:DD:6F:C1"
|
||||
|
||||
@ -65,7 +65,7 @@ async def test_async_step_bluetooth_valid_device_but_missing_payload(hass):
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Temperature/Humidity Sensor 565384 (LYWSD03MMC)"
|
||||
assert result2["title"] == "Temperature/Humidity Sensor 5384 (LYWSD03MMC)"
|
||||
assert result2["data"] == {}
|
||||
assert result2["result"].unique_id == "A4:C1:38:56:53:84"
|
||||
|
||||
@ -123,7 +123,7 @@ async def test_async_step_bluetooth_during_onboarding(hass):
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Baby Thermometer DD6FC1 (MMC-T201-1)"
|
||||
assert result["title"] == "Baby Thermometer 6FC1 (MMC-T201-1)"
|
||||
assert result["data"] == {}
|
||||
assert result["result"].unique_id == "00:81:F9:DD:6F:C1"
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
@ -148,7 +148,7 @@ async def test_async_step_bluetooth_valid_device_legacy_encryption(hass):
|
||||
user_input={"bindkey": "b853075158487ca39a5b5ea9"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"}
|
||||
assert result2["result"].unique_id == "F8:24:41:C5:98:8B"
|
||||
|
||||
@ -180,7 +180,7 @@ async def test_async_step_bluetooth_valid_device_legacy_encryption_wrong_key(has
|
||||
user_input={"bindkey": "b853075158487ca39a5b5ea9"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"}
|
||||
assert result2["result"].unique_id == "F8:24:41:C5:98:8B"
|
||||
|
||||
@ -214,7 +214,7 @@ async def test_async_step_bluetooth_valid_device_legacy_encryption_wrong_key_len
|
||||
user_input={"bindkey": "b853075158487ca39a5b5ea9"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"}
|
||||
assert result2["result"].unique_id == "F8:24:41:C5:98:8B"
|
||||
|
||||
@ -238,7 +238,7 @@ async def test_async_step_bluetooth_valid_device_v4_encryption(hass):
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)"
|
||||
assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)"
|
||||
assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"}
|
||||
assert result2["result"].unique_id == "54:EF:44:E3:9C:BC"
|
||||
|
||||
@ -272,7 +272,7 @@ async def test_async_step_bluetooth_valid_device_v4_encryption_wrong_key(hass):
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)"
|
||||
assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)"
|
||||
assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"}
|
||||
assert result2["result"].unique_id == "54:EF:44:E3:9C:BC"
|
||||
|
||||
@ -306,7 +306,7 @@ async def test_async_step_bluetooth_valid_device_v4_encryption_wrong_key_length(
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)"
|
||||
assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)"
|
||||
assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"}
|
||||
assert result2["result"].unique_id == "54:EF:44:E3:9C:BC"
|
||||
|
||||
@ -370,7 +370,7 @@ async def test_async_step_user_with_found_devices(hass):
|
||||
user_input={"address": "58:2D:34:35:93:21"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Temperature/Humidity Sensor 359321 (LYWSDCGQ)"
|
||||
assert result2["title"] == "Temperature/Humidity Sensor 9321 (LYWSDCGQ)"
|
||||
assert result2["data"] == {}
|
||||
assert result2["result"].unique_id == "58:2D:34:35:93:21"
|
||||
|
||||
@ -405,7 +405,7 @@ async def test_async_step_user_short_payload(hass):
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result3["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == "Temperature/Humidity Sensor 565384 (LYWSD03MMC)"
|
||||
assert result3["title"] == "Temperature/Humidity Sensor 5384 (LYWSD03MMC)"
|
||||
assert result3["data"] == {}
|
||||
assert result3["result"].unique_id == "A4:C1:38:56:53:84"
|
||||
|
||||
@ -453,7 +453,7 @@ async def test_async_step_user_short_payload_then_full(hass):
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Temperature/Humidity Sensor 565384 (LYWSD03MMC)"
|
||||
assert result2["title"] == "Temperature/Humidity Sensor 5384 (LYWSD03MMC)"
|
||||
assert result2["data"] == {"bindkey": "a115210eed7a88e50ad52662e732a9fb"}
|
||||
|
||||
|
||||
@ -486,7 +486,7 @@ async def test_async_step_user_with_found_devices_v4_encryption(hass):
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)"
|
||||
assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)"
|
||||
assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"}
|
||||
assert result2["result"].unique_id == "54:EF:44:E3:9C:BC"
|
||||
|
||||
@ -532,7 +532,7 @@ async def test_async_step_user_with_found_devices_v4_encryption_wrong_key(hass):
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)"
|
||||
assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)"
|
||||
assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"}
|
||||
assert result2["result"].unique_id == "54:EF:44:E3:9C:BC"
|
||||
|
||||
@ -580,7 +580,7 @@ async def test_async_step_user_with_found_devices_v4_encryption_wrong_key_length
|
||||
)
|
||||
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)"
|
||||
assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)"
|
||||
assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"}
|
||||
assert result2["result"].unique_id == "54:EF:44:E3:9C:BC"
|
||||
|
||||
@ -613,7 +613,7 @@ async def test_async_step_user_with_found_devices_legacy_encryption(hass):
|
||||
user_input={"bindkey": "b853075158487ca39a5b5ea9"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"}
|
||||
assert result2["result"].unique_id == "F8:24:41:C5:98:8B"
|
||||
|
||||
@ -658,7 +658,7 @@ async def test_async_step_user_with_found_devices_legacy_encryption_wrong_key(
|
||||
user_input={"bindkey": "b853075158487ca39a5b5ea9"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"}
|
||||
assert result2["result"].unique_id == "F8:24:41:C5:98:8B"
|
||||
|
||||
@ -703,7 +703,7 @@ async def test_async_step_user_with_found_devices_legacy_encryption_wrong_key_le
|
||||
user_input={"bindkey": "b853075158487ca39a5b5ea9"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)"
|
||||
assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"}
|
||||
assert result2["result"].unique_id == "F8:24:41:C5:98:8B"
|
||||
|
||||
@ -822,7 +822,7 @@ async def test_async_step_user_takes_precedence_over_discovery(hass):
|
||||
user_input={"address": "00:81:F9:DD:6F:C1"},
|
||||
)
|
||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == "Baby Thermometer DD6FC1 (MMC-T201-1)"
|
||||
assert result2["title"] == "Baby Thermometer 6FC1 (MMC-T201-1)"
|
||||
assert result2["data"] == {}
|
||||
assert result2["result"].unique_id == "00:81:F9:DD:6F:C1"
|
||||
|
||||
|
@ -42,12 +42,11 @@ async def test_sensors(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 2
|
||||
|
||||
temp_sensor = hass.states.get("sensor.baby_thermometer_dd6fc1_temperature")
|
||||
temp_sensor = hass.states.get("sensor.baby_thermometer_6fc1_temperature")
|
||||
temp_sensor_attribtes = temp_sensor.attributes
|
||||
assert temp_sensor.state == "36.8719980616822"
|
||||
assert (
|
||||
temp_sensor_attribtes[ATTR_FRIENDLY_NAME]
|
||||
== "Baby Thermometer DD6FC1 Temperature"
|
||||
temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Baby Thermometer 6FC1 Temperature"
|
||||
)
|
||||
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C"
|
||||
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
@ -92,10 +91,10 @@ async def test_xiaomi_formaldeyhde(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_formaldehyde")
|
||||
sensor = hass.states.get("sensor.smart_flower_pot_3e7a_formaldehyde")
|
||||
sensor_attr = sensor.attributes
|
||||
assert sensor.state == "2.44"
|
||||
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Formaldehyde"
|
||||
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Formaldehyde"
|
||||
assert sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "mg/m³"
|
||||
assert sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
@ -139,10 +138,10 @@ async def test_xiaomi_consumable(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_consumable")
|
||||
sensor = hass.states.get("sensor.smart_flower_pot_3e7a_consumable")
|
||||
sensor_attr = sensor.attributes
|
||||
assert sensor.state == "96"
|
||||
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Consumable"
|
||||
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Consumable"
|
||||
assert sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
@ -186,17 +185,17 @@ async def test_xiaomi_battery_voltage(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 2
|
||||
|
||||
volt_sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_voltage")
|
||||
volt_sensor = hass.states.get("sensor.smart_flower_pot_3e7a_voltage")
|
||||
volt_sensor_attr = volt_sensor.attributes
|
||||
assert volt_sensor.state == "3.1"
|
||||
assert volt_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Voltage"
|
||||
assert volt_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Voltage"
|
||||
assert volt_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "V"
|
||||
assert volt_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
bat_sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_battery")
|
||||
bat_sensor = hass.states.get("sensor.smart_flower_pot_3e7a_battery")
|
||||
bat_sensor_attr = bat_sensor.attributes
|
||||
assert bat_sensor.state == "100"
|
||||
assert bat_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Battery"
|
||||
assert bat_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Battery"
|
||||
assert bat_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert bat_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
@ -254,42 +253,38 @@ async def test_xiaomi_HHCCJCY01(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 5
|
||||
|
||||
illum_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_illuminance")
|
||||
illum_sensor = hass.states.get("sensor.plant_sensor_3e7a_illuminance")
|
||||
illum_sensor_attr = illum_sensor.attributes
|
||||
assert illum_sensor.state == "0"
|
||||
assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Illuminance"
|
||||
assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Illuminance"
|
||||
assert illum_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx"
|
||||
assert illum_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
cond_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_conductivity")
|
||||
cond_sensor = hass.states.get("sensor.plant_sensor_3e7a_conductivity")
|
||||
cond_sensor_attribtes = cond_sensor.attributes
|
||||
assert cond_sensor.state == "599"
|
||||
assert (
|
||||
cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Conductivity"
|
||||
)
|
||||
assert cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Conductivity"
|
||||
assert cond_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm"
|
||||
assert cond_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
moist_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_moisture")
|
||||
moist_sensor = hass.states.get("sensor.plant_sensor_3e7a_moisture")
|
||||
moist_sensor_attribtes = moist_sensor.attributes
|
||||
assert moist_sensor.state == "64"
|
||||
assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Moisture"
|
||||
assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Moisture"
|
||||
assert moist_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert moist_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
temp_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_temperature")
|
||||
temp_sensor = hass.states.get("sensor.plant_sensor_3e7a_temperature")
|
||||
temp_sensor_attribtes = temp_sensor.attributes
|
||||
assert temp_sensor.state == "24.4"
|
||||
assert (
|
||||
temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Temperature"
|
||||
)
|
||||
assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Temperature"
|
||||
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C"
|
||||
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
batt_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_battery")
|
||||
batt_sensor = hass.states.get("sensor.plant_sensor_3e7a_battery")
|
||||
batt_sensor_attribtes = batt_sensor.attributes
|
||||
assert batt_sensor.state == "5"
|
||||
assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Battery"
|
||||
assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Battery"
|
||||
assert batt_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert batt_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
@ -355,35 +350,31 @@ async def test_xiaomi_HHCCJCY01_not_connectable(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 4
|
||||
|
||||
illum_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_illuminance")
|
||||
illum_sensor = hass.states.get("sensor.plant_sensor_3e7a_illuminance")
|
||||
illum_sensor_attr = illum_sensor.attributes
|
||||
assert illum_sensor.state == "0"
|
||||
assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Illuminance"
|
||||
assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Illuminance"
|
||||
assert illum_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx"
|
||||
assert illum_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
cond_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_conductivity")
|
||||
cond_sensor = hass.states.get("sensor.plant_sensor_3e7a_conductivity")
|
||||
cond_sensor_attribtes = cond_sensor.attributes
|
||||
assert cond_sensor.state == "599"
|
||||
assert (
|
||||
cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Conductivity"
|
||||
)
|
||||
assert cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Conductivity"
|
||||
assert cond_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm"
|
||||
assert cond_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
moist_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_moisture")
|
||||
moist_sensor = hass.states.get("sensor.plant_sensor_3e7a_moisture")
|
||||
moist_sensor_attribtes = moist_sensor.attributes
|
||||
assert moist_sensor.state == "64"
|
||||
assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Moisture"
|
||||
assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Moisture"
|
||||
assert moist_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert moist_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
temp_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_temperature")
|
||||
temp_sensor = hass.states.get("sensor.plant_sensor_3e7a_temperature")
|
||||
temp_sensor_attribtes = temp_sensor.attributes
|
||||
assert temp_sensor.state == "24.4"
|
||||
assert (
|
||||
temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Temperature"
|
||||
)
|
||||
assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Temperature"
|
||||
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C"
|
||||
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
@ -438,42 +429,38 @@ async def test_xiaomi_HHCCJCY01_only_some_sources_connectable(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 5
|
||||
|
||||
illum_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_illuminance")
|
||||
illum_sensor = hass.states.get("sensor.plant_sensor_3e7a_illuminance")
|
||||
illum_sensor_attr = illum_sensor.attributes
|
||||
assert illum_sensor.state == "0"
|
||||
assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Illuminance"
|
||||
assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Illuminance"
|
||||
assert illum_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx"
|
||||
assert illum_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
cond_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_conductivity")
|
||||
cond_sensor = hass.states.get("sensor.plant_sensor_3e7a_conductivity")
|
||||
cond_sensor_attribtes = cond_sensor.attributes
|
||||
assert cond_sensor.state == "599"
|
||||
assert (
|
||||
cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Conductivity"
|
||||
)
|
||||
assert cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Conductivity"
|
||||
assert cond_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm"
|
||||
assert cond_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
moist_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_moisture")
|
||||
moist_sensor = hass.states.get("sensor.plant_sensor_3e7a_moisture")
|
||||
moist_sensor_attribtes = moist_sensor.attributes
|
||||
assert moist_sensor.state == "64"
|
||||
assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Moisture"
|
||||
assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Moisture"
|
||||
assert moist_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert moist_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
temp_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_temperature")
|
||||
temp_sensor = hass.states.get("sensor.plant_sensor_3e7a_temperature")
|
||||
temp_sensor_attribtes = temp_sensor.attributes
|
||||
assert temp_sensor.state == "24.4"
|
||||
assert (
|
||||
temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Temperature"
|
||||
)
|
||||
assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Temperature"
|
||||
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C"
|
||||
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
batt_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_battery")
|
||||
batt_sensor = hass.states.get("sensor.plant_sensor_3e7a_battery")
|
||||
batt_sensor_attribtes = batt_sensor.attributes
|
||||
assert batt_sensor.state == "5"
|
||||
assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Battery"
|
||||
assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Battery"
|
||||
assert batt_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||
assert batt_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
||||
@ -515,14 +502,12 @@ async def test_xiaomi_CGDK2(hass):
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
temp_sensor = hass.states.get(
|
||||
"sensor.temperature_humidity_sensor_122089_temperature"
|
||||
)
|
||||
temp_sensor = hass.states.get("sensor.temperature_humidity_sensor_2089_temperature")
|
||||
temp_sensor_attribtes = temp_sensor.attributes
|
||||
assert temp_sensor.state == "22.6"
|
||||
assert (
|
||||
temp_sensor_attribtes[ATTR_FRIENDLY_NAME]
|
||||
== "Temperature/Humidity Sensor 122089 Temperature"
|
||||
== "Temperature/Humidity Sensor 2089 Temperature"
|
||||
)
|
||||
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C"
|
||||
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
|
||||
|
@ -178,7 +178,7 @@ async def device_light_2(hass, zigpy_device_mock, zha_device_joined):
|
||||
}
|
||||
},
|
||||
ieee=IEEE_GROUPABLE_DEVICE2,
|
||||
manufacturer="Sengled",
|
||||
manufacturer="sengled",
|
||||
nwk=0xC79E,
|
||||
)
|
||||
color_cluster = zigpy_device.endpoints[1].light_color
|
||||
|
@ -5493,7 +5493,7 @@ DEVICES = [
|
||||
DEV_SIG_EVT_CHANNELS: ["1:0x0019"],
|
||||
DEV_SIG_ENTITIES: [
|
||||
"button.sengled_e11_g13_identifybutton",
|
||||
"light.sengled_e11_g13_light",
|
||||
"light.sengled_e11_g13_mintransitionlight",
|
||||
"sensor.sengled_e11_g13_smartenergymetering",
|
||||
"sensor.sengled_e11_g13_smartenergysummation",
|
||||
"sensor.sengled_e11_g13_rssi",
|
||||
@ -5502,8 +5502,8 @@ DEVICES = [
|
||||
DEV_SIG_ENT_MAP: {
|
||||
("light", "00:11:22:33:44:55:66:77-1"): {
|
||||
DEV_SIG_CHANNELS: ["on_off", "level"],
|
||||
DEV_SIG_ENT_MAP_CLASS: "Light",
|
||||
DEV_SIG_ENT_MAP_ID: "light.sengled_e11_g13_light",
|
||||
DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight",
|
||||
DEV_SIG_ENT_MAP_ID: "light.sengled_e11_g13_mintransitionlight",
|
||||
},
|
||||
("button", "00:11:22:33:44:55:66:77-1-3"): {
|
||||
DEV_SIG_CHANNELS: ["identify"],
|
||||
@ -5549,7 +5549,7 @@ DEVICES = [
|
||||
DEV_SIG_EVT_CHANNELS: ["1:0x0019"],
|
||||
DEV_SIG_ENTITIES: [
|
||||
"button.sengled_e12_n14_identifybutton",
|
||||
"light.sengled_e12_n14_light",
|
||||
"light.sengled_e12_n14_mintransitionlight",
|
||||
"sensor.sengled_e12_n14_smartenergymetering",
|
||||
"sensor.sengled_e12_n14_smartenergysummation",
|
||||
"sensor.sengled_e12_n14_rssi",
|
||||
@ -5558,8 +5558,8 @@ DEVICES = [
|
||||
DEV_SIG_ENT_MAP: {
|
||||
("light", "00:11:22:33:44:55:66:77-1"): {
|
||||
DEV_SIG_CHANNELS: ["on_off", "level"],
|
||||
DEV_SIG_ENT_MAP_CLASS: "Light",
|
||||
DEV_SIG_ENT_MAP_ID: "light.sengled_e12_n14_light",
|
||||
DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight",
|
||||
DEV_SIG_ENT_MAP_ID: "light.sengled_e12_n14_mintransitionlight",
|
||||
},
|
||||
("button", "00:11:22:33:44:55:66:77-1-3"): {
|
||||
DEV_SIG_CHANNELS: ["identify"],
|
||||
@ -5605,7 +5605,7 @@ DEVICES = [
|
||||
DEV_SIG_EVT_CHANNELS: ["1:0x0019"],
|
||||
DEV_SIG_ENTITIES: [
|
||||
"button.sengled_z01_a19nae26_identifybutton",
|
||||
"light.sengled_z01_a19nae26_light",
|
||||
"light.sengled_z01_a19nae26_mintransitionlight",
|
||||
"sensor.sengled_z01_a19nae26_smartenergymetering",
|
||||
"sensor.sengled_z01_a19nae26_smartenergysummation",
|
||||
"sensor.sengled_z01_a19nae26_rssi",
|
||||
@ -5614,8 +5614,8 @@ DEVICES = [
|
||||
DEV_SIG_ENT_MAP: {
|
||||
("light", "00:11:22:33:44:55:66:77-1"): {
|
||||
DEV_SIG_CHANNELS: ["on_off", "level", "light_color"],
|
||||
DEV_SIG_ENT_MAP_CLASS: "Light",
|
||||
DEV_SIG_ENT_MAP_ID: "light.sengled_z01_a19nae26_light",
|
||||
DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight",
|
||||
DEV_SIG_ENT_MAP_ID: "light.sengled_z01_a19nae26_mintransitionlight",
|
||||
},
|
||||
("button", "00:11:22:33:44:55:66:77-1-3"): {
|
||||
DEV_SIG_CHANNELS: ["identify"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user