makcu 2.2.2__py3-none-any.whl → 2.3.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/README.md +405 -405
- makcu/__init__.py +1 -1
- makcu/controller.py +425 -410
- makcu/mouse.py +298 -249
- {makcu-2.2.2.dist-info → makcu-2.3.0.dist-info}/METADATA +2 -2
- {makcu-2.2.2.dist-info → makcu-2.3.0.dist-info}/RECORD +9 -9
- {makcu-2.2.2.dist-info → makcu-2.3.0.dist-info}/WHEEL +0 -0
- {makcu-2.2.2.dist-info → makcu-2.3.0.dist-info}/licenses/LICENSE +0 -0
- {makcu-2.2.2.dist-info → makcu-2.3.0.dist-info}/top_level.txt +0 -0
makcu/README.md
CHANGED
@@ -1,406 +1,406 @@
|
|
1
|
-
# 🖱️ Makcu Python Library v2.
|
2
|
-
|
3
|
-
[](https://pypi.org/project/makcu/)
|
4
|
-
[](https://pypi.org/project/makcu/)
|
5
|
-
[](LICENSE)
|
6
|
-
|
7
|
-
Makcu Py Lib is a high-performance Python library for controlling Makcu devices — now with **async/await support**, **zero-delay command execution**, and **automatic reconnection**!
|
8
|
-
|
9
|
-
---
|
10
|
-
|
11
|
-
## 📦 Installation
|
12
|
-
|
13
|
-
### Recommended: PyPI
|
14
|
-
|
15
|
-
```bash
|
16
|
-
pip install makcu
|
17
|
-
```
|
18
|
-
|
19
|
-
### From Source
|
20
|
-
|
21
|
-
```bash
|
22
|
-
git clone https://github.com/SleepyTotem/makcu-py-lib
|
23
|
-
cd makcu-py-lib
|
24
|
-
pip install .
|
25
|
-
```
|
26
|
-
|
27
|
-
---
|
28
|
-
|
29
|
-
## 🧠 Quick Start
|
30
|
-
|
31
|
-
### Synchronous API (Classic)
|
32
|
-
|
33
|
-
```python
|
34
|
-
from makcu import create_controller, MouseButton
|
35
|
-
|
36
|
-
# Create and connect
|
37
|
-
makcu = create_controller(debug=True, auto_reconnect=True)
|
38
|
-
|
39
|
-
# Basic operations
|
40
|
-
makcu.click(MouseButton.LEFT)
|
41
|
-
makcu.move(100, 50)
|
42
|
-
makcu.scroll(-1)
|
43
|
-
|
44
|
-
# Human-like interaction
|
45
|
-
makcu.click_human_like(MouseButton.LEFT, count=2, profile="gaming", jitter=3)
|
46
|
-
|
47
|
-
# Clean disconnect
|
48
|
-
makcu.disconnect()
|
49
|
-
```
|
50
|
-
|
51
|
-
### Asynchronous API (New!)
|
52
|
-
|
53
|
-
```python
|
54
|
-
import asyncio
|
55
|
-
from makcu import create_async_controller, MouseButton
|
56
|
-
|
57
|
-
async def main():
|
58
|
-
# Auto-connect with context manager
|
59
|
-
async with await create_async_controller(debug=True) as makcu:
|
60
|
-
# Parallel operations
|
61
|
-
await asyncio.gather(
|
62
|
-
makcu.move(100, 0),
|
63
|
-
makcu.click(MouseButton.LEFT),
|
64
|
-
makcu.scroll(-1)
|
65
|
-
)
|
66
|
-
|
67
|
-
# Human-like clicking
|
68
|
-
await makcu.click_human_like(MouseButton.RIGHT, count=3)
|
69
|
-
|
70
|
-
asyncio.run(main())
|
71
|
-
```
|
72
|
-
|
73
|
-
---
|
74
|
-
|
75
|
-
## 🎮 Core Features
|
76
|
-
|
77
|
-
### Mouse Control
|
78
|
-
|
79
|
-
```python
|
80
|
-
# Button actions
|
81
|
-
await makcu.click(MouseButton.LEFT)
|
82
|
-
await makcu.double_click(MouseButton.RIGHT)
|
83
|
-
await makcu.press(MouseButton.MIDDLE)
|
84
|
-
await makcu.release(MouseButton.MIDDLE)
|
85
|
-
|
86
|
-
# Movement
|
87
|
-
await makcu.move(100, 50) # Relative movement
|
88
|
-
await makcu.move_smooth(200, 100, segments=20) # Smooth interpolation
|
89
|
-
await makcu.move_bezier(150, 150, segments=30, ctrl_x=75, ctrl_y=200) # Bezier curve
|
90
|
-
|
91
|
-
# Scrolling
|
92
|
-
await makcu.scroll(-5) # Scroll down
|
93
|
-
await makcu.scroll(3) # Scroll up
|
94
|
-
|
95
|
-
# Dragging
|
96
|
-
await makcu.drag(0, 0, 300, 200, button=MouseButton.LEFT, duration=1.5)
|
97
|
-
```
|
98
|
-
|
99
|
-
### Button & Axis Locking
|
100
|
-
|
101
|
-
```python
|
102
|
-
# New unified locking API
|
103
|
-
await makcu.lock(MouseButton.LEFT) # Lock left button
|
104
|
-
await makcu.unlock(MouseButton.RIGHT) # Unlock right button
|
105
|
-
await makcu.lock("X") # Lock X-axis movement
|
106
|
-
await makcu.unlock("Y") # Unlock Y-axis movement
|
107
|
-
|
108
|
-
# Query lock states (no delays!)
|
109
|
-
is_locked = await makcu.is_locked(MouseButton.LEFT)
|
110
|
-
all_states = await makcu.get_all_lock_states()
|
111
|
-
# Returns: {"LEFT": True, "RIGHT": False, "X": True, ...}
|
112
|
-
```
|
113
|
-
|
114
|
-
### Human-like Interactions
|
115
|
-
|
116
|
-
```python
|
117
|
-
# Realistic clicking with timing variations
|
118
|
-
await makcu.click_human_like(
|
119
|
-
button=MouseButton.LEFT,
|
120
|
-
count=5,
|
121
|
-
profile="gaming", # "fast", "normal", "slow", "variable", "gaming"
|
122
|
-
jitter=5 # Random mouse movement between clicks
|
123
|
-
)
|
124
|
-
```
|
125
|
-
|
126
|
-
### Button Event Monitoring
|
127
|
-
|
128
|
-
```python
|
129
|
-
# Real-time button monitoring
|
130
|
-
def on_button_event(button: MouseButton, pressed: bool):
|
131
|
-
print(f"{button.name} {'pressed' if pressed else 'released'}")
|
132
|
-
|
133
|
-
makcu.set_button_callback(on_button_event)
|
134
|
-
await makcu.enable_button_monitoring(True)
|
135
|
-
|
136
|
-
# Check current button states
|
137
|
-
states = makcu.get_button_states()
|
138
|
-
if makcu.is_pressed(MouseButton.RIGHT):
|
139
|
-
print("Right button is pressed")
|
140
|
-
```
|
141
|
-
|
142
|
-
### Connection Management
|
143
|
-
|
144
|
-
```python
|
145
|
-
# Auto-reconnection on disconnect
|
146
|
-
makcu = await create_async_controller(auto_reconnect=True)
|
147
|
-
|
148
|
-
# Connection status callbacks
|
149
|
-
@makcu.on_connection_change
|
150
|
-
async def handle_connection(connected: bool):
|
151
|
-
if connected:
|
152
|
-
print("Device reconnected!")
|
153
|
-
else:
|
154
|
-
print("Device disconnected!")
|
155
|
-
|
156
|
-
# Manual reconnection
|
157
|
-
if not makcu.is_connected():
|
158
|
-
await makcu.connect()
|
159
|
-
```
|
160
|
-
|
161
|
-
---
|
162
|
-
|
163
|
-
## 🔧 Advanced Features
|
164
|
-
|
165
|
-
### Batch Operations
|
166
|
-
|
167
|
-
```python
|
168
|
-
# Execute multiple commands efficiently
|
169
|
-
async def combo_action():
|
170
|
-
await makcu.batch_execute([
|
171
|
-
lambda: makcu.move(50, 0),
|
172
|
-
lambda: makcu.click(MouseButton.LEFT),
|
173
|
-
lambda: makcu.move(-50, 0),
|
174
|
-
lambda: makcu.click(MouseButton.RIGHT)
|
175
|
-
])
|
176
|
-
```
|
177
|
-
|
178
|
-
### Device Information
|
179
|
-
|
180
|
-
```python
|
181
|
-
# Get device details
|
182
|
-
info = await makcu.get_device_info()
|
183
|
-
# {'port': 'COM3', 'vid': '0x1a86', 'pid': '0x55d3', ...}
|
184
|
-
|
185
|
-
# Firmware version
|
186
|
-
version = await makcu.get_firmware_version()
|
187
|
-
```
|
188
|
-
|
189
|
-
### Serial Spoofing
|
190
|
-
|
191
|
-
```python
|
192
|
-
# Spoof device serial
|
193
|
-
await makcu.spoof_serial("CUSTOM123456")
|
194
|
-
|
195
|
-
# Reset to default
|
196
|
-
await makcu.reset_serial()
|
197
|
-
```
|
198
|
-
|
199
|
-
### Low-Level Access
|
200
|
-
|
201
|
-
```python
|
202
|
-
# Send raw commands with tracked responses
|
203
|
-
response = await makcu.transport.async_send_command(
|
204
|
-
"km.version()",
|
205
|
-
expect_response=True,
|
206
|
-
timeout=0.1 # Optimized for gaming
|
207
|
-
)
|
208
|
-
```
|
209
|
-
|
210
|
-
---
|
211
|
-
|
212
|
-
## 🧪 Command-Line Tools
|
213
|
-
|
214
|
-
```bash
|
215
|
-
# Interactive debug console
|
216
|
-
python -m makcu --debug
|
217
|
-
|
218
|
-
# Test specific port
|
219
|
-
python -m makcu --testPort COM3
|
220
|
-
|
221
|
-
# Run automated tests
|
222
|
-
python -m makcu --runtest
|
223
|
-
```
|
224
|
-
|
225
|
-
### Tool Descriptions
|
226
|
-
|
227
|
-
- `--debug`: Launches an interactive console where you can type raw device commands and see live responses.
|
228
|
-
- `--testPort COMx`: Attempts to connect to the given COM port and reports success or failure.
|
229
|
-
- `--runtest`: Runs `test_suite.py` using `pytest` and opens a detailed HTML test report.
|
230
|
-
|
231
|
-
---
|
232
|
-
|
233
|
-
### Test Suite
|
234
|
-
|
235
|
-
- File: `test_suite.py`
|
236
|
-
- Run with: `python -m makcu --runtest`
|
237
|
-
- Output: `latest_pytest.html`
|
238
|
-
|
239
|
-
Includes tests for:
|
240
|
-
- Port connection
|
241
|
-
- Firmware version check
|
242
|
-
- Mouse movement and button control
|
243
|
-
- Button masking and locking
|
244
|
-
|
245
|
-
---
|
246
|
-
|
247
|
-
## Test Timings (v1.3 vs v1.4 vs v2.0)
|
248
|
-
|
249
|
-
| Test Name | v1.3 | v1.4 | v2.0 | Improvement (v1.3 → v2.0) |
|
250
|
-
|--------------------------|--------|-------|-------|----------------------------|
|
251
|
-
| connect_to_port | ~100ms | ~55ms | **46ms** | ~2.2x faster |
|
252
|
-
| press_and_release | ~18ms | ~9ms | **1ms** | ~18x faster |
|
253
|
-
| firmware_version | ~20ms | ~9ms | **1ms** | ~20x faster |
|
254
|
-
| middle_click | ~18ms | ~9ms | **1ms** | ~18x faster |
|
255
|
-
| device_info | ~25ms | ~13ms | **6ms** | ~4.1x faster |
|
256
|
-
| port_connection | ~20ms | ~9ms | **1ms** | ~20x faster |
|
257
|
-
| button_mask | ~17ms | ~8ms | **1ms** | ~17x faster |
|
258
|
-
| get_button_states | ~18ms | ~9ms | **1ms** | ~18x faster |
|
259
|
-
| lock_state | ~33ms | ~10ms | **1ms** | ~33x faster |
|
260
|
-
| makcu_behavior | ~20ms | ~10ms | **1ms** | ~20x faster |
|
261
|
-
| batch_commands | ~350ms | ~90ms | **3ms** | ~117x faster |
|
262
|
-
| rapid_moves | ~17ms | ~8ms | **2ms** | ~8.5x faster |
|
263
|
-
| button_performance | ~18ms | ~9ms | **2ms** | ~9x faster |
|
264
|
-
| mixed_operations | ~22ms | ~10ms | **2ms** | ~11x faster |
|
265
|
-
|
266
|
-
Based on the measured test suite, v2.0 is on average **~17× faster** than v1.3 across all core operations.
|
267
|
-
|
268
|
-
|
269
|
-
### Gaming Performance Targets (v2.0)
|
270
|
-
|
271
|
-
- **144Hz Gaming**: 7ms frame time — ✅ Easily met (avg 1–3ms per operation)
|
272
|
-
- **240Hz Gaming**: 4.2ms frame time — ✅ Consistently met (most ops ≤ 2ms)
|
273
|
-
- **360Hz Gaming**: 2.8ms frame time — ⚡ Achievable for atomic/single ops
|
274
|
-
|
275
|
-
---
|
276
|
-
|
277
|
-
## 🏎️ Performance Optimization Details
|
278
|
-
|
279
|
-
### Version History & Performance
|
280
|
-
|
281
|
-
- **v1.3 and earlier**: Original implementation with sleep delays
|
282
|
-
- **v1.4**: Initial optimizations, removed some sleep delays
|
283
|
-
- **v2.0**: Complete rewrite with zero-delay architecture
|
284
|
-
|
285
|
-
### Key Optimizations in v2.0
|
286
|
-
|
287
|
-
1. **Pre-computed Commands**: All commands are pre-formatted at initialization
|
288
|
-
2. **Bitwise Operations**: Button states use single integer with bit manipulation
|
289
|
-
3. **Zero-Copy Buffers**: Pre-allocated buffers for parsing
|
290
|
-
4. **Reduced Timeouts**: Gaming-optimized timeouts (100ms default)
|
291
|
-
5. **Cache Everything**: Connection states, lock states, and device info cached
|
292
|
-
6. **Minimal Allocations**: Reuse objects and avoid string formatting
|
293
|
-
7. **Fast Serial Settings**: 1ms read timeout, 10ms write timeout
|
294
|
-
8. **Optimized Listener**: Batch processing with minimal overhead
|
295
|
-
|
296
|
-
### Tips for Maximum Performance
|
297
|
-
|
298
|
-
```python
|
299
|
-
# Disable debug mode in production
|
300
|
-
makcu = create_controller(debug=False)
|
301
|
-
|
302
|
-
# Use cached connection checks
|
303
|
-
if makcu.is_connected(): # Cached, no serial check
|
304
|
-
makcu.click(MouseButton.LEFT)
|
305
|
-
|
306
|
-
# Batch similar operations
|
307
|
-
with makcu: # Context manager ensures connection
|
308
|
-
for _ in range(10):
|
309
|
-
makcu.move(10, 0) # No connection check per call
|
310
|
-
```
|
311
|
-
|
312
|
-
---
|
313
|
-
|
314
|
-
## 🔍 Debugging
|
315
|
-
|
316
|
-
Enable debug mode for detailed logging:
|
317
|
-
|
318
|
-
```python
|
319
|
-
makcu = await create_async_controller(debug=True)
|
320
|
-
|
321
|
-
# View command flow (optimized timestamps)
|
322
|
-
# [123.456] [INFO] Sent command #42: km.move(100,50)
|
323
|
-
# [123.458] [DEBUG] Command #42 completed in 0.002s
|
324
|
-
```
|
325
|
-
|
326
|
-
---
|
327
|
-
|
328
|
-
## 🏗️ Migration from v1.x
|
329
|
-
|
330
|
-
Most code works without changes! Key differences:
|
331
|
-
|
332
|
-
```python
|
333
|
-
# v1.x (still works)
|
334
|
-
makcu = create_controller()
|
335
|
-
makcu.move(100, 100)
|
336
|
-
|
337
|
-
# v2.0 (async)
|
338
|
-
makcu = await create_async_controller()
|
339
|
-
await makcu.move(100, 100)
|
340
|
-
|
341
|
-
# v2.0 context manager (auto cleanup)
|
342
|
-
async with await create_async_controller() as makcu:
|
343
|
-
await makcu.click(MouseButton.LEFT)
|
344
|
-
```
|
345
|
-
|
346
|
-
---
|
347
|
-
|
348
|
-
## 📚 API Reference
|
349
|
-
|
350
|
-
### Enumerations
|
351
|
-
|
352
|
-
```python
|
353
|
-
from makcu import MouseButton
|
354
|
-
|
355
|
-
MouseButton.LEFT # Left mouse button
|
356
|
-
MouseButton.RIGHT # Right mouse button
|
357
|
-
MouseButton.MIDDLE # Middle mouse button
|
358
|
-
MouseButton.MOUSE4 # Side button 1
|
359
|
-
MouseButton.MOUSE5 # Side button 2
|
360
|
-
```
|
361
|
-
|
362
|
-
### Exception Handling
|
363
|
-
|
364
|
-
```python
|
365
|
-
from makcu import MakcuError, MakcuConnectionError, MakcuTimeoutError
|
366
|
-
|
367
|
-
try:
|
368
|
-
makcu = await create_async_controller()
|
369
|
-
except MakcuConnectionError as e:
|
370
|
-
print(f"Connection failed: {e}")
|
371
|
-
except MakcuTimeoutError as e:
|
372
|
-
print(f"Command timed out: {e}")
|
373
|
-
```
|
374
|
-
|
375
|
-
---
|
376
|
-
|
377
|
-
## 🛠️ Technical Details
|
378
|
-
|
379
|
-
- **Protocol**: CH343 USB serial at 4Mbps
|
380
|
-
- **Command Format**: ASCII with optional ID tracking (`command#ID`)
|
381
|
-
- **Response Format**: `>>> #ID:response` for tracked commands
|
382
|
-
- **Threading**: High-priority listener thread with async bridge
|
383
|
-
- **Auto-Discovery**: VID:PID=1A86:55D3 detection
|
384
|
-
- **Buffer Size**: 4KB read buffer, 256B line buffer
|
385
|
-
- **Cleanup Interval**: 50ms for timed-out commands
|
386
|
-
|
387
|
-
---
|
388
|
-
|
389
|
-
## 📜 License
|
390
|
-
|
391
|
-
GPL License © SleepyTotem
|
392
|
-
|
393
|
-
---
|
394
|
-
|
395
|
-
## 🙋 Support
|
396
|
-
|
397
|
-
- **Issues**: [GitHub Issues](https://github.com/SleepyTotem/makcu-py-lib/issues)
|
398
|
-
|
399
|
-
---
|
400
|
-
|
401
|
-
## 🌐 Links
|
402
|
-
|
403
|
-
- [GitHub Repository](https://github.com/SleepyTotem/makcu-py-lib)
|
404
|
-
- [PyPI Package](https://pypi.org/project/makcu/)
|
405
|
-
- [Documentation](https://makcu-py-lib.readthedocs.io/)
|
1
|
+
# 🖱️ Makcu Python Library v2.3.0
|
2
|
+
|
3
|
+
[](https://pypi.org/project/makcu/)
|
4
|
+
[](https://pypi.org/project/makcu/)
|
5
|
+
[](LICENSE)
|
6
|
+
|
7
|
+
Makcu Py Lib is a high-performance Python library for controlling Makcu devices — now with **async/await support**, **zero-delay command execution**, and **automatic reconnection**!
|
8
|
+
|
9
|
+
---
|
10
|
+
|
11
|
+
## 📦 Installation
|
12
|
+
|
13
|
+
### Recommended: PyPI
|
14
|
+
|
15
|
+
```bash
|
16
|
+
pip install makcu
|
17
|
+
```
|
18
|
+
|
19
|
+
### From Source
|
20
|
+
|
21
|
+
```bash
|
22
|
+
git clone https://github.com/SleepyTotem/makcu-py-lib
|
23
|
+
cd makcu-py-lib
|
24
|
+
pip install .
|
25
|
+
```
|
26
|
+
|
27
|
+
---
|
28
|
+
|
29
|
+
## 🧠 Quick Start
|
30
|
+
|
31
|
+
### Synchronous API (Classic)
|
32
|
+
|
33
|
+
```python
|
34
|
+
from makcu import create_controller, MouseButton
|
35
|
+
|
36
|
+
# Create and connect
|
37
|
+
makcu = create_controller(debug=True, auto_reconnect=True)
|
38
|
+
|
39
|
+
# Basic operations
|
40
|
+
makcu.click(MouseButton.LEFT)
|
41
|
+
makcu.move(100, 50)
|
42
|
+
makcu.scroll(-1)
|
43
|
+
|
44
|
+
# Human-like interaction
|
45
|
+
makcu.click_human_like(MouseButton.LEFT, count=2, profile="gaming", jitter=3)
|
46
|
+
|
47
|
+
# Clean disconnect
|
48
|
+
makcu.disconnect()
|
49
|
+
```
|
50
|
+
|
51
|
+
### Asynchronous API (New!)
|
52
|
+
|
53
|
+
```python
|
54
|
+
import asyncio
|
55
|
+
from makcu import create_async_controller, MouseButton
|
56
|
+
|
57
|
+
async def main():
|
58
|
+
# Auto-connect with context manager
|
59
|
+
async with await create_async_controller(debug=True) as makcu:
|
60
|
+
# Parallel operations
|
61
|
+
await asyncio.gather(
|
62
|
+
makcu.move(100, 0),
|
63
|
+
makcu.click(MouseButton.LEFT),
|
64
|
+
makcu.scroll(-1)
|
65
|
+
)
|
66
|
+
|
67
|
+
# Human-like clicking
|
68
|
+
await makcu.click_human_like(MouseButton.RIGHT, count=3)
|
69
|
+
|
70
|
+
asyncio.run(main())
|
71
|
+
```
|
72
|
+
|
73
|
+
---
|
74
|
+
|
75
|
+
## 🎮 Core Features
|
76
|
+
|
77
|
+
### Mouse Control
|
78
|
+
|
79
|
+
```python
|
80
|
+
# Button actions
|
81
|
+
await makcu.click(MouseButton.LEFT)
|
82
|
+
await makcu.double_click(MouseButton.RIGHT)
|
83
|
+
await makcu.press(MouseButton.MIDDLE)
|
84
|
+
await makcu.release(MouseButton.MIDDLE)
|
85
|
+
|
86
|
+
# Movement
|
87
|
+
await makcu.move(100, 50) # Relative movement
|
88
|
+
await makcu.move_smooth(200, 100, segments=20) # Smooth interpolation
|
89
|
+
await makcu.move_bezier(150, 150, segments=30, ctrl_x=75, ctrl_y=200) # Bezier curve
|
90
|
+
|
91
|
+
# Scrolling
|
92
|
+
await makcu.scroll(-5) # Scroll down
|
93
|
+
await makcu.scroll(3) # Scroll up
|
94
|
+
|
95
|
+
# Dragging
|
96
|
+
await makcu.drag(0, 0, 300, 200, button=MouseButton.LEFT, duration=1.5)
|
97
|
+
```
|
98
|
+
|
99
|
+
### Button & Axis Locking
|
100
|
+
|
101
|
+
```python
|
102
|
+
# New unified locking API
|
103
|
+
await makcu.lock(MouseButton.LEFT) # Lock left button
|
104
|
+
await makcu.unlock(MouseButton.RIGHT) # Unlock right button
|
105
|
+
await makcu.lock("X") # Lock X-axis movement
|
106
|
+
await makcu.unlock("Y") # Unlock Y-axis movement
|
107
|
+
|
108
|
+
# Query lock states (no delays!)
|
109
|
+
is_locked = await makcu.is_locked(MouseButton.LEFT)
|
110
|
+
all_states = await makcu.get_all_lock_states()
|
111
|
+
# Returns: {"LEFT": True, "RIGHT": False, "X": True, ...}
|
112
|
+
```
|
113
|
+
|
114
|
+
### Human-like Interactions
|
115
|
+
|
116
|
+
```python
|
117
|
+
# Realistic clicking with timing variations
|
118
|
+
await makcu.click_human_like(
|
119
|
+
button=MouseButton.LEFT,
|
120
|
+
count=5,
|
121
|
+
profile="gaming", # "fast", "normal", "slow", "variable", "gaming"
|
122
|
+
jitter=5 # Random mouse movement between clicks
|
123
|
+
)
|
124
|
+
```
|
125
|
+
|
126
|
+
### Button Event Monitoring
|
127
|
+
|
128
|
+
```python
|
129
|
+
# Real-time button monitoring
|
130
|
+
def on_button_event(button: MouseButton, pressed: bool):
|
131
|
+
print(f"{button.name} {'pressed' if pressed else 'released'}")
|
132
|
+
|
133
|
+
makcu.set_button_callback(on_button_event)
|
134
|
+
await makcu.enable_button_monitoring(True)
|
135
|
+
|
136
|
+
# Check current button states
|
137
|
+
states = makcu.get_button_states()
|
138
|
+
if makcu.is_pressed(MouseButton.RIGHT):
|
139
|
+
print("Right button is pressed")
|
140
|
+
```
|
141
|
+
|
142
|
+
### Connection Management
|
143
|
+
|
144
|
+
```python
|
145
|
+
# Auto-reconnection on disconnect
|
146
|
+
makcu = await create_async_controller(auto_reconnect=True)
|
147
|
+
|
148
|
+
# Connection status callbacks
|
149
|
+
@makcu.on_connection_change
|
150
|
+
async def handle_connection(connected: bool):
|
151
|
+
if connected:
|
152
|
+
print("Device reconnected!")
|
153
|
+
else:
|
154
|
+
print("Device disconnected!")
|
155
|
+
|
156
|
+
# Manual reconnection
|
157
|
+
if not makcu.is_connected():
|
158
|
+
await makcu.connect()
|
159
|
+
```
|
160
|
+
|
161
|
+
---
|
162
|
+
|
163
|
+
## 🔧 Advanced Features
|
164
|
+
|
165
|
+
### Batch Operations
|
166
|
+
|
167
|
+
```python
|
168
|
+
# Execute multiple commands efficiently
|
169
|
+
async def combo_action():
|
170
|
+
await makcu.batch_execute([
|
171
|
+
lambda: makcu.move(50, 0),
|
172
|
+
lambda: makcu.click(MouseButton.LEFT),
|
173
|
+
lambda: makcu.move(-50, 0),
|
174
|
+
lambda: makcu.click(MouseButton.RIGHT)
|
175
|
+
])
|
176
|
+
```
|
177
|
+
|
178
|
+
### Device Information
|
179
|
+
|
180
|
+
```python
|
181
|
+
# Get device details
|
182
|
+
info = await makcu.get_device_info()
|
183
|
+
# {'port': 'COM3', 'vid': '0x1a86', 'pid': '0x55d3', ...}
|
184
|
+
|
185
|
+
# Firmware version
|
186
|
+
version = await makcu.get_firmware_version()
|
187
|
+
```
|
188
|
+
|
189
|
+
### Serial Spoofing
|
190
|
+
|
191
|
+
```python
|
192
|
+
# Spoof device serial
|
193
|
+
await makcu.spoof_serial("CUSTOM123456")
|
194
|
+
|
195
|
+
# Reset to default
|
196
|
+
await makcu.reset_serial()
|
197
|
+
```
|
198
|
+
|
199
|
+
### Low-Level Access
|
200
|
+
|
201
|
+
```python
|
202
|
+
# Send raw commands with tracked responses
|
203
|
+
response = await makcu.transport.async_send_command(
|
204
|
+
"km.version()",
|
205
|
+
expect_response=True,
|
206
|
+
timeout=0.1 # Optimized for gaming
|
207
|
+
)
|
208
|
+
```
|
209
|
+
|
210
|
+
---
|
211
|
+
|
212
|
+
## 🧪 Command-Line Tools
|
213
|
+
|
214
|
+
```bash
|
215
|
+
# Interactive debug console
|
216
|
+
python -m makcu --debug
|
217
|
+
|
218
|
+
# Test specific port
|
219
|
+
python -m makcu --testPort COM3
|
220
|
+
|
221
|
+
# Run automated tests
|
222
|
+
python -m makcu --runtest
|
223
|
+
```
|
224
|
+
|
225
|
+
### Tool Descriptions
|
226
|
+
|
227
|
+
- `--debug`: Launches an interactive console where you can type raw device commands and see live responses.
|
228
|
+
- `--testPort COMx`: Attempts to connect to the given COM port and reports success or failure.
|
229
|
+
- `--runtest`: Runs `test_suite.py` using `pytest` and opens a detailed HTML test report.
|
230
|
+
|
231
|
+
---
|
232
|
+
|
233
|
+
### Test Suite
|
234
|
+
|
235
|
+
- File: `test_suite.py`
|
236
|
+
- Run with: `python -m makcu --runtest`
|
237
|
+
- Output: `latest_pytest.html`
|
238
|
+
|
239
|
+
Includes tests for:
|
240
|
+
- Port connection
|
241
|
+
- Firmware version check
|
242
|
+
- Mouse movement and button control
|
243
|
+
- Button masking and locking
|
244
|
+
|
245
|
+
---
|
246
|
+
|
247
|
+
## Test Timings (v1.3 vs v1.4 vs v2.0)
|
248
|
+
|
249
|
+
| Test Name | v1.3 | v1.4 | v2.0 | Improvement (v1.3 → v2.0) |
|
250
|
+
|--------------------------|--------|-------|-------|----------------------------|
|
251
|
+
| connect_to_port | ~100ms | ~55ms | **46ms** | ~2.2x faster |
|
252
|
+
| press_and_release | ~18ms | ~9ms | **1ms** | ~18x faster |
|
253
|
+
| firmware_version | ~20ms | ~9ms | **1ms** | ~20x faster |
|
254
|
+
| middle_click | ~18ms | ~9ms | **1ms** | ~18x faster |
|
255
|
+
| device_info | ~25ms | ~13ms | **6ms** | ~4.1x faster |
|
256
|
+
| port_connection | ~20ms | ~9ms | **1ms** | ~20x faster |
|
257
|
+
| button_mask | ~17ms | ~8ms | **1ms** | ~17x faster |
|
258
|
+
| get_button_states | ~18ms | ~9ms | **1ms** | ~18x faster |
|
259
|
+
| lock_state | ~33ms | ~10ms | **1ms** | ~33x faster |
|
260
|
+
| makcu_behavior | ~20ms | ~10ms | **1ms** | ~20x faster |
|
261
|
+
| batch_commands | ~350ms | ~90ms | **3ms** | ~117x faster |
|
262
|
+
| rapid_moves | ~17ms | ~8ms | **2ms** | ~8.5x faster |
|
263
|
+
| button_performance | ~18ms | ~9ms | **2ms** | ~9x faster |
|
264
|
+
| mixed_operations | ~22ms | ~10ms | **2ms** | ~11x faster |
|
265
|
+
|
266
|
+
Based on the measured test suite, v2.0 is on average **~17× faster** than v1.3 across all core operations.
|
267
|
+
|
268
|
+
|
269
|
+
### Gaming Performance Targets (v2.0)
|
270
|
+
|
271
|
+
- **144Hz Gaming**: 7ms frame time — ✅ Easily met (avg 1–3ms per operation)
|
272
|
+
- **240Hz Gaming**: 4.2ms frame time — ✅ Consistently met (most ops ≤ 2ms)
|
273
|
+
- **360Hz Gaming**: 2.8ms frame time — ⚡ Achievable for atomic/single ops
|
274
|
+
|
275
|
+
---
|
276
|
+
|
277
|
+
## 🏎️ Performance Optimization Details
|
278
|
+
|
279
|
+
### Version History & Performance
|
280
|
+
|
281
|
+
- **v1.3 and earlier**: Original implementation with sleep delays
|
282
|
+
- **v1.4**: Initial optimizations, removed some sleep delays
|
283
|
+
- **v2.0**: Complete rewrite with zero-delay architecture
|
284
|
+
|
285
|
+
### Key Optimizations in v2.0
|
286
|
+
|
287
|
+
1. **Pre-computed Commands**: All commands are pre-formatted at initialization
|
288
|
+
2. **Bitwise Operations**: Button states use single integer with bit manipulation
|
289
|
+
3. **Zero-Copy Buffers**: Pre-allocated buffers for parsing
|
290
|
+
4. **Reduced Timeouts**: Gaming-optimized timeouts (100ms default)
|
291
|
+
5. **Cache Everything**: Connection states, lock states, and device info cached
|
292
|
+
6. **Minimal Allocations**: Reuse objects and avoid string formatting
|
293
|
+
7. **Fast Serial Settings**: 1ms read timeout, 10ms write timeout
|
294
|
+
8. **Optimized Listener**: Batch processing with minimal overhead
|
295
|
+
|
296
|
+
### Tips for Maximum Performance
|
297
|
+
|
298
|
+
```python
|
299
|
+
# Disable debug mode in production
|
300
|
+
makcu = create_controller(debug=False)
|
301
|
+
|
302
|
+
# Use cached connection checks
|
303
|
+
if makcu.is_connected(): # Cached, no serial check
|
304
|
+
makcu.click(MouseButton.LEFT)
|
305
|
+
|
306
|
+
# Batch similar operations
|
307
|
+
with makcu: # Context manager ensures connection
|
308
|
+
for _ in range(10):
|
309
|
+
makcu.move(10, 0) # No connection check per call
|
310
|
+
```
|
311
|
+
|
312
|
+
---
|
313
|
+
|
314
|
+
## 🔍 Debugging
|
315
|
+
|
316
|
+
Enable debug mode for detailed logging:
|
317
|
+
|
318
|
+
```python
|
319
|
+
makcu = await create_async_controller(debug=True)
|
320
|
+
|
321
|
+
# View command flow (optimized timestamps)
|
322
|
+
# [123.456] [INFO] Sent command #42: km.move(100,50)
|
323
|
+
# [123.458] [DEBUG] Command #42 completed in 0.002s
|
324
|
+
```
|
325
|
+
|
326
|
+
---
|
327
|
+
|
328
|
+
## 🏗️ Migration from v1.x
|
329
|
+
|
330
|
+
Most code works without changes! Key differences:
|
331
|
+
|
332
|
+
```python
|
333
|
+
# v1.x (still works)
|
334
|
+
makcu = create_controller()
|
335
|
+
makcu.move(100, 100)
|
336
|
+
|
337
|
+
# v2.0 (async)
|
338
|
+
makcu = await create_async_controller()
|
339
|
+
await makcu.move(100, 100)
|
340
|
+
|
341
|
+
# v2.0 context manager (auto cleanup)
|
342
|
+
async with await create_async_controller() as makcu:
|
343
|
+
await makcu.click(MouseButton.LEFT)
|
344
|
+
```
|
345
|
+
|
346
|
+
---
|
347
|
+
|
348
|
+
## 📚 API Reference
|
349
|
+
|
350
|
+
### Enumerations
|
351
|
+
|
352
|
+
```python
|
353
|
+
from makcu import MouseButton
|
354
|
+
|
355
|
+
MouseButton.LEFT # Left mouse button
|
356
|
+
MouseButton.RIGHT # Right mouse button
|
357
|
+
MouseButton.MIDDLE # Middle mouse button
|
358
|
+
MouseButton.MOUSE4 # Side button 1
|
359
|
+
MouseButton.MOUSE5 # Side button 2
|
360
|
+
```
|
361
|
+
|
362
|
+
### Exception Handling
|
363
|
+
|
364
|
+
```python
|
365
|
+
from makcu import MakcuError, MakcuConnectionError, MakcuTimeoutError
|
366
|
+
|
367
|
+
try:
|
368
|
+
makcu = await create_async_controller()
|
369
|
+
except MakcuConnectionError as e:
|
370
|
+
print(f"Connection failed: {e}")
|
371
|
+
except MakcuTimeoutError as e:
|
372
|
+
print(f"Command timed out: {e}")
|
373
|
+
```
|
374
|
+
|
375
|
+
---
|
376
|
+
|
377
|
+
## 🛠️ Technical Details
|
378
|
+
|
379
|
+
- **Protocol**: CH343 USB serial at 4Mbps
|
380
|
+
- **Command Format**: ASCII with optional ID tracking (`command#ID`)
|
381
|
+
- **Response Format**: `>>> #ID:response` for tracked commands
|
382
|
+
- **Threading**: High-priority listener thread with async bridge
|
383
|
+
- **Auto-Discovery**: VID:PID=1A86:55D3 detection
|
384
|
+
- **Buffer Size**: 4KB read buffer, 256B line buffer
|
385
|
+
- **Cleanup Interval**: 50ms for timed-out commands
|
386
|
+
|
387
|
+
---
|
388
|
+
|
389
|
+
## 📜 License
|
390
|
+
|
391
|
+
GPL License © SleepyTotem
|
392
|
+
|
393
|
+
---
|
394
|
+
|
395
|
+
## 🙋 Support
|
396
|
+
|
397
|
+
- **Issues**: [GitHub Issues](https://github.com/SleepyTotem/makcu-py-lib/issues)
|
398
|
+
|
399
|
+
---
|
400
|
+
|
401
|
+
## 🌐 Links
|
402
|
+
|
403
|
+
- [GitHub Repository](https://github.com/SleepyTotem/makcu-py-lib)
|
404
|
+
- [PyPI Package](https://pypi.org/project/makcu/)
|
405
|
+
- [Documentation](https://makcu-py-lib.readthedocs.io/)
|
406
406
|
- [Changelog](https://makcu-py-lib.readthedocs.io/en/latest/changelog.html)
|