Pull to refresh

Визуализация в IoT: или как самому развернуть систему сбора и отображения данных на MQTT+Telegraf+InfluxDB+Grafana

Level of difficultyMedium
Reading time27 min
Views44K

Введение

В данной статье приведен скоуп информации о том, что взять за основу, чтобы развернуть свой домашний Linux-сервер и систему отображения данных для IoT-устройств, используя MQTT в качестве транспорта с оконечного оборудования.

Многие статьи или инструкции, которые есть в интернете, в части работы с InfluxDB и Telegraf – имеют отношения к довольно старым версиям рассматриваемого ПО, в виду чего у меня ушло какое-то время, чтобы со всем разобраться. Хотелось бы оставить небольшое обновление по инструкциям здесь, возможно, они помогут кому-то сэкономить время и нервы, так как информация агрегирована в виде summury моего погружения в реализацию данного решения. 

Значит понадобилось, как оно водится, по работе, часто взаимодействовать с Linux: CentOS/RHEL, Debian/Ubuntu Server и даже с немного специфичным Clear Linux, специально собранный под процессоры Intel, что дает прирост в производительности во многих бенчмарках (например, тык).

Держать у себя постоянно включенную виртуальную машину стало накладно и решено было найти какой-нибудь интересный мини-пк на просторах популярной китайской площадки, дабы вынести все рабочие моменты на отдельное железо. Бонусом я также получил возможность дополнить данный мини-пк функционалом домашнего Linux-сервера, назначение которого варьируется сколь угодно широко, в зависимости от вашей фантазии. 

В моем случае, учитывая контекст работы и дополнительное увлечение в виде преподавания в сфере IoT, я решил показать студентам, как самим собрать систему визуализации для дипломных устройств, где транспортом для передачи данных служит знакомый им MQTT. 

Состав и описание решения

Рассмотрим состав решения:

Схема взаимодействия компонентов ПО
Схема взаимодействия компонентов ПО
  1. Оконечное оборудование, собирающее телеметрию, доступом в интернет, разрабатываемое студентами индивидуально.

    На оконечном оборудовании реализуется MQTT клиент, который публикует в определённый топик MQTT брокера некую информацию, например, температуру окружающей среды в градусах цельсия.

  2. Mosquitto MQTT broker.

    MQTT брокер служит неким посредником, который позволяет собирать (принимать) информацию от устройств в определенные топики и сразу же «отдавать» ее клиентам, которые эти топики слушают для сбора, обработки, анализа, визуализации получаемых данных.

  3. Telegraf.

    Чтобы получить информацию от MQTT брокера, также необходим клиент, который подписывается на топики брокера для получения данных, реализуя тем самым паттерн Издатель-подписчик (англ. publisher-subscriber или англ. pub/sub). Для этого и используется Telegraf. Он, как клиент-подписчик, прослушивает заданные MQTT топики и, получив сообщение, сразу же записывает информацию в InfluxDB. Вообще, Telegraf – это не только MQTT клиент. Telegraf – это серверный агент для сбора, обработки, агрегирования и записи метрик из различных стеков, датчиков и систем в InfluxDB.

  4. InfluxDB.

    InfluxDB – это система баз данных, оптимизированная для предоставления данных временных рядов и их хранения в привязке ко времени и значению (иными словами база данных временных рядов (time series database – TSDB)), разработанная компанией InfluxData.

    И немного про временные ряды и их данные.

    Временной ряд – это совокупность наблюдений за четко определенными элементами данных, полученных в результате повторяющихся измерений в течение определенного времени. Данные временного ряда индексируются во временном порядке, который представляет собой последовательность точек данных. 

    В InfluxDB есть встроенный конструктор дашбордов для визуализации – Chronograf, на котором можно было бы и остановиться, но он больше сделан для быстрого прототипирования дашбордов и проверки отображения тех или иных метрик в том или ином виде в самой InfluxDB. Гораздо удобнее использовать платформу Grafana, которая является плюс минус стандартном в вопросах визуализации (особенно в сфере IoT). Для этого будет настраиваться интеграция в Grafana на подключение к InfluxDB.

  5. Grafana.

    Grafana – программное обеспечение с открытым исходным кодом, позволяющее запрашивать, визуализировать и исследовать метрики (данные), где бы они ни хранились. По сути, предоставляет пользователю инструменты для преобразования информации из базы данных временных рядов (TSDB) в удобные графики и визуализации.

  6. Node-RED*.

    Это инструмент визуального программирования для интернета вещей, позволяющий подключать друг к другу устройства, API и онлайн-сервисы. Выступает в роли многофункцильного бекэнда с поддержкой множества интерфейсов и протоколов. 

    Звездочка здесь стоит только потому, что данный компонент не обязателен, но всегда должна быть альтернатива, и Node-RED позволяет собирать и передавать данные альтернативным от Telegraf способом, имея мощный функционал промежуточной обработки.

  7. WireGuard.

    Современный VPN-протокол. Необходим, чтобы подключаться к нашему серверу из любой точки через домашнюю сеть. Приятное дополнение – это возможность шифровать трафик в любой публичной Wi-Fi сети без существенных ограничений по скорости и задержкам.

На чем все запускать?

Сердце домашнего сервера и обитель всех рассматриваемых программных компонентов в моем случае – мини-пк Beelink U59 в конфигурации 16(8+8)RAM/512SSD на базе процессора Intel Celeron N5095. Таких характеристик хватит с запасом под разные задачи. Получается отличный вариант по качеству, производительности, сборке. Особенно в контексте цены – 250$, а если еще и распродажа, сами понимаете. На борту есть гигабитный Ethernet-порт и Wi-Fi 5 (ac). И все это в очень компактном корпусе.

Очень радует функция автоматического включения в случае пропадания и восстановления питания. Действительно получается такой мини-сервер, который всегда включен, если есть электричество. Дело остается за малым: чтобы и доступ в интернет не пропадал.

Изначально думал взять какой-нибудь микрокомпьютер, а-ля Raspberry Pi 4 или что-то похожее. Но против тех.спеки не попрешь: U59 на мой взгляд гораздо производительнее и удобнее под рассматриваемые задачи, а стоит аналогично Pi 4. (Если говорить о производительности, то тот же Geekbench на U59 показывает 710/2312 (тык) против 337/877 на Pi 4 (тык

Ознакомиться с подробными техническими характеристиками и отзывами можно по ссылке (тык), а выглядит он вот так:

Вы можете поступить аналогичным образом и раздобыть себе такой же или аналогичный мини-пк. Возможно, перепрофилировать какой-нибудь старый ноутбук или компьютер под эти задачи, или, в конце концов, развернуть виртуальную машину с характеристиками: 1GB RAM/ 1 CPU / 15GB (HDD/SSD). Есть решения, которые позволяют стартовать виртуальные машины при старте системы в фоновом режиме, без какого-либо интерфейса. А чтобы система при старте на помирала, можно настроить отложенный автозапуск. (Знаю, что у Hyper-V или VMware это есть). 

В моем случае U59 стоит рядом с роутером, подключенный к нему по проводу. IP-адрес выдается DHCP-сервером. Итоговая общая схема получается следующая:

На этой схеме дополнительно появляются два блока, которые мы настроим в самом конце статьи. 

Функция "Динамический DNS" (Dynamic DNS / DDNS) позволяет присвоить постоянное доменное имя (адрес для доступа из интернета) публичному IP-адресу, который роутер получает от интернет-провайдера. Публичный IP-адрес может поменяться, а доменное имя, которые вы зарегистрируете – нет. (есть сервисы, позволяющие сделать это бесплатно и вне ПО роутера, рассматриваемого в данной статье). Это будет необходимо для того, чтобы получать доступ к устанавливаемым сервисам через интернет с любого устройства по доменному имени. И порядком упростить конфигурацию, потому что не нужно прописывать конкретный IP адрес в различных конфигурациях ПО.

Далее, Port Forwarding (или Virtual Server) – настройка для WAN-интерфейса (который отвечает за подключение к интернету), позволяющая извне (через интернет) обращаться к конкретным клиентам локальной сети (например, к нашему мини-пк) по определенному порту приложения. 

Таким образом, можно на любом устройстве открыть браузер, ввести зарегистрированное доменное имя и указать порт необходимого приложения, и вуаля, вы зашли на приложение своего сервера. Почти также, как вы попали на habr.com

Установка и настройка ОС

Теперь, когда мы вкратце рассмотрели схемы решения и назначение каждого из компонентов, перейдем к установке и настройке программного обеспечения. 

В качестве основной ОС будет использоваться Linux Debian 12.5

Так как Debian поддерживает три модели выпуска своих ОС «стабильный», «тестируемый», «нестабильный», был выбран второй, так как хотелось иметь более свежие версии ядра и пакетов устанавливаемого ПО. (подробное описание есть на сайте: тык). 

Остается скачать netinst iso-образ для платформы amd64, потому что он содержит минимально необходимый набор базового устанавливаемого ПО. А все пакеты в процессе установки будут загружены из сети, что дает самую актуальную версию ОС и пакетов (ссылочка на образ, чтобы не искать: тык). 

Если при установке возникают ошибки (а такое бывает на тестовых сборках, но редко) вот ссылка на стабильный образ: Linux Debian 12.4 stable: -> тык <-

Процесс установки описывать не буду, он достаточно простой даже для новичков (почти все этапы требуют простого нажатия enter). Пара моментов, которые хотел бы отметить: если устанавливаете через виртуальную машину - обязательно используйте режим bridge (режим моста или сетевого моста), чтобы машина была полноценным отдельным компьютером в вашей домашней сети; обязательная установка пароля для root-пользователя, так как все операции будут выполняться под ним; а также выбор устанавливаемых компонентов, который задается почти в самом конце установки, должен включать только SSH server:

Так выглядит конфигурация установки ОС без лишних компонентов, но с доступом по SSH
Так выглядит конфигурация установки ОС без лишних компонентов, но с доступом по SSH

После установки необходимо войти под пользователем root с паролем, который задавался при установке (и да, пароль при вводе никак не отображается, это нормально).

После ввода root пароля просто нажимаем enter
После ввода root пароля просто нажимаем enter

И внести последнее изменение с самого мини-пк: в конфигурации SSH необходимо разрешить подключение root пользователю, так как, повторюсь, все операции будем выполнять от него. Для этого вводим:

nano /etc/ssh/sshd_config

Ищем закомментированную строку #PermitRootLogin prohibit-password и правим в это: PermitRootLogin yes

Выглядит это так:

Записываем файл ctrl+o, enter и выходим из редактора ctrl+x.
Записываем файл ctrl+o, enter и выходим из редактора ctrl+x.

Перезапускаем сервер:

systemctl restart ssh || systemctl restart sshd

Узнаем ip адрес машины через команду:

ip a

Скорее всего нам нужен будет именно второй интерфейс, а так как IP-адрес получаем по DHCP от роутера, то он будет примерно следующего вида: 

192.168.XXX.YYY (Например, 192.168.0.25 или 192.168.25.136). 

(Во всей статье будет использоваться IP-адрес 192.168.50.56, поэтому держите в уме, что в вашем случае нужно будет заменить его на актуальный IP именно для вашего сервера. Вместо IP-адреса может быть указано также доменное имя)

Узнав адрес, можно отложить ПК в сторону и подключиться по SSH через терминал с основной машины, находящейся в одной локальной сети с сервером, следующей командой (работает в любой ОС):

ssh root@192.168.50.56 

Остается только ввести пароль от пользователя root.

(если на вашей основной машине по каким-либо причинам не установлен ssh-клиент, можете воспользоваться Termius: Win / MacOS / Linux )

Как только получилось авторизоваться, немножко настроим и почистим систему. Уберем поддержку IPv6 и включим переадресацию для IPv4 между сетевыми интерфейсами командой (в терминал вставляется все, так как команды объединены связкой " && \"):

echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf && \
sysctl -w net.ipv4.ip_forward=1

Выключим ненужные сервисы:

systemctl stop cron && \
systemctl stop apparmor && \
systemctl stop console-setup && \
systemctl stop keyboard-setup && \
systemctl disable cron && \
systemctl disable apparmor && \
systemctl disable console-setup && \
systemctl disable keyboard-setup && \
systemctl mask --now systemd-journal-flush && \
systemctl mask --now systemd-journald && \
systemctl set-default multi-user.target

Удалим лишние пакеты и подчистим зависимости:

apt remove -y --purge vim-common vim-tiny ispell iamerican ibritish ienglish-common dictionaries-common emacsen-common wamerican cron cron-daemon-common apparmor console-setup console-setup-linux keyboard-configuration xkb-data kbd isc-dhcp-common shared-mime-info installation-report && \
apt autoclean -y && apt autoremove -y

Теперь установим базовый набор пакетов, необходимый для установки остального ПО:

apt install -y sudo curl wget gnupg2 htop lm-sensors

Отредактируем загрузчик, чтобы убрать 5 секундное ожидание при старте и отключить ограничения по уязвимостям Spectre, Meltdown и другим, открыв файл загрузчика для редактирования:

nano /etc/default/grub

Значения меняем на следующие:

GRUB_TIMEOUT=0
GRUB_CMDLINE_LINUX_DEFAULT="mitigations=off quiet nowatchdog processor.ignore_ppc=1 cpufreq.default_governor=performance"

Записываем файл ctrl+o, enter и выходим из редактора ctrl+x.

Обновляем загрузчик и перезагружаемся:

update-grub && \
reboot

Установка ПО: Mosquitto, Node-RED, WireGuard, Influx, Telegraf, Grafana

После перезагрузки снова коннектимся по SSH:

ssh root@192.168.50.56

Установка Mosquitto

Добавляем пакет и проверяем актуальную версию, должна быть 2.0.18:

sudo wget -qO- https://repo.mosquitto.org/debian/mosquitto-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/mosquitto-repo.gpg && \
sudo wget -O /etc/apt/sources.list.d/mosquitto-bookworm.list https://repo.mosquitto.org/debian/mosquitto-bookworm.list && \
sudo apt update && \
sudo apt-cache show mosquitto | grep Version

Устанавливаем:

sudo apt install -y mosquitto=2.0.18-0mosquitto1~bookworm1 mosquitto-clients=2.0.18-0mosquitto1~bookworm1 && \

Создаем пароль для учетной записи IoT (после ввода команды нужно дважды ввести пароль) и настраиваем права доступа:

sudo mosquitto_passwd -c /etc/mosquitto/passwd IoT && \
sudo chmod 777 /etc/mosquitto/passwd

Создаем конфигурацию:

sudo nano /etc/mosquitto/conf.d/default.conf

И вставляем туда следующие содержимое:

allow_anonymous false
password_file /etc/mosquitto/passwd
listener 1883

Записываем файл ctrl+oenter и выходим из редактора ctrl+x.

Сохраненная только что конфигурация запрещает анонимное подключение, без связки логин-пароль, указывает путь к файлу с заданным ранее паролем для пользователя IoT, а также задает порт, на котором будет работать MQTT брокер. Перезапускаем службу:

systemctl restart mosquitto

Проверим, что все работает, выполнив в двух отдельных терминальных окнах следующие команды (пароль необходимо изменить на свой или использовать student):

mosquitto_sub -h 192.168.50.56 -p 1883 -t Habr -u "IoT" -P "student"
mosquitto_pub -h 192.168.50.56 -p 1883 -t "Habr" -m "Hello, Habr!" -u "IoT" -P "student"

Верхняя команда будет прослушивать топик Habr, командой sub. Нижняя команда отправит на топик с названием Habr сообщение: «Hello, Habr!», командой pub. Что и получилось: В режиме прослушивания (подписки) терминалом была создана строка с полученным значением.

Установка Node-RED + Node.js

Установим сперва актуальную версию Node.js 20:

udo apt-get update && sudo apt-get install -y ca-certificates curl gnupg && \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
NODE_MAJOR=20 && \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list && \
sudo apt-get update && sudo apt-get install nodejs -y

Далее, воспользуемся скриптом-установщиком, который установит Node-RED:

bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

Установщик трижды спросит подтверждение, необходимо дважды ввести «y» и последний раз «n».

Are you really sure you want to install as root ? [y/N] ? y
Are you really sure you want to do this ? [y/N] ? y
Would you like to install the Pi-specific nodes ? [y/N] ? n

Далее, нам необходимо инициализировать параметры командой, если вы вдруг не нажали "y" в процессе установки на запрос конфигурации сейчас:

node-red admin init

Небольшая шпаргалка по ответам на вопросы скрипта:

Settings file -> enter
Do you want to setup user security? –> yes
Username -> admin
Password -> задаете_пароль_для_admin
User permissions -> full access
Add another user? -> yes
Username -> user
Password -> задаете_пароль_для_user
User permissions -> read-only access
Add another user? -> no
Do you want to enable the Projects feature? -> no
Enter a name for your flows file -> enter
Provide a passphrase to encrypt your credentials file -> задаете_пароль_для_credentials_file
Select a theme for the editor -> default 
Select the text editor component to use in the Node-RED Editor -> monaco (default)
Allow Function nodes to load external modules? -> yes

Данная конфигурация включает форму авторизации на Node-RED и создает двух пользователей: admin и user, с полными правами и правами только на чтение соответственно. Затем необходимо включить и запустить сервисы Node-RED:

sudo systemctl enable nodered && \
sudo systemctl start nodered

Проверить, что все работает, можно зайдя по адресу: http://192.168.50.56:1880/

Если все действия выполнены успешно, вас встретит эта замечательная приветственная страница
Если все действия выполнены успешно, вас встретит эта замечательная приветственная страница

Установка WireGuard

WireGuard, как и Node-RED, тоже очень просто устанавливается скриптом-установщиком. Загружаем скрипт, делаем его исполняемым:

sudo curl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh && \
sudo chmod +x wireguard-install.sh && \

И запускаем:

./wireguard-install.sh

Небольшая шпаргалка по ответам на вопросы скрипта:

IPv4 or IPv6 public address: -> my-home-server.noip.com (указываем доменное имя или публичный IP адрес с 2ip.ru, полученное в конце статьи)
Public interface: -> ens## (автоматом подтягивает имеющийся сетевой интерфейс, который мы видели командой ip a, если это он, можно не менять))
WireGuard interface name: -> wg0 (оставляем без изменений)
Server's WireGuard IPv4: -> 10.66.66.1 (оставляем предложенную адресацию без изменений)
Server's WireGuard IPv6: -> fd42:42:42::1(оставляем предложенную адресацию без изменений)
Server's WireGuard port [1-65535]: -> 1870 (указываем любой порт)
First DNS resolver to use for the clients: ->1.1.1.1
Second DNS resolver to use for the clients (optional): -> 1.0.0.1

После нажатия Enter’a, установки и конфигурирования серверной части скриптом, что был выше, скрипт переходит дальше, к настройке клиентской конфигурации, с помощью которой можно будет подключиться через клиентское приложение WireGuard к нашему серверу. Там указывается следующее:

Client name: -> Client_id_1 (или устанавливаем свое название файла)
Clinet's WireGuard IPv4: -> 10.66.66.2 (оставляем предложенную адресацию без изменений)
Clinet's WireGuard IPv6: -> fd42:42:42::2(оставляем предложенную адресацию без изменений)

Конфигурацию можно скачать по QR-коду или через FTP по пути /root/wg0-client-####.conf .

Результат выглядит вот так:

В итоговой конфигурации удаляем все упоминания об IPv6 и ip6tables в строчках с PostUp и PostDown:

nano /etc/wireguard/wg0.conf

Результат должен быть примерно следующий:

[Interface]
Address = 10.66.66.1/24
ListenPort = 1870
PrivateKey = sLdyJJPFXSZCTuPbuaCKdvDvVDOCCdbwjmPj7QgQkEs
PostUp = iptables -A FORWARD -i enp2s0 -o wg0 -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o enp2s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i enp2s0 -o wg0 -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o enp2s0 -j MASQUERADE

### Client
[Peer]
PublicKey = Rxo33+25X0oBni2v94+ftMXBSEveTpeXDDhmb7/x0mc=
PresharedKey = FNKcatwzm8KyAtP4lj8ZuXfSvQY0nh/SeV34TYMYaL0=
AllowedIPs = 10.66.66.2/32

Записываем файл ctrl+o, enter и выходим из редактора ctrl+x.

Перезапускаем службу:

systemctl restart wg-quick@wg0

Если захотите добавить еще одного пользователя (потому что каждая конфигурация поддерживает только одно активное подключение), то снова запустите скрипт (выбрав 1):

./wireguard-install.sh

Для проверки необходимо запустить клиентское приложение WireGuard, импортировать в него созданную ранее клиентскую конфигурацию (wg0-client-####.conf) и запустить подключение:

После установки WireGuard'a обязательно перезапустить систему:

reboot

После чего снова подключаемся по SSH:

ssh root@192.168.50.56

Установка InfluxDB2 + Telegraf + Grafana

Добавим репозитории для InfluxDB2 и Telegraf, скачаем заданную версию Grafana, установим и запустим службы (для Grafana проверяйте наличие обновленной версии перед установкой здесь. Версию можно поправить прямо в скрипте, когда выйдет более актуальная)

sudo wget -q https://repos.influxdata.com/influxdata-archive_compat.key && \
sudo echo '393e8779c89ac8d958f81f942f9ad7fb82a25e133faddaf92e15b16e6ac9ce4c influxdata-archive_compat.key' | sha256sum -c && cat influxdata-archive_compat.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg > /dev/null && \
sudo echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main' | sudo tee /etc/apt/sources.list.d/influxdata.list && \
sudo apt-get install -y adduser libfontconfig1 musl && \
sudo wget https://dl.grafana.com/oss/release/grafana_10.3.4_amd64.deb && \
sudo dpkg -i grafana_10.3.4_amd64.deb && \
sudo rm /root/grafana_10.3.4_amd64.deb && \
sudo systemctl enable grafana-server && \
sudo systemctl start grafana-server && \
sudo apt-get update && sudo apt-get install -y influxdb2 telegraf && \
sudo systemctl start influxd && \
sudo systemctl enable telegraf

Проверим, что InfluxDB и Grafana доступны, зайдя по адресам: http://192.168.50.56:8086/ и http://192.168.50.56:3000/

Должно быть так:

Если все действия выполнены успешно, вас встретит эта замечательная приветственная страница
Если все действия выполнены успешно, вас встретит эта замечательная приветственная страница

И так:

Если все действия выполнены успешно, вас встретит эта замечательная приветственная страница
Если все действия выполнены успешно, вас встретит эта замечательная приветственная страница

Настройка Influx, Telegraf, Grafana

Заходим в InfluxDB по адресу http://192.168.50.56:8086 и нажимаем “GET STARTED” и первым делом создаем учетную запись, указываем название организации и корзины для данных (Organization Name и Bucket Name -> IoT). После заполнения нажать «CONTINUE», а в следующем окне «QUICK START»

Создаем учетную запись, указываем название организации и корзины для данных
Создаем учетную запись, указываем название организации и корзины для данных
Выбираем QUICK START
Выбираем QUICK START

Далее, нам необходимо создать файл конфигурации для Telegraf. Для этого необходимо создать токен доступа InfluxDB (так как просмотр созданных токенов стал запрещен). 

В левом боковом меню нажимаем Load Data -> API Tokens -> GENERATE API TOKEN -> Custom API Token:

GENERATE API TOKEN -> All Access API Token
GENERATE API TOKEN -> All Access API Token

Задаем любое название для создаваемого токена, выбираем все доступы Read и Write для категорий Buckets и Telegrafs и нажимаем GENERATE:

Задаем имя для токена
Задаем имя для токена

Копируем через “COPY TO CLIPBOARD” и сохраняем где-нибудь (еще раз обращу внимание на то, что токен показывается только один раз при его создании).

Копируем токен в буфер обмена (и обязательно сохраняем где-нибудь)
Копируем токен в буфер обмена (и обязательно сохраняем где-нибудь)

Далее, создаем саму конфигурацию для Telegraf:

nano /etc/telegraf/telegraf.d/IoT.conf

И вставляем туда следующее содержимое, которое в части ip-адресов и токена вам нужно будет немного отредактировать:

# Configuration for telegraf agent
[agent]
  interval = "5s"
  round_interval = true
  metric_batch_size = 1000
  metric_buffer_limit = 10000
  collection_jitter = "0s"
  flush_interval = "5s"
  flush_jitter = "0s"
  precision = ""
  hostname = ""
  omit_hostname = false

[[outputs.influxdb_v2]]
  urls = ["http://192.168.50.56:8086"]
  token = "gj8siSCDDuWyPd31LvrA2JIzldDzso_e_R_NiRkjKGJei4VgdoBV4heKIYSb7jMXLvEufhKgZfEv2pjTCHYUXA=="
  organization = "IoT"
  bucket = "IoT"

[[inputs.mqtt_consumer]]
  servers = ["tcp://192.168.50.56:1883"]
  topics = ["#"]
  username = "IoT"
  password = "student"
  data_format = "value"
  data_type = "float"

Записываем файл ctrl+o, enter и выходим из редактора ctrl+x. Затем перезапускаем службу, чтобы применить конфиг:

systemctl restart telegraf

Теперь необходимо отправить данные на наш MQTT брокер:

mosquitto_pub -h 192.168.50.56 -p 1883 -t "Habr/Temp" -m "28.5" -u "IoT" -P "student"

А в InfluxDB проверить, что в Data Explorer -> IoT -> mqtt_consumer есть топик Habr/Temp и данные. Для этого необходимо настроить пространство, как на скриншоте ниже ( нужно поменять тип график на Gauge, aggregate function указать last и нажать SUBMIT):

Все MQTT-сообщения от Telegraf будут собираться в mqtt_consumer
Все MQTT-сообщения от Telegraf будут собираться в mqtt_consumer

Вуаля, наш температурный «спидометр» показывает ровно то значение, которое было отправлено в MQTT сообщении на топик Habr/Temp. Последний шаг, который осталось сделать: скопировать скрипт получения данных из БД. Делается это через SCRIPT EDITOR (рядом с SUBMIT со скриншота выше). Копируем запрос из 6 строк и сохраняем где-нибудь рядом с токеном.

Запрос может быть и больше, если шагом ранее вы выберете несколько метрик
Запрос может быть и больше, если шагом ранее вы выберете несколько метрик

Далее, перейдем к настройкам Grafana. Первая авторизация происходит по логину/паролю admin/admin, после чего система попросит установить новый пароль. 

Hello :)
Hello :)

После чего попадаем на приветственное пространство Grafana. Далее, нам необходимо добавить интеграцию (подключение) с InfluxDB. Нажимаем значок настроек -> Data Sources -> Add Data Sourse -> InfluxDB -> Query Language (Flux) -> URL -> Basic Auth (off) -> Organozation(IoT) -> Default Bicket (IoT) -> Token (Берется в InfluxDB -> Load Data -> Api Tokens -> Admin`stoken) -> Save&Test (должен быть ok)

Много картинок здесь:
Нажимаем значок настроек -> Data Sources ->
Нажимаем значок настроек -> Data Sources ->
-> Add Data Sourse ->
-> Add Data Sourse ->
-> InfluxDB ->
-> InfluxDB ->
-> Query Language (Flux) -> URL (http://192.168.50.56:8086)-> Basic Auth (off) -> Organozation(IoT) -> Default Bicket (IoT) -> Token (Берется в InfluxDB -> Load Data -> Api Tokens -> Admin`stoken) -> Save&Test (должен быть ok)
-> Query Language (Flux) -> URL (http://192.168.50.56:8086)-> Basic Auth (off) -> Organozation(IoT) -> Default Bicket (IoT) -> Token (Берется в InfluxDB -> Load Data -> Api Tokens -> Admin`stoken) -> Save&Test (должен быть ok)

После того, как Grafana успешно подключилась к InfluxDB и обнаружила все корзины с данными, можно добавить дашборд: Dashboards -> New Dashboard -> Add New Panel -> вставляем данные их SCRIPT EDITOR -> Apply -> Save -> Имя дашборда

И много картинок здесь
Dashboards -> New Dashboard ->
Dashboards -> New Dashboard ->
-> Add New Panel ->
-> Add New Panel ->
вставляем данные из SCRIPT EDITOR в InfluxDB -> минимально настраиваем -> Apply
вставляем данные из SCRIPT EDITOR в InfluxDB -> минимально настраиваем -> Apply
Создаем еще одну панель с табличным отображением
Создаем еще одну панель с табличным отображением
Сохраняем итоговый дашборд
Сохраняем итоговый дашборд

На этом настройка первого дашборда по визуализации условной температуры завершена. 

ВАЖНО: Службу Telegraf необходимо перезапускать после каждой перезагрузки системы. Почему-то она стартует в статусе «failed», а перезагружается со статусом «Active». Видимо баг в последних сборках. "Пофиксить" можно следующим образом:

sed -i 14i\ 'RestartSec=2s' /lib/systemd/system/telegraf.service

И применим изменения:

sudo systemctl daemon-reload

Альтернатива с Node-RED

Для этого нам необходимо зайти в приложение http://192.168.50.56:1880/ и авторизоваться под администратором, пароль которого задавался ранее. В базовом наборе есть множество узлов(нод), в том числе MQTT, поэтому остается добавить и настроить интеграцию с InfluxDB. Для этого необходимо загрузить дополнительную палитру node-red-contrib-influxdb, а еще нам понадобится random-generator_node-red-contrib, для генерации случайных чисел.

Для этого в боковом меню выбирается "Управление палитрой", затем установить и в поле поиска вводится название палитры и нажимается кнопка "установить".

Выглядит это так
Боковое меню -> Управление палитрой
Боковое меню -> Управление палитрой
Устанавливаем палитру node-red-contrib-influxd, аналогично действуем для random-generator_node-red-contrib
Устанавливаем палитру node-red-contrib-influxd, аналогично действуем для random-generator_node-red-contrib

После установки всего необходимого соберем поток:

Делаем так:
  1. Возьмем узел стартового генератор событий «inject» в разделе общее, который будет генерировать сообщение с текущей временной меткой

  2. Возьмем узел «Number», в разделе Random Generator, где зададим диапазон случайно генерируемых чисел.

    Настройка узла Number
    Настройка узла Number
  3. Возьмем узел «mqtt out» в разделе сеть, чтобы отправить данные MQTTброкеру. И настроим его. Указав тему (топик), адрес сервера, и данные авторизации.

    (Шаги с 1 по 3 нужны, чтобы с эмулировать данные от устройства, передающего данные по MQTT.)

    Задается тема для публикации и настраивается сервер
    Задается тема для публикации и настраивается сервер
    Задается адрес и порт сервера
    Задается адрес и порт сервера
    Задаются параметры аутентификации
    Задаются параметры аутентификации
  4. Возьмем узел «mqtt in» в разделе сеть, чтобы получать данные от MQTT брокера. И настроем его по аналогии с П.3

    Указывается уже настроенный сервер и задается тема для подписки
    Указывается уже настроенный сервер и задается тема для подписки
  5. Возьмем узел «influx out» в разделе хранилище, чтобы данные записывались в InfluxDB. И настроим его. Укажем организацию и корзину: IoT, задаим название переменной для измерений, укажем версию InfluxDB (2.0), адрес БД и знакомый по прошлым пунктам токен.

    Указывается Org, Bucket и настраивается подключение к InfluxDB
    Указывается Org, Bucket и настраивается подключение к InfluxDB
    Указывается версия БД (2.0 обязательно), адрес и токен
    Указывается версия БД (2.0 обязательно), адрес и токен
  6. Для удобства к узлам «Number» и «mqtt in» можно подключить узел debug, который покажет, что было сгенерировано такое-то значение, на узле “Number”, а оно же было получено на узле «mqtt in». (и, соответственно, записано в БД).

  7. Нажимаем развернуть (чтобы применить любый изменения)

Проверим, что все настройки работают, нажав на запуск события узла «inject»:

Успех!
Успех!

Как мы видим, MQTT подключение к брокеру успешно установлено. А сгенерированные данные были отправлены и получены по MQTT. Проверим теперь запись измерения в InfluxDB. Заходим в уже знакомый раздел Data Explorer и видим там измерение с названием Habr_temp, которые было задано в узле «influx out». 

Данные в метрику Habr_temp получены!
Данные в метрику Habr_temp получены!

Преимущество данного способа в том, что при получении информации по mqtt на шаге 4 выше, после него можно написать какую-нибудь функцию на javasсript по обработке полученных данных. И только потом записать их в InfluxDB.

Перенастройка Grafana на порт 80

Для того, чтобы Grafana была доступна по порту 80, и не было необходимости вводить полный адрес с указанием порта, а только сам ip-адрес, можно использовать команду для настройки переадресации 80 порта на 3000 порт Grafana (после перезагрузки системы правила iptables очищаются, необходимо применять повторно):

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000 && \
sudo systemctl daemon-reload

Если необходимо сделать работу по 80 порту постоянной, то необходимо исправить конфигурацию графаны, указав необходимый порт, а также отредактировать службу, разрешив ей работать с портами <1024:

sed -i 's/;http_port = 3000/http_port = 80/' /etc/grafana/grafana.ini && \
sed -i 52i\ 'CapabilityBoundingSet=CAP_NET_BIND_SERVICE' /lib/systemd/system/grafana-server.service && \
sed -i 53i\ 'AmbientCapabilities=CAP_NET_BIND_SERVICE' /lib/systemd/system/grafana-server.service && \
sed -i 54i\ 'PrivateUsers=false' /lib/systemd/system/grafana-server.service && \
sudo systemctl daemon-reload && \
sudo systemctl restart grafana-server

После чего Grafana становится доступной по 80 порту.

Немного про DDNS и PortFowarding на роутере ASUS и адресацию.

Под конец настроим проброс портов установленных приложений. Для этого необходимо зайти на роутер (в моем случае адрес 192.168.50.1), авторизоваться и перейти в раздел бокового меню WAN. Там выбрать раздел Virtual Server / Port Forwarding и настроить значения следующим образом через “Add profile”. Необходимо ввести имя профиля, порт, который открываем, тип протокола и адрес нашего сервера:

В зависимости от производителя интерфейс может отличаться, но суть остается без изменений.
В зависимости от производителя интерфейс может отличаться, но суть остается без изменений.

На любом другом роутере интерфейс и названия могут отличаться, но функционал должен присутствовать почти на всех современных моделях. Теперь у нас есть доступ к нашим приложениям через интернет, при указании вашего публичного IP адреса и порта приложения.

Далее, перейдем к настройке нашего доменного имени. Необходимо перейти в соседнюю секцию, включить службу DDNS, установить метод запроса IP -> External. Указать свободное доменное имя и зарегистрировать его (в качестве примера используется: yours-linux-server-1.asuscomm.com). Когда процесс успешно завершится, применить всю конфигурацию. Через небольшой промежуток времени ваш публичный IP адрес привяжется к доменному имени, которое вы зарегистрировали и доступ к приложениям можно будет запрашивать по нему, вместо публичного IP адреса.

Кстати, если вы захотите в будущем заморочиться настройкой https соединения, то здесь же можно получить бесплатный сертификат Let`s Encrypt (кнопочка Export), который можно указать в качестве реквизитов при настройке https-соединения в настройках ПО выше.

Настройка службы DDNS на роутере Asus
Настройка службы DDNS на роутере Asus

Немного про адресацию:

Доступ, например, в Node-Red, осуществляется по адресу http://localhost:1880 с компьютера, на котором он установлен, по адресу http://192.168.50.56:1880 если запрос идет из любого другого компьютера домашней локальной сети, и http://<ваш ip адрес на 2ip.ru / или доменное имя>:1880 если настроен проброс портов и запрашивается доступ через интернет. Итого это будет выглядеть следующим образом:

На самом сервере доступ к ПО осуществляется по ссылкам:

http://localhost:1880     –>     Node-RED
http://localhost:1883     –>     Mosquitto MQTT
http://localhost:1871     –>     WireGuard VPN
http://localhost:3000     –>     Grafana
http://localhost:8086     –>     InfluxDBv2

На любом устройстве домашней локальной сети доступ к ПО осуществляется по ссылкам:

http://192.168.50.56:1880     –>     Node-RED
http://192.168.50.56:1883     –>     Mosquitto MQTT
http://192.168.50.56:1871     –>     WireGuard VPN
http://192.168.50.56:3000     –>     Grafana
http://192.168.50.56:8086     –>     InfluxDBv2

На любом устройстве доступ к ПО через интернет осуществляется по ссылкам (на месте yours-linux-server-1.asuscomm.com может быть ваш публичный IP адрес на 2ip.ru):

http://yours-linux-server-1.asuscomm.com:1880     –>     Node-RED
http://yours-linux-server-1.asuscomm.com:1883     –>     Mosquitto MQTT
http://yours-linux-server-1.asuscomm.com:1871     –>     WireGuard VPN
http://yours-linux-server-1.asuscomm.com:3000     –>     Grafana
http://yours-linux-server-1.asuscomm.com:8086     –>     InfluxDBv2

Если вам интересно, как использовать доменное имя (в примере ниже это superpuperhabr.ru), чтобы обращаться к сайтам подобным образом:

https://nodered.superpuperhabr.ru           –>     Node-RED
https://mqtt.superpuperhabr.ru              –>     Mosquitto MQTT
https://wg.superpuperhabr.ru                –>     WireGuard VPN
https://grafana.superpuperhabr.ru           –>     Grafana
https://influx.superpuperhabr.ru            –>     InfluxDBv2
https://chirpstack.superpuperhabr.ru        –>     Chirpstack-v4
https://chirpstack-api.superpuperhabr.ru    –>     Chirpstack-api

То по ссылке далее описано, как это сделать: ---> тык <---

P.S.

Если любопытно посмотреть потребление ресурсов развернутой системы, то можно воспользоваться утилитой htop:

htop

P.S.S: Docker

Для тех, кто предпочитает контейнеры:

Вставляем один большой скрипт (вот прям весь весь):

apt-get update && \
apt-get install -y ca-certificates curl gnupg lsb-release && \
mkdir -m 0755 -p /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && \
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && \
docker run hello-world && \
docker compose version && \
mkdir -m 777 -p ~/mosquitto/config && \
mkdir -m 777 -p ~/mosquitto/data && \
mkdir -m 777 -p ~/mosquitto/log && \
mkdir -m 777 -p ~/influxdb/data && \
mkdir -m 777 -p ~/influxdb/conf && \
mkdir -m 777 -p ~/telegraf/conf && \
mkdir -m 777 -p ~/grafana/data && \
mkdir -m 777 -p ~/grafana/conf && \
mkdir -m 777 -p ~/grafana/log && \
mkdir -m 777 -p ~/node-red/data && \
mkdir -m 777 -p ~/wireguard/config

Создадим конфигурацию для mosquitto:

cat > ~/mosquitto/config/mosquitto.conf <<EOF
listener 1883
#allow_anonymous false
#password_file /mosquitto/config/password.txt
EOF

Создадим конфигурацию для telegraf:

cat > ~/telegraf/conf/telegraf.conf <<EOF
[agent]
  interval = "5s"
  round_interval = true
  metric_batch_size = 1000
  metric_buffer_limit = 10000
  collection_jitter = "0s"
  flush_interval = "5s"
  flush_jitter = "0s"
  precision = ""
  hostname = ""
  omit_hostname = false

[[outputs.influxdb_v2]]
  urls = ["http://192.168.50.56:8086"]
  token = "!copy_token_here!"
  organization = "IoT"
  bucket = "IoT"

[[inputs.mqtt_consumer]]
  servers = ["tcp://192.168.50.56:1883"]
  topics = ["#"]
  username = "IoT"
  password = "student"
  data_format = "value"
  data_type = "float"
EOF

Настроим Grafana на 80 порт:

cat > ~/grafana/conf/grafana.ini <<EOF
[server]
http_port = 80
EOF

Создадим docker-compose.yml:

cat > docker-compose.yml <<EOF
version: "2"
services:
  influxdb:
    container_name: influxdb
    image: influxdb:latest
    environment:
      - TZ=Europe/Moscow
    ports:
      - "8086:8086"
    volumes:
      - ~/influxdb/data:/var/lib/influxdb
    networks:
      - influxdb-net
    restart: always

  wireguard:
    container_name: wireguard
    image: lscr.io/linuxserver/wireguard:latest
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Moscow
      - SERVERURL=192.168.50.56 #optional
      - SERVERPORT=1871 #optional
      - PEERS=5 #optional
      - PEERDNS=1.1.1.1 #optional
      - INTERNAL_SUBNET=10.13.13.0 #optional
      - ALLOWEDIPS=0.0.0.0/0 #optional
      - LOG_CONFS=false #optional
    volumes:
      - ~/wireguard/config:/config
      - /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: always

  telegraf:
    container_name: telegraf
    image: telegraf:latest
    environment:
      - TZ=Europe/Moscow
    volumes:
      - ~/telegraf/conf/telegraf.conf:/etc/telegraf/telegraf.conf
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - telegraf-net
    restart: always
    
  grafana:
    container_name: grafana
    image: grafana/grafana-oss:latest
    environment:
      - TZ=Europe/Moscow
    ports:
      - "80:80"
    volumes:
      - ~/grafana/data:/var/lib/grafana
      - ~/grafana/log:/var/log/grafana
      - ~/grafana/conf/grafana.ini:/etc/grafana/grafana.ini
    links:
      - influxdb
    networks:
      - grafana-net
    restart: always

  mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto:latest
    environment:
      - TZ=Europe/Moscow
    volumes:
      - ~/mosquitto/:/mosquitto  
    ports:
      - 1883:1883
    networks:
      - mosquitto-net
    restart: always

  node-red:
    container_name: node-red
    image: nodered/node-red:latest
    environment:
      - TZ=Europe/Moscow
    ports:
      - "1880:1880"
    volumes:
      - ~/node-red/data:/data
    networks:
      - node-red-net
    restart: always

networks:
  node-red-net:
  influxdb-net:
  mosquitto-net:
  grafana-net:
  telegraf-net:
EOF

Запустим создание контейнеров (процесс займет какое-то время):

docker compose up -d

Далее, необходимо, как в основной части статьи, настроить mosquitto. От вас требуется только придумать пароль:

docker exec -it mosquitto mosquitto_passwd -c /mosquitto/config/password.txt IoT

Включить авторизацию в конфигурации:

cat > ~/mosquitto/config/mosquitto.conf <<EOF
listener 1883
allow_anonymous false
password_file /mosquitto/config/password.txt
EOF

И применить конфигурацию:

docker restart mosquitto

Настроить авторизацию в Node-red, сгенерировав пароль сперва для admin, потом для user, и скопировав хеши куда-нибудь:

docker exec -it node-red node-red-admin hash-pw

И указать их здесь:

nano +76,5 ~/node-red/data/settings.js

Должно быть примерно так:

adminAuth: {
        type: "credentials",
        users: [
                {
                        username: "admin",
                        password: "$2b$08$WhOtjRwX8Cd44vgryrOPue4rS8YkdOxS7DuuvUaUtotGRiSZ1bUny",
                        permissions: "*"
                },
                {
                        username: "user",
                        password: "$2b$08$sksoLeOB6EDecN3IZYLisO7mqNf/KSI519eioh7gtM0BpvAM3wA3q",
                        permissions: "read"
                }
        ]
},

Затем применяем конфигурацию:

docker restart node-red

Получаем токен Influx по шагам в основной статье. И указываем его здесь:

nano +15,12 ~/telegraf/conf/telegraf.conf

И применяем конфигурацию для Telegraf:

docker restart telegraf

Все контейнеры должны быть в статусе UP

docker ps
Выглядит примерно вот так
Выглядит примерно вот так

Конфиг для WireGuard можно получить командой:

docker exec -it wireguard /app/show-peer 1

Не забываем про настройку интеграции с Influx у Grafana и Node-RED (в части настроек все без изменений, как и в основной статье)

Работа с доменным именем

Для того, чтобы использовать доменное имя для своих сервисов, можно воспользоваться этой статьей: ---> тык <---

Выглядеть будет примерно следующим образом:

https://nodered.superpuperhabr.ru           –>     Node-RED
https://mqtt.superpuperhabr.ru              –>     Mosquitto MQTT
https://wg.superpuperhabr.ru                –>     WireGuard VPN
https://grafana.superpuperhabr.ru           –>     Grafana
https://influx.superpuperhabr.ru            –>     InfluxDBv2
https://chirpstack.superpuperhabr.ru        –>     Chirpstack-v4
https://chirpstack-api.superpuperhabr.ru    –>     Chirpstack-api

Вместо заключения

На этом все! Домашний сервер с системой визуализации и подключением по MQTT настроен. Остается только отправлять данные в топики по MQTT и настраивать визуализацию, как душе угодно.

На самом деле в статье рассмотрен лишь частный случай с MQTT. Что Telegraf, что Node-RED – позволяют получать и передавать данные в InfluxDB (и другие БД) по множеству других интерфейсов и протоколов. Но это уже совсем другая история.

e

Tags:
Hubs:
Total votes 17: ↑15 and ↓2+13
Comments15

Articles