116 @type QObject |
116 @type QObject |
117 """ |
117 """ |
118 super().__init__(parent) |
118 super().__init__(parent) |
119 |
119 |
120 self._deviceType = deviceType |
120 self._deviceType = deviceType |
121 self._interface = microPythonWidget.deviceInterface() |
121 self._interface = None |
122 self.microPython = microPythonWidget |
122 self.microPython = microPythonWidget |
123 self._deviceData = {} # dictionary with essential device data |
123 self._deviceData = {} # dictionary with essential device data |
124 |
124 |
125 self._submitMode = "raw" # default is 'raw' mode to submit commands |
125 self._submitMode = "raw" # default is 'raw' mode to submit commands |
126 |
126 |
135 @type bool |
135 @type bool |
136 """ |
136 """ |
137 self._deviceData = {} |
137 self._deviceData = {} |
138 |
138 |
139 if connected: |
139 if connected: |
|
140 self._interface = self.microPython.deviceInterface() |
140 with contextlib.suppress(OSError): |
141 with contextlib.suppress(OSError): |
141 self._deviceData = self.__getDeviceData() |
142 self._deviceData = self.__getDeviceData() |
142 self._deviceData["local_mip"] = ( |
143 self._deviceData["local_mip"] = ( |
143 not self._deviceData["mip"] and not self._deviceData["upip"] |
144 not self._deviceData["mip"] and not self._deviceData["upip"] |
144 ) |
145 ) |
147 ( |
148 ( |
148 self._deviceData["ethernet"], |
149 self._deviceData["ethernet"], |
149 self._deviceData["ethernet_type"], |
150 self._deviceData["ethernet_type"], |
150 ) = self.hasEthernet() |
151 ) = self.hasEthernet() |
151 self._deviceData["ntp"] = self.hasNetworkTime() |
152 self._deviceData["ntp"] = self.hasNetworkTime() |
|
153 else: |
|
154 self._interface = None |
152 |
155 |
153 def getDeviceType(self): |
156 def getDeviceType(self): |
154 """ |
157 """ |
155 Public method to get the device type. |
158 Public method to get the device type. |
156 |
159 |
379 return deviceDirectory |
382 return deviceDirectory |
380 else: |
383 else: |
381 # user cancelled |
384 # user cancelled |
382 return "" |
385 return "" |
383 |
386 |
|
387 def executeCommands(self, commands, *, mode="raw", timeout=0): |
|
388 """ |
|
389 Public method to send commands to the connected device and return the |
|
390 result. |
|
391 |
|
392 If no connected interface is available, empty results will be returned. |
|
393 |
|
394 @param commands list of commands to be executed |
|
395 @type str or list of str |
|
396 @keyparam mode submit mode to be used (one of 'raw' or 'paste') (defaults to |
|
397 'raw') |
|
398 @type str |
|
399 @keyparam timeout per command timeout in milliseconds (0 for configured default) |
|
400 (defaults to 0) |
|
401 @type int (optional) |
|
402 @return tuple containing stdout and stderr output of the device |
|
403 @rtype tuple of (bytes, bytes) |
|
404 """ |
|
405 if self._interface is None: |
|
406 return b"", b"" |
|
407 |
|
408 return self._interface.execute(commands, mode=mode, timeout=timeout) |
|
409 |
384 def sendCommands(self, commandsList): |
410 def sendCommands(self, commandsList): |
385 """ |
411 """ |
386 Public method to send a list of commands to the device. |
412 Public method to send a list of commands to the device. |
387 |
413 |
388 @param commandsList list of commands to be sent to the device |
414 @param commandsList list of commands to be sent to the device |
389 @type list of str |
415 @type list of str |
390 """ |
416 """ |
391 if self._submitMode == "raw": |
417 if self._interface is not None: |
392 rawOn = [ # sequence of commands to enter raw mode |
418 self._interface.executeAsync(commandsList, self._submitMode) |
393 b"\x02", # Ctrl-B: exit raw repl (just in case) |
|
394 b"\r\x03\x03\x03", # Ctrl-C three times: interrupt any running program |
|
395 b"\r\x01", # Ctrl-A: enter raw REPL |
|
396 ] |
|
397 newLine = [ |
|
398 b'print("\\n")\r', |
|
399 ] |
|
400 commands = [c.encode("utf-8)") + b"\r" for c in commandsList] |
|
401 commands.append(b"\r") |
|
402 commands.append(b"\x04") |
|
403 rawOff = [b"\x02", b"\x02"] |
|
404 commandSequence = rawOn + newLine + commands + rawOff |
|
405 self._interface.executeAsync(commandSequence) |
|
406 elif self._submitMode == "paste": |
|
407 commands = b"\n".join([c.encode("utf-8)") for c in commandsList]) |
|
408 commandSequence = ["@PasteOn@", commands] |
|
409 self._interface.executeAsyncPaste(commandSequence) |
|
410 |
419 |
411 @pyqtSlot() |
420 @pyqtSlot() |
412 def handleDataFlood(self): |
421 def handleDataFlood(self): |
413 """ |
422 """ |
414 Public slot handling a data floof from the device. |
423 Public slot handling a data floof from the device. |
541 print(False) |
550 print(False) |
542 del __os_ |
551 del __os_ |
543 """.format( |
552 """.format( |
544 repr(pathname) |
553 repr(pathname) |
545 ) |
554 ) |
546 out, err = self._interface.execute(command, mode=self._submitMode) |
555 out, err = self.executeCommands(command, mode=self._submitMode) |
547 if err: |
556 if err: |
548 raise OSError(self._shortError(err)) |
557 raise OSError(self._shortError(err)) |
549 return out.strip() == b"True" |
558 return out.strip() == b"True" |
550 |
559 |
551 def ls(self, dirname=""): |
560 def ls(self, dirname=""): |
563 print(__os_.listdir('{0}')) |
572 print(__os_.listdir('{0}')) |
564 del __os_ |
573 del __os_ |
565 """.format( |
574 """.format( |
566 dirname |
575 dirname |
567 ) |
576 ) |
568 out, err = self._interface.execute(command, mode=self._submitMode) |
577 out, err = self.executeCommands(command, mode=self._submitMode) |
569 if err: |
578 if err: |
570 raise OSError(self._shortError(err)) |
579 raise OSError(self._shortError(err)) |
571 return ast.literal_eval(out.decode("utf-8")) |
580 return ast.literal_eval(out.decode("utf-8")) |
572 |
581 |
573 def lls(self, dirname="", fullstat=False, showHidden=False): |
582 def lls(self, dirname="", fullstat=False, showHidden=False): |
615 print(listdir_stat('{0}', {1})) |
624 print(listdir_stat('{0}', {1})) |
616 del __os_, stat, listdir_stat, is_visible |
625 del __os_, stat, listdir_stat, is_visible |
617 """.format( |
626 """.format( |
618 dirname, showHidden |
627 dirname, showHidden |
619 ) |
628 ) |
620 out, err = self._interface.execute(command, mode=self._submitMode) |
629 out, err = self.executeCommands(command, mode=self._submitMode) |
621 if err: |
630 if err: |
622 raise OSError(self._shortError(err)) |
631 raise OSError(self._shortError(err)) |
623 fileslist = ast.literal_eval(out.decode("utf-8")) |
632 fileslist = ast.literal_eval(out.decode("utf-8")) |
624 if fileslist is None: |
633 if fileslist is None: |
625 return None |
634 return None |
660 command = """ |
669 command = """ |
661 import os as __os_ |
670 import os as __os_ |
662 print(__os_.getcwd()) |
671 print(__os_.getcwd()) |
663 del __os_ |
672 del __os_ |
664 """ |
673 """ |
665 out, err = self._interface.execute(command, mode=self._submitMode) |
674 out, err = self.executeCommands(command, mode=self._submitMode) |
666 if err: |
675 if err: |
667 raise OSError(self._shortError(err)) |
676 raise OSError(self._shortError(err)) |
668 return out.decode("utf-8").strip() |
677 return out.decode("utf-8").strip() |
669 |
678 |
670 def rm(self, filename): |
679 def rm(self, filename): |
685 raise err |
694 raise err |
686 del __os_ |
695 del __os_ |
687 """.format( |
696 """.format( |
688 filename |
697 filename |
689 ) |
698 ) |
690 out, err = self._interface.execute(command, mode=self._submitMode) |
699 out, err = self.executeCommands(command, mode=self._submitMode) |
691 if err: |
700 if err: |
692 raise OSError(self._shortError(err)) |
701 raise OSError(self._shortError(err)) |
693 |
702 |
694 def rmrf(self, name, recursive=False, force=False): |
703 def rmrf(self, name, recursive=False, force=False): |
695 """ |
704 """ |
732 print(remove_file('{0}', {1}, {2})) |
741 print(remove_file('{0}', {1}, {2})) |
733 del __os_, remove_file |
742 del __os_, remove_file |
734 """.format( |
743 """.format( |
735 name, recursive, force |
744 name, recursive, force |
736 ) |
745 ) |
737 out, err = self._interface.execute( |
746 out, err = self.executeCommands( |
738 command, mode=self._submitMode, timeout=20000 |
747 command, mode=self._submitMode, timeout=20000 |
739 ) |
748 ) |
740 if err: |
749 if err: |
741 raise OSError(self._shortError(err)) |
750 raise OSError(self._shortError(err)) |
742 return ast.literal_eval(out.decode("utf-8")) |
751 return ast.literal_eval(out.decode("utf-8")) |
846 "del f, fd", |
855 "del f, fd", |
847 ] |
856 ] |
848 ) |
857 ) |
849 command = "\n".join(commands) |
858 command = "\n".join(commands) |
850 |
859 |
851 out, err = self._interface.execute(command, mode=self._submitMode) |
860 out, err = self.executeCommands(command, mode=self._submitMode) |
852 if err: |
861 if err: |
853 raise OSError(self._shortError(err)) |
862 raise OSError(self._shortError(err)) |
854 return True |
863 return True |
855 |
864 |
856 def get(self, deviceFileName, hostFileName=None): |
865 def get(self, deviceFileName, hostFileName=None): |
1082 return res |
1091 return res |
1083 |
1092 |
1084 print(get_device_data()) |
1093 print(get_device_data()) |
1085 del get_device_data |
1094 del get_device_data |
1086 """ |
1095 """ |
1087 out, err = self._interface.execute(command, mode=self._submitMode) |
1096 out, err = self.executeCommands(command, mode=self._submitMode) |
1088 if err: |
1097 if err: |
1089 raise OSError(self._shortError(err)) |
1098 raise OSError(self._shortError(err)) |
1090 return ast.literal_eval(out.decode("utf-8")) |
1099 return ast.literal_eval(out.decode("utf-8")) |
1091 |
1100 |
1092 def getBoardInformation(self): |
1101 def getBoardInformation(self): |
1196 return res |
1205 return res |
1197 |
1206 |
1198 print(get_board_info()) |
1207 print(get_board_info()) |
1199 del get_board_info |
1208 del get_board_info |
1200 """ |
1209 """ |
1201 out, err = self._interface.execute(command, mode=self._submitMode) |
1210 out, err = self.executeCommands(command, mode=self._submitMode) |
1202 if err: |
1211 if err: |
1203 raise OSError(self._shortError(err)) |
1212 raise OSError(self._shortError(err)) |
1204 return ast.literal_eval(out.decode("utf-8")) |
1213 return ast.literal_eval(out.decode("utf-8")) |
1205 |
1214 |
1206 def getModules(self): |
1215 def getModules(self): |
1210 @return list of builtin modules |
1219 @return list of builtin modules |
1211 @rtype list of str |
1220 @rtype list of str |
1212 @exception OSError raised to indicate an issue with the device |
1221 @exception OSError raised to indicate an issue with the device |
1213 """ |
1222 """ |
1214 commands = ["help('modules')"] |
1223 commands = ["help('modules')"] |
1215 out, err = self._interface.execute(commands, mode=self._submitMode) |
1224 out, err = self.executeCommands(commands, mode=self._submitMode) |
1216 if err: |
1225 if err: |
1217 raise OSError(self._shortError(err)) |
1226 raise OSError(self._shortError(err)) |
1218 |
1227 |
1219 modules = [] |
1228 modules = [] |
1220 for line in out.decode("utf-8").splitlines()[:-1]: |
1229 for line in out.decode("utf-8").splitlines()[:-1]: |
1253 ) |
1262 ) |
1254 |
1263 |
1255 get_time() |
1264 get_time() |
1256 del get_time |
1265 del get_time |
1257 """ |
1266 """ |
1258 out, err = self._interface.execute(command, mode=self._submitMode) |
1267 out, err = self.executeCommands(command, mode=self._submitMode) |
1259 if err: |
1268 if err: |
1260 if b"NotImplementedError" in err: |
1269 if b"NotImplementedError" in err: |
1261 return "<unsupported> <unsupported>" |
1270 return "<unsupported> <unsupported>" |
1262 raise OSError(self._shortError(err)) |
1271 raise OSError(self._shortError(err)) |
1263 return out.decode("utf-8").strip() |
1272 return out.decode("utf-8").strip() |
1325 now.tm_sec, |
1334 now.tm_sec, |
1326 now.tm_yday, |
1335 now.tm_yday, |
1327 now.tm_isdst, |
1336 now.tm_isdst, |
1328 ), |
1337 ), |
1329 ) |
1338 ) |
1330 out, err = self._interface.execute(command, mode=self._submitMode) |
1339 out, err = self.executeCommands(command, mode=self._submitMode) |
1331 if err: |
1340 if err: |
1332 raise OSError(self._shortError(err)) |
1341 raise OSError(self._shortError(err)) |
1333 |
1342 |
1334 ################################################################## |
1343 ################################################################## |
1335 ## Methods below implement package management related methods |
1344 ## Methods below implement package management related methods |
1352 upip_install() |
1361 upip_install() |
1353 del upip_install |
1362 del upip_install |
1354 """.format( |
1363 """.format( |
1355 repr(packages) |
1364 repr(packages) |
1356 ) |
1365 ) |
1357 return self._interface.execute(command, mode=self._submitMode, timeout=60000) |
1366 return self.executeCommands(command, mode=self._submitMode, timeout=60000) |
1358 |
1367 |
1359 def mipInstall(self, package, index=None, target=None, version=None, mpy=True): |
1368 def mipInstall(self, package, index=None, target=None, version=None, mpy=True): |
1360 """ |
1369 """ |
1361 Public method to install packages using 'mip'. |
1370 Public method to install packages using 'mip'. |
1362 |
1371 |