Skip to content

JameedLabs Non-Invasive Glucose Monitoring Platform

Comprehensive Developer Technical Reference & Codebase API Guide

This Developer Technical Reference is a comprehensive guide to the JameedLabs software architecture, low-level serial communication protocols, and physical data schemas.

It is designed for systems engineers, software developers, and embedded developers tasked with maintaining, extending, or integrating the JameedLabs desktop application with new sensor hardware.


1. System Architecture, Threading Model, & Component Mapping

The JameedLabs application is built on a multi-threaded architecture designed to guarantee the UI remains highly responsive while critical, high-frequency IO operations run safely in the background.

Architecture Context: Heartbeat Indicator - Connected

The JameedLabs desktop application is built on a decoupled, asynchronous, event-driven architecture designed to isolate the high-speed serial I/O pipeline from the CustomTkinter user interface thread.

┌────────────────────────────────────────────────────────────────────────┐
│                              PRESENTATION LAYER                        │
│                     [CustomTkinter App Window / Views]                 │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │ (Non-blocking Queued Events)
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                              BUSINESS LAYER                            │
│                     [ExperimentManager & HistoryManager]               │
└───────────────┬────────────────────────────────────────┬───────────────┘
                │ (Command Instructions)                 ▲ (Parsed Telemetry)
                ▼                                        │
┌────────────────────────────────────────────────────────┴───────────────┐
│                              SERIAL I/O LAYER                          │
│        [SerialController] ──► [DataParser] ──► Thread-Safe Queue       │
└───────────────────────┬────────────────────────────────────────────────┘
                        │ (V3.2 Binary Packets over UART)
                        ▼
┌────────────────────────────────────────────────────────────────────────┐
│                              HARDWARE LAYER                            │
│                  [Arduino / Acetone Motherboard Firmware]              │
└────────────────────────────────────────────────────────────────────────┘

The Multi-Threaded Operational Architecture

To ensure the graphical interface remains responsive and lag-free during high-frequency data collection sweeps ($10\text{Hz}$ sample rate), JameedLabs implements a multi-threaded operational architecture:

┌──────────────────────────────────────────────────────────────────────────────┐
│                                MAIN UI THREAD                                │
│  - Renders CustomTkinter Widgets                                             │
│  - Refreshes Matplotlib Canvas @ 30 FPS                                      │
│  - Reads from Queue (data_queue.get_nowait())                                │
└──────────────────────────────────────┬───────────────────────────────────────┘
                                       │ (Thread-Safe Event Queue)
                                       ▲
┌──────────────────────────────────────┴───────────────────────────────────────┐
│                           BACKGROUND WORKER THREADS                          │
│                                                                              │
│  1. KEEP-ALIVE MONITOR LOOP THREAD:                                          │
│     - Sends CMD_PING (0x10) every 2.0s                                       │
│     - Monitors last_pong_time; triggers heartbeat timeouts                   │
│                                                                              │
│  2. EXPERIMENT RUNNER LOOP THREAD:                                           │
│     - Drives experiment sweeps (CMD_SET_DAC -> Settling -> CMD_GET_SAMPLE)   │
│     - Performs real-time statistical multi-sample analysis                   │
└──────────────────────────────────────────────────────────────────────────────┘
  1. Main UI Thread: Handles the rendering of all CustomTkinter frames, buttons, and custom widgets. It manages the Matplotlib graph updates, running a non-blocking check on a thread-safe Queue.Queue (polling data_queue.get_nowait() every 50ms) to consume incoming sensor events.
  2. Keep-Alive Monitor Loop: A dedicated background thread running in the ExperimentManager loop. It pings the device every 2 seconds with CMD_PING (0x10) to verify the serial link's responsiveness. If the device fails to respond within 6.5 seconds, this thread triggers a heartbeat timeout, safely disconnects the port, and updates the UI.
  3. Experiment Runner Loop: Initiated when a researcher clicks Start Sweep. It takes control of serial communication, running a timed sequence (setting LED current via CMD_SET_DAC, waiting for settling time, requesting data via CMD_GET_SAMPLE, and feeding the parsed telemetry back to the main UI thread).

Module & Class Responsibilities

  • main.py (Application Bootstrapper):
  • Initializes configuration file parsers (ConfigManager).
  • Loads custom TTF font packages (Material Icons) to ensure cross-platform icon rendering.
  • Overrides system themes via ThemeManager to force Light mode for high legibility under clinical lighting.
  • Handles splash screen timeouts, skips authentication in mock/simulation mode, and launches the main App window.
  • core/serial_controller.py (Low-Level Communication Link):
  • Uses pyserial (serial.Serial) to establish UART connections at 115200 baud.
  • Extends port discovery using native Windows serial enumeration, and injects mock COM ports (MOCK_PORT, COM5) for simulation testing.
  • Encapsulates communication blocks inside a reentrant lock (threading.Lock), ensuring commands sent from different threads do not corrupt the serial buffer.
  • core/data_parser.py (Binary Packet Parser):
  • Extracts raw 44-byte binary packets from the serial buffer.
  • Validates sum-based checksum bytes to ensure data integrity.
  • Decodes Little-Endian packed byte arrays into high-precision floating-point values.
  • Translates raw error codes (0x05, 0x07, etc.) into human-readable strings.
  • core/experiment_manager.py (Core Business Logic):
  • Implements the experiment threads for Sweep and Stability modes.
  • Manages safety checks, auto-cooling cooling loops, and sensor warm-up sequences.
  • Integrates statistics calculations (such as mean and standard deviation) for multi-sample sweeps. Technical Debt Note: Inline code comments (lines ~240-247) indicate legacy workarounds for _get_and_log_sample() return types; future developers should refactor this sampling pipeline to ensure robust data aggregation without strict column-index assumptions.
  • core/mock_serial.py (Chamber Simulator):
  • Simulates physical serial interfaces.
  • Generates synthetic sensor voltage curves with adjustable noise multipliers.
  • Emulates firmware protocols, allowing developers to inject simulated temperature and optical failures.

2. V3.2 Serial Communication Protocol Specification

The JameedLabs platform uses a customized, high-reliability serial protocol designed to operate over physical serial connections (115200 Baud, 8 Data Bits, 1 Stop Bit, No Parity).

Architectural Note: While the primary binary protocol is designated as V3.2, the data parser module (data_parser.py) and simulator (mock_serial.py) also provide robust regex-based support for legacy V3.13 text commands (e.g., [DT], PING, GET_STATUS). This dual text/binary protocol support is maintained architecturally for backward compatibility with older verify_protocol.py calibration scripts.

The Protocol Lifecycle

HOST (PC)                                                  DEVICE (Arduino)
  │                                                              │
  ├────── [0xAA] (CMD_READY Handshake) ─────────────────────────►│
  │◄───── [0xBB] (RESP_READY Acknowledgment) ────────────────────┤ (Link Active)
  │                                                              │
  ├────── [0x10] (CMD_PING Heartbeat) ──────────────────────────►│
  │◄───── [0xA0] (ACK_PONG Acknowledgment) ──────────────────────┤ (Keep-Alive)
  │                                                              │
  ├────── [0x20][Payload: 2-Byte DAC] (CMD_SET_DAC) ────────────►│
  │◄───── [0xA2] (ACK_DAC Acknowledgment) ───────────────────────┤ (Set LED Intensity)
  │                                                              │
  ├────── [0x40] (CMD_GET_SAMPLE) ──────────────────────────────►│
  │◄───── [0xD0][Payload: 41-Byte Data][1-Byte CS] (RESP_DATA) ──┤ (High-Freq Telemetry)

Detailed Command & Response Layouts

  • Command Sequence: Host sends 0xAA (CMD_READY).
  • Expected Response: Device replies with 0xBB (RESP_READY).
  • Timeout Rules: If RESP_READY is not received within 1000ms, the host flags a connection failure.

2. Keep-Alive Ping

  • Command Sequence: Host sends 0x10 (CMD_PING).
  • Expected Response: Device replies with 0xA0 (ACK_PONG).
  • Interval: Sent every 2000ms. A timeout is triggered if no response is received within 6.5s.

3. Fetch Device Information (CMD_GET_INFO)

  • Command Sequence: Host sends 0x12.
  • Device Response: Device replies with 0xB0 followed by a 32-byte payload:
  • Firmware Version (Bytes 0–15): Null-terminated ASCII string (e.g., V3.13-Acetone\x00).
  • Board Revision (Bytes 16–19): uint32 revision number (e.g., 0x00000002).
  • Serial Number (Bytes 20–31): 12-byte alphanumeric serial string.

4. Configure LED Intensity (CMD_SET_DAC)

  • Command Sequence: Host sends 0x20 followed by a 2-byte payload:
  • DAC Value (Bytes 0–1): 16-bit unsigned integer (MSB first, representing $0 - 4095$ counts).
  • Expected Response: Device replies with 0xA2 (ACK_DAC) once the DAC output is set.

3. High-Frequency Binary Packet Formats

Data requested via CMD_GET_SAMPLE (0x40) is returned as a 44-byte binary packet.

Telemetry Packet Structure

The packet consists of a 2-byte Sync Header (0xAA 0xD0), a 41-byte Payload containing 10 fields packed in Little-Endian format, and a 1-byte Checksum:

 0      1      2                                             42     43
┌──────┬──────┬─────────────────────────────────────────────┬──────┐
│ 0xAA │ 0xD0 │              41-Byte Data Payload           │  CS  │
└──────┴──────┴─────────────────────────────────────────────┴──────┘

Payload Field Mapping

The 41-byte payload is structured as follows:

Field Index Data Type Size (Bytes) Label / Variable Physical Unit Description
0 uint32 (I) 4 Time milliseconds Relative time elapsed since boot.
1 float (f) 4 Target % Target LED intensity configured.
2 float (f) 4 UVSensor mV Raw silicon carbide sensor voltage.
3 float (f) 4 Ambient Temp °C Ambient room temperature inside casing.
4 float (f) 4 UVLED I mA Drive current delivered to the UV LED.
5 float (f) 4 UVLED V Volts Bus voltage across the excitation LED.
6 float (f) 4 UVLED P mW Calculated electrical power of the LED.
7 float (f) 4 UVSensor I mA Output leakage current of the SiC sensor.
8 float (f) 4 LedTemp °C Thermal junction temperature of the UV LED.
9 float (f) 4 SensV Volts Analog output voltage after transimpedance.
10 uint8 (B) 1 Fan state (0/1) Status of the active cooling fan.

IEEE-754 Single-Precision Floats

All sensor metrics, including temperatures and voltages, are transmitted as IEEE-754 single-precision floating-point numbers (4 bytes per field). The host software uses Python's standard struct library to unpack these bytes:

import struct
# Little-Endian: uint32 (I), 9 floats (9f), uint8 (B)
BINARY_STRUCT = struct.Struct('<I9fB') # 41-byte binary block

Checksum Validation Formula

The final byte (byte 43) is a simple checksum calculated by summing the 41 payload bytes: $$\text{Checksum} = \left( \sum_{i=2}^{42} \text{Byte}_i \right) \ \& \ \text{0xFF}$$ Before unpacking, the DataParser verifies this checksum:

payload = raw_data[2:43]
checksum_received = raw_data[43]
checksum_calculated = sum(payload) & 0xFF

if checksum_calculated != checksum_received:
    raise ValueError("Binary packet checksum mismatch")


4. Hardware Simulation & Test Framework

To allow continuous development without requiring physical access to the exhalation chamber hardware, the JameedLabs suite includes a complete hardware simulator.

Hardware Diagnostic View: Test Card - Passed State

core/mock_serial.py simulates the V3.13 device firmware, allowing developers to test the software's behavior under various operational and error conditions without physical hardware.

Mock Connection Interface

The MockSerial class implements a duck-typed interface that mimics the API of PySerial (serial.Serial), allowing it to integrate seamlessly with the SerialController:

class MockSerial:
    def __init__(self):
        self.is_open = True
        self.port = "MOCK_PORT"
        self.out_buffer = bytearray()
        self.target_dac = 0
This design allows the SerialController to treat MockSerial just like a physical serial port, making mock connections completely transparent to the rest of the application.

State Machine implementation

The simulator uses a simple parsing state machine to process incoming serial bytes:

def _process_byte(self, byte: int) -> None:
    if self._state == 0:  # WAIT_SYNC
        if byte == CMD_READY: # 0xAA
            self._state = 1
            self.out_buffer.append(RESP_READY) # Reply 0xBB
            self._state = 0 # Reset state
    elif self._state == 1: # WAIT_OPCODE
        self._curr_opcode = byte
        if byte == CMD_GET_SAMPLE: # No payload needed
            self._generate_mock_sample()
            self._state = 0
        elif byte == CMD_SET_DAC:
            self._payload_needed = 2
            self._state = 2 # Transition to wait payload

Advanced Fault Injection

  • Simulating Thermal Errors: Sets the internal simulated temperature above $35^\circ\text{C}$ using the fault injection API to verify that the application triggers the warning states and cooling fan overrides.
  • Optical Saturation Simulation: Drives the simulated photodiode voltage ($V_{\text{sens}}$) to its absolute limit ($10\text{V}$) to verify the software's safety alerts.
  • Battery Low Faults: The mock_serial.py simulator automatically injects a "Battery Low" error (0x08) if the simulated bus voltage drops below 9.0V, allowing developers to test power failure UI handling.

5. Storage Engine & Clinical Database Schema

Because clinical trial data must be immutable and verifiable, the application strictly separates raw data acquisition from processed analytics.

Persistence UI State: Success - Profile Saved

The core/storage.py and history_manager.py modules handle the storage and organization of clinical trial records.

Database Design & Schema

All clinical records are saved in local, transactional JSON files to ensure quick, reliable database operations. The database schema enforces a strict structure for each record:

Trial Record:
├── id: String (Incremental unique identifier)
├── timestamp: String (ISO-8601 formatting: "YYYY-MM-DDTHH:MM:SSZ")
├── patient_id: String (Alphanumeric anonymous Subject ID)
├── mode: String ("sweep" or "stability")
├── calibration_baseline: Float (Raw sensor zeroing reference voltage)
├── metrics: Object
│   ├── calculated_absorbance: Float (Peak absorbance at alveolar plateau)
│   ├── estimated_acetone_ppm: Float (Acetone concentration in ppm)
│   └── blood_glucose_estimate: Float (Estimated blood glucose in mg/dL)
├── columns: Array of Strings (CSV headers matching DataParser output)
├── data_rows: Nested Array of Floats (High-frequency raw data points)
└── annotation: String (Researcher notes and metadata)

ZIP Backup File Structure

When exporting a backup under the History tab, the system packages the database records into a single, compressed ZIP file containing the following structure:

JameedLabs_Backup_2026-06-01.zip
├── manifest.json            # Backup metadata and validation checksums
├── database.json            # The full, transactional JSON database
└── audit_log.txt            # Operational history and import logs


6. Embedded Firmware Protection Systems

The application works in tandem with security systems built into the device firmware to protect the delicate optical components from thermal and electrical stress.

                  ┌────────────────────────────────────────┐
                  │        Incoming LED DAC Command        │
                  └───────────────────┬────────────────────┘
                                      │
                                      ▼
                  ┌────────────────────────────────────────┐
                  │    Hardware Protection Verification    │
                  ├────────────────────────────────────────┤
                  │    Ensure DAC <= SAFETY_DAC_LIMIT      │
                  │    Ensure temp < Temp Threshold        │
                  └───────────────────┬────────────────────┘
                                      ├────────────────────┐
                           (Passes)   │                    │ (Fails)
                                      ▼                    ▼
                  ┌────────────────────────┐  ┌────────────────────────┐
                  │ Drive LED at requested │  │ Clamp LED to safe limit│
                  │ intensity              │  │ / Force Fans to 100%   │
                  └────────────────────────┘  └────────────────────────┘
  • DAC Current Clamping: Deep UV LEDs can burn out if driven with excessive current. The software and device firmware enforce a strict physical limit (SAFETY_DAC_LIMIT = 805). Based on the hardware's 12-bit DAC (0–4095) running against a 5.0V reference, this correlates to $(805 / 4095) \times 5.0\text{V} \approx 0.98\text{V} \approx 1.0\text{V}$. This clamps the analog drive signal to a maximum of 100mA, protecting the excitation source. Future hardware revisions using a 3.3V reference or 16-bit DAC will require recalculating this limit.
  • Thermal Override Loop (Software Risk): While often assumed to be a hardware fail-safe, the $35^\circ\text{C}$ fan override is actually implemented in software within the ExperimentManager loop. The desktop app continually polls the temperature and manually sends CMD_SET_FAN(True) if it hits the warning threshold. Architectural Note: Because this relies on the host PC, if the desktop application lags or crashes, the cooling fan will not engage automatically. This software-hardware coupling should be decoupled in future firmware releases.
  • Critical Shutdown (Missing Fallback): The chamber temperature critical limit is defined as $45^\circ\text{C}$. However, the desktop software's monitoring loop does not act on this limit, assuming the firmware will trigger a hardware shutdown of the LED driver. Currently, the mock_serial.py simulator does not simulate this hardware shutdown, representing a slight divergence between the simulation environment and physical hardware behavior.

Document Summary

This Developer Technical Reference provides the detailed specifications of the JameedLabs platform, mapping its software architecture, serial protocols, binary packet structures, simulators, database schemas, and firmware protection loops.

With the Application System Overview, App User Manual, and Developer Technical Reference completed, the JameedLabs documentation suite is now fully implemented.