-
-
Save erijpkema/e2b896155990768f4d53f4734e8d41dd to your computer and use it in GitHub Desktop.
/** | |
* This sketch connects an AirGradient DIY sensor to a WiFi network, and sends | |
* these metrics via MQTT. Adapted from original by Jeff Geerling. | |
*/ | |
#include <AirGradient.h> | |
#include <ESP8266WiFi.h> | |
#include <WiFiClient.h> | |
#include <PubSubClient.h> | |
#include <Wire.h> | |
#include "SSD1306Wire.h" | |
AirGradient ag = AirGradient(); | |
// Config ---------------------------------------------------------------------- | |
// Optional. | |
const char* deviceId = "airgradient"; | |
// Hardware options for AirGradient DIY sensor. | |
const bool hasPM = true; | |
const bool hasCO2 = true; | |
const bool hasSHT = true; | |
// WiFi and IP connection info. | |
const char* ssid = ""; | |
const char* password = ""; | |
const int port = 9926; | |
// MQTT connection info. | |
const char* mqtt_user = "airgradient"; | |
const char* mqtt_pass = ""; | |
const char* clientId = "airgradient"; | |
const char* MQTTtopic = "airgradient"; | |
// Uncomment the line below to configure a static IP address. | |
// #define staticip | |
#ifdef staticip | |
IPAddress static_ip(192, 168, 2, 15); | |
IPAddress gateway(192, 168, 2, 1); | |
IPAddress subnet(255, 255, 255, 0); | |
#endif | |
//The mqtt server | |
IPAddress server(192, 168, 2 ,13); | |
// The frequency of measurement updates. | |
const int updateFrequency = 5000; | |
// The frequency of mqtt messages; | |
const int MQTTFrequency = 60000; | |
// For housekeeping. | |
long lastUpdate = millis(); | |
long lastMQTT = millis(); | |
int counter = 0; | |
String payload = ""; | |
// Config End ------------------------------------------------------------------ | |
SSD1306Wire display(0x3c, SDA, SCL); | |
WiFiClient espClient; | |
PubSubClient client(server, 1883, espClient); | |
void reconnect() { | |
// Loop until we're reconnected | |
while (!client.connected()) { | |
Serial.print("Attempting MQTT connection..."); | |
// Create a random client ID | |
// Attempt to connect | |
if (client.connect(clientId, mqtt_user, mqtt_pass)) { | |
Serial.println("connected"); | |
// Once connected, publish an announcement... | |
// client.publish(MQTTTopic, "Starting..."); | |
} else { | |
Serial.print("failed, rc="); | |
Serial.print(client.state()); | |
Serial.println(" try again in 5 seconds"); | |
// Wait 5 seconds before retrying | |
yield(); | |
delay(5000); | |
} | |
} | |
} | |
void setup() { | |
Serial.begin(57600); | |
// Init Display. | |
display.init(); | |
display.flipScreenVertically(); | |
showTextRectangle("Init", String(ESP.getChipId(),HEX),true); | |
// Set static IP address if configured. | |
#ifdef staticip | |
WiFi.config(static_ip,gateway,subnet); | |
#endif | |
// Set WiFi mode to client (without this it may try to act as an AP). | |
WiFi.mode(WIFI_STA); | |
// Configure Hostname | |
if ((deviceId != NULL) && (deviceId[0] == '\0')) { | |
Serial.printf("No Device ID is Defined, Defaulting to board defaults"); | |
} | |
else { | |
// wifi_station_set_hostname(deviceId); # 'wifi_station_set_hostname' was not declared in this scope | |
WiFi.hostname(deviceId); | |
} | |
// Setup and wait for WiFi. | |
WiFi.begin(ssid, password); | |
Serial.println(""); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
showTextRectangle("Trying to", "connect...", true); | |
Serial.print("."); | |
} | |
// Enable enabled sensors. | |
if (hasPM) ag.PMS_Init(); | |
if (hasCO2) ag.CO2_Init(); | |
if (hasSHT) ag.TMP_RH_Init(0x44); | |
Serial.println(""); | |
Serial.print("Connected to "); | |
Serial.println(ssid); | |
Serial.print("IP address: "); | |
Serial.println(WiFi.localIP()); | |
Serial.print("MAC address: "); | |
Serial.println(WiFi.macAddress()); | |
Serial.print("Hostname: "); | |
Serial.println(WiFi.hostname()); | |
client.setServer(server, 1883); | |
} | |
void loop() { | |
long t = millis(); | |
updateScreen(t); | |
payload = GenerateMetrics(); | |
Serial.println(""); | |
Serial.println("payload: "); | |
Serial.print(payload); | |
if (!client.connected()) { | |
reconnect(); | |
} | |
sendMQTT(t, payload); | |
} | |
String GenerateMetrics() { | |
String message = "{\"id\":\"" + String(deviceId) + "\",\"mac\":\"" + WiFi.macAddress().c_str() + "\""; | |
if (hasPM) { | |
int stat = ag.getPM2_Raw(); | |
// pm02 Particulate Matter PM2.5 value | |
message += ",\"pm02\":" + String(stat); | |
} | |
if (hasCO2) { | |
int stat = ag.getCO2_Raw(); | |
//rco2 CO2 value, in ppm | |
message += ",\"rco2\":" + String(stat); | |
} | |
if (hasSHT) { | |
TMP_RH stat = ag.periodicFetchData(); | |
//atmp Temperature, in degrees Celsius"; | |
message += ",\"atmp\":" + String(stat.t); | |
//Relative humidity, in percent"; | |
message += ",\"rhum\":" + String(stat.rh); | |
} | |
message += "\}"; | |
return message; | |
} | |
// DISPLAY | |
void showTextRectangle(String ln1, String ln2, boolean small) { | |
display.clear(); | |
display.setTextAlignment(TEXT_ALIGN_LEFT); | |
if (small) { | |
display.setFont(ArialMT_Plain_16); | |
} else { | |
display.setFont(ArialMT_Plain_24); | |
} | |
display.drawString(32, 16, ln1); | |
display.drawString(32, 36, ln2); | |
display.display(); | |
} | |
void updateScreen(long now) { | |
if ((now - lastUpdate) > updateFrequency) { | |
// Take a measurement at a fixed interval. | |
switch (counter) { | |
case 0: | |
if (hasPM) { | |
int stat = ag.getPM2_Raw(); | |
showTextRectangle("PM2",String(stat),false); | |
} | |
break; | |
case 1: | |
if (hasCO2) { | |
int stat = ag.getCO2_Raw(); | |
showTextRectangle("CO2", String(stat), false); | |
} | |
break; | |
case 2: | |
if (hasSHT) { | |
TMP_RH stat = ag.periodicFetchData(); | |
showTextRectangle("TMP", String(stat.t, 1) + "C", false); | |
} | |
break; | |
case 3: | |
if (hasSHT) { | |
TMP_RH stat = ag.periodicFetchData(); | |
showTextRectangle("HUM", String(stat.rh) + "%", false); | |
} | |
break; | |
} | |
counter++; | |
if (counter > 3) counter = 0; | |
lastUpdate = millis(); | |
} | |
} | |
void sendMQTT(long now, String payload) { | |
// send out the MQTT message. | |
if ((now - lastMQTT) > MQTTFrequency) { | |
int succ = false; | |
int attempts = 10; | |
while (succ == false && attempts-- > 0) { | |
succ = client.publish(MQTTtopic, payload.c_str()); | |
Serial.print('Sending: '); | |
Serial.println(succ); | |
yield(); | |
delay(500); | |
lastMQTT = millis(); | |
} | |
} | |
} |
complete log attached..................
/Arduino/mqtt-air-grad/mqtt-air-grad.ino:250:22: warning: character constant too long for its type/Arduino/mqtt-air-grad/mqtt-air-grad.ino:7:
250 | Serial.print('Sending: ');
| ^~~~~~~~~~~
mqtt-air-grad:14:30: error: no matching function for call to 'AirGradient::AirGradient()'
14 | AirGradient ag = AirGradient();
| ^
In file included from /
//Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:27:3: note: candidate: 'AirGradient::AirGradient(BoardType)'/Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:27:3: note: candidate expects 1 argument, 0 provided
27 | AirGradient(BoardType type);
| ^~~~~~~~~~~
/
//Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:25:7: note: candidate: 'constexpr AirGradient::AirGradient(const AirGradient&)'/Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:25:7: note: candidate expects 1 argument, 0 provided
25 | class AirGradient {
| ^~~~~~~~~~~
/
//Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:25:7: note: candidate: 'constexpr AirGradient::AirGradient(AirGradient&&)'/Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:25:7: note: candidate expects 1 argument, 0 provided
/
mqtt-air-grad:63:1: error: 'PubSubClient' does not name a type
63 | PubSubClient client(server, 1883, espClient);
| ^~~~~~~~~~~~
//Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void reconnect()':/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void setup()':
mqtt-air-grad:69:11: error: 'client' was not declared in this scope; did you mean 'Client'?
69 | while (!client.connected()) {
| ^~~~~~
| Client
/
mqtt-air-grad:127:17: error: 'class AirGradient' has no member named 'PMS_Init'
127 | if (hasPM) ag.PMS_Init();
| ^~~~~~~~
mqtt-air-grad:128:18: error: 'class AirGradient' has no member named 'CO2_Init'
128 | if (hasCO2) ag.CO2_Init();
| ^~~~~~~~
mqtt-air-grad:129:18: error: 'class AirGradient' has no member named 'TMP_RH_Init'
129 | if (hasSHT) ag.TMP_RH_Init(0x44);
| ^~~~~~~~~~~
mqtt-air-grad:141:3: error: 'client' was not declared in this scope; did you mean 'Client'?
141 | client.setServer(server, 1883);
| ^~~~~~
| Client
//Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void loop()':/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'String GenerateMetrics()':
mqtt-air-grad:153:8: error: 'client' was not declared in this scope; did you mean 'Client'?
153 | if (!client.connected()) {
| ^~~~~~
| Client
/
mqtt-air-grad:166:19: error: 'class AirGradient' has no member named 'getPM2_Raw'
166 | int stat = ag.getPM2_Raw();
| ^~~~~~~~~~
mqtt-air-grad:173:19: error: 'class AirGradient' has no member named 'getCO2_Raw'
173 | int stat = ag.getCO2_Raw();
| ^~~~~~~~~~
mqtt-air-grad:179:5: error: 'TMP_RH' was not declared in this scope
179 | TMP_RH stat = ag.periodicFetchData();
| ^~~~~~
mqtt-air-grad:182:38: error: 'stat' was not declared in this scope
182 | message += ","atmp":" + String(stat.t);
| ^~~~
//Arduino/mqtt-air-grad/mqtt-air-grad.ino:187:14: warning: unknown escape sequence: '}'/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void updateScreen(long int)':
187 | message += "}";
| ^~~~
/
mqtt-air-grad:213:25: error: 'class AirGradient' has no member named 'getPM2_Raw'
213 | int stat = ag.getPM2_Raw();
| ^~~~~~~~~~
mqtt-air-grad:219:25: error: 'class AirGradient' has no member named 'getCO2_Raw'
219 | int stat = ag.getCO2_Raw();
| ^~~~~~~~~~
mqtt-air-grad:225:11: error: 'TMP_RH' was not declared in this scope
225 | TMP_RH stat = ag.periodicFetchData();
| ^~~~~~
mqtt-air-grad:226:43: error: 'stat' was not declared in this scope
226 | showTextRectangle("TMP", String(stat.t, 1) + "C", false);
| ^~~~
mqtt-air-grad:231:11: error: 'TMP_RH' was not declared in this scope
231 | TMP_RH stat = ag.periodicFetchData();
| ^~~~~~
mqtt-air-grad:232:43: error: 'stat' was not declared in this scope
232 | showTextRectangle("HUM", String(stat.rh) + "%", false);
| ^~~~
/~/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void sendMQTT(long int, String)':
mqtt-air-grad:249:16: error: 'client' was not declared in this scope; did you mean 'Client'?
249 | succ = client.publish(MQTTtopic, payload.c_str());
| ^~~~~~
| Client
exit status 1
no matching function for call to 'AirGradient::AirGradient()'
as a newbie I copied the sktech and tried compiling
got these errors
no file or directory for PubSubClient.h so I excluded it
then got this in the end
no matching function call for AirGradient::AirGradient()
Also how do I configure MQTT for this? Just registered an account
any hints appreciated
lastly, very neat coding formatting