#include "WiFi.h"
//#include "WiFiClient.h"
//#include "AsyncUDP.h"
#include "ESPmDNS.h"
#include <Ticker.h>
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <PubSubClient.h>
// Настройка экрана
LiquidCrystal_I2C lcd_i2c(0x27, 20, 4); // I2C адрес 0x27
int currentColumnPosition = 0;
int currentRowPosition = 0;
// Определения для клавиатуры
#define ROW_NUM 4
#define COLUMN_NUM 4
char keys[ROW_NUM][COLUMN_NUM] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte pin_rows[ROW_NUM] = {26, 27, 14, 12};
byte pin_column[COLUMN_NUM] = {19, 18, 5, 4};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
// Данные для подключения к WiFi сети
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Попыткок подключения к точке доступа
byte maxConnectionTries = 10;
// Add your MQTT Broker IP address, example:
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* clientID = "clientId2"; // Client ID username+0001
const char* mqtt_topic = "topic_2mp"; // Publish topic
const char* mqtt_topic_send = "topic_back_2mp";
// Setting up WiFi and MQTT client
WiFiClient espClient;
PubSubClient client(espClient);
// Структура для передачи данных
struct Data {
uint8_t num;
unsigned long millis;
IPAddress boardIP;
uint16_t sensor;
};
// Количество плат
//#define NUM_ESPS 4
// Номер микроконтроллера
//const unsigned int NUM = 2;
// Имя главной платы в сети
//const char* master_host = "esp32master";
// Имя этой платы в сети
//const char* slave_host = "esp32slave";
// Массив структур для передачи
//Data data[NUM_ESPS] {0};
//Определяем порт
//const uint16_t port = 49152;
// Cоздаем объект UDP
//AsyncUDP udp;
// Пины и переменные для кнопки и светодиода
const int buttonPin = 15;
volatile unsigned int lastpress;
volatile boolean button = 0;
volatile boolean button_state = 0;
volatile boolean led_flag = 0;
// Настройка работы светодиодов
const int led = 2;
const int ledRPin = 32;
const int ledGPin = 33;
const int ledBPin = 25;
int ledState = LOW;
String input_line = "";
boolean line_ready = 0;
String state = "regular";
String RGBstate = "";
Ticker tickerSetHigh;
Ticker tickerSetLow;
// Определяем callback функцию обработки UDP пакета
// void ParsePacket(AsyncUDPPacket packet) {
// // Преобразуем указатель на данные к указателю на структуру
// const Data* tmp = (Data*)packet.data();
// // Вычисляем размер данных (ожидаем получить размер в один элемент структур)
// const size_t len = packet.length() / sizeof(data[0]);
// // Если указатель на данные не равен нулю и размер данных больше нуля
// if (tmp != nullptr && len > 0) {
// for(size_t i = 0; i < len; i++) {
// if(i != NUM) {
// data[i].num = tmp[i].num;
// data[i].millis = tmp[i].millis;
// data[i].boardIP = tmp[i].boardIP;
// data[i].sensor = tmp[i].sensor;
// }
// }
// }
// }
void SetColor(int red, int green, int blue) {
ledcWrite(0, red);
ledcWrite(1, green);
ledcWrite(2, blue);
}
void SetPin(int pinstate) {
digitalWrite(led, pinstate);
}
int StringToState(String s) {
if(s == "regular") {
return 0;
}
else if(s == "lamp") {
return 1;
}
else if(s == "rgb") {
return 2;
}
else if(s == "red") {
return 21;
}
else if(s == "green") {
return 22;
}
else if(s == "blue") {
return 23;
}
else if(s == "*") {
return 3;
}
else if(s == "#") {
return 4;
}
else {
return -1;
}
}
void IRAM_ATTR handleInterrupt() {
// button = !digitalRead(buttonPin);
// if(button == 1 && button_state == 0 && millis() - lastpress > 100) {
// button_state = 1;
// led_flag = !led_flag;
// if(led_flag == true) {
// SetColor(255, 255, 255);
// }
// else {
// SetColor(0, 0, 0);
// }
// lastpress = millis();
// }
// ChangeLcdStatus();
}
void NextLcdInput() {
if(currentRowPosition >= 4) {
lcd_i2c.clear();
currentColumnPosition = 0;
currentRowPosition = 0;
lcd_i2c.setCursor(currentColumnPosition, currentRowPosition);
}
if(currentColumnPosition >= 20) {
currentColumnPosition %= 20;
currentRowPosition++;
lcd_i2c.setCursor(currentColumnPosition, currentRowPosition); // Переход на новую строку
} else {
lcd_i2c.setCursor(currentColumnPosition, currentRowPosition); // Установка курсора в текущую позицию
currentColumnPosition++;
}
}
void CustomLcdInput(int column, int row, boolean clear) {
currentColumnPosition = column;
currentRowPosition = row;
if(clear) {
lcd_i2c.clear();
}
lcd_i2c.setCursor(currentColumnPosition, currentRowPosition);
}
void ChangeLcdStatus() {
CustomLcdInput(0, 0, true);
switch(StringToState(state)) {
case 0: {
CustomLcdInput(0, 0, true);
if(led_flag) {
lcd_i2c.print("A.Turn off lamp");
}
else {
lcd_i2c.print("A.Turn on lamp");
}
CustomLcdInput(0, 1, false);
lcd_i2c.print("B.Turn on RGB");
CustomLcdInput(0, 2, false);
lcd_i2c.print("Enter A or B ");
CustomLcdInput(0, 3, false);
break;
}
case 1: {
CustomLcdInput(0, 0, true);
led_flag = !led_flag;
if(led_flag == true) {
lcd_i2c.print("Turn on lamp");
SetColor(255, 255, 255);
client.publish(mqtt_topic_send, "ON");
}
else {
lcd_i2c.print("Turn off lamp");
SetColor(0, 0, 0);
client.publish(mqtt_topic_send, "OFF");
}
delay(500);
state = "regular";
ChangeLcdStatus();
break;
}
case 2: {
CustomLcdInput(0, 0, true);
switch (StringToState(RGBstate)) {
case 21:
lcd_i2c.print("Enter red:");
break;
case 22:
lcd_i2c.print("Enter green:");
break;
case 23:
lcd_i2c.print("Enter blue:");
break;
default:
break;
}
delay(1000);
CustomLcdInput(0, 1, false);
break;
}
default: {
break;
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
int red = 0; int green = 0; int blue = 0;
int i = 0;
while((char)payload[i] != ' ') {
red *= 10;
red += (int)payload[i] - (int)'0';
i++;
}
i++;
while((char)payload[i] != ' ') {
green *= 10;
green += (int)payload[i] - (int)'0';
i++;
}
i++;
while(i < length) {
blue *= 10;
blue += (int)payload[i] - (int)'0';
i++;
}
Serial.println(red);
Serial.println(green);
Serial.println(blue);
CustomLcdInput(0, 0, true);
SetColor(red, green, blue);
if(red == 0 && green == 0 && blue == 0) {
led_flag = 0;
lcd_i2c.print("Light-turned off");
}
else {
led_flag = 1;
lcd_i2c.print("Light-turned on ");
}
delay(1000);
ChangeLcdStatus();
// for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
// message += (char)payload[i];
// }
// Serial.println();
// CustomLcdInput(0, 0, false);
// if(message == "ON") {
// SetColor(255, 255, 255);
// Serial.println("ON");
// led_flag = 1;
// lcd_i2c.print("Light-turned on ");
// }
// else if(message == "OFF") {
// SetColor(0, 0, 0);
// Serial.println("OFF");
// led_flag = 0;
// lcd_i2c.print("Light-turned off");
// }
}
void setup() {
Serial.begin(115200);
lcd_i2c.init(); // инициализирование lcd
lcd_i2c.backlight();
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), handleInterrupt, FALLING);
pinMode(led, OUTPUT);
digitalWrite(led, ledState);
tickerSetLow.attach_ms(500, SetPin, 0);
tickerSetHigh.attach_ms(1000, SetPin, 1);
//data[NUM].num = NUM;
CustomLcdInput(0, 0, true);
lcd_i2c.print("Connecting WiFi");
delay(500);
WiFi.begin(ssid, password, 6);
CustomLcdInput(0, 1, false);
while (--maxConnectionTries && WiFi.status() != WL_CONNECTED) {
delay(500);
lcd_i2c.print(".");
}
CustomLcdInput(0, 0, true);
if(WiFi.status() != WL_CONNECTED) {
lcd_i2c.print("Failed,Rebooting");
ESP.restart();
}
else {
lcd_i2c.print("WiFi Connected!");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
delay(500);
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
//Записываем адрес текущей платы в элемент структуры
//data[NUM].boardIP = WiFi.localIP();
// Инициируем mDNS
// if(!MDNS.begin(String(slave_host + NUM).c_str())) {
// Serial.println(data[NUM].boardIP);
// }
// Узнаём IP адрес платы с UDP сервером
//IPAddress server = MDNS.queryHost(master_host);
// Если удалось подключиться по UDP
// if (udp.connect(server, port)) {
// Serial.println("UDP подключён");
// // вызываем callback функцию при получении пакета
// udp.onPacket(ParsePacket);
// }
// CustomLcdInput(0, 1, false);
// lcd_i2c.print("Client connected");
// delay(500);
ledcSetup(0, 5000, 8); // канал 0 для красного
ledcAttachPin(ledRPin, 0);
ledcSetup(1, 5000, 8);
ledcAttachPin(ledGPin, 1);
ledcSetup(2, 5000, 8);
ledcAttachPin(ledBPin, 2);
SetColor(0, 0, 0);
tickerSetLow.detach();
tickerSetHigh.detach();
digitalWrite(led, HIGH);
ChangeLcdStatus();
}
void loop() {
static int red;
static int green;
static int blue;
if (!client.connected()) {
while (!client.connected()) {
if (client.connect(clientID)) {
Serial.println("wow");
client.subscribe(mqtt_topic);
} else {
delay(50);
}
}
}
client.loop();
if(line_ready) {
line_ready = 0;
switch(StringToState(state)) {
case 0: {
if(input_line == "A") {
state = "lamp";
}
else if(input_line == "B") {
state = "rgb";
RGBstate = "red";
}
else {
CustomLcdInput(0, 0, true);
lcd_i2c.print("Wrong input");
delay(2000);
}
break;
}
case 2: {
int number = input_line.toInt();
switch(StringToState(RGBstate)) {
case 21:
red = constrain(number, 0, 255);
RGBstate = "green";
break;
case 22:
green = constrain(number, 0, 255);
RGBstate = "blue";
break;
case 23:
blue = constrain(number, 0, 255);
RGBstate = "";
state = "regular";
SetColor(red, green, blue);
if(red != 0 || green != 0 || blue != 0) {
led_flag = true;
client.publish(mqtt_topic_send, "ON");
}
else {
led_flag = false;
client.publish(mqtt_topic_send, "OFF");
}
break;
default:
break;
}
break;
}
default: {
break;
}
}
input_line = "";
ChangeLcdStatus();
}
button = !digitalRead(buttonPin);
if(button == 1 && button_state == 0 && millis() - lastpress > 100) {
button_state = 1;
led_flag = !led_flag;
if(led_flag == true) {
SetColor(255, 255, 255);
}
else {
SetColor(0, 0, 0);
}
lastpress = millis();
ChangeLcdStatus();
}
//
//button = !digitalRead(buttonPin);
if(button == 0 && button_state == 1) {
button_state = 0;
if(led_flag == 1) {
client.publish(mqtt_topic_send, "ON");
}
else {
client.publish(mqtt_topic_send, "OFF");
}
}
// button = !digitalRead(buttonPin);
// ActionButton();
char key = keypad.getKey();
if (key) {
if (key == '#') {
line_ready = true;
} else if (key == '*') {
input_line = "";
CustomLcdInput(0, 0, true);
lcd_i2c.print("Clear input line");
delay(1000);
ChangeLcdStatus();
} else {
NextLcdInput();
input_line += key;
lcd_i2c.print(key);
delay(200);
}
}
//Serial.println("Ok");
// Текущие millis
//data[NUM].millis = millis();
// Показания датчика(millis для примера)
//data[NUM].sensor = millis();
// Отправляем данные этой платы побайтово
//udp.broadcastTo((uint8_t*)&data[NUM], sizeof(data[0]), port);
//Выводим значения элементов массива в последовательный порт
// for(size_t i = 0; i < NUM_ESPS; i++) {
// Serial.print("IP адрес платы: ");
// Serial.print(data[i].boardIP);
// Serial.print(", порядковый номер: ");
// Serial.print(data[i].num);
// Serial.print(", текущие millis: ");
// Serial.print(data[i].millis);
// Serial.print(", значение датчика: ");
// Serial.print(data[i].sensor);
// Serial.print("; ");
// Serial.println();
// }
//delay(5000);
}