Skip to content

Configuration

Every tunable value lives in one place: the CONFIG class in C_config.py. There's no need to understand the whole program's architecture — editing this one file covers most of the behavior.

Common Settings

What to adjust Which variable to change Default Notes
Default COM Port to connect to COM_PORT "COM3" the UI dropdown can still override it, without affecting the saved setting
Baud rate BAUD_RATE 115200 must match the hardware side
Serial read timeout READ_TIMEOUT 1.0 (seconds) prevents the program from blocking forever waiting for data
Flask listen port FLASK_PORT 5000 in --no-window mode, the browser connects to http://127.0.0.1:<this port>/
UI update rate UI_UPDATE_MS 1000 (ms) also the interval Demo mode uses to generate simulated packets
Chart history length PLOT_HISTORY 200 only affects how much data is kept in memory for plotting, not the full CSV record
CSV output filename CSV_PATH "adcs_data.csv" Export CSV in the UI can also save to a new path anytime
Default Replay speed REPLAY_INTERVAL 0.5 (seconds) the Speed (s) field in the UI can override it live, even during playback
Window size / title WINDOW_WIDTH / WINDOW_HEIGHT / WINDOW_TITLE 1400 / 900 only takes effect in native window mode (pywebview)
Default packet format TM_FORMAT "auto" auto-detected from the packet's actual length; can also be changed to a fixed format string

After editing C_config.py and saving, restarting the program is enough — no other file needs to change.

Time-Series Chart Colors

Each sensor category's (tab's) color also lives in C_config.py, adjustable via HEX color codes:

Variable Category Default color
COLOR_DEMO Demo format #4FC3F7 (light blue)
COLOR_GYRO Gyro #4FC3F7 (light blue)
COLOR_SUN Sun Sensor #FFD54F (yellow)
COLOR_EARTH Earth Sensor #90A4AE (gray)
COLOR_MGM Magnetometer #F48FB1 (pink)
COLOR_IMTQ iMTQ #CE93D8 (purple)
COLOR_RW Reaction Wheel #A5D6A7 (green)
COLOR_NAV NAV/ACS #FF8A65 (orange)
COLOR_GPS GPS #80CBC4 (teal)

Hook Up Your Own Hardware: Editing Packet Fields

This software ships with a generic demo format (13-byte / 9-byte), letting the program run without any hardware while also serving as a template for writing your own format.

To switch to your own packet format, only the C_packet_def.py file needs editing — no changes to the parser, routes, frontend, or any other code. The parser, CSV columns, API, and the UI's parameter list and format dropdown are all generated dynamically from this file.

Each field looks like this:

_field("demo_temperature",  # field identifier, also becomes the CSV column name
       2,                   # byte position relative to the start of its block
       2,                   # how many bytes it occupies
       "little",            # "little" or "big"
       True,                # signed / unsigned integer
       "°C",                # unit (shown in the UI)
       "Demo",              # which Tab it's shown under in the UI
       "Temperature",       # the name shown in the UI
       formula=lambda b, o: struct.unpack_from('<h', b, o)[0] * 0.01)
  • When formula is None, the UI shows the raw integer value directly (decoded per endian/signed). Handy while a formula hasn't been confirmed yet — check the raw value first, then add the conversion.
  • formula's signature is always (b, o): b is the full packet's bytearray, o is this field's absolute byte position. o is filled in automatically at assembly time — never hardcode a number in the formula.

Common formula patterns:

formula=lambda b, o: struct.unpack_from('<h', b, o)[0] * 0.01   # signed 16-bit x a coefficient
formula=lambda b, o: struct.unpack_from('<H', b, o)[0] * 0.001  # unsigned 16-bit x a coefficient
formula=lambda b, o: struct.unpack_from('<I', b, o)[0]          # unsigned 32-bit
formula=lambda b, o: struct.unpack_from('<f', b, o)[0]          # float32
formula=lambda b, o: b[o]                                       # a single byte (bit flags)

Once a set of fields is defined, place it at an absolute position with _place(block, base) to form a format, then register it in PACKET_DEFS ({packet length: field table}). Once registered, the [TM v] menu in the UI automatically gains an option for this format — no frontend code changes needed.

A field's Tab category

A field's group decides which Tab it's shown under. The available categories are listed in C_config.py's GROUP_COLORS and C_template.py's GROUPS; add a new category in both places together.

The C_packet_def.py file itself has thorough comments explaining what every block does — it's worth opening directly and editing alongside it.