From e79400834979eb044fbcfe643a99deb822527942 Mon Sep 17 00:00:00 2001 From: Pascal Brunot Date: Mon, 20 May 2024 22:29:14 +0200 Subject: [PATCH 1/6] Buzzer: removed frequency generation as buzzer is active type 3V --- conf/conf.hpp | 2 -- src/BoardLogic.cpp | 12 ++++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/conf/conf.hpp b/conf/conf.hpp index 47a3e694..36eef101 100644 --- a/conf/conf.hpp +++ b/conf/conf.hpp @@ -60,10 +60,8 @@ namespace fabomatic namespace conf::buzzer { - static constexpr unsigned short LEDC_PWM_CHANNEL{2}; /* Esp32 pwm channel for beep generation */ static constexpr auto STANDARD_BEEP_DURATION{250ms}; /* Single beep duration, typical value 200ms. Set to 0 to disable beeps. */ static constexpr auto NB_BEEPS{3}; /* Number of beeps every time the function is callsed */ - static constexpr unsigned int BEEP_HZ{660}; /* Beep frequency in Hz */ } // namespace conf::buzzer diff --git a/src/BoardLogic.cpp b/src/BoardLogic.cpp index 0c1182c1..5acb6970 100644 --- a/src/BoardLogic.cpp +++ b/src/BoardLogic.cpp @@ -262,10 +262,6 @@ namespace fabomatic { pinMode(pins.buzzer.pin, OUTPUT); gpio_set_drive_capability(static_cast(pins.buzzer.pin), GPIO_DRIVE_CAP_2); - auto freq = ledcSetup(conf::buzzer::LEDC_PWM_CHANNEL, conf::buzzer::BEEP_HZ, 8U); - ESP_LOGD(TAG, "PWM frequency for buzzer set to %d Hz", freq); - success &= (freq != 0); - ledcAttachPin(pins.buzzer.pin, conf::buzzer::LEDC_PWM_CHANNEL); } ESP_LOGI(TAG, "Board initialization complete, success = %d", success); @@ -448,9 +444,9 @@ namespace fabomatic { if constexpr (conf::buzzer::STANDARD_BEEP_DURATION > 0ms && pins.buzzer.pin != NO_PIN) { - ledcWrite(conf::buzzer::LEDC_PWM_CHANNEL, 127UL); + digitalWrite(pins.buzzer.pin, 1); Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION); - ledcWrite(conf::buzzer::LEDC_PWM_CHANNEL, 0UL); + digitalWrite(pins.buzzer.pin, 0); } } @@ -460,9 +456,9 @@ namespace fabomatic { for (auto i = 0; i < conf::buzzer::NB_BEEPS; i++) { - ledcWrite(conf::buzzer::LEDC_PWM_CHANNEL, 127UL); + digitalWrite(pins.buzzer.pin, 1); Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION); - ledcWrite(conf::buzzer::LEDC_PWM_CHANNEL, 0UL); + digitalWrite(pins.buzzer.pin, 0); Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION); } } From 20c5f452ef7ce0f3a551a41649ace8d9592c74fe Mon Sep 17 00:00:00 2001 From: Pascal Brunot Date: Mon, 20 May 2024 22:28:52 +0200 Subject: [PATCH 2/6] OTA: split from main.cpp into dedicated file --- include/BoardLogic.hpp | 1 + include/OTA.hpp | 24 +++++++ src/BoardLogic.cpp | 6 ++ src/OTA.cpp | 151 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 154 +---------------------------------------- 5 files changed, 183 insertions(+), 153 deletions(-) create mode 100644 include/OTA.hpp create mode 100644 src/OTA.cpp diff --git a/include/BoardLogic.hpp b/include/BoardLogic.hpp index e1bec755..1c3320ae 100644 --- a/include/BoardLogic.hpp +++ b/include/BoardLogic.hpp @@ -75,6 +75,7 @@ namespace fabomatic [[nodiscard]] auto getMachineForTesting() -> Machine &; [[nodiscard]] auto getMachine() const -> const Machine &; [[nodiscard]] auto authorize(const card::uid_t uid) -> bool; + [[nodiscard]] auto getHostname() const -> const std::string; // copy reference BoardLogic &operator=(const BoardLogic &board) = delete; diff --git a/include/OTA.hpp b/include/OTA.hpp new file mode 100644 index 00000000..30f3f2f2 --- /dev/null +++ b/include/OTA.hpp @@ -0,0 +1,24 @@ +#ifndef OTA_HPP +#define OTA_HPP + +#include "ArduinoOTA.h" +#include + +#include "secrets.hpp" + +// For ArduinoOTA +const char *const ssid = fabomatic::secrets::credentials::ssid.data(); +const char *const password = fabomatic::secrets::credentials::password.data(); + +namespace fabomatic +{ + + /// @brief Open the ArduinoOTA configuration portal + /// @param force_reset true to discard saved settings and restore compile-time settings + /// @param disable_portal true to skip portal opening (used at boot time) + void openConfigPortal(bool force_reset, bool disable_portal); + + void setupOTA(); + +} // namespace fabomatic +#endif // #ifndef OTA_HPP \ No newline at end of file diff --git a/src/BoardLogic.cpp b/src/BoardLogic.cpp index 5acb6970..ab07d496 100644 --- a/src/BoardLogic.cpp +++ b/src/BoardLogic.cpp @@ -655,4 +655,10 @@ namespace fabomatic { return this->auth.saveCache(); } + + auto BoardLogic::getHostname() const -> const std::string + { + // Hostname is BOARD + machine_id (which shall be unique) e.g. BOARD1 + return conf::default_config::hostname.data() + std::to_string(conf::default_config::machine_id.id); + } } // namespace fabomatic \ No newline at end of file diff --git a/src/OTA.cpp b/src/OTA.cpp new file mode 100644 index 00000000..2b281f15 --- /dev/null +++ b/src/OTA.cpp @@ -0,0 +1,151 @@ +#include + +#include "OTA.hpp" +#include "BoardLogic.hpp" +#include "language/lang.hpp" + +namespace fabomatic +{ + using Status = BoardLogic::Status; + + std::atomic shouldSaveConfig{false}; + + namespace Board + { + extern BoardLogic logic; + } // namespace Board + + // callback notifying us of the need to save config + void saveConfigCallback() + { + shouldSaveConfig.store(true); + } + + // Called just before the webportal is started after failed WiFi connection + void configModeCallback(WiFiManager *myWiFiManager) + { + ESP_LOGI(TAG, "Entering portal config mode"); + ESP_LOGD(TAG, "%s", WiFi.softAPIP().toString().c_str()); + ESP_LOGD(TAG, "%s", myWiFiManager->getConfigPortalSSID().c_str()); + Board::logic.changeStatus(Status::PortalStarting); + } + + auto getConfig(bool force_reset) -> SavedConfig + { + const auto &opt_settings = SavedConfig::LoadFromEEPROM(); + if (force_reset || !opt_settings) + { + return SavedConfig::DefaultConfig(); + } + + return opt_settings.value(); + } + + // Starts the WiFi and possibly open the config portal in a blocking manner + /// @param force_reset if true, the portal will be reset to factory defaults + /// @param disable_portal if true, the portal will be disabled (useful at boot-time) + void openConfigPortal(bool force_reset, bool disable_portal) + { + WiFiManager wifiManager; + auto config = getConfig(force_reset); + + // We are using config as a buffer for the WiFiManager parameters, make sure it can hold the content + config.mqtt_server.resize(conf::common::STR_MAX_LENGTH); + config.mqtt_switch_topic.resize(conf::common::STR_MAX_LENGTH); + config.machine_id.resize(conf::common::INT_MAX_LENGTH); + + WiFiManagerParameter custom_mqtt_server("Broker", strings::PORTAL_MQTT_BROKER_PROMPT, config.mqtt_server.data(), conf::common::STR_MAX_LENGTH); + WiFiManagerParameter custom_mqtt_topic("Topic", strings::PORTAL_SHELLY_MQTT_PROMPT, config.mqtt_switch_topic.data(), conf::common::STR_MAX_LENGTH); + WiFiManagerParameter custom_machine_id("MachineID", strings::PORTAL_MACHINE_ID_PROMPT, config.machine_id.data(), conf::common::INT_MAX_LENGTH, "type='number' min='0' max='65535'"); + + wifiManager.addParameter(&custom_mqtt_server); + wifiManager.addParameter(&custom_mqtt_topic); + wifiManager.addParameter(&custom_machine_id); + + wifiManager.setTimeout(std::chrono::duration_cast(conf::tasks::PORTAL_CONFIG_TIMEOUT).count()); + wifiManager.setConnectRetries(3); // 3 retries + wifiManager.setConnectTimeout(10); // 10 seconds + wifiManager.setCountry("IT"); + wifiManager.setTitle(strings::PORTAL_TITLE); + wifiManager.setCaptivePortalEnable(true); + wifiManager.setAPCallback(configModeCallback); + wifiManager.setSaveConfigCallback(saveConfigCallback); + + if (force_reset) + { + wifiManager.resetSettings(); + } + +#if (PINS_WOKWI) + wifiManager.setDebugOutput(true); + wifiManager.resetSettings(); + wifiManager.setTimeout(10); // fail fast for debugging +#endif + auto must_skip = disable_portal || config.disablePortal; + if (must_skip) + { + wifiManager.setTimeout(1); + } + + if (wifiManager.autoConnect()) + { + Board::logic.changeStatus(Status::PortalSuccess); + delay(1000); + } + else + { + if (!must_skip) + { + Board::logic.changeStatus(Status::PortalFailed); + delay(3000); + } + } + + if (shouldSaveConfig) + { + // save SSID data from WiFiManager + config.ssid.assign(WiFi.SSID().c_str()); + config.password.assign(WiFi.psk().c_str()); + + // read updated parameters + config.mqtt_server.assign(custom_mqtt_server.getValue()); + config.mqtt_switch_topic.assign(custom_mqtt_topic.getValue()); + config.machine_id.assign(custom_machine_id.getValue()); + + config.disablePortal = true; + + // save the custom parameters to EEPROM + if (config.SaveToEEPROM()) + { + ESP_LOGD(TAG, "Config saved to EEPROM"); + } + else + { + ESP_LOGE(TAG, "Failed to save config to EEPROM"); + } + + // WiFi settings change may require full reboot + Board::logic.setRebootRequest(true); + } + } + + void OTAComplete() + { + ESP_LOGI(TAG, "OTA complete, reboot requested"); + Board::logic.setRebootRequest(true); + } + + void setupOTA() + { + ArduinoOTA.setHostname(Board::logic.getHostname().c_str()); + ArduinoOTA.onStart([]() + { Board::logic.changeStatus(Status::OTAStarting); }); + ArduinoOTA.onEnd(OTAComplete); + ArduinoOTA.onError([](ota_error_t error) + { Board::logic.changeStatus(Status::OTAError); }); + ArduinoOTA.setMdnsEnabled(true); + ArduinoOTA.setRebootOnSuccess(false); + ArduinoOTA.setTimeout(45000); + ArduinoOTA.begin(); + } +} // namespace fabomatic \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 8150ae8b..02a5a511 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,10 +3,7 @@ #include #include #include -#include -#include "ArduinoOTA.h" -#include #include #include "BoardLogic.hpp" @@ -20,10 +17,7 @@ #endif #include "pins.hpp" #include "language/lang.hpp" - -// For ArduinoOTA -const char *const ssid = fabomatic::secrets::credentials::ssid.data(); -const char *const password = fabomatic::secrets::credentials::password.data(); +#include "OTA.hpp" using namespace std::chrono_literals; @@ -45,9 +39,6 @@ namespace fabomatic extern BoardLogic logic; } // namespace Board - // Pre-declaration - void openConfigPortal(bool force_reset, bool disable_portal); - /// @brief Opens WiFi and server connection and updates board state accordingly void taskConnect() { @@ -314,146 +305,6 @@ namespace fabomatic const Task t_sim("RFIDCardsSim", 1s, &taskRFIDCardSim, Board::scheduler, true, 30s); #endif - // flag for saving data - std::atomic shouldSaveConfig = false; - - // callback notifying us of the need to save config - void saveConfigCallback() - { - shouldSaveConfig.store(true); - } - - // Called just before the webportal is started after failed WiFi connection - void configModeCallback(WiFiManager *myWiFiManager) - { - ESP_LOGI(TAG, "Entering portal config mode"); - ESP_LOGD(TAG, "%s", WiFi.softAPIP().toString().c_str()); - ESP_LOGD(TAG, "%s", myWiFiManager->getConfigPortalSSID().c_str()); - Board::logic.changeStatus(Status::PortalStarting); - } - - auto getConfig(bool force_reset) -> SavedConfig - { - const auto &opt_settings = SavedConfig::LoadFromEEPROM(); - if (force_reset || !opt_settings) - { - return SavedConfig::DefaultConfig(); - } - - return opt_settings.value(); - } - - // Starts the WiFi and possibly open the config portal in a blocking manner - /// @param force_reset if true, the portal will be reset to factory defaults - /// @param disable_portal if true, the portal will be disabled (useful at boot-time) - void openConfigPortal(bool force_reset, bool disable_portal) - { - WiFiManager wifiManager; - auto config = getConfig(force_reset); - - // We are using config as a buffer for the WiFiManager parameters, make sure it can hold the content - config.mqtt_server.resize(conf::common::STR_MAX_LENGTH); - config.mqtt_switch_topic.resize(conf::common::STR_MAX_LENGTH); - config.machine_id.resize(conf::common::INT_MAX_LENGTH); - - WiFiManagerParameter custom_mqtt_server("Broker", strings::PORTAL_MQTT_BROKER_PROMPT, config.mqtt_server.data(), conf::common::STR_MAX_LENGTH); - WiFiManagerParameter custom_mqtt_topic("Topic", strings::PORTAL_SHELLY_MQTT_PROMPT, config.mqtt_switch_topic.data(), conf::common::STR_MAX_LENGTH); - WiFiManagerParameter custom_machine_id("MachineID", strings::PORTAL_MACHINE_ID_PROMPT, config.machine_id.data(), conf::common::INT_MAX_LENGTH, "type='number' min='0' max='65535'"); - - wifiManager.addParameter(&custom_mqtt_server); - wifiManager.addParameter(&custom_mqtt_topic); - wifiManager.addParameter(&custom_machine_id); - - wifiManager.setTimeout(std::chrono::duration_cast(conf::tasks::PORTAL_CONFIG_TIMEOUT).count()); - wifiManager.setConnectRetries(3); // 3 retries - wifiManager.setConnectTimeout(10); // 10 seconds - wifiManager.setCountry("IT"); - wifiManager.setTitle(strings::PORTAL_TITLE); - wifiManager.setCaptivePortalEnable(true); - wifiManager.setAPCallback(configModeCallback); - wifiManager.setSaveConfigCallback(saveConfigCallback); - - if (force_reset) - { - wifiManager.resetSettings(); - } - -#if (PINS_WOKWI) - wifiManager.setDebugOutput(true); - wifiManager.resetSettings(); - wifiManager.setTimeout(10); // fail fast for debugging -#endif - auto must_skip = disable_portal || config.disablePortal; - if (must_skip) - { - wifiManager.setTimeout(1); - } - - if (wifiManager.autoConnect()) - { - Board::logic.changeStatus(Status::PortalSuccess); - delay(1000); - } - else - { - if (!must_skip) - { - Board::logic.changeStatus(Status::PortalFailed); - delay(3000); - } - } - - if (shouldSaveConfig) - { - // save SSID data from WiFiManager - config.ssid.assign(WiFi.SSID().c_str()); - config.password.assign(WiFi.psk().c_str()); - - // read updated parameters - config.mqtt_server.assign(custom_mqtt_server.getValue()); - config.mqtt_switch_topic.assign(custom_mqtt_topic.getValue()); - config.machine_id.assign(custom_machine_id.getValue()); - - config.disablePortal = true; - - // save the custom parameters to EEPROM - if (config.SaveToEEPROM()) - { - ESP_LOGD(TAG, "Config saved to EEPROM"); - } - else - { - ESP_LOGE(TAG, "Failed to save config to EEPROM"); - } - - // WiFi settings change may require full reboot - Board::logic.setRebootRequest(true); - } - } - - void OTAComplete() - { - ESP_LOGI(TAG, "OTA complete, reboot requested"); - Board::logic.setRebootRequest(true); - } - - void setupOTA() - { - std::stringstream ss{}; - // Hostname is BOARD + machine_id (which shall be unique) e.g. BOARD1 - ss << conf::default_config::hostname.data() << conf::default_config::machine_id.id; - ArduinoOTA.setHostname(ss.str().c_str()); - ArduinoOTA.onStart([]() - { Board::logic.changeStatus(Status::OTAStarting); }); - ArduinoOTA.onEnd(OTAComplete); - ArduinoOTA.onError([](ota_error_t error) - { Board::logic.changeStatus(Status::OTAError); }); - ArduinoOTA.setMdnsEnabled(true); - ArduinoOTA.setRebootOnSuccess(false); - ArduinoOTA.setTimeout(45000); - ArduinoOTA.begin(); - } - void printCompileSettings() { using namespace conf; @@ -498,10 +349,8 @@ namespace fabomatic std::cout << "\tLOAD_EEPROM_DEFAULTS: " << debug::LOAD_EEPROM_DEFAULTS << '\n'; // namespace conf::buzzer std::cout << "Buzzer settings:" << '\n'; - std::cout << "\tLEDC_PWM_CHANNEL: " << buzzer::LEDC_PWM_CHANNEL << '\n'; std::cout << "\tSTANDARD_BEEP_DURATION: " << std::chrono::milliseconds(buzzer::STANDARD_BEEP_DURATION).count() << "ms" << '\n'; std::cout << "\tNB_BEEPS: " << buzzer::NB_BEEPS << '\n'; - std::cout << "\tBEEP_HZ: " << buzzer::BEEP_HZ << '\n'; // namespace conf::tasks std::cout << "Tasks settings:" << '\n'; std::cout << "\tRFID_CHECK_PERIOD: " << std::chrono::milliseconds(tasks::RFID_CHECK_PERIOD).count() << "ms" << '\n'; @@ -542,7 +391,6 @@ namespace fabomatic std::cout << "\t\tFactory defaults pin:" << +pins.buttons.factory_defaults_pin << '\n'; std::cout << std::endl; } - } // namespace fabomatic #ifndef PIO_UNIT_TESTING From 251eb6e1dcce9f6521183fd0505ec65d9c9d70f0 Mon Sep 17 00:00:00 2001 From: Pascal Brunot Date: Tue, 21 May 2024 22:22:00 +0200 Subject: [PATCH 3/6] removed C-style array --- src/RFIDWrapper.tpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RFIDWrapper.tpp b/src/RFIDWrapper.tpp index 4bdf9ced..2712c9cb 100644 --- a/src/RFIDWrapper.tpp +++ b/src/RFIDWrapper.tpp @@ -51,10 +51,10 @@ namespace fabomatic do { // Detect Tag without looking for collisions - byte bufferATQA[2]; - byte bufferSize = sizeof(bufferATQA); + std::array bufferATQA; + byte len = sizeof(bufferATQA); - if (driver->PICC_WakeupA(bufferATQA, bufferSize)) + if (driver->PICC_WakeupA(bufferATQA.data(), len)) { if (readCardSerial() == original) return true; From dbb3d42482d87f5071fc00132e4a8505e0f935e3 Mon Sep 17 00:00:00 2001 From: Pascal Brunot Date: Tue, 21 May 2024 22:22:17 +0200 Subject: [PATCH 4/6] Force unit for logging --- src/MachineConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MachineConfig.cpp b/src/MachineConfig.cpp index b607fb7f..7d2f82aa 100644 --- a/src/MachineConfig.cpp +++ b/src/MachineConfig.cpp @@ -18,7 +18,7 @@ namespace fabomatic sstream << "), AutologoffDelay (min):" << std::chrono::duration_cast(autologoff).count(); sstream << ", HasRelay:" << hasRelay(); sstream << ", HasMqttSwitch:" << hasMqttSwitch(); - sstream << ", GracePeriod (s):" << grace_period.count(); + sstream << ", GracePeriod (s):" << std::chrono::duration_cast(grace_period).count(); sstream << "))"; return sstream.str(); From dd7ea132eb90a5814479ec911d71b2a17cd25d7a Mon Sep 17 00:00:00 2001 From: Pascal Brunot Date: Thu, 23 May 2024 21:16:27 +0200 Subject: [PATCH 5/6] Code clean-up (#27) * removed C-style array * Force unit for logging * Lcd does not need mockup * Removed some configuration fields who cannot change at runtime * Changed initializers for consistency * Changed initializers for consistency * Trailing return type declarations * Added comments --- conf/conf.hpp | 14 +-- include/AuthProvider.hpp | 4 +- include/FabUser.hpp | 6 +- include/LCDWrapper.hpp | 22 ++-- include/Led.hpp | 8 +- include/MQTTtypes.hpp | 6 +- include/MachineConfig.hpp | 44 ++------ include/MachineID.hpp | 26 +++++ include/OTA.hpp | 6 +- include/card.hpp | 2 +- include/mock/MockLcdLibrary.hpp | 22 ---- include/mock/MockMQTTBroker.hpp | 4 +- include/mock/MockMrfc522.hpp | 11 +- src/FabBackend.cpp | 180 ++++++++++++++++++++++---------- src/Machine.cpp | 10 +- src/MachineConfig.cpp | 14 +-- src/RFIDWrapper.tpp | 6 +- src/mock/MockMQTTBroker.cpp | 70 +++++++++++-- test/test_logic/test_logic.cpp | 4 +- 19 files changed, 280 insertions(+), 179 deletions(-) create mode 100644 include/MachineID.hpp delete mode 100644 include/mock/MockLcdLibrary.hpp diff --git a/conf/conf.hpp b/conf/conf.hpp index 36eef101..f7669490 100644 --- a/conf/conf.hpp +++ b/conf/conf.hpp @@ -5,7 +5,7 @@ #include #include -#include "MachineConfig.hpp" +#include "MachineID.hpp" namespace fabomatic { @@ -13,12 +13,14 @@ namespace fabomatic namespace conf::default_config { - static constexpr std::string_view mqtt_server = "fabpi2.local"; - static constexpr std::string_view mqtt_switch_topic = ""; + static constexpr std::string_view mqtt_server{"fabpi2.local"}; + static constexpr std::string_view mqtt_switch_topic{""}; + static constexpr std::string_view mqtt_switch_on_message{"on"}; + static constexpr std::string_view mqtt_switch_off_message{"off"}; static constexpr MachineID machine_id{1}; - static constexpr std::string_view machine_name = "MACHINE1"; - static constexpr MachineType machine_type = MachineType::Printer3D; - static constexpr std::string_view hostname = "BOARD"; // Machine ID will be added to the hostname in order to form unique hostnames + static constexpr std::string_view machine_name{"MACHINE1"}; + static constexpr MachineType machine_type{MachineType::Printer3D}; + static constexpr std::string_view hostname{"BOARD"}; // Machine ID will be added to the hostname in order to form unique hostnames } // namespace conf::default_config diff --git a/include/AuthProvider.hpp b/include/AuthProvider.hpp index 77dec28f..2da6abfa 100644 --- a/include/AuthProvider.hpp +++ b/include/AuthProvider.hpp @@ -18,7 +18,7 @@ namespace fabomatic private: WhiteList whitelist; mutable CachedCards cache; - mutable size_t cache_idx = 0; + mutable size_t cache_idx{0}; [[nodiscard]] auto uidInWhitelist(card::uid_t uid) const -> std::optional; [[nodiscard]] auto uidInCache(card::uid_t uid) const -> std::optional; [[nodiscard]] auto searchCache(card::uid_t candidate_uid) const -> std::optional; @@ -28,7 +28,7 @@ namespace fabomatic AuthProvider() = delete; AuthProvider(WhiteList whitelist); [[nodiscard]] auto tryLogin(card::uid_t uid, FabBackend &server) const -> std::optional; - void setWhitelist(WhiteList list); + auto setWhitelist(WhiteList list) -> void; auto saveCache() const -> bool; auto loadCache() -> void; }; diff --git a/include/FabUser.hpp b/include/FabUser.hpp index 403adc6b..c9d00ad6 100644 --- a/include/FabUser.hpp +++ b/include/FabUser.hpp @@ -21,10 +21,10 @@ namespace fabomatic FabAdmin, }; - card::uid_t card_uid = card::INVALID; + card::uid_t card_uid {card::INVALID}; std::string holder_name{""}; - bool authenticated = false; - UserLevel user_level = UserLevel::Unknown; + bool authenticated {false}; + UserLevel user_level {UserLevel::Unknown}; FabUser() = default; diff --git a/include/LCDWrapper.hpp b/include/LCDWrapper.hpp index cd1b6e82..bc0cf3e7 100644 --- a/include/LCDWrapper.hpp +++ b/include/LCDWrapper.hpp @@ -17,13 +17,13 @@ namespace fabomatic LCDWrapper(const pins_config::lcd_config &config); using DisplayBuffer = std::array, conf::lcd::ROWS>; - bool begin() override; - void clear() override; - void showConnection(bool show) override; - void showPower(bool show) override; - void setRow(uint8_t row, const std::string_view &text) override; - void update(const BoardInfo &boardinfo, bool forced = false) override; + auto begin() -> bool override; + auto clear() -> void override; + auto showConnection(bool show) -> void override; + auto showPower(bool show) -> void override; + auto setRow(uint8_t row, const std::string_view &text) -> void override; + auto update(const BoardInfo &boardinfo, bool forced = false) -> void override; private: static constexpr auto HEIGHT_PX = 8; @@ -41,7 +41,7 @@ namespace fabomatic static constexpr std::array powered_off_char{0x0a, 0x04, 0x0a, 0x00, 0x1f, 0x1f, 0x0a, 0x0a}; static constexpr std::array powering_off_char{0x0e, 0x15, 0x15, 0x15, 0x17, 0x11, 0x11, 0x0e}; - const pins_config::lcd_config config; + const pins_config::lcd_config &config; LcdDriver lcd; bool show_connection_status; @@ -51,11 +51,11 @@ namespace fabomatic DisplayBuffer current; BoardInfo boardInfo; - void backlightOn() const; - void backlightOff() const; - void prettyPrint(const DisplayBuffer &buffer, const BoardInfo &bi) const; + auto backlightOn() const -> void; + auto backlightOff() const -> void; + auto prettyPrint(const DisplayBuffer &buffer, const BoardInfo &bi) const -> void; [[nodiscard]] auto needsUpdate(const BoardInfo &bi) const -> bool; - void createChar(uint8_t char_idx, const std::array &values); + auto createChar(uint8_t char_idx, const std::array &values) -> void; }; } // namespace fabomatic diff --git a/include/Led.hpp b/include/Led.hpp index 3bb20f26..4250fa98 100644 --- a/include/Led.hpp +++ b/include/Led.hpp @@ -12,7 +12,7 @@ namespace fabomatic class Led { public: - enum class Status : uint8_t + enum class Status { Off, On, @@ -21,9 +21,9 @@ namespace fabomatic Led() = default; - void set(Status status); - void setColor(uint8_t r, uint8_t g, uint8_t b); - void update(); + auto set(Status status) -> void; + auto setColor(uint8_t r, uint8_t g, uint8_t b) -> void; + auto update() -> void; private: Adafruit_NeoPixel pixel{1, pins.led.pin, pins.led.neopixel_config}; diff --git a/include/MQTTtypes.hpp b/include/MQTTtypes.hpp index abc3f2c7..2f39ad8a 100644 --- a/include/MQTTtypes.hpp +++ b/include/MQTTtypes.hpp @@ -147,10 +147,10 @@ namespace fabomatic::ServerMQTT bool is_valid = false; /* True if the machine has a valid ID */ bool maintenance = true; /* True if the machine needs maintenance */ bool allowed = false; /* True if the machine can be used by anybody */ - uint16_t logoff = 0; /* Timeout in minutes */ + uint16_t logoff{0}; /* Timeout in minutes */ std::string name{""}; /* Name of the machine from server DB */ - uint8_t type = 0; /* Type of the machine */ - uint16_t grace = 0; /* Grace period in minutes */ + uint8_t type{0}; /* Type of the machine */ + uint16_t grace{0}; /* Grace period in minutes */ std::string description{""}; /* Description of the expired maintenance */ MachineResponse() = delete; MachineResponse(bool rok) : Response(rok){}; diff --git a/include/MachineConfig.hpp b/include/MachineConfig.hpp index 5f922bd3..762e150f 100644 --- a/include/MachineConfig.hpp +++ b/include/MachineConfig.hpp @@ -1,51 +1,26 @@ #ifndef MACHINECONFIG_HPP_ #define MACHINECONFIG_HPP_ -#include "pins.hpp" #include #include #include +#include "pins.hpp" +#include "MachineID.hpp" +#include "conf.hpp" + namespace fabomatic { - enum class MachineType : uint8_t - { - Invalid = 0, - Printer3D = 1, - Laser = 2, - Cnc = 3, - PrinterResin = 4, - Other = 5 - }; - - struct MachineID - { - uint16_t id; - - constexpr MachineID() : id(0) {} - constexpr MachineID(uint16_t id) : id(id) {} - // Add conversion operator to uint16_t to use in print, streams... - constexpr operator uint16_t() const { return id; } - }; struct MachineConfig { MachineID machine_id{0}; MachineType machine_type{MachineType::Invalid}; std::string machine_name{""}; - struct RelayConfig - { - const uint8_t pin{NO_PIN}; - const bool active_low{false}; - } relay_config; - struct MQTTConfig - { - const std::string topic{""}; - const std::string on_message{"on"}; - const std::string off_message{"off"}; - } mqtt_config; + const pins_config::relay_config &relay_config; + const std::string mqtt_switch_topic{""}; /// @brief Time after which the active user on the machine shall be logged-off - std::chrono::seconds autologoff; + std::chrono::seconds autologoff{conf::machine::DEFAULT_AUTO_LOGOFF_DELAY}; /// @brief Time after which the active user on the machine shall be logged-off std::chrono::seconds grace_period; @@ -55,8 +30,9 @@ namespace fabomatic std::chrono::seconds autologoff, std::chrono::seconds grace_period) : machine_id(id), machine_type(type), machine_name(name), - relay_config{relay.ch1_pin, relay.active_low}, - mqtt_config{topic}, autologoff(autologoff), + relay_config{relay}, + mqtt_switch_topic(topic), + autologoff(autologoff), grace_period{grace_period} {}; [[nodiscard]] auto toString() const -> const std::string; diff --git a/include/MachineID.hpp b/include/MachineID.hpp new file mode 100644 index 00000000..cf27c9ce --- /dev/null +++ b/include/MachineID.hpp @@ -0,0 +1,26 @@ +#ifndef MACHINE_ID_HPP +#define MACHINE_ID_HPP + +#include + +enum class MachineType : uint8_t +{ + Invalid = 0, + Printer3D = 1, + Laser = 2, + Cnc = 3, + PrinterResin = 4, + Other = 5 +}; + +struct MachineID +{ + uint16_t id; + + constexpr MachineID() : id(0) {} + constexpr MachineID(uint16_t id) : id(id) {} + // Add conversion operator to uint16_t to use in print, streams... + constexpr operator uint16_t() const { return id; } +}; + +#endif // MACHINE_ID_HPP \ No newline at end of file diff --git a/include/OTA.hpp b/include/OTA.hpp index 30f3f2f2..657e5629 100644 --- a/include/OTA.hpp +++ b/include/OTA.hpp @@ -16,9 +16,9 @@ namespace fabomatic /// @brief Open the ArduinoOTA configuration portal /// @param force_reset true to discard saved settings and restore compile-time settings /// @param disable_portal true to skip portal opening (used at boot time) - void openConfigPortal(bool force_reset, bool disable_portal); - - void setupOTA(); + auto openConfigPortal(bool force_reset, bool disable_portal) -> void; + + auto setupOTA() -> void; } // namespace fabomatic #endif // #ifndef OTA_HPP \ No newline at end of file diff --git a/include/card.hpp b/include/card.hpp index 33b07482..69607cb1 100644 --- a/include/card.hpp +++ b/include/card.hpp @@ -55,7 +55,7 @@ namespace fabomatic::card return retVal; } - inline void print(uint64_t uid) + inline auto print(uint64_t uid) -> void { ESP_LOGI(TAG, "Card UID = %s", card::uid_str(uid).c_str()); } diff --git a/include/mock/MockLcdLibrary.hpp b/include/mock/MockLcdLibrary.hpp deleted file mode 100644 index 7d5810cd..00000000 --- a/include/mock/MockLcdLibrary.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MOCK_MOCKLCDLIBRARY_HPP_ -#define MOCK_MOCKLCDLIBRARY_HPP_ - -#include - -namespace fabomatic -{ - class MockLcdLibrary final - { - public: - constexpr MockLcdLibrary() = default; - MockLcdLibrary(uint8_t rs_pin, uint8_t en_pin, uint8_t d0_pin, uint8_t d1_pin, uint8_t d2_pin, uint8_t d3_pin){}; - auto begin(uint8_t cols, uint8_t rows) -> void{}; - auto createChar(uint8_t num, const uint8_t *values) -> void{}; - auto clear() -> void{}; - auto print(const char *text) -> void{}; - auto setCursor(uint8_t col, uint8_t row) -> void{}; - auto write(uint8_t value) -> void{}; - }; -} // namespace fabomatic - -#endif // MOCK_MOCKLCDLIBRARY_HPP_ \ No newline at end of file diff --git a/include/mock/MockMQTTBroker.hpp b/include/mock/MockMQTTBroker.hpp index f768e44c..2d95254c 100644 --- a/include/mock/MockMQTTBroker.hpp +++ b/include/mock/MockMQTTBroker.hpp @@ -31,8 +31,8 @@ namespace fabomatic private: std::mutex mutex; - std::string topic = ""; - std::string payload = ""; + std::string topic{""}; + std::string payload{""}; struct query { std::string source_topic{""}; diff --git a/include/mock/MockMrfc522.hpp b/include/mock/MockMrfc522.hpp index c6254ccc..f685de94 100644 --- a/include/mock/MockMrfc522.hpp +++ b/include/mock/MockMrfc522.hpp @@ -33,16 +33,17 @@ namespace fabomatic auto PICC_IsNewCardPresent() -> bool; auto PICC_ReadCardSerial() -> bool; - void reset(); + auto reset() -> void; auto PCD_Init() -> bool; auto PICC_WakeupA(byte *bufferATQA, byte &bufferSize) -> bool; auto PCD_PerformSelfTest() -> bool; auto getDriverUid() const -> MockMrfc522::UidDriver; - void PCD_SetAntennaGain(MFRC522Constants::PCD_RxGain gain); - void PCD_DumpVersionToSerial(); + auto PCD_SetAntennaGain(MFRC522Constants::PCD_RxGain gain) -> void; + auto PCD_DumpVersionToSerial() -> void; - void setUid(const std::optional &uid, const std::optional &max_delay); - void resetUid(); + auto setUid(const std::optional &uid, + const std::optional &max_delay) -> void; + auto resetUid() -> void; static constexpr auto RxGainMax = MFRC522::PCD_RxGain::RxGain_max; }; diff --git a/src/FabBackend.cpp b/src/FabBackend.cpp index 9422e379..1ff2af35 100644 --- a/src/FabBackend.cpp +++ b/src/FabBackend.cpp @@ -1,6 +1,5 @@ #include "FabBackend.hpp" #include "secrets.hpp" - #include "Logging.hpp" #include "SavedConfig.hpp" #include "Tasks.hpp" @@ -13,6 +12,11 @@ namespace fabomatic { + /** + * @brief Configures the FabBackend with the given configuration. + * + * @param config The SavedConfig object containing the configuration parameters. + */ void FabBackend::configure(const SavedConfig &config) { wifi_ssid = config.ssid; @@ -44,9 +48,12 @@ namespace fabomatic ESP_LOGD(TAG, "FabServer configured"); } - /// @brief Posts to MQTT server and waits for answer - /// @param query query to be posted - /// @return true if the server answered + /** + * @brief Posts a query to the MQTT server and waits for a reply. + * + * @param query The query to be posted. + * @return true if the server answered, false otherwise. + */ bool FabBackend::publishWithReply(const ServerMQTT::Query &query) { auto try_cpt = 0; @@ -83,10 +90,14 @@ namespace fabomatic return false; } - /// @brief publish on MQTT the requested info - /// @param mqtt_topic topic to publish to - /// @param mqtt_payload payload to publish - /// @return true if successfull + /** + * @brief Publishes a message on the MQTT server. + * + * @param mqtt_topic The topic to publish to. + * @param mqtt_payload The payload to publish. + * @param waitForAnswer Whether to wait for an answer. + * @return true if the message was published successfully, false otherwise. + */ bool FabBackend::publish(String mqtt_topic, String mqtt_payload, bool waitForAnswer) { if (mqtt_payload.length() + mqtt_topic.length() > FabBackend::MAX_MSG_SIZE - 8) @@ -103,9 +114,12 @@ namespace fabomatic return client.publish(mqtt_topic.c_str(), mqtt_payload.c_str()); } - /// @brief posts to MQTT server - /// @param query message to post - /// @return true if the message was published + /** + * @brief Publishes a query on the MQTT server. + * + * @param query The query to be published. + * @return true if the query was published successfully, false otherwise. + */ bool FabBackend::publish(const ServerMQTT::Query &query) { String s_payload(query.payload().c_str()); @@ -126,6 +140,11 @@ namespace fabomatic return client.publish(s_topic, s_payload); } + /** + * @brief Main loop for the MQTT client. + * + * @return true if the client is running successfully, false otherwise. + */ bool FabBackend::loop() { if (!client.loop()) @@ -140,8 +159,12 @@ namespace fabomatic return true; } - /// @brief blocks until the server answers or until the timeout is reached - /// @return true if the server answered + /** + * @brief Waits for an answer from the MQTT server. + * + * @param max_duration The maximum duration to wait. + * @return true if the server answered, false otherwise. + */ bool FabBackend::waitForAnswer(std::chrono::milliseconds max_duration) { const auto start_time = std::chrono::system_clock::now(); @@ -168,16 +191,22 @@ namespace fabomatic return false; } - /// @brief true if the server has been reached successfully - /// @return boolean + /** + * @brief Checks if the client is online. + * + * @return true if the client is online, false otherwise. + */ bool FabBackend::isOnline() const { return online; } - /// @brief Callback for MQTT messages - /// @param topic topic the message was received on - /// @param payload payload of the message + /** + * @brief Callback function for received MQTT messages. + * + * @param s_topic The topic the message was received on. + * @param s_payload The payload of the message. + */ void FabBackend::messageReceived(String &s_topic, String &s_payload) { ESP_LOGI(TAG, "MQTT Client: Received on %s -> %s", s_topic.c_str(), s_payload.c_str()); @@ -186,8 +215,11 @@ namespace fabomatic answer_pending = false; } - /// @brief Connects to the WiFi network - /// @return true if the connection succeeded + /** + * @brief Connects to the WiFi network. + * + * @return true if the connection succeeded, false otherwise. + */ bool FabBackend::connectWiFi() { static constexpr auto NB_TRIES = 15; @@ -206,7 +238,7 @@ namespace fabomatic { if (WiFi.status() == WL_CONNECTED) { - ESP_LOGD(TAG, "FabServer::connectWiFi() : WiFi connection successfull"); + ESP_LOGD(TAG, "FabServer::connectWiFi() : WiFi connection successful"); break; } Tasks::delay(DELAY_MS); @@ -215,15 +247,18 @@ namespace fabomatic return WiFi.status() == WL_CONNECTED; } - /// @brief Establish WiFi connection and connects to FabServer - /// @return true if both operations succeeded + /** + * @brief Establishes a connection to the WiFi network and the MQTT server. + * + * @return true if both operations succeeded, false otherwise. + */ bool FabBackend::connect() { const auto status = WiFi.status(); ESP_LOGD(TAG, "FabServer::connect() called, Wifi status=%d", status); - // Check if WiFi nextwork is available, and if not, try to connect + // Check if WiFi network is available, and if not, try to connect if (status != WL_CONNECTED) { online = false; @@ -309,7 +344,9 @@ namespace fabomatic return online; } - /// @brief Disconnects from the server + /** + * @brief Disconnects from the MQTT server. + */ void FabBackend::disconnect() { client.disconnect(); @@ -317,11 +354,14 @@ namespace fabomatic Tasks::delay(100ms); } - /// @brief Process a MQTT query and returns the response - /// @tparam T type of the response returned to the caller (it will be wrapped in a unique_ptr) - /// @tparam Q type of the query sent to the server - /// @tparam ...Args arguments to be passed to the constructor of Q - /// @return backend response (if request_ok) + /** + * @brief Processes a query and returns the response. + * + * @tparam RespT The type of the response. + * @tparam QueryT The type of the query. + * @tparam ...Args The arguments to be passed to the query constructor. + * @return A unique_ptr to the response. + */ template std::unique_ptr FabBackend::processQuery(QueryArgs &&...args) { @@ -350,6 +390,13 @@ namespace fabomatic return std::make_unique(false); } + /** + * @brief Processes a query. + * + * @tparam QueryT The type of the query. + * @tparam ...Args The arguments to be passed to the query constructor. + * @return true if the query was processed successfully, false otherwise. + */ template bool FabBackend::processQuery(QueryArgs &&...args) { @@ -370,67 +417,90 @@ namespace fabomatic return false; } - /// @brief Checks if the card ID is known to the server - /// @param uid card uid - /// @return backend response (if request_ok) + /** + * @brief Checks if the card ID is known to the server. + * + * @param uid The card UID. + * @return A unique_ptr to the server response. + */ std::unique_ptr FabBackend::checkCard(card::uid_t uid) { return processQuery(uid); } - /// @brief Checks the machine status on the server - /// @return backend response (if request_ok) + /** + * @brief Checks the machine status on the server. + * + * @return A unique_ptr to the server response. + */ std::unique_ptr FabBackend::checkMachine() { return processQuery(); } - /// @brief register the starting of a machine usage - /// @param uid card uid - /// @return backend response (if request_ok) + /** + * @brief Registers the start of machine usage. + * + * @param uid The card UID of the user. + * @return A unique_ptr to the server response. + */ std::unique_ptr FabBackend::startUse(card::uid_t uid) { return processQuery(uid); } - /// @brief Register end of machine usage - /// @param uid card ID of the machine user - /// @param duration_s duration of usage in seconds - /// @return backend response (if request_ok) + /** + * @brief Registers the end of machine usage. + * + * @param uid The card UID of the user. + * @param duration_s The duration of usage in seconds. + * @return A unique_ptr to the server response. + */ std::unique_ptr FabBackend::finishUse(card::uid_t uid, std::chrono::seconds duration_s) { return processQuery(uid, duration_s); } - /// @brief Inform the backend that the machine is in use. This is used to prevent - /// loosing information if the machine is rebooted while in use. - /// @param uid card ID of the machine user - /// @param duration_s duration of usage in seconds - /// @return backend response (if request_ok) + /** + * @brief Informs the backend that the machine is in use. + * + * @param uid The card UID of the user. + * @param duration_s The duration of usage in seconds. + * @return A unique_ptr to the server response. + */ std::unique_ptr FabBackend::inUse(card::uid_t uid, std::chrono::seconds duration_s) { return processQuery(uid, duration_s); } - /// @brief Registers a maintenance action - /// @param maintainer who performed the maintenance - /// @return server response (if request_ok) + /** + * @brief Registers a maintenance action. + * + * @param maintainer The UID of the person performing maintenance. + * @return A unique_ptr to the server response. + */ std::unique_ptr FabBackend::registerMaintenance(card::uid_t maintainer) { return processQuery(maintainer); } - /// @brief Sends a ping to the server - /// @return true if packet was sent + /** + * @brief Sends a ping to the server. + * + * @return true if the ping was sent successfully, false otherwise. + */ bool FabBackend::alive() { return processQuery(); } - /// @brief set channel to use for WiFi connection - /// @param channel + /** + * @brief Sets the WiFi channel to use. + * + * @param channel The channel number. + */ void FabBackend::setChannel(int32_t channel) { this->channel = channel; } -} // namespace fabomatic \ No newline at end of file +} // namespace fabomatic diff --git a/src/Machine.cpp b/src/Machine.cpp index 44c33851..b50071f3 100644 --- a/src/Machine.cpp +++ b/src/Machine.cpp @@ -31,7 +31,7 @@ namespace fabomatic if (config.value().hasRelay()) { - const auto pin = config.value().relay_config.pin; + const auto pin = config.value().relay_config.ch1_pin; digitalWrite(pin, config.value().relay_config.active_low ? HIGH : LOW); pinMode(pin, OUTPUT); @@ -138,7 +138,7 @@ namespace fabomatic CHECK_CONFIGURED(void); ESP_LOGI(TAG, "Machine::power_relay : power set to %d", value); - const auto pin = config.value().relay_config.pin; + const auto pin = config.value().relay_config.ch1_pin; if (config.value().relay_config.active_low) { @@ -169,10 +169,10 @@ namespace fabomatic ESP_LOGI(TAG, "Machine::power_mqtt : power set to %d", value); auto &mqtt_server = server.value().get(); - auto &act_config = config.value(); + const auto &sw_topic = config.value().mqtt_switch_topic; - String topic{act_config.mqtt_config.topic.data()}; - String payload = value ? act_config.mqtt_config.on_message.data() : act_config.mqtt_config.off_message.data(); + String topic{sw_topic.data()}; + String payload = value ? conf::default_config::mqtt_switch_on_message.data() : conf::default_config::mqtt_switch_on_message.data(); auto retries = 0; while (!mqtt_server.publish(topic, payload, false)) diff --git a/src/MachineConfig.cpp b/src/MachineConfig.cpp index b607fb7f..62914289 100644 --- a/src/MachineConfig.cpp +++ b/src/MachineConfig.cpp @@ -10,15 +10,11 @@ namespace fabomatic sstream << "MachineConfig (ID:" << machine_id.id; sstream << ", Name:" << machine_name; sstream << ", Type:" << static_cast(machine_type); - sstream << ", RelayConfig (pin:" << static_cast(relay_config.pin); - sstream << ", active_low:" << relay_config.active_low; - sstream << "), MQTTConfig (topic:" << mqtt_config.topic; - sstream << ", on_message:" << mqtt_config.on_message; - sstream << ", off_message:" << mqtt_config.off_message; - sstream << "), AutologoffDelay (min):" << std::chrono::duration_cast(autologoff).count(); + sstream << ", AutologoffDelay (min):" << std::chrono::duration_cast(autologoff).count(); + sstream << ", MQTT Switch topic:" << mqtt_switch_topic; sstream << ", HasRelay:" << hasRelay(); sstream << ", HasMqttSwitch:" << hasMqttSwitch(); - sstream << ", GracePeriod (s):" << grace_period.count(); + sstream << ", GracePeriod (s):" << std::chrono::duration_cast(grace_period).count(); sstream << "))"; return sstream.str(); @@ -26,11 +22,11 @@ namespace fabomatic auto MachineConfig::hasRelay() const -> bool { - return relay_config.pin != NO_PIN; + return relay_config.ch1_pin != NO_PIN; } auto MachineConfig::hasMqttSwitch() const -> bool { - return !mqtt_config.topic.empty(); + return !mqtt_switch_topic.empty(); } } // namespace fabomatic \ No newline at end of file diff --git a/src/RFIDWrapper.tpp b/src/RFIDWrapper.tpp index 4bdf9ced..2712c9cb 100644 --- a/src/RFIDWrapper.tpp +++ b/src/RFIDWrapper.tpp @@ -51,10 +51,10 @@ namespace fabomatic do { // Detect Tag without looking for collisions - byte bufferATQA[2]; - byte bufferSize = sizeof(bufferATQA); + std::array bufferATQA; + byte len = sizeof(bufferATQA); - if (driver->PICC_WakeupA(bufferATQA, bufferSize)) + if (driver->PICC_WakeupA(bufferATQA.data(), len)) { if (readCardSerial() == original) return true; diff --git a/src/mock/MockMQTTBroker.cpp b/src/mock/MockMQTTBroker.cpp index 50b78d65..d92a6449 100644 --- a/src/mock/MockMQTTBroker.cpp +++ b/src/mock/MockMQTTBroker.cpp @@ -5,17 +5,28 @@ #include +// TAG for logging purposes static const char *const TAG2 = "MockMQTTBroker"; + namespace fabomatic { + /** + * @brief Starts the MQTT broker. + * + * This function checks if the Wi-Fi is connected and initializes the MQTT broker. + * If the Wi-Fi is not connected, it logs the status and returns. + * If the broker is not running, it initializes the broker with the configured port number. + */ auto MockMQTTBroker::start() -> void { + // Wait for the Wi-Fi to connect while (WiFi.status() != WL_CONNECTED) - { // Wait for the Wi-Fi to connect + { ESP_LOGD(TAG2, "MQTT BROKER: WiFi status changed to %d", WiFi.status()); is_running = false; return; } + // Initialize the broker if it's not running if (!is_running) { is_running = init(conf::mqtt::PORT_NUMBER, true); @@ -23,18 +34,29 @@ namespace fabomatic } } + /** + * @brief Handles MQTT events. + * + * @param event Pointer to the sMQTTEvent object containing event details. + * @return true if the event was handled successfully, false otherwise. + * + * This function handles various types of MQTT events such as new client connections, + * message publications, client removals, connection losses, subscriptions, and unsubscriptions. + */ auto MockMQTTBroker::onEvent(sMQTTEvent *event) -> bool { switch (event->Type()) { case NewClient_sMQTTEventType: { - auto *e = static_cast(event); // NOLINT(unused-variable) + // Handle new client connection event + auto *e = static_cast(event); ESP_LOGD(TAG2, "MQTT BROKER: client connected, id:%s", e->Client()->getClientId().c_str()); } break; case Public_sMQTTEventType: { + // Handle publish event std::lock_guard lock(mutex); auto *e = static_cast(event); topic = e->Topic(); @@ -46,25 +68,29 @@ namespace fabomatic break; case RemoveClient_sMQTTEventType: { - auto *e = static_cast(event); // NOLINT(unused-variable) + // Handle client removal event + auto *e = static_cast(event); ESP_LOGD(TAG2, "MQTT BROKER: removed client id: %s", e->Client()->getClientId().c_str()); } break; case LostConnect_sMQTTEventType: { + // Handle lost connection event is_running = false; ESP_LOGD(TAG2, "MQTT BROKER: lost connection"); } break; case Subscribe_sMQTTEventType: { - auto *e = static_cast(event); // NOLINT(unused-variable) + // Handle subscription event + auto *e = static_cast(event); ESP_LOGD(TAG2, "MQTT BROKER: client %s subscribed to %s", e->Client()->getClientId().c_str(), e->Topic().c_str()); } break; case UnSubscribe_sMQTTEventType: { - auto *e = static_cast(event); // NOLINT(unused-variable) + // Handle unsubscription event + auto *e = static_cast(event); ESP_LOGD(TAG2, "MQTT BROKER: got unsubscribe from %s", e->Topic().c_str()); } break; @@ -75,13 +101,22 @@ namespace fabomatic return true; } + /** + * @brief Checks if the MQTT broker is running. + * + * @return true if the broker is running, false otherwise. + */ auto MockMQTTBroker::isRunning() const -> bool { return is_running; } - /// @brief Returns a fake server reply for testing purposes - /// @return json payload + /** + * @brief Provides fake server replies for testing purposes. + * + * @param query The query string to determine the appropriate response. + * @return The JSON payload response as a string. + */ auto MockMQTTBroker::defaultReplies(const std::string &query) const -> const std::string { if (query.find("checkmachine") != std::string::npos) @@ -156,12 +191,25 @@ namespace fabomatic return std::string{"{\"request_ok\":true}"}; } + /** + * @brief Configures custom replies for MQTT queries. + * + * @param callback A function that takes a topic and query as input and returns the corresponding response. + */ auto MockMQTTBroker::configureReplies(std::function callback) -> void { std::lock_guard lock(mutex); this->callback = callback; } + /** + * @brief Processes pending MQTT queries. + * + * @return The number of remaining queries. + * + * This function processes the queries in the queue by invoking the configured callback function + * and publishes the response to the corresponding reply topic. + */ auto MockMQTTBroker::processQueries() -> size_t { std::lock_guard lock(mutex); @@ -182,6 +230,12 @@ namespace fabomatic return queries.size(); } + /** + * @brief Main loop for the MQTT broker. + * + * This function checks if the broker is running. If not, it starts the broker. + * If the broker is running, it updates the broker state and processes pending queries. + */ void MockMQTTBroker::mainLoop() { // Check if the server is online @@ -195,4 +249,4 @@ namespace fabomatic processQueries(); } } -} // namespace fabomatic \ No newline at end of file +} // namespace fabomatic diff --git a/test/test_logic/test_logic.cpp b/test/test_logic/test_logic.cpp index e0bdff04..961d5e78 100644 --- a/test/test_logic/test_logic.cpp +++ b/test/test_logic/test_logic.cpp @@ -11,7 +11,7 @@ #include "RFIDWrapper.hpp" #include "SavedConfig.hpp" #include "conf.hpp" -#include "mock/MockLcdLibrary.hpp" + #include "mock/MockMQTTBroker.hpp" #include "mock/MockMrfc522.hpp" #include "test_common.h" @@ -64,8 +64,6 @@ namespace fabomatic::tests TEST_ASSERT_TRUE_MESSAGE(config.hasRelay() || fabomatic::pins.relay.ch1_pin == fabomatic::NO_PIN, "Machine relay not configured"); TEST_ASSERT_TRUE_MESSAGE(config.hasMqttSwitch() || fabomatic::conf::default_config::mqtt_switch_topic.empty(), "Machine MQTT switch not configured"); - TEST_ASSERT_TRUE_MESSAGE(config.mqtt_config.topic == fabomatic::conf::default_config::mqtt_switch_topic, "Machine MQTT topic not configured"); - TEST_ASSERT_TRUE_MESSAGE(config.relay_config.pin == fabomatic::pins.relay.ch1_pin, "Machine relay pin not configured"); TEST_ASSERT_TRUE_MESSAGE(config.machine_id.id == fabomatic::conf::default_config::machine_id.id, "Machine ID not configured"); } From 9b6894325f1c053edbf660c51a23c0dab6eba4c3 Mon Sep 17 00:00:00 2001 From: Pascal Brunot Date: Sat, 25 May 2024 09:31:24 +0200 Subject: [PATCH 6/6] Fixed format strings --- include/FabBackend.hpp | 2 +- src/BoardLogic.cpp | 2 +- src/Led.cpp | 2 +- src/Tasks.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/FabBackend.hpp b/include/FabBackend.hpp index 9a6d55fd..fa8e94e1 100644 --- a/include/FabBackend.hpp +++ b/include/FabBackend.hpp @@ -41,7 +41,7 @@ namespace fabomatic bool online{false}; bool answer_pending{false}; - int32_t channel{-1}; + int16_t channel{-1}; auto messageReceived(String &topic, String &payload) -> void; diff --git a/src/BoardLogic.cpp b/src/BoardLogic.cpp index ab07d496..399d794f 100644 --- a/src/BoardLogic.cpp +++ b/src/BoardLogic.cpp @@ -175,7 +175,7 @@ namespace fabomatic const auto response = auth.tryLogin(uid, server); if (!response.has_value() || response.value().user_level == FabUser::UserLevel::Unknown) { - ESP_LOGI(TAG, "Failed login for %s", card::uid_str(uid)); + ESP_LOGI(TAG, "Failed login for %s", card::uid_str(uid).c_str()); changeStatus(Status::LoginDenied); beepFail(); return false; diff --git a/src/Led.cpp b/src/Led.cpp index c5a9a878..1a25ab42 100644 --- a/src/Led.cpp +++ b/src/Led.cpp @@ -10,7 +10,7 @@ namespace fabomatic return; } - ESP_LOGD(TAG, "Initializing LED (pin %d, is_neopixel %d, flags %u)", + ESP_LOGD(TAG, "Initializing LED (pin %d, is_neopixel %d, flags %lu)", pins.led.pin, pins.led.is_neopixel, pins.led.neopixel_config); if constexpr (pins.led.is_neopixel) diff --git a/src/Tasks.cpp b/src/Tasks.cpp index 1aa727fd..10937fba 100644 --- a/src/Tasks.cpp +++ b/src/Tasks.cpp @@ -50,7 +50,7 @@ namespace fabomatic::Tasks avg_delay /= nb_runs; } - ESP_LOGD(TAG, "Scheduler::execute complete: %d tasks total, %lu runs, avg delay/run: %llu ms\r\n", tasks.size(), nb_runs, avg_delay.count()); + ESP_LOGD(TAG, "Scheduler::execute complete: %d tasks total, %d runs, avg delay/run: %llu ms\r\n", tasks.size(), nb_runs, avg_delay.count()); for (const auto &task : tasks) {