Where to Discuss?

Local Group

Preface

Goal: Monitor excel file changes and show the result in browser using websocket.

This is a multiparts article.


8: Multiple Connection Demo

Using different ports.

Remember the connection?

  • WebSocket("ws://localhost:8765")

Sure we can add more port, to serve more user.

Spreadsheet File

Excel as Data Source

Instead of one data source, we can obtain data from two sources.

You can download the sources here

Excel: Multiple Connection Demo: XLSX

We need to display both data in one HTML page in a browser.

Python Source Code

The source is very similar as previous code.

Class Skeleton

The same as previous script.

Python: Multiple Connection Demo: Brief

The only different is the port and data source.

example = Xl2WebExample(
  '/home/epsi/awatch', 'test-b.xlsx',
  'localhost', 8767)
asyncio.run(example.main())

Prepare in CLI

Run both script, because we need to display two panel in our html page.

Sender 16a

❯ python 16a-request.py

Sender 17b

❯ python 17b-request.py

We will get the result later, after we load the page in web browser.

Web Source Code: HTML

Client Side

Load both javascript, that each have differen websocket port.

<head>
  <title>Mission Accomplished</title>
  <link rel="stylesheet" href="bulma.min.css">
  <script src="16a-script.js"></script>
  <script src="17b-script.js"></script>
</head>

Site: Multiple Connection Demo: HTML Head

Web Source Code: Javascript

    // Loop Entry Point
    function startWS(){
      const websocket = new WebSocket("ws://localhost:8767");

      websocket.onopen = function () {...};
      websocket.onmessage = function(event) {...};
      websocket.onclose = function() {...};
    }

Site: Multiple Connection Demo: Websocket Port

    const time_b   = document.getElementById("time-b");
    const status_b = document.getElementById("status-b");
    const value_b1 = document.getElementById("value-b1");
    const value_b2 = document.getElementById("value-b2");
    const value_b3 = document.getElementById("value-b3");

Site: Multiple Connection Demo: Element

Now our page is ready to be launched.

Browser Result

Right click your HTML file from your file manager using right click, and open it using any web browser.

Site: Multiple Connection Demo: Display: Duo

The page should contained data from both excel sources.

Class: Init

Additional connections property, initialized as empty set.

class Xl2WebExample:
  def __init__(self, filepath, filename, site, port):
    # save initial parameter
    self.filepath = filepath
    self.filename = filename
    self.site = site
    self.port = port

    # websocket broadcast collection
    self.connections = set()

![Python: Broadcast: Init][13b-py-init]

Output in CLI

Again check both script, for any logs.

Sender 16a

❯ python 16a-request.py
Hello There.
Timestamp     : Wed Jan  4 11:21:38 2023
File Modified : None
Data 1: 1700
Data 2: 1500
Data 3: 2023

Sender 17b

❯ python 17b-request.py
Hello There.
Timestamp     : Wed Jan  4 11:21:38 2023
File Modified : None
Data 1: 1234
Data 2: 2017
Data 3: 1105

Python: Multiple Connection Demo: Output

Windows User

For comfort in windows environment, you can make a batch file such as run.bat, that contain these two lines:

start cmd /k python 16a-request.py
start cmd /k python 17b-request.py

Rookie Issue

Multiple connection from different client.

There is still unsolved issue however.

In this figure below,#### Class: Init

Additional connections property, initialized as empty set.

class Xl2WebExample:
  def __init__(self, filepath, filename, site, port):
    # save initial parameter
    self.filepath = filepath
    self.filename = filename
    self.site = site
    self.port = port

    # websocket broadcast collection
    self.connections = set()

![Python: Broadcast: Init][13b-py-init] the connection can only be read by only one client. To be precise, the last one. Ignoring the previous websocket.

This means, when I open other client, such as other tab in the same browser, the page in web browser, would not be updated to the latest value. Even when the connection status opened, the page won’t receive any data.

Python: Unsolved Issue: Same IP

The problems lies here. Remember that, we are dealing with concurrency. Setting class property as below, will override previous value. Thus we got the latest websocket.

  # websocket handler
  async def __handler(self, websocket, path):
    self.websocket = websocket

What we should do is, using function argument, instead. Propagate the websocket for each process.

  async def __handler(self, websocket, path):
    task_localfile = asyncio.create_task(
      self.__monitor_localfile(websocket))

    task_webclient = asyncio.create_task(
      self.__monitor_webclient(websocket))

    # run these two coroutines concurrently
    await(task_localfile)
    await(task_webclient)

This is not about, broadcast vs send, but rather switching paradigm to concurrency.


What is Next 🤔?

It works on my computer

We are done. Not perfect, but usable enough. But I haven’t test this in network, nor in real TV.

I have something to do these days, I will be back next week, with tidier code. Separating generic logic flow and custom data setting.

Consider continue reading [ Excel - Monitor - Python Inheritance ].