EFForg / crocodilehunter

Taking one back for Steve Irwin     (๑•̀ㅂ•́)و
GNU General Public License v3.0
964 stars 135 forks source link

overhaul GPS processing #105

Closed cooperq closed 3 years ago

cooperq commented 3 years ago

Right now we are dependent on GPSd running and we bootstrap it with a bash script but this is not a good solution. We should get gps data directly from the serial device and parse it instead, competely ignoring GPSD.

cooperq commented 3 years ago

fixed in #109

alexballas commented 3 years ago

Hello, just a question on this. Is the plan still to move away from gpsd? Getting the coordinates directly from serial would indeed be preferable and fairly easy to do. I was playing around the other day with this concept. Potentially migrate the gps logic to a separate class?

import serial
import sys
import time
from collections import namedtuple
import ocid
import math

class GPS:

    gpgga_info = "$GPGGA,"

    def __init__(self, device, disabled, args):
        '''
        Get GPS coordinates
        '''

        self.logger = args.logger
        self.config = args.config
        self.device = device
        self.disable_gps = disabled
        self.ser = serial.Serial(self.device)

    def get_ocid_location(self):
        Packet = namedtuple("Packet", ("lat", "lon"))
        ocid_key = self.config.get('general', 'ocid_key')
        if ocid_key:
            resp = ocid.ocid_get_location(ocid_key)
            self.logger.info(f"opencellid location {resp}")
            if 'lat' in resp:
                packet = Packet(float(resp['lat']), float(resp['lon']))
                return packet
        return None

    def convert_to_degrees(self,raw_value):
        decimal_value = raw_value/100.00
        degrees = int(decimal_value)
        mm_mmmm = (decimal_value - int(decimal_value))/0.6
        position = degrees + mm_mmmm
        position = "%.5f" %(position)
        return position

    def get_gps(self):
        GPGGA_buffer = 0
        NMEA_buffer = 0

        if self.disable_gps:
            packet = self.get_ocid_location()
            if packet:
                return packet
            Packet = namedtuple("Packet", ("lat", "lon"))
            gps = self.config['general']['gps_default'].split(',')
            packet = Packet(float(gps[0]), float(gps[1]))
        else:
            timeout = time.time() + 5
            Packet = namedtuple("Packet", ("lat", "lon"))
            while True:
                if time.time() > timeout:
                    break
                received_data = (str)(self.ser.readline())
                GPGGA_data_available = received_data.find(self.gpgga_info)
                if (GPGGA_data_available>0):
                    GPGGA_buffer = received_data.split("$GPGGA,",1)[1]
                    NMEA_buffer = (GPGGA_buffer.split(','))
                    nmea_latitude = NMEA_buffer[1]
                    nmea_longitude = NMEA_buffer[3]
                    if nmea_latitude and nmea_longitude:
                        packet = Packet(self.convert_to_degrees(float(nmea_latitude)), self.convert_to_degrees(float(nmea_longitude)))
                        return packet
            return None
cooperq commented 3 years ago

@ThreeSixes made a pretty good case for not directly accessing the device but sticking with GPSD in #105. I'm not inclined to change that at this point unless there is a really good argument for it.