#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 = 34;
const uint8_t pwm_led_pin = 2;
/****************************************************************************/
/*                           WiFi точка за достъп                           */
/****************************************************************************/
#define WLAN_SSID "Wokwi-GUEST"
#define WLAN_PASS ""
/****************************************************************************/
/*                         Настройка на Adafruit.io                         */
/****************************************************************************/
#define AIO_SERVER		"io.adafruit.com"
#define AIO_SERVERPORT  1883
#define AIO_USERNAME	"mitko17"
#define AIO_KEY			"aio_NyFP44PdmKO0wTFg74Vtdb6Zwnd8"
#define AIO_BUTTON_PUBLISH		AIO_USERNAME "/feeds/button_publish"
#define AIO_BUTTON_SUBSCRIBE	AIO_USERNAME "/feeds/button_subscribe"
#define AIO_SLIDER_PUBLISH		AIO_USERNAME "/feeds/slider_publish"
#define AIO_SLIDER_SUBSCRIBE	AIO_USERNAME "/feeds/slider_subscribe"
/****************************************************************************/
/*                            Глобално състояние                            */
/****************************************************************************/
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
/****************************************************************************/
/*                              Adafruit Feeds                              */
/****************************************************************************/
Adafruit_MQTT_Publish button_publish = Adafruit_MQTT_Publish(&mqtt, AIO_BUTTON_PUBLISH);
Adafruit_MQTT_Subscribe button_subscribe = Adafruit_MQTT_Subscribe(&mqtt, AIO_BUTTON_SUBSCRIBE);
Adafruit_MQTT_Publish slider_publish = Adafruit_MQTT_Publish(&mqtt, AIO_SLIDER_PUBLISH);
Adafruit_MQTT_Subscribe slider_subscribe = Adafruit_MQTT_Subscribe(&mqtt, AIO_SLIDER_SUBSCRIBE);
/****************************************************************************/
/*                              Код на скицата                              */
/****************************************************************************/
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(pwm_led_pin, OUTPUT);
	pinMode(button_pin, INPUT);
	pinMode(slider_pin, INPUT);
	Serial.println("Adafruit MQTT demo.");
	wifi_connect();
	mqtt.subscribe(&button_subscribe);
	mqtt.subscribe(&slider_subscribe);
	xTaskCreate(
		publish,
		"Publish",
		4096,
		NULL,
		1,
		NULL
	);
	xTaskCreate(
		subscribe,
		"Subscribe",
		4096,
		NULL,
		1,
		NULL
	);
}
void loop() {
	for (;;) {
		vTaskDelay(20);
		delay(10);
	}
}
void publish(void * pvParameters) {
	for (;;) {
		uint8_t button_val = digitalRead(button_pin);
		uint16_t slider_val = analogRead(slider_pin);
		
		if (!MQTT_connect()) {
			Serial.println("Грешка при свързване към MQTT.");
		}
		if (!button_publish.publish(button_val))
			Serial.println("Грешка при публикуване на данни за бутон.");
		if (!slider_publish.publish(slider_val)) {
			Serial.println("Грешка при публикуване на данни за слайдер.");
		}
		delay(3000);
	}
	vTaskDelete(NULL);
}
void subscribe(void * pvParameters) {
	Adafruit_MQTT_Subscribe *subscription;
	for (;;) {
		while ((subscription = mqtt.readSubscription(2000))) {
			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 == &slider_subscribe) {
				uint16_t slider_val = atoi((char*) slider_subscribe.lastread);
				Serial.print("Нагревател: ");
				Serial.println(slider_val);
				uint8_t led_val = (slider_val * 255) / 4095;
				analogWrite(pwm_led_pin, slider_val);
			}
		}
	}
	vTaskDelete(NULL);
}
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());
}
boolean MQTT_connect() {
	if (mqtt.connected()) {
		return true;
	}
	Serial.print("Свързване с MQTT... ");
	int8_t ret;
	uint8_t retries = 3;
	while ((ret = mqtt.connect()) != 0) {
		Serial.println(mqtt.connectErrorString(ret));
		Serial.println("Повторен опит за свързване към MQTT след 5 секунди...");
		mqtt.disconnect();
		delay(5000);
		if (--retries == 0) {
			return false;
		}
	}
	Serial.println("MQTT свързан!");
	return true;
}