8000 Command Line Interface · arduino/micropython.js@a501fc3 · GitHub
[go: up one dir, main page]

Skip to content

Commit a501fc3

Browse files
committed
Command Line Interface
1 parent df8be89 commit a501fc3

File tree

4 files changed

+420
-50
lines changed

4 files changed

+420
-50
lines changed

CLI.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Command Line Interface
2+
3+
# Usage
4+
5+
`node cli.js [ARGUMENTS]…`
6+
7+
* `--listports`: List available USB ports
8+
* `--port /dev/tty`: Specify which port to connect. Required for the options below.
9+
* `--listfiles`: List files in the board
10+
* `--executestring "print('watch out for string escaping')”`: Evaluate string
11+
* `--executefile filename.py`: Run file from the disk
12+
* `--putfile fileA.py fileB.py`: Upload `fileA.py` from the disk to board renaming it to `fileB.py`
13+
* `--getfile fileA.py fileB.py`: Download `fileA.py` from the board to disk renaming it to `fileB.py`
14+
15+
## Examples
16+
17+
### Listing all available USB ports
18+
19+
```
20+
$ node cli.js --listports
21+
available ports [
22+
{
23+
path: '/dev/ttyACM0',
24+
manufacturer: 'MicroPython',
25+
serialNumber: '5031503337360009',
26+
pnpId: 'usb-MicroPython_Board_in_FS_mode_5031503337360009-if00',
27+
locationId: undefined,
28+
vendorId: '2341',
29+
productId: '025e'
30+
}
31+
]
32+
```
33+
34+
### Listing files in the board
35+
36+
```
37+
$ node cli.js --port /dev/ttyACM0 --listfiles
38+
files at "/" [
39+
'.openmv_disk',
40+
'.fseventsd',
41+
'main.py',
42+
'midi.py',
43+
'boot.py',
44+
'.Trash-1000',
45+
'lib'
46+
]
47+
```
48+
49+
### Evaluating a string
50+
51+
```
52+
$ node cli.js --port /dev/ttyACM0 --executestring "print('hello world!')"
53+
OK
54+
MPY: soft reboot
55+
raw REPL; CTRL-B to exit
56+
>OKhello world!
57+
```
58+
59+
### Running the code from your disk
60+
61+
```
62+
$ node cli.js --port /dev/ttyACM0 --executefile examples/test.py
63+
OK
64+
MPY: soft reboot
65+
raw REPL; CTRL-B to exit
66+
>OKstart
67+
duh
68+
duh
69+
duh
70+
duh
71+
duh
72+
duh
73+
duh
74+
duh
75+
duh
76+
duh
77+
```
78+
79+
### Uploading a file from your disk to the board
80+
81+
```
82+
$ node cli.js --port /dev/ttyACM0 --putfile examples/test.py test.py
83+
```
84+
85+
### Downloading a file from the board to your disk
86+
87+
```
88+
$ node cli.js --port /dev/ttyACM0 --getfile test.py test.py
89+
"""
90+
Test
91+
"""
92+
93+
from machine import Pin
94+
from time import sleep
95+
pin = Pin(6, Pin.OUT)
96+
print("start")
97+
for i in range(0, 10):
98+
pin.on()
99+
sleep(0.1)
100+
pin.off()
101+
sleep(0.1)
102+
print('duh')
103+
```
104+

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@ This is an partial port of [pyboard.py](https://docs.micropython.org/en/latest/r
77
1. Install dependencies `npm install`
88
2. Navigate to example folder `cd examples`
99
3. Execute files with `PORT` environment variable: `PORT=/dev/tty.SLAB_USBtoUART node 05_list_files.js`
10+
11+
## Command Line Interface (CLI)
12+
13+
1. Install dependencies `npm install`
14+
1. Run CLI `node cli.js [ARGUMENTS]...`
15+
16+
[Read more](CLI.md)
17+

cli.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
const Board = require('./micropython.js')
4+
5+
const extractArguments = (args) => {
6+
return args.slice(2)
7+
}
8+
9+
const extractCommands = (args) => {
10+
let commands = {}
11+
let currentCommand = null
12+
// TODO: Use reduce instead of forEach
13+
args.forEach((value) => {
14+
// If it's a command, turn set is as the current one
15+
if (value.slice(0, 2) === '--') {
16+
currentCommand = value
17+
}
18+
// If there isn't a key initialized for that command, do so
19+
if (!commands[currentCommand]) {
20+
commands[currentCommand] = []
21+
} else {
22+
// Otherwise push the values to the current command key
23+
commands[currentCommand].push(value)
24+
}
25+
})
26+
return commands
27+
}
28+
29+
const extractFileArray = (output) => {
30+
output = output.replace(/'/g, '"');
31+
output = output.split('OK')
32+
let files = output[2] || ''
33+
files = files.slice(0, files.indexOf(']')+1)
34+
files = JSON.parse(files)
35+
return files
36+
}
37+
38+
function ensurePort(port) {
39+
if (!port) throw new Error('You must specify a port.')
40+
}
41+
42+
const listPorts = (args) => {
43+
const board = new Board()
44+
board.listPorts()
45+
.then((ports) => {
46+
console.log('available ports', ports)
47+
})
48+
}
49+
50+
const listFiles = (args, port) => {
51+
ensurePort(port)
52+
const board = new Board()
53+
board.open(port)
54+
.then(async () => {
55+
const folder = args[0] || '/'
56+
try {
57+
let output = await board.fs_ls(folder)
58+
let files = extractFileArray(output)
59+
console.log(`files at "${folder}"`, files)
60+
} catch(e) {
61+
console.log('error', e)
62+
}
63+
board.close()
64+
})
65+
}
66+
67+
const executeString = (args, port) => {
68+
ensurePort(port)
69+
const board = new Board()
70+
const code = args[0] || ''
71+
board.open(port)
72+
.then(() => board.enter_raw_repl())
73+
.then(() => board.exec_raw({ command: code }))
74+
.then((out) => {
75+
console.log(out)
76+
return board.exit_raw_repl()
77+
})
78+
.then(() => board.close())
79+
.catch((err) => {
80+
console.log('error')
81+
console.log(err)
82+
board.exit_raw_repl(true)
83+
board.close()
84+
})
85+
}
86+
87+
const executeFile = (args, port) => {
88+
ensurePort(port)
89+
let board = new Board()
90+
const filename = args[0] || ''
91+
board.open(port)
92+
.then(async () => {
93+
try {
94+
await board.execfile(filename)
95+
} catch(e) {
96+
console.log('error', e)
97+
}
98+
board.close()
99+
})
100+
}
101+
102+
const putFile = (args, port) => {
103+
ensurePort(port)
104+
const board = new Board()
105+
const [ diskFilename, boardFilename ] = args
106+
board.open(port)
107+
.then(async () => {
108+
try {
109+
await board.fs_put(diskFilename, boardFilename)
110+
} catch(e) {
111+
console.log('error', e)
112+
}
113+
board.close()
114+
})
115+
}
116+
117+
const getFile = (args, port) => {
118+
ensurePort(port)
119+
const board = new Board()
120+
const [ boardFilename, diskFilename ] = args
121+
board.open(port)
122+
.then(async () => {
123+
try {
124+
let output = await board.fs_cat(boardFilename)
125+
output = output.split('OK')
126+
console.log(output[2])
127+
fs.writeFileSync(diskFilename, output[2])
128+
} catch(e) {
129+
console.log('error', e)
130+
}
131+
board.close()
132+
})
133+
134+
}
135+
136+
const operations = {
137+
'--listports': listPorts,
138+
'--listfiles': listFiles,
139+
'--executestring': executeString,
140+
'--executefile': executeFile,
141+
'--putfile': putFile,
142+
'--getfile': getFile
143+
}
144+
145+
let args = extractArguments(process.argv)
146+
let commands = extractCommands(args)
147+
let port = commands['--port'] ? commands['--port'][0] : null
148+
149+
Object.keys(commands)
150+
.filter((command) => command !== '--port')
151+
.forEach((command) => {
152+
operations[command](commands[command], port)
153+
})
154+

0 commit comments

Comments
 (0)
0