# Xi Control [![Release](https://img.shields.io/github/v/release/Oksion/XiControl?label=release&color=success)](https://github.com/Oksion/XiControl/releases/latest) [![Downloads](https://img.shields.io/github/downloads/Oksion/XiControl/total?label=downloads)](https://github.com/Oksion/XiControl/releases) [![Build](https://img.shields.io/github/actions/workflow/status/Oksion/XiControl/ci.yml?branch=main&label=build)](https://github.com/Oksion/XiControl/actions/workflows/ci.yml) [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=Oksion_XiControl&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Oksion_XiControl) ![Windows](https://img.shields.io/badge/Windows%2010%2F11-x64-0078D6) ![.NET](https://img.shields.io/badge/.NET-8.0-512BD4) ![License](https://img.shields.io/badge/license-GPLv3-blue) [![winget](https://img.shields.io/badge/winget-Oksion.XiControl-0078D6)](https://github.com/microsoft/winget-pkgs/tree/master/manifests/o/Oksion/XiControl) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-%E2%98%95-FFDD00)](https://buymeacoffee.com/3CLiAI1) 🌐 [English](README.md) · **Русский** Лёгкая утилита в трее для ноутбуков **Xiaomi / Redmi (Redmibook)** — в первую очередь для **Xiaomi Book Pro 14 (2026)**, на котором она разработана и обкатана, но не только для него. Защита заряда батареи, режимы производительности, OSD и «оживление» фирменных клавиш. Всё управление идёт **через штатный WMI-интерфейс прошивки** (`MiCommonInterface`, ODM Bitland «MIFS») — тот же канал, которым пользуется официальный Xiaomi PC Manager. **Никакого WinRing0**, никаких сторонних драйверов и прямого доступа к EC.

Панель быстрых настроек

*Панель быстрых настроек (удержание кнопки Mi): пять режимов производительности, лимит заряда, «В дорогу» (разовый заряд до 100%), тачпад и сенсорный экран вкл/выкл, авто-герцовка и «режим совы» (не спать).*

Окно «Монитор»

*Окно «Монитор»: живые графики потребления (Вт), загрузки CPU, GPU и RAM.*

«Монитор» — компактный вид    «Монитор» — только ватты

*В полном виде — живые графики: потребление (Вт), CPU, **GPU** (под процентом — частота и ватты), RAM, **температура** «горячей точки» (горячая зона — вишнёвым) и мощность подключённого адаптера. Сворачивается в компактную строку (Power / CPU / GPU / RAM) или в один показатель ватт — кнопкой «вид» или двойным кликом; направление тока — цветом (заряд зелёный / разряд оранжевый).* *Значок в трее меняется по активному режиму:*

Значок в трее

## Возможности - 🔋 **Защита заряда** — «беречь батарею» с выбираемым порогом (40/50/60/70/80%, выбор в Настройки → Батарея) / полный заряд 100%. - **ChargeGuard**: прошивка сбрасывает лимит после сна и переключения питания — утилита автоматически переустанавливает его. - 🧳 **Режим «В дорогу»** — разово зарядить до 100% поверх «беречь батарею»: кнопка-чемоданчик в панели / пункт меню. По достижении 100% — OSD и звуковой сигнал; при отключении зарядника режим сам сбрасывается (следующее подключение снова порог). - 🔌 **Мощность зарядника** — при подключении зарядки показываем мощность подключённого PD-адаптера (ватты) в OSD и в «Мониторе». Поверх иконки заряда — **бейдж качества блока**: 🔴 «!» если адаптер слабее заданного порога (медленный заряд), ⚪ «?» если блок не-PD (например обычный 5 В — мощность не согласуется). При этом иконка по-прежнему показывает текущий лимит заряда. Порог настраивается (Настройки → Батарея). Driver-free (только чтение). - 🩺 **Здоровье батареи** — Настройки → Батарея: реальный износ (текущая ёмкость к проектной), число циклов заряда, ёмкость в Вт·ч. Штатные данные ACPI/Windows, только чтение. - ⚡ **Режимы производительности**: Эко (скрытый режим прошивки) / Тихий / Авто / Турбо / Полная мощность. Эко и Полную мощность можно убрать из UI через конфиг. - 🖥️ **OSD-оверлей** (тёмная карточка, авторские иконки): - подключение/отключение зарядки («Зарядка до X%» с реальным порогом / «Работа от батареи» + уровень); - смена режима производительности и лимита заряда; - микрофон вкл/выкл, подсветка клавиатуры (выкл / 50% / 100% / авто). - 🅼 **Mi-кнопка**: - короткое нажатие — циклическое переключение режимов с OSD (настраивается); - двойной клик — переключение лимита заряда (настраивается); - удержание — панель быстрых настроек (режимы + лимит заряда, закрытие по Esc/X/клику вне; настраивается). - ⌨️ **Оживление «мёртвых» клавиш** с переназначением: на клики Mi и клавиши «настройки» / AI / «проекция» вешается любая функция — от цикла режимов до запуска своей программы (см. «Переназначение клавиш»); клавиша микрофона мьютит системный микрофон, клавиша подсветки показывает OSD с уровнем. - 🖱️ **Тачпад вкл/выкл** — действие для любой клавиши + ячейка в панели. Отключение штатное (как в Диспетчере устройств, без драйверов) и не переживает перезагрузку — залипнуть выключенным тачпад не может. - 👆 **Сенсорный экран вкл/выкл** — то же самое для тачскрина ноутбука: действие для клавиши, ячейка в панели, штатное отключение без драйверов и авто-включение после перезагрузки. Ячейка появляется только если сенсорный экран в системе есть. - 🔔 **Проверка обновлений** (по умолчанию включена) — раз в сутки утилита спрашивает у GitHub, вышла ли новая версия, и показывает всплывашку со ссылкой на релиз; отметка появляется и на вкладке «О программе». Обновление **не ставится само** — только оповещение (обновиться можно со страницы релиза или `winget upgrade Oksion.XiControl`). Тумблер выключен — приложение **не делает ни одного сетевого запроса**, а проверить можно разово кнопкой. - ⚙️ **Окно «Настройки»** в стиле Windows 11 — все опции по вкладкам (Общие / Функции / Батарея / Экран / Тачпад / Производительность / Клавиши / HTTP API / О программе), тёмная и светлая темы. Вкладка **«Функции»** — что показывать: «Режим совы», тачпад, сенсорный экран и управление частотой; выключенная функция исчезает из меню и панели целиком. - 🎨 Значок в трее меняется по режиму, монохром под светлую/тёмную панель задач; тёмное меню в тон системной теме (переключается на лету). - 🦉 **«Режим совы»** — не засыпать и не гасить экран *(опционально)*; закрытая крышка на питании от сети лишь выключает экран (на батарее — штатный сон). Сова в панели / галочка в меню; тайминги электропитания не изменяются, действие крышки восстанавливается. Если сова нужна только чтобы система не уснула (например, ради удалённого доступа) — `"OwlIgnoreDisplay": true` в конфиге, и экран будет гаснуть как обычно, не выгорая впустую. Можно скрыть фичу целиком (`"OwlMode": false` в конфиге). - 🖥️ **Авто-герцовка** — подключил зарядку → экран 120 Гц, отключил → 60 Гц (частоты настраиваются в конфиге: `AcRefreshRate`/`BatteryRefreshRate`; если такой частоты у панели нет — берётся ближайшая). Переключатель в меню и ячейка в панели; держится после сна и смены питания. Можно скрыть управление частотой целиком (Настройки → Функции или `"RefreshRateFeature": false`) — уйдут пункт меню, ячейка панели и раздел частоты во вкладке «Экран» (сама вкладка остаётся — там живёт яркость). - 🔌 **Профили питания** — свой режим производительности при зарядке и от батареи («Не менять» — не трогать). Применяется на старте и при смене питания; driver-free (WMI прошивки). - 💡 **Запоминание яркости** — отдельная опция (без профилей): яркость экрана запоминается и восстанавливается отдельно для сети и батареи (WMI ACPI, тот же канал, что у Windows). - 🌗 **Лимит яркости** — максимум яркости отдельно для сети и батареи (бережёт OLED-панель от выгорания): превышение плавно возвращается к лимиту, причём не ультиматумом, а «торгом» — раз в минуту на половину разрыва; поднимешь снова — утилита уступит на 2 часа. См. «Лимит яркости экрана» ниже. - 🌐 Язык интерфейса: русский / английский / китайский (中文). - 🚀 Автозапуск через Планировщик заданий (без UAC-запроса при входе, работает на батарее). - 🛰️ **HTTP API для локальной сети** (опционально, по умолчанию **выключен**) — управляй с телефона или из автоматизаций Home Assistant: чтение статуса и заряда (`GET /status`), переключение режима, защиты заряда, «В дорогу» и совы. Белый список команд, авторизация по токену (хранится только SHA-256), bind на `127.0.0.1` по умолчанию — доступ из сети включается отдельным тумблером. См. «HTTP API» ниже. ## Совместимость Проверено на **Xiaomi Book Pro 14** (TM2424). Должно работать на ноутбуках Xiaomi/Redmi производства ODM Bitland с WMI-классом `MiCommonInterface` (большинство Redmibook / Xiaomi Book последних поколений). Проверить свою машину (PowerShell): ```powershell Get-CimClass -Namespace root/wmi -ClassName MiCommonInterface ``` Если класс нашёлся — интерфейс есть. Набор поддерживаемых функций зависит от модели (утилита определяет их в рантайме и не падает на неподдерживаемых). ## Установка Проще всего — через [winget](https://learn.microsoft.com/ru-ru/windows/package-manager/winget/): ```powershell winget install Oksion.XiControl ``` Или готовый exe — на [странице релизов](../../releases): - `XiControl-vX.X.X-win-x64.exe` — самодостаточный, ничего ставить не нужно (~70 МБ); - `XiControl-vX.X.X-win-x64-net8.exe` — лёгкий (~2 МБ), требует [.NET 8 Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/8.0). Запуск — от администратора (это требование WMI-интерфейса прошивки — даже чтение без elevation не работает). ### Антивирусы и ложные срабатывания Xi Control не подписан сертификатом, работает от администратора и правит системные вещи (лимит заряда в прошивке, частоту экрана, правило брандмауэра для опционального HTTP API, задачу автозапуска) — некоторым «слишком умным» эвристикам этого набора хватает, чтобы занервничать. Проверить легко: залейте exe на [VirusTotal](https://www.virustotal.com/) — как правило, из ~70 движков срабатывает разве что **Bkav Pro** (generic-сигнатура вида `W32.Malware.*`), а **Microsoft Defender и все остальные молчат**. Движок Bkav построен на AI/ML-эвристике — это позиционирование самого вендора, и их generic-детект так и называется, `W32.AIDetectMalware`. Такой анализ ищет «подозрительные» паттерны кода, общие и для легитимных, и для вредоносных программ, — отсюда его печальная слава по ложным срабатываниям. Это ложный сигнал, и это не наш баг. Почему сборке можно доверять: - **исходный код открыт** — читайте и компилируйте сами; - **релизы собираются в GitHub Actions** из этого репозитория (видно в логах Actions), а не «с чьего-то ноутбука»; - exe воспроизводится командой `dotnet publish` (ниже) — сверьте сами. Так что если антивирус заругался — это повод извиниться ему, а не паниковать вам. При желании отправьте файл вендору как false positive: такие generic-сигнатуры обычно отваливаются со следующим обновлением баз. Сборка из исходников: ```powershell dotnet build XiControl.sln -c Release # → src/bin/x64/Release/net8.0-windows/XiControl.exe dotnet test XiControl.sln -c Release --no-build # юнит-тесты (железо не требуется) ``` Один переносимый .exe (без установленного .NET): ```powershell dotnet publish src/XiControl.csproj -c Release -r win-x64 --self-contained -p:PublishSingleFile=true ``` ## Использование Запусти `XiControl.exe` (подтверди UAC) — появится значок в трее. | Действие | Результат | |----------|-----------| | Клик по значку в трее | Панель быстрых настроек | | Правый клик по значку | Меню: заряд, «В дорогу», сова, авто-герцовка, «Монитор», режим, «Настройки…», выход | | Mi-кнопка, одинарный клик | Следующий режим производительности + OSD *(настраивается)* | | Mi-кнопка, двойной клик | Переключение лимита заряда порог ↔ 100% + OSD *(настраивается)* | | Mi-кнопка, удержание ~0.5 с | Панель быстрых настроек *(настраивается)* | | Клавиша микрофона | Мьют/анмьют системного микрофона + OSD | | Клавиша «настройки» | Переключение лимита заряда порог ↔ 100% + OSD *(настраивается)* | | Клавиша подсветки клавиатуры | OSD с уровнем (выкл / 50% / 100% / авто) | Все опции собраны в окне **«Настройки…»** (пункт меню трея): вкладки Общие (язык, автозапуск, тема панелей, проверка обновлений, логирование), Функции (сова, тачпад, сенсорный экран, управление частотой), Батарея (порог заряда с пояснением, звук и файл «В дорогу», звук и уведомление на локскрине, OSD мощности зарядника, порог «слабого блока», здоровье батареи), Экран (лимит и запоминание яркости; авто-герцовка, «Удерживать частоту» и частоты — раздел скрыт, если управление частотой выключено), Тачпад (мёртвая зона у нижнего края), Производительность (видимость режимов, режим при старте, профили питания), Клавиши (переназначение), HTTP API (порт, токен, разрешения) и О программе (версия, модель с кодом платы, BIOS, серийный номер — по умолчанию замаскирован, клик раскрывает). Быстрые переключатели (заряд, «В дорогу», сова, герцовка, «Монитор», режим) остаются в меню трея и панели. Тонкие тайминги правятся только в `%APPDATA%\XiControl\config.json` (применяются при следующем запуске): `MiHoldMs` — порог удержания Mi-кнопки (400), `MiDoubleClickMs` — окно двойного клика (300), `OsdDurationMs` — сколько висит OSD (2800). Ключи конфига для настроек из UI (менять руками не нужно, но полезно знать): `CareLimitPercent` — выбранный порог заряда; `TravelLockSound` / `TravelLockToast` — звук и уведомление «В дорогу» на заблокированном экране; `CheckUpdates` — проверять обновления, `SkippedVersion` — версия, о которой уже сообщали, `LastUpdateCheckUtc` — время последней проверки (суточное окно). Для автозапуска включи «Запускать при входе в Windows» (Настройки → Общие) — задача планировщика создаётся с повышенными правами, поэтому при входе UAC-запрос не показывается. Задача **своя у каждой учётной записи** (имя вида `XiControl_S-1-5-21-…`), так что на общем компьютере пользователи не перетирают автозапуск друг другу; задача от прежних версий (просто `XiControl`) распознаётся и переносится на новое имя при следующем переключении. Самопочинка при запуске срабатывает не только если exe пропал, но и если задача поднимает **устаревшую сборку** — типичный случай, когда portable-версию распаковали в новую папку. Кроме входа в систему задача срабатывает на возврат в сеанс при быстром переключении пользователей. ### Режим «В дорогу» (разовый заряд до 100%) Обычно держишь «беречь батарею» (скажем, 80%), но перед поездкой хочется полный заряд. Нажми **кнопку-чемоданчик** в панели (слева от пилюль «порог/100») или пункт **«Зарядить „в дорогу"»** в меню — утилита разово снимет ограничение и дозарядит до 100%. - По достижении **100%** — OSD «можно в дорогу» и звуковой сигнал (переключатель **Настройки → Батарея → «Звук готовности»**, по умолчанию вкл). - **Отключил зарядник → режим сам выключается**; следующее подключение снова бережёт до порога. - Ручной выбор пилюли «порог/100» тоже отменяет режим. При постоянном «100%» кнопка неактивна (дозаряжать некуда). Пилюли «порог/100» показывают **базовую** настройку — «В дорогу» это временный оверрайд поверх неё (driver-free, тот же WMI-канал заряда). В `config.json`: `"TravelMode"`, `"TravelSound"`. Свой звук готовности — поле «Свой звуковой файл» там же в настройках (или `config.json`; пусто или файл не найден → встроенный джингл; поддерживаются `%ПЕРЕМЕННЫЕ%`; только WAV/PCM): ```json "TravelSoundFile": "C:\\Users\\Me\\Sounds\\ready.wav" ``` ### Скрыть ненужные режимы Тумблеры **Настройки → Производительность → «Показывать режим „Эко“» / «Показывать „Полную мощность“»** (применяется сразу; панель при этом не сжимается — ячейки оставшихся режимов растягиваются). То же самое в `%APPDATA%\XiControl\config.json` (скрытый режим включить из приложения станет нельзя): ```json "EcoMode": false, "FullSpeedMode": false ``` - **Эко** — скрытый режим прошивки, которого нет в официальном софте (на проверенной модели гасит подсветку клавиатуры и снижает яркость экрана — самый экономный профиль); - **Полная мощность** — если не пользуешься или хочешь исключить случайное включение (режим шумный и работает только от сети). По умолчанию оба показываются. После правки конфига вручную перезапусти приложение. ### Режим производительности при старте Прошивка сбрасывает режим при перезагрузке. Что включать на старте — радио-выбор **Настройки → Производительность → «Режим при старте»** (взаимоисключающие; четвёртый, «Профили питания», — ниже): - **Не трогать** — оставлять то, что выставила прошивка. - **Восстанавливать последний** — приложение запоминает выбранный режим и возвращает его после перезагрузки (следует за твоими переключениями). При включении сразу запоминает текущий. - **Закрепить текущий** — фиксирует **один** режим: он будет включаться каждый старт, с какого бы ни выключились. Выбираешь, находясь в нужном режиме, — он закрепляется. Если нужный режим на старте недоступен (например, «Полная мощность» на батарее) — включится «Авто». Закреплённый режим можно задать и правкой `config.json`: `"ForceStartMode": "Eco"` (допустимо `"Quiet"` / `"Turbo"` / `"FullSpeed"` / `"Auto"` / `"Eco"`; `null` или удалить строку — снять). ### Профили питания (режим по питанию) Четвёртый вариант «Режима при старте»: **свой режим производительности при зарядке и от батареи**. Выбирается там же — **Настройки → Производительность → «Профили питания»**; под радио-выбором появляются «Режим при зарядке» и «Режим от батареи» (или «Не менять»). ```json "PowerProfiles": true, "AcPerfMode": "Turbo", // режим от сети; null или "Не менять" — не трогать "BatteryPerfMode": "Quiet" // режим от батареи ``` - **Профиль применяется на старте и при каждой смене питания** сеть↔батарея (и после сна), через гард с дебаунсом — как у защиты заряда и авто-герцовки. Driver-free: WMI прошивки `0x08`. - Если прошивка не приняла режим (например, «Полная мощность» на батарее) — мягкий откат на «Авто». ### Запоминание яркости экрана Отдельная опция **Настройки → Экран → «Запоминать яркость экрана»** (по умолчанию **выкл**), работает независимо от «Профилей питания». Утилита следит за твоей яркостью отдельно для сети и батареи и восстанавливает её при каждом переходе: выставил 80 % на зарядке → при следующем подключении вернётся 80 %. Driver-free: WMI `WmiMonitorBrightness*` (ACPI-подсветка, тот же канал, что у Windows). - XiControl при этом **перебивает яркость Windows** своим значением — поэтому опция и включается явно; на переходе возможна кратковременная двойная подстройка (Windows → через ~1.5 с наше). `AcBrightness`/`BatteryBrightness` в конфиге заполняются сами. - Смена режима и яркости — **в фоне** (UI не блокируется); на панели без WMI-яркости фича молча деградирует (пишет в `log.txt`, не падает). Запись конфига дебаунсится (бережём SSD). ### Лимит яркости экрана **Настройки → Экран → «Ограничивать яркость»** (по умолчанию **выкл**) + два лимита — свой для сети и свой для батареи. Задумано для OLED-панели: постоянная высокая яркость ускоряет выгорание, а лимит мягко не даёт ей там жить. Driver-free — тот же WMI-канал ACPI-подсветки. Сразу честно: **заблокировать сам ползунок Windows невозможно** — такого API нет. Утилита может только вернуть яркость после факта, поэтому возврат сделан максимально ненавязчивым: - Превышение снижается **плавно** (~10 с на весь путь, шагами по 1%), не скачком. - **«Вежливый торг» вместо ультиматума**: выставил 80 при лимите 60 — утилита не отматывает сразу, а раз в минуту сокращает разрыв вдвое: 80 → 70 → 65 → 63 → … → 60. Остаток ≤2% доводится сразу. - **Поднял яркость снова после её шага** — это сигнал «мне правда нужно ярче»: утилита уступает и **не трогает яркость 2 часа**. Пауза сбрасывается блокировкой сеанса, сном, сменой питания и перезапуском приложения. - **Понижение ниже лимита не трогается вовсе** — утилита никогда не поднимает яркость. - **С адаптивной яркостью Windows лимит не работает** (иначе двое управляли бы яркостью одновременно): утилита это замечает и пишет причину прямо на вкладке. Отключить адаптивную: Параметры → Система → Дисплей. - Дружит с «Запоминать яркость»: значения выше лимита **не запоминаются вообще** (а не обрезаются) — твоя комфортная яркость в слоте не затирается; при восстановлении слот прижимается к текущему лимиту, но в конфиге остаётся нетронутым. В `config.json`: `BrightnessCapEnabled`, `BrightnessCapAc`/`BrightnessCapBattery` (лимиты, %), и тонкие тайминги — `BrightnessRampMs` (длительность плавного хода, 10000), `BrightnessConvergeMs` (интервал между шагами торга, 60000), `BrightnessBackoffMin` (пауза после повторного подъёма, 120), `BrightnessGapDivisor` (делитель разрыва, 2), `BrightnessSnapPercent` (порог доведения, 2). ### Авто-герцовка (частота экрана по питанию) Экран переключается на разную частоту в зависимости от источника питания: от сети — повыше (плавность), от батареи — пониже (экономия). Включается пунктом меню трея, ячейкой в панели или в **Настройки → Экран**; там же выбираются частоты (применяются сразу). В `config.json`: ```json "AutoRefreshRate": true, "HoldRefreshRate": false, "AcRefreshRate": 120, "BatteryRefreshRate": 60 ``` Как это ведёт себя на самом деле (чистый Win32: встроенная панель ищется через `QueryDisplayConfig`, частота ставится `ChangeDisplaySettingsEx` — драйвер не нужен): - **Только встроенная панель ноутбука**, разрешение и глубина цвета не трогаются — меняется лишь частота. Внешние мониторы не затрагиваются, даже если один из них назначен основным; если панель сейчас не активна (крышка закрыта, режим «только второй экран») — не меняется ничего. - **Берётся ближайшая поддерживаемая частота** при текущем разрешении: попросили 120, а панель умеет только 90/60 → выберет 90 (при равном расстоянии — большую). Поэтому вписать «144» на 60-герцовой матрице безопасно — просто останется 60. Значение ≤ 0 в конфиге игнорируется. - **Срабатывает** на старте приложения, при смене питания сеть↔батарея и при выходе из сна (эти два — через дебаунс ~1.5 с, события приходят пачкой), а также сразу при включении опции. - Если нужная частота **уже стоит — экран не мигает** (лишний вызов не делается). - Частота пишется в реестр дисплея (`CDS_UPDATEREGISTRY`), т.е. **переживает перезагрузку**; но при выключенной опции приложение частоту **не трогает вообще** (в т.ч. в момент снятия галки — что стояло, то и останется, вернуть вручную). - Сама смена видеорежима идёт **в фоновом потоке** (не блокирует UI), а неудача просто пишется в `log.txt`, приложение не падает. OSD смены питания дописывает фактическую частоту («… • 120 Гц»). При правке `AcRefreshRate`/`BatteryRefreshRate` прямо в конфиге перезапусти приложение (выбор в окне настроек применяется сразу; нестандартное значение из конфига окно тоже покажет). **«Удерживать частоту»** (`HoldRefreshRate`, по умолчанию выкл) — отдельный тумблер там же, в **Настройки → Экран**. С ним авто-герцовка следит не только за питанием, но и за самим экраном: если режим сменил кто-то извне — параметры Windows, чужая утилита, драйвер после сброса — заданная частота возвращается через тот же дебаунс ~1.5 с. Без него настройка тихо не держится до следующего события питания. Работает поверх авто-герцовки (без неё возвращать нечего), поэтому пока она выключена — тумблер погашен. Опроса нет: только системное событие смены режима экрана. > Побочный эффект, он же суть фичи: пока опция включена, сменить частоту через параметры Windows > не выйдет — вернём быстрее, чем система успеет спросить «Сохранить изменения?». Нужно поменять > руками — выключи тумблер. ### Мёртвая зона у нижнего края тачпада Если нижний край панели ловит ладонь или большой палец, включи **Настройки → Тачпад → «Мёртвая зона снизу»** и выбери высоту полосы (8/10/12/15/20 мм, по умолчанию 12). В `config.json` это `TouchpadDeadZone` и `TouchpadDeadZoneMm`. Важно понимать, что зона делает: она гасит **начало** касания. Если палец коснулся панели сразу в этой полосе, курсор не сдвинется и тапа не будет — а вот жест, начатый выше, продолжает работать до самого низа панели, так что прокрутка и перетаскивание не рвутся. **Нажатие в зоне по-прежнему срабатывает** — полностью «мёртвой» полоса не становится. Под капотом это штатная настройка Windows Precision Touchpad (`SuperCurtainBottom`), а не перехват ввода: одна машинная запись в реестре, никаких драйверов и хуков. Применяется сразу — приложение перезапускает узел тачпада само, перезаходить в сеанс не нужно (панель на секунду пропадёт). Выключение опции **удаляет** запись, а не пишет ноль. > Зона работает внутри защиты от ладони Windows. Если в **Параметры → Bluetooth и устройства → > Сенсорная панель** выставлена максимальная чувствительность, защита выключена целиком — вместе > с нашей зоной. XiControl это замечает и пишет предупреждение прямо на вкладке. ### Переназначение клавиш Каждой клавише — своё действие: **Настройки → Клавиши**. Слоты — одиночный клик, двойной клик и удержание Mi-кнопки, клавиши «Настройки» (шестерёнка), AI и «Проекция». На любой слот можно навесить: цикл режимов, лимит заряда вкл/выкл, быструю панель, режим совы, «Монитор», «В дорогу», тачпад и сенсорный экран вкл/выкл, системные «Проекция (Win+P)» / «Параметры Windows» / «Copilot (Win+C)», мультимедиа (воспроизведение/пауза, следующий и предыдущий трек, остановка), калькулятор, запуск своей программы или «Ничего». Медиа-действия работают с любым плеером — клавишу получает тот, кто владеет медиа-сессией Windows. Громкости в списке нет намеренно: для неё на клавиатуре есть отдельные кнопки. Тачпад и сенсорный экран отключаются штатным механизмом Windows (как «Отключить устройство» в Диспетчере, без драйверов) и **всегда включаются сами после перезагрузки** — залипнуть выключенными не могут. Их ячейки есть и в быстрой панели, рядом с авто-герцовкой (ячейка сенсорного экрана — только если тачскрин в системе присутствует). - Удержание Mi-кнопки по умолчанию открывает быструю панель, но его можно переназначить — например, повесить панель на одиночный клик, а на удержание «В дорогу». - Двойной клик Mi = «Ничего» → жест отключён, одиночный клик срабатывает мгновенно (без окна ожидания ~300 мс). - Удержание Mi = «Ничего» → жест отключён, и долгое нажатие отрабатывает как обычный клик (а не пропадает впустую). - При открытой панели клавиша «Настройки» всегда переключает заряд (пилюля в панели). - Для «Запустить программу…» подойдёт exe, документ или URL; переменные окружения (`%USERPROFILE%` и т.п.) раскрываются, путь с пробелами — в кавычках, после пути можно дописать аргументы: `"C:\\Program Files\\App\\app.exe" --flag`. Учти: XiControl работает с правами администратора — запущенная программа их унаследует. В `config.json` это пары `*Action`/`*Command` (`MiClick`, `MiDouble`, `MiHold`, `SettingsKey`, `AiKey`, `ProjKey`), значения действий: `modes`, `charge`, `panel`, `owl`, `monitor`, `travel`, `touchpad`, `touchscreen`, `projection`, `settings`, `copilot`, `play`, `next`, `prev`, `stop`, `calc`, `launch`, `none`: ```json "MiClickAction": "modes", "MiDoubleAction": "charge", "AiKeyAction": "launch", "AiKeyCommand": "\"C:\\Program Files\\App\\app.exe\" --flag" ``` Старые опции (`MiShortPress`, `MiDoubleClick`, `SettingsKey`, `AiKeyProgram`/`AiKeyArgs`) переносятся автоматически при первом запуске новой версии. ### HTTP API (управление из локальной сети) Опциональный веб-API, чтобы дёргать XiControl с телефона или из автоматизаций Home Assistant. **По умолчанию выключен** — включается в **Настройки → HTTP API**. Там же задаётся порт, генерируется токен (показывается **один раз** — скопируй сразу; хранится только SHA-256) и поштучно разрешаются команды. По умолчанию доступно только чтение состояния. Маршруты (все — с заголовком `Authorization: Bearer <токен>`, тело — JSON): | Метод / путь | Что делает | |---|---| | `GET /status` | Режим, защита заряда, «В дорогу», сова, % заряда, факт зарядки, ватты, здоровье батареи | | `POST /mode` `{"value":"turbo"}` | Режим производительности (`eco`/`quiet`/`auto`/`turbo`/`fullspeed`) | | `POST /care` `{"on":true}` | «Беречь батарею» вкл/выкл (настроенный порог) | | `POST /travel` `{"on":true}` | Режим «В дорогу» (разовый заряд до 100%) | | `POST /owl` `{"on":true}` | «Режим совы» (не спать) вкл/выкл | ```bash curl -X POST http://192.168.1.50:58125/travel \ -H "Authorization: Bearer <токен>" -d '{"on":true}' ``` Безопасность (утилита работает от администратора, поэтому — осознанно и с оговорками): - **По умолчанию только `127.0.0.1`** — из сети не достучаться даже с токеном. Доступ из локалки — отдельный тумблер «Доступ из локальной сети» с предупреждением; тогда создаётся правило брандмауэра со скоупом **LocalSubnet** (только твоя подсеть) и удаляется при выключении. - **Белый список команд зашит в код** — настройки, автозапуск и запуск программ через API невозможны; выключенная команда отвечает `403`, неизвестный путь — `404`, без токена — `401`. - **Настройки API — в `%ProgramData%\XiControl\api.json` под ACL «запись только администраторам»**: сторонний процесс без прав администратора не может ни включить сервер, ни подменить токен. - Плейнтекст-HTTP (без TLS) — сознательный компромисс: радиус поражения белого списка мал. Ничего из этого не работает и не тратит ресурсы, пока API выключен (сервер попросту не запускается). ## Ограничения - Порог «беречь батарею» выбирается из дискретного набора прошивки — произвольный процент через WMI невозможен. На проверенной модели (TM2424) это 40/50/60/70/80/100%; на других моделях набор может отличаться (прошивка сама валидирует его и отвергает неподдержанные уровни). - Комбинация Fn+Mi не отличима от одиночной Mi (прошивка шлёт одинаковые события), поэтому используется короткое/длинное нажатие. - Набор функций зависит от модели: прошивочная телеметрия (обороты вентиляторов) на проверенной машине не поддерживается. **Температуру** при этом показываем — не из прошивки, а через Intel DPTF (WMI `EsifDeviceInformation`), строкой-графиком в «Мониторе». - **Загрузка GPU** идёт через Intel IGCL — user-mode API графического драйвера (`ControlLib.dll` из System32, ставится вместе с драйвером Intel; прав администратора не требует). На машинах без графики Intel ряд GPU в «Мониторе» просто не появляется. Температуру и обороты вентиляторов этот канал на встроенном GPU не отдаёт — только загрузку, мощность и частоту. ## Как это работает Протокол MIFS разобран и задокументирован в [docs/](docs/): - [01-wmi-protocol.md](docs/01-wmi-protocol.md) — транспорт, формат буфера, коды команд, события клавиш (**главный документ**); - [02-feature-catalog.md](docs/02-feature-catalog.md) — каталог функций; - [03-architecture.md](docs/03-architecture.md) — архитектура приложения; - [07-keymap.md](docs/07-keymap.md) — карта кодов клавиш. Коротко: метод `MiInterface` принимает 32-байтовый буфер (`[1]` — GET `0xFA` / SET `0xFB`, `[3]` — команда, `[4]/[6]` — аргументы) и возвращает статус в `OUT[1]` (`0x80` — ок). Заряд — команда `0x10`, режимы — `0x08`, события клавиш приходят WMI-событием `HID_EVENT20`. Протокол восстановлен по открытым источникам (включая драйвер ядра Linux) **без копирования чужого кода** — переносились только факты об интерфейсе. Подробности и лицензии источников: [docs/04-references.md](docs/04-references.md). ## Разработка ``` src/ приложение (C# / .NET 8 / WinForms): Wmi/ — протокол MIFS, Input/ — клавиши и жесты, Ui/ — трей, панель, OSD, монитор, настройки (Ui/Settings/ — вкладки), SystemIntegration/ — guard-ы, питание, тачпад/экран, Config/, Localization/ tests/ юнит-тесты (xUnit) чистой логики на фейках — гоняются без железа Xiaomi assets/svg/ иконки: osd/ — цветные 128×128, tray/ — монохром 24×24 (currentColor), ui/ — неквадратные картинки интерфейса (кнопка Buy Me a Coffee) assets/sound/ встроенные WAV-джинглы режима «В дорогу» tools/ IconPreview/ — рендер иконок в PNG + генерация app.ico; вспомогательные скрипты docs/ документация протокола и архитектуры reference/ PowerShell-пробы, журналы исследования прошивки ``` Как устроен код (командный слой, швы для тестов, guard-паттерн) — [CLAUDE.md](CLAUDE.md), как контрибьютить — [CONTRIBUTING.md](CONTRIBUTING.md). Диагностика: ошибки пишутся в `%APPDATA%\XiControl\log.txt`. История изменений: [CHANGELOG.md](CHANGELOG.md) · Планы: [ROADMAP.md](ROADMAP.md) ## Лицензия [GPL-3.0](LICENSE). Утилита пригодилась? Можно [угостить кофе ☕](https://buymeacoffee.com/3CLiAI1).