When using the PurpleAir Utility or a Classic-SD sensor modified to record SD data every second data is not in CSV format. Instead, it is in a custom format described below, which may require additional processing to use.
Data From WiFi Capable Sensors
1-second Reports
Every second, one of the laser counters will report. Five reports will be recorded from channel A, then five reports from channel B. This process repeats until the next 2-minute report. This 2-minute report is the averaged data that is uploaded to our API as “Real-time” data. This is the same “Real-time” data you will see for sensors on our map. Intermittent reports from gas sensor (if gas sensor applicable) are recorded about every three seconds, and will appear interspersed with the 1-second reports from the laser counters. Example reports are found below.
Channel A report
.0h10:54.538 2022/12/30T22:10:10z: DATA A(34),82,14,29,859.35,0.03,17872,-57,654,222,508,955,147,338,636,505,388,38928,11925,4614,1296,592,368,25.00Channel A report
.0h10:55.456 2022/12/30T22:10:11z: DATA A(35),82,14,29,859.35,0.03,17872,-57,655,223,508,967,148,338,644,505,388,38850,11927,4602,1318,610,372,25.00Gas Sensor Report
.0h10:56.598 2022/12/30T22:10:12z: p:85936.06 gasR:12917166.00 iaq:25.00 iaqA:0 T:28.12(28.18) H:14.92(14.87) sIaq:25.00 co2Eq:500.00 breathVocEq:0.50Channel B report
.0h10:57.350 2022/12/30T22:10:13z: DATA B(34),82,14,29,859.36,0.03,17872,-56,657,205,485,1018,136,323,678,490,373,35928,11126,4122,1506,756,376,25.00Channel B report
.0h10:58.267 2022/12/30T22:10:14z: DATA B(35),82,14,29,859.36,0.02,17872,-56,658,203,490,1044,135,326,695,493,376,35853,11090,4177,1570,790,390,25.00
1-second Report Breakdown
Channel A Report
.0h11:24.761 2022/12/30T22:10:40z: DATA A(48),82,14,29,859.38,0.03,17872,-59,684,221,496,874,146,330,581,497,380,38442,11710,4418,1206,506,284,25.00
Name | Value |
---|---|
Uptime (written out; includes milliseconds) | .0h11:24.761 |
UTCDateTime | 2022/12/30T22:10:40z |
Channel (number of samples from channel since last upload) | DATA A(48) |
current_temp_f | 82 |
current_humidity | 14 |
current_dewpoint_f | 29 |
pressure | 859.38 |
adc | 0.03 |
mem | 17872 |
rssi | -59 |
uptime | 684 |
pm1_0_cf_1 | 221 |
pm2_5_cf_1 | 496 |
pm10_0_cf_1 | 874 |
pm1_0_atm | 146 |
pm2_5_atm | 330 |
pm10_0_atm | 581 |
pm2.5_aqi_cf_1 | 497 |
pm2.5_aqi_atm | 380 |
p_0_3_um | 38442 |
p_0_5_um | 11710 |
p_1_0_um | 4418 |
p_2_5_um | 1206 |
p_5_0_um | 506 |
p_10_0_um | 284 |
gas | 25.00 |
2-minute Report
This data is what is considered “Real-time” on the Map and API
Every two minutes, the sensor attempts to upload data to PurpleAir, even if it isn’t connected to WiFi. If uploading data fails, an Error: -1
message will be output.
Below is an example of the three sections of a 2-minute report. Section 1 is the raw 2-minute data. This data is used to create the 2-minute report that is uploaded to the API (Section 3). Sections 2 and 3 will be broken down below the example.
1.
{“SensorId”:“xx:xx:xx:xx:xx:xx”,“DateTime”:“2022/12/30T22:00:59z”,“Geo”:“PurpleAir-6e32”,“Mem”:12345,“memfrag”:3,“memfb”:35824,“memcs”:2464,“Id”:1,“lat”:0.000000,“lon”:0.000000,“Adc”:“nan”,“loggingrate”:15,“place”:“”,“version”:“7.02”,“uptime”:103,“rssi”:-62,“period”:103,“httpsuccess”:1,“httpsends”:1,“hardwareversion”:“3.0”,“hardwarediscovered”:“3.0+OPENLOG+NO-DISK+RV3028+BME680+PMSX003-A+PMSX003-B”,“current_temp_f”:82,“current_humidity”:15,“current_dewpoint_f”:30,“pressure”:859.56,“current_temp_f_680”:82,“current_humidity_680”:15,“current_dewpoint_f_680”:30,“pressure_680”:859.56,“gas_680”:“nan”,“p25aqic_b”:“rgb(0,228,0)”,“pm2.5_aqi_b”:0,“pm1_0_cf_1_b”:0.00,“p_0_3_um_b”:72.33,“pm2_5_cf_1_b”:0.00,“p_0_5_um_b”:22.96,“pm10_0_cf_1_b”:0.00,“p_1_0_um_b”:3.38,“pm1_0_atm_b”:0.00,“p_2_5_um_b”:0.22,“pm2_5_atm_b”:0.00,“p_5_0_um_b”:0.00,“pm10_0_atm_b”:0.00,“p_10_0_um_b”:0.00,“p25aqic”:“rgb(0,228,0)”,“pm2.5_aqi”:1,“pm1_0_cf_1”:0.00,“p_0_3_um”:128.02,“pm2_5_cf_1”:0.19,“p_0_5_um”:30.47,“pm10_0_cf_1”:0.33,“p_1_0_um”:7.02,“pm1_0_atm”:0.00,“p_2_5_um”:3.23,“pm2_5_atm”:0.19,“p_5_0_um”:0.56,“pm10_0_atm”:0.33,“p_10_0_um”:0.00,“wlstate”:“Connected”,“status_0”:2,“status_1”:2,“status_2”:2,“status_3”:0,“status_4”:0,“status_5”:0,“status_7”:0,“status_8”:0,“status_9”:0}
2.
UTCDateTime,mac_address,firmware_ver,hardware,current_temp_f,current_humidity,current_dewpoint_f,pressure,adc,mem,rssi,uptime,pm1_0_cf_1,pm2_5_cf_1,pm10_0_cf_1,pm1_0_atm,pm2_5_atm,pm10_0_atm,pm2.5_aqi_cf_1,pm2.5_aqi_atm,p_0_3_um,p_0_5_um,p_1_0_um,p_2_5_um,p_5_0_um,p_10_0_um,pm1_0_cf_1_b,pm2_5_cf_1_b,pm10_0_cf_1_b,pm1_0_atm_b,pm2_5_atm_b,pm10_0_atm_b,pm2.5_aqi_cf_1_b,pm2.5_aqi_atm_b,p_0_3_um_b,p_0_5_um_b,p_1_0_um_b,p_2_5_um_b,p_5_0_um_b,p_10_0_um_b,gas
3.
2022/12/30T22:01:01z,xx:xx:xx:xx:xx:xx,7.02,3.0+OPENLOG+NO-DISK+RV3028+BME680+PMSX003-A+PMSX003-B,82,15,30,859.56,nan,36848,-63,105,0.00,0.19,0.33,0.00,0.19,0.33,1,1,128.02,30.47,7.02,3.23,0.56,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0,0,72.33,22.96,3.38,0.22,0.00,0.00,nan
2 and 3 Side-by-Side (from 2-min report)
Below is a table showing Section 2 (headers) next to Section 3 (values).
2. Name | 3. Value |
---|---|
UTCDateTime | 2022/12/30T22:01:01z |
mac_address | xx:xx:xx:xx:xx:xx |
firmware_ver | 7.02 |
hardware | 3.0+OPENLOG+NO-DISK+RV3028+BME680+PMSX003-A+PMSX003-B |
current_temp_f | 82 |
current_humidity | 15 |
current_dewpoint_f | 30 |
pressure | 859.56 |
adc | NaN |
mem | 36848 |
rssi | -63 |
uptime | 105 |
pm1_0_cf_1 | 0.00 |
pm2_5_cf_1 | 0.19 |
pm10_0_cf_1 | 0.33 |
pm1_0_atm | 0.00 |
pm2_5_atm | 0.19 |
pm10_0_atm | 0.33 |
pm2.5_aqi_cf_1 | 1 |
pm2.5_aqi_atm | 1 |
p_0_3_um | 128.02 |
p_0_5_um | 30.47 |
p_1_0_um | 7.02 |
p_2_5_um | 3.23 |
p_5_0_um | 0.56 |
p_10_0_um | 0.00 |
pm1_0_cf_1_b | 0.00 |
pm2_5_cf_1_b | 0.00 |
pm10_0_cf_1_b | 0.00 |
pm1_0_atm_b | 0.00 |
pm2_5_atm_b | 0.00 |
pm10_0_atm_b | 0.00 |
pm2.5_aqi_cf_1_b | 0 |
pm2.5_aqi_atm_b | 0 |
p_0_3_um_b | 72.33 |
p_0_5_um_b | 22.96 |
p_1_0_um_b | 3.38 |
p_2_5_um_b | 0.22 |
p_5_0_um_b | 0.00 |
p_10_0_um_b | 0.00 |
gas | NaN |
Data From the PurpleAir Pixel
Data from the Pixel is also available via USB serial. The following is some example output starting from soon after the Pixel is first plugged in:
~git branch: main
~git commit: 39badc0e5beb434279403e1f0f40d24d1733ca70
~committed at: 2025-04-01T19:03:01-06:00
~generated at: 2025-04-01T19:03:20-06:00
~firmware version: 1.0.1
=====================================================================
= PurpleAir PIXEL =
= Board ID: 29C263A4261B19AE =
= https://www.purpleair.com/pixel =
=====================================================================
BOSCH BMV080 parameters:
Volumetric Mass Density: 3.40 kg/m^3
Integration Time: 2.0 s
Power Mode: 2 (PM in the range of 0.02 - 3.0 m/s)
Obstruction Detection: false
Vibration Filtering: true
Temperature Compensation: true
Sensor ID: BPC90206441C
uptime_millis,us_epa_aqi,pm2.5,pm2.5_raw,illuminance_percentage
3603,0,0.0,nan,86
4784,0,0.0,nan,79
5954,0,0.0,nan,80
7099,0,0.0,nan,79
7721,0,0.0,nan,80
8515,0,0.0,nan,80
9989,22,5.2,26.0,79
10801,59,15.8,53.0,79
11989,72,22.0,31.0,78
13177,72,22.0,nan,79
13821,72,22.0,nan,78
15059,74,22.6,3.0,79
16249,74,22.6,0.0,79
16893,74,22.6,nan,78
18066,74,22.6,nan,79
Meta Information
Information about the Pixel and its firmware is output shortly after booting up. In order to grab this information, you’ll need to connect to USB serial shortly after the device very first plugs in and powers on.
Items beginning with "~', such as “firmware version” and “generated at” pertain to the specific firmware version present on the device.
“BOSCH BMV080 parameters” refer to parameters which affect PM2.5 readings. Presently, these aren’t configurable but may be in a future firmware update.
CSV Data
After meta-information is output and the Pixel finishes booting up, it will output measured data in CSV format. The table below describes what each CSV field means:
CSV Field | Meaning |
---|---|
uptime_millis | How long the sensor has been running since it powered on, presented in milliseconds. |
us_epa_aqi | The US EPA PM2.5 AQI calculated using the pm2.5 field. A change in the us_epa_aqi may not be immediately reflected on the LEDs, as smoothing is applied to prevent abrupt color changes. |
pm2.5 | PM2.5 in µg/m³. This averages over the past few values, omitting data that is reported as being out of range. |
pm2.5_raw | A PM2.5 reading in µg/m³ taken directly from the Bosch BMV080. If this value is reported as being “out of range”, nan is output instead. |
illuminance_percentage | A percentage value between 0 and 100, indicating the illuminance measured by the Pixel’s light sensor. The illuminance percentage affects how bright the LEDs are. |