makcu 0.1.3__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- makcu/__init__.py +71 -9
- makcu/__main__.py +254 -37
- makcu/conftest.py +27 -17
- makcu/connection.py +439 -224
- makcu/controller.py +345 -100
- makcu/makcu.pyi +13 -0
- makcu/mouse.py +240 -86
- makcu/py.typed +2 -0
- makcu/test_suite.py +113 -54
- makcu-0.2.0.dist-info/METADATA +1141 -0
- makcu-0.2.0.dist-info/RECORD +16 -0
- makcu-0.1.3.dist-info/METADATA +0 -310
- makcu-0.1.3.dist-info/RECORD +0 -14
- {makcu-0.1.3.dist-info → makcu-0.2.0.dist-info}/WHEEL +0 -0
- {makcu-0.1.3.dist-info → makcu-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {makcu-0.1.3.dist-info → makcu-0.2.0.dist-info}/top_level.txt +0 -0
makcu/controller.py
CHANGED
@@ -1,176 +1,421 @@
|
|
1
|
+
import asyncio
|
1
2
|
import random
|
2
3
|
import time
|
4
|
+
from typing import Optional, Dict, Callable, Union, List, Any
|
5
|
+
from concurrent.futures import ThreadPoolExecutor
|
3
6
|
from .mouse import Mouse
|
4
7
|
from .connection import SerialTransport
|
5
8
|
from .errors import MakcuConnectionError
|
6
9
|
from .enums import MouseButton
|
7
10
|
|
8
11
|
class MakcuController:
|
9
|
-
|
10
|
-
|
12
|
+
"""Ultra-optimized MakcuController for gaming performance"""
|
13
|
+
|
14
|
+
# Pre-computed lock mappings for O(1) access
|
15
|
+
_BUTTON_LOCK_MAP = {
|
16
|
+
MouseButton.LEFT: 'lock_left',
|
17
|
+
MouseButton.RIGHT: 'lock_right',
|
18
|
+
MouseButton.MIDDLE: 'lock_middle',
|
19
|
+
MouseButton.MOUSE4: 'lock_side1',
|
20
|
+
MouseButton.MOUSE5: 'lock_side2',
|
21
|
+
}
|
22
|
+
|
23
|
+
def __init__(self, fallback_com_port: str = "", debug: bool = False,
|
24
|
+
send_init: bool = True, auto_reconnect: bool = True,
|
25
|
+
override_port: bool = False) -> None:
|
26
|
+
self.transport = SerialTransport(
|
27
|
+
fallback_com_port,
|
28
|
+
debug=debug,
|
29
|
+
send_init=send_init,
|
30
|
+
auto_reconnect=auto_reconnect,
|
31
|
+
override_port=override_port
|
32
|
+
)
|
11
33
|
self.mouse = Mouse(self.transport)
|
34
|
+
self._executor = ThreadPoolExecutor(max_workers=1)
|
35
|
+
self._connection_callbacks: List[Callable[[bool], None]] = []
|
36
|
+
|
37
|
+
# Cache connection state to avoid repeated checks
|
38
|
+
self._connected = False
|
12
39
|
|
13
|
-
|
40
|
+
# Connection management
|
41
|
+
def connect(self) -> None:
|
42
|
+
"""Connect with state caching"""
|
14
43
|
self.transport.connect()
|
44
|
+
self._connected = True
|
45
|
+
self._notify_connection_change(True)
|
15
46
|
|
16
|
-
def disconnect(self):
|
47
|
+
def disconnect(self) -> None:
|
48
|
+
"""Disconnect with cleanup"""
|
17
49
|
self.transport.disconnect()
|
50
|
+
self._connected = False
|
51
|
+
self._notify_connection_change(False)
|
52
|
+
self._executor.shutdown(wait=False)
|
18
53
|
|
19
|
-
def is_connected(self):
|
20
|
-
|
54
|
+
def is_connected(self) -> bool:
|
55
|
+
"""Fast cached connection check"""
|
56
|
+
return self._connected and self.transport.is_connected()
|
21
57
|
|
22
|
-
def _check_connection(self):
|
23
|
-
|
58
|
+
def _check_connection(self) -> None:
|
59
|
+
"""Inline connection check for speed"""
|
60
|
+
if not self._connected:
|
24
61
|
raise MakcuConnectionError("Not connected")
|
25
62
|
|
26
|
-
def
|
27
|
-
|
28
|
-
self.
|
29
|
-
|
63
|
+
def _notify_connection_change(self, connected: bool) -> None:
|
64
|
+
"""Notify callbacks with error suppression"""
|
65
|
+
for callback in self._connection_callbacks:
|
66
|
+
try:
|
67
|
+
callback(connected)
|
68
|
+
except Exception:
|
69
|
+
pass # Silently ignore for performance
|
70
|
+
|
71
|
+
# Optimized mouse operations
|
72
|
+
def click(self, button: MouseButton) -> None:
|
73
|
+
"""Optimized click - direct command"""
|
74
|
+
if not self._connected:
|
75
|
+
raise MakcuConnectionError("Not connected")
|
76
|
+
self.mouse.press(button)
|
77
|
+
self.mouse.release(button)
|
30
78
|
|
31
|
-
def
|
32
|
-
|
79
|
+
def double_click(self, button: MouseButton) -> None:
|
80
|
+
"""Double click with minimal delay"""
|
81
|
+
if not self._connected:
|
82
|
+
raise MakcuConnectionError("Not connected")
|
83
|
+
self.mouse.press(button)
|
84
|
+
self.mouse.release(button)
|
85
|
+
# 1ms delay for double click recognition
|
86
|
+
time.sleep(0.001)
|
87
|
+
self.mouse.press(button)
|
88
|
+
self.mouse.release(button)
|
89
|
+
|
90
|
+
def move(self, dx: int, dy: int) -> None:
|
91
|
+
"""Direct move"""
|
92
|
+
if not self._connected:
|
93
|
+
raise MakcuConnectionError("Not connected")
|
33
94
|
self.mouse.move(dx, dy)
|
34
95
|
|
35
|
-
def scroll(self, delta: int):
|
36
|
-
|
96
|
+
def scroll(self, delta: int) -> None:
|
97
|
+
"""Direct scroll"""
|
98
|
+
if not self._connected:
|
99
|
+
raise MakcuConnectionError("Not connected")
|
37
100
|
self.mouse.scroll(delta)
|
38
101
|
|
39
|
-
def
|
40
|
-
|
41
|
-
self.
|
102
|
+
def press(self, button: MouseButton) -> None:
|
103
|
+
"""Direct press"""
|
104
|
+
if not self._connected:
|
105
|
+
raise MakcuConnectionError("Not connected")
|
106
|
+
self.mouse.press(button)
|
42
107
|
|
43
|
-
def
|
44
|
-
|
45
|
-
self.
|
108
|
+
def release(self, button: MouseButton) -> None:
|
109
|
+
"""Direct release"""
|
110
|
+
if not self._connected:
|
111
|
+
raise MakcuConnectionError("Not connected")
|
112
|
+
self.mouse.release(button)
|
46
113
|
|
47
|
-
|
48
|
-
|
49
|
-
|
114
|
+
# Advanced movement - unchanged but with connection check optimization
|
115
|
+
def move_smooth(self, dx: int, dy: int, segments: int = 10) -> None:
|
116
|
+
"""Smooth movement"""
|
117
|
+
if not self._connected:
|
118
|
+
raise MakcuConnectionError("Not connected")
|
119
|
+
self.mouse.move_smooth(dx, dy, segments)
|
50
120
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
121
|
+
def move_bezier(self, dx: int, dy: int, segments: int = 20,
|
122
|
+
ctrl_x: Optional[int] = None, ctrl_y: Optional[int] = None) -> None:
|
123
|
+
"""Bezier curve movement"""
|
124
|
+
if not self._connected:
|
125
|
+
raise MakcuConnectionError("Not connected")
|
126
|
+
if ctrl_x is None:
|
127
|
+
ctrl_x = dx // 2
|
128
|
+
if ctrl_y is None:
|
129
|
+
ctrl_y = dy // 2
|
130
|
+
self.mouse.move_bezier(dx, dy, segments, ctrl_x, ctrl_y)
|
54
131
|
|
55
|
-
|
56
|
-
|
132
|
+
# Optimized lock API
|
133
|
+
def lock(self, target: Union[MouseButton, str]) -> None:
|
134
|
+
"""Lock with fast lookup"""
|
135
|
+
if not self._connected:
|
136
|
+
raise MakcuConnectionError("Not connected")
|
137
|
+
|
138
|
+
if isinstance(target, MouseButton):
|
139
|
+
if target in self._BUTTON_LOCK_MAP:
|
140
|
+
getattr(self.mouse, self._BUTTON_LOCK_MAP[target])(True)
|
141
|
+
else:
|
142
|
+
raise ValueError(f"Unsupported button: {target}")
|
143
|
+
elif target.upper() in ['X', 'Y']:
|
144
|
+
if target.upper() == 'X':
|
145
|
+
self.mouse.lock_x(True)
|
146
|
+
else:
|
147
|
+
self.mouse.lock_y(True)
|
148
|
+
else:
|
149
|
+
raise ValueError(f"Invalid lock target: {target}")
|
150
|
+
|
151
|
+
def unlock(self, target: Union[MouseButton, str]) -> None:
|
152
|
+
"""Unlock with fast lookup"""
|
153
|
+
if not self._connected:
|
154
|
+
raise MakcuConnectionError("Not connected")
|
155
|
+
|
156
|
+
if isinstance(target, MouseButton):
|
157
|
+
if target in self._BUTTON_LOCK_MAP:
|
158
|
+
getattr(self.mouse, self._BUTTON_LOCK_MAP[target])(False)
|
159
|
+
else:
|
160
|
+
raise ValueError(f"Unsupported button: {target}")
|
161
|
+
elif target.upper() in ['X', 'Y']:
|
162
|
+
if target.upper() == 'X':
|
163
|
+
self.mouse.lock_x(False)
|
164
|
+
else:
|
165
|
+
self.mouse.lock_y(False)
|
166
|
+
else:
|
167
|
+
raise ValueError(f"Invalid unlock target: {target}")
|
168
|
+
|
169
|
+
# Direct lock methods for backward compatibility
|
170
|
+
def lock_left(self, lock: bool) -> None:
|
171
|
+
if not self._connected:
|
172
|
+
raise MakcuConnectionError("Not connected")
|
57
173
|
self.mouse.lock_left(lock)
|
58
174
|
|
59
|
-
def lock_middle(self, lock: bool):
|
60
|
-
self.
|
175
|
+
def lock_middle(self, lock: bool) -> None:
|
176
|
+
if not self._connected:
|
177
|
+
raise MakcuConnectionError("Not connected")
|
61
178
|
self.mouse.lock_middle(lock)
|
62
179
|
|
63
|
-
def lock_right(self, lock: bool):
|
64
|
-
self.
|
180
|
+
def lock_right(self, lock: bool) -> None:
|
181
|
+
if not self._connected:
|
182
|
+
raise MakcuConnectionError("Not connected")
|
65
183
|
self.mouse.lock_right(lock)
|
66
184
|
|
67
|
-
def lock_side1(self, lock: bool):
|
68
|
-
self.
|
185
|
+
def lock_side1(self, lock: bool) -> None:
|
186
|
+
if not self._connected:
|
187
|
+
raise MakcuConnectionError("Not connected")
|
69
188
|
self.mouse.lock_side1(lock)
|
70
189
|
|
71
|
-
def lock_side2(self, lock: bool):
|
72
|
-
self.
|
190
|
+
def lock_side2(self, lock: bool) -> None:
|
191
|
+
if not self._connected:
|
192
|
+
raise MakcuConnectionError("Not connected")
|
73
193
|
self.mouse.lock_side2(lock)
|
74
194
|
|
75
|
-
def lock_x(self, lock: bool):
|
76
|
-
self.
|
195
|
+
def lock_x(self, lock: bool) -> None:
|
196
|
+
if not self._connected:
|
197
|
+
raise MakcuConnectionError("Not connected")
|
77
198
|
self.mouse.lock_x(lock)
|
78
199
|
|
79
|
-
def lock_y(self, lock: bool):
|
80
|
-
self.
|
200
|
+
def lock_y(self, lock: bool) -> None:
|
201
|
+
if not self._connected:
|
202
|
+
raise MakcuConnectionError("Not connected")
|
81
203
|
self.mouse.lock_y(lock)
|
82
204
|
|
83
|
-
def
|
84
|
-
|
205
|
+
def lock_mouse_x(self, lock: bool) -> None:
|
206
|
+
"""Alias for lock_x"""
|
207
|
+
self.lock_x(lock)
|
208
|
+
|
209
|
+
def lock_mouse_y(self, lock: bool) -> None:
|
210
|
+
"""Alias for lock_y"""
|
211
|
+
self.lock_y(lock)
|
212
|
+
|
213
|
+
def is_locked(self, button: MouseButton) -> bool:
|
214
|
+
"""Check lock state"""
|
215
|
+
if not self._connected:
|
216
|
+
raise MakcuConnectionError("Not connected")
|
217
|
+
return self.mouse.is_locked(button)
|
218
|
+
|
219
|
+
def get_all_lock_states(self) -> Dict[str, bool]:
|
220
|
+
"""Get all lock states"""
|
221
|
+
if not self._connected:
|
222
|
+
raise MakcuConnectionError("Not connected")
|
223
|
+
return self.mouse.get_all_lock_states()
|
224
|
+
|
225
|
+
# Device operations
|
226
|
+
def spoof_serial(self, serial: str) -> None:
|
227
|
+
"""Spoof device serial"""
|
228
|
+
if not self._connected:
|
229
|
+
raise MakcuConnectionError("Not connected")
|
85
230
|
self.mouse.spoof_serial(serial)
|
86
231
|
|
87
|
-
def reset_serial(self):
|
88
|
-
|
232
|
+
def reset_serial(self) -> None:
|
233
|
+
"""Reset device serial"""
|
234
|
+
if not self._connected:
|
235
|
+
raise MakcuConnectionError("Not connected")
|
89
236
|
self.mouse.reset_serial()
|
90
237
|
|
91
|
-
def get_device_info(self):
|
92
|
-
|
238
|
+
def get_device_info(self) -> Dict[str, str]:
|
239
|
+
"""Get device information"""
|
240
|
+
if not self._connected:
|
241
|
+
raise MakcuConnectionError("Not connected")
|
93
242
|
return self.mouse.get_device_info()
|
94
243
|
|
95
|
-
def get_firmware_version(self):
|
96
|
-
|
244
|
+
def get_firmware_version(self) -> str:
|
245
|
+
"""Get firmware version"""
|
246
|
+
if not self._connected:
|
247
|
+
raise MakcuConnectionError("Not connected")
|
97
248
|
return self.mouse.get_firmware_version()
|
98
249
|
|
250
|
+
# Button monitoring - direct transport access for speed
|
99
251
|
def get_button_mask(self) -> int:
|
100
|
-
|
252
|
+
"""Get current button mask"""
|
253
|
+
if not self._connected:
|
254
|
+
raise MakcuConnectionError("Not connected")
|
101
255
|
return self.transport.get_button_mask()
|
102
256
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
257
|
+
def get_button_states(self) -> Dict[str, bool]:
|
258
|
+
"""Get current button states"""
|
259
|
+
if not self._connected:
|
260
|
+
raise MakcuConnectionError("Not connected")
|
261
|
+
return self.transport.get_button_states()
|
262
|
+
|
263
|
+
def is_pressed(self, button: MouseButton) -> bool:
|
264
|
+
"""Check if button is pressed"""
|
265
|
+
if not self._connected:
|
266
|
+
raise MakcuConnectionError("Not connected")
|
267
|
+
return self.transport.get_button_states().get(button.name.lower(), False)
|
106
268
|
|
107
|
-
|
108
|
-
|
109
|
-
|
269
|
+
def enable_button_monitoring(self, enable: bool = True) -> None:
|
270
|
+
"""Enable/disable button monitoring"""
|
271
|
+
if not self._connected:
|
272
|
+
raise MakcuConnectionError("Not connected")
|
273
|
+
self.transport.enable_button_monitoring(enable)
|
110
274
|
|
275
|
+
def set_button_callback(self, callback: Optional[Callable[[MouseButton, bool], None]]) -> None:
|
276
|
+
"""Set button event callback"""
|
277
|
+
if not self._connected:
|
278
|
+
raise MakcuConnectionError("Not connected")
|
279
|
+
self.transport.set_button_callback(callback)
|
111
280
|
|
112
|
-
#
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
#def get_captured_clicks(self, button: MouseButton) -> int:
|
117
|
-
# self._check_connection()
|
118
|
-
# return self.mouse.stop_capturing_clicks(button.name)
|
281
|
+
# Connection management
|
282
|
+
def on_connection_change(self, callback: Callable[[bool], None]) -> None:
|
283
|
+
"""Register connection status change callback"""
|
284
|
+
self._connection_callbacks.append(callback)
|
119
285
|
|
286
|
+
def remove_connection_callback(self, callback: Callable[[bool], None]) -> None:
|
287
|
+
"""Remove connection status callback"""
|
288
|
+
if callback in self._connection_callbacks:
|
289
|
+
self._connection_callbacks.remove(callback)
|
120
290
|
|
291
|
+
# Human-like interactions with optimized timing
|
121
292
|
def click_human_like(self, button: MouseButton, count: int = 1,
|
122
|
-
|
123
|
-
|
293
|
+
profile: str = "normal", jitter: int = 0) -> None:
|
294
|
+
"""Human-like clicking optimized for gaming"""
|
295
|
+
if not self._connected:
|
296
|
+
raise MakcuConnectionError("Not connected")
|
124
297
|
|
298
|
+
# Pre-computed timing profiles (in milliseconds)
|
125
299
|
timing_profiles = {
|
126
300
|
"normal": (60, 120, 100, 180),
|
127
301
|
"fast": (30, 60, 50, 100),
|
128
302
|
"slow": (100, 180, 150, 300),
|
303
|
+
"variable": (40, 200, 80, 250),
|
304
|
+
"gaming": (20, 40, 30, 60), # New gaming profile
|
129
305
|
}
|
130
306
|
|
131
307
|
if profile not in timing_profiles:
|
132
|
-
raise ValueError(f"Invalid profile: {profile}
|
308
|
+
raise ValueError(f"Invalid profile: {profile}")
|
133
309
|
|
134
310
|
min_down, max_down, min_wait, max_wait = timing_profiles[profile]
|
135
311
|
|
136
|
-
for
|
312
|
+
for i in range(count):
|
137
313
|
if jitter > 0:
|
138
314
|
dx = random.randint(-jitter, jitter)
|
139
315
|
dy = random.randint(-jitter, jitter)
|
140
316
|
self.mouse.move(dx, dy)
|
141
317
|
|
142
|
-
self.press(button)
|
318
|
+
self.mouse.press(button)
|
143
319
|
time.sleep(random.uniform(min_down, max_down) / 1000.0)
|
144
320
|
self.mouse.release(button)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
self.
|
153
|
-
|
154
|
-
|
155
|
-
def get_all_lock_states(self) -> dict:
|
156
|
-
self._check_connection()
|
157
|
-
return self.mouse.get_all_lock_states()
|
158
|
-
|
159
|
-
def _send_button_command(self, button: MouseButton, state: int):
|
160
|
-
self.mouse._send_button_command(button, state)
|
161
|
-
|
162
|
-
def press(self, button: MouseButton):
|
163
|
-
self._check_connection()
|
164
|
-
self._send_button_command(button, 1)
|
165
|
-
|
166
|
-
def release(self, button: MouseButton):
|
167
|
-
self._check_connection()
|
168
|
-
self._send_button_command(button, 0)
|
321
|
+
|
322
|
+
if i < count - 1:
|
323
|
+
time.sleep(random.uniform(min_wait, max_wait) / 1000.0)
|
324
|
+
|
325
|
+
def drag(self, start_x: int, start_y: int, end_x: int, end_y: int,
|
326
|
+
button: MouseButton = MouseButton.LEFT, duration: float = 1.0) -> None:
|
327
|
+
"""Optimized drag operation"""
|
328
|
+
if not self._connected:
|
329
|
+
raise MakcuConnectionError("Not connected")
|
169
330
|
|
170
|
-
|
171
|
-
self.
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
self.
|
176
|
-
|
331
|
+
# Move to start
|
332
|
+
self.move(start_x, start_y)
|
333
|
+
time.sleep(0.02) # Reduced from 0.05
|
334
|
+
|
335
|
+
# Press button
|
336
|
+
self.press(button)
|
337
|
+
time.sleep(0.02) # Reduced from 0.05
|
338
|
+
|
339
|
+
# Move to end with smooth motion
|
340
|
+
segments = max(10, int(duration * 30))
|
341
|
+
self.move_smooth(end_x - start_x, end_y - start_y, segments)
|
342
|
+
|
343
|
+
# Release button
|
344
|
+
time.sleep(0.02) # Reduced from 0.05
|
345
|
+
self.release(button)
|
346
|
+
|
347
|
+
# Context manager support
|
348
|
+
def __enter__(self):
|
349
|
+
"""Context manager entry"""
|
350
|
+
if not self.is_connected():
|
351
|
+
self.connect()
|
352
|
+
return self
|
353
|
+
|
354
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
355
|
+
"""Context manager exit"""
|
356
|
+
self.disconnect()
|
357
|
+
|
358
|
+
# Async methods for forward compatibility
|
359
|
+
async def async_connect(self) -> None:
|
360
|
+
"""Async connect"""
|
361
|
+
loop = asyncio.get_running_loop()
|
362
|
+
await loop.run_in_executor(self._executor, self.connect)
|
363
|
+
|
364
|
+
async def async_disconnect(self) -> None:
|
365
|
+
"""Async disconnect"""
|
366
|
+
loop = asyncio.get_running_loop()
|
367
|
+
await loop.run_in_executor(self._executor, self.disconnect)
|
368
|
+
|
369
|
+
async def async_click(self, button: MouseButton) -> None:
|
370
|
+
"""Async click"""
|
371
|
+
loop = asyncio.get_running_loop()
|
372
|
+
await loop.run_in_executor(self._executor, self.click, button)
|
373
|
+
|
374
|
+
async def async_move(self, dx: int, dy: int) -> None:
|
375
|
+
"""Async move"""
|
376
|
+
loop = asyncio.get_running_loop()
|
377
|
+
await loop.run_in_executor(self._executor, self.move, dx, dy)
|
378
|
+
|
379
|
+
async def async_scroll(self, delta: int) -> None:
|
380
|
+
"""Async scroll"""
|
381
|
+
loop = asyncio.get_running_loop()
|
382
|
+
await loop.run_in_executor(self._executor, self.scroll, delta)
|
383
|
+
|
384
|
+
# Async context manager
|
385
|
+
async def __aenter__(self):
|
386
|
+
"""Async context manager entry"""
|
387
|
+
await self.async_connect()
|
388
|
+
return self
|
389
|
+
|
390
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
391
|
+
"""Async context manager exit"""
|
392
|
+
await self.async_disconnect()
|
393
|
+
|
394
|
+
|
395
|
+
# Factory functions with connection optimization
|
396
|
+
def create_controller(fallback_com_port: str = "", debug: bool = False,
|
397
|
+
send_init: bool = True, auto_reconnect: bool = True) -> MakcuController:
|
398
|
+
"""Create and connect a controller"""
|
399
|
+
makcu = MakcuController(
|
400
|
+
fallback_com_port,
|
401
|
+
debug=debug,
|
402
|
+
send_init=send_init,
|
403
|
+
auto_reconnect=auto_reconnect
|
404
|
+
)
|
405
|
+
makcu.connect()
|
406
|
+
return makcu
|
407
|
+
|
408
|
+
|
409
|
+
async def create_async_controller(fallback_com_port: str = "", debug: bool = False,
|
410
|
+
send_init: bool = True, auto_reconnect: bool = True,
|
411
|
+
override_port: bool = False) -> MakcuController:
|
412
|
+
"""Create and connect a controller asynchronously"""
|
413
|
+
makcu = MakcuController(
|
414
|
+
fallback_com_port,
|
415
|
+
debug=debug,
|
416
|
+
send_init=send_init,
|
417
|
+
auto_reconnect=auto_reconnect,
|
418
|
+
override_port=override_port
|
419
|
+
)
|
420
|
+
await makcu.async_connect()
|
421
|
+
return makcu
|
makcu/makcu.pyi
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import Optional, Dict, Callable, List, Union
|
2
|
+
from .controller import MakcuController
|
3
|
+
from .enums import MouseButton
|
4
|
+
from .errors import MakcuError, MakcuConnectionError, MakcuCommandError, MakcuTimeoutError, MakcuResponseError
|
5
|
+
|
6
|
+
__version__: str
|
7
|
+
__all__: List[str]
|
8
|
+
|
9
|
+
def create_controller(
|
10
|
+
fallback_com_port: str = "",
|
11
|
+
debug: bool = False,
|
12
|
+
send_init: bool = True
|
13
|
+
) -> MakcuController: ...
|