Статья

AppDaemon. Часть 2

Как установить AppDaemon и первый запуск читайте тут.

И так рассмотрим вариант когда хочется чего то необычного и запихнуть это в Home Assistants (далее HA).

Например: я купил китайский измеритель мощности переменного тока PZEM-016 он отдает данные по MODBUS, так как cчётчик электроэнергии и сервер находились друг от друга далеко пришлось все это подрубить через конвертер USR-TCP232-304 RS485 => TCP/IP.

К сожалению в HA modbus был какой-то кривой и HA падал непонятно по каким причинам из за этой библиотеки. Пришлось запилить все на AppDaemon.

Первое что делаем это создаем сенсоры в HA.

Добавляем в configuration.yaml следующее:

sensor: - platform: template sensors: t_voltage: friendly_name: 'Счетчик(В)' unit_of_measurement: 'V' value_template: '' t_ampers: friendly_name: 'Счетчик(А)' unit_of_measurement: 'A' value_template: '' t_power_month: friendly_name: 'Месяц(Вт/ч)' unit_of_measurement: 'Wh' value_template: '' t_power: friendly_name: 'Счетчик(Вт)' unit_of_measurement: 'W' value_template: '' t_power_hr: friendly_name: 'Счетчик(Вт/ч)' unit_of_measurement: 'Wh' value_template: '{' t_freq: friendly_name: 'Счетчик(Гц)' unit_of_measurement: 'Hz' value_template: ''

А теперь займемся AppDaemon.

  • Для начала сделаем следующее, создадим файл requirements.txt в корне конфига AppDaemon (далее AD) и добавим строчку pymodbus==2.2.0, после этого лучше перезагрузить AD.
  • Для удобства создаем например папку modbus в папке apps.
  • Далее в папке modbus создаем два файла modbus.yaml и modbus.py.

#modbus.yaml modbus_power: module: modbus class: ModbusPower

#modbus.py import datetime import appdaemon.plugins.hass.hassapi as hass # # Hellow World App # # Args: # from pymodbus.client.sync import ModbusTcpClient as ModbusClient from pymodbus.transaction import ModbusRtuFramer as ModbusFramer class ModbusPower(hass.Hass): def initialize(self): self.log("Modbus App") #эта функция запускает любую функцию (в нашем случае callback) #в определенное время в нашем случае прямо сейчас datetime.datetime.now() #каждые 10 секунд self.run_every(self.callback, datetime.datetime.now(), 10) def callback(self, kwargs): try: #подключаемся к клиенту который отдает нам данные по протоколу modbus TCP client = ModbusClient('192.168.88.18', port=123, framer=ModbusFramer) client.connect() #считываем данные rr = client.read_input_registers(address=0, count=10, unit=0xF8) # вот тут мы раскладываем регистры, применяем коэффициенты и округляем voltage = round((rr.registers[0] * 0.1), 1) ampers = round((rr.registers[1] * 0.001), 3) power = round((rr.registers[3] * 0.1), 1) power_hr = rr.registers[5] freq = round((rr.registers[7] * 0.1), 1) # set_state функция которая передает параметры нашим сенсорам self.set_state('sensor.t_voltage', state=voltage) self.set_state('sensor.t_ampers', state=ampers) self.set_state('sensor.t_power', state=power) self.set_state('sensor.t_power_hr', state=power_hr) self.set_state('sensor.t_freq', state=freq) except Exception as inst: # вот это я создал так как иногда вываливает ошибку и скрипт вываливается self.error('Modbus error {}'.format(inst))

Давайте рассмотрим как еще можно создать сенсоры с помощью AppDaemon, a точнее создаем на лету без конфигурации Home Assistant. Тут недавно в чате обсуждали как вытаскивать данные с роутеров Mikrotik и для этого надо было создавать WEB сервер. Сделаем тоже самое только будем использовать библиотеку routeros для python и без WEB сервера.

  • добавляем в requirements.txt еще одну строчку

    librouteros==2.3.1

  • создадим папку mikrotik в папке app и в нее добавим два файла miktotik.yaml и mikrotik.py.

#mikrotik.yaml Mikrotik: module: mikrotik class: Mikrotik

import datetime import re from librouteros import connect import appdaemon.plugins.hass.hassapi as hass import time # # Mikrotik App # # Args: # class Mikrotik(hass.Hass): def initialize(self): self.log("App Mikrotik") self.run_every(self.callback, datetime.datetime.now(), 10) self.ip_address = ["192.168.0.2"] # тут пишем ip вашего роутера self.user = 'admin' #логин self.passw = 'password' #пароль def callback(self, kwargs): api = connect(username=self.user, password=self.passw, host=self.ip_address[0]) info_eth = api(cmd="/interface/print") for eth in info_eth: sensor_name = 'binary_sensor.mikrotik_' + re.sub(r"\W", "", eth['name'], flags=re.I) eth['device_class'] = 'connectivity' state = "off" if eth['running'] is True: state = 'on' self.set_state(sensor_name, state=state, attributes=eth) self.log(eth) info_system = api(cmd="/system/resource/print") self.set_state('sensor.mikrotik_info', state='running', attributes=info_system[0]) info_ddns = api(cmd="/ip/cloud/print") self.set_state('sensor.mikrotik_ddns', state=info_ddns[0]['public-address'], attributes=info_ddns[0])

В итоге получается вот такая вот красота


У меня вот такая ошибка. Разобраться не получается. Только начал изучение

2019-09-17 10:53:18.006418 WARNING AppDaemon: ------------------------------------------------------------
2019-09-17 10:53:18.007006 WARNING AppDaemon: Unexpected error in worker for App Mikrotik:
2019-09-17 10:53:18.008385 WARNING AppDaemon: Worker Ags: {'name': 'Mikrotik', 'id': UUID('014e40a4-3c2e-4b09-886c-608dced6c1bc'), 'type': 'timer', 'function': <bound method Mikrotik.callback of <mikrotik.Mikrotik object at 0x7fc9215cdf28>>, 'kwargs': {'interval': 10}}
2019-09-17 10:53:18.009074 WARNING AppDaemon: ------------------------------------------------------------
2019-09-17 10:53:18.011095 WARNING AppDaemon: Traceback (most recent call last):
File "/usr/lib/python3.7/site-packages/appdaemon/appdaemon.py", line 586, in worker
funcref(self.sanitize_timer_kwargs(app, args["kwargs"]))
File "/config/appdaemon/apps/mikrotik/mikrotik.py", line 26, in callback
api = connect(username=self.user, password=self.passw, host=self.ip_address[0])
TypeError: 'module' object is not callable

2019-09-17 10:53:18.012167 WARNING AppDaemon: ------------------------------------------------------------

Странно как-то. Сейчас еще раз так же провернул все нормально. Как стоит AppDaemon? и какая версия?

AppDaemon версии 4.0.3 стоит как add-on в Hass.io, которая установлена в Docker. Устанавливается librouteros версии 2.3.0 

Последняя версия стабильная 3.0.5, 4 версия еще бета и судя по всему там много изменений, по этому оно видимо и не работает

Мне предлагают только эту версию. Наверно буду уходить с Hass.io. 

ссылка на установку битая

Подскажите, после запуска AppDaemon и перезапуска HA объекты в системе с именем, содержащим mikrotik, должны сразу появиться? Не нужно в конфигурации добавлять компоненту как описано на https://www.home-assistant.io/components/mikrotik/">https://www.home-assistant.io/...?


У меня HADashboard на порту 5050 доступен (т.е.демон стартовал), но ничего не появилось в HA.

В логе контейнера вижу сообщение об ошибке подключения к HA версии
0.95.4

:

Requirement already up-to-date: librouteros==2.3.1 in /usr/local/lib/python3.6/site-packages (from -r /conf/requirements.txt (line 1)) (2.3.1)

2019-09-18 19:59:28.480442 INFO AppDaemon Version 3.0.5 starting

2019-09-18 19:59:28.480776 INFO Configuration read from: /conf/appdaemon.yaml

2019-09-18 19:59:28.482510 INFO AppDaemon: Starting Apps

2019-09-18 19:59:28.486005 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin

2019-09-18 19:59:28.679030 INFO AppDaemon: HASS: HASS Plugin Initializing

2019-09-18 19:59:28.679491 INFO AppDaemon: HASS: HASS Plugin initialization complete

2019-09-18 19:59:28.679999 INFO Starting Dashboards

2019-09-18 19:59:28.688108 INFO API is disabled

2019-09-18 19:59:28.732934 WARNING AppDaemon: HASS: Disconnected from Home Assistant, retrying in 5 seconds

2019-09-18 19:59:33.743685 WARNING AppDaemon: HASS: Disconnected from Home Assistant, retrying in 5 seconds

Куда копать? Как можно продиагностировать дальше?

так у тебя вобще не подключился к HA, покажи конфиг appdaemon.yaml

Вот конфиг. Мне и непонятно, почему демон не хочет подключаться. Другие внешние сервисы работают (Алекса, Яндекс, Телеграм и т.д.)

log:


  errorfile: STDERR


  logfile: STDOUT


 


appdaemon:


  threads: 10


  plugins:


    HASS:


  type: hass


      ha_url: https://192.168.192.25:8123


      token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIwM2I0NmVmNmI1OWE0YmEyOGVlZmFmOTg0MmJkYTBlMyIsImlhdCI6MTU2ODc1NDk0OCwiZXhwIjoxODg0MTE0OTQ4fQ.UpnbY1F5AdBsHSPp1CCUztZm3hUscUNYxt0cZhfysSM


hadashboard:


  dash_url: http://192.168.192.25:5050



Тут получается идешь по https и по локальному адресу сертификат не валидный. добавь после token 

token: xxxxxxxxxxxxxxxxxxxxxxxxx
cert_verify: False

Спасибо за подсказку.
Но добавление этого параметра не помогло :( . 


Все равно

в логе контейнера
идут сообщения


2019-09-19 17:28:55.902354 INFO AppDaemon: HASS: Connected to Home Assistant 0.95.4                  


2019-09-19 17:28:55.910182 WARNING AppDaemon: HASS: Error in authentication                             


2019-09-19 17:28:55.910614 WARNING AppDaemon: HASS: Disconnected from Home Assistant, retrying in 5 seconds


В логе самого HA

2019-09-19
20:27:10 WARNING (MainThread) [homeassistant.components.http.ban] Login attempt
or request with invalid authentication from 172.17.0.2

Пробовал разные токены. Все равно не подключается. Пробовал давать в териминале на синолоджи команду
curl -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJlODU4Y2Y4NThhMGQ0ZWM3OGQ3MzVjOTM0N2M3MmY3ZSIsImlhdCI6MTU1NTUzNDI5NiwiZXhwIjoxODcwODk0Mjk2fQ._Mhute7Z4dGcErQAVPU9PxGUslp4qiw0KGkY1moCPjwa" \

       -H "Content-Type: application/json" https://hellad.noip.me:88/api/">https://мой.домен.здесь:88/api/


Получаю ответ


401: Unauthorized

Видимо надо дальше копать в сторону сертификатов и провайдеров авторизации HA. Но вот куда именно не совсем понимаю...

А что измеряется в Вт/ч?

китайский измеритель мощности переменного тока PZEM-016 он отдает данные по MODBUS

Это был сарказм. Вы неверно используете единицы измерения. Потребленная мощность измеряется в ВТ*ч.



Хорошо бы Микротик файл обновить


У меня все запускает но красивых картинок нет


https://ibb.co/2SgsF8q">https://sprut.ai/static/media/cache/00/46/21/5/2711893/50260/1000x_image.png?1580143522" alt="1000x_image.png?1580143522" title="1000x_image.png?1580143522" />

а YAML файлик добавил?

да и  ру

у тебя не стартануло почемуто, написано же "no app description found"

Если все было ок то написало бы в логах что то типа Started App Mikrotik

какие права должны быть на файлах ?

и

тут должно ведь все лежать 

https://imgbb.com/">https://i.ibb.co/pjP3JL6/2.jpg" alt="2" border="0" />

ошибся в названии файлов, или файл переименуй или в yaml  

 module: miktotik

ааа  СПС !!! 

Подскажи  теперь вот такое 

как подключить ModuleNotFoundError: No module named 'librouteros'

https://ibb.co/XJy3bYM">https://i.ibb.co/DKG8trT/2.jpg" alt="2" border="0" />

Вот это для кого написано?

добавляем в requirements.txt еще одну строчку librouteros==2.3.1

или делай pip3 install librouteros==2.3.1



строчку добавил сразу

https://ibb.co/VYyTdZT">https://i.ibb.co/F4vz9Mz/image.jpg" alt="image" border="0" />

если ставил не через docker а я так понял что в venv, то тогда заходишь в venv и руками pip3 install нужная библиотека

( я так думаю, просто ни разу не ставил AppDaemon через venv)

+1

вот  если еше подскажете как зайти в 

venv

так а как ты устанавливал AppDaemon лучше расскажи?

 через venv.. твоя статья.. только версия уже 104.

ааа блин, это не моя статья ))))


но смысл такой


sudo -u homeassistant -H -s
cd /srv/appdaemon
source bin/activate
pip install librouteros==2.3.1
или
pip3 install librouteros==2.3.1

Вроде установилось 


но


вообше ругается  что то  не так...  значки должны в НА появиться в неиспользованных ?


https://ibb.co/LzbG987">https://i.ibb.co/kgkdqxC/3.jpg" alt="3" border="0" />

У тебя AppDaemon v4 стоит, там немного по другому надо конфиг, я пол ночи убил чтоб переехать  на 4 версию и то пришлось собирать свой image в докере

self.run_every(self.callback, datetime.datetime.now(), 10)

У вас такая конструкция стабильно работает? У меня ругается что запуск в прошлом не возможен:

File "/usr/lib/python3.8/site-packages/appdaemon/adapi.py", line 2476, in run_every raise ValueError("start cannot be in the past")

Было такое. Это скорее всего в докере не правильно стоит время и TimeZone


Вернуться назад
Вернуться назад