Skip to content

Instantly share code, notes, and snippets.

@kvv69
Created February 8, 2025 08:23
Show Gist options
  • Save kvv69/dd3113a1ed358169b2b93779df60e6a9 to your computer and use it in GitHub Desktop.
Save kvv69/dd3113a1ed358169b2b93779df60e6a9 to your computer and use it in GitHub Desktop.
/*
Режим Wi-Fi: Установлен режим WIFI_AP_STA, чтобы ESP8266 могла быть одновременно точкой доступа и клиентом.
Создание точки доступа: Используется функция WiFi.softAP(AP_SSID, AP_PASSWORD) для создания точки доступа.
Логирование: Добавлены сообщения в Serial Monitor для отладки (SSID, пароль и IP-адрес точки доступа).
Как это работает:
При запуске ESP8266 создает точку доступа с именем ESP8266_AP и паролем 12345678.
Одновременно устройство подключается к указанной Wi-Fi сети.
Вы можете подключиться к точке доступа с любого устройства (например, смартфона или ноутбука) и управлять устройством через Telegram-бота.
*/
#include <ESP8266WiFi.h>
#include <WiFiClientSecureBearSSL.h>
#include <UniversalTelegramBot.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ArduinoJson.h>
// Настройки Wi-Fi и Telegram-бота
const char* ssid = "**-****_****"; // Название сети
const char* password = "********"; // Пароль сети
const String BOTtoken = "********:******************************"; // Токен Telegram бота
const String YOUR_CHAT_ID = "***********"; // Замените на ваш chat_id
// Настройки точки доступа
const char* AP_SSID = "ESP8266_AP"; // Имя точки доступа
const char* AP_PASSWORD = "12345678"; // Пароль точки доступа (минимум 8 символов)
// Массив с ID пользователей
const char* CHAT_IDS[] = {"**********", "**********", "**********"};
const int NUM_CHAT_IDS = sizeof(CHAT_IDS) / sizeof(CHAT_IDS[0]);
// Константы для пинов и настроек
#define LED_PIN D5
#define NUM_LEDS 30
#define ONE_WIRE_BUS D3
#define BUTTON_PIN D6
#define BUTTON2_PIN D7
#define RELAY_PIN D8
#define DEBOUNCE_DELAY 50
// Константы для яркости
#define BRIGHTNESS_25 64
#define BRIGHTNESS_50 128
#define BRIGHTNESS_75 191
#define BRIGHTNESS_100 255
// Объекты для работы с библиотеками
BearSSL::WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Переменные состояния
String lightStatus = "off";
int brightness = BRIGHTNESS_100;
bool auroraMode = false;
bool relayState = false;
bool buttonState = LOW;
bool lastButtonState = LOW;
bool button2State = LOW;
bool lastButton2State = LOW;
unsigned long lastDebounceTime = 0;
unsigned long lastButton2DebounceTime = 0;
unsigned long auroraLastUpdate = 0;
unsigned long auroraInterval = 100;
int botRequestDelay = 500; // Уменьшенный интервал для быстрого ответа
unsigned long lastTimeBotRan = 0;
float currentTemperature = 0.0;
unsigned long lastTemperatureUpdate = 0;
const unsigned long temperatureUpdateInterval = 60000; // 1 минута
// Палитра цветов для эффекта "северное сияние"
uint32_t auroraColors[] = {
strip.Color(100, 50, 150),
strip.Color(120, 60, 160),
strip.Color(140, 70, 170)
};
int auroraColorIndex = 0;
// Функция для проверки авторизации пользователя
bool isAuthorizedUser(const String& chat_id) {
for (int i = 0; i < NUM_CHAT_IDS; i++) {
if (chat_id == CHAT_IDS[i]) {
return true;
}
}
return false;
}
void setup() {
Serial.begin(115200);
// Настройка точки доступа
WiFi.mode(WIFI_AP_STA); // Режим точки доступа и клиента одновременно
WiFi.softAP(AP_SSID, AP_PASSWORD); // Создание точки доступа
Serial.println("Точка доступа запущена");
Serial.print("SSID: ");
Serial.println(AP_SSID);
Serial.print("Пароль: ");
Serial.println(AP_PASSWORD);
Serial.print("IP-адрес точки доступа: ");
Serial.println(WiFi.softAPIP());
// Подключение к Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.print("IP-адрес клиента: ");
Serial.println(WiFi.localIP());
client.setInsecure();
pinMode(BUTTON_PIN, INPUT);
pinMode(BUTTON2_PIN, INPUT);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW); // По умолчанию реле выключено
strip.begin();
strip.show();
sensors.begin();
}
void loop() {
// Проверка подключения к Wi-Fi
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi disconnected. Reconnecting...");
WiFi.begin(ssid, password);
delay(5000); // Подождать 5 секунд перед повторной попыткой
return;
}
// Обработка сообщений
if (millis() - lastTimeBotRan > botRequestDelay) {
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
if (numNewMessages) {
handleBotMessages(numNewMessages);
}
lastTimeBotRan = millis();
}
updateTemperature();
handleButtonPress();
handleButton2Press();
if (auroraMode && millis() - auroraLastUpdate >= auroraInterval) {
auroraLastUpdate = millis();
updateAuroraEffect();
}
}
void handleBotMessages(int numNewMessages) {
Serial.println("New messages: " + String(numNewMessages));
for (int i = 0; i < min(numNewMessages, 3); i++) { // Обрабатываем не более 3 сообщений за раз
String chat_id = String(bot.messages[i].chat_id);
String text = bot.messages[i].text;
Serial.println("Message from: " + chat_id + ", text: " + text);
if (!isAuthorizedUser(chat_id)) {
sendUnauthorizedMessage(chat_id);
continue;
}
if (bot.messages[i].type == "callback_query") {
handleCallbackQuery(chat_id, bot.messages[i].text);
} else if (text == "/start" || text == "меню") {
sendMainMenu(chat_id);
} else if (text == "статус") {
sendStatusMenu(chat_id);
}
}
// Обновляем last_message_received
if (numNewMessages > 0) {
bot.last_message_received = bot.messages[numNewMessages - 1].update_id + 1;
}
}
void sendUnauthorizedMessage(String chat_id) {
String message =
"Вибачте! Мій розробник не дозволяє мені спілкуватися з незнайомими користувачами.\n\n"
"Sorry! My developer doesn't allow me to chat with strangers.\n\n"
"Извините! Мой разработчик не разрешает мне общаться с незнакомыми пользователями.";
bot.sendMessage(chat_id, message);
Serial.println("Попытка доступа от неавторизованного пользователя. ID: " + chat_id);
String logMessage = "Попытка доступа от неавторизованного пользователя. ID: " + chat_id;
bot.sendMessage(YOUR_CHAT_ID, logMessage);
}
void handleCallbackQuery(String chat_id, String callbackData) {
if (callbackData == "light_menu") {
sendLightMenu(chat_id);
} else if (callbackData == "relay_menu") {
sendRelayMenu(chat_id);
} else if (callbackData == "status") {
sendStatusMenu(chat_id);
} else if (callbackData == "main_menu") {
sendMainMenu(chat_id);
} else if (callbackData == "light_on") {
turnOnLights();
bot.sendMessage(chat_id, "Свет включен", "");
} else if (callbackData == "light_off") {
turnOffLights();
bot.sendMessage(chat_id, "Свет выключен", "");
} else if (callbackData == "brightness_25") {
setBrightness(BRIGHTNESS_25);
bot.sendMessage(chat_id, "Яркость установлена на 25%", "");
} else if (callbackData == "brightness_50") {
setBrightness(BRIGHTNESS_50);
bot.sendMessage(chat_id, "Яркость установлена на 50%", "");
} else if (callbackData == "brightness_75") {
setBrightness(BRIGHTNESS_75);
bot.sendMessage(chat_id, "Яркость установлена на 75%", "");
} else if (callbackData == "brightness_100") {
setBrightness(BRIGHTNESS_100);
bot.sendMessage(chat_id, "Яркость установлена на 100%", "");
} else if (callbackData == "aurora_mode") {
auroraMode = !auroraMode;
bot.sendMessage(chat_id, auroraMode ? "Режим 'Северное сияние' включен" : "Режим 'Северное сияние' выключен", "");
} else if (callbackData == "get_temperature") {
String temperatureMsg = "Текущая температура: " + String(currentTemperature) + "°C";
bot.sendMessage(chat_id, temperatureMsg, "");
} else if (callbackData == "relay_on") {
relayState = true;
digitalWrite(RELAY_PIN, HIGH);
bot.sendMessage(chat_id, "Реле включено", "");
} else if (callbackData == "relay_off") {
relayState = false;
digitalWrite(RELAY_PIN, LOW);
bot.sendMessage(chat_id, "Реле выключено", "");
}
}
void sendMainMenu(String chat_id) {
String keyboardJson = "[["
"{\"text\": \"Управление светом\", \"callback_data\": \"light_menu\"},"
"{\"text\": \"Управление реле\", \"callback_data\": \"relay_menu\"}"
"],["
"{\"text\": \"Северное сияние\", \"callback_data\": \"aurora_mode\"},"
"{\"text\": \"Температура\", \"callback_data\": \"get_temperature\"}"
"],["
"{\"text\": \"Статус\", \"callback_data\": \"status\"}"
"]]";
bot.sendMessageWithInlineKeyboard(chat_id, "Главное меню:", "", keyboardJson);
}
void sendLightMenu(String chat_id) {
String keyboardJson = "[["
"{\"text\": \"Включить свет\", \"callback_data\": \"light_on\"},"
"{\"text\": \"Выключить свет\", \"callback_data\": \"light_off\"}"
"],["
"{\"text\": \"Яркость 25%\", \"callback_data\": \"brightness_25\"},"
"{\"text\": \"Яркость 50%\", \"callback_data\": \"brightness_50\"},"
"{\"text\": \"Яркость 75%\", \"callback_data\": \"brightness_75\"},"
"{\"text\": \"Яркость 100%\", \"callback_data\": \"brightness_100\"}"
"],["
"{\"text\": \"Назад\", \"callback_data\": \"main_menu\"}"
"]]";
bot.sendMessageWithInlineKeyboard(chat_id, "Меню управления светом:", "", keyboardJson);
}
void sendRelayMenu(String chat_id) {
String keyboardJson = "[["
"{\"text\": \"Реле ВКЛ\", \"callback_data\": \"relay_on\"},"
"{\"text\": \"Реле ВЫКЛ\", \"callback_data\": \"relay_off\"}"
"],["
"{\"text\": \"Назад\", \"callback_data\": \"main_menu\"}"
"]]";
bot.sendMessageWithInlineKeyboard(chat_id, "Меню управления реле:", "", keyboardJson);
}
void sendStatusMenu(String chat_id) {
String statusMessage = "📊 Текущий статус:\n\n";
statusMessage += "💡 Свет: " + String(lightStatus == "on" ? "Включен" : "Выключен") + "\n";
statusMessage += "☀ Яркость: " + String(brightness) + "\n";
statusMessage += "🌌 Северное сияние: " + String(auroraMode ? "Включено" : "Выключено") + "\n";
statusMessage += "🔌 Реле: " + String(relayState ? "Включено" : "Выключено") + "\n";
statusMessage += "🌡 Температура: " + String(currentTemperature) + "°C\n";
bot.sendMessage(chat_id, statusMessage, "");
}
void turnOnLights() {
lightStatus = "on";
setBrightness(brightness);
}
void turnOffLights() {
lightStatus = "off";
strip.clear();
strip.show();
auroraMode = false;
}
void setBrightness(int level) {
brightness = level;
strip.setBrightness(brightness);
for (int i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(255, 255, 255));
}
strip.show();
}
void updateAuroraEffect() {
for (int i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, auroraColors[auroraColorIndex]);
}
strip.show();
auroraColorIndex = (auroraColorIndex + 1) % (sizeof(auroraColors) / sizeof(auroraColors[0]));
}
void handleButtonPress() {
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
if (lightStatus == "off") {
turnOnLights();
} else {
turnOffLights();
}
}
}
}
lastButtonState = reading;
}
void handleButton2Press() {
int reading = digitalRead(BUTTON2_PIN);
if (reading != lastButton2State) {
lastButton2DebounceTime = millis();
}
if ((millis() - lastButton2DebounceTime) > DEBOUNCE_DELAY) {
if (reading != button2State) {
button2State = reading;
if (button2State == HIGH) {
relayState = !relayState; // Переключаем состояние реле
digitalWrite(RELAY_PIN, relayState ? HIGH : LOW);
}
}
}
lastButton2State = reading;
}
void updateTemperature() {
if (millis() - lastTemperatureUpdate >= temperatureUpdateInterval) {
sensors.requestTemperatures();
currentTemperature = sensors.getTempCByIndex(0);
lastTemperatureUpdate = millis();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment