esim: drive the profile switch ourselves; guard the FCP metadata
Disabling a profile failed with 6985 and left the card stuck until an equip. pySim's send_apdu_checksw auto-handler keeps flushing proactive commands after the REFRESH TERMINAL RESPONSE; the card is then mid-switch and answers 6985 to the next FETCH, which propagated as a 500 and skipped the re-initialization. Per SGP.22 v2.6 5.7.16/5.7.17 a 91XX answer is the ISD-R's 'result OK before REFRESH' (step 6) and the switch completes on the TERMINAL RESPONSE or the following RESET (step 8) - lpac treats 91XX the same way and never retries. - esim.py: build_switch_apdu/parse_switch_response/switch_profile split out of set_profile_state; the switch is one raw STORE DATA via scc._tp.send_apdu, a 91XX runs our own FETCH/TR chain (status_poll=False) and is reported as ok, the STORE DATA is never retried and a chain failure still counts the accepted switch. - server.py: /api/esim/profile answers the REFRESH with our chain, then re-initializes the card and re-reads the profile list, returning verified/state_after; _handle_proactive_chain grew status_poll. - /api/status and /api/select: FCP metadata via _fcp_value - an ADF or a failed select (card with the active profile disabled) has no file_descriptor and used to crash the request handler; _get_file_type no longer raises either. - esim._restore logs a failed selection restore instead of swallowing it. - PWA: esimSwitchStatus shows the verified state / not-confirmed warning. - tests: the switch flow (9000 / 91XX / error SW / chain failure), the FCP guards and the status helper; docs and sw simple-v230.
This commit is contained in:
@@ -23,7 +23,7 @@ function extractFunc(src, name) {
|
||||
|
||||
let code = '';
|
||||
for (const fn of ['esimLabel', 'esimGroupEid', 'esimFieldRows', 'esimResultText',
|
||||
'esimStateLabel', 'esimOperationsText', 'esimProfileRows']) {
|
||||
'esimStateLabel', 'esimOperationsText', 'esimProfileRows', 'esimSwitchStatus']) {
|
||||
code += extractFunc(html, fn) + '\n';
|
||||
}
|
||||
for (const c of ['ESIM_CHIP_LABELS', 'ESIM_RESULT_KEYS']) {
|
||||
@@ -98,6 +98,20 @@ test('esimResultText localizes result codes and passes errors through', () => {
|
||||
assert.strictEqual(esimResultText(null), '');
|
||||
});
|
||||
|
||||
test('esimSwitchStatus reports the switch, re-init, REFRESH and verification', () => {
|
||||
assert.strictEqual(esimSwitchStatus({ ok: true }), 'Profile switched');
|
||||
assert.strictEqual(
|
||||
esimSwitchStatus({ ok: true, reinitialized: true, refresh_seen: true }),
|
||||
'Profile switched — card re-initialized (REFRESH received)');
|
||||
assert.strictEqual(
|
||||
esimSwitchStatus({ ok: true, reinitialized: true, verified: false, state_after: 'disabled' }),
|
||||
'Profile switched — card re-initialized — not confirmed (Disabled)');
|
||||
assert.strictEqual(esimSwitchStatus({ ok: false, result: 'catBusy' }),
|
||||
'Profile switch failed: card is busy with a CAT session');
|
||||
assert.strictEqual(esimSwitchStatus({ ok: false, error: 'SW 6985' }),
|
||||
'Profile switch failed: SW 6985');
|
||||
});
|
||||
|
||||
test('esimStateLabel and esimOperationsText map the profile metadata', () => {
|
||||
assert.strictEqual(esimStateLabel('enabled'), 'Enabled');
|
||||
assert.strictEqual(esimStateLabel('disabled'), 'Disabled');
|
||||
|
||||
Reference in New Issue
Block a user