net: initialize the monitor in the startup equip path (v2.7.1)

The startup init (server booted with the card already in the reader) equips
the card and reads the ICCID itself, but never created server.net_state -
only /api/command equip and the auto-equip worker did.  With a card present
at boot the monitor stayed empty, net-sim responses carried net_state: null
and the panel only started updating after pressing Refresh (which lazily
created the state).  Fix:

- factor _netstate_read(app) / _netstate_install() / _netstate_init() in
  server.py; _apply_equipped_card uses _netstate_init()
- __main__ startup: read the monitored EFs in the same CAT-free window as
  the ICCID and install the state once the server object exists
- _netstate_ensure() lazily initializes the state in the net-sim/event hooks
  so any equip path predating the monitor cannot leave it dead
- netSimRun falls back to netStateFetch() when a response has no net_state
- tests: tests/test_netstate_server.py (candidate order, record vs
  transparent, absent files, install, ensure); SW cache simple-v204
This commit is contained in:
2026-09-20 13:12:00 +03:00
parent b1539d7cd5
commit bb13ed45f8
6 changed files with 155 additions and 21 deletions
+2 -1
View File
@@ -1414,7 +1414,7 @@
// ===== Version =====
// Single source of truth for the PWA version: shown in the header and used
// by the server version check in pysimConnect().
const SIMPLE_VERSION = '2.7.0';
const SIMPLE_VERSION = '2.7.1';
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
// ===== Tab switching =====
@@ -12690,6 +12690,7 @@ async function netSimRun(scenario) {
}
pysimEventsRender();
if (res.net_state) netStateRender(res.net_state);
else netStateFetch();
} catch (e) {
statusEl.textContent = t('Error') + ': ' + e.message;
statusEl.className = 'text-xs text-red-500 mb-1';