A Flutter plugin for interfacing with commercial weight scales via RS232 using the AUTO COMMUNICATE PROTOCOL. Provides real-time weight data streaming and robust device management for Android applications.
- 🔌 Android USB-Serial support: Full USB-Serial communication with commercial scales
- ⚡ Real-time data streaming: Continuous weight readings via EventChannel
- 🛡️ Type-safe error handling: Result pattern instead of exceptions
- 🔍 Device auto-discovery: Automatic USB device detection and validation
- 📊 Protocol validation: Built-in BCC validation and frame structure checks
- 🎯 Configurable: Customizable timeouts, logging, and device filtering
- 📱 Production ready: Memory-efficient circular buffer and connection management
- RS232 AUTO COMMUNICATE PROTOCOL: 16-byte frame structure
- Frame format: SOH + STX + Status + Sign + Weight(6) + Units(2) + BCC + ETX + EOT + Status2
- Baud rate: 9600 (configurable)
- Data validation: BCC (Block Check Character) validation
Currently tested with:
- Aclas scales (VID: 6790, PID: 29987)
- Generic USB-Serial scales
- Any RS232 scale using AUTO COMMUNICATE PROTOCOL
Android Only: This plugin currently supports Android devices only through USB-Serial communication.
| Platform | Status | Features |
|---|---|---|
| Android | ✅ Full | USB-Serial, Real-time streaming |
| iOS | ❌ Not supported | iOS doesn't support USB host mode without MFi accessories |
| Windows | ❌ Not supported | Not implemented |
| macOS | ❌ Not supported | Not implemented |
| Linux | ❌ Not supported | Not implemented |
Note: This plugin is designed specifically for Android applications that need to interface with commercial weight scales via USB-Serial. Other platforms may be considered for future versions based on community demand and technical feasibility.
Add this to your package's pubspec.yaml file:
dependencies:
weight_scale: ^1.0.0Add this to your android/build.gradle (project level):
allprojects {
repositories {
google()
mavenCentral()
maven {
url 'https://www.jitpack.io'
}
}
}Add USB permissions to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.host" />import 'package:weight_scale/weight_scale_manager.dart';
import 'package:weight_scale/core/config.dart';
import 'package:weight_scale/core/logger.dart';
class WeightScaleExample {
late final WeightScaleManager manager;
void initialize() {
manager = WeightScaleManager(
config: const WeightScaleConfig(
deviceCheckTimeout: Duration(seconds: 2),
debugLogging: true,
),
logger: const ConsoleLogger(),
);
}
Future<void> scanAndConnect() async {
// Get available devices
final result = await manager.getAvailableDevices();
result.fold(
(devices) async {
if (devices.isNotEmpty) {
// Connect to first available device
final connectResult = await manager.connect(devices.first);
connectResult.fold(
(_) => print('Connected successfully!'),
(failure) => print('Connection failed: ${failure.message}'),
);
}
},
(failure) => print('Scan failed: ${failure.message}'),
);
}
void startListening() {
manager.initialize();
manager.dataStream?.listen(
(scaleData) {
print('Weight: ${scaleData.numericWeight} ${scaleData.weightUnits}');
print('Status: ${scaleData.isStable ? 'Stable' : 'Unstable'}');
print('Tare: ${scaleData.isTareActive ? 'Active' : 'Inactive'}');
},
onError: (error) => print('Stream error: $error'),
);
}
}final manager = WeightScaleManager(
config: WeightScaleConfig(
deviceCheckTimeout: Duration(milliseconds: 500),
knownScaleDevices: [
...WeightScaleConfig.defaultKnownScales,
ScaleDeviceIdentifier(
vendorID: '1234',
productID: '5678',
name: 'Custom Scale',
),
],
debugLogging: false,
),
logger: SilentLogger(), // For production
);manager.setErrorCallback((error, stackTrace) {
if (error is PlatformException && error.code == 'CONNECTION_LOST') {
print('Scale disconnected - attempting reconnection...');
// Handle reconnection logic
}
});manager.dataStream?.listen((data) {
// Type-safe data access
final weight = data.numericWeight;
final isStable = data.isStable;
final units = data.weightUnits;
// Conditional processing
if (data.isStable && !data.isZero) {
processStableWeight(weight, units);
}
// Raw data access for custom protocols
final rawBytes = data.rawData;
if (rawBytes != null) {
processRawData(rawBytes);
}
});The plugin follows clean architecture principles:
├── core/ # Shared utilities and types
│ ├── result.dart # Result<T> for type-safe error handling
│ ├── config.dart # Configuration and device identifiers
│ └── logger.dart # Logging abstraction
├── repositories/ # Data access interfaces
│ └── device_repository.dart
├── data/ # Data handling interfaces
│ └── data_stream.dart
├── protocol.dart # RS232 protocol implementation
├── weight_scale_manager.dart # Main API (singleton)
└── weight_scale_device.dart # Device model
Run unit tests:
flutter testRun integration tests:
cd example
flutter test integration_test/Calculate BCC values for custom data:
dart test/bcc_calculator.dartDevice not found
- Ensure USB permissions are granted
- Check VID/PID matches your scale model
- Verify scale is using AUTO COMMUNICATE PROTOCOL
Connection timeout
- Increase
deviceCheckTimeoutin config - Check USB cable and connections
- Verify scale is powered on and ready
Data parsing errors
- Ensure scale uses 16-byte frame format
- Check BCC calculation implementation
- Enable debug logging to inspect raw data
Memory issues
- Plugin uses circular buffer to prevent memory leaks
- Dispose resources properly:
await manager.dispose()
Enable detailed logging:
final manager = WeightScaleManager(
config: const WeightScaleConfig(debugLogging: true),
logger: const ConsoleLogger(),
);Contributions are welcome! Please read our contributing guidelines and code of conduct.
- Clone the repository
- Run
flutter pub get - Run tests:
flutter test - Run example:
cd example && flutter run
For maintainers, see PUBLISHING_SETUP.md for automatic release setup.
Quick release process:
# Update version in pubspec.yaml and run:
./scripts/auto-release.sh- iOS support via Lightning/USB-C adapters
- Windows support via COM ports
- macOS and Linux support
- Custom protocol support
- Bluetooth scale support
- Web support via WebSerial API
This project is licensed under the MIT License - see the LICENSE file for details.
See CHANGELOG.md for a detailed list of changes.
- 📖 Documentation
- 🐛 Bug Reports
- 💬 Discussions
- 📧 Contact