Skip to content

Replacing ublox.js with updated code in assist-now.js; #2551

Open
DHaacke wants to merge 2 commits intoiNavFlight:maintenance-9.xfrom
DHaacke:dhaacke-assist-now
Open

Replacing ublox.js with updated code in assist-now.js; #2551
DHaacke wants to merge 2 commits intoiNavFlight:maintenance-9.xfrom
DHaacke:dhaacke-assist-now

Conversation

@DHaacke
Copy link

@DHaacke DHaacke commented Feb 3, 2026

User description

Replacing ublox.js with updated code in assist-now.js; Provides standalone functionality and (coming soon) Configurator functionality.


PR Type

Enhancement, New Feature


Description

  • Port of u-blox AssistNow Python example to Node.js with standalone and Configurator support

  • Implements Zero Touch Provisioning (ZTP) for secure orbit data download and injection

  • Provides UBX message handling with serial communication and ACK/NAK validation

  • Supports both predictive and live orbit modes with GNSS receiver cold-reset and TTFF measurement


Diagram Walkthrough

flowchart LR
  A["Serial Port"] -->|UBX Messages| B["UBXReceiver Class"]
  B -->|Poll Commands| C["GNSS Device"]
  C -->|Responses| B
  B -->|UNIQID + MON-VER| D["ZTP Endpoint"]
  D -->|Chipcode| E["AssistNow Service"]
  E -->|MGA Data| B
  B -->|MGA Messages| C
  C -->|MGA-ACKs| B
  B -->|Cold Reset| C
  C -->|NAV-STATUS| B
  B -->|TTFF Result| F["Console Output"]
Loading

File Walkthrough

Relevant files
New feature
assist-now.js
Complete Node.js port of u-blox AssistNow with ZTP             

js/ublox/assist-now.js

  • New 566-line Node.js implementation replacing ublox.js with full
    AssistNow functionality
  • UBXReceiver class handles serial I/O, message validation, checksum
    verification, and ACK waiting
  • Implements ZTP authentication flow to obtain chipcode for AssistNow
    data download
  • Supports standalone CLI mode with argument parsing for port, baud
    rate, ZTP token, and orbit mode selection
  • Includes MGA message injection with retry logic and TTFF measurement
    after cold-reset
+566/-0 

…ty and (coming soon) Configurator functionality.
@github-actions
Copy link

github-actions bot commented Feb 3, 2026

Branch Targeting Suggestion

You've targeted the master branch with this PR. Please consider if a version branch might be more appropriate:

  • maintenance-9.x - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.

  • maintenance-10.x - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x

If master is the correct target for this change, no action is needed.


This is an automated suggestion to help route contributions to the appropriate branch.

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Feb 3, 2026

PR Compliance Guide 🔍

All compliance sections have been disabled in the configurations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High-level Suggestion

Replace the inefficient setInterval polling in the UBXReceiver class with a more robust, event-driven approach for handling asynchronous responses. This can be achieved using an event emitter or by resolving pending promises directly from the _onData method. [High-level, importance: 8]

Solution Walkthrough:

Before:

class UBXReceiver {
  async sendAndWait(msg, prefix, timeoutMs) {
    this.expectedPrefix = prefix;
    this.messageQueue = [];
    await this.send(msg);

    return new Promise((resolve) => {
      const interval = setInterval(() => {
        if (this.messageQueue.length > 0) {
          clearInterval(interval);
          resolve(this.messageQueue.shift());
        }
        // ... timeout logic
      }, 50);
    });
  }
}

After:

class UBXReceiver {
  constructor() {
    // ...
    this.pendingRequests = new Map(); // or a single pending promise
  }

  _onData(chunk) {
    // ... parse message `msg`
    // Find a matching pending request and resolve it
    const resolver = this.findAndRemoveMatchingResolver(msg);
    if (resolver) {
      resolver(msg);
    }
  }

  async sendAndWait(msg, prefix, timeoutMs) {
    return new Promise((resolve, reject) => {
      // Store resolver to be called from _onData
      this.addPendingResolver(prefix, resolve);
      this.send(msg);
      // ... timeout logic that calls reject
    });
  }
}

@DHaacke
Copy link
Author

DHaacke commented Feb 3, 2026

Quick note: The older ublox.js code is still there and active. I have only added the new file assist-now.js. The new file can run standalone in Node (see instructions at top of code). I wanted to get the code pushed before I start the arduous task of integrating it with the Configurator UI which I plan on starting on in the coming days. Thanks, and holler if you have questions or concerns. -Doug

@DHaacke DHaacke closed this Feb 3, 2026
@DHaacke
Copy link
Author

DHaacke commented Feb 3, 2026

Inadvertently closed. Reopening....

@DHaacke DHaacke reopened this Feb 3, 2026
@qodo-code-review
Copy link
Contributor

PR Compliance Guide 🔍

All compliance sections have been disabled in the configurations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High-level Suggestion

Refactor assist-now.js to use the application's existing serial connection management instead of creating its own. This avoids hardware access conflicts and allows for proper integration into the Configurator. [High-level, importance: 9]

Solution Walkthrough:

Before:

// assist-now.js
import { SerialPort } from "serialport";

class UBXReceiver {
  constructor(portPath, baudRate) {
    // Creates a new, independent serial port connection.
    this.port = new SerialPort({ path: portPath, baudRate, autoOpen: true });
    this.port.on("data", (chunk) => this._onData(chunk));
    // ...
  }
  // ...
}

async function runAssistNow(args) {
  // Instantiates the receiver with a port path string.
  const gnss = new UBXReceiver(args.port, args.baudRate);
  // ... uses gnss to communicate
}

After:

// assist-now.js

class UBXReceiver {
  constructor(connection) { // Expects an existing connection object
    // Reuses the application's main serial connection.
    this.port = connection;
    this.port.on("data", (chunk) => this._onData(chunk));
    // ...
  }
  // ...
}

async function runAssistNow(args, connection) { // Pass connection from the main app
  // Instantiates the receiver with the existing connection.
  const gnss = new UBXReceiver(connection);
  // ... uses gnss to communicate
}

@sensei-hacker sensei-hacker added this to the 9.1 milestone Feb 8, 2026
@sensei-hacker sensei-hacker changed the base branch from master to maintenance-9.x February 8, 2026 21:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants