How to prevent os.dupterm() disconnect https://micropython.org/webrepl/ session?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
HermannSW
Posts: 144
Joined: Wed Nov 01, 2017 7:46 am
Contact:

How to prevent os.dupterm() disconnect https://micropython.org/webrepl/ session?

Post by HermannSW » Thu Oct 25, 2018 10:17 pm

In this posting it is demonstrated how to capture sys.stdout output into a bytearray with help of DUP class:
viewtopic.php?f=2&t=5442&p=31341#p31341

I did similar steps as in that posting:
  1. power up ESP32
  2. open https://micropython.org/webrepl/ in browser
  3. connect
  4. import dup
  5. reload https://micropython.org/webrepl/ in browser
  6. connect
  7. print(bytes(dup.s).decode())
This is dup.py:

Code: Select all

import io
import os
import webrepl

class DUP(io.IOBase):

    def __init__(self, s):
        self.s = s

    def write(self, data):
        self.s += data
        return len(data)

    def readinto(self, data):
        return 0

s = bytearray()
os.dupterm(DUP(s))
help(webrepl)
os.dupterm(None)

This is browser view after step 4:
Image


This is browser view after step 7:
Image


Because steps 5 and 6 are possible, WebREPL service works and does not hang after step 4.
So it seems that the WebREPL session gets disconnected after step 4 os.dupterm()s, without any indication in browser.

Is there a way to prevent that WebREPL session gets terminated, avoiding new login in step 6?

HermannSW
Posts: 144
Joined: Wed Nov 01, 2017 7:46 am
Contact:

Re: How to prevent os.dupterm() disconnect https://micropython.org/webrepl/ session?

Post by HermannSW » Thu Nov 01, 2018 9:13 pm

I looked how the server side of webrepl works:
https://github.com/micropython/micropyt ... webrepl.py

In accept_conn() I learned how to correctly deal with the previous term returned by uos.dupterm():

Code: Select all

...
    prev = uos.dupterm(None)
    uos.dupterm(prev)
...
With that and pagano.paganino's DUP class is is so easy to redirect any stdout output into a bytearray.
Here you see sample application output, "back" is emitted after calling "help(webrepl)" with no visible output.
But after "back" the content of the bytearray gets printed!

Code: Select all

$ webrepl_client.py -p abcd 192.168.4.1
Password: 
WebREPL connected
>>> 
>>> 
MicroPython v1.9.4-623-g34af10d2e on 2018-10-03; ESP32 module with ESP32
Type "help()" for more information.
>>> import dup
back
object <module 'webrepl'> is of type module
  start -- <function start at 0x3ffe6120>
  start_foreground -- <function start_foreground at 0x3ffe6340>
  websocket_helper -- <module 'websocket_helper'>
  accept_conn -- <function accept_conn at 0x3ffe62e0>
  setup_conn -- <function setup_conn at 0x3ffe62d0>
  client_s -- <socket>
  stop -- <function stop at 0x3ffe6100>
  __name__ -- webrepl
  socket -- <module 'usocket'>
  _webrepl -- <module '_webrepl'>
  websocket -- <module 'websocket'>
  listen_s -- <socket>
  network -- <module 'network'>
  uos -- <module 'uos'>

>>> f=open('dup.py'); print(f.read()); f.close()
...

This is new version of "dup.py":

Code: Select all

...
>>> f=open('dup.py'); print(f.read()); f.close()
import io
import os
import webrepl

class DUP(io.IOBase):

    def __init__(self, s):
        self.s = s

    def write(self, data):
        self.s += data
        return len(data)

    def readinto(self, data):
        return 0

s = bytearray()
prev = os.dupterm(DUP(s))
help(webrepl)
os.dupterm(prev)
print("back")
print(bytes(s).decode())

>>> 

With redirection of stdout output I will look now whether a pipe mechanism for upysh commands is possible ...

P.S:
I was successful with proof of concept for adding pipeing to upysh commands, sweet:
viewtopic.php?f=15&t=233&p=31604#p31604

Code: Select all

>>> cat("tst.txt")
first
second().
ThirD
  Fourth()
>>> head(lambda: tail("tst.txt", 3), 2)
second().
ThirD
>>> head("tst.txt", 2)
first
second().
>>> 

Post Reply