Skip to content

Instantly share code, notes, and snippets.

@luke-au
Forked from jasonsnell/epaaq.5m.php
Created October 11, 2020 06:29
Show Gist options
  • Save luke-au/8e5daf43b64969788b44a3d57fccb3e6 to your computer and use it in GitHub Desktop.
Save luke-au/8e5daf43b64969788b44a3d57fccb3e6 to your computer and use it in GitHub Desktop.
Air quality from PurpleAir sensor but with EPA adjustments
#!/usr/bin/env php
<?php
error_reporting( 0 );
// This version uses the "EPA adjustment" for wood smoke
// since my version is really meant to be when there are fires.
// Info here: <https://cfpub.epa.gov/si/si_public_file_download.cfm?p_download_id=540979&Lab=CEMM>
// jsnell@intertext.com
// Put your nearest PurpleAir sensor ID here
$show = '4896';
$url = ( 'https://www.purpleair.com/json?show=' . $show );
// Get the sensor data via JSON
$json = @file_get_contents( $url );
$array = json_decode( $json, true );
for ( $i = 0; $i < sizeof( $array['results'] ); $i++ ) {
$array['results'][ $i ]['Stats'] = json_decode( $array['results'][ $i ]['Stats'], true );
}
$pm25a = $array['results'][0]['pm2_5_cf_1'];
$pm25b = $array['results'][1]['pm2_5_cf_1'];
$humidity = $array['results'][0]['humidity'];
$location = $array['results'][0]['Label'];
$lat = $array['results'][1]['Lat'];
$lon = $array['results'][1]['Lon'];
$sensor1 = $array['results'][0]['Stats']['v2'];
$sensor1l = $array['results'][0]['Stats']['v'];
$asensor = $array['results'][0]['Stats']['v1'];
$bsensor = $array['results'][1]['Stats']['v1'];
$epaPM = ( (0.52 * ( ($pm25a + $pm25b) / 2) - (.085 * $humidity) + 5.71) );
$AQI = aqiFromPM( $epaPM );
$aAQI = aqiFromPM( $asensor );
$bAQI = aqiFromPM( $bsensor );
settype( $AQI, 'integer' );
settype( $aAQI, 'integer' );
settype( $bAQI, 'integer' );
if ($AQI <= 50) {
echo '🟢' . '
---
' . getAQIDescription( $AQI ) . ' (' . $AQI . getAQItrend( $sensor1, $sensor1l ) . ')|color=' . getAQIcolor( $AQI ) . '
' . $location . '|href=https://www.purpleair.com/map?opt=1/i/mAQI/a10/cC0&select=' . $show . '#11/' . $lat . '/' . $lon ;
} else {
echo ( getAQIDescription( $AQI ) . ' (' . $AQI . getAQItrend( $sensor1, $sensor1l ) . ')|color=' . getAQIcolor( $AQI ) . '
---
' . $location . '|href=https://www.purpleair.com/map?opt=1/i/mAQI/a10/cC0&select=' . $show . '#11/' . $lat . '/' . $lon );
}
// Function to get AQI number from PPM reading
function aqiFromPM( $pm ) {
if ( is_nan( $pm ) ) {
return '-';
}
if ( isset( $pm ) == false ) {
return 'Error: No value';
}
if ( $pm < 0.0 ) {
return $pm;
}
if ( $pm > 1000.0 ) {
return '-';
}
if ( $pm > 350.5 ) {
return calcAQI( $pm, 500.0, 401.0, 500.0, 350.5 );
} elseif ( $pm > 250.5 ) {
return calcAQI( $pm, 400.0, 301.0, 350.4, 250.5 );
} elseif ( $pm > 150.5 ) {
return calcAQI( $pm, 300.0, 201.0, 250.4, 150.5 );
} elseif ( $pm > 55.5 ) {
return calcAQI( $pm, 200.0, 151.0, 150.4, 55.5 );
} elseif ( $pm > 35.5 ) {
return calcAQI( $pm, 150.0, 101.0, 55.4, 35.5 );
} elseif ( $pm > 12.1 ) {
return calcAQI( $pm, 100.0, 51.0, 35.4, 12.1 );
} elseif ( $pm >= 0.0 ) {
return calcAQI( $pm, 50.0, 0.0, 12.0, 0.0 );
} else {
return '-';
}
}
// Function that actually calculates the AQI number
function calcAQI( $Cp, $Ih, $Il, $BPh, $BPl ) {
$a = ( $Ih - $Il );
$b = ( $BPh - $BPl );
$c = ( $Cp - $BPl );
return round( ( $a / $b ) * $c + $Il );
}
// Function that gets the AQI's description
function getAQIDescription( $aqinum ) {
if ( $aqinum >= 401 ) {
return 'Hazardous';
} elseif ( $aqinum >= 301 ) {
return 'Hazardous';
} elseif ( $aqinum >= 201 ) {
return 'Very Unhealthy';
} elseif ( $aqinum >= 151 ) {
return 'Unhealthy';
} elseif ( $aqinum >= 101 ) {
return 'Unhealthy SG';
} elseif ( $aqinum >= 51 ) {
return 'Moderate';
} elseif ( $aqinum >= 0 ) {
return 'Good';
} else {
return 'Unknown';
}
}
// Function that gets the AQI's color code
function getAQIColor( $aqinum ) {
$darkmode = shell_exec('osascript <<EOF
tell application "System Events"
tell appearance preferences
set theMode to dark mode
end tell
end tell
return theMode
EOF
');
$darkmodestate = filter_var($darkmode, FILTER_VALIDATE_BOOLEAN);
if ( $darkmodestate ) {
// we are in dark mode
if ( $aqinum >= 301 ) {
return '#7e0023';
} elseif ( $aqinum >= 201 ) {
return '#8f3f97';
} elseif ( $aqinum >= 151 ) {
return '#ff0000';
} elseif ( $aqinum >= 101 ) {
return 'Orange';
} elseif ( $aqinum >= 51 ) {
return '#ffff00';
} elseif ( $aqinum >= 0 ) {
return '#00e400';
} else {
return '#ffffff';
}
} else {
// we are in light mode
if ( $aqinum >= 301 ) {
return '#7e0023';
} elseif ( $aqinum >= 201 ) {
return '#8f3f97';
} elseif ( $aqinum >= 151 ) {
return '#ff0000';
} elseif ( $aqinum >= 101 ) {
return '#cf7332';
} elseif ( $aqinum >= 51 ) {
return '#333333';
} elseif ( $aqinum >= 0 ) {
return '#0c990c';
} else {
return '#000000';
}
}
}
// Function that checks for the AQI trend
function getAQItrend( $average, $live ) {
if ( ( $average - $live ) > 6 ) {
return '↓';
} elseif ( ( $average - $live ) < -6 ) {
return '↑';
} else {
return '';
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment