feat: the conditional event objects are complete

The six forms that still missed conditional/optional objects now carry them:

- Location status (0x03): Location Information (MCC/MNC + LAC + Cell ID) -
  included only for Normal service, as TS 102 223 8.19 requires.
- Channel status (0x0A): Bearer Description (B5, type + parameters) and
  Other address (BE, IPv4 dotted / IPv6 hex / the empty "dynamic address"
  form); new eventIpBytes() helper.
- Call disconnected (0x02): IMS call disconnection cause (D5, SIP/Q.850 +
  2-byte cause).
- Network rejection (0x12): Extended information (F2, CAG ID / NID / RedCap).
- CAG cell selection (0x1E): CAG Human-readable network name list (D7,
  80-tagged names).
- Slices status change (0x1F): Allowed slices with S-NSSAI mapping (F7),
  Allowed slices (F8), Rejected slices with mapping (D7) and Rejected slices
  (B1) beside the served list.

Every implemented event form now carries all the objects of its spec table.
Tests: the new build vectors.  Help EN/RU and both AGENTS files; sw
simple-v350.
This commit is contained in:
2026-10-01 22:57:01 +03:00
parent 7061f42781
commit 69abbe2fa5
5 changed files with 129 additions and 15 deletions
+33
View File
@@ -216,3 +216,36 @@ test('the IMS, CAG and slices events build their object sets', () => {
assert.strictEqual(EVENT_FORMS[0x1F].build({ status: '1', tech: '8', served: '01020304' }),
'BF0108D50101D6050101020304');
});
test('the location-status event can carry the location information', () => {
const build = EVENT_FORMS[0x03].build;
// Normal service: the 8.19 object follows the status
assert.strictEqual(build({ status: '0', mcc: '250', mnc: '01', lac: '00FF', cell: '0001' }),
'9B0100930752F01000FF0001');
// Limited / No service: no location information
assert.strictEqual(build({ status: '1', mcc: '250' }), '9B0101');
assert.strictEqual(build({ status: '0' }), '9B0100');
});
test('the channel-status event can carry the bearer and the local address', () => {
const build = EVENT_FORMS[0x0A].build;
assert.strictEqual(build({ channel: '1', state: '128', info: '0' }), 'B8028100');
assert.strictEqual(build({ channel: '1', state: '128', info: '0', bearer: '5', addr_type: '21', addr: '192.168.1.2' }),
'B8028100B50105BE0521C0A80102');
assert.strictEqual(build({ channel: '1', state: '128', info: '0', addr_type: '00' }), 'B8028100BE00');
});
test('the disconnected/rejection/CAG/slices events carry their extra objects', () => {
// IMS call disconnection cause: protocol + 2-byte cause (603 -> 025B)
assert.strictEqual(EVENT_FORMS[0x02].build({ ti: '00', cause_mode: '', media: '', ims_proto: '1', ims_cause: '603' }),
'1C0100D50301025B');
// Extended information (CAG ID, 4 bytes)
assert.ok(EVENT_FORMS[0x12].build({ reg_type: '9', access_tech: '8', cause: '2', ext_info_type: '1', ext_info: '00000001' })
.endsWith('F2050100000001'));
// CAG HRNN list (80-tagged names)
assert.ok(EVENT_FORMS[0x1E].build({ status: '1', list: '', hrnn: 'A,B' }).endsWith('D706800141800142'));
// allowed/served/rejected slice lists, with and without mapping
assert.ok(EVENT_FORMS[0x1F].build({ status: '1', served: '', allowed_map: '01020304', allowed: '01020304',
rejected_map: '01020304', rejected: '01020304' })
.endsWith('F70401020304F80401020304D70401020304B10401020304'));
});