Hallo,
ich schreibe gerade eine Anwendung zur Steuerung einer Startampel für Motorsport-Veranstaltungen mittels eines Raspberry Pi und compiliere diese mit FreePascal 2.6.0. Dieser steuert über die GPIO-Ports die eigentliche Ampel-Schaltung bzw. liest deren Zustand aus. Dazu enthält die Anwendung auch einen Webserver auf
Indy-Basis (TIdHTTPServer). Gleichzeitig ist an das Kamera-Interface des Pi auch noch eine passende Kamera angeschlossen, die einen Videostream liefert, aus dem dann interrupt-gesteuert bei Auslösen einer Lichtschranke das aktuelle Frame des Videostreams zwischengespeichert wird. Dies zur Überwachung des Startbereiches, für den die Startampel zuständig ist.
Eben dieses zwischengespeicherte Videoframe möchte ich als JPEG-Bild über den HTTP-Server ausgeben. Geht auch alles wunderbar, solange nur 1 Client auf das Webinterface zugreift. Sobald mehrere auf das Videobild zugreifen, stürzt die Software ab. Ich muss folgendes dazu sagen: die Umwandlung des Videoframes in das JPEG-Format einschließlich der Ausgabe in einen MemoryStream dauert ca. 2-3 Sekunden. Solange müssen alle Webclients warten, da die Erstellung mittels einer Critical Section geschützt ist.
Nochmal eine kurze Funktionsübersicht:
- Steuerung bzw. Auslesen der Startampel mittels GPIOs und Interrupts
- Abfangen einzelner Video-Frames der CSI-Kamera über einen GPIO-Interrupt, der durch eine angeschlossene Lichtschranke ausgelöst wird
- Ausgabe des Startampel-Zustands (Zählerstand, welche roten bzw. grünen LEDs leuchten etc.) + Steuerung über Webinterface mittels von TIdHTTPServer abgeleiteter Klasse
Nach langem Testen habe ich herausgefunden, dass die zeitliche Dauer der JPEG-Erstellung das Problem ist, da ich den Absturz der Anwendung auch dadurch herbeiführen kann, dass ich in das DoCommandGet-Event ein Sleep(2000) einfügen kann. Dies führt dann selbst beim Aufruf einfacher Text-Pages zum Absturz, unabhängig davon, ob ich "ContentText" oder "ContentStream" für die Ausgabe verwende. Dann auch schon, wenn nur 1 Webclient auf das Webinterface zugreift.
Wenn ich in der "TIdHTTPResponseInfo.WriteContent"-Methode (TIdCustomHTTPServer.pas)die "FConnection.IOHandler.Write"-Aufrufe auskommentiere, geht naturgemäß zwar keine Webausgabe, aber dann stürzt auch mein Programm nicht ab. Bei kurzen Antwortzeiten (kleine Seiten, Bilder etc.), die nur wenige Millisekunden benötigen, funktioniert alles wunderbar.
Ein kurzes Code-Beispiel:
Delphi-Quellcode:
procedure THTTPServer.DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
var
fs : TFileStream;
fileExt, document, content, filePath, fileName :
string;
commandNumber : Integer;
begin
document := '
HTTP' + StringReplace(ARequestInfo.Document, '
..', '
', [rfReplaceAll]);
if document = '
HTTP/'
then
document := document + '
index.html';
filePath := SysUtils.ExtractFilePath(document);
fileName := SysUtils.ExtractFileName(document);
try
// ...
// Hier werden ContentText bzw. ContentStream befüllt
// ...
finally
if Assigned(AResponseInfo.ContentStream)
then
begin
try
Sleep(2000);
// <--- führt zum kommentarlosen Crash
AResponseInfo.WriteContent;
except on e:
exception do
Writeln(e.
Message);
end;
end
else if AResponseInfo.ContentText <> '
'
then
begin
Sleep(2000);
// <--- führt ebenfalls zum kommentarlosen Crash
AResponseInfo.WriteContent;
end;
end;
end;
Es wird auch keine Fehlermeldung angezeigt. Die Anwendung ist eine Konsolenanwendung (ohne LCL) und ist dann einfach weg.
Ich hoffe, dass von euch jemand Erfahrungen und evtl. auch Lösungsansätze in der Richtung hat. Vielen Dank für eure Mühen!