Skip to content

Instantly share code, notes, and snippets.

@kakopappa
Last active November 3, 2023 02:17
Show Gist options
  • Save kakopappa/462f5f2504edf04134265ce7999028c0 to your computer and use it in GitHub Desktop.
Save kakopappa/462f5f2504edf04134265ce7999028c0 to your computer and use it in GitHub Desktop.
#ifndef _AIRQUALITYSENSOR_H_
#define _AIRQUALITYSENSOR_H_
#include <SinricProDevice.h>
#include <Capabilities/ModeController.h>
#include <Capabilities/RangeController.h>
#include <Capabilities/PushNotification.h>
class AirQualitySensor
: public SinricProDevice
, public ModeController<AirQualitySensor>
, public RangeController<AirQualitySensor>
, public PushNotification<AirQualitySensor> {
friend class ModeController<AirQualitySensor>;
friend class RangeController<AirQualitySensor>;
friend class PushNotification<AirQualitySensor>;
public:
AirQualitySensor(const String &deviceId) : SinricProDevice(deviceId, "AirQualitySensor") {};
};
#endif
// Uncomment the following line to enable serial debug output
//#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG_ESP_PORT Serial
#define NODEBUG_WEBSOCKETS
#define NDEBUG
#endif
#include <Arduino.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef ESP32
#include <WiFi.h>
#endif
#include <TroykaMQ.h> // https://github.com/amperka/TroykaMQ
#include <SinricPro.h>
#include "AirQualitySensor.h"
#define WIFI_SSID "" // Your WiFI SSID name
#define WIFI_PASS "" // Your WiFi Password.
#define APP_KEY "" // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx" (Get it from Portal -> Secrets)
#define APP_SECRET "" // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx" (Get it from Portal -> Secrets)
#define DEVICE_ID "" // Should look like "5dc1564130xxxxxxxxxxxxxx" (Get it from Portal -> Devices)
#define BAUD_RATE 115200 // Change baudrate to your need (used for serial monitor)
#define EVENT_WAIT_TIME 60000 // send event every 60 seconds
#define BAUD_RATE 115200
#define EVENT_WAIT_TIME 60000 // send event every 60 seconds
#if defined(ESP8266)
#define SENSOR_PIN A0
#elif defined(ESP32)
#define SENSOR_PIN 34
#endif
MQ135 mq135(SENSOR_PIN);
const int AQI_THRESHOLD_SEVERE = 700;
const int AQI_THRESHOLD_VERY_POOR = 600;
const int AQI_THRESHOLD_POOR = 500;
const int AQI_THRESHOLD_MODERATE = 400;
int ppm = 0;
int lastPPM = 0;
String lastAirQualityLevelStr = "";
AirQualitySensor &airQualitySensor = SinricPro[DEVICE_ID];
// ModeController
void updateMode(String mode) {
airQualitySensor.sendModeEvent("modeInstance1", mode, "PHYSICAL_INTERACTION");
}
// RangeController
void updateRangeValue(int value) {
airQualitySensor.sendRangeValueEvent("rangeInstance1", value);
}
// PushNotificationController
void sendPushNotification(String notification) {
airQualitySensor.sendPushNotification(notification);
}
/*********
* Setup *
*********/
void setupAirQualitySensor() {
// before calibrating the sensor, warm it up for 60 seconds calibrate the sensor in clean air
mq135.calibrate();
// if you know the resistance of the sensor in clean air
// you can specify it manually, eg: 160 mq135.calibrate(160);
Serial.print("Ro = ");
Serial.println(mq135.getRo());
}
void setupSinricPro() {
SinricPro.onConnected([]{ Serial.printf("[SinricPro]: Connected\r\n"); });
SinricPro.onDisconnected([]{ Serial.printf("[SinricPro]: Disconnected\r\n"); });
SinricPro.begin(APP_KEY, APP_SECRET);
};
void setupWiFi() {
#if defined(ESP8266)
WiFi.setSleepMode(WIFI_NONE_SLEEP);
WiFi.setAutoReconnect(true);
#elif defined(ESP32)
WiFi.setSleep(false);
WiFi.setAutoReconnect(true);
#endif
WiFi.begin(SSID, PASS);
Serial.printf("[WiFi]: Connecting to %s", SSID);
while (WiFi.status() != WL_CONNECTED) {
Serial.printf(".");
delay(250);
}
Serial.printf("connected\r\n");
}
void setup() {
Serial.begin(BAUD_RATE);
setupAirQualitySensor();
setupWiFi();
setupSinricPro();
}
/********
* Loop *
********/
void handleAirQualitySensor() {
if (SinricPro.isConnected() == false) {
return;
}
static unsigned long last_millis;
unsigned long current_millis = millis();
if (last_millis && current_millis - last_millis < EVENT_WAIT_TIME) return;
last_millis = current_millis;
ppm = mq135.readCO2();
Serial.printf("Present ppm: %d\r\n", ppm);
if (ppm == lastPPM) {
Serial.printf("PPM did not changed. do nothing...!\r\n");
return;
}
/* determine air quality level */
String airQualityLevelStr = "";
if (ppm > AQI_THRESHOLD_SEVERE) {
airQualityLevelStr = "SEVERE";
} else if (ppm > AQI_THRESHOLD_VERY_POOR) {
airQualityLevelStr = "VERY POOR";
} else if (ppm > AQI_THRESHOLD_POOR) {
airQualityLevelStr = "POOR";
} else if (ppm > AQI_THRESHOLD_MODERATE) {
airQualityLevelStr = "MODERATE";
} else {
airQualityLevelStr = "GOOD";
}
/* Update air quality level label if changed */
if(lastAirQualityLevelStr != airQualityLevelStr) {
lastAirQualityLevelStr = airQualityLevelStr;
updateMode(lastAirQualityLevelStr);
}
delay(500);
/* update PPM label */
updateRangeValue(ppm);
/* send a push notification when air quality level is bad! */
if (ppm > AQI_THRESHOLD_SEVERE) {
sendPushNotification("Air quality is SEVERE!");
} else if (ppm > AQI_THRESHOLD_VERY_POOR) {
sendPushNotification("Air quality is VERY POOR!");
} else if (ppm > AQI_THRESHOLD_POOR) {
sendPushNotification("Air quality is VERY POOR!");
}
lastPPM = ppm; // save to compare next time.
}
void loop() {
handleAirQualitySensor();
SinricPro.handle();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment