3

I'm wanting to be able to print and update values retrieved from a small GPS in real time. For whatever reason, the code will not update the GPS value, and only prints the same value until I restart the code. My guess is the variable is not able to update, but I wouldn't know how to fix that.

while ser.inWaiting() > 0:
decoded = (ser.read(1).decode)
echo += decoded()

class GPS:
    def __init__(self):
        #Write GPSinput
        out = ''
        ser.write(com.GPSstatus.encode())
        time.sleep(1)

        #Read output
        while ser.inWaiting() > 0:
            decoded = (ser.read(1).decode)
            out += decoded()

        strlen = len(str(out))
        substr = out[0:strlen-9]

        #GPS? information list
        variables = substr.splitlines()

        #Storing each output in a variable
        self.PULSE_SAWTOOTH = [int(s) for s in variables[1] if s.isdigit()]
        self.TRACKED_SATELLITES = [int(s) for s in variables[2] if s.isdigit()]
        self.VISIBLE_SATELLITES = [int(s) for s in variables[3] if s.isdigit()]

        self.LONGITUDE = variables[5]
        self.longlen = len(self.LONGITUDE)
        self.LONGDEG = self.LONGITUDE[0:self.longlen-7]
        self.LONGMIN = self.LONGITUDE[self.longlen-7:]

        self.LATITUDE = variables[6]
        self.latlen = len(self.LATITUDE)
        self.LATDEG = self.LATITUDE[0:self.latlen-7]
        self.LATMIN = self.LATITUDE[self.latlen-7:]

        self.HEIGHT = variables[7]
        self.KNOTS = variables[8]
        self.DEGREES = [9]

        self.GPS_STATUS = variables[10]
        self.TIMING_MODE = variables[17] 
        self.FIRMWARE_VERSION = variables[20]

if __name__ == "__main__":

    #Call the functions
    gps = GPS()
    for i in range(100):
        print(gps.LATITUDE)    
    #Enterable Parameters
    # PULSE_SAWTOOTH
    # TRACKED_SATELLITES 
    # VISIBLE_SATELLITES
    # LONGITUDE
    # longlen
    # LONGDEG
    # LONGMIN
    # LATITUDE
    # latlen
    # LATDEG
    # LATMIN
    # HEIGHT  
    # KNOTS
    # DEGREES 
    # GPS_STATUS 
    # TIMING_MODE 
    # FIRMWARE_VERSION

I'm guessing this is a pretty simple solution, but I'm a beginner and I don't fully understand whats happening enough to fix it. If anyone could shed some knowledge and help with my problem it would be greatly appreciated.

  • For starters your while loop at the start has an indentation error, might just be poor formatting. And I'm assuming you're seeing the same value of `gps.LATITUDE ` , this is normal considering you only make 1 GPS object that always has a value of whatever `variables[6]` has. – GKE Feb 15 '20 at 03:44
  • 1
    I can't offer a simple answer since the structure of your program isn't what you need. Updating the variables from the GPS needs to occur inside a big loop. Each time through that loop you need to print the updated values. The code that's currently inside of your init function runs only once (when you call the GPS() constructor). You need to ,move it out of there to a loop of some sort.. – Paul Cornelius Feb 15 '20 at 03:45
  • 1
    Should `decoded = (ser.read(1).decode)` be `decoded = (ser.read(1).decode())`? – tdelaney Feb 15 '20 at 04:30
  • @GKE the value of ' variables[6] ' is constantly changing and updating in real time, it has no set value. – Denver Quin Feb 15 '20 at 05:58
  • @PaulCornelius I see, I'll give that a try. – Denver Quin Feb 15 '20 at 05:58
  • @tdelaney the code appears to run fine either way, so I'm not sure if that's an issue. – Denver Quin Feb 15 '20 at 05:59

1 Answers1

1

Aside from the while loop indent error and possible decode error. You're getting the same output for print(gps.LATITUDE) every time because you never update it, either by the gps object, or a call to a member function of class GPS. Your initial gps object always has LATITUDE equal to the value variables[6] and if that variable isn't changing, neither will your LATITUDE variable. You have options, you can either update LATITUDE directly:

class GPS:
    def __init__(self , latitudeValue = 0):
        self.LATITUDE = latitudeValue

if __name__ == "__main__":
    gps = GPS()
    print(gps.LATITUDE) # Prints 0, default value of latitudeValue
    gps.LATITUDE = 5
    print(gps.LATITUDE) # Now prints 5, changed value of LATITUDE in gps object

Or you can make it part of a function call:

class GPS:
    def __init__(self , latitudeValue = 0):
        self.LATITUDE = latitudeValue
    def updateLatitude(self , newValue):
        self.LATITUDE = newValue

if __name__ == "__main__":
    gps = GPS()
    print(gps.LATITUDE) # Prints 0
    gps.updateLatitude(10) # Updates LATITUDE VALUE
    print(gps.LATITUDE) # Prints 10

You can use either method with whatever the value of variables[6] is. Likewise, you can use this with all member variables of your class.

For real-time updating you need to use a event handling function, this scenario possibly calls for a listener. Without knowing more about the device passing data through the bus. If the manufacturer of your device doesn't supply an API to work with, then while you can use a loop to constantly reinitialize an object, another approach is module reloading.

GKE
  • 960
  • 8
  • 21
  • 1
    Thanks for the comment. Sorry I don't think I was specific enough. The value for 'variables[6]' is constantly updating, they are being retrieved from a GPS in real time. However those values will not display. I had it written at one point in a way which did update the values in real time, however the values were stored inside a class inside another function, and they were not initialized so they couldn't have been called outside of the function. However, a return statement seemed to capture the values I needed. But with how it is written now you cannot use a return statement. – Denver Quin Feb 15 '20 at 05:56
  • 1
    If that's the case, then you need to use a listener function. Whatever GPA device you're using should have some API and docs that explains and supply event handling functions. If you can link the device you're using or it's API docs then I may be able to be more specific – GKE Feb 15 '20 at 06:04
  • 1
    It's funny, because like I said it worked at one point, but now it doesn't after I moved the function inside the class and made it an " __init__()" function.. If it helps, I'm trying to update the values in a pyQT program from a separate script, and I have a timer which refreshes the screen and constantly calls that class each time, however it doesn't work in that case either. This code also has more to it, but nothing that would influence my problem. https://www.microsemi.com/document-portal/doc_download/133459-gps-2700-manual – Denver Quin Feb 15 '20 at 06:22
  • 1
    quick update, I managed to get it to work. But I don't think the method is a good practice. Essentially, in the `for` loop in `__main__`, I added a `gps.__init__()` to re-initialize the variables, hence updating them. I am, however, under the impression that this is a bad practice, but it seems to work. If you still had a better solution I'm open to anything. Thanks for your help though. – Denver Quin Feb 15 '20 at 06:56
  • 1
    Looking through the specs of the device, I can't seem to find an API from the manufacturer. While your solution is not the most "pythonic", it works, another option you may want to explore is [module reloading](https://stackoverflow.com/questions/1517038/python-refresh-reload) , but without an API from the manufacturers, you're really left to make your own scripts that achieve what you want. – GKE Feb 15 '20 at 07:33