docs: align the READMEs, help and API reference with the current UI (v3.0.1)
- docs/api.md: document GET /api/net-state and POST /api/net-state-refresh (state shape, monitored keys, refresh filter, 503); add eid/euicc to /api/status; correct the /api/net-sim FPLMN wording (roaming_denied appends, attach clears; 5GS files untouched) and its response (net_state); move the stray /api/event-send example back into its section; refresh the version examples to 3.x. - README/RUS: Cards — ADM field, the three TARs, the SCP80/SCP81 fieldsets and the header markers; File Browser — Read raw/Read decoded pills, Edit raw, named FCI block, Verify ADM; Profiler — Clone, three list tabs; Custom files — root/parent/FID/alias form, canonical paths, cascade delete, legacy-path resolution; Phone simulator — three pills, eSIM, Network state monitor, Home network button, corrected FPLMN wording, proactive-log row content; RU CLI table gaps (--sms-oa/ --sms-sm-sc, --terminal-profile, --mcc-mnc-list) and the missing event-form bullets. - help EN/RU: three profiler list tabs, 3.x compatibility example. - Version 3.0.1 (docs release), sw.js simple-v228.
This commit is contained in:
@@ -465,23 +465,26 @@ Delete confirms via a browser prompt before sending the GP `DELETE` command via
|
|||||||
|
|
||||||
## Cards
|
## Cards
|
||||||
|
|
||||||
Stores saved card configurations (presets) in `localStorage`. A preset holds the cryptographic keys, SPI settings, TAR and replay counter for SCP80 operations, plus the **PSK identity / PSK key** pair used by the SCP81 HTTP OTA listener. Cards is a **top-level tab**. When the card is equipped its EF.ICCID is read and the preset with the same ICCID is selected automatically in both SCP80 views.
|
Stores saved card configurations (presets) in `localStorage`. A preset holds the cryptographic keys, SPI settings, TARs and replay counter for SCP80 operations, the optional **ADM** key, plus the **PSK identity / PSK key** pair used by the SCP81 HTTP OTA listener. Cards is a **top-level tab**. The form groups the fields into two bordered blocks — **SCP80 (GSM 03.48, ETSI TS 102 225)** and **SCP81 (HTTP OTA)** — with the optional **ADM** field in the top row. When the card is equipped its EF.ICCID is read and the preset with the same ICCID is selected automatically in both SCP80 views. The header shows gray **SCP80** / **SCP81** markers and a key glyph on the **ADM** badge when the preset matching the equipped card's ICCID has those settings filled in.
|
||||||
|
|
||||||
| Field | Description |
|
| Field | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Name | Human-readable label (required) |
|
| Name | Human-readable label (required) |
|
||||||
| ICCID | Optional card identifier |
|
| ICCID | Optional card identifier |
|
||||||
|
| ADM | Optional administrator PIN (hex, or up to 8 ASCII digits), stored for the file manager; not used by the SCP80/SCP81 views |
|
||||||
| SPI1 / SPI2 | Security level and PoR settings |
|
| SPI1 / SPI2 | Security level and PoR settings |
|
||||||
| KIc / KID index | Key version number (required together with the keys) |
|
| KIc / KID index | Key version number (required together with the keys) |
|
||||||
| KIc / KID key | Encryption and MAC key hex |
|
| KIc / KID key | Encryption and MAC key hex |
|
||||||
| TAR | Toolkit Application Reference (3 bytes) |
|
| ISD TAR | Issuer Security Domain TAR (TS 101 220 Annex D), used for RAM/GP operations; spec default `000000` |
|
||||||
|
| UICC RFM TAR | UICC Shared File System RFM TAR (TS 102 226 §7.2), used by the SIM RFM view; spec default `B00000` |
|
||||||
|
| ADF RFM TAR | ADF RFM TAR (TS 102 226 §7.3), linked to the ADF AID (ADF.USIM in the USIM RFM view); spec default `B00001` |
|
||||||
| Counter (CNTR) | 10-digit hex replay counter, auto-incremented after each successful SCP80 send |
|
| Counter (CNTR) | 10-digit hex replay counter, auto-incremented after each successful SCP80 send |
|
||||||
| PSK identity | SCP81 HTTP OTA: the identity the card sends in the TLS handshake |
|
| PSK identity | SCP81 HTTP OTA: the identity the card sends in the TLS handshake |
|
||||||
| PSK key | SCP81 HTTP OTA: 32 hex chars (16 bytes); the listener picks it by the identity the card presents |
|
| PSK key | SCP81 HTTP OTA: 32 hex chars (16 bytes); the listener picks it by the identity the card presents |
|
||||||
|
|
||||||
The **SCP81** column shows whether the preset supplies a usable PSK pair: **✓** (identity and key), **⚠** (only one of the two — the listener ignores such a preset), **—** (no PSK). Identity and key must be set together.
|
The **SCP81** column shows whether the preset supplies a usable PSK pair: **✓** (identity and key), **⚠** (only one of the two — the listener ignores such a preset), **—** (no PSK). Identity and key must be set together.
|
||||||
|
|
||||||
**Add a card:** fill in the name, ICCID (optional — **From card** fills it from the equipped card's EF.ICCID), SPI1/SPI2, KIc/KID keys and indices, TAR, the SCP81 PSK pair (optional) and click **Add**. A duplicate ICCID (compared ignoring spaces and the raw-hex form) is refused, naming the conflicting preset. The card appears in the list and becomes available in the RAM tab's **Card preset** dropdown.
|
**Add a card:** fill in the name, ICCID (optional — **From card** fills it from the equipped card's EF.ICCID), the optional **ADM**, SPI1/SPI2, KIc/KID keys and indices, the three TARs, the SCP81 PSK pair (optional) and click **Add**. A duplicate ICCID (compared ignoring spaces and the raw-hex form) is refused, naming the conflicting preset. The card appears in the list and becomes available in the RAM tab's **Card preset** dropdown.
|
||||||
|
|
||||||
**Edit / remove:** **Edit** loads a preset into the form (the Add button becomes **Save**; **Cancel** clears the form); **Remove** deletes the row from `localStorage`. A successful SCP80 send advances and stores the replay counter, and edits are pushed into a running SCP81 listener automatically.
|
**Edit / remove:** **Edit** loads a preset into the form (the Add button becomes **Save**; **Cancel** clears the form); **Remove** deletes the row from `localStorage`. A successful SCP80 send advances and stores the replay counter, and edits are pushed into a running SCP81 listener automatically.
|
||||||
|
|
||||||
@@ -495,15 +498,13 @@ Connects to the bundled [`pysim-simple-server`](pysim_simple_server/) for live c
|
|||||||
|
|
||||||
### File Browser
|
### File Browser
|
||||||
|
|
||||||
Browse the UICC filesystem in a tree view. Files are shown with names, FIDs, and AIDs (for ADFs). Click to read contents.
|
Browse the UICC filesystem in a tree view. Files are shown with names, FIDs, and AIDs (for ADFs). Selecting a file shows its detail pane: FID, file type, size / record layout and the decoded FCI (in a bordered block labelled with the file's symbolic name) above the content pane.
|
||||||
|
|
||||||
- Entries are grouped with DFs above EFs and sorted by **FID** or symbolic **Name** (pills above the tree, remembered in `localStorage`)
|
- Entries are grouped with DFs above EFs and sorted by **FID** or symbolic **Name** (pills pinned above the tree together with **Probe all files**, remembered in `localStorage`)
|
||||||
- **Read** — reads the selected file (auto-detects transparent vs record files)
|
- **Read raw** / **Read decoded** — read the selected file as a hex dump or as a decoded field table (client-side decoders for IMSI, ICCID, SPN, PLMN lists, LOCI/EPSLOCI, ADN/MSISDN, service tables, SUME, …); the highlighted pill is the current view and clicking either pill (re-)reads the file. The server-side pySim JSON of the same read stays behind a collapsed *pySim JSON (server)* disclosure; **Read decoded** is disabled when the client-side decoders do not cover the file (resolved by name/FID before reading)
|
||||||
- **Edit** — switch to edit mode, modify hex data, click **Save** to write back
|
- **Edit raw** — edit the raw hex data and **Save** to write back (or **Cancel**); transparent files use a textarea, record files one input per record with selection checkboxes. The decoded view is read-only — **Edit raw** switches to the hex view first and reads the file if needed
|
||||||
- **Raw / Decoded** — toggle between the hex dump and a decoded field table (client-side decoders for IMSI, ICCID, SPN, PLMN lists, LOCI/EPSLOCI, ADN/MSISDN, service tables, SUME, …); the server-side pySim JSON of the same read stays behind a collapsed disclosure
|
- **Probe all files** — walks the whole tree (incl. custom files), marks every entry present/absent with *N / total* progress, stoppable, and ends with a summary; browsing itself stays lazy. Missing files are shown in red (✗); a present but empty DF shows `(empty)`
|
||||||
- Selecting a file shows its FID, file type, size / record layout and the decoded FCI above the contents
|
- **ADM** — files that need the administrator PIN fail with `6982`/`9804`; when the matching card preset (same ICCID) carries an ADM key, a **Verify ADM** button appears next to the error and the header badge (`ADM ✓/✗ ⚿`) becomes clickable. Every wrong key consumes an attempt (the remaining attempts are shown and a retry asks for confirmation); a blocked ADM needs the card's unblock key
|
||||||
- Missing files are shown in red (✗); a present but empty DF shows `(empty)`
|
|
||||||
- **Probe all files** — walks the whole tree (incl. custom files), marks every entry present/absent with *N / total* progress, stoppable, and ends with a summary; browsing itself stays lazy
|
|
||||||
|
|
||||||
### Command Hints
|
### Command Hints
|
||||||
|
|
||||||
@@ -516,7 +517,7 @@ Type a command name in the **pySim command line** input. Usage hints appear as a
|
|||||||
Verifies that a card matches a named **profile** — an ordered set of rules describing the expected file system and, optionally, file contents. Profiles are stored in `localStorage`.
|
Verifies that a card matches a named **profile** — an ordered set of rules describing the expected file system and, optionally, file contents. Profiles are stored in `localStorage`.
|
||||||
|
|
||||||
- **New profile** creates an empty ruleset; **Profile from card** scans the equipped card and generates one rule per existing file; **Profile from snapshot** generates the same ruleset from a saved snapshot (same ignore/mask/FCP-FCI options, no card reader, name prefilled from the snapshot); **Import profile** loads a ruleset from JSON (the name is stored inside the file).
|
- **New profile** creates an empty ruleset; **Profile from card** scans the equipped card and generates one rule per existing file; **Profile from snapshot** generates the same ruleset from a saved snapshot (same ignore/mask/FCP-FCI options, no card reader, name prefilled from the snapshot); **Import profile** loads a ruleset from JSON (the name is stored inside the file).
|
||||||
- Each profile row has **Check card ▶** (run against the equipped card), **Check card snapshot** (run offline against a saved snapshot), **Edit**, **Export**, and **Delete**.
|
- Each profile row has **Check card ▶** (run against the equipped card), **Check card snapshot** (run offline against a saved snapshot), **Edit**, **Clone** (copies the profile as *Copy of <name>* and opens the copy in the editor), **Export** (download JSON), and **Delete**.
|
||||||
|
|
||||||
A filesystem rule is defined by:
|
A filesystem rule is defined by:
|
||||||
|
|
||||||
@@ -533,7 +534,7 @@ The scan dialog asks for a profile name and offers the FCP/FCI mode described ab
|
|||||||
|
|
||||||
#### Card snapshots
|
#### Card snapshots
|
||||||
|
|
||||||
The list view has two tabs — **Profiles** and **Card snapshots**. A snapshot is an immutable capture of the card filesystem: for every existing file it stores the path, symbolic name, file type, size (or record length/count), the raw FCI from the SELECT response, and the contents whenever the file is readable (no ignore list, no masking). The ICCID is decoded from EF.ICCID and shown next to the snapshot name. Captured contents are shown with their decoded form where a decoder exists — a field table for transparent files and a one-line summary per record for record files. The scan also measures every card command (SELECT / READ BINARY / READ RECORD) from command to response and stores min/avg/max per type plus the total scan time; the snapshot view shows these in the summary and the select/read time per file (read time per record). Timings are display-only and ignored by checks/comparisons.
|
The list view has three tabs — **Profiles**, **Card snapshots** and **Custom files**. A snapshot is an immutable capture of the card filesystem: for every existing file it stores the path, symbolic name, file type, size (or record length/count), the raw FCI from the SELECT response, and the contents whenever the file is readable (no ignore list, no masking). The ICCID is decoded from EF.ICCID and shown next to the snapshot name. Captured contents are shown with their decoded form where a decoder exists — a field table for transparent files and a one-line summary per record for record files. The scan also measures every card command (SELECT / READ BINARY / READ RECORD) from command to response and stores min/avg/max per type plus the total scan time; the snapshot view shows these in the summary and the select/read time per file (read time per record). Timings are display-only and ignored by checks/comparisons.
|
||||||
|
|
||||||
- **New snapshot** scans the card; **Import snapshot** loads JSON.
|
- **New snapshot** scans the card; **Import snapshot** loads JSON.
|
||||||
- Each snapshot row has **Open** (all captured data read-only, raw FCI with decoded FCI and contents; only the name is editable), **Export**, and **Delete**.
|
- Each snapshot row has **Open** (all captured data read-only, raw FCI with decoded FCI and contents; only the name is editable), **Export**, and **Delete**.
|
||||||
@@ -547,19 +548,17 @@ The list view has two tabs — **Profiles** and **Card snapshots**. A snapshot i
|
|||||||
|
|
||||||
#### Custom files
|
#### Custom files
|
||||||
|
|
||||||
Files not in pysim's model can be added manually:
|
Files not in pysim's model can be added manually from the **Custom files** tab in the Profiler list:
|
||||||
|
|
||||||
1. Switch to the **Custom files** tab in the Profiler list
|
1. Pick the **Root (MF / ADF)** and type the **Parent DF** path — the root itself, a standard DF known from the file-manager tree, or a custom DF (any depth; suggestions while you type). A parent that has not been seen in the tree yet stays valid and is marked `⚠`
|
||||||
2. Enter the file path (e.g., `3F00/6F46`) and an alias (e.g., `EF.SPN`)
|
2. Enter the 4-hex **FID** and an alias (`EF.…`/`DF.…`; the prefix decides whether the entry is an EF or a DF)
|
||||||
3. Click **Add** — the file appears in the tree in italics (unverified)
|
3. Click **Add** — the file appears in the File manager tree; use **Edit** on a row to reload it into the form (the button becomes **Save**, **Cancel** aborts) or **Delete** to remove it (deleting a DF also deletes its child entries after a confirmation)
|
||||||
4. Use **Edit** on a row to reload it into the form (the button becomes **Save** and a **Cancel** button appears) or **Delete** to remove it
|
|
||||||
5. Click the file to verify existence — on success, it behaves like a model file
|
|
||||||
|
|
||||||
Custom files persist in `localStorage` across sessions. Export/import as JSON for sharing.
|
The canonical path removes the old ambiguity where the same file could be described both relatively and absolutely. Custom files persist in `localStorage` across sessions and are included in card scans under the same existence check. Export/import as JSON for sharing; legacy relative paths (e.g. `a153/4954`) are resolved on load, unresolvable ones are dropped and reported in the list.
|
||||||
|
|
||||||
## Phone simulator
|
## Phone simulator
|
||||||
|
|
||||||
The **Phone simulator** tab provides real-time CAT session interaction. It has two pills: **Phone** (STK menu, STATUS and polling, subscribed events, proactive command log) and **TR Config** (response data injected into TERMINAL RESPONSEs for proactive commands).
|
The **Phone simulator** tab provides real-time CAT session interaction. It has three pills: **Phone** (STK menu, STATUS and polling, subscribed events, proactive command log), **TR Config** (response data injected into TERMINAL RESPONSEs for proactive commands) and **eSIM** (local eUICC operations).
|
||||||
|
|
||||||
**Subscribed Events** — the card's SET UP EVENT LIST is displayed with per-event **Send** buttons. Clicking opens a form specific to the event type:
|
**Subscribed Events** — the card's SET UP EVENT LIST is displayed with per-event **Send** buttons. Clicking opens a form specific to the event type:
|
||||||
|
|
||||||
@@ -574,7 +573,7 @@ The **Phone simulator** tab provides real-time CAT session interaction. It has t
|
|||||||
technology selection, and 53-cause unified rejection cause code dropdown
|
technology selection, and 53-cause unified rejection cause code dropdown
|
||||||
covering EMM, GMM, 5GMM, and LU causes
|
covering EMM, GMM, 5GMM, and LU causes
|
||||||
|
|
||||||
**Proactive Command Log** — chronological list of proactive commands encountered (seconds elapsed, type code, name, byte count). Covers SET UP MENU, SET UP EVENT LIST, POLL INTERVAL, DISPLAY TEXT, SELECT ITEM, PROVIDE LOCAL INFORMATION, TIMER MANAGEMENT, and the BIP commands (OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA, GET CHANNEL STATUS); BIP commands are decoded with both plain and comprehension-required TLV tags.
|
**Proactive Command Log** — chronological list of proactive commands encountered (elapsed time, type code, name and a decoded qualifier; expanding a row shows the decoded command and the TERMINAL RESPONSE). Covers SET UP MENU, SET UP EVENT LIST, POLL INTERVAL, DISPLAY TEXT, SELECT ITEM, PROVIDE LOCAL INFORMATION, TIMER MANAGEMENT, REFRESH and the BIP commands (OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA, GET CHANNEL STATUS); BIP commands are decoded with both plain and comprehension-required TLV tags.
|
||||||
|
|
||||||
**Timer management** — the server acts as the terminal for TIMER MANAGEMENT (TS 102 223 §6.6.21/§7.4): started timers are tracked per card session, deactivate/get TERMINAL RESPONSEs carry the remaining value, and on expiry the card receives ENVELOPE (TIMER EXPIRATION). The live card uses this to retry the OTA session after a failed OPEN CHANNEL.
|
**Timer management** — the server acts as the terminal for TIMER MANAGEMENT (TS 102 223 §6.6.21/§7.4): started timers are tracked per card session, deactivate/get TERMINAL RESPONSEs carry the remaining value, and on expiry the card receives ENVELOPE (TIMER EXPIRATION). The live card uses this to retry the OTA session after a failed OPEN CHANNEL.
|
||||||
|
|
||||||
@@ -595,7 +594,11 @@ The **Phone simulator** tab provides real-time CAT session interaction. It has t
|
|||||||
|
|
||||||
Values persist on the server until restart. Apply → hex updates; Save → POSTs to server. The server will use these values to populate TERMINAL RESPONSE data for future PLI proactive commands.
|
Values persist on the server until restart. Apply → hex updates; Save → POSTs to server. The server will use these values to populate TERMINAL RESPONSE data for future PLI proactive commands.
|
||||||
|
|
||||||
**Network simulation** — replays the card-facing write patterns of a real phone on network-condition changes (trace study: `projects/UICC_NAA.md`): **Cold boot**, **EPS attach**, **2G attach**, **Service lost**, **Limited service**, **Roaming denied**, **Churn**, **SMS received**, **CB reconfig** and **AUTHENTICATE**. Each scenario sends the Location status event (only when the card subscribed to it), updates the EPS NAS context, location files, Kc and CB/SMS files exactly as observed, and logs every step with its SW. Parameters (collapsed) cover the operator (searchable worldwide MCC/MNC list served by the server, plus a random roaming picker), LAC/Cell ID/TAC/RAC, optional identity values (empty = random: TMSI, GUTI, KSI, KASME, Kc, NAS counts, algorithm, RAND/AUTN), scenario toggles and the churn count/delay. Only UPDATE BINARY/RECORD, ENVELOPE and AUTHENTICATE are sent; FPLMN and 5GS location files are never touched. The operator list is bundled (`pysim_simple_server/data/mcc-mnc-list.json`, MIT; MVNO entries are hidden — the picker lists real networks), and `--mcc-mnc-list` overrides it.
|
**Network simulation** — replays the card-facing write patterns of a real phone on network-condition changes (trace study: `projects/UICC_NAA.md`): **Cold boot**, **EPS attach**, **2G attach**, **Service lost**, **Limited service**, **Roaming denied**, **Churn**, **SMS received**, **CB reconfig** and **AUTHENTICATE**. Each scenario sends the Location status event (only when the card subscribed to it), updates the EPS NAS context, location files, Kc and CB/SMS files exactly as observed, and logs every step with its SW. Parameters (collapsed) cover the operator (searchable worldwide MCC/MNC list served by the server, plus a random roaming picker and a **Home network** button that fills the card's HPLMN from EF.HPLMNwAcT's first record, falling back to the IMSI), LAC/Cell ID/TAC/RAC, optional identity values (empty = random: TMSI, GUTI, KSI, KASME, Kc, NAS counts, algorithm, RAND/AUTN), scenario toggles and the churn count/delay. Only UPDATE BINARY/RECORD, ENVELOPE and AUTHENTICATE are sent; EF.FPLMN is appended only by **Roaming denied** (TS 31.102 §4.2.16, duplicates skipped) and an attach to a listed PLMN clears its entry first (successful manual selection, TS 23.122), while the 5GS location files are never written. The operator list is bundled (`pysim_simple_server/data/mcc-mnc-list.json`, MIT; MVNO entries are hidden — the picker lists real networks), and `--mcc-mnc-list` overrides it.
|
||||||
|
|
||||||
|
**Network state monitor** — a compact **Network state** panel next to the simulation buttons shows what the card currently holds and what was last simulated. Its header carries the **simulated service state** (*Undefined* until a scenario or a Location status event sets it, then *Normal service* / *Limited service* / *No service*) with a *PLMN not allowed* marker when the location files or EF.FPLMN show a rejection, plus the current location: PLMN, country and operator, the LAI/RAI/TAI, and the **roaming class** (*Home* when the PLMN equals the HPLMN, *Home equivalent* when it is in EF.EHPLMN, otherwise *Guest*). Below it, one compact line per monitored file (IMSI, EHPLMN, SPDI, HPLMNwAcT, LOCI, PSLOCI, EPSLOCI, EPSNSC, CBMI, CBMIR, SMSstatus, FPLMN) with its decoded summary and how it was last updated (`init`, `write`, `read`, `refresh`); hover for the full decoded fields — long PLMN lists are abbreviated (EF.HPLMNwAcT shows only the first network plus a `… +N` counter). The panel reads the files once at equip (only when the ICCID was readable), updates them in place from the bytes the simulator wrote, re-reads EF.IMSI after every scenario and Location-status event, and never polls the card — **Refresh** re-reads all files on demand.
|
||||||
|
|
||||||
|
**eSIM** — for an eUICC (SGP.22/SGP.32) the **eSIM** pill reads the chip and manages the installed profiles through the local ES10 interface (via pySim, no SM-DP+ contact): **Chip** (EID, EUICCInfo1/2, configured default SM-DP+ / root DS addresses), **Profiles** (state, nickname, provider, ICCID, ISD-P AID, class, owner; **Enable**/**Disable** switches a profile — the card usually sends REFRESH first and the card session is then re-initialized like an equip, so the ICCID, network state and every cached card view are re-read) and **Notifications** (read-only pending list). No profile downloads, no notification handling and no SM-DP+ interaction — only the local ES10a/b/c functions are used; a non-eUICC card is reported as such.
|
||||||
|
|
||||||
## SCP81
|
## SCP81
|
||||||
|
|
||||||
@@ -686,6 +689,7 @@ pysim-simple-server --http-port 8080
|
|||||||
| `--sms-oa` / `--sms-sm-sc` | SMS-DELIVER originating address / SM-SC for PoR-in-submit |
|
| `--sms-oa` / `--sms-sm-sc` | SMS-DELIVER originating address / SM-SC for PoR-in-submit |
|
||||||
| `--terminal-profile` | TERMINAL PROFILE payload hex (default: 33-byte real-handset profile that advertises BIP events/commands; the live card ignores HTTP OTA without it) |
|
| `--terminal-profile` | TERMINAL PROFILE payload hex (default: 33-byte real-handset profile that advertises BIP events/commands; the live card ignores HTTP OTA without it) |
|
||||||
| `--poll-interval` | Idle interval before automatic STATUS polling (default 30s; `0` disables polling) |
|
| `--poll-interval` | Idle interval before automatic STATUS polling (default 30s; `0` disables polling) |
|
||||||
|
| `--mcc-mnc-list` | Override the bundled worldwide MCC/MNC operator list (`pysim_simple_server/data/mcc-mnc-list.json`) |
|
||||||
| `--full-pysim-init` | Use pysim's stock init/equip (redundant card resets). The default init/equip is reset-free — only explicit equip/reset reconnect the card |
|
| `--full-pysim-init` | Use pysim's stock init/equip (redundant card resets). The default init/equip is reset-free — only explicit equip/reset reconnect the card |
|
||||||
| `--no-auto-equip` | Do not initialize a card automatically right after it is inserted (default: auto-equip on) |
|
| `--no-auto-equip` | Do not initialize a card automatically right after it is inserted (default: auto-equip on) |
|
||||||
| `--menu-timeout` | Auto-answer a paused STK command with a timeout TERMINAL RESPONSE (default 60s; `0` disables) |
|
| `--menu-timeout` | Auto-answer a paused STK command with a timeout TERMINAL RESPONSE (default 60s; `0` disables) |
|
||||||
@@ -708,4 +712,4 @@ See [docs/api.md](docs/api.md) for the full endpoint reference.
|
|||||||
| any | older major | ❌ Outdated — update server |
|
| any | older major | ❌ Outdated — update server |
|
||||||
| any | newer major | ⚠️ Server newer — update PWA |
|
| any | newer major | ⚠️ Server newer — update PWA |
|
||||||
|
|
||||||
The PWA checks the server version on connect via `GET /api/version` and compares the major version (e.g. a 2.x PWA with a 2.x server; a 1.x server is flagged as outdated).
|
The PWA checks the server version on connect via `GET /api/version` and compares the major version (e.g. a 3.x PWA with a 3.x server; a 2.x server is flagged as outdated).
|
||||||
|
|||||||
+31
-24
@@ -439,23 +439,26 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
|
|
||||||
## Карты
|
## Карты
|
||||||
|
|
||||||
Хранит сохранённые конфигурации карт (пресеты) в `localStorage`. Пресет содержит криптографические ключи, настройки SPI, TAR и счётчик повторов для SCP80-операций, а также пару **PSK identity / PSK key** для слушателя SCP81 HTTP OTA. «Карты» — **верхнеуровневая вкладка**. При подключении карты читается её EF.ICCID, и пресет с тем же ICCID автоматически выбирается в обоих видах SCP80.
|
Хранит сохранённые конфигурации карт (пресеты) в `localStorage`. Пресет содержит криптографические ключи, настройки SPI, TAR-ы и счётчик повторов для SCP80-операций, необязательный ключ **ADM**, а также пару **PSK identity / PSK key** для слушателя SCP81 HTTP OTA. «Карты» — **верхнеуровневая вкладка**. Поля формы сгруппированы в два блока с рамкой — **SCP80 (GSM 03.48, ETSI TS 102 225)** и **SCP81 (HTTP OTA)**; необязательное поле **ADM** находится в верхней строке. При подключении карты читается её EF.ICCID, и пресет с тем же ICCID автоматически выбирается в обоих видах SCP80. В шапке отображаются серые маркеры **SCP80** / **SCP81** и значок ключа на бейдже **ADM**, когда в пресете с ICCID подключённой карты эти поля заполнены.
|
||||||
|
|
||||||
| Поле | Описание |
|
| Поле | Описание |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Name | Понятная метка (обязательна) |
|
| Name | Понятная метка (обязательна) |
|
||||||
| ICCID | Опциональный идентификатор карты; кнопка **С карты** подставляет EF.ICCID подключённой карты (активна, только когда ICCID читается) |
|
| ICCID | Опциональный идентификатор карты; кнопка **С карты** подставляет EF.ICCID подключённой карты (активна, только когда ICCID читается) |
|
||||||
|
| ADM | Необязательный администраторский PIN (hex или до 8 ASCII-цифр), сохраняется для файлового менеджера; представлениями SCP80/SCP81 не используется |
|
||||||
| SPI1 / SPI2 | Уровень безопасности и настройки PoR |
|
| SPI1 / SPI2 | Уровень безопасности и настройки PoR |
|
||||||
| Индекс KIc / KID | Номер версии ключа (задаётся вместе с ключами) |
|
| Индекс KIc / KID | Номер версии ключа (задаётся вместе с ключами) |
|
||||||
| Ключ KIc / KID | Hex-ключи шифрования и MAC |
|
| Ключ KIc / KID | Hex-ключи шифрования и MAC |
|
||||||
| TAR | Toolkit Application Reference (3 байта) |
|
| ISD TAR | TAR Issuer Security Domain (TS 101 220 Annex D), используется для операций RAM/GP; умолчание `000000` |
|
||||||
|
| UICC RFM TAR | TAR UICC Shared File System RFM (TS 102 226 §7.2), используется в представлении SIM RFM; умолчание `B00000` |
|
||||||
|
| ADF RFM TAR | TAR ADF RFM (TS 102 226 §7.3), привязан к AID приложения (ADF.USIM в представлении USIM RFM); умолчание `B00001` |
|
||||||
| Счётчик (CNTR) | 10-значный hex-счётчик повторов, автоматически увеличивается после каждой успешной отправки SCP80 |
|
| Счётчик (CNTR) | 10-значный hex-счётчик повторов, автоматически увеличивается после каждой успешной отправки SCP80 |
|
||||||
| PSK identity | SCP81 HTTP OTA: идентификатор, который карта присылает в TLS-рукопожатии |
|
| PSK identity | SCP81 HTTP OTA: идентификатор, который карта присылает в TLS-рукопожатии |
|
||||||
| PSK key | SCP81 HTTP OTA: 32 hex-символа (16 байт); ключ выбирается по идентификатору, который предъявляет карта |
|
| PSK key | SCP81 HTTP OTA: 32 hex-символа (16 байт); ключ выбирается по идентификатору, который предъявляет карта |
|
||||||
|
|
||||||
Столбец **SCP81** показывает, задана ли в пресете рабочая пара PSK: **✓** (идентификатор и ключ), **⚠** (только одно из двух — слушатель такой пресет игнорирует), **—** (PSK нет). Идентификатор и ключ задаются вместе.
|
Столбец **SCP81** показывает, задана ли в пресете рабочая пара PSK: **✓** (идентификатор и ключ), **⚠** (только одно из двух — слушатель такой пресет игнорирует), **—** (PSK нет). Идентификатор и ключ задаются вместе.
|
||||||
|
|
||||||
**Добавить карту:** заполните имя, ICCID (опционально — кнопка **С карты** подставляет EF.ICCID подключённой карты), SPI1/SPI2, ключи и индексы KIc/KID, TAR, при необходимости пару PSK и нажмите **Add**. Дубликат ICCID (сравнение без пробелов и с учётом сырой hex-формы) отклоняется с указанием конфликтующего пресета. Карта появится в списке и станет доступна в выпадающем списке **Card preset** на вкладке RAM.
|
**Добавить карту:** заполните имя, ICCID (опционально — кнопка **С карты** подставляет EF.ICCID подключённой карты), необязательный **ADM**, SPI1/SPI2, ключи и индексы KIc/KID, три TAR-а, при необходимости пару PSK и нажмите **Add**. Дубликат ICCID (сравнение без пробелов и с учётом сырой hex-формы) отклоняется с указанием конфликтующего пресета. Карта появится в списке и станет доступна в выпадающем списке **Card preset** на вкладке RAM.
|
||||||
|
|
||||||
**Изменить/удалить:** **Edit** загружает пресет в форму (кнопка Add становится **Save**; **Cancel** очищает форму); **Remove** удаляет строку из `localStorage`. Успешная отправка SCP80 увеличивает и сохраняет счётчик повторов, а изменения сразу передаются работающему слушателю SCP81.
|
**Изменить/удалить:** **Edit** загружает пресет в форму (кнопка Add становится **Save**; **Cancel** очищает форму); **Remove** удаляет строку из `localStorage`. Успешная отправка SCP80 увеличивает и сохраняет счётчик повторов, а изменения сразу передаются работающему слушателю SCP81.
|
||||||
|
|
||||||
@@ -469,15 +472,13 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
|
|
||||||
### Файловый менеджер
|
### Файловый менеджер
|
||||||
|
|
||||||
Дерево файлов UICC. Отображаются имена, FID и AID (для ADF). Клик для чтения содержимого.
|
Дерево файлов UICC. Отображаются имена, FID и AID (для ADF). При выборе файла открывается панель деталей: FID, тип файла, размер / структура записей и декодированный FCI (в блоке с рамкой и именем файла) над панелью содержимого.
|
||||||
|
|
||||||
- Элементы сгруппированы (DF выше EF) и отсортированы по **FID** или символьному **имени** (пиллы над деревом, выбор сохраняется в `localStorage`)
|
- Элементы сгруппированы (DF выше EF) и отсортированы по **FID** или символьному **имени** (пиллы закреплены над деревом вместе с **«Проверить все файлы»**, выбор сохраняется в `localStorage`)
|
||||||
- **Read** — чтение файла (автоопределение transparent/record)
|
- **Read raw** / **Read decoded** — чтение выбранного файла как hex-дампа или как таблицы декодированных полей (клиентские декодеры: IMSI, ICCID, SPN, списки PLMN, LOCI/EPSLOCI, ADN/MSISDN, таблицы сервисов, SUME, …); подсвеченная пилла — текущий вид, клик по любой из них перечитывает файл. Серверный pySim JSON того же чтения остаётся в свёрнутом блоке *pySim JSON (server)*; **Read decoded** отключается, когда клиентские декодеры не покрывают файл (определяется по имени/FID до чтения)
|
||||||
- **Edit** — режим редактирования, измените hex-данные и нажмите **Save** для записи
|
- **Edit raw** — редактирование сырых hex-данных и **Save** для записи (или **Cancel**); для transparent-файлов — textarea, для record-файлов — по полю на запись с флажками выбора. Декодированный вид только для чтения — **Edit raw** сначала переключается на hex и при необходимости читает файл
|
||||||
- **Raw / Decoded** — переключение между hex-дампом и таблицей декодированных полей (клиентские декодеры: IMSI, ICCID, SPN, списки PLMN, LOCI/EPSLOCI, ADN/MSISDN, таблицы сервисов, SUME, …); серверный pySim JSON того же чтения остаётся в свёрнутом блоке
|
- **Проверить все файлы** — обход всего дерева (включая пользовательские) с пометкой «есть/нет», прогрессом *N / всего*, возможностью остановки и сводкой в конце; сам просмотр остаётся ленивым. Отсутствующие файлы показаны красным (✗); существующий пустой DF — `(пусто)`
|
||||||
- При выборе файла над содержимым показываются FID, тип файла, размер / структура записей и декодированный FCI
|
- **ADM** — файлы, требующие администраторский PIN, возвращают `6982`/`9804`; если в подходящей предустановке карты (тот же ICCID) есть ключ ADM, рядом с ошибкой появляется кнопка **«Проверить ADM»**, а значок в заголовке (`ADM ✓/✗ ⚿`) становится кликабельным. Каждый неверный ключ расходует попытку (остаток показывается, повторная попытка требует подтверждения); заблокированный ADM требует ключа разблокировки карты
|
||||||
- Отсутствующие файлы показаны красным (✗); существующий пустой DF — `(пусто)`
|
|
||||||
- **Проверить все файлы** — обход всего дерева (включая пользовательские) с пометкой «есть/нет», прогрессом *N / всего*, возможностью остановки и сводкой в конце; сам просмотр остаётся ленивым
|
|
||||||
|
|
||||||
### Подсказки команд
|
### Подсказки команд
|
||||||
|
|
||||||
@@ -490,7 +491,7 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
Проверка соответствия карты именованному **профилю** — упорядоченному набору правил, описывающих ожидаемую файловую систему и (опционально) содержимое файлов. Профили хранятся в `localStorage`.
|
Проверка соответствия карты именованному **профилю** — упорядоченному набору правил, описывающих ожидаемую файловую систему и (опционально) содержимое файлов. Профили хранятся в `localStorage`.
|
||||||
|
|
||||||
- **Новый профиль** создаёт пустой набор правил; **Профиль с карты** сканирует подключённую карту и создаёт по правилу на каждый существующий файл; **Профиль из снимка** создаёт тот же набор правил из сохранённого снимка (те же опции игнорирования/масок/FCP-FCI, без картридера, имя подставляется из снимка); **Импорт профиля** загружает набор из JSON (имя хранится внутри файла).
|
- **Новый профиль** создаёт пустой набор правил; **Профиль с карты** сканирует подключённую карту и создаёт по правилу на каждый существующий файл; **Профиль из снимка** создаёт тот же набор правил из сохранённого снимка (те же опции игнорирования/масок/FCP-FCI, без картридера, имя подставляется из снимка); **Импорт профиля** загружает набор из JSON (имя хранится внутри файла).
|
||||||
- В каждой строке профиля: **Проверить карту ▶** (на подключённой карте), **Проверить снимок карты** (offline по сохранённому снимку), **Редактировать**, **Экспорт** и **Удалить**.
|
- В каждой строке профиля: **Проверить карту ▶** (на подключённой карте), **Проверить снимок карты** (offline по сохранённому снимку), **Редактировать**, **Клонировать** (копия профиля под именем *Copy of <имя>* открывается в редакторе), **Экспорт** (скачать JSON) и **Удалить**.
|
||||||
|
|
||||||
Правило файловой системы задаётся:
|
Правило файловой системы задаётся:
|
||||||
|
|
||||||
@@ -507,7 +508,7 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
|
|
||||||
#### Снимки карт
|
#### Снимки карт
|
||||||
|
|
||||||
Представление списка имеет две вкладки — **«Профили»** и **«Снимки карт»**. Снимок — неизменяемая фиксация файловой системы: путь, символьное имя, тип, размер (или длина/число записей), сырой FCI и содержимое (если читается) каждого существующего файла. ICCID декодируется из EF.ICCID и показывается рядом с именем. Захваченное содержимое показывается вместе с декодированным представлением, где есть декодер — таблица полей для transparent-файлов и однострочная сводка по каждой записи для record-файлов. При сканировании также измеряется время каждой команды карты (SELECT / READ BINARY / READ RECORD) от отправки до ответа; сохраняются min/сред/max по типам и общее время сканирования — они показываются в сводке снимка и по файлам/записям. Время носит информационный характер и не используется при проверках и сравнении.
|
Представление списка имеет три вкладки — **«Профили»**, **«Снимки карт»** и **«Пользовательские файлы»**. Снимок — неизменяемая фиксация файловой системы: путь, символьное имя, тип, размер (или длина/число записей), сырой FCI и содержимое (если читается) каждого существующего файла. ICCID декодируется из EF.ICCID и показывается рядом с именем. Захваченное содержимое показывается вместе с декодированным представлением, где есть декодер — таблица полей для transparent-файлов и однострочная сводка по каждой записи для record-файлов. При сканировании также измеряется время каждой команды карты (SELECT / READ BINARY / READ RECORD) от отправки до ответа; сохраняются min/сред/max по типам и общее время сканирования — они показываются в сводке снимка и по файлам/записям. Время носит информационный характер и не используется при проверках и сравнении.
|
||||||
|
|
||||||
- **Новый снимок** сканирует карту; **Импорт снимка** загружает JSON.
|
- **Новый снимок** сканирует карту; **Импорт снимка** загружает JSON.
|
||||||
- В строке снимка: **Открыть** (все данные только для чтения, сырой FCI с декодированным и содержимое; редактируется только имя), **Экспорт**, **Удалить**.
|
- В строке снимка: **Открыть** (все данные только для чтения, сырой FCI с декодированным и содержимое; редактируется только имя), **Экспорт**, **Удалить**.
|
||||||
@@ -521,30 +522,29 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
|
|
||||||
#### Пользовательские файлы
|
#### Пользовательские файлы
|
||||||
|
|
||||||
Файлы, отсутствующие в модели pysim, можно добавить вручную:
|
Файлы, отсутствующие в модели pysim, можно добавить вручную на вкладке **Custom files** списка профайлера:
|
||||||
|
|
||||||
1. Перейдите на вкладку **Custom files** в списке профайлера
|
1. Выберите **Root (MF / ADF)** и введите путь **Parent DF** — сам корень, стандартный DF из дерева файлового менеджера или пользовательский DF (любая глубина; подсказки при вводе). Родитель, ещё не встреченный в дереве, остаётся допустимым и помечается `⚠`
|
||||||
2. Введите путь (например, `3F00/6F46`) и псевдоним (например, `EF.SPN`)
|
2. Введите 4-hex **FID** и псевдоним (`EF.…`/`DF.…`; префикс определяет, EF это или DF)
|
||||||
3. Нажмите **Add** — файл появится в дереве курсивом (непроверенный)
|
3. Нажмите **Add** — файл появится в дереве файлового менеджера; кнопка **Edit** загружает запись в форму (кнопка становится **Save**, **Cancel** отменяет), **Delete** удаляет запись (удаление DF удаляет и дочерние записи после подтверждения)
|
||||||
4. Кнопка **Edit** загружает запись в форму (кнопка становится **Save**, появляется **Cancel**), **Delete** удаляет запись без подтверждения
|
|
||||||
5. Кликните для проверки существования — при успехе работает как обычный файл
|
|
||||||
|
|
||||||
Пользовательские файлы сохраняются в `localStorage`. Экспорт/импорт в JSON для обмена.
|
Канонический путь убирает прежнюю неоднозначность, когда один и тот же файл можно было описать и относительно, и абсолютно. Пользовательские файлы сохраняются в `localStorage` между сессиями и включаются в сканирование карты с той же проверкой существования. Экспорт/импорт в JSON для обмена; устаревшие относительные пути (напр. `a153/4954`) разрешаются при загрузке, неразрешимые отбрасываются и показываются в списке.
|
||||||
|
|
||||||
## Симулятор телефона
|
## Симулятор телефона
|
||||||
|
|
||||||
Вкладка **«Симулятор телефона»** обеспечивает взаимодействие с CAT-сессией в реальном времени. Две подвкладки: **«Телефон»** (меню STK, STATUS и опрос, подписанные события, журнал проактивных команд) и **«Конфигурация TR»** (данные ответов, подставляемые в TERMINAL RESPONSE для проактивных команд).
|
Вкладка **«Симулятор телефона»** обеспечивает взаимодействие с CAT-сессией в реальном времени. Три подвкладки: **«Телефон»** (меню STK, STATUS и опрос, подписанные события, журнал проактивных команд), **«Конфигурация TR»** (данные ответов, подставляемые в TERMINAL RESPONSE для проактивных команд) и **«eSIM»** (локальные операции с eUICC).
|
||||||
|
|
||||||
**Subscribed Events** — список событий SET UP EVENT LIST с кнопками **Send**. Клик открывает форму для конкретного типа события:
|
**Subscribed Events** — список событий SET UP EVENT LIST с кнопками **Send**. Клик открывает форму для конкретного типа события:
|
||||||
|
|
||||||
- **События без данных** (User Activity, Idle Screen и др.) — однократное уведомление
|
- **События без данных** (User Activity, Idle Screen и др.) — однократное уведомление
|
||||||
- **Location Status** — выпадающий список: Normal / Limited / No service
|
- **Location Status** — выпадающий список: Normal / Limited / No service
|
||||||
- **Access Technology Change** — 13 типов RAT
|
- **Access Technology Change** — 13 типов RAT
|
||||||
|
- **Card Reader Status, Language, UICC Access** — соответствующие поля ввода
|
||||||
- **Channel Status** — выбор канала, состояние линии (не установлена / TCP
|
- **Channel Status** — выбор канала, состояние линии (не установлена / TCP
|
||||||
LISTEN / установлена) и информация (нет данных / линия разорвана), TS 102 223 8.56
|
LISTEN / установлена) и информация (нет данных / линия разорвана), TS 102 223 8.56
|
||||||
- **Network Rejection** — полная адаптивная форма: тип регистрации (LU / GPRS / EPS / 5GS), поля локации (MCC, MNC, LAC, RAC, TAC), доступные технологии, 53-позиционный выпадающий список причин отказа (EMM, GMM, 5GMM, LU)
|
- **Network Rejection** — полная адаптивная форма: тип регистрации (LU / GPRS / EPS / 5GS), поля локации (MCC, MNC, LAC, RAC, TAC), доступные технологии, 53-позиционный выпадающий список причин отказа (EMM, GMM, 5GMM, LU)
|
||||||
|
|
||||||
**Proactive Command Log** — хронологический список проактивных команд. Каждая строка показывает время, код типа, имя и декодированный квалификатор. Поддерживаются SET UP MENU, SET UP EVENT LIST, POLL INTERVAL, DISPLAY TEXT, SELECT ITEM, PROVIDE LOCAL INFORMATION, TIMER MANAGEMENT и BIP-команды (OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA, GET CHANNEL STATUS); BIP-команды декодируются с обычными и comprehension-required TLV-тегами.
|
**Proactive Command Log** — хронологический список проактивных команд. Каждая строка показывает время, код типа, имя и декодированный квалификатор; при раскрытии видны декодированная команда и TERMINAL RESPONSE. Поддерживаются SET UP MENU, SET UP EVENT LIST, POLL INTERVAL, DISPLAY TEXT, SELECT ITEM, PROVIDE LOCAL INFORMATION, TIMER MANAGEMENT, REFRESH и BIP-команды (OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA, GET CHANNEL STATUS); BIP-команды декодируются с обычными и comprehension-required TLV-тегами.
|
||||||
|
|
||||||
**Управление таймерами** — сервер выполняет роль терминала для TIMER MANAGEMENT (TS 102 223 §6.6.21/§7.4): запущенные картой таймеры отслеживаются в рамках сессии, TERMINAL RESPONSE на deactivate/get содержит остаток, а по истечении карта получает ENVELOPE (TIMER EXPIRATION). Живая карта использует это для повторения OTA-сессии после неудачного OPEN CHANNEL.
|
**Управление таймерами** — сервер выполняет роль терминала для TIMER MANAGEMENT (TS 102 223 §6.6.21/§7.4): запущенные картой таймеры отслеживаются в рамках сессии, TERMINAL RESPONSE на deactivate/get содержит остаток, а по истечении карта получает ENVELOPE (TIMER EXPIRATION). Живая карта использует это для повторения OTA-сессии после неудачного OPEN CHANNEL.
|
||||||
|
|
||||||
@@ -565,7 +565,11 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на
|
|||||||
|
|
||||||
Значения сохраняются на сервере до перезапуска. Apply → hex обновляется; Save → POST на сервер.
|
Значения сохраняются на сервере до перезапуска. Apply → hex обновляется; Save → POST на сервер.
|
||||||
|
|
||||||
**Симуляция сети** — воспроизводит шаблоны записи реального телефона при смене сетевых условий (исследование трасс: `projects/UICC_NAA.md`): **Холодная загрузка**, **Подключение EPS**, **Подключение 2G**, **Потеря сервиса**, **Ограниченный сервис**, **Роуминг запрещён**, **Серия переподключений**, **Принято SMS**, **Перенастройка CB** и **AUTHENTICATE**. Каждый сценарий отправляет событие Location status (только если карта на него подписана), обновляет контекст EPS NAS, location-файлы, Kc и файлы CB/SMS в точности как в трассах и журналирует каждый шаг с его SW. Параметры (свёрнуты) задают оператора (поиск по мировому списку MCC/MNC с сервера плюс случайный роуминг-оператор), LAC/Cell ID/TAC/RAC, необязательные идентификаторы (пусто = случайно: TMSI, GUTI, KSI, KASME, Kc, счётчики NAS, алгоритм, RAND/AUTN), переключатели и число циклов/задержку. Отправляются только UPDATE BINARY/RECORD, ENVELOPE и AUTHENTICATE; FPLMN и 5GS location-файлы не затрагиваются. Список операторов входит в поставку (`pysim_simple_server/data/mcc-mnc-list.json`, MIT; записи MVNO скрыты — в списке только реальные сети), переопределяется `--mcc-mnc-list`.
|
**Симуляция сети** — воспроизводит шаблоны записи реального телефона при смене сетевых условий (исследование трасс: `projects/UICC_NAA.md`): **Холодная загрузка**, **Подключение EPS**, **Подключение 2G**, **Потеря сервиса**, **Ограниченный сервис**, **Роуминг запрещён**, **Серия переподключений**, **Принято SMS**, **Перенастройка CB** и **AUTHENTICATE**. Каждый сценарий отправляет событие Location status (только если карта на него подписана), обновляет контекст EPS NAS, location-файлы, Kc и файлы CB/SMS в точности как в трассах и журналирует каждый шаг с его SW. Параметры (свёрнуты) задают оператора (поиск по мировому списку MCC/MNC с сервера, случайный роуминг-оператор и кнопка **«Домашняя сеть»**, заполняющая HPLMN карты из первой записи EF.HPLMNwAcT с откатом на IMSI), LAC/Cell ID/TAC/RAC, необязательные идентификаторы (пусто = случайно: TMSI, GUTI, KSI, KASME, Kc, счётчики NAS, алгоритм, RAND/AUTN), переключатели и число циклов/задержку. Отправляются только UPDATE BINARY/RECORD, ENVELOPE и AUTHENTICATE; EF.FPLMN дописывается только сценарием **«Роуминг запрещён»** (TS 31.102 §4.2.16, без дубликатов), а подключение к сети из списка сначала очищает её запись (успешный ручной выбор, TS 23.122); 5GS location-файлы не записываются. Список операторов входит в поставку (`pysim_simple_server/data/mcc-mnc-list.json`, MIT; записи MVNO скрыты — в списке только реальные сети), переопределяется `--mcc-mnc-list`.
|
||||||
|
|
||||||
|
**Монитор сетевого состояния** — компактная панель **«Сетевое состояние»** рядом с кнопками симуляции показывает, что сейчас хранит карта и что было сэмулировано последним. В заголовке — **сэмулированное состояние сервиса** (*Не определено*, пока его не задаст сценарий или событие Location status, затем *Обычный сервис* / *Ограниченный сервис* / *Нет сервиса*) с пометкой *PLMN не разрешён*, если location-файлы или EF.FPLMN указывают на отказ, плюс текущее местоположение: PLMN, страна и оператор, LAI/RAI/TAI и **класс роуминга** (*Домашняя сеть*, если PLMN совпадает с HPLMN; *Эквивалентная домашней*, если он есть в EF.EHPLMN; иначе *Гостевая (роуминг)*). Ниже — по одной компактной строке на контролируемый файл (IMSI, EHPLMN, SPDI, HPLMNwAcT, LOCI, PSLOCI, EPSLOCI, EPSNSC, CBMI, CBMIR, SMSstatus, FPLMN) с декодированной сводкой и признаком последнего обновления (`init`, `write`, `read`, `refresh`); при наведении — все декодированные поля; длинные списки PLMN сокращаются (EF.HPLMNwAcT показывает только первую сеть и пометку `… +N`). Панель читает файлы один раз при подключении карты (только если ICCID читается), обновляет их на месте по записанным симулятором байтам, перечитывает EF.IMSI после каждого сценария и события Location status и никогда не опрашивает карту — кнопка **«Обновить»** перечитывает все файлы по требованию.
|
||||||
|
|
||||||
|
**eSIM** — для eUICC (SGP.22/SGP.32) подвкладка **«eSIM»** читает чип и управляет установленными профилями через локальный интерфейс ES10 (через pySim, без обращения к SM-DP+): **Chip** (EID, EUICCInfo1/2, настроенные адреса SM-DP+ / root DS), **Profiles** (состояние, nickname, провайдер, ICCID, AID ISD-P, класс, владелец; **Enable**/**Disable** переключает профиль — карта обычно сначала присылает REFRESH, после чего сессия карты переинициализируется как при equip, и ICCID, сетевое состояние и все кэшированные представления перечитываются) и **Notifications** (список ожидающих уведомлений, только чтение). Никаких загрузок профилей, обработки уведомлений и взаимодействия с SM-DP+ — используются только локальные функции ES10a/b/c; для карты не-eUICC подвкладка сообщает об этом.
|
||||||
|
|
||||||
## SCP81
|
## SCP81
|
||||||
|
|
||||||
@@ -620,7 +624,7 @@ SIMple — Progressive Web App. Можно установить для offline-
|
|||||||
| любая | старее мажорная | ❌ Сервер устарел — обновите сервер |
|
| любая | старее мажорная | ❌ Сервер устарел — обновите сервер |
|
||||||
| любая | новее мажорная | ⚠️ Сервер новее — обновите PWA |
|
| любая | новее мажорная | ⚠️ Сервер новее — обновите PWA |
|
||||||
|
|
||||||
PWA проверяет версию сервера при подключении через `GET /api/version` и сравнивает мажорную версию (например, PWA 2.x с сервером 2.x; сервер 1.x помечается как устаревший).
|
PWA проверяет версию сервера при подключении через `GET /api/version` и сравнивает мажорную версию (например, PWA 3.x с сервером 3.x; сервер 2.x помечается как устаревший).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -665,7 +669,10 @@ pysim-simple-server --http-port 8080
|
|||||||
| `--no-card-init` | Пропустить инициализацию карты (сохранить CAT-сессию) |
|
| `--no-card-init` | Пропустить инициализацию карты (сохранить CAT-сессию) |
|
||||||
| `--apdu-trace` | Лог APDU-трафика в stderr |
|
| `--apdu-trace` | Лог APDU-трафика в stderr |
|
||||||
| `--log-requests` | Лог запросов/ответов в stderr |
|
| `--log-requests` | Лог запросов/ответов в stderr |
|
||||||
|
| `--sms-oa` / `--sms-sm-sc` | Адрес отправителя SMS-DELIVER / SM-SC для PoR-in-submit |
|
||||||
|
| `--terminal-profile` | Hex TERMINAL PROFILE (по умолчанию — 33-байтовый профиль реального телефона с BIP-событиями/командами; без него живая карта не запускает HTTP OTA) |
|
||||||
| `--poll-interval` | Интервал автоопроса STATUS (по умолчанию 30с; `0` отключает опрос) |
|
| `--poll-interval` | Интервал автоопроса STATUS (по умолчанию 30с; `0` отключает опрос) |
|
||||||
|
| `--mcc-mnc-list` | Переопределить встроенный мировой список MCC/MNC (`pysim_simple_server/data/mcc-mnc-list.json`) |
|
||||||
| `--full-pysim-init` | Штатная инициализация/equip из pysim (с лишними сбросами карты). По умолчанию инициализация без лишних сбросов — карта переподключается только по явным equip/reset |
|
| `--full-pysim-init` | Штатная инициализация/equip из pysim (с лишними сбросами карты). По умолчанию инициализация без лишних сбросов — карта переподключается только по явным equip/reset |
|
||||||
| `--no-auto-equip` | Не инициализировать карту автоматически сразу после вставки (по умолчанию автоинициализация включена) |
|
| `--no-auto-equip` | Не инициализировать карту автоматически сразу после вставки (по умолчанию автоинициализация включена) |
|
||||||
| `--menu-timeout` | Автоответ timeout TERMINAL RESPONSE на приостановленную STK-команду (по умолчанию 60с; `0` отключает) |
|
| `--menu-timeout` | Автоответ timeout TERMINAL RESPONSE на приостановленную STK-команду (по умолчанию 60с; `0` отключает) |
|
||||||
|
|||||||
+79
-17
@@ -13,8 +13,8 @@ on the preflight), so the API is reachable from a separately-hosted PWA.
|
|||||||
| newer major | any | ⚠️ Server newer — update PWA |
|
| newer major | any | ⚠️ Server newer — update PWA |
|
||||||
|
|
||||||
The server reports its version via `GET /api/version`. The PWA checks this on
|
The server reports its version via `GET /api/version`. The PWA checks this on
|
||||||
connect and compares the major version (a 1.x server is flagged as outdated by
|
connect and compares the major version (a 2.x server is flagged as outdated by
|
||||||
a 2.x PWA).
|
a 3.x PWA).
|
||||||
|
|
||||||
## Endpoints
|
## Endpoints
|
||||||
|
|
||||||
@@ -46,6 +46,8 @@ a 2.x PWA).
|
|||||||
| `/api/events` | GET | Event list from SET UP EVENT LIST |
|
| `/api/events` | GET | Event list from SET UP EVENT LIST |
|
||||||
| `/api/event-send` | POST | Send ENVELOPE(Event Download) |
|
| `/api/event-send` | POST | Send ENVELOPE(Event Download) |
|
||||||
| `/api/net-sim` | POST | Run a network-condition scenario (attach, service loss, roaming, churn, 2G, SMS, CB, AUTHENTICATE) |
|
| `/api/net-sim` | POST | Run a network-condition scenario (attach, service loss, roaming, churn, 2G, SMS, CB, AUTHENTICATE) |
|
||||||
|
| `/api/net-state` | GET | Cached network-state monitor (service, location, per-file state) |
|
||||||
|
| `/api/net-state-refresh` | POST | Re-read the monitored files (optional `files` list) and return the updated monitor state |
|
||||||
| `/api/mcc-mnc` | GET | Search the optional MCC/MNC operator list (`?q=`; `?random=1&exclude=`) |
|
| `/api/mcc-mnc` | GET | Search the optional MCC/MNC operator list (`?q=`; `?random=1&exclude=`) |
|
||||||
| `/api/proactive-log` | GET | Last 50 proactive commands |
|
| `/api/proactive-log` | GET | Last 50 proactive commands |
|
||||||
| `/api/status-poll` | POST | Manual STATUS poll + FETCH if 91XX |
|
| `/api/status-poll` | POST | Manual STATUS poll + FETCH if 91XX |
|
||||||
@@ -74,7 +76,7 @@ Returns server version for compatibility checking.
|
|||||||
|
|
||||||
**Example response:**
|
**Example response:**
|
||||||
```json
|
```json
|
||||||
{"version": "2.1.2"}
|
{"version": "3.0.1"}
|
||||||
```
|
```
|
||||||
|
|
||||||
### `GET /api/status`
|
### `GET /api/status`
|
||||||
@@ -82,8 +84,12 @@ Returns server version for compatibility checking.
|
|||||||
Card reader, card type, current selection, and card state. Reported fields:
|
Card reader, card type, current selection, and card state. Reported fields:
|
||||||
`reader`, `connected`, `card_present`, `card_session` (increments on every
|
`reader`, `connected`, `card_present`, `card_session` (increments on every
|
||||||
equip/disconnect), `proactive_seq`, `equipping`, `auto_equip`, `card`,
|
equip/disconnect), `proactive_seq`, `equipping`, `auto_equip`, `card`,
|
||||||
`profile`, `iccid`, `app_ready`, `adm_verified`, `atr`, `cla_byte`,
|
`profile`, `eid`, `euicc`, `iccid`, `app_ready`, `adm_verified`, `atr`,
|
||||||
`sel_ctrl`, `current_selection`, `channels`.
|
`cla_byte`, `sel_ctrl`, `current_selection`, `channels`.
|
||||||
|
|
||||||
|
`eid` is the eUICC identifier read from the ISD-R at equip (`null` for a
|
||||||
|
non-eUICC card) and `euicc` says whether the equipped card is an eUICC
|
||||||
|
(SGP.22/32); both are used by the PWA's eSIM view.
|
||||||
|
|
||||||
`iccid` is the E.118 digit string read from EF.ICCID (MF/2FE2) when the card is
|
`iccid` is the E.118 digit string read from EF.ICCID (MF/2FE2) when the card is
|
||||||
equipped, or `null` when it is not connected / the card does not let the
|
equipped, or `null` when it is not connected / the card does not let the
|
||||||
@@ -486,6 +492,24 @@ event byte values, or `[]` when none was received).
|
|||||||
|
|
||||||
Sends an `ENVELOPE(Event Download)` for a subscribed event.
|
Sends an `ENVELOPE(Event Download)` for a subscribed event.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"event_type": 4, "event_data": "01A0"}
|
||||||
|
```
|
||||||
|
|
||||||
|
`event_type` is required (the SET UP EVENT LIST event byte); `event_data` is
|
||||||
|
optional hex for events that carry data. Returns the SW and any response data:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"sw": "9000", "data": "..."}
|
||||||
|
```
|
||||||
|
|
||||||
|
Channel status (event `0x0A`, TS 102 223 §8.56) carries the Channel status TLV
|
||||||
|
`B8 02 <status> <info>`, where the status byte is the channel id (1–7) OR-ed
|
||||||
|
with the state bits (0x00 link not established / 0x40 TCP LISTEN / 0x80 link
|
||||||
|
established) and the info byte is `00` (no further info) or `05` (link
|
||||||
|
dropped). The server also sends this event automatically when a BIP link drops
|
||||||
|
outside a proactive command and the card subscribed to `0x0A`.
|
||||||
|
|
||||||
### `POST /api/net-sim`
|
### `POST /api/net-sim`
|
||||||
|
|
||||||
Runs one network-condition scenario from `projects/UICC_NAA.md` section 13
|
Runs one network-condition scenario from `projects/UICC_NAA.md` section 13
|
||||||
@@ -505,26 +529,64 @@ Scenarios: `cold_boot`, `attach_eps`, `attach_2g`, `service_lost`,
|
|||||||
`invalidate_epsnsc`, `keep_kasme`, `write_kc`, `sms_location`, `cb_clear`
|
`invalidate_epsnsc`, `keep_kasme`, `write_kc`, `sms_location`, `cb_clear`
|
||||||
(empty identity values are randomized). The event step is skipped when the
|
(empty identity values are randomized). The event step is skipped when the
|
||||||
card did not subscribe to Location status; only UPDATE BINARY/RECORD,
|
card did not subscribe to Location status; only UPDATE BINARY/RECORD,
|
||||||
ENVELOPE and AUTHENTICATE are sent (never FPLMN/5GS location files). The
|
ENVELOPE and AUTHENTICATE are sent — EF.FPLMN is appended only by
|
||||||
response is `{success, error, steps:[{action, file, path, data, sw, ok}]}`.
|
`roaming_denied` (shift-list semantics of TS 31.102 §4.2.16, duplicates
|
||||||
|
skipped) and an attach to a listed PLMN clears its entry first (successful
|
||||||
|
manual selection, TS 23.122), while the 5GS location files are never written.
|
||||||
|
The response is `{success, error, steps:[{action, file, path, data, sw, ok}],
|
||||||
|
net_state}` where `net_state` is the updated monitor state (see
|
||||||
|
`GET /api/net-state`).
|
||||||
|
|
||||||
|
### `GET /api/net-state`
|
||||||
|
|
||||||
|
Returns the cached **network-state monitor** — the panel the PWA's Phone tab
|
||||||
|
shows next to the simulation buttons. The state is created when a card is
|
||||||
|
equipped (only when EF.ICCID was readable) and is updated in place from the
|
||||||
|
bytes the network simulation wrote, so this endpoint performs no card I/O:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"event_type": 4, "event_data": "01A0"}
|
{"available": true, "state": {
|
||||||
|
"files": {"imsi": {"name": "EF.IMSI", "fid": "6F07",
|
||||||
|
"path": "ADF.USIM/6F07", "present": true,
|
||||||
|
"source": "init", "updated": 1758396000.0,
|
||||||
|
"kind": "transparent", "data": "0829051032547698"},
|
||||||
|
"epsnsc": {"kind": "record",
|
||||||
|
"records": [{"num": 1, "data": "..."}]}},
|
||||||
|
"service": {"state": "normal", "source": "service_lost",
|
||||||
|
"time": 1758396123.0},
|
||||||
|
"network": {"service": {"state": "normal"},
|
||||||
|
"location": {"plmn": "26201", "mcc": "262", "mnc": "01",
|
||||||
|
"area": "6CD7", "lac": "6CD7",
|
||||||
|
"country": "Germany", "operator": "Telekom",
|
||||||
|
"roaming": "home", "rejected": false,
|
||||||
|
"source": "write"},
|
||||||
|
"home": "26201"},
|
||||||
|
"read_at": 1758396000.0}}
|
||||||
```
|
```
|
||||||
|
|
||||||
`event_type` is required (the SET UP EVENT LIST event byte); `event_data` is
|
`available: false` with `state: null` means no monitor state exists yet (no
|
||||||
optional hex for events that carry data. Returns the SW and any response data:
|
card equipped or EF.ICCID not readable). `service.state` is the simulated
|
||||||
|
service state (`normal` / `limited` / `none`, `null` until a scenario or a
|
||||||
|
Location status event sets it); `network.location.roaming` is `home` /
|
||||||
|
`equivalent` / `guest` against EF.HPLMNwAcT and EF.EHPLMN, and `rejected` is
|
||||||
|
set when the location files or EF.FPLMN show a permanent rejection.
|
||||||
|
Monitored file keys: `imsi`, `ehplmn`, `spdi`, `hplmnwact`, `loci`, `psloci`,
|
||||||
|
`epsloci`, `epsnsc`, `cbmi`, `cbmir`, `smsstatus`, `fplmn`; each entry's
|
||||||
|
`source` is `init` (equip read), `read`, `refresh` or `write` (patched from
|
||||||
|
the simulator's own writes). The PWA decodes the entries client-side.
|
||||||
|
|
||||||
|
### `POST /api/net-state-refresh`
|
||||||
|
|
||||||
|
Re-reads the monitored files from the card, merges them into the cached state
|
||||||
|
(`source: refresh`) and returns the same shape as `GET /api/net-state`. The
|
||||||
|
optional body filters the read:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"sw": "9000", "data": "..."}
|
{"files": ["imsi", "loci", "epsnsc"]}
|
||||||
```
|
```
|
||||||
|
|
||||||
Channel status (event `0x0A`, TS 102 223 §8.56) carries the Channel status TLV
|
Without a body all monitored files are re-read. Answers `503` when the reader
|
||||||
`B8 02 <status> <info>`, where the status byte is the channel id (1–7) OR-ed
|
is not initialized.
|
||||||
with the state bits (0x00 link not established / 0x40 TCP LISTEN / 0x80 link
|
|
||||||
established) and the info byte is `00` (no further info) or `05` (link
|
|
||||||
dropped). The server also sends this event automatically when a BIP link drops
|
|
||||||
outside a proactive command and the card subscribed to `0x0A`.
|
|
||||||
|
|
||||||
### `GET /api/proactive-log`
|
### `GET /api/proactive-log`
|
||||||
|
|
||||||
|
|||||||
@@ -426,7 +426,7 @@
|
|||||||
<p class="text-sm mb-2">Диалог сканирования запрашивает имя профиля и предлагает селектор <strong>«Проверка FCP/FCI»</strong> (те же три режима, по умолчанию <strong>Тип файла + размер (FCP)</strong>), применяемый ко всем создаваемым правилам, а также список <strong>«Игнорировать содержимое файлов»</strong> (все отмечены по умолчанию, кроме <code class="font-mono text-sm">EF.ARR</code>; флажок в заголовке отмечает или снимает весь список) часто перезаписываемых файлов, содержимое которых пропускается: <code class="font-mono text-sm">EF.LOCI</code>, <code class="font-mono text-sm">EF.PSLOCI</code>, <code class="font-mono text-sm">EF.EPSLOCI</code>, <code class="font-mono text-sm">EF.5GS3GPPLOCI</code>, <code class="font-mono text-sm">EF.Keys</code>, <code class="font-mono text-sm">EF.KeysPS</code>, <code class="font-mono text-sm">EF.SMS</code>, <code class="font-mono text-sm">EF.Kc</code>, <code class="font-mono text-sm">EF.KcGPRS</code>, <code class="font-mono text-sm">EF.LOCIGPRS</code>, <code class="font-mono text-sm">EF.CBMID</code>, <code class="font-mono text-sm">EF.SMSS</code>, <code class="font-mono text-sm">EF.ACC</code>, <code class="font-mono text-sm">EF.EPSNSC</code>, <code class="font-mono text-sm">EF.START-HFN</code>, <code class="font-mono text-sm">EF.ARR</code>. Ещё две отмеченные по умолчанию опции <strong>«Сравнивать первые 4 байта для»</strong> <code class="font-mono text-sm">EF.IMSI</code> и <code class="font-mono text-sm">EF.ICCID</code> захватывают содержимое этих файлов как маску только первых 4 байт (снимите для точного сравнения). Строка прогресса показывает <em>N / всего файлов</em> с текущим путём файла во время сканирования; при сканировании опции скрываются, а кнопки блокируются. Правила создаются только для файлов, которые реально существуют на карте (возвращён FCP-шаблон); отсутствующие файлы пропускаются. Пользовательские файлы из подвкладки <strong>«Пользовательские файлы»</strong> включаются с той же проверкой существования. Тот же диалог и опции использует <strong>«Профиль из снимка»</strong>: вместо карты обходятся захваченные файлы выбранного снимка; для файлов, содержимое которых не было захвачено, правило создаётся без проверки содержимого (при последующей проверке профиля они помечаются как непроверяемые).</p>
|
<p class="text-sm mb-2">Диалог сканирования запрашивает имя профиля и предлагает селектор <strong>«Проверка FCP/FCI»</strong> (те же три режима, по умолчанию <strong>Тип файла + размер (FCP)</strong>), применяемый ко всем создаваемым правилам, а также список <strong>«Игнорировать содержимое файлов»</strong> (все отмечены по умолчанию, кроме <code class="font-mono text-sm">EF.ARR</code>; флажок в заголовке отмечает или снимает весь список) часто перезаписываемых файлов, содержимое которых пропускается: <code class="font-mono text-sm">EF.LOCI</code>, <code class="font-mono text-sm">EF.PSLOCI</code>, <code class="font-mono text-sm">EF.EPSLOCI</code>, <code class="font-mono text-sm">EF.5GS3GPPLOCI</code>, <code class="font-mono text-sm">EF.Keys</code>, <code class="font-mono text-sm">EF.KeysPS</code>, <code class="font-mono text-sm">EF.SMS</code>, <code class="font-mono text-sm">EF.Kc</code>, <code class="font-mono text-sm">EF.KcGPRS</code>, <code class="font-mono text-sm">EF.LOCIGPRS</code>, <code class="font-mono text-sm">EF.CBMID</code>, <code class="font-mono text-sm">EF.SMSS</code>, <code class="font-mono text-sm">EF.ACC</code>, <code class="font-mono text-sm">EF.EPSNSC</code>, <code class="font-mono text-sm">EF.START-HFN</code>, <code class="font-mono text-sm">EF.ARR</code>. Ещё две отмеченные по умолчанию опции <strong>«Сравнивать первые 4 байта для»</strong> <code class="font-mono text-sm">EF.IMSI</code> и <code class="font-mono text-sm">EF.ICCID</code> захватывают содержимое этих файлов как маску только первых 4 байт (снимите для точного сравнения). Строка прогресса показывает <em>N / всего файлов</em> с текущим путём файла во время сканирования; при сканировании опции скрываются, а кнопки блокируются. Правила создаются только для файлов, которые реально существуют на карте (возвращён FCP-шаблон); отсутствующие файлы пропускаются. Пользовательские файлы из подвкладки <strong>«Пользовательские файлы»</strong> включаются с той же проверкой существования. Тот же диалог и опции использует <strong>«Профиль из снимка»</strong>: вместо карты обходятся захваченные файлы выбранного снимка; для файлов, содержимое которых не было захвачено, правило создаётся без проверки содержимого (при последующей проверке профиля они помечаются как непроверяемые).</p>
|
||||||
|
|
||||||
<h4 id="card-snapshots" class="font-medium mb-1">Снимки карт</h4>
|
<h4 id="card-snapshots" class="font-medium mb-1">Снимки карт</h4>
|
||||||
<p class="text-sm mb-2">Представление списка имеет две вкладки — <strong>«Профили»</strong> и <strong>«Снимки карт»</strong>. Снимок карты — неизменяемая фиксация файловой системы карты: для каждого существующего файла сохраняются путь, символьное имя, тип, размер (или длина/число записей), сырой FCI из ответа SELECT и содержимое, если файл читается (без списка игнорирования и без масок). ICCID декодируется из EF.ICCID и показывается рядом с именем снимка. Захваченное содержимое показывается вместе с декодированным представлением, где есть декодер — таблица полей для transparent-файлов и однострочная сводка по каждой записи для record-файлов. При сканировании измеряется время каждой команды карты (SELECT, READ BINARY, READ RECORD) от отправки до ответа; снимок хранит min/сред/max по каждому типу команд и общее время сканирования, а в представлении эти значения показываются в сводке под заголовком, время select/read — для каждого файла и время чтения — для каждой записи. Время носит информационный характер и не используется при проверках и сравнении.</p>
|
<p class="text-sm mb-2">Представление списка имеет три вкладки — <strong>«Профили»</strong>, <strong>«Снимки карт»</strong> и <strong>«Пользовательские файлы»</strong> (см. ниже). Снимок карты — неизменяемая фиксация файловой системы карты: для каждого существующего файла сохраняются путь, символьное имя, тип, размер (или длина/число записей), сырой FCI из ответа SELECT и содержимое, если файл читается (без списка игнорирования и без масок). ICCID декодируется из EF.ICCID и показывается рядом с именем снимка. Захваченное содержимое показывается вместе с декодированным представлением, где есть декодер — таблица полей для transparent-файлов и однострочная сводка по каждой записи для record-файлов. При сканировании измеряется время каждой команды карты (SELECT, READ BINARY, READ RECORD) от отправки до ответа; снимок хранит min/сред/max по каждому типу команд и общее время сканирования, а в представлении эти значения показываются в сводке под заголовком, время select/read — для каждого файла и время чтения — для каждой записи. Время носит информационный характер и не используется при проверках и сравнении.</p>
|
||||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||||
<li><strong>Новый снимок: <ICCID></strong> — запрашивает имя и сканирует карту, затем возвращает к списку.</li>
|
<li><strong>Новый снимок: <ICCID></strong> — запрашивает имя и сканирует карту, затем возвращает к списку.</li>
|
||||||
<li><strong>Импорт снимка</strong> — загружает снимок из JSON-файла.</li>
|
<li><strong>Импорт снимка</strong> — загружает снимок из JSON-файла.</li>
|
||||||
@@ -576,7 +576,7 @@ pysim-simple-server --http-port 8080</pre>
|
|||||||
<tr><td class="py-1 px-2 font-mono">любая</td><td class="py-1 px-2 font-mono">новее мажорная</td><td class="py-1 px-2">⚠️ Сервер новее — обновите PWA</td></tr>
|
<tr><td class="py-1 px-2 font-mono">любая</td><td class="py-1 px-2 font-mono">новее мажорная</td><td class="py-1 px-2">⚠️ Сервер новее — обновите PWA</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p class="text-sm">PWA проверяет версию сервера при подключении через <code class="font-mono text-sm">GET /api/version</code> и сравнивает мажорную версию (например, PWA 2.x с сервером 2.x; сервер 1.x помечается как устаревший).</p>
|
<p class="text-sm">PWA проверяет версию сервера при подключении через <code class="font-mono text-sm">GET /api/version</code> и сравнивает мажорную версию (например, PWA 3.x с сервером 3.x; сервер 2.x помечается как устаревший).</p>
|
||||||
|
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
+2
-2
@@ -426,7 +426,7 @@
|
|||||||
<p class="text-sm mb-2">The scan dialog asks for a profile name and offers a <strong>“FCP/FCI check”</strong> selector (the same three modes above, default <strong>Filetype + size</strong>) applied to every generated rule, plus an <strong>“Ignore contents of files”</strong> checklist (all checked by default except <code class="font-mono text-sm">EF.ARR</code>; the header checkbox checks or unchecks the whole list) of frequently-overwritten files whose contents are skipped: <code class="font-mono text-sm">EF.LOCI</code>, <code class="font-mono text-sm">EF.PSLOCI</code>, <code class="font-mono text-sm">EF.EPSLOCI</code>, <code class="font-mono text-sm">EF.5GS3GPPLOCI</code>, <code class="font-mono text-sm">EF.Keys</code>, <code class="font-mono text-sm">EF.KeysPS</code>, <code class="font-mono text-sm">EF.SMS</code>, <code class="font-mono text-sm">EF.Kc</code>, <code class="font-mono text-sm">EF.KcGPRS</code>, <code class="font-mono text-sm">EF.LOCIGPRS</code>, <code class="font-mono text-sm">EF.CBMID</code>, <code class="font-mono text-sm">EF.SMSS</code>, <code class="font-mono text-sm">EF.ACC</code>, <code class="font-mono text-sm">EF.EPSNSC</code>, <code class="font-mono text-sm">EF.START-HFN</code>, <code class="font-mono text-sm">EF.ARR</code>. Two further checked-by-default options <strong>“Match first 4 bytes for”</strong> <code class="font-mono text-sm">EF.IMSI</code> and <code class="font-mono text-sm">EF.ICCID</code> capture those files’ contents as a mask of only the first 4 bytes (uncheck for exact matching). A progress line shows <em>N / total files</em> with the current file path while scanning; during the scan the options are hidden and the buttons are locked. Rules are created only for files that actually exist on the card (a FCP template is returned); missing files are skipped. Custom files from the <strong>Custom files</strong> sub-tab are included under the same existence check. The same dialog and options are used by <strong>Profile from snapshot</strong>, which walks the selected snapshot’s captured files instead of the card; rules for files whose contents were not captured during the scan get no content check (they are reported as unverifiable when the profile is later checked).</p>
|
<p class="text-sm mb-2">The scan dialog asks for a profile name and offers a <strong>“FCP/FCI check”</strong> selector (the same three modes above, default <strong>Filetype + size</strong>) applied to every generated rule, plus an <strong>“Ignore contents of files”</strong> checklist (all checked by default except <code class="font-mono text-sm">EF.ARR</code>; the header checkbox checks or unchecks the whole list) of frequently-overwritten files whose contents are skipped: <code class="font-mono text-sm">EF.LOCI</code>, <code class="font-mono text-sm">EF.PSLOCI</code>, <code class="font-mono text-sm">EF.EPSLOCI</code>, <code class="font-mono text-sm">EF.5GS3GPPLOCI</code>, <code class="font-mono text-sm">EF.Keys</code>, <code class="font-mono text-sm">EF.KeysPS</code>, <code class="font-mono text-sm">EF.SMS</code>, <code class="font-mono text-sm">EF.Kc</code>, <code class="font-mono text-sm">EF.KcGPRS</code>, <code class="font-mono text-sm">EF.LOCIGPRS</code>, <code class="font-mono text-sm">EF.CBMID</code>, <code class="font-mono text-sm">EF.SMSS</code>, <code class="font-mono text-sm">EF.ACC</code>, <code class="font-mono text-sm">EF.EPSNSC</code>, <code class="font-mono text-sm">EF.START-HFN</code>, <code class="font-mono text-sm">EF.ARR</code>. Two further checked-by-default options <strong>“Match first 4 bytes for”</strong> <code class="font-mono text-sm">EF.IMSI</code> and <code class="font-mono text-sm">EF.ICCID</code> capture those files’ contents as a mask of only the first 4 bytes (uncheck for exact matching). A progress line shows <em>N / total files</em> with the current file path while scanning; during the scan the options are hidden and the buttons are locked. Rules are created only for files that actually exist on the card (a FCP template is returned); missing files are skipped. Custom files from the <strong>Custom files</strong> sub-tab are included under the same existence check. The same dialog and options are used by <strong>Profile from snapshot</strong>, which walks the selected snapshot’s captured files instead of the card; rules for files whose contents were not captured during the scan get no content check (they are reported as unverifiable when the profile is later checked).</p>
|
||||||
|
|
||||||
<h4 id="card-snapshots" class="font-medium mb-1">Card snapshots</h4>
|
<h4 id="card-snapshots" class="font-medium mb-1">Card snapshots</h4>
|
||||||
<p class="text-sm mb-2">The list view has two tabs — <strong>Profiles</strong> and <strong>Card snapshots</strong>. A card snapshot is an immutable capture of the card filesystem: for every existing file it stores the path, symbolic name, file type, size (or record length/count), the raw FCI from the SELECT response, and the contents whenever the file is readable (no ignore list, no masking). The ICCID is decoded from EF.ICCID and shown next to the snapshot name. Captured contents are shown with their decoded form where a decoder exists — a field table for transparent files and a one-line summary per record for record files. The scan also measures each card command (SELECT, READ BINARY, READ RECORD) from command to response; the snapshot stores min/avg/max per command type and the total scan time, and the view shows these in the summary under the title plus the select/read times per file and the read time per record. Timings are informational only and are not used by checks or comparisons.</p>
|
<p class="text-sm mb-2">The list view has three tabs — <strong>Profiles</strong>, <strong>Card snapshots</strong> and <strong>Custom files</strong> (see below). A card snapshot is an immutable capture of the card filesystem: for every existing file it stores the path, symbolic name, file type, size (or record length/count), the raw FCI from the SELECT response, and the contents whenever the file is readable (no ignore list, no masking). The ICCID is decoded from EF.ICCID and shown next to the snapshot name. Captured contents are shown with their decoded form where a decoder exists — a field table for transparent files and a one-line summary per record for record files. The scan also measures each card command (SELECT, READ BINARY, READ RECORD) from command to response; the snapshot stores min/avg/max per command type and the total scan time, and the view shows these in the summary under the title plus the select/read times per file and the read time per record. Timings are informational only and are not used by checks or comparisons.</p>
|
||||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||||
<li><strong>New snapshot: <ICCID></strong> — asks for a name and scans the card, then returns to the list.</li>
|
<li><strong>New snapshot: <ICCID></strong> — asks for a name and scans the card, then returns to the list.</li>
|
||||||
<li><strong>Import snapshot</strong> — loads a snapshot from a JSON file.</li>
|
<li><strong>Import snapshot</strong> — loads a snapshot from a JSON file.</li>
|
||||||
@@ -576,7 +576,7 @@ pysim-simple-server --http-port 8080</pre>
|
|||||||
<tr><td class="py-1 px-2 font-mono">any</td><td class="py-1 px-2 font-mono">newer major</td><td class="py-1 px-2">⚠️ Server newer — update PWA</td></tr>
|
<tr><td class="py-1 px-2 font-mono">any</td><td class="py-1 px-2 font-mono">newer major</td><td class="py-1 px-2">⚠️ Server newer — update PWA</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p class="text-sm">The PWA checks the server version on connect via <code class="font-mono text-sm">GET /api/version</code> and compares the major version (e.g. 2.x PWA with a 2.x server; a 1.x server is flagged as outdated).</p>
|
<p class="text-sm">The PWA checks the server version on connect via <code class="font-mono text-sm">GET /api/version</code> and compares the major version (e.g. 3.x PWA with a 3.x server; a 2.x server is flagged as outdated).</p>
|
||||||
|
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
+1
-1
@@ -1436,7 +1436,7 @@
|
|||||||
// ===== Version =====
|
// ===== Version =====
|
||||||
// Single source of truth for the PWA version: shown in the header and used
|
// Single source of truth for the PWA version: shown in the header and used
|
||||||
// by the server version check in pysimConnect().
|
// by the server version check in pysimConnect().
|
||||||
const SIMPLE_VERSION = '3.0.0';
|
const SIMPLE_VERSION = '3.0.1';
|
||||||
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||||
|
|
||||||
// ===== Tab switching =====
|
// ===== Tab switching =====
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
const CACHE = 'simple-v227';
|
const CACHE = 'simple-v228';
|
||||||
const URLS = [
|
const URLS = [
|
||||||
'index.html',
|
'index.html',
|
||||||
'help.html',
|
'help.html',
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pysim-simple-server"
|
name = "pysim-simple-server"
|
||||||
version = "3.0.0"
|
version = "3.0.1"
|
||||||
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ from osmocom.tlv import BER_TLV_IE
|
|||||||
from osmocom.utils import rpad
|
from osmocom.utils import rpad
|
||||||
|
|
||||||
|
|
||||||
VERSION = '3.0.0'
|
VERSION = '3.0.1'
|
||||||
|
|
||||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user