Seite 1 von 1

Werte von Arduino mit Python in Postgres schreiben

Verfasst: Mittwoch 9. Januar 2019, 12:59
von linuxubuntu
Hallo Zusammen

Ich versuche mit folgendem Python Script Daten in meine Postgres Datenbank zu schreiben. Ich weiss der Code kann noch verbessert werden und daran arbeite ich auch noch.

Code: Alles auswählen

from datetime import datetime

import psycopg2
import serial

db_connect = psycopg2.connect(user="xxxxx", password="xxxxxxx", host="1xxxxx", port="xxxxx",
                              database="mydb")

read_arduino = serial.Serial('/dev/ttyACM3', 9600)
db_curser = db_connect.cursor()

while True:
    data_arduino = read_arduino.readline()
    data_arduino_dec = data_arduino.decode("UTF8")
    data_arduino_dec_split = data_arduino_dec.split(",")
    returns_temp_name = data_arduino_dec_split[0]
    returns_temp_value = data_arduino_dec_split[1]
    leader_temp_value = data_arduino_dec_split[3]
    living_temp_value = data_arduino_dec_split[5]
    time_s = datetime.now().timestamp()
# Insert Value temperatur leader and returns in Database
    db_curser.execute(f"INSERT INTO my_smart_home(sensor_name, sensor_value, time_s)"
                      f"VALUES({str(returns_temp_name)}," f"{float(returns_temp_value)}, {time_s})")
    db_connect.commit()
Zur erklährung returns_temp_name ist der name des Sensors returns_temp_value ist der Wert vom Sensor.

Nun ist das Problem, dass ich vom Python folgende Fehlermeldung erhalte:

", line 22, in <module>
db_curser.execute(f"INSERT INTO my_smart_home(sensor_name, sensor_value, time_s)"
psycopg2.ProgrammingError: column "returns_temp" does not exist
LINE 1: ...art_home(sensor_name, sensor_value, time_s)VALUES(returns_te..."

Die Column "returns_temp" ist keine column sondern der name des Sensors und dieser soll in die Column sensor_name geschrieben werden.
Kann mir jemand helfen und sagen was ich falsch mache?

Besten Dank und Gruss


^

Re: Werte von Arduino mit Python in Postgres schreiben

Verfasst: Mittwoch 9. Januar 2019, 13:07
von sparrow
Dann führe ein insert so durch, wie es die Doku sagt und bau dir den String nicht irgendwie zusammen (Stichwort: SQl-Injection):

http://initd.org/psycopg/docs/usage.htm ... dule-usage

Code: Alles auswählen

cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)",  (100, "abc'def"))
%s als Platzhalter, die Variablen in einem tuple als 2. Parameter an execute.

Re: Werte von Arduino mit Python in Postgres schreiben

Verfasst: Mittwoch 9. Januar 2019, 13:42
von linuxubuntu
Danke für die rasche Rückmeldung. Habe es nun hinbekommen:

Code: Alles auswählen

# Insert Value temperatur leader and returns in Database
    db_curser.execute("INSERT INTO my_smart_home (sensor_name, sensor_value, time_s) VALUES (%s, %s, %s)",
                      (str(returns_temp_name), float(returns_temp_value), float(time_s)))
    db_connect.commit()
Hättest du dies auch so gelöst?

Re: Werte von Arduino mit Python in Postgres schreiben

Verfasst: Mittwoch 9. Januar 2019, 13:44
von Sirius3
Man braucht nicht jedes Zwischenergebnis an eine Variable binden, insbesondere, wenn die Namen immer kryptischer werden.
Statt temp_value sollte es temperature heißen, dass es sich um einen Wert handelt, ist bei einer Variable nicht wirklich erhellend.
Serial-Objekte sind iterierbar, statt der while-Schleife würde sich also eine for-Schleife anbieten.
Statt die aktuelle Zeit selbst zu übergeben, würde ich das der Datenbank überlassen, oder gleich als default für das Feld nehmen: TIMESTAMP WITH TIMEZONE DEFAULT NOW().
Werte formatiert man nicht in SQL-Statements hinein. Bei den Datenbankfeldern, was soll das `s` bei `time_s`. Der Name my_smart_home ist für eine Tabelle, die Sensordaten sammelt auch seltsam, ich würde sie 'temperature' nennen, falls das nur Temperatursensordaten sind.

Code: Alles auswählen

for line in read_arduino:
    returns_name, returns_temperature, _, leader_temperature, _, living_temperature = line.decode('UTF8').split(",")
    db_curser = db_connect.cursor()
    db_curser.execute("INSERT INTO my_smart_home (sensor_name, sensor_value, time_s) VALUES (%s, %s, NOW())",
        (returns_name, float(returns_temperature)))
    db_connect.commit()