From 8b93e08e15c627d79a26b157e63246ff99004f7e Mon Sep 17 00:00:00 2001 From: Julien Lazarewicz Date: Wed, 21 May 2025 01:37:23 +0200 Subject: [PATCH] Update to be simplier --- .gitignore | 5 + include/config.h | 5 +- platformio.ini | 2 +- src/main.cpp | 273 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/include/config.h b/include/config.h index 51d6a01..95c70b1 100644 --- a/include/config.h +++ b/include/config.h @@ -34,16 +34,17 @@ constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U; #define SERIAL_DEBUG true // Enable MQTT RPC debug -#define MQTT_RPC_DEBUG true +#define MQTT_RPC_DEBUG false // Enable Thingsboard library debug -#define THINGSBOARD_ENABLE_DEBUG true +#define THINGSBOARD_ENABLE_DEBUG false // WIFI parameters constexpr char WIFI_SSID[] = "thingsboard"; constexpr char WIFI_PASSWORD[] = "thingsboard"; // Module actionneur Thingsboard token access +// Doit être modifié suivant binome constexpr char TOKEN[] = "1voazulw2mqr9avkdonw"; // Thingsboard server IP address diff --git a/platformio.ini b/platformio.ini index ff01a11..3f56db2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,5 +16,5 @@ lib_deps = adafruit/Adafruit NeoPixel@^1.12.5 thingsboard/ThingsBoard@^0.15.0 -; Need to be updated +; Need to be updated according to your OS and hardware configuration upload_port = /dev/cu.usbserial-59100221861 diff --git a/src/main.cpp b/src/main.cpp index 309b884..4ce8db4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,16 +9,6 @@ #include #include -// then these pins will be defined for us -#if defined(ADAFRUIT_FEATHER_ESP32_V2) or defined(ARDUINO_ADAFRUIT_ITSYBITSY_ESP32) -#define PIN_NEOPIXEL 0 -#define NEOPIXEL_I2C_POWER 2 -#endif - -#if defined(PIN_NEOPIXEL) -Adafruit_NeoPixel pixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800); -#endif - // Initialize underlying client, used to establish a connection #if ENCRYPTED WiFiClientSecure espClient; @@ -29,6 +19,89 @@ WiFiClient espClient; // Initalize the Mqtt client instance Arduino_MQTT_Client mqttClient(espClient); +// Actuator status global variables +bool VMC_STATUS; // Status VMC +bool LIGHT_STATUS; // Status light +bool HEATER_STATUS; // Status heater +bool AC_STATUS; // Status A/C + +/// @brief Initalizes WiFi connection, +// will endlessly delay until a connection has been successfully established +void InitWiFi(); + +/// @brief Reconnects the WiFi uses InitWiFi if the connection has been removed +/// @return Returns true as soon as a connection has been established again +bool reconnect(); + +/// @brief Update callback that will be called as soon as one of the provided shared attributes +/// changes value, if none are provided we subscribe to any shared attribute change instead +/// @param data Data containing the shared attributes that were changed and their current value +void processSharedAttributeUpdate(const JsonObjectConst& data); + +/// @brief Process Light change RPC +void processSwitchLightChange(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process VMC change RPC +void processSwitchVmcChange(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process heater change RPC +void processSwitchHeaterChange(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process AC change RPC +void processSwitchACChange(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process light status inquiry RPC +void getSwitchLight(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process VMC status inquiry RPC +void getSwitchVmc(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process heater status inquiry RPC +void getSwitchHeater(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Process AC status inquiry RPC +void getSwitchAC(const JsonVariantConst& data, JsonDocument& response); + +/// @brief Set light pin value and publish it to Thingsboard server +/// @return Returns true if pin is HIGH, false if LOW +bool setLight(bool status); + +/// @brief Set VMC pin value and publish it to Thingsboard server +/// @return Returns true if pin is HIGH, false if LOW +bool setVMC(bool status); + +/// @brief Set heater pin value and publish it to Thingsboard server +/// @return Returns true if pin is HIGH, false if LOW +bool setHeater(bool status); + +/// @brief Set AC pin value and publish it to Thingsboard server +/// @return Returns true if pin is HIGH, false if LOW +bool setAC(bool status); + +constexpr const char CONNECTING_MSG[] = "Connecting to: (%s) with token (%s)\n"; +constexpr const char LIGHT_RELAY_KEY[] = "LIGHT_RELAY"; +constexpr const char VMC_RELAY_KEY[] = "VMC_RELAY"; +constexpr const char HEATER_RELAY_KEY[] = "HEATER_RELAY"; +constexpr const char AC_RELAY_KEY[] = "AC_RELAY"; +constexpr const char VERSION_KEY[] = "VERSION"; + +constexpr const char RPC_JSON_METHOD[] = "example_json"; +constexpr const char RPC_GET_LIGHT_SWITCH_METHOD[] = "get_light_switch"; +constexpr const char RPC_SET_LIGHT_SWITCH_METHOD[] = "set_light_switch"; +constexpr const char RPC_LIGHT_SWITCH_KEY[] = "LIGHT_RELAY"; + +constexpr const char RPC_GET_VMC_SWITCH_METHOD[] = "get_vmc_switch"; +constexpr const char RPC_SET_VMC_SWITCH_METHOD[] = "set_vmc_switch"; +constexpr const char RPC_VMC_SWITCH_KEY[] = "VMC_RELAY"; + +constexpr const char RPC_GET_HEATER_SWITCH_METHOD[] = "get_heater_switch"; +constexpr const char RPC_SET_HEATER_SWITCH_METHOD[] = "set_heater_switch"; +constexpr const char RPC_HEATER_SWITCH_KEY[] = "HEATER_RELAY"; + +constexpr const char RPC_GET_AC_SWITCH_METHOD[] = "get_ac_switch"; +constexpr const char RPC_SET_AC_SWITCH_METHOD[] = "set_ac_switch"; +constexpr const char RPC_AC_SWITCH_KEY[] = "AC_RELAY"; + // Maximum size packets will ever be sent or received by the underlying MQTT client, // if the size is to small messages might not be sent or received messages will be discarded constexpr uint16_t MAX_MESSAGE_SEND_SIZE = 128U; @@ -53,10 +126,10 @@ ThingsBoard tb( mqttClient, MAX_MESSAGE_RECEIVE_SIZE, MAX_MESSAGE_SEND_SIZE, Default_Max_Stack_Size, apis); // Statuses for subscribing to shared attributes -bool subscribed = false; +bool RPC_subscribed = false; -// Send once -bool once = true; +// Initial client attributes sent +bool init_att_published = false; void setup() { @@ -78,10 +151,184 @@ void setup() digitalWrite(HEATER_PIN, LOW); digitalWrite(AC_PIN, LOW); + // Set global variables actuator status as FALSE + // Init Wifi connexion + InitWiFi(); } void loop() { + if (!reconnect()) + { + return; + } + + // Check Thingsboard connection + if (!tb.connected()) + { + // Reconnect to the ThingsBoard server, + // if a connection was disrupted or has not yet been established +#if SERIAL_DEBUG + Serial.printf(CONNECTING_MSG, THINGSBOARD_SERVER, TOKEN); +#endif + if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT)) + { +#if SERIAL_DEBUG + Serial.println("Failed to connect"); +#endif + return; + } + } + + // Send initial values + if (!init_att_published) + { + Serial.println("Sending device type attribute..."); + tb.sendAttributeData(VERSION_KEY, VERSION); + tb.sendAttributeData(LIGHT_RELAY_KEY, LIGHT_STATUS); + // NEED TO COMPLETED + init_att_published = true; + } + + if (!RPC_subscribed) + { + Serial.println("Requesting RPC...."); + + Serial.println("Subscribing for RPC..."); + const RPC_Callback callbacks[MAX_RPC_SUBSCRIPTIONS] = { + { RPC_SET_LIGHT_SWITCH_METHOD, processSwitchLightChange }, + { RPC_SET_VMC_SWITCH_METHOD, processSwitchVmcChange } + // NEED TO BE COMPLETED + }; + + if (!server_rpc.RPC_Subscribe(callbacks + 0U, callbacks + MAX_RPC_SUBSCRIPTIONS)) + { + Serial.println("Failed to subscribe for RPC"); + return; + } + + Serial.println("Subscribe done"); + RPC_subscribed = true; + } + tb.loop(); +} + +/// @brief Initalizes WiFi connection, +// will endlessly delay until a connection has been successfully established +void InitWiFi() +{ +#if SERIAL_DEBUG + Serial.println("Connecting to AP ..."); +#endif + // Attempting to establish a connection to the given WiFi network + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + while (WiFi.status() != WL_CONNECTED) + { + // Delay 500ms until a connection has been successfully established + delay(500); +#if SERIAL_DEBUG + Serial.print("."); +#endif + } +#if SERIAL_DEBUG + Serial.printf("\nConnected to AP : %s\n", WIFI_SSID); +#endif +#if ENCRYPTED + espClient.setCACert(ROOT_CERT); +#endif +} + +/// @brief Reconnects the WiFi uses InitWiFi if the connection has been removed +/// @return Returns true as soon as a connection has been established again +bool reconnect() +{ + // Check to ensure we aren't connected yet + const wl_status_t status = WiFi.status(); + if (status == WL_CONNECTED) + { + return true; + } + + // If we aren't establish a new connection to the given WiFi network + InitWiFi(); + return true; +} + +/// @brief Process VMC change RPC +void processSwitchVmcChange(const JsonVariantConst& data, JsonDocument& response) +{ + bool rcvSwitchStatus; + +#if SERIAL_DEBUG + Serial.println("Received the set vmc switch method"); +#endif + + const int switch_state = data["enabled"]; + + if (switch_state == 0) + { + rcvSwitchStatus = false; + } + if (switch_state == 1) + { + rcvSwitchStatus = true; + } + +#if SERIAL_DEBUG + Serial.print("VMC switch received state: "); + Serial.println(switch_state); +#endif + + response.set(rcvSwitchStatus); + setVMC(rcvSwitchStatus); +} + +/// @brief Process light status inquiry RPC +void getSwitchLight(const JsonVariantConst& data, JsonDocument& response) +{ +#if SERIAL_DEBUG + Serial.println("Received the json RPC method"); +#endif + + // Size of the response document needs to be configured to the size of the innerDoc + 1. + StaticJsonDocument<16> doc; + StaticJsonDocument innerDoc; + if (LIGHT_STATUS) + { + innerDoc = true; + } + else + { + innerDoc = false; + } + response[LIGHT_RELAY_KEY] = innerDoc; +} + +/// @brief Set heater pin value and publish it to Thingsboard server +/// @return Returns true if pin is HIGH, false if LOW +bool setHeater(bool status) +{ +#if SERIAL_DEBUG + Serial.printf("Changing heater status to : %s\n", status ? "true" : "false"); +#endif + digitalWrite(HEATER_PIN, status); + HEATER_STATUS = status; + if (!tb.connected()) + { +// Reconnect to the ThingsBoard server, +// if a connection was disrupted or has not yet been established +#if SERIAL_DEBUG + Serial.printf(CONNECTING_MSG, THINGSBOARD_SERVER, TOKEN); +#endif + if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT)) + { +#if SERIAL_DEBUG + Serial.println("Failed to connect"); +#endif + } + } + tb.sendAttributeData(HEATER_RELAY_KEY, HEATER_STATUS); + return status; } \ No newline at end of file