Skip to content

Commit

Permalink
Merge pull request #150 from kike-canaries/mqtt_anaire_pm25
Browse files Browse the repository at this point in the history
MQTT Anaire cloud integration (CO2, PM2.5)
  • Loading branch information
hpsaturn authored Nov 24, 2021
2 parents 8556dd1 + 5e91de8 commit 12a3d94
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 50 deletions.
3 changes: 3 additions & 0 deletions include/wifi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <OTAHandler.h>
#include <esp_wifi.h>
#include <InfluxDbClient.h>
#include <MQTT.h>
#include <ConfigApp.hpp>
#include <GUILib.hpp>
#include <Watchdog.hpp>
Expand All @@ -10,6 +11,8 @@
#define PUBLISH_INTERVAL 30 // publish to cloud each 30 seconds
#define WIFI_RETRY_CONNECTION 30 // 30 seconds wait for wifi connection
#define IFX_RETRY_CONNECTION 5 // influxdb publish retry
#define MQTT_RETRY_CONNECTION 1 // mqtt publish retry
#define MQTT_DELAYED_TIME 30 // mqtt retry connection delayed time

void otaLoop();
void otaInit();
Expand Down
2 changes: 1 addition & 1 deletion lib/canairioota/src/OTAHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void OTAHandler::setup(const char* ESP_ID, const char* ESP_PASS) {
ota.getInstance()->m_pOTAHandlerCallbacks->onProgress(progress,total);
})
.onError([](ota_error_t error) {
Serial.printf("-->[E][OTA] Error[%u]: ", error);
Serial.printf("[E][OTA] Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
Expand Down
85 changes: 75 additions & 10 deletions lib/configlib/ConfigApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ void ConfigApp::reload() {
devmode = preferences.getBool("debugEnable", false);
pax_enable = preferences.getBool("paxEnable", true);
i2conly = preferences.getBool("i2conly", false);
hassip = preferences.getString("hassip", "");
hasspt = preferences.getUInt("hasspt", 1883);
hassusr = preferences.getString("hassusr", "");
hasspsw = preferences.getString("hasspsw", "");

preferences.end();
}
Expand All @@ -59,8 +63,13 @@ String ConfigApp::getCurrentConfig() {
doc["i2conly"] = preferences.getBool("i2conly", false); // force only i2c sensors
doc["toffset"] = preferences.getFloat("toffset", 0.0); // temperature offset
doc["altoffset"] = preferences.getFloat("altoffset",0.0);// altitude offset
doc["hassip"] = preferences.getString("hassip", ""); // Home Assistant MQTT server ip
doc["hasspt"] = preferences.getUInt("hasspt", 1883); // Home Assistant MQTT server port
doc["hassusr"] = preferences.getString("hassusr", ""); // Home Assistant MQTT user
doc["hasspsw"] = preferences.getString("hasspsw", ""); // Home Assistant MQTT password
doc["lskey"] = lastKeySaved; // last key saved
doc["wmac"] = (uint16_t)(chipid >> 32); // chipid calculated in init
doc["anaireid"] = getStationName(); // deviceId for Anaire cloud
doc["wsta"] = wifi_connected; // current wifi state
doc["vrev"] = REVISION;
doc["vflv"] = FLAVOR;
Expand Down Expand Up @@ -123,7 +132,7 @@ bool ConfigApp::saveDeviceName(String name) {
Serial.println("-->[CONF] set device name to: " + name);
return true;
}
DEBUG("-->[E][CONF] device name is empty!");
DEBUG("[E][CONF] device name is empty!");
return false;
}

Expand All @@ -134,7 +143,7 @@ bool ConfigApp::saveSampleTime(int time) {
Serial.println(time);
return true;
}
DEBUG("-->[W][CONF] warning: sample time is too low!");
DEBUG("[W][CONF] warning: sample time is too low!");
return false;
}

Expand Down Expand Up @@ -173,7 +182,7 @@ bool ConfigApp::saveSSID(String ssid){
Serial.println("-->[CONF] WiFi SSID saved!");
return true;
}
DEBUG("-->[W][CONF] empty Wifi SSID");
DEBUG("[W][CONF] empty Wifi SSID");
return false;
}

Expand All @@ -191,7 +200,7 @@ bool ConfigApp::saveWifi(String ssid, String pass){
log_i("[CONF] ssid:%s pass:%s",ssid,pass);
return true;
}
DEBUG("-->[W][CONF] empty Wifi SSID");
DEBUG("[W][CONF] empty Wifi SSID");
return false;
}

Expand All @@ -209,7 +218,7 @@ bool ConfigApp::saveInfluxDb(String db, String ip, int pt) {
Serial.println("-->[CONF] influxdb config saved.");
return true;
}
DEBUG("-->[W][CONF] wrong InfluxDb params!");
DEBUG("[W][CONF] wrong InfluxDb params!");
return false;
}

Expand All @@ -226,7 +235,7 @@ bool ConfigApp::saveGeo(double lat, double lon, String geo){
Serial.println(geo);
return true;
}
DEBUG("-->[W][CONF] wrong GEO params!");
DEBUG("[W][CONF] wrong GEO params!");
return false;
}

Expand Down Expand Up @@ -265,11 +274,47 @@ bool ConfigApp::saveI2COnly(bool enable) {
return true;
}

bool ConfigApp::saveHassIP(String ip) {
preferences.begin(_app_name, false);
preferences.putString("hassip", ip);
preferences.end();
setLastKeySaved("hassip");
Serial.printf("-->[CONF] Hass IP: %s saved.\n",ip.c_str());
return true;
}

bool ConfigApp::saveHassPort(int port) {
preferences.begin(_app_name, false);
preferences.putInt("hasspt", port);
preferences.end();
setLastKeySaved("hasspt");
Serial.printf("-->[CONF] Hass Port: %i saved.\n", port);
return true;
}

bool ConfigApp::saveHassUser(String user) {
preferences.begin(_app_name, false);
preferences.putString("hassusr", user);
preferences.end();
setLastKeySaved("hassusr");
Serial.printf("-->[CONF] Hass User: %s saved.\n", user.c_str());
return true;
}

bool ConfigApp::saveHassPassword(String passw) {
preferences.begin(_app_name, false);
preferences.putString("hasspsw", passw);
preferences.end();
setLastKeySaved("hasspsw");
Serial.println("-->[CONF] Hass password saved.");
return true;
}

bool ConfigApp::save(const char *json) {
StaticJsonDocument<1000> doc;
auto error = deserializeJson(doc, json);
if (error) {
Serial.print(F("-->[E][CONF] deserialize Json failed with code "));
Serial.print(F("[E][CONF] deserialize Json failed with code "));
Serial.println(error.c_str());
return false;
}
Expand All @@ -293,8 +338,11 @@ bool ConfigApp::save(const char *json) {
if (doc.containsKey("lat")) return saveGeo(doc["lat"].as<double>(), doc["lon"].as<double>(), doc["geo"] | "");
if (doc.containsKey("toffset")) return saveTempOffset(doc["toffset"].as<float>());
if (doc.containsKey("altoffset")) return saveAltitudeOffset(doc["altoffset"].as<float>());
if (doc.containsKey("hassip")) return saveHassIP(doc["hassip"] | "");
if (doc.containsKey("hasspt")) return saveHassPort(doc["hasspt"] | 1883);
if (doc.containsKey("hassusr")) return saveHassUser(doc["hassusr"] | "");
if (doc.containsKey("hasspsw")) return saveHassPassword(doc["hasspsw"] | "");


// some actions with chopid validation (for security reasons)
if (cmd == ((uint16_t)(chipid >> 32)) && act.length() > 0) {
if (act.equals("wst")) return wifiEnable(doc["wenb"].as<bool>());
Expand All @@ -307,7 +355,7 @@ bool ConfigApp::save(const char *json) {
if (act.equals("clb")) performCO2Calibration();
return true;
} else {
Serial.println("-->[E][CONF] invalid config file!");
Serial.println("[E][CONF] invalid config file!");
return false;
}
}
Expand All @@ -316,7 +364,7 @@ bool ConfigApp::getTrackStatusValues(const char *json) {
StaticJsonDocument<200> doc;
auto error = deserializeJson(doc, json);
if (error) {
Serial.print(F("-->[E][CONF] deserialize Json failed with code "));
Serial.print(F("[E][CONF] deserialize Json failed with code "));
Serial.println(error.c_str());
return false;
}
Expand All @@ -339,13 +387,30 @@ String ConfigApp::getDeviceId() {
return String(baseMacChr);
}

String ConfigApp::getAnaireDeviceId() {
uint32_t chipId = 0;
for (int i = 0; i < 17; i = i + 8) chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
return String(chipId, HEX);
}

String ConfigApp::getDeviceIdShort() {
String devId = getDeviceId();
devId = devId.substring(13);
devId.replace(":","");
return devId;
}

String ConfigApp::getStationName() {
if (geo.isEmpty()) return getAnaireDeviceId();
String name = ""+geo.substring(0,3); // GeoHash ~70km https://en.wikipedia.org/wiki/Geohash
name = name + String(FLAVOR).substring(0,7); // Flavor short, firmware name (board)
name = name + getDeviceId().substring(10); // MAC address 4 digts
name.replace("_","");
name.replace(":","");
name.toUpperCase();
return name;
}

bool ConfigApp::isWifiEnable() {
return wifi_enable;
}
Expand Down
18 changes: 18 additions & 0 deletions lib/configlib/ConfigApp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ConfigApp {
uint64_t chipid;
String deviceId;
String dname;

int stime;
int stype;
double lat;
Expand All @@ -19,6 +20,11 @@ class ConfigApp {
String ssid;
String pass;

String hassip;
String hassusr;
String hasspsw;
int16_t hasspt;

struct ifxdbValues {
String db = "canairio";
String ip = "influxdb.canair.io";
Expand Down Expand Up @@ -71,6 +77,14 @@ class ConfigApp {

bool paxEnable(bool enable);

bool saveHassIP(String ip);

bool saveHassPort(int port);

bool saveHassPassword(String pass);

bool saveHassUser(String user);

String getCurrentConfig();

bool isWifiEnable();
Expand All @@ -87,6 +101,8 @@ class ConfigApp {

String getDeviceIdShort();

String getStationName();

int getSensorType();

void clear();
Expand Down Expand Up @@ -141,6 +157,8 @@ class ConfigApp {

void performCO2Calibration();

String getAnaireDeviceId();

void DEBUG(const char* text, const char* textb = "");

// @todo use DEBUG_ESP_PORT ?
Expand Down
10 changes: 6 additions & 4 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ platform = espressif32
framework = arduino
upload_speed = 1500000
monitor_speed = 115200
version = 0.4.6
revision = 841
version = 0.4.7
revision = 851
target = prod
monitor_filters = time
extra_scripts = pre:prebuild.py
Expand All @@ -27,8 +27,10 @@ build_flags =
lib_deps =
bblanchon/ArduinoJson @ ^6
tobiasschuerg/ESP8266 Influxdb @ ^3.8.0
https://github.com/hpsaturn/esp32FOTA.git
hpsaturn/CanAirIO Air Quality Sensors Library@^0.3.7
https://github.com/256dpi/arduino-mqtt.git
; chrisjoyce911/esp32FOTA @ ^0.1.4
https://github.com/chrisjoyce911/esp32FOTA.git
hpsaturn/CanAirIO Air Quality Sensors Library@^0.3.8

[esp32_common]
platform = espressif32
Expand Down
6 changes: 3 additions & 3 deletions src/bluetooth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class MyConfigCallbacks : public BLECharacteristicCallbacks {
if(sensors.devmode != cfg.devmode) sensors.setDebugMode(cfg.devmode);
}
else{
Serial.println("-->[E][BTLE][CONFIG] saving error!");
Serial.println("[E][BTLE][CONFIG] saving error!");
}
}
};
Expand All @@ -106,12 +106,12 @@ class MyStatusCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0 && cfg.getTrackStatusValues(value.c_str())) {
log_v("-->[E][BTLE][STATUS] "+String(value.c_str()));
log_v("[E][BTLE][STATUS] "+String(value.c_str()));
gui.setTrackValues(cfg.track.spd,cfg.track.kms);
gui.setTrackTime(cfg.track.hrs,cfg.track.min,cfg.track.seg);
}
else {
Serial.println("-->[E][BTLE][STATUS] write error!");
Serial.println("[E][BTLE][STATUS] write error!");
}
}
};
Expand Down
1 change: 0 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ void setup() {
gui.setCallbacks(new MyGUIUserPreferencesCallbacks());
gui.showWelcome();


// device wifi mac addres and firmware version
Serial.println("-->[INFO] ESP32MAC: " + cfg.deviceId);
Serial.println("-->[INFO] Revision: " + gui.getFirmwareVersionCode());
Expand Down
Empty file added src/mqtt_hass.cpp
Empty file.
Loading

0 comments on commit 12a3d94

Please sign in to comment.