pygpt-net 2.6.26__py3-none-any.whl → 2.6.28__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.
Files changed (63) hide show
  1. pygpt_net/CHANGELOG.txt +10 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +5 -1
  4. pygpt_net/controller/access/voice.py +3 -5
  5. pygpt_net/controller/audio/audio.py +9 -6
  6. pygpt_net/controller/audio/ui.py +263 -0
  7. pygpt_net/controller/chat/common.py +17 -1
  8. pygpt_net/controller/kernel/kernel.py +2 -0
  9. pygpt_net/controller/notepad/notepad.py +10 -1
  10. pygpt_net/controller/theme/markdown.py +2 -0
  11. pygpt_net/controller/theme/theme.py +4 -1
  12. pygpt_net/controller/ui/tabs.py +5 -0
  13. pygpt_net/core/audio/backend/native.py +114 -82
  14. pygpt_net/core/audio/backend/pyaudio.py +16 -19
  15. pygpt_net/core/audio/backend/pygame.py +12 -15
  16. pygpt_net/core/audio/capture.py +10 -9
  17. pygpt_net/core/audio/context.py +3 -6
  18. pygpt_net/core/command/command.py +2 -0
  19. pygpt_net/core/render/web/helpers.py +13 -3
  20. pygpt_net/core/render/web/renderer.py +3 -3
  21. pygpt_net/data/config/config.json +7 -5
  22. pygpt_net/data/config/models.json +3 -3
  23. pygpt_net/data/config/settings.json +24 -10
  24. pygpt_net/data/css/web-blocks.darkest.css +91 -0
  25. pygpt_net/data/css/web-chatgpt.css +7 -5
  26. pygpt_net/data/css/web-chatgpt.dark.css +5 -2
  27. pygpt_net/data/css/web-chatgpt.darkest.css +91 -0
  28. pygpt_net/data/css/web-chatgpt.light.css +8 -2
  29. pygpt_net/data/css/web-chatgpt_wide.css +7 -4
  30. pygpt_net/data/css/web-chatgpt_wide.dark.css +5 -2
  31. pygpt_net/data/css/web-chatgpt_wide.darkest.css +91 -0
  32. pygpt_net/data/css/web-chatgpt_wide.light.css +9 -6
  33. pygpt_net/data/locale/locale.de.ini +2 -0
  34. pygpt_net/data/locale/locale.en.ini +2 -0
  35. pygpt_net/data/locale/locale.es.ini +2 -0
  36. pygpt_net/data/locale/locale.fr.ini +2 -0
  37. pygpt_net/data/locale/locale.it.ini +2 -0
  38. pygpt_net/data/locale/locale.pl.ini +3 -1
  39. pygpt_net/data/locale/locale.uk.ini +2 -0
  40. pygpt_net/data/locale/locale.zh.ini +2 -0
  41. pygpt_net/data/themes/dark_darkest.css +31 -0
  42. pygpt_net/data/themes/dark_darkest.xml +10 -0
  43. pygpt_net/plugin/audio_input/simple.py +5 -10
  44. pygpt_net/plugin/audio_output/plugin.py +4 -17
  45. pygpt_net/plugin/tuya/__init__.py +12 -0
  46. pygpt_net/plugin/tuya/config.py +256 -0
  47. pygpt_net/plugin/tuya/plugin.py +117 -0
  48. pygpt_net/plugin/tuya/worker.py +588 -0
  49. pygpt_net/plugin/wikipedia/__init__.py +12 -0
  50. pygpt_net/plugin/wikipedia/config.py +228 -0
  51. pygpt_net/plugin/wikipedia/plugin.py +114 -0
  52. pygpt_net/plugin/wikipedia/worker.py +430 -0
  53. pygpt_net/provider/core/config/patch.py +11 -0
  54. pygpt_net/ui/layout/chat/input.py +5 -2
  55. pygpt_net/ui/main.py +1 -2
  56. pygpt_net/ui/widget/audio/bar.py +5 -1
  57. pygpt_net/ui/widget/tabs/output.py +2 -0
  58. pygpt_net/ui/widget/textarea/input.py +483 -55
  59. {pygpt_net-2.6.26.dist-info → pygpt_net-2.6.28.dist-info}/METADATA +78 -35
  60. {pygpt_net-2.6.26.dist-info → pygpt_net-2.6.28.dist-info}/RECORD +63 -49
  61. {pygpt_net-2.6.26.dist-info → pygpt_net-2.6.28.dist-info}/LICENSE +0 -0
  62. {pygpt_net-2.6.26.dist-info → pygpt_net-2.6.28.dist-info}/WHEEL +0 -0
  63. {pygpt_net-2.6.26.dist-info → pygpt_net-2.6.28.dist-info}/entry_points.txt +0 -0
@@ -80,7 +80,7 @@ agent.eval.feedback = Feedback
80
80
  agent.eval.next = Ponowne uruchomienie z feedbackiem
81
81
  agent.eval.score = Ocena ewaluatora
82
82
  agent.eval.score.good = Odpowiedź wystarczająco dobra, wychodzenie.
83
- agent.evolve.generation = Generacja
83
+ agent.evolve.generation = Generacja
84
84
  agent.evolve.maxgen_limit = Osiągnięto maksymalną liczbę generacji, wychodzenie.
85
85
  agent.evolve.option.max_generations = Maksymalna liczba generacji
86
86
  agent.evolve.option.num_parents = Liczba rodziców
@@ -1117,6 +1117,8 @@ settings.audio.input.backend = Backend dla wejścia audio
1117
1117
  settings.audio.input.backend.desc = Wybierz backend dla wejścia audio.
1118
1118
  settings.audio.input.channels = Kanały
1119
1119
  settings.audio.input.channels.desc = Kanały wejściowe, domyślnie: 1
1120
+ settings.audio.input.continuous = Ciągłe Nagrywanie Dźwięku (Kawałki)
1121
+ settings.audio.input.continuous.desc = Włącz nagrywanie w kawałkach dla długich nagrań audio w notatniku (notatki głosowe).
1120
1122
  settings.audio.input.device = Urządzenie do wejścia audio
1121
1123
  settings.audio.input.device.desc = Wybierz urządzenie do wejścia mikrofonu.
1122
1124
  settings.audio.input.rate = Częstotliwość próbkowania
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = Бекенд для аудіовходу
1116
1116
  settings.audio.input.backend.desc = Виберіть бекенд для аудіовходу.
1117
1117
  settings.audio.input.channels = Канали
1118
1118
  settings.audio.input.channels.desc = Вхідні канали, за замовчуванням: 1
1119
+ settings.audio.input.continuous = Безперервний Аудіозапис (Частини)
1120
+ settings.audio.input.continuous.desc = Увімкніть запис частинами для довгих аудіозаписів у блокноті (голосові нотатки).
1119
1121
  settings.audio.input.device = Пристрій для аудіовходу
1120
1122
  settings.audio.input.device.desc = Виберіть пристрій для входу мікрофону.
1121
1123
  settings.audio.input.rate = Частота дискретизації
@@ -1116,6 +1116,8 @@ settings.audio.input.backend = 音频输入的后端
1116
1116
  settings.audio.input.backend.desc = 选择音频输入的后端。
1117
1117
  settings.audio.input.channels = 声道
1118
1118
  settings.audio.input.channels.desc = 输入声道,默认: 1
1119
+ settings.audio.input.continuous = 连续音频录制(片段)
1120
+ settings.audio.input.continuous.desc = 启用记事本中的长音频录制分段记录(语音笔记)。
1119
1121
  settings.audio.input.device = 音频输入的设备
1120
1122
  settings.audio.input.device.desc = 选择用于麦克风输入的音频设备。
1121
1123
  settings.audio.input.rate = 采样率
@@ -0,0 +1,31 @@
1
+ .layout-output-web {{
2
+ background-color: #202020 !important;
3
+ }}
4
+ QListView::item:selected,
5
+ QTreeView::item:selected {{
6
+ color: #ffffff;
7
+ selection-color: #ffffff;
8
+ }}
9
+ QComboBox::item:selected {{
10
+ color: #000;
11
+ selection-color: #000;
12
+ }}
13
+ QComboBox::item:disabled {{
14
+ color: #d1d2d2;
15
+ }}
16
+ QListView::item:selected:focus,
17
+ QComboBox::item:selected:focus,
18
+ QTreeView::item:selected:focus {{
19
+ color: #ffffff;
20
+ selection-color: #000000;
21
+ }}
22
+ QListView::item::disabled {{
23
+ color: #959595;
24
+ font-weight: bold;
25
+ }}
26
+ QMenuBar::item:selected {{
27
+ color: #000000;
28
+ }}
29
+ QMenu::item:selected {{
30
+ color: #000000;
31
+ }}
@@ -0,0 +1,10 @@
1
+ <!--?xml version="1.0" encoding="UTF-8"?-->
2
+ <resources>
3
+ <color name="primaryColor">#ffffff</color>
4
+ <color name="primaryLightColor">#ffffff</color>
5
+ <color name="secondaryColor">#1b1b1b</color>
6
+ <color name="secondaryLightColor">#202020</color>
7
+ <color name="secondaryDarkColor">#202020</color>
8
+ <color name="primaryTextColor">#ffffff</color>
9
+ <color name="secondaryTextColor">#ffffff</color>
10
+ </resources>
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.07 03:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -41,14 +41,11 @@ class Simple:
41
41
 
42
42
  def switch_btn_stop(self):
43
43
  """Switch button to stop"""
44
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setText(trans('audio.speak.btn.stop'))
45
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setToolTip(
46
- trans('audio.speak.btn.stop.tooltip'))
44
+ self.plugin.window.controller.audio.ui.on_input_begin("input")
47
45
 
48
46
  def switch_btn_start(self):
49
47
  """Switch button to start"""
50
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setText(trans('audio.speak.btn'))
51
- self.plugin.window.ui.plugin_addon['audio.input.btn'].btn_toggle.setToolTip(trans('audio.speak.btn.tooltip'))
48
+ self.plugin.window.controller.audio.ui.on_input_end("input")
52
49
 
53
50
  def stop_timeout(self):
54
51
  """Stop timeout"""
@@ -85,10 +82,8 @@ class Simple:
85
82
  # stop audio output if playing
86
83
  self.plugin.window.controller.audio.stop_output()
87
84
 
88
- # set audio volume bar
89
- self.plugin.window.core.audio.capture.set_bar(
90
- self.plugin.window.ui.plugin_addon['audio.input.btn'].bar
91
- )
85
+ # set audio input mode
86
+ self.plugin.window.core.audio.capture.set_mode("input")
92
87
 
93
88
  # start timeout timer to prevent infinite recording
94
89
  # disable in continuous mode
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.15 23:00:00 #
9
+ # Updated Date: 2025.08.27 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any
@@ -250,7 +250,8 @@ class Plugin(BasePlugin):
250
250
  worker.signals.stop.connect(self.handle_stop)
251
251
  worker.signals.volume_changed.connect(self.handle_volume)
252
252
 
253
- self.window.controller.audio.on_begin("")
253
+ if not self.window.controller.audio.ui.recording:
254
+ self.window.controller.audio.on_begin("")
254
255
 
255
256
  backend = self.window.core.config.get("audio.output.backend", "native")
256
257
  if backend == "native":
@@ -275,20 +276,6 @@ class Plugin(BasePlugin):
275
276
  """
276
277
  self.window.ui.plugin_addon['audio.output'].set_status(status)
277
278
 
278
- def show_stop_button(self):
279
- """Show stop button"""
280
- self.window.ui.plugin_addon['audio.output'].stop.setVisible(True)
281
-
282
- def hide_stop_button(self):
283
- """Hide stop button"""
284
- self.window.ui.plugin_addon['audio.output'].stop.setVisible(False)
285
-
286
- def stop_speak(self):
287
- """Stop speaking"""
288
- self.window.ui.plugin_addon['audio.output'].stop.setVisible(False)
289
- self.window.ui.plugin_addon['audio.output'].set_status('Stopped')
290
- self.window.ui.plugin_addon['audio.output'].stop_audio()
291
-
292
279
  def stop_audio(self):
293
280
  """
294
281
  Event: AUDIO_OUTPUT_STOP
@@ -336,4 +323,4 @@ class Plugin(BasePlugin):
336
323
 
337
324
  :param volume: volume level
338
325
  """
339
- self.window.ui.plugin_addon['audio.output.bar'].setLevel(volume)
326
+ self.window.controller.audio.ui.on_output_volume_change(int(volume))
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2025.08.27 20:00:00 #
10
+ # ================================================== #
11
+
12
+ from .plugin import *
@@ -0,0 +1,256 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2025.08.27 20:00:00 #
10
+ # ================================================== #
11
+
12
+ from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
13
+
14
+
15
+ class Config(BaseConfig):
16
+ def __init__(self, plugin: BasePlugin = None, *args, **kwargs):
17
+ super(Config, self).__init__(plugin)
18
+ self.plugin = plugin
19
+
20
+ def from_defaults(self, plugin: BasePlugin = None):
21
+ # Endpoints / HTTP
22
+ plugin.add_option(
23
+ "api_base",
24
+ type="text",
25
+ value="https://openapi.tuyaeu.com",
26
+ label="API base",
27
+ description="Tuya API base (eu/us/cn/in: https://openapi.tuyaeu.com / tuyaus / tuyacn / tuyain).",
28
+ )
29
+ plugin.add_option(
30
+ "http_timeout",
31
+ type="int",
32
+ value=30,
33
+ label="HTTP timeout (s)",
34
+ description="Requests timeout in seconds.",
35
+ )
36
+ plugin.add_option(
37
+ "lang",
38
+ type="text",
39
+ value="en",
40
+ label="Language",
41
+ description="Language header (e.g., en, pl).",
42
+ )
43
+
44
+ # Credentials
45
+ plugin.add_option(
46
+ "tuya_client_id",
47
+ type="text",
48
+ value="",
49
+ label="Tuya Client ID",
50
+ description="Client ID from Tuya IoT Platform Cloud project.",
51
+ secret=True,
52
+ )
53
+ plugin.add_option(
54
+ "tuya_client_secret",
55
+ type="text",
56
+ value="",
57
+ label="Tuya Client Secret",
58
+ description="Client secret from Tuya IoT Platform Cloud project.",
59
+ secret=True,
60
+ )
61
+ plugin.add_option(
62
+ "tuya_uid",
63
+ type="text",
64
+ value="",
65
+ label="Tuya UID (App Account)",
66
+ description="UID of linked Tuya App account (required for listing devices).",
67
+ )
68
+
69
+ # Tokens (auto)
70
+ plugin.add_option(
71
+ "tuya_access_token",
72
+ type="textarea",
73
+ value="",
74
+ label="(auto) Access token",
75
+ description="Stored Tuya access token.",
76
+ secret=True,
77
+ )
78
+ plugin.add_option(
79
+ "tuya_refresh_token",
80
+ type="textarea",
81
+ value="",
82
+ label="(auto) Refresh token",
83
+ description="Stored Tuya refresh token (not always used).",
84
+ secret=True,
85
+ )
86
+ plugin.add_option(
87
+ "tuya_token_expires_in",
88
+ type="text",
89
+ value="",
90
+ label="(auto) Expires in (s)",
91
+ description="Token lifetime seconds.",
92
+ )
93
+ plugin.add_option(
94
+ "tuya_token_expire_at",
95
+ type="text",
96
+ value="0",
97
+ label="(auto) Expire at (epoch s)",
98
+ description="Timestamp when token is considered expired.",
99
+ )
100
+
101
+ # Cache
102
+ plugin.add_option(
103
+ "tuya_cached_devices",
104
+ type="textarea",
105
+ value="[]",
106
+ label="(auto) Cached devices",
107
+ description="Cached devices for quick search.",
108
+ )
109
+
110
+ # ---------------- Commands ----------------
111
+
112
+ # Auth
113
+ plugin.add_cmd(
114
+ "tuya_set_keys",
115
+ instruction="Set Tuya Cloud credentials.",
116
+ params=[
117
+ {"name": "client_id", "type": "str", "required": True, "description": "Tuya Client ID"},
118
+ {"name": "client_secret", "type": "str", "required": True, "description": "Tuya Client Secret"},
119
+ ],
120
+ enabled=True,
121
+ description="Auth: set keys",
122
+ tab="auth",
123
+ )
124
+ plugin.add_cmd(
125
+ "tuya_set_uid",
126
+ instruction="Set Tuya App Account UID (for listing devices).",
127
+ params=[
128
+ {"name": "uid", "type": "str", "required": True, "description": "UID of linked Tuya account"},
129
+ ],
130
+ enabled=True,
131
+ description="Auth: set UID",
132
+ tab="auth",
133
+ )
134
+ plugin.add_cmd(
135
+ "tuya_token_get",
136
+ instruction="Obtain access token (grant_type=1).",
137
+ params=[],
138
+ enabled=True,
139
+ description="Auth: get token",
140
+ tab="auth",
141
+ )
142
+
143
+ # Devices
144
+ plugin.add_cmd(
145
+ "tuya_devices_list",
146
+ instruction="List devices for UID.",
147
+ params=[
148
+ {"name": "uid", "type": "str", "required": False, "description": "Override UID (optional)"},
149
+ {"name": "page_no", "type": "int", "required": False, "description": "Page number (default 1)"},
150
+ {"name": "page_size", "type": "int", "required": False, "description": "Page size (default 100)"},
151
+ ],
152
+ enabled=True,
153
+ description="Devices: list",
154
+ tab="devices",
155
+ )
156
+ plugin.add_cmd(
157
+ "tuya_device_get",
158
+ instruction="Get device info.",
159
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Device ID"}],
160
+ enabled=True,
161
+ description="Devices: get info",
162
+ tab="devices",
163
+ )
164
+ plugin.add_cmd(
165
+ "tuya_device_status",
166
+ instruction="Get device status (DP values).",
167
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Device ID"}],
168
+ enabled=True,
169
+ description="Devices: status",
170
+ tab="devices",
171
+ )
172
+ plugin.add_cmd(
173
+ "tuya_device_functions",
174
+ instruction="Get device supported functions (DP codes).",
175
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Device ID"}],
176
+ enabled=True,
177
+ description="Devices: functions",
178
+ tab="devices",
179
+ )
180
+ plugin.add_cmd(
181
+ "tuya_find_device",
182
+ instruction="Find device(s) by name (uses cached device list).",
183
+ params=[{"name": "name", "type": "str", "required": True, "description": "Substring match"}],
184
+ enabled=True,
185
+ description="Devices: find by name",
186
+ tab="devices",
187
+ )
188
+
189
+ # Control
190
+ plugin.add_cmd(
191
+ "tuya_device_set",
192
+ instruction="Set a device DP value or multiple values.",
193
+ params=[
194
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
195
+ {"name": "code", "type": "str", "required": False, "description": "DP code (if single)"},
196
+ {"name": "value", "type": "str", "required": False, "description": "Value for 'code'"},
197
+ {"name": "codes", "type": "dict", "required": False, "description": "Dict of {code: value}"},
198
+ ],
199
+ enabled=True,
200
+ description="Control: set DP(s)",
201
+ tab="control",
202
+ )
203
+ plugin.add_cmd(
204
+ "tuya_device_send",
205
+ instruction="Send raw commands list to device.",
206
+ params=[
207
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
208
+ {"name": "commands", "type": "list", "required": True, "description": "[{'code':'','value':..},...]"},
209
+ ],
210
+ enabled=True,
211
+ description="Control: send commands",
212
+ tab="control",
213
+ )
214
+ plugin.add_cmd(
215
+ "tuya_device_on",
216
+ instruction="Turn device ON (guesses switch code if not provided).",
217
+ params=[
218
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
219
+ {"name": "code", "type": "str", "required": False, "description": "Preferred switch code"},
220
+ ],
221
+ enabled=True,
222
+ description="Control: on",
223
+ tab="control",
224
+ )
225
+ plugin.add_cmd(
226
+ "tuya_device_off",
227
+ instruction="Turn device OFF (guesses switch code if not provided).",
228
+ params=[
229
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
230
+ {"name": "code", "type": "str", "required": False, "description": "Preferred switch code"},
231
+ ],
232
+ enabled=True,
233
+ description="Control: off",
234
+ tab="control",
235
+ )
236
+ plugin.add_cmd(
237
+ "tuya_device_toggle",
238
+ instruction="Toggle device state (reads current boolean DP).",
239
+ params=[
240
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
241
+ {"name": "code", "type": "str", "required": False, "description": "Preferred switch code"},
242
+ ],
243
+ enabled=True,
244
+ description="Control: toggle",
245
+ tab="control",
246
+ )
247
+
248
+ # Sensors
249
+ plugin.add_cmd(
250
+ "tuya_sensors_read",
251
+ instruction="Read and normalize common sensor values.",
252
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Sensor device ID"}],
253
+ enabled=True,
254
+ description="Sensors: read",
255
+ tab="sensors",
256
+ )
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2025.08.27 20:00:00 #
10
+ # ================================================== #
11
+
12
+ from pygpt_net.plugin.base.plugin import BasePlugin
13
+ from pygpt_net.core.events import Event
14
+ from pygpt_net.item.ctx import CtxItem
15
+
16
+ from .config import Config
17
+
18
+
19
+ class Plugin(BasePlugin):
20
+ def __init__(self, *args, **kwargs):
21
+ super(Plugin, self).__init__(*args, **kwargs)
22
+ self.id = "tuya"
23
+ self.name = "Tuya (IoT)"
24
+ self.description = "Handle Tuya Smart Home devices via Tuya Cloud API."
25
+ self.prefix = "API"
26
+ self.order = 100
27
+ self.allowed_cmds = [
28
+ "tuya_set_keys",
29
+ "tuya_set_uid",
30
+ "tuya_token_get",
31
+ "tuya_devices_list",
32
+ "tuya_device_get",
33
+ "tuya_device_status",
34
+ "tuya_device_functions",
35
+ "tuya_find_device",
36
+ "tuya_device_set",
37
+ "tuya_device_send",
38
+ "tuya_device_on",
39
+ "tuya_device_off",
40
+ "tuya_device_toggle",
41
+ "tuya_sensors_read"
42
+ ]
43
+ self.use_locale = False
44
+ self.worker = None
45
+ self.config = Config(self)
46
+ self.init_options()
47
+
48
+ def init_options(self):
49
+ """Initialize options"""
50
+ self.config.from_defaults(self)
51
+
52
+ def handle(self, event: Event, *args, **kwargs):
53
+ """
54
+ Handle dispatched event
55
+
56
+ :param event: event object
57
+ :param args: event args
58
+ :param kwargs: event kwargs
59
+ """
60
+ name = event.name
61
+ data = event.data
62
+ ctx = event.ctx
63
+
64
+ if name == Event.CMD_SYNTAX:
65
+ self.cmd_syntax(data)
66
+
67
+ elif name == Event.CMD_EXECUTE:
68
+ self.cmd(
69
+ ctx,
70
+ data['commands'],
71
+ )
72
+
73
+ def cmd_syntax(self, data: dict):
74
+ """
75
+ Event: CMD_SYNTAX
76
+
77
+ :param data: event data dict
78
+ """
79
+ for option in self.allowed_cmds:
80
+ if self.has_cmd(option):
81
+ data['cmd'].append(self.get_cmd(option)) # append command
82
+
83
+ def cmd(self, ctx: CtxItem, cmds: list):
84
+ """
85
+ Event: CMD_EXECUTE
86
+
87
+ :param ctx: CtxItem
88
+ :param cmds: commands dict
89
+ """
90
+ from .worker import Worker
91
+
92
+ is_cmd = False
93
+ my_commands = []
94
+ for item in cmds:
95
+ if item["cmd"] in self.allowed_cmds:
96
+ my_commands.append(item)
97
+ is_cmd = True
98
+
99
+ if not is_cmd:
100
+ return
101
+
102
+ # set state: busy
103
+ self.cmd_prepare(ctx, my_commands)
104
+
105
+ try:
106
+ worker = Worker()
107
+ worker.from_defaults(self)
108
+ worker.cmds = my_commands
109
+ worker.ctx = ctx
110
+
111
+ if not self.is_async(ctx):
112
+ worker.run()
113
+ return
114
+ worker.run_async()
115
+
116
+ except Exception as e:
117
+ self.error(e)