UPnP, SOAP, HTTP

Alle Fragen zur Netzwerkkommunikation
Antworten
WeePee
Beiträge: 25
Registriert: So 8. Dez 2013, 13:46

UPnP, SOAP, HTTP

Beitrag von WeePee »

Hallo,

ich habe hier ein paar UPnP-fähige Geräte, die ich gerne via Programm monitoren möchte. Leider gibt es ja für Free Pascal keine funktionierende UPnP-Bibliothek, sodass ich versuche, die UPnP-Befehle, die ja im Prinzip HTTP-Requests/Responds sind, zu simulieren.

Das, was ich simulieren möchte, findet sich im ersten Bild, welches ich mit dem UPnP-Tool DeviceSpy erstellt habe.

Mit dem Tool DeviceSpy erzeugt.
Mit dem Tool DeviceSpy erzeugt.


Ich habe nun die Unit fphttpclient entdeckt, die es ermöglicht, HTTP-Requests zu versenden. Mein Beispielprogramm sieht so aus:

Code: Alles auswählen

var
  message : TStringList;
  message_string : string;
  c : TFPHTTPClient;
  return_stream : TMemoryStream;
  a_int : array of integer;
  i : integer;
 
begin
  c := TFPHTTPClient.Create(nil);
 
  message := TStringList.Create;
//  message.Add('POST /MediaRenderer/AVTransport/Control HTTP/1.1');
//  message.Add('HOST: 192.168.1.22:1400');
  message.Add('SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo"');
  message.Add('CONTENT-TYPE: text/xml; charset="utf-8"');
  message.Add('Content-Length: 351');
  message.Add(' ');
  message.Add('<?xml version="1.0" encoding="utf-8"?>');
  message.Add('<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">');
  message.Add('  <s:Body>');
  message.Add('    <u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">');
  message.Add('      <InstanceID>0</InstanceID>');
  message.Add('    </u:GetPositionInfo>');
  message.Add('  </s:Body>');
  message.Add('</s:Envelope>');
 
  message_string := message.Strings[0];
  for i := 1 to message.count - 1 do
    message_string := message_string + chr(13) + chr(10) + message.Strings[i];
 
  return_stream := TMemoryStream.Create;
  c.HTTPMethod(message_string, 'http://192.168.1.22:1400/MediaRenderer/AVTransport/Control', return_stream, a_int);
 
  writeln(IntToStr(return_stream.Size));
  for i:=0 to return_stream.Size - 1 do
  begin
    return_stream.Position := i;
    write(chr(ord(return_stream.ReadByte)));
  end;


Leider funktioniert das noch nicht so richtig.

In der obigen Form wird die Nachricht versendet und es gibt auch eine Antwort. Die besagt aber: Bad Request.

Wenn die beiden Kommentarzeilen als Code ausgeführt werden, dann gibt es noch nicht mal eine Antwort. Der Aufruf c.HTTPMethod kehrt nicht zurück.

Mir ist klar, dass ich noch irgendetwas falsch mache. Bloß was? Hat jemand eine Idee?

Liebe Grüße
Wolfram

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: UPnP, SOAP, HTTP

Beitrag von gocher »

Hallo WeePee,
ein SOAP-Client wäre für dieses Projekt besser!

Falls Du jedoch Deinen Weg fortführen möchtest sollte es eher in folgende Richtung gehen:

Code: Alles auswählen

program httpsoaptest;
 
uses SysUtils, Classes, fphttpclient;
 
var
  client: TFPHttpClient;
  request: TStringList;
  stream, result: TMemoryStream;
  i: integer;
begin
  client := TFPHttpClient.Create(Nil);
  client.RequestHeaders.Add('HOST: 192.168.1.22:1400');
  client.RequestHeaders.Add('SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo"');
  client.RequestHeaders.Add('CONTENT-TYPE: text/xml; charset="utf-8"');
  request := TStringList.Create;
  request.Add('<?xml version="1.0" encoding="utf-8"?>');
  request.Add('<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">');
  request.Add('  <s:Body>');
  request.Add('    <u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">');
  request.Add('      <InstanceID>0</InstanceID>');
  request.Add('    </u:GetPositionInfo>');
  request.Add('  </s:Body>');
  request.Add('</s:Envelope>');
  stream := TMemoryStream.Create;
  request.SaveToStream(stream);
  stream.Position := 0;
  request.Clear;
  client.RequestHeaders.Add('Content-Length: '+IntToStr(stream.Size));
  client.RequestBody := stream;
  result := TMemoryStream.Create;
  client.Post('http://192.168.1.22:1400/MediaRenderer/AVTransport/Control', result);
  result.Position := 0;
  request.LoadFromStream(result);
  for i:=0 to request.Count-1 do
    writeln(request.Strings[i]);
  request.Free;
  stream.Free;
  client.Free;
end.


Fertig!
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

WeePee
Beiträge: 25
Registriert: So 8. Dez 2013, 13:46

Re: UPnP, SOAP, HTTP

Beitrag von WeePee »

Hallo,

danke für den Tipp. Ich werde das mal ausprobieren.

Grüße
Wolfram

WeePee
Beiträge: 25
Registriert: So 8. Dez 2013, 13:46

Re: UPnP, SOAP, HTTP

Beitrag von WeePee »

Es hat funktioniert .... vielen Dank!

Antworten