https://finabill.genius.africa/api/scale/ingest
A Windows weighing-scale bridge that reads readings over a serial port, publishes them to the POS terminal via a named pipe, and optionally pushes them to the FinaBill cloud API. It runs as a normal GUI app for setup/testing or as an always-on Windows Service so readings keep flowing even when no user is logged in and no one has to remember to open the app.
- Overview & Architecture
- Requirements
- What gets built / Deployment file set
- Building from source
- Installation — where to put the files
- Running as a Windows Service
- Running as the interactive app (GUI)
- Configuration —
scale-settings.json - Logs
- Paths & how install location is resolved
- POS integration (named pipe + HTTP)
- Command-line reference
- Troubleshooting
- Changelog
┌─────────────────────────── FinaScale (Genius.Scale) ───────────────────────────┐
USB/RS232 │ │
Scale ───────▶│ SerialPort ──▶ ScaleEngine ──▶ ScalePipePublisher ── ▶ named pipe ──▶ POS │
(JSJ asc) │ │ └──▶ ScaleApiClient ──▶ HTTP ──▶ FinaBill API │
│ └──────────────▶ Log (weighing + api_push) └──▶ log files │
└──────────────────────────────────────────────────────────────────────────────────┘
| Component | File | Role |
|---|---|---|
ScaleEngine |
Services/ScaleEngine.cs |
Headless core. Owns the serial port, the pipe publisher and the API client. Runs with no UI so it can be hosted by the GUI or the service. |
FinaScaleService |
Services/FinaScaleService.cs |
ServiceBase wrapper that hosts ScaleEngine as a Windows Service. |
ServiceInstallerHelper |
Services/ServiceInstallerHelper.cs |
Registers/unregisters the service via sc.exe. |
ScalePipePublisher |
Services/ScalePipePublisher.cs |
Named pipe server (LogicPOSScale) delivering newline-delimited JSON readings. |
ScaleApiClient |
Services/ScaleApiClient.cs |
HTTP client pushing readings to the cloud API with X-API-Key auth. |
ScaleSettings |
Services/ScaleSettings.cs |
JSON settings persistence (scale-settings.json). |
Program |
Program/Program.cs |
Dual-mode entry point (--service / --install / --uninstall / GUI). |
FrmMain |
FrmMain.cs |
Interactive GUI (setup + real-time monitoring). |
- Windows (any modern version : 7 / 10 / 11, and Server). Service mode requires an edition that
supports Windows Services (Windows Home qualifies for Service
sc.exe). - .NET Framework 4.8 runtime (pre-installed on Windows 10 v1903+ / Windows 11).
- Administrator privileges to install the service.
- A scale that speaks the JSJ (Jia Shang Jia) "asc" serial protocol at 9600 baud, 8 data bits, No parity, 1 stop bit.
- Optional: an API endpoint (FinaBill
POST /api/scale/ingest) + API key to push readings to the cloud.
Serial driver note: it is installed when you build from source (below). For a pre-built binary you must ship the file set described in §3 and your own copy of
System.Windows.Forms.Extension.dll. See the file set below.
A successful build (bin\) produces these files that must be copied/deployed together:
| File | Required? | Notes |
|---|---|---|
Genius.Scale.exe |
✅ | The main executable (GUI + service host). |
Genius.Scale.exe.config |
✅ | .NET runtime config (target v4.8). |
System.Windows.Forms.Extension.dll |
✅ | UI control library. Must sit next to the exe (fixed binding). |
Newtonsoft.Json.dll |
✅ | JSON serialization for settings + API client. |
install-service.bat |
optional | Convenience installer (run as admin). |
uninstall-service.bat |
optional | Convenience uninstaller (run as admin). |
At runtime the app creates a few files next to the exe:
scale-settings.json— your configuration (API URL/key, COM port, scale brand).logs\— rolling log files (see §9).
The project is a legacy non-SDK .NET Framework 4.8 WinForms project. Build from the repo:
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" ^
"packages\scale\Genius.Scale\Genius.Scale.csproj" /p:Configuration=Release /t:Build /v:minimalOutput lands in packages\scale\Genius.Scale\bin\Release\.
.NET Framework 4.8 must be installed on the machine that builds (or referenced via
Microsoft.NETFramework.ReferenceAssemblies). The project targetsv4.8.
Important: the app resolves everything relative to the exe's own folder — there are no
hard-coded absolute paths (C:\...) and no assumption that it lives inside a bin\ folder.
That means you can install it anywhere and it will treat that folder as its root for config, logs
and the service binary path.
- Per-machine (recommended) —
C:\FinaScale\(or your standard program-files-of-your-choice). - Per-user —
%LOCALAPPDATA%\FinaScale\or any folder the user owns.
Why not
C:\Program Files\...? For a simple app there's no installer granting WRITE access to its own folder. The app writesscale-settings.jsonandlogs\next to the exe, and the service also needs to write there. Installing to a folder the (service) account can write to is recommended. UseC:\Program Files\only if you grant the service account write on that folder.
- Copy the entire file set from §3 into the target folder (e.g.
C:\Apps\FinaScale\). - Put
install-service.batanduninstall-service.batin the same folder as the exe (they locate the exe automatically — same folder first, then abin\subfolder, so they also work in the source layout). - Optionally create a Start-Menu / Desktop shortcut to the GUI (
Genius.Scale.exe).
The layout should look like:
C:\FinaScale\
│ Genius.Scale.exe
│ Genius.Scale.exe.config
│ System.Windows.Forms.Extension.dll
│ Newtonsoft.Json.dll
│ scale-settings.json ← created on first run
│ install-service.bat
│ uninstall-service.bat
└─ logs\ ← created on first run
├─ 20260807.txt ← system / general log
└─ weighing\
└─ 20260807.txt ← weighing readings log
The service lets the app start at boot and run 24/7 without any user interaction. It reads the scale over the serial port, publishes to the POS pipe, and pushes stable readings to the API even while no one is logged into a desktop session.
Option A — double-click the script (easiest):
- Right-click
install-service.bat→ Run as administrator. - It finds the exe, registers the
FinaScaleservice (auto-start, delayed-auto, auto-restart on failure) and starts it.
Option B — repeatable from an admin PowerShell/CMD from the install folder:
.\Genius.Scale.exe --installBoth do the same thing. Verification:
sc query FinaScale # STATE: 4 RUNNING
Get-Service FinaScale # Status: Running- Creates a service named
FinaScale(display name "FinaScale Scale Bridge"). - Sets the executable binary path to
<install folder>\Genius.Scale.exe --service— the path is resolved from where the exe actually is, so it can be installed any folder. - Sets auto start (delayed) so USB/RS serial drivers have time to enumerate before connecting.
- Configures auto-restart on failure (5s / 10s / 30s backoff) so the bridge self-heals.
- Starts the service.
sc start FinaScale # start
sc stop FinaScale # stop
sc delete FinaScale # unregister (also: uninstall-service.bat)The service reads the scale/API settings from scale-settings.json in the install folder. To
pre-populate them cleanly, run the GUI once first (§7), enter the API URL, API key, select the
COM port and scale brand, then close the GUI. That writes scale-settings.json, and the service
auto-connects to the saved COM port on start.
Service account note — the service runs under Local System by default and therefore needs
read/write access to its own folder (to read settings and write logs). When installing to a
protected folder such as C:\Program Files\, grant "Modify" to the service account, or (simpler)
install into a writable location like C:\FinaScale\.
Launch Genius.Scale.exe (with no arguments). The GUI is for setup and live monitoring:
- Displays the live weight, status (
Stable/Unstable/Overweight), pipe status. - Lets you pick the COM port, scale brand, API URL, and API key.
- Open / Close the serial port, Tare, Zero.
Settings you change are saved to scale-settings.json on change and on exit, so you typically
configure once and then rely on the service.
GUI vs Service conflict: the app deliberately prevents two processes from fighting over the serial port / pipe. If the
FinaScaleservice is running, the GUI will inform you and exit. Stop the service (sc stop FinaScale) if you want to use the GUI for anything testing, then restart the service when done.
Created automatically in the install/exe folder at first run (GUI or service). Example:
{
"ApiUrl": "https://api.yourdomain.com/api/scale/ingest",
"ApiKey": "your-secret-key",
"ComPort": "COM3",
"ScaleBrand": "JSJASC"
}| Key | Meaning |
|---|---|
ApiUrl |
Full endpoint that receives the POST /ingest. Empty = API disabled. |
ApiKey |
Secret sent in the X-API-Key header. Empty = API disabled. |
ComPort |
COM port the scale is attached to (e.g. COM3). Empty + API unset → local-only, no push. |
ScaleBrand |
Scale protocol variant (only JSJASC / brand selector). |
Behavior with / without API:
- API configured → stable readings are pushed to the API and the outcome is logged (SUCCESS/FAILED).
- API not configured or offline → readings are still logged locally (weighing log) so you have a dated record of every reading even during an internet outage; they are simply not pushed.
All logs go under logs\ next to the exe (resolved from AppDomain.CurrentDomain.BaseDirectory,
which is the install folder — works for GUI and service alike, no hard .cwd).
| File | Contents |
|---|---|
logs\YYYYMMDD.txt |
General / system log (port open, API submissions, errors, pipe connects). |
logs\weighing\YYYYMMDD.txt |
Every reading plus API push outcomes (see format below). |
Example weighing log:
WEIGHING | 2026-08-07 16:45:12.123 | Weight: 1.250 kg | Status: stable | Sequence: 42
WEIGHING | 2026-08-07 16:45:12.123 | Weight: 1.250 kg | Status: stable | Sequence: 43
API_PUSH | 2026-08-07 16:45:12.115 | Weight: 1.250 kg | Status: stable | Sequence: 43 | Endpoint: https://.../ingest | Result: FAILED
WEIGHING | 2026-08-07 16:45:14.300 | Weight: 0.000 kg | Status: unstable | Sequence: 44
- Every parsed reading logs a
WEIGHINGline regardless of API state. API_PUSHlines appear only when a push was actually attempted, recording the endpoint andSUCCESS/FAILED. This lets you tell the difference between "reading existed but never pushed" (noAPI_PUSHline) vs "pushed and failed" (API_PUSH ... Result=FAILED).
The app never hard-codes bin\ or absolute directories. All critical paths derive from the
running exe's own location at runtime:
| What | Resolution | Reason |
|---|---|---|
scale-settings.json |
AppDomain.CurrentDomain.BaseDirectory + file |
Works from any install folder |
logs\* |
AppDomain.CurrentDomain.BaseDirectory + logs |
Service/gui log to the same place |
| Service binary path (registered) | Assembly.GetExecutingAssembly().Location |
${exe} --service used for sc create / binPath |
System.Windows.Forms.Extension.dll |
Copied next to exe (single-assembly binding) | Known FileNotFound saved by marking the reference Private=True and matching its real version |
The only place that historically inferred a relative bin\ sub-folder was the install-service.bat
/ uninstall-service.bat; those now detect the exe — same folder first, then bin\ — so they
work whether you run them from the source tree or from an installed folder.
The app delivers readings to the POS in two ways:
-
Named pipe (
\\.\pipe\LogicPOSScale) — the primary, low-latency channel for local POS terminals. Messages are newline-delimited JSON which frame each reading:{"v":1,"seq":43,"kg":1.250,"status":"stable","atUtc":"2026-08-07T15:45:12.115Z"}The service auto-connects when the POS opens the pipe (server accepts reconnects).
-
Cloud API (
POST {ApiUrl}) — sends{weight, status, sequence, timestamp, source:"JSJScale"}with anX-API-Keyheader. The API is only called for stable, new readings (deduplicated so a settled scale does not spam requests).
Both paths emit logs (pipe connect / API SUCCESS / FAILED) so you can audit what happened.
| Argument | Action |
|---|---|
| (no argument) | Launch the interactive GUI. |
--service |
Run the headless host as a Windows Service (used as the binPath of the service). |
--install |
Register + configure + start the FinaScale service (admin required). |
--uninstall |
Stop + delete the FinaScale service (admin required). |
Occurs when the UI assembly is missing or a version mismatch between the csproj reference and
the real .dll. Fix:
- Ensure
System.Windows.Forms.Extension.dllis copied next toGenius.Scale.exe. - Rebuild so the reference version matches the shipped DLL (must be
1.0.9197.21818).
The service is running and holds the serial port/pipe. Stop it (sc stop FinaScale) to run the
GUI, or just use the service.
- Verify the app is running the current build (kill any old instance locking
bin\). - Check
logs\weighing\YYYYMMDD.txtin the install folder (not a stale bin folder).
- Check
ApiUrlandApiKeyare set inscale-settings.jsonor set via GUI. API_PUSH ... Result=FAILED→ network/endpoint/reject (check URL, key, server).- No
API_PUSHline at all → the API client is disabled (URL/key missing) or the reading isn't stable.
- Confirm it's started:
sc query FinaScale. - Confirm the install folder has correct permissions for the service account.
- Look at
logs\*for the actual exception.
- 2026-08-07 — Documented the Windows Service deployment model; clarified that the tool is
runnable as an installable, 24/7 service while preserving an interactive GUI; added
location-independent
install-service.bat/uninstall-service.bat; fixedSystem.Windows.Forms .Extensionversion + copy so the binary runs in any install directory.
Generated: 2026-08-07 · FinaScale Tool (Genius.Scale)