// Пример за виртуален мултитаскинг
// Определение за библиотеки
#include <WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/****************************************************************************/
/* Дефиниране на изводите */
/****************************************************************************/
const uint8_t red_led = 12; // за визуализиране на състоянието на
// нагревателя (изключено състояние)
const uint8_t green_led = 14; // за визуализиране на състоянието на
// нагревателя (включено състояние)
const uint8_t button_pin = 13; // за прочитане на данни от сензора
const uint8_t slider_pin = 15;
const uint8_t servo_pin = 4;
/****************************************************************************/
/* WiFi точка за достъп */
/****************************************************************************/
#define WLAN_SSID "Wokwi-GUEST"
#define WLAN_PASS ""
/****************************************************************************/
/* Настройка на Adafruit.io */
/****************************************************************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // използвайте 8883 за SSL
// Това е мястото, където трябва да поставите вашите идентификатори.
#define AIO_USERNAME "s_dimitrova1707"
#define AIO_KEY "aio_vUmn92n63opj0hHGvPLrbt82Efxa"
#define AIO_BUTTON_PUBLISH AIO_USERNAME "/feeds/button_publish"
#define AIO_BUTTON_SUBSCRIBE AIO_USERNAME "/feeds/button_subscribe"
#define AIO_FEED_SLIDER AIO_USERNAME "/feeds/slider"
#define AIO_FEED_SERVO AIO_USERNAME "/feeds/servo"
// Обърнете внимание, че пътищата на MQTT за AIO следват формата:
// <username>/feeds/<feedname>
// <username>/f/<feedname>
/****************************************************************************/
/* Глобално състояние (не е необходимо да го променяте!) */
/****************************************************************************/
// Създаване на клас ESP8266 WiFiClient за свързване с MQTT сървъра.
WiFiClient client;
// Също може да използвате SSL клиент:
// WiFiClientSecure client;
// Настройте класа на MQTT клиента, като подадете данните за WiFi клиента и MQTT сървъра и данните за вход.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
/****************************************************************************/
/* Adafruit Feeds */
/****************************************************************************/
// Настройка на канал, наречен 'feed_sensor', за публикуване на промени.
Adafruit_MQTT_Publish button_publish = Adafruit_MQTT_Publish(&mqtt, AIO_BUTTON_PUBLISH);
// Настройка на канал, наречен 'feed_heater', за абониране за промени.
Adafruit_MQTT_Subscribe button_subscribe = Adafruit_MQTT_Subscribe(&mqtt, AIO_BUTTON_SUBSCRIBE);
Adafruit_MQTT_Publish slider = Adafruit_MQTT_Publish(&mqtt, AIO_FEED_SLIDER);
Adafruit_MQTT_Subscribe servo = Adafruit_MQTT_Subscribe(&mqtt, AIO_FEED_SERVO);
/****************************************************************************/
/* Код на скицата */
/****************************************************************************/
// Дефиниране на прототипи на функции
void mqtt_publish();
void mqtt_subscribe();
void wifi_connect();
boolean MQTT_connect();
void setup() {
Serial.begin(115200);
delay(10);
pinMode(red_led, OUTPUT);
pinMode(green_led, OUTPUT);
pinMode(servo_pin, OUTPUT);
pinMode(button_pin, INPUT);
pinMode(slider_pin, INPUT);
Serial.println("Adafruit MQTT demo.");
wifi_connect(); // Свързване към точка за достъп WiFi.
// Настройка на абонамент за MQTT за състояние на нагревател.
mqtt.subscribe(&button_subscribe);
mqtt.subscribe(&servo);
// Създаване на виртуална задача за канал „sensor“
xTaskCreate(
sensor_publish, // Указател към функция (име на функция).
"Sensor_Publish", // Име на задачата
4096, // Размер на заделения стек на задачата.
NULL, // Допълнителни параметри на задачата.
1, // Приоритет на задача.
NULL // Задаване на "task handler".
);
// Създаване на виртуална задача за канал „heater“
xTaskCreate(
heater_subscribe,
"Heater_Subscribe",
4096,
NULL,
1,
NULL
);
}
void loop() {
while (true) {
vTaskDelay(20);
delay(10);
}
}
void sensor_publish(void * pvParameters) {
while (true) {
// Четене на данни, пристигащи от сензор sensor_pin
uint8_t i = digitalRead(button_pin);
// const char* val = i ? "ON" : "OFF";
// Проверка на MQTT връзка
if (!MQTT_connect()) {
Serial.println("Грешка при свързване към MQTT.");
}
// Публикуване на данни от сензор в канал “sensor” и
// връщане на резултата (успех/неуспех)
if (!button_publish.publish(i)) {
Serial.println("Грешка при публикуване на данни.");
}
delay(3000);
}
vTaskDelete(NULL);
}
void heater_subscribe(void * pvParameters) {
Adafruit_MQTT_Subscribe *subscription;
while (true) {
// Подцикъл, който изчаква входящи абонаментни пакети
while ((subscription = mqtt.readSubscription(2000))) {
// Четене на данни, пристигащ от канал "heater"
if (subscription == &button_subscribe) {
const char* button_state = (char*) button_subscribe.lastread;
Serial.print("On-Off бутон: ");
Serial.println(button_state);
if (strcmp(button_state, "ON") == 0) {
digitalWrite(green_led, HIGH);
digitalWrite(red_led, LOW);
}
if (strcmp(button_state, "OFF") == 0) {
digitalWrite(green_led, LOW);
digitalWrite(red_led, HIGH);
}
}
if (subscription == &servo) {
uint16_t sliderval = atoi((char*) servo.lastread);
Serial.print("Нагревател: ");
Serial.println(sliderval);
analogWrite(servo_pin, sliderval);
}
}
}
vTaskDelete(NULL);
}
// Функция за свързване към Wi-Fi.
void wifi_connect() {
Serial.print("Свързване към ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi свързан");
Serial.println("IP адрес: ");
Serial.println(WiFi.localIP());
}
// Функция за свързване и повторно свързване, ако е необходимо, с MQTT.
boolean MQTT_connect() {
// Спрете, ако вече сте свързани.
if (mqtt.connected()) {
return true;
}
Serial.print("Свързване с MQTT... ");
int8_t ret;
uint8_t retries = 3;
// При успешно свързване, функцията mqtt.connect() ще върне 0.
// В противен случай, тя ще върне номера на грешката.
while ((ret = mqtt.connect()) != 0) {
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Повторен опит за свързване към MQTT след 5 секунди...");
mqtt.disconnect();
delay(5000);
retries--;
if (retries == 0) {
return false;
}
}
Serial.println("MQTT свързан!");
return true;
}