Wed, 08 Feb 2023 11:54:36 +0100
MicroPython
- added a menu entry to show the list of modules built into the firmware of the connected device
8122 | 1 | # -*- coding: utf-8 -*- |
2 | ||
9653
e67609152c5e
Updated copyright for 2023.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9496
diff
changeset
|
3 | # Copyright (c) 2021 - 2023 Detlev Offenbach <detlev@die-offenbachs.de> |
8122 | 4 | # |
5 | ||
6 | """ | |
7 | Module implementing the device interface class for RP2040 based boards | |
8 | (e.g. Raspberry Pi Pico). | |
9 | """ | |
10 | ||
9747 | 11 | from PyQt6.QtCore import QUrl, pyqtSlot |
12 | from PyQt6.QtNetwork import QNetworkRequest | |
8122 | 13 | |
9747 | 14 | from eric7 import Globals, Preferences |
15 | from eric7.EricWidgets import EricMessageBox | |
16 | from eric7.EricWidgets.EricApplication import ericApp | |
9473
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
17 | |
9747 | 18 | from .MicroPythonDevices import FirmwareGithubUrls, MicroPythonDevice |
8122 | 19 | from .MicroPythonWidget import HAS_QTCHART |
20 | ||
21 | ||
22 | class RP2040Device(MicroPythonDevice): | |
23 | """ | |
24 | Class implementing the device for RP2040 based boards. | |
25 | """ | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
26 | |
8122 | 27 | def __init__(self, microPythonWidget, deviceType, parent=None): |
28 | """ | |
29 | Constructor | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
30 | |
8122 | 31 | @param microPythonWidget reference to the main MicroPython widget |
32 | @type MicroPythonWidget | |
33 | @param deviceType device type assigned to this device interface | |
34 | @type str | |
35 | @param parent reference to the parent object | |
36 | @type QObject | |
37 | """ | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
38 | super().__init__(microPythonWidget, deviceType, parent) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
39 | |
8122 | 40 | def setButtons(self): |
41 | """ | |
42 | Public method to enable the supported action buttons. | |
43 | """ | |
8218
7c09585bd960
Applied some more code simplifications suggested by the new Simplify checker (super(Foo, self) => super()).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8122
diff
changeset
|
44 | super().setButtons() |
8122 | 45 | self.microPython.setActionButtons( |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
46 | run=True, repl=True, files=True, chart=HAS_QTCHART |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
47 | ) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
48 | |
8122 | 49 | def forceInterrupt(self): |
50 | """ | |
51 | Public method to determine the need for an interrupt when opening the | |
52 | serial connection. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
53 | |
8122 | 54 | @return flag indicating an interrupt is needed |
55 | @rtype bool | |
56 | """ | |
57 | return False | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
58 | |
8122 | 59 | def deviceName(self): |
60 | """ | |
61 | Public method to get the name of the device. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
62 | |
8122 | 63 | @return name of the device |
64 | @rtype str | |
65 | """ | |
66 | return self.tr("RP2040") | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
67 | |
8122 | 68 | def canStartRepl(self): |
69 | """ | |
70 | Public method to determine, if a REPL can be started. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
71 | |
8122 | 72 | @return tuple containing a flag indicating it is safe to start a REPL |
73 | and a reason why it cannot. | |
74 | @rtype tuple of (bool, str) | |
75 | """ | |
76 | return True, "" | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
77 | |
8122 | 78 | def canStartPlotter(self): |
79 | """ | |
80 | Public method to determine, if a Plotter can be started. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
81 | |
8122 | 82 | @return tuple containing a flag indicating it is safe to start a |
83 | Plotter and a reason why it cannot. | |
84 | @rtype tuple of (bool, str) | |
85 | """ | |
86 | return True, "" | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
87 | |
8122 | 88 | def canRunScript(self): |
89 | """ | |
90 | Public method to determine, if a script can be executed. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
91 | |
8122 | 92 | @return tuple containing a flag indicating it is safe to start a |
93 | Plotter and a reason why it cannot. | |
94 | @rtype tuple of (bool, str) | |
95 | """ | |
96 | return True, "" | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
97 | |
8122 | 98 | def runScript(self, script): |
99 | """ | |
100 | Public method to run the given Python script. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
101 | |
8122 | 102 | @param script script to be executed |
103 | @type str | |
104 | """ | |
105 | pythonScript = script.split("\n") | |
106 | self.sendCommands(pythonScript) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
107 | |
8122 | 108 | def canStartFileManager(self): |
109 | """ | |
110 | Public method to determine, if a File Manager can be started. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
111 | |
8122 | 112 | @return tuple containing a flag indicating it is safe to start a |
113 | File Manager and a reason why it cannot. | |
114 | @rtype tuple of (bool, str) | |
115 | """ | |
116 | return True, "" | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
117 | |
8122 | 118 | def addDeviceMenuEntries(self, menu): |
119 | """ | |
120 | Public method to add device specific entries to the given menu. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
121 | |
8122 | 122 | @param menu reference to the context menu |
123 | @type QMenu | |
124 | """ | |
125 | connected = self.microPython.isConnected() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
126 | |
9747 | 127 | menu.addAction( |
128 | self.tr("Show MicroPython Versions"), self.__showFirmwareVersions | |
129 | ).setEnabled(connected) | |
130 | menu.addAction( | |
131 | self.tr("Activate Bootloader"), self.__activateBootloader | |
132 | ).setEnabled(connected) | |
133 | menu.addAction( | |
134 | self.tr("Flash MicroPython Firmware"), self.__flashPython | |
135 | ).setEnabled(not connected) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
136 | |
8122 | 137 | def hasFlashMenuEntry(self): |
138 | """ | |
139 | Public method to check, if the device has its own flash menu entry. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
140 | |
8122 | 141 | @return flag indicating a specific flash menu entry |
142 | @rtype bool | |
143 | """ | |
144 | return True | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
145 | |
8122 | 146 | @pyqtSlot() |
147 | def __flashPython(self): | |
148 | """ | |
149 | Private slot to flash a MicroPython firmware to the device. | |
150 | """ | |
151 | from .UF2FlashDialog import UF2FlashDialog | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
152 | |
8122 | 153 | dlg = UF2FlashDialog(boardType="rp2040") |
154 | dlg.exec() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
155 | |
8122 | 156 | def __activateBootloader(self): |
157 | """ | |
158 | Private method to switch the board into 'bootloader' mode. | |
159 | """ | |
160 | if self.microPython.isConnected(): | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
161 | self.microPython.commandsInterface().execute( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
162 | [ |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
163 | "import machine", |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
164 | "machine.bootloader()", |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
165 | ] |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
166 | ) |
8122 | 167 | # simulate pressing the disconnect button |
168 | self.microPython.on_connectButton_clicked() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
169 | |
9747 | 170 | @pyqtSlot() |
171 | def __showFirmwareVersions(self): | |
172 | """ | |
173 | Private slot to show the firmware version of the connected device and the | |
174 | available firmware version. | |
175 | """ | |
176 | if self.microPython.isConnected(): | |
177 | interface = self.microPython.commandsInterface() | |
178 | if interface is not None: | |
179 | impInfo = interface.getImplementation() | |
180 | if impInfo["name"] != "micropython": | |
181 | EricMessageBox.critical( | |
182 | None, | |
183 | self.tr("Show MicroPython Versions"), | |
184 | self.tr( | |
185 | """The firmware of the connected device cannot be""" | |
186 | """ determined or the board does not run MicroPython.""" | |
187 | """ Aborting...""" | |
188 | ), | |
189 | ) | |
190 | else: | |
191 | if impInfo["variant"] == "Pimoroni": | |
192 | # MicroPython with Pimoroni add-on libraries | |
193 | url = QUrl(FirmwareGithubUrls["pimoroni_pico"]) | |
194 | else: | |
195 | url = QUrl(FirmwareGithubUrls["micropython"]) | |
196 | ui = ericApp().getObject("UserInterface") | |
197 | request = QNetworkRequest(url) | |
198 | reply = ui.networkAccessManager().head(request) | |
199 | reply.finished.connect( | |
9748 | 200 | lambda: self.__firmwareVersionResponse(reply, impInfo) |
9747 | 201 | ) |
202 | ||
203 | def __firmwareVersionResponse(self, reply, implementation): | |
204 | """ | |
205 | Private method handling the response of the latest version request. | |
206 | ||
207 | @param reply reference to the reply object | |
208 | @type QNetworkReply | |
209 | @param implementation dictionary containing the implementation data of the | |
210 | connected device | |
211 | @type dict | |
212 | """ | |
213 | latestUrl = reply.url().toString() | |
214 | tag = latestUrl.rsplit("/", 1)[-1] | |
215 | while tag and not tag[0].isdecimal(): | |
216 | # get rid of leading non-decimal characters | |
217 | tag = tag[1:] | |
218 | latestVersion = Globals.versionToTuple(tag) | |
219 | ||
220 | if implementation["version"] == "unknown": | |
221 | currentVersionStr = self.tr("unknown") | |
222 | currentVersion = (0, 0, 0) | |
223 | else: | |
224 | currentVersionStr = implementation["version"] | |
225 | currentVersion = Globals.versionToTuple(currentVersionStr) | |
226 | ||
227 | msg = self.tr( | |
228 | "<h4>MicroPython Version Information</h4>" | |
229 | "<table>" | |
230 | "<tr><td>Installed:</td><td>{0}</td><td></td></tr>" | |
231 | "<tr><td>Available:</td><td>{1}</td><td></td>{2}</tr>" | |
232 | "</table>" | |
233 | ).format( | |
234 | currentVersionStr, | |
235 | tag, | |
236 | self.tr("({0})").format(implementation["variant"]) | |
237 | if implementation["variant"] | |
238 | else "", | |
239 | ) | |
240 | if ( | |
241 | implementation["variant"] not in ["Pimoroni"] | |
242 | and currentVersion < latestVersion | |
243 | ): | |
244 | # cannot derive that info for 'Pimoroni' variant | |
245 | msg += self.tr("<p><b>Update available!</b></p>") | |
246 | ||
247 | EricMessageBox.information( | |
248 | None, | |
249 | self.tr("MicroPython Version"), | |
250 | msg, | |
251 | ) | |
252 | ||
8122 | 253 | def getDocumentationUrl(self): |
254 | """ | |
255 | Public method to get the device documentation URL. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
256 | |
8122 | 257 | @return documentation URL of the device |
258 | @rtype str | |
259 | """ | |
260 | return Preferences.getMicroPython("MicroPythonDocuUrl") | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
261 | |
8122 | 262 | def getDownloadMenuEntries(self): |
263 | """ | |
264 | Public method to retrieve the entries for the downloads menu. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
265 | |
8122 | 266 | @return list of tuples with menu text and URL to be opened for each |
267 | entry | |
268 | @rtype list of tuple of (str, str) | |
269 | """ | |
270 | return [ | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
271 | ( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
272 | self.tr("MicroPython Firmware"), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
273 | Preferences.getMicroPython("MicroPythonFirmwareUrl"), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
274 | ), |
8122 | 275 | ("<separator>", ""), |
9748 | 276 | (self.tr("Pimoroni Pico Firmware"), FirmwareGithubUrls["pimoroni_pico"]), |
9747 | 277 | ("<separator>", ""), |
278 | ( | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
279 | self.tr("CircuitPython Firmware"), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
280 | Preferences.getMicroPython("CircuitPythonFirmwareUrl"), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
281 | ), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
282 | ( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
283 | self.tr("CircuitPython Libraries"), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
284 | Preferences.getMicroPython("CircuitPythonLibrariesUrl"), |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
285 | ), |
8122 | 286 | ] |
9496
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
287 | |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
288 | |
9738 | 289 | def createDevice(microPythonWidget, deviceType, vid, pid, boardName): |
9496
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
290 | """ |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
291 | Function to instantiate a MicroPython device object. |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
292 | |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
293 | @param microPythonWidget reference to the main MicroPython widget |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
294 | @type MicroPythonWidget |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
295 | @param deviceType device type assigned to this device interface |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
296 | @type str |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
297 | @param vid vendor ID |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
298 | @type int |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
299 | @param pid product ID |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
300 | @type int |
9738 | 301 | @param boardName name of the board |
302 | @type str | |
9496
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
303 | @return reference to the instantiated device object |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
304 | @rtype RP2040Device |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
305 | """ |
05017f795c24
Changed MicroPython device imports to use importlib.import_module().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9473
diff
changeset
|
306 | return RP2040Device(microPythonWidget, deviceType) |