88class 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