Бета по приглашениям бесплатно, вход по коду Получить код

Уведомления

Облако само замечает, что камера перестала выходить на связь, и говорит вам об этом – письмом, в Telegram или запросом на ваш адрес. Панель и приложение для этого открывать не нужно: о пропаже сообщит облако, а не вкладка в браузере. Камера вернулась – придёт и об этом.

Что приходит без настройки

Письмо на почту аккаунта – о ваших камерах. Ничего включать не нужно: если камера пропала, а вы ни разу не открывали раздел «Уведомления», письмо всё равно придёт.

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

Когда облако считает камеру пропавшей

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

О возвращении пишем только туда, куда писали о пропаже, и говорим, сколько камеры не было.

Если отвалились сразу несколько камер – за одним роутером, например, – придёт одно сообщение со списком, а не по одному на камеру. А если разом замолчала большая часть всех камер облака, это почти наверняка беда на нашей стороне, а не у вас: такое мы не рассылаем, а чиним.

Telegram

Панель → «Уведомления» → «Подключить Telegram». Откройте ссылку и нажмите Start – чат привязан. С компьютера ссылку можно отсканировать телефоном. Ссылка одноразовая и живёт десять минут.

Чтобы уведомления приходили в группу, нажмите «Добавить в группу» и выберите группу: бот привяжет её к вашему аккаунту.

Под сообщением о пропаже две кнопки: «Открыть» ведёт на страницу камеры в панели (нужен вход – ссылку можно переслать, и камеру по ней никто чужой не увидит), «Тишина на час» глушит эту камеру на час. Команда /stop в чате выключает уведомления туда. Заблокировали бота или удалили его из группы – канал выключится сам, и панель покажет почему.

В приложении

Приложение на телефоне получает уведомления пушем – даже закрытое. Пуши появятся с ближайшим обновлением приложения; облако к ним уже готово.

Подключать ничего не нужно: после входа приложение само сообщает облаку, куда слать, а при выходе из аккаунта – отключает. Каждый телефон виден в панели среди каналов как «Приложение», и там его можно выключить: приложение это решение не перебьёт. Вошли на телефоне в другой аккаунт – уведомления прежнего аккаунта на него больше не придут.

Пуш идёт через Firebase (Google) или, на телефонах без сервисов Google, через UnifiedPush – например, приложение ntfy. На экран блокировки попадает только имя камеры и время: ни адресов, ни ссылок на просмотр. Камеры, отвалившиеся вместе, приходят одним пушем.

Удалили приложение – облако узнает об этом от сервиса пушей и перестанет туда слать, а панель покажет почему. Установили снова и вошли – уведомления вернутся сами.

Настройки

В разделе «Уведомления» панели:

  • Куда приходят – почта, Telegram-чаты, телефоны с приложением и вебхуки. Любой можно выключить или проверить кнопкой «Проверить»; почту аккаунта можно выключить, но не удалить.
  • Когда говорить – сколько ждать, прежде чем написать о пропаже; писать ли о возвращении; писать ли о чужих камерах; язык сообщений.
  • Устройства – выключить уведомления об одной камере: например, о той, что выключают на ночь.
  • Последние уведомления – что и когда отправлено, и дошло ли.

Вебхук

Для своей автоматизации – Home Assistant, n8n, свой бот – облако отправит событие на ваш адрес. Панель → «Уведомления» → «Вебхук»: укажите https-адрес, и панель один раз покажет секрет подписи.

Адрес должен быть публичным и по https: на локальные и внутренние адреса облако не ходит.

Запрос – POST с JSON:

{
  "id": "evt_0192f3a1…",
  "type": "node.offline",
  "at": "2026-10-12T15:42:07Z",
  "node": { "id": "node_…", "name": "Подъезд", "kind": "Camera" },
  "lastSeenAt": "2026-10-12T15:40:31Z",
  "offlineSince": null,
  "count": null,
  "url": "https://cloud-panel.openipc.ru/#device=node_…"
}

Типы: node.offline – камера пропала, node.online – вернулась (в offlineSince – с какого момента её не было), test – кнопка «Проверить».

Заголовки:

ЗаголовокЧто в нём
X-Streq-Eventтип события
X-Streq-Deliveryномер доставки – повтор приходит с тем же номером
X-Streq-Timestampвремя отправки, секунды Unix
X-Streq-Signaturesha256= и HMAC-SHA256 от <время>.<тело> секретом подписи

Доставка – хотя бы раз: если ваш адрес не ответил 2xx, облако повторит позже, с тем же X-Streq-Delivery. Отбрасывайте повторы по нему. Адрес, который не принял двадцать доставок подряд, выключается сам; включите его в панели, когда почините.

Проверка подписи на Python:

import hashlib, hmac, time

def valid(secret: str, headers, body: bytes) -> bool:
    ts = headers["X-Streq-Timestamp"]
    if abs(time.time() - int(ts)) > 300:
        return False
    mac = hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest("sha256=" + mac, headers["X-Streq-Signature"])

На Node.js:

import { createHmac, timingSafeEqual } from 'node:crypto';

export function valid(secret, headers, body /* Buffer */) {
  const ts = headers['x-streq-timestamp'];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const mac = 'sha256=' + createHmac('sha256', secret).update(`${ts}.`).update(body).digest('hex');
  const got = Buffer.from(headers['x-streq-signature'] ?? '');
  return got.length === mac.length && timingSafeEqual(got, Buffer.from(mac));
}

На Go:

func valid(secret string, h http.Header, body []byte) bool {
	ts := h.Get("X-Streq-Timestamp")
	sec, err := strconv.ParseInt(ts, 10, 64)
	if err != nil || math.Abs(float64(time.Now().Unix()-sec)) > 300 {
		return false
	}
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(ts + "."))
	mac.Write(body)
	want := "sha256=" + hex.EncodeToString(mac.Sum(nil))
	return hmac.Equal([]byte(want), []byte(h.Get("X-Streq-Signature")))
}

Подпись считается от тела как оно пришло, байт в байт: не разбирайте JSON и не собирайте его заново перед проверкой.