Add PLI qualifier description to PROVIDE LOCAL INFORMATION decode
- PLI_QUALIFIERS: TS 102 223 qualifier values (Location Info, IMEI, NMR, Date/time, Timing Advance, Access Technology, etc.) - _command_details_name(): appends the qualifier description to PROVIDE LOCAL INFORMATION (type 0x26) in Command Details - decode_cat (FETCH) and decode_tr_command (TR) now use it, so both 'cat_command' and 'response_to' carry the qualifier (e.g. 'PROVIDE LOCAL INFORMATION — IMEI') tests: PLI qualifier cases (TR/FETCH, IMEI/location/date, non-PLI)
This commit is contained in:
1 parent
f30fe41d75
commit
31011301ea
2 files changed
+75
-5
No files matched your search
@@ -478,6 +478,51 @@ def parse_tlv(data):
|
|||||||
return tlvs
|
return tlvs
|
||||||
|
|
||||||
|
|
||||||
|
# TS 102 223 — PROVIDE LOCAL INFORMATION command qualifier values
|
||||||
|
PLI_QUALIFIERS = {
|
||||||
|
0x00: 'Location Info (MCC, MNC, LAC/TAC, Cell ID)',
|
||||||
|
0x01: 'IMEI',
|
||||||
|
0x02: 'Network Measurement results',
|
||||||
|
0x03: 'Date, time and time zone',
|
||||||
|
0x04: 'Language setting',
|
||||||
|
0x05: 'Timing Advance',
|
||||||
|
0x06: 'Access Technology (single)',
|
||||||
|
0x08: 'IMEISV',
|
||||||
|
0x09: 'Search Mode',
|
||||||
|
0x0A: 'Battery charge state',
|
||||||
|
0x0C: 'Current WSID',
|
||||||
|
0x0D: 'Broadcast Network info',
|
||||||
|
0x0E: 'Multiple Access Technologies',
|
||||||
|
0x0F: 'Location Info (multi-RAT)',
|
||||||
|
0x10: 'NMR (multi-RAT)',
|
||||||
|
0x11: 'CSG ID list + HNB name',
|
||||||
|
0x12: 'H(e)NB IP address',
|
||||||
|
0x13: 'H(e)NB surrounding macrocells',
|
||||||
|
0x14: 'Current WLAN identifier',
|
||||||
|
0x15: 'Slices information',
|
||||||
|
0x16: 'CAG information list',
|
||||||
|
0x17: 'Rejected slices information',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _command_details_name(value):
|
||||||
|
"""Decode a Command Details TLV value (number, type, qualifier).
|
||||||
|
|
||||||
|
Returns the command type name, with the PLI qualifier description
|
||||||
|
appended for PROVIDE LOCAL INFORMATION (type 0x26).
|
||||||
|
"""
|
||||||
|
if len(value) < 2:
|
||||||
|
return None
|
||||||
|
name = CAT_COMMAND_TYPES.get(value[1])
|
||||||
|
if not name:
|
||||||
|
return None
|
||||||
|
if value[1] == 0x26 and len(value) >= 3: # PROVIDE LOCAL INFORMATION
|
||||||
|
q = PLI_QUALIFIERS.get(value[2])
|
||||||
|
if q:
|
||||||
|
name = f'{name} — {q}'
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
def decode_cat(ins, body):
|
def decode_cat(ins, body):
|
||||||
"""Decode a CAT (TS 102 223) payload, returning the command/event name.
|
"""Decode a CAT (TS 102 223) payload, returning the command/event name.
|
||||||
|
|
||||||
@@ -493,8 +538,8 @@ def decode_cat(ins, body):
|
|||||||
if tag != 0xD0:
|
if tag != 0xD0:
|
||||||
continue
|
continue
|
||||||
for t2, _l2, v2 in parse_tlv(value):
|
for t2, _l2, v2 in parse_tlv(value):
|
||||||
if t2 == 0x81 and len(v2) >= 2:
|
if t2 == 0x81:
|
||||||
return CAT_COMMAND_TYPES.get(v2[1])
|
return _command_details_name(v2)
|
||||||
elif ins == 0xC2: # ENVELOPE → envelope type
|
elif ins == 0xC2: # ENVELOPE → envelope type
|
||||||
return ENVELOPE_TYPES.get(body[0])
|
return ENVELOPE_TYPES.get(body[0])
|
||||||
return None
|
return None
|
||||||
@@ -508,8 +553,8 @@ def decode_tr_command(body):
|
|||||||
if not body:
|
if not body:
|
||||||
return None
|
return None
|
||||||
for tag, _length, value in parse_tlv(body):
|
for tag, _length, value in parse_tlv(body):
|
||||||
if tag == 0x81 and len(value) >= 2:
|
if tag == 0x81:
|
||||||
return CAT_COMMAND_TYPES.get(value[1])
|
return _command_details_name(value)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+26
-1
@@ -58,7 +58,8 @@ class TestCatDecoding(unittest.TestCase):
|
|||||||
def test_fetch_provide_local_info(self):
|
def test_fetch_provide_local_info(self):
|
||||||
r = decode_message(bytes.fromhex(
|
r = decode_message(bytes.fromhex(
|
||||||
'801200000BD0098103012600820281829000'))
|
'801200000BD0098103012600820281829000'))
|
||||||
self.assertEqual(r['cat_command'], 'PROVIDE LOCAL INFORMATION')
|
self.assertEqual(r['cat_command'],
|
||||||
|
'PROVIDE LOCAL INFORMATION — Location Info (MCC, MNC, LAC/TAC, Cell ID)')
|
||||||
|
|
||||||
def test_envelope_event_download(self):
|
def test_envelope_event_download(self):
|
||||||
r = decode_message(bytes.fromhex(
|
r = decode_message(bytes.fromhex(
|
||||||
@@ -138,6 +139,30 @@ class TestTerminalResponse(unittest.TestCase):
|
|||||||
self.assertEqual(r['response_to'], 'POLL INTERVAL')
|
self.assertEqual(r['response_to'], 'POLL INTERVAL')
|
||||||
|
|
||||||
|
|
||||||
|
class TestPliQualifier(unittest.TestCase):
|
||||||
|
def test_tr_pli_imei(self):
|
||||||
|
r = decode_message(bytes.fromhex(
|
||||||
|
'8014000016810301260102028281030106130952F0991EC57A68009F'))
|
||||||
|
self.assertEqual(r['response_to'], 'PROVIDE LOCAL INFORMATION — IMEI')
|
||||||
|
|
||||||
|
def test_fetch_pli_location(self):
|
||||||
|
r = decode_message(bytes.fromhex(
|
||||||
|
'801200000BD0098103012600820281829000'))
|
||||||
|
self.assertEqual(r['cat_command'],
|
||||||
|
'PROVIDE LOCAL INFORMATION — Location Info (MCC, MNC, LAC/TAC, Cell ID)')
|
||||||
|
|
||||||
|
def test_fetch_pli_date_time(self):
|
||||||
|
r = decode_message(bytes.fromhex(
|
||||||
|
'801200000BD0098103012603820281829000'))
|
||||||
|
self.assertEqual(r['cat_command'],
|
||||||
|
'PROVIDE LOCAL INFORMATION — Date, time and time zone')
|
||||||
|
|
||||||
|
def test_non_pli_no_qualifier(self):
|
||||||
|
r = decode_message(bytes.fromhex(
|
||||||
|
'801400000C810301250002028281830100910F'))
|
||||||
|
self.assertEqual(r['response_to'], 'SET UP MENU')
|
||||||
|
|
||||||
|
|
||||||
class TestGetResponseContext(unittest.TestCase):
|
class TestGetResponseContext(unittest.TestCase):
|
||||||
GET_RESPONSE = bytes.fromhex('00C000002962278202782183023F00A50A800171')
|
GET_RESPONSE = bytes.fromhex('00C000002962278202782183023F00A50A800171')
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user