ONVIF-адаптер для ioBroker
Адаптер для ONVIF-камер
Этот адаптер использует библиотеки Sentry для автоматического сообщения разработчикам об исключениях и ошибках в коде. Более подробную информацию, а также инструкции по отключению отправки сообщений об ошибках см. в документации Sentry-Plugin ! Система отчетности Sentry используется начиная с js-controller 3.0.
Добавить камеры
Открытие:
При каждом запуске адаптера выполняется поиск с использованием имени пользователя и пароля, введенных в настройках, и предпринимается попытка входа в камеру. Если камера еще не добавлена в раздел «Объекты».
Обнаружение можно выполнить вручную в настройках. Если у камер разные учетные данные, вам нужно будет ввести их и выполнить обнаружение. В журнале вы увидите подробности процесса.
Для того чтобы камера снова была обнаружена, её достаточно просто удалить в разделе «Объекты».
Ручной поиск
Если функция обнаружения не работает, поиск камер можно выполнить вручную. Для этого необходимо ввести диапазон IP-адресов и портов и выполнить поиск вручную. В журнале можно увидеть подробности процесса.
Штаты
onvif.0.IP_PORT.events События камеры, например, обнаружение движения. Иногда для просмотра события необходимо его инициировать.
onvif.0.IP_PORT.general Общая информация о камерах
Информация о камере в файле onvif.0.IP_PORT.infos обновляется только при запуске адаптера или при выполнении команды remote.refresh.
URL видео и снимков экрана:
onvif.0.IP_PORT.infos.streamUris.MediaProfile_Channel1_MainStream.snapshotUrl.uri
onvif.0.IP_PORT.remote Управление камерой
onvif.0.IP_PORT.remote.refresh Обновление информационных данных
onvif.0.IP_PORT.remote.gotoHomePosition Установить PTZ-камеру в исходное положение
onvif.0.IP_PORT.remote.gotoPreset Выберите номер предустановки PTZ-камеры
onvif.0.IP_PORT.remote.snapshot Сохранить снимок в onvif.0.IP_PORT.snapshot
Сообщение
Адаптер получает сообщение "снимок" и возвращает изображение.
sendTo('onvif.0', 'snapshot', '192_168_178_100_80', (result) => {
if (result) {
sendTo('telegram.0', {
text: result,
type: 'photo',
caption: 'camera2',
});
}
});
Сообщение, отправленное через Telegram
on('onvif.0.192_168_178_100_80.events.RuleEngine/CellMotionDetector/Motion', (obj) => {
if (obj.state.val === true) {
sendTo('onvif.0', 'snapshot', '192_168_178_100_80', (result) => {
if (result) {
sendTo('telegram.0', {
text: result,
type: 'photo',
caption: 'Camera 2',
});
}
});
}
});
Включить поток в визуализацию
Если потоковое изображение должно отображаться в Apple HomeKit, создайте камеру непосредственно в Yahka. Если это не сработает или требуется HKSV, установите Scrypted в Docker и добавьте камеру с ONVIF и плагином HomeKit.
go2rtsp Docker
Поток обычно передается через RTSP. Преобразование через MotionEye очень ресурсоемко и сопровождается задержкой. Преобразование в WebRTC происходит быстрее и экономит ресурсы. Я рекомендую использовать go2rtsp . Для этого необходимо создать Docker-образ из alexxit/go2rtc. https://hub.docker.com/r/alexxit/go2rtc
image: alexxit/go2rtc
network_mode: host # important for WebRTC, HomeKit, UDP cameras
privileged: true # only for FFmpeg hardware transcoding
restart: unless-stopped # autorestart on fail or config change from WebUI
environment:
- TZ=Europe/Berlin # timezone in logs
volumes:
- "~/go2rtc:/config" # folder for go2rtc.yaml file (edit from WebUI)
Необходимо указать в качестве пути /config том, а в качестве хоста — сеть.
Затем доступ к go2rtsp осуществляется через
http://IP:1984
Затем вы можете добавить поток. URL-адрес потока можно найти, например, в разделеonvif.0.IP_PORT.infos.streamUris.ProfileName.live_stream_tcp.uri
Вставить поток как iFrame
ДобавитьiFrame Вставьте виджет в Vis и используйте ссылку на поток от go2rtsp в качестве источника.
http://192.168.178.1:1984/stream.html?src=camera&mode=webrtc
Rtsp2Web Docker
Альтернативным вариантом является Docker-контейнер RTSPtoWeb . Однако его настройка сложнее. Docker-контейнер необходимо создать по адресу ghcr.io/deepch/rtsptoweb:latest.
docker run --name rtsp-to-web -v /YOURPATHFORCONFIG:/config --network host ghcr.io/deepch/rtsptoweb:latest
Необходимо указать том для пути /config, а сеть должна быть настроена как хост.
Затем доступ к rtsptoweb можно получить через
http://IP:8083
Затем вы можете добавить поток. URL-адрес потока можно найти, например, в разделеonvif.0.IP_PORT.infos.streamUris.ProfileName.live_stream_tcp.uri
Затем нам понадобится идентификатор потока. Для этого отредактируйте поток и скопируйте идентификатор из URL-адреса.
http://192.168.178.2:8083/pages/stream/edit/ddbdb583-9f80-4b61-bafa-613aa7a5daa5
Вставьте отдельный поток в визуализацию.
Затем выберите HTML-объект в виджете. После этого в поле HTML введите адрес rtsp2web-сервера с идентификатором потока:
Если необходимо добавить несколько потоков,webrtc-url иwebrtc-video В HTML и скрипте необходимо заменить новым идентификатором, например:webrtc-url2 иwebrtc-video2
<input
type="hidden"
name="webrtc-url"
id="webrtc-url"
value="http://192.168.0.2:8083/stream/ddbdb583-9f80-4b61-bafa-613aa7a5daa5/channel/0/webrtc"
/>
<video id="webrtc-video" autoplay muted playsinline controls style="max-width: 100%; max-height: 100%;"></video>
Добавьте этот скрипт в виджет в разделе «Скрипты»:
setTimeout(function () {
function startPlay(videoEl, url) {
const webrtc = new RTCPeerConnection({
iceServers: [
{
urls: ['stun:stun.l.google.com:19302'],
},
],
sdpSemantics: 'unified-plan',
});
webrtc.ontrack = function (event) {
console.log(event.streams.length + ' track is delivered');
videoEl.srcObject = event.streams[0];
videoEl.play();
};
webrtc.addTransceiver('video', { direction: 'sendrecv' });
webrtc.onnegotiationneeded = async function handleNegotiationNeeded() {
const offer = await webrtc.createOffer();
await webrtc.setLocalDescription(offer);
fetch(url, {
method: 'POST',
body: new URLSearchParams({ data: btoa(webrtc.localDescription.sdp) }),
})
.then((response) => response.text())
.then((data) => {
try {
webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: atob(data) }));
} catch (e) {
console.warn(e);
}
});
};
const webrtcSendChannel = webrtc.createDataChannel('rtsptowebSendChannel');
webrtcSendChannel.onopen = (event) => {
console.log(`${webrtcSendChannel.label} has opened`);
webrtcSendChannel.send('ping');
};
webrtcSendChannel.onclose = (_event) => {
console.log(`${webrtcSendChannel.label} has closed`);
startPlay(videoEl, url);
};
webrtcSendChannel.onmessage = (event) => console.log(event.data);
}
const videoEl = document.querySelector('#webrtc-video');
const webrtcUrl = document.querySelector('#webrtc-url').value;
startPlay(videoEl, webrtcUrl);
}, 1000);
Все потоки отображаются в виде iFrame.
В качестве альтернативы вы также можете вставить обзор камеры в виде iframe: Добавить виджетiFrame и введите сервер rtsp2web в качестве источника:
http://192.168.0.2:8083/pages/multiview/full?controls
поддержка FFMpeg
Если камера не поддерживает создание снимков, ffmpeg создаст снимок из потока RTSP.
Включите сервер моментальных снимков в визуальные данные.
Адаптер предоставляет сервер для создания моментальных снимков без пароля. Активируйте сервер в настройках экземпляра, и вы сможете получить текущий моментальный снимок по адресу http://iobrokerIp:8095/CAMERAIP_PORT, например, http://192.168.0.1:8095/192_168_0_1_80 .
Вставьте виджет изображения в визуализацию, укажите URL-адрес в качестве источника и выберите время обновления.
Включить снимок в визуализацию
По возможности используйте snapshotUri, например.
onvif.0.IP_PORT.infos.streamUris.MediaProfile_Channel1_MainStream.snapshotUrl.uri
Не используйте состояние в качестве потока, иначе нагрузка на диск будет слишком высокой.
Обновите состояние через onvif.0.IP_PORT.remote.snapshot
НазначитьString img src элемент в состояние onvif.0.IP_PORT.snapshot.
Или в качестве альтернативы, еслиString img src не работает
Вставьте состояние onvif.0.IP_PORT.snapshot следующим образом:HTML вставьте элемент в визуальный элемент со следующим содержимым
<img src="/ru/adapterref/iobroker.onvif/{onvif.0.IP_PORT.snapshot}" width="500px" />
Создать новый снимок по событию:
on('onvif.0.192_168_178_100_80.events.RuleEngine/CellMotionDetector/Motion', (obj) => {
if (obj.state.val === true) {
setState('onvif.0.192_168_178_100_80.remote.snapshot', true, false);
}
});
Дискуссия (на немецком языке)
https://forum.iobroker.net/topic/63145/test-adapter-onvif-camera-v1-0-0
Changelog
1.1.8 (2026-08-21)
- (TA2k) Fixed reconnect loop: the watchdog now only rebuilds on non-retryable event errors, so cameras that periodically reset the event socket ("socket hang up") are left to the onvif library's own retry instead of reconnecting every 30s
- (TA2k) Retryable event errors are logged at debug instead of warn and no longer flip the connection state
- (TA2k) Updated onvif to 0.8.2 and dev dependencies
1.1.7 (2026-08-20)
- (mcm1957) clean release built to fix missing tagging and github release
1.1.6 (2026-08-08)
- (TA2k) Faster reconnect after a camera reboot (detection in ~30-50s instead of ~4min)
- (TA2k) Connection state now reflects the real reconnect instead of flipping back to true too early
- (TA2k) Throttled the repeated event error log messages during a reboot
1.1.5 (2026-08-06)
- (copilot) Adapter requires node.js >= 22 now
- (copilot) Adapter requires admin >= 7.7.22 now
- (copilot) Adapter requires js-controller >= 6.0.11 now
1.1.4 (2024-05-27)
- update onvif lib to support newer TAPO cameras
- (mcm1957) Adapter requires nodejs >=18 now.
1.1.3 (2024-03-15)
- Allow non number PTZ presets
License
MIT License
Copyright (c) 2026 iobroker-community-adapters iobroker-community-adapters@gmx.de
Copyright (c) 2023-2024 TA2k tombox2020@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.