Страница 2 из 2

Re: GSM КОНТРОЛЛЕР. Модуль удаленного управления.

Добавлено: 02 май 2026, 21:25
MarkT
Заказал железо, теперь ждём, пока приедет.

По существу, текущая тема себя уже исчерпала: из «GSM‑контроллера на соплях» мы вышли на вменяемую архитектуру с ESP32‑S3 + 4G‑модемом, встроенным АКБ и нормальными возможностями для веб‑морды и IoT. Дальше обсуждать в рамках старой концепции уже нет смысла — будет по факту совершенно новый контроллер и другой класс устройства. Так что эту тему логичнее закрыть. Когда плата доедет и начнутся реальные эксперименты с ESP32‑S3 SIM7670G, под это уже заведу новую тему, с тестами, схемами обвязки и результатами по работе в роли «мозгов» вендингового/холодильного аппарата.

Эксперимент с GSM‑контроллером в целом удался: СМС приходили, контроллер их обрабатывал, и светодиод отрабатывал «открытие двери холодильника» — побаловались, убедились, что базовая концепция рабочая. Но на практике стало видно, что из‑за нестабильности и перспективы потратить очень много времени на отладку и разбор всех особенностей блока на SIM800/аналогах, его схемотехники и протоколов, проще и разумнее сразу взять железо посерьёзнее, заточенное под IoT и долгую жизнь.

От варианта с мини‑ПК тоже сознательно отказался. Причины простые:
  • долгая загрузка ОС и сервисов по сравнению с микроконтроллером;
  • нельзя надёжно и просто «пнуть» систему после потери питания так же, как MCU (риски повреждения файловой системы, зависаний при буте и т.п.);
  • нет встроенной схемы бесперебойного питания — приходится отдельно городить UPS;
  • лишние устройства и усложнение конструкции (отдельный модем, отдельный контроллер, больше точек отказа и больше тепла).
Под задачу «надёжные мозги холодильника/вендинга» связка на ESP32‑S3 + 4G‑модуле с батареей выглядит куда более логичной и управляемой, чем городить полноценный мини‑ПК с роутером и GSM‑приблудами вокруг.

Re: GSM КОНТРОЛЛЕР. Модуль удаленного управления.

Добавлено: 08 май 2026, 09:01
MarkT
Эволюция от идеи до реального кода отражается в следующем:

Сценарий: ESP32-S3 + SIM7670 (A7670), TCP‑шлюз на Node.js и интеграция с WordPress

Исходные данные:

– Устройство: ESP32-S3 с SIM7670 (A7670), связь через LTE/4G.
– Оператор: Билайн (APN: internet.beeline.ru, логин/пароль: beeline).
– На сервере уже есть Node.js проект с HTTP API:

– API listening on port 3005
– API Key: gsm-secret-key-2026
– API URL: http://localhost:3005

Цель: построить нормальный GSM‑шлюз для холодильников, который:

– держит постоянное TCP‑соединение с устройствами;
– мгновенно передает команды (например, OPEN для замка);
– обменивается телеметрией;
– при этом WordPress работает только с HTTP API шлюза, а не лезет напрямую к железу.

Ниже вся архитектура и протокол в одном месте.

Роли компонентов

Устройство (ESP32-S3 + SIM7670)

– Постоянный TCP‑клиент.
– Подключается к TCP‑серверу, отправляет HELLO с ID и секретом.
– Периодически шлет ping с телеметрией.
– Принимает команды (OPEN и т.п.) и отправляет события (DOOR_OPENED и т.д.).

Node‑шлюз (порт 3005 + отдельный TCP‑порт)

– На Node.js:
– TCP‑сервер для холодильников (отдельный порт, например 4000).
– REST API (уже есть: http://localhost:3005, с API‑ключом).
– Держит карту подключений fridge_id → socket.
– Принимает телеметрию и события от устройств.
– По HTTP‑запросам от WordPress отправляет команды нужным холодильникам по TCP.

WordPress + плагин (например stolovka-fridges-gateway.php)

– Не общается с устройствами напрямую.
– При нажатии в админке «Открыть холодильник» делает HTTP‑запрос к Node‑шлюзу, например:

POST http://localhost:3005/open
X-API-Key: gsm-secret-key-2026
fridge_id=123

– Node‑шлюз находит TCP‑сокет для fridge_id=123 и отправляет через него команду OPEN.

Протокол TCP (JSON по строкам)

Все сообщения – одна строка JSON + символ перевода строки \n. Это сильно упрощает парсинг.

2.1. Устройство → Node

Регистрация (HELLO)

Отправляется сразу после установления TCP‑соединения:

Код: Выделить всё

{"type":"hello","id":"fridge-123","secret":"ABCDEF123456","fw":"1.0.0"}
– id – уникальный ID холодильника (из админки).
– secret – секретный ключ (из админки/БД).
– fw – версия прошивки (по желанию).

Пинг с телеметрией

На регулярном интервале (например, каждые N секунд):

Код: Выделить всё

{"type":"ping","id":"fridge-123","t":4.5,"door":0,"comp":1,"mains":1}
Где:

– t – температура (С).
– door – состояние двери (0/1).
– comp – состояние компрессора (0/1).
– mains – наличие 220В (0/1).

События

Например, дверь открылась:

Код: Выделить всё

{"type":"event","id":"fridge-123","event":"DOOR_OPENED"}
Дверь закрылась:

Код: Выделить всё

{"type":"event","id":"fridge-123","event":"DOOR_CLOSED"}
Можно расширять (ALARM, POWER_LOSS и т.д.).

2.2. Node → Устройство

Подтверждение регистрации

После успешного HELLO:

Код: Выделить всё

{"type":"hello_ok","mode":"idle"}
mode – необязательное поле, можно использовать для режимов (idle/active) или вообще не использовать.

Команда открыть замок

Код: Выделить всё

{"type":"cmd","cmd":"OPEN"}
Устройство:

– срабатывает openLock();
– ждёт, пока концевик двери покажет открытие;
– отправляет событие DOOR_OPENED.

Позднее можно добавить другие команды:

Код: Выделить всё

{"type":"cmd","cmd":"LOCK"}
{"type":"cmd","cmd":"REBOOT"}
Скетч устройства (основные моменты)

Скетч на ESP32-S3 + SIM7670 (через TinyGSM) делает следующее:

– настраивает APN Билайн;
– поднимает модем и GPRS;
– устанавливает TCP‑соединение с Node‑шлюзом;
– отправляет HELLO сразу после connect;
– периодически шлет ping;
– читает входящие строки JSON и выполняет команды.

Настройки APN под Билайн:

Код: Выделить всё

const char APN[] = "internet.beeline.ru";
const char GPRS_USER[] = "beeline";
const char GPRS_PASS[] = "beeline";
После успешного connectTcp() отправляем HELLO:

Код: Выделить всё

void sendHello() {
String payload = "{";
payload += ""type":"hello",";
payload += ""id":"fridge-123","; // TODO: взять из настроек
payload += ""secret":"ABCDEF123456""; // TODO: взять из настроек
payload += "}\n";
client.print(payload);
}
В loop():

Код: Выделить всё

void loop() {
ensureConnected(); // если TCP отвалился, пробуем пересоздать сеть и коннект

if (client.connected()) {
// Периодический пинг
unsigned long now = millis();
if (now - lastPingMs >= PING_INTERVAL_MS) {
lastPingMs = now;
sendPing(); // JSON: type=ping + телеметрия
}

// Обработка входящих команд
handleIncoming(); // парсит строки JSON, ищет type=cmd, cmd=OPEN и т.п.
}

delay(10);
}
Детали отправки ping и обработки команд можно подгонять под свой формат.

Node‑шлюз: TCP‑сервер + HTTP‑API

Идея: Node‑процесс слушает TCP‑порт для устройств и HTTP‑порт (3005) для WordPress.

4.1. TCP‑сервер (удерживает сокеты устройств)

Псевдокод на Node.js (упрощённый пример):

Код: Выделить всё

const net = require('net');

const socketsById = new Map(); // fridge_id -> socket

const server = net.createServer(socket => {
let buffer = '';

socket.on('data', data => {
buffer += data.toString('utf8');
let index;
while ((index = buffer.indexOf('\n')) >= 0) {
const line = buffer.slice(0, index).trim();
buffer = buffer.slice(index + 1);
if (!line) continue;

try {
const msg = JSON.parse(line);

if (msg.type === 'hello') {
const fridgeId = msg.id;
// TODO: проверить секрет msg.secret по БД или конфигу
socketsById.set(fridgeId, socket);
socket.fridgeId = fridgeId;
socket.write(JSON.stringify({ type: 'hello_ok', mode: 'idle' }) + "\n");
}

if (msg.type === 'ping') {
// обновить телеметрию в БД/кэше
}

if (msg.type === 'event') {
// обработать событие (лог, уведомление, HTTP‑hook в WP и т.д.)
}

} catch (e) {
console.error('Bad JSON from device:', e);
}
}
});

socket.on('close', () => {
if (socket.fridgeId) {
socketsById.delete(socket.fridgeId);
}
});

socket.on('error', err => {
console.error('Socket error:', err);
});
});

server.listen(4000, () => {
console.log('TCP gateway listening on port 4000');
});
4.2. HTTP‑API «открыть холодильник» (для WordPress)

В существующем Express‑API (порт 3005) добавляется endpoint:

Код: Выделить всё

app.post('/open', (req, res) => {
const apiKey = req.header('X-API-Key') || req.query.api_key;
if (apiKey !== 'gsm-secret-key-2026') {
return res.status(403).json({ error: 'forbidden' });
}

const fridgeId = req.body.fridge_id || req.query.fridge_id;
if (!fridgeId) {
return res.status(400).json({ error: 'fridge_id required' });
}

const socket = socketsById.get(fridgeId);
if (!socket) {
return res.status(503).json({ error: 'device_offline' });
}

const cmd = JSON.stringify({ type: 'cmd', cmd: 'OPEN' }) + "\n";
socket.write(cmd);

res.json({ status: 'queued' });
});
Теперь любая система (в том числе WordPress) может сделать:

– POST http://localhost:3005/open
– Заголовок X-API-Key: gsm-secret-key-2026
– Тело: fridge_id=fridge-123

Node‑шлюз найдёт сокет холодильника и отправит ему команду OPEN по TCP.

Интеграция с WordPress

В плагине stolovka-fridges-gateway.php:

– Кнопка «Открыть холодильник» в админке вызывает REST‑handler плагина.
– Этот handler делает внутренний HTTP‑запрос к Node‑шлюзу.

Примерно так:

Код: Выделить всё

$response = wp_remote_post('http://localhost:3005/open', [
'headers' => [
'X-API-Key' => 'gsm-secret-key-2026',
],
'body' => [
'fridge_id' => $fridge_id, // ID устройства, привязанное к записи/терминалу
],
]);

if (is_wp_error($response)) {
// обработать ошибку
}
Node‑шлюз дальше сам общается с устройством по TCP.

Вывод

– Для мгновенных команд и большого количества устройств (холодильников) постоянное TCP‑соединение + отдельный Node‑шлюз – нормальная и правильная архитектура.
– WordPress в такой схеме работает только с HTTP API Node‑шлюза, не общаясь напрямую с железом.
– Устройство (ESP32-S3 + SIM7670) остаётся максимально простым: TCP‑клиент, который шлет HELLO, pинг и события, и выполняет команды, приходящие от Node‑шлюза.