Skip to content

[Bug]: Websocket blocking requests #190

@kratochvil01

Description

@kratochvil01

Prerequisites

  • I am running the latest Evok version
  • I have searched other issues

Describe the bug

When controlling the device using the websocket protocol, the protocol gets stuck when writing to the device fails. websocket connection is still active and it is possible to send requests that are not actually executed.

When the connection is reestablished, Evok then executes all the requests sent and received during the period of protocol inactivity in one moment.

In the stuck state, Evok does not control even devices on another bus

Evok log

DEBUG:evok:New WebSocket client connected
ERROR:evok:xS11: Error while scanning: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 223, in scan_boards
    if await self.modbus_cache_map.do_scan(slave=self.modbus_address) is True:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 99, in do_scan
    vals = await self.modbus_slave.client.read_holding_registers(m_reg_group['start_reg'], m_reg_group['count'], slave=slave)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
WARNING:evok:Slowing down device: 'xS11'
ERROR:evok:Error in set RO: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 839, in set
    await self.arm.modbus_slave.client.write_coil(self.coil, parsed_value, slave=self.arm.modbus_address)
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
ERROR:evok:EsHandler error in request: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/evok.py", line 194, in on_message
    result = await func(value)
             ^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 850, in set
    raise E
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 839, in set
    await self.arm.modbus_slave.client.write_coil(self.coil, parsed_value, slave=self.arm.modbus_address)
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
ERROR:evok:Error in set RO: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 839, in set
    await self.arm.modbus_slave.client.write_coil(self.coil, parsed_value, slave=self.arm.modbus_address)
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
ERROR:evok:EsHandler error in request: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/evok.py", line 194, in on_message
    result = await func(value)
             ^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 850, in set
    raise E
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 839, in set
    await self.arm.modbus_slave.client.write_coil(self.coil, parsed_value, slave=self.arm.modbus_address)
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
ERROR:evok:Error in set RO: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 839, in set
    await self.arm.modbus_slave.client.write_coil(self.coil, parsed_value, slave=self.arm.modbus_address)
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
ERROR:evok:EsHandler error in request: 'NoneType' object has no attribute 'close'
Traceback (most recent call last):
  File "/opt/evok/lib/python3.11/site-packages/evok/evok.py", line 194, in on_message
    result = await func(value)
             ^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 850, in set
    raise E
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_slave.py", line 839, in set
    await self.arm.modbus_slave.client.write_coil(self.coil, parsed_value, slave=self.arm.modbus_address)
  File "/opt/evok/lib/python3.11/site-packages/evok/modbus_unipi.py", line 42, in ret
    aret = await operation(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 206, in async_execute
    self.close(reconnect=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/client/base.py", line 153, in close
    self.connection_lost(asyncio.TimeoutError("Server not responding"))
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 300, in connection_lost
    self.transport_close(intern=True)
  File "/opt/evok/lib/python3.11/site-packages/pymodbus/transport/transport.py", line 419, in transport_close
    self.transport.close()
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'close'
INFO:evok:Communication with device is back: 'xS11'

Steps to reproduce

  • send requests for device control
  • disconnect from one of the controlled devices
  • < all device control does not respond - websocket does not report error >
  • reconnect to a disconnected device
  • < After a while, all actions are performed at once >

Python code for sending requests for device control

import time
from threading import Thread

import websocket, json


def on_message(ws, message):
    print(f"Received message: {message}")


def on_close(ws, status, message):
    print(f"WebSocket connection closed")


def on_open(ws):
    print("WebSocket connection opened")


if __name__ == "__main__":
    url = 'ws://192.168.221.168/ws'
    ws = websocket.WebSocketApp(url, on_message=on_message, on_close=on_close, on_open=on_open)
    ws_thread = Thread(target=ws.run_forever)
    ws_thread.start()
    time.sleep(.1)
    
    try:
        value: bool = False
        while True:
            msg = {"cmd": "set", "dev": "ro", "circuit": "xS11_01", "value": int(value)}
            ws.send(json.dumps(msg))
            msg = {"cmd": "set", "dev": "ro", "circuit": "L523_2_01", "value": int(value)}
            ws.send(json.dumps(msg))
            value = not value
            time.sleep(1)
    finally:
        ws.close()
        ws_thread.join()

Expected behavior

The websocket will not get stuck on a failed write.

Actual behavior

The websocket got stuck when the write failed.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions