-
Notifications
You must be signed in to change notification settings - Fork 646
Description
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 :)