Skip to content

Commit

Permalink
Fix #46
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Wood committed Mar 6, 2021
1 parent db78bf0 commit d7c6101
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 60 deletions.
13 changes: 11 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
"stopOnEntry": false,
"smartStep": true,
"skipFiles": [
"${workspaceFolder}/node_modules/**/*.js",
"<node_internals>/**/*.js",
"**/*async_hook*.js",
"**/Unknown Source/**"
]
]
},
{
"name": "Python: Debug Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
"name": "pico-go",
"displayName": "Pico-Go",
"description": "Adds a REPL console to the terminal that connects to your Raspberry Pi Pico board. Run single files or synchronize your project files to your board.",
"version": "1.2.0",
"version": "1.2.1",
"publisher": "ChrisWood",
"homepage": "http://pico-go.net/",
"repository": "https://github.com/cpwood/Pico-Go",
"icon": "images/logo.png",
"license": "SEE LICENSE IN <LICENSE.md>",
"xtype": "module",
"galleryBanner": {
"color": "#ffffff",
"theme": "light"
Expand Down
19 changes: 13 additions & 6 deletions src/activator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ export default class Activator {
let sw = new SettingsWrapper();
await sw.initialize();

let nodeInstalled = await this._checkNodeVersion();
let pythonInstalled = await this._checkPythonVersion();

if (!nodeInstalled) {
if (!pythonInstalled) {
vscode.window.showErrorMessage(
'NodeJS not detected on this machine, which is required for Pico-Go to work.'
'Python3 is not detected on this machine so Pico-Go cannot work. Ensure it is in your PATH.'
);
return;
}
Expand Down Expand Up @@ -177,9 +177,16 @@ export default class Activator {
return v;
}

async _checkNodeVersion() {
let result = await exec('node -v');
return result.stdout.substr(0, 1) == 'v';
async _checkPythonVersion() {
let executable = process.platform == 'win32' ? 'py' : 'python3';
let result = await exec(`${executable} -V`);
let match = /(?<major>[0-9]+)\.[0-9]+\.[0-9]+/gm.exec(result.stdout);

if (match == null)
return false;

let major = parseInt(match.groups.major);
return major >= 3;
}

_getPinMapHtml(imageUrl) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/terminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export default class Term {
this.createFailed = false;
this.port = parseInt(Math.random() * 1000 + 1337);
try {
let termpath = this.api.getPackagePath() + 'terminalExec.js';
let shellpath = this.isWindows ? 'node.exe' : 'node';
let termpath = this.api.getPackagePath() + 'terminalExec.py';
let shellpath = this.isWindows ? 'py.exe' : 'python3';
this.terminal = vscode.window.createTerminal({ name: this.terminalName,
shellPath: shellpath, shellArgs: [termpath, this.port
.toString()] });
Expand Down
48 changes: 0 additions & 48 deletions terminalExec.js

This file was deleted.

139 changes: 139 additions & 0 deletions terminalExec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/python

import sys
import socket
import selectors
import types
import os
import threading

isWindows = sys.platform == "win32"

if isWindows:
import msvcrt
else:
import termios
import fcntl

port = int(sys.argv[1]) if len(sys.argv) == 2 else 1337
ip = "127.0.0.1"
debug = False
sel = selectors.DefaultSelector()

clients = set()
clients_lock = threading.Lock()

def acceptWrapper(sock):
conn, addr = sock.accept() # Should be ready to read

log("Accepted connection from " + str(addr))
with clients_lock:
clients.add(conn)

conn.setblocking(False)
data = types.SimpleNamespace(addr=addr, inb=b"", outb=b"")
events = selectors.EVENT_READ | selectors.EVENT_WRITE
sel.register(conn, events, data=data)

def serviceConnection(key, mask):
sock = key.fileobj
data = key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024) # Should be ready to read
if recv_data:
#data.outb += recv_data
boardInput(recv_data)
else:
log("Closing connection to " + str(data.addr))
sel.unregister(sock)
sock.close()
clients.remove(sock)

def getCharacterPosix():
fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
while True:
try:
c = sys.stdin.read(1)
yield c
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

def getCharacterWindows():
while True:
c = msvcrt.getch().decode("utf-8")
yield c

def boardInput(data: bytes):
sys.stdout.write(data.decode("utf-8"))
sys.stdout.flush()

def userInput(ch: str):
if (ch != ""):
log("Received: " + ch)
# Posix sends \n only; Windows sends \r only.
# The board expects \r\n.
if ch == "\n" or ch == "\r":
ch = "\r\n"

with clients_lock:
for client in clients:
client.sendall(str.encode(ch))

def log(msg: str):
if debug:
print(msg)

def runServer():
log("Starting server...")

lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((ip, port))
lsock.listen()
lsock.setblocking(False)

sel.register(lsock, selectors.EVENT_READ, data=None)

try:
while True:
events = sel.select(timeout=None)
for key, mask in events:
if key.data is None:
acceptWrapper(key.fileobj)
else:
serviceConnection(key, mask)
except KeyboardInterrupt:
log("Caught keyboard interrupt: exiting!")
finally:
sel.close()

def listenForInput():
if isWindows:
while True:
for ch in getCharacterWindows():
sys.stdout.flush()
userInput(ch)
else:
while True:
for ch in getCharacterPosix():
sys.stdout.flush()
userInput(ch)

server = threading.Thread(target=runServer)
server.start()

inputMonitor = threading.Thread(target=listenForInput)
inputMonitor.start()

server.join()

0 comments on commit d7c6101

Please sign in to comment.