Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Реализация управления кранами: пример обмена по API #21

Open
Gimlir opened this issue Dec 27, 2021 · 32 comments

Comments

@Gimlir
Copy link
Contributor

Gimlir commented Dec 27, 2021

Очень хотелось бы получить возможность управления кранами. Хочу помочь продвинуться в этом направлении.
Увидел в комментариях других issues, что в предоставленных документах по API от Saures не было про управление кранами. Выкладываю свой пример команд на открытие и закрытие, взятый в ЛК потребителя из браузера.

Выход, подключенный к управляющему каналу кранов в классификации Saures - Тип: Кран/реле, тип цифрой: 6, в списке meters выгдядит как:

{
		"meter_id": ***91,    #обязательный
		"meter_name": "Краны управление",
		"input": 6,
		"approve_dt": null,
		"eirc_num": "",
		"sn": "*******8-6",    #опциональный, может отсутствовать
		"type": {
			"name": "Кран/реле",
			"number": 6
		},
		"state": {
			"name": "Ошибок нет",
			"number": 0
		},
		"unit": "",
		"vals": [
			0                       <===текущее состояние управляющего сигнала = открыть (соотв. 1 = закрыть)
		],
		"active_text": "Закрытие",
		"passive_text": "Открытие"
	}
}

если в системе зарегистрирована ожидающая своего исполнения команда для канала этого типа, то она видна в ответе на запрос /object/meters между vals и active_text как command:

...
		"vals": [
			0
		],
		"command": {
			"type": "close",
			"description": "закрытие 27.12 в 12:35"
		},
		"active_text": "Закрытие",
		"passive_text": "Открытие"
...

Управление
Запрос заголовки

POST /1.0/meter/control HTTP/1.1
Host: api.saures.ru
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Content-Length: 62
Origin: https://lk.saures.ru
Connection: keep-alive
Referer: https://lk.saures.ru/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache

POST Data для открытия

sid=a3c5****-****-****-****-**********1c
id=****91                           # id здесь совпадает с meter_id, не (!) sn канала, куда заведен провод управления кранами
command=open

и закрытия

sid=59ce25c4-55c0-44d3-a0ab-8920efb8e2aa
id=***91
command=close

Ответ, заголовки

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: User-Agent,Keep-Alive,Content-Type
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 142
Content-Type: application/json; charset=utf-8
Strict-Transport-Security: max-age=31536000
Date: Mon, 27 Dec 2021 06:45:51 GMT

ответ тело (так как открытие происходит не в realtime, а в момент выхода контроллера на связь в следующий раз, сервер возвращает ориентировочное время этого ожидаемого выхода, выход и закрытие в это время может и не случиться)

{"status": "ok", "errors": [], "data": {"type": "open", "description": "\u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 27.12 \u0432 10:34"}}

и на закрытие

{"status": "ok", "errors": [], "data": {"type": "close", "description": "\u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 27.12 \u0432 12:35"}}

image

ответ при просроченной сессии авторизации

{"status": "bad", "errors": [{"name": "WrongSIDException", "msg": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 sid"}], "data": {}}

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

POST /1.0/meter/control HTTP/1.1
Host: api.saures.ru
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Content-Length: 63
Origin: https://lk.saures.ru
Connection: keep-alive
Referer: https://lk.saures.ru/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache
sid=a3c5****-****-****-****-**********1c
id=***91
command=clear

ответ

{"status": "ok", "errors": [], "data": {}}

Логика, зашитая во фронтенде ЛК Саурес при нажатии на кнопку отправки команды закрытия(открытия): запрос GET на /objects/meters для проверки текущего состояния и наличия уже ожидающей команды, запрос POST на /meter/control с командой и снова GET на /objects/meters для проверки взятия команды в очередь.

@Gimlir
Copy link
Contributor Author

Gimlir commented Dec 27, 2021

UPD на https://api.saures.ru/doc/1.0/meter/control опубликовано, что нужно отправлять command = activate|deactivate, но в ЛК шлется именно open|close|clear

@Gimlir
Copy link
Contributor Author

Gimlir commented Feb 16, 2022

@volshebniks Удалось ли взглянуть? Можем надеяться на реализацию?

@alleonname
Copy link

О! Если получится, то было бы суперски-афигенно!!! ;)

@volshebniks
Copy link
Owner

volshebniks commented May 5, 2022

Gimlir
alleonname

На данный момент реализация добавлена в master версию. К сожалению я не могу полноценной протестировать, так как у меня нет таких кранов, а demo кабинет возвращает ошибку "Недостаточно прав" при попытке управлять краном.

Если можете поставьте master версию. Обратите внимание что настройка компонента стала вообще другой.
минимально достаточно так в configuration.yaml. Из всех других мест настройки удалить.

sauresha:
     email: !secret saures_login
     password: !secret saures_pass

@alleonname
Copy link

alleonname commented May 15, 2022

sauresha:
email: !secret saures_login
password: !secret saures_pass

при такой настройке
binary_sensor_xxx - False
sensor.sauresha_ххх - unknown

@volshebniks
Copy link
Owner

sauresha:
email: !secret saures_login
password: !secret saures_pass

при такой настройке binary_sensor_xxx - False sensor.sauresha_ххх - unknown

А что в логах? Логин и пароль свой точно правильно указали?
Заранее большое спасибо за ответ.

@alleonname
Copy link

Где смотреть логи?
Логин/пароль правильные
Состояние: False
В Атрибутах:
friendly_name: Датчик протечки Кухня
condition: Ошибок нет
sn:
type: Датчик
meter_id: 59325
input: 5
last_update_time: 2022-05-15T20:31:32.497573
next_update_time: 2022-05-15T20:32:32.497585
icon: mdi:alarm-check

@volshebniks
Copy link
Owner

логи ваш сервер/config/logs
Датчик протечки Кухня - имя датчика соответсвует вашему?

@alleonname
Copy link

2022-05-15 20:30:30 WARNING (SyncWorker_10) [custom_components.sauresha.api] ID flat: далее адрес и ID flat
Да, имя датчика соответствует, другие датчики тоже с именем в Атрибутах.

@volshebniks
Copy link
Owner

а ошибки связаннные с компонентом есть в логе?

@alleonname
Copy link

нет, больше нет ошибок.
у сенсоров (счетчиков) состояние (расход воды) появилось

@volshebniks
Copy link
Owner

а switch созданных не появилось? - для кранов

@alleonname
Copy link

switch появился

@volshebniks
Copy link
Owner

switch появился

а пробовали его включить/выключить - на кран это как то влияет? ошибки поле этого в логе есть?

@alleonname
Copy link

никак не влияет, ошибок нет, состояние всё время "off"

@Gimlir
Copy link
Contributor Author

Gimlir commented May 16, 2022

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

  1. в логах при старте ha имею только 4 WARN сообщения с ID flat, ошибок нет
  2. в HA появились все мои
    • датчики протечки - как бинарный сенсор,
    • краны (каналы состояния) - как сенсор, показывает 1 или 0 (1=закрыт, 0=открыт)
    • счетчики - как сенсор
    • кран (канал управления) - как выключатель,

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

  • нажатие на выключатель (включение) в HA - ставит в очередь задачу на закрытие кранов в ЛК Саурес, при этом выключатель визуально переводится из состояние выкл в состояние вкл на время выполнение запроса по АПИ и возвращается через секунду в исходное состояние.
  • в лк сайурес после этого действия появляется информация о запланированном закрытии кранов и указывается время расчетного выхода на связь контроллера
  • когда из ЛК Саурес команда в очередной сеанс связи долетает до кранов, те закрываются
  • контроллер детектит изменение состояния кранов и выгружает свое новое состояние в ЛК Саурес,
  • в ЛК Суарес пропадает информация о запланированном закрытии на канале управления кранами и сам канал переходит в состояние закрыт, каналы состояния кранов показывают состояние закрыт.
  • только на следующий после этого момента апдейт HA переводит состояние выключателя во включено.
    Screenshot 2022-05-16 165736

@volshebniks
Copy link
Owner

@Gimlir - замечательно. спасибо большое. значит все же работает.
релиз новой версии компонента скорее всего - будет с настройкой через GUI Home Assistant.
подумаю - что еще можно изменить.
К сожалению Saures банит - если опрашивать их сервер часто и это вносит существенные корективы :(

@alleonname
Copy link

в HA появились все мои
датчики протечки - как бинарный сенсор

а состояние какое? у меня по-прежнему - "False"

@Gimlir
Copy link
Contributor Author

Gimlir commented May 16, 2022

@volshebniks поймал баг с невозможностью отмены поставленной в очередь задачи по закрытию (открытию).
Из за того, как реагирует switch на клик (см. я описал пошагово выше) в интерфейсе HA не возможно отменить закрытие (открытие) до того, как оно фактически случилось.

Если попытаться вызвать принудительно сервис - тоже не получится. Вот пример сценария:

  • исходное состояние, выключатель HA из интеграции в состоянии on, краны фактически закрыты, в ЛК Саурес канал управления в состоянии Закрытие.
  • нажимаем на выключатель HA чтобы выключить его (открыть краны)
  • на секунду выключатель переключается в off и тут же возвращается в on, в ЛК Саурес канал управления все так же в состоянии Закрытие, но есть запланированное открытие, краны фактически закрыты
  • теперь мы хотим отменить запланированное открытие. вызываем в явном виде сервис HA switch.turn_on для выключетеля интеграции - в логах получаем
    2022-05-16 17:45:19 ERROR (SyncWorker_5) [custom_components.sauresha.api] Ошибка выполнения комманды - command: activate ,meter_id: *****, ошибка: Неверная команда.
  • вызываем в явном виде сервис HA switch.turn_off - никакой активности в логах и ЛК Саурес

@Gimlir
Copy link
Contributor Author

Gimlir commented May 16, 2022

релиз новой версии компонента скорее всего - будет с настройкой через GUI Home Assistant.

Как сейчас можно снизить частоту обращений к серверу саурес? вижу, что по умолчанию идет интервал 10 мин, я ранее использовал 1 час.

Такой синтаксис проканает?

sauresha:
  email: ***
  password: ***
  scan_interval:
     minutes: 60

@Gimlir
Copy link
Contributor Author

Gimlir commented May 16, 2022

в HA появились все мои
датчики протечки - как бинарный сенсор

а состояние какое? у меня по-прежнему - "False"

Все верно, у меня так же. False в бинарном сенсоре HA эквивалентно состоянию Неактивен в ЛК Саурес эквивалентно отсутствию протечки.

@Gimlir
Copy link
Contributor Author

Gimlir commented May 16, 2022

@volshebniks, я еще один баг поймал. Оказывается, я поторопился сказать, что после фактического изменения положения кранов следующий апдейт данных по апи принесет смену статуса выключателю.
Этого не происходит, хотя дата прошлого и следующего обновления данных в атрибутах показывают, что апдейт состоялся, сотояние свича не меняется. То же самое и с бинарными сенсорами, которые показывают состояние кранов по каналу состояния.
При этом перезапуск HA приводит к корректному считыванию статусов, выключатель приходит в синхронизированное с ЛК Саурес состояние, бинарные сенсоры тоже

@volshebniks
Copy link
Owner

да проблему обновления - я уже тоже словил. буду разбираться

@volshebniks
Copy link
Owner

выложил в master новую версию. полностью всё переделал. это еще скорее всего не конечная версия.
настройка только через GUI. старые настройки нужно удалить. из релизной версии настройки из yaml конвертятся в GUI.

@Gimlir
Copy link
Contributor Author

Gimlir commented Jun 1, 2022

поставил версию из hacs из master, пока застрял на сохранении логина через GUI, см issue #27

@Gimlir
Copy link
Contributor Author

Gimlir commented Jun 7, 2022

@volshebniks
Новая версия из master по состоянию на #32 создает объект switch, но при попытке вызова сервисов включения и выключения для этого выключателя

2022-06-07 17:21:28 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140672299931632] 'SauresHA' object has no attribute 'get_switches'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 192, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1636, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1673, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 204, in handle_service
await self.hass.helpers.service.entity_service_call(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 668, in entity_service_call
future.result() # pop exception if have
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 949, in async_request_call
await coro
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 705, in _handle_entity_call
await result
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1011, in async_turn_off
await self.hass.async_add_executor_job(ft.partial(self.turn_off, **kwargs))
File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/config/custom_components/sauresha/entity.py", line 504, in turn_off
self.controller.get_switches(self.flat_id, True)
AttributeError: 'SauresHA' object has no attribute 'get_switches'
2022-06-07 17:21:31 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140672299931632] 'SauresHA' object has no attribute 'get_switches'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 192, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1636, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1673, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 204, in handle_service
await self.hass.helpers.service.entity_service_call(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 668, in entity_service_call
future.result() # pop exception if have
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 949, in async_request_call
await coro
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 705, in _handle_entity_call
await result
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1003, in async_turn_on
await self.hass.async_add_executor_job(ft.partial(self.turn_on, **kwargs))
File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/config/custom_components/sauresha/entity.py", line 499, in turn_on
self.controller.get_switches(self.flat_id, True)
AttributeError: 'SauresHA' object has no attribute 'get_switches'

@volshebniks
Copy link
Owner

@Gimlir

Новая версия из master по состоянию на #32 создает объект switch, но при попытке вызова сервисов включения и выключения для этого выключателя

Спасибо вам огромное - за тестирование!!!
Поправил. Должно работать.

@Gimlir
Copy link
Contributor Author

Gimlir commented Jun 7, 2022

Обновился, выключатель крана создался в выключенном состоянии, как и положено, нажал включить (выключатель в UI как и раньше дернулся во включенное состояние и вернулся назад в выключенное). Команда на сервер саурес ушла, краны закрылись. Буду ждать как отобразится состояние выключателя после следующего обновления данных интеграцией.

ЗЫ @volshebniks не могли бы вы сопровождать исправления при выгрузке в репозиторий как раньше тегами с номером релиза, а то без них HACS не дает обновляться с версии master на нее же (не понимает, что комиты добавились) и уж очень много действий для применения каждого исправления приходится проделывать (удалять все интеграции, репозиторий и запись о кастомном репозитории и возвращать все в обратном порядке)

@Gimlir
Copy link
Contributor Author

Gimlir commented Jun 9, 2022

Результаты тестов:

  1. Проблема с обновлением статуса свича управления кранами и бинарных сенсоров статуса крана сохранилась. При очередном обновлении данных по АПИ состояние объектов в HA не меняется, не смотря на то, что все другие сенсоры обновляются и показывают новые значения (счетчики воды например). При перезапуске НА, как и прежде, верный статус бинарных сенсоров и свича восстанавливается.
  2. Когда канал управления кранами находится в состоянии Закрытие и свич в НА включен - нажатие на свич для выключения приводит к выводу ошибки в GUI HA
    image
    при этом команда на открытие по АПИ уходит и в ЛК Саурес регистрируется задание на открытие.
    в логе НА
2022-06-09 11:53:56 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140702374451520] 'SauresHA' object has no attribute 'async_get_switchess'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 192, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1636, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1673, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 204, in handle_service
await self.hass.helpers.service.entity_service_call(
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 668, in entity_service_call
future.result() # pop exception if have
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 949, in async_request_call
await coro
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 705, in _handle_entity_call
await result
File "/config/custom_components/sauresha/entity.py", line 545, in async_turn_off
await self.controller.async_get_switchess(self.flat_id, True)
AttributeError: 'SauresHA' object has no attribute 'async_get_switchess'

@volshebniks
Copy link
Owner

volshebniks commented Jun 9, 2022

поправил + сделал проверку на то что статус крана = открыто или закрыто. если что то другое - по крайней мере падать не должно

@Gimlir
Copy link
Contributor Author

Gimlir commented Jun 9, 2022

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

Я подумал, может быть при создании объектов, если создаем объект свича для крана - то создавать в пару к нему сенсор "Ожидающая команда управления" со статусом "Нет ожидающих команд", "Ожидается открытие", "Ожидается закрытие" и атрибутом "Время ожидаемого исполнения" (или эти статусы и время можно в атрибуты самого свича поместить, чтобы на плодить сущности).

При наличии такого доп объекта или атрибутов можно было бы после клика на свиче менять состояние сенсора\атрибута, а состояние свича заранее переводить в ожидаемое состояние - тогда пользователь будет видеть интуитивное понятную реакцию на свое действие: кликнул на свич закрыть - свич переключился и остался в своем новом положении - сенсор\атрибут показал что зарегистрирована команда и мы ждем ее исполнения.
Когда по апи придет новое состояние кранов и пропадет информация о ждущей задаче открытия - сенсор\атрибут вернуть в состояние по умолчанию а свич останется включенным.
Что думаете о такой логике?

@volshebniks
Copy link
Owner

да атрибут добавить не сложно. думаю сделаю и переводить в предполагаемое сосотояние тоже.
вот думаю зарелиить master ветку....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants