- Сообщения
- 202
- Реакции
- 0
При работе с большим количеством IP-камер в TRASSIR может возникнуть проблема с распределением лицензий.
В моём случае на сервере используется около 40 камер разных производителей: Hikvision, HiWatch, китайские камеры и другие устройства. Лицензии также используются разных типов, в том числе ANYIP.
Проблема проявлялась после перезагрузки сервера TRASSIR:
Решил автоматизировать этот процесс с помощью встроенного Python-скрипта TRASSIR.
После запуска TRASSIR сценарий автоматически:
То есть схема получается следующая:
Таким образом устройство, которое раньше забирало лицензии, подключается последним.
В большинстве случаев достаточно изменить только два параметра.
Список камер, которые должны получить лицензии первыми:
И IP устройства, которое должно подключаться последним:
Количество приоритетных камер может быть другим.
Например:
Скрипт не просто ждёт фиксированное количество секунд.
Для каждой камеры проверяется наличие реального видеопотока.
Если поток появился, камера считается подключившейся.
После того как видео появилось от всех приоритетных камер, выполняется несколько дополнительных проверок:
По умолчанию проверка выполняется каждые 2 секунды:
То есть видеопоток должен сохраняться примерно 6 секунд подряд.
После этого скрипт ждёт ещё 5 секунд и включает последнее устройство.
Если одна из приоритетных камер неисправна или недоступна по сети, ждать её бесконечно не нужно.
Для этого используется:
Через 180 секунд регистратор будет запущен в любом случае:
Если требуется строгий режим, можно изменить:
В этом случае последнее устройство не будет включено, пока не появятся все приоритетные камеры.
Все сообщения скрипта имеют префикс:
Например:
Перед использованием обязательно замените IP-адреса из примера на адреса своих устройств.
Желательно сначала проверить сценарий на работающем сервере вручную, без полной перезагрузки.
Скрипт намеренно управляет только указанными устройствами и не отключает остальные камеры на сервере.
В моём случае на сервере используется около 40 камер разных производителей: Hikvision, HiWatch, китайские камеры и другие устройства. Лицензии также используются разных типов, в том числе ANYIP.
Проблема проявлялась после перезагрузки сервера TRASSIR:
- часть камер должна была получить лицензии ANYIP;
- сетевой видеорегистратор подключался раньше нужных камер;
- регистратор занимал доступные лицензии;
- несколько приоритетных камер оставались без лицензии;
- приходилось вручную отключать регистратор, подключать камеры и затем снова включать регистратор.
Решил автоматизировать этот процесс с помощью встроенного Python-скрипта TRASSIR.
Что делает скрипт
После запуска TRASSIR сценарий автоматически:
- Находит регистратор по IP-адресу.
- Временно отключает его.
- Отключает приоритетные камеры.
- Ждёт освобождения лицензий.
- Повторно включает приоритетные камеры.
- Проверяет появление реального видеопотока от каждой камеры.
- Несколько раз проверяет стабильность видеопотока.
- Только после успешного подключения всех приоритетных камер включает регистратор.
- Если одна из камер не появилась в течение заданного времени, срабатывает аварийный таймаут.
То есть схема получается следующая:
Код:
TRASSIR запускается
|
v
Регистратор -> OFF
|
v
Освобождаются лицензии
|
v
Приоритетные камеры -> OFF -> ON
|
v
Ожидание видеопотока от всех камер
|
v
Проверка стабильности
|
v
Регистратор -> ON
Таким образом устройство, которое раньше забирало лицензии, подключается последним.
Готовый скрипт
Python:
# -*- coding: utf-8 -*-
# ============================================================
# TRASSIR ANYIP PRIORITY STARTUP
#
# Сначала подключаются камеры из PRIORITY_IPS.
# Регистратор NVR_IP подключается последним.
# ============================================================
import time
# ------------------------------------------------------------
# НАСТРОЙКИ
# ------------------------------------------------------------
PRIORITY_IPS = [
"192.168.0.145",
"192.168.0.127",
"192.168.0.124",
"192.168.0.121",
"192.168.0.120",
"192.168.0.118",
]
# Устройство, которое должно подключаться последним
NVR_IP = "192.168.0.238"
# Небольшая задержка после запуска скрипта
INITIAL_DELAY_MS = 5000
# Время на освобождение лицензий после отключения регистратора
LICENSE_RELEASE_DELAY_MS = 5000
# Интервал проверки состояния камер
CHECK_INTERVAL_MS = 2000
# Количество успешных проверок видеопотока подряд
STABLE_CHECKS_REQUIRED = 3
# Дополнительная задержка перед включением регистратора
FINAL_DELAY_MS = 5000
# Максимальное время ожидания камер
MAX_WAIT_SEC = 180
# True - после таймаута всё равно запустить регистратор
# False - не запускать регистратор, пока не заработают все камеры
FORCE_NVR_AFTER_TIMEOUT = True
# ------------------------------------------------------------
# СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ
# ------------------------------------------------------------
wait_started = 0
stable_checks = 0
poll_counter = 0
finished = False
prepare_attempts = 0
# ------------------------------------------------------------
# ЛОГ
# ------------------------------------------------------------
def log(text):
message("[ANYIP PRIORITY] " + text)
# ------------------------------------------------------------
# ПОИСК IP-УСТРОЙСТВА
# ------------------------------------------------------------
def find_device(ip):
try:
devices = settings("ip_cameras").ls()
except Exception as e:
log("Cannot read ip_cameras: %s" % str(e))
return None
for dev in devices:
try:
if dev.type != "Grabber":
continue
if dev["connection_ip"] == ip:
return dev
except:
pass
return None
# ------------------------------------------------------------
# ВКЛЮЧЕНИЕ / ВЫКЛЮЧЕНИЕ УСТРОЙСТВА
# ------------------------------------------------------------
def set_device_enabled(ip, enabled):
dev = find_device(ip)
if dev is None:
log("Device not found: %s" % ip)
return False
try:
dev["grabber_enabled"] = 1 if enabled else 0
if enabled:
log("ENABLE %s" % ip)
else:
log("DISABLE %s" % ip)
return True
except Exception as e:
log("Error changing %s: %s" % (ip, str(e)))
return False
# ------------------------------------------------------------
# ПОЛУЧЕНИЕ FPS ОСНОВНОГО КАНАЛА
# ------------------------------------------------------------
def get_camera_fps(ip):
dev = find_device(ip)
if dev is None:
return -1
try:
channel_guid = dev["channel00_guid"]
if not channel_guid:
return 0
stats = settings(
"channels/%s/stats" % channel_guid
)
fps = float(stats["fps_main"])
return fps
except:
return 0
# ------------------------------------------------------------
# ЗАПУСК РЕГИСТРАТОРА
# ------------------------------------------------------------
def start_nvr():
global finished
if finished:
return
finished = True
log("------------------------------------------")
log("Starting NVR LAST: %s" % NVR_IP)
if set_device_enabled(NVR_IP, True):
log("NVR started successfully")
else:
log("ERROR: NVR could not be started")
log("Priority startup procedure finished")
log("------------------------------------------")
def start_nvr_after_delay():
log(
"All priority cameras are stable. "
"NVR will start in %d sec."
% (FINAL_DELAY_MS / 1000)
)
timeout(
FINAL_DELAY_MS,
start_nvr
)
# ------------------------------------------------------------
# ПРОВЕРКА ПРИОРИТЕТНЫХ КАМЕР
# ------------------------------------------------------------
def check_priority_cameras():
global stable_checks
global poll_counter
if finished:
return
poll_counter += 1
ready_count = 0
not_ready = []
for ip in PRIORITY_IPS:
dev = find_device(ip)
if dev is not None:
try:
if dev["grabber_enabled"] == 0:
dev["grabber_enabled"] = 1
log("Re-enabled priority camera: %s" % ip)
except:
pass
fps = get_camera_fps(ip)
if fps > 0:
ready_count += 1
else:
not_ready.append(ip)
if poll_counter % 5 == 0:
log(
"Priority cameras ready: %d/%d"
% (ready_count, len(PRIORITY_IPS))
)
if len(not_ready) > 0:
log(
"Waiting for: %s"
% ", ".join(not_ready)
)
if ready_count == len(PRIORITY_IPS):
stable_checks += 1
log(
"All cameras have video. Stability check %d/%d"
% (
stable_checks,
STABLE_CHECKS_REQUIRED
)
)
if stable_checks >= STABLE_CHECKS_REQUIRED:
start_nvr_after_delay()
return
else:
stable_checks = 0
elapsed = time.time() - wait_started
if elapsed >= MAX_WAIT_SEC:
log("------------------------------------------")
log(
"WARNING: timeout %d sec reached"
% MAX_WAIT_SEC
)
if len(not_ready) > 0:
log(
"Cameras without video: %s"
% ", ".join(not_ready)
)
if FORCE_NVR_AFTER_TIMEOUT:
log("Emergency mode: starting NVR anyway")
start_nvr()
return
else:
log("Strict mode: NVR remains disabled")
timeout(
CHECK_INTERVAL_MS,
check_priority_cameras
)
# ------------------------------------------------------------
# ВКЛЮЧЕНИЕ ПРИОРИТЕТНЫХ КАМЕР
# ------------------------------------------------------------
def start_priority_cameras():
global wait_started
global stable_checks
global poll_counter
stable_checks = 0
poll_counter = 0
log("------------------------------------------")
log("Starting priority cameras")
for ip in PRIORITY_IPS:
set_device_enabled(ip, True)
wait_started = time.time()
log(
"Waiting for real video from all %d cameras..."
% len(PRIORITY_IPS)
)
timeout(
CHECK_INTERVAL_MS,
check_priority_cameras
)
# ------------------------------------------------------------
# ПОДГОТОВКА
# ------------------------------------------------------------
def prepare():
global prepare_attempts
prepare_attempts += 1
log("Preparing priority startup...")
nvr = find_device(NVR_IP)
if nvr is None:
if prepare_attempts < 30:
log(
"NVR %s not found yet. Retry..."
% NVR_IP
)
timeout(
2000,
prepare
)
return
log(
"ERROR: NVR %s was not found"
% NVR_IP
)
return
log("------------------------------------------")
log("Disabling NVR first: %s" % NVR_IP)
set_device_enabled(
NVR_IP,
False
)
log("Resetting priority cameras...")
for ip in PRIORITY_IPS:
dev = find_device(ip)
if dev is None:
log(
"WARNING: priority device not found: %s"
% ip
)
else:
try:
dev["grabber_enabled"] = 0
log("RESET OFF %s" % ip)
except Exception as e:
log(
"Cannot disable %s: %s"
% (ip, str(e))
)
log(
"Waiting %d sec for licenses to be released..."
% (LICENSE_RELEASE_DELAY_MS / 1000)
)
timeout(
LICENSE_RELEASE_DELAY_MS,
start_priority_cameras
)
# ------------------------------------------------------------
# СТАРТ СКРИПТА
# ------------------------------------------------------------
log("==========================================")
log("ANYIP Priority Startup script loaded")
log("NVR must start LAST: %s" % NVR_IP)
log("==========================================")
timeout(
INITIAL_DELAY_MS,
prepare
)
Что необходимо изменить под свой сервер
В большинстве случаев достаточно изменить только два параметра.
Список камер, которые должны получить лицензии первыми:
Python:
PRIORITY_IPS = [
"192.168.0.145",
"192.168.0.127",
"192.168.0.124",
]
И IP устройства, которое должно подключаться последним:
Python:
NVR_IP = "192.168.0.238"
Количество приоритетных камер может быть другим.
Например:
Python:
PRIORITY_IPS = [
"10.0.0.11",
"10.0.0.12",
"10.0.0.15",
"10.0.0.20",
]
Как работает проверка камер
Скрипт не просто ждёт фиксированное количество секунд.
Для каждой камеры проверяется наличие реального видеопотока.
Если поток появился, камера считается подключившейся.
После того как видео появилось от всех приоритетных камер, выполняется несколько дополнительных проверок:
Python:
STABLE_CHECKS_REQUIRED = 3
По умолчанию проверка выполняется каждые 2 секунды:
Python:
CHECK_INTERVAL_MS = 2000
То есть видеопоток должен сохраняться примерно 6 секунд подряд.
После этого скрипт ждёт ещё 5 секунд и включает последнее устройство.
Аварийный таймаут
Если одна из приоритетных камер неисправна или недоступна по сети, ждать её бесконечно не нужно.
Для этого используется:
Python:
MAX_WAIT_SEC = 180
Через 180 секунд регистратор будет запущен в любом случае:
Python:
FORCE_NVR_AFTER_TIMEOUT = True
Если требуется строгий режим, можно изменить:
Python:
FORCE_NVR_AFTER_TIMEOUT = False
В этом случае последнее устройство не будет включено, пока не появятся все приоритетные камеры.
Установка скрипта в TRASSIR
- Открыть настройки TRASSIR.
- Перейти в раздел автоматизации/скриптов.
- Создать новый скрипт.
- Вставить код.
- Изменить PRIORITY_IPS под свои камеры.
- Указать NVR_IP.
- Сохранить и запустить скрипт.
- Первую проверку желательно выполнить без перезагрузки сервера.
- После успешного теста перезагрузить сервер и проверить автоматическую последовательность подключения устройств.
Логирование
Все сообщения скрипта имеют префикс:
Код:
[ANYIP PRIORITY]
Например:
Код:
[ANYIP PRIORITY] Disabling NVR first: 192.168.0.238
[ANYIP PRIORITY] Starting priority cameras
[ANYIP PRIORITY] Priority cameras ready: 6/6
[ANYIP PRIORITY] All cameras have video. Stability check 3/3
[ANYIP PRIORITY] Starting NVR LAST: 192.168.0.238
[ANYIP PRIORITY] NVR started successfully
Важно
Перед использованием обязательно замените IP-адреса из примера на адреса своих устройств.
Желательно сначала проверить сценарий на работающем сервере вручную, без полной перезагрузки.
Скрипт намеренно управляет только указанными устройствами и не отключает остальные камеры на сервере.