src/eric7/MicroPython/MicroPythonDevices.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 9051
903d596d7b17
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2019 - 2022 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 logging
12 import os
13
14 from PyQt6.QtCore import pyqtSlot, QObject, QCoreApplication
15 from PyQt6.QtWidgets import QInputDialog
16
17 from EricWidgets.EricApplication import ericApp
18
19 import UI.PixmapCache
20 import Preferences
21
22
23 SupportedBoards = {
24 "esp": {
25 "ids": [
26 (0x0403, 0x6001), # M5Stack ESP32 device"),
27 (0x0403, 0x6001), # FT232/FT245 (XinaBox CW01, CW02)
28 (0x0403, 0x6010), # FT2232C/D/L/HL/Q (ESP-WROVER-KIT)
29 (0x0403, 0x6011), # FT4232
30 (0x0403, 0x6014), # FT232H
31 (0x0403, 0x6015), # Sparkfun ESP32
32 (0x0403, 0x601C), # FT4222H
33 (0x10C4, 0xEA60), # CP210x
34 (0x1A86, 0x55D4), # CH343
35 (0x1A86, 0x7523), # HL-340, CH340
36 ],
37 "description": "ESP32, ESP8266",
38 "icon": "esp32Device",
39 "port_description": "",
40 },
41
42 "circuitpython": {
43 "ids": [
44 (0x04D8, 0xEA2A), # BHDynamics DynaLoRa_USB
45 (0x04D8, 0xEAD1), # BH Dynamics DynOSSAT-EDU-EPS-v1.0
46 (0x04D8, 0xEAD2), # BH Dynamics DynOSSAT-EDU-OBC-v1.0
47 (0x04D8, 0xEC44), # maholli PyCubed
48 (0x04D8, 0xEC63), # Kevin Neubauer CircuitBrains Basic
49 (0x04D8, 0xEC64), # Kevin Neubauer CircuitBrains Deluxe
50 (0x04D8, 0xEC72), # XinaBox CC03
51 (0x04D8, 0xEC75), # XinaBox CS11
52 (0x04D8, 0xED5F), # Itaca Innovation uChip CircuitPython
53 (0x04D8, 0xED94), # maholli kicksat-sprite
54 (0x04D8, 0xEDB3), # Capable Robot Programmable USB Hub
55 (0x04D8, 0xEDBE), # maholli SAM32
56 (0x04D8, 0xEE8C), # J&J Studios LLC datum-Distance
57 (0x04D8, 0xEE8D), # J&J Studios LLC datum-IMU
58 (0x04D8, 0xEE8E), # J&J Studios LLC datum-Light
59 (0x04D8, 0xEE8F), # J&J Studios LLC datum-Weather
60 (0x04D8, 0xEF67), # senseBox MCU
61 (0x054C, 0x0BC2), # Sony Spresense
62 (0x1209, 0x2017), # Benjamin Shockley Mini SAM M4
63 (0x1209, 0x3141), # CrumpSpace CrumpS2
64 (0x1209, 0x3252), # Targett Module Clip w/Wroom
65 (0x1209, 0x3253), # Targett Module Clip w/Wrover
66 (0x1209, 0x4D43), # Robotics Masters Robo HAT MM1 M4
67 (0x1209, 0x4DDD), # ODT CP Sapling
68 (0x1209, 0x4DDE), # ODT CP Sapling M0 w/ SPI Flash
69 (0x1209, 0x4DDF), # ODT CP Sapling Rev B
70 (0x1209, 0x4DF0), # Oak Dev Tech Pixelwing ESP32S2
71 (0x1209, 0x4DF1), # Oak Dev Tech BREAD2040
72 (0x1209, 0x4DF2), # Oak Dev Tech CAST AWAY RP2040
73 (0x1209, 0x5BF0), # Foosn Fomu
74 (0x1209, 0x7150), # Electronic Cats Hunter Cat NFC
75 (0x1209, 0x7382), # Invector Labs AB iLabs Challenger 840
76 (0x1209, 0x805A), # Electronic Cats BastBLE
77 (0x1209, 0xA182), # Solder Party RP2040 Stamp
78 (0x1209, 0xBAB0), # Electronic Cats Bast WiFi
79 (0x1209, 0xBAB1), # Electronic Cats Meow Meow
80 (0x1209, 0xBAB2), # Electronic Cats CatWAN USBStick
81 (0x1209, 0xBAB3), # Electronic Cats Bast Pro Mini M0
82 (0x1209, 0xBAB6), # Electronic Cats Escornabot Makech
83 (0x1209, 0xBAB8), # Electronic Cats NFC Copy Cat
84 (0x1209, 0xC051), # Betrusted Simmel
85 (0x1209, 0xD10D), # Diodes Delight Piunora
86 (0x1209, 0xE3E3), # StackRduino M0 PRO
87 (0x1209, 0xF500), # Silicognition LLC M4-Shim
88 (0x16D0, 0x08C6), # Pimoroni Keybow 2040
89 (0x16D0, 0x08C7), # Pimoroni Tiny 2040 (8MB)
90 (0x16D0, 0x08C8), # Pimoroni PicoSystem
91 (0x1915, 0xB001), # Makerdiary Pitaya Go
92 (0x192F, 0xB1B2), # WarmBit BluePixel nRF52840
93 (0x1B4F, 0x0015), # SparkFun RedBoard Turbo Board
94 (0x1B4F, 0x0016), # SparkFun SAMD51 Thing+
95 (0x1B4F, 0x0017), # SparkFun LUMIDrive Board
96 (0x1B4F, 0x0020), # SparkFun MicroMod SAMD51 Processor
97 (0x1B4F, 0x0021), # SparkFun MicroMod nRF52840 Processor
98 (0x1B4F, 0x0024), # SparkFun MicroMod RP2040 Processor
99 (0x1B4F, 0x0025), # SparkFun Thing Plus RP2040
100 (0x1B4F, 0x0026), # SparkFun Pro Micro RP2040
101 (0x1B4F, 0x0027), # SparkFun STM32 MicroMod Processor
102 (0x1B4F, 0x0028), # SparkFun Thing Plus - STM32
103 (0x1B4F, 0x002E), # PJRC/Sparkfun Teensy MicroMod
104 (0x1B4F, 0x5289), # SparkFun SFE_nRF52840_Mini
105 (0x1B4F, 0x8D22), # SparkFun SAMD21 Mini Breakout
106 (0x1B4F, 0x8D23), # SparkFun SAMD21 Dev Breakout
107 (0x1B4F, 0x8D24), # SparkFun Qwiic Micro
108 (0x1D50, 0x60E8), # Radomir Dopieralski PewPew M4
109 (0x1D50, 0x6152), # nrf52.jpconstantineau.com BlueMicro833
110 (0x1D50, 0x6153), # JPConstantineau PyKey18
111 (0x1D50, 0x6153), # JPConstantineau PyKey44
112 (0x1D50, 0x6153), # JPConstantineau PyKey60
113 (0x1D50, 0x6153), # JPConstantineau PyKey87
114 (0x1D50, 0x6154), # JPConstantineau EncoderPad RP2040
115 (0x1D50, 0x6161), # nrf52.jpconstantineau.com BlueMicro840
116 (0x2341, 0x8053), # Arduino MKR1300
117 (0x2341, 0x8057), # Arduino Nano 33 IoT
118 (0x2341, 0x805A), # Arduino Arduino_Nano_33_BLE
119 (0x2341, 0x824D), # Arduino Zero
120 (0x2786, 0x9207), # Switch Sc. BLE-SS dev board Multi Sensor
121 (0x2786, 0x920D), # Switch Sc. SSCI ISP1807 Dev Board
122 (0x2786, 0x920F), # Switch Sc. SSCI ISP1807 Micro Board
123 (0x2886, 0x002F), # Seeed Seeeduino XIAO
124 (0x2886, 0x0042), # Seeed Seeeduino XIAO RP2040
125 (0x2886, 0x0045), # Seeed XIAO nRF52840 Sense
126 (0x2886, 0x802D), # Seeed Seeeduino Wio Terminal
127 (0x2886, 0x802F), # Seeed Seeeduino XIAO KB
128 (0x2886, 0xF001), # Makerdiary nRF52840 M.2 Developer Kit
129 (0x2886, 0xF002), # Makerdiary M60 Keyboard
130 (0x2B04, 0xC00C), # Particle Argon
131 (0x2B04, 0xC00D), # Particle Boron
132 (0x2B04, 0xC00E), # Particle Xenon
133 (0x2E8A, 0x1000), # Cytron Maker Pi RP2040
134 (0x2E8A, 0x1002), # Pimoroni Pico LiPo (4MB)
135 (0x2E8A, 0x1003), # Pimoroni Pico LiPo (16MB)
136 (0x2E8A, 0x1005), # Melopero Shake RP2040
137 (0x2E8A, 0x1006), # Invector Labs Challenger RP2040 WiFi
138 (0x2E8A, 0x1008), # Pimoroni PGA2040
139 (0x2E8A, 0x1009), # Pimoroni Interstate 75
140 (0x2E8A, 0x100A), # Pimoroni Plasma 2040
141 (0x2E8A, 0x100B), # Invector Labs Challenger RP2040 LTE
142 (0x2E8A, 0x100D), # Invector Labs Challenger NB RP2040 WiFi
143 (0x2E8A, 0x100E), # Raspberry Pi Zero
144 (0x2E8A, 0x100F), # Cytron Maker Nano RP2040
145 (0x2E8A, 0x1012), # Raspberry Pi Compute Module 4 IO Board
146 (0x2E8A, 0x1013), # Raspberry Pi 4B
147 (0x2E8A, 0x1014), # Raspberry Pi Compute Module 4
148 (0x2E8A, 0x1015), # Raspberry Pi Zero 2W
149 (0x2E8A, 0x1016), # Pimoroni Tiny 2040 (2MB)
150 (0x2E8A, 0x1019), # Pimoroni Motor 2040
151 (0x2E8A, 0x101A), # Pimoroni Servo 2040
152 (0x2E8A, 0x101B), # Pimoroni Badger 2040
153 (0x2E8A, 0x101E), # Raspberry Pi Zero W
154 (0x2E8A, 0x101F), # Waveshare Electronics RP2040-Zero
155 (0x2E8A, 0x1026), # ELECFREAKS Pico:ed
156 (0x2E8A, 0x1027), # WIZnet W5100S-EVB-Pico
157 (0x303A, 0x7001), # Espressif ESP32-S2-HMI-DevKit-1
158 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1
159 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N8
160 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N8R2
161 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N8R8
162 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-nopsram
163 (0x303A, 0x7005), # Espressif ESP32-S3-Box-2.5
164 (0x303A, 0x7007), # Espressif ESP32-S3-DevKitM-1-N8
165 (0x303A, 0x7009), # Espressif ESP32-S2-DevKitC-1-N4
166 (0x303A, 0x7009), # Espressif ESP32-S2-DevKitC-1-N4R2
167 (0x303A, 0x700B), # Espressif ESP32-S3-USB-OTG-N8
168 (0x303A, 0x8002), # UnexpectedMaker TinyS2
169 (0x303A, 0x8007), # LILYGO TTGO T8 ESP32-S2
170 (0x303A, 0x800D), # Gravitech Cucumber RS
171 (0x303A, 0x80A1), # Gravitech Cucumber R
172 (0x303A, 0x80A4), # Gravitech Cucumber M
173 (0x303A, 0x80A7), # Gravitech Cucumber MS
174 (0x303A, 0x80AA), # Espressif Franzininho WIFI w/Wroom
175 (0x303A, 0x80AD), # Espressif Franzininho WIFI w/Wrover
176 (0x303A, 0x80AF), # Artisense Reference Design RD00
177 (0x303A, 0x80B2), # Muselab nanoESP32-S2 w/Wrover
178 (0x303A, 0x80B5), # UnexpectedMaker FeatherS2 Neo
179 (0x303A, 0x80B7), # MORPHEANS MORPHESP-240
180 (0x303A, 0x80C3), # Lolin S2 Mini
181 (0x303A, 0x80C6), # Lolin S2 Pico
182 (0x303A, 0x80D1), # UnexpectedMaker TinyS3
183 (0x303A, 0x80D4), # UnexpectedMaker ProS3
184 (0x303A, 0x80D7), # UnexpectedMaker FeatherS3
185 (0x303A, 0x80D9), # FutureKeys HexKy_S2
186 (0x303A, 0x80E8), # HiiBot IoTs2
187 (0x303A, 0x80EA), # LILYGO TTGO T8 ESP32-S2-WROOM
188 (0x303A, 0x80ED), # LILYGO TTGO T8 ESP32-S2
189 (0x30A4, 0x0002), # Blues Inc. Swan R5
190 (0x3171, 0x0101), # 8086.net Commander
191 (0x31E2, 0x2001), # BDMICRO LLC VINA-D21
192 (0x31E2, 0x2011), # BDMICRO LLC VINA-D51
193 (0x31E2, 0x2021), # BDMICRO LLC VINA-D51
194 (0x32BD, 0x3001), # Alorium Tech. AloriumTech Evo M51
195 (0x4097, 0x0001), # TG-Boards Datalore IP M4
196 (0x612B, 0x80A7), # Ai-Thinker ESP 12k NodeMCU
197
198 (0x239A, None), # Any Adafruit Boards
199 ],
200 "description": "CircuitPython",
201 "icon": "circuitPythonDevice",
202 "port_description": "",
203 },
204
205 "bbc_microbit": {
206 "ids": [
207 (0x0D28, 0x0204), # micro:bit
208 ],
209 "description": "BBC micro:bit",
210 "icon": "microbitDevice",
211 "port_description": "BBC micro:bit CMSIS-DAP",
212 },
213
214 "calliope": {
215 "ids": [
216 (0x0D28, 0x0204), # Calliope mini
217 ],
218 "description": "Calliope mini",
219 "icon": "calliope_mini",
220 "port_description": "DAPLink CMSIS-DAP",
221 },
222
223 "pyboard": {
224 "ids": [
225 (0xF055, 0x9800), # Pyboard in CDC mode
226 (0xF055, 0x9801), # Pyboard in CDC+HID mode
227 (0xF055, 0x9802), # Pyboard in CDC+MSC mode
228 ],
229 "description": "PyBoard",
230 "icon": "micropython48",
231 "port_description": "",
232 },
233
234 "rp2040": {
235 "ids": [
236 (0x2E8A, 0x0005), # Raspberry Pi Pico
237 ],
238 "description": QCoreApplication.translate(
239 "MicroPythonDevice", "RP2040 based"),
240 "icon": "rp2040Device",
241 "port_description": "",
242 },
243
244 "generic": {
245 # only manually configured devices use this
246 "ids": [],
247 "description": QCoreApplication.translate(
248 "MicroPythonDevice", "Generic Board"),
249 "icon": "micropython48",
250 "port_description": "",
251 },
252 }
253
254 IgnoredBoards = (
255 (0x8086, 0x9c3d),
256 (0x8086, None),
257 )
258
259
260 def getSupportedDevices():
261 """
262 Function to get a list of supported MicroPython devices.
263
264 @return set of tuples with the board type and description
265 @rtype set of tuples of (str, str)
266 """
267 boards = []
268 for board in SupportedBoards:
269 boards.append(
270 (board, SupportedBoards[board]["description"]))
271 return boards
272
273
274 def getFoundDevices():
275 """
276 Function to check the serial ports for supported MicroPython devices.
277
278 @return tuple containing a list of tuples with the board type, the port
279 description, a description, the serial port it is connected at, the
280 VID and PID for known device types, a list of tuples with VID, PID
281 and description for unknown devices and a list of tuples with VID,
282 PID, description and port name for ports with missing VID or PID
283 @rtype tuple of (list of tuples of (str, str, str, str, int, int),
284 list of tuples of (int, int, str),
285 list of tuples of (int, int, str, str)
286 """
287 from PyQt6.QtSerialPort import QSerialPortInfo
288
289 foundDevices = []
290 unknownDevices = []
291 unknownPorts = []
292
293 manualDevices = {}
294 for deviceDict in Preferences.getMicroPython("ManualDevices"):
295 manualDevices[(deviceDict["vid"], deviceDict["pid"])] = deviceDict
296
297 availablePorts = QSerialPortInfo.availablePorts()
298 for port in availablePorts:
299 if port.hasVendorIdentifier() and port.hasProductIdentifier():
300 supported = False
301 vid = port.vendorIdentifier()
302 pid = port.productIdentifier()
303
304 for board in SupportedBoards:
305 if (
306 (vid, pid) in SupportedBoards[board]["ids"] or
307 (vid, None) in SupportedBoards[board]["ids"]
308 ):
309 if (
310 board in ("bbc_microbit", "calliope") and
311 (port.description().strip() !=
312 SupportedBoards[board]["port_description"])
313 ):
314 # both boards have the same VID and PID
315 # try to differentiate based on port description
316 continue
317 foundDevices.append((
318 board,
319 port.description(),
320 SupportedBoards[board]["description"],
321 port.portName(),
322 vid,
323 pid,
324 ))
325 supported = True
326 if not supported and (vid, pid) in manualDevices:
327 # check the locally added ones next
328 board = manualDevices[(vid, pid)]["type"]
329 foundDevices.append((
330 board,
331 port.description(),
332 SupportedBoards[board]["description"],
333 port.portName(),
334 vid,
335 pid,
336 ))
337 supported = True
338 if not supported:
339 if vid and pid:
340 if (
341 (vid, pid) not in IgnoredBoards and
342 (vid, None) not in IgnoredBoards
343 ):
344 unknownDevices.append((vid, pid, port.description()))
345 logging.debug("Unknown device: (0x%04x:0x%04x %s)",
346 vid, pid, port.description())
347 else:
348 # either VID or PID or both not detected
349 desc = port.description()
350 if not desc:
351 desc = QCoreApplication.translate("MicroPythonDevice",
352 "Unknown Device")
353 unknownPorts.append((vid, pid, desc, port.portName()))
354
355 return foundDevices, unknownDevices, unknownPorts
356
357
358 def getDeviceIcon(boardName, iconFormat=True):
359 """
360 Function to get the icon for the given board.
361
362 @param boardName name of the board
363 @type str
364 @param iconFormat flag indicating to get an icon or a pixmap
365 @type bool
366 @return icon for the board (iconFormat == True) or
367 a pixmap (iconFormat == False)
368 @rtype QIcon or QPixmap
369 """
370 iconName = (
371 SupportedBoards[boardName]["icon"]
372 if boardName in SupportedBoards else
373 # return a generic MicroPython icon
374 "micropython48"
375 )
376
377 if iconFormat:
378 return UI.PixmapCache.getIcon(iconName)
379 else:
380 return UI.PixmapCache.getPixmap(iconName)
381
382
383 def getDevice(deviceType, microPythonWidget, vid, pid):
384 """
385 Public method to instantiate a specific MicroPython device interface.
386
387 @param deviceType type of the device interface
388 @type str
389 @param microPythonWidget reference to the main MicroPython widget
390 @type MicroPythonWidget
391 @param vid vendor ID (only used for deviceType 'generic')
392 @type int
393 @param pid product ID (only used for deviceType 'generic')
394 @type int
395 @return instantiated device interface
396 @rtype MicroPythonDevice
397 """
398 if deviceType == "esp":
399 from .EspDevices import EspDevice
400 return EspDevice(microPythonWidget, deviceType)
401 elif deviceType == "circuitpython":
402 from .CircuitPythonDevices import CircuitPythonDevice
403 return CircuitPythonDevice(microPythonWidget, deviceType)
404 elif deviceType in ("bbc_microbit", "calliope"):
405 from .MicrobitDevices import MicrobitDevice
406 return MicrobitDevice(microPythonWidget, deviceType)
407 elif deviceType == "pyboard":
408 from .PyBoardDevices import PyBoardDevice
409 return PyBoardDevice(microPythonWidget, deviceType)
410 elif deviceType == "rp2040":
411 from .RP2040Devices import RP2040Device
412 return RP2040Device(microPythonWidget, deviceType)
413 elif deviceType == "generic":
414 from .GenericMicroPythonDevices import GenericMicroPythonDevice
415 return GenericMicroPythonDevice(microPythonWidget, deviceType,
416 vid, pid)
417 else:
418 # nothing specific requested
419 return MicroPythonDevice(microPythonWidget, deviceType)
420
421
422 class MicroPythonDevice(QObject):
423 """
424 Base class for the more specific MicroPython devices.
425 """
426 def __init__(self, microPythonWidget, deviceType, parent=None):
427 """
428 Constructor
429
430 @param microPythonWidget reference to the main MicroPython widget
431 @type MicroPythonWidget
432 @param deviceType device type assigned to this device interface
433 @type str
434 @param parent reference to the parent object
435 @type QObject
436 """
437 super().__init__(parent)
438
439 self._deviceType = deviceType
440 self.microPython = microPythonWidget
441
442 def getDeviceType(self):
443 """
444 Public method to get the device type.
445
446 @return type of the device
447 @rtype str
448 """
449 return self._deviceType
450
451 def setButtons(self):
452 """
453 Public method to enable the supported action buttons.
454 """
455 self.microPython.setActionButtons(
456 open=False, save=False,
457 run=False, repl=False, files=False, chart=False)
458
459 def forceInterrupt(self):
460 """
461 Public method to determine the need for an interrupt when opening the
462 serial connection.
463
464 @return flag indicating an interrupt is needed
465 @rtype bool
466 """
467 return True
468
469 def deviceName(self):
470 """
471 Public method to get the name of the device.
472
473 @return name of the device
474 @rtype str
475 """
476 return self.tr("Unsupported Device")
477
478 def canStartRepl(self):
479 """
480 Public method to determine, if a REPL can be started.
481
482 @return tuple containing a flag indicating it is safe to start a REPL
483 and a reason why it cannot.
484 @rtype tuple of (bool, str)
485 """
486 return False, self.tr("REPL is not supported by this device.")
487
488 def setRepl(self, on):
489 """
490 Public method to set the REPL status and dependent status.
491
492 @param on flag indicating the active status
493 @type bool
494 """
495 pass
496
497 def canStartPlotter(self):
498 """
499 Public method to determine, if a Plotter can be started.
500
501 @return tuple containing a flag indicating it is safe to start a
502 Plotter and a reason why it cannot.
503 @rtype tuple of (bool, str)
504 """
505 return False, self.tr("Plotter is not supported by this device.")
506
507 def setPlotter(self, on):
508 """
509 Public method to set the Plotter status and dependent status.
510
511 @param on flag indicating the active status
512 @type bool
513 """
514 pass
515
516 def canRunScript(self):
517 """
518 Public method to determine, if a script can be executed.
519
520 @return tuple containing a flag indicating it is safe to start a
521 Plotter and a reason why it cannot.
522 @rtype tuple of (bool, str)
523 """
524 return False, self.tr("Running scripts is not supported by this"
525 " device.")
526
527 def runScript(self, script):
528 """
529 Public method to run the given Python script.
530
531 @param script script to be executed
532 @type str
533 """
534 pass
535
536 def canStartFileManager(self):
537 """
538 Public method to determine, if a File Manager can be started.
539
540 @return tuple containing a flag indicating it is safe to start a
541 File Manager and a reason why it cannot.
542 @rtype tuple of (bool, str)
543 """
544 return False, self.tr("File Manager is not supported by this device.")
545
546 def setFileManager(self, on):
547 """
548 Public method to set the File Manager status and dependent status.
549
550 @param on flag indicating the active status
551 @type bool
552 """
553 pass
554
555 def supportsLocalFileAccess(self):
556 """
557 Public method to indicate file access via a local directory.
558
559 @return flag indicating file access via local directory
560 @rtype bool
561 """
562 return False # default
563
564 def getWorkspace(self):
565 """
566 Public method to get the workspace directory.
567
568 @return workspace directory used for saving files
569 @rtype str
570 """
571 return (
572 Preferences.getMicroPython("MpyWorkspace") or
573 Preferences.getMultiProject("Workspace") or
574 os.path.expanduser("~")
575 )
576
577 def selectDeviceDirectory(self, deviceDirectories):
578 """
579 Public method to select the device directory from a list of detected
580 ones.
581
582 @param deviceDirectories list of directories to select from
583 @type list of str
584 @return selected directory or an empty string
585 @rtype str
586 """
587 deviceDirectory, ok = QInputDialog.getItem(
588 None,
589 self.tr("Select Device Directory"),
590 self.tr("Select the directory for the connected device:"),
591 [""] + deviceDirectories,
592 0, False)
593 if ok:
594 return deviceDirectory
595 else:
596 # user cancelled
597 return ""
598
599 def sendCommands(self, commandsList):
600 """
601 Public method to send a list of commands to the device.
602
603 @param commandsList list of commands to be sent to the device
604 @type list of str
605 """
606 rawOn = [ # sequence of commands to enter raw mode
607 b'\x02', # Ctrl-B: exit raw repl (just in case)
608 b'\r\x03\x03\x03', # Ctrl-C three times: interrupt any running
609 # program
610 b'\r\x01', # Ctrl-A: enter raw REPL
611 ]
612 newLine = [b'print("\\n")\r', ]
613 commands = [c.encode("utf-8)") + b'\r' for c in commandsList]
614 commands.append(b'\r')
615 commands.append(b'\x04')
616 rawOff = [b'\x02', b'\x02']
617 commandSequence = rawOn + newLine + commands + rawOff
618 self.microPython.commandsInterface().executeAsync(commandSequence)
619
620 @pyqtSlot()
621 def handleDataFlood(self):
622 """
623 Public slot handling a data floof from the device.
624 """
625 pass
626
627 def addDeviceMenuEntries(self, menu):
628 """
629 Public method to add device specific entries to the given menu.
630
631 @param menu reference to the context menu
632 @type QMenu
633 """
634 pass
635
636 def hasFlashMenuEntry(self):
637 """
638 Public method to check, if the device has its own flash menu entry.
639
640 @return flag indicating a specific flash menu entry
641 @rtype bool
642 """
643 return False
644
645 def hasTimeCommands(self):
646 """
647 Public method to check, if the device supports time commands.
648
649 The default returns True.
650
651 @return flag indicating support for time commands
652 @rtype bool
653 """
654 return True
655
656 def hasDocumentationUrl(self):
657 """
658 Public method to check, if the device has a configured documentation
659 URL.
660
661 @return flag indicating a configured documentation URL
662 @rtype bool
663 """
664 return bool(self.getDocumentationUrl())
665
666 def getDocumentationUrl(self):
667 """
668 Public method to get the device documentation URL.
669
670 @return documentation URL of the device
671 @rtype str
672 """
673 return ""
674
675 def hasFirmwareUrl(self):
676 """
677 Public method to check, if the device has a configured firmware
678 download URL.
679
680 @return flag indicating a configured firmware download URL
681 @rtype bool
682 """
683 return bool(self.getFirmwareUrl())
684
685 def getFirmwareUrl(self):
686 """
687 Public method to get the device firmware download URL.
688
689 @return firmware download URL of the device
690 @rtype str
691 """
692 return ""
693
694 def downloadFirmware(self):
695 """
696 Public method to download the device firmware.
697 """
698 url = self.getFirmwareUrl()
699 if url:
700 ericApp().getObject("UserInterface").launchHelpViewer(url)
701
702 def getDownloadMenuEntries(self):
703 """
704 Public method to retrieve the entries for the downloads menu.
705
706 @return list of tuples with menu text and URL to be opened for each
707 entry
708 @rtype list of tuple of (str, str)
709 """
710 return []

eric ide

mercurial