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:
@@ -501,13 +501,13 @@
|
||||
<p class="text-sm mb-2">События, которые отслеживает карта. У каждого события есть кнопка <strong>Отправить</strong>, открывающая форму, специфичную для типа события:</p>
|
||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||
<li><strong>События без данных</strong> (User Activity, Idle Screen, Data Available, …) — уведомление в один клик</li>
|
||||
<li><strong>Location Status</strong> — выпадающий список: Normal / Limited / No service (тег <code class="font-mono text-sm">9B</code>)</li>
|
||||
<li><strong>Location Status</strong> — выпадающий список: Normal / Limited / No service (тег <code class="font-mono text-sm">9B</code>); для Normal service можно добавить location information (MCC/MNC + LAC + Cell ID)</li>
|
||||
<li><strong>Access Technology Change</strong> — 13 типов RAT (тег <code class="font-mono text-sm">BF</code>)</li>
|
||||
<li><strong>Network Rejection</strong> — полная адаптивная форма: тип регистрации (LU / GPRS / EPS / 5GS), поля местоположения (MCC, MNC, LAC, RAC, TAC), технология доступа и единый выпадающий список из 53 кодов причин (EMM, GMM, 5GMM и LU)</li>
|
||||
<li><strong>События звонка</strong> — MT call (transaction identifier, номер вызывающего + TON → Address, subaddress, IMS URI, media type; источник <em>network</em>), Call connected и Call disconnected (transaction identifier, источник near/far, media type и причина — отсутствует, нулевая форма radio link timeout или свои байты)</li>
|
||||
<li><strong>Network Rejection</strong> — полная адаптивная форма: тип регистрации (LU / GPRS / EPS / 5GS), поля местоположения (MCC, MNC, LAC, RAC, TAC), технология доступа и единый выпадающий список из 53 кодов причин (EMM, GMM, 5GMM и LU), а также необязательные extended cause и extended information (CAG ID / NID / RedCap)</li>
|
||||
<li><strong>События звонка</strong> — MT call (transaction identifier, номер вызывающего + TON → Address, subaddress, IMS URI, media type; источник <em>network</em>), Call connected и Call disconnected (transaction identifier, источник near/far, media type и причина — отсутствует, нулевая форма radio link timeout или свои байты), а также необязательная причина IMS-разрыва (SIP / Q.850 + cause)</li>
|
||||
<li><strong>Browser termination</strong> (причина user / error), <strong>(I-)WLAN access status</strong> (нет покрытия / покрытие / соединение) и <strong>CSG cell selection</strong> (статус + механизм выбора, access technology, CSG ID, HNB name, PLMN ID; источник <em>network</em>)</li>
|
||||
<li><strong>Data available</strong> (канал + состояние звена + инфо, и длина данных канала, теги <code class="font-mono text-sm">B8</code>/<code class="font-mono text-sm">B7</code>), <strong>Display parameters changed</strong> (строки/столбцы + флаги sizing/fonts/effects, тег <code class="font-mono text-sm">C0</code>), <strong>Network search mode change</strong> (manual/automatic, тег <code class="font-mono text-sm">E5</code>), <strong>Browsing status</strong> (код ошибки браузера, тег <code class="font-mono text-sm">E4</code>) и <strong>Frames information change</strong> (фрейм по умолчанию + инфо по фреймам, тег <code class="font-mono text-sm">E7</code>)</li>
|
||||
<li><strong>IMS registration</strong> (IMPU URI + IMS status code) и <strong>Incoming IMS data</strong> (IARI) — источник <em>network</em>; <strong>CAG cell selection</strong> (статус + механизм, access technology, CAG information list) и <strong>Slices status change</strong> (allowed / rejected / served / partially, access technology, served S-NSSAIs) — источник <em>network</em></li>
|
||||
<li><strong>Channel status</strong> (канал + состояние звена + инфо, тег <code class="font-mono text-sm">B8</code>, с необязательными bearer description <code class="font-mono text-sm">B5</code> и local address <code class="font-mono text-sm">BE</code>) и <strong>Data available</strong> (тот же channel status + длина данных канала, тег <code class="font-mono text-sm">B7</code>), <strong>Display parameters changed</strong> (строки/столбцы + флаги sizing/fonts/effects, тег <code class="font-mono text-sm">C0</code>), <strong>Network search mode change</strong> (manual/automatic, тег <code class="font-mono text-sm">E5</code>), <strong>Browsing status</strong> (код ошибки браузера, тег <code class="font-mono text-sm">E4</code>) и <strong>Frames information change</strong> (фрейм по умолчанию + инфо по фреймам, тег <code class="font-mono text-sm">E7</code>)</li>
|
||||
<li><strong>IMS registration</strong> (IMPU URI + IMS status code) и <strong>Incoming IMS data</strong> (IARI) — источник <em>network</em>; <strong>CAG cell selection</strong> (статус + механизм, access technology, CAG information list + HRNN list) и <strong>Slices status change</strong> (allowed / rejected / served / partially, access technology, списки allowed / served / rejected S-NSSAI, с маппингом и без) — источник <em>network</em></li>
|
||||
<li><strong>Data Connection Status Change</strong> (0x1D) — статус (successful / rejected / dropped-deactivated), тип соединения (PDP / PDN / PDU), необязательная причина (E/5G)SM, transaction identifier и location status, а также необязательные date-time, access technology, APN, тип PDP/PDN/PDU и location information (MCC/MNC + LAC + Cell ID) — TS 131 111 §7.5.25</li>
|
||||
<li><strong>Poll Interval Negotiation</strong> (0x1C) — предлагает интервал опроса в виде Duration (единица + значение); после отправки показывается ответ UICC (принято / отклонено / изменено + длительность), а значение <em>изменено</em> становится интервалом фонового опроса (TS 102 223 §7.5.22). Форма появляется, когда карта подписана на это событие.</li>
|
||||
</ul>
|
||||
|
||||
+5
-5
@@ -500,13 +500,13 @@
|
||||
<p class="text-sm mb-2">The events the card monitors. Each event has a <strong>Send</strong> button that opens a form specific to the event type:</p>
|
||||
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
|
||||
<li><strong>No-data events</strong> (User Activity, Idle Screen, Data Available, …) — one-click notification</li>
|
||||
<li><strong>Location Status</strong> — dropdown: Normal / Limited / No service (tag <code class="font-mono text-sm">9B</code>)</li>
|
||||
<li><strong>Location Status</strong> — dropdown: Normal / Limited / No service (tag <code class="font-mono text-sm">9B</code>); for Normal service the location information (MCC/MNC + LAC + Cell ID) can be included</li>
|
||||
<li><strong>Access Technology Change</strong> — 13 RAT types (tag <code class="font-mono text-sm">BF</code>)</li>
|
||||
<li><strong>Network Rejection</strong> — full adaptive form: registration type (LU / GPRS / EPS / 5GS), location fields (MCC, MNC, LAC, RAC, TAC), access technology, and a 53-cause unified rejection cause dropdown covering EMM, GMM, 5GMM and LU causes</li>
|
||||
<li><strong>Call events</strong> — MT call (transaction identifier, calling party number + TON → Address, subaddress, IMS URI, media type; source <em>network</em>), Call connected and Call disconnected (transaction identifier, near/far-end source, media type, and a cause — absent, the zero-length radio-link-timeout form, or custom bytes)</li>
|
||||
<li><strong>Network Rejection</strong> — full adaptive form: registration type (LU / GPRS / EPS / 5GS), location fields (MCC, MNC, LAC, RAC, TAC), access technology, and a 53-cause unified rejection cause dropdown covering EMM, GMM, 5GMM and LU causes, plus the optional extended cause and extended information (CAG ID / NID / RedCap)</li>
|
||||
<li><strong>Call events</strong> — MT call (transaction identifier, calling party number + TON → Address, subaddress, IMS URI, media type; source <em>network</em>), Call connected and Call disconnected (transaction identifier, near/far-end source, media type, and a cause — absent, the zero-length radio-link-timeout form, or custom bytes), plus the optional IMS disconnection cause (SIP / Q.850 + cause)</li>
|
||||
<li><strong>Browser termination</strong> (user / error cause), <strong>(I-)WLAN access status</strong> (no coverage / coverage / connection on-going) and <strong>CSG cell selection</strong> (status + selection mechanism, access technology, CSG ID, HNB name, PLMN ID; source <em>network</em>)</li>
|
||||
<li><strong>Data available</strong> (channel + link state + channel info, and the channel data length, tags <code class="font-mono text-sm">B8</code>/<code class="font-mono text-sm">B7</code>), <strong>Display parameters changed</strong> (rows/columns + sizing/fonts/effects flags, tag <code class="font-mono text-sm">C0</code>), <strong>Network search mode change</strong> (manual/automatic, tag <code class="font-mono text-sm">E5</code>), <strong>Browsing status</strong> (browser error code, tag <code class="font-mono text-sm">E4</code>) and <strong>Frames information change</strong> (default frame + per-frame info, tag <code class="font-mono text-sm">E7</code>)</li>
|
||||
<li><strong>IMS registration</strong> (IMPU URIs + IMS status code) and <strong>Incoming IMS data</strong> (IARI) — source <em>network</em>; <strong>CAG cell selection</strong> (status + mechanism, access technology, CAG information list) and <strong>Slices status change</strong> (allowed / rejected / served / partially status, access technology, served S-NSSAIs) — source <em>network</em></li>
|
||||
<li><strong>Channel status</strong> (channel + link state + channel info, tag <code class="font-mono text-sm">B8</code>, with an optional bearer description <code class="font-mono text-sm">B5</code> and local address <code class="font-mono text-sm">BE</code>) and <strong>Data available</strong> (the same channel status plus the channel data length, tag <code class="font-mono text-sm">B7</code>), <strong>Display parameters changed</strong> (rows/columns + sizing/fonts/effects flags, tag <code class="font-mono text-sm">C0</code>), <strong>Network search mode change</strong> (manual/automatic, tag <code class="font-mono text-sm">E5</code>), <strong>Browsing status</strong> (browser error code, tag <code class="font-mono text-sm">E4</code>) and <strong>Frames information change</strong> (default frame + per-frame info, tag <code class="font-mono text-sm">E7</code>)</li>
|
||||
<li><strong>IMS registration</strong> (IMPU URIs + IMS status code) and <strong>Incoming IMS data</strong> (IARI) — source <em>network</em>; <strong>CAG cell selection</strong> (status + mechanism, access technology, CAG information list + HRNN list) and <strong>Slices status change</strong> (allowed / rejected / served / partially status, access technology, allowed / served / rejected S-NSSAI lists, with and without mapping) — source <em>network</em></li>
|
||||
<li><strong>Data Connection Status Change</strong> (0x1D) — status (successful / rejected / dropped-deactivated), connection type (PDP / PDN / PDU), optional (E/5G)SM cause, transaction identifier and location status, plus optional date-time, access technology, APN, PDP/PDN/PDU type and location information (MCC/MNC + LAC + Cell ID) — TS 131 111 §7.5.25</li>
|
||||
<li><strong>Poll Interval Negotiation</strong> (0x1C) — proposes a poll interval as a Duration (unit + value); after sending, the UICC's answer is shown (accepted / rejected / modified + duration), and a <em>modified</em> duration becomes the background poll interval (TS 102 223 §7.5.22). The form appears when the card subscribed to this event.</li>
|
||||
</ul>
|
||||
|
||||
+85
-4
@@ -13070,6 +13070,17 @@ function eventAddressTlv(number, ton) {
|
||||
return '86' + (value.length / 2).toString(16).padStart(2, '0') + value;
|
||||
}
|
||||
|
||||
// Other address value (TS 102 223 8.58): a dotted IPv4 or hex address
|
||||
// bytes; '' when the text is not an even-length hex string.
|
||||
function eventIpBytes(text, type) {
|
||||
const s = String(text || '').trim();
|
||||
if (type === '21' && /^\d{1,3}(\.\d{1,3}){3}$/.test(s)) {
|
||||
return s.split('.').map(n => (parseInt(n, 10) & 0xFF).toString(16).padStart(2, '0')).join('').toUpperCase();
|
||||
}
|
||||
const h = s.replace(/[^0-9a-fA-F]/g, '');
|
||||
return h.length % 2 ? '' : h.toUpperCase();
|
||||
}
|
||||
|
||||
const ACCESSTECH = [
|
||||
{v:0,l:'GSM'},{v:1,l:'TIA/EIA-553-A'},{v:2,l:'TIA/EIA-136-270'},{v:3,l:'UTRAN'},
|
||||
{v:4,l:'TETRA'},{v:5,l:'TIA/EIA-95-B'},{v:6,l:'CDMA2000 1x'},{v:7,l:'CDMA2000 HRPD'},
|
||||
@@ -13129,6 +13140,9 @@ const EVENT_FORMS = {
|
||||
{ id: 'cause', label: 'Cause bytes (hex)', type: 'text', pattern: '[0-9A-Fa-f]{2,60}', placeholder: 'e.g. 10', g: 'custom' },
|
||||
{ id: 'media', label: 'Media Type (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'},{v:0,l:'00 \u2014 voice'},{v:1,l:'01 \u2014 video'}] },
|
||||
{ id: 'ims_proto', label: 'IMS disconnection cause (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'},{v:1,l:'01 \u2014 SIP'},{v:2,l:'02 \u2014 Q.850'}] },
|
||||
{ id: 'ims_cause', label: 'Cause value', type: 'number', min: '0', max: '65535', placeholder: '0\u201365535, e.g. 603' },
|
||||
],
|
||||
build(v) {
|
||||
let d = '1C01' + (v.ti || '00').replace(/[^0-9a-fA-F]/g, '').padStart(2, '0').slice(0, 2);
|
||||
@@ -13138,15 +13152,29 @@ const EVENT_FORMS = {
|
||||
d += '9A' + (cause.length / 2).toString(16).padStart(2, '0') + cause;
|
||||
if (v.media !== '' && v.media !== undefined)
|
||||
d += 'FE01' + ((parseInt(v.media) || 0) & 0xFF).toString(16).padStart(2, '0');
|
||||
if (v.ims_proto !== '' && v.ims_proto !== undefined && v.ims_cause !== '' && v.ims_cause !== undefined)
|
||||
d += 'D503' + ((parseInt(v.ims_proto) || 0) & 0xFF).toString(16).padStart(2, '0') +
|
||||
((parseInt(v.ims_cause) || 0) & 0xFFFF).toString(16).padStart(4, '0');
|
||||
return d.toUpperCase();
|
||||
}
|
||||
},
|
||||
0x03: { title: 'Location status',
|
||||
fields: [
|
||||
{ id: 'status', label: 'Service Status', type: 'select',
|
||||
opts: [{v:0,l:'Normal service'},{v:1,l:'Limited service'},{v:2,l:'No service'}] }
|
||||
opts: [{v:0,l:'Normal service'},{v:1,l:'Limited service'},{v:2,l:'No service'}] },
|
||||
{ id: 'mcc', label: 'MCC (Location Information)', type: 'text', pattern: '\\d{3}', placeholder: 'sent for Normal service' },
|
||||
{ id: 'mnc', label: 'MNC', type: 'text', pattern: '\\d{2,3}', placeholder: 'e.g. 01' },
|
||||
{ id: 'lac', label: 'LAC', type: 'text', pattern: '[0-9A-Fa-f]{4}', placeholder: 'hex, e.g. 00FF' },
|
||||
{ id: 'cell', label: 'Cell ID', type: 'text', pattern: '[0-9A-Fa-f]{4}', placeholder: 'hex, e.g. 0001' },
|
||||
],
|
||||
build(v) { return '9B01' + (v.status|0).toString(16).padStart(2,'0'); }
|
||||
build(v) {
|
||||
let d = '9B01' + (v.status|0).toString(16).padStart(2,'0');
|
||||
// 8.19: the location information is only included for Normal service
|
||||
if ((parseInt(v.status) || 0) === 0 && v.mcc)
|
||||
d += '9307' + encPlmn(v.mcc, v.mnc || '01') +
|
||||
(v.lac || '0000').toUpperCase() + (v.cell || '0001').toUpperCase();
|
||||
return d.toUpperCase();
|
||||
}
|
||||
},
|
||||
0x04: null,
|
||||
0x05: null,
|
||||
@@ -13205,10 +13233,34 @@ const EVENT_FORMS = {
|
||||
{ id: 'info', label: 'Channel info', type: 'select',
|
||||
opts: [{v:0x00,l:'No further info can be given'},
|
||||
{v:0x05,l:'Link dropped (network failure or user cancellation)'}] },
|
||||
{ id: 'bearer', label: 'Bearer Description (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'},
|
||||
{v:0x03,l:'03 \u2014 default bearer for the requested transport layer'},
|
||||
{v:0x04,l:'04 \u2014 local link technology independent'},
|
||||
{v:0x05,l:'05 \u2014 Bluetooth'},{v:0x06,l:'06 \u2014 IrDA'},
|
||||
{v:0x07,l:'07 \u2014 RS232'},{v:0x10,l:'10 \u2014 USB'}] },
|
||||
{ id: 'bearer_params', label: 'Bearer parameters (hex, optional)', type: 'text', pattern: '[0-9A-Fa-f]{2,40}', placeholder: 'bearer specific' },
|
||||
{ id: 'addr_type', label: 'Other address \u2014 local address (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'},{v:'21',l:'21 \u2014 IPv4 address'},
|
||||
{v:'57',l:'57 \u2014 IPv6 address'},{v:'00',l:'empty (request a dynamic address)'}] },
|
||||
{ id: 'addr', label: 'Address', type: 'text', placeholder: 'dotted IPv4 (192.168.1.2) or hex' },
|
||||
],
|
||||
build(v) {
|
||||
const st = (parseInt(v.state) || 0) | (parseInt(v.channel) || 0);
|
||||
return 'B802' + st.toString(16).padStart(2,'0') + (parseInt(v.info) || 0).toString(16).padStart(2,'0');
|
||||
let d = 'B802' + st.toString(16).padStart(2,'0') + ((parseInt(v.info) || 0) & 0xFF).toString(16).padStart(2,'0');
|
||||
if (v.bearer !== '' && v.bearer !== undefined) {
|
||||
const params = (v.bearer_params || '').replace(/[^0-9a-fA-F]/g, '');
|
||||
d += 'B5' + (1 + params.length / 2).toString(16).padStart(2, '0') +
|
||||
((parseInt(v.bearer) || 0) & 0xFF).toString(16).padStart(2, '0') + params;
|
||||
}
|
||||
if (v.addr_type !== '' && v.addr_type !== undefined) {
|
||||
if (v.addr_type === '00') d += 'BE00';
|
||||
else {
|
||||
const h = eventIpBytes(v.addr, v.addr_type);
|
||||
if (h) d += 'BE' + (1 + h.length / 2).toString(16).padStart(2, '0') + v.addr_type + h;
|
||||
}
|
||||
}
|
||||
return d.toUpperCase();
|
||||
}
|
||||
},
|
||||
0x0B: { title: 'Access Technology Change',
|
||||
@@ -13296,7 +13348,10 @@ const EVENT_FORMS = {
|
||||
{ id: 'access_tech', label: 'Access Technology', type: 'select',
|
||||
opts: [{v:0x00,l:'GSM'},{v:0x03,l:'UTRAN'},{v:0x08,l:'E-UTRAN'},{v:0x0A,l:'NG-RAN'},{v:0x0B,l:'Satellite NG-RAN'},{v:0x0C,l:'Satellite E-UTRAN'}], g: 'lu,gprs,eps' },
|
||||
{ id: 'cause', label: 'Rejection cause code', type: 'select', opts: REJECTION_CAUSES, g: 'lu,gprs,eps' },
|
||||
{ id: 'ext_cause', label: 'Extended EMM cause (optional)', type: 'number', min: '0', max: '255', placeholder: '0–255', g: 'eps' },
|
||||
{ id: 'ext_cause', label: 'Extended EMM cause (optional)', type: 'number', min: '0', max: '255', placeholder: '0\u2013255', g: 'eps' },
|
||||
{ id: 'ext_info_type', label: 'Extended information (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'},{v:1,l:'01 \u2014 CAG ID'},{v:2,l:'02 \u2014 NID'},{v:3,l:'03 \u2014 RedCap'}] },
|
||||
{ id: 'ext_info', label: 'Extended identification (hex)', type: 'text', pattern: '[0-9A-Fa-f]{2,20}', placeholder: 'CAG ID: 4 bytes' },
|
||||
],
|
||||
build(v) {
|
||||
const rt = parseInt(v.reg_type) || 0;
|
||||
@@ -13316,6 +13371,11 @@ const EVENT_FORMS = {
|
||||
d += '5701' + (parseInt(v.ext_cause)|0).toString(16).padStart(2,'0');
|
||||
}
|
||||
}
|
||||
if (v.ext_info_type !== '' && v.ext_info_type !== undefined) {
|
||||
const h = (v.ext_info || '').replace(/[^0-9a-fA-F]/g, '');
|
||||
d += 'F2' + (1 + h.length / 2).toString(16).padStart(2, '0') +
|
||||
((parseInt(v.ext_info_type) || 0) & 0xFF).toString(16).padStart(2, '0') + h;
|
||||
}
|
||||
return d.toUpperCase();
|
||||
}
|
||||
},
|
||||
@@ -13470,6 +13530,7 @@ const EVENT_FORMS = {
|
||||
{ id: 'tech', label: 'Access Technology (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'}].concat(ACCESSTECH) },
|
||||
{ id: 'list', label: 'CAG information list (optional, hex)', type: 'text', pattern: '[0-9A-Fa-f]{2,80}', placeholder: 'CAG identity list' },
|
||||
{ id: 'hrnn', label: 'CAG HRNN list (optional)', type: 'text', placeholder: 'one or more names, comma-separated' },
|
||||
],
|
||||
build(v) {
|
||||
let d = '';
|
||||
@@ -13482,6 +13543,14 @@ const EVENT_FORMS = {
|
||||
const h = v.list.replace(/[^0-9a-fA-F]/g, '');
|
||||
d += 'D6' + (h.length / 2).toString(16).padStart(2, '0') + h;
|
||||
}
|
||||
if (v.hrnn) {
|
||||
let inner = '';
|
||||
String(v.hrnn).split(/[\s,;]+/).filter(Boolean).forEach(n => {
|
||||
const b = new TextEncoder().encode(n).slice(0, 60);
|
||||
inner += '80' + b.length.toString(16).padStart(2, '0') + bytesToHex(Array.from(b));
|
||||
});
|
||||
if (inner) d += 'D7' + (inner.length / 2).toString(16).padStart(2, '0') + inner;
|
||||
}
|
||||
return d.toUpperCase();
|
||||
}
|
||||
},
|
||||
@@ -13493,19 +13562,31 @@ const EVENT_FORMS = {
|
||||
{v:0x82,l:'82 \u2014 partially rejected'}] },
|
||||
{ id: 'tech', label: 'Access Technology (optional)', type: 'select',
|
||||
opts: [{v:'',l:'\u2014 not present \u2014'}].concat(ACCESSTECH) },
|
||||
{ id: 'allowed_map', label: 'Allowed slices with S-NSSAI mapping (optional, hex)', type: 'text', pattern: '[0-9A-Fa-f]{2,80}', placeholder: 'TS 24.501 S-NSSAI-with-mapping elements' },
|
||||
{ id: 'served', label: 'Served S-NSSAIs (optional, hex)', type: 'text', pattern: '[0-9A-Fa-f]{8,80}', placeholder: '4 bytes per S-NSSAI (SST + SD)' },
|
||||
{ id: 'allowed', label: 'Allowed slices (optional, hex)', type: 'text', pattern: '[0-9A-Fa-f]{8,80}', placeholder: '4 bytes per S-NSSAI (SST + SD)' },
|
||||
{ id: 'rejected_map', label: 'Rejected slices with S-NSSAI mapping (optional, hex)', type: 'text', pattern: '[0-9A-Fa-f]{2,80}', placeholder: 'TS 24.501 elements + rejection cause' },
|
||||
{ id: 'rejected', label: 'Rejected slices (optional, hex)', type: 'text', pattern: '[0-9A-Fa-f]{2,80}', placeholder: 'TS 24.501 rejected S-NSSAI elements' },
|
||||
],
|
||||
build(v) {
|
||||
let d = '';
|
||||
if (v.tech !== '' && v.tech !== undefined)
|
||||
d += 'BF01' + ((parseInt(v.tech) || 0) & 0xFF).toString(16).padStart(2, '0');
|
||||
d += 'D501' + ((parseInt(v.status) || 1) & 0xFF).toString(16).padStart(2, '0');
|
||||
const list = (val, tag) => {
|
||||
const h = (val || '').replace(/[^0-9a-fA-F]/g, '');
|
||||
if (h) d += tag + (h.length / 2).toString(16).padStart(2, '0') + h;
|
||||
};
|
||||
list(v.allowed_map, 'F7');
|
||||
const h = (v.served || '').replace(/[^0-9a-fA-F]/g, '');
|
||||
if (h) {
|
||||
const n = Math.floor(h.length / 8);
|
||||
d += 'D6' + (1 + n * 4).toString(16).padStart(2, '0') +
|
||||
n.toString(16).padStart(2, '0') + h.slice(0, n * 8);
|
||||
}
|
||||
list(v.allowed, 'F8');
|
||||
list(v.rejected_map, 'D7');
|
||||
list(v.rejected, 'B1');
|
||||
return d.toUpperCase();
|
||||
}
|
||||
},
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simple-v349';
|
||||
const CACHE = 'simple-v350';
|
||||
const URLS = [
|
||||
'index.html',
|
||||
'help.html',
|
||||
|
||||
@@ -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'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user