2610.1 - First commit
This commit is contained in:
1 parent
1a247323f1
commit
d8d131e1c1
69 files changed
+2073
-2
No files matched your search
@@ -1,3 +1,123 @@
|
||||
# lbms_py
|
||||
# LBMS
|
||||
|
||||
Python version of LBMS
|
||||
Laser gun monitoring system: listens on a serial port for XBee packets from 44
|
||||
tracked guns, decodes fire counts and "seen" beacons, estimates on-time (battery
|
||||
use), and displays a live grid of gun tiles. Includes a history dialog
|
||||
(per-gun stats, battery-change log) and a simulate mode that replays captured
|
||||
log files.
|
||||
|
||||
This repository contains:
|
||||
|
||||
- `LBMS/` — the original VB.NET WinForms project (reference, unchanged)
|
||||
- `lbms/`, `main.py` — the **Python port** (documented below)
|
||||
|
||||
## Python port
|
||||
|
||||
### Requirements
|
||||
|
||||
- Python 3.8+
|
||||
- `tkinter` (standard library; on Debian/Ubuntu: `sudo apt install python3-tk`)
|
||||
- [`pyserial`](https://pypi.org/project/pyserial/)
|
||||
|
||||
```sh
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Running
|
||||
|
||||
```sh
|
||||
python3 main.py [options]
|
||||
```
|
||||
|
||||
Options (all optional, `key=value` pairs):
|
||||
|
||||
| Option | Default | Description |
|
||||
|-----------|---------|----------------------------------------------------------|
|
||||
| `com` | — | Serial port to open automatically on start (e.g. `/dev/ttyUSB0`). The main window is minimized when this is used. |
|
||||
| `admin` | `false` | `admin=true` unlocks the SetFired/SetTime controls in the history dialog. |
|
||||
| `fired` | `11000` | Fire-count threshold; reaching it flags the gun for a battery change. |
|
||||
| `battery` | `660` | On-time (minutes) threshold; reaching it flags the gun for a battery change. |
|
||||
|
||||
If no port is given, enter one in the text box (e.g. `COM4` / `/dev/ttyUSB0`)
|
||||
and click **Button1** to open/close it. Status shows in `Label1` (Open/Closed).
|
||||
|
||||
### Interface
|
||||
|
||||
- **LBMS Console** (main window) — port controls, live decode stats
|
||||
(lines read, valid packets, queue/decode lengths, raw hex), and a scrolling
|
||||
per-gun summary.
|
||||
- **LBMS** (gun grid) — one tile per gun, 8x6 grid. Tile color:
|
||||
- green — seen in the last second
|
||||
- orange — seen in the last second but flagged for battery change
|
||||
- fading green — seen within the last 30 seconds
|
||||
- default grey — no recent contact
|
||||
- gun icon appears for ~3 s after a fire event; battery icon shows
|
||||
estimated remaining time/shots; both flash when a battery change is due.
|
||||
- Click a tile to open its **History** dialog: current + historical
|
||||
fired/on-time totals, change log, and **Change Batteries** (rolls current
|
||||
totals into history and zeroes them). Admin mode adds SetFired/SetTime.
|
||||
- Double-click the grid window to exit the app (with confirmation).
|
||||
- **Simulate** — pick a capture log (`timestamp,hex` per line, e.g. the files
|
||||
inside `LBMS/220619.zip`), and packets are replayed through the normal
|
||||
decode pipeline at their original timing.
|
||||
|
||||
### Serial protocol
|
||||
|
||||
The port runs 115200, 8N1. Data is uppercased to hex and fed into a queue;
|
||||
the 75 ms main timer drains it into a decode buffer and scans for:
|
||||
|
||||
| Marker | Length (hex chars) | Layout | Action |
|
||||
|-----------|--------------------|---------------------------------------------------------------|-------------------------------|
|
||||
| `7E002480`| 80 | head(8) + MAC(16) + payload(34) + fire count(4) + tail(18) | add fire count, mark seen |
|
||||
| `7E002A80`| 92 | head(8) + MAC(16) + payload(36) + tail(32) | mark seen |
|
||||
|
||||
Fire count is big-endian (`hi*256 + lo`). When a count ever decreases (gun
|
||||
rebooted), the previous count is added to the gun's overall total and battery
|
||||
time is rolled over. Every time a known gun is seen and the last count is
|
||||
older than `CountInterval` (10 min), that interval is added to its on-time —
|
||||
which is how battery life is estimated. Junk data: if no packet is found and
|
||||
the buffer exceeds 200 chars, the first half is discarded.
|
||||
|
||||
### Persistence
|
||||
|
||||
State is saved to `./items/<gun_id>.cfg` (one JSON file per gun) on close and
|
||||
every ~61 s. On start, if `./items/` exists it is loaded; otherwise all 44
|
||||
guns are created fresh from the MAC list in `lbms/main_window.py`
|
||||
(`_create_id_list`).
|
||||
|
||||
### Project layout
|
||||
|
||||
```
|
||||
main.py # entry point
|
||||
requirements.txt
|
||||
lbms/
|
||||
├── globals.py # shared state: gun list, message queue, helpers
|
||||
├── gun_object.py # GunObject model + JSON save/load
|
||||
├── cls_com_ports.py # ComPorts serial wrapper (pyserial)
|
||||
├── resources.py # PNG image loader (lbms/resources/)
|
||||
├── gun_button.py # one gun tile (text, colors, battery/gun icons)
|
||||
├── frm_guns.py # gun grid window
|
||||
├── frm_history.py # per-gun history dialog
|
||||
└── main_window.py # console window: timers, serial reader, packet decoder
|
||||
```
|
||||
|
||||
### Threading model
|
||||
|
||||
- A daemon **reader thread** polls the serial port and enqueues hex strings
|
||||
into `lbms.globals.message_queue`.
|
||||
- All decoding and UI updates happen on the tkinter thread via `after()`
|
||||
timers (75 ms main tick, 5 ms simulate, 1000 ms summary, 250/500 ms per
|
||||
tile) — the same architecture as the original WinForms event/timer design.
|
||||
- Unrecoverable decode errors are appended to `err.log` and the app exits
|
||||
(matching the VB `End` behavior).
|
||||
|
||||
## Differences from the VB.NET original
|
||||
|
||||
- GUI: WinForms → tkinter; serial: `System.IO.Ports` → pyserial.
|
||||
- `./items/*.cfg` files are plain **JSON** instead of base64-wrapped
|
||||
`BinaryFormatter` blobs, so .NET-era `.cfg` files are not readable by the
|
||||
Python port (state starts fresh on first run).
|
||||
- The VB `Form1.vb` referenced a `Button2` missing from its designer file; the
|
||||
port implements it as the **Button2** "save now" button next to Button1.
|
||||
- The simulate log format `YYYY-MM-DD HH:MM:SS.mmm,<hex>` is parsed with
|
||||
`datetime.fromisoformat`.
|
||||
Reference in new issue
Block a user