Имеется 25 счетчиков электроэнергии Меркурий 236 ART, объединенных сетью RS485 для дистанционного получения данных. Появилась задача - как можно скорее организовать мониторинг состояния приборов учета и в автоматическом режиме сохранять значения накопленной ими энергии.
Получение данных от счетчиков
После небольших доработок утилиты mercury236 я получил возможность обращаться к счетчикам по индивидуальным адресам и получать от них данные в формате JSON. Процесс установки утилиты и демонстрация ее работы ниже.
[root@localhost ~]# git clone https://github.com/ensoelectric/mercury236
[root@localhost ~]# cd mercury236
[root@localhost mercury236]# make
-std=c99 -lpthread -lrt
cc mercury-cli.c mercury236.c -std=c99 -lpthread -lrt -o mercury236
cc mercury-mon.c mercury236.c -std=c99 -lpthread -lrt -o mercury-mon
[root@localhost mercury236]# cp mercury236/mercury236 /usr/bin/
[root@localhost mercury236]# mercury236 /dev/ttyr00 115
Mains status: On
Voltage (V): 228.38 227.51 226.93
Current (A): 9.06 8.09 11.87
Cos(f): 0.58 0.43 0.74 ( 0.60)
Frequency (Hz): 49.97
Phase angles (deg): 119.83 240.15 120.32
Active power (W): 1208.21 792.42 1991.39 ( 3992.02)
Reactive power (VA): 2070.08 1839.36 2695.36 ( 6604.80)
Total consumed, all tariffs (KWh): 766174.88
including day tariff (KWh): 500278.53
including night tariff (KWh): 265896.28
Yesterday consumed (KWh): 90.32
Today consumed (KWh): 40.33
[root@localhost mercury236]# mercury236 /dev/ttyr00 115 --json
{"mainsStatus":1,"U":{"p1":228.14,"p2":227.41,"p3":226.68},"I":{"p1":9.11,"p2":8.13,"p3":12.39},"CosF":{"p1":0.58,"p2":0.43,"p3":0.75,"sum":0.61},"F":49.97,"A":{"p1":119.90,"p2":240.01,"p3":120.11},"P":{"p1":1207.87,"p2":794.27,"p3":2094.69,"sum":4096.83},"S":{"p1":2078.40,"p2":1848.64,"p3":2809.92,"sum":6736.96},"PR":{"ap":766174.88},"PR-day":{"ap":500278.53},"PR-night":{"ap":265896.28},"PY":{"ap":90.32},"PT":{"ap":40.33}}
Настраиваем мониторинг
В качестве системы мониторинга будет использоваться Zabbix 5.4. Каждый прибор учета я рассматриваю как хост, поэтому был создан шаблон. Он содержит элемент типа "Zabbix траппер" и несколько зависимых от него элементов.
При создании хоста подключаем шаблон и выбираем название, придерживаясь следующего правила: "Mercury [0-255]", где [0-255] - сетевой адрес счетчика.
Хранение "показаний"
Подготовим таблицы для хранения значений накопленной счетчиками энергии (A+).
-- Версия сервера: 10.3.22-MariaDB
DROP DATABASE IF EXISTS Mercury236Reports;
CREATE DATABASE Mercury236Reports;
USE Mercury236Reports;
--
-- Таблица `daily_consumed` содержит значения
-- накопленной активной энергии (A+) за сутки.
--
CREATE TABLE `daily_consumed` (
`addr` tinyint(4) UNSIGNED NOT NULL,
`report` date NOT NULL,
`ap` float NOT NULL,
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`addr`,`report`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
--
-- Таблица `total_consumed` содержит значения накопленной от сброса
-- активной энергии (A+) по сумме тарифов. Сохраняем последнее значение,
-- полученное в текущем часе.
--
CREATE TABLE `total_consumed` (
`addr` tinyint(4) UNSIGNED NOT NULL,
`report` datetime NOT NULL,
`ap` float NOT NULL,
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`addr`,`report`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Отправляем и сохраняем данные
Для отправки данных Zabbix серверу и сохранения информации в БД потребуется утилита zabbix_sender и shell-скрипт следующего содержания.
#!/bin/bash
# mercury236polling.sh
#Power meters address
pm_address=(7 34 43 48 50 54 67 70 73 76 80 81 82 84 89 93 97 115 125 142 144 146 158 199 234)
#ZBX Server
zbx_host="127.0.0.1"
#DB credential
db_host="127.0.0.1"
db_name="Mercury236Reports"
db_user="user"
db_passwd="passwd"
while [ 1 = 1 ]
do
for i in ${!pm_address[@]}
do
data=$(mercury236 /dev/ttyr00 ${pm_address[$i]} --json)
zabbix_sender -z $zbx_host -s "Mercury ${pm_address[$i]}" -k data -o "$data"
#Save A+ values
py=$(echo "$data" | jq '.PY.ap')
pr=$(echo "$data" | jq '.PR.ap')
mysql --host=$db_host --user=$db_user --password=$db_passwd $db_name -e "INSERT INTO daily_consumed (addr, report, ap) VALUES (${pm_address[$i]}, SUBDATE(CURRENT_DATE, 1), $py) ON DUPLICATE KEY UPDATE ap=$py;"
mysql --host=$db_host --user=$db_user --password=$db_passwd $db_name -e "INSERT INTO total_consumed (addr, report, ap) VALUES (${pm_address[$i]}, DATE_FORMAT(NOW(), \"%Y-%m-%d %H:59:59\"), $pr) ON DUPLICATE KEY UPDATE ap=$pr;"
sleep 1
done
done
После запуска скрипта в консоли траппер-элементы должны получать JSON, а БД - пополняться данными о накопленной энергии.
Создаем сервис в systemd
Для того чтобы регулярно запрашивать данные от приборов учета, создадим сервис на основе скрипта mercury236polling.sh.
[root@localhost ~]# cp mercury236polling.sh /usr/bin/
[root@localhost ~]# cat /etc/systemd/system/mercury236polling.service
[Unit]
Description=Monitoring of electricity meters "Incotex Mercury 236"
After=network.target
[Service]
Type=simple
ExecStart=mercury236polling.sh
[Install]
WantedBy=multi-user.target
[root@localhost ~]# systemctl enable mercury236polling.service
[root@localhost ~]# systemctl start mercury236polling.service
[root@localhost ~]# systemctl -l status mercury236polling.service
● mercury236polling.service - Monitoring of electricity meters "Incotex Mercury 236"
Loaded: loaded (/etc/systemd/system/mercury236polling.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2021-11-09 17:26:48 +03; 10min ago
Main PID: 3458296 (mercury236polli)
Tasks: 2 (limit: 23669)
Memory: 672.0K
CGroup: /system.slice/mercury236polling.service
├─3458296 /bin/bash /usr/bin/mercury236polling.sh
└─3462352 sleep 1
Результат
В дальнейшем, вероятно, потребуется настройка оповещений, пока же на достигнутом можно остановиться. Ниже скриншоты дашбордов с графиками фазного напряжения, мгновенной мощности в web-интерфейсе Zabbix и пример выборки накопленных показаний из БД.