/* * *
* _____________________________________
* / __ __ /
* / ___ / / ____ _/ /_ ____ /
* / / _ \/ / / __ `/ __ \/_ / /
* / / __/ /___/ /_/ / /_/ / / /_ /
* / \___/_____/\__,_/_.___/ /___/ /
* /____________________________________/
* ~ Embedded Labz :: eLabz.Net ~
*
* Project: ProjectName
*
* Author: Designed by Andre Santana [eLabz.Net/Santana]
*
* Sketch: Sketch.ino
* [github.com/e-Labz/xxxxxx]
*
* Description: Simple implementation of vsRTOS to
* demostrate library resouces
*
* Version: 00.10
* Release Date: 2023/04/18
*
* License: GPL-3.0-or-later
*
* This is free software, please consider supporting to
* help keep our coffee or beer @ [eLabz.Net/donate] ;-)
*
* This program comes with ABSOLUTELY NO WARRANTY. This is
* free software, and you are welcome to redistribute it
* under certain conditions.
*
* See [www.gnu.org/licenses] for more details.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ------------------ Identify MPU Archeture -------------------- */
#ifdef ESP8266 // check for ESP8266 MCU
#include <ESP8266WiFi.h> // ESP8266 WiFi Library
#define MPU_Arch "ESP8266" // define ESP8266 Arch
#elif defined(ESP32) // check for ESP32 MCU
#include <WiFi.h> // ESP32 WiFi Library
#define MPU_Arch "ESP32" // define ESP32 Arch
#else // if not supported
#error "Supported MCUs ESP8266 or ESP32" // publish error msg
#endif
/* ----------------------- Library Imports ---------------------- */
#include "vsRTOS.h" // vsRTOS Library
#include <PubSubClient.h> // MQTT broker Library
/* ----------------------- Global Variables --------------------- */
#define DevID "ESP32C3-Teste"
#define SerialBaudRate 9600UL
#define failRetries 5
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const uint16_t mqtt_port = 1883;
const char* mqtt_id = DevID;
const char* inTopic = "casa-teste/topic-teste/sub";
const char* outTopic = "casa-teste/topic-teste/pub";
//char* ipAddr[16];
String ipAddr;
String serialData = "";
struct tskFlag { // flag struct:
bool firstBoot; // 1st boot
bool netOn; // network online
bool brokerOn; // broker online
} tskFlag = {true, false, false}; // set initial runlevel
static tsk tskWiFi, tskBroker,tskMQTT,
tskSerialRead, tskSerialData; // task thread identifier
/* -------------------- Initialize Libraries -------------------- */
WiFiClient tcpSocket; // WiFi Client
PubSubClient broker(tcpSocket); // MQTT Broker
/* ----------------------- Setup Function ----------------------- */
void setup() {
Serial.begin(SerialBaudRate); // init uart interface
broker.setServer(mqtt_server, mqtt_port); // define mqtt broker
broker.setCallback(brokerCallback); // set callback function
TSK_INIT ( &tskWiFi ); // network handle
TSK_INIT ( &tskBroker ); // broker handle
TSK_INIT ( &tskMQTT ); // mqttPub handle
TSK_INIT ( &tskSerialRead ); // serialRead handle
TSK_INIT ( &tskSerialData ); // serialData handle
}
/* --------------- Main (Infinite) Loop Function ---------------- */
void loop() {
TSK_RUN ( thWiFi ( &tskWiFi ) ); // thread WiFi Handle
TSK_RUN ( thBroker ( &tskBroker ) );
TSK_RUN ( thMQTTpub ( &tskMQTT, 60 ) ); // task, delay interval
TSK_RUN ( thSerialRead ( &tskSerialRead ) );
TSK_RUN ( thSerialData ( &tskSerialData ) );
}
/* --------------- MQTT Broker Callback Function ---------------- */
void brokerCallback(const char* topic, byte* payload, const unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
/* --------------- Check / Connects to WiFi network ------------- */
TSK_THREAD( thWiFi(struct tsk *tsk) ) {
TSK_BEGIN(tsk);
while(true) {
static unsigned char failCount = 0;
if (WiFi.status() != WL_CONNECTED) {
TSK_FLAG_SET(tskFlag, netOn, false);
TSK_LOGI(DevID, "Conecting to WiFi network...");
WiFi.begin(ssid, password);
TSK_DELAY(tsk, 3000);
if(WiFi.status() == WL_CONNECTED) {
ipAddr = WiFi.localIP().toString();
TSK_LOGI(DevID, "Connected to " + String(ssid));
TSK_FLAG_SET(tskFlag, netOn, true);
failCount = 0;
} else {
failCount++;
TSK_LOGW(DevID, "Fail to connect to WiFi network!");
WiFi.disconnect();
if(failCount > failRetries) {
TSK_LOGE(DevID, "System restart...");
ESP.restart(); // if error persists, restart device
}
TSK_DELAY(tsk, 10000);
}
}
TSK_YIELD(tsk);
}
TSK_END(tsk);
}
/* --------------- Check / Connect to Broker --------------- */
TSK_THREAD( thBroker(struct tsk *tsk) ) {
TSK_BEGIN(tsk);
while(true) {
TSK_WAIT_UNTIL(tsk, TSK_FLAG_GET(tskFlag, netOn)); // wait wifi connection
if (!broker.connected()) {
TSK_LOGI(DevID, "Conecting to MQTT broker...");
if (broker.connect(mqtt_id)) {
TSK_LOGI(DevID, "Connected to broker " + String(mqtt_server));
broker.subscribe(inTopic);
TSK_FLAG_SET(tskFlag, brokerOn, true);
} else {
TSK_LOGW(DevID, "Fail to connect to MQTT broker!");
static unsigned char failCount = 0; failCount++;
TSK_FLAG_SET(tskFlag, brokerOn, false);
if(failCount > failRetries) {
broker.disconnect();
WiFi.disconnect();
TSK_FLAG_SET(tskFlag, netOn, false);
failCount = 0;
}
TSK_DELAY(tsk, 30000)
}
}
broker.loop();
TSK_YIELD(tsk);
}
TSK_END(tsk);
}
/* ----------------- MQTT Broker Publish Tread ----------------- */
TSK_THREAD( thMQTTpub(struct tsk *tsk, int interval) ) {
TSK_BEGIN(tsk);
while(true) {
TSK_WAIT_UNTIL(tsk, TSK_FLAG_GET(tskFlag, brokerOn)); // wait broker connection
if(TSK_FLAG_GET(tskFlag, firstBoot)) { // check for boot flag
String bootLog = "DevID: " // booLog payload
+ String(DevID)
+ " IP Addr: "
+ ipAddr;
TSK_LOGI(DevID, bootLog); // print payload to serial
broker.publish(outTopic, bootLog.c_str()); // initial MQTT pub
TSK_FLAG_SET(tskFlag, firstBoot, false);
}
TSK_DELAY(tsk, interval * 1000);
int RSSI = WiFi.RSSI();
char payload[25];
sprintf(payload, "Signal Strength: %d dBm", RSSI);
TSK_LOGI(DevID, payload);
broker.publish(outTopic, payload);
//TSK_YIELD(tsk);
}
TSK_END(tsk);
}
/* --------------------- Serial Read Thread -------------------- */
TSK_THREAD( thSerialRead(struct tsk *tsk) ) {
TSK_BEGIN(tsk);
while (true) {
TSK_WAIT_UNTIL(tsk, Serial.available() > 0);
serialData = Serial.readStringUntil('\n');
TSK_LOGI(DevID, "Task 4 run: " + String(millis()));
TSK_YIELD(tsk);
}
TSK_END(tsk);
}
/* --------------------- Serial Data Thread -------------------- */
TSK_THREAD( thSerialData(struct tsk *tsk) ) {
TSK_BEGIN(tsk);
while (TSK_FLAG_GET(tskFlag, brokerOn)) {
TSK_WAIT_UNTIL(tsk, serialData.length() > 0);
if (serialData == "broker_off") { // simulate broker down
broker.disconnect();
serialData = "";
} else if (serialData == "wifi_off") { // simulate wifi down
WiFi.disconnect();
serialData = "";
} else {
TSK_LOGI(DevID, "Serial Data: " + serialData);
broker.publish(outTopic, serialData.c_str());
serialData = "";
}
}
TSK_END(tsk);
}
/* * *
* This is free software, please consider supporting to
* help keep our coffee or beer @ [eLabz.Net/donate] ;-)
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */