[RELEASE] Free PurpleAir Air Quality Station - Now with native Hubitat support!

Do a string search for the station name … the ID is three “fields” to the left, right after the brace, ‘{’ … and just pray that the station name is unique :smile:

BTW, the station name will appear twice … for channels A and B. You probably can use either, but I just use the ID for channel A.

1 Like

Thanks I will try that.


That looks to be a WebCore bug - the value (as a number) displays correctly in my DTH, and it is also stored correctly in the State variables for the DTH.


In webCoRE, using your unmodified DTH, I tried retrieving the data as integers, floats, and strings ---- with the same results :frowning_face:

I suggest reporting the bug to the WebCore team.

1 Like

Just checking out some of the indoor sensors in the LA area … l know it gets smoggy there at times, but geez LOL … hope everyone is alright:

Has anyone been able to figure out how to pull this reading into ActionTiles? I get temperature and humidity but have not been able to pull the most recent air quality reading into a tile.

You may need to contact he Action Tiles guys about it - there isn’t a native “air quality” attribute in SmartThings.

Thanks for the good info. That brings an interesting idea. I will just build a Piston to copy the data to an attribute it can understand.


Barry (@storageanarchy), the DH works fine on Hubitat … just two, very minor changes:

 Commented out line 37:     include 'asynchttp_v1'
 Changed line 254 from:
       asynchttp_v1.get(purpleAirResponse, params)
       asynchttpGet(purpleAirResponse, params)

Got all the AQI data displayed via webCoRE.

Very cool - I will annotate the code to reflect those changes…

I take it that there isn’t a way to tell if code is running (or being compiled) on hubitat vs. smartthings…

Updated to v1.0.13 on November 7, 2018 at 11:25am EST

  • Annotated the two edits required to make this run on hubitat (thanks @elf )

No actual code changes, so there is no need for anyone to upgrade to the latest

Fairly sure it’s running on the Hubitat hub, but, I may have fallen for Hubitat propaganda about localization :smile: … I suppose I could disconnect my internet connection to find out, but of course, I won’t have access to the PurpleAir data servers LOL.

I’m pretty sure its running on the hub also. What I’m wondering is whether there is some way I could set the source code up so that it automatically compiled correctly based on some flag or compile-time variable. I know I can create my own flag, just curious if the Hubitat have created something so I could do this:

if (running_on_hubitat) { asynchttpget() } else { asyncHttp_v1.get() }


Yeah, that would be ideal.

Got the hub about two weeks ago, so I’m still groping around (hmmm … bad phrase to use these days) the Hubitat environment … and still have to migrate some my devices :neutral_face: Haven’t had a chance to look at some of the developer docs.

Hello, I Must be missing something. Im looking for the station ID for CCA Hillcrest & Rodeo. Can you help?

“ID”:6170,“ParentID”:null,“Label”:“CCA Hillcrest & Rodeo”


How to find your PurpleAir Sensor ID

  1. In your browser, go to http://purpleair.com/json
    • This lists EVERY registered PurpleAir station
    • This will take a while - minutes even - this is now a HUGE JSON payload
    • If you use Chrome, I suggest finding and installing the jsonview plug-in (makes the JSON more human-friendly)
  2. Use your browser search feature to search for the name you gave your station when you registered it
    • You should find an entry like the example below
    • Your STATION ID is the number after the first occurrence of "ID: " (the one that has a Parent ID of null)
    • The second ID (if present) is the ID of your secondary sensor (if your PurpleAir has 2 - Internal ones only have 1)
    • The PurpleAir DTH will find and use both sensors’ data if they are marked as valid by PurpleAir



  • ID: 2492,
    * ParentID: null,
    * Label: “'66 Envi Center”,
    * DEVICE_LOCATIONTYPE: “outside”,
    * THINGSPEAK_PRIMARY_ID: “312808”,
    * Lat: 42.714377,
    * Lon: -73.202118,
    * PM2_5Value: “4.87”,
    * LastSeen: 1542814921,
    * State: null,
    * Type: “PMS5003+PMS5003+BME280”,
    * Hidden: “false”,
    * Flag: null,
    * isOwner: 0,
    * A_H: null,
    * temp_f: “42”,
    * humidity: “46”,
    * pressure: “989.21”,
    * AGE: 84,
    * Stats: “{“v”:4.87,“v1”:5.22,“v2”:5.37,“v3”:5.87,“v4”:7.22,“v5”:10.18,“v6”:6.27,“pm”:4.87,” lastModified":1542814921928,“timeSinceModified”:79983}"
    * ID: 2493,
    * ParentID: 2492,
    * Label: “'66 Envi Center B”,
    * THINGSPEAK_PRIMARY_ID: “312810”,
    * Lat: 42.714377,
    * Lon: -73.202118,
    * PM2_5Value: “0.00”,
    * LastSeen: 1542814871,
    * State: null,
    * Type: null,
    * Hidden: “false”,
    * Flag: 1,
    * isOwner: 0,
    * A_H: null,
    * temp_f: “42”,
    * humidity: “46”,
    * pressure: “989.27”,
    * AGE: 84,
    * Stats: “{“v”:0.0,“v1”:0.0,“v2”:0.0,“v3”:0.0,“v4”:0.0,“v5”:0.0,“v6”:0.3,“pm”:0.0, “lastModified”:1542814871915,“timeSinceModified”:79998}”

This is really cool. Thanks for developing. Is there a way to trigger actions if AQI exceeds a certain amount?

Yes, of course:

  • You can subscribe to the attribute “aqi”: subscribe(purpleDevice, 'aqi', aqiChangeHandler)
  • or poll it: device.currentValue('aqi') which will return the AQI
  • or use it directly within WebCoRE

Its value should always be a number (or null when first starting up).