0

I try to resolve this problem about asynchronous WebSocket using python. I don't know why when I used the asynchronous process I get the error log bellow. But my code is totally fine when I didn't used the asynchronous.

error log

C:\ProgramData\Anaconda3\lib\site-packages\numpy\__init__.py:148: UserWarning: mkl-service package failed to import, therefore Intel(R) MKL initialization ensuring its correct out-of-the box operation under condition when Gnu OpenMP had already been loaded by Python process is not assured. Please install mkl-service package, see http://github.com/IntelPython/mkl-service
  from . import _distributor_init
[2022-12-15 12:51:26,677][root][INFO] - Connected to localhost object_detection mysql database
Error executing job with overrides: []
Traceback (most recent call last):
  File "e:\alfa_beta\etl-python\object_counting\object_counting.py", line 102, in object_counter
  File "e:\alfa_beta\etl-python\object_counting\object_counting.py", line 102, in object_counter
    obj_counting.async_runner()
  File "e:\alfa_beta\etl-python\object_counting\object_counting.py", line 41, in async_runner
    asyncio.run(self.vehicle_async())
  File "C:\ProgramData\Anaconda3\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\ProgramData\Anaconda3\lib\asyncio\base_events.py", line 647, in run_until_complete
    return future.result()
  File "e:\alfa_beta\etl-python\object_counting\object_counting.py", line 62, in vehicle_async
    async with create_connection(self.ws_connection) as async_ws_connection:
AttributeError: __aenter__

Set the environment variable HYDRA_FULL_ERROR=1 for a complete stack trace.

hydra config

mode: object_counter

# internal database (mysql)
local_db:
  database: object_detection
  enabled: true
  host: localhost
  password: ""
  port: 3306
  user: root
  db_type: mysql

# service camera
service:
  vehichle_counting:
    table: history_vehicles
    ip_cam: 123.23.322.10
    ws_connect: ws://123.23.322.24:324/
    ws_host: 123.23.322.24
    ws_port: 324
    ws_prefix:
      json_data: 3242
      unknown: 42
      video_stream: 0222

Main code to run async object_counting.py

from omegaconf import DictConfig
from pyrootutils import setup_root
from types import SimpleNamespace
from websocket import create_connection, enableTrace
import dill as pickle
import asyncio
import hydra
import json

root = setup_root(
    search_from=__file__,
    indicator=[".git", "pyproject.toml"],
    pythonpath=True,
    dotenv=True,
)

# internal package
import websocket_data as wsd
from src.config.database_config import Database
from src.infra import time_infra as ABTime

# from object_counting import websocket_data as wsd

# TODO multi processing

class ObjectCounting:

    def __init__(self, config: DictConfig, ip_camera: str, ws_connection: str):
        self.config = config
        self.ip_camera = ip_camera
        self.ws_connection = ws_connection  # websocket


    def async_runner(self):
        """
        async_runner will help us to run the asynchronous process in object detection
        for now will runn vehicle_async
        """        
        asyncio.run(self.vehicle_async())
        
    async def vehicle_async(self):
        """
        vehicle_async is the asynchronous process for vehicle detection. 
        It will take data from WebSocket with ANPR type and push the license 
        plate number with vehicle type of each caught vehicle to MYSQL database
        """        
        # database
        self.local_db = Database(
            self.config.local_db.host,
            self.config.local_db.port,
            self.config.local_db.user,
            self.config.local_db.password,
            self.config.local_db.database,
            self.config.local_db.db_type,
        ) if self.config.local_db.enabled else None
        
        self.push_table = self.config.service.vehichle_counting_cam_1.table
        
        # enableTrace(True)
        async with create_connection(self.ws_connection) as async_ws_connection:
            while True:
                try:
                    json_data = json.loads(await async_ws_connection.recv(), 
                                           object_hook=lambda d: SimpleNamespace(**d))
                    if json_data.type == "anpr":
                        raw_data = wsd.WebsocketData(json_data.type, 
                                                 json_data.payload, 
                                                 json_data.img)
                        payload_ws = raw_data.payload[0]
                        result_json = payload_ws.resjson
                        image_ws = raw_data.img
                        if result_json != '':
                            print("\ncatch!")
                            print('\nPayload: {}'.format(payload_ws))
                            # push_table = "history_vehicle"
                            response = {"camera_id": 123, 
                                        "camera_name": "test_camera", 
                                        "plate_number": payload_ws.label,
                                        "vehicle_type": payload_ws.vehicle_type,
                                        "datetime": ABTime.ab_timestamp(),
                                        "image": image_ws,
                                        }
                            self.local_db.push_data(self.push_table, response, self.local_db.db_type)
                            # TODO push data to mysql

                except Exception as e:
                    print("error :", e)


if __name__ == "__main__":
    
    @hydra.main(config_path=root / "config", config_name="object_counter", version_base=None)
    def object_counter(hydra_config: DictConfig):
        
        hydra_service = hydra_config.service.vehichle_counting_cam_1
        ip_camera = hydra_service.ip_cam
        ws_connection = hydra_service.ws_connect
        
        obj_counting = ObjectCounting(hydra_config, ip_camera, ws_connection)
        obj_counting.async_runner()
    object_counter()

Object parsing data to convert WebSocket data to python object

from typing import List

class Box:
    xmin: int
    ymin: int
    xmax: int
    ymax: int

    def __init__(self, xmin: int, ymin: int, xmax: int, ymax: int) -> None:
        self.xmin = xmin
        self.ymin = ymin
        self.xmax = xmax
        self.ymax = ymax
        


class Candidate:
    score: float
    plate: str

    def __init__(self, score: float, plate: str) -> None:
        self.score = score
        self.plate = plate


class Color:
    color: str
    score: float

    def __init__(self, color: str, score: float) -> None:
        self.color = color
        self.score = score


class ModelMake:
    make: str
    model: str
    score: float

    def __init__(self, make: str, model: str, score: float) -> None:
        self.make = make
        self.model = model
        self.score = score


class Orientation:
    orientation: str
    score: float

    def __init__(self, orientation: str, score: float) -> None:
        self.orientation = orientation
        self.score = score


class Region:
    code: str
    score: float

    def __init__(self, code: str, score: float) -> None:
        self.code = code
        self.score = score


class Vehicle:
    score: float
    type: str
    box: Box

    def __init__(self, score: float, type: str, box: Box) -> None:
        self.score = score
        self.type = type
        self.box = box


class Resjson:
    box: Box
    plate: str
    region: Region
    score: float
    candidates: List[Candidate]
    dscore: float
    vehicle: Vehicle
    model_make: List[ModelMake]
    color: List[Color]
    orientation: List[Orientation]

    def __init__(self, box: Box, plate: str, region: Region, score: float, candidates: List[Candidate], dscore: float, vehicle: Vehicle, model_make: List[ModelMake], color: List[Color], orientation: List[Orientation]) -> None:
        self.box = box
        self.plate = plate
        self.region = region
        self.score = score
        self.candidates = candidates
        self.dscore = dscore
        self.vehicle = vehicle
        self.model_make = model_make
        self.color = color
        self.orientation = orientation


class Payload:
    label: str
    vehicle_type: str
    resjson: Resjson

    def __init__(self, label: str, vehicle_type: str, resjson: Resjson) -> None:
        self.label = label
        self.vehicle_type = vehicle_type
        self.resjson = resjson


class WebsocketData:
    type: str
    payload: List[Payload]
    img: str

    def __init__(self, type: str, payload: List[Payload], img: str) -> None:
        self.type = type
        self.payload = payload
        self.img = img
  • I used websockets version 10.4 and my websocket-client version is 0.58.0 – Moch. Chamdani M Dec 15 '22 at 09:28
  • I hope it's the correct documentation link - https://websocket-client.readthedocs.io/en/latest/threading.html#asyncio-library-usage - it states that that that library is not `asyncio` compatible. – VPfB Dec 15 '22 at 09:47
  • I have other solution too, I try to replace the `websocket.create_connection` to `websokets.connect` and it is works – Moch. Chamdani M Dec 15 '22 at 09:58

0 Answers0