diff --git a/frontend/index.html b/frontend/index.html
index 4847cf0..5bbbc7d 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1881,7 +1881,7 @@ function onFilterChange() {
}
// ──────────────────── Versioning ────────────────────
-const PWA_VERSION = '1.15.0';
+const PWA_VERSION = '1.15.1';
const MIN_SERVER_VERSION = '1.0.0';
function parseVersion(v) {
diff --git a/frontend/sw.js b/frontend/sw.js
index 0c16157..2c3a8eb 100644
--- a/frontend/sw.js
+++ b/frontend/sw.js
@@ -1,4 +1,4 @@
-const CACHE = 'simtrace-analyser-v20';
+const CACHE = 'simtrace-analyser-v21';
const PRECACHE = [
'index.html',
diff --git a/pyproject.toml b/pyproject.toml
index 882998e..6ae3e51 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
[project]
name = "simtrace2-pysniff"
-version = "1.15.0"
+version = "1.15.1"
description = "Python-based sniffing tool for SIMtrace2 hardware (SIM card communication sniffer)"
readme = {file = "README.md", content-type = "text/markdown"}
license = {text = "GPL-2.0-or-later"}
diff --git a/simtrace2_pysniff/__init__.py b/simtrace2_pysniff/__init__.py
index 4c6bc5f..fc0124e 100644
--- a/simtrace2_pysniff/__init__.py
+++ b/simtrace2_pysniff/__init__.py
@@ -6,7 +6,7 @@ from .gsmtap import GsmtapSender, GsmtapReceiver
from .pcap import PcapWriter
from .dump import FileDumper, format_message
-__version__ = '1.15.0'
+__version__ = '1.15.1'
__all__ = [
'SniffSession',
'DeviceDisconnected',
diff --git a/simtrace2_pysniff/server/decode.py b/simtrace2_pysniff/server/decode.py
index d344cfb..95a7f26 100644
--- a/simtrace2_pysniff/server/decode.py
+++ b/simtrace2_pysniff/server/decode.py
@@ -1069,20 +1069,9 @@ COMMAND_QUALIFIERS = {
0x01: REFRESH_MODES, # REFRESH
0x26: PLI_QUALIFIERS, # PROVIDE LOCAL INFORMATION
}
-
-
-def _idle_text_qualifier(qualifier):
- """SET UP IDLE MODE TEXT (TS 102 223 §6.6.13): bit 1 = icon
- self-explanatory flag, all other bits RFU."""
- if qualifier & ~0x01:
- return f'0x{qualifier:02X}'
- if qualifier & 0x01:
- return 'icon self-explanatory'
- return None
-
-
-# TS 102 223 §6.6.13 — SET UP IDLE MODE TEXT
-COMMAND_QUALIFIERS[0x28] = _idle_text_qualifier
+# NOTE: SET UP IDLE MODE TEXT ('28') has no entry — its Command Qualifier
+# is RFU per TS 102 223 V18.3.0 §8.6 ("this byte is RFU"); the generic
+# fallback (hidden at '00', raw hex otherwise) applies.
# ──────────────────── §8.6 bitmask qualifier decoders ────────────────────
diff --git a/tests/test_decode.py b/tests/test_decode.py
index 491c0cc..803507c 100644
--- a/tests/test_decode.py
+++ b/tests/test_decode.py
@@ -1556,14 +1556,16 @@ class TestIdleModeText(unittest.TestCase):
bytes.fromhex('80120000%02x' % len(body)) + body + b'\x90\x00')
def test_8bit_text_icon_qualifier(self):
- # "Hello" 8-bit + icon record 5 + qualifier bit 1 (self-explanatory)
+ # "Hello" 8-bit + icon record 5 + qualifier 0x01 (RFU byte — no
+ # icon bit exists per TS 102 223 V18.3.0 §8.6)
r = self._fetch(
'810301280182028182' # cmd details (qual 0x01) + device ids
'8d060448656c6c6f' # Text String: DCS 0x04 (8-bit), "Hello"
'1e0105') # Icon Identifier: record 5
self.assertEqual(r['cat_command'], 'SET UP IDLE MODE TEXT')
self.assertEqual(r['cmd']['text'], 'Hello')
- self.assertEqual(r['cmd']['qualifier'], 'icon self-explanatory')
+ # Qualifier byte is RFU per V18.3.0 §8.6 — non-zero shows raw
+ self.assertEqual(r['cmd']['qualifier'], '0x01')
self.assertEqual(r['cmd']['icon_id'], 5)
def test_ucs2_text(self):
diff --git a/tests/test_pcap_import.py b/tests/test_pcap_import.py
index 2dc33f9..9219d2f 100644
--- a/tests/test_pcap_import.py
+++ b/tests/test_pcap_import.py
@@ -197,7 +197,7 @@ class TestImportEndpoint(unittest.TestCase):
class TestVersion(unittest.TestCase):
def test_package_version(self):
from simtrace2_pysniff import __version__
- self.assertEqual(__version__, '1.15.0')
+ self.assertEqual(__version__, '1.15.1')
def test_status_includes_version(self):
import os