esim: implement profile switching and deletion#37779
Merged
adeebshihadeh merged 12 commits intocommaai:masterfrom Apr 11, 2026
Merged
esim: implement profile switching and deletion#37779adeebshihadeh merged 12 commits intocommaai:masterfrom
adeebshihadeh merged 12 commits intocommaai:masterfrom
Conversation
lte.sh already blocks until the modem is online, so no post-reset sleep needed. open_isdr and send_apdu retry loops recover without delays. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add TLV encoding utilities: encode_tlv, string_to_tbcd, require_tag, int_bytes for constructing ES10x commands - Generalize _decode_profile_fields into decode_struct with FieldMap type for reuse across profile, notification, and other TLV structures - Add set_profile_nickname function (ES10c SetNickname command) - TiciLPA: remove singleton pattern, add _acquire_channel context manager with filesystem lock and ModemManager inhibit for exclusive modem access - Wrap list_profiles and nickname_profile with _acquire_channel - Add base64_trim, b64d helpers for downstream ES9P/download use Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f26dfd1 to
6fc4cb0
Compare
- TiciLPA.switch_profile: enable profile with device-specific refresh flag (tizi uses SIM presence refresh, mici uses CFUN cycle), catBusy retry with lte.sh modem reset, post-switch modem recovery - TiciLPA.delete_profile: encode DeleteProfile TLV command with comma profile guard (refuses to delete Webbing/comma profiles) - TiciLPA._enable_profile: send ES10c EnableProfile command - TiciLPA._has_sim_presence: detect tizi vs mici for refresh strategy - hardware.py: use AT+CFUN=1,1 for modem reboot (enables network registration after power-on) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b3ce36d to
3415e3e
Compare
Contributor
Process replay diff reportReplays driving segments through this PR and compares the behavior to master. ✅ 0 changed, 66 passed, 0 errors |
3fb484c to
4004370
Compare
- Consolidate modem reset into AtClient._reset_modem(), used by both reset() and open_isdr() - Add AtClient.send_raw() and flush_input() to avoid private _serial access - Use HARDWARE.get_device_type() instead of importing tici module directly - Extract PROFILE_OK, PROFILE_NOT_IN_DISABLED_STATE, PROFILE_CAT_BUSY constants Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4004370 to
6d5e9ed
Compare
Both mici and tizi now do a CFUN reset after EnableProfile to force a SIM re-read, ensuring list_profiles returns fresh data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The EG25 (tizi) doesn't recover from CFUN alone after a profile switch — the SIM never comes back. Setting refreshFlag=1 tells the eUICC to issue a proactive SIM REFRESH, which the modem handles natively. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mici (EG916Q) doesn't update ModemManager after refreshFlag=1 — mmcli shows stale ICCID. Add a CFUN cycle (using proper query() instead of send_raw) for mici only. tizi (EG25) handles refreshFlag natively via SIM REFRESH. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AT+CFUN=0 drops the serial connection before OK is sent, so query() times out. Use send_raw like before, with a 0.5s settle and flush. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sending both CFUN commands in one send_raw was unreliable — modem sometimes processes them too fast without a full radio cycle. Split into two sends with 0.5s gap so CFUN=0 completes before CFUN=1. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tizi (EG25): refreshFlag=1 triggers native SIM REFRESH, 0.2s settle. mici (EG916Q): refreshFlag=0 + CFUN cycle via send_raw, 0.5s settle. This matches the configuration that was previously tested reliable on both devices. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6578bb6 to
79b2050
Compare
4664366 to
39097fc
Compare
Instead of device-specific sleep values, use refreshFlag=0 + CFUN on all devices and poll list_profiles until the target profile shows as enabled. Timeout after 15s. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
39097fc to
12cdb38
Compare
d0d6ad4 to
a6b336b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
switch_profile(): EnableProfile TLV command with refreshFlag support (tizi uses SIM toolkit refresh, mici uses CFUN cycle)delete_profile(): DeleteProfile TLV command with comma profile guard (is_comma_profilecheck)PROFILE_ERROR_CODES,TAG_ENABLE_PROFILE,TAG_DELETE_PROFILEconstantsStress test results (15 switches each, 10s between)
tizi (EG25) — 15/15 passed
mici (EG916Q) — 15/15 passed
Sample test code