Bild von IP Kamera holen
-
- Beiträge: 1224
- Registriert: So 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
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_ac ... n#Overview
Muss ich das selber programmieren oder macht das der fphttpclient für mich?
Muss ich das selber programmieren oder macht das der fphttpclient für mich?
-
- Beiträge: 582
- Registriert: Sa 22. Okt 2016, 23:12
- OS, Lazarus, FPC: W10, L 3.8
- CPU-Target: 32+64bit
- Wohnort: Dresden
Re: Bild von IP Kamera holen
schau mal hier wurde was mit synapse gemacht: http://forum.lazarus.freepascal.org/ind ... 747.0.html
LG Maik
Windows 10,
- Lazarus 3.8 (stable) + fpc 3.2.2 (stable)
- Lazarus 4.99 (trunk) + fpc 3.3.1 (main/trunk)
Windows 10,
- Lazarus 3.8 (stable) + fpc 3.2.2 (stable)
- Lazarus 4.99 (trunk) + fpc 3.3.1 (main/trunk)
- kupferstecher
- Beiträge: 431
- Registriert: Do 17. Nov 2016, 11:52
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):
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;
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Bild von IP Kamera holen
Das macht auch wieder Basic Authentification. Das kann auch der FPHTTPClientkupferstecher 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.
Musst du wohl oder übel selbst machen. Aber wie gesagt, Indy kann das bereits, ich würd einfach Indy verwenden. Ansonsten siehe:Timm Thaler hat geschrieben:Ich hab jetzt was in der englischen Wikipedia zur Berechnung des response gefunden: https://en.wikipedia.org/wiki/Digest_ac ... n#Overview
Muss ich das selber programmieren oder macht das der fphttpclient für mich?
Da wurde das per hand in synapse implementiertsstvmaster hat geschrieben:schau mal hier wurde was mit synapse gemacht: http://forum.lazarus.freepascal.org/ind ... 747.0.html
-
- Beiträge: 1224
- Registriert: So 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
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.
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.
-
- Beiträge: 1224
- Registriert: So 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
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?
Mein Gottchen, MD5 ist doch eh kaputt, eigentlich könnte man sich den Mist auch sparen, oder?
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Bild von IP Kamera holen
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 genugTimm 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?
-
- Beiträge: 1224
- Registriert: So 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
Re: Bild von IP Kamera holen
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.
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;
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.
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Bild von IP Kamera holen
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)));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.
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
-
- Beiträge: 1224
- Registriert: So 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
Re: Bild von IP Kamera holen
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.Warf hat geschrieben:Wenn du nach jedem .Create ein Try - Finally machst, vergisst du das Free auch weniger
Ich hab das jetzt auch nochmal auseinandergenommen und die Authentifizierung in eigene Prozeduren gepackt.