У меня есть уже данные в Home Assistant, но давно хотел сделать автоматическую отправку показаний. Актуально для жителей Челябинска и области, возможно еще где-то используется сервис voda.uu.ru. Первое, что нужно сделать - получить номера ИПУ. Возможно, в будущем допишу скрипт и это будет делаться автоматически, но сейчас придется делать вручную.
Получаем номера ИПУ
Переходим на сайт http://lk.voda.uu.ru -> Передать показания.Нажимаем F12, Переходим на вкладку network, ставим галочку preserver log.Вводим показания по одному счетчику, можно изменить сотые или десятые.Нажимаем кнопку Передать показания. В списке запросов ищем input/ ->Вкаладка Headers ->Reqest Headers.Находим значние counter_list[]: 79462304904.79462304904 - это номер нашего счетчика ГВС.Проделываем тоже самое для ХВС.
Обязательно убедитесь в правильности номера счетчиков, иначе можно передать неверные показания
Добавляем cкрипт в Home Assistant
Создаем папку python_scripts в /configs
Сохраняем мой скрипт по пути /config/python_scripts/voda_uu_ru.py
# -*- coding: utf-8 -*- import requests from datetime import datetime, date, time import sys import re # -------------- Voda_API ---------------------- class Voda_API: def __init__(self, timeout=15.0): """ """ self.timeout = timeout self.account_page = '' self.cookie = '' self.sess = requests.Session() self.headers = { # 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 'Accept': 'text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', } self.sendformdata = {} def login(self, **kwargs): """ :param login: :param password: :return: """ r = self.sess.get('https://lk.voda.uu.ru/login', headers=self.headers, timeout=self.timeout) assert r.ok formdata = dict() formdata['j_username'] = kwargs.get('username') formdata['j_password'] = kwargs.get('password') r = self.sess.post('https://lk.voda.uu.ru/j_spring_security_check', allow_redirects=False, data=formdata, headers=self.headers, timeout=self.timeout) assert r.ok, 'Ошибка авторизации' def no_login(self, **kwargs): """ :param account: :param numer of building: :param apartment: :return: """ r = self.sess.get('https://lk.voda.uu.ru/login', headers=self.headers, timeout=self.timeout) assert r.ok formdata = dict() formdata['j_account'] = kwargs.get('account') formdata['j_building'] = kwargs.get('building') formdata['j_apartment'] = kwargs.get('apartment') formdata['j_login_ipu'] = '1' formdata['submit'] = '' r = self.sess.post('https://lk.voda.uu.ru/protected_ipu/logon', allow_redirects=False, data=formdata, headers=self.headers, timeout=self.timeout) assert r.ok, 'Ошибка авторизации' def send_values(self,login_mode,**kwargs): body_cold = dict() body_hot = dict() body_cold['input_date'] = str(date.today().strftime("%d.%m.%Y")) body_hot['input_date'] = str(date.today().strftime("%d.%m.%Y")) if login_mode == 'login': body_cold['counters_list[]'] = str(kwargs.get('cold_counter_id')) body_cold['readings_list[]'] = str(kwargs.get('cold_water_value')) body_hot['counters_list[]'] = str(kwargs.get('hot_counter_id')) body_hot['readings_list[]'] = str(kwargs.get('hot_water_value')) else: body_cold['counters_list'] = str(kwargs.get('cold_counter_id')) body_cold['readings_list'] = str(kwargs.get('cold_water_value')) body_hot['counters_list'] = str(kwargs.get('hot_counter_id')) body_hot['readings_list'] = str(kwargs.get('hot_water_value')) self.sendformdata=body_cold r_cold = self.sess.post(kwargs.get('ipulink'), data=self.sendformdata, headers=self.headers, timeout=self.timeout) assert r_cold.ok, 'Ошибка авторизации' if r_cold.status_code == 200: print('Показания счетчика холодной воды успешно переданы') self.sendformdata=body_hot r_hot = self.sess.post(kwargs.get('ipulink'), data=self.sendformdata, headers=self.headers, timeout=self.timeout) if r_hot.status_code == 200: print('Показания счетчика горячей воды успешно переданы') assert r_hot.ok, 'Ошибка авторизации' def logout(self, **kwargs): r = self.sess.get('https://lk.voda.uu.ru/logoff', headers=self.headers, timeout=self.timeout) assert r.ok if __name__ == '__main__': email_regex = r'\b[A-Za-z0-9._% -] @[A-Za-z0-9.-] \.[A-Z|a-z]\b' data = { 'cold_counter_id': '', 'hot_counter_id':'', } api = Voda_API() try: if(re.fullmatch(email_regex, sys.argv[1])): data['username']=str(sys.argv[1]) data['password']=str(sys.argv[2]) data['cold_counter_id']=str(sys.argv[3]) data['hot_counter_id']=str(sys.argv[4]) data['cold_water_value']=str(sys.argv[5]) data['hot_water_value']=str(sys.argv[6]) data['ipulink']='https://lk.voda.uu.ru/protected/input' print("login_mode") api.login(**data) api.send_values('login',**data) else: data['account']=str(sys.argv[1]) data['building']=sys.argv[2] data['apartment']=str(sys.argv[3]) data['cold_counter_id']=str(sys.argv[4]) data['hot_counter_id']=str(sys.argv[5]) data['cold_water_value']=str(sys.argv[6]) data['hot_water_value']=str(sys.argv[7]) data['ipulink']='https://lk.voda.uu.ru/protected_ipu/input' print("no_login_mode") api.no_login(**data) api.send_values('no_login',**data) finally: api.logout() print('close')
Вход на сайт возможен двумя способами - через личный кабинет или по лицевому счету,№ дома, №кв.
Скрипт, в зависимости от аргументов, тоже логинится по-разному. Если первый аргумент- это email, то вход по логину/паролю, во втором случае - по номеру договора. Не забудьте перезапустить HASS после внесения изменений в configurations.yaml !!!
Теперь в configurations.yaml нужно прописать наш скрипт с параметрами.
Вариант 1 send_water_conters_values: 'python3 /config/python_scripts/voda_uu_ru.py example@gmail.com email_password 79462304777 79462310777 {{ states("sensor.water_control_cold_count") }} {{ states("sensor.water_control_hot_count") }}' Вариант 2 send_water_conters_values: 'python3 /config/python_scripts/voda_uu_ru.py 31406477 77A 137 79462310777 7946230477 {{ states("sensor.water_control_cold_count") }} {{ states("sensor.water_control_hot_count") }}' Пример отправки вариант 2 send_water_conters_values: 'python3 /config/python_scripts/voda_uu_ru.py 3140645672 77A 137 79462310777 79462304777 77.247 49.153'
Вариант 1:
example@gmail.com - почта для входа в личный кабинет
email_password - пароль для входа в личный кабинет
79462304777 - номер счетчика хвс, который мы узнали ранее.
79462310777- номер счетчика гвс, который мы узнали ранее.
{{ states("sensor.water_control_cold_count") }} - показания хвс. Должны быть разделены точкой 77.247!!!
{{ states("sensor.water_control_cold_count") }} - показания гвс. Должны быть разделены точкой 49.153!!!
Вариант 2:
номер договора номер доманомер квартиры79462304777 - номер счетчика хвс, который мы узнали ранее.79462310777- номер счетчика гвс, который мы узнали ранее.{{ states("sensor.water_control_cold_count") }} - показания хвс. Должны быть разделены точкой 77.247!!!{{ states("sensor.water_control_cold_count") }} - показания гвс. Должны быть разделены точкой 49.153!!!
Добавляем автоматизацию для отправки показаний
Добавляем автоматизацию в automations.yaml. Можно изменить дату, я отправляю 20 числа.
Теперь все готово, можно провести ручное тестирование. Я бы прописал значения немного больше, например на 0.1. И попробовал отправить через Настройки -> Автоматизации ->Запустить действие.
Проверяем на сайте voda.uu.ru наши показания. Если вдруг показания не отправились, то нужно проверить логи Home Assistant на ошибки.
- alias: "Отправка показаний на voda.uu.ru" trigger: - platform: time at: '08:00:00' condition: - condition: template # Поменять 20 на необходимую дату value_template: "{{ now().day == 20 }}" action: - service: shell_command.send_water_conters_values
Если при поиск номера ИПУ вы авторизировались с помощью номер договора(он же лицевой счет) запрос будет немного другой.
https://sprut.ai/static/media/cache/00/44/69/5/10827071/83744/1000x_image.png?1638178662" alt="1000x_image.png?1638178662" />
Лайк от Ватериуса!
Если у вас несколько счетов, то нужен еще POST запрос /protected/accounts/?account_id=bill.
А чтобы не лазить в код страницы, а передавать по серийникам, то можно считать все счетчики GET запросом /protected/input/measurers/
Спасибо,будет время добавлю возможности.
Друзья в скрипте пропадаю знаки в регулярном выражении email_regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' .Проблема движка сайта.Копируйте пжл отсюда.
Друзья скрипт не актуальный движок сайт вносит правки. Я выложу код на гитхаб в ближ время
Ну вот, теперь точно пора доделывать счетчики! Спасибо, земляк:)
Только чую, придётся думать как это их HA перенести в другое место. У меня все на NodeRed.
И да, ссылочку бы на гитхаб, пришлёшь?
Да, ещё вопрос: а чем собираются показания со счетчиков? Я пробовал на NodeRed и ESPEasy сделать свой счётчик, но там проблема была на тот момент - он задваивал значения.
Статья про счётчики
https://sprut.ai/client/article/4336">https://sprut.ai/client/articl...
на гитхаб свежий скрипт залью сегодня завтра. Думаю допилить что бы номера счётчиков были как сенсор, но нужно время.
Ну и планирую в уралэнергосбыт тоже сделать.
https://github.com/ilkarataev/voda.uu.ru_Home_Assistant">Репозиторий проекта
https://github.com/ilkarataev/voda.uu.ru_Home_Assistant">Репозиторий проекта