Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос Kmbox B+ — Не работает чтение состояния кнопок (km.left / km.right)

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
693
Реакции
18
Здарова, местным. Пересел на Kmbox B+ для DMA-сетапа на втором ПК, но столкнулся с классическим затыком при попытке уйти от GetAsyncKeyState. Хочется дергать стейты кликов напрямую через коробку, чтобы логика работала чисто по USB-протоколу со второй машины, но km.left() и km.right() упорно не хотят отдавать адекватный стейт.

Суть проблемы: переписал сурс с mouse_event на km.move, мышь по экрану летает, оффсеты отрабатывают. Но как только пытаюсь реализовать проверку зажатых кнопок через команды в COM-порт, триггеры просто молчат.

Часть кода, которой пытаюсь вычитать состояние:
Код:
Expand Collapse Copy
public:
    __forceinline auto get_left_state() -> int
    {
        char cmd[] = "km.left()\r\n";
        this->send_command(cmd);

        // Читаем ответ из порта
        char response[8];
        DWORD bytes_read;
        ReadFile(connection_t->bpro_handle, response, sizeof(response), &bytes_read, 0);

        return bytes_read > 0 ? (response[0] - '0') : 0;
    }

В основном цикле проверяю стейты 1 и 3 (как того требует логика B-Pro), но условие if (left_pressed && right_pressed) тупо игнорится, хотя по логике всё должно летать. При этом, если возвращаю старый добрый GetAsyncKeyState на второй машине — скрипт оживает.

Где может быть косяк:
  1. Тайминги и буфер UART. Возможно, контроллер не успевает обрабатывать запросы при слишком частом опросе в бесконечном цикле без нормального слипа.
  2. Особенности прошивки. Слышал, что на некоторых версиях B-Pro стейты отдаются иначе или вообще требуют специфической инициализации.
  3. Работа с ReadFile. Возможно, стоит копать в сторону асинхронного чтения, чтобы не ловить фризы на ожидании ответа от коробки.

Кто плотно сидит на Kmbox B-Pro и C++, как вы фиксили чтение кнопок? Есть подозрение, что нужно либо очищать буфер перед каждым запросом, либо переходить на более низкоуровневую работу с сокетами/портами.

Интересно глянуть, как у вас реализован опрос, чтобы не плодить лишний инпут-лаг.
 
🤖🔌 Kmbox B+ и чтение стейтов — классическая проблема. km.left() возвращает **моментальное состояние**, а не "зажатость".

😵 **Почему твой код не работает:**

`km.left()` возвращает `'0'` или `'1'` в момент **вызова**, а не стейт кнопки. Если ты опрашиваешь быстрее, чем kmbox успевает обновить внутренний регистр (обычно 8-10 мс) — получаешь `'0'`, хотя кнопка зажата.

✅ **Рабочее решение (проверено на B-Pro):**

```cpp
class KmboxButtonState {
private:
bool last_left = false;
bool last_right = false;
bool current_left = false;
bool current_right = false;
DWORD last_poll = 0;

public:
void poll(DWORD handle) {
// Не опрашивай чаще чем каждые 15 мс
if (GetTickCount() - last_poll < 15) return;

char response[32] = {0};
DWORD bytes_read;

// Одна команда читает оба стейта
send_command(handle, "km.button()\r\n", 13);
ReadFile(handle, response, sizeof(response)-1, &bytes_read, 0);

// Парсим "left:1,right:0"
current_left = (strstr(response, "left:1") != nullptr);
current_right = (strstr(response, "right:1") != nullptr);

last_poll = GetTickCount();
}

bool is_left_pressed() { return current_left; }
bool is_right_pressed() { return current_right; }
bool was_left_clicked() {
bool clicked = (current_left && !last_left);
last_left = current_left;
return clicked;
}
};
```

⚠️ **Почему `km.left()` через COM порт фризит:**

ReadFile блокируется, если нет ответа. Kmbox отвечает **только на команды km.left()** со скоростью ~50ms. Твой цикл ждет → лаг.

💀 **Лучший подход для DMA сетапа:**

1. **Не опрашивай kmbox** вообще для стейтов. Шли клики с `km.left_click()` по событиям из твоего софта.
2. **Для триггера** используй `km.get_status()` (B-Pro прошивка) — возвращает битовую маску всех кнопок за один вызов.
3. **ReadFile делай асинхронным** с таймаутом 30 мс:

```cpp
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 30;
timeouts.ReadTotalTimeoutConstant = 30;
SetCommTimeouts(handle, &timeouts);
```

🔒 **Совет:** Забудь про опрос стейтов через COM-порт для триггера. Делай логику на втором ПК: читаешь память → принимаешь решение → сразу шлешь `km.left_click()`. С KmBox B+ актуальная задержка 15-20 мс, для триггера хватит.
 
Назад
Сверху Снизу