fix: drop the "Reserved for 3GPP" event-name cross-reference (v3.6.22)

The event list tables carried labels like
"12  Reserved for 3GPP - Network rejection (TS 31.111 7.5.2)".  The phrase is
an ETSI-to-3GPP document pointer, not a usage restriction, and it is not
what a user needs - the event name is.

- EVENT_NAMES (PWA + server mirror): the 3GPP-assigned codings carry their
  plain TS 31.111 7.5 name ((I-)WLAN access status, Network rejection, CSG
  cell selection, IMS registration, Incoming IMS data, Data connection
  status change, CAG cell selection, Slices status change).
- 0x20-0x22: "Reserved (future usage)" (no attribution).
- 0x0B/0x14: the spec's full "(single access technology)" / "(multiple
  access technologies)" wording instead of the cryptic "(single)/(multiple)".
- tests pin the exact names and that no name contains the cross-reference.

652 frontend / 500 Python green; version 3.6.22; sw simple-v295.
This commit is contained in:
2026-09-28 21:54:28 +03:00
parent 5372a770eb
commit 3c104f5685
6 changed files with 68 additions and 59 deletions
+18 -17
View File
@@ -1711,7 +1711,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.6.21'; const SIMPLE_VERSION = '3.6.22';
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION; document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
// ===== Tab switching ===== // ===== Tab switching =====
@@ -10730,34 +10730,35 @@ function pysimFsResetEdit() {
} }
// ===== proactive UICC events ===== // ===== proactive UICC events =====
// Event list codings (TS 102 223 v18.3.0 8.25). Values the CAT spec leaves // Event list codings (TS 102 223 v18.3.0 8.25). The values the CAT spec only
// "Reserved for 3GPP" carry the concrete 3GPP event name where TS 31.111 // points at 3GPP for carry their TS 31.111 7.5 event name; "Reserved for
// defines one (clause in parentheses), so the list stays informative. // 3GPP" is a spec cross-reference, not a usage restriction, so it never
// appears in the user-facing names.
const EVENT_NAMES = { const EVENT_NAMES = {
0x00: 'MT call', 0x01: 'Call connected', 0x02: 'Call disconnected', 0x00: 'MT call', 0x01: 'Call connected', 0x02: 'Call disconnected',
0x03: 'Location status', 0x04: 'User activity', 0x05: 'Idle screen available', 0x03: 'Location status', 0x04: 'User activity', 0x05: 'Idle screen available',
0x06: 'Card reader status', 0x07: 'Language selection', 0x06: 'Card reader status', 0x07: 'Language selection',
0x08: 'Browser termination', 0x09: 'Data available', 0x08: 'Browser termination', 0x09: 'Data available',
0x0A: 'Channel status', 0x0B: 'Access technology change (single)', 0x0A: 'Channel status', 0x0B: 'Access technology change (single access technology)',
0x0C: 'Display parameters changed', 0x0D: 'Local connection', 0x0C: 'Display parameters changed', 0x0D: 'Local connection',
0x0E: 'Network search mode change', 0x0F: 'Browsing status', 0x0E: 'Network search mode change', 0x0F: 'Browsing status',
0x10: 'Frames information change', 0x10: 'Frames information change',
0x11: 'Reserved for 3GPP — (I-)WLAN access status (TS 31.111 7.5.1)', 0x11: '(I-)WLAN access status',
0x12: 'Reserved for 3GPP — Network rejection (TS 31.111 7.5.2)', 0x12: 'Network rejection',
0x13: 'HCI connectivity', 0x13: 'HCI connectivity',
0x14: 'Access technology change (multiple)', 0x14: 'Access technology change (multiple access technologies)',
0x15: 'Reserved for 3GPP — CSG cell selection (TS 31.111 7.5.3)', 0x15: 'CSG cell selection',
0x16: 'Contactless state request', 0x16: 'Contactless state request',
0x17: 'Reserved for 3GPP — IMS registration (TS 31.111 7.5.21)', 0x17: 'IMS registration',
0x18: 'Reserved for 3GPP — Incoming IMS data (TS 31.111 7.5.20)', 0x18: 'Incoming IMS data',
0x19: 'Profile container', 0x1A: 'Void', 0x1B: 'Secured profile container', 0x19: 'Profile container', 0x1A: 'Void', 0x1B: 'Secured profile container',
0x1C: 'Poll interval negotiation', 0x1C: 'Poll interval negotiation',
0x1D: 'Reserved for 3GPP — Data connection status change (TS 31.111 7.5.25)', 0x1D: 'Data connection status change',
0x1E: 'Reserved for 3GPP — CAG cell selection (TS 31.111 7.5.26)', 0x1E: 'CAG cell selection',
0x1F: 'Reserved for 3GPP — Slices status change (TS 31.111 7.5.27)', 0x1F: 'Slices status change',
0x20: 'Reserved for 3GPP (future usage)', 0x20: 'Reserved (future usage)',
0x21: 'Reserved for 3GPP (future usage)', 0x21: 'Reserved (future usage)',
0x22: 'Reserved for 3GPP (future usage)', 0x22: 'Reserved (future usage)',
}; };
const REJECTION_CAUSES = [ const REJECTION_CAUSES = [
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'simple-v294'; const CACHE = 'simple-v295';
const URLS = [ const URLS = [
'index.html', 'index.html',
'help.html', 'help.html',
+9 -5
View File
@@ -66,15 +66,19 @@ test('cmdQualifierShort returns empty for unknown types', () => {
}); });
test('EVENT_NAMES follows the pinned CAT spec and names the 3GPP events', () => { test('EVENT_NAMES follows the pinned CAT spec and names the 3GPP events', () => {
assert.strictEqual(EVENT_NAMES[0x0B], 'Access technology change (single)'); assert.strictEqual(EVENT_NAMES[0x0B], 'Access technology change (single access technology)');
assert.strictEqual(EVENT_NAMES[0x14], 'Access technology change (multiple)'); assert.strictEqual(EVENT_NAMES[0x14], 'Access technology change (multiple access technologies)');
assert.strictEqual(EVENT_NAMES[0x19], 'Profile container'); assert.strictEqual(EVENT_NAMES[0x19], 'Profile container');
assert.strictEqual(EVENT_NAMES[0x1C], 'Poll interval negotiation'); assert.strictEqual(EVENT_NAMES[0x1C], 'Poll interval negotiation');
for (const [v, frag] of [[0x11, '(I-)WLAN access status'], [0x12, 'Network rejection'], for (const [v, name] of [[0x11, '(I-)WLAN access status'], [0x12, 'Network rejection'],
[0x15, 'CSG cell selection'], [0x17, 'IMS registration'], [0x18, 'Incoming IMS data'], [0x15, 'CSG cell selection'], [0x17, 'IMS registration'], [0x18, 'Incoming IMS data'],
[0x1D, 'Data connection status change'], [0x1E, 'CAG cell selection'], [0x1D, 'Data connection status change'], [0x1E, 'CAG cell selection'],
[0x1F, 'Slices status change']]) { [0x1F, 'Slices status change'], [0x20, 'Reserved (future usage)']]) {
assert.ok(EVENT_NAMES[v].includes(frag), '0x' + v.toString(16) + ': ' + EVENT_NAMES[v]); assert.strictEqual(EVENT_NAMES[v], name, '0x' + v.toString(16));
}
// the "Reserved for 3GPP" spec cross-reference is never user-facing
for (const [v, name] of Object.entries(EVENT_NAMES)) {
assert.ok(!name.includes('Reserved for 3GPP'), v + ': ' + name);
} }
}); });
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "pysim-simple-server" name = "pysim-simple-server"
version = "3.6.21" version = "3.6.22"
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.
+18 -17
View File
@@ -31,7 +31,7 @@ from osmocom.tlv import BER_TLV_IE
from osmocom.utils import rpad from osmocom.utils import rpad
VERSION = '3.6.21' VERSION = '3.6.22'
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
@@ -1769,34 +1769,35 @@ def _tr_data_only(tr_tlv):
return bytes(data) return bytes(data)
# Event list codings (TS 102 223 v18.3.0 8.25). Values the CAT spec leaves # Event list codings (TS 102 223 v18.3.0 8.25). The values the CAT spec only
# "Reserved for 3GPP" carry the concrete 3GPP event name where TS 31.111 # points at 3GPP for carry their TS 31.111 7.5 event name; "Reserved for
# defines one (clauses in parentheses), so the list stays informative. # 3GPP" is a spec cross-reference, not a usage restriction, so it never
# appears in the user-facing names.
EVENT_NAMES = { EVENT_NAMES = {
0x00: 'MT call', 0x01: 'Call connected', 0x02: 'Call disconnected', 0x00: 'MT call', 0x01: 'Call connected', 0x02: 'Call disconnected',
0x03: 'Location status', 0x04: 'User activity', 0x05: 'Idle screen available', 0x03: 'Location status', 0x04: 'User activity', 0x05: 'Idle screen available',
0x06: 'Card reader status', 0x07: 'Language selection', 0x06: 'Card reader status', 0x07: 'Language selection',
0x08: 'Browser termination', 0x09: 'Data available', 0x08: 'Browser termination', 0x09: 'Data available',
0x0A: 'Channel status', 0x0B: 'Access technology change (single)', 0x0A: 'Channel status', 0x0B: 'Access technology change (single access technology)',
0x0C: 'Display parameters changed', 0x0D: 'Local connection', 0x0C: 'Display parameters changed', 0x0D: 'Local connection',
0x0E: 'Network search mode change', 0x0F: 'Browsing status', 0x0E: 'Network search mode change', 0x0F: 'Browsing status',
0x10: 'Frames information change', 0x10: 'Frames information change',
0x11: 'Reserved for 3GPP \u2014 (I-)WLAN access status (TS 31.111 7.5.1)', 0x11: '(I-)WLAN access status',
0x12: 'Reserved for 3GPP \u2014 Network rejection (TS 31.111 7.5.2)', 0x12: 'Network rejection',
0x13: 'HCI connectivity', 0x13: 'HCI connectivity',
0x14: 'Access technology change (multiple)', 0x14: 'Access technology change (multiple access technologies)',
0x15: 'Reserved for 3GPP \u2014 CSG cell selection (TS 31.111 7.5.3)', 0x15: 'CSG cell selection',
0x16: 'Contactless state request', 0x16: 'Contactless state request',
0x17: 'Reserved for 3GPP \u2014 IMS registration (TS 31.111 7.5.21)', 0x17: 'IMS registration',
0x18: 'Reserved for 3GPP \u2014 Incoming IMS data (TS 31.111 7.5.20)', 0x18: 'Incoming IMS data',
0x19: 'Profile container', 0x1A: 'Void', 0x1B: 'Secured profile container', 0x19: 'Profile container', 0x1A: 'Void', 0x1B: 'Secured profile container',
0x1C: 'Poll interval negotiation', 0x1C: 'Poll interval negotiation',
0x1D: 'Reserved for 3GPP \u2014 Data connection status change (TS 31.111 7.5.25)', 0x1D: 'Data connection status change',
0x1E: 'Reserved for 3GPP \u2014 CAG cell selection (TS 31.111 7.5.26)', 0x1E: 'CAG cell selection',
0x1F: 'Reserved for 3GPP \u2014 Slices status change (TS 31.111 7.5.27)', 0x1F: 'Slices status change',
0x20: 'Reserved for 3GPP (future usage)', 0x20: 'Reserved (future usage)',
0x21: 'Reserved for 3GPP (future usage)', 0x21: 'Reserved (future usage)',
0x22: 'Reserved for 3GPP (future usage)', 0x22: 'Reserved (future usage)',
} }
ACCESSTECH_NAMES = { ACCESSTECH_NAMES = {
+21 -18
View File
@@ -36,35 +36,38 @@ class ProactiveTypeNamesTests(unittest.TestCase):
class EventNamesTests(unittest.TestCase): class EventNamesTests(unittest.TestCase):
"""Event list names follow TS 102 223 v18.3.0 8.25; the values the CAT """Event list names follow TS 102 223 v18.3.0 8.25; the values the CAT
spec leaves "Reserved for 3GPP" carry the TS 31.111 event name.""" spec points at 3GPP for carry their TS 31.111 7.5 event name."""
def test_reassigned_values_match_the_pinned_spec(self): def test_reassigned_values_match_the_pinned_spec(self):
for value, name in [ for value, name in [
(0x0B, 'Access technology change (single)'), (0x0B, 'Access technology change (single access technology)'),
(0x14, 'Access technology change (multiple)'), (0x14, 'Access technology change (multiple access technologies)'),
(0x19, 'Profile container'), (0x19, 'Profile container'),
(0x1A, 'Void'), (0x1A, 'Void'),
(0x1B, 'Secured profile container'), (0x1B, 'Secured profile container'),
(0x1C, 'Poll interval negotiation'), (0x1C, 'Poll interval negotiation'),
(0x20, 'Reserved for 3GPP (future usage)'), (0x20, 'Reserved (future usage)'),
]: ]:
self.assertEqual(EVENT_NAMES[value], name, hex(value)) self.assertEqual(EVENT_NAMES[value], name, hex(value))
def test_3gpp_reserved_events_carry_their_3gpp_name(self): def test_3gpp_assigned_events_carry_their_name(self):
for value, fragment, clause in [ for value, name in [
(0x11, '(I-)WLAN access status', 'TS 31.111 7.5.1'), (0x11, '(I-)WLAN access status'),
(0x12, 'Network rejection', 'TS 31.111 7.5.2'), (0x12, 'Network rejection'),
(0x15, 'CSG cell selection', 'TS 31.111 7.5.3'), (0x15, 'CSG cell selection'),
(0x17, 'IMS registration', 'TS 31.111 7.5.21'), (0x17, 'IMS registration'),
(0x18, 'Incoming IMS data', 'TS 31.111 7.5.20'), (0x18, 'Incoming IMS data'),
(0x1D, 'Data connection status change', 'TS 31.111 7.5.25'), (0x1D, 'Data connection status change'),
(0x1E, 'CAG cell selection', 'TS 31.111 7.5.26'), (0x1E, 'CAG cell selection'),
(0x1F, 'Slices status change', 'TS 31.111 7.5.27'), (0x1F, 'Slices status change'),
]: ]:
name = EVENT_NAMES[value] self.assertEqual(EVENT_NAMES[value], name, hex(value))
self.assertIn('Reserved for 3GPP', name, hex(value))
self.assertIn(fragment, name, hex(value)) def test_no_reserved_for_3gpp_wording(self):
self.assertIn(clause, name, hex(value)) # a spec cross-reference, not a usage restriction - it must never
# reach the user-facing names
for value, name in EVENT_NAMES.items():
self.assertNotIn('Reserved for 3GPP', name, hex(value))
def test_names_are_nonempty_strings(self): def test_names_are_nonempty_strings(self):
for value, name in EVENT_NAMES.items(): for value, name in EVENT_NAMES.items():