|
1 | 1 | import gc |
| 2 | +import json |
2 | 3 | import os |
3 | 4 | import time |
4 | 5 |
|
|
25 | 26 |
|
26 | 27 | boot_time: float = time.time() |
27 | 28 |
|
| 29 | +cube_ids = ["Listener1", "Listener2", "Listener3"] |
| 30 | +my_cubesat_id = "Listener1" |
| 31 | + |
28 | 32 | rtc = MicrocontrollerManager() |
29 | 33 |
|
30 | 34 | (boot_count := Counter(index=Register.boot_count)).increment() |
@@ -134,19 +138,85 @@ def nominal_power_loop(): |
134 | 138 | bytes_remaining=gc.mem_free(), |
135 | 139 | ) |
136 | 140 |
|
137 | | - uhf_packet_manager.send(config.radio.license.encode("utf-8")) |
138 | | - |
139 | | - beacon.send() |
140 | | - |
141 | | - cdh.listen_for_commands(10) |
142 | | - |
143 | | - sleep_helper.safe_sleep(config.sleep_duration) |
| 141 | + message: dict[str, object] = dict() |
| 142 | + for cube_id in cube_ids: |
| 143 | + if cube_id == my_cubesat_id: |
| 144 | + continue |
| 145 | + |
| 146 | + # --- 1. Send a ping to a single cubesat --- |
| 147 | + logger.info(f"Pinging {cube_id}...") |
| 148 | + message["current_time"] = time.monotonic() |
| 149 | + message["cube_id"] = cube_id |
| 150 | + message["command"] = "ping" |
| 151 | + encoded_message = json.dumps(message, separators=(",", ":")).encode("utf-8") |
| 152 | + |
| 153 | + if not uhf_packet_manager.send(encoded_message): |
| 154 | + logger.warning(f"Failed to send ping to {cube_id}") |
| 155 | + sleep_helper.safe_sleep(1) # Wait a moment before trying the next one |
| 156 | + continue |
| 157 | + |
| 158 | + # --- 2. Listen for an immediate pong response --- |
| 159 | + logger.info(f"Listening for pong from {cube_id} for 10 seconds.") |
| 160 | + received_message = uhf_packet_manager.listen(10) |
| 161 | + |
| 162 | + if received_message: |
| 163 | + try: |
| 164 | + decoded_message = json.loads(received_message.decode("utf-8")) |
| 165 | + sender_id = decoded_message.get("cube_id") |
| 166 | + command = decoded_message.get("command") |
| 167 | + if command == "pong" and sender_id == cube_id: |
| 168 | + logger.info(f"Success! Received pong for me from {sender_id}.") |
| 169 | + else: |
| 170 | + logger.warning( |
| 171 | + f"Received unexpected message: {decoded_message}" |
| 172 | + ) |
| 173 | + except (json.JSONDecodeError, UnicodeError) as e: |
| 174 | + logger.error("Could not process received message", e) |
| 175 | + else: |
| 176 | + logger.warning(f"No response from {cube_id} within the time limit.") |
| 177 | + |
| 178 | + # --- 3. Wait before contacting the next satellite --- |
| 179 | + logger.debug("Waiting 5 seconds before contacting next satellite.") |
| 180 | + sleep_helper.safe_sleep(5) |
| 181 | + |
| 182 | + def listener_nominal_power_loop(): |
| 183 | + # logger.debug( |
| 184 | + # "FC Board Stats", |
| 185 | + # bytes_remaining=gc.mem_free(), |
| 186 | + # ) |
| 187 | + |
| 188 | + # logger.info("Listening for messages for 60 seconds") |
| 189 | + received_message: bytes | None = uhf_packet_manager.listen(5) |
| 190 | + |
| 191 | + if received_message: |
| 192 | + try: |
| 193 | + decoded_message = json.loads(received_message.decode("utf-8")) |
| 194 | + logger.info(f"Received message: {decoded_message}") |
| 195 | + |
| 196 | + cubesat_id = decoded_message.get("cube_id") |
| 197 | + if cubesat_id == my_cubesat_id: |
| 198 | + command = decoded_message.get("command") |
| 199 | + if command == "ping": |
| 200 | + logger.info(f"Received ping from {cubesat_id}") |
| 201 | + response_message = { |
| 202 | + "current_time": time.monotonic(), |
| 203 | + "cube_id": my_cubesat_id, |
| 204 | + "command": "pong", |
| 205 | + } |
| 206 | + encoded_response = json.dumps( |
| 207 | + response_message, separators=(",", ":") |
| 208 | + ).encode("utf-8") |
| 209 | + sleep_helper.safe_sleep(1) |
| 210 | + uhf_packet_manager.send(encoded_response) |
| 211 | + |
| 212 | + except (json.JSONDecodeError, UnicodeError) as e: |
| 213 | + logger.error("Failed to decode message", e) |
144 | 214 |
|
145 | 215 | try: |
146 | 216 | logger.info("Entering main loop") |
147 | 217 | while True: |
148 | 218 | # TODO(nateinaction): Modify behavior based on power state |
149 | | - nominal_power_loop() |
| 219 | + listener_nominal_power_loop() |
150 | 220 |
|
151 | 221 | except Exception as e: |
152 | 222 | logger.critical("Critical in Main Loop", e) |
|
0 commit comments