From 0accfa2d3e167db9df2a76154384383283ebeeec Mon Sep 17 00:00:00 2001 From: controllerzz <79202101363@mail.ru> Date: Thu, 11 Dec 2025 15:10:58 +0300 Subject: [PATCH] add open_can_channel_custom --- README.md | 31 ++++++++++----- carbus_async/device.py | 90 ++++++++++++++++++++++++++++++++++++++++++ main.py | 6 ++- 3 files changed, 116 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 5fa5ae5..9a684ea 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ pip install -e . --- -## 1. Работа с CAN +## Работа с CAN Простейший пример: открыть устройство, настроить канал и отправить / принять кадр. @@ -60,7 +60,7 @@ async def main(): nominal_bitrate=500_000, ) - # включаем терминатор 120 Ом на канале 1 + # включаем терминатор 120 Ω на канале 1 await dev.set_terminator(channel=1, enabled=True) # отправка кадра 0x7E0 8 байт @@ -76,8 +76,19 @@ async def main(): asyncio.run(main()) ```` +Возможность настройки канала через Bit Timing +````python +# CANFD+BRS 500/2000 kbit/s +await dev.open_can_channel_custom( + channel=1, + nominal=(15, 12, 3, 1), # Prescaler, tqSeg1, tqSeg2, SyncJW + data=(6, 7, 2, 1), # Prescaler, tqSeg1, tqSeg2, SyncJW + fd=True, + brs=True, +) +```` -## 2. Информация об устройстве и фильтры +## Информация об устройстве и фильтры Пример запроса DEVICE_INFO и настройки фильтров: ````python @@ -102,7 +113,7 @@ await dev.set_std_id_filter( await dev.set_terminator(channel=1, enabled=True) ```` -## 3. ISO-TP (isotp_async) +## ISO-TP (isotp_async) ISO-TP канал строится поверх CarBusDevice: ````python from isotp_async.transport import IsoTpChannel @@ -118,7 +129,7 @@ resp = await isotp.recv_pdu(timeout=30.0) print("ISO-TP:", resp.hex()) ```` -## 4. UDS Client (uds_async.client) +## UDS Client (uds_async.client) Клиент UDS использует IsoTpChannel: ````python @@ -136,9 +147,9 @@ print("VIN:", vin.decode(errors="ignore")) -## 5. Удалённая работа через TCP (tcp_bridge) +## Удалённая работа через TCP (tcp_bridge) -### 5.1. Сервер (рядом с адаптером) +### 1. Сервер (рядом с адаптером) На машине, где физически подключён CAN-адаптер: @@ -146,7 +157,7 @@ print("VIN:", vin.decode(errors="ignore")) Адаптер открывается локально, а поверх него поднимается TCP-мост. -### 5.2. Клиент (удалённая машина) +### 2. Клиент (удалённая машина) На другой машине можно использовать тот же API, как с локальным COM, но через `open_tcp`: ````python @@ -174,7 +185,7 @@ async def main(): asyncio.run(main()) ```` -## 6. Логирование +## Логирование Для отладки удобно включить подробное логирование: ````python @@ -193,7 +204,7 @@ asyncio.run(main()) --- -## 7. Лицензия +## Лицензия MIT. diff --git a/carbus_async/device.py b/carbus_async/device.py index 781300d..ec8d6fb 100644 --- a/carbus_async/device.py +++ b/carbus_async/device.py @@ -761,6 +761,96 @@ class CarBusDevice: f"Unexpected CHANNEL_OPEN response: cmd=0x{cmd:02X}, flags=0x{flags:04X}" ) + async def open_can_channel_custom( + self, + channel: int = 1, + *, + nominal: tuple[int, int, int, int] | None, + data: tuple[int, int, int, int] | None = None, + fd: bool = False, + brs: bool = False, + listen_only: bool = False, + loopback: bool = False, + retransmit: bool = False, + non_iso: bool = False, + ) -> None: + + def _build_bus_custom_baudrate_words( + base_cc: int, + prescaler: int, + seg1: int, + seg2: int, + sjw: int, + ) -> list[int]: + + packed = struct.pack("