Skip to content

Core Module API

auth_manager.py

File: core\auth_manager.py

class AuthManager (line 11)

Manages user authentication and local account storage. Passwords are hashed with PBKDF2-HMAC-SHA256 and salt.

Public Methods: * get_users_path(cls) — No docstring * load_users(cls) — No docstring * save_users(cls, users: Dict[str, dict]) — No docstring * initialize(cls) — Ensure default admin user exists if no users. * register(cls, username, password, role, users_dict) — Register a new user. * login(cls, username, password) — Attempt login. Returns True if successful. * logout(cls) — No docstring * get_current_user(cls) — No docstring * is_admin(cls) — No docstring

config_manager.py

File: core\config_manager.py

class ConfigManager (line 5)

Centralized configuration management. Stores settings in AppData/settings.json.

Public Methods: * initialize(cls) — Load settings from disk. * get(cls, key, default) — Get a setting value. * set(cls, key, value) — Set a setting value and save. * save(cls) — Save settings to disk. * get_data_path(cls) — Return the user-configured data path, or default AppData path.

data_parser.py

File: core\data_parser.py

class DataParser (line 27)

Parses incoming serial data (Compact Protocol).

Handles both binary packets (V3.13) and text-based responses. Parsed data is pushed to a thread-safe queue for consumption by the UI.

Constructor: DataParser(data_queue: queue.Queue)

Initialize the parser.

Args: data_queue: Thread-safe queue for parsed data messages.

Public Methods: * start_time() — Backward compatibility for start_time attribute. * start_time(value: Optional[int]) — No docstring * packet_pattern() — Backward compatibility for packet_pattern attribute. * parse_binary_packet(raw_data: bytes) — Parse a 44-byte binary packet: [AA D0][Payload 41][CS 1]

Args: raw_data: Raw 44-byte packet dat * parse_line(line: str) — Parse a raw line from serial.

Args: line: Text line from serial port

Returns: True if * parse_json_response(line: str, extra_data: Any) — Compatibility shim for ExperimentManager. * reset() — Reset parser state. * get_column_names() — Get current column headers. * update_headers(header_str: str) — Update headers from CSV string.

Args: header_str: Comma-separated header string

Returns:

experiment_manager.py

File: core\experiment_manager.py

class ExperimentManager (line 19)

Orchestrates the experiment: - Runs sweeps (SET_DAC -> Wait -> GET_SAMPLE) - Runs stability tests (SET_DAC -> Sample over time) - Polls status (GET_STATUS) when idle

Constructor: ExperimentManager(serial_controller)

Public Methods: * register_pong() — Called by GUI when [ACK:PONG] is received. * set_sensor(on: bool) — Send CMD_SET_SENSOR to hardware and update tracked state. * set_fan(on: bool) — Send CMD_SET_FAN to hardware and update tracked state. * start_monitoring() — Starts the background monitoring thread. * stop_monitoring() — Stops the monitoring thread. * start_sweep(start_val, end_val, step_val, samples_per_step) — Starts the sweep in a separate thread. * start_stability_test(intensity, duration, interval_ms) — Starts the stability test in a separate thread.

export_manager.py

File: core\export_manager.py

class ExportManager (line 13)

Public Methods: * export_to_csv(experiment_data: Dict[str, Any], filepath: Path) — Export a single experiment to CSV. * export_batch_csv(experiments: List[Dict[str, Any]], output_dir: Path) — Export multiple experiments as individual CSV files in the output directory. * export_combined_csv(experiments: List[Dict[str, Any]], filepath: Path) — Export multiple experiments into a single combined CSV file. Adds an 'Experiment ID' and 'Label' col * export_full_history_archive(history: Dict[str, Any], filepath: Path) — Create a ZIP archive containing all experiments as JSON files and a summary CSV.

firmware_manager.py

File: core\firmware_manager.py

class FirmwareManager (line 15)

Manage Arduino firmware compilation and upload.

Constructor: FirmwareManager()

Public Methods: * is_cli_available() — Check if Arduino CLI is available. * get_cli_version() — Get Arduino CLI version. * get_embedded_firmware_path() — Get path to embedded firmware file. * get_firmware_version_from_file(path: Path) — Extract firmware version from .ino file. * list_connected_boards() — List connected Arduino boards. * compile_firmware(firmware_path: Path) — Compile firmware without uploading.

Returns: (success: bool, message: str) * upload_firmware(port: str, firmware_path: Path) — Compile and upload firmware to device.

Args: port: Serial port (e.g., "COM3") firmware_path * verify_device_version(serial_controller) — Check device firmware version and compare to embedded.

Returns: (device_version, needs_update)

Module Functions: * get_firmware_manager() — No docstring

history_manager.py

File: core\history_manager.py

Module Functions: * load_history() — Loads experiment history from the JSON file in AppData. Returns an empty dictionary if the file does * save_history(history: Dict[str, Any]) — Saves the entire experiment history to the JSON file. Returns True on success. * add_experiment(history: Dict[str, Any], exp_id: str, data: Dict[str, Any]) — Adds a single experiment to the history and saves it. * delete_experiment(history: Dict[str, Any], exp_id: str) — Deletes a single experiment from the history and saves it. * delete_experiments(history: Dict[str, Any], exp_ids: list[str]) — Deletes multiple experiments from the history and saves it. * move_experiments(history: Dict[str, Any], exp_ids: list[str], target_folder: str) — Moves multiple experiments to a target folder. * archive_experiments(history: Dict[str, Any], exp_ids: list[str], archive: bool) — Sets the archived status for multiple experiments. * get_folders(history: Dict[str, Any]) — Returns a list of unique folders found in the history. * get_experiment(history: Dict[str, Any], exp_id: str) — Gets a single experiment by ID. * list_experiments(history: Dict[str, Any], sort_by, reverse, filter_folder) — Returns list of experiment IDs, optionally filtered and sorted. * migrate_old_history(old_path: Path) — Migrate history from old local path to AppData. Call this once at app startup.

mock_serial.py

File: core\mock_serial.py

class MockSerial (line 31)

Simulates the Acetone Motherboard V3.13 Firmware.

Provides synthetic data, responds to binary commands, and handles payloads. Used for testing and development without real hardware.

Constructor: MockSerial()

Public Methods: * inject_error(code: int) — Forces the next command to return an error. * set_noise_level(level: float) — Set noise multiplier for sensor readings. * simulate_disconnect() — Simulate a disconnection. * set_sim_battery(volts: float) — Set simulated battery voltage. * set_sim_temp(temp: float) — Set simulated LED temperature. * set_sim_sensor(volts: float) — Set simulated sensor voltage. * close() — Close the mock connection. * flush() — Flush buffers (no-op for mock). * reset_input_buffer() — Clear input buffer and reset state machine. * in_waiting() — Return number of bytes waiting. * read(size: int) — Read bytes from the mock output buffer. * write(data: bytes) — Process incoming data (commands from host).

profile_manager.py

File: core\profile_manager.py

class ProfileManager (line 5)

Manages loading, saving, and deleting experiment profiles. Profiles are stored in AppData via StorageManager. Format: {"Profile Name": {"start": 0, "end": 100, "step": 10}}

Constructor: ProfileManager(filepath)

Public Methods: * load_profiles() — No docstring * save_profile(name, start, end, step) — No docstring * delete_profile(name) — No docstring * get_profile_names() — No docstring * get_profile(name) — No docstring

serial_controller.py

File: core\serial_controller.py

class SerialController (line 44)

Manages serial connection and synchronous command-response communication.

Thread-safe implementation for sending binary protocol commands and receiving responses from the Acetone Motherboard.

Constructor: SerialController(data_queue: Optional[queue.Queue], mock_mode: bool)

Initialize the serial controller.

Args: data_queue: Optional queue for parsed data messages. If None, a new queue is created. mock_mode: If True, enables mock serial ports for testing without hardware. App starts disconnected; user manually connects to MOCK_PORT.

Public Methods: * find_ports() — Return list of available serial ports. * is_connected() — Check if serial connection is open. * is_mock() — Check if using mock serial connection. * connect(port: str) — Connect to the specified serial port.

Args: port: Serial port name (e.g., 'COM3', 'MOCK_PORT', * disconnect() — Disconnect from the serial port. * check_handshake() — Perform V3.2 Handshake: Send 0xAA -> Expect 0xBB (RESP_READY).

Returns: True if handshake succe * send_instruction(opcode: int, payload: bytes, timeout: float, retries: int) — Send a binary instruction and wait for response.

Protocol: [0xAA] [Opcode] [Payload] -> [0xAA] [Res * read_binary(size: int, timeout: float) — Read a fixed number of bytes from the serial port.

Args: size: Number of bytes to read time

storage.py

File: core\storage.py

class StorageManager (line 13)

Manages all persistent storage in %APPDATA%/JameedLab/.

Public Methods: * get_app_dir(cls) — Get the main application data directory. * get_logs_dir(cls) — Get the logs directory. * get_data_dir(cls) — Get the directory where user data (experiments, profiles) is stored. * get_experiments_dir(cls) — Get the experiments data directory. * get_history_path(cls) — Get the path to experiments history file. * get_profiles_path(cls) — Get the path to user profiles file. * get_settings_path(cls) — Get the path to application settings file. * get_firmware_cache_dir(cls) — Get the firmware cache directory. * load_json(cls, path: Path, default: dict | list) — Safely load JSON file with fallback to default. * save_json(cls, path: Path, data: dict | list) — Safely save JSON file with backup. * migrate_from_local(cls, local_history: Path, local_profiles: Path) — Migrate data from old local paths to AppData.

Module Functions: * get_app_dir() — No docstring * get_logs_dir() — No docstring * get_history_path() — No docstring

theme_builder.py

File: core\theme_builder.py

class MaterialThemeBuilder (line 7)

Generates a Material 3 color scheme from a single seed color. Uses HSL adjustments to approximate tonal tonal palettes.

Public Methods: * hex_to_rgb(hex_color) — No docstring * rgb_to_hex(r, g, b) — No docstring * get_tone(h, s, l_target) — Get a color with specific lightness (tone 0-100). * generate_palette(cls, seed_hex) — Generate full light and dark schemes from seed.

theme_manager.py

File: core\theme_manager.py

class ThemeManager (line 9)

Public Methods: * set_theme(cls, theme_name: str) — Set the application theme and notify listeners. * add_listener(cls, callback: Callable[[str], None]) — Register a callback function to be called on theme change. * remove_listener(cls, callback: Callable[[str], None]) — Unregister a callback function. * get_current_theme(cls) — Get the current theme name. * get_color(cls, color_tuple: Tuple[str, str]) — Get the correct color code from a (Light, Dark) tuple based on current theme. Useful for non-ctk wid