The PSLab app currently depends on flusbserial for desktop USB serial communication. We should remove this dependency and replace it with a small FOSSASIA-maintained serial transport layer that is focused on PSLab hardware.
The goal is not to create a general-purpose USB serial library. PSLab only needs reliable communication with PSLab devices. Therefore the replacement should be scoped to the serial communication requirements of PSLab and should avoid unnecessary support for unrelated USB serial chipsets.
flusbserial states that it is based on/inspired by code from UsbSerial and quick_usb. To avoid dependency and provenance concerns, the new implementation should be developed independently and documented clearly.
Goal
Implement a PSLab-owned serial transport layer that allows the app to communicate with PSLab hardware on desktop platforms without depending on flusbserial.
This issue focuses on Option A:
- Remove
flusbserial from the PSLab desktop path.
- Keep the existing Android USB serial implementation temporarily.
- Introduce a clean PSLab serial abstraction.
- Implement desktop communication through standard OS serial ports where possible.
- Replace Android separately in a later issue.
Non-goals
This issue does not aim to:
- Build a generic Flutter USB serial library.
- Support every USB serial chipset.
- Reimplement
flusbserial.
- Reuse/copy code from
flusbserial, quick_usb, or UsbSerial.
- Replace the existing Android serial implementation immediately.
Technical architecture
1. Add a PSLab serial abstraction
Create a small transport interface used by the PSLab app instead of calling flusbserial directly.
Suggested structure:
lib/
communication/
serial/
pslab_serial_transport.dart
pslab_serial_device.dart
pslab_serial_port.dart
implementations/
desktop_serial_transport.dart
android_serial_transport.dart
Suggested interface:
abstract class PslabSerialTransport {
Future<List<PslabSerialDevice>> listDevices();
Future<PslabSerialPort> openDevice(
PslabSerialDevice device, {
required int baudRate,
});
}
abstract class PslabSerialPort {
Stream<Uint8List> get input;
Future<void> open();
Future<int> write(Uint8List data);
Future<void> close();
bool get isOpen;
}
Optional methods can be added only if PSLab actually needs them:
Future<void> setDtr(bool value);
Future<void> setRts(bool value);
Future<void> flush();
The app should depend on this abstraction, not directly on a third-party USB serial package.
2. Keep Android path temporarily
For this issue, Android should continue using the existing Android USB serial implementation behind the new abstraction.
Implementation idea:
android_serial_transport.dart
This class should wrap the current Android serial behavior and expose it through PslabSerialTransport.
This allows us to remove flusbserial from the desktop path without breaking Android.
3. Implement desktop serial transport
For Linux, macOS and Windows, implement a PSLab desktop transport using standard serial ports instead of direct USB/libusb access.
Expected platform behavior:
- Linux: detect
/dev/ttyUSB*, /dev/ttyACM*, preferably /dev/serial/by-id/*
- macOS: detect
/dev/cu.* or /dev/tty.*
- Windows: detect
COMx ports
The PSLab device should be detected using available serial-port metadata where possible, for example:
- USB vendor ID
- USB product ID
- serial number
- device path/name containing CP210x / Silicon Labs / PSLab identifiers where available
If metadata is incomplete on one platform, fallback behavior may allow the user or app to select a candidate serial port.
4. Avoid direct libusb for the first implementation
The first implementation should not use direct libusb unless there is a strong reason.
Reason:
- PSLab communication is serial communication.
- CP210x devices can appear as standard virtual COM/TTY devices through normal OS drivers.
- Standard serial ports reduce complexity.
- This avoids Windows driver replacement issues that can happen with direct USB/libusb approaches.
- It keeps the implementation small and PSLab-focused.
5. App integration
Update the app code so that PSLab communication goes through the new abstraction.
Required changes:
- Identify all imports/usages of
package:flusbserial.
- Replace them with
PslabSerialTransport.
- Keep platform selection inside the transport layer, not in feature/instrument code.
- Keep the instrument logic independent from the underlying serial implementation.
Example platform selection:
PslabSerialTransport createPslabSerialTransport() {
if (Platform.isAndroid) {
return AndroidSerialTransport();
}
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return DesktopSerialTransport();
}
throw UnsupportedError('Unsupported platform');
}
Implementation steps
Step 1: Audit current usage
-
Find all usages of flusbserial.
-
Identify which PSLab features depend on it.
-
Document the required operations:
- list devices
- open device
- set baud rate
- read bytes
- write bytes
- close connection
- handle disconnect/reconnect
Step 2: Add transport interfaces
- Add
PslabSerialTransport.
- Add
PslabSerialPort.
- Add
PslabSerialDevice.
- Do not change behavior yet.
Step 3: Add temporary adapters
- Add an Android adapter around the current Android serial implementation.
- Add a temporary desktop adapter if needed to keep the app working during migration.
- Ensure instrument code uses only the new abstraction.
Step 4: Implement desktop transport
Implement desktop serial communication using standard serial ports.
Minimum required functionality:
- List likely PSLab serial devices.
- Open selected serial port.
- Configure baud rate.
- Write binary data.
- Read binary data.
- Close port.
- Report connection errors clearly.
Step 5: Replace desktop flusbserial usage
- Remove direct desktop usage of
flusbserial.
- Ensure no app code imports
package:flusbserial.
- Keep Android behavior unchanged for this issue.
Step 6: Validate with PSLab hardware
Test at least:
- Device detection
- Connect/disconnect
- Firmware/version query
- Basic command-response communication
- Multimeter workflow
- Oscilloscope/data acquisition workflow
- Waveform generator workflow, if currently supported
- Long-running read/write test
- Reconnect after unplug/replug
- App restart with device connected
Step 7: Remove dependency
After desktop communication works:
- Remove
flusbserial from pubspec.yaml.
- Run dependency cleanup.
- Confirm build works on supported platforms.
- Add documentation for serial-port permissions and troubleshooting.
Acceptance criteria
pslab-app no longer depends on flusbserial.
- No source file imports
package:flusbserial.
- PSLab desktop communication works on Linux, macOS and Windows through the new PSLab-owned serial transport.
- Android continues to work through the existing Android implementation wrapped behind the new abstraction.
- Core PSLab communication works with real PSLab hardware.
- The implementation is PSLab-focused and does not attempt to become a general-purpose USB serial library.
- Basic documentation is added for desktop serial-port setup and troubleshooting.
Suggested follow-up issue
After this issue is completed, create a separate issue:
Replace Android usb_serial dependency with PSLab-owned Android serial transport
That follow-up can implement a native Android CP210x/PSLab serial path using Android UsbManager, but it should not block removal of flusbserial from the desktop path.
Estimated effort
For an experienced Flutter/native developer familiar with serial communication:
- Minimal PSLab-focused desktop replacement: 1–2 weeks
- With review, hardware testing and cleanup: 2–4 weeks
This estimate assumes we keep the scope limited to PSLab communication and do not build a generic USB serial library.
The PSLab app currently depends on
flusbserialfor desktop USB serial communication. We should remove this dependency and replace it with a small FOSSASIA-maintained serial transport layer that is focused on PSLab hardware.The goal is not to create a general-purpose USB serial library. PSLab only needs reliable communication with PSLab devices. Therefore the replacement should be scoped to the serial communication requirements of PSLab and should avoid unnecessary support for unrelated USB serial chipsets.
flusbserialstates that it is based on/inspired by code fromUsbSerialandquick_usb. To avoid dependency and provenance concerns, the new implementation should be developed independently and documented clearly.Goal
Implement a PSLab-owned serial transport layer that allows the app to communicate with PSLab hardware on desktop platforms without depending on
flusbserial.This issue focuses on Option A:
flusbserialfrom the PSLab desktop path.Non-goals
This issue does not aim to:
flusbserial.flusbserial,quick_usb, orUsbSerial.Technical architecture
1. Add a PSLab serial abstraction
Create a small transport interface used by the PSLab app instead of calling
flusbserialdirectly.Suggested structure:
Suggested interface:
Optional methods can be added only if PSLab actually needs them:
The app should depend on this abstraction, not directly on a third-party USB serial package.
2. Keep Android path temporarily
For this issue, Android should continue using the existing Android USB serial implementation behind the new abstraction.
Implementation idea:
This class should wrap the current Android serial behavior and expose it through
PslabSerialTransport.This allows us to remove
flusbserialfrom the desktop path without breaking Android.3. Implement desktop serial transport
For Linux, macOS and Windows, implement a PSLab desktop transport using standard serial ports instead of direct USB/libusb access.
Expected platform behavior:
/dev/ttyUSB*,/dev/ttyACM*, preferably/dev/serial/by-id/*/dev/cu.*or/dev/tty.*COMxportsThe PSLab device should be detected using available serial-port metadata where possible, for example:
If metadata is incomplete on one platform, fallback behavior may allow the user or app to select a candidate serial port.
4. Avoid direct libusb for the first implementation
The first implementation should not use direct
libusbunless there is a strong reason.Reason:
5. App integration
Update the app code so that PSLab communication goes through the new abstraction.
Required changes:
package:flusbserial.PslabSerialTransport.Example platform selection:
Implementation steps
Step 1: Audit current usage
Find all usages of
flusbserial.Identify which PSLab features depend on it.
Document the required operations:
Step 2: Add transport interfaces
PslabSerialTransport.PslabSerialPort.PslabSerialDevice.Step 3: Add temporary adapters
Step 4: Implement desktop transport
Implement desktop serial communication using standard serial ports.
Minimum required functionality:
Step 5: Replace desktop
flusbserialusageflusbserial.package:flusbserial.Step 6: Validate with PSLab hardware
Test at least:
Step 7: Remove dependency
After desktop communication works:
flusbserialfrompubspec.yaml.Acceptance criteria
pslab-appno longer depends onflusbserial.package:flusbserial.Suggested follow-up issue
After this issue is completed, create a separate issue:
That follow-up can implement a native Android CP210x/PSLab serial path using Android
UsbManager, but it should not block removal offlusbserialfrom the desktop path.Estimated effort
For an experienced Flutter/native developer familiar with serial communication:
This estimate assumes we keep the scope limited to PSLab communication and do not build a generic USB serial library.