From f4fe6e3a1e26dd0a8810bccba3440a246f2b4a17 Mon Sep 17 00:00:00 2001 From: Juerd Waalboer Date: Sun, 27 Dec 2020 20:57:53 +0100 Subject: [PATCH] Code cleanup - Removed unused #define and 'using namespace' - Moved magic literals to global const - Reordered functions - Changed timers in main loop to simple macro instead of Timer class - Changed several identifiers - Reformatted global variable assignments --- operame.ino | 438 +++++++++++++++++++++++++--------------------------- 1 file changed, 208 insertions(+), 230 deletions(-) diff --git a/operame.ino b/operame.ino index d0a2095..6c9a2b1 100644 --- a/operame.ino +++ b/operame.ino @@ -1,4 +1,3 @@ -#define Sprintf(f, ...) ({ char* s; asprintf(&s, f, __VA_ARGS__); String r = s; free(s); r; }) #include #include #include @@ -10,48 +9,36 @@ #include #include -using namespace std; - -unsigned long mqtt_interval; -const int portalbutton = 35; -const int demobutton = 0; -bool ota_enabled; -int co2_warning; -int co2_critical; -int co2_blink; - enum Driver { AQC, MHZ }; -Driver driver; +Driver driver; +MQTTClient mqtt; +HardwareSerial hwserial1(1); +TFT_eSPI display; +TFT_eSprite sprite(&display); +MHZ19 mhz; -int mhz_co2_init = 410; // magic value reported while initializing +const int pin_portalbutton = 35; +const int pin_demobutton = 0; +const int pin_backlight = 4; +const int pin_sensor_rx = 27; +const int pin_sensor_tx = 26; +const int pin_pcb_ok = 12; // pulled to GND by PCB trace +int mhz_co2_init = 410; // magic value reported during init -MQTTClient mqtt; -HardwareSerial hwserial1(1); -TFT_eSPI display; -TFT_eSprite sprite(&display); -MHZ19 mhz; -String mqtt_topic; -String mqtt_template; -bool add_units; -bool wifi_enabled; -bool mqtt_enabled; -int max_failures; +// Configuration via WiFiSettings +unsigned long mqtt_interval; +bool ota_enabled; +int co2_warning; +int co2_critical; +int co2_blink; +String mqtt_topic; +String mqtt_template; +bool add_units; +bool wifi_enabled; +bool mqtt_enabled; +int max_failures; -struct Timer { - unsigned long previous; - unsigned long interval; - std::function function; - void operator()() { - if (millis() - previous >= interval) { - function(); - previous = millis(); - } - } - Timer(unsigned long ms, std::function f) - : interval(ms), function(f) {} -}; - -void retain(String topic, String message) { +void retain(const String& topic, const String& message) { Serial.printf("%s %s\n", topic.c_str(), message.c_str()); mqtt.publish(topic, message, true, 0); } @@ -103,47 +90,6 @@ void display_logo() { sprite.pushSprite(0, 0); } -void panic(const String& message) { - display_big(message, TFT_RED); - delay(5000); - ESP.restart(); -} - -void setup_ota() { - ArduinoOTA.setHostname(WiFiSettings.hostname.c_str()); - ArduinoOTA.setPassword(WiFiSettings.password.c_str()); - ArduinoOTA.onStart( []() { display_big("OTA", TFT_BLUE); }); - ArduinoOTA.onEnd( []() { display_big("OTA done", TFT_GREEN); }); - ArduinoOTA.onError( [](ota_error_t e) { display_big("OTA failed", TFT_RED); }); - ArduinoOTA.onProgress([](unsigned int p, unsigned int t) { - String pct { (int) ((float) p / t * 100) }; - display_big(pct + "%"); - }); - ArduinoOTA.begin(); -} - -bool button(int pin) { - if (digitalRead(pin)) return false; - unsigned long start = millis(); - while (!digitalRead(pin)) { - if (millis() - start >= 50) display_big(""); - } - return millis() - start >= 50; -} - -void check_portalbutton() { - if (button(portalbutton)) WiFiSettings.portal(); -} - -void check_demobutton() { - if (button(demobutton)) ppm_demo(); -} - -void check_buttons() { - check_portalbutton(); - check_demobutton(); -} - void display_ppm(int ppm) { int fg, bg; if (ppm >= co2_critical) { @@ -170,7 +116,7 @@ void ppm_demo() { delay(1000); for (int p = 400; p < 1200; p++) { display_ppm(p); - if (button(demobutton)) { + if (button(pin_demobutton)) { display_logo(); delay(500); return; @@ -181,132 +127,45 @@ void ppm_demo() { delay(5000); } -void setup() { - Serial.begin(115200); - Serial.println("Operame start"); - SPIFFS.begin(true); - pinMode(portalbutton, INPUT_PULLUP); - pinMode(demobutton, INPUT_PULLUP); - pinMode(4, OUTPUT); - digitalWrite(4, HIGH); +void panic(const String& message) { + display_big(message, TFT_RED); + delay(5000); + ESP.restart(); +} - display.init(); - display.fillScreen(TFT_BLACK); - display.setRotation(1); - sprite.createSprite(display.width(), display.height()); - - pinMode(12, INPUT_PULLUP); - while (digitalRead(12)) { - display_big("module verkeerd om!", TFT_RED); - delay(1000); +bool button(int pin) { + if (digitalRead(pin)) return false; + unsigned long start = millis(); + while (!digitalRead(pin)) { + if (millis() - start >= 50) display_big(""); } + return millis() - start >= 50; +} - hwserial1.begin(9600, SERIAL_8N1, 27, 26); +void check_portalbutton() { + if (button(pin_portalbutton)) WiFiSettings.portal(); +} - if (aqc_get_co2() >= 0) { - driver = AQC; - hwserial1.setTimeout(100); - Serial.println("Using AQC driver."); - } else { - driver = MHZ; - mhz_setup(); - Serial.println("Using MHZ driver."); - } +void check_demobutton() { + if (button(pin_demobutton)) ppm_demo(); +} - display_logo(); - delay(2000); +void check_buttons() { + check_portalbutton(); + check_demobutton(); +} - WiFiSettings.hostname = "operame-"; - wifi_enabled = WiFiSettings.checkbox("operame_wifi", false, "WiFi-verbinding gebruiken"); - ota_enabled = WiFiSettings.checkbox("operame_ota", false, "Draadloos herprogrammeren inschakelen. (Gebruikt portaalwachtwoord!)") && wifi_enabled; - - WiFiSettings.heading("CO2-niveaus"); - co2_warning = WiFiSettings.integer("operame_co2_warning", 400, 5000, 700, "Geel vanaf [ppm]"); - co2_critical = WiFiSettings.integer("operame_co2_critical",400, 5000, 800, "Rood vanaf [ppm]"); - co2_blink = WiFiSettings.integer("operame_co2_blink", 800, 5000, 800, "Knipperen vanaf [ppm]"); - - WiFiSettings.heading("MQTT"); - mqtt_enabled = WiFiSettings.checkbox("operame_mqtt", false, "Metingen via het MQTT-protocol versturen") && wifi_enabled; - String server = WiFiSettings.string("mqtt_server", 64, "", "Broker"); - int port = WiFiSettings.integer("mqtt_port", 0, 65535, 1883, "Broker TCP-poort"); - max_failures = WiFiSettings.integer("operame_max_failures", 0, 1000, 10, "Aantal verbindingsfouten voor automatische herstart"); - mqtt_topic = WiFiSettings.string("operame_mqtt_topic", WiFiSettings.hostname, "Topic"); - mqtt_interval = 1000UL * WiFiSettings.integer("operame_mqtt_interval", 10, 3600, 60, "Publicatie-interval [s]"); - mqtt_template = WiFiSettings.string("operame_mqtt_template", "{} PPM", "Berichtsjabloon"); - WiFiSettings.info("De {} in het sjabloon wordt vervangen door de gemeten waarde."); - - if (ota_enabled) WiFiSettings.onPortal = setup_ota; - - WiFiSettings.onConnect = [] { - display_big("Verbinden met WiFi...", TFT_BLUE); - check_portalbutton(); - return 50; - }; - WiFiSettings.onFailure = [] { - display_big("WiFi mislukt!", TFT_RED); - delay(2000); - }; - static int portal_phase = 0; - WiFiSettings.onPortalView = [] { - if (portal_phase < 2) portal_phase = 2; - }; - WiFiSettings.onConfigSaved = [] { - portal_phase = 3; - }; - WiFiSettings.onPortalWaitLoop = [] { - if (WiFi.softAPgetStationNum() == 0) portal_phase = 0; - else if (! portal_phase) portal_phase = 1; - - switch (portal_phase) { - case 0: { - display_lines({ - "Voor configuratie,", - "verbind met WiFi", - "\"" + WiFiSettings.hostname + "\"", - "met een smartphone." - }, TFT_WHITE, TFT_BLUE); - break ; - } - case 1: { - display_lines({ - "Volg instructies op", - "uw smartphone.", - "(inlog-notificatie)" - }, TFT_WHITE, TFT_BLUE); - break; - } - case 2: { - display_lines({ - "Wijzig instellingen", - "en klik op \"Save\".", - "(rechtsonder)" - }, TFT_WHITE, TFT_BLUE); - break; - } - case 3: { - display_lines({ - "Wijzig instellingen", - "en klik op \"Save\".", - "Of \"Restart device\"", - "als u klaar bent." - }, TFT_WHITE, TFT_BLUE); - break; - } - } - if (portal_phase == 0 && millis() > 10*60*1000) { - panic("Tijd verstreken"); - } - - if (ota_enabled) ArduinoOTA.handle(); - if (button(portalbutton)) ESP.restart(); - }; - - if (wifi_enabled) WiFiSettings.connect(false, 15); - - static WiFiClient wificlient; - if (mqtt_enabled) mqtt.begin(server.c_str(), port, wificlient); - - if (ota_enabled) setup_ota(); +void setup_ota() { + ArduinoOTA.setHostname(WiFiSettings.hostname.c_str()); + ArduinoOTA.setPassword(WiFiSettings.password.c_str()); + ArduinoOTA.onStart( []() { display_big("OTA", TFT_BLUE); }); + ArduinoOTA.onEnd( []() { display_big("OTA done", TFT_GREEN); }); + ArduinoOTA.onError( [](ota_error_t e) { display_big("OTA failed", TFT_RED); }); + ArduinoOTA.onProgress([](unsigned int p, unsigned int t) { + String pct { (int) ((float) p / t * 100) }; + display_big(pct + "%"); + }); + ArduinoOTA.begin(); } void connect_mqtt() { @@ -401,47 +260,166 @@ int get_co2() { return -1; // suppress warning } +void setup() { + Serial.begin(115200); + Serial.println("Operame start"); + SPIFFS.begin(true); + + pinMode(pin_portalbutton, INPUT_PULLUP); + pinMode(pin_demobutton, INPUT_PULLUP); + pinMode(pin_pcb_ok, INPUT_PULLUP); + pinMode(pin_backlight, OUTPUT); + + digitalWrite(pin_backlight, HIGH); + + display.init(); + display.fillScreen(TFT_BLACK); + display.setRotation(1); + sprite.createSprite(display.width(), display.height()); + + while (digitalRead(pin_pcb_ok)) { + display_big("module verkeerd om!", TFT_RED); + delay(1000); + } + + hwserial1.begin(9600, SERIAL_8N1, pin_sensor_rx, pin_sensor_tx); + + if (aqc_get_co2() >= 0) { + driver = AQC; + hwserial1.setTimeout(100); + Serial.println("Using AQC driver."); + } else { + driver = MHZ; + mhz_setup(); + Serial.println("Using MHZ driver."); + } + + display_logo(); + delay(2000); + + WiFiSettings.hostname = "operame-"; + wifi_enabled = WiFiSettings.checkbox("operame_wifi", false, "WiFi-verbinding gebruiken"); + ota_enabled = WiFiSettings.checkbox("operame_ota", false, "Draadloos herprogrammeren inschakelen. (Gebruikt portaalwachtwoord!)") && wifi_enabled; + + WiFiSettings.heading("CO2-niveaus"); + co2_warning = WiFiSettings.integer("operame_co2_warning", 400, 5000, 700, "Geel vanaf [ppm]"); + co2_critical = WiFiSettings.integer("operame_co2_critical",400, 5000, 800, "Rood vanaf [ppm]"); + co2_blink = WiFiSettings.integer("operame_co2_blink", 800, 5000, 800, "Knipperen vanaf [ppm]"); + + WiFiSettings.heading("MQTT"); + mqtt_enabled = WiFiSettings.checkbox("operame_mqtt", false, "Metingen via het MQTT-protocol versturen") && wifi_enabled; + String server = WiFiSettings.string("mqtt_server", 64, "", "Broker"); + int port = WiFiSettings.integer("mqtt_port", 0, 65535, 1883, "Broker TCP-poort"); + max_failures = WiFiSettings.integer("operame_max_failures", 0, 1000, 10, "Aantal verbindingsfouten voor automatische herstart"); + mqtt_topic = WiFiSettings.string("operame_mqtt_topic", WiFiSettings.hostname, "Topic"); + mqtt_interval = 1000UL * WiFiSettings.integer("operame_mqtt_interval", 10, 3600, 60, "Publicatie-interval [s]"); + mqtt_template = WiFiSettings.string("operame_mqtt_template", "{} PPM", "Berichtsjabloon"); + WiFiSettings.info("De {} in het sjabloon wordt vervangen door de gemeten waarde."); + + if (ota_enabled) WiFiSettings.onPortal = setup_ota; + + WiFiSettings.onConnect = [] { + display_big("Verbinden met WiFi...", TFT_BLUE); + check_portalbutton(); + return 50; + }; + WiFiSettings.onFailure = [] { + display_big("WiFi mislukt!", TFT_RED); + delay(2000); + }; + static int portal_phase = 0; + WiFiSettings.onPortalView = [] { + if (portal_phase < 2) portal_phase = 2; + }; + WiFiSettings.onConfigSaved = [] { + portal_phase = 3; + }; + WiFiSettings.onPortalWaitLoop = [] { + if (WiFi.softAPgetStationNum() == 0) portal_phase = 0; + else if (! portal_phase) portal_phase = 1; + + switch (portal_phase) { + case 0: { + display_lines({ + "Voor configuratie,", + "verbind met WiFi", + "\"" + WiFiSettings.hostname + "\"", + "met een smartphone." + }, TFT_WHITE, TFT_BLUE); + break ; + } + case 1: { + display_lines({ + "Volg instructies op", + "uw smartphone.", + "(inlog-notificatie)" + }, TFT_WHITE, TFT_BLUE); + break; + } + case 2: { + display_lines({ + "Wijzig instellingen", + "en klik op \"Save\".", + "(rechtsonder)" + }, TFT_WHITE, TFT_BLUE); + break; + } + case 3: { + display_lines({ + "Wijzig instellingen", + "en klik op \"Save\".", + "Of \"Restart device\"", + "als u klaar bent." + }, TFT_WHITE, TFT_BLUE); + break; + } + } + if (portal_phase == 0 && millis() > 10*60*1000) { + panic("Tijd verstreken"); + } + + if (ota_enabled) ArduinoOTA.handle(); + if (button(pin_portalbutton)) ESP.restart(); + }; + + if (wifi_enabled) WiFiSettings.connect(false, 15); + + static WiFiClient wificlient; + if (mqtt_enabled) mqtt.begin(server.c_str(), port, wificlient); + + if (ota_enabled) setup_ota(); +} + +#define every(t) for (static uint16_t _lasttime; (uint16_t)((uint16_t)millis() - _lasttime) >= (t); _lasttime += (t)) void loop() { static int co2; - static Timer read_sensor { - 5000, - [] { - co2 = get_co2(); - Serial.println(co2); - } - }; - read_sensor(); + every(5000) { + co2 = get_co2(); + Serial.println(co2); + } - static Timer display { - 50, - [] { - if (co2 < 0) { - display_big("sensorfout", TFT_RED); - } else if (co2 == 0) { - display_big("wacht..."); - } else { - // some MH-Z19's go to 10000 but the display has space for 4 digits - display_ppm(co2 > 9999 ? 9999 : co2); - } + every(50) { + if (co2 < 0) { + display_big("sensorfout", TFT_RED); + } else if (co2 == 0) { + display_big("wacht..."); + } else { + // some MH-Z19's go to 10000 but the display has space for 4 digits + display_ppm(co2 > 9999 ? 9999 : co2); } - }; - display(); + } - static Timer publish { - mqtt_interval, - [] { - if (co2 <= 0) return; + if (mqtt_enabled) { + mqtt.loop(); + every(mqtt_interval) { + if (co2 <= 0) break; connect_mqtt(); String message = mqtt_template; message.replace("{}", String(co2)); retain(mqtt_topic, message); } - }; - if (mqtt_enabled) { - mqtt.loop(); - publish(); } if (ota_enabled) ArduinoOTA.handle();