From 57d77b647a32b9a248a149cdc2d525cc72c4a9ba Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 00:34:19 -0400 Subject: [PATCH 1/9] fixed Iridium driver --- MainControlLoop/lib/drivers/Iridium.py | 40 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/MainControlLoop/lib/drivers/Iridium.py b/MainControlLoop/lib/drivers/Iridium.py index 23d5859..cceafa2 100644 --- a/MainControlLoop/lib/drivers/Iridium.py +++ b/MainControlLoop/lib/drivers/Iridium.py @@ -1,11 +1,10 @@ from enum import Enum -from time import sleep from serial import Serial from MainControlLoop.lib.devices.device import Device -class Commands(Enum): +class IridiumCommand(Enum): TEST_IRIDIUM = 'AT' GEOLOCATION = 'AT-MSGEO' ACTIVE_CONFIG = 'AT+V' @@ -29,11 +28,6 @@ class Commands(Enum): SOFT_RESET = 'ATZn' -class ResponseCode(Enum): - OK = [b'O', b'K'] - ERROR = [b'E', b'R', b'R', b'O', b'R'] - - class Iridium(Device): PORT = '/dev/serial0' BAUDRATE = 19200 @@ -73,18 +67,40 @@ def functional(self) -> bool: except: return False - def write(self, command: str) -> bool: + def write(self, message: str) -> bool: """ - Write a command to the serial port. - :param command: (str) Command to write + Write a message to the serial port. + :param message: (str) Message to write :return: (bool) if the serial write worked """ + if not self.functional(): return False - command = command + "\r\n" + message = message + "\r\n" + try: + self.serial.write(message.encode("UTF-8")) + except: + return False + + return True + + def write_command(self, command: IridiumCommand) -> bool: + """ + Writes one of the Iridium commands to the serial port + :param command: (IridiumCommand) Command to write + :return: (bool) if the serial write worked + """ + + if type(command) != IridiumCommand: + return False + + if not self.functional(): + return False + + command_str = command.value + "\r\n" try: - self.serial.write(command.encode("UTF-8")) + self.serial.write(command_str.encode("UTF-8")) except: return False From 7503279305d1d5a777b492247ce75cfbd50000b8 Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 00:43:34 -0400 Subject: [PATCH 2/9] Iridium StateField's added to SFR --- .../lib/StateFieldRegistry/registry.py | 10 ++++++++- .../lib/StateFieldRegistry/state_fields.py | 22 +++++++++++++++++-- MainControlLoop/lib/drivers/Iridium.py | 3 +-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/MainControlLoop/lib/StateFieldRegistry/registry.py b/MainControlLoop/lib/StateFieldRegistry/registry.py index 2844c84..4835ef4 100644 --- a/MainControlLoop/lib/StateFieldRegistry/registry.py +++ b/MainControlLoop/lib/StateFieldRegistry/registry.py @@ -10,7 +10,9 @@ def __init__(self): Defines all the StateFields present in the state registry """ self.registry = { - # DUMP / BEACON TELEMETRY + # region DUMP / BEACON TELEMETRY + + # EPS DATA StateField.TIME: 0.0, StateField.IIDIODE_OUT: 0.0, StateField.VIDIODE_OUT: 0.0, @@ -38,6 +40,12 @@ def __init__(self): StateField.PDM_7_STAT: -1, StateField.PDM_8_STAT: -1, + # IRIDIUM DATA + StateField.GEOLOCATION: '', + StateField.IRIDIUM_SIGNAL: '', + + # endregion + # INTERVALS StateField.APRS_BEACON_INTERVAL: -1, StateField.IRIDIUM_BEACON_INTERVAL: -1, diff --git a/MainControlLoop/lib/StateFieldRegistry/state_fields.py b/MainControlLoop/lib/StateFieldRegistry/state_fields.py index 365b755..1c7a9a5 100644 --- a/MainControlLoop/lib/StateFieldRegistry/state_fields.py +++ b/MainControlLoop/lib/StateFieldRegistry/state_fields.py @@ -3,7 +3,9 @@ class StateField(Enum): - # DUMP / BEACON TELEMETRY + # region DUMP / BEACON TELEMETRY + + # EPS DATA TIME = 'TIME' IIDIODE_OUT = 'IIDIODE_OUT' VIDIODE_OUT = 'VIDIODE_OUT' @@ -31,6 +33,12 @@ class StateField(Enum): PDM_7_STAT = "PDM_7_STAT" PDM_8_STAT = "PDM_8_STAT" + # IRIDIUM DATA + GEOLOCATION = "GEOLOCATION" + IRIDIUM_SIGNAL = "IRIDIUM_SIGNAL" + + # end region + # TIME INTERVALS APRS_BEACON_INTERVAL = 'APRS_BEACON_INTERVAL' IRIDIUM_BEACON_INTERVAL = 'IRIDIUM_BEACON_INTERVAL' @@ -56,7 +64,9 @@ class ErrorFlag(Enum): StateFieldTypeCheck = { - # DUMP / BEACON TELEMETRY + # region DUMP / BEACON TELEMETRY + + # EPS DATA StateField.TIME: float, StateField.IIDIODE_OUT: float, StateField.VIDIODE_OUT: float, @@ -83,6 +93,12 @@ class ErrorFlag(Enum): StateField.PDM_6_STAT: int, StateField.PDM_7_STAT: int, StateField.PDM_8_STAT: int, + + # IRIDIUM DATA + StateField.GEOLOCATION: str, + StateField.IRIDIUM_SIGNAL: str, + + # endregion # INTERVALS StateField.APRS_BEACON_INTERVAL: int, @@ -101,6 +117,8 @@ class ErrorFlag(Enum): StateField.ANTENNA_DEPLOY_ATTEMPTED: bool } +# FIXME: the following should be removed before production + for state_field in StateField: if state_field not in StateFieldTypeCheck: raise NotImplementedError(f"{state_field}'s type has not been declared in StateFieldTypeCheck dictionary.") diff --git a/MainControlLoop/lib/drivers/Iridium.py b/MainControlLoop/lib/drivers/Iridium.py index cceafa2..7543aee 100644 --- a/MainControlLoop/lib/drivers/Iridium.py +++ b/MainControlLoop/lib/drivers/Iridium.py @@ -12,9 +12,8 @@ class IridiumCommand(Enum): PHONE_MODEL = 'AT+CGMM' PHONE_REVISION = 'AT+CGMR' PHONE_IMEI = 'AT+CSGN' - CHECK_NETWORK = 'AT-MSSTM' + CHECK_NETWORK = 'AT-MSSTM' # FIXME: Iridium documentation says this is for system time? SHUT_DOWN = 'AT*F' - SIGNAL_QUAL = 'AT+CSQ' # FIXME: cannot be tested until patch antenna is working # following commands probably need to be retested once patch antenna is fixed From 4f91faaa2e1dafd4fd002afad292a911da40e7f8 Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 01:16:06 -0400 Subject: [PATCH 3/9] read task started --- .../lib/StateFieldRegistry/state_fields.py | 2 +- MainControlLoop/tasks/Iridium/read_task.py | 59 ++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/MainControlLoop/lib/StateFieldRegistry/state_fields.py b/MainControlLoop/lib/StateFieldRegistry/state_fields.py index 1c7a9a5..3b76958 100644 --- a/MainControlLoop/lib/StateFieldRegistry/state_fields.py +++ b/MainControlLoop/lib/StateFieldRegistry/state_fields.py @@ -96,7 +96,7 @@ class ErrorFlag(Enum): # IRIDIUM DATA StateField.GEOLOCATION: str, - StateField.IRIDIUM_SIGNAL: str, + StateField.IRIDIUM_SIGNAL: int, # endregion diff --git a/MainControlLoop/tasks/Iridium/read_task.py b/MainControlLoop/tasks/Iridium/read_task.py index 27868a2..0684768 100644 --- a/MainControlLoop/tasks/Iridium/read_task.py +++ b/MainControlLoop/tasks/Iridium/read_task.py @@ -1,5 +1,13 @@ -from MainControlLoop.lib.drivers.Iridium import Iridium -from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, StateField +import re +from enum import Enum + +from MainControlLoop.lib.drivers.Iridium import Iridium, IridiumCommand +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, StateField, ErrorFlag + + +class Response(Enum): + OK = "OK" + ERROR = "ERROR" class IridiumReadTask: @@ -13,31 +21,52 @@ def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): self.last_message = "" def execute(self): + self.last_message = "" current_time: float = self.state_field_registry.get(StateField.TIME) last_message_time: float = self.state_field_registry.get(StateField.IRIDIUM_LAST_MESSAGE_TIME) if current_time - last_message_time > self.CLEAR_BUFFER_TIMEOUT: self.buffer = [] - next_byte: bytes = self.iridium.read() - self.last_message = "" + next_bytes, success = self.iridium.read() - if next_byte is False: + if success is False: # Iridium Hardware Fault - # TODO: Figure out how to represent hardware fault flags in the SFR + self.state_field_registry.raise_flag(ErrorFlag.IRIDIUM_FAILURE) return - if len(next_byte) == 0: + self.state_field_registry.drop_flag(ErrorFlag.IRIDIUM_FAILURE) + + if len(next_bytes) == 0: return - if next_byte == '\n'.encode('utf-8'): - message: str = "" - while len(self.buffer) > 0: - buffer_byte: bytes = self.buffer.pop(0) - message += buffer_byte.decode('utf-8') + self.buffer.append(next_bytes) + buffer_content = ''.join([b.decode('UTF-8') for b in self.buffer]) + buffer_items = re.split(r'OK|ERROR', buffer_content) + self.buffer = [] + + for item in buffer_items: + if item == '' or item == '\r\n': + continue + + if Response.OK.value not in item and Response.ERROR.value not in item: + self.buffer.append(item.encode('UTF-8')) + continue - self.last_message = message self.state_field_registry.update(StateField.IRIDIUM_LAST_MESSAGE_TIME, current_time) - return - self.buffer.append(next_byte) + if IridiumCommand.GEOLOCATION.value in item: + item_split = re.split(r'MSGEO:', item) + if len(item_split) < 2: + continue + + location = re.split('\r', item_split[1].strip())[0] + self.state_field_registry.update(StateField.GEOLOCATION, location) + continue + + if IridiumCommand.SIGNAL.value in item: + signal_strength = int('0' + re.sub(r'[^\d]*', '', item)) + self.state_field_registry.update(StateField.IRIDIUM_SIGNAL, signal_strength) + continue + + # TODO: design message structure for commands sent via Iridium from ground station From 7618e2a4eb05434fe24d59f07c27b8a9a380fad1 Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 16:01:07 -0400 Subject: [PATCH 4/9] actuate task --- .../DownLinkProducer/down_link_producer.py | 10 ++--- .../tasks/Iridium/actuate/__init__.py | 4 ++ MainControlLoop/tasks/Iridium/actuate/dump.py | 37 +++++++++++++++++++ .../tasks/Iridium/actuate/geolocation.py | 19 ++++++++++ .../tasks/Iridium/actuate/reset.py | 19 ++++++++++ .../tasks/Iridium/actuate/signal.py | 19 ++++++++++ MainControlLoop/tasks/Iridium/actuate_task.py | 37 +++++++++++++++++++ 7 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 MainControlLoop/tasks/Iridium/actuate/__init__.py create mode 100644 MainControlLoop/tasks/Iridium/actuate/dump.py create mode 100644 MainControlLoop/tasks/Iridium/actuate/geolocation.py create mode 100644 MainControlLoop/tasks/Iridium/actuate/reset.py create mode 100644 MainControlLoop/tasks/Iridium/actuate/signal.py create mode 100644 MainControlLoop/tasks/Iridium/actuate_task.py diff --git a/MainControlLoop/tasks/DownLinkProducer/down_link_producer.py b/MainControlLoop/tasks/DownLinkProducer/down_link_producer.py index 5ca62bf..cb0f693 100644 --- a/MainControlLoop/tasks/DownLinkProducer/down_link_producer.py +++ b/MainControlLoop/tasks/DownLinkProducer/down_link_producer.py @@ -43,17 +43,17 @@ def create_dump(state_field_registry: StateFieldRegistry) -> [str]: StateField.PDM_8_STAT ] - dumpList = [dump_header] + dump_list = [dump_header] for element in elements: value = state_field_registry.get(element) dump_addition = f"{value};" - if len(dumpList[-1] + dump_addition) > max_length: + if len(dump_list[-1] + dump_addition) > max_length: # Add the message number, len() - 1 because indexing by 0 - dumpList.append(dump_header + f"{len(dumpList) - 1};") - dumpList[-1] += dump_addition + dump_list.append(dump_header + f"{len(dump_list) - 1};") + dump_list[-1] += dump_addition - return dumpList + return dump_list @staticmethod def create_beacon(state_field_registry: StateFieldRegistry) -> str: diff --git a/MainControlLoop/tasks/Iridium/actuate/__init__.py b/MainControlLoop/tasks/Iridium/actuate/__init__.py new file mode 100644 index 0000000..dec9848 --- /dev/null +++ b/MainControlLoop/tasks/Iridium/actuate/__init__.py @@ -0,0 +1,4 @@ +from .dump import IridiumDumpActuateTask +from .geolocation import IridiumGeolocationActuateTask +from .reset import IridiumResetActuateTask +from .signal import IridiumSignalStrengthActuateTask diff --git a/MainControlLoop/tasks/Iridium/actuate/dump.py b/MainControlLoop/tasks/Iridium/actuate/dump.py new file mode 100644 index 0000000..fb9130c --- /dev/null +++ b/MainControlLoop/tasks/Iridium/actuate/dump.py @@ -0,0 +1,37 @@ +from MainControlLoop.lib.drivers.Iridium import Iridium +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, ErrorFlag + + +class IridiumDumpActuateTask: + def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): + self.iridium: Iridium = iridium + self.state_field_registry: StateFieldRegistry = state_field_registry + self.run = False + self.dump: list = [] + + def set_dump(self, messages: list): + if not isinstance(messages, list): + return + + for message in messages: + if not isinstance(message, str): + return + + self.dump = messages + + def execute(self): + if not self.run: + return + + self.run = False + if len(self.dump) == 0: + return + + for portion in self.dump: + success = self.iridium.write(portion) + if not success: + self.state_field_registry.raise_flag(ErrorFlag.IRIDIUM_FAILURE) + self.dump = [] + return + + self.dump = [] diff --git a/MainControlLoop/tasks/Iridium/actuate/geolocation.py b/MainControlLoop/tasks/Iridium/actuate/geolocation.py new file mode 100644 index 0000000..75b7bcb --- /dev/null +++ b/MainControlLoop/tasks/Iridium/actuate/geolocation.py @@ -0,0 +1,19 @@ +from MainControlLoop.lib.drivers.Iridium import Iridium, IridiumCommand +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, ErrorFlag + + +class IridiumGeolocationActuateTask: + def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): + self.iridium: Iridium = iridium + self.state_field_registry: StateFieldRegistry = state_field_registry + self.run = False + + def execute(self): + if not self.run: + return + + self.run = False + + success = self.iridium.write_command(IridiumCommand.GEOLOCATION) + if not success: + self.state_field_registry.raise_flag(ErrorFlag.IRIDIUM_FAILURE) diff --git a/MainControlLoop/tasks/Iridium/actuate/reset.py b/MainControlLoop/tasks/Iridium/actuate/reset.py new file mode 100644 index 0000000..cd14165 --- /dev/null +++ b/MainControlLoop/tasks/Iridium/actuate/reset.py @@ -0,0 +1,19 @@ +from MainControlLoop.lib.drivers.Iridium import Iridium, IridiumCommand +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, ErrorFlag + + +class IridiumResetActuateTask: + def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): + self.iridium: Iridium = iridium + self.state_field_registry: StateFieldRegistry = state_field_registry + self.run = False + + def execute(self): + if not self.run: + return + + self.run = False + + success = self.iridium.write_command(IridiumCommand.SOFT_RESET) + if not success: + self.state_field_registry.raise_flag(ErrorFlag.IRIDIUM_FAILURE) diff --git a/MainControlLoop/tasks/Iridium/actuate/signal.py b/MainControlLoop/tasks/Iridium/actuate/signal.py new file mode 100644 index 0000000..3bc3a46 --- /dev/null +++ b/MainControlLoop/tasks/Iridium/actuate/signal.py @@ -0,0 +1,19 @@ +from MainControlLoop.lib.drivers.Iridium import Iridium, IridiumCommand +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, ErrorFlag + + +class IridiumSignalStrengthActuateTask: + def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): + self.iridium: Iridium = iridium + self.state_field_registry: StateFieldRegistry = state_field_registry + self.run = False + + def execute(self): + if not self.run: + return + + self.run = False + + success = self.iridium.write_command(IridiumCommand.SIGNAL) + if not success: + self.state_field_registry.raise_flag(ErrorFlag.IRIDIUM_FAILURE) diff --git a/MainControlLoop/tasks/Iridium/actuate_task.py b/MainControlLoop/tasks/Iridium/actuate_task.py new file mode 100644 index 0000000..5e8c2f7 --- /dev/null +++ b/MainControlLoop/tasks/Iridium/actuate_task.py @@ -0,0 +1,37 @@ +from MainControlLoop.lib.drivers import Iridium +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry + +from MainControlLoop.tasks.Iridium.actuate import IridiumDumpActuateTask +from MainControlLoop.tasks.Iridium.actuate import IridiumGeolocationActuateTask +from MainControlLoop.tasks.Iridium.actuate import IridiumResetActuateTask +from MainControlLoop.tasks.Iridium.actuate import IridiumSignalStrengthActuateTask + + +class APRSActuateTask: + + def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): + self.dump_actuate_task = IridiumDumpActuateTask(iridium, state_field_registry) + self.geolocation_actuate_task = IridiumGeolocationActuateTask(iridium, state_field_registry) + self.reset_actuate_task = IridiumResetActuateTask(iridium, state_field_registry) + self.signal_strength_actuate_task = IridiumSignalStrengthActuateTask(iridium, state_field_registry) + + def set_dump(self, dump): + self.dump_actuate_task.set_dump(dump) + + def enable_dump(self): + self.dump_actuate_task.run = True + + def enable_geolocation(self): + self.geolocation_actuate_task.run = True + + def enable_reset(self): + self.reset_actuate_task.run = True + + def enable_signal_strength(self): + self.signal_strength_actuate_task.run = True + + def execute(self): + self.reset_actuate_task.execute() + self.dump_actuate_task.execute() + self.geolocation_actuate_task.execute() + self.signal_strength_actuate_task.execute() From 97a3cae9dd98efa03a6ae6ca02ddf4d544ad4081 Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 16:23:06 -0400 Subject: [PATCH 5/9] control task --- MainControlLoop/tasks/Iridium/control_task.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 MainControlLoop/tasks/Iridium/control_task.py diff --git a/MainControlLoop/tasks/Iridium/control_task.py b/MainControlLoop/tasks/Iridium/control_task.py new file mode 100644 index 0000000..e69de29 From 13f42ed07c8915b2f9cacbd7a701cee7509ec7af Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 16:23:12 -0400 Subject: [PATCH 6/9] control task --- .../lib/StateFieldRegistry/registry.py | 3 +- .../lib/StateFieldRegistry/state_fields.py | 6 ++- MainControlLoop/tasks/Iridium/actuate_task.py | 2 +- MainControlLoop/tasks/Iridium/control_task.py | 46 +++++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/MainControlLoop/lib/StateFieldRegistry/registry.py b/MainControlLoop/lib/StateFieldRegistry/registry.py index 4835ef4..e85ba9c 100644 --- a/MainControlLoop/lib/StateFieldRegistry/registry.py +++ b/MainControlLoop/lib/StateFieldRegistry/registry.py @@ -48,12 +48,13 @@ def __init__(self): # INTERVALS StateField.APRS_BEACON_INTERVAL: -1, - StateField.IRIDIUM_BEACON_INTERVAL: -1, + StateField.IRIDIUM_DUMP_INTERVAL: -1, # TIME RECORDINGS StateField.APRS_LAST_MESSAGE_TIME: 0.0, StateField.IRIDIUM_LAST_MESSAGE_TIME: 0.0, StateField.APRS_LAST_BEACON_TIME: 0.0, + StateField.IRIDIUM_LAST_DUMP_TIME: 0.0, StateField.LAST_ARCHIVE_TIME: 0.0, StateField.BOOT_TIME: -1, diff --git a/MainControlLoop/lib/StateFieldRegistry/state_fields.py b/MainControlLoop/lib/StateFieldRegistry/state_fields.py index 3b76958..6e07cea 100644 --- a/MainControlLoop/lib/StateFieldRegistry/state_fields.py +++ b/MainControlLoop/lib/StateFieldRegistry/state_fields.py @@ -41,12 +41,13 @@ class StateField(Enum): # TIME INTERVALS APRS_BEACON_INTERVAL = 'APRS_BEACON_INTERVAL' - IRIDIUM_BEACON_INTERVAL = 'IRIDIUM_BEACON_INTERVAL' + IRIDIUM_DUMP_INTERVAL = 'IRIDIUM_BEACON_INTERVAL' # TIME RECORDINGS APRS_LAST_MESSAGE_TIME = 'APRS_LAST_MESSAGE_TIME' IRIDIUM_LAST_MESSAGE_TIME = 'IRIDIUM_LAST_MESSAGE_TIME' APRS_LAST_BEACON_TIME = 'APRS_LAST_BEACON_TIME' + IRIDIUM_LAST_DUMP_TIME = "IRIDIUM_LAST_DUMP_TIME" LAST_ARCHIVE_TIME = 'LAST_ARCHIVE_TIME' BOOT_TIME = 'BOOT_TIME' @@ -102,12 +103,13 @@ class ErrorFlag(Enum): # INTERVALS StateField.APRS_BEACON_INTERVAL: int, - StateField.IRIDIUM_BEACON_INTERVAL: int, + StateField.IRIDIUM_DUMP_INTERVAL: int, # TIME RECORDINGS StateField.APRS_LAST_MESSAGE_TIME: float, StateField.IRIDIUM_LAST_MESSAGE_TIME: float, StateField.APRS_LAST_BEACON_TIME: float, + StateField.IRIDIUM_LAST_DUMP_TIME: float, StateField.LAST_ARCHIVE_TIME: float, StateField.BOOT_TIME: float, diff --git a/MainControlLoop/tasks/Iridium/actuate_task.py b/MainControlLoop/tasks/Iridium/actuate_task.py index 5e8c2f7..83ae866 100644 --- a/MainControlLoop/tasks/Iridium/actuate_task.py +++ b/MainControlLoop/tasks/Iridium/actuate_task.py @@ -7,7 +7,7 @@ from MainControlLoop.tasks.Iridium.actuate import IridiumSignalStrengthActuateTask -class APRSActuateTask: +class IridiumActuateTask: def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry): self.dump_actuate_task = IridiumDumpActuateTask(iridium, state_field_registry) diff --git a/MainControlLoop/tasks/Iridium/control_task.py b/MainControlLoop/tasks/Iridium/control_task.py index e69de29..978a82f 100644 --- a/MainControlLoop/tasks/Iridium/control_task.py +++ b/MainControlLoop/tasks/Iridium/control_task.py @@ -0,0 +1,46 @@ +from MainControlLoop.lib.drivers.Iridium import Iridium +from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry, StateField, StateFieldRegistryLocker +from MainControlLoop.lib.modes import Mode +from MainControlLoop.tasks.Iridium.actuate_task import IridiumActuateTask +from MainControlLoop.tasks.DownLinkProducer import DownLinkProducer + +import re +from enum import Enum + + +class DumpInterval(Enum): + NORMAL = 120 + NEVER = -1 + + +class IridiumControlTask: + + def __init__(self, iridium: Iridium, state_field_registry: StateFieldRegistry, actuate_task: IridiumActuateTask): + self.iridium: Iridium = iridium + self.state_field_registry: StateFieldRegistry = state_field_registry + self.mode: Mode = Mode.BOOT + + self.actuate_task: IridiumActuateTask = actuate_task + + def execute(self): + current_sys_time: float = self.state_field_registry.get(StateField.TIME) + + if self.mode == Mode.SAFE: + # TODO: safe mode implementation + return + + if self.mode != Mode.NORMAL: + self.state_field_registry.update(StateField.IRIDIUM_DUMP_INTERVAL, DumpInterval.NEVER) + return + self.state_field_registry.update(StateField.IRIDIUM_DUMP_INTERVAL, DumpInterval.NORMAL) + + interval = self.state_field_registry.get(StateField.IRIDIUM_DUMP_INTERVAL) + last_beacon_time: float = self.state_field_registry.get(StateField.IRIDIUM_LAST_DUMP_TIME) + + if current_sys_time - last_beacon_time > interval: + dump = DownLinkProducer.create_dump(self.state_field_registry) + self.actuate_task.set_dump(dump) + self.actuate_task.enable_dump() + + self.actuate_task.enable_geolocation() + self.actuate_task.enable_signal_strength() From 4a851ce707cde63e16532ac5dd96b6ed791f64fe Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 16:26:30 -0400 Subject: [PATCH 7/9] iridium task --- MainControlLoop/main_control_loop.py | 4 +++- MainControlLoop/tasks/Iridium/task.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/MainControlLoop/main_control_loop.py b/MainControlLoop/main_control_loop.py index 26c30d1..ce2041e 100644 --- a/MainControlLoop/main_control_loop.py +++ b/MainControlLoop/main_control_loop.py @@ -19,7 +19,7 @@ def __init__(self): def execute(self): # READ BLOCK - commands = ['', '', ''] # APRS, Iridium, System + commands = ['', ''] # APRS, Iridium self.pi_monitor.read() commands[0] = self.aprs.read() commands[1] = self.iridium.read() @@ -29,7 +29,9 @@ def execute(self): self.archiver.control() self.pi_monitor.control(commands) self.aprs.control(commands) + self.iridium.control() # ACTUATE BLOCK self.pi_monitor.actuate() self.aprs.actuate() + self.iridium.actuate() diff --git a/MainControlLoop/tasks/Iridium/task.py b/MainControlLoop/tasks/Iridium/task.py index 076bbb5..6f2490b 100644 --- a/MainControlLoop/tasks/Iridium/task.py +++ b/MainControlLoop/tasks/Iridium/task.py @@ -1,6 +1,10 @@ from MainControlLoop.lib.drivers.Iridium import Iridium from MainControlLoop.lib.StateFieldRegistry import StateFieldRegistry +from MainControlLoop.lib.modes import Mode + from MainControlLoop.tasks.Iridium.read_task import IridiumReadTask +from MainControlLoop.tasks.Iridium.control_task import IridiumControlTask +from MainControlLoop.tasks.Iridium.actuate_task import IridiumActuateTask class IridiumTask: @@ -8,8 +12,25 @@ class IridiumTask: def __init__(self, state_field_registry: StateFieldRegistry): self.iridium: Iridium = Iridium() self.state_field_registry: StateFieldRegistry = state_field_registry + self.mode = Mode.BOOT + self.read_task = IridiumReadTask(self.iridium, self.state_field_registry) + self.actuate_task = IridiumActuateTask(self.iridium, self.state_field_registry) + self.control_task = IridiumControlTask(self.iridium, self.state_field_registry, self.actuate_task) + + def set_mode(self, mode: Mode): + if not isinstance(mode, Mode): + return + + self.mode = mode + self.control_task.mode = self.mode def read(self): self.read_task.execute() return self.read_task.last_message + + def control(self): + self.control_task.execute() + + def actuate(self): + self.actuate_task.execute() From da30a84f71d15151f56b82976284431776732b1e Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 16:39:53 -0400 Subject: [PATCH 8/9] iridium reads commands --- MainControlLoop/tasks/Iridium/read_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainControlLoop/tasks/Iridium/read_task.py b/MainControlLoop/tasks/Iridium/read_task.py index 0684768..d162eb5 100644 --- a/MainControlLoop/tasks/Iridium/read_task.py +++ b/MainControlLoop/tasks/Iridium/read_task.py @@ -69,4 +69,4 @@ def execute(self): self.state_field_registry.update(StateField.IRIDIUM_SIGNAL, signal_strength) continue - # TODO: design message structure for commands sent via Iridium from ground station + self.last_message = item.replace('OK', '') From a8e8bfe8acf94f5d2fd1a8179617226655c2666e Mon Sep 17 00:00:00 2001 From: Shreepa Parthaje Date: Fri, 27 Mar 2020 16:42:33 -0400 Subject: [PATCH 9/9] iridium driver comments --- MainControlLoop/lib/drivers/Iridium.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/MainControlLoop/lib/drivers/Iridium.py b/MainControlLoop/lib/drivers/Iridium.py index 7543aee..b78aa59 100644 --- a/MainControlLoop/lib/drivers/Iridium.py +++ b/MainControlLoop/lib/drivers/Iridium.py @@ -5,8 +5,16 @@ class IridiumCommand(Enum): - TEST_IRIDIUM = 'AT' + # Used Commands + # FIXME: test these commands once patch antenna is working GEOLOCATION = 'AT-MSGEO' + SOFT_RESET = 'ATZn' + SIGNAL = 'AT+CSQ' + + # FIXME: delete the following region before production + # region unused commands + + TEST_IRIDIUM = 'AT' ACTIVE_CONFIG = 'AT+V' CHECK_REGISTRATION = 'AT+SBDREG?' PHONE_MODEL = 'AT+CGMM' @@ -15,16 +23,14 @@ class IridiumCommand(Enum): CHECK_NETWORK = 'AT-MSSTM' # FIXME: Iridium documentation says this is for system time? SHUT_DOWN = 'AT*F' - # FIXME: cannot be tested until patch antenna is working # following commands probably need to be retested once patch antenna is fixed - SEND_SMS = 'AT+CMGS=' - SIGNAL = 'AT+CSQ' SBD_RING_ALERT_ON = 'AT+SBDMTA=1' SBD_RING_ALERT_OFF = 'AT+SBDMTA=0' BATTERY_CHECK = 'AT+CBC=?' CALL_STATUS = 'AT+CLCC=?' - SOFT_RESET = 'ATZn' + + # endregion class Iridium(Device):