IPCAM integration in FHEM TabletUI

Begonnen von Adimarantis, 05 Februar 2019, 13:22:00

Vorheriges Thema - Nächstes Thema

Adimarantis

Nachdem ich hier lange rumgesucht habe, bis ich meine Kameras voll in TabletUI integrieren konnte, möchte ich meinen Ansatz hier mal vorstellen.

Situation:
- Zwei IPCameras (verschiedene Inkovideo Modelle - am Ende also China Kameras)
- FHEM auf Rapsi mit nginx
- Kamerabild soll im TabletUI erscheinen

Problemstellung:
- Browser unterstützen kein RTSP
- Kameras verlangen Authentifizierung
- Authenfizierung über user:password@host geht nicht mehr und basicAuth ist wegen cross-site nicht möglich

Lösung:

1. Passwortfreier Zugang auf Kamera

Hier kommt ein reverse-proxy via nginx zum Einsatz. Dazu in die nginx reverse-proxy folgendes eintragen:

server {
    listen 3333;
    server_name ipcam;

    location / {
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://<Adresse der ipcam>;
    proxy_set_header Authorization "Basic <base64-password string>";
     }
}


Entsprechend die Adresse der ipcam x.x.x.x:80 einsetzen und den user:password der Ipcam nach base64 convertieren (z.B. mit https://www.base64encode.org/ - mit dem Linux command "base64" hatte ich Probleme und ewig rumprobiert). Diesen entsprechend bei <base64-password string> ohne Anführungszeichen eintragen.

Die meisten Cameras stellen ein jpg Standbild zur Verfügung. Meine z.B. unter

http://ipcam1/tmpfs/auto.jpg
bzw.
http://ipcam2/snap.jpg?size=m

Nach einem reload der nginx config (sudo nginx -s reload) solltet ihr jetzt mit

http://<fhem-server>:3333/tmpfs/auto.jpg

auf das Kamera Standbild kommen, ohne das Passwort eingeben zu müssen.

2. Bild in der TabletUI einbinden:

Entsprechend einen Bereich mit dem Bild eintragen:
                <div class="sheet">
<img id="img1" src="http://<fhem-server>:3333/tempfs/auto.jpg">
                </div>


Soweit so gut - jetzt sollte euer TableUI ein Standbild eurer Kamera anzeigen.

3. Als die Bilder laufen lernten

Um jetzt aus dem Standbild ein Video zu machen, kommt noch etwas Javascript dazu, welches das Bild periodisch neu lädt. Dieses im <head> Bereich eurer index.html einfügen:

<script language="javascript">
<!--
var img = new Image();
var imgObj;
var myurl;

function changesrc()
{
img.src=myurl + "?" + (new Date()).getTime();
imgObj.src = img.src;
}

function load()
{
myurl = "http://<fhem-server>:3333//tmpfs/auto.jpg"
imgObj = document.getElementById('img1');
changesrc();
setInterval(changesrc,1000);
}

//-->
</script>


In diesem Fall wird das Bild einmal pro Sekunde erneuert - wer es flüssiger will reduziert den Wert 1000 (in Millisekunden) entsprechend.
Das Anhängen eines timestamps mit "?" dient dazu den Cache-Mechanismus auszutricksen, der sich sonst weigern würde das selbe Bild nochmal zu laden.

Damit das Script jetzt noch initialisiert wird, muss noch die "body" Anweisung abgeändert werden:

<body onload="load()">

Fertig sollte eure Kameraintegration sein. Durch entsprechendes Duplizieren des Codes/Variablen lassen sich auch mehrere Kameras gleichzeitig darstellen. In nginx braucht ihr dazu jeweils eine neue "server" Sektion mit neuem Port.

Gruß,
Jörg
Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

Adimarantis

Noch ein weiterführender Tipp dazu.

Leider gibt es auch IPCAMs bei denen so ein .jpg Standbild nicht existiert (oder zumindest nicht dokumentiert ist, wie man dran kommt).
Den RTSP Stream gibt es aber normalerweise immer.
Mit diesem kann jetzt eine Webpage nicht viel anfangen.

Es gibt aber eine Möglichkeit dieses .jpg zu simulieren.

Dazu benötigt ihr "ffmpeg" - ist normalerweise auf einem Raspberry installiert - sonst mit
sudo apt-get install ffmpeg
installieren.

Die Herausforderung ist die richtigen Kommandozeilenoptionen zu finden. Das funktioniert so (user, password und IP entsprechend anpassen):
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.1.61:554/11 -y -updatefirst 1 -r 1 /tmp/cam.jpg
Leider setzt das den Raspberry je nach Auflösung ziemlich unter Stress obwohl meistens keiner hinschaut.

Meine Lösung ist, dass diese Kameras in einer Tablet UI Unterseite angezeigt werden.
Zu Beginn der load() Funktion (wie im vorigen Post beschrieben) setzt man folgenden Befehl:
ftui.sendFhemCommand('{qx(cpulimit -l 50 -- ffmpeg -nostats -loglevel quiet -rtsp_transport tcp -t 00:00:30 -i rtsp://user:password\\@192.168.1.61:554/13 -s 500x312 -y -updatefirst 1 -r 1 /tmp/cam2.jpg >/dev/null 2>/dev/null);;}');


Der Befehl "cpulimit" muss nicht sein (muss aber evtl. mit "sudo apt-get install cpulimit" erst installiert werden) - damit will ich nur die Belastung weiter reduzieren. Dann sollte man aber "&" anhängen um den Prozess in den Hintergrund zu schicken, da "qx" sonst FHEM blockiert.

Beim Laden der Seite wird jetzt für 30 Sekunden die Bilderzeugung gestartet. Der "-s" Parameter reduziert die Größe und beschleunigt damit den Prozess. Wer das volle Bild braucht, einfach weglassen.

Weitere Optimierungen wären nur eine Ausschnitt zu verwenden (crop) und die Uhrzeit einzublenden. Dazu folgendes vor dem "-r 1" einfügen:
-filter:v  "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:  text='%{localtime\:%T}':fontsize=20: fontcolor=green: x=680: y=300, crop=570:286:670:40"

Das jpeg schreibe ich nach /tmp (welches bei mir auf einem RAM Filesystem liegt) um die SD Karte zu schonen. Um darauf zugreifen zu können mit "ln -s /tmp/cam.jpg cam.jpg" einen Softlink in das Tablet UI html Verzeichnis erzeugen.

Statt der URL in meinem ersten Post, jetzt einfach "cam.jpg" verwenden.

In diesem Fall braucht man auch kein nginx, da das Bild lokal liegt - hat auch den Vorteil, dass hier sogar der Zugriff außerhalb des LAN funktioniert, sofern man das eingerichtet hat.

Damit nicht auffällt, das das Bild nur 30 Sekunden aktualisert wird, springe ich nach dieser Zeit wieder auf die Hauptseite:
Im <body>:
<meta http-equiv="refresh" content="30; URL=index.html">

Gruß,
Jörg


Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

patator

Hallo zusammen,

ich habe heute schon mal in einen älteren Post der das gleiche mit Apache macht geschrieben.
Habe dieses Beispiel nun übernommen und komme leider nicht weiter.
Ich habe eine Wansview W2 Kamera, deren Webinterface mit Username und Passwort gesichert sind.
Wenn ich den Nginx so konfiguriere mit meinem base64 username:pasword string, dann bekomme ich keinen Login in die Kamera Oberfläche lediglich ein Login Popup für Username und Passwort dass die hinterlegten Kennwörter nicht annimmt.

Hier meine Nginx Konfig:

server {
    listen 3333;
    server_name ipcam1;

    location / {
proxy_method POST;
proxy_set_header        Content-Length "";
proxy_pass_request_body off;
proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "Basic <mein code>";
proxy_pass http://192.168.2.26;
    }
}


Nehme ich proxy_set_header raus kann ich mich mit meinen Credentials anmelden.
Würde gerne diesen Weg nutzen, dass ich praktisch im eigenen Netz die Passwort Eingabe umgehe, um den Webstream der Kamera via Tablet UI im Fully Browser darstellen kann.

Für jede Art Hilfe wäre ich sehr dankbar.

Viele Grüße

Patrick

Zitat von: Adimarantis am 05 Februar 2019, 13:22:00
Nachdem ich hier lange rumgesucht habe, bis ich meine Kameras voll in TabletUI integrieren konnte, möchte ich meinen Ansatz hier mal vorstellen.

Situation:
- Zwei IPCameras (verschiedene Inkovideo Modelle - am Ende also China Kameras)
- FHEM auf Rapsi mit nginx
- Kamerabild soll im TabletUI erscheinen

Problemstellung:
- Browser unterstützen kein RTSP
- Kameras verlangen Authentifizierung
- Authenfizierung über user:password@host geht nicht mehr und basicAuth ist wegen cross-site nicht möglich

Lösung:

1. Passwortfreier Zugang auf Kamera

Hier kommt ein reverse-proxy via nginx zum Einsatz. Dazu in die nginx reverse-proxy folgendes eintragen:

server {
    listen 3333;
    server_name ipcam;

    location / {
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://<Adresse der ipcam>;
    proxy_set_header Authorization "Basic <base64-password string>";
     }
}


Entsprechend die Adresse der ipcam x.x.x.x:80 einsetzen und den user:password der Ipcam nach base64 convertieren (z.B. mit https://www.base64encode.org/ - mit dem Linux command "base64" hatte ich Probleme und ewig rumprobiert). Diesen entsprechend bei <base64-password string> ohne Anführungszeichen eintragen.

Die meisten Cameras stellen ein jpg Standbild zur Verfügung. Meine z.B. unter

http://ipcam1/tmpfs/auto.jpg
bzw.
http://ipcam2/snap.jpg?size=m

Nach einem reload der nginx config (sudo nginx -s reload) solltet ihr jetzt mit

http://<fhem-server>:3333/tmpfs/auto.jpg

auf das Kamera Standbild kommen, ohne das Passwort eingeben zu müssen.

2. Bild in der TabletUI einbinden:

Entsprechend einen Bereich mit dem Bild eintragen:
                <div class="sheet">
<img id="img1" src="http://<fhem-server>:3333/tempfs/auto.jpg">
                </div>


Soweit so gut - jetzt sollte euer TableUI ein Standbild eurer Kamera anzeigen.

3. Als die Bilder laufen lernten

Um jetzt aus dem Standbild ein Video zu machen, kommt noch etwas Javascript dazu, welches das Bild periodisch neu lädt. Dieses im <head> Bereich eurer index.html einfügen:

<script language="javascript">
<!--
var img = new Image();
var imgObj;
var myurl;

function changesrc()
{
img.src=myurl + "?" + (new Date()).getTime();
imgObj.src = img.src;
}

function load()
{
myurl = "http://<fhem-server>:3333//tmpfs/auto.jpg"
imgObj = document.getElementById('img1');
changesrc();
setInterval(changesrc,1000);
}

//-->
</script>


In diesem Fall wird das Bild einmal pro Sekunde erneuert - wer es flüssiger will reduziert den Wert 1000 (in Millisekunden) entsprechend.
Das Anhängen eines timestamps mit "?" dient dazu den Cache-Mechanismus auszutricksen, der sich sonst weigern würde das selbe Bild nochmal zu laden.

Damit das Script jetzt noch initialisiert wird, muss noch die "body" Anweisung abgeändert werden:

<body onload="load()">

Fertig sollte eure Kameraintegration sein. Durch entsprechendes Duplizieren des Codes/Variablen lassen sich auch mehrere Kameras gleichzeitig darstellen. In nginx braucht ihr dazu jeweils eine neue "server" Sektion mit neuem Port.

Gruß,
Jörg

patator

Hallo Zusammen,

kleiner Nachtrag, da die Wansview W2 eine Digest Authentifizierung macht, ist der Proxy Bypass mit Auth Header so nicht umsetzbar.
Falls mal einer auf das gleiche Problem stösst und sich dusselig sucht.

VG

majestro84

Zitat von: patator am 19 April 2019, 18:28:13
Hallo zusammen,

ich habe heute schon mal in einen älteren Post der das gleiche mit Apache macht geschrieben.
Habe dieses Beispiel nun übernommen und komme leider nicht weiter.
Ich habe eine Wansview W2 Kamera, deren Webinterface mit Username und Passwort gesichert sind.
Wenn ich den Nginx so konfiguriere mit meinem base64 username:pasword string, dann bekomme ich keinen Login in die Kamera Oberfläche lediglich ein Login Popup für Username und Passwort dass die hinterlegten Kennwörter nicht annimmt.

Hier meine Nginx Konfig:

server {
    listen 3333;
    server_name ipcam1;

    location / {
proxy_method POST;
proxy_set_header        Content-Length "";
proxy_pass_request_body off;
proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "Basic <mein code>";
proxy_pass http://192.168.2.26;
    }
}


Nehme ich proxy_set_header raus kann ich mich mit meinen Credentials anmelden.
Würde gerne diesen Weg nutzen, dass ich praktisch im eigenen Netz die Passwort Eingabe umgehe, um den Webstream der Kamera via Tablet UI im Fully Browser darstellen kann.

Für jede Art Hilfe wäre ich sehr dankbar.

Viele Grüße

Patrick
Hallo Patrick
Hast du in der Zwischenzeit einen Weg gefunden den Livestream der W2 in die TabletUi zubekommen?
VG Alex
Server: Fujitsu ESPRIMO Q920 - aktuellen FHEM-Docker Image:Z-Wave (RollerShutter,DoorWindow,Socket,PIR,....) | ENIGMA2 | EGPM2LAN | BLE-Tag(PRESENCE) | HUE | alexa-fhem | Shelly | MQTT2
1.Pi-Zero:Viessmann(optolink) mit 89_VCONTROL300.pm
2.Pi3 Dongle Server: Zigbee2MQTT(CC1352P-2), Z-Wave(UZB1), BT