Skip to content

Commit 17430e2

Browse files
committed
fix logic
1 parent 9c62391 commit 17430e2

File tree

6 files changed

+98
-68
lines changed

6 files changed

+98
-68
lines changed

examples/mouse.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from src.arduino_hid_controller.constants import MOUSE_RIGHT, MOUSE_LEFT
55

66
with HIDController() as hid:
7-
print(f"Текущая позиция мыши: {hid.get_position()}")
7+
print(f"Текущая позиция мыши: {hid.mouse.get_position()}")
88

99
print('Ожидание 2 секунды...')
1010
sleep(2)
@@ -15,23 +15,12 @@
1515
print('Ожидание 2 секунды...')
1616
sleep(2)
1717

18-
print('Перемещение мыши в координаты 500,300 и клик правой кнопкой')
19-
hid.mouse.move_absolute(500, 300, 1)
20-
hid.mouse.click(MOUSE_RIGHT)
21-
22-
print('Ожидание 2 секунды...')
23-
sleep(2)
24-
25-
print('Перемещение мыши в координаты 100,100 и клик левой кнопкой')
26-
hid.mouse.move_absolute(100, 100, 1)
27-
hid.mouse.click(MOUSE_LEFT)
28-
29-
print('Ожидание 2 секунды...')
30-
sleep(2)
31-
32-
print('Перемещение на 100 пикселей вправо/вниз и клик левой кнопкой')
33-
hid.mouse.move_relative(100, 100)
34-
hid.mouse.click()
18+
# Square movement pattern
19+
points = [(100, 100), (100, 200), (200, 200), (200, 100), (100, 100)]
20+
for x, y in points:
21+
hid.mouse.move_absolute(x, y, duration=2)
22+
sleep(1)
23+
#hid.mouse.click(MOUSE_LEFT)
3524

3625
print('Ожидание 2 секунды...')
3726
sleep(2)

sketches/adruino-hid.ino

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void loop() {
4343

4444
Device parseDevice(const String& deviceStr) {
4545
if (deviceStr == F("keyboard")) return DEVICE_KEYBOARD;
46-
if (actionStr == F("press")) return DEVICE_MOUSE;
46+
if (deviceStr == F("mouse")) return DEVICE_MOUSE;
4747
return DEVICE_UNKNOWN;
4848
}
4949

@@ -195,7 +195,7 @@ bool handleKeyboard(ActionKeyboard action, const String& args) {
195195
Serial.println(F("Error: Missing keyboard text to print"));
196196
return false;
197197
}
198-
Keyboard.print(args)
198+
Keyboard.print(args);
199199
return true;
200200
}
201201
default:
@@ -244,7 +244,10 @@ String separateString(const String& data, char separator, int index, bool getRem
244244
}
245245
found++;
246246
strIndex[0] = strIndex[1] + 1;
247-
strIndex[1] = (i == maxIndex) ? i + 1 : i;
247+
strIndex[1] = i;
248+
if (i == maxIndex && data.charAt(i) != separator) {
249+
strIndex[1] = i + 1;
250+
}
248251
}
249252
}
250253
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";

src/arduino_hid_controller/arduino_controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ def _send_command(self, device: str, action: str, *args) -> bool:
7878
self.__logger.warning("Попытка отправить команду без соединения")
7979
return False
8080

81-
command = f"{device}|{action}"
81+
command = f"{device}|{action}|"
8282
if args:
83-
command += "|" + "|".join(str(arg) for arg in args)
83+
command += "|".join(str(arg) for arg in args)
8484

8585
try:
8686
self.__serial.write(f"{command}\n".encode())

src/arduino_hid_controller/hid_controller.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from .arduino_controller import ArduinoController
12
from .keyboard_controller import KeyboardController
23
from .mouse_controller import MouseController
34

@@ -9,5 +10,12 @@ def __init__(self):
910
"""
1011
Инициализация контроллера HID-устройств
1112
"""
12-
self.keyboard = KeyboardController()
13-
self.mouse = MouseController()
13+
self._arduino = ArduinoController()
14+
self.keyboard = KeyboardController(self._arduino)
15+
self.mouse = MouseController(self._arduino)
16+
17+
def __enter__(self):
18+
return self
19+
20+
def __exit__(self, exc_type, exc_val, exc_tb):
21+
return self

src/arduino_hid_controller/keyboard_controller.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,21 @@
66

77
class KeyboardController(ArduinoController):
88
"""Класс для эмуляции клавиатуры через Arduino"""
9-
10-
def __init__(self):
11-
super().__init__()
9+
def __init__(self, arduino: ArduinoController):
10+
self._arduino = arduino
1211
self.__logger = logging.getLogger(__name__)
1312
self.__is_started = False
1413

1514
def start(self) -> bool:
1615
"""Начать эмуляцию клавиатуры"""
17-
result = self._send_command("keyboard", "start")
16+
result = self._arduino._send_command("keyboard", "start")
1817
if result:
1918
self.__is_started = True
2019
return result
2120

2221
def stop(self) -> bool:
2322
"""Остановить эмуляцию клавиатуры"""
24-
result = self._send_command("keyboard", "stop")
23+
result = self._arduino._send_command("keyboard", "stop")
2524
if result:
2625
self.__is_started = False
2726
return result
@@ -44,7 +43,7 @@ def press(self, key: Union[str, int]) -> bool:
4443
key_str = hex(key) if isinstance(key, int) else key
4544
if not key_str:
4645
self.__logger.error("Не указана клавиша для нажатия")
47-
return self._send_command("keyboard", "press", key_str)
46+
return self._arduino._send_command("keyboard", "press", key_str)
4847

4948
def release(self, key: Union[str, int]) -> bool:
5049
"""
@@ -61,7 +60,7 @@ def release(self, key: Union[str, int]) -> bool:
6160
if not key_str:
6261
self.__logger.error("Не указана клавиша для отпускания")
6362
return False
64-
return self._send_command("keyboard", "release", key_str)
63+
return self._arduino._send_command("keyboard", "release", key_str)
6564

6665
def press_and_release(self, key: Union[str, int], delay: float = 0.05) -> bool:
6766
"""
@@ -121,7 +120,7 @@ def release_all(self) -> bool:
121120
if not self.__is_started:
122121
self.__logger.warning("Попытка отпустить все клавиши при неактивной эмуляции")
123122
return False
124-
return self._send_command("keyboard", "release_all")
123+
return self._arduino._send_command("keyboard", "release_all")
125124

126125
def write(self, text: str) -> bool:
127126
"""
@@ -137,4 +136,4 @@ def write(self, text: str) -> bool:
137136
if not text:
138137
self.__logger.warning("Попытка отправить пустой текст")
139138
return False
140-
return self._send_command("keyboard", "print", text)
139+
return self._arduino._send_command("keyboard", "print", text)

src/arduino_hid_controller/mouse_controller.py

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
class MouseController(ArduinoController):
99
"""Класс для эмуляции мыши через Arduino"""
1010

11-
def __init__(self):
12-
super().__init__()
11+
def __init__(self, arduino: ArduinoController):
12+
self._arduino = arduino
1313
self.__logger = logging.getLogger(__name__)
1414
self.__current_x = None
1515
self.__current_y = None
@@ -38,14 +38,14 @@ def __set_positions(self):
3838

3939
def start(self) -> bool:
4040
"""Начать эмуляцию мыши"""
41-
result = self._send_command("mouse", "start")
41+
result = self._arduino._send_command("mouse", "start")
4242
if result:
4343
self.__is_started = True
4444
return result
4545

4646
def stop(self) -> bool:
4747
"""Остановить эмуляцию мыши"""
48-
result = self._send_command("mouse", "stop")
48+
result = self._arduino._send_command("mouse", "stop")
4949
if result:
5050
self.__is_started = False
5151
return result
@@ -70,7 +70,7 @@ def press(self, button: Union[str, int]) -> bool:
7070
self.__logger.error("Не указана кнопка мыши")
7171
return False
7272

73-
return self._send_command("mouse", "press", button_str)
73+
return self._arduino._send_command("mouse", "press", button_str)
7474

7575
def release(self, button: Union[str, int]) -> bool:
7676
"""
@@ -88,7 +88,7 @@ def release(self, button: Union[str, int]) -> bool:
8888
self.__logger.error("Не указана кнопка мыши")
8989
return False
9090

91-
return self._send_command("mouse", "release", button_str)
91+
return self._arduino._send_command("mouse", "release", button_str)
9292

9393
def click(self, button: Union[str, int]) -> bool:
9494
"""
@@ -98,54 +98,85 @@ def click(self, button: Union[str, int]) -> bool:
9898
button: Может быть 'left', 'right', 'middle' или код кнопки
9999
"""
100100
button_str = hex(button) if isinstance(button, int) else button
101-
return self._send_command("mouse", "click", button_str)
101+
return self._arduino._send_command("mouse", "click", button_str)
102102

103+
#TODO: Работает не корректно
103104
def move_absolute(self, target_x: int, target_y: int, duration: float = 1.0) -> bool:
104105
"""
105-
Плавное перемещение курсора в указанные координаты за заданное время
106-
107-
Аргументы:
108-
target_x: Конечная координата X (0 - левый край экрана)
109-
target_y: Конечная координата Y (0 - верхний край экрана)
110-
duration: Время перемещения в секундах (минимум 0.01)
111-
112-
Возвращает:
113-
bool: True если перемещение успешно, False в случае ошибки
106+
Усовершенствованное перемещение с коррекцией координат и проверкой отклонений.
107+
Возвращает True при успешном перемещении, False при ошибке.
114108
"""
115-
# Проверка и корректировка координат
116109
if not self.__is_started:
117110
self.__logger.warning("Попытка перемещения при неактивной эмуляции")
118111
return False
119112

120113
if duration <= 0:
121-
self.__logger.error("Длительность должна быть положительной")
114+
self.__logger.error("Некорректная длительность перемещения")
122115
return False
123116

117+
# Получаем и корректируем координаты
124118
self.__set_positions()
125-
target_x = max(0, min(target_x, self.__screen_width - 1))
126-
target_y = max(0, min(target_y, self.__screen_height - 1))
119+
target_x = max(0, min(int(target_x), self.__screen_width - 1))
120+
target_y = max(0, min(int(target_y), self.__screen_height - 1))
127121

128-
if target_x == self.__current_x and target_y == self.__current_y:
122+
# Проверяем необходимость перемещения
123+
if (target_x, target_y) == (self.__current_x, self.__current_y):
129124
return True
130125

131-
steps = max(1, int(min(duration, 300.0) * 60))
126+
# Рассчитываем общее перемещение
127+
total_x = target_x - self.__current_x
128+
total_y = target_y - self.__current_y
129+
130+
# Оптимальные параметры перемещения
131+
steps = max(1, min(int(duration * 60), 300)) # 60 шагов/сек, макс 300 шагов
132132
step_delay = duration / steps
133-
step_x = (target_x - self.__current_x) / steps
134-
step_y = (target_y - self.__current_y) / steps
133+
max_deviation = 5 # Максимально допустимое отклонение в пикселях
134+
135+
# Основной цикл перемещения с коррекцией
136+
for step in range(1, steps + 1):
137+
# Плавное движение с ускорением/замедлением
138+
progress = step / steps
139+
eased_progress = progress # Можно изменить на ease-in/out функцию
135140

136-
for i in range(steps):
137-
new_x = int(self.__current_x + step_x * (i + 1))
138-
new_y = int(self.__current_y + step_y * (i + 1))
139-
rel_x = new_x - self.__current_x
140-
rel_y = new_y - self.__current_y
141+
# Целевые координаты на текущем шаге
142+
new_x = self.__current_x + total_x * eased_progress
143+
new_y = self.__current_y + total_y * eased_progress
144+
145+
# Относительное перемещение
146+
rel_x = round(new_x - self.__current_x)
147+
rel_y = round(new_y - self.__current_y)
141148

142149
if rel_x != 0 or rel_y != 0:
143-
if not self._send_command("mouse", "move", rel_x, rel_y):
150+
# Отправляем команду перемещения
151+
if not self._arduino._send_command("mouse", "move", rel_x, rel_y):
152+
self.__logger.error(f"Ошибка перемещения на шаге {step}")
144153
return False
145154

146-
self.__current_x = new_x
147-
self.__current_y = new_y
148-
time.sleep(step_delay)
155+
# Обновляем текущую позицию
156+
self.__current_x += rel_x
157+
self.__current_y += rel_y
158+
159+
# Проверка отклонения (дополнительная страховка)
160+
expected_x = self.__current_x + total_x * eased_progress
161+
expected_y = self.__current_y + total_y * eased_progress
162+
deviation = ((self.__current_x - expected_x) ** 2 +
163+
(self.__current_y - expected_y) ** 2) ** 0.5
164+
165+
if deviation > max_deviation:
166+
self.__logger.warning(f"Коррекция отклонения: {deviation:.1f} пикселей")
167+
return self.move_absolute(target_x, target_y, duration / 2)
168+
169+
time.sleep(step_delay)
170+
171+
# Финальная коррекция
172+
final_rel_x = target_x - self.__current_x
173+
final_rel_y = target_y - self.__current_y
174+
if final_rel_x != 0 or final_rel_y != 0:
175+
success = self._arduino._send_command("mouse", "move", final_rel_x, final_rel_y)
176+
if success:
177+
self.__current_x = target_x
178+
self.__current_y = target_y
179+
return success
149180

150181
return True
151182

@@ -161,7 +192,7 @@ def move_relative(self, x: int, y: int) -> bool:
161192
self.__logger.warning("Попытка перемещения при неактивной эмуляции")
162193
return False
163194

164-
return self._send_command("mouse", "move", x, y)
195+
return self._arduino._send_command("mouse", "move", x, y)
165196

166197
def get_position(self) -> Tuple[int, int]:
167198
"""Получить текущие виртуальные координаты курсора"""

0 commit comments

Comments
 (0)