Категории

Как я поднял IoT-хаб с нуля на Raspberry Pi: Zigbee, MQTT, MySQL и веб-интерфейс

2025-09-04 00:49:06 | IOT умный дом

Введение

Решил с нуля собрать IoT-хаб на Raspberry Pi. Раньше у меня уже был MQTT, но Zigbee не "закрутился", Node.js не работал. Решил всё пересобрать чисто — и вот что получилось.

В итоге: Zigbee2MQTT + Mosquitto + MariaDB (вместо MySQL) + Nginx + PHP + веб-интерфейс. Всё работает, датчики ловит, данные пишет, управлять можно.

Цель

Сделать универсальный хаб для Zigbee-датчиков, который:

Оборудование

Шаг 1: Установка системы

Поставил Raspberry Pi OS (64-bit, Lite). Подключился по SSH.

        sudo apt update && sudo apt upgrade -y
    

Шаг 2: Безопасность — SSH и UFW

        sudo systemctl enable ssh
        sudo apt install ufw -y
        sudo ufw allow OpenSSH
        sudo ufw allow 1883/tcp    # MQTT
        sudo ufw allow 8080/tcp    # Zigbee2MQTT Web UI
        sudo ufw allow 80/tcp      # Веб-интерфейс
        sudo ufw enable
    

Шаг 3: Установка Mosquitto (MQTT-брокер)

        sudo apt install mosquitto mosquitto-clients -y
        sudo systemctl enable mosquitto

        # Создаём пользователя
        sudo mosquitto_passwd -c /etc/mosquitto/passwd iotuser
        # Пароль: 123456
    

Конфиг: /etc/mosquitto/conf.d/mqtt.conf

allow_anonymous false
password_file /etc/mosquitto/passwd
listener 1883
    

Шаг 4: Установка MariaDB (вместо MySQL)

В Debian 12+ MySQL больше нет в репозиториях — ставим MariaDB (полная замена).

        sudo apt install mariadb-server mariadb-client -y
        sudo mysql_secure_installation
    

Создаём БД и пользователя:

sudo mysql -u root -p

CREATE DATABASE iot_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'iot_user'@'localhost' IDENTIFIED BY '123456';
GRANT ALL PRIVILEGES ON iot_db.* TO 'iot_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
    

Шаг 5: Установка Node.js 20

Zigbee2MQTT 2.6.1 требует Node.js 20+.

cd /tmp
wget https://nodejs.org/dist/v20.19.0/node-v20.19.0-linux-arm64.tar.xz
sudo tar -xf node-v20.19.0-linux-arm64.tar.xz -C /usr/local --strip-components=1

node --version  # v20.19.0
npm --version   # 10.8.3
    

Шаг 6: Установка Zigbee2MQTT

cd ~
git clone https://github.com/Koenkk/zigbee2mqtt.git
cd zigbee2mqtt

# Устанавливаем pnpm (теперь обязателен)
sudo npm install -g pnpm

# Копируем конфиг
cp data/configuration.yaml.example data/configuration.yaml
nano data/configuration.yaml
    

Конфигурация data/configuration.yaml

homeassistant: false
permit_join: true

mqtt:
  base_topic: zigbee2mqtt
  server: 'mqtt://localhost'
  user: 'iotuser'
  password: '123456'

serial:
  port: /dev/ttyUSB0
  adapter: ezsp

frontend:
  port: 8080

advanced:
  log_level: info
  channel: 11
  network_key: GENERATE
    

Шаг 7: Запуск и проверка

npm start
    

Если видишь:

Zigbee2MQTT:info  Coordinator firmware version: ...
Zigbee2MQTT:info  Zigbee2MQTT started!
    

— поздравляю, хаб заработал!

Шаг 8: Веб-интерфейс

Открой в браузере:

http://:8080
    

Там можно:

Шаг 9: Веб-панель управления (index.php)

Как в статье хомасистент на пхп.

Установка Nginx + PHP

sudo apt install nginx php-fpm php-mysql mariadb-client -y
sudo systemctl enable nginx php-fpm
    

Создание сайта

sudo mkdir -p /var/www/html/iot
    

Туда копируем:

Конфиг Nginx

sudo nano /etc/nginx/sites-available/iot
    
server {
    listen 80;
    root /var/www/html/iot;
    index index.php;
    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}
    
sudo ln -s /etc/nginx/sites-available/iot /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo systemctl reload nginx
    

Шаг 10: Создание таблиц в MariaDB

Важно создать структуру БД, как в статье.

sudo mysql -u root -p
    
USE iot_db;

-- Таблица с данными датчиков
CREATE TABLE IF NOT EXISTS sensor_data (
    id INT AUTO_INCREMENT PRIMARY KEY,
    topic VARCHAR(255) NOT NULL,
    value VARCHAR(255),
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_topic (topic),
    INDEX idx_time (timestamp)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Таблица с информацией о датчиках
CREATE TABLE IF NOT EXISTS sensor_info (
    id INT AUTO_INCREMENT PRIMARY KEY,
    topic VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255),
    room VARCHAR(255),
    group_name VARCHAR(255),
    icon VARCHAR(50),
    INDEX idx_topic (topic)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

Шаг 11: Сохранение данных из MQTT в MySQL

Из-за PEP 668 в новых системах нельзя ставить пакеты через pip3 install — используем виртуальное окружение.

Создаём виртуальное окружение

python3 -m venv ~/mqtt-env
source ~/mqtt-env/bin/activate
pip install PyMySQL
    

Скрипт: ~/mqtt_to_mysql.py

import paho.mqtt.client as mqtt
import pymysql.cursors
import json

# Подключение к MySQL через PyMySQL
connection = pymysql.connect(
    host='localhost',
    user='iot_user',
    password='123456',
    database='iot_db',
    charset='utf8mb4',
    cursorclass=pymysql.cursors.DictCursor
)

def on_connect(client, userdata, flags, rc):
    print("✅ MQTT: Подключено")
    client.subscribe("zigbee2mqtt/#")

def on_message(client, userdata, msg):
    topic = msg.topic
    payload = msg.payload.decode()

    # Пропускаем служебные топики
    if any(x in topic for x in ["availability", "set", "linkquality", "info", "log"]):
        return

    try:
        data = json.loads(payload)

        # Обработка списка или объекта
        if isinstance(data, list):
            for item in data:
                process_data(item, topic)
        elif isinstance(data, dict):
            process_data(data, topic)
        else:
            save_to_db(topic, data)

    except Exception as e:
        print("❌ Ошибка при обработке:", e)

def process_data(data, base_topic):
    if not isinstance(data, dict):
        return
    for key, value in data.items():
        if key in ['temperature', 'humidity', 'pressure', 'battery', 'voltage', 'co2', 'pm25', 'light', 'water_pressure']:
            full_topic = f"{base_topic}/{key}"
            save_to_db(full_topic, value)

def save_to_db(topic, value):
    try:
        with connection.cursor() as cursor:
            sql = "INSERT INTO sensor_data (topic, value) VALUES (%s, %s)"
            cursor.execute(sql, (topic, str(value)))
        connection.commit()
    except Exception as e:
        print("❌ Ошибка записи в БД:", e)

# Настройка MQTT
client = mqtt.Client()
client.username_pw_set("iotuser", "123456")
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)
print("📡 Ожидание данных с Zigbee...")
client.loop_forever()
    

Шаг 12: Автозапуск через systemd

Чтобы всё работало после перезагрузки.

1. Zigbee2MQTT

sudo nano /etc/systemd/system/zigbee2mqtt.service
    
[Unit]
Description=Zigbee2MQTT
After=network.target

[Service]
Type=simple
User=mazzick
WorkingDirectory=/home/user/zigbee2mqtt
ExecStart=/usr/bin/npm start
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
    
sudo systemctl enable zigbee2mqtt
    

2. MQTT → MySQL

sudo nano /etc/systemd/system/mqtt-to-mysql.service
    
[Unit]
Description=MQTT to MySQL Bridge
After=network.target zigbee2mqtt.service

[Service]
Type=simple
User=mazzick
WorkingDirectory=/home/user
ExecStart=/home/user/mqtt-env/bin/python /home/user/mqtt_to_mysql.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
    
sudo systemctl enable mqtt-to-mysql.service
sudo systemctl start mqtt-to-mysql.service
    

Шаг 13: Добавление датчика

  1. Включи режим сопряжения (5–10 сек)
  2. В вебе (:8080) задай имя: bedroom_sensor
  3. Добавь в БД:
INSERT INTO sensor_info (topic, name, room, group_name, icon) VALUES
('zigbee2mqtt/bedroom_sensor/temperature', 'Температура', 'Спальня', 'Датчики', '🌡️'),
('zigbee2mqtt/bedroom_sensor/humidity', 'Влажность', 'Спальня', 'Датчики', '💧');
    

Шаг 14: Проверка

Открой:

http:///iot
    

Должны отображаться датчики, графики, кнопки управления.

Заключение

Хаб готов. Всё работает. Датчики добавляются, данные идут в БД, интерфейс красивый.

Теперь можно масштабировать: дача, гараж, теплица — через WireGuard в единой сети.

Планы:

Админка доступна по запросу — если хочешь повторить, пиши в комментарии!

Как превратить Raspberry Pi в энергоэффективный сервер

Задумался я тут, а сколько жрет малинка с GUI. и решил немного оптимизировать ее. Т.к. GUI мне не нужны. Хотел конечно использовать ее как домашний комп. Но как увидел сколько всего к ней подключается, это какой-то ядерный реактор а не компьютер. Пусть лучше в ящике как сервер крутится. Так ну и самое интересное, сколько я сэкономлю энергии за год если переведу малинку в режим полноценного сервера.<.p>

Как сэкономить электроэнергию, отключив GUI и лишние службы. Реальные цифры и простые шаги.

Вы поставили Raspberry Pi OS с графическим интерфейсом, но теперь решили использовать малинку как сервер — для хранения, торрентов, веба или домашнего облака. Отлично! Но знаете ли вы, что простое отключение GUI может сэкономить до 0.25 Вт в режиме 24/7?

Почему это важно?

Даже небольшое энергопотребление складывается:

Это может показаться мало, но если вы используете несколько Pi или питаете от батареек / солнечных панелей — каждая миллиампер-час (мА·ч) имеет значение.

GUI: враг или друг?

Графический интерфейс (GUI) удобен, но для сервера он — :

Что происходит при отключении GUI?

Когда вы отключаете GUI командой:

sudo systemctl set-default multi-user.target

Система загружается в текстовом режиме, но пакеты GUI всё ещё установлены. Они не запускаются, но:

Сравнение: GUI включён vs удалён

Показатель Только GUI отключён GUI полностью удалён
Потребление энергии (примерно) ~3.0 Вт ~2.75 Вт
Использование RAM при старте ~200–250 МБ ~60–100 МБ
Занятое место на диске ~4–6 ГБ ~1.5–2 ГБ
Фоновые службы Много (X, LXDE, Bluetooth) Только необходимые
Годовое энергопотребление ~26 кВт·ч ~24 кВт·ч
💡 Совет: Если вы используете Pi как сервер 24/7, удаление GUI сэкономит около 2 кВт·ч в год — а это бесплатно!

Как полностью удалить GUI и стать "Lite"

Выполните команды (в терминале через SSH):

sudo apt remove --purge --autoremove \\
    raspberrypi-ui-mods lxpanel lxsession openbox \\
    xserver-xorg xinit lightdm desktop-base \\
    chromium-browser firefox-esr libreoffice* \\
    scratch* sonic-pi penguinspuzzle claws-mail

sudo apt autoremove -y
sudo apt clean
    

После этого ваша система будет почти идентична Raspberry Pi OS Lite — чистая, быстрая и энергоэффективная.

Дополнительная экономия

Чтобы сэкономить ещё больше:

Вывод

Превратить Raspberry Pi в сервер — легко. А сделать его по-настоящему эффективным — просто:

  1. Отключите GUI: sudo systemctl set-default multi-user.target
  2. Удалите ненужные пакеты
  3. Отключите фоновые службы
  4. Наслаждайтесь экономией энергии и стабильностью

Каждый ватт на счету — особенно когда ваш сервер работает круглосуточно.

Комментарии

Пока нет комментариев. Будьте первым!

Оставить комментарий

← Назад к списку статей

DISCLAIMER: Блог-эксперимент

Внимание: Cтатьи здесь сгенерированы нейросетью, пока не правил ошибки, только запустил его да и не до этого. Просто чтобы вы знали и не запускали ядерный реактор по моим статьям ))
НО!
Каждый кейс я реально делал минимум один раз. Серьёзно.
Сервера стоят, клиенты довольны, дата-центры не горят.
Это не просто копипаста — это опыт, выстраданный в бою, просто пересказанный через ИИ.
Если у вас есть вопросы, или Нашли неточность? пишите в коментах — вместе поправим и сделаем статью более качественной. Я лично объясню нюансы из практики.

Посетителей сегодня: 0


© Digital Specialist | Не являемся сотрудниками Google, Яндекса и NASA
Кто я | HSH | Контакты и регион