[SOLVED] uansycio.websocket.server/example_websock.py

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

[SOLVED] uansycio.websocket.server/example_websock.py

Post by pidou46 » Fri Jun 14, 2019 12:59 pm

Here it is my working setup for asynchronious communication between esp(32 or 8266) server and python3.6 client using websocket. I hope it could help someone...

server side (esp):

download and install official micropython firmware (25/09/19)
install "uasyncio 2.0" and "websocket server" libraries from micropython-lib:

Code: Select all

import upip
pip.install(uasyncio)
pip.install(uasyncio.websocket.server)
Edit server.py (modifaction are already there but commented out, why are they not been merged?)

Code: Select all

/lib/uasyncio/websocket/server.py

Code: Select all

3 import uwebsocket # change websocket by uwebsocket
...
10    respkey = ubinascii.b2a_base64(respkey)[:-1] #uncomment [:-1]
 ....
 56        #await writer.awrite("\r\n") #Comment
 57       await writer.awrite("\r\n\r\n") #Uncomment
 ...
 
create a script to start the ws server:

Code: Select all

import uasyncio
from uasyncio.websocket.server import WSReader, WSWriter


def echo(reader, writer):
    # Consume GET line
    yield from reader.readline()

    reader = yield from WSReader(reader, writer)
    writer = WSWriter(reader, writer)

    while 1:
        l = yield from reader.readline()
        print(l)
        if l == b"\r":
            await writer.awrite(b"\r\n")
        else:
            await writer.awrite(l)


import logging
logging.basicConfig(level=logging.INFO)
logging.basicConfig(level=logging.DEBUG)
loop = uasyncio.get_event_loop()
loop.create_task(uasyncio.start_server(echo, "192.168.4.1", 8081))
loop.run_forever()
loop.close()

client side Cpython >= 3.6:

Code: Select all

pip install websockets
client code based on websockets example:

Code: Select all

#!/usr/bin/env python

import asyncio
import websockets

async def hello():
    uri = "ws://192.168.4.1:8081" # replaced "ws://localhost:8765" by "192.168.4.1:8081"
    async with websockets.connect(uri) as websocket:
        await websocket.send(b'hello\r\n') # replaced "Hello world!" by b'hello\r\n'
        await websocket.recv()

asyncio.get_event_loop().run_until_complete(hello())

====================================================

Hi

I would like to run the example module of async version of websocket server from "https://github.com/micropython/micropyt ... websock.py" on a "esp32spiram-20190529-v1.11.bin"

It failed due to "websocket" library not available in the "server.py" module.

I haven't found "websocket" in micropython-lib directory, wher can I found it ?

Thanks
Last edited by pidou46 on Wed Sep 25, 2019 2:32 pm, edited 3 times in total.
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: uansycio.websocket.server/example_websock.py

Post by jimmo » Fri Jun 14, 2019 1:43 pm

It's built-in, but it's actually called uwebsocket.

Some of the "ufoo" modules are aliased (via a weak link) to the "foo" but this doesn't appear to be the case for websocket.

Sorry I don't know if there's something I'm missing - but maybe try changing the "import websocket" to "import uwebsocket" and see if that helps?

The only other thing I know that uses websocket is webrepl, which does "import uwebsocket"

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: uansycio.websocket.server/example_websock.py

Post by pidou46 » Mon Jun 17, 2019 8:00 am

Ok, thank you

I will try when at home
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: uansycio.websocket.server/example_websock.py

Post by pidou46 » Mon Sep 23, 2019 2:29 pm

Hello,

I would like to build a GUI running on handled device (smartphone or the like) for esp mcu's.

The communication would be built upon asyncio version of websockets via wifi.

All the bricks seems to be available in the micropython-lib repository: "uasyncio", "uasyncio.websocket.server"

After changing "websocket" to "uwebsocket" in "server.py", I'm able to run the example server "example_websocket.py"

It is listening, and I'm able to connect using a basic websocket client:

Code: Select all

#!/usr/bin/env python

import asyncio
import websockets

async def hello():
    uri = "ws://192.168.4.1:8081"
    async with websockets.connect(uri) as websocket:
        await websocket.send("Hello world!")
        await websocket.recv()

asyncio.get_event_loop().run_until_complete(hello())

Handshake is running successfully, but further communication failed.

The server continuously get empty strings:

Code: Select all

b'Host: 192.168.4.1:8081\r\n'
b'Upgrade: websocket\r\n'
b'Connection: Upgrade\r\n'
b'Sec-WebSocket-Key: zHyz1IS6CGm00fVz9SqkGA==\r\n'
b'Sec-WebSocket-Version: 13\r\n'
b'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n'
b'User-Agent: Python/3.7 websockets/7.0\r\n'
b'\r\n'
Finished webrepl handshake
b''
b''
b''
b''
b''
b''
b''
b''
Could it be related to change between websocket and uwebsocket implementation ?

pidou46
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

jomas
Posts: 59
Joined: Mon Dec 25, 2017 1:48 pm
Location: Netherlands

Re: uansycio.websocket.server/example_websock.py

Post by jomas » Tue Sep 24, 2019 11:03 am

uwebsocket should work. Can you try another client? For example on this site: https://www.websocket.org/echo.html look at "Creating your own test"

I used this to do a simular project as you and that worked (websocket on esp8266).
The advantage is that if you use "index.html, js , css" in a folder on your computer to test it. You can then easily convert this directory in a WebView in android studio to creat an Android app.

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: uansycio.websocket.server/example_websock.py

Post by pidou46 » Tue Sep 24, 2019 3:44 pm

Thank's Jomas,

With your advices I get a step further.

On the client side (Android Firefox) I get the following output :

Code: Select all

WebSocket Test

CONNECTED
SENT: WebSocket rocks

ERROR : undefined

DISCONNECTED
On the server I get the following output:

Code: Select all

b'Host: 192.168.4.1:8081\r\n'
b'User-Agent: Mozilla/5.0 (Android 7.0; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0\r\n'
b'Accept: */*\r\n'
b'Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3\r\n'
b'Accept-Encoding: gzip, deflate\r\n'
b'Sec-WebSocket-Version: 13\r\n'
b'Origin: null\r\n'
b'Sec-WebSocket-Extensions: permessage-deflate\r\n'
b'Sec-WebSocket-Key: wW5om9pUqE8JLLzlO8c/1g==\r\n'
b'Connection: keep-alive, Upgrade\r\n'
b'Pragma: no-cache\r\n'
b'Cache-Control: no-cache\r\n'
b'Upgrade: websocket\r\n'
b'\r\n'
Finished webrepl handshake
b'WebSocket rocks\r\n'
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
b''
Traceback (most recent call last):
  File "<stdin>", line 26, in <module>
  File "/lib/uasyncio/core.py", line 109, in run_forever
  File "<stdin>", line 18, in echo
  File "/lib/uasyncio/websocket/server.py", line 23, in awrite
  File "/lib/uasyncio/__init__.py", line 169, in awrite
OSError: [Errno 104] ECONNRESET

I have to get rid of thoses remaining errors. If someone have an hint...

I have learn that client implentation matters

My client would not be based on js but python with kivy framework, I've made some experiments with python and kivy on android and it work well.
So it's a pure python project!
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

jomas
Posts: 59
Joined: Mon Dec 25, 2017 1:48 pm
Location: Netherlands

Re: uansycio.websocket.server/example_websock.py

Post by jomas » Tue Sep 24, 2019 4:06 pm

I had that error too (error on client side) when I was trying to develop an Android App (based on html, js and css that worked on my laptop and Google Chrome browser). I finally found out that it was caused by using the emulator of Android Studio. As soon as I used my "real" telephone as test device everything worked as expected.

Can you test the little script (with the 'websocket rocks') on an Windows laptop using Chrome Webbrowser? That should work.

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: uansycio.websocket.server/example_websock.py

Post by pidou46 » Tue Sep 24, 2019 4:12 pm

I have made some experiments with the app "Web Dev Tools" and it worked nicely, no more error I can send message and get the echo back.

Code: Select all

b'Upgrade: websocket\r\n'
b'Connection: Upgrade\r\n'
b'Sec-WebSocket-Key: QX5plYXbL6wOZXq6L+0AcQ==\r\n'
b'Sec-WebSocket-Version: 13\r\n'
b'Host: 192.168.4.1:8081\r\n'
b'Accept-Encoding: gzip\r\n'
b'User-Agent: okhttp/3.11.0\r\n'
b'\r\n'
Finished webrepl handshake
b'test'
b'yes ca marche'
b'ping'
b''
b''
Still, when I try to disconnet I get an empty string but it does not disconnect.

So it still some room for improvement!

Does anyone could advice a python client supporting asyncio that work well with "asyncio.websocket.server" ?

thanks
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: uansycio.websocket.server/example_websock.py

Post by pidou46 » Tue Sep 24, 2019 4:59 pm

When I try the interactive client from websockets module (https://websockets.readthedocs.io/en/stable/intro.html) :

Code: Select all

$ python -m websockets ws://192.168.4.1:8081/
I get the following error:

Code: Select all

Failed to connect to ws://192.168.4.1:8081: Malformed HHTP message.
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: uansycio.websocket.server/example_websock.py

Post by pidou46 » Wed Sep 25, 2019 7:57 am

It seems that a CRLF : "\r\n" is missing somewhere in the sever answer.

Here it is the client traceback:

Code: Select all

Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/client.py", line 90, in read_http_response                                     status_code, headers = yield from read_response(self.reader)                                                          File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/http.py", line 136, in read_response                                           headers = yield from read_headers(stream)                 File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/http.py", line 159, in read_headers                                            line = yield from read_line(stream)                       File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/http.py", line 196, in read_line                                               raise ValueError("Line without CRLF")                   ValueError: Line without CRLF                               The above exception was the direct cause of the following exception:                                                    Traceback (most recent call last):                            File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
    start(fakepyfile,mainpyfile)
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 12, in <module>
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
    return future.result()
  File "<string>", line 8, in hello
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/py35/client.py", line 2, in __aenter__
    return await self
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/py35/client.py", line 20, in __await_impl__
    extra_headers=protocol.extra_headers,
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/client.py", line 283, in handshake
    status_code, response_headers = yield from self.read_http_response()
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.7/site-packages/websockets/client.py", line 92, in read_http_response
    raise InvalidMessage("Malformed HTTP message") from exc
websockets.exceptions.InvalidMessage: Malformed HTTP message
[Program finished]
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

Post Reply