简体   繁体   中英

python-can J1939 filter mask

I have been working in a Raspberry with an MCP2515 CAN bus device for read entire values of J1939 messages on broadcasting with python.

I would like to filter the J1939 messages, but i'm not undestand the meaning of the can-mask and how I discorver that. In the docs of python-can says:

All messages that match at least one filter are returned. If filters is None or a zero length sequence, all messages are matched.

[{"can_id": 0x11, "can_mask": 0x21, "extended": False}]

Even though I understood this 'None' part, i didn't understand how identify the mask for my ID message

Example:

I would like to just get by script just the messages with ID "0xCF00400" and "0x18fee927"

import can

# CAN Setting
can_interface = 'can0'
bus = can.interface.Bus(can_interface, bustype='socketcan_native')

while True:
     message = bus.recv()

     bus.set_filters([{"can_id":0xF004 , "can_mask": ?? , "extended": True},
                      {"can_id":0xfee9 , "can_mask": ?? , "extended": True}])

How i should fill each variable and how I determine the mask of an ID?

UPDATING 03/10/2021

I have tried the code below, but still returning all messages

import can

# CAN Setting
can_interface = 'can0'

can_filters = [{"can_id":0xCF00400, "can_mask": 0, "extended": True},
               {"can_id":0x18fee927, "can_mask": 0, "extended": True}]

bus = can.interface.Bus(can_interface, bustype='socketcan_native',can_filters=can_filters)

while True:
     message = bus.recv()
     print(message)

Output:

Timestamp: 1615382511.238233    ID: 18fee500    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.238893    ID: 18fef100    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.247038    ID: 18fef100    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.247611    ID: 18fee500    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.248222    ID: 18fee900    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.248868    ID: 0cf00400    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.257056    ID: 0cf00400    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.257623    ID: 18fee900    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.258223    ID: 18fef100    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.258827    ID: 18fee500    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.267039    ID: 18fee500    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.267624    ID: 18fef100    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.268229    ID: 0cf00400    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.268835    ID: 18fee900    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.277035    ID: 18fee900    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.277620    ID: 0cf00400    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.278220    ID: 18fee500    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0
Timestamp: 1615382511.278823    ID: 18fef100    X                DLC:  8    ff ff ff ff ff ff ff ff     Channel: can0

You can use "can_id":0xCF00400, "can_mask": 0xFFFFFFF to efficiently filter (at the kernel level) for the cob ID you want, with no mask/filter required. The mask of 0xFFFFFFF (all mask bits set to 1) requires an exact match on the can_id.

bus.set_filters([{"can_id":0xCF00400, "can_mask": 0xFFFFFFF, "extended": True},
                 {"can_id":0x18fee927, "can_mask": 0xFFFFFFF, "extended": True}])

For example, the documentation says:

A filter matches, when <received_can_id> & can_mask == can_id & can_mask . If extended is set as well, it only matches messages where <received_is_extended> == extended . Else it matches every messages based only on the arbitration ID and mask.

So as an example:

# The following just equals zero
0xCF00400 & 0 == 0 # True

# The following equals 0xCF00400 (217056256 in decimal) exactly
0xCF00400 & 0xFFFFFFF == 0xCF00400 # True
0xCF00400 & 0xFFFFFFF == 217056256 # True

# The following can_id would not get through the filter + mask:
0x18fee500 & 0xFFFFFFF == 0xCF00400 & 0xFFFFFFF # False

# The following obviously would get through the filter + mask:
0xCF00400 & 0xFFFFFFF == 0xCF00400 & 0xFFFFFFF # True

I'd put the bus.set_filters() before the while True loop, and before the bus.recv . It's a setting, so you only need to set it once at the start.

Preferable, you would add it when you initialize the bus, like this:

can_filters = [{"can_id":0xCF00400, "can_mask": 0xFFFFFFF, "extended": True},
               {"can_id":0x18fee927, "can_mask": 0xFFFFFFF, "extended": True}]

bus = can.Bus(
    interface="socketcan",
    channel="can0",
    can_filters=can_filters
)

Also, I believe bustype='socketcan_native' is deprecated in favour of interface="socketcan" . I've been using the latter with success for quite some time, and no warning messages.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM