tauri-plugin-serialplugin

repository·main·Indexed 41 days ago

https://github.com/s00d/tauri-plugin-serialplugin

A Tauri plugin for serial port access on desktop and Android, providing a complete API for reading, writing, and configuring serial devices. Version 3.0.7 includes support for Android USB host requirements, runtime permissions, and a wide range of USB-to-serial controllers via the android-usb-serial crate.

Tokens
37.9K
Snippets
120
Records
181
Agent score
51%

What's inside tauri-plugin-serialplugin

  1. Use the USB Driver Tester features

    main

    The USB Driver Tester is a standalone Android application designed to verify USB serial drivers on-device. Key features include:

    • List USB Devices: View all attached USB devices along with their probed driver names.
    • Self-test: Executes an in-process fake-transport matrix to simulate various drivers (FTDI, CP21xx, CH34x, PL2303, CDC).
    • Device test: Performs a real test on a physical device by tapping it. This uses the real NusbTransport via the UsbDeviceConnection file descriptor (sequence: probe → open → write/read → close).
    • Share log: Exports a step report via the Android share sheet, which is useful for bug reporting.
  2. Explore serialport-test features and layout

    main

    The serialport-test demo provides several panels for interacting with serial hardware:

    • Status bar: Displays device capabilities, current log level, and Rust get_ports_programmatically status (on desktop).
    • Port picker: Supports live hotplugging via watchAvailablePorts, manual path entry, and managed ports.
    • Terminal: A scrollable log showing RX (Receive), TX (Transmit), URC (Unregistered Context), and system logs.
    • Tools panel: Provides access to:
      • Signals: Control RTS, DTR, CTS, etc.
      • AT script queue: Manage sequences of AT commands.
      • Port config: Configure serial port parameters.
  3. Use AT commands with the native FIFO queue

    main

    For modems and AT-compatible devices, the plugin provides specialized methods that use a native FIFO queue to prevent concurrency errors (like "Exchange already in progress"). These methods handle line-framed AT completion (detecting OK, ERROR, etc.).

    Key Methods

    • sendAt(command): Sends a command and waits for a single structured AtCommandResult response.
    • sendAtPhases(...): Used for multi-phase interactions (e.g., SMS prompts).
    • sendSmsPdu(...): Specifically for sending SMS via PDU.
    • configureAtSession(...): Sets defaults for the AT session, such as expectOk, stopOnError, appendCr, and resultFormat.

    AT Modes

    ModeRX BehaviorBest Use Case
    watch()Streaming events + onUrcGeneral I/O and live Unsolicited Result Codes (URC)
    sendAt()One structured response per commandRequest/response scripts and AT modems

    CMUX Support

    To use multiple logical channels on a single USB port via CMUX, use enableMux() followed by openMuxChannel(dlci). The resulting channel provides its own virtual path.

    // Session defaults
    await port.configureAtSession({ expectOk: true, defaultTimeoutMs: 5000 });
    
    await port.sendAt('AT^SYSCFG?');
    await port.sendAt('ATV0', { resultFormat: 'numeric' });
    await port.sendSmsPdu(pduLength, pduBytes);
    
    // CMUX: second logical channel on same USB port
    await port.enableMux({ command: 'AT+CMUX=0,0,5,31,10,2' });
    const dataPort = await port.openMuxChannel(2);
    await dataPort.sendAt('AT');
  4. Configure SerialPort permissions

    main

    Ensure your Tauri capabilities file (e.g., src-tauri/capabilities/default.json) includes the serialplugin:default permission to allow the frontend to communicate with the plugin.

    {
      "$schema": "../gen/schemas/desktop-schema.json",
      "identifier": "default",
      "description": "Capability for the main window",
      "windows": ["main"],
      "permissions": [
        "core:default",
        "serialplugin:default"
      ]
    }
    // src-tauri/capabilities/default.json
    {
      "$schema": "../gen/schemas/desktop-schema.json",
      "identifier": "default",
      "description": "Capability for the main window",
      "windows": ["main"],
      "permissions": [
        "core:default",
        "serialplugin:default"
      ]
    }
  5. Run JVM unit tests with Robolectric

    main

    To run the JVM unit tests (which use Robolectric), you must have JDK 17 installed. Use the following commands to navigate to the android directory and execute the tests via Gradle:

    export JAVA_HOME=$(/usr/libexec/java_home -v 17)  # macOS
    cd android && ./gradlew test
    export JAVA_HOME=$(/usr/libexec/java_home -v 17)  # macOS
    cd android && ./gradlew test
  6. Install the SerialPort plugin

    main

    You can install the plugin using the Tauri CLI, which automatically handles both the Rust backend and the JavaScript frontend.

    Prerequisites

    • Rust: version 1.79 or higher
    • Tauri: version 2.0 or higher
    • Node.js and an npm-compatible package manager (npm, yarn, pnpm, deno, or bun)

    Use the Tauri CLI to install both parts of the plugin:

    # npm
    npm run tauri add serialplugin
    
    # yarn
    yarn run tauri add serialplugin
    
    # pnpm
    pnpm tauri add serialplugin
    
    # deno
    deno task tauri add serialplugin
    
    # bun
    bun tauri add serialplugin
    
    # cargo
    cargo tauri add serialplugin

    Manual Installation

    If you prefer manual setup:

    Backend (Rust): Add the plugin to your src-tauri directory using cargo:

    cd ./src-tauri
    cargo add tauri-plugin-serialplugin

    Frontend (JavaScript/TypeScript): Install the API package:

    npm install tauri-plugin-serialplugin-api
    # or
    pnpm add tauri-plugin-serialplugin-api
    # npm
    npm run tauri add serialplugin
    
    # yarn  
    yarn run tauri add serialplugin
    
    # pnpm
    pnpm tauri add serialplugin
    
    # deno
    deno task tauri add serialplugin
    
    # bun
    bun tauri add serialplugin
    
    # cargo
    cargo tauri add serialplugin
  7. Configure Android app requirements for SerialPlugin

    main

    To use the Android serial plugin in your consumer application, you must satisfy three requirements:

    1. Manifest Declaration: Declare USB host support in your AndroidManifest.xml (using android.hardware.usb.host is optional but recommended).
    2. Device Filtering: Ship a device_filter.xml file in your app resources that aligns with the plugin's default probe table (ProbeTable::default_table()). The reference implementation can be found at src/main/res/xml/device_filter.xml.
    3. Permissions: You must request runtime USB permission before attempting to open a device. The plugin handles this using PendingIntent.FLAG_MUTABLE and setPackage().
  8. Run Android JNI integration tests on an emulator or device

    main

    The plugin provides instrumented integration tests that use FakeTransport via android-test-harness. This allows you to test the JNI and file descriptor (fd) path on an emulator (such as an arm64 AVD) without requiring a real USB connection.

    To run these tests, use the provided integration script:

    ANDROID_INTEGRATION_NDK_ARCH=arm64-v8a ./scripts/android-integration-ci.sh all
    ANDROID_INTEGRATION_NDK_ARCH=arm64-v8a ./scripts/android-integration-ci.sh all
  9. Migrate to v3.0

    main

    If you are upgrading from a previous version, note the following API changes:

    Old APINew API
    port.at.enqueue('AT')port.sendAt('AT')
    port.at.enqueuePhases(...)port.sendAtPhases(...)
    port.at.sendSmsPdu(...)port.sendSmsPdu(...)
    port.at.cancel()port.cancelAt()
    Parallel exchange() throwsexchange() awaits turn in native queue

    Note that atSession configuration still applies during open() via configureAtSession.

  10. Regenerate Rust-only fixtures and verify parity

    main

    The current workflow for managing golden fixtures involves regenerating them using Rust-only tools and then verifying parity. This process uses the android-usb-serial package with the fake-transport feature enabled.

    Follow these steps to regenerate and verify fixtures:

    1. Run the golden recorder binary to generate new fixtures.
    2. Run the parity tests to ensure the new fixtures match expected behavior.
    3. Run the migration verification script to confirm the Android USB migration is correct.
    cargo run -p android-usb-serial --features fake-transport --bin golden_record
    cargo test -p android-usb-serial --features fake-transport --test golden_parity
    ./scripts/verify-android-usb-migration.sh
  11. Build, install, and view logs for serialport-test

    main

    Follow these steps to build the application, install it on your Android device, and monitor the plugin logs.

    1. Build the application

    pnpm tauri android build --debug

    2. Install the APK

    Use adb to install the generated APK. Note that the path may vary based on your local setup.

    adb -s "$ADB_SERIAL" install -r /Users/s00d/packeges/tauri-plugin-serialplugin/examples/serialport-test/src-tauri/gen/android/app/build/outputs/apk/universal/debug/app-universal-debug.apk

    3. Launch the application

    Force stop the existing package and start the main activity:

    adb -s "$ADB_SERIAL" shell am force-stop com.serialport.test
    adb -s "$ADB_SERIAL" shell am start -n com.serialport.test/.MainActivity

    4. Monitor logs

    Important: All Rust plugin logs are sent to the SerialPlugin tag, not RustStdout. Use the following command to view them:

    adb -s "$ADB_SERIAL" logcat -c
    adb -s "$ADB_SERIAL" logcat -v time -s UsbFdBridge SerialPlugin Console
    pnpm tauri android build --debug
    
    adb -s "$ADB_SERIAL" install -r /Users/s00d/packeges/tauri-plugin-serialplugin/examples/serialport-test/src-tauri/gen/android/app/build/outputs/apk/universal/debug/app-universal-debug.apk
    
    adb -s "$ADB_SERIAL" shell am force-stop com.serialport.test
    adb -s "$ADB_SERIAL" shell am start -n com.serialport.test/.MainActivity
    
    adb -s "$ADB_SERIAL" logcat -c
    adb -s "$ADB_SERIAL" logcat -v time -s UsbFdBridge SerialPlugin Console