2016-12-30 4 views
0

ich ein Gerät habe, die folgende http Nachricht an meinem Raspberry Pi sendet:Erstellen Sie ein HTTP-Objekt aus einer Zeichenfolge in Python

POST /sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData HTTP/1.1 
Host: www.automation.siemens.com 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 349 

xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd> 

Ich kann nichts auf dem Gerät ändern.

Auf dem Raspberry Pi im Ausführen eines Skripts die Nachricht von einem Socket zu hören und zu empfangen. Das funktioniert so weit und die empfangene Nachricht ist die obige.

Jetzt möchte ich ein HTTP-Objekt aus dieser Nachricht erstellen und dann bequem die Header, Inhalt und so weiter extrahieren. Ähnlich wie das folgende Beispiel:

r = requests.get('https://www.google.com') 
r.status_code 

jedoch ohne "immer" eine URL. Ich möchte nur die Zeichenfolge lesen, die ich bereits habe.

Pseudo-Beispiel:

r = requests.read(hereComesTheString) 
r.status_code 

Ich hoffe, dass das Problem verständlich wurde.

Wäre froh, einige Hinweise zu bekommen.

Danke und viele Grüße, Christoph

+2

Wenn dies alles lokal/serverless ist, warum interessieren Sie sich, was die Header oder Statuscode sind? Würdest du dich nicht nur um den Inhalt der Saite kümmern? Ich versuche herauszufinden, was dein wirklicher Nutzen ist. – birryree

+0

Sie meinen, von Ihrem RPi, möchten Sie die HTTP-Anfrage sezieren und eine HTTP-Antwort machen? Hat Ihr Socket-Server bereits HTTP implementiert? –

+0

Mögliches Duplikat [Python-Parse-HTTP-Antwort (string)] (http://stackoverflow.com/questions/24728088/python-parse-http-response-string) – martianwars

Antwort

0

Sie verwenden die status_code Eigenschaft in Ihrem Beispiel, aber was Sie erhalten, ist eine Anforderung keine Antwort. Sie können jedoch weiterhin ein einfaches Objekt für den Zugriff auf die Daten in der Anforderung erstellen.

Es ist wahrscheinlich am einfachsten Ihre eigenen Klasse zu erstellen:

import mimetools 
from StringIO import StringIO 

request = """POST /sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData HTTP/1.1 
Host: www.automation.siemens.com 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 349 

xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd>""" 

class Request: 
    def __init__(self, request): 
     stream = StringIO(request) 
     request = stream.readline() 

     words = request.split() 
     [self.command, self.path, self.version] = words 

     self.headers = mimetools.Message(stream, 0) 
     self.content = stream.read() 

    def __getitem__(self, key): 
     return self.headers.get(key, '') 

r = Request(request) 
print(r.command) 
print(r.path) 
print(r.version) 

for header in r.headers: 
    print(header, r[header]) 

print(r.content) 

Diese Ausgänge:

POST 
/sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData 
HTTP/1.1 
('host', 'www.automation.siemens.com') 
('content-type', 'application/x-www-form-urlencoded') 
('content-length', '349') 
xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd> 
0

Wenn Sie Normal Socket-Server verwenden, dann müssen Sie einen HTTP-Server implementieren, so dass Sie die Anforderung aufspalten und reagieren entsprechend dem Protokoll.

Es ist wahrscheinlich einfacher, nur einen vorhandenen HTTP-Server und App-Server zu verwenden. Flask ist ideal dafür:

from flask import Flask 
from flask import request 

app = Flask(__name__) 

@app.route("/sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData", methods=['POST']) 
def dataCollector(): 
    data = request.form['xmlData'] 
    print(data) 
    # parseData. Take a look at ElementTree 

if __name__ == "__main__": 
    app.run(host=0.0.0.0, port=80) 
+0

Sieht interessant und ich werde es morgen testen, da das Gerät offline ist. – cmolitor

0

Dank Alden. Unter Ihrem Code mit ein paar Änderungen, so funktioniert es mit Python3.

import email 
from io import StringIO 

request = """POST /sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData HTTP/1.1 
Host: www.automation.siemens.com 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 349 

xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd>""" 

class Request: 
    def __init__(self, request): 
     stream = StringIO(request) 
     request = stream.readline() 

     words = request.split() 
     [self.command, self.path, self.version] = words 

     self.headers = email.message_from_string(request) 
     self.content = stream.read() 

    def __getitem__(self, key): 
     return self.headers.get(key, '') 

r = Request(request) 
print(r.command) 
print(r.path) 
print(r.version) 

for header in r.headers: 
    print(header, r[header]) 

print(r.content) 
Verwandte Themen