123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- import machine
- import time
- import struct
- class NMEA(object):
- def __init__(self, id):
- self.__id = str(id)
- class Value(object):
- def __init__(self, v, u, t=(0,0,0.0)):
- self.__val = float(v)
- self.__unit = u
- self.__time = t
- def value(self):
- return self.__val
- def unit(self):
- return self.__unit
- def time(self):
- return self.__time
- def rad(self):
- return self.__val * math.pi / 180
- def __repr__(self):
- return "%f %s" % (self.value(), self.unit())
- def __float__(self):
- return float(self.__val)
- class Distance(Value):
- def __init__(self, v, u, t):
- super().__init__(v, u, t)
- class Position(Value):
- def __init__(self, v, u, t):
- super().__init__(v if u in ("N", "E") else -v, u, t)
- def __sub__(self, other):
- return Position(self.value() - other.value())
- class Speed(Value):
- def __init__(self, v, u, t):
- super().__init__(v, u, t)
- def to_kmh(self):
- if self.unit() in ("knot", "N"):
- return Speed(self.value() * 1.85200, "kmh", self.time())
- return self
- def to_knot(self):
- if self.unit() in ("kmh", "K"):
- return Speed(self.value() / 1.85200, "knot", self.time())
- return self
- class Course(Value):
- def __init__(self, v, t):
- super().__init__(v, "D", t)
- class Location(object):
- def __init__(self):
- self.__valid = False
- self.__lat = None
- self.__long = None
- self.__alt = None
- self.__height = None
- self.__speed = None
- self.__course = None
- self.__satellites = -1
- def __repr__(self):
- return "Satelittes: %s, %s\n\tLat/long: %s/%s\n\tAlt/h: %s/%s\n\tSpeed/course: %s/%s" % (
- self.__satellites, repr(self.__valid),
- self.__lat, self.__lat,
- self.__alt, self.__height,
- self.__speed, self.__course,
- )
- def set(self, msgid, segment):
- data = segment.split(",")
- if msgid == b'$GPGGA':
- if len(data) >= 6 and data[5] in ("1", "2", "6"):
- t = self.__time_from_seg(data[0])
- self.__set_lat(data[1], data[2], t)
- self.__set_long(data[3], data[4], t)
- if self.__satellites < 0 and self.__seg_set(data, 6):
- self.__satellites = int(data[6])
- if self.__seg_set(data, 7):
- self.__alt = Distance(data[7], "M", t)
- if self.__seg_set(data, 8):
- self.__height = Distance(data[8], "M", t)
- elif msgid == b'$GPGLL':
- if len(data) >= 6 and data[5] == "A":
- t = self.__time_from_seg(data[4])
- self.__set_lat(data[0], data[1], t)
- self.__set_long(data[2], data[3], t)
- elif msgid == b'$GPRMC':
- if len(data) >= 6 and data[1] == "A":
- t = self.__time_from_seg(data[0])
- self.__set_lat(data[2], data[3], t)
- self.__set_long(data[4], data[5], t)
- self.__set_speed(data[6], "N", t)
- self.__set_course(data[7], t)
- elif msgid == b'$GPVTG':
- if len(data) >= 7 and data[2] == "T":
- self.__set_speed(data[4], data[6], (0, 0, 0.0))
- self.__set_course(data[5], data[0], (0, 0, 0.0))
- elif msgid == b'$GPGSV':
- if self.__seg_set(data, 2) and data[0] == data[1]:
- self.__satellites = int(data[2])
- elif msgid == b'$GPMSS':
- pass
- self.__valid = False if self.__lat is None or self.__long is None else True
- return self.valid()
- def valid(self):
- return self.__valid
- def __seg_set(self, d, i):
- return len(d) >= (i + 1) and len(d[i]) != 0
- def __set_speed(self, v, u, t):
- if len(v) == 0:
- return None
- if self.__speed is None or self.__speed.time() < t:
- self.__speed = Speed(v, u, t)
- def __set_course(self, v, t):
- if len(v) == 0:
- return None
- print("Course", v, t)
- if self.__course is None or self.__course.time() < t:
- self.__course = Course(v, t)
- def __set_lat(self, v, d, t):
- if len(v) == 0:
- return None
- if self.__lat is None or self.__lat.time() < t:
- self.__lat = Position(float(v[0:2]) + (float(v[2:]) / 60), d, t)
- def __set_long(self, v, d, t):
- if len(v) == 0:
- return None
- if self.__long is None or self.__long.time() < t:
- self.__long = Position(float(v[0:3]) + (float(v[3:]) / 60), d, t)
- def __time_from_seg(self, ts):
- return (int(ts[0:2]), int(ts[2:4]), float(ts[4:]))
- class Data(object):
- def __init__(self, pins=("P3", "P4"), baud=9600):
- self.__com = machine.UART(1, pins=pins, baudrate=baud)
- self.__location = None
- self.__last_update = time.time()
- def new_location(self, ttw=5):
-
- if time.time() - (self.__last_update + ttw) < 0:
- return False
- self.__data = Location()
- data = []
- while self.__com.any():
- tmp_data = self.__com.readline()
- if tmp_data[0:1] == b'$':
- self.__update(data)
- data = [tmp_data]
- elif len(data) != 0:
- data.append(tmp_data)
- else:
- self.__update(data)
-
- return self.__data.valid()
- def get_location(self):
- return self.__data
- def __update(self, data):
- if len(data) == 0:
- return False
- data = b''.join(data)
- if data[len(data)-1:len(data)] not in (b'\n', b'\r'):
- return False
- if data[len(data)-1:len(data)] != b'\n':
- data += '\n'
- if self.__data.set(data[0:6], ("%s" % (data[7:len(data)-2],))[2:-1]):
- self.__last_update = time.time()
|