0

I am having quite a frustrating issue, and I'm quite new to Python/Raspberry pi

I have a script that is to match gps coordinates with a SSID filtered iwlist scan and then email the resulting file out whenever there is a wifi connection.

My issue is, the results are continuously buffered, so the gps coordinates could be significantly far away from the scanned SSIDs.

I have the serial line being flushed at the beginning of the while loop, but it doesn't seem to work. I also have python running un-buffered (-u, but that may only be for the text files..) I added Output.flush(), but I have not been able to test it yet. Figured I'd ask first.

So, my question is, is there a way to turn off the serial line buffer so every iteration is getting the GPS coordinate at the time the while loop is executing? All of my text files have file.flush() after they have been written. Does that need to be before the files are written, or would that not affect the serial buffer? What am I missing?

Any help would be appreciated

#!/usr/bin/python -u
import os
import gps
import time
import serial
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders

username = 'gmail account'
password = 'account password'

port = serial.Serial("/dev/ttyAMA0", baudrate=9600)

#Setting GPS session, listen on port 2947 (gpsd) of localhost
session = gps.gps("localhost", "2947")
session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)

#Begin GPS and WiFi Scan loop..
while True:

    try:
        port.flushInput()
        #port.flushOutput() commented out because I haven't tested with this yet.
        time.sleep(.5)
        report = session.next()
        #Uncomment below for report data
        #print report
        if report['class'] == 'TPV':
            if hasattr(report, 'lat' and 'lon'):
                #setting GPS variables and strings
                latitude = report.lat
                latString = "%f" %(latitude)
                longitude = report.lon
                lonString = "%f" %(longitude)

        #WiFi scan and parse script. I don't think it is necessary to post,       
        #but if it is, I will. All text files are flushed before being closed

        #Email when connected
        ping = os.system('sudo ping -c4 8.8.8.8')
        try:
            if ping == 0:
                msg = MIMEMultipart()
                msg['Subject'] = "GPS/WiFi data from GPS PILOT"
                msg['From'] = username
                msg['To'] = username

                body = "GPS/WiFi data attached.."

                msg.attach(MIMEText(body, 'plain'))
                part = MIMEBase('application', "octet-stream")
                part.set_payload(open("/home/pi/gpsMaster/dataLog.csv", "rb").read())
                Encoders.encode_base64(part)
                part.add_header('Content-Disposition', 'attachment; filename="GPSWiFi_Scan.csv"')

                msg.attach(part)

                server = smtplib.SMTP('smtp.gmail.com:587')
                server.ehlo()
                server.starttls()
                server.login(username, password)
                server.sendmail(username, username, msg.as_string())
                server.quit()
                os.system("sudo rm /home/pi/gpsMaster/dataLog.csv")
            else:
                pass

        except smtplib.SMTPException:
            os.system('sudo reboot now')

            #Adding loop delay
            time.sleep(10)

    #Loop ending exceptions            
    except KeyError:
        pass
    except IOError:
        print ("ERROR")
        #os.system('sudo reboot now')
    except KeyboardInterrupt:
        quit()
    except StopIteration:
        session = None
        os.system("sudo reboot now")
sjo91190
  • 69
  • 6
  • Why are you flushing the port, and is `/dev/ttyAMA0` the same as your gps? – Nodak Mar 04 '16 at 05:53
  • @Nodak I am flushing the port to attempt to get the latest GPS coordinate instead of pulling one from the buffer. Say, if I drive 5 miles with target SSIDs every mile, towards the end of the trip, the script is plotting that coordinate near the beginning of the trip (Depending on how big the buffer is). /dev/ttyAMA0 is the port the GPS is on, and I am able to see current readings by typing the command 'cgps -s' – sjo91190 Mar 04 '16 at 12:55
  • GPSD handles the device. It doesn't share the device. It shares the data. You just want to pull data from the gpsd stream. – Nodak Mar 04 '16 at 15:12

2 Answers2

2

I was having a similar issue. I fixed by flushing input and output.

port.flushInput()
port.flushOutput()
Tom
  • 66
  • 2
0

I appreciate that this is an old question, but it is still relevant as I hit the same problem. The issue is due to:

time.sleep(10)

in the main loop. The gpsd thread is adding received data to a queue which is accessed via:

report = session.next()

This mean that when you get to pull the next sample, over time it will drift further and further from reality (you are using GPS coordinates that lag behind your current location). We have a big queue, the consumer is pulling data much more slowly than it is being added due to the 10s sleep. I had much fun solving this and only by cutting the system to its bare essentials did I finally happen across the cause. The solution is to pull the data as soon as it is available, but discard as many data points as necessary until your delay time has been achieved. This stops the gpsd queue getting out of sync as the gpsd Python client is consuming them too slowly which causes coordinate drift over time.

Pseudo code (it can be polished, an exercise left for the reader):

import time

start = time.time()

while True:
   # Consume the report from the gpsd
   report = session.next()

   # What time is it?
   now = time.time()

   # Magic number of 10s
   if now > (start + 10):

        # use the data contained in report

        # Update with the latest time ready for the next iteration.
        start = now
cambesol
  • 1
  • 3