New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add air pollutants component #18707
Merged
Merged
Add air pollutants component #18707
Changes from 8 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
bf8e124
Add air pollutants component
fabaff 547e302
Fix lint issue
fabaff 937f47b
Update docstrings
fabaff 8effa80
Revert change
fabaff 7f19b2c
Remove entries
fabaff 1b53ae7
Remove imports
fabaff 7e1ad3c
Fix variable and other fixes
fabaff a2eeb46
Change tests
fabaff 3f31a36
Set SCAN_INTERVAL
fabaff File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
""" | ||
Component for handling Air Pollutants data for your location. | ||
|
||
For more details about this component, please refer to the documentation at | ||
https://home-assistant.io/components/air_pollutants/ | ||
""" | ||
import logging | ||
|
||
from homeassistant.helpers.entity_component import EntityComponent | ||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa | ||
from homeassistant.helpers.entity import Entity | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
DOMAIN = 'air_pollutants' | ||
|
||
ENTITY_ID_FORMAT = DOMAIN + '.{}' | ||
|
||
ATTR_AIR_POLLUTANTS_AQI = 'air_quality_index' | ||
ATTR_AIR_POLLUTANTS_ATTRIBUTION = 'attribution' | ||
ATTR_AIR_POLLUTANTS_C02 = 'carbon_dioxide' | ||
ATTR_AIR_POLLUTANTS_CO = 'carbon_monoxide' | ||
ATTR_AIR_POLLUTANTS_N2O = 'nitrogen_oxide' | ||
ATTR_AIR_POLLUTANTS_NO = 'nitrogen_monoxide' | ||
ATTR_AIR_POLLUTANTS_NO2 = 'nitrogen_dioxide' | ||
ATTR_AIR_POLLUTANTS_OZONE = 'ozone' | ||
ATTR_AIR_POLLUTANTS_PM_0_1 = 'particulate_matter_0_1' | ||
ATTR_AIR_POLLUTANTS_PM_10 = 'particulate_matter_10' | ||
ATTR_AIR_POLLUTANTS_PM_2_5 = 'particulate_matter_2_5' | ||
ATTR_AIR_POLLUTANTS_SO2 = 'sulphur_dioxide' | ||
|
||
|
||
async def async_setup(hass, config): | ||
"""Set up the air pollutants component.""" | ||
component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass) | ||
await component.async_setup(config) | ||
return True | ||
|
||
|
||
async def async_setup_entry(hass, entry): | ||
"""Set up a config entry.""" | ||
return await hass.data[DOMAIN].async_setup_entry(entry) | ||
|
||
|
||
async def async_unload_entry(hass, entry): | ||
"""Unload a config entry.""" | ||
return await hass.data[DOMAIN].async_unload_entry(entry) | ||
|
||
|
||
class AirPollutantsEntity(Entity): | ||
"""ABC for air pollutants data.""" | ||
|
||
@property | ||
def particulate_matter_2_5(self): | ||
"""Return the particulate matter 2.5 level.""" | ||
raise NotImplementedError() | ||
|
||
@property | ||
def particulate_matter_10(self): | ||
"""Return the particulate matter 10 level.""" | ||
return None | ||
|
||
@property | ||
def particulate_matter_0_1(self): | ||
"""Return the particulate matter 0.1 level.""" | ||
return None | ||
|
||
@property | ||
def temperature_unit(self): | ||
"""Return the unit of measurement of the temperature.""" | ||
return None | ||
|
||
@property | ||
def air_quality_index(self): | ||
"""Return the Air Quality Index (AQI).""" | ||
return None | ||
|
||
@property | ||
def ozone(self): | ||
"""Return the O3 (ozone) level.""" | ||
return None | ||
|
||
@property | ||
def carbon_monoxide(self): | ||
"""Return the CO (carbon monoxide) level.""" | ||
return None | ||
|
||
@property | ||
def carbon_dioxide(self): | ||
"""Return the CO2 (carbon dioxide) level.""" | ||
return None | ||
|
||
@property | ||
def attribution(self): | ||
"""Return the attribution.""" | ||
return None | ||
|
||
@property | ||
def sulphur_dioxide(self): | ||
"""Return the SO2 (sulphur dioxide) level.""" | ||
return None | ||
|
||
@property | ||
def nitrogen_oxide(self): | ||
"""Return the N2O (nitrogen oxide) level.""" | ||
return None | ||
|
||
@property | ||
def nitrogen_monoxide(self): | ||
"""Return the NO (nitrogen monoxide) level.""" | ||
return None | ||
|
||
@property | ||
def nitrogen_dioxide(self): | ||
"""Return the NO2 (nitrogen dioxide) level.""" | ||
return None | ||
|
||
@property | ||
def state_attributes(self): | ||
"""Return the state attributes.""" | ||
data = {} | ||
|
||
air_quality_index = self.air_quality_index | ||
if air_quality_index is not None: | ||
data[ATTR_AIR_POLLUTANTS_AQI] = air_quality_index | ||
|
||
ozone = self.ozone | ||
if ozone is not None: | ||
data[ATTR_AIR_POLLUTANTS_OZONE] = ozone | ||
|
||
particulate_matter_0_1 = self.particulate_matter_0_1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've used a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks |
||
if particulate_matter_0_1 is not None: | ||
data[ATTR_AIR_POLLUTANTS_PM_0_1] = particulate_matter_0_1 | ||
|
||
particulate_matter_10 = self.particulate_matter_10 | ||
if particulate_matter_10 is not None: | ||
data[ATTR_AIR_POLLUTANTS_PM_10] = particulate_matter_10 | ||
|
||
sulphur_dioxide = self.sulphur_dioxide | ||
if sulphur_dioxide is not None: | ||
data[ATTR_AIR_POLLUTANTS_SO2] = sulphur_dioxide | ||
|
||
nitrogen_oxide = self.nitrogen_oxide | ||
if nitrogen_oxide is not None: | ||
data[ATTR_AIR_POLLUTANTS_N2O] = nitrogen_oxide | ||
|
||
nitrogen_monoxide = self.nitrogen_monoxide | ||
if nitrogen_monoxide is not None: | ||
data[ATTR_AIR_POLLUTANTS_NO] = nitrogen_monoxide | ||
|
||
nitrogen_dioxide = self.nitrogen_dioxide | ||
if nitrogen_dioxide is not None: | ||
data[ATTR_AIR_POLLUTANTS_NO2] = nitrogen_dioxide | ||
|
||
carbon_dioxide = self.carbon_dioxide | ||
if carbon_dioxide is not None: | ||
data[ATTR_AIR_POLLUTANTS_C02] = carbon_dioxide | ||
|
||
carbon_monoxide = self.carbon_monoxide | ||
if carbon_monoxide is not None: | ||
data[ATTR_AIR_POLLUTANTS_CO] = carbon_monoxide | ||
|
||
attribution = self.attribution | ||
if attribution is not None: | ||
data[ATTR_AIR_POLLUTANTS_ATTRIBUTION] = attribution | ||
|
||
return data | ||
|
||
@property | ||
def state(self): | ||
"""Return the current state.""" | ||
return self.particulate_matter_2_5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
""" | ||
Demo platform that offers fake air pollutants data. | ||
|
||
For more details about this platform, please refer to the documentation | ||
https://home-assistant.io/components/demo/ | ||
""" | ||
from homeassistant.components.air_pollutants import AirPollutantsEntity | ||
|
||
|
||
def setup_platform(hass, config, add_entities, discovery_info=None): | ||
"""Set up the Air Pollutants.""" | ||
add_entities([ | ||
DemoAirPollutants('Home', 14, 23, 100), | ||
DemoAirPollutants('Office', 4, 16, None) | ||
]) | ||
|
||
|
||
class DemoAirPollutants(AirPollutantsEntity): | ||
"""Representation of Air Pollutants data.""" | ||
|
||
def __init__(self, name, pm_2_5, pm_10, n2o): | ||
"""Initialize the Demo Air Pollutants.""" | ||
self._name = name | ||
self._pm_2_5 = pm_2_5 | ||
self._pm_10 = pm_10 | ||
self._n2o = n2o | ||
|
||
@property | ||
def name(self): | ||
"""Return the name of the sensor.""" | ||
return '{} {}'.format('Demo Air Pollutants', self._name) | ||
|
||
@property | ||
def should_poll(self): | ||
"""No polling needed for Demo Air Pollutants.""" | ||
return False | ||
|
||
@property | ||
def particulate_matter_2_5(self): | ||
"""Return the particulate matter 2.5 level.""" | ||
return self._pm_2_5 | ||
|
||
@property | ||
def particulate_matter_10(self): | ||
"""Return the particulate matter 10 level.""" | ||
return self._pm_10 | ||
|
||
@property | ||
def nitrogen_oxide(self): | ||
"""Return the nitrogen oxide (N2O) level.""" | ||
return self._n2o | ||
|
||
@property | ||
def attribution(self): | ||
"""Return the attribution.""" | ||
return 'Powered by Home Assistant' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""The tests for Air Pollutants platforms.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
"""The tests for the Air Pollutants component.""" | ||
from homeassistant.components.air_pollutants import ( | ||
ATTR_AIR_POLLUTANTS_ATTRIBUTION, ATTR_AIR_POLLUTANTS_N2O, | ||
ATTR_AIR_POLLUTANTS_OZONE, ATTR_AIR_POLLUTANTS_PM_10) | ||
from homeassistant.setup import async_setup_component | ||
|
||
|
||
async def test_state(hass): | ||
"""Test Air Pollutants state.""" | ||
config = { | ||
'air_pollutants': { | ||
'platform': 'demo', | ||
} | ||
} | ||
|
||
assert await async_setup_component(hass, 'air_pollutants', config) | ||
|
||
state = hass.states.get('air_pollutants.demo_air_pollutants_home') | ||
assert state is not None | ||
|
||
assert state.state == '14' | ||
|
||
|
||
async def test_attributes(hass): | ||
"""Test Air Pollutants attributes.""" | ||
config = { | ||
'air_pollutants': { | ||
'platform': 'demo', | ||
} | ||
} | ||
|
||
assert await async_setup_component(hass, 'air_pollutants', config) | ||
|
||
state = hass.states.get('air_pollutants.demo_air_pollutants_office') | ||
assert state is not None | ||
|
||
data = state.attributes | ||
assert data.get(ATTR_AIR_POLLUTANTS_PM_10) == 16 | ||
assert data.get(ATTR_AIR_POLLUTANTS_N2O) is None | ||
assert data.get(ATTR_AIR_POLLUTANTS_OZONE) is None | ||
assert data.get(ATTR_AIR_POLLUTANTS_ATTRIBUTION) == \ | ||
'Powered by Home Assistant' |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we set the default scan interval to 30 seconds as for sensors, instead of 15 seconds as is the main default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should.