mysqlpython-3.5sql-insertmysql-pythonasyncore

Python 3 MySQL GPS tracker database insert error


I'm a beginner to Python programming (no more than 6 months of learning and practice). I have a gps tracker atached to my car and another to my father car. I want to log al data sent by this two GPS tracker to a database for future statistics. Everything works fine till I try to write data received over TCP into mysql table.

I tried to find a solution to my problem but I did not succeed (here,here,here). Any ideea, help, no matter how small I would be will be apreciated.

Console error message Get data from ('tracker_ip', 25904) ('tracker_id', latitude, longitude, '102456', '010817', 'N', 'E', '0', '0.00', 10.3) error: uncaptured python exception, closing channel <main.EchoHandler connected tracker_ip:25904 at 0x7f627f6e2b38> (:dbinsert() missing 1 required positional argument: 'data_tuple' [/usr/lib/python3.5/asyncore.py|read|83] [/usr/lib/python3.5/asynco re.py|handle_read_event|423] [server3_1.py|handle_read|84])

My code

#!/usr/bin/python3
import pymysql
import asyncore
import socket
import re


class Database():
    def __init__(self):
        self.dbconnection = pymysql.connect('localhost','db_user','password','db' )
        self.cursor = self.dbconnection.cursor()

        sql = """CREATE TABLE IF NOT EXISTS GPS (
           signature  CHAR(50) NOT NULL,
           latitude REAL,
           orientationNS CHAR(1),
           longitude REAL,
           orientationEV CHAR(1),
           gpstime CHAR(10),
           gpsdate CHAR(10),
           speed CHAR(6),
           direction CHAR(3),
           distance REAL)"""
        self.cursor.execute(sql)
        self.dbconnection.commit()


    def dbinsert(self,data_tuple):

        cmd =("""INSERT INTO GPS (signature,latitude,longitude,gpstime,gpsdata,orientationNS,orientationEV,direction,speed,distance)\
          VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""")            
        self.cursor.execute(cmd,data_tuple)
        self.dbconnection.commit()



    def  __del__(self):
        self.dbconnection.close()



class ClientHandler(asyncore.dispatcher):

    def ConvertCoordinates(self,latitude,longitude):
        lat_degree = int(float(latitude) / 100);
        lng_degree = int(float(longitude) / 100);
        # Extracting minutes for latitude and longitude
        lat_mm_mmmm = float(latitude) % 100
        lng_mm_mmmmm = float(longitude) % 100

        converted_latitude = lat_degree + (lat_mm_mmmm / 60)
        converted_longitude = lng_degree + (lng_mm_mmmmm / 60)
        return (converted_latitude,converted_longitude)  #tuple

    def GetData(self,data_string):
        data_list = re.sub(r'\s', '', data_string).split(',')
        signature = data_list[1]
        latitude,longitude = self.ConvertCoordinates(data_list[5],data_list[7])
        orientationNS = data_list[6] #latitude
        orientationEV = data_list[8] #longitude
        gpstime = data_list[3]
        gpsdate =data_list[11]
        gps_fix_validate = data_list[4] #
        speed= data_list[9]
        direction = data_list[10]
        distance = 10.3 #dummy data
        return (signature,latitude,longitude,gpstime,gpsdate,orientationNS,orientationEV,direction,speed,distance)


    def handle_read(self):
        data = self.recv(8192)
        data_string = data.decode(errors="ignore")
        #print(len(data_string))
        if len(data_string) >= 84 and len(data_string) <= 88 :
            data_tuple = self.GetData(data_string)
            print(data_tuple)
            Database.dbinsert(data_tuple)


class DataServer(asyncore.dispatcher):

    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(5)

    def handle_accept(self):
        pair = self.accept()
        if pair is None:
            return
        else:
            sock, addr = pair
            print('Get data from %s' % repr(addr))
            handler = ClientHandler(sock)

database=Database()
server = DataServer('192.168.10.10', 21112)
asyncore.loop()

Solution

  • I like what you're doing with the cars and the GPS's.. Is not so easy to debug this kind of thing without the working code in front of one to play with the variables but have some ideas as have used pymysql a lot and also got that error missing 1 required positional argument

    Things to try:

    1. Lose the brackets around cmd =("""INSERT INTO GPS (signature,latitude,longitude,gpstime,gpsdata,orientationNS,orientationEV,direction,speed,distance) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""") and put it on one line for now even if that breaks PEP 8 rules. Have checked my code and there were no brackets around this string.

    2. Try an extra set of brackets here like this : self.cursor.execute((cmd,data_tuple))

    3. Try an extra set of brackets in your handle_read function: Database.dbinsert((data_tuple))

    4. Add cursorclass=pymysql.cursors.DictCursor to the things in brackets here ('localhost','db_user','password','db' ) You might even want to fill those things out with the handles, host='localhost' etc to be safe.

    Anyway, I hope one of these things works, just from my experience that error message comes up when there is something wrong with the brackets as these variables are a passed between your functions.