Skip to content

Instantly share code, notes, and snippets.

@erijpkema
Created March 3, 2022 15:32
Show Gist options
  • Save erijpkema/e2b896155990768f4d53f4734e8d41dd to your computer and use it in GitHub Desktop.
Save erijpkema/e2b896155990768f4d53f4734e8d41dd to your computer and use it in GitHub Desktop.
airgradient_mqtt.ino
/**
* 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();
}
}
}
@ksmart07
Copy link

ksmart07 commented Sep 10, 2024

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

@ksmart07
Copy link

complete log attached..................

/Arduino/mqtt-air-grad/mqtt-air-grad.ino:250:22: warning: character constant too long for its type
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/mqtt-air-grad/mqtt-air-grad.ino:7:
//Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:27:3: note: candidate: 'AirGradient::AirGradient(BoardType)'
27 | AirGradient(BoardType type);
| ^~~~~~~~~~~
/
/Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:27:3: note: candidate expects 1 argument, 0 provided
//Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:25:7: note: candidate: 'constexpr AirGradient::AirGradient(const AirGradient&)'
25 | class AirGradient {
| ^~~~~~~~~~~
/
/Arduino/libraries/AirGradient_Air_Quality_Sensor/src/AirGradient.h:25:7: note: candidate expects 1 argument, 0 provided
//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()':
mqtt-air-grad:69:11: error: 'client' was not declared in this scope; did you mean 'Client'?
69 | while (!client.connected()) {
| ^~~~~~
| Client
/
/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void setup()':
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()':
mqtt-air-grad:153:8: error: 'client' was not declared in this scope; did you mean 'Client'?
153 | if (!client.connected()) {
| ^~~~~~
| Client
/
/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'String GenerateMetrics()':
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: '}'
187 | message += "}";
| ^~~~
/
/Arduino/mqtt-air-grad/mqtt-air-grad.ino: In function 'void updateScreen(long int)':
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()'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment