no message
This commit is contained in:
@@ -39,23 +39,22 @@ constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;
|
|||||||
// Enable Thingsboard library debug
|
// Enable Thingsboard library debug
|
||||||
#define THINGSBOARD_ENABLE_DEBUG false
|
#define THINGSBOARD_ENABLE_DEBUG false
|
||||||
|
|
||||||
// WIFI parameters
|
|
||||||
constexpr char WIFI_SSID[] = "thingsboard";
|
constexpr char WIFI_SSID[] = "thingsboard";
|
||||||
constexpr char WIFI_PASSWORD[] = "thingsboard";
|
constexpr char WIFI_PASSWORD[] = "thingsboard";
|
||||||
|
|
||||||
// Module actionneur Thingsboard token access
|
// Module actionneur Thingsboard token access
|
||||||
// Doit être modifié suivant binome
|
// Doit être modifié suivant binome
|
||||||
constexpr char TOKEN[] = "1voazulw2mqr9avkdonw";
|
constexpr char device_id[] = "LAZ";
|
||||||
|
|
||||||
// Thingsboard server IP address
|
// Thingsboard server IP address
|
||||||
constexpr char THINGSBOARD_SERVER[] = "10.42.0.1";
|
constexpr char MQTT_SERVER[] = "10.42.0.2";
|
||||||
|
|
||||||
// MQTT port used to communicate with the server, 1883 is the default unencrypted MQTT port,
|
// MQTT port used to communicate with the server, 1883 is the default unencrypted MQTT port,
|
||||||
// whereas 8883 would be the default encrypted SSL MQTT port
|
// whereas 8883 would be the default encrypted SSL MQTT port
|
||||||
#if ENCRYPTED
|
#if ENCRYPTED
|
||||||
constexpr uint16_t THINGSBOARD_PORT = 8883U;
|
constexpr uint16_t THINGSBOARD_PORT = 8883U;
|
||||||
#else
|
#else
|
||||||
constexpr uint16_t THINGSBOARD_PORT = 1883U;
|
constexpr uint16_t THINGSBOARD_PORT = 1884U;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENCRYPTED
|
#if ENCRYPTED
|
||||||
|
|||||||
@@ -14,7 +14,5 @@ board = adafruit_feather_esp32_v2
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/Adafruit NeoPixel@^1.12.5
|
adafruit/Adafruit NeoPixel@^1.12.5
|
||||||
thingsboard/ThingsBoard@^0.15.0
|
bblanchon/ArduinoJson@^7.2.2
|
||||||
|
knolleary/PubSubClient@^2.8
|
||||||
; Need to be updated according to your OS and hardware configuration
|
|
||||||
upload_port = /dev/cu.usbserial-59100221861
|
|
||||||
|
|||||||
507
src/main.cpp
507
src/main.cpp
@@ -1,334 +1,293 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WiFiClientSecure.h>
|
|
||||||
#include <Adafruit_NeoPixel.h>
|
|
||||||
|
|
||||||
#include <Arduino_MQTT_Client.h>
|
|
||||||
#include <Server_Side_RPC.h>
|
|
||||||
#include <ThingsBoard.h>
|
|
||||||
|
|
||||||
// Initialize underlying client, used to establish a connection
|
|
||||||
#if ENCRYPTED
|
#if ENCRYPTED
|
||||||
WiFiClientSecure espClient;
|
#include <WiFiClientSecure.h>
|
||||||
#else
|
#else
|
||||||
WiFiClient espClient;
|
#include <WiFiClient.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
// Initalize the Mqtt client instance
|
// -----------------------------------------------------------------------------
|
||||||
Arduino_MQTT_Client mqttClient(espClient);
|
// Notes:
|
||||||
|
// - device_id from config.h is used as the device_id. Nothing is hardcoded.
|
||||||
|
// - The actuator publishes its real state on:
|
||||||
|
// imt_test/actuator/<device_id>/state
|
||||||
|
// - The actuator listens for commands on:
|
||||||
|
// imt_test/actuator/<device_id>/set
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Actuator status global variables
|
namespace
|
||||||
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;
|
|
||||||
constexpr uint16_t MAX_MESSAGE_RECEIVE_SIZE = 128U;
|
|
||||||
constexpr uint8_t MAX_RPC_SUBSCRIPTIONS = 8U;
|
|
||||||
constexpr uint8_t MAX_RPC_RESPONSE = 16U;
|
|
||||||
constexpr uint8_t MAX_RPC_REQUEST = 10U;
|
|
||||||
constexpr uint64_t REQUEST_TIMEOUT_MICROSECONDS = 5000U * 1000U;
|
|
||||||
|
|
||||||
// Maximum amount of attributs we can request or subscribe, has to be set both in the ThingsBoard
|
|
||||||
// template list and Attribute_Request_Callback template list and should be the same as the amount
|
|
||||||
// of variables in the passed array. If it is less not all variables will be requested or subscribed
|
|
||||||
constexpr size_t MAX_ATTRIBUTES = 3U;
|
|
||||||
|
|
||||||
// Initialize used apis
|
|
||||||
Server_Side_RPC<MAX_RPC_SUBSCRIPTIONS, MAX_RPC_RESPONSE> server_rpc;
|
|
||||||
const std::array<IAPI_Implementation*, 1U> apis
|
|
||||||
= { &server_rpc /*, &client_rpc , &shared_update */ };
|
|
||||||
|
|
||||||
// Initialize ThingsBoard instance with the maximum needed buffer size
|
|
||||||
ThingsBoard tb(
|
|
||||||
mqttClient, MAX_MESSAGE_RECEIVE_SIZE, MAX_MESSAGE_SEND_SIZE, Default_Max_Stack_Size, apis);
|
|
||||||
|
|
||||||
// Statuses for subscribing to shared attributes
|
|
||||||
bool RPC_subscribed = false;
|
|
||||||
|
|
||||||
// Initial client attributes sent
|
|
||||||
bool init_att_published = false;
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
{
|
||||||
// Initalize serial connection for debugging
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.begin(SERIAL_DEBUG_BAUD);
|
|
||||||
delay(200);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set VMC, LIGHT, HEATER & AC pin mode as OUTPUT
|
constexpr uint32_t WIFI_CONNECT_TIMEOUT_MS = 15000U;
|
||||||
|
constexpr uint32_t MQTT_CONNECT_TIMEOUT_MS = 10000U;
|
||||||
|
constexpr uint32_t MQTT_RECONNECT_DELAY_MS = 1000U;
|
||||||
|
|
||||||
|
bool g_vmcState = false;
|
||||||
|
bool g_lightState = false;
|
||||||
|
bool g_heaterState = false;
|
||||||
|
bool g_acState = false;
|
||||||
|
|
||||||
|
String stateTopic;
|
||||||
|
String setTopic;
|
||||||
|
|
||||||
|
#if ENCRYPTED
|
||||||
|
WiFiClientSecure netClient;
|
||||||
|
#else
|
||||||
|
WiFiClient netClient;
|
||||||
|
#endif
|
||||||
|
PubSubClient mqttClient(netClient);
|
||||||
|
|
||||||
|
void initOutputs()
|
||||||
|
{
|
||||||
pinMode(VMC_PIN, OUTPUT);
|
pinMode(VMC_PIN, OUTPUT);
|
||||||
pinMode(LIGHT_PIN, OUTPUT);
|
pinMode(LIGHT_PIN, OUTPUT);
|
||||||
pinMode(HEATER_PIN, OUTPUT);
|
pinMode(HEATER_PIN, OUTPUT);
|
||||||
pinMode(AC_PIN, OUTPUT);
|
pinMode(AC_PIN, OUTPUT);
|
||||||
|
|
||||||
// Set initial value LOW for VMC, LIGHT, HEATER & AC pin
|
|
||||||
digitalWrite(VMC_PIN, LOW);
|
digitalWrite(VMC_PIN, LOW);
|
||||||
digitalWrite(LIGHT_PIN, LOW);
|
digitalWrite(LIGHT_PIN, LOW);
|
||||||
digitalWrite(HEATER_PIN, LOW);
|
digitalWrite(HEATER_PIN, LOW);
|
||||||
digitalWrite(AC_PIN, LOW);
|
digitalWrite(AC_PIN, LOW);
|
||||||
|
|
||||||
// Set global variables actuator status as FALSE
|
g_vmcState = false;
|
||||||
|
g_lightState = false;
|
||||||
// Init Wifi connexion
|
g_heaterState = false;
|
||||||
InitWiFi();
|
g_acState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
bool setVmc(const bool status)
|
||||||
{
|
{
|
||||||
if (!reconnect())
|
digitalWrite(VMC_PIN, status ? HIGH : LOW);
|
||||||
|
g_vmcState = status;
|
||||||
|
return g_vmcState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setLight(const bool status)
|
||||||
|
{
|
||||||
|
digitalWrite(LIGHT_PIN, status ? HIGH : LOW);
|
||||||
|
g_lightState = status;
|
||||||
|
return g_lightState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setHeater(const bool status)
|
||||||
|
{
|
||||||
|
digitalWrite(HEATER_PIN, status ? HIGH : LOW);
|
||||||
|
g_heaterState = status;
|
||||||
|
return g_heaterState;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setAc(const bool status)
|
||||||
|
{
|
||||||
|
digitalWrite(AC_PIN, status ? HIGH : LOW);
|
||||||
|
g_acState = status;
|
||||||
|
return g_acState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buildTopics()
|
||||||
|
{
|
||||||
|
stateTopic = String("imt_test/actuator/") + device_id + "/state";
|
||||||
|
setTopic = String("imt_test/actuator/") + device_id + "/set";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool publishState()
|
||||||
|
{
|
||||||
|
StaticJsonDocument<256> doc;
|
||||||
|
doc["device_id"] = device_id;
|
||||||
|
doc["vmc"] = g_vmcState;
|
||||||
|
doc["heating"] = g_heaterState;
|
||||||
|
doc["lighting"] = g_lightState;
|
||||||
|
doc["cooling"] = g_acState;
|
||||||
|
doc["version"] = VERSION;
|
||||||
|
|
||||||
|
char payload[256];
|
||||||
|
const size_t len = serializeJson(doc, payload, sizeof(payload));
|
||||||
|
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.print("Publish state topic: ");
|
||||||
|
Serial.println(stateTopic);
|
||||||
|
Serial.print("Payload: ");
|
||||||
|
Serial.println(payload);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return mqttClient.publish(
|
||||||
|
stateTopic.c_str(), reinterpret_cast<const uint8_t*>(payload), len, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyCommandJson(const JsonDocument& doc)
|
||||||
|
{
|
||||||
|
if (doc.containsKey("vmc"))
|
||||||
{
|
{
|
||||||
|
setVmc(doc["vmc"].as<bool>());
|
||||||
|
}
|
||||||
|
if (doc.containsKey("heating"))
|
||||||
|
{
|
||||||
|
setHeater(doc["heating"].as<bool>());
|
||||||
|
}
|
||||||
|
if (doc.containsKey("lighting"))
|
||||||
|
{
|
||||||
|
setLight(doc["lighting"].as<bool>());
|
||||||
|
}
|
||||||
|
if (doc.containsKey("cooling"))
|
||||||
|
{
|
||||||
|
setAc(doc["cooling"].as<bool>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqttCallback(char* topic, byte* payload, unsigned int length)
|
||||||
|
{
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.print("MQTT rx topic: ");
|
||||||
|
Serial.println(topic);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (String(topic) != setTopic)
|
||||||
|
{
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.println("Ignoring message on unexpected topic");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Thingsboard connection
|
StaticJsonDocument<256> doc;
|
||||||
if (!tb.connected())
|
const auto err = deserializeJson(doc, payload, length);
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
// Reconnect to the ThingsBoard server,
|
|
||||||
// if a connection was disrupted or has not yet been established
|
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.printf(CONNECTING_MSG, THINGSBOARD_SERVER, TOKEN);
|
Serial.print("JSON parse error: ");
|
||||||
|
Serial.println(err.c_str());
|
||||||
#endif
|
#endif
|
||||||
if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT))
|
return;
|
||||||
{
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println("Failed to connect");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send initial values
|
applyCommandJson(doc);
|
||||||
if (!init_att_published)
|
publishState();
|
||||||
{
|
|
||||||
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,
|
bool connectWiFi()
|
||||||
// will endlessly delay until a connection has been successfully established
|
|
||||||
void InitWiFi()
|
|
||||||
{
|
{
|
||||||
#if SERIAL_DEBUG
|
if (WiFi.status() == WL_CONNECTED)
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't establish a new connection to the given WiFi network
|
#if SERIAL_DEBUG
|
||||||
InitWiFi();
|
Serial.print("Connecting to WiFi SSID: ");
|
||||||
|
Serial.println(WIFI_SSID);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||||
|
|
||||||
|
const uint32_t start = millis();
|
||||||
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
|
delay(250);
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.print('.');
|
||||||
|
#endif
|
||||||
|
if ((millis() - start) > WIFI_CONNECT_TIMEOUT_MS)
|
||||||
|
{
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("WiFi connection timeout");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.println();
|
||||||
|
Serial.print("WiFi connected, IP: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Process VMC change RPC
|
bool connectMqtt()
|
||||||
void processSwitchVmcChange(const JsonVariantConst& data, JsonDocument& response)
|
|
||||||
{
|
{
|
||||||
bool rcvSwitchStatus;
|
if (mqttClient.connected())
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println("Received the set vmc switch method");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const int switch_state = data["enabled"];
|
|
||||||
|
|
||||||
if (switch_state == 0)
|
|
||||||
{
|
{
|
||||||
rcvSwitchStatus = false;
|
return true;
|
||||||
}
|
|
||||||
if (switch_state == 1)
|
|
||||||
{
|
|
||||||
rcvSwitchStatus = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
#if ENCRYPTED
|
||||||
Serial.print("VMC switch received state: ");
|
netClient.setCACert(ROOT_CERT);
|
||||||
Serial.println(switch_state);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
response.set(rcvSwitchStatus);
|
mqttClient.setServer(MQTT_SERVER, THINGSBOARD_PORT);
|
||||||
setVMC(rcvSwitchStatus);
|
mqttClient.setCallback(mqttCallback);
|
||||||
}
|
|
||||||
|
const String clientId = String("actuator-") + device_id;
|
||||||
|
const uint32_t start = millis();
|
||||||
|
|
||||||
/// @brief Process light status inquiry RPC
|
|
||||||
void getSwitchLight(const JsonVariantConst& data, JsonDocument& response)
|
|
||||||
{
|
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.println("Received the json RPC method");
|
Serial.print("Connecting to MQTT broker ");
|
||||||
|
Serial.print(MQTT_SERVER);
|
||||||
|
Serial.print(":");
|
||||||
|
Serial.println(THINGSBOARD_PORT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Size of the response document needs to be configured to the size of the innerDoc + 1.
|
while (!mqttClient.connected())
|
||||||
StaticJsonDocument<16> doc;
|
|
||||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> innerDoc;
|
|
||||||
if (LIGHT_STATUS)
|
|
||||||
{
|
{
|
||||||
innerDoc = true;
|
if (mqttClient.connect(clientId.c_str()))
|
||||||
}
|
|
||||||
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
|
#if SERIAL_DEBUG
|
||||||
Serial.println("Failed to connect");
|
Serial.println("MQTT connected");
|
||||||
#endif
|
#endif
|
||||||
|
if (!mqttClient.subscribe(setTopic.c_str()))
|
||||||
|
{
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.println("MQTT subscribe failed");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.print("Subscribed to: ");
|
||||||
|
Serial.println(setTopic);
|
||||||
|
#endif
|
||||||
|
publishState();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((millis() - start) > MQTT_CONNECT_TIMEOUT_MS)
|
||||||
|
{
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.print("MQTT connection timeout, rc=");
|
||||||
|
Serial.println(mqttClient.state());
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.print('.');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
tb.sendAttributeData(HEATER_RELAY_KEY, HEATER_STATUS);
|
|
||||||
return status;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.begin(SERIAL_DEBUG_BAUD);
|
||||||
|
delay(300);
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Actuator firmware startup");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
initOutputs();
|
||||||
|
buildTopics();
|
||||||
|
|
||||||
|
connectWiFi();
|
||||||
|
connectMqtt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user