Решил с нуля собрать IoT-хаб на Raspberry Pi. Раньше у меня уже был MQTT, но Zigbee не "закрутился", Node.js не работал. Решил всё пересобрать чисто — и вот что получилось.
В итоге: Zigbee2MQTT + Mosquitto + MariaDB (вместо MySQL) + Nginx + PHP + веб-интерфейс. Всё работает, датчики ловит, данные пишет, управлять можно.
Сделать универсальный хаб для Zigbee-датчиков, который:
Поставил Raspberry Pi OS (64-bit, Lite). Подключился по SSH.
sudo apt update && sudo apt upgrade -y
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
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
В 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;
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
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
npm start
Если видишь:
Zigbee2MQTT:info Coordinator firmware version: ...
Zigbee2MQTT:info Zigbee2MQTT started!
— поздравляю, хаб заработал!
Открой в браузере:
http://:8080
Там можно:
Как в статье хомасистент на пхп.
sudo apt install nginx php-fpm php-mysql mariadb-client -y
sudo systemctl enable nginx php-fpm
sudo mkdir -p /var/www/html/iot
Туда копируем:
index.phpadmin/api/js/, css/, img/
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
Важно создать структуру БД, как в статье.
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;
Из-за 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()
Чтобы всё работало после перезагрузки.
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
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
:8080) задай имя: bedroom_sensor
INSERT INTO sensor_info (topic, name, room, group_name, icon) VALUES
('zigbee2mqtt/bedroom_sensor/temperature', 'Температура', 'Спальня', 'Датчики', '🌡️'),
('zigbee2mqtt/bedroom_sensor/humidity', 'Влажность', 'Спальня', 'Датчики', '💧');
Открой:
http:///iot
Должны отображаться датчики, графики, кнопки управления.
Хаб готов. Всё работает. Датчики добавляются, данные идут в БД, интерфейс красивый.
Теперь можно масштабировать: дача, гараж, теплица — через WireGuard в единой сети.
Админка доступна по запросу — если хочешь повторить, пиши в комментарии!
Задумался я тут, а сколько жрет малинка с GUI. и решил немного оптимизировать ее. Т.к. GUI мне не нужны. Хотел конечно использовать ее как домашний комп. Но как увидел сколько всего к ней подключается, это какой-то ядерный реактор а не компьютер. Пусть лучше в ящике как сервер крутится. Так ну и самое интересное, сколько я сэкономлю энергии за год если переведу малинку в режим полноценного сервера.<.p>
Как сэкономить электроэнергию, отключив GUI и лишние службы. Реальные цифры и простые шаги.
Вы поставили Raspberry Pi OS с графическим интерфейсом, но теперь решили использовать малинку как сервер — для хранения, торрентов, веба или домашнего облака. Отлично! Но знаете ли вы, что простое отключение GUI может сэкономить до 0.25 Вт в режиме 24/7?
Даже небольшое энергопотребление складывается:
Это может показаться мало, но если вы используете несколько Pi или питаете от батареек / солнечных панелей — каждая миллиампер-час (мА·ч) имеет значение.
Графический интерфейс (GUI) удобен, но для сервера он — :
Когда вы отключаете GUI командой:
sudo systemctl set-default multi-user.target
Система загружается в текстовом режиме, но пакеты GUI всё ещё установлены. Они не запускаются, но:
dbus, avahi-daemon)| Показатель | Только GUI отключён | GUI полностью удалён |
|---|---|---|
| Потребление энергии (примерно) | ~3.0 Вт | ~2.75 Вт |
| Использование RAM при старте | ~200–250 МБ | ~60–100 МБ |
| Занятое место на диске | ~4–6 ГБ | ~1.5–2 ГБ |
| Фоновые службы | Много (X, LXDE, Bluetooth) | Только необходимые |
| Годовое энергопотребление | ~26 кВт·ч | ~24 кВт·ч |
Выполните команды (в терминале через 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 — чистая, быстрая и энергоэффективная.
Чтобы сэкономить ещё больше:
sudo systemctl disable bluetooth hciuart — отключить Bluetoothsudo systemctl disable avahi-daemon — отключить mDNS (если не нужен)echo 0 | sudo tee /sys/class/leds/led0/brightnessПревратить Raspberry Pi в сервер — легко. А сделать его по-настоящему эффективным — просто:
sudo systemctl set-default multi-user.targetКаждый ватт на счету — особенно когда ваш сервер работает круглосуточно.
Блог только запустил, все статьи генерирую через нейросеть т.к. лень, возможны ошибки. Просто чтобы вы знали и не запускали ядерный реактор по моим статьям ))
Если у вас есть вопросы, или Нашли неточность? пишите в коментах — вместе поправим и сделаем статью более качественной. Я лично объясню нюансы из практики.
Комментарии
Пока нет комментариев. Будьте первым!