HeroLink: Industrial IoT Hub
A C# desktop application automating parcel dimensioning and weighing via laser sensors and hardware integration.
- Context
- In the warehouse, parcel dimensions and weight were typed in by hand, with errors that cost money in shipping fees.
- My role
- Built the C# desktop app: sensor control, UI, ERP integration, automated build and release.
- Outcome
- In production: one scale and three lasers driven at once, measurements sent to the ERP as soon as the barcode is scanned.
The need
In e-commerce logistics, manual entry of parcel dimensions and weight is a major bottleneck. It is time-consuming and prone to typos, which ultimately leads to costly shipping surcharges.
The goal of HeroLink was to create a “Plug-and-Play” station. The application orchestrates 4 peripherals simultaneously (1 scale + 3 lasers) to capture parcel data as soon as a barcode is scanned, then synchronizes the information with an ERP via an API.
Technical choices
Why .NET 10 & Avalonia UI?
- .NET 10 & C#: I chose C# because .NET 10 allows for top-tier asynchronous performance, which is essential for handling multiple hardware data streams without latency.
- Avalonia UI: Chosen for its modern rendering engine and flexible styling system. It is a natural successor to WPF and leaves the door open to cross-platform later.
The Hardware Stack
Everything relies on System.IO.Ports for serial communication (COM):
- Scale: Real-time text/hex frame parsing to obtain stabilized weight data.
- Lasers (x3): Custom binary parser developed to extract distances (e.g.,
AA 00 00 20...) and convert them into actual dimensions after calibration.
The problem: unstable serial ports
During testing, the connection with the scale was inconsistent. After about ten minutes of inactivity, the port would stop responding. This occasionally blocked the main thread, causing the user interface to freeze.
The fix: rethinking the threading
To resolve this, I overhauled the communication architecture:
- Thread-Safety: Implemented
SemaphoreSlimto orchestrate port access and prevent data write conflicts. - Decoupling: Port reading is handled by background tasks to keep the UI responsive.
- Auto-reconnect: Added a “Watchdog” mechanism that detects timeouts and automatically restarts the connection.
The API
I used Refit to transform the API into a strongly-typed C# interface:
- Security: Automatic API key injection into the HTTP pipeline.
- Robustness: Centralized error handling and JSON mapping via Newtonsoft.
What I learned
- Mastering Avalonia: Discovered the framework’s resource lifecycle and the power of the MVVM pattern for complex interfaces.
- Industrial UX: In a warehouse, every second counts. The app is designed to be event-driven (responding to scans and weight stability), reducing manual interactions to the absolute minimum.
Retrospective
The project is currently in production. If I were to evolve it further, I would isolate the hardware logic into a separate Windows Service (Background Worker). The interface would then act as a light client communicating via SignalR, making data capture entirely independent of the UI state.