String direkt über FTP in eine Datei auf dem Server schreiben.

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

Hallo,
ich arbeite mich gerade in Python ein und komme gerade nicht weiter.

Ich kann einen Meßwert mit einem Raspi auslesen, ihn in einer Datei speichern und diese Datei über FTP auf einen Server schicken. Dort wird diese mit HTML und PHP ausgewertet und beim Aufrufen der Webseite dargestellt.

Nun speichere ich gerade 1x pro Sekunde in eine Datei. Die SDKarte wird in ein paar Monaten tot sein. Deshalb möchte ich direkt in die Datei auf dem Server schreiben oder alternativ die Datei nur im RAM des Raspberry speichern.

Ich lade die Datei mit
ftp.storbinary('STOR 'messwert.txt, open(messwert.txt, 'rb'))

open(messwert.txt, 'rb') durch einen String oder Variable ersetzen funktioniert nicht.........

Habt ihr eine Idee?
Grüße
Dirk
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Statt FTP nimm eine Speicher-basierte DB wie zb REDIS, und Update die Daten darin. In PHP kann die dann a gefragt werden.
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

Danke, da das nur eine Spielerei ist, möchte ich keinen kostenpflichtigen Service buchen. Geht das auch anders?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Immer schön zu sehen, wenn Leute sich intensiv mit einer Antwort auseinandersetzen. Das gibt einem das gute, warme Gefühl mit der gebotenen Hilfestellung einen kleinen Beitrag geleistet zu haben….🙄

Redis ist ein service wie jeder andere auch, den du einfach installieren und laufen lassen kannst. Wie deine FTP Server. Etwas, dass man lernt, wenn man mal “redis raspberry Pi” googelt. Erster Link: https://amalgjose.com/2020/08/11/how-to ... pberry-pi/

Aber das ist wohl Zuviel verlangt.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Geht ziemlich einfach, aber die Lösung ist schlecht, weil auf der anderen Seite die Daten dann auch wieder einzeln eingelesen werden müssen.

Dafür nimmt man normalerweise Datenbanken (Redis, Grafana, mariadb, postgresql) und für den Transport wird meist MQTT verwandt, sofern nicht direkt in die DB geschrieben wird, sondern irgendwo ein Server ist, der diese Nachrichten empfängt und dann in seine Datenbank einträgt.

Code: Alles auswählen

import ftplib
from io import BytesIO
from getpass import getpass


with ftplib.FTP_TLS() as ftp:
    ftp.connect("ftp-server.domain.tld")
    ftp.login("USERLOGIN", getpass())
    ftp.prot_p()

    data = BytesIO(b"Hello World 2\n")
    ftp.storbinary(f"STOR www/test.txt", data)
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

DeaD_EyE hat geschrieben: Mittwoch 29. Juni 2022, 11:05 Geht ziemlich einfach, aber die Lösung ist schlecht, weil auf der anderen Seite die Daten dann auch wieder einzeln eingelesen werden müssen.
Edit: irgendwie habe ich dein Posting missverstanden. Mir ist unklar, was MQTT hier genau an Vorteil bringt, statt direkt mit dem Service zu reden.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Mir ist unklar, was MQTT hier genau an Vorteil bringt, statt direkt mit dem Service zu reden.
Mit diesem Szenario wahrscheinlich nicht viel, aber man wird damit sowieso in Kontakt kommen.
MQTT wird sehr gerne in Verbindung mit Mikrocontrollern verwendet, da das Protokoll sehr einfach aufgebaut ist.

Wenn man z.B. ganz viele Mikrocontroller mit vielen Sensoren hat und das hierarchisch organisieren will, lohnt sich der Einsatz von MQTT.
Kann man natürlich auch mit einem SoC (Raspberry Pi 1-4) machen.

Die senden dann einfach ihre Messwerte an den Broker und ein anderes Programm auf einem PC/Server muss sich dann darum kümmern, die Daten in die DB einzutragen.

Mit nur einem Mikrocontroller oder Raspberry Pi wäre es natürlich einfacher direkt in die DB zu schreiben.

Dennoch wird der OP irgendwann zwangsweise sich mit MQTT beschäftigen. Das kommt sowiso.

EDIT: Redis kann übrigens auch das Publish/Subscribe Verfahren. Nur so als Hinweis.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ok, aber im konkreten wuerde ich's mir sparen, es bringt ja nicht wirklich was, wenn man eh schon ein volles Linux + Python zur Verfuegung hat. Ein Micro ist hier ja gar nicht im Spiel.
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

Hallo, ich wollte nicht unhöflich sein. Wenn ich redisDB_Kosten google kommt das hier: "Die Kosten pro Stunde betragen also 8 * 0,027 $, was ungefähr 0,22 $ pro Stunde bzw."

Aber das es auf dem RPi läuft möchte ich ja vermeiden, denn so wird ja wieder jede s geschrieben.(Ich brauche keine Timeline, nur Echtzeitanzeige im Browser).

Ich bin in diesem Thema noch nicht lange unterwegs. Was haltet Ihr von der InfluxDB Cloud? Kostenlos (mit Einschränkungen...) und ich habe die Speicherung ausgelagert. Wenn das so funktioniert.
Ich erkläre mal was ich machen möchte: Meinen Meßwert kann ich per ModbusTCP von einem Gerät in meinem Ethernet ziehen. Dargestellt soll er auf einer Webseite im Internet werden. Kein Verlauf nur aktueller Meßwert.
So habe ich es bis ejtzt gelöst: Ich kann einen Meßwert mit einem Raspi auslesen, ihn in einer Datei speichern und diese Datei über FTP auf einen Server schicken. Dort wird diese mit HTML und PHP ausgewertet und beim Aufrufen der Webseite dargestellt. Problem SD irgenwann kaputt.

Ich versuche mich gerade in InfluxDB einzuarbeiten. Geht das so? Telegraf auf Rpi so konfigurieren, dass Meßwert in Influxcloud gesepeichert wird . Das geht glaube ich. Aber wie bekomme ich es von dort auf meine Webseite?
Im Moment kann ich nichtmal Telegraf installieren, da meine Platform Raspbian32 nicht aufgeführt ist. Linux32 funktioniert nicht...ich probiere noch...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

"redis db kosten" muss man ja erstmal googeln wollen. "influx db kosten" kommen genauso Kosten.

Die InfluxDB speichert auch. Der Grund Redis zu nehmen ist, dass es *in memory* ist. Das war ja nun die Anforderung, die du hattest: keine Schreibzyklen.

Wobei das in deinem Scenario mit dem Pi ja eh wenig zu tun hat. Der muss das ja gar nicht speichern. Du musst lediglich eine PHP-Seite bauen, die den Wert entgegennimmt, und dann zB auf dem Server speichert. Auch wenn ich da auch InfluxDB oder sowas nehmen wuerde, aber da sollte ja vor allem keine SD-Karte involviert sein.

Und dein Python-Skript muss eben zB mit requests oder so diese PHP-Seite immer aufrufen, wenn du einen neuen Wert akquiriert hast.
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

Für mich wäre es am einfachsten wenn ich die Datei die ich per FTP auf den Webserver schicke nicht auf SD speichern müsste.
so ist mit Speichern: ftp.storbinary('STOR 'messwert.txt, open(messwert.txt, 'rb'))

wenn ich open(messwert.txt, 'rb') durch einen String ersetzen könnte, wäre toll. Geht aber nicht, Der Parameter muss eine Datei sein.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na du must die doch ueberhautp nicht speichern, sondern kannst als zweites Argument direkt den Inhalt der Datei angeben. FTP ist zwar viel zu komplex, und natuerlich hast du auch eine race-condition auf der Server-Seite, bei der du die Datei liest waehrend sie beschrieben wird - aber ist ja alles nur fuer den Spass.
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

dateiinhalt = "wert"
ftp.storbinary('STOR 'messwert.txt, dateiinhalt)

funktioniert nicht.
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

Traceback (most recent call last):
File "/home/pi/Python1/FTP.py", line 25, in <module>
placeFile()
File "/home/pi/Python1/FTP.py", line 22, in placeFile
ftp.storbinary('STOR '+filename, dateiinhalt)
File "/usr/lib/python3.9/ftplib.py", line 493, in storbinary
buf = fp.read(blocksize)
AttributeError: 'int' object has no attribute 'read'
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ducis71: Da brauchst Du schon ein Dateiobjekt. Aber keine Datei. Die Dokumentation sagt dazu ja, dass es ein Objekt mit einer `read()`-Methode sein muss die eine Byteanzahl als Argument entgegen nimmt. Das muss ja kein Objekt sein, dass durch `open()` & Co entstanden ist. Mehr sage ich dazu jetzt aber nicht, denn ich halte das auch für den falschen Weg.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ah, mein Fehler. Muss ein io.Bytes-Objekt mit dem Inhalt sein.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

es zwingt dich doch keiner, aus dem Raspi auf ein physisches Laufwerk zu speichern. Du kannst ein "file-like object" nehmen (wie z.B. aus dem besagten `io` Modul), das sich wie eine Datei verhält, aber im RAM ist. Du kannst die mit SQLite eine DB anlegen, die nur im RAM ist. Du kannst dir mit Bordmitteln von Linux eine (kleine) RAM-Disc anlegen, die halt nur im RAM ist. Du kannst Redis laufen lassen, was man so konfigurieren kann, dass die DB nur im Speicher gehalten wird. Redis ist OpenSource Software, frei verfügbar und läuft auch auf dem Raspi. Komplett kostenlose.

Oder du schreibst direkt in eine DB auf einem entfernten Server, dann brauchst du dir über lokale Datenhaltung keine Gedanken machen.

FTP ist ja schon ziemlich "old-school" in dem dem Kontext die IMHO komplziertere Lösung.

Gruß, noisefloor
ducis71
User
Beiträge: 7
Registriert: Dienstag 28. Juni 2022, 14:37

Ok, Danke für eure Tips. Ich habe jetzt mal ein bisschen Stoff zum probieren.

Ich möchte mal ein bisschen aufklären. Ich habe das letzte mal programmiert (ausser SPS) als Turbopascal noch das NonPlusUltra war. Jetzt spiele ich seit einer Woche mit das erste Mal Raspberry und Arduino rum und bin von den ganzen Befehlsvielfalt echt erschlagen. Aber zum Glück funktionieren die Grundfunktionen wie Schleifen noch wie 1986 auf dem KC85. ;-)

Ich muss mich noch daran gewöhnen, dass es einfacher ist MB große Datenbankinstanzen laufen zu lassen nur um 32Bits zu speichern. Aber die Harware gibt es ja locker her.
Grüße
Dirk
Antworten