--- a/eric6/MicroPython/MicroPythonFileSystem.py Tue Jul 23 19:43:14 2019 +0200 +++ b/eric6/MicroPython/MicroPythonFileSystem.py Wed Jul 24 20:12:19 2019 +0200 @@ -74,10 +74,13 @@ """ Private method to switch the connected device to 'raw' mode. - Note: switching to raw mode is done with synchroneous writes. + Note: switching to raw mode is done with synchronous writes. + + @return flag indicating success + @@rtype bool """ if not self.__serial: - return + return False rawReplMessage = b"raw REPL; CTRL-B to exit\r\n" softRebootMessage = b"soft reboot\r\n" @@ -92,16 +95,25 @@ self.__serial.readAll() # read all data and discard it self.__serial.write(b"\r\x01") # send CTRL-A to enter raw mode self.__serial.readUntil(rawReplMessage) + if self.__serial.hasTimedOut(): + return False self.__serial.write(b"\x04") # send CTRL-D to soft reset self.__serial.readUntil(softRebootMessage) + if self.__serial.hasTimedOut(): + return False # some MicroPython devices seem to need to be convinced in some # special way data = self.__serial.readUntil(rawReplMessage) + if self.__serial.hasTimedOut(): + return False if not data.endswith(rawReplMessage): self.__serial.write(b"\r\x01") # send CTRL-A again self.__serial.readUntil(rawReplMessage) + if self.__serial.hasTimedOut(): + return False self.__serial.readAll() # read all data and discard it + return True def __rawOff(self): """ @@ -128,7 +140,13 @@ result = bytearray() err = b"" - self.__rawOn() + ok = self.__rawOn() + if not ok: + return ( + b"", + b"Could not switch to raw mode. Is the device switched on?" + ) + QThread.msleep(10) for command in commands: if command: @@ -136,9 +154,14 @@ self.__serial.write(commandBytes + b"\x04") # read until prompt response = self.__serial.readUntil(b"\x04>") - # split stdout, stderr - out, err = response[2:-2].split(b"\x04") - result += out + if self.__serial.hasTimedOut(): + return b"", b"Timeout while processing commands." + if b"\x04" in response[2:-2]: + # split stdout, stderr + out, err = response[2:-2].split(b"\x04") + result += out + else: + err = b"invalid response received: " + response if err: return b"", err QThread.msleep(10) @@ -511,21 +534,30 @@ " try:", # Pyboard (it doesn't have machine.RTC()) " import pyb", " rtc = pyb.RTC()", - " rtc.datetime(rtc_time)", + " clock_time = rtc_time[:6] + (rtc_time[6] + 1, 0)", + " rtc.datetime(clock_time)", " except:", " try:", " import machine", " rtc = machine.RTC()", - " try:", # ESP8266 uses rtc.datetime() - " rtc.datetime(rtc_time)", + " try:", # ESP8266 may use rtc.datetime() + " clock_time = rtc_time[:6] +" + " (rtc_time[6] + 1, 0)", + " rtc.datetime(clock_time)", " except:", # ESP32 uses rtc.init() - " rtc.init(rtc_time)", + " rtc.init(rtc_time[:6])", " except:", - " pass", + " try:", + " import rtc, time", + " clock=rtc.RTC()", + " clock.datetime = time.struct_time(rtc_time +" + " (-1, -1))", + " except:", + " pass", ]), "set_time({0})".format((now.tm_year, now.tm_mon, now.tm_mday, - now.tm_wday + 1, now.tm_hour, now.tm_min, - now.tm_sec, 0)) + now.tm_hour, now.tm_min, now.tm_sec, + now.tm_wday)) ] out, err = self.__execute(commands) if err: @@ -570,21 +602,17 @@ @signal rsyncDone(localName, deviceName) emitted after the rsync operation has been completed @signal rsyncMessages(list) emitted with a list of messages + @signal removeDirectoryDone() emitted after a directory has been deleted + @signal createDirectoryDone() emitted after a directory was created + @signal synchTimeDone() emitted after the time was synchronizde to the + device + @signal showTimeDone(dateTime) emitted after the date and time was fetched + from the connected device + @signal showVersionDone(versionInfo) emitted after the version information + was fetched from the connected device - @signal longListFilesFailed(exc) emitted with a failure message to indicate - a failed long listing operation - @signal currentDirFailed(exc) emitted with a failure message to indicate - that the current directory is not available - @signal currentDirChangeFailed(exc) emitted with a failure message to - indicate that the current directory could not be changed - @signal getFileFailed(exc) emitted with a failure message to indicate that - the file could not be fetched - @signal putFileFailed(exc) emitted with a failure message to indicate that - the file could not be copied - @signal deleteFileFailed(exc) emitted with a failure message to indicate - that the file could not be deleted on the device - @signal rsyncFailed(exc) emitted with a failure message to indicate that - the rsync operation could not be completed + @signal error(exc) emitted with a failure message to indicate a failure + during the most recent operation """ longListFiles = pyqtSignal(tuple) currentDir = pyqtSignal(str) @@ -594,14 +622,13 @@ deleteFileDone = pyqtSignal(str) rsyncDone = pyqtSignal(str, str) rsyncMessages = pyqtSignal(list) + removeDirectoryDone = pyqtSignal() + createDirectoryDone = pyqtSignal() + synchTimeDone = pyqtSignal() + showTimeDone = pyqtSignal(str) + showVersionDone = pyqtSignal(dict) - longListFilesFailed = pyqtSignal(str) - currentDirFailed = pyqtSignal(str) - currentDirChangeFailed = pyqtSignal(str) - getFileFailed = pyqtSignal(str) - putFileFailed = pyqtSignal(str) - deleteFileFailed = pyqtSignal(str) - rsyncFailed = pyqtSignal(str) + error = pyqtSignal(str, str) def __init__(self, port, parent=None): """ @@ -650,7 +677,7 @@ name, (mode, size, time) in filesList] self.longListFiles.emit(tuple(result)) except Exception as exc: - self.longListFilesFailed.emit(str(exc)) + self.error.emit("lls", str(exc)) @pyqtSlot() def pwd(self): @@ -661,7 +688,7 @@ pwd = self.__fs.pwd() self.currentDir.emit(pwd) except Exception as exc: - self.currentDirFailed.emit(str(exc)) + self.error.emit("pwd", str(exc)) @pyqtSlot(str) def cd(self, dirname): @@ -675,7 +702,7 @@ self.__fs.cd(dirname) self.currentDirChanged.emit(dirname) except Exception as exc: - self.currentDirChangeFailed.emit(str(exc)) + self.error.emit("cd", str(exc)) @pyqtSlot(str) @pyqtSlot(str, str) @@ -696,7 +723,7 @@ self.__fs.get(deviceFileName, hostFileName) self.getFileDone.emit(deviceFileName, hostFileName) except Exception as exc: - self.getFileFailed.emit(str(exc)) + self.error.emit("get", str(exc)) @pyqtSlot(str) @pyqtSlot(str, str) @@ -713,7 +740,7 @@ self.__fs.put(hostFileName, deviceFileName) self.putFileDone.emit(hostFileName, deviceFileName) except Exception as exc: - self.putFileFailed.emit(str(exc)) + self.error.emit("put", str(exc)) @pyqtSlot(str) def delete(self, deviceFileName): @@ -727,7 +754,7 @@ self.__fs.rm(deviceFileName) self.deleteFileDone.emit(deviceFileName) except Exception as exc: - self.deleteFileFailed.emit(str(exc)) + self.error.emit("delete", str(exc)) def __rsync(self, hostDirectory, deviceDirectory, mirror=True): """ @@ -841,9 +868,11 @@ return messages, errors + @pyqtSlot(str, str) + @pyqtSlot(str, str, bool) def rsync(self, hostDirectory, deviceDirectory, mirror=True): """ - Public method to synchronize a local directory to the device. + Public slot to synchronize a local directory to the device. @param hostDirectory name of the local directory @type str @@ -856,9 +885,82 @@ messages, errors = self.__rsync(hostDirectory, deviceDirectory, mirror=mirror) if errors: - self.rsyncFailed.emit("\n".join(errors)) + self.error.emit("rsync", "\n".join(errors)) if messages: self.rsyncMessages.emit(messages) self.rsyncDone.emit(hostDirectory, deviceDirectory) + + @pyqtSlot(str) + def mkdir(self, dirname): + """ + Public slot to create a new directory. + + @param dirname name of the directory to create + @type str + """ + try: + self.__fs.mkdir(dirname) + self.createDirectoryDone.emit() + except Exception as exc: + self.error.emit("mkdir", str(exc)) + + @pyqtSlot(str) + @pyqtSlot(str, bool) + def rmdir(self, dirname, recursive=False): + """ + Public slot to (recursively) remove a directory. + + @param dirname name of the directory to be removed + @type str + @param recursive flag indicating a recursive removal + @type bool + """ + try: + if recursive: + self.__fs.rmrf(dirname, recursive=True, force=True) + else: + self.__fs.rmdir(dirname) + self.removeDirectoryDone.emit() + except Exception as exc: + self.error.emit("rmdir", str(exc)) + + ################################################################## + ## some non-filesystem related methods below + ################################################################## + + @pyqtSlot() + def synchronizeTime(self): + """ + Public slot to set the time of the connected device to the local + computer's time. + """ + try: + self.__fs.syncTime() + self.synchTimeDone.emit() + except Exception as exc: + self.error.emit("rmdir", str(exc)) + + @pyqtSlot() + def showTime(self): + """ + Public slot to get the current date and time of the device. + """ + try: + dt = self.__fs.showTime() + self.showTimeDone.emit(dt) + except Exception as exc: + self.error.emit("showTime", str(exc)) + + @pyqtSlot() + def showVersion(self): + """ + Public slot to get the version info for the MicroPython run by the + connected device. + """ + try: + versionInfo = self.__fs.version() + self.showVersionDone.emit(versionInfo) + except Exception as exc: + self.error.emit("showVersion", str(exc))