Skip to content

Add webrepl cli tool for console connection #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
webrepl_content.js
__pycache__
*.pyc
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ connections. As WebREPL is intended to be used only within a user's
local network, HTTPS isn't strictly required, and not accessing
webrepl.html over HTTPS is a suggested workaround.

WebREPL remote console
----------------------

The webrepl.py script can be used to connect from remote to a device.
Run

webrepl_scp.py --help

to see usage information. Note that you will need the python websocket_client
module.

WebREPL file transfer
---------------------

Expand All @@ -32,14 +43,14 @@ This feature is currently in alpha and has known issues on systems
which have it enabled (ESP8266).

To use WebREPL file transfer capabilities, a separate command line
utility is provided, webrepl_cli.py (file transfer is not supported
utility is provided, webrepl_scp.py (file transfer is not supported
via webrepl.html client). Run

webrepl_cli.py --help
webrepl_scp.py --help

to see usage information. Note that there can be only one active
WebREPL connection, so while webrepl.html is connected to device,
webrepl_cli.py can't transfer files, and vice versa.
webrepl_scp.py can't transfer files, and vice versa.


Technical details
Expand Down Expand Up @@ -102,7 +113,7 @@ This protocol uses WebSocket "binary"-flagged messages. At this point,
this protocol is in early research/design/proof-of-concept phase. The
only available specification of it is the reference code implementation,
and the protocol is subject to frequent and incompatible changes.
The `webrepl_cli.py` module mentioned above intended to be both a
The `webrepl_scp.py` module mentioned above intended to be both a
command-line tool and a library for 3rd-party projects to use, though
it may not be there yet. If you're interested in integrating WebREPL
transfer/control capabilities into your application, please submit
Expand Down
72 changes: 72 additions & 0 deletions webrepl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/python3

import sys
import select
import termios, tty
import argparse
import textwrap

import websocket # requires python3-websocket_client

ap = argparse.ArgumentParser()
ap.add_argument('host', type=str, help=textwrap.dedent('''\
The host to connect to.
The port is optional and defaults to 8266.
These formats are accepted:
1.2.3.4, 1.2.3.4:8266, [fdff:abc::1], [fe80::1%%eth0]:8266, foobar.de:8266,
ws://1.2.3.4/, wss://foobar.de:443/
'''))
ap.add_argument('-p', dest='password', type=str, help=textwrap.dedent('''\
Password for authentication.
Will be requested interactively by remote if omitted.
'''))
args = ap.parse_args()

default_port = "8266"

if args.host.startswith('ws://') or args.host.startswith('wss://'):
url = args.host
elif ']' in args.host:
if ':' in args.host.split(']')[1]:
# we got ipv6 address like [2000::123]:8266 or [fe80::123%eth0]:8266
url = f"ws://{args.host}/"
else:
# we got ipv6 address like [2000::123] or [fe80::123%eth0]
url = f"ws://{args.host}:{default_port}/"
elif args.host.count(':') > 1:
# we got ipv6 address like 2000::123 or fe80::123%eth0
url = f"ws://[{args.host}]:{default_port}/"
elif ':' in args.host:
# we got ipv4 address like 1.2.3.4:8266 or hostnmae like foo.de:8266
url = f"ws://{args.host}/"
else:
# we got ipv4 address like 1.2.3.4 or hostnmae like foo.de
url = f"ws://{args.host}:{default_port}/"

ws = websocket.WebSocket()
ws.connect(url)
print(f"Connected to '{url}'. Exit with Ctrl+]")

password_sent = False
old_settings = termios.tcgetattr(0)
try:
tty.setraw(sys.stdin.fileno())
while True:
readable, _, _ = select.select([ws.sock.fileno(), sys.stdin.fileno()], [], [])
for s in readable:
if s == ws.sock.fileno():
r = ws.recv()
sys.stdout.write(r)
sys.stdout.flush()
if r == "Password: " and args.password and not password_sent:
print('*'*len(args.password))
ws.send(f"{args.password}\n")
password_sent = True
elif s == sys.stdin.fileno():
c = sys.stdin.buffer.read(1)
if c == b'\x1d':
termios.tcsetattr(0, termios.TCSADRAIN, old_settings)
sys.exit()
ws.send(c)
finally:
termios.tcsetattr(0, termios.TCSADRAIN, old_settings)
File renamed without changes.