aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Dzenis <rixript@gmail.com>2014-06-09 10:05:24 +0300
committerilya <ilja@Ilyas-MacBook-Pro.local>2014-10-24 17:46:19 +0300
commit7cfeaa73e5f046a5dbf2b2f4f7f266145acc10d3 (patch)
tree4584eb78cc1b07b8d8d0306eda9ce5615e69a1e0
parent6eaebe08e1aff3749075cc73b09d4ebb2c57dd5e (diff)
downloadpx4-firmware-7cfeaa73e5f046a5dbf2b2f4f7f266145acc10d3.tar.gz
px4-firmware-7cfeaa73e5f046a5dbf2b2f4f7f266145acc10d3.tar.bz2
px4-firmware-7cfeaa73e5f046a5dbf2b2f4f7f266145acc10d3.zip
Tools/fileman/ nsh scripts; writefile command.
-rwxr-xr-xTools/fileman/deletelogs.py24
-rwxr-xr-xTools/fileman/delmix.py24
-rwxr-xr-xTools/fileman/delrc.py24
-rwxr-xr-xTools/fileman/getlog.py80
-rwxr-xr-xTools/fileman/getmix.py34
-rwxr-xr-xTools/fileman/getrc.py34
-rwxr-xr-xTools/fileman/nsh.py222
-rwxr-xr-xTools/fileman/setmix.py30
-rwxr-xr-xTools/fileman/setrc.py30
-rwxr-xr-xsrc/systemcmds/writefile/module.mk8
-rwxr-xr-xsrc/systemcmds/writefile/writefile.c92
11 files changed, 602 insertions, 0 deletions
diff --git a/Tools/fileman/deletelogs.py b/Tools/fileman/deletelogs.py
new file mode 100755
index 000000000..b27b3e87b
--- /dev/null
+++ b/Tools/fileman/deletelogs.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# Logs deleter
+#
+
+from nsh import NSH
+
+def main():
+ try:
+ logs_dir = "/fs/microsd/log"
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ for file in nsh.get_all_files(logs_dir):
+ print("Removing file: {}{}".format(logs_dir, file))
+ nsh.exec_cmd("rm {}{}".format(logs_dir, file), 2.0)
+ for dir in nsh.get_all_dirs(logs_dir):
+ print("Removing dir: {}/{}".format(logs_dir, dir))
+ nsh.exec_cmd("rmdir {}/{}".format(logs_dir, dir[:-1]), 1.0)
+ print("Done.")
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/Tools/fileman/delmix.py b/Tools/fileman/delmix.py
new file mode 100755
index 000000000..b6b8cdd4b
--- /dev/null
+++ b/Tools/fileman/delmix.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# /fs/microsd/etc/mixers/FMU_quad_x.mix file deleter
+#
+
+from nsh import NSH
+
+def main():
+ fn = "/fs/microsd/etc/mixers/FMU_quad_x.mix"
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if nsh.file_exists(fn):
+ nsh.exec_cmd("rm {}".format(fn), 2.0)
+ print("Success.")
+ else:
+ print("Cannot find {}".format(fn))
+
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/Tools/fileman/delrc.py b/Tools/fileman/delrc.py
new file mode 100755
index 000000000..3606d2bed
--- /dev/null
+++ b/Tools/fileman/delrc.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# /fs/microsd/etc/rc.txt file deleter
+#
+
+from nsh import NSH
+
+def main():
+ fn = "/fs/microsd/etc/rc.txt"
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if nsh.file_exists(fn):
+ nsh.exec_cmd("rm {}".format(fn), 2.0)
+ print("Success.")
+ else:
+ print("Cannot find {}".format(fn))
+
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/Tools/fileman/getlog.py b/Tools/fileman/getlog.py
new file mode 100755
index 000000000..e3a68baac
--- /dev/null
+++ b/Tools/fileman/getlog.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+#
+# Log file downloader
+#
+
+from nsh import NSH
+from sys import argv, exit
+from datetime import datetime
+import re
+
+def main():
+ if(len(argv) != 2):
+ print("usage: getlog [last|list|log_path]")
+ exit(1)
+
+ cmd = argv[1]
+ logs_dir = "/fs/microsd/log"
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if cmd == "list":
+ for file in nsh.get_all_files(logs_dir):
+ print(file)
+ elif cmd == "all":
+ for file in nsh.get_all_files(logs_dir):
+ with open(fn[fn.rindex('/')+1:], "wb") as f:
+ data = nsh.download_file(logs_dir + file)
+ print("Writing buffer to file..")
+ f.write(data)
+ print("Success.")
+ elif cmd == "last":
+ dirs = nsh.ls_dir(logs_dir)
+ # Keep entries only "date/" entries
+ dirs = filter(lambda d: re.sub("[0-9]{4}\-[0-9]{2}\-[0-9]{2}", '', d) == "/", dirs)
+ if dirs:
+ dirs.sort(key=lambda x: datetime.strptime(x, '%Y-%m-%d/'))
+
+ last_dir = dirs.pop()
+ print("Getting logs from {}/{}".format(logs_dir, last_dir))
+
+ logs = nsh.ls_dir(logs_dir + '/' + last_dir)
+ # Keep entries only which end with .bin
+ logs = filter(lambda l: l.endswith('.bin'), logs)
+ if logs:
+ logs.sort(key=lambda x: datetime.strptime(x, "%H_%M_%S.bin"))
+
+ last_log = logs.pop()
+ data = nsh.download_file(logs_dir + '/' + last_dir + last_log)
+ with open(last_log, "wb") as f:
+ f.write(data)
+
+ preflight = "preflight_perf" + last_log[:-3] + "txt"
+ if nsh.file_exists(logs_dir + '/' + last_dir + preflight):
+ data = nsh.download_file(logs_dir + '/' + last_dir + preflight)
+ with open(preflight, "wb") as f:
+ f.write(data)
+ else:
+ print("Cannot find {} file (ignoring it).".format(preflight))
+
+ print("Success.")
+ else:
+ print("Cannot find any log with timestamp!")
+ else:
+ print("Unable to find any log with date")
+ else:
+ fn = logs_dir + "/" + cmd
+ if nsh.file_exists(fn):
+ data = nsh.download_file(fn)
+ with open(fn[fn.rindex('/')+1:], "wb") as f:
+ f.write(data)
+ print("Success.")
+ else:
+ print("File {} does not exists!")
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
+
diff --git a/Tools/fileman/getmix.py b/Tools/fileman/getmix.py
new file mode 100755
index 000000000..e375c71ae
--- /dev/null
+++ b/Tools/fileman/getmix.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# /fs/microsd/etc/mixers/FMU_quad_x.mix file downloader
+#
+
+from nsh import NSH
+
+def main():
+ fn = "/fs/microsd/etc/mixers/FMU_quad_x.mix"
+
+ if len(argv) == 1:
+ out_fn = fn[fn.rindex('/')+1:]
+ else:
+ out_fn = argv[1]
+
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if nsh.file_exists(fn):
+ with open(out_fn, "wb") as f:
+ data = nsh.download_file(fn)
+ print("Writing buffer to file..")
+ f.write(data)
+ print("Success.")
+ else:
+ print("Cannot find {}".format(fn))
+
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
+
diff --git a/Tools/fileman/getrc.py b/Tools/fileman/getrc.py
new file mode 100755
index 000000000..902fe857b
--- /dev/null
+++ b/Tools/fileman/getrc.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# /fs/microsd/etc/rc.txt file downloader
+#
+
+from nsh import NSH
+from sys import argv
+
+def main():
+ fn = "/fs/microsd/etc/rc.txt"
+
+ if len(argv) == 1:
+ out_fn = fn[fn.rindex('/')+1:]
+ else:
+ out_fn = argv[1]
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if nsh.file_exists(fn):
+ with open(out_fn, "wb") as f:
+ data = nsh.download_file(fn)
+ print("Writing buffer to file..")
+ f.write(data)
+ print("Success.")
+ else:
+ print("Cannot find {}".format(fn))
+
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
+
diff --git a/Tools/fileman/nsh.py b/Tools/fileman/nsh.py
new file mode 100755
index 000000000..8336b3c50
--- /dev/null
+++ b/Tools/fileman/nsh.py
@@ -0,0 +1,222 @@
+import os, sys, serial, time, struct
+
+class NSH:
+ def __init__(self):
+ self.serial = None
+
+ def flush(self):
+ self.serial.flush()
+
+ def send(self, data):
+ from collections import deque
+ data = deque(data)
+ attempt = 0
+ while data:
+ if self.serial.write(data.popleft()) == 0:
+ print("Failed to write {}".format(attempt))
+ attempt += 1
+ if attempt > 50:
+ raise RuntimeError("fail")
+ else:
+ attempt = 0
+ self.serial.flush()
+
+ def recv(self, size=1):
+ if size is not None:
+ attempt = 1
+ data = self.serial.read(size)
+ if len(data) < 1:
+ raise RuntimeError("timeout waiting for data")
+ size -= len(data)
+ if size > 0:
+ #raise RuntimeError("received less data than expected ({}/{})".format(len(data), size))
+ attempt += 1
+ if attempt > 10:
+ raise RuntimeError("Couldn't receive all the data ({} bytes left)".format(size))
+ return data
+ else:
+ return self.serial.read()
+
+ def wait_for_string(self, s, timeout, debug=False):
+ t0 = time.time()
+ buf = []
+ res = []
+ n = 0
+ if type(s) == str:
+ s = (s,)
+ maxlen = max((len(string) for string in s))
+ while True:
+ c = self.recv(size=None)
+ if debug:
+ sys.stderr.write(c)
+ buf.append(c)
+ if len(buf) > maxlen:
+ res.append(buf.pop(0))
+ n += 1
+ if n % 10000 == 0:
+ sys.stderr.write(str(n) + "\n")
+ string = "".join(buf)
+ for sz in s:
+ index = string.find(sz)
+ if index != -1:
+ res += buf[:index]
+ return "".join(res)
+ if timeout > 0.0 and time.time() - t0 > timeout:
+ raise Exception("Timeout while waiting for: {}".format(s))
+
+ def exec_cmd(self, cmd, timeout, cmd_end_str=("nsh> \x1b[K",)):
+ print("nsh> {}".format(cmd))
+ self.send(cmd + "\n")
+ self.flush()
+ self.wait_for_string(cmd + "\r\n", timeout)
+ if cmd_end_str:
+ return self.wait_for_string(cmd_end_str, timeout)
+ else:
+ return None
+
+ def identify(self):
+ #ver hw
+ #PX4FMU_V2
+ return self.exec_cmd("ver hw", 1.0).startswith("PX4FMU_V2")
+
+ def ls_dir(self, dir, timeout=1.0):
+ res = []
+ dir = dir.rstrip("/")
+ for line in self.exec_cmd("ls " + dir, timeout).splitlines()[1:]:
+ res.append(line[1:])
+ return res
+
+ def get_dir_files(self, directory="/"):
+ res = []
+ for f in self.ls_dir(directory):
+ if f[-1] != '/': #is file
+ res.append(f)
+ return f
+
+ def get_all_files(self, basedir="/", subdir="/"):
+ dir = basedir + subdir
+ res = []
+ for d in self.ls_dir(dir):
+ if d[-1] == '/':
+ res += self.get_all_files(basedir, subdir + d)
+ else:
+ res.append(subdir + d)
+ return res
+
+ def get_all_dirs(self, basedir="/", subdir="/"):
+ dir = basedir + subdir
+ res = []
+ for d in self.ls_dir(dir):
+ if d[-1] == '/':
+ res += self.get_all_files(basedir, subdir + d)
+ res.append(d)
+ return res
+
+ def file_exists(self, fn):
+ rslash = fn.rindex("/")
+ dir = fn[:rslash]
+ fn = fn[rslash+1:]
+ found = False
+ for file in self.ls_dir(dir):
+ if file == fn:
+ return True
+ return False
+
+ def download_file(self, fn):
+ res = self.exec_cmd("dumpfile " + fn, 1.0, ("\n",))
+ data = []
+ if res.startswith("OK"):
+ size = int(res.split()[1])
+ block_size = 1024 * 16
+ print("Reading file {}:".format(fn))
+ while size > 0:
+ buf = self.recv(min(size, block_size))
+ data.append(buf)
+ size -= len(buf)
+ print("Read {} bytes / {} left".format(len(buf), size))
+ sys.stdout.flush()
+ print("Successfully read file {}".format(fn))
+ else:
+ raise Exception("Error downloading file (not exists?)")
+ self.wait_for_string("nsh> \x1b[K", 2.0)
+ return "".join(data)
+
+ def random_str(self, length):
+ from random import shuffle
+ from math import ceil
+ abc = ''.join([chr(c) for c in range(ord('a'), ord('z') + 1)])
+ ABC = ''.join([chr(c) for c in range(ord('A'), ord('Z') + 1)])
+ num = '0123456789'
+ string = abc + ABC + num
+ mul = int(ceil(float(length) / len(string)))
+ res = list(string * mul)
+ shuffle(res)
+ return ''.join(res[:length])
+
+ def upload_file(self, out_fn, in_fn):
+ f = open(in_fn, 'rb')
+ filedata = f.read()
+ f.close()
+
+ szOK = "OK\r\n"
+ szDEFEND = "nsh> \x1b[K"
+
+ while True:
+ tmp_fn = '/fs/microsd/' + self.random_str(14) + '.tmp'
+ if not self.file_exists(tmp_fn):
+ break
+
+ res = self.exec_cmd("writefile {} {}".format(tmp_fn, len(filedata)), 1.0, (szDEFEND, szOK))
+ if len(res) == 0: #szOK found
+ self.flush()
+ print("Writing file {}".format(tmp_fn))
+ self.send(filedata)
+ self.wait_for_string("nsh> \x1b[K", 2.0)
+ print("Deleting {}".format(out_fn))
+ self.exec_cmd("rm {}".format(out_fn), 2.0)
+ print("Coping {} to {}".format(tmp_fn, out_fn))
+ self.exec_cmd("cp {} {}".format(tmp_fn, out_fn), 2.0)
+ print("Removing temponary file {}".format(tmp_fn))
+ self.exec_cmd("rm {}".format(tmp_fn), 2.0)
+ return True
+ else: #nsh> found
+ print("Error occured during the file upload (`{}` < `{}`)".format(out_fn, in_fn))
+ print(res)
+ return False
+
+ def wait_and_open_nsh(self):
+ print("Waiting for the device.. (Press Ctrl+C to stop)")
+ while True:
+ if os.name == 'nt':
+ port_list = ['COM32', 'COM31', 'COM30', 'COM29', 'COM28', 'COM27', 'COM26', 'COM25', 'COM24', 'COM23', 'COM22', 'COM21', 'COM20', 'COM19', 'COM18', 'COM17', 'COM16', 'COM15', 'COM14', 'COM13', 'COM12', 'COM11', 'COM10', 'COM9', 'COM8', 'COM7', 'COM6', 'COM5', 'COM4', 'COM3', 'COM2', 'COM1', 'COM0']
+ else:
+ from glob import glob
+ port_list = glob("/dev/serial/by-id/usb-3D_Robotics*") #linux
+ port_list += glob("/dev/tty.usbmodem*") #mac
+
+ for port in port_list:
+ try:
+ self.serial = serial.Serial(port, 57600, timeout=0.5)
+ except serial.SerialException:
+ #open failed, rate-limit our attempts
+ time.sleep(0.05)
+ # and loop to the next port
+ continue
+
+ # port is open, try talking to it
+ # identify the bootloader
+ if self.identify():
+ print("Found device on port {}".format(port))
+ return
+ else:
+ print("Ignoring invalid board on port {}".format(port))
+ self.close()
+ continue
+
+ def close(self):
+ if self.serial is not None:
+ self.serial.close()
+
+if __name__ == "__main__":
+ print("This is class file. It does nothing.")
+
diff --git a/Tools/fileman/setmix.py b/Tools/fileman/setmix.py
new file mode 100755
index 000000000..d010596c8
--- /dev/null
+++ b/Tools/fileman/setmix.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+#
+# /fs/microsd/etc/mixers/FMU_quad_x.mix file uploader
+#
+
+from nsh import NSH
+
+from os import path
+from sys import argv, exit
+
+def main():
+ if len(argv) != 2:
+ print("usage: setmix <path to FMU_quad_x.mix>")
+ exit(1)
+
+ rc_path = argv[1]
+ if not path.isfile(rc_path):
+ print("cannot find file {}".format(rc_path))
+ exit(2)
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if nsh.upload_file("/fs/microsd/etc/mixers/FMU_quad_x.mix", rc_path):
+ print("Success.")
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/Tools/fileman/setrc.py b/Tools/fileman/setrc.py
new file mode 100755
index 000000000..13088f721
--- /dev/null
+++ b/Tools/fileman/setrc.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+#
+# /fs/microsd/etc/rc.txt file uploader
+#
+
+from nsh import NSH
+
+from os import path
+from sys import argv, exit
+
+def main():
+ if len(argv) != 2:
+ print("usage: setrc <path to rc.txt>")
+ exit(1)
+
+ rc_path = argv[1]
+ if not path.isfile(rc_path):
+ print("cannot find file {}".format(rc_path))
+ exit(2)
+
+ try:
+ nsh = NSH()
+ nsh.wait_and_open_nsh()
+ if nsh.upload_file("/fs/microsd/etc/rc.txt", rc_path):
+ print("Success.")
+ finally:
+ nsh.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/src/systemcmds/writefile/module.mk b/src/systemcmds/writefile/module.mk
new file mode 100755
index 000000000..10390a454
--- /dev/null
+++ b/src/systemcmds/writefile/module.mk
@@ -0,0 +1,8 @@
+#
+# Write file utility
+#
+
+MODULE_COMMAND = writefile
+SRCS = writefile.c
+
+MAXOPTIMIZATION = -Os
diff --git a/src/systemcmds/writefile/writefile.c b/src/systemcmds/writefile/writefile.c
new file mode 100755
index 000000000..54b210805
--- /dev/null
+++ b/src/systemcmds/writefile/writefile.c
@@ -0,0 +1,92 @@
+/**
+ * @file writefile.c
+ *
+ * Write file utility. Writes file from stdin.
+ *
+ * @author Richard Dzenis <rixript@gmail.com>
+ */
+
+#include <nuttx/config.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <systemlib/err.h>
+
+__EXPORT int writefile_main(int argc, char *argv[]);
+
+static
+ssize_t
+min(ssize_t v1, ssize_t v2)
+{
+ return v1 > v2 ? v2 : v1;
+}
+
+int
+writefile_main(int argc, char *argv[])
+{
+ if (argc < 3) {
+ errx(1, "usage: writefile <filename> <filesize in bytes>");
+ }
+
+ /* open output file */
+ FILE *f;
+ f = fopen(argv[1], "w");
+
+ if (f == NULL) {
+ printf("ERROR opening file\n");
+ exit(1);
+ }
+
+ ssize_t size = atol(argv[2]);
+ if(size <= 0) {
+ warnx("ERROR invalid size");
+ }
+
+ /* configure stdin */
+ int in = fileno(stdin);
+
+ struct termios tc;
+ struct termios tc_old;
+ tcgetattr(in, &tc);
+
+ /* save old terminal attributes to restore it later on exit */
+ memcpy(&tc_old, &tc, sizeof(tc));
+
+ /* don't add CR on each LF*/
+ tc.c_oflag &= ~ONLCR;
+
+ if (tcsetattr(in, TCSANOW, &tc) < 0) {
+ warnx("ERROR setting stdin attributes");
+ exit(1);
+ }
+
+ char buf[512];
+ ssize_t nread = 0;
+
+ printf("OK\r\n");
+
+ /* read stdin, and write to file */
+ while ((nread = read(in, buf, min(sizeof(buf), size))) > 0) {
+ if (fwrite(buf, 1, nread, f) != nread) {
+ warnx("ERROR writing file");
+ break;
+ }
+ size -= nread;
+ if (size <= 0)
+ break;
+ }
+
+ fclose(f);
+
+ /* restore old terminal attributes */
+ if (tcsetattr(in, TCSANOW, &tc_old) < 0) {
+ warnx("ERROR restoring stdin attributes");
+ exit(1);
+ }
+
+ return OK;
+}