Bild von IP Kamera holen

Alle Fragen zur Netzwerkkommunikation

Re: Bild von IP Kamera holen

Beitragvon Timm Thaler » 2. Okt 2018, 20:52 Re: Bild von IP Kamera holen

Ich hab jetzt was in der englischen Wikipedia zur Berechnung des response gefunden: https://en.wikipedia.org/wiki/Digest_access_authentication#Overview

Muss ich das selber programmieren oder macht das der fphttpclient für mich?
Timm Thaler
 
Beiträge: 901
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon sstvmaster » 2. Okt 2018, 20:55 Re: Bild von IP Kamera holen

schau mal hier wurde was mit synapse gemacht: http://forum.lazarus.freepascal.org/ind ... 747.0.html
sstvmaster
 
Beiträge: 196
Registriert: 22. Okt 2016, 22:12
Wohnort: Dresden
OS, Lazarus, FPC: Windows 7 32bit (L 2.0.2 FPC 3.0.4) | 
CPU-Target: 32Bit
Nach oben

Beitragvon kupferstecher » 2. Okt 2018, 21:02 Re: Bild von IP Kamera holen

Ich hab mal mit Synapse eine URL-Anfrage mit User und Passwort (erfolgreich) durchgeführt. Hat aber nichts mit einer Kamera zu tun gehabt.

Hier mal die entscheidenden Stellen rauskopiert (hoffentlich komplett):

Code: Alles auswählen
uses HTTPSend;
//// Initialisierung
HTTP:= THTTPSend.Create;
 
HTTP.UserName:= 'Timm';
HTTP.Password:= '123456';
 
HTTP.Sock.SocksTimeout:= 5000; //ms
 
////Vorbereiten
HTTP.Clear;
WriteToMemStream(HTTP.Document,'URL-Anfrage');
 
////Senden
success:= HTTP.HTTPMethod('POST','Adresse');
 
////Antwort auslesen
if success and (HTTP.Document.Size > 0) then begin
  ReadFromMemStream(HTTP.Document,RecvStr);
end;
 
//Fertig
HTTP.Abort;
HTTP.Destroy;
kupferstecher
 
Beiträge: 206
Registriert: 17. Nov 2016, 11:52

Beitragvon Warf » 2. Okt 2018, 21:37 Re: Bild von IP Kamera holen

kupferstecher hat geschrieben:Ich hab mal mit Synapse eine URL-Anfrage mit User und Passwort (erfolgreich) durchgeführt. Hat aber nichts mit einer Kamera zu tun gehabt.


Das macht auch wieder Basic Authentification. Das kann auch der FPHTTPClient

Timm Thaler hat geschrieben:Ich hab jetzt was in der englischen Wikipedia zur Berechnung des response gefunden: https://en.wikipedia.org/wiki/Digest_access_authentication#Overview

Muss ich das selber programmieren oder macht das der fphttpclient für mich?


Musst du wohl oder übel selbst machen. Aber wie gesagt, Indy kann das bereits, ich würd einfach Indy verwenden. Ansonsten siehe:
sstvmaster hat geschrieben:schau mal hier wurde was mit synapse gemacht: http://forum.lazarus.freepascal.org/ind ... 747.0.html


Da wurde das per hand in synapse implementiert
Warf
 
Beiträge: 1111
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 2. Okt 2018, 22:03 Re: Bild von IP Kamera holen

Ich denk mal, ich werde mir das selbst zusammenzimmern, ehe ich jetzt wieder auf ein externes Projekt wie Indy setze.

Ich nehme an, den Server dazu zu überreden Base64 Auth zu verwenden, wenn er Digest Auth will ist nicht möglich.

Ist ja schön, dass die Chinesen sich hier so um die Sicherheit Gedanken machen. Etwas grotesk ist halt, dass sie andererseits die Kamerabilder per Default um den halben Globus schicken und das Passwort dafür 123456 ist. Ich hab das selbe Passwort an meinem Koffer.
Timm Thaler
 
Beiträge: 901
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Timm Thaler » 2. Okt 2018, 22:31 Re: Bild von IP Kamera holen

Ich hab jetzt wireshark noch auf dem Raspi installiert und die Kamera mit curl abgefragt. curl macht dabei im Prinzip das Gleiche wie Chromium unter Windows: Anfrage, 401 Error, erneute Anfrage mit den Login-Daten per Digest-Auth. Nur der cnonce-String sieht sehr anders aus, muss mal sehen, wie der ermittelt wird. < Ah, der Client-Nonce wird einmal im Klartext und einmal mit MD5 verschlüsselt im responce versendet.

Mein Gottchen, MD5 ist doch eh kaputt, eigentlich könnte man sich den Mist auch sparen, oder?
Timm Thaler
 
Beiträge: 901
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 3. Okt 2018, 00:08 Re: Bild von IP Kamera holen

Timm Thaler hat geschrieben:Ich hab jetzt wireshark noch auf dem Raspi installiert und die Kamera mit curl abgefragt. curl macht dabei im Prinzip das Gleiche wie Chromium unter Windows: Anfrage, 401 Error, erneute Anfrage mit den Login-Daten per Digest-Auth. Nur der cnonce-String sieht sehr anders aus, muss mal sehen, wie der ermittelt wird. < Ah, der Client-Nonce wird einmal im Klartext und einmal mit MD5 verschlüsselt im responce versendet.

Mein Gottchen, MD5 ist doch eh kaputt, eigentlich könnte man sich den Mist auch sparen, oder?


Könnte man, wenn man HTTPs verwendet kann man auch Basic auth verwenden. Aber MD5 ist in so fern unsicher das man gezielt kollisionen erzeugen kann, ich glaube aber echtes "entschlüsseln" ist damit auch nicht wirklich möglich. Für die meisten fälle wohl sicher genug
Warf
 
Beiträge: 1111
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 3. Okt 2018, 13:31 Re: Bild von IP Kamera holen

Verdammte Axt, ich glaub es läuft.

Code: Alles auswählen
uses
  Classes, SysUtils, StrUtils, DateUtils, Crt,
  md5, fphttpclient, fpimage, fpwritejpeg;
 
const
  host = 'http://192.168.2.10';
  uri = '/mjpeg/snap.cgi?chn=0';
  url = host + uri;
  user = 'admin';
  pwd = '123456';
var
  fname : string = 'test.jpg';
  k, j : integer;
 
function GetImageData(const data : TMemoryStream) : integer;
const
  ncount : integer = 0;
  realm : string = '';
  qop : string = '';
  nonce : string = '';
  cnonce : string = '';
  oldnonce : string = '';
  oldcnonce : string = '';
var
  hcli : TFPHTTPClient;
  param : TStringList;
  i : integer;
  txt : string;
  nc, h1, h2, h3 : string;
begin
  GetImageData := 0;
  try
    hcli := TFPHTTPClient.Create(nil);
    try
      hcli.AddHeader('User-Agent','Mozilla/5.0 (compatible; fpweb)');
      if nonce <> '' then begin  // prüfen ob bereits Parameter für Auth von Kamera erhalten
        if nonce = oldnonce then begin  // Anmeldung noch gültig
          Inc(ncount);
          cnonce := oldcnonce;
        end else begin  // neue Anmeldung
          ncount := 1;
          cnonce := md5Print(md5String(IntToStr(DateTimeToUnix(Now()))));
          WriteLn(ncount, ' ', cnonce);
          oldnonce := nonce;
          oldcnonce := cnonce;
        end;
        nc := RightStr('00000000' + IntToStr(ncount), 8);
        h1 := md5Print(md5String(user + ':' + realm + ':' + pwd));
        h2 := md5Print(md5String('GET' + ':' + uri));
        h3 := md5Print(md5String(h1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + h2));
        txt := 'Digest username=' + AnsiQuotedStr(user,#34) + ', realm=' + AnsiQuotedStr(realm, #34) + ', nonce=' + AnsiQuotedStr(nonce,#34) + ', uri=' + AnsiQuotedStr(uri, #34) + ', qop=' + qop + ', nc=' + nc + ', cnonce=' + AnsiQuotedStr(cnonce, #34) + ', response=' + AnsiQuotedStr(h3, #34);
        hcli.AddHeader('Authorization', txt);
      end;
      data.Clear;
      hcli.HTTPMethod('GET', url, data, [200, 400, 401, 403, 404]);
 
      if hcli.ResponseStatusCode = 401 then begin  // wenn Auth gefordert
        txt := Trim(hcli.ResponseHeaders.Values['www-authenticate'])// Auth ermitteln
        if Lowercase(LeftStr(txt, 6)) = 'digest' then begin
          param := TStringList.Create();
          param.Clear;
          param.StrictDelimiter := true;
          param.Delimiter := ',';
          param.DelimitedText := Trim(Copy(txt, 7, Length(txt)));
          for i := 0 to param.Count - 1 do begin
            param[i] := StringReplace(Trim(param[i]), '"', '', [rfReplaceAll]);
          end;
          realm := param.Values['realm']// Parameter der Auth übernehmen
          nonce := param.Values['nonce'];
          qop := param.Values['qop'];
          param.Free;
          oldnonce := '';
          ncount := 0;
        end;
      end;
      data.Position := 0// Stream auf Anfang
      GetImageData := hcli.ResponseStatusCode;
    except
      WriteLn('Fehler beim Senden');
    end;
  finally
    hcli.Free;
  end;
end;
 
 
 
procedure ReadCamera();
var
  idata : TMemoryStream;
  ifile : TFileStream;
  stat : integer;
begin
  idata := TMemoryStream.Create();
  stat := GetImageData(idata);
  if stat = 401 then begin  // wenn Auth angefordert
    stat := GetImageData(idata)// nochmal mit Auth abrufen
  end;
  if stat = 200 then begin  // wenn erfolgreich
    try
      ifile := TFileStream.Create(fname, fmCreate);
      ifile.CopyFrom(idata, idata.Size);
      WriteLn('Bild gespeichert');
    finally
      ifile.Free;
    end;
  end;
  idata.Free;
end;


Funktioniert soweit erstmal. Hat gerade ein paar hundert Bilder geholt. Ist zwischendrin mit einer Exception "Server nicht erreichbar" abgeschmiert, aber um das Exception-Handling muss ich mich noch kümmern.

Der Client merkt sich die Anmeldedaten und versucht erstmal mit diesen Daten - oder Nichts beim Starten - ein Bild zu holen. Schlägt das fehl, versucht er es mit den übermittelten Parametern erneut.

Das ist noch etwas unausgegoren, eigentlich müsste ich noch prüfen, ob qop = 'auth' und so Kram. Ich bin da für Verbesserungsvorschläge offen. Bitte schaut mal drüber und teilt mir auch grobe Schnitzer mit, besonders anfällig bin ich für vergessene oder falsch platzierte Frees.

Wenn das läuft, stelle ich es gern ins Wiki. Prinzipiell sollte es für alle Kameras gehen, die Onvif unterstützen, denn dort ist die Einzelbildabfrage mit Digest Auth per http einer der Standards.
Timm Thaler
 
Beiträge: 901
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 3. Okt 2018, 20:24 Re: Bild von IP Kamera holen

Timm Thaler hat geschrieben:Verdammte Axt, ich glaub es läuft.

Funktioniert soweit erstmal. Hat gerade ein paar hundert Bilder geholt. Ist zwischendrin mit einer Exception "Server nicht erreichbar" abgeschmiert, aber um das Exception-Handling muss ich mich noch kümmern.

Der Client merkt sich die Anmeldedaten und versucht erstmal mit diesen Daten - oder Nichts beim Starten - ein Bild zu holen. Schlägt das fehl, versucht er es mit den übermittelten Parametern erneut.

Das ist noch etwas unausgegoren, eigentlich müsste ich noch prüfen, ob qop = 'auth' und so Kram. Ich bin da für Verbesserungsvorschläge offen. Bitte schaut mal drüber und teilt mir auch grobe Schnitzer mit, besonders anfällig bin ich für vergessene oder falsch platzierte Frees.

Wenn das läuft, stelle ich es gern ins Wiki. Prinzipiell sollte es für alle Kameras gehen, die Onvif unterstützen, denn dort ist die Einzelbildabfrage mit Digest Auth per http einer der Standards.


Statt es ins wiki zu stellen wäre es besser einfach das ganze in die HTTP client klasse zu basteln und die dann über den Bugtracker oder so zu submitten. Zu den Frees, benutz immer try-finally. Wenn eine Exception auftritt wird die Methode verlassen und die Exception hoch gegeben. Aller speicher der nicht durch ein Finally bereinigt wird ist verloren. Z.B. deine Zeile: param.DelimitedText := Trim(Copy(txt, 7, Length(txt)));
Wenn du nicht genug speicher frei hast (oder dein Speicher zu fragmentiert ist) dann bekommst du eine Exception, die Methode wird verlassen und Param wird nie freigegeben.

Wenn du nach jedem .Create ein Try - Finally machst, vergisst du das Free auch weniger
Warf
 
Beiträge: 1111
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 3. Okt 2018, 21:17 Re: Bild von IP Kamera holen

Warf hat geschrieben:Wenn du nach jedem .Create ein Try - Finally machst, vergisst du das Free auch weniger


Das ist wohl war, aber das kann eine ordentliche try-finally-Orgie werden. Was mir auch fehlt ist ein try-exception-finally, also die Exception abhandeln und dann abschließende Bereinigung.

Ich hab das jetzt auch nochmal auseinandergenommen und die Authentifizierung in eigene Prozeduren gepackt.
Timm Thaler
 
Beiträge: 901
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

• Themenende •
Vorherige

Zurück zu Netzwerk



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried