post image

Дух кухні (IoT). Історія одного передозу С++ та Node.js

Етап 1: "Залізо" з характером

Серце системи - ESP32. Це такий собі "маленький атлант", який розправив плечі тримає на собі WiFi, MQTT-клієнт та OLED-дисплей.

Головним викликом був датчик DHT11. Якщо запитувати його занадто часто, він починає брехати або просто ігнорувати вас. Тому я ввів правило "Non-blocking Heartbeat":

  • Пристрій не "спить", він працює.

  • Дані відправляються на сервер, тільки якщо температура змінилася хоча б на 0.2°C, або якщо минуло 5 хвилин (щоб я знав, що "Дух" не помер).

    unsigned long now = millis(); // Код, який рятує процесор від депресії (без delay)
    
    bool dataChanged = (abs(t - lastTemp) >= tempThreshold || abs(h - lastHum) >= humThreshold);
    
    bool timeToForceSend = (now - lastMsgTime >= forceSendInterval);

    if (dataChanged || timeToForceSend) {
        if (timeToForceSend && !dataChanged) {
            Serial.println("Heartbeat: sending data anyway...");
        } else {
            Serial.printf("Sensor changed! T: %.1f, H: %.1f\n", t, h);
        }
        
        sendSensorData(t, h);
        
        lastTemp = t;
        lastHum = h;
        lastMsgTime = now;
    }

Етап 2: MQTT - брокер повідомлень

Щоб дані з ESP32 потрапили до мене на сайт, я використовую MQTT. Це протокол для тих, хто не любить нічого зайвого. Дані летять через брокер emqx.io. Швидко, надійно і безкоштовно (поки я не став власником мережі з 10 000 кухонь).

Етап 3: SSE: Бекенд, який не спить

Я не хотів, щоб користувач постійно тиснув F5. Тому я обрав SSE (Server-Sent Events). Це як нескінченний стрім, де сервер сам "штовхає" дані в браузер, як тільки вони прийшли від MQTT. Чому SSE, а не просто оновлення сторінки? Бо ми в 2026-му! Я хочу бачити, як цифра змінюється в реальному часі, поки я смажу яєшню.

А щоб сервер не тримав підключення до MQTT просто так (коли на сайт ніхто не заходить), я додав "ледачу" логіку керування клієнтом:

const toggleMQTT = (action) => {
    if (action === 'connect' && !mqttClient) {
        console.log('🚀 Перший юзер на сайті! Запускаємо MQTT...');
        mqttClient = mqtt.connect('mqtt://broker.emqx.io:1883');
        // ... слухаємо повідомлення ...
    } else if (action === 'disconnect' && activeClients === 0) {
        console.log('💤 Клієнтів немає. Вимикаємо MQTT, економимо ресурси.');
        mqttClient.end();
        mqttClient = null;
    }
};

Етап 4: Інтерфейс

Дисплей на самому пристрої - це окреме задоволення. Всього 0.96 дюйма, але там помістилося все: годинник (синхронізований через космос/NTP), температура, вологість та іконка WiFi.

Якщо іконка зникає - значить, WiFi пішов за хлібом. Якщо цифри замерли - значить, датчик не працює. Але зазвичай все працює як годинник.

Навіщо це все?

Коли я показав це друзям, вони запитали: "А навіщо, якщо можна просто глянути на звичайний градусник?".

Наївні.

  1. Це Fullstack досвід. Від напруги на фізичній ніжці контролера до SQL-запиту в хмарі.

  2. Це масштабованість. Сьогодні це кухня, а завтра - мережа розумних магнітів на холодильник (вже працюю над цим!).

  3. Це просто кайфово. Дивитися, як твій сайт синхронізується з датчиками з твоєї квартири. Справжній девелоперський дзен

Погода на кухні

21.5°C

36.0%