kotonebot 0.4.0__py3-none-any.whl → 0.5.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.
- kotonebot/__init__.py +39 -39
- kotonebot/backend/bot.py +312 -312
- kotonebot/backend/color.py +525 -525
- kotonebot/backend/context/__init__.py +3 -3
- kotonebot/backend/context/task_action.py +183 -183
- kotonebot/backend/core.py +129 -129
- kotonebot/backend/debug/entry.py +89 -89
- kotonebot/backend/debug/mock.py +78 -78
- kotonebot/backend/debug/server.py +222 -222
- kotonebot/backend/debug/vars.py +351 -351
- kotonebot/backend/dispatch.py +227 -227
- kotonebot/backend/flow_controller.py +196 -196
- kotonebot/backend/ocr.py +535 -529
- kotonebot/backend/preprocessor.py +103 -103
- kotonebot/client/__init__.py +9 -9
- kotonebot/client/device.py +528 -503
- kotonebot/client/fast_screenshot.py +377 -377
- kotonebot/client/host/__init__.py +43 -12
- kotonebot/client/host/adb_common.py +107 -103
- kotonebot/client/host/custom.py +118 -114
- kotonebot/client/host/leidian_host.py +196 -201
- kotonebot/client/host/mumu12_host.py +353 -358
- kotonebot/client/host/protocol.py +214 -213
- kotonebot/client/host/windows_common.py +58 -58
- kotonebot/client/implements/__init__.py +71 -15
- kotonebot/client/implements/adb.py +89 -85
- kotonebot/client/implements/adb_raw.py +162 -158
- kotonebot/client/implements/nemu_ipc/__init__.py +11 -7
- kotonebot/client/implements/nemu_ipc/external_renderer_ipc.py +284 -284
- kotonebot/client/implements/nemu_ipc/nemu_ipc.py +327 -327
- kotonebot/client/implements/remote_windows.py +188 -188
- kotonebot/client/implements/uiautomator2.py +85 -81
- kotonebot/client/implements/windows.py +176 -172
- kotonebot/client/protocol.py +69 -69
- kotonebot/client/registration.py +24 -24
- kotonebot/config/base_config.py +96 -96
- kotonebot/config/manager.py +36 -36
- kotonebot/errors.py +76 -71
- kotonebot/interop/win/__init__.py +10 -3
- kotonebot/interop/win/_mouse.py +311 -0
- kotonebot/interop/win/message_box.py +313 -313
- kotonebot/interop/win/reg.py +37 -37
- kotonebot/interop/win/shortcut.py +43 -43
- kotonebot/interop/win/task_dialog.py +513 -513
- kotonebot/logging/__init__.py +2 -2
- kotonebot/logging/log.py +17 -17
- kotonebot/primitives/__init__.py +17 -17
- kotonebot/primitives/geometry.py +862 -290
- kotonebot/primitives/visual.py +63 -63
- kotonebot/tools/mirror.py +354 -354
- kotonebot/ui/file_host/sensio.py +36 -36
- kotonebot/ui/file_host/tmp_send.py +54 -54
- kotonebot/ui/pushkit/__init__.py +3 -3
- kotonebot/ui/pushkit/image_host.py +88 -87
- kotonebot/ui/pushkit/protocol.py +13 -13
- kotonebot/ui/pushkit/wxpusher.py +54 -53
- kotonebot/ui/user.py +148 -148
- kotonebot/util.py +436 -436
- {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/METADATA +82 -81
- kotonebot-0.5.0.dist-info/RECORD +71 -0
- {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/licenses/LICENSE +673 -673
- kotonebot-0.4.0.dist-info/RECORD +0 -70
- {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/WHEEL +0 -0
- {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/top_level.txt +0 -0
kotonebot/backend/dispatch.py
CHANGED
|
@@ -1,228 +1,228 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import logging
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from typing import Any, Callable, Literal
|
|
5
|
-
|
|
6
|
-
from dataclasses import dataclass
|
|
7
|
-
|
|
8
|
-
from kotonebot.backend.ocr import StringMatchFunction
|
|
9
|
-
from kotonebot.primitives import Rect, is_rect
|
|
10
|
-
|
|
11
|
-
from .core import Image
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger(__name__)
|
|
14
|
-
|
|
15
|
-
@dataclass
|
|
16
|
-
class ClickParams:
|
|
17
|
-
finish: bool = False
|
|
18
|
-
log: str | None = None
|
|
19
|
-
|
|
20
|
-
class ClickCenter:
|
|
21
|
-
def __init__(self, sd: 'SimpleDispatcher', target: Image | str | StringMatchFunction | Literal['center'], *, params: ClickParams = ClickParams()):
|
|
22
|
-
self.target = target
|
|
23
|
-
self.params = params
|
|
24
|
-
self.sd = sd
|
|
25
|
-
|
|
26
|
-
def __call__(self):
|
|
27
|
-
from kotonebot import device
|
|
28
|
-
if self.params.log:
|
|
29
|
-
self.sd.logger.info(self.params.log)
|
|
30
|
-
device.click_center()
|
|
31
|
-
if self.params.finish:
|
|
32
|
-
self.sd.finished = True
|
|
33
|
-
|
|
34
|
-
class ClickImage:
|
|
35
|
-
def __init__(self, sd: 'SimpleDispatcher', image: Image, *, params: ClickParams = ClickParams()):
|
|
36
|
-
self.image = image
|
|
37
|
-
self.params = params
|
|
38
|
-
self.sd = sd
|
|
39
|
-
|
|
40
|
-
def __call__(self):
|
|
41
|
-
from kotonebot import device, image
|
|
42
|
-
if image.find(self.image):
|
|
43
|
-
if self.params.log:
|
|
44
|
-
self.sd.logger.info(self.params.log)
|
|
45
|
-
device.click()
|
|
46
|
-
if self.params.finish:
|
|
47
|
-
self.sd.finished = True
|
|
48
|
-
|
|
49
|
-
class ClickImageAny:
|
|
50
|
-
def __init__(self, sd: 'SimpleDispatcher', images: list[Image], params: ClickParams = ClickParams()):
|
|
51
|
-
self.images = images
|
|
52
|
-
self.params = params
|
|
53
|
-
self.sd = sd
|
|
54
|
-
|
|
55
|
-
def __call__(self):
|
|
56
|
-
from kotonebot import device, image
|
|
57
|
-
if image.find_multi(self.images):
|
|
58
|
-
if self.params.log:
|
|
59
|
-
self.sd.logger.info(self.params.log)
|
|
60
|
-
device.click()
|
|
61
|
-
if self.params.finish:
|
|
62
|
-
self.sd.finished = True
|
|
63
|
-
|
|
64
|
-
class ClickText:
|
|
65
|
-
def __init__(
|
|
66
|
-
self,
|
|
67
|
-
sd: 'SimpleDispatcher',
|
|
68
|
-
text: str | StringMatchFunction,
|
|
69
|
-
params: ClickParams = ClickParams()
|
|
70
|
-
):
|
|
71
|
-
self.text = text
|
|
72
|
-
self.params = params
|
|
73
|
-
self.sd = sd
|
|
74
|
-
|
|
75
|
-
def __call__(self):
|
|
76
|
-
from kotonebot import device, ocr
|
|
77
|
-
if ocr.find(self.text):
|
|
78
|
-
if self.params.log:
|
|
79
|
-
self.sd.logger.info(self.params.log)
|
|
80
|
-
device.click()
|
|
81
|
-
if self.params.finish:
|
|
82
|
-
self.sd.finished = True
|
|
83
|
-
|
|
84
|
-
class ClickRect:
|
|
85
|
-
def __init__(self, sd: 'SimpleDispatcher', rect: Rect, *, params: ClickParams = ClickParams()):
|
|
86
|
-
self.rect = rect
|
|
87
|
-
self.params = params
|
|
88
|
-
self.sd = sd
|
|
89
|
-
|
|
90
|
-
def __call__(self):
|
|
91
|
-
from kotonebot import device
|
|
92
|
-
if device.click(self.rect):
|
|
93
|
-
if self.params.log:
|
|
94
|
-
self.sd.logger.info(self.params.log)
|
|
95
|
-
if self.params.finish:
|
|
96
|
-
self.sd.finished = True
|
|
97
|
-
|
|
98
|
-
class UntilText:
|
|
99
|
-
def __init__(
|
|
100
|
-
self,
|
|
101
|
-
sd: 'SimpleDispatcher',
|
|
102
|
-
text: str | StringMatchFunction,
|
|
103
|
-
*,
|
|
104
|
-
rect: Rect | None = None,
|
|
105
|
-
result: Any | None = None
|
|
106
|
-
):
|
|
107
|
-
self.text = text
|
|
108
|
-
self.sd = sd
|
|
109
|
-
self.rect = rect
|
|
110
|
-
self.result = result
|
|
111
|
-
|
|
112
|
-
def __call__(self):
|
|
113
|
-
from kotonebot import ocr
|
|
114
|
-
if ocr.find(self.text, rect=self.rect):
|
|
115
|
-
self.sd.finished = True
|
|
116
|
-
self.sd.result = self.result
|
|
117
|
-
|
|
118
|
-
class UntilImage:
|
|
119
|
-
def __init__(
|
|
120
|
-
self,
|
|
121
|
-
sd: 'SimpleDispatcher',
|
|
122
|
-
image: Image,
|
|
123
|
-
*,
|
|
124
|
-
rect: Rect | None = None,
|
|
125
|
-
result: Any | None = None
|
|
126
|
-
):
|
|
127
|
-
self.image = image
|
|
128
|
-
self.sd = sd
|
|
129
|
-
self.rect = rect
|
|
130
|
-
self.result = result
|
|
131
|
-
|
|
132
|
-
def __call__(self):
|
|
133
|
-
from kotonebot import image
|
|
134
|
-
if self.rect:
|
|
135
|
-
logger.warning(f'UntilImage with rect is deprecated. Use UntilText instead.')
|
|
136
|
-
if image.find(self.image):
|
|
137
|
-
self.sd.finished = True
|
|
138
|
-
self.sd.result = self.result
|
|
139
|
-
|
|
140
|
-
class SimpleDispatcher:
|
|
141
|
-
def __init__(self, name: str, *, min_interval: float = 0.3):
|
|
142
|
-
self.name = name
|
|
143
|
-
self.logger = logging.getLogger(f'SimpleDispatcher of {name}')
|
|
144
|
-
self.blocks: list[Callable] = []
|
|
145
|
-
self.finished: bool = False
|
|
146
|
-
self.result: Any | None = None
|
|
147
|
-
self.min_interval = min_interval
|
|
148
|
-
self.timeout_value: float | None = None
|
|
149
|
-
self.timeout_critical: bool = False
|
|
150
|
-
self.__last_run_time: float = 0
|
|
151
|
-
|
|
152
|
-
def click(
|
|
153
|
-
self,
|
|
154
|
-
target: Image | StringMatchFunction | Literal['center'] | Rect,
|
|
155
|
-
*,
|
|
156
|
-
finish: bool = False,
|
|
157
|
-
log: str | None = None
|
|
158
|
-
):
|
|
159
|
-
params = ClickParams(finish=finish, log=log)
|
|
160
|
-
if isinstance(target, Image):
|
|
161
|
-
self.blocks.append(ClickImage(self, target, params=params))
|
|
162
|
-
elif is_rect(target):
|
|
163
|
-
self.blocks.append(ClickRect(self, target, params=params))
|
|
164
|
-
elif callable(target):
|
|
165
|
-
self.blocks.append(ClickText(self, target, params=params))
|
|
166
|
-
elif target == 'center':
|
|
167
|
-
self.blocks.append(ClickCenter(self, target='center', params=params))
|
|
168
|
-
else:
|
|
169
|
-
raise ValueError(f'Invalid target: {target}')
|
|
170
|
-
return self
|
|
171
|
-
|
|
172
|
-
def click_any(
|
|
173
|
-
self,
|
|
174
|
-
target: list[Image],
|
|
175
|
-
*,
|
|
176
|
-
finish: bool = False,
|
|
177
|
-
log: str | None = None
|
|
178
|
-
):
|
|
179
|
-
params = ClickParams(finish=finish, log=log)
|
|
180
|
-
self.blocks.append(ClickImageAny(self, target, params))
|
|
181
|
-
return self
|
|
182
|
-
|
|
183
|
-
def until(
|
|
184
|
-
self,
|
|
185
|
-
text: StringMatchFunction | Image,
|
|
186
|
-
*,
|
|
187
|
-
rect: Rect | None = None,
|
|
188
|
-
result: Any | None = None
|
|
189
|
-
):
|
|
190
|
-
if isinstance(text, Image):
|
|
191
|
-
self.blocks.append(UntilImage(self, text, rect=rect, result=result))
|
|
192
|
-
else:
|
|
193
|
-
self.blocks.append(UntilText(self, text, rect=rect, result=result))
|
|
194
|
-
return self
|
|
195
|
-
|
|
196
|
-
def timeout(self, timeout: float, *, critical: bool = False, result: Any | None = None):
|
|
197
|
-
self.timeout_value = timeout
|
|
198
|
-
self.timeout_critical = critical
|
|
199
|
-
self.timeout_result = result
|
|
200
|
-
return self
|
|
201
|
-
|
|
202
|
-
def run(self):
|
|
203
|
-
from kotonebot import device, sleep
|
|
204
|
-
while True:
|
|
205
|
-
logger.debug(f'Running dispatcher "{self.name}"')
|
|
206
|
-
time_delta = time.time() - self.__last_run_time
|
|
207
|
-
if time_delta < self.min_interval:
|
|
208
|
-
sleep(self.min_interval - time_delta)
|
|
209
|
-
# 依次执行 block
|
|
210
|
-
done = False
|
|
211
|
-
for block in self.blocks:
|
|
212
|
-
block()
|
|
213
|
-
if self.finished:
|
|
214
|
-
done = True
|
|
215
|
-
break
|
|
216
|
-
if done:
|
|
217
|
-
break
|
|
218
|
-
|
|
219
|
-
self.__last_run_time = time.time()
|
|
220
|
-
if self.timeout_value and time.time() - self.__last_run_time > self.timeout_value:
|
|
221
|
-
if self.timeout_critical:
|
|
222
|
-
raise TimeoutError(f'Dispatcher "{self.name}" timed out.')
|
|
223
|
-
else:
|
|
224
|
-
self.logger.warning(f'Dispatcher "{self.name}" timed out.')
|
|
225
|
-
self.result = self.timeout_result
|
|
226
|
-
break
|
|
227
|
-
device.screenshot()
|
|
1
|
+
import time
|
|
2
|
+
import logging
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from kotonebot.backend.ocr import StringMatchFunction
|
|
9
|
+
from kotonebot.primitives import Rect, is_rect
|
|
10
|
+
|
|
11
|
+
from .core import Image
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class ClickParams:
|
|
17
|
+
finish: bool = False
|
|
18
|
+
log: str | None = None
|
|
19
|
+
|
|
20
|
+
class ClickCenter:
|
|
21
|
+
def __init__(self, sd: 'SimpleDispatcher', target: Image | str | StringMatchFunction | Literal['center'], *, params: ClickParams = ClickParams()):
|
|
22
|
+
self.target = target
|
|
23
|
+
self.params = params
|
|
24
|
+
self.sd = sd
|
|
25
|
+
|
|
26
|
+
def __call__(self):
|
|
27
|
+
from kotonebot import device
|
|
28
|
+
if self.params.log:
|
|
29
|
+
self.sd.logger.info(self.params.log)
|
|
30
|
+
device.click_center()
|
|
31
|
+
if self.params.finish:
|
|
32
|
+
self.sd.finished = True
|
|
33
|
+
|
|
34
|
+
class ClickImage:
|
|
35
|
+
def __init__(self, sd: 'SimpleDispatcher', image: Image, *, params: ClickParams = ClickParams()):
|
|
36
|
+
self.image = image
|
|
37
|
+
self.params = params
|
|
38
|
+
self.sd = sd
|
|
39
|
+
|
|
40
|
+
def __call__(self):
|
|
41
|
+
from kotonebot import device, image
|
|
42
|
+
if image.find(self.image):
|
|
43
|
+
if self.params.log:
|
|
44
|
+
self.sd.logger.info(self.params.log)
|
|
45
|
+
device.click()
|
|
46
|
+
if self.params.finish:
|
|
47
|
+
self.sd.finished = True
|
|
48
|
+
|
|
49
|
+
class ClickImageAny:
|
|
50
|
+
def __init__(self, sd: 'SimpleDispatcher', images: list[Image], params: ClickParams = ClickParams()):
|
|
51
|
+
self.images = images
|
|
52
|
+
self.params = params
|
|
53
|
+
self.sd = sd
|
|
54
|
+
|
|
55
|
+
def __call__(self):
|
|
56
|
+
from kotonebot import device, image
|
|
57
|
+
if image.find_multi(self.images):
|
|
58
|
+
if self.params.log:
|
|
59
|
+
self.sd.logger.info(self.params.log)
|
|
60
|
+
device.click()
|
|
61
|
+
if self.params.finish:
|
|
62
|
+
self.sd.finished = True
|
|
63
|
+
|
|
64
|
+
class ClickText:
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
sd: 'SimpleDispatcher',
|
|
68
|
+
text: str | StringMatchFunction,
|
|
69
|
+
params: ClickParams = ClickParams()
|
|
70
|
+
):
|
|
71
|
+
self.text = text
|
|
72
|
+
self.params = params
|
|
73
|
+
self.sd = sd
|
|
74
|
+
|
|
75
|
+
def __call__(self):
|
|
76
|
+
from kotonebot import device, ocr
|
|
77
|
+
if ocr.find(self.text):
|
|
78
|
+
if self.params.log:
|
|
79
|
+
self.sd.logger.info(self.params.log)
|
|
80
|
+
device.click()
|
|
81
|
+
if self.params.finish:
|
|
82
|
+
self.sd.finished = True
|
|
83
|
+
|
|
84
|
+
class ClickRect:
|
|
85
|
+
def __init__(self, sd: 'SimpleDispatcher', rect: Rect, *, params: ClickParams = ClickParams()):
|
|
86
|
+
self.rect = rect
|
|
87
|
+
self.params = params
|
|
88
|
+
self.sd = sd
|
|
89
|
+
|
|
90
|
+
def __call__(self):
|
|
91
|
+
from kotonebot import device
|
|
92
|
+
if device.click(self.rect):
|
|
93
|
+
if self.params.log:
|
|
94
|
+
self.sd.logger.info(self.params.log)
|
|
95
|
+
if self.params.finish:
|
|
96
|
+
self.sd.finished = True
|
|
97
|
+
|
|
98
|
+
class UntilText:
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
sd: 'SimpleDispatcher',
|
|
102
|
+
text: str | StringMatchFunction,
|
|
103
|
+
*,
|
|
104
|
+
rect: Rect | None = None,
|
|
105
|
+
result: Any | None = None
|
|
106
|
+
):
|
|
107
|
+
self.text = text
|
|
108
|
+
self.sd = sd
|
|
109
|
+
self.rect = rect
|
|
110
|
+
self.result = result
|
|
111
|
+
|
|
112
|
+
def __call__(self):
|
|
113
|
+
from kotonebot import ocr
|
|
114
|
+
if ocr.find(self.text, rect=self.rect):
|
|
115
|
+
self.sd.finished = True
|
|
116
|
+
self.sd.result = self.result
|
|
117
|
+
|
|
118
|
+
class UntilImage:
|
|
119
|
+
def __init__(
|
|
120
|
+
self,
|
|
121
|
+
sd: 'SimpleDispatcher',
|
|
122
|
+
image: Image,
|
|
123
|
+
*,
|
|
124
|
+
rect: Rect | None = None,
|
|
125
|
+
result: Any | None = None
|
|
126
|
+
):
|
|
127
|
+
self.image = image
|
|
128
|
+
self.sd = sd
|
|
129
|
+
self.rect = rect
|
|
130
|
+
self.result = result
|
|
131
|
+
|
|
132
|
+
def __call__(self):
|
|
133
|
+
from kotonebot import image
|
|
134
|
+
if self.rect:
|
|
135
|
+
logger.warning(f'UntilImage with rect is deprecated. Use UntilText instead.')
|
|
136
|
+
if image.find(self.image):
|
|
137
|
+
self.sd.finished = True
|
|
138
|
+
self.sd.result = self.result
|
|
139
|
+
|
|
140
|
+
class SimpleDispatcher:
|
|
141
|
+
def __init__(self, name: str, *, min_interval: float = 0.3):
|
|
142
|
+
self.name = name
|
|
143
|
+
self.logger = logging.getLogger(f'SimpleDispatcher of {name}')
|
|
144
|
+
self.blocks: list[Callable] = []
|
|
145
|
+
self.finished: bool = False
|
|
146
|
+
self.result: Any | None = None
|
|
147
|
+
self.min_interval = min_interval
|
|
148
|
+
self.timeout_value: float | None = None
|
|
149
|
+
self.timeout_critical: bool = False
|
|
150
|
+
self.__last_run_time: float = 0
|
|
151
|
+
|
|
152
|
+
def click(
|
|
153
|
+
self,
|
|
154
|
+
target: Image | StringMatchFunction | Literal['center'] | Rect,
|
|
155
|
+
*,
|
|
156
|
+
finish: bool = False,
|
|
157
|
+
log: str | None = None
|
|
158
|
+
):
|
|
159
|
+
params = ClickParams(finish=finish, log=log)
|
|
160
|
+
if isinstance(target, Image):
|
|
161
|
+
self.blocks.append(ClickImage(self, target, params=params))
|
|
162
|
+
elif is_rect(target):
|
|
163
|
+
self.blocks.append(ClickRect(self, target, params=params))
|
|
164
|
+
elif callable(target):
|
|
165
|
+
self.blocks.append(ClickText(self, target, params=params))
|
|
166
|
+
elif target == 'center':
|
|
167
|
+
self.blocks.append(ClickCenter(self, target='center', params=params))
|
|
168
|
+
else:
|
|
169
|
+
raise ValueError(f'Invalid target: {target}')
|
|
170
|
+
return self
|
|
171
|
+
|
|
172
|
+
def click_any(
|
|
173
|
+
self,
|
|
174
|
+
target: list[Image],
|
|
175
|
+
*,
|
|
176
|
+
finish: bool = False,
|
|
177
|
+
log: str | None = None
|
|
178
|
+
):
|
|
179
|
+
params = ClickParams(finish=finish, log=log)
|
|
180
|
+
self.blocks.append(ClickImageAny(self, target, params))
|
|
181
|
+
return self
|
|
182
|
+
|
|
183
|
+
def until(
|
|
184
|
+
self,
|
|
185
|
+
text: StringMatchFunction | Image,
|
|
186
|
+
*,
|
|
187
|
+
rect: Rect | None = None,
|
|
188
|
+
result: Any | None = None
|
|
189
|
+
):
|
|
190
|
+
if isinstance(text, Image):
|
|
191
|
+
self.blocks.append(UntilImage(self, text, rect=rect, result=result))
|
|
192
|
+
else:
|
|
193
|
+
self.blocks.append(UntilText(self, text, rect=rect, result=result))
|
|
194
|
+
return self
|
|
195
|
+
|
|
196
|
+
def timeout(self, timeout: float, *, critical: bool = False, result: Any | None = None):
|
|
197
|
+
self.timeout_value = timeout
|
|
198
|
+
self.timeout_critical = critical
|
|
199
|
+
self.timeout_result = result
|
|
200
|
+
return self
|
|
201
|
+
|
|
202
|
+
def run(self):
|
|
203
|
+
from kotonebot import device, sleep
|
|
204
|
+
while True:
|
|
205
|
+
logger.debug(f'Running dispatcher "{self.name}"')
|
|
206
|
+
time_delta = time.time() - self.__last_run_time
|
|
207
|
+
if time_delta < self.min_interval:
|
|
208
|
+
sleep(self.min_interval - time_delta)
|
|
209
|
+
# 依次执行 block
|
|
210
|
+
done = False
|
|
211
|
+
for block in self.blocks:
|
|
212
|
+
block()
|
|
213
|
+
if self.finished:
|
|
214
|
+
done = True
|
|
215
|
+
break
|
|
216
|
+
if done:
|
|
217
|
+
break
|
|
218
|
+
|
|
219
|
+
self.__last_run_time = time.time()
|
|
220
|
+
if self.timeout_value and time.time() - self.__last_run_time > self.timeout_value:
|
|
221
|
+
if self.timeout_critical:
|
|
222
|
+
raise TimeoutError(f'Dispatcher "{self.name}" timed out.')
|
|
223
|
+
else:
|
|
224
|
+
self.logger.warning(f'Dispatcher "{self.name}" timed out.')
|
|
225
|
+
self.result = self.timeout_result
|
|
226
|
+
break
|
|
227
|
+
device.screenshot()
|
|
228
228
|
return self.result
|