Daten aus Kosole an Server senden - arduino Raspberry Pi

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

Hallo.

Die Situation:
Ein Arduino schickt per USB Kabel Daten an einen Raspberry Pi. Auf dem Pi, der nur in der Konsole läuft, habe ich ein Python Script das die Daten an eine Webseite senden soll. Hier wartet ein php Script das die Daten in eine Datenbank schreibt.

Das Problem ist das ich es nicht schaffe die Daten an den Server zu senden.
Wenn ich im Browser diese Zeile eingebe

Code: Alles auswählen

http://WEBSEITE.DE/SaveDataToMySQL.php?key=EIN_PASSWORT&T1=14.23&T2=12.12&ld=1015&ldr=256&lkl=1
dann funktioniert es wunderbar.

Die Frage ist ob das überhaupt möglich ist. Ich habe mich mit curl, urllib, httplib befasst aber sehe die Lösung nicht.
Ich möchte diese Zeile auch nur senden und keine Antwort.

Wo fange ich am besten noch einmal an?
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Schau Dir mal das externe Modul ``Requests`` an! Das hat ein hübscheres API als die eingebauten Module a la ``urllib``.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

Danke, das ist das richtige Modul.
Jedoch habe ich noch ein Problem das ich nicht erklären kann.

Das funktioniert.

Code: Alles auswählen

import serial
import requests
url = "http://WEBSEITE.DE/SaveDataToMySQL.php?key=EIN_PASSWORT&T1=14.23&T2=12.12&ld=1015&ldr=256&lkl=1"

#url = serial.Serial('/dev/ttyACM0', 9600)
while 1:
    r = requests.get(url)
    print (r.url)
Das funktioniert nicht.

Code: Alles auswählen

import serial
import requests

url = serial.Serial('/dev/ttyACM0', 9600)
while 1:
    r = requests.get(url)
    print (r.url)
Wenn ich mir aber mit

Code: Alles auswählen

print url.readline()
die Daten vom Arduino anzeigen lasse sehen sie genau so aus wie im funktionierenden Beispiel definiert.
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was bedeutet denn "funktioniert nicht"? Kommt ein Fehler? Geschieht etwas nicht, was Du erwartet hast? Bitte bei solchen Fragen immer präzise beschreiben, worin der Fehler besteht!

Sehe ich das richtig, dass die komplette URL vom Arduino kommt?

Aufgrund Deines letzten Einwurfes denke ich mal, dass ``url?`` im zweiten Fall eben noch kein String, sondern eine Art ``file``-Objekt ist! Du musst dann eben das ``readline`` noch aufrufen, um wirklich die URL als String an ``requests`` zu übergeben. Das hast Du ja eigentlich schon selber erkannt... ;-)

Mal als generelle Anmerkung: URLs mit Parametern kann man mittels Request auch elegant selber zusammen bauen. Du magst das jetzt nicht brauchen, aber für die Zukunft sei es Dir ans Herz gelegt :-)

Ach ja, nimme ``while True`` statt ``while 1``! Python kennt Literale für wahr und falsch ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

Es kommt diese Fehlermeldung.
Traceback (most recent call last):
File "test2.py", line 11, in <module>
r = requests.get(url)
File "/usr/lib/python2.7/dist-packages/requests/api.py", line 55, in get
return request('get', url, **kwargs)
File "/usr/lib/python2.7/dist-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 421, in request
prep = self.prepare_request(req)
File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 359, in prepare_request
hooks=merge_hooks(request.hooks, self.hooks),
File "/usr/lib/python2.7/dist-packages/requests/models.py", line 287, in prepare
self.prepare_url(url, params)
File "/usr/lib/python2.7/dist-packages/requests/models.py", line 338, in prepare_url
"Perhaps you meant http://{0}?".format(url))
requests.exceptions.MissingSchema: Invalid URL u"Serial<id=0x7f3d4a382cd0, open=True>(port='/dev/ttyACM0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)": No schema supplied. Perhaps you meant http://Serial<id=0x7f3d4a382cd0, open=True>(port='/dev/ttyACM0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)?
Die URL wird komplett vom Arduino geliefert da es hier ausreicht weil ich ja sonst nichts weiter auf dem Raspberry Pi damit machen möchte.

Im funktionierenden Beispiel wird
gemeldet
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

Manchmal sieht man es einfach nicht.
Habe mir url mal in eine Datei ausgeben lassen und gesehen das es nicht das war was ich erwartet hatte.

Das funktionierende Ergebnis mit einer Abfrage auf den Anfang des Datensatz. Die war nötig weil das ganze abbricht wenn nur Teildaten vom Arduino übernommen werden z.B. beim start des Programms.

Code: Alles auswählen

ser = serial.Serial('/dev/ttyACM0', 9600)
while True:
    data = ser.readline()
    data = str(data)
    print(data)
    if "http" in data:
        r = urllib2.get(data)
    else:
        print "falsche Daten"
        pass
Leider funktioniert das ganze nur unter Ubuntu auf dem Raspberry Pi jedoch nicht.
Hier gibt es die Meldung
ImportError: No module named requests
Wie installiere ich den das Modul und wo kommt es her?
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
BlackJack

@skeeter: Du solltest die empfohlene Zeit nach dem öffnen der seriellen Verbindung warten, dann kommen da höchstwahrscheinlich auch keine kaputten Daten beim ersten lesen. Wenn man die serielle Verbindung öffnet, dann führt der Arduino einen Reset durch und wartet eine zeit lang ob man ein neues Programm flashen möchte. Solange kann man die Verbindung nicht sinnvoll für anderes verwenden weil man dann nicht mit dem eigenen Programm kommuniziert sondern mit dem Bootloader.

Statt der ``while``-Schleife könntest Du eine ``for``-Schleife über das `Serial`-Objekt schreiben.

Der `str()`-Aufruf mit `data` macht keinen Sinn. Und wenn dann würde man da keine extra Zeile für schreiben.

Die Klammern beim ``print`` gehören da nicht hin. Solange man nicht Python 3 benutzt oder bei Python 2 ein `print_function` aus dem `__future__`-Modul importiert ist ``print`` keine Funktion und man sollte auch nicht so tun als wenn dem so wäre, denn spätestens wenn man versucht mehr als ein ”Argument” zu übergeben funktioniert das nicht mehr so wie man das von einer Funktion erwarten würde.

``pass`` macht keinen Sinn wenn es nicht die einzige Anweisung in einem Block ist.

In dem Code benutzt Du `requests` doch gar nicht‽
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

sorry, die Zeile

Code: Alles auswählen

r = urllib2.get(data)
muß natürlich

Code: Alles auswählen

        r = requests.get(data)
lauten. Da hatte ich etwas probiert und dann den falschen Code kopiert.

Deswegen die Frage nach dem Modul. Das ich inzwischen mit

Code: Alles auswählen

sudo apt-get install python-requests
installiert habe. Allerdings bleibt es bei der Meldung. Muß das Modul noch irgendwo aktiviert werden?
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
BlackJack

@skeeter: Das Modul sollte sich dann importieren lassen.
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

@BlackJack: Das funktioniert jetzt auch.
Was meinst du mit der empfohlenen Zeit nach dem öffnen der seriellen Verbindung?
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
BlackJack

@skeeter: Na die Zeit die man am Anfang mit dem Bootloader vom Arduino kommunizieren würde statt mit dem Programm das man darauf laufen lässt. Solange muss man halt abwarten. Steht irgendwo in der Arduino-Dokumentation.
skeeter
User
Beiträge: 9
Registriert: Freitag 6. Mai 2011, 18:06

Danke euch beiden ich habe wieder was gelernt :D

Eine Sicherheit habe ich noch eingebaut falls mal kein Internet verfügbar ist und das Script nicht abbricht.

Code: Alles auswählen

        try:
            r = requests.get(data)
        except IOError:
            pass
        else:
            print "keine Verbindung"
“Ich denke, es gibt weltweit einen Markt für vielleicht fünf Computer.” [Thomas Watson, Vorsitzender von IBM, 1943]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dafuer gibst du genau dann "keine Verbindung" aus, wenn du eine hast.
BlackJack

Und es wird mit einem falschen Wert für `r` weitergemacht.
Antworten