Вы абсолютно правы в своей осторожности. Здоровый скептицизм в таких делах — это половина успеха. Но позвольте я объясню техническую магию, почему это все-таки сработает, и доработаю скетч, чтобы он был «умнее».
Почему это сработает (без специального «приложения»)?
Вы пишете: "Нужно чтобы на плате крутился телнет клиент".
Скетч, который я написал, и есть Телнет-клиент.
Дело вот в чем:
- Telnet — это на самом деле очень простой протокол. Это просто «голый текст», летящий по сети (TCP) на порт 23.
- Когда вы открываете Putty на компьютере — это программа с графическим интерфейсом.
- Команда WiFiClient в моем коде открывает точно такой же «канал» связи (сокет), как и Putty.
- Для роутера нет разницы, кто к нему постучался: красивая программа Putty или наш микрочип. Роутер видит входящее соединение, пишет "Login:" и ждет текст в ответ.
ОДНАКО, вы правы в главном:
В прошлом варианте я использовал таймеры (delay). То есть: «подключились, подождали 1 сек, плюнули логин, подождали 1 сек...». Это ненадежно. Если роутер задумается на 2 секунды — пароль уйдет в пустоту, и ничего не сработает.
Давайте сделаем настоящий, «умный» Telnet-клиент.
Он будет работать по логике «Жду приглашения -> Отвечаю». Как живой человек.
Вот
обновленный, "железобетонный" код. Он читает то, что пишет роутер, и реагирует на конкретные слова ("Login", "Password").
Улучшенный скетч (Smart Telnet Client)
Замените прошлый код на этот. Тут добавлена логика ожидания ответа от роутера.
C++
C++:
#include <ESP8266WiFi.h>
// ================= НАСТРОЙКИ =================
const char* ssid = "Keenetic-XXXX";
const char* password = "wifi_password";
const char* router_ip = "192.168.1.1";
const int telnet_port = 23;
const char* router_login = "telnet";
const char* router_pass = "TelnetTelnet";
// ВАЖНО: Проверьте команду отправки. Для некоторых модемов кавычки внутри нужны, для некоторых нет.
// Я добавил экранированные кавычки \", чтобы роутер понял, что текст сообщения - это одно целое.
const char* phone_number = "+79000000000";
const int sensorPin = D1;
// =============================================
WiFiClient client; // Вот он - наш клиент
bool powerState = true;
void setup() {
Serial.begin(115200);
pinMode(sensorPin, INPUT_PULLUP);
Serial.println("\nStarting...");
WiFi.begin(ssid, password);
// Ждем вайфай, но не вечно (чтобы плата не зависла, если роутер перезагружается)
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected");
} else {
Serial.println("\nWiFi NOT connected (yet)");
}
// Инициализация состояния
if (digitalRead(sensorPin) == LOW) powerState = true;
else powerState = false;
}
void loop() {
// Если Вайфай отвалился (роутер перезагрузился), пытаемся переподключиться
if (WiFi.status() != WL_CONNECTED) {
WiFi.reconnect();
delay(5000);
return;
}
int currentReading = digitalRead(sensorPin);
// === СВЕТ ПРОПАЛ ===
if (currentReading == HIGH && powerState == true) {
Serial.println("ALARM: Power Lost! (Pin D1 Open)");
powerState = false;
delay(3000); // Ждем 3 сек для верности
if(digitalRead(sensorPin) == HIGH) {
sendSmsSmart("NO POWER 220V");
}
}
// === СВЕТ ДАЛИ ===
else if (currentReading == LOW && powerState == false) {
Serial.println("INFO: Power Restored! (Pin D1 Closed)");
powerState = true;
delay(3000);
if(digitalRead(sensorPin) == LOW) {
sendSmsSmart("POWER RESTORED");
}
}
delay(500);
}
// === ФУНКЦИЯ УМНОЙ ОТПРАВКИ ===
void sendSmsSmart(String msg) {
if (!client.connect(router_ip, telnet_port)) {
Serial.println("Connection failed!");
return;
}
Serial.println("Connected to Telnet...");
// 1. Ждем, когда роутер спросит "Login:"
if (!waitForString("Login", 5000)) return;
client.println(router_login);
Serial.println("Login sent");
// 2. Ждем, когда роутер спросит "Password:"
if (!waitForString("Password", 5000)) return;
client.println(router_pass);
Serial.println("Password sent");
// 3. Ждем появления командной строки (обычно это ">" или имя роутера)
// Просто подождем чуть-чуть успешного входа
delay(1000);
// Очистим мусор из буфера
while(client.available()) client.read();
// 4. Входим в меню SMS
client.println("sms UsbQmi0");
delay(500);
// 5. Отправляем SMS
String command = "send " + String(phone_number) + " \"" + msg + "\"";
client.println(command);
Serial.println("Command sent: " + command);
// Ждем немного, чтобы модем успел принять команду
delay(3000);
client.println("exit");
client.stop();
Serial.println("Done.");
}
// === ПОМОЩНИК: ЖДЕТ КОНКРЕТНОЕ СЛОВО ОТ РОУТЕРА ===
bool waitForString(String target, int timeout) {
unsigned long start = millis();
String received = "";
while (millis() - start < timeout) {
if (client.available()) {
char c = client.read();
received += c;
// Serial.write(c); // Раскомментируйте, если хотите видеть переписку в мониторе порта
// Если нашли нужное слово внутри принятого текста
if (received.indexOf(target) != -1) {
return true;
}
}
}
Serial.print("Timeout waiting for: ");
Serial.println(target);
return false;
}
В чем разница?
Посмотрите на функцию waitForString в конце кода.
- Плата подключается.
- Она слушает эфир.
- Как только роутер присылает слово "Login", плата тут же отвечает логином.
- Как только роутер присылает "Password", плата отвечает паролем.
Это гарантирует, что мы не пошлем пароль раньше времени или в пустоту. Это и есть реализация примитивного Telnet-клиента.
Как проверить, не собирая схему с 220В?
Я понимаю, что сразу лезть в щиток страшно. Давайте протестируем "на столе".
- Залейте этот скетч.
- Возьмите проводок (перемычку).
- Один конец воткните в GND, второй в D1.
- Пока проводок воткнут — плата думает "Свет есть".
- Выдерните проводок из D1 — плата подумает "Свет пропал" и попытается отправить СМС.
- Откройте в Arduino IDE Монитор порта (значок лупы в углу), поставьте скорость 115200. Там вы увидите весь процесс: "Connected...", "Login sent...", "Command sent...".
Если в мониторе порта вы увидите "Timeout waiting for Login" — значит роутер не отвечает, и тогда будем думать дальше. Но на Кинетиках этот метод работает железно.
Важно про Кинетик Экстра:
Убедитесь, что в настройках роутера (через браузер) установлен компонент "Сервер Telnet".
Управление -> Параметры системы -> Изменить набор компонентов -> ищите там "Сервер Telnet" (обычно он стоит по умолчанию, но лучше проверить).