MaaFw 4.4.0b1__py3-none-manylinux2014_x86_64.whl → 5.4.0__py3-none-manylinux2014_x86_64.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.
Potentially problematic release.
This version of MaaFw might be problematic. Click here for more details.
- maa/agent/agent_server.py +221 -3
- maa/agent_client.py +170 -2
- maa/bin/libMaaAdbControlUnit.so +0 -0
- maa/bin/libMaaAgentClient.so +0 -0
- maa/bin/libMaaAgentServer.so +0 -0
- maa/bin/libMaaCustomControlUnit.so +0 -0
- maa/bin/libMaaFramework.so +0 -0
- maa/bin/libMaaToolkit.so +0 -0
- maa/bin/libMaaUtils.so +0 -0
- maa/bin/libc++.so.1 +0 -0
- maa/bin/libc++abi.so.1 +0 -0
- maa/bin/libfastdeploy_ppocr.so +0 -0
- maa/bin/libonnxruntime.so.1 +0 -0
- maa/bin/{libopencv_world4.so.408 → libopencv_world4.so.411} +0 -0
- maa/bin/libunwind.so.1 +0 -0
- maa/bin/plugins/libMaaPluginDemo.so +0 -0
- maa/buffer.py +168 -0
- maa/context.py +402 -10
- maa/controller.py +685 -44
- maa/custom_action.py +43 -0
- maa/custom_recognition.py +61 -9
- maa/define.py +450 -20
- maa/event_sink.py +103 -0
- maa/job.py +77 -1
- maa/library.py +118 -50
- maa/pipeline.py +509 -0
- maa/resource.py +430 -21
- maa/tasker.py +630 -90
- maa/toolkit.py +52 -91
- {maafw-4.4.0b1.dist-info → maafw-5.4.0.dist-info}/METADATA +90 -45
- maafw-5.4.0.dist-info/RECORD +35 -0
- {maafw-4.4.0b1.dist-info → maafw-5.4.0.dist-info}/WHEEL +1 -1
- maa/bin/libMaaDbgControlUnit.so +0 -0
- maa/notification_handler.py +0 -197
- maafw-4.4.0b1.dist-info/RECORD +0 -30
- {maafw-4.4.0b1.dist-info → maafw-5.4.0.dist-info}/licenses/LICENSE.md +0 -0
maa/tasker.py
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import ctypes
|
|
2
|
+
import dataclasses
|
|
2
3
|
import json
|
|
3
4
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
5
|
+
from typing import Dict, Optional, Union
|
|
6
|
+
|
|
7
|
+
import numpy
|
|
5
8
|
|
|
6
9
|
from .define import *
|
|
7
10
|
from .library import Library
|
|
8
11
|
from .buffer import ImageListBuffer, RectBuffer, StringBuffer, ImageBuffer
|
|
9
12
|
from .job import Job, JobWithResult
|
|
10
|
-
from .
|
|
13
|
+
from .event_sink import EventSink, NotificationType
|
|
11
14
|
from .resource import Resource
|
|
12
15
|
from .controller import Controller
|
|
16
|
+
from .pipeline import JRecognitionParam, JActionParam, JRecognitionType, JActionType
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
class Tasker:
|
|
16
|
-
_notification_handler: Optional[NotificationHandler]
|
|
17
20
|
_handle: MaaTaskerHandle
|
|
18
21
|
_own: bool
|
|
19
22
|
|
|
@@ -21,19 +24,24 @@ class Tasker:
|
|
|
21
24
|
|
|
22
25
|
def __init__(
|
|
23
26
|
self,
|
|
24
|
-
notification_handler: Optional[NotificationHandler] = None,
|
|
25
27
|
handle: Optional[MaaTaskerHandle] = None,
|
|
26
28
|
):
|
|
29
|
+
"""创建实例 / Create instance
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
handle: 可选的外部句柄 / Optional external handle
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
RuntimeError: 如果创建失败
|
|
36
|
+
"""
|
|
37
|
+
|
|
27
38
|
self._set_api_properties()
|
|
28
39
|
|
|
29
40
|
if handle:
|
|
30
41
|
self._handle = handle
|
|
31
42
|
self._own = False
|
|
32
43
|
else:
|
|
33
|
-
self.
|
|
34
|
-
self._handle = Library.framework().MaaTaskerCreate(
|
|
35
|
-
*NotificationHandler._gen_c_param(self._notification_handler)
|
|
36
|
-
)
|
|
44
|
+
self._handle = Library.framework().MaaTaskerCreate()
|
|
37
45
|
self._own = True
|
|
38
46
|
|
|
39
47
|
if not self._handle:
|
|
@@ -44,6 +52,15 @@ class Tasker:
|
|
|
44
52
|
Library.framework().MaaTaskerDestroy(self._handle)
|
|
45
53
|
|
|
46
54
|
def bind(self, resource: Resource, controller: Controller) -> bool:
|
|
55
|
+
"""关联资源和控制器 / Bind resource and controller
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
resource: 资源对象 / Resource object
|
|
59
|
+
controller: 控制器对象 / Controller object
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
bool: 是否成功 / Whether successful
|
|
63
|
+
"""
|
|
47
64
|
# avoid gc
|
|
48
65
|
self._resource_holder = resource
|
|
49
66
|
self._controller_holder = controller
|
|
@@ -58,6 +75,14 @@ class Tasker:
|
|
|
58
75
|
|
|
59
76
|
@property
|
|
60
77
|
def resource(self) -> Resource:
|
|
78
|
+
"""获取关联的资源 / Get bound resource
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Resource: 资源对象 / Resource object
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
RuntimeError: 如果获取失败
|
|
85
|
+
"""
|
|
61
86
|
resource_handle = Library.framework().MaaTaskerGetResource(self._handle)
|
|
62
87
|
if not resource_handle:
|
|
63
88
|
raise RuntimeError("Failed to get resource.")
|
|
@@ -66,6 +91,14 @@ class Tasker:
|
|
|
66
91
|
|
|
67
92
|
@property
|
|
68
93
|
def controller(self) -> Controller:
|
|
94
|
+
"""获取关联的控制器 / Get bound controller
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Controller: 控制器对象 / Controller object
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
RuntimeError: 如果获取失败
|
|
101
|
+
"""
|
|
69
102
|
controller_handle = Library.framework().MaaTaskerGetController(self._handle)
|
|
70
103
|
if not controller_handle:
|
|
71
104
|
raise RuntimeError("Failed to get controller.")
|
|
@@ -74,28 +107,132 @@ class Tasker:
|
|
|
74
107
|
|
|
75
108
|
@property
|
|
76
109
|
def inited(self) -> bool:
|
|
110
|
+
"""判断是否正确初始化 / Check if initialized correctly
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
bool: 是否已正确初始化 / Whether correctly initialized
|
|
114
|
+
"""
|
|
77
115
|
return bool(Library.framework().MaaTaskerInited(self._handle))
|
|
78
116
|
|
|
79
117
|
def post_task(self, entry: str, pipeline_override: Dict = {}) -> JobWithResult:
|
|
118
|
+
"""异步执行任务 / Asynchronously execute task
|
|
119
|
+
|
|
120
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
121
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
entry: 任务入口 / Task entry
|
|
125
|
+
pipeline_override: 用于覆盖的 json / JSON for overriding
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
JobWithResult: 任务作业对象,可通过 status/wait 查询状态,通过 get() 获取结果 / Task job object, can query status via status/wait, get result via get()
|
|
129
|
+
"""
|
|
80
130
|
taskid = Library.framework().MaaTaskerPostTask(
|
|
81
131
|
self._handle,
|
|
82
132
|
*Tasker._gen_post_param(entry, pipeline_override),
|
|
83
133
|
)
|
|
84
134
|
return self._gen_task_job(taskid)
|
|
85
135
|
|
|
136
|
+
def post_recognition(
|
|
137
|
+
self,
|
|
138
|
+
reco_type: JRecognitionType,
|
|
139
|
+
reco_param: JRecognitionParam,
|
|
140
|
+
image: numpy.ndarray,
|
|
141
|
+
) -> JobWithResult:
|
|
142
|
+
"""异步执行识别 / Asynchronously execute recognition
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
reco_type: 识别类型 / Recognition type
|
|
146
|
+
reco_param: 识别参数 / Recognition parameters
|
|
147
|
+
image: 前序截图 / Previous screenshot
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
JobWithResult: 任务作业对象 / Task job object
|
|
151
|
+
"""
|
|
152
|
+
img_buffer = ImageBuffer()
|
|
153
|
+
img_buffer.set(image)
|
|
154
|
+
reco_param_json = json.dumps(dataclasses.asdict(reco_param), ensure_ascii=False)
|
|
155
|
+
taskid = Library.framework().MaaTaskerPostRecognition(
|
|
156
|
+
self._handle,
|
|
157
|
+
reco_type.encode(),
|
|
158
|
+
reco_param_json.encode(),
|
|
159
|
+
img_buffer._handle,
|
|
160
|
+
)
|
|
161
|
+
return self._gen_task_job(taskid)
|
|
162
|
+
|
|
163
|
+
def post_action(
|
|
164
|
+
self,
|
|
165
|
+
action_type: JActionType,
|
|
166
|
+
action_param: JActionParam,
|
|
167
|
+
box: Rect = Rect(0, 0, 0, 0),
|
|
168
|
+
reco_detail: str = "",
|
|
169
|
+
) -> JobWithResult:
|
|
170
|
+
"""异步执行操作 / Asynchronously execute action
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
action_type: 操作类型 / Action type
|
|
174
|
+
action_param: 操作参数 / Action parameters
|
|
175
|
+
box: 前序识别位置 / Previous recognition position
|
|
176
|
+
reco_detail: 前序识别详情 / Previous recognition details
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
JobWithResult: 任务作业对象 / Task job object
|
|
180
|
+
"""
|
|
181
|
+
rect_buffer = RectBuffer()
|
|
182
|
+
rect_buffer.set(box)
|
|
183
|
+
action_param_json = json.dumps(
|
|
184
|
+
dataclasses.asdict(action_param), ensure_ascii=False
|
|
185
|
+
)
|
|
186
|
+
taskid = Library.framework().MaaTaskerPostAction(
|
|
187
|
+
self._handle,
|
|
188
|
+
action_type.encode(),
|
|
189
|
+
action_param_json.encode(),
|
|
190
|
+
rect_buffer._handle,
|
|
191
|
+
reco_detail.encode(),
|
|
192
|
+
)
|
|
193
|
+
return self._gen_task_job(taskid)
|
|
194
|
+
|
|
86
195
|
@property
|
|
87
196
|
def running(self) -> bool:
|
|
197
|
+
"""判断实例是否还在运行 / Check if instance is still running
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
bool: 是否正在运行 / Whether running
|
|
201
|
+
"""
|
|
88
202
|
return bool(Library.framework().MaaTaskerRunning(self._handle))
|
|
89
203
|
|
|
90
204
|
def post_stop(self) -> Job:
|
|
205
|
+
"""异步停止实例 / Asynchronously stop instance
|
|
206
|
+
|
|
207
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
208
|
+
停止操作会中断当前运行的任务,并停止资源加载和控制器操作
|
|
209
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
210
|
+
The stop operation will interrupt the currently running task and stop resource loading and controller operations
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
214
|
+
"""
|
|
91
215
|
taskid = Library.framework().MaaTaskerPostStop(self._handle)
|
|
92
216
|
return self._gen_task_job(taskid)
|
|
93
217
|
|
|
94
218
|
@property
|
|
95
219
|
def stopping(self) -> bool:
|
|
220
|
+
"""判断实例是否正在停止中(尚未停止) / Check if instance is stopping (not yet stopped)
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
bool: 是否正在停止 / Whether stopping
|
|
224
|
+
"""
|
|
96
225
|
return bool(Library.framework().MaaTaskerStopping(self._handle))
|
|
97
226
|
|
|
98
227
|
def get_latest_node(self, name: str) -> Optional[NodeDetail]:
|
|
228
|
+
"""获取任务的最新节点号 / Get latest node id for task
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
name: 任务名 / Task name
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Optional[NodeDetail]: 节点详情,如果不存在则返回 None / Node detail, or None if not exists
|
|
235
|
+
"""
|
|
99
236
|
c_node_id = MaaNodeId()
|
|
100
237
|
ret = bool(
|
|
101
238
|
Library.framework().MaaTaskerGetLatestNode(
|
|
@@ -110,81 +247,90 @@ class Tasker:
|
|
|
110
247
|
return self.get_node_detail(int(c_node_id.value))
|
|
111
248
|
|
|
112
249
|
def clear_cache(self) -> bool:
|
|
250
|
+
"""清理所有可查询的信息 / Clear all queryable information
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
bool: 是否成功 / Whether successful
|
|
254
|
+
"""
|
|
113
255
|
return bool(Library.framework().MaaTaskerClearCache(self._handle))
|
|
114
256
|
|
|
115
|
-
|
|
116
|
-
def set_log_dir(path: Union[Path, str]) -> bool:
|
|
117
|
-
strpath = str(path)
|
|
118
|
-
return bool(
|
|
119
|
-
Library.framework().MaaSetGlobalOption(
|
|
120
|
-
MaaOption(MaaGlobalOptionEnum.LogDir),
|
|
121
|
-
strpath.encode(),
|
|
122
|
-
len(strpath),
|
|
123
|
-
)
|
|
124
|
-
)
|
|
257
|
+
_sink_holder: Dict[int, "EventSink"] = {}
|
|
125
258
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
cbool = ctypes.c_bool(save_draw)
|
|
129
|
-
return bool(
|
|
130
|
-
Library.framework().MaaSetGlobalOption(
|
|
131
|
-
MaaOption(MaaGlobalOptionEnum.SaveDraw),
|
|
132
|
-
ctypes.pointer(cbool),
|
|
133
|
-
ctypes.sizeof(ctypes.c_bool),
|
|
134
|
-
)
|
|
135
|
-
)
|
|
259
|
+
def add_sink(self, sink: "TaskerEventSink") -> Optional[int]:
|
|
260
|
+
"""添加实例事件监听器 / Add instance event listener
|
|
136
261
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
cbool = ctypes.c_bool(recording)
|
|
140
|
-
return bool(
|
|
141
|
-
Library.framework().MaaSetGlobalOption(
|
|
142
|
-
MaaOption(MaaGlobalOptionEnum.Recording),
|
|
143
|
-
ctypes.pointer(cbool),
|
|
144
|
-
ctypes.sizeof(ctypes.c_bool),
|
|
145
|
-
)
|
|
146
|
-
)
|
|
262
|
+
Args:
|
|
263
|
+
sink: 事件监听器 / Event sink
|
|
147
264
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Library.framework().
|
|
153
|
-
|
|
154
|
-
ctypes.pointer(clevel),
|
|
155
|
-
ctypes.sizeof(MaaLoggingLevel),
|
|
265
|
+
Returns:
|
|
266
|
+
Optional[int]: 监听器 id,失败返回 None / Listener id, or None if failed
|
|
267
|
+
"""
|
|
268
|
+
sink_id = int(
|
|
269
|
+
Library.framework().MaaTaskerAddSink(
|
|
270
|
+
self._handle, *EventSink._gen_c_param(sink)
|
|
156
271
|
)
|
|
157
272
|
)
|
|
273
|
+
if sink_id == MaaInvalidId:
|
|
274
|
+
return None
|
|
158
275
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
cbool = ctypes.c_bool(show_hit_draw)
|
|
162
|
-
return bool(
|
|
163
|
-
Library.framework().MaaSetGlobalOption(
|
|
164
|
-
MaaOption(MaaGlobalOptionEnum.ShowHitDraw),
|
|
165
|
-
ctypes.pointer(cbool),
|
|
166
|
-
ctypes.sizeof(ctypes.c_bool),
|
|
167
|
-
)
|
|
168
|
-
)
|
|
276
|
+
self._sink_holder[sink_id] = sink
|
|
277
|
+
return sink_id
|
|
169
278
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
279
|
+
def remove_sink(self, sink_id: int) -> None:
|
|
280
|
+
"""移除实例事件监听器 / Remove instance event listener
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
sink_id: 监听器 id / Listener id
|
|
284
|
+
"""
|
|
285
|
+
Library.framework().MaaTaskerRemoveSink(self._handle, sink_id)
|
|
286
|
+
self._sink_holder.pop(sink_id)
|
|
287
|
+
|
|
288
|
+
def clear_sinks(self) -> None:
|
|
289
|
+
"""清除所有实例事件监听器 / Clear all instance event listeners"""
|
|
290
|
+
Library.framework().MaaTaskerClearSinks(self._handle)
|
|
291
|
+
|
|
292
|
+
def add_context_sink(self, sink: "ContextEventSink") -> Optional[int]:
|
|
293
|
+
"""添加上下文事件监听器 / Add context event listener
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
sink: 上下文事件监听器 / Context event sink
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
Optional[int]: 监听器 id,失败返回 None / Listener id, or None if failed
|
|
300
|
+
"""
|
|
301
|
+
sink_id = int(
|
|
302
|
+
Library.framework().MaaTaskerAddContextSink(
|
|
303
|
+
self._handle, *EventSink._gen_c_param(sink)
|
|
178
304
|
)
|
|
179
305
|
)
|
|
306
|
+
if sink_id == MaaInvalidId:
|
|
307
|
+
return None
|
|
308
|
+
|
|
309
|
+
self._sink_holder[sink_id] = sink
|
|
310
|
+
return sink_id
|
|
311
|
+
|
|
312
|
+
def remove_context_sink(self, sink_id: int) -> None:
|
|
313
|
+
"""移除上下文事件监听器 / Remove context event listener
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
sink_id: 监听器 id / Listener id
|
|
317
|
+
"""
|
|
318
|
+
Library.framework().MaaTaskerRemoveContextSink(self._handle, sink_id)
|
|
319
|
+
self._sink_holder.pop(sink_id)
|
|
320
|
+
|
|
321
|
+
def clear_context_sinks(self) -> None:
|
|
322
|
+
"""清除所有上下文事件监听器 / Clear all context event listeners"""
|
|
323
|
+
Library.framework().MaaTaskerClearContextSinks(self._handle)
|
|
180
324
|
|
|
181
325
|
### private ###
|
|
182
326
|
|
|
183
327
|
@staticmethod
|
|
184
328
|
def _gen_post_param(entry: str, pipeline_override: Dict) -> Tuple[bytes, bytes]:
|
|
329
|
+
pipeline_json = json.dumps(pipeline_override, ensure_ascii=False)
|
|
330
|
+
|
|
185
331
|
return (
|
|
186
332
|
entry.encode(),
|
|
187
|
-
|
|
333
|
+
pipeline_json.encode(),
|
|
188
334
|
)
|
|
189
335
|
|
|
190
336
|
def _gen_task_job(self, taskid: MaaTaskId) -> JobWithResult:
|
|
@@ -202,8 +348,16 @@ class Tasker:
|
|
|
202
348
|
return Library.framework().MaaTaskerWait(self._handle, id)
|
|
203
349
|
|
|
204
350
|
def get_recognition_detail(self, reco_id: int) -> Optional[RecognitionDetail]:
|
|
351
|
+
"""获取识别信息 / Get recognition info
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
reco_id: 识别号 / Recognition id
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
Optional[RecognitionDetail]: 识别详情,如果不存在则返回 None / Recognition detail, or None if not exists
|
|
358
|
+
"""
|
|
205
359
|
name = StringBuffer()
|
|
206
|
-
algorithm = StringBuffer()
|
|
360
|
+
algorithm = StringBuffer() # type: ignore
|
|
207
361
|
hit = MaaBool()
|
|
208
362
|
box = RectBuffer()
|
|
209
363
|
detail_json = StringBuffer()
|
|
@@ -226,25 +380,89 @@ class Tasker:
|
|
|
226
380
|
return None
|
|
227
381
|
|
|
228
382
|
raw_detail = json.loads(detail_json.get())
|
|
229
|
-
|
|
230
|
-
parsed_detail =
|
|
383
|
+
algorithm_str = algorithm.get()
|
|
384
|
+
parsed_detail = self._parse_recognition_raw_detail(algorithm_str, raw_detail)
|
|
385
|
+
|
|
386
|
+
try:
|
|
387
|
+
algorithm_enum = AlgorithmEnum(algorithm_str)
|
|
388
|
+
except ValueError:
|
|
389
|
+
algorithm_enum = algorithm_str # type: ignore
|
|
231
390
|
|
|
232
391
|
return RecognitionDetail(
|
|
233
392
|
reco_id=reco_id,
|
|
234
393
|
name=name.get(),
|
|
235
|
-
algorithm=
|
|
394
|
+
algorithm=algorithm_enum,
|
|
395
|
+
hit=bool(hit),
|
|
236
396
|
box=bool(hit) and box.get() or None,
|
|
237
397
|
all_results=parsed_detail[0],
|
|
238
|
-
|
|
398
|
+
filtered_results=parsed_detail[1],
|
|
239
399
|
best_result=parsed_detail[2],
|
|
240
400
|
raw_detail=raw_detail,
|
|
241
401
|
raw_image=raw.get(),
|
|
242
402
|
draw_images=draws.get(),
|
|
243
403
|
)
|
|
244
404
|
|
|
405
|
+
def get_action_detail(self, action_id: int) -> Optional[ActionDetail]:
|
|
406
|
+
"""获取操作信息 / Get action info
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
action_id: 操作号 / Action id
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Optional[ActionDetail]: 操作详情,如果不存在则返回 None / Action detail, or None if not exists
|
|
413
|
+
"""
|
|
414
|
+
name = StringBuffer()
|
|
415
|
+
action = StringBuffer()
|
|
416
|
+
box = RectBuffer()
|
|
417
|
+
c_success = MaaBool()
|
|
418
|
+
detail_json = StringBuffer()
|
|
419
|
+
|
|
420
|
+
ret = bool(
|
|
421
|
+
Library.framework().MaaTaskerGetActionDetail(
|
|
422
|
+
self._handle,
|
|
423
|
+
MaaActId(action_id),
|
|
424
|
+
name._handle,
|
|
425
|
+
action._handle,
|
|
426
|
+
box._handle,
|
|
427
|
+
ctypes.pointer(c_success),
|
|
428
|
+
detail_json._handle,
|
|
429
|
+
)
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
if not ret:
|
|
433
|
+
return None
|
|
434
|
+
|
|
435
|
+
raw_detail = json.loads(detail_json.get())
|
|
436
|
+
action_str = action.get()
|
|
437
|
+
parsed_result = Tasker._parse_action_raw_detail(action_str, raw_detail)
|
|
438
|
+
|
|
439
|
+
try:
|
|
440
|
+
action_enum = ActionEnum(action_str)
|
|
441
|
+
except ValueError:
|
|
442
|
+
action_enum = action_str # type: ignore
|
|
443
|
+
|
|
444
|
+
return ActionDetail(
|
|
445
|
+
action_id=action_id,
|
|
446
|
+
name=name.get(),
|
|
447
|
+
action=action_enum,
|
|
448
|
+
box=box.get(),
|
|
449
|
+
success=bool(c_success),
|
|
450
|
+
result=parsed_result,
|
|
451
|
+
raw_detail=raw_detail,
|
|
452
|
+
)
|
|
453
|
+
|
|
245
454
|
def get_node_detail(self, node_id: int) -> Optional[NodeDetail]:
|
|
455
|
+
"""获取节点信息 / Get node info
|
|
456
|
+
|
|
457
|
+
Args:
|
|
458
|
+
node_id: 节点号 / Node id
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
Optional[NodeDetail]: 节点详情,如果不存在则返回 None / Node detail, or None if not exists
|
|
462
|
+
"""
|
|
246
463
|
name = StringBuffer()
|
|
247
464
|
c_reco_id = MaaRecoId()
|
|
465
|
+
c_action_id = MaaActId()
|
|
248
466
|
c_completed = MaaBool()
|
|
249
467
|
|
|
250
468
|
ret = bool(
|
|
@@ -253,6 +471,7 @@ class Tasker:
|
|
|
253
471
|
MaaNodeId(node_id),
|
|
254
472
|
name._handle,
|
|
255
473
|
ctypes.pointer(c_reco_id),
|
|
474
|
+
ctypes.pointer(c_action_id),
|
|
256
475
|
ctypes.pointer(c_completed),
|
|
257
476
|
)
|
|
258
477
|
)
|
|
@@ -260,18 +479,34 @@ class Tasker:
|
|
|
260
479
|
if not ret:
|
|
261
480
|
return None
|
|
262
481
|
|
|
263
|
-
recognition =
|
|
264
|
-
|
|
265
|
-
|
|
482
|
+
recognition = (
|
|
483
|
+
self.get_recognition_detail(int(c_reco_id.value))
|
|
484
|
+
if c_reco_id.value != 0
|
|
485
|
+
else None
|
|
486
|
+
)
|
|
487
|
+
action = (
|
|
488
|
+
self.get_action_detail(int(c_action_id.value))
|
|
489
|
+
if c_action_id.value != 0
|
|
490
|
+
else None
|
|
491
|
+
)
|
|
266
492
|
|
|
267
493
|
return NodeDetail(
|
|
268
494
|
node_id=node_id,
|
|
269
495
|
name=name.get(),
|
|
270
496
|
recognition=recognition,
|
|
497
|
+
action=action,
|
|
271
498
|
completed=bool(c_completed),
|
|
272
499
|
)
|
|
273
500
|
|
|
274
501
|
def get_task_detail(self, task_id: int) -> Optional[TaskDetail]:
|
|
502
|
+
"""获取任务信息 / Get task info
|
|
503
|
+
|
|
504
|
+
Args:
|
|
505
|
+
task_id: 任务号 / Task id
|
|
506
|
+
|
|
507
|
+
Returns:
|
|
508
|
+
Optional[TaskDetail]: 任务详情,如果不存在则返回 None / Task detail, or None if not exists
|
|
509
|
+
"""
|
|
275
510
|
size = MaaSize()
|
|
276
511
|
entry = StringBuffer()
|
|
277
512
|
status = MaaStatus()
|
|
@@ -311,33 +546,239 @@ class Tasker:
|
|
|
311
546
|
task_id=task_id, entry=entry.get(), nodes=nodes, status=Status(status)
|
|
312
547
|
)
|
|
313
548
|
|
|
314
|
-
|
|
549
|
+
@staticmethod
|
|
550
|
+
def set_log_dir(path: Union[Path, str]) -> bool:
|
|
551
|
+
"""设置日志路径 / Set the log path
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
path: 日志路径 / Log path
|
|
555
|
+
|
|
556
|
+
Returns:
|
|
557
|
+
bool: 是否成功 / Whether successful
|
|
558
|
+
"""
|
|
559
|
+
strpath = str(path)
|
|
560
|
+
return bool(
|
|
561
|
+
Library.framework().MaaGlobalSetOption(
|
|
562
|
+
MaaOption(MaaGlobalOptionEnum.LogDir),
|
|
563
|
+
strpath.encode(),
|
|
564
|
+
len(strpath),
|
|
565
|
+
)
|
|
566
|
+
)
|
|
315
567
|
|
|
316
568
|
@staticmethod
|
|
317
|
-
def
|
|
569
|
+
def set_save_draw(save_draw: bool) -> bool:
|
|
570
|
+
"""设置是否将识别保存到日志路径/vision中 / Set whether to save recognition results to log path/vision
|
|
571
|
+
|
|
572
|
+
开启后 RecoDetail 将可以获取到 draws / When enabled, RecoDetail can retrieve draws
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
save_draw: 是否保存 / Whether to save
|
|
576
|
+
|
|
577
|
+
Returns:
|
|
578
|
+
bool: 是否成功 / Whether successful
|
|
579
|
+
"""
|
|
580
|
+
cbool = ctypes.c_bool(save_draw)
|
|
581
|
+
return bool(
|
|
582
|
+
Library.framework().MaaGlobalSetOption(
|
|
583
|
+
MaaOption(MaaGlobalOptionEnum.SaveDraw),
|
|
584
|
+
ctypes.pointer(cbool),
|
|
585
|
+
ctypes.sizeof(ctypes.c_bool),
|
|
586
|
+
)
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
@staticmethod
|
|
590
|
+
def set_recording(recording: bool) -> bool:
|
|
591
|
+
"""
|
|
592
|
+
Deprecated
|
|
593
|
+
"""
|
|
594
|
+
return False
|
|
595
|
+
|
|
596
|
+
@staticmethod
|
|
597
|
+
def set_stdout_level(level: LoggingLevelEnum) -> bool:
|
|
598
|
+
"""设置日志输出到 stdout 中的级别 / Set the log output level to stdout
|
|
599
|
+
|
|
600
|
+
Args:
|
|
601
|
+
level: 日志级别 / Logging level
|
|
602
|
+
|
|
603
|
+
Returns:
|
|
604
|
+
bool: 是否成功 / Whether successful
|
|
605
|
+
"""
|
|
606
|
+
clevel = MaaLoggingLevel(level)
|
|
607
|
+
return bool(
|
|
608
|
+
Library.framework().MaaGlobalSetOption(
|
|
609
|
+
MaaOption(MaaGlobalOptionEnum.StdoutLevel),
|
|
610
|
+
ctypes.pointer(clevel),
|
|
611
|
+
ctypes.sizeof(MaaLoggingLevel),
|
|
612
|
+
)
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
@staticmethod
|
|
616
|
+
def set_debug_mode(debug_mode: bool) -> bool:
|
|
617
|
+
"""设置是否启用调试模式 / Set whether to enable debug mode
|
|
618
|
+
|
|
619
|
+
调试模式下, RecoDetail 将可以获取到 raw/draws; 所有任务都会被视为 focus 而产生回调
|
|
620
|
+
In debug mode, RecoDetail can retrieve raw/draws; all tasks are treated as focus and produce callbacks
|
|
621
|
+
|
|
622
|
+
Args:
|
|
623
|
+
debug_mode: 是否启用调试模式 / Whether to enable debug mode
|
|
624
|
+
|
|
625
|
+
Returns:
|
|
626
|
+
bool: 是否成功 / Whether successful
|
|
627
|
+
"""
|
|
628
|
+
cbool = ctypes.c_bool(debug_mode)
|
|
629
|
+
return bool(
|
|
630
|
+
Library.framework().MaaGlobalSetOption(
|
|
631
|
+
MaaOption(MaaGlobalOptionEnum.DebugMode),
|
|
632
|
+
ctypes.pointer(cbool),
|
|
633
|
+
ctypes.sizeof(ctypes.c_bool),
|
|
634
|
+
)
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
@staticmethod
|
|
638
|
+
def set_save_on_error(save_on_error: bool) -> bool:
|
|
639
|
+
"""设置是否在错误时保存截图到日志路径/on_error中 / Set whether to save screenshot on error to log path/on_error
|
|
640
|
+
|
|
641
|
+
Args:
|
|
642
|
+
save_on_error: 是否保存 / Whether to save
|
|
643
|
+
|
|
644
|
+
Returns:
|
|
645
|
+
bool: 是否成功 / Whether successful
|
|
646
|
+
"""
|
|
647
|
+
cbool = ctypes.c_bool(save_on_error)
|
|
648
|
+
return bool(
|
|
649
|
+
Library.framework().MaaGlobalSetOption(
|
|
650
|
+
MaaOption(MaaGlobalOptionEnum.SaveOnError),
|
|
651
|
+
ctypes.pointer(cbool),
|
|
652
|
+
ctypes.sizeof(ctypes.c_bool),
|
|
653
|
+
)
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
@staticmethod
|
|
657
|
+
def set_draw_quality(quality: int) -> bool:
|
|
658
|
+
"""设置识别可视化图像的 JPEG 质量 / Set the JPEG quality for recognition visualization images
|
|
659
|
+
|
|
660
|
+
Args:
|
|
661
|
+
quality: JPEG 质量(0-100),默认 85 / JPEG quality (0-100), default 85
|
|
662
|
+
|
|
663
|
+
Returns:
|
|
664
|
+
bool: 是否成功 / Whether successful
|
|
665
|
+
"""
|
|
666
|
+
cquality = ctypes.c_int(quality)
|
|
667
|
+
return bool(
|
|
668
|
+
Library.framework().MaaGlobalSetOption(
|
|
669
|
+
MaaOption(MaaGlobalOptionEnum.DrawQuality),
|
|
670
|
+
ctypes.pointer(cquality),
|
|
671
|
+
ctypes.sizeof(ctypes.c_int),
|
|
672
|
+
)
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
@staticmethod
|
|
676
|
+
def set_reco_image_cache_limit(limit: int) -> bool:
|
|
677
|
+
"""设置识别图像缓存数量限制 / Set the recognition image cache limit
|
|
678
|
+
|
|
679
|
+
Args:
|
|
680
|
+
limit: 缓存数量限制,默认 4096 / Cache limit, default 4096
|
|
681
|
+
|
|
682
|
+
Returns:
|
|
683
|
+
bool: 是否成功 / Whether successful
|
|
684
|
+
"""
|
|
685
|
+
climit = ctypes.c_size_t(limit)
|
|
686
|
+
return bool(
|
|
687
|
+
Library.framework().MaaGlobalSetOption(
|
|
688
|
+
MaaOption(MaaGlobalOptionEnum.RecoImageCacheLimit),
|
|
689
|
+
ctypes.pointer(climit),
|
|
690
|
+
ctypes.sizeof(ctypes.c_size_t),
|
|
691
|
+
)
|
|
692
|
+
)
|
|
693
|
+
|
|
694
|
+
@staticmethod
|
|
695
|
+
def load_plugin(path: Union[Path, str]) -> bool:
|
|
696
|
+
"""加载插件 / Load plugin
|
|
697
|
+
|
|
698
|
+
可以使用完整路径或仅使用名称, 仅使用名称时会在系统目录和当前目录中搜索. 也可以递归搜索目录中的插件
|
|
699
|
+
Can use full path or name only. When using name only, will search in system directory and current directory. Can also recursively search for plugins in a directory
|
|
700
|
+
|
|
701
|
+
Args:
|
|
702
|
+
path: 插件库路径或名称 / Plugin library path or name
|
|
703
|
+
|
|
704
|
+
Returns:
|
|
705
|
+
bool: 是否成功 / Whether successful
|
|
706
|
+
"""
|
|
707
|
+
strpath = str(path)
|
|
708
|
+
return bool(
|
|
709
|
+
Library.framework().MaaGlobalLoadPlugin(
|
|
710
|
+
strpath.encode(),
|
|
711
|
+
)
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
_api_properties_initialized: bool = False
|
|
715
|
+
|
|
716
|
+
def _parse_recognition_raw_detail(self, algorithm: str, raw_detail):
|
|
318
717
|
if not raw_detail:
|
|
319
718
|
return [], [], None
|
|
320
719
|
|
|
321
|
-
|
|
720
|
+
try:
|
|
721
|
+
algorithm_enum = AlgorithmEnum(algorithm)
|
|
722
|
+
except ValueError:
|
|
723
|
+
return [], [], None
|
|
724
|
+
|
|
725
|
+
ResultType = AlgorithmResultDict.get(algorithm_enum)
|
|
322
726
|
if not ResultType:
|
|
323
727
|
return [], [], None
|
|
324
728
|
|
|
729
|
+
# And/Or 的 detail 是子识别结果数组,递归获取完整的 RecognitionDetail
|
|
730
|
+
if algorithm_enum in (AlgorithmEnum.And, AlgorithmEnum.Or):
|
|
731
|
+
sub_results = []
|
|
732
|
+
for sub in raw_detail:
|
|
733
|
+
reco_id = sub.get("reco_id")
|
|
734
|
+
if not reco_id:
|
|
735
|
+
continue
|
|
736
|
+
sub_detail = self.get_recognition_detail(reco_id)
|
|
737
|
+
if sub_detail:
|
|
738
|
+
sub_results.append(sub_detail)
|
|
739
|
+
result = ResultType(sub_results=sub_results)
|
|
740
|
+
return [result], [result], result
|
|
741
|
+
|
|
325
742
|
all_results: List[RecognitionResult] = []
|
|
326
|
-
|
|
743
|
+
filtered_results: List[RecognitionResult] = []
|
|
327
744
|
best_result: Optional[RecognitionResult] = None
|
|
328
745
|
|
|
329
746
|
raw_all_results = raw_detail.get("all", [])
|
|
330
|
-
|
|
747
|
+
raw_filtered_results = raw_detail.get("filtered", [])
|
|
331
748
|
raw_best_result = raw_detail.get("best", None)
|
|
332
749
|
|
|
333
750
|
for raw_result in raw_all_results:
|
|
334
751
|
all_results.append(ResultType(**raw_result))
|
|
335
|
-
for raw_result in
|
|
336
|
-
|
|
752
|
+
for raw_result in raw_filtered_results:
|
|
753
|
+
filtered_results.append(ResultType(**raw_result))
|
|
337
754
|
if raw_best_result:
|
|
338
755
|
best_result = ResultType(**raw_best_result)
|
|
339
756
|
|
|
340
|
-
return all_results,
|
|
757
|
+
return all_results, filtered_results, best_result
|
|
758
|
+
|
|
759
|
+
@staticmethod
|
|
760
|
+
def _parse_action_raw_detail(
|
|
761
|
+
action: str, raw_detail: Dict
|
|
762
|
+
) -> Optional[ActionResult]:
|
|
763
|
+
if not raw_detail:
|
|
764
|
+
return None
|
|
765
|
+
|
|
766
|
+
try:
|
|
767
|
+
action_enum = ActionEnum(action)
|
|
768
|
+
except ValueError:
|
|
769
|
+
return None
|
|
770
|
+
|
|
771
|
+
ResultType = ActionResultDict.get(action_enum)
|
|
772
|
+
if not ResultType:
|
|
773
|
+
return None
|
|
774
|
+
|
|
775
|
+
try:
|
|
776
|
+
# cv::Point 在 JSON 中是数组 [x, y],不需要转换
|
|
777
|
+
# 直接使用 raw_detail 创建结果对象
|
|
778
|
+
return ResultType(**raw_detail)
|
|
779
|
+
except (TypeError, KeyError):
|
|
780
|
+
# 如果解析失败,返回 None
|
|
781
|
+
return None
|
|
341
782
|
|
|
342
783
|
@staticmethod
|
|
343
784
|
def _set_api_properties():
|
|
@@ -345,12 +786,21 @@ class Tasker:
|
|
|
345
786
|
return
|
|
346
787
|
Tasker._api_properties_initialized = True
|
|
347
788
|
|
|
348
|
-
Library.framework().
|
|
349
|
-
Library.framework().
|
|
350
|
-
|
|
351
|
-
|
|
789
|
+
Library.framework().MaaGlobalSetOption.restype = MaaBool
|
|
790
|
+
Library.framework().MaaGlobalSetOption.argtypes = [
|
|
791
|
+
MaaGlobalOption,
|
|
792
|
+
MaaOptionValue,
|
|
793
|
+
MaaOptionValueSize,
|
|
794
|
+
]
|
|
795
|
+
|
|
796
|
+
Library.framework().MaaGlobalLoadPlugin.restype = MaaBool
|
|
797
|
+
Library.framework().MaaGlobalLoadPlugin.argtypes = [
|
|
798
|
+
ctypes.c_char_p,
|
|
352
799
|
]
|
|
353
800
|
|
|
801
|
+
Library.framework().MaaTaskerCreate.restype = MaaTaskerHandle
|
|
802
|
+
Library.framework().MaaTaskerCreate.argtypes = []
|
|
803
|
+
|
|
354
804
|
Library.framework().MaaTaskerDestroy.restype = None
|
|
355
805
|
Library.framework().MaaTaskerDestroy.argtypes = [MaaTaskerHandle]
|
|
356
806
|
|
|
@@ -376,6 +826,23 @@ class Tasker:
|
|
|
376
826
|
ctypes.c_char_p,
|
|
377
827
|
]
|
|
378
828
|
|
|
829
|
+
Library.framework().MaaTaskerPostRecognition.restype = MaaId
|
|
830
|
+
Library.framework().MaaTaskerPostRecognition.argtypes = [
|
|
831
|
+
MaaTaskerHandle,
|
|
832
|
+
ctypes.c_char_p,
|
|
833
|
+
ctypes.c_char_p,
|
|
834
|
+
MaaImageBufferHandle,
|
|
835
|
+
]
|
|
836
|
+
|
|
837
|
+
Library.framework().MaaTaskerPostAction.restype = MaaId
|
|
838
|
+
Library.framework().MaaTaskerPostAction.argtypes = [
|
|
839
|
+
MaaTaskerHandle,
|
|
840
|
+
ctypes.c_char_p,
|
|
841
|
+
ctypes.c_char_p,
|
|
842
|
+
MaaRectHandle,
|
|
843
|
+
ctypes.c_char_p,
|
|
844
|
+
]
|
|
845
|
+
|
|
379
846
|
Library.framework().MaaTaskerStatus.restype = MaaStatus
|
|
380
847
|
Library.framework().MaaTaskerStatus.argtypes = [
|
|
381
848
|
MaaTaskerHandle,
|
|
@@ -416,12 +883,24 @@ class Tasker:
|
|
|
416
883
|
MaaImageListBufferHandle,
|
|
417
884
|
]
|
|
418
885
|
|
|
886
|
+
Library.framework().MaaTaskerGetActionDetail.restype = MaaBool
|
|
887
|
+
Library.framework().MaaTaskerGetActionDetail.argtypes = [
|
|
888
|
+
MaaTaskerHandle,
|
|
889
|
+
MaaActId,
|
|
890
|
+
MaaStringBufferHandle,
|
|
891
|
+
MaaStringBufferHandle,
|
|
892
|
+
MaaRectHandle,
|
|
893
|
+
ctypes.POINTER(MaaBool),
|
|
894
|
+
MaaStringBufferHandle,
|
|
895
|
+
]
|
|
896
|
+
|
|
419
897
|
Library.framework().MaaTaskerGetNodeDetail.restype = MaaBool
|
|
420
898
|
Library.framework().MaaTaskerGetNodeDetail.argtypes = [
|
|
421
899
|
MaaTaskerHandle,
|
|
422
900
|
MaaNodeId,
|
|
423
901
|
MaaStringBufferHandle,
|
|
424
902
|
ctypes.POINTER(MaaRecoId),
|
|
903
|
+
ctypes.POINTER(MaaActId),
|
|
425
904
|
ctypes.POINTER(MaaBool),
|
|
426
905
|
]
|
|
427
906
|
|
|
@@ -447,9 +926,70 @@ class Tasker:
|
|
|
447
926
|
MaaTaskerHandle,
|
|
448
927
|
]
|
|
449
928
|
|
|
450
|
-
Library.framework().
|
|
451
|
-
Library.framework().
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
929
|
+
Library.framework().MaaTaskerAddSink.restype = MaaSinkId
|
|
930
|
+
Library.framework().MaaTaskerAddSink.argtypes = [
|
|
931
|
+
MaaTaskerHandle,
|
|
932
|
+
MaaEventCallback,
|
|
933
|
+
ctypes.c_void_p,
|
|
934
|
+
]
|
|
935
|
+
|
|
936
|
+
Library.framework().MaaTaskerRemoveSink.restype = None
|
|
937
|
+
Library.framework().MaaTaskerRemoveSink.argtypes = [
|
|
938
|
+
MaaTaskerHandle,
|
|
939
|
+
MaaSinkId,
|
|
455
940
|
]
|
|
941
|
+
|
|
942
|
+
Library.framework().MaaTaskerClearSinks.restype = None
|
|
943
|
+
Library.framework().MaaTaskerClearSinks.argtypes = [MaaTaskerHandle]
|
|
944
|
+
|
|
945
|
+
Library.framework().MaaTaskerAddContextSink.restype = MaaSinkId
|
|
946
|
+
Library.framework().MaaTaskerAddContextSink.argtypes = [
|
|
947
|
+
MaaTaskerHandle,
|
|
948
|
+
MaaEventCallback,
|
|
949
|
+
ctypes.c_void_p,
|
|
950
|
+
]
|
|
951
|
+
|
|
952
|
+
Library.framework().MaaTaskerRemoveContextSink.restype = None
|
|
953
|
+
Library.framework().MaaTaskerRemoveContextSink.argtypes = [
|
|
954
|
+
MaaTaskerHandle,
|
|
955
|
+
MaaSinkId,
|
|
956
|
+
]
|
|
957
|
+
|
|
958
|
+
Library.framework().MaaTaskerClearContextSinks.restype = None
|
|
959
|
+
Library.framework().MaaTaskerClearContextSinks.argtypes = [MaaTaskerHandle]
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
class TaskerEventSink(EventSink):
|
|
963
|
+
|
|
964
|
+
@dataclass
|
|
965
|
+
class TaskerTaskDetail:
|
|
966
|
+
task_id: int
|
|
967
|
+
entry: str
|
|
968
|
+
uuid: str
|
|
969
|
+
hash: str
|
|
970
|
+
|
|
971
|
+
def on_tasker_task(
|
|
972
|
+
self, tasker: Tasker, noti_type: NotificationType, detail: TaskerTaskDetail
|
|
973
|
+
):
|
|
974
|
+
pass
|
|
975
|
+
|
|
976
|
+
def on_raw_notification(self, tasker: Tasker, msg: str, details: dict):
|
|
977
|
+
pass
|
|
978
|
+
|
|
979
|
+
def _on_raw_notification(self, handle: ctypes.c_void_p, msg: str, details: dict):
|
|
980
|
+
|
|
981
|
+
tasker = Tasker(handle=handle)
|
|
982
|
+
self.on_raw_notification(tasker, msg, details)
|
|
983
|
+
|
|
984
|
+
noti_type = EventSink._notification_type(msg)
|
|
985
|
+
if msg.startswith("Tasker.Task"):
|
|
986
|
+
detail = self.TaskerTaskDetail(
|
|
987
|
+
task_id=details["task_id"],
|
|
988
|
+
entry=details["entry"],
|
|
989
|
+
uuid=details["uuid"],
|
|
990
|
+
hash=details["hash"],
|
|
991
|
+
)
|
|
992
|
+
self.on_tasker_task(tasker, noti_type, detail)
|
|
993
|
+
|
|
994
|
+
else:
|
|
995
|
+
self.on_unknown_notification(tasker, msg, details)
|