1

I am working on a python class that represents an air quality station. Each air quality station has a GPS associated with it so that we can identify the latitudinal and longitudinal coordinates of the station. A GpsPoller is invoked on a separate thread and runs continuously until the thread is terminated. The GpsPoller should be used to get the most recent GPS data at any given time.

Here's what I have done so far:

class AirStation:

    def __init__(self):
        if not self._init_station():
            raise InitException("Could not initialize the AirStation!")

    def _init_station(self):
        self._id = utils.get_mac('wlan0')
        self._gpsp = utils.GpsPoller()
        self._gpsp.start()  # start polling the GPS sensor

        self._lat = self._gpsp.get_gps_data()
        self._lon = self._gpsp.get_gps_data()
        return True


class GpsPoller(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.session = gps(mode=WATCH_ENABLE)
        self.current_value = None
        self.running = True

    def get_gps_data(self):
        return self.current_value

    def run(self):
        while self.running:
            self.current_value = self.session.next()

I have two problems/questions about this code:

  1. What is the best way of ensuring a latitudinal and longitudinal reading in the initialization function of the AirStation class? At initilization I am getting a latitudinal and longitudinal value of None (I suspect due to the lack of time that the GPS has had to get a satellite fix).

  2. What is the standard way of ensuring that the GpsPoller gets terminated along with the AirStation instance? Whenever I test this at the command line, the exit() command hangs because the additional thread hangs.


I have taken a look at quite a few examples and documentation including the following:

Any additional resources or direct answers would be much appreciated!

Community
  • 1
  • 1
Jonathan
  • 671
  • 1
  • 8
  • 21

2 Answers2

1
  1. I'm not familiar with the gps module you seem to be using in your GpsPoller class, and whether or not it supports polling on it (check for the existance of a fileno attribute). However assuming that it doesn't, the best way I can offer is to busywait until the values are set

Something like:

while True:
    if self._lat is None:
        self._lat = self._gpsp.get_gps_data()
    elif self._lon is None:
        self._lon = self._gpsp.get_gps_data()
    else:
        break
  1. The best way to ensure that a thread dies with the parent process is to do what you've already done, and associate a boolean with its main loop which can be set to False, breaking the loop when the thread is supposed to terminate. What I assume you're missing is a call to set the running attribute of your GpsPollers to False when your AirStation class closes.
Warren Spencer
  • 324
  • 2
  • 7
0

I believe I have found the best solution for the questions that I posted above. Here are my thoughts:

  1. The GPS module needs enough time to get a satellite fix. There is no way to speed up this process (for the sake of this application at least). From my experiments it appears that the GPS module I am using consistently returns all of the GPS fixes within roughly 4-5 seconds.

    To answer my first question, the best way to ensure that the latitudinal and longitudinal coordinates are obtained in the initialization of the AirStation object is to simply wait a few seconds after starting the GpsPoller.

  2. The best way to ensure that the GpsPoller thread gets terminated is to terminate the looping condition by setting self._gpsp.running = False in the parent process and then waiting for the thread to join back up with the parent thread using self._gpsp.join().

    These operations can be put into a close() method which should be invoked at the end of the life of the station object.

Community
  • 1
  • 1
Jonathan
  • 671
  • 1
  • 8
  • 21