Any free integration that allows HA to pull in Particulate Matter 2.5 µm current and forecast for location in USA?

I’d like to correlate my Particulate Matter 2.5 µg measurements to local area current and forecast data. I tried several integrations but none offered this data.

I’ve tried:

While some of these show the PM data on their site, you can’t pull it into HA… or at least I did not see any sensors created for that purpose after adding the integration.

Is there any such source of data?

Background: This morning I found that the PM 2.5 inside the house was over 100 µg/m³ and there was no obvious source for it (cooking, burning, etc). I checked the pollution data and it was high outdoors too but that is a single data point. I wanted to pull in outdoor data (without putting a sensor outdoors) and correlate it to indoor measurements. This would help me figure out sources of indoor air pollution. Opening the window in the room with the sensor caused the measurement to go back down to 30 µg when it typically is very close to 0 indoors unless I am soldering or cooking…

1 Like

I subscribe to OpenWeatherMap air pollution API, it’s free but you do need to subscribe,

- platform: rest
  name: "OWM Report"
  scan_interval: 3600
  resource: !secret openweathermap
  value_template: 'OK'
  json_attributes_path: "$.list[0]"
  json_attributes:
    - main
    - components

then I use this to break the reading out

- platform: template
  sensors:
    owm_air_quality:
      friendly_name: AQI
      value_template: >-
        {{ state_attr('sensor.owm_report', 'main')['aqi'] }}
    owm_carbon_monoxide:
      friendly_name: CO
      value_template: >-
        {{ '%.2f' | format(state_attr('sensor.owm_report', 'components')['co'] / 100) }}
    owm_nitrogen_monoxide:
      friendly_name: NO
      value_template: "{{ state_attr('sensor.owm_report', 'components')['no'] }}"
    owm_nitrogen_dioxide:
      friendly_name: NO2
      value_template: "{{ state_attr('sensor.owm_report', 'components')['no2'] }}"
    owm_ozone:
      friendly_name: O3
      value_template: "{{ state_attr('sensor.owm_report', 'components')['o3'] }}"
    owm_sulfur_dioxide:
      friendly_name: S2
      value_template: "{{ state_attr('sensor.owm_report', 'components')['so2'] }}"
    owm_fine_particles:
      friendly_name: PM2
      value_template: "{{ state_attr('sensor.owm_report', 'components')['pm2_5'] }}"
    owm_coarse_particles:
      friendly_name: PM10
      value_template: "{{ state_attr('sensor.owm_report', 'components')['pm10'] }}"
    owm_ammonia:
      friendly_name: OWM Ammonia
      value_template: "{{ state_attr('sensor.owm_report', 'components')['nh3'] }}"
3 Likes

@cyn - Awesome, thank you! I already use openweathermap for my weather and did not realize it has all this other data. I’ll look into it right away, and thanks for sharing the YAML too!

Thank you @cyn !

For others wanting to implement this:

Get an API key (free tier):

https://openweathermap.org/price

Details on the Pollution API can be found here:

https://openweathermap.org/api/air-pollution

I placed the first code snipped shared by @cyn in configuration.yaml in the sensor: section:

Note: I made some changes to @cyn 's YAML to have more descriptive naming, and to add support for both Current and Forecast reports:

#Open Weather Map - Air Pollution API - Current Report
  - platform: rest
    name: "Openweathermap: Air Pollution"
    scan_interval: 3600
    resource: !secret openweathermap_current
    value_template: 'OK'
    json_attributes_path: "$.list[0]"
    json_attributes:
      - main
      - components

#Open Weather Map - Air Pollution API - Forecast Report - TO DO: no start/end time set so not sure on what timeframe it is for
  - platform: rest
    name: "Openweathermap Forecast: Air Pollution"
    scan_interval: 3600
    resource: !secret openweathermap_forecast
    value_template: 'OK'
    json_attributes_path: "$.list[0]"
    json_attributes:
      - main
      - components

In secrets.yaml, add the following but remember to replace {...} with your data:

openweathermap_current: http://api.openweathermap.org/data/2.5/air_pollution?lat={lat}&lon={lon}&appid={API Key}

openweathermap_forecast: http://api.openweathermap.org/data/2.5/air_pollution/forecast?lat={lat}&lon={lon}&appid={API Key}

In configuration.yaml I added the current report sensors:

Note: I made some changes to @cyn 's YAML to have more descriptive naming, add device_class and unit_of_measurement, and to add support for both Current and Forecast reports:

  - platform: template
    sensors:
      openweathermap_air_quality_index:
        friendly_name: "Openweathermap: Air Quality Index"
        device_class: "aqi"
        value_template: >-
          {{ state_attr('sensor.openweathermap_air_pollution', 'main')['aqi'] }}
      openweathermap_carbon_monoxide:
        friendly_name: "Openweathermap: Carbon Monoxide CO"
        device_class: "carbon_monoxide"
        unit_of_measurement: 'µg/m³'
        value_template: >-
          {{ '%.2f' | format(state_attr('sensor.openweathermap_air_pollution', 'components')['co'] / 100) }}
      openweathermap_nitrogen_monoxide:
        friendly_name: "Openweathermap: Nitrogen Monoxide NO"
        device_class: "nitrogen_monoxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['no'] }}"
      openweathermap_nitrogen_dioxide:
        friendly_name: "Openweathermap: Nitrogen Dioxide NO2"
        device_class: "nitrogen_dioxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['no2'] }}"
      openweathermap_ozone:
        friendly_name: "Openweathermap: Ozone O3"
        device_class: "ozone"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['o3'] }}"
      openweathermap_sulfur_dioxide:
        friendly_name: "Openweathermap: Sulfur Dioxide SO2"
        device_class: "sulphur_dioxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['so2'] }}"
      openweathermap_particulate_matter_2_5:
        friendly_name: "Openweathermap: PM 2.5"
        device_class: "pm25"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['pm2_5'] }}"
      openweathermap_particulate_matter_10:
        friendly_name: "Openweathermap: PM 10"
        device_class: "pm10"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['pm10'] }}"
      openweathermap_ammonia:
        friendly_name: "Openweathermap: Ammonia NH3"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_air_pollution', 'components')['nh3'] }}"

and the forecast sensors…

  - platform: template
    sensors:
      openweathermap_forecast_air_quality_index:
        friendly_name: "Openweathermap Forecast: Air Quality Index"
        device_class: "aqi"
        value_template: >-
          {{ state_attr('sensor.openweathermap_forecast_air_pollution', 'main')['aqi'] }}
      openweathermap_forecast_carbon_monoxide:
        friendly_name: "Openweathermap Forecast: Carbon Monoxide CO"
        device_class: "carbon_monoxide"
        unit_of_measurement: 'µg/m³'
        value_template: >-
          {{ '%.2f' | format(state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['co'] / 100) }}
      openweathermap_forecast_nitrogen_monoxide:
        friendly_name: "Openweathermap Forecast: Nitrogen Monoxide NO"
        device_class: "nitrogen_monoxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['no'] }}"
      openweathermap_forecast_nitrogen_dioxide:
        friendly_name: "Openweathermap Forecast: Nitrogen Dioxide NO2"
        device_class: "nitrogen_dioxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['no2'] }}"
      openweathermap_forecast_ozone:
        friendly_name: "Openweathermap Forecast: Ozone O3"
        device_class: "ozone"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['o3'] }}"
      openweathermap_forecast_sulfur_dioxide:
        friendly_name: "Openweathermap Forecast: Sulfur Dioxide SO2"
        device_class: "sulphur_dioxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['so2'] }}"
      openweathermap_forecast_particulate_matter_2_5:
        friendly_name: "Openweathermap Forecast: PM 2.5"
        device_class: "pm25"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['pm2_5'] }}"
      openweathermap_forecast_particulate_matter_10:
        friendly_name: "Openweathermap Forecast: PM 10"
        device_class: "pm10"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['pm10'] }}"
      openweathermap_forecast_ammonia:
        friendly_name: "Openweathermap Forecast: Ammonia NH3"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['nh3'] }}"

As for the forecast, it appears that the API sends back the next 5 days of forecast but the template only captures 1… so I assume it is tomorrow’s forecast. The forecast data comes back with a dt field that is unix time and date for the forecast day. I will play around with adding a template sensor to grab it to confirm the data shown is indeed the next day.

Edit: I did not add a device_class for Ammonia as I don’t believe HA has one. The unit_of_measurement: 'µg/m³' listed individually for all sensors may be unnecessary since I added the device_class. If anyone confirms (or I’ll give it a try), I can get rid of them to simplify the YAML.

Edit2: Lol, now I have an itch to put a PM sensor outdoors to see whether my measurements are close to what Openweathermap reports… Indoors, with the window next to me open I still read 10x what OPW says it should be (40µg vs 4 µg).

5 Likes

I am trying to grab the dt datapoint but don’t know how… the data sent back from OWM API is in this format:

{
  "coord": [
    50.0,
    50.0
  ],
  "list": [
    {
      "dt": 1605916800,
      "main": {
        "aqi": 1.0
      },
      "components": {
        "co": 211.954,
        "no": 0.0,
        "no2": 0.217,
        "o3": 72.956,
        "so2": 0.514,
        "pm2_5": 2.563,
        "pm10": 5.757,
        "nh3": 0.216
      }
    },
    {
      "dt": 1605920400,
      "main": {
        "aqi": 1.0
      },
      "components": {
        "co": 211.954,
        "no": 0.0,
        "no2": 0.201,
        "o3": 72.241,
        "so2": 0.469,
        "pm2_5": 2.662,
        "pm10": 5.622,
        "nh3": 0.224
      }
    },
    {
      "dt": 1605924000,
      "main": {
        "aqi": 1.0
      },
      "components": {
        "co": 213.623,
        "no": 0.0,
        "no2": 0.185,
        "o3": 71.526,
        "so2": 0.443,
        "pm2_5": 2.724,
        "pm10": 5.51,
        "nh3": 0.23
      }
    },
    {
      "dt": 1605927600,
      "main": {
        "aqi": 1.0
      },
      "components": {
        "co": 213.623,
        "no": 0.0,
        "no2": 0.17,
        "o3": 72.241,
        "so2": 0.432,
        "pm2_5": 2.812,
        "pm10": 5.687,
        "nh3": 0.234
      }
    },
    .....

In the code @cyn shared, the YAML to capture aqui under main is:

value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'main')['aqi'] }}"

so I tried a few variations to capture dt but it is not working. In my latest attempt I put dt for both the upper and lower level (sorry no idea what proper terms are), but I also tried omitting the lower level completely, or just leaving empty quotes.

value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'dt')['dt'] }}"

Any suggestions?

This is just a quick thought, try adding dt in the json attributes on the rest sensor configuration.
Can’t play today but might have time before football tomorrow.

1 Like

@cyn , you are awesome!

#Open Weather Map - Air Pollution API - Forecast Report
  - platform: rest
    name: "Openweathermap Forecast: Air Pollution"
    scan_interval: 3600
    resource: !secret openweathermap_forecast
    value_template: 'OK'
    json_attributes_path: "$.list[0]"
    json_attributes:
      - dt
      - main
      - components

and

  - platform: template
    sensors:
      openweathermap_forecast_air_pollution_forecast_date:
        friendly_name: "Openweathermap Forecast: Air Pollution Forecast Date"
        unique_id: openweathermap_forecast_air_pollution_forecast_date
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'dt') | timestamp_custom('%Y-%m-%d') }}"
        device_class: "date"
      openweathermap_forecast_air_quality_index:
        friendly_name: "Openweathermap Forecast: Air Quality Index"
        unique_id: openweathermap_forecast_air_quality_index
        device_class: "aqi"
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'main')['aqi'] }}"
      openweathermap_forecast_carbon_monoxide:
        friendly_name: "Openweathermap Forecast: Carbon Monoxide CO"
        unique_id: openweathermap_forecast_carbon_monoxide
        device_class: "carbon_monoxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ '%.2f' | format(state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['co'] / 100) }}"
      openweathermap_forecast_nitrogen_monoxide:
        friendly_name: "Openweathermap Forecast: Nitrogen Monoxide NO"
        unique_id: openweathermap_forecast_nitrogen_monoxide
        device_class: "nitrogen_monoxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['no'] }}"
      openweathermap_forecast_nitrogen_dioxide:
        friendly_name: "Openweathermap Forecast: Nitrogen Dioxide NO2"
        unique_id: openweathermap_forecast_nitrogen_dioxide
        device_class: "nitrogen_dioxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['no2'] }}"
      openweathermap_forecast_ozone:
        friendly_name: "Openweathermap Forecast: Ozone O3"
        unique_id: openweathermap_forecast_ozone
        device_class: "ozone"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['o3'] }}"
      openweathermap_forecast_sulfur_dioxide:
        friendly_name: "Openweathermap Forecast: Sulfur Dioxide SO2"
        unique_id: openweathermap_forecast_sulfur_dioxide
        device_class: "sulphur_dioxide"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['so2'] }}"
      openweathermap_forecast_particulate_matter_2_5:
        friendly_name: "Openweathermap Forecast: PM 2.5"
        unique_id: openweathermap_forecast_particulate_matter_2_5
        device_class: "pm25"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['pm2_5'] }}"
      openweathermap_forecast_particulate_matter_10:
        friendly_name: "Openweathermap Forecast: PM 10"
        unique_id: openweathermap_forecast_particulate_matter_10
        device_class: "pm10"
        unit_of_measurement: 'µg/m³'
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['pm10'] }}"
      openweathermap_forecast_ammonia:
        friendly_name: "Openweathermap Forecast: Ammonia NH3"
        unique_id: openweathermap_forecast_ammonia
        unit_of_measurement: 'µg/m³'
        icon_template: mdi:molecule
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'components')['nh3'] }}"

For easier readability, this is the part where I added the sensor to pull in the date:

      openweathermap_forecast_air_pollution_forecast_date:
        friendly_name: "Openweathermap Forecast: Air Pollution Forecast Date"
        unique_id: openweathermap_forecast_air_pollution_forecast_date
        value_template: "{{ state_attr('sensor.openweathermap_forecast_air_pollution', 'dt') | timestamp_custom('%Y-%m-%d') }}"
        device_class: "date"

The weird thing is that the date appears to be “today” but the values are different from the current forecast. Maybe, it was the forecast which obviously would never match actual so we would need to pull in dt + 1 day for it to be useful. I am guessing that is where ['dt'] comes into play but I have to figure out how to indicate which position in the array I need for the dt and all subsequent values.

On another note, by adding unique_id I eliminated an annoying error in the entity settings. Adding this also allows you to further customize the entity. I wonder whether there is some way to de-duplicate the YAML:

      openweathermap_forecast_air_pollution_forecast_date:

and

        unique_id: openweathermap_forecast_air_pollution_forecast_date

This is the data I get:

This is the output of the forecast API. I believe dt is in UTC so I also need to convert that to local. It appears the response includes hourly forecast data and it gets longer as time passes. When I checked the last dt it was 3 days out. The thing I don’t get is why the data that populated in my sensors doesn’t match any of the data below.

{"coord":{"lon":-xx.xxxx,"lat":xx.xxxx},"list":[{"main":{"aqi":1},"components":{"co":273.71,"no":0.01,"no2":10.63,"o3":44.7,"so2":0.1,"pm2_5":5.55,"pm10":8.91,"nh3":1.46},"dt":1672444800},{"main":{"aqi":1},"components":{"co":313.76,"no":0.03,"no2":16.79,"o3":30.04,"so2":0.07,"pm2_5":6.24,"pm10":9.35,"nh3":2},"dt":1672448400},{"main":{"aqi":1},"components":{"co":353.81,"no":0.13,"no2":21.25,"o3":17.35,"so2":0.05,"pm2_5":7.31,"pm10":10.49,"nh3":2.44},"dt":1672452000},{"main":{"aqi":1},"components":{"co":367.17,"no":0.24,"no2":21.59,"o3":11.62,"so2":0.05,"pm2_5":8.07,"pm10":11.26,"nh3":2.6},"dt":1672455600},{"main":{"aqi":1},"components":{"co":383.85,"no":0.48,"no2":22.62,"o3":7.42,"so2":0.06,"pm2_5":9,"pm10":12.29,"nh3":3.26},"dt":1672459200},{"main":{"aqi":1},"components":{"co":400.54,"no":0.94,"no2":23.99,"o3":4.11,"so2":0.08,"pm2_5":9.92,"pm10":13.13,"nh3":4.18},"dt":1672462800},{"main":{"aqi":1},"components":{"co":397.21,"no":0.89,"no2":22.96,"o3":3.76,"so2":0.1,"pm2_5":9.93,"pm10":12.72,"nh3":4.56},"dt":1672466400},{"main":{"aqi":1},"components":{"co":363.83,"no":0.23,"no2":19.88,"o3":7.24,"so2":0.11,"pm2_5":9.23,"pm10":11.44,"nh3":4.18},"dt":1672470000},{"main":{"aqi":1},"components":{"co":330.45,"no":0.04,"no2":15.59,"o3":12.52,"so2":0.11,"pm2_5":8.51,"pm10":10.28,"nh3":3.83},"dt":1672473600},{"main":{"aqi":1},"components":{"co":307.08,"no":0.02,"no2":12.68,"o3":16.45,"so2":0.12,"pm2_5":8.21,"pm10":9.75,"nh3":3.86},"dt":1672477200},{"main":{"aqi":1},"components":{"co":287.06,"no":0.01,"no2":10.37,"o3":17.7,"so2":0.1,"pm2_5":8.19,"pm10":9.76,"nh3":3.42},"dt":1672480800},{"main":{"aqi":1},"components":{"co":273.71,"no":0.04,"no2":8.82,"o3":14.84,"so2":0.08,"pm2_5":8.2,"pm10":10.09,"nh3":2.12},"dt":1672484400},{"main":{"aqi":1},"components":{"co":267.03,"no":0.15,"no2":8.48,"o3":10.01,"so2":0.06,"pm2_5":8.47,"pm10":10.73,"nh3":1.09},"dt":1672488000},{"main":{"aqi":1},"components":{"co":263.69,"no":0.3,"no2":8.48,"o3":8.76,"so2":0.08,"pm2_5":7.7,"pm10":9.71,"nh3":0.56},"dt":1672491600},{"main":{"aqi":1},"components":{"co":290.39,"no":0.89,"no2":12.34,"o3":5.9,"so2":0.1,"pm2_5":7.39,"pm10":9.15,"nh3":0.5},"dt":1672495200},{"main":{"aqi":1},"components":{"co":330.45,"no":5.2,"no2":12.68,"o3":9.48,"so2":0.18,"pm2_5":7.26,"pm10":9.06,"nh3":0.56},"dt":1672498800},{"main":{"aqi":1},"components":{"co":290.39,"no":4.36,"no2":10.11,"o3":30.4,"so2":0.81,"pm2_5":4.64,"pm10":6.32,"nh3":0.61},"dt":1672502400},{"main":{"aqi":1},"components":{"co":283.72,"no":5.09,"no2":9.17,"o3":35.05,"so2":1.01,"pm2_5":4.29,"pm10":6.27,"nh3":0.82},"dt":1672506000},{"main":{"aqi":1},"components":{"co":270.37,"no":4.14,"no2":7.8,"o3":41.13,"so2":1.15,"pm2_5":4.01,"pm10":6.09,"nh3":0.94},"dt":1672509600},{"main":{"aqi":2},"components":{"co":223.64,"no":1.12,"no2":3.51,"o3":65.09,"so2":1.67,"pm2_5":2.4,"pm10":3.97,"nh3":0.65},"dt":1672513200},{"main":{"aqi":2},"components":{"co":208.62,"no":0.47,"no2":2.04,"o3":77.25,"so2":2.8,"pm2_5":2.19,"pm10":3.6,"nh3":0.47},"dt":1672516800},{"main":{"aqi":2},"components":{"co":206.95,"no":0.35,"no2":1.89,"o3":82.97,"so2":2.74,"pm2_5":2.4,"pm10":3.88,"nh3":0.44},"dt":1672520400},{"main":{"aqi":2},"components":{"co":210.29,"no":0.31,"no2":2.51,"o3":83.69,"so2":2.3,"pm2_5":3.05,"pm10":4.73,"nh3":0.51},"dt":1672524000},{"main":{"aqi":2},"components":{"co":223.64,"no":0.25,"no2":5.01,"o3":80.82,"so2":2.24,"pm2_5":4.3,"pm10":6.27,"nh3":0.67},"dt":1672527600},{"main":{"aqi":2},"components":{"co":236.99,"no":0.02,"no2":7.88,"o3":77.25,"so2":2.44,"pm2_5":5.4,"pm10":7.69,"nh3":0.82},"dt":1672531200},{"main":{"aqi":2},"components":{"co":247,"no":0,"no2":9.43,"o3":73.67,"so2":2.65,"pm2_5":5.72,"pm10":8.14,"nh3":0.93},"dt":1672534800},{"main":{"aqi":2},"components":{"co":247,"no":0,"no2":9.94,"o3":69.38,"so2":2.89,"pm2_5":5.45,"pm10":7.82,"nh3":0.95},"dt":1672538400},{"main":{"aqi":2},"components":{"co":243.66,"no":0,"no2":9.25,"o3":65.09,"so2":3.1,"pm2_5":5.38,"pm10":7.65,"nh3":0.94},"dt":1672542000},{"main":{"aqi":2},"components":{"co":236.99,"no":0,"no2":7.8,"o3":63.66,"so2":2.86,"pm2_5":5.37,"pm10":7.61,"nh3":0.97},"dt":1672545600},{"main":{"aqi":2},"components":{"co":233.65,"no":0,"no2":6.43,"o3":64.37,"so2":2.27,"pm2_5":5.64,"pm10":8.07,"nh3":1.03},"dt":1672549200},{"main":{"aqi":2},"components":{"co":230.31,"no":0,"no2":5.14,"o3":65.09,"so2":1.83,"pm2_5":6.53,"pm10":9.41,"nh3":1},"dt":1672552800},{"main":{"aqi":2},"components":{"co":230.31,"no":0,"no2":4.11,"o3":65.09,"so2":1.67,"pm2_5":7.82,"pm10":10.96,"nh3":0.85},"dt":1672556400},{"main":{"aqi":2},"components":{"co":226.97,"no":0,"no2":3.73,"o3":64.37,"so2":1.62,"pm2_5":9.13,"pm10":12.15,"nh3":0.67},"dt":1672560000},{"main":{"aqi":2},"components":{"co":226.97,"no":0,"no2":3.68,"o3":65.09,"so2":1.65,"pm2_5":9.84,"pm10":12.51,"nh3":0.52},"dt":1672563600},{"main":{"aqi":2},"components":{"co":223.64,"no":0,"no2":3.68,"o3":65.8,"so2":1.67,"pm2_5":9.51,"pm10":11.8,"nh3":0.42},"dt":1672567200},{"main":{"aqi":2},"components":{"co":220.3,"no":0,"no2":3.73,"o3":65.09,"so2":1.61,"pm2_5":8.77,"pm10":10.83,"nh3":0.38},"dt":1672570800},{"main":{"aqi":2},"components":{"co":220.3,"no":0,"no2":4.07,"o3":63.66,"so2":1.55,"pm2_5":8.29,"pm10":10.29,"nh3":0.37},"dt":1672574400},{"main":{"aqi":2},"components":{"co":223.64,"no":0,"no2":5.06,"o3":60.08,"so2":1.54,"pm2_5":7.97,"pm10":10.06,"nh3":0.38},"dt":1672578000},{"main":{"aqi":1},"components":{"co":233.65,"no":0.01,"no2":7.11,"o3":55.79,"so2":1.68,"pm2_5":7.96,"pm10":10.37,"nh3":0.38},"dt":1672581600},{"main":{"aqi":1},"components":{"co":243.66,"no":0.46,"no2":8.4,"o3":53.64,"so2":2,"pm2_5":8.22,"pm10":11.25,"nh3":0.33},"dt":1672585200},{"main":{"aqi":1},"components":{"co":243.66,"no":1.16,"no2":7.37,"o3":54.36,"so2":2.27,"pm2_5":8.6,"pm10":12.38,"nh3":0.25},"dt":1672588800},{"main":{"aqi":1},"components":{"co":240.33,"no":1.3,"no2":6.6,"o3":55.08,"so2":2.33,"pm2_5":9.05,"pm10":13.27,"nh3":0.19},"dt":1672592400},{"main":{"aqi":1},"components":{"co":236.99,"no":1.1,"no2":6.08,"o3":57.22,"so2":2.21,"pm2_5":9.45,"pm10":13.57,"nh3":0.1},"dt":1672596000},{"main":{"aqi":2},"components":{"co":230.31,"no":0.73,"no2":5.31,"o3":63.66,"so2":1.89,"pm2_5":10.05,"pm10":13.65,"nh3":0.02},"dt":1672599600},{"main":{"aqi":2},"components":{"co":230.31,"no":0.5,"no2":4.67,"o3":67.23,"so2":1.49,"pm2_5":10.36,"pm10":13.59,"nh3":0.05},"dt":1672603200},{"main":{"aqi":2},"components":{"co":226.97,"no":0.34,"no2":3.43,"o3":70.81,"so2":0.94,"pm2_5":10,"pm10":13,"nh3":0.1},"dt":1672606800},{"main":{"aqi":2},"components":{"co":230.31,"no":0.4,"no2":2.61,"o3":71.53,"so2":0.52,"pm2_5":9.82,"pm10":12.68,"nh3":0.22},"dt":1672610400},{"main":{"aqi":2},"components":{"co":233.65,"no":0.25,"no2":3.6,"o3":65.8,"so2":0.35,"pm2_5":9.42,"pm10":12.2,"nh3":0.45},"dt":1672614000},{"main":{"aqi":1},"components":{"co":236.99,"no":0.02,"no2":4.84,"o3":57.22,"so2":0.29,"pm2_5":7.92,"pm10":10.43,"nh3":0.58},"dt":1672617600},{"main":{"aqi":1},"components":{"co":233.65,"no":0,"no2":4.93,"o3":54.36,"so2":0.29,"pm2_5":6.16,"pm10":8.38,"nh3":0.58},"dt":1672621200},{"main":{"aqi":1},"components":{"co":226.97,"no":0,"no2":4.63,"o3":55.08,"so2":0.26,"pm2_5":5.17,"pm10":7.52,"nh3":0.52},"dt":1672624800},{"main":{"aqi":1},"components":{"co":223.64,"no":0,"no2":3.86,"o3":53.64,"so2":0.19,"pm2_5":4.54,"pm10":7.15,"nh3":0.39},"dt":1672628400},{"main":{"aqi":1},"components":{"co":211.95,"no":0,"no2":2.7,"o3":45.06,"so2":0.16,"pm2_5":3.74,"pm10":6.01,"nh3":0.27},"dt":1672632000},{"main":{"aqi":1},"components":{"co":205.28,"no":0,"no2":2.14,"o3":37.55,"so2":0.16,"pm2_5":3.46,"pm10":5.36,"nh3":0.22},"dt":1672635600},{"main":{"aqi":1},"components":{"co":203.61,"no":0,"no2":1.76,"o3":37.19,"so2":0.17,"pm2_5":3.58,"pm10":5.53,"nh3":0.19},"dt":1672639200},{"main":{"aqi":1},"components":{"co":201.94,"no":0,"no2":1.5,"o3":39.34,"so2":0.2,"pm2_5":3.84,"pm10":5.91,"nh3":0.17},"dt":1672642800},{"main":{"aqi":1},"components":{"co":200.27,"no":0,"no2":1.36,"o3":40.05,"so2":0.22,"pm2_5":3.95,"pm10":6.03,"nh3":0.15},"dt":1672646400},{"main":{"aqi":1},"components":{"co":198.6,"no":0,"no2":1.23,"o3":40.41,"so2":0.23,"pm2_5":4.09,"pm10":6.08,"nh3":0.14},"dt":1672650000},{"main":{"aqi":1},"components":{"co":198.6,"no":0,"no2":1.18,"o3":39.7,"so2":0.25,"pm2_5":4.19,"pm10":5.94,"nh3":0.13},"dt":1672653600},{"main":{"aqi":1},"components":{"co":198.6,"no":0,"no2":1.18,"o3":38.27,"so2":0.25,"pm2_5":4.15,"pm10":5.56,"nh3":0.12},"dt":1672657200},{"main":{"aqi":1},"components":{"co":200.27,"no":0,"no2":1.3,"o3":36.48,"so2":0.24,"pm2_5":4.51,"pm10":5.68,"nh3":0.12},"dt":1672660800},{"main":{"aqi":1},"components":{"co":203.61,"no":0,"no2":1.71,"o3":35.76,"so2":0.23,"pm2_5":4.81,"pm10":5.69,"nh3":0.12},"dt":1672664400},{"main":{"aqi":1},"components":{"co":205.28,"no":0,"no2":2.42,"o3":34.69,"so2":0.26,"pm2_5":4.3,"pm10":5,"nh3":0.14},"dt":1672668000},{"main":{"aqi":1},"components":{"co":203.61,"no":0.01,"no2":2.68,"o3":33.62,"so2":0.3,"pm2_5":3.52,"pm10":4.09,"nh3":0.15},"dt":1672671600},{"main":{"aqi":1},"components":{"co":195.27,"no":0.06,"no2":2.38,"o3":34.33,"so2":0.3,"pm2_5":2.9,"pm10":3.37,"nh3":0.15},"dt":1672675200},{"main":{"aqi":1},"components":{"co":188.59,"no":0.12,"no2":2.14,"o3":35.05,"so2":0.32,"pm2_5":2.38,"pm10":2.76,"nh3":0.15},"dt":1672678800},{"main":{"aqi":1},"components":{"co":185.25,"no":0.18,"no2":1.99,"o3":35.41,"so2":0.36,"pm2_5":2.12,"pm10":2.47,"nh3":0.15},"dt":1672682400},{"main":{"aqi":1},"components":{"co":186.92,"no":0.35,"no2":2.44,"o3":36.12,"so2":0.59,"pm2_5":1.92,"pm10":2.37,"nh3":0.18},"dt":1672686000},{"main":{"aqi":1},"components":{"co":193.6,"no":0.69,"no2":3,"o3":40.05,"so2":0.89,"pm2_5":1.89,"pm10":2.49,"nh3":0.24},"dt":1672689600},{"main":{"aqi":1},"components":{"co":200.27,"no":0.75,"no2":3,"o3":46.49,"so2":0.9,"pm2_5":1.98,"pm10":2.59,"nh3":0.27},"dt":1672693200},{"main":{"aqi":1},"components":{"co":213.62,"no":0.77,"no2":3.94,"o3":52.21,"so2":1.09,"pm2_5":2.53,"pm10":3.24,"nh3":0.36},"dt":1672696800},{"main":{"aqi":1},"components":{"co":236.99,"no":0.55,"no2":7.11,"o3":54.36,"so2":2.15,"pm2_5":3.92,"pm10":4.89,"nh3":0.51},"dt":1672700400},{"main":{"aqi":1},"components":{"co":257.02,"no":0.05,"no2":10.45,"o3":54.36,"so2":3.01,"pm2_5":6.21,"pm10":7.54,"nh3":0.63},"dt":1672704000},{"main":{"aqi":1},"components":{"co":280.38,"no":0,"no2":13.54,"o3":49.35,"so2":2.62,"pm2_5":9.11,"pm10":10.99,"nh3":0.92},"dt":1672707600},{"main":{"aqi":2},"components":{"co":307.08,"no":0,"no2":15.77,"o3":41.13,"so2":1.76,"pm2_5":12.15,"pm10":14.73,"nh3":1.2},"dt":1672711200},{"main":{"aqi":2},"components":{"co":313.76,"no":0,"no2":13.71,"o3":38.27,"so2":1.16,"pm2_5":13.72,"pm10":16.7,"nh3":1.19},"dt":1672714800},{"main":{"aqi":2},"components":{"co":300.41,"no":0,"no2":9.94,"o3":38.98,"so2":0.82,"pm2_5":12.07,"pm10":14.87,"nh3":1.14},"dt":1672718400},{"main":{"aqi":1},"components":{"co":260.35,"no":0,"no2":4.97,"o3":43.99,"so2":0.47,"pm2_5":7.7,"pm10":10.34,"nh3":1.11},"dt":1672722000},{"main":{"aqi":1},"components":{"co":220.3,"no":0,"no2":2.04,"o3":56.51,"so2":0.2,"pm2_5":3.45,"pm10":6.81,"nh3":0.94},"dt":1672725600},{"main":{"aqi":2},"components":{"co":195.27,"no":0,"no2":1,"o3":79.39,"so2":0.1,"pm2_5":1,"pm10":2.85,"nh3":0.59},"dt":1672729200},{"main":{"aqi":2},"components":{"co":190.26,"no":0,"no2":0.69,"o3":91.55,"so2":0.08,"pm2_5":0.5,"pm10":1.14,"nh3":0.49},"dt":1672732800},{"main":{"aqi":2},"components":{"co":188.59,"no":0,"no2":0.56,"o3":97.28,"so2":0.08,"pm2_5":0.5,"pm10":1.19,"nh3":0.5},"dt":1672736400},{"main":{"aqi":2},"components":{"co":191.93,"no":0,"no2":0.51,"o3":95.84,"so2":0.09,"pm2_5":0.53,"pm10":2.16,"nh3":0.55},"dt":1672740000},{"main":{"aqi":2},"components":{"co":191.93,"no":0,"no2":0.55,"o3":92.98,"so2":0.1,"pm2_5":0.84,"pm10":3.75,"nh3":0.63},"dt":1672743600},{"main":{"aqi":2},"components":{"co":193.6,"no":0,"no2":0.71,"o3":88.69,"so2":0.1,"pm2_5":1.07,"pm10":4.85,"nh3":0.7},"dt":1672747200},{"main":{"aqi":2},"components":{"co":196.93,"no":0,"no2":1.29,"o3":85.12,"so2":0.11,"pm2_5":1.25,"pm10":5.49,"nh3":0.78},"dt":1672750800},{"main":{"aqi":2},"components":{"co":201.94,"no":0,"no2":2.01,"o3":82.25,"so2":0.12,"pm2_5":1.33,"pm10":5.66,"nh3":0.82},"dt":1672754400},{"main":{"aqi":2},"components":{"co":201.94,"no":0.03,"no2":2.06,"o3":81.54,"so2":0.13,"pm2_5":1.32,"pm10":5.71,"nh3":0.78},"dt":1672758000},{"main":{"aqi":2},"components":{"co":198.6,"no":0.11,"no2":1.48,"o3":82.25,"so2":0.14,"pm2_5":1.19,"pm10":5.26,"nh3":0.68},"dt":1672761600},{"main":{"aqi":2},"components":{"co":195.27,"no":0.16,"no2":1.05,"o3":85.12,"so2":0.14,"pm2_5":1.05,"pm10":4.6,"nh3":0.59},"dt":1672765200},{"main":{"aqi":2},"components":{"co":191.93,"no":0.15,"no2":0.77,"o3":88.69,"so2":0.14,"pm2_5":1.13,"pm10":4.98,"nh3":0.55},"dt":1672768800},{"main":{"aqi":2},"components":{"co":191.93,"no":0.12,"no2":0.61,"o3":92.98,"so2":0.14,"pm2_5":1.26,"pm10":5.58,"nh3":0.48},"dt":1672772400},{"main":{"aqi":2},"components":{"co":191.93,"no":0.11,"no2":0.58,"o3":95.84,"so2":0.14,"pm2_5":1.36,"pm10":5.79,"nh3":0.45},"dt":1672776000},{"main":{"aqi":2},"components":{"co":191.93,"no":0.1,"no2":0.61,"o3":95.84,"so2":0.16,"pm2_5":1.53,"pm10":6.37,"nh3":0.48},"dt":1672779600},{"main":{"aqi":2},"components":{"co":200.27,"no":0.24,"no2":1.63,"o3":88.69,"so2":0.16,"pm2_5":1.76,"pm10":6.71,"nh3":0.62},"dt":1672783200},{"main":{"aqi":2},"components":{"co":213.62,"no":0.33,"no2":4.2,"o3":77.96,"so2":0.16,"pm2_5":2.05,"pm10":6.95,"nh3":0.86},"dt":1672786800},{"main":{"aqi":2},"components":{"co":230.31,"no":0.05,"no2":6.68,"o3":69.38,"so2":0.14,"pm2_5":2.26,"pm10":7.1,"nh3":1.08},"dt":1672790400},{"main":{"aqi":2},"components":{"co":236.99,"no":0,"no2":7.45,"o3":66.52,"so2":0.13,"pm2_5":2.47,"pm10":7.39,"nh3":1.24},"dt":1672794000},{"main":{"aqi":2},"components":{"co":236.99,"no":0,"no2":6.94,"o3":65.09,"so2":0.12,"pm2_5":2.61,"pm10":7.38,"nh3":1.31},"dt":1672797600},{"main":{"aqi":2},"components":{"co":240.33,"no":0,"no2":6.6,"o3":62.23,"so2":0.13,"pm2_5":2.7,"pm10":7.02,"nh3":1.36},"dt":1672801200},{"main":{"aqi":1},"components":{"co":243.66,"no":0,"no2":7.2,"o3":57.94,"so2":0.16,"pm2_5":2.75,"pm10":6.53,"nh3":1.43},"dt":1672804800},{"main":{"aqi":1},"components":{"co":233.65,"no":0,"no2":6.43,"o3":57.22,"so2":0.16,"pm2_5":2.42,"pm10":5.69,"nh3":1.35},"dt":1672808400},{"main":{"aqi":2},"components":{"co":220.3,"no":0,"no2":4.5,"o3":60.08,"so2":0.12,"pm2_5":1.89,"pm10":4.85,"nh3":1.19},"dt":1672812000},{"main":{"aqi":2},"components":{"co":208.62,"no":0,"no2":2.83,"o3":62.94,"so2":0.11,"pm2_5":1.58,"pm10":4.85,"nh3":1.05},"dt":1672815600},{"main":{"aqi":2},"components":{"co":203.61,"no":0,"no2":2.01,"o3":63.66,"so2":0.1,"pm2_5":1.65,"pm10":6.09,"nh3":1},"dt":1672819200},{"main":{"aqi":2},"components":{"co":201.94,"no":0,"no2":1.69,"o3":65.09,"so2":0.12,"pm2_5":2.03,"pm10":8.55,"nh3":1},"dt":1672822800},{"main":{"aqi":2},"components":{"co":201.94,"no":0,"no2":1.46,"o3":67.23,"so2":0.14,"pm2_5":2.62,"pm10":11.42,"nh3":1},"dt":1672826400},{"main":{"aqi":2},"components":{"co":203.61,"no":0,"no2":1.34,"o3":70.1,"so2":0.17,"pm2_5":3.02,"pm10":12.41,"nh3":0.99},"dt":1672830000},{"main":{"aqi":2},"components":{"co":206.95,"no":0,"no2":1.41,"o3":72.24,"so2":0.2,"pm2_5":3.11,"pm10":11.83,"nh3":1},"dt":1672833600},{"main":{"aqi":2},"components":{"co":211.95,"no":0,"no2":1.99,"o3":72.96,"so2":0.22,"pm2_5":3.1,"pm10":11.16,"nh3":1.06},"dt":1672837200},{"main":{"aqi":2},"components":{"co":216.96,"no":0,"no2":3,"o3":72.24,"so2":0.23,"pm2_5":3.06,"pm10":10.71,"nh3":1.12},"dt":1672840800},{"main":{"aqi":2},"components":{"co":220.3,"no":0.14,"no2":2.91,"o3":74.39,"so2":0.25,"pm2_5":2.97,"pm10":10.99,"nh3":1.08},"dt":1672844400},{"main":{"aqi":2},"components":{"co":216.96,"no":0.28,"no2":1.99,"o3":79.39,"so2":0.3,"pm2_5":2.97,"pm10":12.84,"nh3":0.96},"dt":1672848000},{"main":{"aqi":2},"components":{"co":213.62,"no":0.34,"no2":1.63,"o3":80.82,"so2":0.3,"pm2_5":3.16,"pm10":14.89,"nh3":0.93},"dt":1672851600},{"main":{"aqi":2},"components":{"co":211.95,"no":0.29,"no2":1.31,"o3":83.69,"so2":0.29,"pm2_5":3.55,"pm10":17.71,"nh3":0.89},"dt":1672855200},{"main":{"aqi":2},"components":{"co":208.62,"no":0.16,"no2":0.79,"o3":94.41,"so2":0.25,"pm2_5":4.19,"pm10":22.78,"nh3":0.61},"dt":1672858800},{"main":{"aqi":2},"components":{"co":208.62,"no":0.13,"no2":0.73,"o3":95.84,"so2":0.24,"pm2_5":5.42,"pm10":31,"nh3":0.59},"dt":1672862400},{"main":{"aqi":2},"components":{"co":208.62,"no":0.12,"no2":0.75,"o3":95.84,"so2":0.24,"pm2_5":6.03,"pm10":35.16,"nh3":0.63},"dt":1672866000},{"main":{"aqi":2},"components":{"co":233.65,"no":0.73,"no2":4.11,"o3":77.25,"so2":0.2,"pm2_5":6.52,"pm10":33.71,"nh3":1.06},"dt":1672869600},{"main":{"aqi":2},"components":{"co":270.37,"no":1.03,"no2":9.94,"o3":55.79,"so2":0.15,"pm2_5":7.17,"pm10":32.7,"nh3":1.55},"dt":1672873200},{"main":{"aqi":2},"components":{"co":297.07,"no":0.16,"no2":15.59,"o3":41.49,"so2":0.12,"pm2_5":7.5,"pm10":32.06,"nh3":1.98},"dt":1672876800}]}

It appears I am getting the first row from the API response pasted above:

dt for that row is:

I am puzzled… is it a forecast for the beginning of the hour? 18.39 right now, and dt is for 18:00. The next dt is for 19:00

The 7th row has midnight… the 8th row 01:00 and so on…

How do I get the next day forecast? I have never worked with an API so I may be asking a noobie question…

1 Like

I just came across this thread. I checked the OpenWeatherMap folder, but could not find the mentioned files “secrets.yaml” or “configuration.yaml”. Could someone please help? TIA.

I recommend you install Studio Code Server addon and both files will be super easy to find and edit. They are in the root config folder if I recall correctly and are not specific to OpenWeather but rather core files of HA.

1 Like

@cyn , @aruffell - Thank you for sharing your amazing work!

I’ve just added your code to HA. Very pleased with the output. Did you ever get UTC / local time figured out?

I think what I have now may have evolved from what is shared here. As soon as I can, I will review what I have and share that. You will likely notice some log warnings about the unit of measure for some of the metrics. Based on my research, it would seem that HA erroneously states those metrics should be PPM instead of what I used (which also matches the API output). An important European report on pollution also used the same unit of measure (microgram per meter cube) so am I not inclined to change it no matter the frequent log warnings. I believe I also had created a Github issue which I believe was summarily dismissed.

@aruffell Thank you for the overview of this functionality, I would be interested in any updated details you can share as I would like to implement this in my setup