Add air quality sensors to Accuweather integration (#91516)

pull/91861/head
Maciej Bieniek 2023-04-22 15:19:21 +00:00 committed by GitHub
parent 20a42c65cf
commit ee23d79a00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 173 additions and 50 deletions

View File

@ -62,6 +62,15 @@ class AccuWeatherSensorDescription(
FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = ( FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
AccuWeatherSensorDescription(
key="AirQuality",
icon="mdi:air-filter",
name="Air quality",
value_fn=lambda data: cast(str, data[ATTR_CATEGORY]),
device_class=SensorDeviceClass.ENUM,
options=["good", "hazardous", "high", "low", "moderate", "unhealthy"],
translation_key="air_quality",
),
AccuWeatherSensorDescription( AccuWeatherSensorDescription(
key="CloudCoverDay", key="CloudCoverDay",
icon="mdi:weather-cloudy", icon="mdi:weather-cloudy",
@ -86,6 +95,7 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
value_fn=lambda data: cast(int, data[ATTR_VALUE]), value_fn=lambda data: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]}, attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="grass_pollen",
), ),
AccuWeatherSensorDescription( AccuWeatherSensorDescription(
key="HoursOfSun", key="HoursOfSun",
@ -102,6 +112,7 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
value_fn=lambda data: cast(int, data[ATTR_VALUE]), value_fn=lambda data: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]}, attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="mold_pollen",
), ),
AccuWeatherSensorDescription( AccuWeatherSensorDescription(
key="Ragweed", key="Ragweed",
@ -111,6 +122,7 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
value_fn=lambda data: cast(int, data[ATTR_VALUE]), value_fn=lambda data: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]}, attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="ragweed_pollen",
), ),
AccuWeatherSensorDescription( AccuWeatherSensorDescription(
key="RealFeelTemperatureMax", key="RealFeelTemperatureMax",
@ -164,6 +176,7 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
value_fn=lambda data: cast(int, data[ATTR_VALUE]), value_fn=lambda data: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]}, attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="tree_pollen",
), ),
AccuWeatherSensorDescription( AccuWeatherSensorDescription(
key="UVIndex", key="UVIndex",
@ -172,6 +185,7 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
native_unit_of_measurement=UV_INDEX, native_unit_of_measurement=UV_INDEX,
value_fn=lambda data: cast(int, data[ATTR_VALUE]), value_fn=lambda data: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]}, attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="uv_index",
), ),
AccuWeatherSensorDescription( AccuWeatherSensorDescription(
key="WindGustDay", key="WindGustDay",

View File

@ -30,6 +30,91 @@
"rising": "Rising", "rising": "Rising",
"falling": "Falling" "falling": "Falling"
} }
},
"air_quality": {
"state": {
"good": "Good",
"hazardous": "Hazardous",
"high": "High",
"low": "Low",
"moderate": "Moderate",
"unhealthy": "Unhealthy"
}
},
"grass_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"mold_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"ragweed_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"tree_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"uv_index": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
} }
} }
}, },

View File

@ -15,34 +15,35 @@
"UnitType": 17 "UnitType": 17
} }
}, },
"Ozone": { "AirQuality": {
"Value": 32, "Value": 0,
"Category": "Good", "Category": "good",
"CategoryValue": 1 "CategoryValue": 1,
"Type": "Ozone"
}, },
"Grass": { "Grass": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Mold": { "Mold": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Ragweed": { "Ragweed": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Tree": { "Tree": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"UVIndex": { "UVIndex": {
"Value": 5, "Value": 5,
"Category": "Moderate", "Category": "moderate",
"CategoryValue": 2 "CategoryValue": 2
}, },
"TemperatureMin": { "TemperatureMin": {
@ -214,34 +215,35 @@
"UnitType": 17 "UnitType": 17
} }
}, },
"Ozone": { "AirQuality": {
"Value": 39, "Value": 0,
"Category": "Good", "Category": "good",
"CategoryValue": 1 "CategoryValue": 1,
"Type": "Ozone"
}, },
"Grass": { "Grass": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Mold": { "Mold": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Ragweed": { "Ragweed": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Tree": { "Tree": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"UVIndex": { "UVIndex": {
"Value": 7, "Value": 7,
"Category": "High", "Category": "high",
"CategoryValue": 3 "CategoryValue": 3
}, },
"TemperatureMin": { "TemperatureMin": {
@ -409,34 +411,35 @@
"UnitType": 17 "UnitType": 17
} }
}, },
"Ozone": { "AirQuality": {
"Value": 29, "Value": 0,
"Category": "Good", "Category": "good",
"CategoryValue": 1 "CategoryValue": 1,
"Type": "Ozone"
}, },
"Grass": { "Grass": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Mold": { "Mold": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Ragweed": { "Ragweed": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Tree": { "Tree": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"UVIndex": { "UVIndex": {
"Value": 7, "Value": 7,
"Category": "High", "Category": "high",
"CategoryValue": 3 "CategoryValue": 3
}, },
"TemperatureMin": { "TemperatureMin": {
@ -604,34 +607,35 @@
"UnitType": 17 "UnitType": 17
} }
}, },
"Ozone": { "AirQuality": {
"Value": 18, "Value": 0,
"Category": "Good", "Category": "good",
"CategoryValue": 1 "CategoryValue": 1,
"Type": "Ozone"
}, },
"Grass": { "Grass": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Mold": { "Mold": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Ragweed": { "Ragweed": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Tree": { "Tree": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"UVIndex": { "UVIndex": {
"Value": 6, "Value": 6,
"Category": "High", "Category": "high",
"CategoryValue": 3 "CategoryValue": 3
}, },
"TemperatureMin": { "TemperatureMin": {
@ -799,34 +803,35 @@
"UnitType": 17 "UnitType": 17
} }
}, },
"Ozone": { "AirQuality": {
"Value": 14, "Value": 0,
"Category": "Good", "Category": "good",
"CategoryValue": 1 "CategoryValue": 1,
"Type": "Ozone"
}, },
"Grass": { "Grass": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Mold": { "Mold": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Ragweed": { "Ragweed": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"Tree": { "Tree": {
"Value": 0, "Value": 0,
"Category": "Low", "Category": "low",
"CategoryValue": 1 "CategoryValue": 1
}, },
"UVIndex": { "UVIndex": {
"Value": 7, "Value": 7,
"Category": "High", "Category": "high",
"CategoryValue": 3 "CategoryValue": 3
}, },
"TemperatureMin": { "TemperatureMin": {

View File

@ -189,13 +189,32 @@ async def test_sensor_with_forecast(hass: HomeAssistant) -> None:
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny" assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UV_INDEX assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UV_INDEX
assert state.attributes.get("level") == "Moderate" assert state.attributes.get("level") == "moderate"
assert state.attributes.get(ATTR_STATE_CLASS) is None assert state.attributes.get(ATTR_STATE_CLASS) is None
entry = registry.async_get("sensor.home_uv_index_0d") entry = registry.async_get("sensor.home_uv_index_0d")
assert entry assert entry
assert entry.unique_id == "0123456-uvindex-0" assert entry.unique_id == "0123456-uvindex-0"
state = hass.states.get("sensor.home_air_quality_0d")
assert state
assert state.state == "good"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:air-filter"
assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.ENUM
assert state.attributes.get(ATTR_OPTIONS) == [
"good",
"hazardous",
"high",
"low",
"moderate",
"unhealthy",
]
entry = registry.async_get("sensor.home_air_quality_0d")
assert entry
assert entry.unique_id == "0123456-airquality-0"
async def test_sensor_disabled(hass: HomeAssistant) -> None: async def test_sensor_disabled(hass: HomeAssistant) -> None:
"""Test sensor disabled by default.""" """Test sensor disabled by default."""
@ -499,7 +518,7 @@ async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None:
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER == CONCENTRATION_PARTS_PER_CUBIC_METER
) )
assert state.attributes.get("level") == "Low" assert state.attributes.get("level") == "low"
assert state.attributes.get(ATTR_ICON) == "mdi:grass" assert state.attributes.get(ATTR_ICON) == "mdi:grass"
assert state.attributes.get(ATTR_STATE_CLASS) is None assert state.attributes.get(ATTR_STATE_CLASS) is None
@ -515,7 +534,7 @@ async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None:
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER == CONCENTRATION_PARTS_PER_CUBIC_METER
) )
assert state.attributes.get("level") == "Low" assert state.attributes.get("level") == "low"
assert state.attributes.get(ATTR_ICON) == "mdi:blur" assert state.attributes.get(ATTR_ICON) == "mdi:blur"
entry = registry.async_get("sensor.home_mold_pollen_0d") entry = registry.async_get("sensor.home_mold_pollen_0d")
@ -530,7 +549,7 @@ async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None:
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER == CONCENTRATION_PARTS_PER_CUBIC_METER
) )
assert state.attributes.get("level") == "Low" assert state.attributes.get("level") == "low"
assert state.attributes.get(ATTR_ICON) == "mdi:sprout" assert state.attributes.get(ATTR_ICON) == "mdi:sprout"
entry = registry.async_get("sensor.home_ragweed_pollen_0d") entry = registry.async_get("sensor.home_ragweed_pollen_0d")
@ -568,7 +587,7 @@ async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None:
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER == CONCENTRATION_PARTS_PER_CUBIC_METER
) )
assert state.attributes.get("level") == "Low" assert state.attributes.get("level") == "low"
assert state.attributes.get(ATTR_ICON) == "mdi:tree-outline" assert state.attributes.get(ATTR_ICON) == "mdi:tree-outline"
assert state.attributes.get(ATTR_STATE_CLASS) is None assert state.attributes.get(ATTR_STATE_CLASS) is None