Module lib.shell.commands
Class defining a minimalist shell, directly executable on the board. We modify directories, list, delete, move files, edit files .. The commands are : - cd : change directory - pwd : current directory - cat : display the content of file - cls : clear screen - cleanupsd : erase on sdcard all unnecessary files left behind by mac os or windows - mkdir : create directory - mv : move file - rmdir : remove directory - cp : copy file - rm : remove file - ls : list file - ll : list file long - date : get the system date or synchronize with Ntp - setdate : set date and time - uptime : the amount of time system is running - find : find a file - run : execute python script - download : transfer files from device to computer (only available with camflasher) - upload : transfer files from computer to device (only available with camflasher) - edit : edit a text file - exit : exit of shell - exec : execute python string with exec - eval : evaluate python expression - gc : garbage collection - grep : grep text in many files - mount : mount sd card - umount : umount sd card - temperature : device temperature - meminfo : memory informations - flashinfo : flash informations - sysinfo : system informations - deepsleep : deepsleep of board - ping : ping host - reboot : reboot board - help : list all command available - man : manual of one command - df : display free disk space - ip2host : convert ip address in hostname - host2ip : convert hostname in ip address - eval : evaluation python string - exec : execute python string - dump : display hexadecimal dump of the content of file
Expand source code
# Distributed under Pycameresp License
# Copyright (c) 2023 Remi BERTHOLET
# pylint:disable=too-many-lines
# pylint:disable=consider-using-f-string
# pylint:disable=unspecified-encoding
""" Class defining a minimalist shell, directly executable on the board.
We modify directories, list, delete, move files, edit files ..
The commands are :
- cd : change directory
- pwd : current directory
- cat : display the content of file
- cls : clear screen
- cleanupsd : erase on sdcard all unnecessary files left behind by mac os or windows
- mkdir : create directory
- mv : move file
- rmdir : remove directory
- cp : copy file
- rm : remove file
- ls : list file
- ll : list file long
- date : get the system date or synchronize with Ntp
- setdate : set date and time
- uptime : the amount of time system is running
- find : find a file
- run : execute python script
- download : transfer files from device to computer (only available with camflasher)
- upload : transfer files from computer to device (only available with camflasher)
- edit : edit a text file
- exit : exit of shell
- exec : execute python string with exec
- eval : evaluate python expression
- gc : garbage collection
- grep : grep text in many files
- mount : mount sd card
- umount : umount sd card
- temperature : device temperature
- meminfo : memory informations
- flashinfo : flash informations
- sysinfo : system informations
- deepsleep : deepsleep of board
- ping : ping host
- reboot : reboot board
- help : list all command available
- man : manual of one command
- df : display free disk space
- ip2host : convert ip address in hostname
- host2ip : convert hostname in ip address
- eval : evaluation python string
- exec : execute python string
- dump : display hexadecimal dump of the content of file
"""
# pylint:disable=wrong-import-position
import sys
import io
import os
import uos
import machine
import tools.useful
import tools.logger
import tools.sdcard
import tools.filesystem
import tools.exchange
import tools.info
import tools.strings
import tools.terminal
import tools.watchdog
import tools.lang
import tools.date
import tools.console
import tools.system
import tools.archiver
shell_commands = None
def get_screen_size():
""" Return the screen size and check if output redirected """
# pylint:disable=global-variable-not-assigned
if tools.console.Console.is_redirected() is False:
height, width = tools.terminal.get_screen_size()
else:
height, width = tools.terminal.MAXINT, 80
return height, width
def print_part(message, width, height, count):
""" Print a part of text """
# pylint:disable=global-variable-not-assigned
if isinstance(message , bytes):
message = message.decode("utf8")
if count is not None and count >= height:
tools.console.Console.print(message,end="")
if tools.console.Console.is_redirected() is False:
key = tools.terminal.getch()
else:
key = " "
count = 1
if key in ["x","X","q","Q","\x1B"]:
return None
tools.console.Console.print("\n", end="")
else:
if count is None:
count = 1
else:
count += 1
tools.console.Console.print(message)
return count
class Displayer:
""" Displayer file """
def __init__(self, path, long, action=print_part):
""" Constructor """
self.height, self.width = get_screen_size()
self.path = path
self.showdir = True
self.count = 1
self.long = long
self.action = action
def purge_path(self, path):
""" Purge the path for the display """
path = path.encode("utf8")
path = tools.filesystem.normpath(path)
prefix = tools.filesystem.prefix([path, self.path.encode("utf8")])
return path[len(prefix):].lstrip(b"/")
def get_info(self, path):
""" Get info on file or directory """
result = None, False
fileinfo = tools.filesystem.fileinfo(path)
file_date = fileinfo[8]
size = fileinfo[6]
# If directory
if fileinfo[0] & 0x4000 == 0x4000:
if self.showdir:
if self.long:
message = b"%s %s [%s]"%(tools.date.date_to_bytes(file_date),b" "*7,self.purge_path(path))
else:
message = b"[%s]"%self.purge_path(path)
result = message, True
# If file
else:
if self.long:
message = b"%s %s %s"%(tools.date.date_to_bytes(file_date),tools.strings.size_to_bytes(size),self.purge_path(path))
else:
message = self.purge_path(path)
result = message, False
return result
def show(self, path):
""" Show the information of a file or directory """
message, directory = self.get_info(path)
if message is not None:
self.count = self.action(message, self.width, self.height, self.count)
def show_dir(self, state):
""" Indicates if the directory must show """
self.showdir = state
def cd(directory = "/"):
""" Change directory """
try:
uos.chdir(tools.filesystem.normpath(directory))
except:
if directory != ".":
tools.console.Console.print("No such file or directory '%s'"%directory)
def pwd():
""" Display the current directory """
tools.console.Console.print("%s"%uos.getcwd())
def mkdir(directory, recursive=False, quiet=False):
""" Make directory """
try:
if quiet is False:
tools.console.Console.print("mkdir '%s'"%directory)
tools.filesystem.makedir(tools.filesystem.normpath(directory), recursive)
except:
tools.console.Console.print("Cannot mkdir '%s'"%directory)
def removedir(directory, force=False, quiet=False, simulate=False, ignore_error=False):
""" Remove directory """
try:
if tools.filesystem.exists(directory+"/.DS_Store"):
rmfile(directory+"/.DS_Store", quiet, force, simulate)
if (tools.filesystem.ismicropython() or force) and simulate is False:
uos.rmdir(directory)
if quiet is False:
tools.console.Console.print("rmdir '%s'"%(directory))
except:
if ignore_error is False:
tools.console.Console.print("rmdir '%s' not removed"%(directory))
def rmdir(directory, root=None, recursive=False, force=False, quiet=False, simulate=False, ignore_error=False):
""" Remove directory """
directory = tools.filesystem.normpath(directory)
if recursive is False:
removedir(directory, force=force, quiet=quiet, simulate=simulate, ignore_error=ignore_error)
else:
directories = [directory]
d = directory
while 1:
parts = tools.filesystem.split(d)
if parts[1] == "" or parts[0] == "":
break
if root:
if len(parts[0]) <= len(root):
break
directories.append(parts[0])
d = parts[0]
if "/" in directories:
directories.remove("/")
if tools.sdcard.SdCard.get_mountpoint() in directories:
directories.remove(tools.sdcard.SdCard.get_mountpoint())
for d in directories:
if tools.filesystem.exists(d) and d != ".":
removedir(d, force=force, quiet=quiet, simulate=simulate, ignore_error=ignore_error)
def movefile(source, destination, quiet):
""" Move file """
source = tools.filesystem.normpath(source)
destination = tools.filesystem.normpath(destination)
if quiet is False:
tools.console.Console.print("mv '%s' -> '%s'"%(source,destination))
uos.rename(source,destination)
def mv(source, destination, quiet=False):
""" Move or rename file """
source = tools.filesystem.normpath(source)
destination = tools.filesystem.normpath(destination)
try:
if tools.filesystem.isfile(source):
movefile(source,destination,quiet)
else:
if tools.filesystem.isdir(source):
# If destination existing
if tools.filesystem.exists(destination):
# If destination is file
if tools.filesystem.isfile(destination):
raise IOError()
else:
# Move source into destination directory
destination = destination + "/" + tools.filesystem.split(source)[1]
movefile(tools.filesystem.normpath(source),tools.filesystem.normpath(destination), quiet)
else:
# Rename
movefile(tools.filesystem.normpath(source),tools.filesystem.normpath(destination), quiet)
else:
# Move many files
path, pattern = tools.filesystem.split(source)
if path == "":
path = uos.getcwd()
_, filenames = tools.filesystem.scandir(path, pattern, False)
for src in filenames:
dst = destination + "/" + src[len(path):]
movefile(src,dst,quiet)
except:
tools.console.Console.print("Cannot mv '%s'->'%s'"%(source,destination))
def copyfile(src,dst,quiet):
""" Copy file """
dst = dst.replace("//","/")
dst = dst.replace("//","/")
dstdir, dstfile = tools.filesystem.split(dst)
try:
if not tools.filesystem.exists(dstdir):
if dstdir != "." and dstdir != "":
mkdir(dstdir, recursive=True, quiet=quiet)
src_file = open(src, 'rb')
dst_file = open(dst, 'wb')
if quiet is False:
tools.console.Console.print("cp '%s' -> '%s'"%(src,dst))
while True:
buf = src_file.read(256)
if len(buf) > 0:
dst_file.write(buf)
if len(buf) < 256:
break
src_file.close()
dst_file.close()
except:
tools.console.Console.print("Cannot cp '%s' -> '%s'"%(src, dst))
def cp(source, destination, recursive=False, quiet=False):
""" Copy file command """
source = tools.filesystem.normpath(source)
destination = tools.filesystem.normpath(destination)
if tools.filesystem.isfile(source):
copyfile(source,destination,quiet)
else:
if tools.filesystem.isdir(source):
path = source
pattern = "*"
else:
path, pattern = tools.filesystem.split(source)
_, filenames = tools.filesystem.scandir(path, pattern, recursive)
for src in filenames:
dst = destination + "/" + src[len(path):]
copyfile(src,dst,quiet)
def rmfile(filename, quiet=False, force=False, simulate=False):
""" Remove file """
try:
if (tools.filesystem.ismicropython() or force) and simulate is False:
uos.remove(tools.filesystem.normpath(filename))
if quiet is False:
tools.console.Console.print("rm '%s'"%(filename))
except:
tools.console.Console.print("rm '%s' not removed"%(filename))
class Remover(Displayer):
""" Class to remove files and directories """
def __init__(self, file, recursive=False, quiet=False, force=False, simulate=False):
Displayer.__init__(self, uos.getcwd(), False)
self.directories = set()
self.path = uos.getcwd()
self.file = file
self.quiet = quiet
self.force = force
self.simulate = simulate
self.recursive = recursive
if recursive:
if tools.filesystem.isdir(self.path + "/" + file):
self.directories.add(self.path + "/" + file)
def show(self, path):
""" Show the information of a file or directory """
message, directory = self.get_info(path)
if message is not None:
if directory is False:
rmfile(path, force=self.force, quiet=self.quiet, simulate=self.simulate)
if directory:
self.directories.add(path)
def remove_dir(self):
""" Remove directories """
if self.recursive:
directories = list(self.directories)
directories.sort()
directories.reverse()
for directory in directories:
rmdir(directory, root=self.path, recursive=self.recursive, force=self.force, quiet=self.quiet, simulate=self.simulate, ignore_error=True)
def rm(file, recursive=False, quiet=False, force=False, simulate=False):
""" Remove file command """
remover = Remover(file, recursive, quiet, force, simulate)
searchfile(file, recursive, remover)
remover.remove_dir()
def ls(file="", recursive=False, long=False):
""" List files command """
searchfile(file, recursive, Displayer(uos.getcwd(), long))
def ll(file="", recursive=False):
""" List files long command """
searchfile(file, recursive, Displayer(uos.getcwd(), True))
def searchfile(file, recursive, obj = None):
""" Search file """
file = tools.filesystem.normpath(file)
p = tools.filesystem.abspath(uos.getcwd(), file)
filenames = []
try:
# If file not defined then current directory used
if file == "":
_,filenames = tools.filesystem.scandir(uos.getcwd(), "*", recursive, obj)
# If one file detected
elif tools.filesystem.isfile(p):
if obj is not None:
obj.show_dir(False)
obj.show(p)
filenames = [p]
# If directory detected
elif tools.filesystem.isdir(p):
_, filenames = tools.filesystem.scandir(p, "*", recursive, obj)
# Else pattern detected
else:
path, pattern = tools.filesystem.split(p)
if pattern != "*":
if obj is not None:
obj.show_dir(False)
_, filenames = tools.filesystem.scandir(path, pattern, recursive, obj)
except Exception as err:
tools.console.Console.print(err)
if len(filenames) == 0 and file != "" and file != "." and tools.filesystem.isdir(file) is False:
tools.console.Console.print("%s : No such file or directory"%file)
return filenames
def find(file):
""" Find a file in directories """
filenames = searchfile(file, True)
for filename in filenames:
tools.console.Console.print(filename)
def grep(file, text, recursive=False, ignorecase=False, regexp=False):
""" Grep command """
from re import search
file = tools.filesystem.normpath(file)
def __search(text, content, ignorecase, regexp):
if ignorecase:
content = content.lower()
text = text.lower()
if regexp:
if search(text, content):
return True
else:
if content.find(text) != -1:
return True
return False
def __grep(text, filename, ignorecase, regexp, width, height, count):
lineNumber = 1
with open(filename,"r", encoding="latin-1") as f:
while 1:
line = f.readline()
if line:
if __search(text, line, ignorecase, regexp):
line = line.replace("\t"," ")
message = "%s:%d:%s"%(filename, lineNumber, line)
message = message.rstrip()[:width]
count = print_part(message, width, height, count)
if count is None:
tools.console.Console.print("")
return None
lineNumber += 1
else:
break
return count
if tools.filesystem.isfile(file):
filenames = [file]
else:
path, pattern = tools.filesystem.split(file)
_, filenames = tools.filesystem.scandir(path, pattern, recursive)
height, width = get_screen_size()
count = 1
for filename in filenames:
count = __grep(text, filename, ignorecase, regexp, width, height, count)
if count is None:
break
def ping(host):
""" Ping host """
try:
from server.ping import ping as ping_
ping_(host, count=4, timeout=1)
except:
tools.console.Console.print("Not available")
def ip2host(ip_address):
""" Convert ip to hostname """
try:
import wifi.station
_, _, _, dns = wifi.station.Station.get_info()
from server.dnsclient import resolve_hostname
tools.console.Console.print(resolve_hostname(dns, ip_address))
except:
tools.console.Console.print("Not available")
def host2ip(hostname):
""" Convert hostname to ip """
try:
import wifi.station
_, _, _, dns = wifi.station.Station.get_info()
from server.dnsclient import resolve_ip_address
tools.console.Console.print(resolve_ip_address(dns, hostname))
except:
tools.console.Console.print("Not available")
def mountsd(mountpoint="/sd"):
""" Mount command """
try:
tools.sdcard.SdCard.mount(mountpoint)
tools.console.Console.print("Sd mounted on '%s'"%mountpoint)
except:
tools.console.Console.print("Cannot mount sd on '%s'"%mountpoint)
def umountsd(mountpoint="/sd"):
""" Umount command """
try:
tools.sdcard.SdCard.umount(mountpoint)
tools.console.Console.print("Sd umounted from '%s'"%mountpoint)
except:
tools.console.Console.print("Cannot umount sd from '%s'"%mountpoint)
def date_time(update=False, offsetUTC=+1, noDst=False):
""" Get or set date """
try:
from server.timesetting import set_date
if update:
if noDst:
dst = False
else:
dst = True
set_date(offsetUTC, dst)
del sys.modules["server.timesetting"]
except:
pass
tools.console.Console.print(tools.date.date_to_string())
def setdate(datetime=""):
""" Set date and time """
import re
file_date=re.compile("[/: ]")
failed = False
try:
spls = file_date.split(datetime)
lst = []
if len(spls) > 1:
for spl in spls:
if len(spl) > 0:
try:
r = spl.lstrip("0")
if len(r) == 0:
lst.append(0)
else:
lst.append(eval(r))
except:
failed = True
break
if len(lst) == 6:
# pylint: disable=unbalanced-tuple-unpacking
year,month,day,hour,minute,second = lst
machine.RTC().datetime((year, month, day, 0, hour, minute, second, 0))
else:
failed = True
else:
failed = True
except Exception as err:
failed = True
tools.logger.syslog(err)
if failed is True:
tools.console.Console.print('Expected format "YYYY/MM/DD hh:mm:ss"')
def formatsd(fstype="FAT"):
""" Format sd card """
if fstype in ["FAT","LFS"]:
if tools.sdcard.SdCard.is_mounted() is False:
res = input("All data will be lost on Sd card ? proceed with format (y/n) :")
if res in ["y","Y"]:
if tools.sdcard.SdCard.formatsd() is True:
tools.console.Console.print("Formatting terminated")
else:
tools.console.Console.print("Formatting failed")
else:
tools.console.Console.print("Sd card is mounted, a reboot required")
else:
tools.console.Console.print("Filesystem supported : FAT or LFS")
def cleanupsd():
""" Remove not useful directory and file from sd card """
if tools.sdcard.SdCard.is_mounted():
cd(tools.sdcard.SdCard.get_mountpoint())
rm (".Spotlight-V100", recursive=True)
rm (".fseventsd", recursive=True)
rm (".Trashes", recursive=True)
rm ("RECYCLER", recursive=True)
rm ("/._*", recursive=True)
rm ("/.DS_Store", recursive=True)
rm ("System Volume Information", recursive=True)
else:
tools.console.Console.print("Sd card not mounted")
def reboot():
""" Reboot command """
try:
tools.system.reboot("Reboot device with command")
except:
machine.deepsleep(1000)
def deepsleep(seconds=60):
""" Deep sleep command """
machine.deepsleep(int(seconds)*1000)
def ligthsleep(seconds=60):
""" Light sleep command """
machine.lightsleep(int(seconds)*1000)
edit_class = None
def edit(file, no_color=False, read_only=False):
""" Edit command """
# pylint:disable=global-variable-not-assigned
global edit_class
if tools.console.Console.is_redirected() is False:
if edit_class is None:
try:
from shell.editor import Editor
except:
from editor import Editor
edit_class = Editor
edit_class(file, no_color=no_color, read_only=read_only)
def cat(file):
""" Cat command """
try:
f = open(file, "r")
height, width = get_screen_size()
count = 1
while 1:
line = f.readline()
if not line:
break
message = line.replace("\t"," ").rstrip()[:width]
count = print_part(message, width, height, count)
if count is None:
break
f.close()
except:
tools.console.Console.print("Cannot cat '%s'"%(file))
def df(mountpoint = None):
""" Display free disk space """
tools.console.Console.print(tools.strings.tostrings(tools.info.flashinfo(mountpoint=mountpoint)))
def gc():
""" Garbage collector command """
from gc import collect
collect()
def uptime():
""" Tell how long the system has been running """
tools.console.Console.print(tools.strings.tostrings(tools.info.uptime()))
def man(command):
""" Man command """
tools.console.Console.print(man_one(command))
def man_one(command_name):
""" Manual of one command """
try:
command_name, command_function, command_params, command_flags = get_command(command_name)
text = " " + command_name + " "
for param in command_params:
text += param + " "
text += "\n"
for flag,flagName,val in command_flags:
text += " %s : %s\n"%(flag,flagName)
result = text[:-1]
except:
result = "Unknown command '%s'"%command_name
return result
# pylint: disable=redefined-builtin
def help():
""" Help command """
height, width = get_screen_size()
count = 1
cmds = list(shell_commands.keys())
cmds.sort()
for command in cmds:
lines = man_one(command)
lines = "-"*30+"\n" + lines
for line in lines.split("\n"):
count = print_part(line, width, height, count)
if count is None:
return
def eval_(string):
""" Evaluate content of string """
tools.console.Console.print(eval(string))
def exec_(string):
""" Execute content of string """
exec(string)
shell_exited = False
def exit():
""" Exit shell command """
global shell_exited
shell_exited = True
def dump_(filename):
""" dump file content """
height, width = get_screen_size()
if tools.console.Console.is_redirected() is False:
width = (width - 12)//4
else:
width = 16
offset = 0
file = open(filename, "rb")
data = b' '
count = 1
while True:
line = io.BytesIO()
line.write(b'%08X ' % offset)
data = file.read(width)
if len(data) <= 0:
break
tools.strings.dump_line (data, line, width)
offset += width
count = print_part(line.getvalue(), width, height, count)
if count is None:
break
def cls():
""" clear screen """
tools.console.Console.print("\x1B[2J\x1B[0;0f", end="")
def check_cam_flasher():
""" Check if the terminal is CamFlasher """
# pylint:disable=global-variable-not-assigned
if tools.console.Console.is_redirected() is False:
# Request terminal device attribut
sys.stdout.write(b"\x1B[0c")
# Wait terminal device attribut response
response = tools.terminal.getch(duration=1000)
# If CamFlasher detected
if response == "\x1B[?3;2c":
return True
return False
def upload(file="", recursive=False):
""" Upload file from computer to device """
if check_cam_flasher():
tools.console.Console.print("Upload to device start")
try:
command = tools.exchange.UploadCommand(uos.getcwd())
command.write(file, recursive, sys.stdin.buffer, sys.stdout.buffer)
result = True
while result:
file_reader = tools.exchange.FileReader()
result = file_reader.read(uos.getcwd(), sys.stdin.buffer, sys.stdout.buffer)
tools.watchdog.WatchDog.feed()
tools.console.Console.print("Upload end")
except Exception as err:
tools.logger.syslog(err, display=False)
tools.console.Console.print("Upload failed")
else:
tools.console.Console.print("CamFlasher application required for this command")
class Exporter:
""" Exporter file to camflasher """
def __init__(self):
""" Constructor """
def send_file(self, path):
""" Send the file """
result = True
fileinfo = tools.filesystem.fileinfo(path)
# If a file
if fileinfo[0] & 0x4000 != 0x4000:
file_write = tools.exchange.FileWriter()
if tools.filesystem.exists(path):
sys.stdout.buffer.write("࿊".encode("utf8"))
result = file_write.write(path, sys.stdin.buffer, sys.stdout.buffer)
tools.watchdog.WatchDog.feed()
return result
def show(self, path):
""" Show the information of a file or directory """
for _ in range(3):
# If the send successful exit, else retry three time
if self.send_file(path) is True:
break
def show_dir(self, state):
""" Indicates if the directory must show """
def download(file="", recursive=False):
""" Download file from device to computer """
if check_cam_flasher():
tools.console.Console.print("Download from device start")
try:
searchfile(file, recursive, Exporter())
tools.console.Console.print("Download end")
except Exception as err:
tools.logger.syslog(err, display=False)
tools.console.Console.print("Download failed")
else:
tools.console.Console.print("CamFlasher application required for this command")
def temperature():
""" Get the internal temperature """
celcius, farenheit = tools.info.temperature()
tools.console.Console.print("%.2f°C, %d°F"%(celcius, farenheit))
def meminfo():
""" Get memory informations """
tools.console.Console.print(tools.strings.tostrings(b"%s : %s"%(tools.lang.memory_label, tools.info.meminfo())))
def flashinfo(mountpoint=None):
""" Get flash informations """
tools.console.Console.print(tools.strings.tostrings(b"%s : %s"%(tools.lang.flash_label, tools.info.flashinfo(mountpoint=mountpoint))))
def sysinfo():
""" Get system informations """
tools.console.Console.print(tools.strings.tostrings(tools.info.sysinfo()))
def execute(python_string):
""" Execute python string """
exec(python_string)
def evaluate(python_string):
""" Evaluate python string """
print(eval(python_string))
def vtcolors():
""" Show all VT100 colors """
res = b'\x1B[4m4 bits colors\x1B[m\n'
for i in range(16):
if i % 8 == 0:
res += b"\n "
if i < 9:
forecolor = 15
else:
forecolor = 0
res += b"\x1B[38;5;%dm\x1B[48;5;%dm %2d \x1B[0m"%(forecolor, i,i)
res += b'\n\n\x1B[4m8 bits colors\x1B[m\n'
j = 0
for i in range(16,256):
if j % 12== 0:
res += b"\n "
backcolor = i
if j % 36 < 36//2:
forecolor = 15
else:
forecolor = 0
res += b"\x1B[38;5;%dm\x1B[48;5;%dm %3d \x1B[0m"%(forecolor,backcolor,i)
j += 1
res += b'\n\n\x1B[4mModifiers\x1B[m\n\n'
for i,j in [(0,"reset/normal"),(1,b"bold"),(3,b"italic"),(4,b"underline"),(7,b"reverse")]:
res += b" %d : \x1B[%dm%s\x1B[0m\n"%(i,i,j)
res += b'\n\x1B[4mExamples\x1B[m\n\n'
res += b' >>> print("\\033[\033[1m1\033[m;\033[7m7\033[mmBold reverse\\033[0m")\n'
res += b" \033[1;7mBold reverse\033[0m"
res += b"\n\n"
res += b' >>> print("\033[38;5;15m\033[48;5;1m\\033[48;5;1m\033[m\033[38;5;13m\\033[38;5;13m\033[mHello\\033[m")\n'
res += b" \033[48;5;1m\033[38;5;13mHello\033[m\n"
tools.console.Console.print(res.decode("utf8"))
def get_command(command_name):
""" Get a command callback according to the command name """
try:
# pylint:disable=global-variable-not-assigned
global shell_commands
command = shell_commands[command_name]
command_function = command[0]
command_params = []
command_flags = []
for item in command[1:]:
if type(item) == type(""):
command_params.append(item)
if type(item) == type((0,)):
command_flags.append(item)
except Exception as err:
# pylint: disable=raise-missing-from
raise RuntimeError("Command not found '%s'"%command_name)
return command_name, command_function, command_params, command_flags
def exec_command(args):
""" Execute command """
# pylint:disable=global-variable-not-assigned
command_name = ""
command_function = None
command_params = []
command_flags = []
output_redirection = None
output_filename = None
try:
if len(args) >= 1:
paramsCount = 0
flags = {}
for arg in args:
arg = arg.strip()
if len(arg) > 0:
if command_name == "":
command_name, command_function, command_params, command_flags = get_command(arg)
else:
if len(arg) >= 2 and arg[:2] == "--":
for commandFlag in command_flags:
if arg.strip()[2:] == commandFlag[1].strip():
flags[commandFlag[1]] = commandFlag[2]
break
else:
raise RuntimeError("Illegal option '%s'"%arg)
elif arg[0] == "-":
for commandFlag in command_flags:
if arg.strip() == commandFlag[0].strip():
flags[commandFlag[1]] = commandFlag[2]
break
else:
raise RuntimeError("Illegal option '%s'"%arg)
elif arg[0] == ">":
output_redirection = True
else:
if output_redirection is None:
if paramsCount >= len(command_params):
raise RuntimeError("Too many parameters on '%s'"%command_name)
else:
flags[command_params[paramsCount]] = arg
paramsCount += 1
elif output_redirection is True:
output_filename = arg
except Exception as err:
tools.console.Console.print(err)
return
tools.console.Console.close()
try:
if command_name.strip() != "":
if output_filename is not None:
try:
tools.console.Console.open(output_filename)
except:
pass
command_function(**flags)
except TypeError as err:
tools.logger.syslog(err, display=False)
tools.console.Console.print("Missing parameters for '%s'"%command_name)
except KeyboardInterrupt as err:
tools.logger.syslog(err)
tools.console.Console.print(" [Canceled]")
except Exception as err:
tools.logger.syslog(err)
finally:
tools.console.Console.close()
def parse_command_line(commandLine):
""" Parse command line """
commands_ = []
args = []
quote = None
arg = ""
for char in commandLine:
if char == '"' or char == "'":
if quote is not None:
if quote == char:
args.append(arg)
arg = ""
quote = None
else:
arg += char
else:
quote = char
elif char == " ":
if quote is not None:
arg += char
else:
args.append(arg)
arg = ""
elif char == ";":
if quote is not None:
arg += char
else:
if len(arg) > 0:
args.append(arg)
commands_.append(args)
arg = ""
args = []
else:
arg += char
if len(arg) > 0:
args.append(arg)
if len(args) > 0:
commands_.append(args)
for command in commands_:
exec_command(command)
def commands(path=None, throw=False):
""" Start the shell """
global shell_exited, shell_commands
current_dir = uos.getcwd()
create_shell_commands()
if path is not None:
uos.chdir(path)
shell_exited = False
while shell_exited is False:
try:
commandLine = ""
commandLine = input("%s=> "%os.getcwd())
tools.watchdog.WatchDog.feed()
except EOFError:
tools.console.Console.print("")
break
except KeyboardInterrupt:
tools.console.Console.print("Ctr-C detected, use 'exit' to restart server or 'quit' to get python prompt")
if commandLine.strip() == "quit":
if throw is True:
raise KeyboardInterrupt()
else:
break
parse_command_line(commandLine)
shell_commands = None
uos.chdir(current_dir)
def create_shell_commands():
""" Return the shell commands """
global shell_commands
shell_commands = \
{
"cd" :[cd ,"directory" ],
"pwd" :[pwd ],
"cat" :[cat ,"file" ],
"cls" :[cls ],
"mkdir" :[mkdir ,"directory", ("-r","recursive",True)],
"mv" :[mv ,"source","destination", ("-q","quiet",True) ],
"rmdir" :[rmdir ,"directory", ("-r","recursive",True),("-f","force",True),("-q","quiet",True),("-s","simulate",True)],
"cp" :[cp ,"source","destination", ("-r","recursive",True),("-q","quiet",True)],
"rm" :[rm ,"file", ("-r","recursive",True),("-f","force",True),("-s","simulate",True)],
"ls" :[ls ,"file", ("-r","recursive",True),("-l","long",True)],
"ll" :[ll ,"file", ("-r","recursive",True)],
"date" :[date_time ,"offsetUTC" , ("-u","update",True), ("-n","noDst",True)],
"setdate" :[setdate ,"datetime" ],
"uptime" :[uptime ],
"find" :[find ,"file" ],
"run" :[tools.useful.run ,"filename" ],
"download" :[download ,"file", ("-r","recursive",True)],
"upload" :[upload ,"file", ("-r","recursive",True)],
"edit" :[edit ,"file", ("-n","no_color",True),("-r","read_only",True)],
"exit" :[exit ],
"exec" :[execute ,"python_string" ],
"eval" :[evaluate ,"python_string" ],
"gc" :[gc ],
"grep" :[grep ,"text","file", ("-r","recursive",True),("-i","ignorecase",True),("-e","regexp",True)],
"mount" :[mountsd ,"mountpoint" ],
"umount" :[umountsd ,"mountpoint" ],
"temperature":[temperature ],
"meminfo" :[meminfo ],
"flashinfo" :[flashinfo ],
"sysinfo" :[sysinfo ],
"deepsleep" :[deepsleep ,"seconds" ],
"lightsleep" :[ligthsleep ,"seconds" ],
"ping" :[ping ,"host" ],
"reboot" :[reboot ],
"help" :[help ],
"man" :[man ,"command" ],
"memdump" :[tools.info.memdump ],
"df" :[df ,"mountpoint" ],
"ip2host" :[ip2host ,"ip_address" ],
"host2ip" :[host2ip ,"hostname" ],
"eval" :[eval_ ,"string" ],
"exec" :[exec_ ,"string" ],
"dump" :[dump_ ,"filename" ],
"formatsd" :[formatsd ,"fstype" ],
"cleanupsd" :[cleanupsd ],
"vtcolors" :[vtcolors ],
}
if __name__ == "__main__":
commands(sys.argv[1])
Functions
def cat(file)-
Cat command
Expand source code
def cat(file): """ Cat command """ try: f = open(file, "r") height, width = get_screen_size() count = 1 while 1: line = f.readline() if not line: break message = line.replace("\t"," ").rstrip()[:width] count = print_part(message, width, height, count) if count is None: break f.close() except: tools.console.Console.print("Cannot cat '%s'"%(file)) def cd(directory='/')-
Change directory
Expand source code
def cd(directory = "/"): """ Change directory """ try: uos.chdir(tools.filesystem.normpath(directory)) except: if directory != ".": tools.console.Console.print("No such file or directory '%s'"%directory) def check_cam_flasher()-
Check if the terminal is CamFlasher
Expand source code
def check_cam_flasher(): """ Check if the terminal is CamFlasher """ # pylint:disable=global-variable-not-assigned if tools.console.Console.is_redirected() is False: # Request terminal device attribut sys.stdout.write(b"\x1B[0c") # Wait terminal device attribut response response = tools.terminal.getch(duration=1000) # If CamFlasher detected if response == "\x1B[?3;2c": return True return False def cleanupsd()-
Remove not useful directory and file from sd card
Expand source code
def cleanupsd(): """ Remove not useful directory and file from sd card """ if tools.sdcard.SdCard.is_mounted(): cd(tools.sdcard.SdCard.get_mountpoint()) rm (".Spotlight-V100", recursive=True) rm (".fseventsd", recursive=True) rm (".Trashes", recursive=True) rm ("RECYCLER", recursive=True) rm ("/._*", recursive=True) rm ("/.DS_Store", recursive=True) rm ("System Volume Information", recursive=True) else: tools.console.Console.print("Sd card not mounted") def cls()-
clear screen
Expand source code
def cls(): """ clear screen """ tools.console.Console.print("\x1B[2J\x1B[0;0f", end="") def commands(path=None, throw=False)-
Start the shell
Expand source code
def commands(path=None, throw=False): """ Start the shell """ global shell_exited, shell_commands current_dir = uos.getcwd() create_shell_commands() if path is not None: uos.chdir(path) shell_exited = False while shell_exited is False: try: commandLine = "" commandLine = input("%s=> "%os.getcwd()) tools.watchdog.WatchDog.feed() except EOFError: tools.console.Console.print("") break except KeyboardInterrupt: tools.console.Console.print("Ctr-C detected, use 'exit' to restart server or 'quit' to get python prompt") if commandLine.strip() == "quit": if throw is True: raise KeyboardInterrupt() else: break parse_command_line(commandLine) shell_commands = None uos.chdir(current_dir) def copyfile(src, dst, quiet)-
Copy file
Expand source code
def copyfile(src,dst,quiet): """ Copy file """ dst = dst.replace("//","/") dst = dst.replace("//","/") dstdir, dstfile = tools.filesystem.split(dst) try: if not tools.filesystem.exists(dstdir): if dstdir != "." and dstdir != "": mkdir(dstdir, recursive=True, quiet=quiet) src_file = open(src, 'rb') dst_file = open(dst, 'wb') if quiet is False: tools.console.Console.print("cp '%s' -> '%s'"%(src,dst)) while True: buf = src_file.read(256) if len(buf) > 0: dst_file.write(buf) if len(buf) < 256: break src_file.close() dst_file.close() except: tools.console.Console.print("Cannot cp '%s' -> '%s'"%(src, dst)) def cp(source, destination, recursive=False, quiet=False)-
Copy file command
Expand source code
def cp(source, destination, recursive=False, quiet=False): """ Copy file command """ source = tools.filesystem.normpath(source) destination = tools.filesystem.normpath(destination) if tools.filesystem.isfile(source): copyfile(source,destination,quiet) else: if tools.filesystem.isdir(source): path = source pattern = "*" else: path, pattern = tools.filesystem.split(source) _, filenames = tools.filesystem.scandir(path, pattern, recursive) for src in filenames: dst = destination + "/" + src[len(path):] copyfile(src,dst,quiet) def create_shell_commands()-
Return the shell commands
Expand source code
def create_shell_commands(): """ Return the shell commands """ global shell_commands shell_commands = \ { "cd" :[cd ,"directory" ], "pwd" :[pwd ], "cat" :[cat ,"file" ], "cls" :[cls ], "mkdir" :[mkdir ,"directory", ("-r","recursive",True)], "mv" :[mv ,"source","destination", ("-q","quiet",True) ], "rmdir" :[rmdir ,"directory", ("-r","recursive",True),("-f","force",True),("-q","quiet",True),("-s","simulate",True)], "cp" :[cp ,"source","destination", ("-r","recursive",True),("-q","quiet",True)], "rm" :[rm ,"file", ("-r","recursive",True),("-f","force",True),("-s","simulate",True)], "ls" :[ls ,"file", ("-r","recursive",True),("-l","long",True)], "ll" :[ll ,"file", ("-r","recursive",True)], "date" :[date_time ,"offsetUTC" , ("-u","update",True), ("-n","noDst",True)], "setdate" :[setdate ,"datetime" ], "uptime" :[uptime ], "find" :[find ,"file" ], "run" :[tools.useful.run ,"filename" ], "download" :[download ,"file", ("-r","recursive",True)], "upload" :[upload ,"file", ("-r","recursive",True)], "edit" :[edit ,"file", ("-n","no_color",True),("-r","read_only",True)], "exit" :[exit ], "exec" :[execute ,"python_string" ], "eval" :[evaluate ,"python_string" ], "gc" :[gc ], "grep" :[grep ,"text","file", ("-r","recursive",True),("-i","ignorecase",True),("-e","regexp",True)], "mount" :[mountsd ,"mountpoint" ], "umount" :[umountsd ,"mountpoint" ], "temperature":[temperature ], "meminfo" :[meminfo ], "flashinfo" :[flashinfo ], "sysinfo" :[sysinfo ], "deepsleep" :[deepsleep ,"seconds" ], "lightsleep" :[ligthsleep ,"seconds" ], "ping" :[ping ,"host" ], "reboot" :[reboot ], "help" :[help ], "man" :[man ,"command" ], "memdump" :[tools.info.memdump ], "df" :[df ,"mountpoint" ], "ip2host" :[ip2host ,"ip_address" ], "host2ip" :[host2ip ,"hostname" ], "eval" :[eval_ ,"string" ], "exec" :[exec_ ,"string" ], "dump" :[dump_ ,"filename" ], "formatsd" :[formatsd ,"fstype" ], "cleanupsd" :[cleanupsd ], "vtcolors" :[vtcolors ], } def date_time(update=False, offsetUTC=1, noDst=False)-
Get or set date
Expand source code
def date_time(update=False, offsetUTC=+1, noDst=False): """ Get or set date """ try: from server.timesetting import set_date if update: if noDst: dst = False else: dst = True set_date(offsetUTC, dst) del sys.modules["server.timesetting"] except: pass tools.console.Console.print(tools.date.date_to_string()) def deepsleep(seconds=60)-
Deep sleep command
Expand source code
def deepsleep(seconds=60): """ Deep sleep command """ machine.deepsleep(int(seconds)*1000) def df(mountpoint=None)-
Display free disk space
Expand source code
def df(mountpoint = None): """ Display free disk space """ tools.console.Console.print(tools.strings.tostrings(tools.info.flashinfo(mountpoint=mountpoint))) def download(file='', recursive=False)-
Download file from device to computer
Expand source code
def download(file="", recursive=False): """ Download file from device to computer """ if check_cam_flasher(): tools.console.Console.print("Download from device start") try: searchfile(file, recursive, Exporter()) tools.console.Console.print("Download end") except Exception as err: tools.logger.syslog(err, display=False) tools.console.Console.print("Download failed") else: tools.console.Console.print("CamFlasher application required for this command") def dump_(filename)-
dump file content
Expand source code
def dump_(filename): """ dump file content """ height, width = get_screen_size() if tools.console.Console.is_redirected() is False: width = (width - 12)//4 else: width = 16 offset = 0 file = open(filename, "rb") data = b' ' count = 1 while True: line = io.BytesIO() line.write(b'%08X ' % offset) data = file.read(width) if len(data) <= 0: break tools.strings.dump_line (data, line, width) offset += width count = print_part(line.getvalue(), width, height, count) if count is None: break def edit(file, no_color=False, read_only=False)-
Edit command
Expand source code
def edit(file, no_color=False, read_only=False): """ Edit command """ # pylint:disable=global-variable-not-assigned global edit_class if tools.console.Console.is_redirected() is False: if edit_class is None: try: from shell.editor import Editor except: from editor import Editor edit_class = Editor edit_class(file, no_color=no_color, read_only=read_only) def eval_(string)-
Evaluate content of string
Expand source code
def eval_(string): """ Evaluate content of string """ tools.console.Console.print(eval(string)) def evaluate(python_string)-
Evaluate python string
Expand source code
def evaluate(python_string): """ Evaluate python string """ print(eval(python_string)) def exec_(string)-
Execute content of string
Expand source code
def exec_(string): """ Execute content of string """ exec(string) def exec_command(args)-
Execute command
Expand source code
def exec_command(args): """ Execute command """ # pylint:disable=global-variable-not-assigned command_name = "" command_function = None command_params = [] command_flags = [] output_redirection = None output_filename = None try: if len(args) >= 1: paramsCount = 0 flags = {} for arg in args: arg = arg.strip() if len(arg) > 0: if command_name == "": command_name, command_function, command_params, command_flags = get_command(arg) else: if len(arg) >= 2 and arg[:2] == "--": for commandFlag in command_flags: if arg.strip()[2:] == commandFlag[1].strip(): flags[commandFlag[1]] = commandFlag[2] break else: raise RuntimeError("Illegal option '%s'"%arg) elif arg[0] == "-": for commandFlag in command_flags: if arg.strip() == commandFlag[0].strip(): flags[commandFlag[1]] = commandFlag[2] break else: raise RuntimeError("Illegal option '%s'"%arg) elif arg[0] == ">": output_redirection = True else: if output_redirection is None: if paramsCount >= len(command_params): raise RuntimeError("Too many parameters on '%s'"%command_name) else: flags[command_params[paramsCount]] = arg paramsCount += 1 elif output_redirection is True: output_filename = arg except Exception as err: tools.console.Console.print(err) return tools.console.Console.close() try: if command_name.strip() != "": if output_filename is not None: try: tools.console.Console.open(output_filename) except: pass command_function(**flags) except TypeError as err: tools.logger.syslog(err, display=False) tools.console.Console.print("Missing parameters for '%s'"%command_name) except KeyboardInterrupt as err: tools.logger.syslog(err) tools.console.Console.print(" [Canceled]") except Exception as err: tools.logger.syslog(err) finally: tools.console.Console.close() def execute(python_string)-
Execute python string
Expand source code
def execute(python_string): """ Execute python string """ exec(python_string) def exit()-
Exit shell command
Expand source code
def exit(): """ Exit shell command """ global shell_exited shell_exited = True def find(file)-
Find a file in directories
Expand source code
def find(file): """ Find a file in directories """ filenames = searchfile(file, True) for filename in filenames: tools.console.Console.print(filename) def flashinfo(mountpoint=None)-
Get flash informations
Expand source code
def flashinfo(mountpoint=None): """ Get flash informations """ tools.console.Console.print(tools.strings.tostrings(b"%s : %s"%(tools.lang.flash_label, tools.info.flashinfo(mountpoint=mountpoint)))) def formatsd(fstype='FAT')-
Format sd card
Expand source code
def formatsd(fstype="FAT"): """ Format sd card """ if fstype in ["FAT","LFS"]: if tools.sdcard.SdCard.is_mounted() is False: res = input("All data will be lost on Sd card ? proceed with format (y/n) :") if res in ["y","Y"]: if tools.sdcard.SdCard.formatsd() is True: tools.console.Console.print("Formatting terminated") else: tools.console.Console.print("Formatting failed") else: tools.console.Console.print("Sd card is mounted, a reboot required") else: tools.console.Console.print("Filesystem supported : FAT or LFS") def gc()-
Garbage collector command
Expand source code
def gc(): """ Garbage collector command """ from gc import collect collect() def get_command(command_name)-
Get a command callback according to the command name
Expand source code
def get_command(command_name): """ Get a command callback according to the command name """ try: # pylint:disable=global-variable-not-assigned global shell_commands command = shell_commands[command_name] command_function = command[0] command_params = [] command_flags = [] for item in command[1:]: if type(item) == type(""): command_params.append(item) if type(item) == type((0,)): command_flags.append(item) except Exception as err: # pylint: disable=raise-missing-from raise RuntimeError("Command not found '%s'"%command_name) return command_name, command_function, command_params, command_flags def get_screen_size()-
Return the screen size and check if output redirected
Expand source code
def get_screen_size(): """ Return the screen size and check if output redirected """ # pylint:disable=global-variable-not-assigned if tools.console.Console.is_redirected() is False: height, width = tools.terminal.get_screen_size() else: height, width = tools.terminal.MAXINT, 80 return height, width def grep(file, text, recursive=False, ignorecase=False, regexp=False)-
Grep command
Expand source code
def grep(file, text, recursive=False, ignorecase=False, regexp=False): """ Grep command """ from re import search file = tools.filesystem.normpath(file) def __search(text, content, ignorecase, regexp): if ignorecase: content = content.lower() text = text.lower() if regexp: if search(text, content): return True else: if content.find(text) != -1: return True return False def __grep(text, filename, ignorecase, regexp, width, height, count): lineNumber = 1 with open(filename,"r", encoding="latin-1") as f: while 1: line = f.readline() if line: if __search(text, line, ignorecase, regexp): line = line.replace("\t"," ") message = "%s:%d:%s"%(filename, lineNumber, line) message = message.rstrip()[:width] count = print_part(message, width, height, count) if count is None: tools.console.Console.print("") return None lineNumber += 1 else: break return count if tools.filesystem.isfile(file): filenames = [file] else: path, pattern = tools.filesystem.split(file) _, filenames = tools.filesystem.scandir(path, pattern, recursive) height, width = get_screen_size() count = 1 for filename in filenames: count = __grep(text, filename, ignorecase, regexp, width, height, count) if count is None: break def help()-
Help command
Expand source code
def help(): """ Help command """ height, width = get_screen_size() count = 1 cmds = list(shell_commands.keys()) cmds.sort() for command in cmds: lines = man_one(command) lines = "-"*30+"\n" + lines for line in lines.split("\n"): count = print_part(line, width, height, count) if count is None: return def host2ip(hostname)-
Convert hostname to ip
Expand source code
def host2ip(hostname): """ Convert hostname to ip """ try: import wifi.station _, _, _, dns = wifi.station.Station.get_info() from server.dnsclient import resolve_ip_address tools.console.Console.print(resolve_ip_address(dns, hostname)) except: tools.console.Console.print("Not available") def ip2host(ip_address)-
Convert ip to hostname
Expand source code
def ip2host(ip_address): """ Convert ip to hostname """ try: import wifi.station _, _, _, dns = wifi.station.Station.get_info() from server.dnsclient import resolve_hostname tools.console.Console.print(resolve_hostname(dns, ip_address)) except: tools.console.Console.print("Not available") def ligthsleep(seconds=60)-
Light sleep command
Expand source code
def ligthsleep(seconds=60): """ Light sleep command """ machine.lightsleep(int(seconds)*1000) def ll(file='', recursive=False)-
List files long command
Expand source code
def ll(file="", recursive=False): """ List files long command """ searchfile(file, recursive, Displayer(uos.getcwd(), True)) def ls(file='', recursive=False, long=False)-
List files command
Expand source code
def ls(file="", recursive=False, long=False): """ List files command """ searchfile(file, recursive, Displayer(uos.getcwd(), long)) def man(command)-
Man command
Expand source code
def man(command): """ Man command """ tools.console.Console.print(man_one(command)) def man_one(command_name)-
Manual of one command
Expand source code
def man_one(command_name): """ Manual of one command """ try: command_name, command_function, command_params, command_flags = get_command(command_name) text = " " + command_name + " " for param in command_params: text += param + " " text += "\n" for flag,flagName,val in command_flags: text += " %s : %s\n"%(flag,flagName) result = text[:-1] except: result = "Unknown command '%s'"%command_name return result def meminfo()-
Get memory informations
Expand source code
def meminfo(): """ Get memory informations """ tools.console.Console.print(tools.strings.tostrings(b"%s : %s"%(tools.lang.memory_label, tools.info.meminfo()))) def mkdir(directory, recursive=False, quiet=False)-
Make directory
Expand source code
def mkdir(directory, recursive=False, quiet=False): """ Make directory """ try: if quiet is False: tools.console.Console.print("mkdir '%s'"%directory) tools.filesystem.makedir(tools.filesystem.normpath(directory), recursive) except: tools.console.Console.print("Cannot mkdir '%s'"%directory) def mountsd(mountpoint='/sd')-
Mount command
Expand source code
def mountsd(mountpoint="/sd"): """ Mount command """ try: tools.sdcard.SdCard.mount(mountpoint) tools.console.Console.print("Sd mounted on '%s'"%mountpoint) except: tools.console.Console.print("Cannot mount sd on '%s'"%mountpoint) def movefile(source, destination, quiet)-
Move file
Expand source code
def movefile(source, destination, quiet): """ Move file """ source = tools.filesystem.normpath(source) destination = tools.filesystem.normpath(destination) if quiet is False: tools.console.Console.print("mv '%s' -> '%s'"%(source,destination)) uos.rename(source,destination) def mv(source, destination, quiet=False)-
Move or rename file
Expand source code
def mv(source, destination, quiet=False): """ Move or rename file """ source = tools.filesystem.normpath(source) destination = tools.filesystem.normpath(destination) try: if tools.filesystem.isfile(source): movefile(source,destination,quiet) else: if tools.filesystem.isdir(source): # If destination existing if tools.filesystem.exists(destination): # If destination is file if tools.filesystem.isfile(destination): raise IOError() else: # Move source into destination directory destination = destination + "/" + tools.filesystem.split(source)[1] movefile(tools.filesystem.normpath(source),tools.filesystem.normpath(destination), quiet) else: # Rename movefile(tools.filesystem.normpath(source),tools.filesystem.normpath(destination), quiet) else: # Move many files path, pattern = tools.filesystem.split(source) if path == "": path = uos.getcwd() _, filenames = tools.filesystem.scandir(path, pattern, False) for src in filenames: dst = destination + "/" + src[len(path):] movefile(src,dst,quiet) except: tools.console.Console.print("Cannot mv '%s'->'%s'"%(source,destination)) def parse_command_line(commandLine)-
Parse command line
Expand source code
def parse_command_line(commandLine): """ Parse command line """ commands_ = [] args = [] quote = None arg = "" for char in commandLine: if char == '"' or char == "'": if quote is not None: if quote == char: args.append(arg) arg = "" quote = None else: arg += char else: quote = char elif char == " ": if quote is not None: arg += char else: args.append(arg) arg = "" elif char == ";": if quote is not None: arg += char else: if len(arg) > 0: args.append(arg) commands_.append(args) arg = "" args = [] else: arg += char if len(arg) > 0: args.append(arg) if len(args) > 0: commands_.append(args) for command in commands_: exec_command(command) def ping(host)-
Ping host
Expand source code
def ping(host): """ Ping host """ try: from server.ping import ping as ping_ ping_(host, count=4, timeout=1) except: tools.console.Console.print("Not available") def print_part(message, width, height, count)-
Print a part of text
Expand source code
def print_part(message, width, height, count): """ Print a part of text """ # pylint:disable=global-variable-not-assigned if isinstance(message , bytes): message = message.decode("utf8") if count is not None and count >= height: tools.console.Console.print(message,end="") if tools.console.Console.is_redirected() is False: key = tools.terminal.getch() else: key = " " count = 1 if key in ["x","X","q","Q","\x1B"]: return None tools.console.Console.print("\n", end="") else: if count is None: count = 1 else: count += 1 tools.console.Console.print(message) return count def pwd()-
Display the current directory
Expand source code
def pwd(): """ Display the current directory """ tools.console.Console.print("%s"%uos.getcwd()) def reboot()-
Reboot command
Expand source code
def reboot(): """ Reboot command """ try: tools.system.reboot("Reboot device with command") except: machine.deepsleep(1000) def removedir(directory, force=False, quiet=False, simulate=False, ignore_error=False)-
Remove directory
Expand source code
def removedir(directory, force=False, quiet=False, simulate=False, ignore_error=False): """ Remove directory """ try: if tools.filesystem.exists(directory+"/.DS_Store"): rmfile(directory+"/.DS_Store", quiet, force, simulate) if (tools.filesystem.ismicropython() or force) and simulate is False: uos.rmdir(directory) if quiet is False: tools.console.Console.print("rmdir '%s'"%(directory)) except: if ignore_error is False: tools.console.Console.print("rmdir '%s' not removed"%(directory)) def rm(file, recursive=False, quiet=False, force=False, simulate=False)-
Remove file command
Expand source code
def rm(file, recursive=False, quiet=False, force=False, simulate=False): """ Remove file command """ remover = Remover(file, recursive, quiet, force, simulate) searchfile(file, recursive, remover) remover.remove_dir() def rmdir(directory, root=None, recursive=False, force=False, quiet=False, simulate=False, ignore_error=False)-
Remove directory
Expand source code
def rmdir(directory, root=None, recursive=False, force=False, quiet=False, simulate=False, ignore_error=False): """ Remove directory """ directory = tools.filesystem.normpath(directory) if recursive is False: removedir(directory, force=force, quiet=quiet, simulate=simulate, ignore_error=ignore_error) else: directories = [directory] d = directory while 1: parts = tools.filesystem.split(d) if parts[1] == "" or parts[0] == "": break if root: if len(parts[0]) <= len(root): break directories.append(parts[0]) d = parts[0] if "/" in directories: directories.remove("/") if tools.sdcard.SdCard.get_mountpoint() in directories: directories.remove(tools.sdcard.SdCard.get_mountpoint()) for d in directories: if tools.filesystem.exists(d) and d != ".": removedir(d, force=force, quiet=quiet, simulate=simulate, ignore_error=ignore_error) def rmfile(filename, quiet=False, force=False, simulate=False)-
Remove file
Expand source code
def rmfile(filename, quiet=False, force=False, simulate=False): """ Remove file """ try: if (tools.filesystem.ismicropython() or force) and simulate is False: uos.remove(tools.filesystem.normpath(filename)) if quiet is False: tools.console.Console.print("rm '%s'"%(filename)) except: tools.console.Console.print("rm '%s' not removed"%(filename)) def searchfile(file, recursive, obj=None)-
Search file
Expand source code
def searchfile(file, recursive, obj = None): """ Search file """ file = tools.filesystem.normpath(file) p = tools.filesystem.abspath(uos.getcwd(), file) filenames = [] try: # If file not defined then current directory used if file == "": _,filenames = tools.filesystem.scandir(uos.getcwd(), "*", recursive, obj) # If one file detected elif tools.filesystem.isfile(p): if obj is not None: obj.show_dir(False) obj.show(p) filenames = [p] # If directory detected elif tools.filesystem.isdir(p): _, filenames = tools.filesystem.scandir(p, "*", recursive, obj) # Else pattern detected else: path, pattern = tools.filesystem.split(p) if pattern != "*": if obj is not None: obj.show_dir(False) _, filenames = tools.filesystem.scandir(path, pattern, recursive, obj) except Exception as err: tools.console.Console.print(err) if len(filenames) == 0 and file != "" and file != "." and tools.filesystem.isdir(file) is False: tools.console.Console.print("%s : No such file or directory"%file) return filenames def setdate(datetime='')-
Set date and time
Expand source code
def setdate(datetime=""): """ Set date and time """ import re file_date=re.compile("[/: ]") failed = False try: spls = file_date.split(datetime) lst = [] if len(spls) > 1: for spl in spls: if len(spl) > 0: try: r = spl.lstrip("0") if len(r) == 0: lst.append(0) else: lst.append(eval(r)) except: failed = True break if len(lst) == 6: # pylint: disable=unbalanced-tuple-unpacking year,month,day,hour,minute,second = lst machine.RTC().datetime((year, month, day, 0, hour, minute, second, 0)) else: failed = True else: failed = True except Exception as err: failed = True tools.logger.syslog(err) if failed is True: tools.console.Console.print('Expected format "YYYY/MM/DD hh:mm:ss"') def sysinfo()-
Get system informations
Expand source code
def sysinfo(): """ Get system informations """ tools.console.Console.print(tools.strings.tostrings(tools.info.sysinfo())) def temperature()-
Get the internal temperature
Expand source code
def temperature(): """ Get the internal temperature """ celcius, farenheit = tools.info.temperature() tools.console.Console.print("%.2f°C, %d°F"%(celcius, farenheit)) def umountsd(mountpoint='/sd')-
Umount command
Expand source code
def umountsd(mountpoint="/sd"): """ Umount command """ try: tools.sdcard.SdCard.umount(mountpoint) tools.console.Console.print("Sd umounted from '%s'"%mountpoint) except: tools.console.Console.print("Cannot umount sd from '%s'"%mountpoint) def upload(file='', recursive=False)-
Upload file from computer to device
Expand source code
def upload(file="", recursive=False): """ Upload file from computer to device """ if check_cam_flasher(): tools.console.Console.print("Upload to device start") try: command = tools.exchange.UploadCommand(uos.getcwd()) command.write(file, recursive, sys.stdin.buffer, sys.stdout.buffer) result = True while result: file_reader = tools.exchange.FileReader() result = file_reader.read(uos.getcwd(), sys.stdin.buffer, sys.stdout.buffer) tools.watchdog.WatchDog.feed() tools.console.Console.print("Upload end") except Exception as err: tools.logger.syslog(err, display=False) tools.console.Console.print("Upload failed") else: tools.console.Console.print("CamFlasher application required for this command") def uptime()-
Tell how long the system has been running
Expand source code
def uptime(): """ Tell how long the system has been running """ tools.console.Console.print(tools.strings.tostrings(tools.info.uptime())) def vtcolors()-
Show all VT100 colors
Expand source code
def vtcolors(): """ Show all VT100 colors """ res = b'\x1B[4m4 bits colors\x1B[m\n' for i in range(16): if i % 8 == 0: res += b"\n " if i < 9: forecolor = 15 else: forecolor = 0 res += b"\x1B[38;5;%dm\x1B[48;5;%dm %2d \x1B[0m"%(forecolor, i,i) res += b'\n\n\x1B[4m8 bits colors\x1B[m\n' j = 0 for i in range(16,256): if j % 12== 0: res += b"\n " backcolor = i if j % 36 < 36//2: forecolor = 15 else: forecolor = 0 res += b"\x1B[38;5;%dm\x1B[48;5;%dm %3d \x1B[0m"%(forecolor,backcolor,i) j += 1 res += b'\n\n\x1B[4mModifiers\x1B[m\n\n' for i,j in [(0,"reset/normal"),(1,b"bold"),(3,b"italic"),(4,b"underline"),(7,b"reverse")]: res += b" %d : \x1B[%dm%s\x1B[0m\n"%(i,i,j) res += b'\n\x1B[4mExamples\x1B[m\n\n' res += b' >>> print("\\033[\033[1m1\033[m;\033[7m7\033[mmBold reverse\\033[0m")\n' res += b" \033[1;7mBold reverse\033[0m" res += b"\n\n" res += b' >>> print("\033[38;5;15m\033[48;5;1m\\033[48;5;1m\033[m\033[38;5;13m\\033[38;5;13m\033[mHello\\033[m")\n' res += b" \033[48;5;1m\033[38;5;13mHello\033[m\n" tools.console.Console.print(res.decode("utf8"))
Classes
class Displayer (path, long, action=<function print_part>)-
Displayer file
Constructor
Expand source code
class Displayer: """ Displayer file """ def __init__(self, path, long, action=print_part): """ Constructor """ self.height, self.width = get_screen_size() self.path = path self.showdir = True self.count = 1 self.long = long self.action = action def purge_path(self, path): """ Purge the path for the display """ path = path.encode("utf8") path = tools.filesystem.normpath(path) prefix = tools.filesystem.prefix([path, self.path.encode("utf8")]) return path[len(prefix):].lstrip(b"/") def get_info(self, path): """ Get info on file or directory """ result = None, False fileinfo = tools.filesystem.fileinfo(path) file_date = fileinfo[8] size = fileinfo[6] # If directory if fileinfo[0] & 0x4000 == 0x4000: if self.showdir: if self.long: message = b"%s %s [%s]"%(tools.date.date_to_bytes(file_date),b" "*7,self.purge_path(path)) else: message = b"[%s]"%self.purge_path(path) result = message, True # If file else: if self.long: message = b"%s %s %s"%(tools.date.date_to_bytes(file_date),tools.strings.size_to_bytes(size),self.purge_path(path)) else: message = self.purge_path(path) result = message, False return result def show(self, path): """ Show the information of a file or directory """ message, directory = self.get_info(path) if message is not None: self.count = self.action(message, self.width, self.height, self.count) def show_dir(self, state): """ Indicates if the directory must show """ self.showdir = stateSubclasses
Methods
def get_info(self, path)-
Get info on file or directory
Expand source code
def get_info(self, path): """ Get info on file or directory """ result = None, False fileinfo = tools.filesystem.fileinfo(path) file_date = fileinfo[8] size = fileinfo[6] # If directory if fileinfo[0] & 0x4000 == 0x4000: if self.showdir: if self.long: message = b"%s %s [%s]"%(tools.date.date_to_bytes(file_date),b" "*7,self.purge_path(path)) else: message = b"[%s]"%self.purge_path(path) result = message, True # If file else: if self.long: message = b"%s %s %s"%(tools.date.date_to_bytes(file_date),tools.strings.size_to_bytes(size),self.purge_path(path)) else: message = self.purge_path(path) result = message, False return result def purge_path(self, path)-
Purge the path for the display
Expand source code
def purge_path(self, path): """ Purge the path for the display """ path = path.encode("utf8") path = tools.filesystem.normpath(path) prefix = tools.filesystem.prefix([path, self.path.encode("utf8")]) return path[len(prefix):].lstrip(b"/") def show(self, path)-
Show the information of a file or directory
Expand source code
def show(self, path): """ Show the information of a file or directory """ message, directory = self.get_info(path) if message is not None: self.count = self.action(message, self.width, self.height, self.count) def show_dir(self, state)-
Indicates if the directory must show
Expand source code
def show_dir(self, state): """ Indicates if the directory must show """ self.showdir = state
class Exporter-
Exporter file to camflasher
Constructor
Expand source code
class Exporter: """ Exporter file to camflasher """ def __init__(self): """ Constructor """ def send_file(self, path): """ Send the file """ result = True fileinfo = tools.filesystem.fileinfo(path) # If a file if fileinfo[0] & 0x4000 != 0x4000: file_write = tools.exchange.FileWriter() if tools.filesystem.exists(path): sys.stdout.buffer.write("࿊".encode("utf8")) result = file_write.write(path, sys.stdin.buffer, sys.stdout.buffer) tools.watchdog.WatchDog.feed() return result def show(self, path): """ Show the information of a file or directory """ for _ in range(3): # If the send successful exit, else retry three time if self.send_file(path) is True: break def show_dir(self, state): """ Indicates if the directory must show """Methods
def send_file(self, path)-
Send the file
Expand source code
def send_file(self, path): """ Send the file """ result = True fileinfo = tools.filesystem.fileinfo(path) # If a file if fileinfo[0] & 0x4000 != 0x4000: file_write = tools.exchange.FileWriter() if tools.filesystem.exists(path): sys.stdout.buffer.write("࿊".encode("utf8")) result = file_write.write(path, sys.stdin.buffer, sys.stdout.buffer) tools.watchdog.WatchDog.feed() return result def show(self, path)-
Show the information of a file or directory
Expand source code
def show(self, path): """ Show the information of a file or directory """ for _ in range(3): # If the send successful exit, else retry three time if self.send_file(path) is True: break def show_dir(self, state)-
Indicates if the directory must show
Expand source code
def show_dir(self, state): """ Indicates if the directory must show """
class Remover (file, recursive=False, quiet=False, force=False, simulate=False)-
Class to remove files and directories
Constructor
Expand source code
class Remover(Displayer): """ Class to remove files and directories """ def __init__(self, file, recursive=False, quiet=False, force=False, simulate=False): Displayer.__init__(self, uos.getcwd(), False) self.directories = set() self.path = uos.getcwd() self.file = file self.quiet = quiet self.force = force self.simulate = simulate self.recursive = recursive if recursive: if tools.filesystem.isdir(self.path + "/" + file): self.directories.add(self.path + "/" + file) def show(self, path): """ Show the information of a file or directory """ message, directory = self.get_info(path) if message is not None: if directory is False: rmfile(path, force=self.force, quiet=self.quiet, simulate=self.simulate) if directory: self.directories.add(path) def remove_dir(self): """ Remove directories """ if self.recursive: directories = list(self.directories) directories.sort() directories.reverse() for directory in directories: rmdir(directory, root=self.path, recursive=self.recursive, force=self.force, quiet=self.quiet, simulate=self.simulate, ignore_error=True)Ancestors
Methods
def remove_dir(self)-
Remove directories
Expand source code
def remove_dir(self): """ Remove directories """ if self.recursive: directories = list(self.directories) directories.sort() directories.reverse() for directory in directories: rmdir(directory, root=self.path, recursive=self.recursive, force=self.force, quiet=self.quiet, simulate=self.simulate, ignore_error=True)
Inherited members