diff --git a/modules/gps/src/gpsinterface.py b/modules/gps/src/gpsinterface.py index 0d696e27..9bcfd86b 100644 --- a/modules/gps/src/gpsinterface.py +++ b/modules/gps/src/gpsinterface.py @@ -1,6 +1,5 @@ import threading from .steGPS import Gps -from core.sensor import Sensor # Define RX and TX pins for the board's serial port connected to the GPS. # These are the defaults you should use for the GPS FeatherWing. # For other boards set RX = GPS module TX, and TX = GPS module RX pins. @@ -9,89 +8,43 @@ from .settings import Settings -class GpsInterface(Sensor): +class GpsInterface(): - def __init__(self, settings: Settings, timezone_hours=+1): - self._settings = settings - self._settings_lock = threading.Lock() - self._gps = Gps('/dev/ttyAMA1', timezone_hours) + def __init__( + self, + latitude_start: float, + longitude_start: float, + latitude_end: float, + longitude_end: float, + serial_port: str, + ): + self._latitude_start = latitude_start + self._longitude_start = longitude_start + self._latitude_end = latitude_end + self._longitude_end = longitude_end + self._gps = Gps(serial_port) - def signal(self, value: str): - if value == 'reset': - self.reset_distance() - - def export(self): + def read_data(self): return { - 'timestamp': self.timestamp, - 'latitude': round(self.latitude, 6), - 'longitude': round(self.longitude, 6), - 'altitude': self.altitude, - 'speedGPS': round(self.speed, 2), - 'distanceGPS': self.travelled_distance, - 'satellites': self.satellites + 'timestampGPS': self._gps.timestamp, + 'latitude': round(self._gps.latitude, 6), + 'longitude': round(self._gps.longitude, 6), + 'altitude': self._gps.altitude, + 'speedGPS': round(self._gps.speed, 2), + 'distanceGPS': self._gps.travelled_distance, + 'satellites': self._gps.satellites, + 'distance2timing': self.distance2timing() } - - def update_settings(self, settings: Settings): - with self._settings_lock: - self._settings = settings - - @property - def position(self): - return self._gps.position - - @property - def latitude(self): - return self._gps.latitude - - @property - def longitude(self): - return self._gps.longitude - - @property - def altitude(self): - return self._gps.altitude - - @property - def speed(self): - return self._gps.speed - - @property - def satellites(self): - return self._gps.satellites - - @property - def day_time(self): - return self._gps.message_time - - @property - def date(self): - return self._gps.date - - @property - def timestamp(self): - return self._gps.timestamp - - def distance(self, latitude: float, longitude: float): - return self._gps.distance(latitude, longitude) - - @property - def travelled_distance(self): - return self._gps.travelled_distance - - @property + + # it returns distance from rider position to timing zone def distance2timing(self): - latitude = float(self._settings.latitude_timing_start) - longitude = float(self._settings.longitude_timing_start) - return self._gps.distance(latitude, longitude) + # if distance to the end of time zone is less than distance to start of it + # it means that timing zone is already passed by the rider + distance_to_start = self._gps.distance(self._latitude_start, self._longitude_end) + distance_to_end = self._gps.distance(self._latitude_end, self._longitude_end) + if distance_to_start > distance_to_end: + return 0.0 + return distance_to_start def reset_distance(self): self._gps.travelled_distance = 0 - - def is_in_timing(self): - latitude_start = float(self._settings.latitude_timing_start) - longitude_start = float(self._settings.longitude_timing_start) - latitude_end = float(self._settings.latitude_timing_end) - longitude_end = float(self._settings.longitude_timing_end) - distance_start = self._gps.distance(latitude_start, longitude_start) - distance_end = self._gps.distance(latitude_end, longitude_end) - return distance_end - distance_start < self._settings.trap_length diff --git a/modules/gps/src/main.py b/modules/gps/src/main.py index 7d833757..62b0f20a 100644 --- a/modules/gps/src/main.py +++ b/modules/gps/src/main.py @@ -1,43 +1,107 @@ -import time -import sys -import json -from .settings import Settings -from core.mqtt import MqttSensor +import asyncio +import threading +import logging +import os + +from core import log, Mqtt, Database, time + from .gpsinterface import GpsInterface -gps: GpsInterface - - -def message_handler(topic, message): - if topic == 'signals': - gps.signal(message.decode()) - - -def start(): - # total arguments - n = len(sys.argv) - if n < 2: - print("Total arguments passed:", n) - return - print("Mqtt server ip:", sys.argv[1]) - print('Starting GPS') - settings = Settings({ - 'trap_length': 200, - 'latitude_timing_start': 45.032888, - 'longitude_timing_start': 7.792347, - 'latitude_timing_end': 45.032888, - 'longitude_timing_end': 7.792347 - }, 'gps') - global gps - gps = GpsInterface(settings) - mqtt = MqttSensor(sys.argv[1], 1883, 'gps', ['reset'], - settings, message_handler) +# global data storage +data = dict() + + +async def read_data(gps_interface): + while True: + data.update(gps_interface.read_data()) + + await asyncio.sleep(0.1) + + +async def mqtt(): + while True: + try: + async with Mqtt() as client: + while True: + for key, value in data.items(): + await client.sensor_publish(f"gps/{key}", value) + await asyncio.sleep(0.2) + except Exception as e: + log.err(e) + finally: + await asyncio.sleep(1) + + +async def write_db(db): + curr_row = None + row = { + "timestamp": str(0), + "timestampGPS": str(0), + "latitude": 0, + "longitude": 0, + "altitude": 0, + "speedGPS": 0, + "distanceGPS": 0, + "satellites": 0, + "distance2timing": 0 + } + while True: - print(gps.export()) - mqtt.publish(json.dumps(gps.export())) - time.sleep(1) + try: + row.update(data) + + if row != curr_row: + row.update({"timestamp": time.human_timestamp()}) + + db.insert("gps", list(row.values())) + + curr_row = dict(row) + except: + pass + finally: + await asyncio.sleep(0.2) + + +async def main(): + while True: + try: + # retrive configurations from db + home_path = os.getenv("HOME") + db_path = os.getenv("DATABASE_PATH") or f"{home_path}/bob/database.db" + + db = Database(table="gps", path=db_path, max_pending=10) + config = db.config("gps") + + bike = config.get("name") + latitude_start = config.get(f"latitude_start") + longitude_start = config.get(f"longitude_start") + latitude_end = config.get(f"latitude_end") + longitude_end = config.get(f"longitude_start") + serial_port = config.get(f"{bike}_gps_serial") + + gps_interface = GpsInterface( + latitude_start, + longitude_start, + latitude_end, + longitude_end, + serial_port + ) + + await asyncio.gather( + read_data(gps_interface), + mqtt(), + write_db(db), + ) + # todo: exception should be something related to serial port + except Exception as e: + print(e) + await asyncio.sleep(0.5) + + +def entry_point(): + asyncio.run(main()) -if __name__ == '__main__': - start() +if __name__ == "__main__": + entry_point()