Last active
November 29, 2020 23:24
-
-
Save hfiennes/8a812b9623ae5d2f32a6fbb7f1eb5153 to your computer and use it in GitHub Desktop.
imp001 air quality monitoring (with AQI index)
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
// Ensure we have a default reading | |
lastreading <- { "pm10":0, "pm25":0, "pm100":0 }; | |
// Code to convert particlate density to AQI index | |
// based on https://gist.github.com/kfury/822bbba2cb0f946abb73baa156722ab1 | |
function Linear(AQIhigh, AQIlow, Conchigh, Conclow, Conc) { | |
local a=((Conc-Conclow)/(Conchigh-Conclow))*(AQIhigh-AQIlow)+AQIlow; | |
return math.floor(a+0.5); | |
} | |
function PM25toAQI(Conc) { | |
local c=(math.floor(10*Conc))/10; | |
local AQI = 9999; | |
if (c>=0 && c<12.1) { | |
AQI=Linear(50,0,12,0,c); | |
} else if (c>=12.1 && c<35.5) { | |
AQI=Linear(100,51,35.4,12.1,c); | |
} else if (c>=35.5 && c<55.5) { | |
AQI=Linear(150,101,55.4,35.5,c); | |
} else if (c>=55.5 && c<150.5) { | |
AQI=Linear(200,151,150.4,55.5,c); | |
} else if (c>=150.5 && c<250.5) { | |
AQI=Linear(300,201,250.4,150.5,c); | |
} else if (c>=250.5 && c<350.5) { | |
AQI=Linear(400,301,350.4,250.5,c); | |
} else if (c>=350.5 && c<500.5) { | |
AQI=Linear(500,401,500.4,350.5,c); | |
} | |
return AQI; | |
} | |
// When we get data from the device, log it and keep a copy | |
device.on("aq", function(v) { | |
lastreading = v; | |
server.log(http.jsonencode(lastreading)); | |
}); | |
// Handle slack calls | |
http.onrequest(function(req, res) { | |
local status = format("Current air quality: PM1.0: %dug/m3, PM2.5: %dug/m3, PM10: %dug/m3, ", | |
lastreading.pm10, lastreading.pm25, lastreading.pm100); | |
local aqi = PM25toAQI(lastreading.pm25); | |
status += format("PM2.5 AQI index %d ", aqi); | |
if (aqi < 51) status += "(good)"; | |
else if (aqi < 101) status += "(moderate)"; | |
else if (aqi < 151) status += "(unhealthy for sensitive groups)"; | |
else if (aqi < 201) status += "(unhealthy)"; | |
else if (aqi < 301) status += "(very unhealthy)"; | |
else if (aqi < 501) status += "(hazardous)"; | |
else status += "(get out of there)"; | |
// Check for slack | |
if (req.path == "/slack") { | |
res.send(200, http.jsonencode({"text": status})); | |
} else { | |
// Otherwise, if someone hits the agent, just send status as plain text | |
res.send(200, status+"\n"); | |
} | |
}); |
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 part runs on the device | |
// Cut and paste this into the "device" side of impcentral | |
// DFrobot PM2.5 laser dust sensor connected to pins 1 & 2 | |
uart <- hardware.uart12; | |
// Current serial state and packet | |
state <- -1; | |
packet <- blob(31); | |
// Deal with receiving a single byte | |
function rx() { | |
local b = uart.read(); | |
// Waiting for start of a packet? | |
if (state == -1) { | |
// Packets always start with 0x42 | |
if (b == 0x42) state++; | |
return; | |
} | |
// Collect the byte | |
packet[state++] = b; | |
// Got the whole packet? | |
if (state == 31) { | |
// Process it | |
rxpacket(); | |
// Reset state for next one | |
state = -1; | |
} | |
} | |
// We've got a whole packet, check that it's valid | |
function rxpacket() { | |
// Calculate checksum | |
local chk = 0x42; | |
for(local a=0; a<29;a++) chk += packet[a]; | |
// Does it match what we were sent? | |
if (packet[29] == (chk >> 8) && packet[30] == (chk & 0xff)) { | |
// Extract reading & send to server | |
local reading = {}; | |
reading.pm10 <- (packet[3]<<8)|packet[4]; | |
reading.pm25 <- (packet[5]<<8)|packet[6]; | |
reading.pm100 <- (packet[7]<<8)|packet[8]; | |
agent.send("aq", reading); | |
} | |
} | |
// Configure UART and attach receive handler | |
uart.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, rx); | |
server.log("AQ sensor online"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment