Self-contained SVGs (EN + RU) showing Browser -> HTTP :8080 ->
pysim-simple-server -> PC/SC -> card reader -> UICC/SIM, referenced
from the top of each README. They ride the package's whole-docs tree,
so the links resolve in the release zip too.
- Add a 'Related tools' section (EN + RU) introducing SIMple, SIMtrace
Analyser and sigrok_iso7816_stream as independent tools.
- Cross-link the two READMEs (English/Russian) at the top.
- Russian: replace the 'pill' calque with 'button' (README_RUS + help-ru),
and tighten the PC/SC-fallback, init-output and canonical-path wording.
- Bump the SW cache for the help-ru.html change.
cardsAutoSelectByIccid latched its 'already handled' guard even when no
matching preset was found, so a card equipped before /api/presets had
loaded (the connect-time race with the status/availability polls) never
got auto-selected: navigating to SCP80/RAM showed no preset until the card
was re-inserted. The guard is now latched only after a successful
selection, and cardsFetch re-runs the auto-selection once the store
arrives, so the card's preset is picked as soon as both resources are
available.
Bumps VERSION to 3.40.3 and the SW cache to simple-v488.
The Windows bullet now states the pyscard wheel situation plainly (3.13
= wheels, no compile; 3.14 = build from source) without repeating the
SCP81 TLS-PSK 3.13+ requirement already given in the Python bullet.
PWA is kept only where it matters: the first occurrence (unpacked as
'Progressive Web App') and the '## PWA' install/offline section. The
RU text declines 'фронтенд' correctly.
The UI and API are served from one origin by default, so CORS is a
non-issue — the quick start no longer calls it out. Not re-added
elsewhere (kept unobtrusive).
A red ✕ next to the filter selector appears whenever the filter is not
"All" and resets it to "All" in one click (pysimFsFilterClear). Bump
VERSION/pyproject/PWA header to 3.40.2 and the SW cache to simple-v487.
Drop the invented "SMS-related" / "CB-related" filter categories: those
files are service-declared and are already reached through their
per-service options (per-spec service names). Bump VERSION/pyproject/
PWA header to 3.40.1 and the SW cache to simple-v486.
Bump VERSION/pyproject/PWA header to 3.40.0 and the SW cache to
simple-v485 (index.html changed). CHANGELOG [3.40.0] documents the
file-tree filter (checkbox multiselect, path-exact DF hiding, expand/
collapse all, auto-expand, and the "To EF filter" cross-link).
- "Expand all" / "Collapse all" links in the sort row: expand-all walks
the directory tree loading children on demand (skipping DFs the probe
found absent), collapse-all resets every directory.
- Selecting any filter but "All" auto-expands the tree so the matched
files are visible (pysimFsAutoExpandForFilter, wired into the two
filter setters).
- i18n EN/RU for the two links.
Frontend 1163 tests green (+2). (Version/sw bump still deferred.)
A non-'All' selection turns the collapsed filter button blue (like the
active sort pill) so it stands out; 'All' keeps the default style.
Frontend 1161 tests green.
When a filter is active (not "All"), only the matching files, their
ancestor directories and the MF root stay; every other directory is
hidden. The ancestors come from the standard file list (name -> paths):
pysimFsFilterMatchingPaths unions the registry paths of every matching
name, and pysimFsFilterShow keeps a directory iff it matches itself
(e.g. DF.GSM for svc:GPRS) or its canonical path prefixes a matching
path. Custom files contribute their own paths; the not-loaded window
keeps directories rather than hiding everything.
Frontend 1160 tests green (+8). (Version/sw bump still deferred.)
The per-service cross-link is now a single compact glyph (U+25BE) with
'To EF filter' as the title/aria-label, instead of a text button that
shifted the grid. Frontend 1152 tests green.
In the SST/UST/IST/EST decoded editors, each service row backed by files
gains a small "To EF filter" action that sets the file-tree filter to
exactly that service's option:
- The four service-table fields carry a `table` key (sst/ust/est/ist);
servicesFeatureByNumber() inverts SERVICES_CROSS_REF into per-table
number->feature maps (lazy, cached).
- pysimFsFilterBtnHtml(table, n) renders the button only for file-backed
features; pysimFsSetFilterToService(table, n) sets pysimFsFilter to
['svc:<feature>'], persists, and re-renders the dropdown + tree.
- i18n: "To EF filter" (EN/RU). No CSS rebuild needed.
Frontend 1152 tests green (+6). (Version/sw bump still deferred.)
Replace the <select multiple size=4> filter with a single-row button that
expands into a scrollable checkbox menu (All + Custom files, then the
Identifiers/PLMN/Services headings with the categories and per-service
options), mirroring simtrace-analyser's command filter.
- pysimFsFilterSummary/Label, pysimFsFilterToggle, pysimFsFilterSetEntry
(all-exclusive, empty -> all) and a rewritten pysimFsFilterRender;
pysimFsSetFilter is gone.
- Closes on outside click and Escape. i18n: "Selected: {n}".
- No CSS rebuild needed (swapped to utility classes already in the
prebuilt style.css).
Frontend 1146 tests green. (Version/sw bump still deferred.)
Fill in the scaffolded file-tree filter:
- FS_FILTER_GROUPS: Identifiers, PLMN selection, Provider names,
WLAN/I-WLAN, SMS-related and CB-related (cell broadcast), each with
its exact file list; plus one option per file-backed feature of
SERVICES_FS_MAP (svc:<feature>).
- "All" is the default and exclusive; a top-level "Custom files"
option matches the injected custom-file nodes by their flag.
- fsFilterIndexBuild inverts name -> criterion set; pysimFsFilterMatch
matches by name (and custom by flag); pysimFsFilterShow keeps a
directory while it has a matching (loaded) descendant, and keeps
never-expanded directories. The dropdown renders All / Custom files
and three optgroups (Identifiers / PLMN / Services).
- i18n EN/RU for the new labels.
Frontend 1145 tests green (fs_filter.test.js 19).
Add a Filter multiselect next to the sort pills in the file tree toolbar.
The option list is large and undecided, so FS_FILTER_OPTIONS is empty and
the per-node match is a no-op for now; the mechanism is wired end to end:
- FS_FILTER_OPTIONS const (empty), pysimFsFilter state persisted to
simple_fs_filter, pysimFsSetFilter / pysimFsFilterMatch /
pysimFsFilterRender, and the render loop consults pysimFsFilterMatch.
- The dropdown re-renders on language switch; "Filter:" and
"(no filters yet)" are translated (EN/RU).
Frontend 1132 tests green (6 new scaffold pins).
Bump VERSION/pyproject/PWA header to 3.39.0 and the SW cache to
simple-v484 (index.html + help changed). CHANGELOG [3.39.0] folds the
unreleased 3.38.2 start-script fix and documents the decoded-editing
batch: DF-context resolution, EF.ECC/EF.AD split, path-based selection,
EF.SST tri-state editor, the Services editor + path-exact FS check, and
the UST 147-150 completion.
Show the established animate-spin throbber next to the Check filesystem
button while the scan (tree load + probe-all + report) is in flight, and
hide it when it settles. Frontend 1126 tests green.
Rework the FS check from FID-level to path-exact:
- SERVICES_FS_MAP now maps a feature to symbolic roles (registry names),
not FIDs; the (name, root) -> path index resolves each role to its
unambiguous canonical path (same-FID files in other DFs - EF.SAI vs
EF.PBR, EF.AST - resolve separately).
- Per-tree declaration: SST -> MF, UST/EST -> ADF.USIM, IST -> ADF.ISIM,
with a DF.TELECOM fallback for USIM/ISIM roles whose DFs live under
DF.TELECOM (MMS storage, MCPTT, V2X, A2X), except the GSM-application
mapped copies (ADN/EXT1/ECCP).
- The report carries the path (and declaring tree) for missing and
present-but-undeclared, plus an honest "unchecked" bucket for roles
with no path yet (DF.GRAPHICS/IMG, SIM DF.SoLSA/MExE copies,
EF.3GPPPSDATAOFFservicelist).
- efDfFromPath maps A000000087100B -> ADF.USIM-NON-IMSI.
Frontend 1126 + Python 1091 tests green. (Version/sw bump still
deferred for the decoded-editing batch.)
Add a supplement to the cardless registry generator for the 13 files the
Services editor's FS check references but pySim does not emit (optional,
service-gated): EF.LRPLMNSI/IAL/IPD/3GPPPSDATAOFF/TVCONFIG, DF.MExE +
EF.MExE-ST/ORPK/ARPK/TPRPK, DF.SoLSA + EF.SAI/EF.SLL, DF.BCAST,
DF.ACDC + EF.ACDC_LIST, DF.TV, and DF.A2X + EF.AST/EF.A2X_CONFIG (under
DF.TELECOM). Emitted with distinct (name, path) so same-FID files in
other DFs (EF.SAI vs EF.PBR, EF.AST) stay separate; ADF.USIM rows are
mirrored to ADF.USIM-NON-IMSI. 490 -> 527 entries.
Regenerated the asset; test_uicc_files.py pins the 20 new paths, the
FID-collision cases and (name, root) uniqueness. 1091 Python tests.
Add a "Check filesystem" action to the Services pill:
- SERVICES_FS_MAP: the feature -> FID list transcribed from
docs/services-editor.md §A (127 file-backed + 34 capability features,
157 distinct FIDs; a completeness/data test pins it).
- servicesFsReport: pure two-direction check - declared features whose
mapped files are absent, and present files whose features are
undeclared. FID-level (not DF-exact) for this first pass; documented.
- The Check runs the tree probe (once per session) and renders the
missing/extra lists or the "matches" line, with an FID-level note.
Also fix a doc typo (eCall Data's EF.FDN was written as 6F3A = EF.ADN).
Frontend 1120 + Python 1090 tests green. (Version/sw bump still
deferred for the decoded-editing batch.)
Add a Services pill to the Card reader tab that shows the card's service
tables side by side:
- SERVICES_CROSS_REF: the 161-row feature cross-reference (SST/UST/EST/IST
numbers + class) transcribed from docs/services-editor.md §A; a
completeness test pins every non-RFU service number to exactly one row.
- Reads the four files (DF.GSM/6F38, ADF.USIM/6F38, ADF.USIM/6F56,
ADF.ISIM/6F07) via /api/read, cached per card session; a column renders
only for a present file (no ISIM -> no IST column).
- SST cell is on/allocated-off only (never de-allocates); UST/EST/IST are
checkboxes; per-file Save buttons write via /api/write, preserving
unmodelled bits and reporting each result.
Frontend 1105 + Python 1090 tests green. (Version/sw bump deferred;
FS-check is the next step.)
Give EF.SST its own per-file editor for the 2-bit SIM service table
(TS 51.011 10.3.7: allocated + activated per service):
- efEncSst encodes the pair layout, preserving unmodelled pairs and the
file length; validates service number, fit and state.
- A new `bits2` field kind renders a three-state select per service and
collects {n, name, allocated, activated}; registered as EF_SST_FIELDS
with the encoder (df '7F20'), and SST leaves EF_READONLY_NAMES.
- i18n: Deleted/Off/On + the state-error and hint strings (EN/RU).
Docs/help updated: SST is no longer read-only. Frontend 1093 + Python
1090 tests green. (Version/sw bump still deferred for the unreleased
decoded-editing batch.)
Make the DF context from the resolver actually reach the live views:
- pysimFsSelected now stores the canonical path (pysimFsNodePath), not
the node name; pysimFsRenderNode emits the path in the click/toggle
handlers; every consumer resolves via pysimFsFindNodeByPath. The
name-based pysimFsFindNode is removed - two same-named files under
different DFs (EF.ECC/EF.AD, DF.PHONEBOOK copies) are now distinct.
- efDfFromPath maps ADF-rooted parent segments by RID (A0000000871002
-> ADF.USIM, A0000000871004 -> ADF.ISIM), so snapshot/profile paths
rooted by AID resolve to the same DF key as the named form.
- efDecEcc shares efEccCategory with efDecEccUsim (TS 24.008
Table 10.5.135d), so the SIM and USIM category displays can't drift.
Frontend 1087 + Python 1090 tests green. (Version/sw bump deferred -
this is part of the unreleased decoded-editing batch.)
The decoder/encoder lookup now takes an optional DF context and resolves
DF-first, then name, then FID (the spec keys files by FID within their
DF; the name is a display label). efDfFromPath derives the parent DF
segment of a canonical path.
EF.ECC is split into its two DF-specific decoders: DF.GSM (7F20)
transparent 3n (existing) and ADF.USIM linear-fixed X+4 - the new
efDecEccUsim reads the 3-byte Emergency Call Code, the Annex A alpha and
the Emergency Service Category (decoded per TS 24.008 Table 10.5.135d).
EF.AD is registered as DF-keyed entries (7F20 / ADF.USIM / ADF.ISIM),
reusing the existing encoder.
The df is threaded through the file-manager decoded-view/edit/save and
the snapshot/compare decode. No ECC editor yet (read-only).
Frontend 1081 + Python 1090 tests green.
The PWA's EF_UST_SERVICES stopped at 146; TS 31.102 §4.2.8 pins 147-150
(5MBS UE pre-configuration, Operator Controlled Signal Threshold per
Access Technology, A2X, IMS Data Channel Indication). Add them and fix
the two test fixtures that assumed the 146-service table.
Resolve the three Services-editor FS mappings against the spec:
- eCall Data (89) -> EF.SDN 6F49 (+ EF.FDN 6F3A)
- eCall Data over IMS (112) -> EF.SDNURI 6FEF (+ EF.FDNURI 6FED)
- EARFCN list for MTC/NB-IOT (121) -> EF.EARFCNList 6FFD; "Extended
EARFCN support" (100) is a capability, not a file.
Record the FID-first rule: the resolver and FS check key by (DF, FID),
the symbolic name is only a label; and clarify that the FS check is
card-only (independent of the cardless uicc_files.json list).
Feature cross-reference (SST/UST/IST/EST) and feature->filesystem
mapping for the planned cross-file Services editor. Reconciliation
exact: 160 feature rows, every service number exactly once.
Flags for review: UST list is 4 short of the spec (147-150 missing
from EF_UST_SERVICES), GSM Access gates DF.GSM-ACCESS 5F3B (not DF.GSM),
CCP/CCP2/ECCP equivalence, and three unresolved file mappings.
The first line was hardcoded to http://127.0.0.1:8080 while the flags
were passed through, so ./start.sh --http-host 10.0.28.161 printed
127.0.0.1 although the server bound 10.0.28.161 (its own listening banner
named it). Both start scripts now parse --http-host/--http-port (space
and = forms, the last value wins like argparse) and echo the effective
address; start.bat parses with shift (%* is unaffected, so the server
still receives every argument).
Bump 3.38.2 (server, pyproject, PWA header, sw simple-v483) and add the
CHANGELOG entry.
Tests: tests/test_pcsc_startup.py pins the parsing/echo (2 new).
1090 Python + 1075 frontend.
A headless/SSH box can show a world-writable /run/pcscd/pcscd.comm
(srw-rw-rw- root root) and still be denied: pcscd enforces its PolicyKit
policy, whose defaults allow only active local sessions. The startup
report, the start.sh pre-flight and the README troubleshooting now name
the exact rule (99-pcscd-allow.rules, org.debian.pcsc-lite.access_pcsc
and access_card) and explain why the socket mode does not matter. The
pcscd-group instruction is gone: there may be no such group, and it is
not the gate. The group route stays only as a note for a pcscd built
without PolicyKit.
Tests: tests/test_pcsc_startup.py asserts the polkit action IDs, the
rule filename and the 0666-socket explanation.
1088 Python + 1075 frontend.
A failed venv creation (e.g. the Debian/Ubuntu python3-venv package
missing) left the .venv directory behind; the next run saw it, skipped
creation and failed to source/activate a venv without activate/pip.
setup.sh now validates bin/activate, bin/python and bin/pip, removes an
incomplete directory and creates it again; a creation failure removes the
partial directory and names the venv package. setup.bat does the same
with Scripts\activate.bat/python.exe/pip.exe and !errorlevel!.
READMEs (prerequisites + scripts table), CHANGELOG (folded into the
unreleased 3.38.1) and AGENTS updated.
Tests: tests/test_setup_scripts.py (5: the shell/bat source pins and
bash -n). 1088 Python + 1075 frontend.
When no reader was named and readers() failed (e.g. SCARD_E_NO_ACCESS -
the user may not use pcscd), the auto-detect swallowed the error and pySim
fell back to the Serial transport, failing on /dev/ttyUSB0 while the
server still printed "listening". The startup now probes PC/SC,
classifies the failure by hresult (access/service/reader), reports the
cause with the pcscd group/polkit and pcsc_scan guidance and exits 2; the
python -m guard uses sys.exit(main()). An explicit -d/--device keeps the
serial path; a reader without a card stays a normal cardless start; a
readerless start exits with its own message.
start.sh runs the same access pre-flight before launching (readers() with
a 3x retry for socket activation; -d is detected and skips it). READMEs,
CHANGELOG (folded into the unreleased 3.38.1) and AGENTS updated.
Tests: tests/test_pcsc_startup.py (16: the error classifier, the probe,
the report guidance, the serial-arg detection and the source pins).
1083 Python + 1075 frontend.
pySim's scc.read_binary/read_record call select_path(ef) first, so the
ICCID, network-state, EF.ARR and EF.PBR readers - which had already made a
parent-scoped selection and hold its FCP - sent a second SELECT per file
and per record. _read_selected_ef() issues READ BINARY (chunked at
max_cmd_len from the FCP file size) / READ RECORD (b2<rec>04<len> at the
FCP record length) directly; the pySim helpers stay as the fallback when
the FCP lacks the value.
The startup TERMINAL PROFILE drain now breaks on the chain's idle SW
instead of polling STATUS once more.
Measured on the last startup: ~3.4 s traced init (netstate/ARR/PBR 271
APDUs / 1.26 s incl. 169 SELECTs; the card's own TP processing 1.58 s);
the change removes ~0.7-0.8 s of the read phase without touching any data
or the TP.
v3.38.1; tests: tests/test_read_selected.py (direct reads, chunking, the
fallback and the drain source pin) and the ARR/PBR/ICCID/netstate fakes.
1067 Python + 1075 frontend. sw cache simple-v482.
The test-run banner (visible on every Test-script view) now carries the
same live stats as the script head and the suite summary: elapsed so far,
the average per completed iteration and the estimated time left. The
text is built by a pure helper (testRunBannerText) so it is testable;
testRender only calls it while a run is active, and non-load runs keep
their position text (step or suite-member progress).
The existing banner-source assertion moved to the helper. Tests: the
banner text for a load suite and a plain run. 1061 Python + 1075
frontend; sw cache simple-v481. CHANGELOG/help/docs/AGENTS updated.
The script-run head and the suite summary now display, while a load run
repeats: the elapsed time so far, the average per completed iteration and
the estimated time left (testLoadTiming / testDurationText /
testIterAvgText), recomputed on every 2 s status poll. A finished run
keeps the server's final elapsed_ms/avg_ms (no estimate), and before the
first completed iteration only the elapsed time is shown - no bogus
average or ETA.
The timing is client-side over the existing load block (started, done,
iterations), so it works with the running server as well; no server
change is needed.
Tests: the timing math and the two formatters, the script head render and
the suite summary render (3 new). 1061 Python + 1074 frontend.
sw cache simple-v480; CHANGELOG [3.38.0], help EN/RU,
docs/test-scripts.md and the AGENTS notes.
Both layers: the server's _TEST_LOAD_MAX and the PWA's
TEST_ITERATIONS_MAX plus the two input max attributes. The value stays
inside 2^53-1 (the JavaScript safe-integer range), so the counters and the
progress display survive the JSON/JS round trip exactly; the practical
ceiling is the run duration (50 ms/iteration ~1.6 years at the cap).
The server's range error names the new cap automatically. The frontend
tests read the cap from index.html instead of stubbing a literal, and
clamp at it (above the cap, exactly at it, and the input max).
Docs: api.md, test-scripts.md, help EN/RU, the CHANGELOG (folded into the
unreleased 3.38.0) and the AGENTS notes. sw cache simple-v479.
1061 Python + 1071 frontend.