Created
March 3, 2022 15:32
-
-
Save erijpkema/e2b896155990768f4d53f4734e8d41dd to your computer and use it in GitHub Desktop.
airgradient_mqtt.ino
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 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(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 provided27 | 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 provided25 | 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()'