Peter Magnusson 9 роки тому
батько
коміт
f059a13f26
2 змінених файлів з 102 додано та 60 видалено
  1. 15 4
      README.md
  2. 87 56
      nodemcu-uploader.py

+ 15 - 4
README.md

@@ -3,18 +3,29 @@ nodemcu-uploader.py
 
 
 A simple tool for uploading files to the filesystem of an
-ESP8266 running nodeMcu.
+ESP8266 running nodeMcu as well as some other usefull commands.
 
 It should work on linux and windows and with any type of file 
-that fits the filesystem.
+that fits the filesystem, binary or text.
 
 
 Usage
 -----
-```
-./nodemcu-uploader.py --port /dev/ttyUSB0 --verbose init.lua README.md
+--port and --baud are set to default /dev/ttyUSB0 and 9600 respectively.
 
+###Upload
+Uploading a number of files
+```
+./nodemcu-uploader.py upload init.lua README.md nodemcu-uploader.py
+```
 
+###List files
+```
+./nodemcu-uploader.py --port com1 file list
 ```
 
+###Format filesystem
+```
+./nodemcu-uploader.py file format
+```
  

+ 87 - 56
nodemcu-uploader.py

@@ -1,3 +1,6 @@
+#!/usr/bin/env python
+# Copyright (C) 2015 Peter Magnusson
+
 # For NodeMcu version 0.9.4 build 2014-12-30 and newer.
 
 import os
@@ -5,14 +8,13 @@ import serial
 import sys
 import argparse
 import time
+import logging
+
+log = logging.getLogger(__name__)
 
 def minify(script):
     return ' '.join([line.strip() for line in script.split('\n')])
 
-def log(msg):
-    sys.stdout.write(msg)
-    sys.stdout.flush()
-
 save_lua = \
 r"""
 function recv_block(d)
@@ -58,20 +60,19 @@ class Uploader:
     TIMEOUT = 1
 
     def __init__(self, port = 0, baud = BAUD):
-        self._port = serial.Serial(port, baud, timeout=Uploader.TIMEOUT)
-        self.line_number = 0
-        self.verbose = False
-        self.debug = False
-
-
-    def set_verbose(self):
-        self.verbose = True
-
+        self._port = serial.Serial(port, Uploader.BAUD, timeout=Uploader.TIMEOUT)
+        if baud != Uploader.BAUD:
+            log.info('Changing communication to %s baud', baud)
+            self._port.write('uart.setup(0,%s,8,0,1,1)\r\n' % baud)
+            log.info(self.dump())
+            self._port.close()
+            self._port = serial.Serial(port, baud, timeout=Uploader.TIMEOUT)
 
-    def set_debug(self):
-        self.verbose = True
-        self.debug = True
+        self.line_number = 0
 
+    def close(self):
+        self._port.write('uart.setup(0,%s,8,0,1,1)\r\n' % Uploader.BAUD)
+        self._port.close()
 
     def dump(self, timeout=TIMEOUT):
         t = self._port.timeout
@@ -88,20 +89,19 @@ class Uploader:
 
 
     def prepare(self):
-        if self.verbose: log('Preparing esp for transfer.')
+        log.info('Preparing esp for transfer.')
         self.write_lines(save_lua.replace('9600', '%d' % self._port.baudrate))
         self._port.write('\r\n')
-        if self.verbose: log('.')
+        
         d = self.dump(0.1)
         if 'unexpected' in d or len(d) > len(save_lua)+10:
-            print 'error in save_lua', d
+            log.error('error in save_lua "%s"' % d)
             return
-        if self.verbose: print('.done')
 
 
     def write(self, path):
         filename = os.path.basename(path)
-        if self.verbose: log('Transfering %s' % filename)
+        log.info('Transfering %s' % filename)
         self.dump()
         self._port.write(r"recv()" + '\n')
 
@@ -110,19 +110,18 @@ class Uploader:
             time.sleep(1)
             count += 1
             if count > 5:
-                print 'Error waiting for esp', self.dump()
+                log.error('Error waiting for esp "%s"' % self.dump())
                 return
         self.dump(0.5)
-        if self.verbose: log('.')
-        if self.debug: print 'sending filename', filename
+        log.debug('sending filename "%s"', filename)
         self._port.write(filename + '\x00')
 
         if not self.got_ack():
-            print 'did not ack filename', self.dump()
+            log.error('did not ack filename: "%s"' % self.dump())
             return
-        if self.verbose: log('.')
+
         f = open( path, 'rt' ); content = f.read(); f.close()
-        if self.debug: print 'sending %d bytes in %s' % (len(content), filename)
+        log.debug('sending %d bytes in %s' % (len(content), filename))
         pos = 0
         chunk_size = 128
         error = False
@@ -130,26 +129,22 @@ class Uploader:
             data = content[pos: pos+chunk_size]
             if not self.write_chunk(data):
                 error = True
-                print 'Bad send'
                 d = self.dump()
-                print d
-                print ':'.join(x.encode('hex') for x in d)
+                log.error('Bad chunk response "%s" %s' % (d, ':'.join(x.encode('hex') for x in d)))
                 break
 
             pos += chunk_size
             if pos + chunk_size > len(content):
                 chunk_size = len(content) - pos
             
-        if self.verbose: log('.')
-        if self.debug: print 'sending zero block'
+        log.debug('sending zero block')
         if not error:
             #zero size block
             self.write_chunk('')
-        if self.verbose: print 'done'
 
-    
+
     def got_ack(self):
-        if self.debug: print 'waiting for ack'
+        log.debug('waiting for ack')
         r = self._port.read(1)
         return r == '\x06' #ACK
 
@@ -160,24 +155,44 @@ class Uploader:
         for line in lines:
             self._port.write(line + '\r\n')
             d = self.dump(0.1)
-            if self.debug: log(d)
+            log.debug(d)
         return
 
 
     def write_chunk(self, chunk):
-        if self.debug: print 'writing %d bytes chunk' % len(chunk)
+        log.debug('writing %d bytes chunk' % len(chunk))
         data = '\x01' + chr(len(chunk)) + chunk
         if len(chunk) < 128:
             padding = 128 - len(chunk)
-            if self.debug: print 'pad with %d characters' % padding
+            log.debug('pad with %d characters' % padding)
             data = data + (' ' * padding)
-        if self.debug: print "packet size %d" % len(data)
+        log.debug("packet size %d" % len(data))
         self._port.write(data)
 
         return self.got_ack()
         
 
-   
+    def file_list(self):
+        log.info('Listing files')
+        self._port.write('for key,value in pairs(file.list()) do print(key,value) end' + '\r\n')
+        r = self.dump()
+        log.info(r)
+        return r
+
+    def file_format(self):
+        log.info('Format')
+        self._port.write('file.format()' + '\r\n')
+        r = self.dump()
+        log.info(r)
+        return r
+
+    def node_heap(self):
+        log.info('Heap')
+        self._port.write('print(node.heap())\r\n')
+        r = self.dump()
+        log.info(r)
+        return r
+
 
 def arg_auto_int(x):
     return int(x, 0)
@@ -192,7 +207,7 @@ if __name__ == '__main__':
 
     parser.add_argument(
             '--baud', '-b',
-            help = 'Serial port baud rate',
+            help = 'Serial port baudrate',
             type = arg_auto_int,
             default = Uploader.BAUD)
 
@@ -202,25 +217,41 @@ if __name__ == '__main__':
             action = 'store_true',
             default = False)
 
-    parser.add_argument(
-            '--debug', '-d',
-            help = 'debug output',
-            action = 'store_true',
-            default = False)
+    subparsers = parser.add_subparsers(
+        dest='operation',
+        help = 'Run nodemcu-uploader {command} -h for additional help')
+
+    upload_parser = subparsers.add_parser(
+            'upload',
+            help = 'Upload file(s)')
 
-    parser.add_argument('filename',  nargs='+', help = 'Lua file to upload')
+    upload_parser.add_argument('filename',  nargs='+', help = 'Lua file to upload')
 
+    file_parser = subparsers.add_parser(
+        'file', 
+        help = 'File functions')
+
+    file_parser.add_argument('cmd', choices=('list', 'format'))
 
     args = parser.parse_args()
     
+    formatter = logging.Formatter('%(message)s')
+    logging.basicConfig(level=logging.INFO, format='%(message)s')
+    
     uploader = Uploader(args.port, args.baud)
     if args.verbose:
-        uploader.set_verbose()
-    if args.debug:
-        uploader.set_debug()
-    
-    uploader.prepare()    
-    for f in args.filename:
-        uploader.write(f)
-    if args.verbose: 
-        print 'All done!' 
+        logger.setLevel(logging.DEBUG)
+
+    if args.operation == 'upload':
+        uploader.prepare()    
+        for f in args.filename:
+            uploader.write(f) 
+        print 'All done!'
+
+    elif args.operation == 'file':
+        if args.cmd == 'list': 
+            uploader.file_list()
+        elif args.cmd == 'format': 
+            uploader.file_format()
+
+    uploader.close()