Skip to content

Asyncio implementation - listeners and notifiers #1336

@Reowald

Description

@Reowald

This is really more of a general question than a bug or feature request apologies if it is annoying to post this general enquiry here I am happy to delete.

I am using a cm4 to bring in CAN messages and then make them available to a PLC using umodbus. I became interested in the asyncio capabilities. I did some general asyncio research and also looked in to the python-can implementation but due to my own lack of understanding have struggled to implement the python-can tools using the can.AsyncBufferedReader() - listeners and notifiers in the way that works.

Would someone be able to interpret my implementation using the basic asyncio syntax into the python-can asyncio functionality with listeners and notifiers.

I have simplified my code into hopefully something that demonstrates what I trying to achieve. I want to request a load of data and catch it and deal with it as it becomes available.


import asyncio
import can
import os
import pandas as pd
import collections

os.system(f'sudo ip link set can0 type can bitrate 500000')
os.system(f'sudo ifconfig can0 up')
bus = can.Bus("can0", bustype="socketcan", receive_own_messages=True)

#some pids (adresses) that I would like to request and read in the 100's
# list_of_ids = [b'\x00\x10', b'\x01\x10', b'\x10\x10', b'\x11\x10']
# as per original pandas decode n.b. endianess flipped
list_of_ids_cmd = [b'\x00\x10', b'\x01\x10', b'\x10\x10',
                   b'\x11\x10', b'\x12\x10', b'\x13\x10']

list_of_ids_inst = [b'\x80@', b'\x81@', b'\x82@', b'\x83@',
                    b'\x84@', b'\x85@', b'\x86@', b'\x87@']

list_of_ids = list_of_ids_cmd + list_of_ids_inst

#The active ids on my network
request_arbid = [286326784, 287440896] #'0x11110000', '0x11220000'
respond_arbid = [268439810, 268444162] #'0x10001102', '0x10002202'

# this is a placeholder of another config that decides who is gathering the data
master_id = request_arbid[0]

# declaring defaultdict sets default to catch undefined pids
request_dict = collections.defaultdict(lambda: 'This PID has not been configured')
respond_dict = collections.defaultdict(lambda: 'This PID has not been configured')

# a dict for requested data ordered by arbid and pid
request_dict = {request_arbid[i]: list_of_ids_cmd for i in range(len(request_arbid))}

#create somewhere to store data
data_dict = {list_of_ids[i]: None for i in range(len(list_of_ids))}

#this has been made a global so another module can access it
global respond_dict
# data storage by arb id
respond_dict = {respond_arbid[i]: data_dict for i in range(len(respond_arbid))}

# finds arb id and pid and logs the data from the message
async def store_data(arb_id, msg_data, msg_dlc):
    data_subset = respond_dict[arb_id]
    pid = msg_data[0:2]
    if msg_dlc == 5:
        data = msg_data[2:4]
    elif msg_dlc == 7:
        data = msg_data[2:6]
    data_subset[pid] = data

# reads bus
async def read_msg():
    while True:
        msg = bus.recv()
        arb_id = msg.arbitration_id
        msg_data = msg.data
        dlc = msg.dlc
        await store_data(arb_id, msg_data)

#eventually there would be multiple dictionary's
# with different delays and priorities async def req_read(type, delay):
async def req_read(delay):
    pids = request_dict[master_id]
    #get the arb ids currently online
    arb_ids = request_arbid
    while True:
        for i in range(len(arb_ids)):
            arb_id = arb_ids[i]
            for u in range(len(pids)):
                pid = pids[u]
                msg = can.Message(arbitration_id=arb_id, data=pid)
                bus.send(msg)
                await asyncio.sleep(delay)


loop = asyncio.get_event_loop()

#as described may have different sets of data at different rates
loop.create_task(req_read(0.2))
loop.create_task(req_read(0.5))
loop.create_task(req_read(5))

loop.run_forever()
loop.stop()

It would be fantastic if someone could point me in the right direction as to how I could implement this sort of idea with the python-can Asyncio tools like listeners, notifiers.

As always posing the question and laying it out helps and maybe that's why I am here :)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions