Use external uploader version
This commit is contained in:
parent
3314850e15
commit
40b2d16463
4 changed files with 1 additions and 621 deletions
1
nodemcu/nodemcu-uploader
Symbolic link
1
nodemcu/nodemcu-uploader
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../extern/nodemcu-uploader
|
|
@ -1,22 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 Peter Magnusson
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
nodemcu-uploader.py
|
|
||||||
===================
|
|
||||||
|
|
||||||
|
|
||||||
A simple tool for uploading files to the filesystem of an
|
|
||||||
ESP8266 running NodeMCU as well as some other useful commands.
|
|
||||||
|
|
||||||
It should work on Linux, Windows, and OS X; and with any type of file
|
|
||||||
that fits the filesystem, binary or text.
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
--port and --baud are set to default /dev/ttyUSB0 and 9600 respectively.
|
|
||||||
|
|
||||||
###Upload
|
|
||||||
Uploading a number of files.
|
|
||||||
Supports multiple files. If you want an alternate destination name, just
|
|
||||||
add a colon ":" and the new destination filename.
|
|
||||||
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py upload init.lua README.md nodemcu-uploader.py [--compile] [--restart]
|
|
||||||
```
|
|
||||||
|
|
||||||
Uploading a number of files, but saving with a different file name.
|
|
||||||
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py upload init.lua:new_init.lua README.md:new_README.md [--compile] [--restart]
|
|
||||||
```
|
|
||||||
|
|
||||||
Uploading a number of files and verify successful uploading.
|
|
||||||
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py upload init.lua README.md nodemcu-uploader.py -v
|
|
||||||
```
|
|
||||||
|
|
||||||
###Download
|
|
||||||
Downloading a number of files.
|
|
||||||
Supports multiple files. If you want an alternate destination name, just
|
|
||||||
add a colon ":" and the new destination filename.
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py download init.lua README.md nodemcu-uploader.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Downloading a number of files, but saving with a different file name.
|
|
||||||
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py download init.lua:new_init.lua README.md:new_README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
###List files
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py --port com1 file list
|
|
||||||
```
|
|
||||||
|
|
||||||
###Format filesystem
|
|
||||||
```
|
|
||||||
./nodemcu-uploader.py file format
|
|
||||||
```
|
|
||||||
|
|
||||||
Todo
|
|
||||||
----
|
|
||||||
* Speed up the initial step of uploading the script to NodeMCU
|
|
||||||
* Implement a change of baudrate for the actual transfer and go back when done
|
|
||||||
|
|
||||||
Details
|
|
||||||
-------
|
|
||||||
This is *almost* an implementation of xmodem protocol for the upload part.
|
|
||||||
|
|
||||||
1. Client calls the function recv()
|
|
||||||
2. NodeMCU disables echo and send a 'C' to tell that it's ready to receive data
|
|
||||||
3. Client sends a filename terminated with 0x00
|
|
||||||
4. NodeMCU sends ACK
|
|
||||||
5. Client send block of data according to the definition.
|
|
||||||
6. Client sends ACK
|
|
||||||
7. Step 5 and 6 are repeated until NodeMCU receives a block with 0 as size.
|
|
||||||
8. NodeMCU enables normal terminal again with echo
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Data Block Definition
|
|
||||||
__SOH__, __size__, __data[128]__
|
|
||||||
|
|
||||||
* SOH = 0x01
|
|
||||||
* Single byte telling how much of the 128 bytes data that are actually used.
|
|
||||||
* Data padded with random bytes to fill out the 128 bytes frame.
|
|
||||||
|
|
||||||
This gives a total 130 bytes per block.
|
|
||||||
|
|
||||||
The block size was decided for...
|
|
||||||
|
|
||||||
1. Being close to xmodem from where the inspiration came
|
|
||||||
2. A fixed size allow the use of the uart.on('data') event very easy.
|
|
||||||
3. 130 bytes would fit in the receive buffer buffer.
|
|
||||||
4. It would not waste that much traffic if the total size uploaded was not a multiple of the allowed datasize.
|
|
|
@ -1,504 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (C) 2015 Peter Magnusson
|
|
||||||
|
|
||||||
# For NodeMCU version 0.9.4 build 2014-12-30 and newer.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import serial
|
|
||||||
import sys
|
|
||||||
import argparse
|
|
||||||
import time
|
|
||||||
import logging
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
save_lua = \
|
|
||||||
r"""
|
|
||||||
function recv_block(d)
|
|
||||||
if string.byte(d, 1) == 1 then
|
|
||||||
size = string.byte(d, 2)
|
|
||||||
uart.write(0,'\006')
|
|
||||||
if size > 0 then
|
|
||||||
file.write(string.sub(d, 3, 3+size-1))
|
|
||||||
else
|
|
||||||
file.close()
|
|
||||||
uart.on('data')
|
|
||||||
uart.setup(0,9600,8,0,1,1)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
uart.write(0, '\021' .. d)
|
|
||||||
uart.setup(0,9600,8,0,1,1)
|
|
||||||
uart.on('data')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function recv_name(d) d = string.gsub(d, '\000', '') file.remove(d) file.open(d, 'w') uart.on('data', 130, recv_block, 0) uart.write(0, '\006') end
|
|
||||||
function recv() uart.setup(0,9600,8,0,1,0) uart.on('data', '\000', recv_name, 0) uart.write(0, 'C') end
|
|
||||||
"""
|
|
||||||
|
|
||||||
CHUNK_END = '\v'
|
|
||||||
CHUNK_REPLY = '\v'
|
|
||||||
|
|
||||||
from serial.tools.miniterm import Miniterm, console, NEWLINE_CONVERISON_MAP
|
|
||||||
|
|
||||||
class MyMiniterm(Miniterm):
|
|
||||||
def __init__(self, serial):
|
|
||||||
self.serial = serial
|
|
||||||
self.echo = False
|
|
||||||
self.convert_outgoing = 2
|
|
||||||
self.repr_mode = 1
|
|
||||||
self.newline = NEWLINE_CONVERISON_MAP[self.convert_outgoing]
|
|
||||||
self.dtr_state = True
|
|
||||||
self.rts_state = True
|
|
||||||
self.break_state = False
|
|
||||||
|
|
||||||
class Uploader:
|
|
||||||
BAUD = 9600
|
|
||||||
PORT = '/dev/ttyUSB0'
|
|
||||||
TIMEOUT = 5
|
|
||||||
|
|
||||||
def expect(self, exp='> ', timeout=TIMEOUT):
|
|
||||||
t = self._port.timeout
|
|
||||||
|
|
||||||
# Checking for new data every 100us is fast enough
|
|
||||||
lt = 0.0001
|
|
||||||
if self._port.timeout != lt:
|
|
||||||
self._port.timeout = lt
|
|
||||||
|
|
||||||
end = time.time() + timeout
|
|
||||||
|
|
||||||
# Finish as soon as either exp matches or we run out of time (work like dump, but faster on success)
|
|
||||||
data = ''
|
|
||||||
while not data.endswith(exp) and time.time() <= end:
|
|
||||||
data += self._port.read()
|
|
||||||
|
|
||||||
self._port.timeout = t
|
|
||||||
log.debug('expect return: %s', data)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def write(self, output, binary=False):
|
|
||||||
if not binary:
|
|
||||||
log.debug('write: %s', output)
|
|
||||||
else:
|
|
||||||
log.debug('write binary: %s' % ':'.join(x.encode('hex') for x in output))
|
|
||||||
self._port.write(output)
|
|
||||||
self._port.flush()
|
|
||||||
|
|
||||||
def writeln(self, output):
|
|
||||||
self.write(output + '\n')
|
|
||||||
|
|
||||||
def exchange(self, output):
|
|
||||||
self.writeln(output)
|
|
||||||
return self.expect()
|
|
||||||
|
|
||||||
def __init__(self, port = 0, baud = BAUD):
|
|
||||||
self._port = serial.Serial(port, Uploader.BAUD, timeout=Uploader.TIMEOUT)
|
|
||||||
|
|
||||||
# Keeps things working, if following conections are made:
|
|
||||||
## RTS = CH_PD (i.e reset)
|
|
||||||
## DTR = GPIO0
|
|
||||||
self._port.setRTS(False)
|
|
||||||
self._port.setDTR(False)
|
|
||||||
|
|
||||||
# Get in sync with LUA (this assumes that NodeMCU gets reset by the previous two lines)
|
|
||||||
self.exchange(';'); # Get a defined state
|
|
||||||
self.writeln('print("%sync%");');
|
|
||||||
self.expect('%sync%\r\n> ');
|
|
||||||
|
|
||||||
if baud != Uploader.BAUD:
|
|
||||||
log.info('Changing communication to %s baud', baud)
|
|
||||||
self.writeln('uart.setup(0,%s,8,0,1,1)' % baud)
|
|
||||||
|
|
||||||
# Wait for the string to be sent before switching baud
|
|
||||||
time.sleep(0.1)
|
|
||||||
self._port.setBaudrate(baud)
|
|
||||||
|
|
||||||
# Get in sync again
|
|
||||||
self.exchange('')
|
|
||||||
self.exchange('')
|
|
||||||
|
|
||||||
self.line_number = 0
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.writeln('uart.setup(0,%s,8,0,1,1)' % Uploader.BAUD)
|
|
||||||
self._port.close()
|
|
||||||
|
|
||||||
def prepare(self):
|
|
||||||
log.info('Preparing esp for transfer.')
|
|
||||||
|
|
||||||
data = save_lua.replace('9600', '%d' % self._port.baudrate)
|
|
||||||
lines = data.replace('\r', '').split('\n')
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
line = line.strip().replace(', ', ',').replace(' = ', '=')
|
|
||||||
|
|
||||||
if len(line) == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
d = self.exchange(line)
|
|
||||||
|
|
||||||
if 'unexpected' in d or len(d) > len(save_lua)+10:
|
|
||||||
log.error('error in save_lua "%s"' % d)
|
|
||||||
return
|
|
||||||
|
|
||||||
def download_file(self, filename):
|
|
||||||
chunk_size=256
|
|
||||||
bytes_read = 0
|
|
||||||
data=""
|
|
||||||
while True:
|
|
||||||
d = self.exchange("file.open('" + filename + r"') print(file.seek('end', 0)) file.seek('set', %d) uart.write(0, file.read(%d))file.close()" % (bytes_read, chunk_size))
|
|
||||||
cmd, size, tmp_data = d.split('\n', 2)
|
|
||||||
data=data+tmp_data[0:chunk_size]
|
|
||||||
bytes_read=bytes_read+chunk_size
|
|
||||||
if bytes_read > int(size):
|
|
||||||
break
|
|
||||||
data = data[0:int(size)]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def read_file(self, filename, destination = ''):
|
|
||||||
if not destination:
|
|
||||||
destination = filename
|
|
||||||
log.info('Transfering %s to %s' %(filename, destination))
|
|
||||||
data = self.download_file(filename)
|
|
||||||
with open(destination, 'w') as f:
|
|
||||||
f.write(data)
|
|
||||||
|
|
||||||
def write_file(self, path, destination = '', verify = False):
|
|
||||||
filename = os.path.basename(path)
|
|
||||||
if not destination:
|
|
||||||
destination = filename
|
|
||||||
log.info('Transfering %s as %s' %(filename, destination))
|
|
||||||
self.writeln("recv()")
|
|
||||||
|
|
||||||
r = self.expect('C> ')
|
|
||||||
if not r.endswith('C> '):
|
|
||||||
log.error('Error waiting for esp "%s"' % r)
|
|
||||||
return
|
|
||||||
log.debug('sending destination filename "%s"', destination)
|
|
||||||
self.write(destination + '\x00', True)
|
|
||||||
if not self.got_ack():
|
|
||||||
log.error('did not ack destination filename')
|
|
||||||
return
|
|
||||||
|
|
||||||
f = open( path, 'rt' ); content = f.read(); f.close()
|
|
||||||
log.debug('sending %d bytes in %s' % (len(content), filename))
|
|
||||||
pos = 0
|
|
||||||
chunk_size = 128
|
|
||||||
error = False
|
|
||||||
while pos < len(content):
|
|
||||||
rest = len(content) - pos
|
|
||||||
if rest > chunk_size:
|
|
||||||
rest = chunk_size
|
|
||||||
|
|
||||||
data = content[pos:pos+rest]
|
|
||||||
if not self.write_chunk(data):
|
|
||||||
d = self.expect()
|
|
||||||
log.error('Bad chunk response "%s" %s' % (d, ':'.join(x.encode('hex') for x in d)))
|
|
||||||
return
|
|
||||||
|
|
||||||
pos += chunk_size
|
|
||||||
|
|
||||||
log.debug('sending zero block')
|
|
||||||
#zero size block
|
|
||||||
self.write_chunk('')
|
|
||||||
|
|
||||||
if verify:
|
|
||||||
log.info('Verifying...')
|
|
||||||
data = self.download_file(destination)
|
|
||||||
if content != data:
|
|
||||||
log.error('Verification failed.')
|
|
||||||
|
|
||||||
def exec_file(self, path):
|
|
||||||
filename = os.path.basename(path)
|
|
||||||
log.info('Execute %s' %(filename,))
|
|
||||||
|
|
||||||
f = open( path, 'rt' );
|
|
||||||
|
|
||||||
res = '> '
|
|
||||||
for line in f:
|
|
||||||
line = line.rstrip('\r\n')
|
|
||||||
retlines = (res + self.exchange(line)).splitlines()
|
|
||||||
# Log all but the last line
|
|
||||||
res = retlines.pop()
|
|
||||||
for l in retlines:
|
|
||||||
log.info(l)
|
|
||||||
# last line
|
|
||||||
log.info(res)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def got_ack(self):
|
|
||||||
log.debug('waiting for ack')
|
|
||||||
r = self._port.read(1)
|
|
||||||
log.debug('ack read %s', r.encode('hex'))
|
|
||||||
return r == '\x06' #ACK
|
|
||||||
|
|
||||||
|
|
||||||
def write_lines(self, data):
|
|
||||||
lines = data.replace('\r', '').split('\n')
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
self.exchange(line)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def write_chunk(self, chunk):
|
|
||||||
log.debug('writing %d bytes chunk' % len(chunk))
|
|
||||||
data = '\x01' + chr(len(chunk)) + chunk
|
|
||||||
if len(chunk) < 128:
|
|
||||||
padding = 128 - len(chunk)
|
|
||||||
log.debug('pad with %d characters' % padding)
|
|
||||||
data = data + (' ' * padding)
|
|
||||||
log.debug("packet size %d" % len(data))
|
|
||||||
self.write(data)
|
|
||||||
|
|
||||||
return self.got_ack()
|
|
||||||
|
|
||||||
|
|
||||||
def file_list(self):
|
|
||||||
log.info('Listing files')
|
|
||||||
r = self.exchange('for key,value in pairs(file.list()) do print(key,value) end')
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def file_do(self, f):
|
|
||||||
log.info('Executing '+f)
|
|
||||||
r = self.exchange('dofile("'+f+'")')
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def file_format(self):
|
|
||||||
log.info('Formating...')
|
|
||||||
r = self.exchange('file.format()')
|
|
||||||
if 'format done' not in r:
|
|
||||||
log.error(r)
|
|
||||||
else:
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def node_heap(self):
|
|
||||||
log.info('Heap')
|
|
||||||
r = self.exchange('print(node.heap())')
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def node_restart(self):
|
|
||||||
log.info('Restart')
|
|
||||||
r = self.exchange('node.restart()')
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def file_compile(self, path):
|
|
||||||
log.info('Compile '+path)
|
|
||||||
cmd = 'node.compile("%s")' % path
|
|
||||||
r = self.exchange(cmd)
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def file_remove(self, path):
|
|
||||||
log.info('Remove '+path)
|
|
||||||
cmd = 'file.remove("%s")' % path
|
|
||||||
r = self.exchange(cmd)
|
|
||||||
log.info(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def terminal(self):
|
|
||||||
miniterm = MyMiniterm(self._port)
|
|
||||||
|
|
||||||
log.info('Started terminal. Hit ctrl-] to leave terminal')
|
|
||||||
|
|
||||||
console.setup()
|
|
||||||
miniterm.start()
|
|
||||||
try:
|
|
||||||
miniterm.join(True)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
miniterm.join()
|
|
||||||
|
|
||||||
def arg_auto_int(x):
|
|
||||||
return int(x, 0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
parser = argparse.ArgumentParser(description = 'NodeMCU Lua file uploader', prog = 'nodemcu-uploader')
|
|
||||||
parser.add_argument(
|
|
||||||
'--verbose',
|
|
||||||
help = 'verbose output',
|
|
||||||
action = 'store_true',
|
|
||||||
default = False)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'--port', '-p',
|
|
||||||
help = 'Serial port device',
|
|
||||||
default = Uploader.PORT)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'--baud', '-b',
|
|
||||||
help = 'Serial port baudrate',
|
|
||||||
type = arg_auto_int,
|
|
||||||
default = Uploader.BAUD)
|
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(
|
|
||||||
dest='operation',
|
|
||||||
help = 'Run nodemcu-uploader {command} -h for additional help')
|
|
||||||
|
|
||||||
upload_parser = subparsers.add_parser(
|
|
||||||
'upload',
|
|
||||||
help = 'Path to one or more files to be uploaded. Destination name will be the same as the file name.')
|
|
||||||
|
|
||||||
# upload_parser.add_argument(
|
|
||||||
# '--filename', '-f',
|
|
||||||
# help = 'File to upload. You can specify this option multiple times.',
|
|
||||||
# action='append')
|
|
||||||
|
|
||||||
# upload_parser.add_argument(
|
|
||||||
# '--destination', '-d',
|
|
||||||
# help = 'Name to be used when saving in NodeMCU. You should specify one per file.',
|
|
||||||
# action='append')
|
|
||||||
|
|
||||||
upload_parser.add_argument('filename', nargs='+', help = 'Lua file to upload. Use colon to give alternate destination.')
|
|
||||||
|
|
||||||
upload_parser.add_argument(
|
|
||||||
'--compile', '-c',
|
|
||||||
help = 'If file should be uploaded as compiled',
|
|
||||||
action='store_true',
|
|
||||||
default=False
|
|
||||||
)
|
|
||||||
|
|
||||||
upload_parser.add_argument(
|
|
||||||
'--verify', '-v',
|
|
||||||
help = 'To verify the uploaded data.',
|
|
||||||
action='store_true',
|
|
||||||
default=False
|
|
||||||
)
|
|
||||||
|
|
||||||
upload_parser.add_argument(
|
|
||||||
'--dofile', '-e',
|
|
||||||
help = 'If file should be run after upload.',
|
|
||||||
action='store_true',
|
|
||||||
default=False
|
|
||||||
)
|
|
||||||
|
|
||||||
upload_parser.add_argument(
|
|
||||||
'--terminal', '-t',
|
|
||||||
help = 'If miniterm should claim the port after all uploading is done.',
|
|
||||||
action='store_true',
|
|
||||||
default=False
|
|
||||||
)
|
|
||||||
|
|
||||||
upload_parser.add_argument(
|
|
||||||
'--restart', '-r',
|
|
||||||
help = 'If esp should be restarted',
|
|
||||||
action='store_true',
|
|
||||||
default=False
|
|
||||||
)
|
|
||||||
|
|
||||||
exec_parser = subparsers.add_parser(
|
|
||||||
'exec',
|
|
||||||
help = 'Path to one or more files to be executed line by line.')
|
|
||||||
|
|
||||||
exec_parser.add_argument('filename', nargs='+', help = 'Lua file to execute.')
|
|
||||||
|
|
||||||
download_parser = subparsers.add_parser(
|
|
||||||
'download',
|
|
||||||
help = 'Path to one or more files to be downloaded. Destination name will be the same as the file name.')
|
|
||||||
|
|
||||||
# download_parser.add_argument(
|
|
||||||
# '--filename', '-f',
|
|
||||||
# help = 'File to download. You can specify this option multiple times.',
|
|
||||||
# action='append')
|
|
||||||
|
|
||||||
# download_parser.add_argument(
|
|
||||||
# '--destination', '-d',
|
|
||||||
# help = 'Name to be used when saving in NodeMCU. You should specify one per file.',
|
|
||||||
# action='append')
|
|
||||||
|
|
||||||
download_parser.add_argument('filename', nargs='+', help = 'Lua file to download. Use colon to give alternate destination.')
|
|
||||||
|
|
||||||
|
|
||||||
file_parser = subparsers.add_parser(
|
|
||||||
'file',
|
|
||||||
help = 'File functions')
|
|
||||||
|
|
||||||
file_parser.add_argument('cmd', choices=('list', 'do', 'format'))
|
|
||||||
file_parser.add_argument('filename', nargs='*', help = 'Lua file to run.')
|
|
||||||
|
|
||||||
node_parse = subparsers.add_parser(
|
|
||||||
'node',
|
|
||||||
help = 'Node functions')
|
|
||||||
|
|
||||||
node_parse.add_argument('ncmd', choices=('heap', 'restart'))
|
|
||||||
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
formatter = logging.Formatter('%(message)s')
|
|
||||||
logging.basicConfig(level=logging.INFO, format='%(message)s')
|
|
||||||
|
|
||||||
if args.verbose:
|
|
||||||
log.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
uploader = Uploader(args.port, args.baud)
|
|
||||||
|
|
||||||
if args.operation == 'upload' or args.operation == 'download':
|
|
||||||
sources = args.filename
|
|
||||||
destinations = []
|
|
||||||
for i in range(0, len(sources)):
|
|
||||||
sd = sources[i].split(':')
|
|
||||||
if len(sd) == 2:
|
|
||||||
destinations.append(sd[1])
|
|
||||||
sources[i]=sd[0]
|
|
||||||
else:
|
|
||||||
destinations.append(sd[0])
|
|
||||||
|
|
||||||
if args.operation == 'upload':
|
|
||||||
if len(destinations) == len(sources):
|
|
||||||
uploader.prepare()
|
|
||||||
for f, d in zip(sources, destinations):
|
|
||||||
if args.compile:
|
|
||||||
uploader.file_remove(os.path.splitext(d)[0]+'.lc')
|
|
||||||
uploader.write_file(f, d, args.verify)
|
|
||||||
if args.compile and d != 'init.lua':
|
|
||||||
uploader.file_compile(d)
|
|
||||||
uploader.file_remove(d)
|
|
||||||
if args.dofile:
|
|
||||||
uploader.file_do(os.path.splitext(d)[0]+'.lc')
|
|
||||||
elif args.dofile:
|
|
||||||
uploader.file_do(d)
|
|
||||||
else:
|
|
||||||
raise Exception('You must specify a destination filename for each file you want to upload.')
|
|
||||||
|
|
||||||
if args.terminal:
|
|
||||||
uploader.terminal()
|
|
||||||
if args.restart:
|
|
||||||
uploader.node_restart()
|
|
||||||
log.info('All done!')
|
|
||||||
|
|
||||||
if args.operation == 'download':
|
|
||||||
if len(destinations) == len(sources):
|
|
||||||
for f, d in zip(sources, destinations):
|
|
||||||
uploader.read_file(f, d)
|
|
||||||
else:
|
|
||||||
raise Exception('You must specify a destination filename for each file you want to download.')
|
|
||||||
log.info('All done!')
|
|
||||||
|
|
||||||
elif args.operation == 'exec':
|
|
||||||
sources = args.filename
|
|
||||||
for f in sources:
|
|
||||||
uploader.exec_file(f)
|
|
||||||
|
|
||||||
elif args.operation == 'file':
|
|
||||||
if args.cmd == 'list':
|
|
||||||
uploader.file_list()
|
|
||||||
if args.cmd == 'do':
|
|
||||||
for f in args.filename:
|
|
||||||
uploader.file_do(f)
|
|
||||||
elif args.cmd == 'format':
|
|
||||||
uploader.file_format()
|
|
||||||
|
|
||||||
elif args.operation == 'node':
|
|
||||||
if args.ncmd == 'heap':
|
|
||||||
uploader.node_heap()
|
|
||||||
elif args.ncmd == 'restart':
|
|
||||||
uploader.node_restart()
|
|
||||||
|
|
||||||
uploader.close()
|
|
Loading…
Add table
Reference in a new issue