Камера Уфанет в Home Assistant
UPDATE @AlexxIT добавил поддержку в go2rtс 🥳
https://t.me/homassistant/971504
как добавлять камеры описано тут, листаем до секции уфанет: https://github.com/AlexxIT/go2rtc/blob/master/internal/expr/README.md
устаревший вариант (более не нужен, т.к. появилась поддержка камер уфанет в go2rtc)
Благодарность Anton @simple1elf за метод!
Описание настроек go2rtc относятся к go2rtc установленному как аддон!
Если у вас другой тип установки go2rtc - расположение файлов будет другое, главное чтобы у go2rtc был доступ до файлов, ориентируйтесь на свой сервер.
Понадобится:
1. логин пароль от Уфанет с доступом к https://ucams.ufanet.ru/ (можно будет подтянуть камеры которые там отображаются)
2. go2rtc (например, аддоном)
1. Ищем нужные нам данные по камере.
Заходим https://ucams.ufanet.ru/ в браузере, напримере Chromе
Видим наши камеры, нажимаем на просмотр, чтобы шел поток от камеры
Жмякаем F12 чтобы попасть в консоль разработчика
На вкладке сеть будет виден hls поток, копируем его URL
Получаем ссылку подобную этой:
https://manul-9.cams.ufanet.ru/16161614917OJQ678/0/16434534534517OJQ678-17632342344675-2615945.ts?token=eyJ0eXAiOiJKV1QiL(и далее длинный токен)
Нам понадобится номер сервера
manul-9.cams.ufanet.ru
manul-9.cams.ufanet.ru/16161614917OJQ678/0/
В home assistant любым удобным способом попадаем в папку конфигурации и создаем папку ufanet_video
/config/ufanet_video
Внутри папки создаем файл ufanet_video.py
(полный путь будет /config/ufanet_video/ufanet_video.py)
import requests
import json
import os
import argparse
from datetime import datetime, timedelta
# Парсинг аргументов командной строки
parser = argparse.ArgumentParser(description="Получение RTSP-ссылки с токеном для камеры Уфанет")
parser.add_argument("--camera-id", required=True, help="Идентификатор камеры")
parser.add_argument("--username", required=True, help="Имя пользователя (логин)")
parser.add_argument("--password", required=True, help="Пароль")
parser.add_argument("--manul-id", default="21", help="Идентификатор manul-сервера (по умолчанию: 21)")
parser.add_argument("--token-dir", default="/config/ufanet_video", help="Директория для хранения token.json (по умолчанию: /config/ufanet_video)")
args = parser.parse_args()
camera_id = args.camera_id
credentials = {
"username": args.username,
"password": args.password
}
manul_id = args.manul_id
token_dir = args.token_dir
# Уникальное имя файла токена для каждой камеры + пользователя (защита от конфликтов)
safe_name = f"{args.username}_{camera_id}".replace("/", "_").replace("\\", "_")
token_file = os.path.join(token_dir, f"token_{safe_name}.json")
ttl_minutes = 30 # время жизни токена
def load_token_if_valid():
if not os.path.exists(token_file):
return None
try:
with open(token_file, "r", encoding="utf-8") as f:
data = json.load(f)
token = data.get("token")
obtained_at_str = data.get("obtained_at")
if not token or not obtained_at_str:
return None
obtained_at = datetime.fromisoformat(obtained_at_str)
if datetime.now() - obtained_at < timedelta(minutes=ttl_minutes):
return token
else:
return None
except (json.JSONDecodeError, ValueError, KeyError):
return None
def save_token(token):
token_info = {
"token": token,
"obtained_at": datetime.now().isoformat()
}
os.makedirs(token_dir, exist_ok=True)
with open(token_file, "w", encoding="utf-8") as f:
json.dump(token_info, f, ensure_ascii=False, indent=4)
def get_new_token():
session = requests.Session()
response = session.post("https://ucams.ufanet.ru/api/internal/login/", data=credentials)
if response.status_code != 200:
raise Exception(f"Auth API error: {response.status_code} {response.text}")
sessionid = session.cookies.get("sessionid")
cookies = {"sessionid": sessionid}
camera_payload = {
"fields": ["token_l", "token_r"],
"token_l_ttl": 3600,
"token_r_ttl": 3600,
"numbers": [camera_id]
}
cam_response = requests.post(
"https://ucams.ufanet.ru/api/v0/cameras/this/?lang=ru",
json=camera_payload,
cookies=cookies
)
if cam_response.status_code != 200:
raise Exception(f"Camera API error: {cam_response.status_code} {cam_response.text}")
result = cam_response.json()["results"][0]
return result["token_l"]
# Основной поток
token = load_token_if_valid()
if token is None:
token = get_new_token()
save_token(token)
rtsp_url = f"rtsp://manul-{manul_id}.cams.ufanet.ru/{camera_id}?token={token}#audio=pcmu#video=h265"
print(rtsp_url)Сначала надо доустановить пакеты python, для этого добавляем в go2rtc stream
streams: domofon3: | echo: pip install requests -t /config/ufanet_video
Сохраняем и открываем полученный поток на просмотр. Скачаются пакеты.
Поток можно убрать, больше не понадобится.
Добавляем в go2rtc источники, столько сколько надо камер получить в ХА
streams: domofon1: | echo: python3 /config/ufanet_video/ufanet_video.py --camera-id "111111111" --username "123123123" --password "321321" --manul-id "666" domofon2: | echo: python3 /config/ufanet_video/ufanet_video.py --camera-id "222222222" --username "123123123" --password "321321" --manul-id "777"
Где:
--camera-id "111111111"
1111111 = номер камеры, полученный выше
--username "123123123" --password "321321"
логин пароль от сайта ucams.ufanet.ru
--manul-id "777"
777 = номер сервера, полученный выше
И получаем потоки с камер уфанет
Например, rtsp://192.168.1.100:8554/domofon1
Не забудьте сменить ip на свой
Поток можно проверить в видеоплеере VLC
И всё это можно связать с открытием домофона из Home Assistant