diff --git a/homeassistant/components/homematicip_cloud/__init__.py b/homeassistant/components/homematicip_cloud/__init__.py index 2b078966ee8..7ea6a4fe0b4 100644 --- a/homeassistant/components/homematicip_cloud/__init__.py +++ b/homeassistant/components/homematicip_cloud/__init__.py @@ -1,11 +1,14 @@ """Support for HomematicIP Cloud devices.""" +import logging + import voluptuous as vol from homeassistant import config_entries from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_NAME, EVENT_HOMEASSISTANT_STOP -from homeassistant.helpers import device_registry as dr +from homeassistant.helpers import device_registry as dr, entity_registry as er import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity_registry import async_entries_for_config_entry from homeassistant.helpers.typing import ConfigType, HomeAssistantType from .const import ( @@ -20,6 +23,8 @@ from .generic_entity import HomematicipGenericEntity # noqa: F401 from .hap import HomematicipAuth, HomematicipHAP # noqa: F401 from .services import async_setup_services, async_unload_services +_LOGGER = logging.getLogger(__name__) + CONFIG_SCHEMA = vol.Schema( { vol.Optional(DOMAIN, default=[]): vol.All( @@ -83,6 +88,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool return False await async_setup_services(hass) + await async_remove_obsolete_entities(hass, entry, hap) # Register on HA stop event to gracefully shutdown HomematicIP Cloud connection hap.reset_connection_listener = hass.bus.async_listen_once( @@ -91,16 +97,16 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool # Register hap as device in registry. device_registry = await dr.async_get_registry(hass) + home = hap.home - # Add the HAP name from configuration if set. - hapname = home.label if not home.name else f"{home.name} {home.label}" + hapname = home.label if home.label != entry.unique_id else f"Home-{home.label}" + device_registry.async_get_or_create( config_entry_id=entry.entry_id, identifiers={(DOMAIN, home.id)}, manufacturer="eQ-3", + # Add the name from config entry. name=hapname, - model=home.modelType, - sw_version=home.currentAPVersion, ) return True @@ -113,3 +119,23 @@ async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> boo await async_unload_services(hass) return await hap.async_reset() + + +async def async_remove_obsolete_entities( + hass: HomeAssistantType, entry: ConfigEntry, hap: HomematicipHAP +): + """Remove obsolete entities from entity registry.""" + + if hap.home.currentAPVersion < "2.2.12": + return + + entity_registry = await er.async_get_registry(hass) + er_entries = async_entries_for_config_entry(entity_registry, entry.entry_id) + for er_entry in er_entries: + if er_entry.unique_id.startswith("HomematicipAccesspointStatus"): + entity_registry.async_remove(er_entry.entity_id) + continue + + for hapid in hap.home.accessPointUpdateStates: + if er_entry.unique_id == f"HomematicipBatterySensor_{hapid}": + entity_registry.async_remove(er_entry.entity_id) diff --git a/homeassistant/components/homematicip_cloud/binary_sensor.py b/homeassistant/components/homematicip_cloud/binary_sensor.py index e03738e4a76..12bca8378c3 100644 --- a/homeassistant/components/homematicip_cloud/binary_sensor.py +++ b/homeassistant/components/homematicip_cloud/binary_sensor.py @@ -146,7 +146,15 @@ class HomematicipCloudConnectionSensor(HomematicipGenericEntity, BinarySensorEnt def __init__(self, hap: HomematicipHAP) -> None: """Initialize the cloud connection sensor.""" - super().__init__(hap, hap.home, "Cloud Connection") + super().__init__(hap, hap.home) + + @property + def name(self) -> str: + """Return the name cloud connection entity.""" + + name = "Cloud Connection" + # Add a prefix to the name if the homematic ip home has a name. + return name if not self._home.name else f"{self._home.name} {name}" @property def device_info(self) -> Dict[str, Any]: diff --git a/homeassistant/components/homematicip_cloud/hap.py b/homeassistant/components/homematicip_cloud/hap.py index 164997d5582..151807391b9 100644 --- a/homeassistant/components/homematicip_cloud/hap.py +++ b/homeassistant/components/homematicip_cloud/hap.py @@ -240,8 +240,9 @@ class HomematicipHAP: home = AsyncHome(hass.loop, async_get_clientsession(hass)) home.name = name - home.label = "Access Point" - home.modelType = "HmIP-HAP" + # Use the title of the config entry as title for the home. + home.label = self.config_entry.title + home.modelType = "HomematicIP Cloud Home" home.set_auth_token(authtoken) try: diff --git a/homeassistant/components/homematicip_cloud/manifest.json b/homeassistant/components/homematicip_cloud/manifest.json index 3ecf668e449..30ca5165c85 100644 --- a/homeassistant/components/homematicip_cloud/manifest.json +++ b/homeassistant/components/homematicip_cloud/manifest.json @@ -3,7 +3,7 @@ "name": "HomematicIP Cloud", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/homematicip_cloud", - "requirements": ["homematicip==0.11.0"], + "requirements": ["homematicip==0.12.1"], "codeowners": ["@SukramJ"], "quality_scale": "platinum" } diff --git a/homeassistant/components/homematicip_cloud/sensor.py b/homeassistant/components/homematicip_cloud/sensor.py index 66e0e1afd70..9e202302c10 100644 --- a/homeassistant/components/homematicip_cloud/sensor.py +++ b/homeassistant/components/homematicip_cloud/sensor.py @@ -6,6 +6,7 @@ from homematicip.aio.device import ( AsyncFullFlushSwitchMeasuring, AsyncHeatingThermostat, AsyncHeatingThermostatCompact, + AsyncHomeControlAccessPoint, AsyncLightSensor, AsyncMotionDetectorIndoor, AsyncMotionDetectorOutdoor, @@ -39,7 +40,6 @@ from homeassistant.const import ( from homeassistant.helpers.typing import HomeAssistantType from . import DOMAIN as HMIPC_DOMAIN, HomematicipGenericEntity -from .generic_entity import ATTR_IS_GROUP, ATTR_MODEL_TYPE from .hap import HomematicipHAP ATTR_CURRENT_ILLUMINATION = "current_illumination" @@ -63,8 +63,10 @@ async def async_setup_entry( ) -> None: """Set up the HomematicIP Cloud sensors from a config entry.""" hap = hass.data[HMIPC_DOMAIN][config_entry.unique_id] - entities = [HomematicipAccesspointStatus(hap)] + entities = [] for device in hap.home.devices: + if isinstance(device, AsyncHomeControlAccessPoint): + entities.append(HomematicipAccesspointDutyCycle(hap, device)) if isinstance(device, (AsyncHeatingThermostat, AsyncHeatingThermostatCompact)): entities.append(HomematicipHeatingThermostat(hap, device)) entities.append(HomematicipTemperatureSensor(hap, device)) @@ -119,23 +121,12 @@ async def async_setup_entry( async_add_entities(entities) -class HomematicipAccesspointStatus(HomematicipGenericEntity): +class HomematicipAccesspointDutyCycle(HomematicipGenericEntity): """Representation of then HomeMaticIP access point.""" - def __init__(self, hap: HomematicipHAP) -> None: + def __init__(self, hap: HomematicipHAP, device) -> None: """Initialize access point status entity.""" - super().__init__(hap, device=hap.home, post="Duty Cycle") - - @property - def device_info(self) -> Dict[str, Any]: - """Return device specific attributes.""" - # Adds a sensor to the existing HAP device - return { - "identifiers": { - # Serial numbers of Homematic IP device - (HMIPC_DOMAIN, self._home.id) - } - } + super().__init__(hap, device, post="Duty Cycle") @property def icon(self) -> str: @@ -145,28 +136,13 @@ class HomematicipAccesspointStatus(HomematicipGenericEntity): @property def state(self) -> float: """Return the state of the access point.""" - return self._home.dutyCycle - - @property - def available(self) -> bool: - """Return if access point is available.""" - return self._home.connected + return self._device.dutyCycleLevel @property def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return PERCENTAGE - @property - def device_state_attributes(self) -> Dict[str, Any]: - """Return the state attributes of the access point.""" - state_attr = super().device_state_attributes - - state_attr[ATTR_MODEL_TYPE] = "HmIP-HAP" - state_attr[ATTR_IS_GROUP] = False - - return state_attr - class HomematicipHeatingThermostat(HomematicipGenericEntity): """Representation of the HomematicIP heating thermostat.""" diff --git a/requirements_all.txt b/requirements_all.txt index c06edfd25cc..d30c5b463aa 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -780,7 +780,7 @@ homeassistant-pyozw==0.1.10 homeconnect==0.6.3 # homeassistant.components.homematicip_cloud -homematicip==0.11.0 +homematicip==0.12.1 # homeassistant.components.horizon horimote==0.4.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c00bb2bbc40..8d1887a5ce3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -406,7 +406,7 @@ homeassistant-pyozw==0.1.10 homeconnect==0.6.3 # homeassistant.components.homematicip_cloud -homematicip==0.11.0 +homematicip==0.12.1 # homeassistant.components.google # homeassistant.components.remember_the_milk diff --git a/tests/components/homematicip_cloud/conftest.py b/tests/components/homematicip_cloud/conftest.py index b967ef79094..9764ee74e22 100644 --- a/tests/components/homematicip_cloud/conftest.py +++ b/tests/components/homematicip_cloud/conftest.py @@ -56,7 +56,7 @@ def hmip_config_entry_fixture() -> config_entries.ConfigEntry: config_entry = MockConfigEntry( version=1, domain=HMIPC_DOMAIN, - title=HAPID, + title="Home Test SN", unique_id=HAPID, data=entry_data, source=SOURCE_IMPORT, diff --git a/tests/components/homematicip_cloud/helper.py b/tests/components/homematicip_cloud/helper.py index dbbf0249c0c..ca7d8862756 100644 --- a/tests/components/homematicip_cloud/helper.py +++ b/tests/components/homematicip_cloud/helper.py @@ -136,9 +136,9 @@ class HomeTemplate(Home): def __init__(self, connection=None, home_name="", test_devices=[], test_groups=[]): """Init template with connection.""" super().__init__(connection=connection) - self.label = "Access Point" self.name = home_name - self.model_type = "HmIP-HAP" + self.label = "Home" + self.model_type = "HomematicIP Home" self.init_json_state = None self.test_devices = test_devices self.test_groups = test_groups @@ -196,7 +196,7 @@ class HomeTemplate(Home): and sets required attributes. """ mock_home = Mock( - spec=AsyncHome, wraps=self, label="Access Point", modelType="HmIP-HAP" + spec=AsyncHome, wraps=self, label="Home", modelType="HomematicIP Home" ) mock_home.__dict__.update(self.__dict__) diff --git a/tests/components/homematicip_cloud/test_binary_sensor.py b/tests/components/homematicip_cloud/test_binary_sensor.py index f7bfcbf2f96..420977cd40c 100644 --- a/tests/components/homematicip_cloud/test_binary_sensor.py +++ b/tests/components/homematicip_cloud/test_binary_sensor.py @@ -38,12 +38,10 @@ async def test_manually_configured_platform(hass): assert not hass.data.get(HMIPC_DOMAIN) -async def test_hmip_access_point_cloud_connection_sensor( - hass, default_mock_hap_factory -): +async def test_hmip_home_cloud_connection_sensor(hass, default_mock_hap_factory): """Test HomematicipCloudConnectionSensor.""" - entity_id = "binary_sensor.access_point_cloud_connection" - entity_name = "Access Point Cloud Connection" + entity_id = "binary_sensor.cloud_connection" + entity_name = "Cloud Connection" device_model = None mock_hap = await default_mock_hap_factory.async_get_mock_hap( test_devices=[entity_name] @@ -55,7 +53,7 @@ async def test_hmip_access_point_cloud_connection_sensor( assert ha_state.state == STATE_ON - await async_manipulate_test_data(hass, hmip_device, "connected", False) + await async_manipulate_test_data(hass, mock_hap.home, "connected", False) ha_state = hass.states.get(entity_id) assert ha_state.state == STATE_OFF diff --git a/tests/components/homematicip_cloud/test_device.py b/tests/components/homematicip_cloud/test_device.py index 4fecd3865a4..31e62a1a719 100644 --- a/tests/components/homematicip_cloud/test_device.py +++ b/tests/components/homematicip_cloud/test_device.py @@ -22,7 +22,7 @@ async def test_hmip_load_all_supported_devices(hass, default_mock_hap_factory): test_devices=None, test_groups=None ) - assert len(mock_hap.hmip_device_by_entity_id) == 231 + assert len(mock_hap.hmip_device_by_entity_id) == 233 async def test_hmip_remove_device(hass, default_mock_hap_factory): @@ -268,4 +268,4 @@ async def test_hmip_multi_area_device(hass, default_mock_hap_factory): # get the hap hap_device = device_registry.async_get(device.via_device_id) - assert hap_device.name == "Access Point" + assert hap_device.name == "Home" diff --git a/tests/components/homematicip_cloud/test_init.py b/tests/components/homematicip_cloud/test_init.py index 37b293a3452..46059f12d00 100644 --- a/tests/components/homematicip_cloud/test_init.py +++ b/tests/components/homematicip_cloud/test_init.py @@ -145,6 +145,7 @@ async def test_unload_entry(hass): instance.home.id = "1" instance.home.modelType = "mock-type" instance.home.name = "mock-name" + instance.home.label = "mock-label" instance.home.currentAPVersion = "mock-ap-version" instance.async_reset = AsyncMock(return_value=True) @@ -158,7 +159,7 @@ async def test_unload_entry(hass): assert config_entries[0].state == ENTRY_STATE_LOADED await hass.config_entries.async_unload(config_entries[0].entry_id) assert config_entries[0].state == ENTRY_STATE_NOT_LOADED - assert mock_hap.return_value.mock_calls[3][0] == "async_reset" + assert mock_hap.return_value.mock_calls[2][0] == "async_reset" # entry is unloaded assert hass.data[HMIPC_DOMAIN] == {} @@ -187,6 +188,7 @@ async def test_setup_services_and_unload_services(hass): instance.home.id = "1" instance.home.modelType = "mock-type" instance.home.name = "mock-name" + instance.home.label = "mock-label" instance.home.currentAPVersion = "mock-ap-version" instance.async_reset = AsyncMock(return_value=True) @@ -220,6 +222,7 @@ async def test_setup_two_haps_unload_one_by_one(hass): instance.home.id = "1" instance.home.modelType = "mock-type" instance.home.name = "mock-name" + instance.home.label = "mock-label" instance.home.currentAPVersion = "mock-ap-version" instance.async_reset = AsyncMock(return_value=True) diff --git a/tests/components/homematicip_cloud/test_sensor.py b/tests/components/homematicip_cloud/test_sensor.py index 20c5c41a5b5..34c119595b3 100644 --- a/tests/components/homematicip_cloud/test_sensor.py +++ b/tests/components/homematicip_cloud/test_sensor.py @@ -46,11 +46,11 @@ async def test_manually_configured_platform(hass): async def test_hmip_accesspoint_status(hass, default_mock_hap_factory): """Test HomematicipSwitch.""" - entity_id = "sensor.access_point_duty_cycle" - entity_name = "Access Point Duty Cycle" - device_model = None + entity_id = "sensor.home_control_access_point_duty_cycle" + entity_name = "HOME_CONTROL_ACCESS_POINT Duty Cycle" + device_model = "HmIP-HAP" mock_hap = await default_mock_hap_factory.async_get_mock_hap( - test_devices=[entity_name] + test_devices=["HOME_CONTROL_ACCESS_POINT"] ) ha_state, hmip_device = get_and_check_entity_basics( @@ -60,11 +60,6 @@ async def test_hmip_accesspoint_status(hass, default_mock_hap_factory): assert ha_state.state == "8.0" assert ha_state.attributes[ATTR_UNIT_OF_MEASUREMENT] == PERCENTAGE - await async_manipulate_test_data(hass, hmip_device, "dutyCycle", 17.3) - - ha_state = hass.states.get(entity_id) - assert ha_state.state == "17.3" - async def test_hmip_heating_thermostat(hass, default_mock_hap_factory): """Test HomematicipHeatingThermostat.""" diff --git a/tests/fixtures/homematicip_cloud.json b/tests/fixtures/homematicip_cloud.json index 4060ca7a820..9c2a1b1e371 100644 --- a/tests/fixtures/homematicip_cloud.json +++ b/tests/fixtures/homematicip_cloud.json @@ -14,6 +14,248 @@ } }, "devices": { + "3014F711A000000BAD0CAAAA": { + "availableFirmwareVersion": "2.2.18", + "connectionType": "HMIP_LAN", + "firmwareVersion": "2.2.18", + "firmwareVersionInteger": 131602, + "functionalChannels": { + "0": { + "accessPointPriority": 0, + "busConfigMismatch": null, + "carrierSenseLevel": 2.0, + "coProFaulty": false, + "coProRestartNeeded": false, + "coProUpdateFailure": false, + "configPending": false, + "deviceId": "3014F711A000000BAD0CAAAA", + "deviceOverheated": false, + "deviceOverloaded": false, + "devicePowerFailureDetected": false, + "deviceUndervoltage": false, + "dutyCycle": false, + "dutyCycleLevel": 8.0, + "functionalChannelType": "ACCESS_CONTROLLER_CHANNEL", + "groupIndex": 0, + "groups": [], + "index": 0, + "label": "", + "lowBat": null, + "multicastRoutingEnabled": false, + "powerShortCircuit": null, + "routerModuleEnabled": false, + "routerModuleSupported": false, + "rssiDeviceValue": null, + "rssiPeerValue": null, + "shortCircuitDataLine": null, + "signalBrightness": 1.0, + "supportedOptionalFeatures": { + "IFeatureBusConfigMismatch": false, + "IFeatureDeviceCoProError": false, + "IFeatureDeviceCoProRestart": false, + "IFeatureDeviceCoProUpdate": false, + "IFeatureDeviceIdentify": false, + "IFeatureDeviceOverheated": false, + "IFeatureDeviceOverloaded": false, + "IFeatureDevicePowerFailure": false, + "IFeatureDeviceTemperatureOutOfRange": false, + "IFeatureDeviceUndervoltage": false, + "IFeatureMulticastRouter": false, + "IFeaturePowerShortCircuit": false, + "IFeatureRssiValue": false, + "IFeatureShortCircuitDataLine": false, + "IOptionalFeatureDutyCycle": true, + "IOptionalFeatureLowBat": false + }, + "temperatureOutOfRange": false, + "unreach": false + } + }, + "homeId": "00000000-0000-0000-0000-000000000001", + "id": "3014F711A000000BAD0CAAAA", + "label": "AP1", + "lastStatusUpdate": 1604522238580, + "liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED", + "manufacturerCode": 1, + "modelId": 270, + "modelType": "HmIP-HAP", + "oem": "eQ-3", + "permanentlyReachable": true, + "serializedGlobalTradeItemNumber": "3014F711A000000BAD0CAAAA", + "type": "HOME_CONTROL_ACCESS_POINT", + "updateState": "BACKGROUND_UPDATE_NOT_SUPPORTED" + }, + "3014F711A000000BAD0C0DED": { + "availableFirmwareVersion": "2.2.18", + "connectionType": "HMIP_LAN", + "firmwareVersion": "2.2.18", + "firmwareVersionInteger": 131602, + "functionalChannels": { + "0": { + "accessPointPriority": 1, + "busConfigMismatch": null, + "carrierSenseLevel": 2.0, + "coProFaulty": false, + "coProRestartNeeded": false, + "coProUpdateFailure": false, + "configPending": false, + "deviceId": "3014F711A000000BAD0C0DED", + "deviceOverheated": false, + "deviceOverloaded": false, + "devicePowerFailureDetected": false, + "deviceUndervoltage": false, + "dutyCycle": false, + "dutyCycleLevel": 8.0, + "functionalChannelType": "ACCESS_CONTROLLER_CHANNEL", + "groupIndex": 0, + "groups": [], + "index": 0, + "label": "", + "lowBat": null, + "multicastRoutingEnabled": false, + "powerShortCircuit": null, + "routerModuleEnabled": false, + "routerModuleSupported": false, + "rssiDeviceValue": null, + "rssiPeerValue": null, + "shortCircuitDataLine": null, + "signalBrightness": 1.0, + "supportedOptionalFeatures": { + "IFeatureBusConfigMismatch": false, + "IFeatureDeviceCoProError": false, + "IFeatureDeviceCoProRestart": false, + "IFeatureDeviceCoProUpdate": false, + "IFeatureDeviceIdentify": false, + "IFeatureDeviceOverheated": false, + "IFeatureDeviceOverloaded": false, + "IFeatureDevicePowerFailure": false, + "IFeatureDeviceTemperatureOutOfRange": false, + "IFeatureDeviceUndervoltage": false, + "IFeatureMulticastRouter": false, + "IFeaturePowerShortCircuit": false, + "IFeatureRssiValue": false, + "IFeatureShortCircuitDataLine": false, + "IOptionalFeatureDutyCycle": true, + "IOptionalFeatureLowBat": false + }, + "temperatureOutOfRange": false, + "unreach": false + } + }, + "homeId": "00000000-0000-0000-0000-000000000001", + "id": "3014F711A000000BAD0C0DED", + "label": "HOME_CONTROL_ACCESS_POINT", + "lastStatusUpdate": 1604522238580, + "liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED", + "manufacturerCode": 1, + "modelId": 270, + "modelType": "HmIP-HAP", + "oem": "eQ-3", + "permanentlyReachable": true, + "serializedGlobalTradeItemNumber": "3014F711A000000BAD0C0DED", + "type": "HOME_CONTROL_ACCESS_POINT", + "updateState": "BACKGROUND_UPDATE_NOT_SUPPORTED" + }, + "3014F71100BLIND_MODULE00": { + "availableFirmwareVersion": "0.0.0", + "connectionType": "HMIP_RF", + "firmwareVersion": "1.0.4", + "firmwareVersionInteger": 65540, + "functionalChannels": { + "0": { + "busConfigMismatch": null, + "coProFaulty": false, + "coProRestartNeeded": false, + "coProUpdateFailure": false, + "configPending": false, + "deviceId": "3014F71100BLIND_MODULE00", + "deviceOverheated": false, + "deviceOverloaded": false, + "devicePowerFailureDetected": false, + "deviceUndervoltage": false, + "dutyCycle": false, + "functionalChannelType": "DEVICE_BASE", + "groupIndex": 0, + "groups": [ + ], + "index": 0, + "label": "", + "lowBat": false, + "multicastRoutingEnabled": false, + "powerShortCircuit": null, + "routerModuleEnabled": false, + "routerModuleSupported": false, + "rssiDeviceValue": -85, + "rssiPeerValue": -78, + "shortCircuitDataLine": null, + "supportedOptionalFeatures": { + "IFeatureBusConfigMismatch": false, + "IFeatureDeviceCoProError": false, + "IFeatureDeviceCoProRestart": false, + "IFeatureDeviceCoProUpdate": false, + "IFeatureDeviceIdentify": false, + "IFeatureDeviceOverheated": false, + "IFeatureDeviceOverloaded": false, + "IFeatureDevicePowerFailure": false, + "IFeatureDeviceTemperatureOutOfRange": false, + "IFeatureDeviceUndervoltage": false, + "IFeatureMulticastRouter": false, + "IFeaturePowerShortCircuit": false, + "IFeatureRssiValue": true, + "IFeatureShortCircuitDataLine": false, + "IOptionalFeatureDutyCycle": true, + "IOptionalFeatureLowBat": true + }, + "temperatureOutOfRange": false, + "unreach": false + }, + "1": { + "automationDriveSpeed": "SLOW_SPEED", + "deviceId": "3014F71100BLIND_MODULE00", + "favoritePrimaryShadingPosition": 0.5, + "favoriteSecondaryShadingPosition": 0.5, + "functionalChannelType": "SHADING_CHANNEL", + "groupIndex": 1, + "groups": [ + ], + "identifyOemSupported": true, + "index": 1, + "label": "", + "manualDriveSpeed": "NOMINAL_SPEED", + "previousPrimaryShadingLevel": null, + "previousSecondaryShadingLevel": null, + "primaryCloseAdjustable": true, + "primaryOpenAdjustable": true, + "primaryShadingLevel": 0.94956, + "primaryShadingStateType": "POSITION_USED", + "processing": false, + "productId": 10, + "profileMode": "AUTOMATIC", + "secondaryCloseAdjustable": false, + "secondaryOpenAdjustable": false, + "secondaryShadingLevel": null, + "secondaryShadingStateType": "NOT_EXISTENT", + "shadingDriveVersion": null, + "shadingPackagePosition": "TOP", + "shadingPositionAdjustmentActive": null, + "shadingPositionAdjustmentClientId": null, + "userDesiredProfileMode": "AUTOMATIC" + } + }, + "homeId": "00000000-0000-0000-0000-000000000001", + "id": "3014F71100BLIND_MODULE00", + "label": "Sonnenschutz Balkont\u00fcr", + "lastStatusUpdate": 1600002124559, + "liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED", + "manufacturerCode": 7, + "modelId": 1, + "modelType": "HmIP-HDM1", + "oem": "HunterDouglas", + "permanentlyReachable": true, + "serializedGlobalTradeItemNumber": "3014F71100BLIND_MODULE00", + "type": "BLIND_MODULE", + "updateState": "UP_TO_DATE" + }, "3014F7110TILTVIBRATIONSENSOR": { "availableFirmwareVersion": "0.0.0", "connectionType": "HMIP_RF", @@ -7307,6 +7549,11 @@ }, "home": { "accessPointUpdateStates": { + "3014F711A000000BAD0CAAAA": { + "accessPointUpdateState": "UP_TO_DATE", + "successfulUpdateTimestamp": 0, + "updateStateChangedTimestamp": 0 + }, "3014F711A000000BAD0C0DED": { "accessPointUpdateState": "UP_TO_DATE", "successfulUpdateTimestamp": 0, @@ -7449,4 +7696,4 @@ "windSpeed": 8.568 } } -} \ No newline at end of file +}