Skip to content

Выбор порога заряда 40/50/60/70/80/100% (XIC-4) - #7

Merged
Oksion merged 6 commits into
mainfrom
oksion/xic-4-charge-levels
Jul 29, 2026
Merged

Выбор порога заряда 40/50/60/70/80/100% (XIC-4)#7
Oksion merged 6 commits into
mainfrom
oksion/xic-4-charge-levels

Conversation

@Oksion

@Oksion Oksion commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Закрывает XIC-4.

Что и почему

Команда защиты заряда MIFS 0x10/0x02, которую мы считали бинарной («беречь ~80%» / 100%), на самом деле многоуровневая. Нашли реверсом лимит-селектора в Xiaomi PC Manager (живой мониторинг MIFS + реестра во время переключений) и подтвердили перечислением значений на TM2424.

Прошивка держит коды {0:100, 1:80, 4:80, 5:70, 6:60, 7:50, 8:40} (granular-шкала % = 120 − код·10) и сама валидирует набор: невалидное отвергает статусом 0x00 и зажимает к ближайшему. 90% нет — код 3 отвергается.

Это переоткрывает вопрос, ранее закрытый как «порог фиксирован прошивкой, произвольный процент недоступен» (был в docs/05, CLAUDE.md, ROADMAP). Разбор — docs/12-charge-levels.md.

Изменения

Слой Что
Wmi/Mifs.cs таблица уровней, ChargeCodeForPercent/ChargePercentForCode, ChargeCarePresets
IMifsClient/MifsClient GetChargeCare/SetChargeCare(bool)GetChargeLimit()/SetChargeLimit(percent); пишет код с ре-армом off→on, возвращает признак приёма прошивкой
Config/AppConfig CareLimitPercent (дефолт 80 → старые config.json мигрируются сами) + CarePercent() с фолбэком для руками-правленного значения
Ui/AppController SetCareLimit(percent) — применяет на железе, только когда защита активна и не перебита «В дорогу»; отказ прошивки → откат выбора + честный error-OSD
SystemIntegration/ChargeGuard армит выбранный порог, а не хардкод
UI пикер в Настройки → Батарея; панель/меню/OSD показывают реальный %
Localization 3 новых ключа ru/en/zh, menu.charge с параметром; переписан settings.battery.note (утверждал, что порог фиксирован)

Дизайн по договорённости: панель остаётся бинарным тумблером «X% ↔ 100%» (не перегружаем быстрый доступ), сам выбор X — в настройках как редкая операция.

Проверка

  • dotnet build XiControl.sln -c Release0 ошибок / 0 предупреждений
  • dotnet test169 зелёных (было 141; +28: маппинг код↔%, клэмп конфига, 5 кейсов SetCareLimit)
  • На железе (TM2424) нашим же кодом: Set(60)→60%, Set(50)→50%, Set(80)→80% — accepted + readback совпал; Set(90)→False. Порог возвращён на 80%.

Оговорки

  • Деградация на моделях без granular сделана рантаймом, а не гейтом по SKU (в духе «набор функций определяем в рантайме»): прошивка сама валидирует, отказ → откат + ошибка, а 80/100 (legacy-коды 1/0) работают всегда. Read-only запроса «какие уровни держит прошивка» в MIFS нет, поэтому пикер показывает все пресеты, а неподдержка выясняется попыткой — задокументировано.
  • Не проверено вживую, что EC физически режет заряд на 60/50/40 (нужно наблюдение за зарядом во времени). Механизм тот же, что у подтверждённых 80%.

🤖 Generated with Claude Code

Oksion and others added 6 commits July 29, 2026 01:22
Фундамент под многоуровневый лимит заряда: Mifs.ChargeCarePresets (80/70/60/50/40),
ChargeCodeForPercent / ChargePercentForCode (код 0x10/02 <-> %), по docs/12.
Аддитивно, сборка 0/0. Дальше — client-слой, конфиг+миграция, UI, Loc, тесты.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Шов IMifsClient: GetChargeCare/SetChargeCare(bool) -> GetChargeLimit/SetChargeLimit(percent).
- MifsClient пишет код уровня по таблице (re-arm off->on), возвращает признак приёма прошивкой
- AppConfig.CareLimitPercent (дефолт 80 = старое поведение, миграция автоматическая) + CarePercent()
  с фолбэком при руками-правленном значении
- AppController/ChargeGuard/TrayMenuBuilder/Program(DI) — на проценты; гвард армит выбранный порог
- Fakes/тесты обновлены под новый шов

Сборка 0/0, тесты 141 зелёных.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Настройки -> Батарея: пикер порога (пресеты 80/70/60/50/40) через новый
  SettingsActions.SetCareLimit -> AppController.SetCareLimit (применяет на железе,
  только когда защита активна и не перебита travel; отказ прошивки -> откат выбора)
- Панель/меню/OSD показывают реальный выбранный %, не хардкод 80
- Loc ru/en/zh: 3 новых ключа + menu.charge с параметром; переписан settings.battery.note
  (утверждал, что порог фиксирован — теперь неверно)
- Тесты: ChargeLevelsTests (маппинг код<->%, клэмп конфига) + 5 кейсов SetCareLimit

Сборка 0/0, тесты 169 зелёных (было 141).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… откат комбо, синхрон доков (XIC-4)

- MifsClient.SetChargeLimit(100): возвращаем Ok первой записи, а не безусловный true —
  иначе ToggleCare(off)/SetTravel(on) рапортуют успех при отвергнутой записи
- ChargeGuard.Reapply: отказ прошивки на ре-арме теперь оставляет след в log.txt
- BatteryTab: комбо реально откатывается к фактическому порогу, когда прошивка
  отвергла уровень (раньше визуально залипал отвергнутый выбор до переоткрытия окна)
- Доки: CLAUDE.md/README/docs 01-02 больше не утверждают «порог зашит, бинарно» —
  многоуровневый набор, прошивка валидирует (docs/12)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- README (ru/en): фичи, OSD, таблица хоткеев, сценарий «В дорогу», таблица API —
  «80%» больше не хардкод, а выбираемый порог
- CLAUDE.md: «Что это» упоминает выбор порога; «Релизы и CI» — про dev-версию 0.0.0-dev
- ROADMAP: XIC-4 перенесён из «Ближайшее» в «Сделано» (unreleased); убран дубль секции
  «Ближайшее» с уже сделанным HTTP API (XIC-13); открытый вопрос про другие модели
  уточнён под фактическую реализацию (деградация попыткой, а не перечислением)
- CHANGELOG [Unreleased]: запись о фиче + пометка dev-версии

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Oksion
Oksion merged commit 30b215c into main Jul 29, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant