MaaFw 4.4.0a3__py3-none-macosx_13_0_x86_64.whl → 5.0.0b2__py3-none-macosx_13_0_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 +108 -3
- maa/agent_client.py +49 -1
- maa/bin/libMaaAdbControlUnit.dylib +0 -0
- maa/bin/libMaaAgentClient.dylib +0 -0
- maa/bin/libMaaAgentServer.dylib +0 -0
- maa/bin/libMaaCustomControlUnit.dylib +0 -0
- maa/bin/libMaaFramework.dylib +0 -0
- maa/bin/libMaaToolkit.dylib +0 -0
- maa/bin/libMaaUtils.dylib +0 -0
- maa/bin/libfastdeploy_ppocr.dylib +0 -0
- maa/bin/libonnxruntime.1.19.2.dylib +0 -0
- maa/bin/{libopencv_world4.4.8.0.dylib → libopencv_world4.4.11.0.dylib} +0 -0
- maa/bin/plugins/libMaaPluginDemo.dylib +0 -0
- maa/context.py +217 -5
- maa/controller.py +422 -34
- maa/custom_action.py +3 -0
- maa/custom_recognition.py +4 -4
- maa/define.py +189 -10
- maa/event_sink.py +74 -0
- maa/pipeline.py +406 -0
- maa/resource.py +290 -21
- maa/tasker.py +446 -77
- maa/toolkit.py +22 -91
- {maafw-4.4.0a3.dist-info → maafw-5.0.0b2.dist-info}/METADATA +39 -23
- maafw-5.0.0b2.dist-info/RECORD +32 -0
- maa/bin/libMaaDbgControlUnit.dylib +0 -0
- maa/notification_handler.py +0 -197
- maafw-4.4.0a3.dist-info/RECORD +0 -30
- {maafw-4.4.0a3.dist-info → maafw-5.0.0b2.dist-info}/WHEEL +0 -0
- {maafw-4.4.0a3.dist-info → maafw-5.0.0b2.dist-info}/licenses/LICENSE.md +0 -0
maa/agent/agent_server.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import ctypes
|
|
2
|
-
import sys
|
|
3
2
|
|
|
4
3
|
from ..define import *
|
|
5
4
|
from ..library import Library
|
|
6
|
-
from ..
|
|
5
|
+
from ..event_sink import EventSink
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class AgentServer:
|
|
@@ -88,12 +87,94 @@ class AgentServer:
|
|
|
88
87
|
Library.agent_server().MaaAgentServerJoin()
|
|
89
88
|
|
|
90
89
|
@staticmethod
|
|
91
|
-
def detach(
|
|
90
|
+
def detach() -> None:
|
|
92
91
|
|
|
93
92
|
AgentServer._set_api_properties()
|
|
94
93
|
|
|
95
94
|
Library.agent_server().MaaAgentServerDetach()
|
|
96
95
|
|
|
96
|
+
_sink_holder: Dict[int, "EventSink"] = {}
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def resource_sink():
|
|
100
|
+
def wrapper_sink(sink):
|
|
101
|
+
AgentServer.add_resource_sink(sink=sink())
|
|
102
|
+
return sink
|
|
103
|
+
|
|
104
|
+
return wrapper_sink
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def add_resource_sink(sink: "ResourceEventSink") -> None:
|
|
108
|
+
sink_id = int(
|
|
109
|
+
Library.agent_server().MaaAgentServerAddResourceSink(
|
|
110
|
+
*EventSink._gen_c_param(sink)
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
if sink_id == MaaInvalidId:
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
AgentServer._sink_holder[sink_id] = sink
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def controller_sink():
|
|
120
|
+
def wrapper_sink(sink):
|
|
121
|
+
AgentServer.add_controller_sink(sink=sink())
|
|
122
|
+
return sink
|
|
123
|
+
|
|
124
|
+
return wrapper_sink
|
|
125
|
+
|
|
126
|
+
@staticmethod
|
|
127
|
+
def add_controller_sink(sink: "ControllerEventSink") -> None:
|
|
128
|
+
sink_id = int(
|
|
129
|
+
Library.agent_server().MaaAgentServerAddControllerSink(
|
|
130
|
+
*EventSink._gen_c_param(sink)
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
if sink_id == MaaInvalidId:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
AgentServer._sink_holder[sink_id] = sink
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def tasker_sink():
|
|
140
|
+
def wrapper_sink(sink):
|
|
141
|
+
AgentServer.add_tasker_sink(sink=sink())
|
|
142
|
+
return sink
|
|
143
|
+
|
|
144
|
+
return wrapper_sink
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def add_tasker_sink(sink: "TaskerEventSink") -> None:
|
|
148
|
+
sink_id = int(
|
|
149
|
+
Library.agent_server().MaaAgentServerAddTaskerSink(
|
|
150
|
+
*EventSink._gen_c_param(sink)
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
if sink_id == MaaInvalidId:
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
AgentServer._sink_holder[sink_id] = sink
|
|
157
|
+
|
|
158
|
+
@staticmethod
|
|
159
|
+
def context_sink():
|
|
160
|
+
def wrapper_sink(sink):
|
|
161
|
+
AgentServer.add_context_sink(sink=sink())
|
|
162
|
+
return sink
|
|
163
|
+
|
|
164
|
+
return wrapper_sink
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
def add_context_sink(sink: "ContextEventSink") -> None:
|
|
168
|
+
sink_id = int(
|
|
169
|
+
Library.agent_server().MaaAgentServerAddContextSink(
|
|
170
|
+
*EventSink._gen_c_param(sink)
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
if sink_id == MaaInvalidId:
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
AgentServer._sink_holder[sink_id] = sink
|
|
177
|
+
|
|
97
178
|
_api_properties_initialized: bool = False
|
|
98
179
|
|
|
99
180
|
@staticmethod
|
|
@@ -130,3 +211,27 @@ class AgentServer:
|
|
|
130
211
|
|
|
131
212
|
Library.agent_server().MaaAgentServerDetach.restype = None
|
|
132
213
|
Library.agent_server().MaaAgentServerDetach.argtypes = []
|
|
214
|
+
|
|
215
|
+
Library.agent_server().MaaAgentServerAddResourceSink.restype = MaaSinkId
|
|
216
|
+
Library.agent_server().MaaAgentServerAddResourceSink.argtypes = [
|
|
217
|
+
MaaEventCallback,
|
|
218
|
+
ctypes.c_void_p,
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
Library.agent_server().MaaAgentServerAddControllerSink.restype = MaaSinkId
|
|
222
|
+
Library.agent_server().MaaAgentServerAddControllerSink.argtypes = [
|
|
223
|
+
MaaEventCallback,
|
|
224
|
+
ctypes.c_void_p,
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
Library.agent_server().MaaAgentServerAddTaskerSink.restype = MaaSinkId
|
|
228
|
+
Library.agent_server().MaaAgentServerAddTaskerSink.argtypes = [
|
|
229
|
+
MaaEventCallback,
|
|
230
|
+
ctypes.c_void_p,
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
Library.agent_server().MaaAgentServerAddContextSink.restype = MaaSinkId
|
|
234
|
+
Library.agent_server().MaaAgentServerAddContextSink.argtypes = [
|
|
235
|
+
MaaEventCallback,
|
|
236
|
+
ctypes.c_void_p,
|
|
237
|
+
]
|
maa/agent_client.py
CHANGED
|
@@ -3,6 +3,8 @@ import ctypes
|
|
|
3
3
|
from .define import *
|
|
4
4
|
from .library import Library
|
|
5
5
|
from .resource import Resource
|
|
6
|
+
from .controller import Controller
|
|
7
|
+
from .tasker import Tasker
|
|
6
8
|
from .buffer import StringBuffer
|
|
7
9
|
|
|
8
10
|
|
|
@@ -47,6 +49,30 @@ class AgentClient:
|
|
|
47
49
|
)
|
|
48
50
|
)
|
|
49
51
|
|
|
52
|
+
def register_sink(
|
|
53
|
+
self, resource: Resource, controller: Controller, tasker: Tasker
|
|
54
|
+
) -> bool:
|
|
55
|
+
# avoid gc
|
|
56
|
+
self._sinks = [resource, controller, tasker]
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
bool(
|
|
60
|
+
Library.agent_client().MaaAgentClientRegisterResourceSink(
|
|
61
|
+
self._handle, resource._handle
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
and bool(
|
|
65
|
+
Library.agent_client().MaaAgentClientRegisterControllerSink(
|
|
66
|
+
self._handle, controller._handle
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
and bool(
|
|
70
|
+
Library.agent_client().MaaAgentClientRegisterTaskerSink(
|
|
71
|
+
self._handle, tasker._handle
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
50
76
|
def connect(self) -> bool:
|
|
51
77
|
return bool(Library.agent_client().MaaAgentClientConnect(self._handle))
|
|
52
78
|
|
|
@@ -62,7 +88,11 @@ class AgentClient:
|
|
|
62
88
|
return bool(Library.agent_client().MaaAgentClientAlive(self._handle))
|
|
63
89
|
|
|
64
90
|
def set_timeout(self, milliseconds: int) -> bool:
|
|
65
|
-
return bool(
|
|
91
|
+
return bool(
|
|
92
|
+
Library.agent_client().MaaAgentClientSetTimeout(
|
|
93
|
+
self._handle, ctypes.c_int64(milliseconds)
|
|
94
|
+
)
|
|
95
|
+
)
|
|
66
96
|
|
|
67
97
|
_api_properties_initialized: bool = False
|
|
68
98
|
|
|
@@ -96,6 +126,24 @@ class AgentClient:
|
|
|
96
126
|
MaaResourceHandle,
|
|
97
127
|
]
|
|
98
128
|
|
|
129
|
+
Library.agent_client().MaaAgentClientRegisterResourceSink.restype = MaaBool
|
|
130
|
+
Library.agent_client().MaaAgentClientRegisterResourceSink.argtypes = [
|
|
131
|
+
MaaAgentClientHandle,
|
|
132
|
+
MaaResourceHandle,
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
Library.agent_client().MaaAgentClientRegisterControllerSink.restype = MaaBool
|
|
136
|
+
Library.agent_client().MaaAgentClientRegisterControllerSink.argtypes = [
|
|
137
|
+
MaaAgentClientHandle,
|
|
138
|
+
MaaControllerHandle,
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
Library.agent_client().MaaAgentClientRegisterTaskerSink.restype = MaaBool
|
|
142
|
+
Library.agent_client().MaaAgentClientRegisterTaskerSink.argtypes = [
|
|
143
|
+
MaaAgentClientHandle,
|
|
144
|
+
MaaTaskerHandle,
|
|
145
|
+
]
|
|
146
|
+
|
|
99
147
|
Library.agent_client().MaaAgentClientConnect.restype = MaaBool
|
|
100
148
|
Library.agent_client().MaaAgentClientConnect.argtypes = [
|
|
101
149
|
MaaAgentClientHandle,
|
|
Binary file
|
maa/bin/libMaaAgentClient.dylib
CHANGED
|
Binary file
|
maa/bin/libMaaAgentServer.dylib
CHANGED
|
Binary file
|
|
Binary file
|
maa/bin/libMaaFramework.dylib
CHANGED
|
Binary file
|
maa/bin/libMaaToolkit.dylib
CHANGED
|
Binary file
|
maa/bin/libMaaUtils.dylib
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
maa/context.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import ctypes
|
|
2
2
|
import json
|
|
3
|
-
from typing import Dict, Optional, Tuple
|
|
3
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
|
4
4
|
|
|
5
5
|
import numpy
|
|
6
6
|
|
|
7
|
+
from .event_sink import EventSink, NotificationType
|
|
7
8
|
from .buffer import ImageBuffer, RectBuffer, StringBuffer, StringListBuffer
|
|
8
9
|
from .define import *
|
|
9
10
|
from .library import Library
|
|
10
11
|
from .tasker import Tasker
|
|
12
|
+
from .pipeline import JPipelineData, JPipelineParser
|
|
11
13
|
from .job import JobWithResult
|
|
12
14
|
|
|
13
15
|
|
|
@@ -32,6 +34,15 @@ class Context:
|
|
|
32
34
|
def run_task(
|
|
33
35
|
self, entry: str, pipeline_override: Dict = {}
|
|
34
36
|
) -> Optional[TaskDetail]:
|
|
37
|
+
"""同步执行任务 / Synchronously execute task
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
entry: 任务入口 / Task entry
|
|
41
|
+
pipeline_override: 用于覆盖的 json / JSON for overriding
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Optional[TaskDetail]: 任务详情,执行失败则返回 None / Task detail, or None if execution failed
|
|
45
|
+
"""
|
|
35
46
|
task_id = int(
|
|
36
47
|
Library.framework().MaaContextRunTask(
|
|
37
48
|
self._handle, *Context._gen_post_param(entry, pipeline_override)
|
|
@@ -43,8 +54,24 @@ class Context:
|
|
|
43
54
|
return self.tasker.get_task_detail(task_id)
|
|
44
55
|
|
|
45
56
|
def run_recognition(
|
|
46
|
-
self,
|
|
57
|
+
self,
|
|
58
|
+
entry: str,
|
|
59
|
+
image: numpy.ndarray,
|
|
60
|
+
pipeline_override: Dict = {},
|
|
47
61
|
) -> Optional[RecognitionDetail]:
|
|
62
|
+
"""同步执行识别逻辑 / Synchronously execute recognition logic
|
|
63
|
+
|
|
64
|
+
不会执行后续操作, 不会执行后续 next
|
|
65
|
+
Will not execute subsequent operations or next steps
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
entry: 任务名 / Task name
|
|
69
|
+
image: 前序截图 / Previous screenshot
|
|
70
|
+
pipeline_override: 用于覆盖的 json / JSON for overriding
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Optional[RecognitionDetail]: 识别详情,执行失败则返回 None / Recognition detail, or None if execution failed
|
|
74
|
+
"""
|
|
48
75
|
image_buffer = ImageBuffer()
|
|
49
76
|
image_buffer.set(image)
|
|
50
77
|
reco_id = int(
|
|
@@ -66,6 +93,20 @@ class Context:
|
|
|
66
93
|
reco_detail: str = "",
|
|
67
94
|
pipeline_override: Dict = {},
|
|
68
95
|
) -> Optional[NodeDetail]:
|
|
96
|
+
"""同步执行操作逻辑 / Synchronously execute action logic
|
|
97
|
+
|
|
98
|
+
不会执行后续 next
|
|
99
|
+
Will not execute subsequent next steps
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
entry: 任务名 / Task name
|
|
103
|
+
box: 前序识别位置 / Previous recognition position
|
|
104
|
+
reco_detail: 前序识别详情 / Previous recognition details
|
|
105
|
+
pipeline_override: 用于覆盖的 json / JSON for overriding
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Optional[NodeDetail]: 节点详情,执行失败则返回 None / Node detail, or None if execution failed
|
|
109
|
+
"""
|
|
69
110
|
rect = RectBuffer()
|
|
70
111
|
rect.set(box)
|
|
71
112
|
|
|
@@ -84,14 +125,36 @@ class Context:
|
|
|
84
125
|
return self.tasker.get_node_detail(node_id)
|
|
85
126
|
|
|
86
127
|
def override_pipeline(self, pipeline_override: Dict) -> bool:
|
|
128
|
+
"""覆盖 pipeline / Override pipeline_override
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
pipeline_override: 用于覆盖的 json / JSON for overriding
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
bool: 是否成功 / Whether successful
|
|
135
|
+
"""
|
|
136
|
+
pipeline_json = json.dumps(pipeline_override, ensure_ascii=False)
|
|
137
|
+
|
|
87
138
|
return bool(
|
|
88
139
|
Library.framework().MaaContextOverridePipeline(
|
|
89
140
|
self._handle,
|
|
90
|
-
|
|
141
|
+
pipeline_json.encode(),
|
|
91
142
|
)
|
|
92
143
|
)
|
|
93
144
|
|
|
94
145
|
def override_next(self, name: str, next_list: List[str]) -> bool:
|
|
146
|
+
"""覆盖任务的 next 列表 / Override the next list of task
|
|
147
|
+
|
|
148
|
+
如果节点不存在,此方法会失败
|
|
149
|
+
This method will fail if the node does not exist
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
name: 任务名 / Task name
|
|
153
|
+
next_list: next 列表 / Next list
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
bool: 成功返回 True,如果节点不存在则返回 False / Returns True on success, False if node does not exist
|
|
157
|
+
"""
|
|
95
158
|
list_buffer = StringListBuffer()
|
|
96
159
|
list_buffer.set(next_list)
|
|
97
160
|
|
|
@@ -101,7 +164,34 @@ class Context:
|
|
|
101
164
|
)
|
|
102
165
|
)
|
|
103
166
|
|
|
104
|
-
def
|
|
167
|
+
def override_image(self, image_name: str, image: numpy.ndarray) -> bool:
|
|
168
|
+
"""覆盖图片 / Override the image corresponding to image_name
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
image_name: 图片名 / Image name
|
|
172
|
+
image: 图片数据 / Image data
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
bool: 是否成功 / Whether successful
|
|
176
|
+
"""
|
|
177
|
+
image_buffer = ImageBuffer()
|
|
178
|
+
image_buffer.set(image)
|
|
179
|
+
|
|
180
|
+
return bool(
|
|
181
|
+
Library.framework().MaaContextOverrideImage(
|
|
182
|
+
self._handle, image_name.encode(), image_buffer._handle
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
def get_node_data(self, name: str) -> Optional[Dict]:
|
|
187
|
+
"""获取任务当前的定义 / Get the current definition of task
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
name: 任务名 / Task name
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Optional[Dict]: 任务定义字典,如果不存在则返回 None / Task definition dict, or None if not exists
|
|
194
|
+
"""
|
|
105
195
|
string_buffer = StringBuffer()
|
|
106
196
|
if not Library.framework().MaaContextGetNodeData(
|
|
107
197
|
self._handle, name.encode(), string_buffer._handle
|
|
@@ -117,11 +207,32 @@ class Context:
|
|
|
117
207
|
except json.JSONDecodeError:
|
|
118
208
|
return None
|
|
119
209
|
|
|
210
|
+
def get_node_object(self, name: str) -> Optional[JPipelineData]:
|
|
211
|
+
node_data = self.get_node_data(name)
|
|
212
|
+
|
|
213
|
+
if not node_data:
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
return JPipelineParser.parse_pipeline_data(node_data)
|
|
217
|
+
|
|
120
218
|
@property
|
|
121
219
|
def tasker(self) -> Tasker:
|
|
220
|
+
"""获取实例 / Get instance
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
Tasker: 实例对象 / Instance object
|
|
224
|
+
"""
|
|
122
225
|
return self._tasker
|
|
123
226
|
|
|
124
227
|
def get_task_job(self) -> JobWithResult:
|
|
228
|
+
"""获取对应任务号的任务作业 / Get task job for corresponding task id
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
JobWithResult: 任务作业对象 / Task job object
|
|
232
|
+
|
|
233
|
+
Raises:
|
|
234
|
+
ValueError: 如果任务 id 为 None
|
|
235
|
+
"""
|
|
125
236
|
task_id = Library.framework().MaaContextGetTaskId(self._handle)
|
|
126
237
|
if not task_id:
|
|
127
238
|
raise ValueError("task_id is None")
|
|
@@ -129,6 +240,14 @@ class Context:
|
|
|
129
240
|
return self.tasker._gen_task_job(task_id)
|
|
130
241
|
|
|
131
242
|
def clone(self) -> "Context":
|
|
243
|
+
"""复制上下文 / Clone context
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
Context: 复制的上下文对象 / Cloned context object
|
|
247
|
+
|
|
248
|
+
Raises:
|
|
249
|
+
ValueError: 如果克隆失败
|
|
250
|
+
"""
|
|
132
251
|
cloned_handle = Library.framework().MaaContextClone(self._handle)
|
|
133
252
|
if not cloned_handle:
|
|
134
253
|
raise ValueError("cloned_handle is None")
|
|
@@ -145,9 +264,11 @@ class Context:
|
|
|
145
264
|
|
|
146
265
|
@staticmethod
|
|
147
266
|
def _gen_post_param(entry: str, pipeline_override: Dict) -> Tuple[bytes, bytes]:
|
|
267
|
+
pipeline_json = json.dumps(pipeline_override, ensure_ascii=False)
|
|
268
|
+
|
|
148
269
|
return (
|
|
149
270
|
entry.encode(),
|
|
150
|
-
|
|
271
|
+
pipeline_json.encode(),
|
|
151
272
|
)
|
|
152
273
|
|
|
153
274
|
_api_properties_initialized: bool = False
|
|
@@ -196,6 +317,13 @@ class Context:
|
|
|
196
317
|
MaaStringListBufferHandle,
|
|
197
318
|
]
|
|
198
319
|
|
|
320
|
+
Library.framework().MaaContextOverrideImage.restype = MaaBool
|
|
321
|
+
Library.framework().MaaContextOverrideImage.argtypes = [
|
|
322
|
+
MaaContextHandle,
|
|
323
|
+
ctypes.c_char_p,
|
|
324
|
+
MaaImageBufferHandle,
|
|
325
|
+
]
|
|
326
|
+
|
|
199
327
|
Library.framework().MaaContextGetNodeData.restype = MaaBool
|
|
200
328
|
Library.framework().MaaContextGetNodeData.argtypes = [
|
|
201
329
|
MaaContextHandle,
|
|
@@ -217,3 +345,87 @@ class Context:
|
|
|
217
345
|
Library.framework().MaaContextClone.argtypes = [
|
|
218
346
|
MaaContextHandle,
|
|
219
347
|
]
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
class ContextEventSink(EventSink):
|
|
351
|
+
|
|
352
|
+
@dataclass
|
|
353
|
+
class NodeNextListDetail:
|
|
354
|
+
task_id: int
|
|
355
|
+
name: str
|
|
356
|
+
next_list: list[str]
|
|
357
|
+
focus: Any
|
|
358
|
+
|
|
359
|
+
def on_node_next_list(
|
|
360
|
+
self,
|
|
361
|
+
context: Context,
|
|
362
|
+
noti_type: NotificationType,
|
|
363
|
+
detail: NodeNextListDetail,
|
|
364
|
+
):
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
@dataclass
|
|
368
|
+
class NodeRecognitionDetail:
|
|
369
|
+
task_id: int
|
|
370
|
+
reco_id: int
|
|
371
|
+
name: str
|
|
372
|
+
focus: Any
|
|
373
|
+
|
|
374
|
+
def on_node_recognition(
|
|
375
|
+
self,
|
|
376
|
+
context: Context,
|
|
377
|
+
noti_type: NotificationType,
|
|
378
|
+
detail: NodeRecognitionDetail,
|
|
379
|
+
):
|
|
380
|
+
pass
|
|
381
|
+
|
|
382
|
+
@dataclass
|
|
383
|
+
class NodeActionDetail:
|
|
384
|
+
task_id: int
|
|
385
|
+
node_id: int
|
|
386
|
+
name: str
|
|
387
|
+
focus: Any
|
|
388
|
+
|
|
389
|
+
def on_node_action(
|
|
390
|
+
self, context: Context, noti_type: NotificationType, detail: NodeActionDetail
|
|
391
|
+
):
|
|
392
|
+
pass
|
|
393
|
+
|
|
394
|
+
def on_raw_notification(self, context: Context, msg: str, details: dict):
|
|
395
|
+
pass
|
|
396
|
+
|
|
397
|
+
def _on_raw_notification(self, handle: ctypes.c_void_p, msg: str, details: dict):
|
|
398
|
+
|
|
399
|
+
context = Context(handle=handle)
|
|
400
|
+
self.on_raw_notification(context, msg, details)
|
|
401
|
+
|
|
402
|
+
noti_type = EventSink._notification_type(msg)
|
|
403
|
+
if msg.startswith("Node.NextList"):
|
|
404
|
+
detail = self.NodeNextListDetail(
|
|
405
|
+
task_id=details["task_id"],
|
|
406
|
+
name=details["name"],
|
|
407
|
+
next_list=details["list"],
|
|
408
|
+
focus=details["focus"],
|
|
409
|
+
)
|
|
410
|
+
self.on_node_next_list(context, noti_type, detail)
|
|
411
|
+
|
|
412
|
+
elif msg.startswith("Node.Recognition"):
|
|
413
|
+
detail = self.NodeRecognitionDetail(
|
|
414
|
+
task_id=details["task_id"],
|
|
415
|
+
reco_id=details["reco_id"],
|
|
416
|
+
name=details["name"],
|
|
417
|
+
focus=details["focus"],
|
|
418
|
+
)
|
|
419
|
+
self.on_node_recognition(context, noti_type, detail)
|
|
420
|
+
|
|
421
|
+
elif msg.startswith("Node.Action"):
|
|
422
|
+
detail = self.NodeActionDetail(
|
|
423
|
+
task_id=details["task_id"],
|
|
424
|
+
node_id=details["node_id"],
|
|
425
|
+
name=details["name"],
|
|
426
|
+
focus=details["focus"],
|
|
427
|
+
)
|
|
428
|
+
self.on_node_action(context, noti_type, detail)
|
|
429
|
+
|
|
430
|
+
else:
|
|
431
|
+
self.on_unknown_notification(context, msg, details)
|