goal: use python and websockets to talk to browser

Use this rather than long-polling.

https://websockets.readthedocs.io/en/stable/intro.html

pip3 install websockets

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

RESULT:

Full back and forth between python server and web browser:



python3 test.py

browser: test.html

Hardcoded on websocket port 6789 on localhost

================================
================================
================================
METHODS

================================
EXAMPLE 1 from websockets code:

python3 browser.py

openBrowser: browser.html

RESULT: works! Prints the time every 1.5 seconds or so

Great and simple: server: webscoket.send(xx), client: onmessage(event.data)

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

EXAMPLE 2:

python3 sync.py

openBrowser1: sync.html

openBrowser2: sync.html

RESULT: works!

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

Full back and forth:

python3 test.py

browser: test.html

Hardcoded on websocket port 6789 on localhost

This has buttons, text area, key presses. These events are sent to
python. Python then updates in internal STATE variable and echos the
state back to the browser which picks it up and places it in a
RESPONSE area on the webpage. Python and the web browser can talk to
each other freely.

The python logic gets a bit messy because it is using several
techniques for asynchronous / parallel / concurrent computation. It
needs to do this because GUIs are "event driven" which means things
can happen at any point and the computer can't be sleeping and miss
those events. This is not a new problem and is the reason that from
the begining CPUs have physcial interrupt wires so that they can
immediately respond to things like keyboard presses even if they are
busy doing other computation.

For Python there are three main ingredients:

----- asyncio routines that accept/close connections (register,
unregister) and repond to websocket messages from the browser
(ws_handle_event). These wait for some event to happen and then make a
callback function to handle it. These functions update an internal
STATE variable.

This code waits for data coming in: "async for data in
websocket:". This code sends data out: "await( websocket.send(tosend)
)"

----- a thread that spins off the websocket handling allowing the main
process to do the main computation:
"tt=threading.Thread(target=start_loop, args=(new_loop,myws))"

---- the main process that does any heavy computation, responds to
events that have updated the STATE variable, and sends information to
the browser
("asyncio.run_coroutine_threadsafe(ws_send_server(CONNECTIONS[0],data),new_loop)")

So all coordination between the browser and Python happens through the
STATE variable. The asyncio routines update STATE according to browser
messages. The main process does the "real" computation to update STATE
and commuinates this to the browser. Note because things are happening
asynchronously, if your STATE is keeping track of things like a bank
account balance, then you need to do extra work like blocking or
transactions to ensure integrity of the data. You don't want two
events each depositing $100 into an empty account EXACTLY
SIMULTANEOUSLY such that the final balance is $100 = $0+$100/$0+$100
and not the correct $200 = $0+$100/$100+$100.

For the browser, things are a bit easier because it is designed to be
an event-driven client. Input messages are handled with:
"websocket.onmessage = function (event)". GUI events and sending
messages are handled with: "document.getElementById("next").onclick =
websocket.send('next');"

Screenshot:


This after sending information from browser to server then sending
"SERVER!" from server to browser.