Skip to content

Commit 95d7410

Browse files
committed
listener works, writes to filwsystem
1 parent 9b979bf commit 95d7410

File tree

4 files changed

+228
-98
lines changed

4 files changed

+228
-98
lines changed

src/flight-software/boot.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
# This tells the computer to disconnect from the board's mass storage device (CIRCUITPY drive).
1111
# This is the correct method for CircuitPython 9+
1212
storage.disable_usb_drive() # disable CIRCUITPY
13+
try:
14+
with open('/sd/leaderboard.json', 'r') as file:
15+
pass # File exists
16+
except OSError:
17+
with open('/sd/leaderboard.json', 'w') as file:
18+
file.write('{}')
19+
20+
21+
22+
1323
# After the USB drive is disabled, we can remount the /sd filesystem
1424
# as writable for our CircuitPython code.
1525
# storage.remount("/sd", readonly=False)

src/flight-software/main.py

Lines changed: 3 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from lib.pysquared.sleep_helper import SleepHelper
2424
from lib.pysquared.watchdog import Watchdog
2525
from version import __version__
26+
from utils import nominal_power_loop, listener_nominal_power_loop
2627

2728
boot_time: float = time.time()
2829

@@ -132,95 +133,12 @@
132133
boot_count,
133134
)
134135

135-
def nominal_power_loop():
136-
logger.debug(
137-
"FC Board Stats",
138-
bytes_remaining=gc.mem_free(),
139-
)
140-
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(
169-
f"_______!!!!!!!!!!Success! Received pong for me from {sender_id}.!!!!!!!!!!!!_______"
170-
)
171-
else:
172-
logger.warning(
173-
f"Received unexpected message: {decoded_message}"
174-
)
175-
except (json.JSONDecodeError, UnicodeError) as e:
176-
logger.error("Could not process received message", e)
177-
else:
178-
logger.warning(f"No response from {cube_id} within the time limit.")
179-
180-
# --- 3. Wait before contacting the next satellite ---
181-
logger.debug("Waiting 5 seconds before contacting next satellite.")
182-
sleep_helper.safe_sleep(5)
183-
184-
def listener_nominal_power_loop():
185-
# logger.debug(
186-
# "FC Board Stats",
187-
# bytes_remaining=gc.mem_free(),
188-
# )
189-
190-
# logger.info("Listening for messages for 60 seconds")
191-
received_message: bytes | None = uhf_packet_manager.listen(5)
192-
193-
if received_message:
194-
try:
195-
decoded_message = json.loads(received_message.decode("utf-8"))
196-
logger.info(f"Received message: {decoded_message}")
197-
198-
cubesat_id = decoded_message.get("cube_id")
199-
if cubesat_id == my_cubesat_id:
200-
command = decoded_message.get("command")
201-
if command == "ping":
202-
logger.info(
203-
f"_______!!!!!!!!!! Received ping from {cubesat_id} !!!!!!!!!!!!_______"
204-
)
205-
response_message = {
206-
"current_time": time.monotonic(),
207-
"cube_id": my_cubesat_id,
208-
"command": "pong",
209-
}
210-
encoded_response = json.dumps(
211-
response_message, separators=(",", ":")
212-
).encode("utf-8")
213-
sleep_helper.safe_sleep(1)
214-
uhf_packet_manager.send(encoded_response)
215-
216-
except (json.JSONDecodeError, UnicodeError) as e:
217-
logger.error("Failed to decode message", e)
218-
219136
try:
220137
logger.info("Entering main loop")
221138
while True:
222139
# TODO(nateinaction): Modify behavior based on power state
223-
listener_nominal_power_loop()
140+
nominal_power_loop(logger, uhf_packet_manager, sleep_helper, my_cubesat_id="Listener1")
141+
#nominal_power_loop(logger, uhf_packet_manager, sleep_helper, cube_id=["Listener1", "Listener2", "Listener3"])
224142

225143
except Exception as e:
226144
logger.critical("Critical in Main Loop", e)

src/flight-software/repl.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@
88

99
import storage
1010

11+
import microcontroller
12+
13+
#hard reboot = microcontroller.reset()
14+
# do an on boot file later
1115
#need to call this to write new code to the board, otherwise the baord will not appear!
12-
def wipe_system():
16+
def erase_system():
1317
storage.erase_filesystem()
18+
19+
def hard_reboot():
20+
microcontroller.reset()
1421
# from lib.pysquared.Big_Data import AllFaces ### This is Hacky V5a Devel Stuff##
1522
from lib.pysquared.beacon import Beacon
1623
from lib.pysquared.cdh import CommandDataHandler
@@ -31,18 +38,7 @@ def wipe_system():
3138
from lib.pysquared.sleep_helper import SleepHelper
3239
from lib.pysquared.watchdog import Watchdog
3340
from version import __version__
34-
35-
#TO DO: turn this into a real test for our flash memory
36-
def test_sd():
37-
print(os.listdir())
38-
print("___________")
39-
os.mkdir('sd/new_folder')
40-
print(os.listdir('sd'))
41-
print("_______________")
42-
with open('boot_out.txt', 'r') as file:
43-
print(file.read())
44-
45-
41+
from utils import nominal_power_loop, listener_nominal_power_loop, test_sd, update_leaderboard, display_leaderboard, send_leaderboard, send_leaderboard_power_loop
4642

4743
from lib.adafruit_mcp230xx.mcp23017 import (
4844
MCP23017, # This is Hacky V5a Devel Stuff###
@@ -253,3 +249,4 @@ def all_faces_on():
253249
antenna_deployment = BurnwireManager(
254250
logger, burnwire_heater_enable, burnwire1_fire, enable_logic=True
255251
)
252+

src/flight-software/utils.py

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
2+
import gc
3+
import json
4+
import os
5+
import time
6+
import json
7+
8+
import board
9+
import digitalio
10+
import microcontroller
11+
from lib.proveskit_rp2350_v5b.register import Register
12+
from lib.pysquared.beacon import Beacon
13+
from lib.pysquared.cdh import CommandDataHandler
14+
from lib.pysquared.config.config import Config
15+
from lib.pysquared.hardware.busio import _spi_init, initialize_i2c_bus
16+
from lib.pysquared.hardware.digitalio import initialize_pin
17+
from lib.pysquared.hardware.imu.manager.lsm6dsox import LSM6DSOXManager
18+
from lib.pysquared.hardware.magnetometer.manager.lis2mdl import LIS2MDLManager
19+
from lib.pysquared.hardware.radio.manager.rfm9x import RFM9xManager
20+
from lib.pysquared.hardware.radio.manager.sx1280 import SX1280Manager
21+
from lib.pysquared.hardware.radio.packetizer.packet_manager import PacketManager
22+
from lib.pysquared.logger import Logger
23+
from lib.pysquared.nvm.counter import Counter
24+
from lib.pysquared.rtc.manager.microcontroller import MicrocontrollerManager
25+
from lib.pysquared.sleep_helper import SleepHelper
26+
from lib.pysquared.watchdog import Watchdog
27+
28+
29+
SENDLEADERBOARD = "send_leaderboard"
30+
SENDPING = "ping"
31+
CUBSATID = "Listener"
32+
UPDATE_LEADERBOARD = "update_leaderboard"
33+
34+
def nominal_power_loop(logger, uhf_packet_manager, sleep_helper, cube_ids=["Listener1", "Listener2", "Listener3"]):
35+
36+
message: dict[str, object] = dict()
37+
for cube_id in cube_ids:
38+
if cube_id == my_cubesat_id:
39+
continue
40+
41+
# --- 1. Send a ping to a single cubesat ---
42+
logger.info(f"Pinging {cube_id}...")
43+
message["current_time"] = time.monotonic()
44+
message["cube_id"] = cube_id
45+
message["command"] = PING
46+
encoded_message = json.dumps(message, separators=(",", ":")).encode("utf-8")
47+
48+
if not uhf_packet_manager.send(encoded_message):
49+
logger.warning(f"Failed to send ping to {cube_id}")
50+
sleep_helper.safe_sleep(1) # Wait a moment before trying the next one
51+
continue
52+
53+
# --- 2. Listen for an immediate pong response ---
54+
logger.info(f"Listening for pong from {cube_id} for 10 seconds.")
55+
received_message = uhf_packet_manager.listen(10)
56+
57+
if received_message:
58+
try:
59+
decoded_message = json.loads(received_message.decode("utf-8"))
60+
sender_id = decoded_message.get("cube_id")
61+
command = decoded_message.get("command")
62+
if command == "pong" and sender_id == cube_id:
63+
logger.info(
64+
f"_______!!!!!!!!!!Success! Received pong for me from {sender_id}.!!!!!!!!!!!!_______"
65+
)
66+
else:
67+
logger.warning(
68+
f"Received unexpected message: {decoded_message}"
69+
)
70+
except (json.JSONDecodeError, UnicodeError) as e:
71+
logger.error("Could not process received message", e)
72+
else:
73+
logger.warning(f"No response from {cube_id} within the time limit.")
74+
75+
# --- 3. Wait before contacting the next satellite ---
76+
logger.debug("Waiting 5 seconds before contacting next satellite.")
77+
sleep_helper.safe_sleep(5)
78+
79+
80+
def send_leaderboard_power_loop(logger, uhf_packet_manager, sleep_helper, cube_ids=["Listener1", "Listener2", "Listener3"]):
81+
message: dict[str, object] = dict()
82+
for cube_id in cube_ids:
83+
# --- 1. Send a ping to a single cubesat ---
84+
logger.info(f"Pinging {cube_id}...")
85+
message["current_time"] = time.monotonic()
86+
message["cube_id"] = cube_id
87+
message["command"] = SENDLEADERBOARD
88+
encoded_message = json.dumps(message, separators=(",", ":")).encode("utf-8")
89+
if not uhf_packet_manager.send(encoded_message):
90+
logger.warning(f"Failed to send ping to {cube_id}")
91+
sleep_helper.safe_sleep(1) # Wait a moment before trying the next one
92+
continue
93+
# --- 2. Listen for an immediate pong response ---
94+
logger.info(f"Listening for pong from {cube_id} for 10 seconds.")
95+
received_message = uhf_packet_manager.listen(10)
96+
if received_message:
97+
try:
98+
decoded_message = json.loads(received_message.decode("utf-8"))
99+
sender_id = decoded_message.get("cube_id")
100+
command = decoded_message.get("command")
101+
if command == "pong" and sender_id == cube_id:
102+
logger.info(
103+
f"_______!!!!!!!!!!Success! Received pong for me from {sender_id}.!!!!!!!!!!!!_______"
104+
)
105+
else:
106+
logger.warning(
107+
f"Received unexpected message: {decoded_message}"
108+
)
109+
except (json.JSONDecodeError, UnicodeError) as e:
110+
logger.error("Could not process received message", e)
111+
else:
112+
logger.warning(f"No response from {cube_id} within the time limit.")
113+
# --- 3. Wait before contacting the next satellite ---
114+
logger.debug("Waiting 5 seconds before contacting next satellite.")
115+
sleep_helper.safe_sleep(5)
116+
117+
118+
def listener_nominal_power_loop(logger, uhf_packet_manager, sleep_helper, my_cubesat_id=CUBSATID):
119+
120+
received_message: bytes | None = uhf_packet_manager.listen(5)
121+
122+
if received_message:
123+
try:
124+
decoded_message = json.loads(received_message.decode("utf-8"))
125+
logger.info(f"Received message: {decoded_message}")
126+
127+
cubesat_id = decoded_message.get("cube_id")
128+
if cubesat_id == my_cubesat_id:
129+
command = decoded_message.get("command")
130+
if command == PING:
131+
logger.info(
132+
f"_______!!!!!!!!!! Received ping from {cubesat_id} !!!!!!!!!!!!_______"
133+
)
134+
response_message = {
135+
"current_time": time.monotonic(),
136+
"cube_id": my_cubesat_id,
137+
"command": "pong",
138+
}
139+
encoded_response = json.dumps(
140+
response_message, separators=(",", ":")
141+
).encode("utf-8")
142+
sleep_helper.safe_sleep(1)
143+
uhf_packet_manager.send(encoded_response)
144+
145+
elif command == SENDLEADERBOARD:
146+
send_leaderboard(sleep_helper, uhf_packet_manager)
147+
elif command == UPDATE_LEADERBOARD:
148+
update_leaderboard(decoded_message.get("name"))
149+
except (json.JSONDecodeError, UnicodeError) as e:
150+
logger.error("Failed to decode message", e)
151+
152+
153+
154+
#TO DO: turn this into a real test for our flash memory
155+
def test_sd():
156+
print(os.listdir())
157+
print("___________")
158+
os.mkdir('sd/new_folder')
159+
print(os.listdir('sd'))
160+
print("_______________")
161+
with open('boot_out.txt', 'r') as file:
162+
print(file.read())
163+
164+
def update_leaderboard(name):
165+
with open('sd/leaderboard.json', 'r') as file:
166+
current_leaderboard = json.load(file)
167+
if name not in current_leaderboard:
168+
current_leaderboard[name] = 1
169+
else:
170+
current_leaderboard[name] = current_leaderboard[name] + 1
171+
with open('sd/leaderboard.json', 'w') as file:
172+
json.dump(current_leaderboard, file)
173+
174+
175+
def display_leaderboard():
176+
print("LEADERBOARD:")
177+
with open('sd/leaderboard.json', 'r') as file:
178+
current_leaderboard = json.load(file)
179+
180+
sorted_leaderboard = sorted(current_leaderboard.items(), key=lambda kv: (-kv[1], kv[0]))
181+
i = 0
182+
for v in sorted_leaderboard:
183+
i+=1
184+
print(str(i) + ". " + v[0] + " : " + str(v[1]))
185+
186+
def send_leaderboard(sleep_helper, uhf_packet_manager, my_cubesat_id=CUBSATID):
187+
with open('sd/leaderboard.json', 'r') as file:
188+
current_leaderboard = json.load(file)
189+
message = {}
190+
encoded_message = json.dumps(message, separators=(",", ":")).encode("utf-8")
191+
response_message = {
192+
"current_time": time.monotonic(),
193+
"cube_id": my_cubesat_id,
194+
"command": "pong",
195+
"leaderboard": current_leaderboard,
196+
}
197+
encoded_response = json.dumps(response_message, separators=(",", ":")).encode("utf-8")
198+
print(encoded_response)
199+
sleep_helper.safe_sleep(1)
200+
uhf_packet_manager.send(encoded_response)
201+
#Clear all the old values
202+
with open('sd/leaderboard.json', 'w') as file:
203+
file.write("{}")
204+
205+

0 commit comments

Comments
 (0)