sauresha icon indicating copy to clipboard operation
sauresha copied to clipboard

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

Open Gimlir opened this issue 3 years ago • 32 comments

Очень хотелось бы получить возможность управления кранами. Хочу помочь продвинуться в этом направлении. Увидел в комментариях других 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 avatar Dec 27 '21 09:12 Gimlir

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

Gimlir avatar Dec 27 '21 12:12 Gimlir

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

Gimlir avatar Feb 16 '22 06:02 Gimlir

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

alleonname avatar Feb 19 '22 09:02 alleonname

Gimlir alleonname

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

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

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

volshebniks avatar May 05 '22 10:05 volshebniks

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

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

alleonname avatar May 15 '22 16:05 alleonname

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

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

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

volshebniks avatar May 15 '22 17:05 volshebniks

Где смотреть логи? Логин/пароль правильные Состояние: 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

alleonname avatar May 15 '22 17:05 alleonname

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

volshebniks avatar May 15 '22 17:05 volshebniks

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

alleonname avatar May 15 '22 17:05 alleonname

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

volshebniks avatar May 15 '22 17:05 volshebniks

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

alleonname avatar May 15 '22 18:05 alleonname

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

volshebniks avatar May 15 '22 18:05 volshebniks

switch появился

alleonname avatar May 15 '22 19:05 alleonname

switch появился

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

volshebniks avatar May 15 '22 19:05 volshebniks

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

alleonname avatar May 15 '22 21:05 alleonname

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

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

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

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

Gimlir avatar May 16 '22 14:05 Gimlir

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

volshebniks avatar May 16 '22 14:05 volshebniks

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

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

alleonname avatar May 16 '22 14:05 alleonname

@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 avatar May 16 '22 14:05 Gimlir

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

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

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

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

Gimlir avatar May 16 '22 14:05 Gimlir

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

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

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

Gimlir avatar May 16 '22 14:05 Gimlir

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

Gimlir avatar May 16 '22 16:05 Gimlir

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

volshebniks avatar May 16 '22 16:05 volshebniks

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

volshebniks avatar Jun 01 '22 07:06 volshebniks

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

Gimlir avatar Jun 01 '22 12:06 Gimlir

@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'

Gimlir avatar Jun 07 '22 14:06 Gimlir

@Gimlir

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

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

volshebniks avatar Jun 07 '22 15:06 volshebniks

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

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

Gimlir avatar Jun 07 '22 15:06 Gimlir

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

  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'

Gimlir avatar Jun 09 '22 08:06 Gimlir

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

volshebniks avatar Jun 09 '22 09:06 volshebniks