GPS-Werte in Datenbank eintragen - brauche Hilfe

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
TOP
User
Beiträge: 2
Registriert: Samstag 4. April 2015, 15:34

Grüßt euch,
ich brauchen mal eure Unterstützung. Ich erhalte aus einem Strings Werte von einem GPS-Modul.
Diese Werte würde ich gerne in meine mySQL-Datenbank schreiben, jedoch schaffe ich es irgendwie nicht.

Wenn ich mir die Daten per Print auslesen lasse, erhalte ich diese auf dem Schirm.
Sofern ich diese jedoch in die Datenbank schreiben will, erhalte ich diverse Fehlermeldungen :(

Code: Alles auswählen

        datum = gpsd.utc
        zeit = gpsd.fix.time
        latitude = gpsd.fix.latitude
        longitude = gpsd.fix.longitude

        dbcon = MySQLdb.connect(host="localhost",user="xxxx",passwd="xxxxx",db="raspi_gps" )
        cursor = dbcon.cursor()
        cursor.execute("INSERT INTO position (datum, zeit, latitude, longitude) VALUES (%s, %s, %s, %s)",(datum, zeit, latitude, longitude))
        cursor.close()
        dbcon.commit()

        print 'latitude    ' , gpsd.fix.latitude
        print 'longitude   ' , gpsd.fix.longitude
        print 'time utc    ' , gpsd.utc,' + ', gpsd.fix.time

wäre klasse, wenn mir einer von euch helfen könnte.
Mit PHP kenn ich mich aus, aber Python ist für mich was komplett neues.

Danke und Gruß TOP
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@TOP: wäre schon, wenn Du uns diese Fehlermeldungen inklusive Traceback auch mitteilen könntest 8)
TOP
User
Beiträge: 2
Registriert: Samstag 4. April 2015, 15:34

Hi sirius3,
was meinst du mit Traceback?

Folgende Fehlermeldung erhalten ich wenn ich das Script ausführe:

Traceback (most recent call last):
File "./test1.py", line 46, in <module>
cursor.execute("INSERT INTO position (datum, zeit, latitude, longitude) VALUES (%s, %s, %s, %s)",(datum, zeit, latitude, longitude))
File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 174, in execute
self.errorhandler(self, exc, value)
File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (1054, "Unknown column 'nan' in 'field list'")

Zur Sicherheit nochmal das ganze Script von mir:

Code: Alles auswählen

#! /usr/bin/python
# Written by Dan Mandle http://dan.mandle.me September 2012
# License: GPL 2.0

import os
from gps import *
from time import *
import time
import threading
import MySQLdb

gpsd = None #seting the global variable

os.system('clear') #clear the terminal (optional)

class GpsPoller(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    global gpsd #bring it in scope
    gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
    self.current_value = None
    self.running = True #setting the thread running to true

  def run(self):
    global gpsd
    while gpsp.running:
      gpsd.next() #this will continue to loop and grab EACH set of gpsd info to clear the buffer

if __name__ == '__main__':
  gpsp = GpsPoller() # create the thread
  try:
    gpsp.start() # start it up
    while True:
      #It may take a second or two to get good data
      #print gpsd.fix.latitude,', ',gpsd.fix.longitude,'  Time: ',gpsd.utc

        os.system('clear')

        datum = gpsd.utc
        zeit = gpsd.fix.time
        latitude = gpsd.fix.latitude
        longitude = gpsd.fix.longitude

        dbcon = MySQLdb.connect(host="localhost",user="root",passwd="Saskia2804!",db="raspi_gps" )
        cursor = dbcon.cursor()
        cursor.execute("INSERT INTO position (datum, zeit, latitude, longitude) VALUES (%s, %s, %s, %s)",(datum, zeit, latitude, longitude))
        cursor.close()
        dbcon.commit()

        print '----------------------------------------'
        print 'latitude    ' , gpsd.fix.latitude
        print 'longitude   ' , gpsd.fix.longitude
#      print 'time utc    ' , gpsd.utc,' + ', gpsd.fix.time
#      print 'altitude (m)' , gpsd.fix.altitude
#      print 'eps         ' , gpsd.fix.eps
#      print 'epx         ' , gpsd.fix.epx
#      print 'epv         ' , gpsd.fix.epv
#      print 'ept         ' , gpsd.fix.ept
#      print 'speed (m/s) ' , gpsd.fix.speed
#      print 'climb       ' , gpsd.fix.climb
#      print 'track       ' , gpsd.fix.track
#      print 'mode        ' , gpsd.fix.mode
#      print
#      print 'sats        ' , gpsd.satellites

        time.sleep(2) #set to whatever

  except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
    print "\nKilling Thread..."
    gpsp.running = False
    gpsp.join() # wait for the thread to finish what it's doing
  print "Done.\nExiting."
Gruß TOP
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@TOP: na, was steht in der ersten Zeile Deiner Fehlermeldung :wink:

Einer Deiner Werte enthält 'NaN' (Not a Number), wahrscheinlich weil der Wert nicht ermittelt werden konnte. Das versteht MySQL nicht, weil Dezimalzahlen dieses Konzept nicht unterstützen. Alternativ gibt es bei SQL den Wert NULL, der auch soviel heißt wie, diesen Wert gibt es nicht. Das mußt Du aber selbst prüfen und anpassen, etwa in der Art:

Code: Alles auswählen

if math.isnan(latitute):
    latitute = None
Noch ein paar Anmerkungen zum Code:
Sternchenimporte solltest Du vermeiden, weil Du nicht kontrollieren kannst, was da alles in den eigenen Namensraum importiert wird. Einrücktiefe sollte 4 Leerzeichen sein, das ergibt die beste Lesbarkeit. global solltest Du gar nicht verwenden. Warum bindest Du gpsd nicht an ein Attribut der GpsPoller-Klasse? current_value wird gar nicht benutzt und in Zeile 26 sollte es self.running heißen. Alles was nach "if __name__ == '__main__'" steht sollte in eine Funktion main wandern, damit solche Fehler wie in Zeile 26 gleich auffallen. Innerhalb des "if ..." wird dann nur noch main() aufgerufen.
BlackJack

@TOP: Ein Traceback ist das was mit dem Wort *Traceback* beginnt, also das was Du als Fehlermeldung gepostet hast. ;-)

Kann es sein dass MySQL mit irgendwelchen SQL-Erweiterungen kompiliert wurde, oder das Erweiterungen geladen wurde, oder Funktionen definiert wurden? Das sieht nämlich fast so aus als würde `latitude` oder `longitude` in der Liste der Spaltennamen zu `nan` ausgewertet‽ Setz die Namen mal in doppelte Anführungszeichen (SQL-Standard) oder Backticks (MySQLs Idee vom Standard abzuweichen).

Ansonsten enthält das Programm noch einige sehr unschöne Sachen die man dringend loswerden sollte (Sternchen-Import, ``global``, ein ungenutztes Attribut, eine unnötige Subklasse von `Thread`, überhaupt soweit ich das sehe sinnlose Verwendung eines Threads) und einen fetten Fehler denn nichts garantiert das die von `gpsd` abgefragten Daten tatsächlich zusammen gehören.

Ich würde auch nicht alle zwei Sekunden die Verbindung zur Datenbank neu auf- und dann wieder abbauen.

Das Hauptprogramm gehört auch in eine Funktion.

`os.system('clear')` ist nicht portabel und Autoren von Programmen die einfach so ungefragt die Konsole leeren sollten immer über die Schulter schauen ob nicht ein wütender Benutzer hinter ihnen her ist. ;-)
BlackJack

@TOP: Das ganze mal etwas sauberer und den Fehler der durch den ungeschützen Zugriff auf `gpsd` entsteht (komplett ungetestet):

Code: Alles auswählen

#!/usr/bin/env python
# Based on code by Dan Mandle http://dan.mandle.me September 2012
# License: GPL 2.0
from __future__ import absolute_import, division, print_function
from contextlib import closing, contextmanager
from threading import Lock, Thread
from time import sleep

import MySQLdb
from gps import gps, WATCH_ENABLE


class GpsPoller(Thread):

    def __init__(self):
        Thread.__init__(self)
        self._gpsd = gps(mode=WATCH_ENABLE)
        self.lock = Lock()
        self.stop_requested = False

    @contextmanager
    def locked_gpsd(self):
        with self.lock:
            yield self._gpsd

    def run(self):
        while not self.stop_requested:
            # This will continue to loop and grab EACH set of gpsd info to
            # clear the buffer.
            with self.lock:
                self._gpsd.next()

    def stop(self):
        self.stop_requested = True
        self.join()


def main():
    gps_poller = GpsPoller()
    try:
        gps_poller.start()
        db_connection = MySQLdb.connect(
            host='localhost', user='root', passwd='Saskia2804!', db='raspi_gps'
        )
        with closing(db_connection.cursor()) as cursor:
            while True:
                # It may take a second or two to get good data.
                sleep(2)

                with gps_poller.locked_gpsd() as gpsd:
                    date = gpsd.utc
                    time = gpsd.fix.time
                    latitude = gpsd.fix.latitude
                    longitude = gpsd.fix.longitude

                cursor.execute(
                    'INSERT INTO position'
                    ' (datum, zeit, "latitude", "longitude")'
                    ' VALUES (%s, %s, %s, %s)',
                    (date, time, latitude, longitude)
                )
                db_connection.commit()

                print('-' * 40)
                print('latitude    ', latitude)
                print('longitude   ', longitude)

    except KeyboardInterrupt:  # Handling CTRL+C.
        print('\nStopping thread...')
        gps_poller.stop()

    print('Done.\nExiting.')


if __name__ == '__main__':
    main()
Antworten