#python #can-bus #python-can #j1939
#python #can-bus #python-can #j1939
Вопрос:
Я работал в малине с устройством шины CAN MCP2515 для чтения целых значений сообщений J1939 при трансляции с помощью python.
Я хотел бы отфильтровать сообщения J1939, но я не понимаю значения can-маски и того, как я ее искажаю. В документах python-can говорится :
Возвращаются все сообщения, соответствующие хотя бы одному фильтру. Если filters — None или последовательность нулевой длины, все сообщения сопоставляются.
[{"can_id": 0x11, "can_mask": 0x21, "extended": False}]
Несмотря на то, что я понял эту часть «Нет», я не понял, как идентифицировать маску для моего идентификационного сообщения
Пример:
Я хотел бы просто получить с помощью скрипта только сообщения с идентификаторами «0xCF00400» и «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}])
Как я должен заполнять каждую переменную и как я определяю маску идентификатора?
ОБНОВЛЕНИЕ 03/10/2021
Я попробовал приведенный ниже код, но все равно возвращаю все сообщения
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)
Вывод:
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
Ответ №1:
Вы можете использовать "can_id":0xCF00400, "can_mask": 0xFFFFFFF
для эффективной фильтрации (на уровне ядра) для нужного вам идентификатора cob без необходимости маски / фильтра. Маска 0xFFFFFFF
(для всех битов маски установлено значение 1) требует точного совпадения с can_id .
bus.set_filters([{"can_id":0xCF00400, "can_mask": 0xFFFFFFF, "extended": True},
{"can_id":0x18fee927, "can_mask": 0xFFFFFFF, "extended": True}])
Например, в документации говорится:
Фильтр соответствует, когда
<received_can_id> amp; can_mask == can_id amp; can_mask
. Еслиextended
также задано, оно соответствует только сообщениям where<received_is_extended> == extended
. В противном случае он соответствует всем сообщениям, основанным только на идентификаторе и маске арбитража.
Итак, в качестве примера:
# The following just equals zero
0xCF00400 amp; 0 == 0 # True
# The following equals 0xCF00400 (217056256 in decimal) exactly
0xCF00400 amp; 0xFFFFFFF == 0xCF00400 # True
0xCF00400 amp; 0xFFFFFFF == 217056256 # True
# The following can_id would not get through the filter mask:
0x18fee500 amp; 0xFFFFFFF == 0xCF00400 amp; 0xFFFFFFF # False
# The following obviously would get through the filter mask:
0xCF00400 amp; 0xFFFFFFF == 0xCF00400 amp; 0xFFFFFFF # True
Я бы поставил bus.set_filters()
перед while True
циклом и перед bus.recv
. Это настройка, поэтому вам нужно установить ее только один раз при запуске.
Предпочтительнее, чтобы вы добавляли ее при инициализации шины, например:
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
)
Кроме того, я считаю bustype='socketcan_native'
, что он устарел в пользу interface="socketcan"
. Я успешно использую последнее в течение довольно долгого времени, и никаких предупреждающих сообщений.
Комментарии:
1. Привет, @Sean. Я пытался протестировать ваш код, но на самом деле он еще не работает, он по-прежнему возвращает все сообщения, а не только сообщения, которые я установил :/
2. @GabrielLincoln виноват. Мой
"can_mask": 0
(все биты 0 или выключены) просто пропускает все. Для точного совпадения попробуйте"can_mask": 0xFFFFFFF
(все биты маски 1 или установлены на).3. Спасибо @Sean! Это сработало, а также помогло мне понять, как работает маска. Кроме того, спасибо за подсказку о «встроенном сокете»