import json from utils.racer_helper import RacerHelper from utils.clients_setup_helper import ClientsSetupHelper import utils.constants as constants from time import sleep import datetime class RaceRunner: def __init__(self) -> None: self.racerHelper = RacerHelper() clients_helper = ClientsSetupHelper(self.racerHelper) self.car_and_race_update_client = clients_helper.car_and_race_update_client self.race_track_update_client = clients_helper.slot_car_update_client def send_lap_times_to_iot_core(self): while len(self.racerHelper.lapTimes) > 0: lap_time = self.racerHelper.lapTimes.popleft() self.car_and_race_update_client.send_payload( payload={ "topic": constants.LAP_TIME_TOPIC, "message_string": lap_time.json_representation_for_mqtt() } ) def send_race_analytics_to_mqtt(self): analytics_items = [] while len(self.racerHelper.raceAnalyticsItems) > 0: driveIntArray, slotcarIntArray = self.racerHelper.raceAnalyticsItems.popleft() analytics_items.append({ "raceId": self.racerHelper.current_race_id, "driveIntArray": str(driveIntArray), "slotcarIntArray": str(slotcarIntArray), "timestamp": datetime.datetime.now().isoformat(sep=' ', timespec='milliseconds') }) if len(analytics_items) > 0: self.car_and_race_update_client.send_payload( payload={ "topic": constants.RACE_ANALYTICS_TOPIC, "message_string": json.dumps(analytics_items) } ) def send_int_array_to_slot_cars(self): if self.race_track_update_client._client_type in constants.DIRECT_SLOT_CAR_CLIENTS: # If we're talking directly to the slot cars, repeatedly send the byte array payload = { "int_array": self.racerHelper.current_int_array, "recv_handler": self.racerHelper.handleIntArray } self.race_track_update_client.send_payload(payload=payload, racer_helper=self.racerHelper) elif self.race_track_update_client._client_type in constants.MQTT_CLIENT_SETTINGS: # If we're not talking directly only send byte array if we have a new array if self.racerHelper.previous_int_array != self.racerHelper.current_int_array: print(self.racerHelper.current_int_array) payload = { "topic": constants.TRACK_MQTT_TOPIC_NAME_PUB, "message_string": str(self.racerHelper.current_int_array) } self.race_track_update_client.send_payload(payload=payload) self.racerHelper.previous_int_array = self.racerHelper.current_int_array else: raise ValueError("Unrecognised Client") def is_connected(self): return self.car_and_race_update_client._connected == True and self.race_track_update_client._connected == True def run_race(self): last_run_time_slot_cars, last_run_time_iot_core, last_run_time_analytics = datetime.datetime.now(), datetime.datetime.now(), datetime.datetime.now() while True: if not self.is_connected(): print("waiting for connection...") sleep(1) continue current_run_time = datetime.datetime.now() # TODO: REFACTOR THIS CODE time_elapsed_slot_cars = (current_run_time - last_run_time_slot_cars).total_seconds() * 1000 # Elapsed time in MS if time_elapsed_slot_cars > constants.SLOT_CARS_SERIAL_REFRESH_RATE_MILLISECONDS: self.send_int_array_to_slot_cars() last_run_time_slot_cars = current_run_time time_elapsed_iot_core = (current_run_time - last_run_time_iot_core).total_seconds() * 1000 # Elapsed time in MS if time_elapsed_iot_core > constants.MQTT_REFRESH_RATE_MILLISECONDS: self.send_lap_times_to_iot_core() last_run_time_iot_core = current_run_time time_elapsed_iot_core = (current_run_time - last_run_time_analytics).total_seconds() * 1000 # Elapsed time in MS if constants.SEND_RACE_ANALYTICS_TO_MQTT and time_elapsed_iot_core > constants.ANALYTICS_REFRESH_RATE_MILLISECONDS: self.send_race_analytics_to_mqtt() last_run_time_analytics = current_run_time sleep(0.01) # Wait 10 ms anyways if __name__ == "__main__": RaceRunner().run_race()