src/eric7/MicroPython/Devices/DeviceBase.py

branch
eric7
changeset 9756
9854647c8c5c
parent 9755
1a09700229e7
child 9763
52f982c08301
equal deleted inserted replaced
9755:1a09700229e7 9756:9854647c8c5c
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2019 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing some utility functions and the MicroPythonDevice base
8 class.
9 """
10
11 import contextlib
12 import copy
13 import os
14
15 from PyQt6.QtCore import QObject, pyqtSlot
16 from PyQt6.QtWidgets import QInputDialog
17
18 from eric7 import Preferences
19 from eric7.EricWidgets import EricMessageBox
20 from eric7.EricWidgets.EricApplication import ericApp
21
22
23 class BaseDevice(QObject):
24 """
25 Base class for the more specific MicroPython devices.
26 """
27
28 def __init__(self, microPythonWidget, deviceType, parent=None):
29 """
30 Constructor
31
32 @param microPythonWidget reference to the main MicroPython widget
33 @type MicroPythonWidget
34 @param deviceType device type assigned to this device interface
35 @type str
36 @param parent reference to the parent object
37 @type QObject
38 """
39 super().__init__(parent)
40
41 self._deviceType = deviceType
42 self.microPython = microPythonWidget
43 self._deviceData = {} # dictionary with essential device data
44
45 def setConnected(self, connected):
46 """
47 Public method to set the connection state.
48
49 Note: This method can be overwritten to perform actions upon connect
50 or disconnect of the device.
51
52 @param connected connection state
53 @type bool
54 """
55 self._deviceData = {}
56
57 if connected:
58 with contextlib.suppress(OSError):
59 self._deviceData = self.microPython.commandsInterface().getDeviceData()
60
61 def getDeviceType(self):
62 """
63 Public method to get the device type.
64
65 @return type of the device
66 @rtype str
67 """
68 return self._deviceType
69
70 def getDeviceData(self):
71 """
72 Public method to get a copy of the determined device data.
73
74 @return dictionary containing the essential device data
75 @rtype dict
76 """
77 return copy.deepcopy(self._deviceData)
78
79 def checkDeviceData(self):
80 """
81 Public method to check the validity of the device data determined during
82 connecting the device.
83
84 @return flag indicating valid device data
85 @rtype bool
86 """
87 if bool(self._deviceData):
88 return True
89 else:
90 EricMessageBox.critical(
91 None,
92 self.tr("Show MicroPython Versions"),
93 self.tr(
94 """<p>The device data is not available. Try to connect to the"""
95 """ device again. Aborting...</p>"""
96 ).format(self.getDeviceType()),
97 )
98 return False
99
100 def setButtons(self):
101 """
102 Public method to enable the supported action buttons.
103 """
104 self.microPython.setActionButtons(
105 open=False, save=False, run=False, repl=False, files=False, chart=False
106 )
107
108 def forceInterrupt(self):
109 """
110 Public method to determine the need for an interrupt when opening the
111 serial connection.
112
113 @return flag indicating an interrupt is needed
114 @rtype bool
115 """
116 return True
117
118 def deviceName(self):
119 """
120 Public method to get the name of the device.
121
122 @return name of the device
123 @rtype str
124 """
125 return self.tr("Unsupported Device")
126
127 def canStartRepl(self):
128 """
129 Public method to determine, if a REPL can be started.
130
131 @return tuple containing a flag indicating it is safe to start a REPL
132 and a reason why it cannot.
133 @rtype tuple of (bool, str)
134 """
135 return False, self.tr("REPL is not supported by this device.")
136
137 def setRepl(self, on):
138 """
139 Public method to set the REPL status and dependent status.
140
141 @param on flag indicating the active status
142 @type bool
143 """
144 pass
145
146 def canStartPlotter(self):
147 """
148 Public method to determine, if a Plotter can be started.
149
150 @return tuple containing a flag indicating it is safe to start a
151 Plotter and a reason why it cannot.
152 @rtype tuple of (bool, str)
153 """
154 return False, self.tr("Plotter is not supported by this device.")
155
156 def setPlotter(self, on):
157 """
158 Public method to set the Plotter status and dependent status.
159
160 @param on flag indicating the active status
161 @type bool
162 """
163 pass
164
165 def canRunScript(self):
166 """
167 Public method to determine, if a script can be executed.
168
169 @return tuple containing a flag indicating it is safe to start a
170 Plotter and a reason why it cannot.
171 @rtype tuple of (bool, str)
172 """
173 return False, self.tr("Running scripts is not supported by this device.")
174
175 def runScript(self, script):
176 """
177 Public method to run the given Python script.
178
179 @param script script to be executed
180 @type str
181 """
182 pass
183
184 def canStartFileManager(self):
185 """
186 Public method to determine, if a File Manager can be started.
187
188 @return tuple containing a flag indicating it is safe to start a
189 File Manager and a reason why it cannot.
190 @rtype tuple of (bool, str)
191 """
192 return False, self.tr("File Manager is not supported by this device.")
193
194 def setFileManager(self, on):
195 """
196 Public method to set the File Manager status and dependent status.
197
198 @param on flag indicating the active status
199 @type bool
200 """
201 pass
202
203 def supportsLocalFileAccess(self):
204 """
205 Public method to indicate file access via a local directory.
206
207 @return flag indicating file access via local directory
208 @rtype bool
209 """
210 return False # default
211
212 def getWorkspace(self):
213 """
214 Public method to get the workspace directory.
215
216 @return workspace directory used for saving files
217 @rtype str
218 """
219 return (
220 Preferences.getMicroPython("MpyWorkspace")
221 or Preferences.getMultiProject("Workspace")
222 or os.path.expanduser("~")
223 )
224
225 def selectDeviceDirectory(self, deviceDirectories):
226 """
227 Public method to select the device directory from a list of detected
228 ones.
229
230 @param deviceDirectories list of directories to select from
231 @type list of str
232 @return selected directory or an empty string
233 @rtype str
234 """
235 deviceDirectory, ok = QInputDialog.getItem(
236 None,
237 self.tr("Select Device Directory"),
238 self.tr("Select the directory for the connected device:"),
239 [""] + deviceDirectories,
240 0,
241 False,
242 )
243 if ok:
244 return deviceDirectory
245 else:
246 # user cancelled
247 return ""
248
249 def sendCommands(self, commandsList):
250 """
251 Public method to send a list of commands to the device.
252
253 @param commandsList list of commands to be sent to the device
254 @type list of str
255 """
256 rawOn = [ # sequence of commands to enter raw mode
257 b"\x02", # Ctrl-B: exit raw repl (just in case)
258 b"\r\x03\x03\x03", # Ctrl-C three times: interrupt any running
259 # program
260 b"\r\x01", # Ctrl-A: enter raw REPL
261 ]
262 newLine = [
263 b'print("\\n")\r',
264 ]
265 commands = [c.encode("utf-8)") + b"\r" for c in commandsList]
266 commands.append(b"\r")
267 commands.append(b"\x04")
268 rawOff = [b"\x02", b"\x02"]
269 commandSequence = rawOn + newLine + commands + rawOff
270 self.microPython.commandsInterface().executeAsync(commandSequence)
271
272 @pyqtSlot()
273 def handleDataFlood(self):
274 """
275 Public slot handling a data floof from the device.
276 """
277 pass
278
279 def addDeviceMenuEntries(self, menu):
280 """
281 Public method to add device specific entries to the given menu.
282
283 @param menu reference to the context menu
284 @type QMenu
285 """
286 pass
287
288 def hasFlashMenuEntry(self):
289 """
290 Public method to check, if the device has its own flash menu entry.
291
292 @return flag indicating a specific flash menu entry
293 @rtype bool
294 """
295 return False
296
297 def hasTimeCommands(self):
298 """
299 Public method to check, if the device supports time commands.
300
301 The default returns True.
302
303 @return flag indicating support for time commands
304 @rtype bool
305 """
306 return True
307
308 def hasDocumentationUrl(self):
309 """
310 Public method to check, if the device has a configured documentation
311 URL.
312
313 @return flag indicating a configured documentation URL
314 @rtype bool
315 """
316 return bool(self.getDocumentationUrl())
317
318 def getDocumentationUrl(self):
319 """
320 Public method to get the device documentation URL.
321
322 @return documentation URL of the device
323 @rtype str
324 """
325 return ""
326
327 def hasFirmwareUrl(self):
328 """
329 Public method to check, if the device has a configured firmware
330 download URL.
331
332 @return flag indicating a configured firmware download URL
333 @rtype bool
334 """
335 return bool(self.getFirmwareUrl())
336
337 def getFirmwareUrl(self):
338 """
339 Public method to get the device firmware download URL.
340
341 @return firmware download URL of the device
342 @rtype str
343 """
344 return ""
345
346 def downloadFirmware(self):
347 """
348 Public method to download the device firmware.
349 """
350 url = self.getFirmwareUrl()
351 if url:
352 ericApp().getObject("UserInterface").launchHelpViewer(url)
353
354 def getDownloadMenuEntries(self):
355 """
356 Public method to retrieve the entries for the downloads menu.
357
358 @return list of tuples with menu text and URL to be opened for each
359 entry
360 @rtype list of tuple of (str, str)
361 """
362 return []

eric ide

mercurial