Teile einer CSV oder DB3 Datei auslesen

Sempervivum

Erfahrenes Mitglied
Kurze Rückfrage, du schriebst "nur von einer Steckdose". Ich nehme an, die erste Spalte ist offenbar die AIN und enthält so eine Art ID, die angibt, von welcher Steckdose die Daten sind?
 

Sempervivum

Erfahrenes Mitglied
So, ich habe eine Basisversion des Skripts fertig. Du musst dann Python auf dem PC installieren, damit es laufen kann. Zum Testen zunächst direkt starten durch Doppelklick oder Aufruf in der Eingabeaufforderung.
Das Skript benutzt FTP mit TLS und zwar musste ich auf dem FTP-Server als SSL-Modus "Explicit" einstellen.
Code:
import sys
import os
import time
from csv import reader
import json
from ftplib import FTP
from ftplib import FTP_TLS
import io

try:
    # Intervall in Sekunden für das Prüfen der CSV-Datei:
    intv = 10
    # Parameter in der CSV-Datei
    # Schlüssel: Frei wählbarer Name
    # Wert: Der Index in der CSV-Zeile
    confParams = {
        'AIN': 0,
        'voltage': 1,
        # bei den folgenden Parametern wusste ich die Bedeutung nicht
        # ergänze sie
        'date': 5,
        'time': 6
    }
    # AIN der Steckdose, die gelesen werden soll:
    ainToRead = '116570450402'
    # Dateiname der CSV-Datei:
    filename = 'DectRead_test.csv'
    # Dateiname unter dem die JSON-Datei
    # auf dem FTP-Server abgelegt werden soll:
    ftpFilename = 'dect-read.json'
    # FTP-Server, Name oder IP:
    ftpServer = ''
    # FTP-Port:
    ftpPort = 2221
    # Benutzername für FTP:
    ftpUser = ''
    # Passwort für FTP:
    ftpPasswd = ''
    # Verzeichnis auf dem FTP-Server:
    ftpDir = ''

    # Ab hier braucht nichts mehr geändert zu werden

    # Verzeichnis dieser Skriptdatei ermitteln:
    dir = os.path.dirname(os.path.realpath(__file__))
    # Wir gehen davon aus,
    # dass Skript und CSV-Datei im selben Verzeichnis liegen:
    path = dir + '\\' + filename
    # Merker für Zeitstempel:
    tim = 0
    # Endlosschleife:
    while True:
        # Zeit der letzten Änderung der CSV-Datei ermitteln:
        mtime = os.path.getmtime(path)
        # Hat sich die Zeit geändert?
        if(mtime > tim):
            # Neue Zeit merken:
            tim = mtime
            # CSV-Datei öffnen:
            with open(path, 'r') as read_obj:
                output = []
                # pass the file object to reader() to get the reader object
                csv_reader = reader(read_obj)
                # Iterate over each row in the csv using reader object
                for row in csv_reader:
                    # row variable is a list that represents a row in csv
                    # print(row)
                    # Gilt die Zeile für die Steckdose, die übertragen werden soll?
                    if row[confParams['AIN']] == ainToRead:
                        # Alle Parameter zum Ausgabe-Array hinzu fügen:
                        params = {}
                        for key in confParams:
                            params[key] = row[confParams[key]]
                        output.append(params)
                # Ausgabe-Array in JSON kodieren:
                outputJson = json.dumps(output)
                print(outputJson)
                # Mit FTP-Server verbinden und JSON hochladen:
                # ftp = FTP()
                ftp = FTP_TLS()
                ftp.connect(ftpServer, ftpPort)
                ftp.login(ftpUser, ftpPasswd)
                ftp.prot_p()
                ftp.cwd(ftpDir)
                bio = io.BytesIO()
                bio.write(outputJson.encode())
                bio.seek(0)  # move to beginning of file
                ftp.storbinary('STOR ' + ftpFilename, bio)
                ftp.close()
        # Konfigurierte Zeit warten:
        time.sleep(intv)
except:
    print("Error at line", sys.exc_info()[2].tb_lineno, sys.exc_info())
# Zum testen, damit wir die Fehleranzeigen zu Gesicht bekommen:
input()
Gefiltert wird noch nichts außer der AIN. Versuche zunächst ob es so bei dir läuft.
 
Zuletzt bearbeitet:

mstut

Mitglied
Hallo
Da sind sie wieder, meine Probleme.
Ich bekomme keine Verbindung, liegt bestimmt am SSL.
Error at line 81
Bin bei Domain Factory und habe dort nichts gefunden.
Kann man nicht einfach die Datei auf dem PC speichern?
Kann heute erst ein mal nicht weiter machen.
mfg
Michael
 

Sempervivum

Erfahrenes Mitglied
Kann man nicht einfach die Datei auf dem PC speichern?
Mit dem FTP hatte ich auch einige Probleme bis es lief. Natürlich kann man die Datei auch auf dem PC speichern aber Du willst die Daten ja auf der Website anzeigen. Ich wollte erst fragen: "Läuft dein Webserver denn auf dem selben PC?" aber da Du von Domainfactory schreibst, wird die HP offenbar dort gehostet.
 

mstut

Mitglied
In Post 7 hatte ich das ja geschrieben, alle 10 Min. auf die HP.
Was ist das dann für eine Datei die erzeugt wird?
Kann ich die dann in meine Seite einfügen, zb. als Tabelle oder Liste?
So jetzt muss ich aber weg.
mfg
 

Sempervivum

Erfahrenes Mitglied
Das ist eine JSON-Datei, die Du problemlos in PHP einlesen kannst. Muss aber, wenn ich das richtig verstehe, automatisch erfolgen, einschl. des Hochladens auf deine HP.
 

Sempervivum

Erfahrenes Mitglied
Laut Doku von Domainfactory wird SFTP unterstützt. Ich habe das Skript mal darauf angepasst:
Code:
import sys
import os
import time
import datetime
from csv import reader
import json
import paramiko
import io
import ftplogin

try:
    # Intervall in Sekunden für das Prüfen der CSV-Datei:
    intvPoll = 10
    # Anzahl von Datensätzen, die aus der
    # CSV-Datei übernommern werden sollen:
    nrData = 10
    # Intervall in Sekunden, in dem die CSS-Datei
    # aktualisiert wird:
    intvCsv = 600  # 10 Minuten
    # Parameter in der CSV-Datei
    # Schlüssel: Frei wählbarer Name
    # Wert: Der Index in der CSV-Zeile
    confParams = {
        'AIN': 0,
        'Spannung': 1,
        'Leistung': 2,
        'Zählerstand': 3,
        'Temperatur': 4,
        'Datum': 5,
        'Zeit': 6
    }
    # AIN der Steckdose, die gelesen werden soll:
    ainToRead = '116570450402'
    # Dateiname der CSV-Datei:
    filename = 'DectRead_test.csv'

    # Ab hier braucht nichts mehr geändert zu werden

    # Zeitraum, innerhalb dessen Daten übernommen werden sollen
    # bzw. maximales Alter der Daten:
    maxAge = nrData * intvCsv
    # Verzeichnis dieser Skriptdatei ermitteln:
    dir = os.path.dirname(os.path.realpath(__file__))
    # Wir gehen davon aus,
    # dass Skript und CSV-Datei im selben Verzeichnis liegen:
    path = dir + '\\' + filename
    # Merker für Zeitstempel:
    tim = 0
    # Endlosschleife:
    while True:
        # Zeit der letzten Änderung der CSV-Datei ermitteln:
        mtime = os.path.getmtime(path)
        # Hat sich die Zeit geändert?
        if(mtime > tim):
            # Neue Zeit merken:
            tim = mtime
            now = datetime.datetime.now()
            # CSV-Datei öffnen:
            with open(path, 'r') as read_obj:
                output = []
                # pass the file object to reader() to get the reader object
                csv_reader = reader(read_obj)
                # Iterate over each row in the csv using reader object
                for row in csv_reader:
                    # row variable is a list that represents a row in csv
                    # print(row)
                    # Zeit für die aktuelle Zeile ermitteln:
                    timeRow = datetime.datetime.strptime(
                        row[confParams['Datum']] + 'T' + row[confParams['Zeit']], "%Y-%m-%dT%H:%M:%S")
                    # Alter der Daten ermittteln durch Subtrahieren der Zeit der Zeile
                    # von der Jetzt-Zeit:
                    ageRow = (now - timeRow).total_seconds()
                    # Ist das Alter der Zeile kleiner als das konfigurierte maximale?
                    if ageRow < maxAge:
                        # Gilt die Zeile für die Steckdose, die übertragen werden soll?
                        if row[confParams['AIN']] == ainToRead:
                            # Alle Parameter zum Ausgabe-Array hinzu fügen:
                            params = {}
                            for key in confParams:
                                params[key] = row[confParams[key]]
                            output.append(params)
                # Ausgabe-Array in JSON kodieren:
                outputJson = json.dumps(output)
                bio = io.BytesIO()
                bio.write(outputJson.encode())
                bio.seek(0)  # move to beginning of file
                print(bio.getvalue())

                # Mit FTP-Server verbinden und JSON hochladen:
                # Create a Transport object
                transport = paramiko.Transport(
                    (ftplogin.ftpServer, ftplogin.ftpPort))
                # Connect to a Transport server
                transport.connect(username=ftplogin.ftpUser,
                                  password=ftplogin.ftpPasswd)
                sftp = paramiko.SFTPClient.from_transport(transport)

                # Upload file to server
                sftp.putfo(bio, ftplogin.ftpPath)
                # print(sftp.listdir('./'))

                sftp.close()
                transport.close()
        # Konfigurierte Zeit warten:
        time.sleep(intvPoll)
except:
    print("Error at line", sys.exc_info()[2].tb_lineno, sys.exc_info())
# Zum testen, damit wir die Fehleranzeigen zu Gesicht bekommen:
input()
Die FTP-Daten habe ich in eine Datei ftplogin.py ausgelagert:
Code:
# FTP-Server, Name oder IP:
ftpServer = 'server'
# FTP-Port:
ftpPort = 22
# Benutzername für SFTP:
ftpUser = 'username'
# Passwort für SFTP:
ftpPasswd = 'password'
# Pfad auf dem FTP-Server einschl. Dateiname:
ftpPath = 'path-on-server'
Das Skript braucht jetzt die Erweiterung paramiko. Diese musst Du installieren mit
Code:
pip install paramiko
in der Eingabeaufforderung.
 
Zuletzt bearbeitet: