Daly BMS: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
| (не показано 28 промежуточных версий этого же участника) | |||
| Строка 1: | Строка 1: | ||
[[Категория:UPS]] |
[[Категория:UPS]] |
||
[[Категория:BMS]] |
[[Категория:BMS]] |
||
| + | [[Категория:Daly]] |
||
| + | [[Категория:Linux]] |
||
| + | [[Категория:SNMP]] |
||
| + | [[Категория:Zabbix]] |
||
=Daly BMS= |
=Daly BMS= |
||
| + | Идея а том что бы снимать данные и складывать в заббикс |
||
| + | * дернуть скрипт кроном раз в минуту <code>batt-dale-snmp.py</code>, результат работы сохранить в файл (<code>/var/lib/snmp/daly.json</code>) |
||
| + | * отдать результат через <code>SNMP pass</code> |
||
| + | =Прежде чем начать= |
||
| − | =<code>C</code> version= |
||
| + | У меня сгорел "родной" переходник на котором был распаян разъем (фото нет, и я не знаю как он называется - и нигде не смог найти такой!)<BR> |
||
| − | <PRE> |
||
| + | Для замены использовал такой переходник: |
||
| − | cd /opt |
||
| − | < |
+ | <BR> |
| + | [[Файл:Daly BMS 1.JPG|600px]] |
||
| − | <PRE> |
||
| + | <BR> |
||
| − | git clone https://github.com/immortalserg/DalyBMS_linux.git |
||
| + | {{ |
||
| − | </PRE> |
||
| + | caution|text=У меня напряжение было 3.3В на пинах RX/TX со стороны BMC - отсюда я сделал вывод что надо переключить UART-конвертер в 3.3V (джампер) |
||
| − | <PRE> |
||
| + | }} |
||
| − | cd DalyBMS_linux |
||
| + | <BR> |
||
| − | |||
| + | [[Файл:Daly BMS 2.JPG|600px]] |
||
| − | cmake . && make |
||
| − | < |
+ | <BR> |
| + | <BR> |
||
| − | в папке появится файл <code>smart_bms</code>, <BR> |
||
| + | Фото BMS в шакальем качестве |
||
| − | отредактируйте файл bms.conf указав порт к которому подключен Daly BMS и интервал опроса, |
||
| + | <BR> |
||
| − | в mqtt появятся соответствующие топики, добавьте в crontab строку запуска |
||
| − | < |
+ | <BR> |
| + | [[Файл:Daly BMS 3.JPG|600px]] |
||
| − | crontab - e |
||
| − | < |
+ | <BR> |
| + | <BR> |
||
| − | @reboot cd /opt/DalyBMS_linux ./smart_bms |
||
| − | |||
| − | перезагрузите устройство. Подписавшись на топик Вы получите данные. |
||
=Dalybms на python.= |
=Dalybms на python.= |
||
| − | {{caution|text=У меня напряжение было 3.3В |
||
| − | }} |
||
В консоли устанавливаем python-pip |
В консоли устанавливаем python-pip |
||
| Строка 40: | Строка 43: | ||
<PRE> |
<PRE> |
||
pip3 install pyserial |
pip3 install pyserial |
||
| + | </PRE> |
||
| − | |||
| + | Модуль для MQTT по желанию (мне не был нужен) |
||
| + | <PRE> |
||
pip3 install paho-mqtt |
pip3 install paho-mqtt |
||
</PRE> |
</PRE> |
||
| Строка 50: | Строка 55: | ||
подключаем нашу BMS к uart порту либо через usb-uart адаптер либо через uart разъем на одноплатнике (необходимо включить порт в настройках), далее будет рассмотрено подключение через usb-uart |
подключаем нашу BMS к uart порту либо через usb-uart адаптер либо через uart разъем на одноплатнике (необходимо включить порт в настройках), далее будет рассмотрено подключение через usb-uart |
||
Подключаем следующим образом: |
Подключаем следующим образом: |
||
| + | <PRE> |
||
| − | |||
BMS — UART |
BMS — UART |
||
GND — GND |
GND — GND |
||
RX — TX |
RX — TX |
||
TX — RX |
TX — RX |
||
| + | </PRE> |
||
После подключения usb-uart адаптера смотрим имя адаптера введя команду |
После подключения usb-uart адаптера смотрим имя адаптера введя команду |
||
| + | <PRE> |
||
| − | |||
ls -n /dev/ttyU* |
ls -n /dev/ttyU* |
||
| + | </PRE> |
||
| − | |||
должен показать устройства |
должен показать устройства |
||
| + | <PRE> |
||
crw-rw—- 1 0 20 188, 0 Feb 24 21:12 /dev/ttyUSB0 |
crw-rw—- 1 0 20 188, 0 Feb 24 21:12 /dev/ttyUSB0 |
||
crw-rw—-+ 1 0 20 188, 0 Feb 24 19:57 /dev/ttyUSB1 |
crw-rw—-+ 1 0 20 188, 0 Feb 24 19:57 /dev/ttyUSB1 |
||
| + | </PRE> |
||
| − | где /dev/ttyUSB0 и /dev/ttyUSB1 это наши USB устройства, у меня их 2 и с этим могут быть проблемы поскольку при перезагрузки они могут иметь имена наоборот и после перезагрузки устройства не будут работать. Для того чтобы это исключить мы будем обращаться к устройства по ID, получаем id наших устройств, вводим команду: |
||
| + | где <code>/dev/ttyUSB0</code> и <code>/dev/ttyUSB1</code> это наши USB устройства, у меня их 2 и с этим могут быть проблемы поскольку при перезагрузки они могут иметь имена наоборот и после перезагрузки устройства не будут работать. Для того чтобы это исключить мы будем обращаться к устройства по ID, получаем id наших устройств, вводим команду: |
||
| − | |||
| + | <PRE> |
||
ls -n /dev/serial/by-id/* |
ls -n /dev/serial/by-id/* |
||
| + | </PRE> |
||
| − | |||
получаем список |
получаем список |
||
| + | <PRE> |
||
lrwxrwxrwx 1 0 0 13 Sep 8 09:58 /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_12967c31b312ec11b6da21c7bd930c07-if00-port0 -> ../../ttyUSB0 |
lrwxrwxrwx 1 0 0 13 Sep 8 09:58 /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_12967c31b312ec11b6da21c7bd930c07-if00-port0 -> ../../ttyUSB0 |
||
lrwxrwxrwx 1 0 0 13 Feb 24 22:18 /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB1 |
lrwxrwxrwx 1 0 0 13 Feb 24 22:18 /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB1 |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | ls -n /dev/serial/by-id/* |
||
| + | lrwxrwxrwx 1 0 0 13 Jan 12 15:29 /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A5XK3RJT-if00-port0 -> ../../ttyUSB0 |
||
| + | </PRE> |
||
синим это наши устройства, в дальнейшем в конфигах и командах можно использовать как /dev/ttyUSB0 так и полный путь к id устройству. |
синим это наши устройства, в дальнейшем в конфигах и командах можно использовать как /dev/ttyUSB0 так и полный путь к id устройству. |
||
У меня как видно Sonoff Zigbee USB стик и USB-UART адаптер на чипе CP2102 (USB-UART адаптеры бывают на разных чипах) |
У меня как видно Sonoff Zigbee USB стик и USB-UART адаптер на чипе CP2102 (USB-UART адаптеры бывают на разных чипах) |
||
Теперь проверим соединение с нашей BMS. |
Теперь проверим соединение с нашей BMS. |
||
| + | <PRE> |
||
| + | daly-bms-cli -d /dev/ttyUSB0 --all |
||
| + | </PRE> |
||
| + | или можно по id, |
||
| + | <PRE> |
||
| + | daly-bms-cli -d /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 --all |
||
| + | </PRE> |
||
| + | мы получим все параметры. Если данные не получены то возможно Ваша BMS сделана на другом чипе, для этого надо добавить флаг —sinowealth |
||
| + | <PRE> |
||
| − | daly-bms-cli -d /dev/ttyUSB1 --all |
||
| + | daly-bms-cli -d /dev/ttyUSB0 --all --sinowealth |
||
| + | </PRE> |
||
| + | Теперь есть несколько вариантов просмотра данных, не зависимо от того какую систему домашней автоматизации Вы используете мы будем передавать данные в систему домашней автоматизации по популярному протоколу mqtt, команда которую мы написали выше будет иметь вид: |
||
| + | <PRE> |
||
| + | daly-bms-cli -d /dev/ttyUSB0 --all --mqtt |
||
| + | </PRE> |
||
| − | или можно по id, |
||
| − | daly-bms-cli -d /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 --all |
||
| + | =<code>collect_batt_status.sh</code>= |
||
| − | мы получим все параметры. Если данные не получены то возможно Ваша BMS сделана на другом чипе, для этого надо добавить флаг —sinowealth |
||
| + | Запускаю из крона (<code>/etc/cron.d/batt_dale_status</code>): |
||
| + | <PRE> |
||
| + | */3 * * * * root /etc/nut/collect_batt_status.sh |
||
| + | </PRE> |
||
| + | Конечный результат в файле <code>/var/lib/snmp/daly.json</code> (который разбираем для SNMP) |
||
| + | <PRE> |
||
| − | daly-bms-cli -d /dev/ttyUSB1 --all --sinowealth |
||
| + | #!/usr/bin/env bash |
||
| − | Теперь есть несколько вариантов просмотра данных, не зависимо от того какую систему домашней автоматизации Вы используете мы будем передавать данные в систему домашней автоматизации по популярному протоколу mqtt, команда которую мы написали выше будет иметь вид: |
||
| + | DEV="/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A5XK3RJT-if00-port0" |
||
| − | daly-bms-cli -d /dev/ttyUSB0 --all --mqtt |
||
| + | sudo -u nut \ |
||
| − | нам надо сделать периодический опрос нашей BMS, lдобавим периодический запуск в планировщик: |
||
| + | /usr/local/virtualenvs/daly-bms-cli/bin/python3 \ |
||
| + | /usr/local/virtualenvs/daly-bms-cli/bin/daly-bms-cli -d ${DEV} --all > /tmp/daly.json 2>>/var/lib/snmp/daly.err && \ |
||
| + | mv /tmp/daly.json /var/lib/snmp/daly.json |
||
| + | </PRE> |
||
| − | crontab - e |
||
| + | {{#spoiler:show=Пример результата| |
||
| + | <PRE> |
||
| − | в конец вставляем команду: |
||
| + | { |
||
| + | "soc": { |
||
| + | "total_voltage": 56.1, |
||
| + | "current": 0.6, |
||
| + | "soc_percent": 94.1 |
||
| + | }, |
||
| + | "cell_voltage_range": { |
||
| + | "highest_voltage": 3.592, |
||
| + | "highest_cell": 9, |
||
| + | "lowest_voltage": 3.409, |
||
| + | "lowest_cell": 15 |
||
| + | }, |
||
| + | "temperature_range": { |
||
| + | "highest_temperature": 24, |
||
| + | "highest_sensor": 1, |
||
| + | "lowest_temperature": 24, |
||
| + | "lowest_sensor": 1 |
||
| + | }, |
||
| + | "mosfet_status": { |
||
| + | "mode": "stationary", |
||
| + | "charging_mosfet": true, |
||
| + | "discharging_mosfet": true, |
||
| + | "capacity_ah": 263.48 |
||
| + | }, |
||
| + | "status": { |
||
| + | "cells": 16, |
||
| + | "temperature_sensors": 2, |
||
| + | "charger_running": false, |
||
| + | "load_running": false, |
||
| + | "states": { |
||
| + | "DI1": false |
||
| + | }, |
||
| + | "cycles": 3 |
||
| + | }, |
||
| + | "cell_voltages": { |
||
| + | "1": 3.487, |
||
| + | "2": 3.525, |
||
| + | "3": 3.475, |
||
| + | "4": 3.482, |
||
| + | "5": 3.539, |
||
| + | "6": 3.363, |
||
| + | "7": 3.526, |
||
| + | "8": 3.559, |
||
| + | "9": 3.592, |
||
| + | "10": 3.498, |
||
| + | "11": 3.512, |
||
| + | "12": 3.516, |
||
| + | "13": 3.46, |
||
| + | "14": 3.478, |
||
| + | "15": 3.409, |
||
| + | "16": 3.531 |
||
| + | }, |
||
| + | "temperatures": { |
||
| + | "1": 24, |
||
| + | "2": 24 |
||
| + | }, |
||
| + | "balancing_status": { |
||
| + | "error": "not implemented" |
||
| + | }, |
||
| + | "errors": [ |
||
| + | "one stage warning of unit over voltage" |
||
| + | ] |
||
| + | } |
||
| + | </PRE> |
||
| + | }} |
||
| + | =<code>SNMP</code>= |
||
| + | Для того что бы дергать скрипт на пайтоне через SNMP и отдавать данные заббиксу делаю так |
||
| + | <PRE> |
||
| + | pass .1.3.6.1.4.1.418 /etc/nut/batt-dale-snmp.py |
||
| + | </PRE> |
||
| + | =<code>batt-dale-snmp.py</code>= |
||
| − | */1 * * * * daly-bms-cli -d /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 --all --mqtt |
||
| + | {{#spoiler:show=batt-dale-snmp.py| |
||
| + | <PRE> |
||
| − | сохраняем, теперь команда будет запускаться каждую минуту (чаще в crontab не сделать) |
||
| + | #!/usr/bin/env python3 |
||
| − | Теперь в программе автоматизации надо подписаться на топик daly_bms и разобрать полученные данные. |
||
| + | import sys |
||
| − | Если в консоль я получил данные читаемо, то в mqtt не удалось корректно получить данные. |
||
| + | import subprocess |
||
| + | import logging |
||
| + | import json |
||
| + | from logging.handlers import RotatingFileHandler |
||
| + | LOGFILE = "/var/log/snmp/snmp-batt-test.log" |
||
| + | DATA_FILE="/var/lib/snmp/daly.json" |
||
| + | UPS_NAME = "mpp" |
||
| + | def flatten_dict(d, parent_key="", sep="_"): |
||
| + | flat = {} |
||
| + | for key, value in d.items(): |
||
| + | new_key = f"{parent_key}{sep}{key}" if parent_key else str(key) |
||
| + | if isinstance(value, dict): |
||
| + | flat.update(flatten_dict(value, new_key, sep=sep)) |
||
| + | else: |
||
| + | flat[new_key] = value |
||
| + | return flat |
||
| + | |||
| − | https://kusheev.com/archives/1539 |
||
| + | def get_oid_data(key): |
||
| + | with open(DATA_FILE, 'r') as file: |
||
| + | data = json.load(file) |
||
| + | flat = flatten_dict(data) |
||
| + | logger.debug(f"[get_oid_data] data: {data} б flat: {flat}") |
||
| + | val = flat.get(key) |
||
| + | logger.debug(f"[get_oid_data] value: {val}") |
||
| + | return str(val) |
||
| + | |||
| + | |||
| + | def batt_status(nut, nut_key): |
||
| + | val = get_oid_data(nut, nut_key) |
||
| + | s = str(batt_status_code(val)) |
||
| + | logger.debug("[batt_status] Status: {s}") |
||
| + | return s |
||
| + | |||
| + | def mosfet_status(key): |
||
| + | with open(DATA_FILE, 'r') as file: |
||
| + | data = json.load(file) |
||
| + | flat = flatten_dict(data) |
||
| + | logger.debug(f"mosfet_status] data: {data} flat: {flat}") |
||
| + | |||
| + | val = flat.get(key) |
||
| + | logger.debug(f"[mosfet_status] value: {val}") |
||
| + | |||
| + | if key == "mosfet_status_mode": |
||
| + | if val == "discharging": |
||
| + | return "1" |
||
| + | else: |
||
| + | return "0" |
||
| + | elif key == "mosfet_status_charging_mosfet": |
||
| + | if val: |
||
| + | return "1" |
||
| + | else: |
||
| + | return "0" |
||
| + | elif key == "mosfet_status_discharging_mosfet": |
||
| + | if val: |
||
| + | return "1" |
||
| + | else: |
||
| + | return "0" |
||
| + | else: |
||
| + | return str(val) |
||
| + | |||
| + | def status_status(key): |
||
| + | with open(DATA_FILE, 'r') as file: |
||
| + | data = json.load(file) |
||
| + | flat = flatten_dict(data) |
||
| + | logger.debug(f"status_status] data: {data} flat: {flat}") |
||
| + | |||
| + | val = flat.get(key) |
||
| + | logger.debug(f"[status_status] value: {val}") |
||
| + | if key == "status_charger_running": |
||
| + | if val: |
||
| + | return "1" |
||
| + | else: |
||
| + | return "0" |
||
| + | elif key == "status_load_running": |
||
| + | if val: |
||
| + | return "1" |
||
| + | else: |
||
| + | return "0" |
||
| + | elif key == "status_states_DI1": |
||
| + | if val: |
||
| + | return "1" |
||
| + | else: |
||
| + | return "0" |
||
| + | else: |
||
| + | return str(val) |
||
| + | |||
| + | |||
| + | OIDS = { |
||
| + | # SOC |
||
| + | "1.3.6.1.4.1.418.1.1": { |
||
| + | "name": "DALYBMS-MIB::soc_total_voltage", |
||
| + | "object_key": "soc_total_voltage", |
||
| + | "max_value": 60 |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.1.2": { |
||
| + | "name": "DALYBMS-MIB::soc_current", |
||
| + | "object_key": "soc_current", |
||
| + | "max_value": 100, |
||
| + | "min_value": -80, |
||
| + | |||
| + | }, |
||
| + | "1.3.6.1.4.1.418.1.3": { |
||
| + | "name": "DALYBMS-MIB::soc_soc_percent", |
||
| + | "object_key": "soc_soc_percent", |
||
| + | }, |
||
| + | # CELL VOLTAGE |
||
| + | "1.3.6.1.4.1.418.2.1": { |
||
| + | "name": "DALYBMS-MIB::cell_voltage_range_highest_voltage", |
||
| + | "object_key": "cell_voltage_range_highest_voltage", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.2.2": { |
||
| + | "name": "DALYBMS-MIB::cell_voltage_range_highest_cell", |
||
| + | "object_key": "cell_voltage_range_highest_cell", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.2.3": { |
||
| + | "name": "DALYBMS-MIB::cell_voltage_range_lowest_voltage", |
||
| + | "object_key": "cell_voltage_range_lowest_voltage", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.3.4": { |
||
| + | "name": "DALYBMS-MIB::cell_voltage_range_lowest_cell", |
||
| + | "object_key": "cell_voltage_range_lowest_cell", |
||
| + | }, |
||
| + | # TEMPERATURE RANGE |
||
| + | "1.3.6.1.4.1.418.3.1": { |
||
| + | "name": "DALYBMS-MIB::temperature_range_highest_temperature", |
||
| + | "object_key": "temperature_range_highest_temperature", |
||
| + | "max_value": 35 |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.3.2": { |
||
| + | "name": "DALYBMS-MIB::temperature_range_highest_sensor", |
||
| + | "object_key": "temperature_range_highest_sensor", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.3.3": { |
||
| + | "name": "DALYBMS-MIB::temperature_range_lowest_temperature", |
||
| + | "object_key": "temperature_range_lowest_temperature", |
||
| + | "min_value":0 |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.3.4": { |
||
| + | "name": "DALYBMS-MIB::temperature_range_lowest_sensor", |
||
| + | "object_key": "temperature_range_lowest_sensor", |
||
| + | }, |
||
| + | # MOSFET STATUS |
||
| + | "1.3.6.1.4.1.418.4.1": { |
||
| + | "name": "DALYBMS-MIB::mosfet_status_mode", |
||
| + | "object_key": "mosfet_status_mode", |
||
| + | "get_oid_method": mosfet_status, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.4.2": { |
||
| + | "name": "DALYBMS-MIB::mosfet_status_charging_mosfet", |
||
| + | "object_key": "mosfet_status_charging_mosfet", |
||
| + | "get_oid_method": mosfet_status, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.4.3": { |
||
| + | "name": "DALYBMS-MIB::mosfet_status_discharging_mosfet", |
||
| + | "object_key": "mosfet_status_discharging_mosfet", |
||
| + | "get_oid_method": mosfet_status, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.4.4": { |
||
| + | "name": "DALYBMS-MIB::mosfet_status_capacity_ah", |
||
| + | "object_key": "mosfet_status_capacity_ah", |
||
| + | "get_oid_method": mosfet_status, |
||
| + | "max_value": 400, |
||
| + | "min_value": 0, |
||
| + | }, |
||
| + | # |
||
| + | #status_cycles |
||
| + | "1.3.6.1.4.1.418.5.1.0": { |
||
| + | "name": "DALYBMS-MIB::status_cells", |
||
| + | "object_key": "status_cells", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.5.2.0": { |
||
| + | "name": "DALYBMS-MIB::status_temperature_sensors", |
||
| + | "object_key": "status_temperature_sensors", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.5.3.0": { |
||
| + | "name": "DALYBMS-MIB::status_charger_running", |
||
| + | "object_key": "status_charger_running", |
||
| + | "get_oid_method": status_status, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.5.4.0": { |
||
| + | "name": "DALYBMS-MIB::status_load_running", |
||
| + | "object_key": "status_load_running", |
||
| + | "get_oid_method": status_status, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.5.5.0": { |
||
| + | "name": "DALYBMS-MIB::status_states_DI1", |
||
| + | "object_key": "status_states_DI1", |
||
| + | "get_oid_method": status_status, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.5.6.0": { |
||
| + | "name": "DALYBMS-MIB::status_cycles", |
||
| + | "object_key": "status_cycles", |
||
| + | }, |
||
| + | # cell_voltages |
||
| + | "1.3.6.1.4.1.418.6.1": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_1", |
||
| + | "object_key": "cell_voltages_1", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.2": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_2", |
||
| + | "object_key": "cell_voltages_2", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.3": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_3", |
||
| + | "object_key": "cell_voltages_3", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.4": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_4", |
||
| + | "object_key": "cell_voltages_4", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.5": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_5", |
||
| + | "object_key": "cell_voltages_5", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.6": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_6", |
||
| + | "object_key": "cell_voltages_6", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.7": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_6", |
||
| + | "object_key": "cell_voltages_7", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.8": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_8", |
||
| + | "object_key": "cell_voltages_8", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.9": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_9", |
||
| + | "object_key": "cell_voltages_9", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.10": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_10", |
||
| + | "object_key": "cell_voltages_10", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.11": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_11", |
||
| + | "object_key": "cell_voltages_11", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.12": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_12", |
||
| + | "object_key": "cell_voltages_12", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.13": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_13", |
||
| + | "object_key": "cell_voltages_13", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.14": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_14", |
||
| + | "object_key": "cell_voltages_14", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.15": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_15", |
||
| + | "object_key": "cell_voltages_15", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.6.16": { |
||
| + | "name": "DALYBMS-MIB::cell_voltages_16", |
||
| + | "object_key": "cell_voltages_16", |
||
| + | "min_value": 2.7, |
||
| + | }, |
||
| + | |||
| + | # temperatures |
||
| + | "1.3.6.1.4.1.418.7.1": { |
||
| + | "name": "DALYBMS-MIB::temperatures_1", |
||
| + | "object_key": "temperatures_1", |
||
| + | }, |
||
| + | "1.3.6.1.4.1.418.7.2": { |
||
| + | "name": "DALYBMS-MIB::temperatures_2", |
||
| + | "object_key": "temperatures_2", |
||
| + | }, |
||
| + | } |
||
| + | |||
| + | |||
| + | |||
| + | def get_logger(): |
||
| + | logger = logging.getLogger("snmp_test_oid") |
||
| + | if logger.handlers: |
||
| + | return logger |
||
| + | |||
| + | # logger.setLevel(logging.INFO) |
||
| + | logger.setLevel(logging.DEBUG) |
||
| + | |||
| + | handler = RotatingFileHandler( |
||
| + | LOGFILE, |
||
| + | maxBytes=200_000_000, |
||
| + | backupCount=3, |
||
| + | ) |
||
| + | fmt = logging.Formatter( |
||
| + | "%(asctime)s [%(levelname)s] %(message)s", |
||
| + | "%Y-%m-%dT%H:%M:%S", |
||
| + | ) |
||
| + | handler.setFormatter(fmt) |
||
| + | logger.addHandler(handler) |
||
| + | |||
| + | return logger |
||
| + | |||
| + | |||
| + | logger = get_logger() |
||
| + | |||
| + | # Это нужно что бы сортировать OID правильно |
||
| + | # строковая сортировка в лоб дает неправильнй результат |
||
| + | # ".1.3.6.1.2.1.33.1.10" < ".1.3.6.1.2.1.33.1.2" как строки |
||
| + | # а по SNMP-логике должно быть наоборот (10 > 2). |
||
| + | def oid_key(oid: str): |
||
| + | return tuple(int(x) for x in oid.strip(".").split(".") if x) |
||
| + | |||
| + | def batt_status_code(status_str: str) -> int: |
||
| + | """ |
||
| + | UPS-MIB upsBatteryStatus: |
||
| + | 1=unknown, 2=normal, 3=low, 4=depleted |
||
| + | """ |
||
| + | if "LB" in status_str: |
||
| + | return 3 |
||
| + | if "OB" in status_str or "OL" in status_str: |
||
| + | return 2 |
||
| + | return 1 |
||
| + | |||
| + | |||
| + | def value_for_oid(oid: str): |
||
| + | """Вернуть (type, value) или (None, None), если OID не знаем.""" |
||
| + | # По умолчанию |
||
| + | OID = OIDS.get(oid) |
||
| + | logger.debug(f"OID object: {OID}") |
||
| + | if OID: |
||
| + | logger.debug(f"[value_for_oid] OID = {OID.get('name')}: {oid}") |
||
| + | get_method = OID.get("get_oid_method", get_oid_data) |
||
| + | |||
| + | try: |
||
| + | oid_value = get_method(OID.get("object_key")) |
||
| + | except TypeError: |
||
| + | oid_value = get_method() |
||
| + | |||
| + | oid_type = OID.get("type", "string") |
||
| + | custom_multiplier = OID.get("custom_multiplier", 1) |
||
| + | logger.debug(f"[value_for_oid] custom_multiplier: {custom_multiplier}") |
||
| + | if custom_multiplier != 1: |
||
| + | try: |
||
| + | oid_value_digit = float(oid_value) |
||
| + | oid_value = oid_value_digit * custom_multiplier |
||
| + | |||
| + | except Exception as e: |
||
| + | logger.debug(f"[value_for_oid] Error: {e}, ignoring. Original value: {oid_value}") |
||
| + | |||
| + | # ингда приходят странные данные которые я хочу игнорировать |
||
| + | try: |
||
| + | oid_value_digit = float(oid_value) |
||
| + | logger.debug(f"[value_for_oid] Check min/max value for OID {oid}") |
||
| + | max_value = OID.get("max_value", oid_value_digit) |
||
| + | min_value = OID.get("min_value", oid_value_digit) |
||
| + | logger.debug(f"[value_for_oid] MAX value for OID {oid} is {max_value}") |
||
| + | logger.debug(f"[value_for_oid] MIN value for OID {oid} is {min_value}") |
||
| + | if oid_value_digit > max_value: |
||
| + | oid_value = max_value |
||
| + | |||
| + | if oid_value_digit < min_value: |
||
| + | oid_value = min_value |
||
| + | |||
| + | except Exception as e: |
||
| + | logger.debug(f"[value_for_oid] Error (not float data): {e}, ignoring. Original value: {oid_value}") |
||
| + | |||
| + | logger.debug(f"OID Data: {oid} {oid_type} {oid_value}") |
||
| + | |||
| + | |||
| + | return (oid_type, str(oid_value)) |
||
| + | |||
| + | logger.debug(f"[value_for_oid] OID is not in the list of known OIDs") |
||
| + | return (None, None) |
||
| + | |||
| + | |||
| + | def handle_get(oid: str): |
||
| + | logger.debug(f"handle GET: oid: {oid}") |
||
| + | t, v = value_for_oid(oid) |
||
| + | if t is None: |
||
| + | logger.debug(f"handle GET: type: None") |
||
| + | # Ничего не печатаем -> NoSuchInstance |
||
| + | return |
||
| + | |||
| + | logger.debug(f"handle GET: oid: {oid} type: {t} value: {v}") |
||
| + | logger.debug("Data printed to stdout 1") |
||
| + | |||
| + | print(f".{oid}") |
||
| + | print(f"{t}") |
||
| + | print(f"{v}") |
||
| + | logger.debug("Data printed to stdout") |
||
| + | |||
| + | |||
| + | |||
| + | |||
| + | def handle_getnext(request_oid: str): |
||
| + | # Преобразовать строковый OID в tuple |
||
| + | req_key = oid_key(request_oid) |
||
| + | logger.debug(f"[handle_getnext] {request_oid} {req_key}") |
||
| + | |||
| + | # Сортировка по ключу tuple |
||
| + | SORTED_OIDS = sorted(OIDS.keys(), key=oid_key) |
||
| + | |||
| + | # сначала пробуем найти точное совпадение |
||
| + | try: |
||
| + | # так как ищем след от текущего то находим индекс текущего |
||
| + | # если он не последний -- if idx + 1 < len(SORTED_OIDS) |
||
| + | idx = SORTED_OIDS.index(request_oid) |
||
| + | logger.debug(f"[handle_getnext] {request_oid} has index {idx}") |
||
| + | next_oid = SORTED_OIDS[idx + 1] if idx + 1 < len(SORTED_OIDS) else None |
||
| + | logger.debug(f"[handle_getnext] Next OID {next_oid}") |
||
| + | except ValueError: |
||
| + | # если точного совпадения нет — ищем первый > request_oid |
||
| + | next_oid = None |
||
| + | for candidate in SORTED_OIDS: |
||
| + | # |
||
| + | if oid_key(candidate) > req_key: |
||
| + | next_oid = candidate |
||
| + | logger.debug(f"[handle_getnext] Next OID {next_oid}") |
||
| + | break |
||
| + | |||
| + | if not next_oid: |
||
| + | logger.debug(f"[handle_getnext] Next OID ont found") |
||
| + | return # NoSuchInstance (ничего не печатаем) |
||
| + | |||
| + | oid_type, oid_value = value_for_oid(next_oid) |
||
| + | |||
| + | logger.debug(f"handle GET: oid: {next_oid} type: {oid_type} value: {oid_value}") |
||
| + | logger.debug("Data printed to stdout") |
||
| + | print(f".{next_oid}") |
||
| + | print(f"{oid_type}") |
||
| + | print(f"{oid_value}") |
||
| + | logger.debug("Data printed to stdout") |
||
| + | |||
| + | |||
| + | def main(): |
||
| + | logger.debug(f"sys.argv: {sys.argv}") |
||
| + | if len(sys.argv) < 3: |
||
| + | logger.debug(f"sys.argv should be 3 arguments, nothing to do, exiting") |
||
| + | return |
||
| + | |||
| + | cmd = sys.argv[1] |
||
| + | # Remove leading dot if any |
||
| + | oid = sys.argv[2] |
||
| + | oid = oid.lstrip('.') |
||
| + | logger.debug(f"cmd: {cmd}. OID: {oid}") |
||
| + | |||
| + | if cmd == "-g": |
||
| + | logger.debug("Handle get") |
||
| + | handle_get(oid) |
||
| + | elif cmd == "-n": |
||
| + | logger.debug("Handle get next") |
||
| + | handle_getnext(oid) |
||
| + | # SET не поддерживаем, ничего не печатаем |
||
| + | else: |
||
| + | logger.debug("Handle is not configured") |
||
| + | |||
| + | if __name__ == "__main__": |
||
| + | logger.info("Start") |
||
| + | main() |
||
| + | </PRE> |
||
| + | |||
| + | }} |
||
| + | =Zabbix Template= |
||
| + | Максимально просто, никаких дискавери, все элемент просто получаются по OID |
||
| + | {{#spoiler:show=template.yaml| |
||
| + | <PRE> |
||
| + | zabbix_export: |
||
| + | version: '7.0' |
||
| + | template_groups: |
||
| + | - uuid: 3dcd5bbe90534f9e8eb5c2d53756af63 |
||
| + | name: Templates/Power |
||
| + | templates: |
||
| + | - uuid: 6044b86a15594724ab3ed309627776eb |
||
| + | template: 'Template DALY BMS by SNMP' |
||
| + | name: 'Template DALY BMS by SNMP' |
||
| + | groups: |
||
| + | - name: Templates/Power |
||
| + | items: |
||
| + | - uuid: cbe5ae7ef5064a3789d59212d284648e |
||
| + | name: cell_voltages_1 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.1 |
||
| + | key: cell_voltages_1 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: bd2b5a652688438482d824e57febca0e |
||
| + | name: cell_voltages_2 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.2 |
||
| + | key: cell_voltages_2 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: ccdd99bd03e34afaa9f566fd903ab2e6 |
||
| + | name: cell_voltages_3 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.3 |
||
| + | key: cell_voltages_3 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: ea62e350c5e14fa3b349a4f232f9ce94 |
||
| + | name: cell_voltages_4 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.4 |
||
| + | key: cell_voltages_4 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: aecac8b9da0847b7b81a04cf486b47f9 |
||
| + | name: cell_voltages_5 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.5 |
||
| + | key: cell_voltages_5 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 1f7e3b69c5054187b1b0ad20eb527db3 |
||
| + | name: cell_voltages_6 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.6 |
||
| + | key: cell_voltages_6 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 6f86549b7c2b4a4b90af311f39b0fc7c |
||
| + | name: cell_voltages_7 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.7 |
||
| + | key: cell_voltages_7 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: d5a7c8ea041a48a1899608c0abc27664 |
||
| + | name: cell_voltages_8 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.8 |
||
| + | key: cell_voltages_8 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 594d43cdce694ac894b12e9b25e2218d |
||
| + | name: cell_voltages_9 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.9 |
||
| + | key: cell_voltages_9 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: f23a34a1a6684001be0d79907820ee0e |
||
| + | name: cell_voltages_10 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.10 |
||
| + | key: cell_voltages_10 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: c4ce669ac14a4d4393ec82c573e7e51d |
||
| + | name: cell_voltages_11 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.11 |
||
| + | key: cell_voltages_11 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: c1a245d1bf9e4abdb57f74471fea0247 |
||
| + | name: cell_voltages_12 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.12 |
||
| + | key: cell_voltages_12 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 6ed6ef135b65454eb08822d495bb9a5e |
||
| + | name: cell_voltages_13 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.13 |
||
| + | key: cell_voltages_13 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 4ecc6516e79444eda478c2d69978978c |
||
| + | name: cell_voltages_14 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.14 |
||
| + | key: cell_voltages_14 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 9d546a8decda4fa58938daf3d004ba70 |
||
| + | name: cell_voltages_15 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.15 |
||
| + | key: cell_voltages_15 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 8e17e4caa0bf4f168a40414826b6f76f |
||
| + | name: cell_voltages_16 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.6.16 |
||
| + | key: cell_voltages_16 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: a929ffda17dd43fd9ec9fe181ffbfa23 |
||
| + | name: cell_voltage_range_highest_cell |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.2.2 |
||
| + | key: cell_voltage_range_highest_cell |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 5305259c5f084a1fa7d22a224c304734 |
||
| + | name: cell_voltage_range_highest_voltage |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.2.1 |
||
| + | key: cell_voltage_range_highest_voltage |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 7ad75f03d7334606a9ed130f0e51ae56 |
||
| + | name: cell_voltage_range_lowest_cell |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.2.4 |
||
| + | key: cell_voltage_range_lowest_cell |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: b861dd43f76b4b4c8d5f780f761c7c1c |
||
| + | name: cell_voltage_range_lowest_voltage |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.2.3 |
||
| + | key: cell_voltage_range_lowest_voltage |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 3d1c490069994842853e8f9606352cbd |
||
| + | name: mosfet_status_capacity_ah |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.4.4 |
||
| + | key: mosfet_status_capacity_ah |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: 'A*H' |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 6ccca7e31baa4965aed35572664ed167 |
||
| + | name: mosfet_status_charging_mosfet |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.4.2 |
||
| + | key: mosfet_status_charging_mosfet |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 3ee90a36692c483c992eae93b12a7108 |
||
| + | name: mosfet_status_discharging_mosfet |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.4.3 |
||
| + | key: mosfet_status_discharging_mosfet |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: fe31f1f091ca4daeb777d99e90ab0d83 |
||
| + | name: mosfet_status_mode |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.4.1 |
||
| + | key: mosfet_status_mode |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 56f94235dff545f99a63a70b8acdfe61 |
||
| + | name: soc_current |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.1.2 |
||
| + | key: soc_current |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: A |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 172212b88fef4cbebec583d11dc5b5cd |
||
| + | name: soc_soc_percent |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.1.3 |
||
| + | key: soc_soc_percent |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: '%' |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 95eeef199f8f40a9a18caaa9a9665378 |
||
| + | name: soc_total_voltage |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.1.1 |
||
| + | key: soc_total_voltage |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: V |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 4571efd987634eeb9ab5ace33fe5997a |
||
| + | name: status_cells |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.5.1.0 |
||
| + | key: status_cells |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 996ed11a787c45c981b9fad4316976a1 |
||
| + | name: status_charger_running |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.5.3.0 |
||
| + | key: status_charger_running |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 08569b139e404c07b93ecc9fe8c0fd55 |
||
| + | name: status_cycles |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.5.6.0 |
||
| + | key: status_cycles |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: a16015a367d14db49a59e0e62eafae68 |
||
| + | name: status_load_running |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.5.4.0 |
||
| + | key: status_load_running |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 89d8714254214a0fb720608fb1c5bc06 |
||
| + | name: status_states_DI1 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.5.5.0 |
||
| + | key: status_states_DI1 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 830947cb28f64816a60ecb6a2a47c8c6 |
||
| + | name: status_temperature_sensors |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.5.2.0 |
||
| + | key: status_temperature_sensors |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 62aee0d7f2f945d38a1160647b58729e |
||
| + | name: temperatures_1 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.7.1 |
||
| + | key: temperatures_1 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: C |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: e9223f34756c4ceabbf1f71f6e162d15 |
||
| + | name: temperatures_2 |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.7.2 |
||
| + | key: temperatures_2 |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: C |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 5ad90b295e9e4fc7b17981cd986bdf8d |
||
| + | name: temperature_range_highest_sensor |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.3.2 |
||
| + | key: temperature_range_highest_sensor |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: b51f6da831bf45409c6043a995a0d262 |
||
| + | name: temperature_range_highest_temperature |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.3.1 |
||
| + | key: temperature_range_highest_temperature |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: C |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 15ea5da6198440b382bb0042481ffafd |
||
| + | name: temperature_range_lowest_sensor |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.3.4 |
||
| + | key: temperature_range_lowest_sensor |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: C |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | - uuid: 9ebe055204224cee82bd4c56aff4708f |
||
| + | name: temperature_range_lowest_temperature |
||
| + | type: SNMP_AGENT |
||
| + | snmp_oid: 1.3.6.1.4.1.418.3.3 |
||
| + | key: temperature_range_lowest_temperature |
||
| + | history: 365d |
||
| + | value_type: FLOAT |
||
| + | units: C |
||
| + | tags: |
||
| + | - tag: component |
||
| + | value: power |
||
| + | tags: |
||
| + | - tag: class |
||
| + | value: power |
||
| + | - tag: target |
||
| + | value: BMS |
||
| + | - tag: target |
||
| + | value: DALY |
||
| + | dashboards: |
||
| + | - uuid: bc012219291246a990a28971eb210477 |
||
| + | name: 'Daly BMS' |
||
| + | display_period: '120' |
||
| + | pages: |
||
| + | - widgets: |
||
| + | - type: svggraph |
||
| + | name: 'BMS Voltage / Percent' |
||
| + | width: '72' |
||
| + | height: '5' |
||
| + | fields: |
||
| + | - type: STRING |
||
| + | name: ds.0.color |
||
| + | value: FF465C |
||
| + | - type: STRING |
||
| + | name: ds.0.items.0 |
||
| + | value: soc_total_voltage |
||
| + | - type: INTEGER |
||
| + | name: ds.1.axisy |
||
| + | value: '1' |
||
| + | - type: STRING |
||
| + | name: ds.1.color |
||
| + | value: FFD54F |
||
| + | - type: STRING |
||
| + | name: ds.1.items.0 |
||
| + | value: soc_soc_percent |
||
| + | - type: STRING |
||
| + | name: reference |
||
| + | value: PHJOY |
||
| + | - type: svggraph |
||
| + | name: 'BMS Cells Voltage' |
||
| + | 'y': '5' |
||
| + | width: '72' |
||
| + | height: '5' |
||
| + | fields: |
||
| + | - type: STRING |
||
| + | name: ds.0.color |
||
| + | value: 4000FF |
||
| + | - type: INTEGER |
||
| + | name: ds.0.fill |
||
| + | value: '0' |
||
| + | - type: STRING |
||
| + | name: ds.0.items.0 |
||
| + | value: cell_voltages_1 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.1 |
||
| + | value: cell_voltages_2 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.2 |
||
| + | value: cell_voltages_3 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.3 |
||
| + | value: cell_voltages_4 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.4 |
||
| + | value: cell_voltages_5 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.5 |
||
| + | value: cell_voltages_6 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.6 |
||
| + | value: cell_voltages_7 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.7 |
||
| + | value: cell_voltages_8 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.8 |
||
| + | value: cell_voltages_9 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.9 |
||
| + | value: cell_voltages_10 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.10 |
||
| + | value: cell_voltages_11 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.11 |
||
| + | value: cell_voltages_12 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.12 |
||
| + | value: cell_voltages_13 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.13 |
||
| + | value: cell_voltages_14 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.14 |
||
| + | value: cell_voltages_15 |
||
| + | - type: STRING |
||
| + | name: ds.0.items.15 |
||
| + | value: cell_voltages_16 |
||
| + | - type: INTEGER |
||
| + | name: ds.1.axisy |
||
| + | value: '1' |
||
| + | - type: STRING |
||
| + | name: ds.1.color |
||
| + | value: FF4000 |
||
| + | - type: STRING |
||
| + | name: ds.1.items.0 |
||
| + | value: cell_voltage_range_highest_voltage |
||
| + | - type: INTEGER |
||
| + | name: ds.1.type |
||
| + | value: '1' |
||
| + | - type: INTEGER |
||
| + | name: ds.2.axisy |
||
| + | value: '1' |
||
| + | - type: STRING |
||
| + | name: ds.2.color |
||
| + | value: 00897B |
||
| + | - type: STRING |
||
| + | name: ds.2.items.0 |
||
| + | value: cell_voltage_range_lowest_voltage |
||
| + | - type: INTEGER |
||
| + | name: ds.2.type |
||
| + | value: '1' |
||
| + | - type: STRING |
||
| + | name: lefty_max |
||
| + | value: '3.8' |
||
| + | - type: STRING |
||
| + | name: lefty_min |
||
| + | value: '2.7' |
||
| + | - type: INTEGER |
||
| + | name: legend_lines |
||
| + | value: '10' |
||
| + | - type: INTEGER |
||
| + | name: legend_lines_mode |
||
| + | value: '1' |
||
| + | - type: STRING |
||
| + | name: reference |
||
| + | value: ZATVX |
||
| + | - type: STRING |
||
| + | name: righty_max |
||
| + | value: '3.8' |
||
| + | - type: STRING |
||
| + | name: righty_min |
||
| + | value: '2.7' |
||
| + | - type: svggraph |
||
| + | name: 'SOC current' |
||
| + | 'y': '10' |
||
| + | width: '72' |
||
| + | height: '5' |
||
| + | fields: |
||
| + | - type: STRING |
||
| + | name: ds.0.color |
||
| + | value: FF465C |
||
| + | - type: STRING |
||
| + | name: ds.0.items.0 |
||
| + | value: soc_current |
||
| + | - type: STRING |
||
| + | name: lefty_max |
||
| + | value: '80' |
||
| + | - type: STRING |
||
| + | name: lefty_min |
||
| + | value: '-80' |
||
| + | - type: STRING |
||
| + | name: reference |
||
| + | value: BVHUJ |
||
| + | - type: INTEGER |
||
| + | name: righty |
||
| + | value: '0' |
||
| + | - type: svggraph |
||
| + | name: mosfet_status_capacity_ah |
||
| + | 'y': '15' |
||
| + | width: '72' |
||
| + | height: '5' |
||
| + | fields: |
||
| + | - type: STRING |
||
| + | name: ds.0.color |
||
| + | value: FF465C |
||
| + | - type: STRING |
||
| + | name: ds.0.items.0 |
||
| + | value: mosfet_status_capacity_ah |
||
| + | - type: STRING |
||
| + | name: lefty_max |
||
| + | value: '300' |
||
| + | - type: STRING |
||
| + | name: lefty_min |
||
| + | value: '0' |
||
| + | - type: STRING |
||
| + | name: reference |
||
| + | value: QSQWU |
||
| + | - type: INTEGER |
||
| + | name: righty |
||
| + | value: '0' |
||
| + | - type: svggraph |
||
| + | name: mosfet_status_charging_mosfet |
||
| + | 'y': '20' |
||
| + | width: '72' |
||
| + | height: '5' |
||
| + | fields: |
||
| + | - type: STRING |
||
| + | name: ds.0.color |
||
| + | value: FF465C |
||
| + | - type: STRING |
||
| + | name: ds.0.items.0 |
||
| + | value: mosfet_status_charging_mosfet |
||
| + | - type: STRING |
||
| + | name: ds.0.items.1 |
||
| + | value: mosfet_status_discharging_mosfet |
||
| + | - type: STRING |
||
| + | name: ds.0.items.2 |
||
| + | value: mosfet_status_mode |
||
| + | - type: STRING |
||
| + | name: reference |
||
| + | value: DYIIC |
||
| + | - type: INTEGER |
||
| + | name: righty |
||
| + | value: '0' |
||
| + | - type: svggraph |
||
| + | name: Temperature |
||
| + | 'y': '25' |
||
| + | width: '71' |
||
| + | height: '5' |
||
| + | fields: |
||
| + | - type: STRING |
||
| + | name: ds.0.color |
||
| + | value: FF465C |
||
| + | - type: STRING |
||
| + | name: ds.0.items.0 |
||
| + | value: temperature_range_highest_temperature |
||
| + | - type: STRING |
||
| + | name: ds.0.items.1 |
||
| + | value: temperature_range_lowest_temperature |
||
| + | - type: STRING |
||
| + | name: ds.1.color |
||
| + | value: FFD54F |
||
| + | - type: STRING |
||
| + | name: ds.1.items.0 |
||
| + | value: temperatures_1 |
||
| + | - type: STRING |
||
| + | name: ds.1.items.1 |
||
| + | value: temperatures_2 |
||
| + | - type: STRING |
||
| + | name: lefty_max |
||
| + | value: '35' |
||
| + | - type: STRING |
||
| + | name: lefty_min |
||
| + | value: '0' |
||
| + | - type: STRING |
||
| + | name: reference |
||
| + | value: XQRWM |
||
| + | - type: INTEGER |
||
| + | name: righty |
||
| + | value: '0' |
||
| + | graphs: |
||
| + | - uuid: 2e63e3e1831a45e48a1ae46b434ec79d |
||
| + | name: 'Battery Total SOC Voltage' |
||
| + | graph_items: |
||
| + | - color: 1A7C11 |
||
| + | calc_fnc: ALL |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: soc_total_voltage |
||
| + | - uuid: f1e954331c50430780493379b967be65 |
||
| + | name: 'Cell Voltages' |
||
| + | yaxismax: '0' |
||
| + | show_work_period: 'NO' |
||
| + | show_triggers: 'NO' |
||
| + | type: PIE |
||
| + | graph_items: |
||
| + | - color: '274482' |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_1 |
||
| + | - sortorder: '1' |
||
| + | color: 1A7C11 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_2 |
||
| + | - sortorder: '2' |
||
| + | color: F63100 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_3 |
||
| + | - sortorder: '3' |
||
| + | color: 2774A4 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_4 |
||
| + | - sortorder: '4' |
||
| + | color: A54F10 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_5 |
||
| + | - sortorder: '5' |
||
| + | color: FC6EA3 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_6 |
||
| + | - sortorder: '6' |
||
| + | color: 6C59DC |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_7 |
||
| + | - sortorder: '7' |
||
| + | color: AC8C14 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_8 |
||
| + | - sortorder: '8' |
||
| + | color: 611F27 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_9 |
||
| + | - sortorder: '9' |
||
| + | color: F230E0 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_10 |
||
| + | - sortorder: '10' |
||
| + | color: 5CCD18 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_11 |
||
| + | - sortorder: '11' |
||
| + | color: BB2A02 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_12 |
||
| + | - sortorder: '12' |
||
| + | color: 5A2B57 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_13 |
||
| + | - sortorder: '13' |
||
| + | color: 89ABF8 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_14 |
||
| + | - sortorder: '14' |
||
| + | color: 7EC25C |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_15 |
||
| + | - sortorder: '15' |
||
| + | color: 2B5429 |
||
| + | calc_fnc: MIN |
||
| + | item: |
||
| + | host: 'Template DALY BMS by SNMP' |
||
| + | key: cell_voltages_16 |
||
| + | </PRE> |
||
| + | }} |
||
Текущая версия на 17:54, 15 января 2026
Daly BMS
Идея а том что бы снимать данные и складывать в заббикс
- дернуть скрипт кроном раз в минуту
batt-dale-snmp.py, результат работы сохранить в файл (/var/lib/snmp/daly.json) - отдать результат через
SNMP pass
Прежде чем начать
У меня сгорел "родной" переходник на котором был распаян разъем (фото нет, и я не знаю как он называется - и нигде не смог найти такой!)
Для замены использовал такой переходник:
|
У меня напряжение было 3.3В на пинах RX/TX со стороны BMC - отсюда я сделал вывод что надо переключить UART-конвертер в 3.3V (джампер) |
Dalybms на python.
В консоли устанавливаем python-pip
sudo apt install python3-pip
Далее создать virtualenv и устанавливаем dalybms
pip3 install dalybms
для работы с uat портом и mqtt сервером ставим соответствующие пакеты
pip3 install pyserial
Модуль для MQTT по желанию (мне не был нужен)
pip3 install paho-mqtt
необходимо так же установить mqtt сервер если он ещё не установлен и нужен <ЗКУ> sudo apt install mosquitto
на этом установка завершена подключаем нашу BMS к uart порту либо через usb-uart адаптер либо через uart разъем на одноплатнике (необходимо включить порт в настройках), далее будет рассмотрено подключение через usb-uart Подключаем следующим образом:
BMS — UART GND — GND RX — TX TX — RX
После подключения usb-uart адаптера смотрим имя адаптера введя команду
ls -n /dev/ttyU*
должен показать устройства
crw-rw—- 1 0 20 188, 0 Feb 24 21:12 /dev/ttyUSB0 crw-rw—-+ 1 0 20 188, 0 Feb 24 19:57 /dev/ttyUSB1
где /dev/ttyUSB0 и /dev/ttyUSB1 это наши USB устройства, у меня их 2 и с этим могут быть проблемы поскольку при перезагрузки они могут иметь имена наоборот и после перезагрузки устройства не будут работать. Для того чтобы это исключить мы будем обращаться к устройства по ID, получаем id наших устройств, вводим команду:
ls -n /dev/serial/by-id/*
получаем список
lrwxrwxrwx 1 0 0 13 Sep 8 09:58 /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_12967c31b312ec11b6da21c7bd930c07-if00-port0 -> ../../ttyUSB0 lrwxrwxrwx 1 0 0 13 Feb 24 22:18 /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB1
ls -n /dev/serial/by-id/* lrwxrwxrwx 1 0 0 13 Jan 12 15:29 /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A5XK3RJT-if00-port0 -> ../../ttyUSB0
синим это наши устройства, в дальнейшем в конфигах и командах можно использовать как /dev/ttyUSB0 так и полный путь к id устройству. У меня как видно Sonoff Zigbee USB стик и USB-UART адаптер на чипе CP2102 (USB-UART адаптеры бывают на разных чипах) Теперь проверим соединение с нашей BMS.
daly-bms-cli -d /dev/ttyUSB0 --all
или можно по id,
daly-bms-cli -d /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 --all
мы получим все параметры. Если данные не получены то возможно Ваша BMS сделана на другом чипе, для этого надо добавить флаг —sinowealth
daly-bms-cli -d /dev/ttyUSB0 --all --sinowealth
Теперь есть несколько вариантов просмотра данных, не зависимо от того какую систему домашней автоматизации Вы используете мы будем передавать данные в систему домашней автоматизации по популярному протоколу mqtt, команда которую мы написали выше будет иметь вид:
daly-bms-cli -d /dev/ttyUSB0 --all --mqtt
collect_batt_status.sh
Запускаю из крона (/etc/cron.d/batt_dale_status):
*/3 * * * * root /etc/nut/collect_batt_status.sh
Конечный результат в файле /var/lib/snmp/daly.json (который разбираем для SNMP)
#!/usr/bin/env bash
DEV="/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A5XK3RJT-if00-port0"
sudo -u nut \
/usr/local/virtualenvs/daly-bms-cli/bin/python3 \
/usr/local/virtualenvs/daly-bms-cli/bin/daly-bms-cli -d ${DEV} --all > /tmp/daly.json 2>>/var/lib/snmp/daly.err && \
mv /tmp/daly.json /var/lib/snmp/daly.json
SNMP
Для того что бы дергать скрипт на пайтоне через SNMP и отдавать данные заббиксу делаю так
pass .1.3.6.1.4.1.418 /etc/nut/batt-dale-snmp.py
batt-dale-snmp.py
Zabbix Template
Максимально просто, никаких дискавери, все элемент просто получаются по OID