eric6/MicroPython/MicroPythonFileSystem.py

branch
micropython
changeset 7082
ec199ef0cfc6
parent 7081
ed510767c096
child 7083
217862c28319
equal deleted inserted replaced
7081:ed510767c096 7082:ec199ef0cfc6
72 72
73 def __rawOn(self): 73 def __rawOn(self):
74 """ 74 """
75 Private method to switch the connected device to 'raw' mode. 75 Private method to switch the connected device to 'raw' mode.
76 76
77 Note: switching to raw mode is done with synchroneous writes. 77 Note: switching to raw mode is done with synchronous writes.
78
79 @return flag indicating success
80 @@rtype bool
78 """ 81 """
79 if not self.__serial: 82 if not self.__serial:
80 return 83 return False
81 84
82 rawReplMessage = b"raw REPL; CTRL-B to exit\r\n" 85 rawReplMessage = b"raw REPL; CTRL-B to exit\r\n"
83 softRebootMessage = b"soft reboot\r\n" 86 softRebootMessage = b"soft reboot\r\n"
84 87
85 self.__serial.write(b"\x02") # end raw mode if required 88 self.__serial.write(b"\x02") # end raw mode if required
90 self.__serial.waitForBytesWritten() 93 self.__serial.waitForBytesWritten()
91 QThread.msleep(10) 94 QThread.msleep(10)
92 self.__serial.readAll() # read all data and discard it 95 self.__serial.readAll() # read all data and discard it
93 self.__serial.write(b"\r\x01") # send CTRL-A to enter raw mode 96 self.__serial.write(b"\r\x01") # send CTRL-A to enter raw mode
94 self.__serial.readUntil(rawReplMessage) 97 self.__serial.readUntil(rawReplMessage)
98 if self.__serial.hasTimedOut():
99 return False
95 self.__serial.write(b"\x04") # send CTRL-D to soft reset 100 self.__serial.write(b"\x04") # send CTRL-D to soft reset
96 self.__serial.readUntil(softRebootMessage) 101 self.__serial.readUntil(softRebootMessage)
102 if self.__serial.hasTimedOut():
103 return False
97 104
98 # some MicroPython devices seem to need to be convinced in some 105 # some MicroPython devices seem to need to be convinced in some
99 # special way 106 # special way
100 data = self.__serial.readUntil(rawReplMessage) 107 data = self.__serial.readUntil(rawReplMessage)
108 if self.__serial.hasTimedOut():
109 return False
101 if not data.endswith(rawReplMessage): 110 if not data.endswith(rawReplMessage):
102 self.__serial.write(b"\r\x01") # send CTRL-A again 111 self.__serial.write(b"\r\x01") # send CTRL-A again
103 self.__serial.readUntil(rawReplMessage) 112 self.__serial.readUntil(rawReplMessage)
113 if self.__serial.hasTimedOut():
114 return False
104 self.__serial.readAll() # read all data and discard it 115 self.__serial.readAll() # read all data and discard it
116 return True
105 117
106 def __rawOff(self): 118 def __rawOff(self):
107 """ 119 """
108 Private method to switch 'raw' mode off. 120 Private method to switch 'raw' mode off.
109 """ 121 """
126 return b"", b"" 138 return b"", b""
127 139
128 result = bytearray() 140 result = bytearray()
129 err = b"" 141 err = b""
130 142
131 self.__rawOn() 143 ok = self.__rawOn()
144 if not ok:
145 return (
146 b"",
147 b"Could not switch to raw mode. Is the device switched on?"
148 )
149
132 QThread.msleep(10) 150 QThread.msleep(10)
133 for command in commands: 151 for command in commands:
134 if command: 152 if command:
135 commandBytes = command.encode("utf-8") 153 commandBytes = command.encode("utf-8")
136 self.__serial.write(commandBytes + b"\x04") 154 self.__serial.write(commandBytes + b"\x04")
137 # read until prompt 155 # read until prompt
138 response = self.__serial.readUntil(b"\x04>") 156 response = self.__serial.readUntil(b"\x04>")
139 # split stdout, stderr 157 if self.__serial.hasTimedOut():
140 out, err = response[2:-2].split(b"\x04") 158 return b"", b"Timeout while processing commands."
141 result += out 159 if b"\x04" in response[2:-2]:
160 # split stdout, stderr
161 out, err = response[2:-2].split(b"\x04")
162 result += out
163 else:
164 err = b"invalid response received: " + response
142 if err: 165 if err:
143 return b"", err 166 return b"", err
144 QThread.msleep(10) 167 QThread.msleep(10)
145 self.__rawOff() 168 self.__rawOff()
146 169
509 "def set_time(rtc_time):", 532 "def set_time(rtc_time):",
510 " rtc = None", 533 " rtc = None",
511 " try:", # Pyboard (it doesn't have machine.RTC()) 534 " try:", # Pyboard (it doesn't have machine.RTC())
512 " import pyb", 535 " import pyb",
513 " rtc = pyb.RTC()", 536 " rtc = pyb.RTC()",
514 " rtc.datetime(rtc_time)", 537 " clock_time = rtc_time[:6] + (rtc_time[6] + 1, 0)",
538 " rtc.datetime(clock_time)",
515 " except:", 539 " except:",
516 " try:", 540 " try:",
517 " import machine", 541 " import machine",
518 " rtc = machine.RTC()", 542 " rtc = machine.RTC()",
519 " try:", # ESP8266 uses rtc.datetime() 543 " try:", # ESP8266 may use rtc.datetime()
520 " rtc.datetime(rtc_time)", 544 " clock_time = rtc_time[:6] +"
545 " (rtc_time[6] + 1, 0)",
546 " rtc.datetime(clock_time)",
521 " except:", # ESP32 uses rtc.init() 547 " except:", # ESP32 uses rtc.init()
522 " rtc.init(rtc_time)", 548 " rtc.init(rtc_time[:6])",
523 " except:", 549 " except:",
524 " pass", 550 " try:",
551 " import rtc, time",
552 " clock=rtc.RTC()",
553 " clock.datetime = time.struct_time(rtc_time +"
554 " (-1, -1))",
555 " except:",
556 " pass",
525 ]), 557 ]),
526 "set_time({0})".format((now.tm_year, now.tm_mon, now.tm_mday, 558 "set_time({0})".format((now.tm_year, now.tm_mon, now.tm_mday,
527 now.tm_wday + 1, now.tm_hour, now.tm_min, 559 now.tm_hour, now.tm_min, now.tm_sec,
528 now.tm_sec, 0)) 560 now.tm_wday))
529 ] 561 ]
530 out, err = self.__execute(commands) 562 out, err = self.__execute(commands)
531 if err: 563 if err:
532 raise IOError(self.__shortError(err)) 564 raise IOError(self.__shortError(err))
533 565
568 @signal deleteFileDone(deviceFile) emitted after the file has been deleted 600 @signal deleteFileDone(deviceFile) emitted after the file has been deleted
569 on the connected device 601 on the connected device
570 @signal rsyncDone(localName, deviceName) emitted after the rsync operation 602 @signal rsyncDone(localName, deviceName) emitted after the rsync operation
571 has been completed 603 has been completed
572 @signal rsyncMessages(list) emitted with a list of messages 604 @signal rsyncMessages(list) emitted with a list of messages
573 605 @signal removeDirectoryDone() emitted after a directory has been deleted
574 @signal longListFilesFailed(exc) emitted with a failure message to indicate 606 @signal createDirectoryDone() emitted after a directory was created
575 a failed long listing operation 607 @signal synchTimeDone() emitted after the time was synchronizde to the
576 @signal currentDirFailed(exc) emitted with a failure message to indicate 608 device
577 that the current directory is not available 609 @signal showTimeDone(dateTime) emitted after the date and time was fetched
578 @signal currentDirChangeFailed(exc) emitted with a failure message to 610 from the connected device
579 indicate that the current directory could not be changed 611 @signal showVersionDone(versionInfo) emitted after the version information
580 @signal getFileFailed(exc) emitted with a failure message to indicate that 612 was fetched from the connected device
581 the file could not be fetched 613
582 @signal putFileFailed(exc) emitted with a failure message to indicate that 614 @signal error(exc) emitted with a failure message to indicate a failure
583 the file could not be copied 615 during the most recent operation
584 @signal deleteFileFailed(exc) emitted with a failure message to indicate
585 that the file could not be deleted on the device
586 @signal rsyncFailed(exc) emitted with a failure message to indicate that
587 the rsync operation could not be completed
588 """ 616 """
589 longListFiles = pyqtSignal(tuple) 617 longListFiles = pyqtSignal(tuple)
590 currentDir = pyqtSignal(str) 618 currentDir = pyqtSignal(str)
591 currentDirChanged = pyqtSignal(str) 619 currentDirChanged = pyqtSignal(str)
592 getFileDone = pyqtSignal(str, str) 620 getFileDone = pyqtSignal(str, str)
593 putFileDone = pyqtSignal(str, str) 621 putFileDone = pyqtSignal(str, str)
594 deleteFileDone = pyqtSignal(str) 622 deleteFileDone = pyqtSignal(str)
595 rsyncDone = pyqtSignal(str, str) 623 rsyncDone = pyqtSignal(str, str)
596 rsyncMessages = pyqtSignal(list) 624 rsyncMessages = pyqtSignal(list)
597 625 removeDirectoryDone = pyqtSignal()
598 longListFilesFailed = pyqtSignal(str) 626 createDirectoryDone = pyqtSignal()
599 currentDirFailed = pyqtSignal(str) 627 synchTimeDone = pyqtSignal()
600 currentDirChangeFailed = pyqtSignal(str) 628 showTimeDone = pyqtSignal(str)
601 getFileFailed = pyqtSignal(str) 629 showVersionDone = pyqtSignal(dict)
602 putFileFailed = pyqtSignal(str) 630
603 deleteFileFailed = pyqtSignal(str) 631 error = pyqtSignal(str, str)
604 rsyncFailed = pyqtSignal(str)
605 632
606 def __init__(self, port, parent=None): 633 def __init__(self, port, parent=None):
607 """ 634 """
608 Constructor 635 Constructor
609 636
648 str(size), 675 str(size),
649 mtime2string(time)) for 676 mtime2string(time)) for
650 name, (mode, size, time) in filesList] 677 name, (mode, size, time) in filesList]
651 self.longListFiles.emit(tuple(result)) 678 self.longListFiles.emit(tuple(result))
652 except Exception as exc: 679 except Exception as exc:
653 self.longListFilesFailed.emit(str(exc)) 680 self.error.emit("lls", str(exc))
654 681
655 @pyqtSlot() 682 @pyqtSlot()
656 def pwd(self): 683 def pwd(self):
657 """ 684 """
658 Public slot to get the current directory of the device. 685 Public slot to get the current directory of the device.
659 """ 686 """
660 try: 687 try:
661 pwd = self.__fs.pwd() 688 pwd = self.__fs.pwd()
662 self.currentDir.emit(pwd) 689 self.currentDir.emit(pwd)
663 except Exception as exc: 690 except Exception as exc:
664 self.currentDirFailed.emit(str(exc)) 691 self.error.emit("pwd", str(exc))
665 692
666 @pyqtSlot(str) 693 @pyqtSlot(str)
667 def cd(self, dirname): 694 def cd(self, dirname):
668 """ 695 """
669 Public slot to change the current directory of the device. 696 Public slot to change the current directory of the device.
673 """ 700 """
674 try: 701 try:
675 self.__fs.cd(dirname) 702 self.__fs.cd(dirname)
676 self.currentDirChanged.emit(dirname) 703 self.currentDirChanged.emit(dirname)
677 except Exception as exc: 704 except Exception as exc:
678 self.currentDirChangeFailed.emit(str(exc)) 705 self.error.emit("cd", str(exc))
679 706
680 @pyqtSlot(str) 707 @pyqtSlot(str)
681 @pyqtSlot(str, str) 708 @pyqtSlot(str, str)
682 def get(self, deviceFileName, hostFileName=""): 709 def get(self, deviceFileName, hostFileName=""):
683 """ 710 """
694 os.path.basename(deviceFileName)) 721 os.path.basename(deviceFileName))
695 try: 722 try:
696 self.__fs.get(deviceFileName, hostFileName) 723 self.__fs.get(deviceFileName, hostFileName)
697 self.getFileDone.emit(deviceFileName, hostFileName) 724 self.getFileDone.emit(deviceFileName, hostFileName)
698 except Exception as exc: 725 except Exception as exc:
699 self.getFileFailed.emit(str(exc)) 726 self.error.emit("get", str(exc))
700 727
701 @pyqtSlot(str) 728 @pyqtSlot(str)
702 @pyqtSlot(str, str) 729 @pyqtSlot(str, str)
703 def put(self, hostFileName, deviceFileName=""): 730 def put(self, hostFileName, deviceFileName=""):
704 """ 731 """
711 """ 738 """
712 try: 739 try:
713 self.__fs.put(hostFileName, deviceFileName) 740 self.__fs.put(hostFileName, deviceFileName)
714 self.putFileDone.emit(hostFileName, deviceFileName) 741 self.putFileDone.emit(hostFileName, deviceFileName)
715 except Exception as exc: 742 except Exception as exc:
716 self.putFileFailed.emit(str(exc)) 743 self.error.emit("put", str(exc))
717 744
718 @pyqtSlot(str) 745 @pyqtSlot(str)
719 def delete(self, deviceFileName): 746 def delete(self, deviceFileName):
720 """ 747 """
721 Public slot to delete a file on the device. 748 Public slot to delete a file on the device.
725 """ 752 """
726 try: 753 try:
727 self.__fs.rm(deviceFileName) 754 self.__fs.rm(deviceFileName)
728 self.deleteFileDone.emit(deviceFileName) 755 self.deleteFileDone.emit(deviceFileName)
729 except Exception as exc: 756 except Exception as exc:
730 self.deleteFileFailed.emit(str(exc)) 757 self.error.emit("delete", str(exc))
731 758
732 def __rsync(self, hostDirectory, deviceDirectory, mirror=True): 759 def __rsync(self, hostDirectory, deviceDirectory, mirror=True):
733 """ 760 """
734 Private method to synchronize a local directory to the device. 761 Private method to synchronize a local directory to the device.
735 762
839 except Exception as exc: 866 except Exception as exc:
840 messages.append(str(exc)) 867 messages.append(str(exc))
841 868
842 return messages, errors 869 return messages, errors
843 870
871 @pyqtSlot(str, str)
872 @pyqtSlot(str, str, bool)
844 def rsync(self, hostDirectory, deviceDirectory, mirror=True): 873 def rsync(self, hostDirectory, deviceDirectory, mirror=True):
845 """ 874 """
846 Public method to synchronize a local directory to the device. 875 Public slot to synchronize a local directory to the device.
847 876
848 @param hostDirectory name of the local directory 877 @param hostDirectory name of the local directory
849 @type str 878 @type str
850 @param deviceDirectory name of the directory on the device 879 @param deviceDirectory name of the directory on the device
851 @type str 880 @type str
854 @type bool 883 @type bool
855 """ 884 """
856 messages, errors = self.__rsync(hostDirectory, deviceDirectory, 885 messages, errors = self.__rsync(hostDirectory, deviceDirectory,
857 mirror=mirror) 886 mirror=mirror)
858 if errors: 887 if errors:
859 self.rsyncFailed.emit("\n".join(errors)) 888 self.error.emit("rsync", "\n".join(errors))
860 889
861 if messages: 890 if messages:
862 self.rsyncMessages.emit(messages) 891 self.rsyncMessages.emit(messages)
863 892
864 self.rsyncDone.emit(hostDirectory, deviceDirectory) 893 self.rsyncDone.emit(hostDirectory, deviceDirectory)
894
895 @pyqtSlot(str)
896 def mkdir(self, dirname):
897 """
898 Public slot to create a new directory.
899
900 @param dirname name of the directory to create
901 @type str
902 """
903 try:
904 self.__fs.mkdir(dirname)
905 self.createDirectoryDone.emit()
906 except Exception as exc:
907 self.error.emit("mkdir", str(exc))
908
909 @pyqtSlot(str)
910 @pyqtSlot(str, bool)
911 def rmdir(self, dirname, recursive=False):
912 """
913 Public slot to (recursively) remove a directory.
914
915 @param dirname name of the directory to be removed
916 @type str
917 @param recursive flag indicating a recursive removal
918 @type bool
919 """
920 try:
921 if recursive:
922 self.__fs.rmrf(dirname, recursive=True, force=True)
923 else:
924 self.__fs.rmdir(dirname)
925 self.removeDirectoryDone.emit()
926 except Exception as exc:
927 self.error.emit("rmdir", str(exc))
928
929 ##################################################################
930 ## some non-filesystem related methods below
931 ##################################################################
932
933 @pyqtSlot()
934 def synchronizeTime(self):
935 """
936 Public slot to set the time of the connected device to the local
937 computer's time.
938 """
939 try:
940 self.__fs.syncTime()
941 self.synchTimeDone.emit()
942 except Exception as exc:
943 self.error.emit("rmdir", str(exc))
944
945 @pyqtSlot()
946 def showTime(self):
947 """
948 Public slot to get the current date and time of the device.
949 """
950 try:
951 dt = self.__fs.showTime()
952 self.showTimeDone.emit(dt)
953 except Exception as exc:
954 self.error.emit("showTime", str(exc))
955
956 @pyqtSlot()
957 def showVersion(self):
958 """
959 Public slot to get the version info for the MicroPython run by the
960 connected device.
961 """
962 try:
963 versionInfo = self.__fs.version()
964 self.showVersionDone.emit(versionInfo)
965 except Exception as exc:
966 self.error.emit("showVersion", str(exc))

eric ide

mercurial