mirror of
https://github.com/home-assistant/core.git
synced 2026-08-20 05:10:44 +01:00
Add a carbon dioxide sensor to homematicip_cloud (#179187)
This commit is contained in:
@@ -146,6 +146,12 @@ ATTR_TEMPERATURE_OFFSET = "temperature_offset"
|
||||
ATTR_WIND_DIRECTION = "wind_direction"
|
||||
ATTR_WIND_DIRECTION_VARIATION = "wind_direction_variation_in_degree"
|
||||
ATTR_ESI_TYPE = "type"
|
||||
|
||||
CARBON_DIOXIDE_CHANNELS = (
|
||||
FunctionalChannelType.CARBON_DIOXIDE_SENSOR_CHANNEL,
|
||||
FunctionalChannelType.WALL_MOUNTED_THERMOSTAT_WITH_CARBON_CHANNEL,
|
||||
)
|
||||
|
||||
ESI_TYPE_UNKNOWN = "UNKNOWN"
|
||||
ESI_CONNECTED_SENSOR_TYPE_IEC = "ES_IEC"
|
||||
ESI_CONNECTED_SENSOR_TYPE_GAS = "ES_GAS"
|
||||
@@ -368,6 +374,14 @@ async def async_setup_entry(
|
||||
if smoke_detector_channel_data_exists(device, description.channel_field)
|
||||
)
|
||||
|
||||
entities.extend(
|
||||
HomematicipCarbonDioxideSensor(hap, device, channel.index)
|
||||
for device in hap.home.devices
|
||||
for channel_type in CARBON_DIOXIDE_CHANNELS
|
||||
for channel in get_channels_from_device(device, channel_type)
|
||||
if getattr(channel, "carbonDioxideConcentration", None) is not None
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
@@ -620,6 +634,33 @@ class HomematicipHeatingThermostat(HomematicipGenericEntity, SensorEntity):
|
||||
return round(self._device.valvePosition * 100)
|
||||
|
||||
|
||||
class HomematicipCarbonDioxideSensor(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of the HomematicIP carbon dioxide sensor."""
|
||||
|
||||
_attr_device_class = SensorDeviceClass.CO2
|
||||
_attr_native_unit_of_measurement = UnitOfRatio.PARTS_PER_MILLION
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
|
||||
def __init__(self, hap: HomematicipHAP, device: Device, channel: int) -> None:
|
||||
"""Initialize the carbon dioxide sensor."""
|
||||
super().__init__(
|
||||
hap,
|
||||
device,
|
||||
channel=channel,
|
||||
# the channel is not at the same index on every device
|
||||
channel_real_index=channel,
|
||||
is_multi_channel=True,
|
||||
feature_id="carbon_dioxide",
|
||||
use_description_name=True,
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> float | None:
|
||||
"""Return the state."""
|
||||
return self.get_channel_or_raise().carbonDioxideConcentration
|
||||
|
||||
|
||||
class HomematicipHumiditySensor(HomematicipGenericEntity, SensorEntity):
|
||||
"""Representation of the HomematicIP humidity sensor."""
|
||||
|
||||
|
||||
@@ -417,3 +417,366 @@ def mock_connection_init_fixture():
|
||||
def simple_mock_auth_fixture() -> Auth:
|
||||
"""Return a simple AsyncAuth Mock."""
|
||||
return AsyncMock(spec=Auth, pin=HAPPIN, create=True)
|
||||
|
||||
|
||||
@pytest.fixture(name="wall_mounted_thermostat_with_carbon_device_data")
|
||||
def wall_mounted_thermostat_with_carbon_device_data_fixture() -> dict[str, Any]:
|
||||
"""Return fixture data for an HmIP-WGTC device."""
|
||||
return {
|
||||
"availableFirmwareVersion": "1.0.18",
|
||||
"connectionType": "HMIP_RF",
|
||||
"deviceArchetype": "HMIP",
|
||||
"firmwareVersion": "1.0.18",
|
||||
"firmwareVersionInteger": 65554,
|
||||
"functionalChannels": {
|
||||
"0": {
|
||||
"altitude": None,
|
||||
"bootedRecently": False,
|
||||
"busConfigMismatch": None,
|
||||
"coProFaulty": False,
|
||||
"coProRestartNeeded": False,
|
||||
"coProUpdateFailure": False,
|
||||
"configPending": False,
|
||||
"controlsMountingOrientation": None,
|
||||
"daliBusState": None,
|
||||
"dataDecodingFailedError": None,
|
||||
"defaultLinkedGroup": [],
|
||||
"deviceAliveSignalEnabled": None,
|
||||
"deviceCanBusError": None,
|
||||
"deviceCommunicationError": None,
|
||||
"deviceDriveError": None,
|
||||
"deviceDriveModeError": None,
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"deviceOperationMode": None,
|
||||
"deviceOverheated": False,
|
||||
"deviceOverloaded": False,
|
||||
"devicePowerFailureDetected": False,
|
||||
"deviceUndervoltage": False,
|
||||
"displayContrast": None,
|
||||
"displayMode": None,
|
||||
"displayMountingOrientation": None,
|
||||
"dutyCycle": False,
|
||||
"fanControlMode": None,
|
||||
"frostProtectionError": None,
|
||||
"frostProtectionErrorAcknowledged": None,
|
||||
"functionalChannelType": "DEVICE_OPERATIONLOCK",
|
||||
"groupIndex": 0,
|
||||
"groups": [],
|
||||
"index": 0,
|
||||
"input1CoproEnabled": None,
|
||||
"input2CoproEnabled": None,
|
||||
"input3CoproEnabled": None,
|
||||
"input4CoproEnabled": None,
|
||||
"inputLayoutMode": None,
|
||||
"invertedDisplayColors": None,
|
||||
"label": "",
|
||||
"lastBootTimestamp": 1784278839458,
|
||||
"lockJammed": None,
|
||||
"lowBat": None,
|
||||
"mountingModuleError": None,
|
||||
"mountingOrientation": None,
|
||||
"multicastRoutingEnabled": False,
|
||||
"noDataFromLinkyError": None,
|
||||
"notRechargeableBattery": None,
|
||||
"operationDays": None,
|
||||
"operationLockActive": False,
|
||||
"particulateMatterSensorCommunicationError": None,
|
||||
"particulateMatterSensorError": None,
|
||||
"powerShortCircuit": None,
|
||||
"profilePeriodLimitReached": None,
|
||||
"routerModuleEnabled": False,
|
||||
"routerModuleSupported": False,
|
||||
"rssiDeviceValue": -75,
|
||||
"rssiPeerValue": None,
|
||||
"sensorCommunicationError": None,
|
||||
"sensorError": None,
|
||||
"shortCircuitDataLine": None,
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureDeviceIdentify": True,
|
||||
"IFeatureDeviceMountingModuleError": True,
|
||||
"IFeatureDeviceOverloaded": True,
|
||||
"IFeatureProfilePeriodLimit": True,
|
||||
"IFeatureRssiValue": True,
|
||||
"IOptionalFeatureDeviceSwitchChannelMode": True,
|
||||
"IOptionalFeatureDutyCycle": True,
|
||||
},
|
||||
"switchChannelMode": "FLOOR_HEATING",
|
||||
"temperatureHumiditySensorCommunicationError": None,
|
||||
"temperatureHumiditySensorError": None,
|
||||
"temperatureOutOfRange": False,
|
||||
"ticVersionError": None,
|
||||
"unreach": False,
|
||||
"valveFlowError": None,
|
||||
"valveWaterError": None,
|
||||
},
|
||||
"1": {
|
||||
"channelRole": "KEY_OR_SWITCH_FOR_GROUP",
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"functionalChannelType": "INPUT_QUICK_ACTION_DISPLAY_CHANNEL",
|
||||
"groupIndex": 1,
|
||||
"groups": [],
|
||||
"index": 1,
|
||||
"label": "",
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureLightGroupSensorChannel": True,
|
||||
"IFeatureShadingGroupSensorChannel": True,
|
||||
},
|
||||
},
|
||||
"2": {
|
||||
"channelRole": "DIMMING_ACTUATOR",
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"dimLevel": 0.02,
|
||||
"functionalChannelType": "BACKLIGHT_CHANNEL",
|
||||
"groupIndex": 2,
|
||||
"groups": [],
|
||||
"index": 2,
|
||||
"label": "",
|
||||
"on": True,
|
||||
"powerUpDimLevel": 0.02,
|
||||
"powerUpSwitchState": "PERMANENT_ON",
|
||||
"profileMode": "AUTOMATIC",
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureLightProfileActuatorChannel": True
|
||||
},
|
||||
"switchVisualization": "LIGHT",
|
||||
"userDesiredProfileMode": "AUTOMATIC",
|
||||
},
|
||||
"3": {
|
||||
"actualTemperature": 22.6,
|
||||
"carbonDioxideConcentration": 440.0,
|
||||
"channelRole": "WALL_MOUNTED_THERMOSTAT",
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"display": "ACTUAL",
|
||||
"functionalChannelType": "WALL_MOUNTED_THERMOSTAT_WITH_CARBON_CHANNEL",
|
||||
"groupIndex": 3,
|
||||
"groups": [],
|
||||
"humidity": 48,
|
||||
"index": 3,
|
||||
"label": "Wandthermostat (3 + 4) Child",
|
||||
"setPointTemperature": 18.0,
|
||||
"supportedOptionalFeatures": {
|
||||
"IOptionalFeatureClimateControlDisplayCarbonSupported": True,
|
||||
"IOptionalFeatureClimateControlDisplayHumidityOnlySupported": True,
|
||||
"IOptionalFeatureThermostatCoolingSupported": True,
|
||||
},
|
||||
"temperatureOffset": -0.5,
|
||||
"vaporAmount": 9.619851889906071,
|
||||
},
|
||||
"4": {
|
||||
"climateControlType": "PWM_CONTROL",
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"frostProtectionTemperature": 8.0,
|
||||
"functionalChannelType": "INTERNAL_SWITCH_CHANNEL",
|
||||
"groupIndex": 3,
|
||||
"groups": [],
|
||||
"heatingValveType": "NORMALLY_CLOSE",
|
||||
"index": 4,
|
||||
"internalSwitchOutputEnabled": False,
|
||||
"label": "Wandthermostat (3 + 4) Child",
|
||||
"supportedOptionalFeatures": {
|
||||
"IOptionalFeatureClimateControlType": True,
|
||||
"IOptionalFeatureFloorHeatingSpecificGroupSupported": True,
|
||||
},
|
||||
"valvePosition": 0.0,
|
||||
"valveProtectionDuration": 5,
|
||||
"valveProtectionSwitchingInterval": 14,
|
||||
},
|
||||
"5": {
|
||||
"channelRole": None,
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"functionalChannelType": "SWITCH_CHANNEL",
|
||||
"groupIndex": 0,
|
||||
"groups": [],
|
||||
"index": 5,
|
||||
"internalLinkConfiguration": None,
|
||||
"label": "",
|
||||
"on": False,
|
||||
"powerUpSwitchState": "PERMANENT_OFF",
|
||||
"profileMode": "AUTOMATIC",
|
||||
"supportedOptionalFeatures": {
|
||||
"IOptionalFeaturePowerUpSwitchState": True
|
||||
},
|
||||
"switchVisualization": None,
|
||||
"userDesiredProfileMode": "AUTOMATIC",
|
||||
},
|
||||
"6": {
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"functionalChannelType": "HEAT_DEMAND_CHANNEL",
|
||||
"groupIndex": 0,
|
||||
"groups": [],
|
||||
"index": 6,
|
||||
"label": "",
|
||||
},
|
||||
"7": {
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"functionalChannelType": "DEHUMIDIFIER_DEMAND_CHANNEL",
|
||||
"groupIndex": 0,
|
||||
"groups": [],
|
||||
"index": 7,
|
||||
"label": "",
|
||||
},
|
||||
"8": {
|
||||
"deviceId": "3014F711000000000000WGTC",
|
||||
"functionalChannelType": "CHANGE_OVER_CHANNEL",
|
||||
"groupIndex": 0,
|
||||
"groups": [],
|
||||
"index": 8,
|
||||
"label": "",
|
||||
},
|
||||
},
|
||||
"homeId": "00000000-0000-0000-0000-000000000001",
|
||||
"id": "3014F711000000000000WGTC",
|
||||
"label": "Wandthermostat mit CO2",
|
||||
"lastStatusUpdate": 1784553668564,
|
||||
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
|
||||
"manuallyUpdateForced": False,
|
||||
"manufacturerCode": 1,
|
||||
"measuredAttributes": {
|
||||
"3": {
|
||||
"actualTemperature": True,
|
||||
"carbonDioxideConcentration": True,
|
||||
"humidity": True,
|
||||
"setPointTemperature": True,
|
||||
}
|
||||
},
|
||||
"modelId": 568,
|
||||
"modelType": "HmIP-WGTC",
|
||||
"oem": "eQ-3",
|
||||
"permanentlyReachable": True,
|
||||
"serializedGlobalTradeItemNumber": "3014F711000000000000WGTC",
|
||||
"type": "WALL_MOUNTED_GLASS_THERMOSTAT_CARBON",
|
||||
"updateState": "UP_TO_DATE",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(name="carbon_dioxide_sensor_device_data")
|
||||
def carbon_dioxide_sensor_device_data_fixture() -> dict[str, Any]:
|
||||
"""Return fixture data for an HmIP-SCTH230 device."""
|
||||
return {
|
||||
"availableFirmwareVersion": "1.0.6",
|
||||
"connectionType": "HMIP_RF",
|
||||
"deviceArchetype": "HMIP",
|
||||
"firmwareVersion": "1.0.6",
|
||||
"firmwareVersionInteger": 65542,
|
||||
"functionalChannels": {
|
||||
"0": {
|
||||
"busConfigMismatch": None,
|
||||
"coProFaulty": False,
|
||||
"coProRestartNeeded": False,
|
||||
"coProUpdateFailure": False,
|
||||
"configPending": False,
|
||||
"controlsMountingOrientation": None,
|
||||
"deviceCommunicationError": None,
|
||||
"deviceDriveError": None,
|
||||
"deviceDriveModeError": None,
|
||||
"deviceId": "3014F711000000000SCTH230",
|
||||
"deviceOperationMode": None,
|
||||
"deviceOverheated": False,
|
||||
"deviceOverloaded": False,
|
||||
"devicePowerFailureDetected": False,
|
||||
"deviceUndervoltage": False,
|
||||
"displayContrast": None,
|
||||
"dutyCycle": False,
|
||||
"functionalChannelType": "DEVICE_BASE",
|
||||
"groupIndex": 0,
|
||||
"groups": ["00000000-0000-0000-0000-000000000052"],
|
||||
"index": 0,
|
||||
"label": "",
|
||||
"lockJammed": None,
|
||||
"lowBat": None,
|
||||
"mountingOrientation": None,
|
||||
"multicastRoutingEnabled": False,
|
||||
"particulateMatterSensorCommunicationError": None,
|
||||
"particulateMatterSensorError": None,
|
||||
"powerShortCircuit": None,
|
||||
"profilePeriodLimitReached": None,
|
||||
"routerModuleEnabled": False,
|
||||
"routerModuleSupported": False,
|
||||
"rssiDeviceValue": -66,
|
||||
"rssiPeerValue": None,
|
||||
"shortCircuitDataLine": None,
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureBusConfigMismatch": False,
|
||||
"IFeatureDeviceCoProError": False,
|
||||
"IFeatureDeviceCoProRestart": False,
|
||||
"IFeatureDeviceCoProUpdate": False,
|
||||
"IFeatureDeviceCommunicationError": False,
|
||||
"IFeatureDeviceDriveError": False,
|
||||
"IFeatureDeviceDriveModeError": False,
|
||||
"IFeatureDeviceIdentify": False,
|
||||
"IFeatureDeviceOverheated": False,
|
||||
"IFeatureDeviceOverloaded": False,
|
||||
"IFeatureDeviceParticulateMatterSensorCommunicationError": False,
|
||||
"IFeatureDeviceParticulateMatterSensorError": False,
|
||||
"IFeatureDevicePowerFailure": False,
|
||||
"IFeatureDeviceTemperatureHumiditySensorCommunicationError": False,
|
||||
"IFeatureDeviceTemperatureHumiditySensorError": False,
|
||||
"IFeatureDeviceTemperatureOutOfRange": False,
|
||||
"IFeatureDeviceUndervoltage": False,
|
||||
"IFeatureMulticastRouter": False,
|
||||
"IFeaturePowerShortCircuit": False,
|
||||
"IFeatureProfilePeriodLimit": True,
|
||||
"IFeatureRssiValue": True,
|
||||
"IFeatureShortCircuitDataLine": False,
|
||||
"IOptionalFeatureDeviceErrorLockJammed": False,
|
||||
"IOptionalFeatureDeviceOperationMode": False,
|
||||
"IOptionalFeatureDisplayContrast": False,
|
||||
"IOptionalFeatureDutyCycle": True,
|
||||
"IOptionalFeatureLowBat": False,
|
||||
"IOptionalFeatureMountingOrientation": False,
|
||||
},
|
||||
"temperatureHumiditySensorCommunicationError": None,
|
||||
"temperatureHumiditySensorError": None,
|
||||
"temperatureOutOfRange": False,
|
||||
"unreach": False,
|
||||
},
|
||||
"1": {
|
||||
"actualTemperature": 25.5,
|
||||
"carbonDioxideConcentration": 1181.0,
|
||||
"carbonDioxideVisualisationEnabled": True,
|
||||
"channelRole": "CARBON_DIOXIDE_SENSOR",
|
||||
"deviceId": "3014F711000000000SCTH230",
|
||||
"functionalChannelType": "CARBON_DIOXIDE_SENSOR_CHANNEL",
|
||||
"groupIndex": 1,
|
||||
"groups": ["00000000-0000-0000-0000-000000000053"],
|
||||
"humidity": 37,
|
||||
"index": 1,
|
||||
"label": "",
|
||||
"vaporAmount": 8.739326558877478,
|
||||
},
|
||||
"2": {
|
||||
"channelRole": "SWITCH_ACTUATOR",
|
||||
"deviceId": "3014F711000000000SCTH230",
|
||||
"functionalChannelType": "SWITCH_CHANNEL",
|
||||
"groupIndex": 2,
|
||||
"groups": ["00000000-0000-0000-0000-000000000054"],
|
||||
"index": 2,
|
||||
"internalLinkConfiguration": None,
|
||||
"label": "",
|
||||
"on": False,
|
||||
"powerUpSwitchState": "PERMANENT_OFF",
|
||||
"profileMode": "AUTOMATIC",
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureAccessAuthorizationActuatorChannel": False,
|
||||
"IFeatureLightGroupActuatorChannel": True,
|
||||
"IFeatureLightProfileActuatorChannel": True,
|
||||
"IOptionalFeatureInternalLinkConfiguration": False,
|
||||
"IOptionalFeaturePowerUpSwitchState": True,
|
||||
},
|
||||
"userDesiredProfileMode": "AUTOMATIC",
|
||||
},
|
||||
},
|
||||
"homeId": "00000000-0000-0000-0000-000000000001",
|
||||
"id": "3014F711000000000SCTH230",
|
||||
"label": "CO2 Sensor miko ",
|
||||
"lastStatusUpdate": 1676606756797,
|
||||
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
|
||||
"manufacturerCode": 1,
|
||||
"modelId": 435,
|
||||
"modelType": "HmIP-SCTH230",
|
||||
"oem": "eQ-3",
|
||||
"permanentlyReachable": True,
|
||||
"serializedGlobalTradeItemNumber": "3014F711000000000SCTH230",
|
||||
"type": "CARBON_DIOXIDE_SENSOR",
|
||||
"updateState": "UP_TO_DATE",
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ from homeassistant.const import (
|
||||
STATE_UNKNOWN,
|
||||
UnitOfLength,
|
||||
UnitOfPower,
|
||||
UnitOfRatio,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
UnitOfVolume,
|
||||
@@ -1079,3 +1080,58 @@ async def test_hmip_soil_temperature_sensor(
|
||||
)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == "18.3"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device_data_fixture", "device_label", "entity_id", "device_model", "channel"),
|
||||
[
|
||||
(
|
||||
"wall_mounted_thermostat_with_carbon_device_data",
|
||||
"Wandthermostat mit CO2",
|
||||
"sensor.wandthermostat_mit_co2_carbon_dioxide",
|
||||
"HmIP-WGTC",
|
||||
3,
|
||||
),
|
||||
(
|
||||
"carbon_dioxide_sensor_device_data",
|
||||
"CO2 Sensor miko ",
|
||||
"sensor.co2_sensor_miko_carbon_dioxide",
|
||||
"HmIP-SCTH230",
|
||||
1,
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_hmip_carbon_dioxide_sensor(
|
||||
hass: HomeAssistant,
|
||||
default_mock_hap_factory: HomematicipHAP,
|
||||
request: pytest.FixtureRequest,
|
||||
device_data_fixture: str,
|
||||
device_label: str,
|
||||
entity_id: str,
|
||||
device_model: str,
|
||||
channel: int,
|
||||
) -> None:
|
||||
"""Test the carbon dioxide sensor on both channel types."""
|
||||
device_data = request.getfixturevalue(device_data_fixture)
|
||||
mock_hap = await default_mock_hap_factory.async_get_mock_hap(
|
||||
test_devices=[device_label], extra_devices=[device_data]
|
||||
)
|
||||
|
||||
ha_state, hmip_device = get_and_check_entity_basics(
|
||||
hass, mock_hap, entity_id, f"{device_label} Carbon dioxide", device_model
|
||||
)
|
||||
|
||||
assert (
|
||||
ha_state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfRatio.PARTS_PER_MILLION
|
||||
)
|
||||
assert ha_state.attributes[ATTR_STATE_CLASS] == SensorStateClass.MEASUREMENT
|
||||
|
||||
await async_manipulate_test_data(
|
||||
hass,
|
||||
hmip_device,
|
||||
"carbonDioxideConcentration",
|
||||
812.0,
|
||||
channel=channel,
|
||||
channel_real_index=channel,
|
||||
)
|
||||
assert hass.states.get(entity_id).state == "812.0"
|
||||
|
||||
Reference in New Issue
Block a user