update 0.1.9

This commit is contained in:
controllerzz
2026-06-17 20:44:18 +03:00
parent 32163c0001
commit 99451aceb8
12 changed files with 814 additions and 275 deletions
+74
View File
@@ -0,0 +1,74 @@
import asyncio
from carbus_async import CarBusDevice, PeriodicCanSender
from carbus_async.device import CanTiming
async def main(is_debug=False):
dev = await CarBusDevice.open("COM6")
# await dev.open_can_channel_custom(
# channel=1,
#
# nominal_timing=CanTiming(
# prescaler=15,
# tq_seg1=12,
# tq_seg2=3,
# sjw=1
# ),
# data_timing=CanTiming(
# prescaler=6,
# tq_seg1=7,
# tq_seg2=2,
# sjw=1
# ),
# fd=True,
# brs=True,
# )
await dev.open_can_channel(
channel=1,
nominal_bitrate=500_000,
data_bitrate=2_000_000,
fd=True,
brs=True,
)
await dev.ensure_terminator(channel=1, enabled=True)
sender = PeriodicCanSender(dev)
def mod(tick, data):
b = bytearray(data)
b[0] = tick & 0xFF
return bytes(b)
sender.add(
"cnt",
channel=1,
fd=True,
brs=True,
can_id=0x100,
data=b"\x00" * 8,
period_s=0.5,
modify=mod
)
sender.add(
"heartbeat",
channel=1,
can_id=0x123,
data=b"\x01\x02\x03\x04\x05\x06\x07\x08",
period_s=0.05,
)
try:
await asyncio.Event().wait()
finally:
await sender.stop_all()
await dev.close()
return
asyncio.run(main())
+136
View File
@@ -0,0 +1,136 @@
from __future__ import annotations
import argparse
import asyncio
import logging
from typing import Optional
from carbus_async.device import CarBusDevice
# подстрой импорт под свой проект
from carbus_async.remote.client import open_remote_device
log = logging.getLogger("carbus.can_bridge.simple")
def _ensure_hooks(dev: CarBusDevice) -> None:
# фикс для твоей ошибки: где-то в CarBusDevice используется _can_hooks,
# но он не создаётся в open/open_stream
if not hasattr(dev, "_can_hooks"):
dev._can_hooks = [] # type: ignore[attr-defined]
async def _open_local(port: str, baudrate: int) -> CarBusDevice:
dev = await CarBusDevice.open(port, baudrate=baudrate, use_can=True, use_lin=False)
_ensure_hooks(dev)
return dev
async def _open_remote(relay: str, serial: int, password: str) -> CarBusDevice:
if ":" not in relay:
raise ValueError("relay must be host:port")
host, p = relay.rsplit(":", 1)
dev = await open_remote_device(host, int(p), serial=serial, password=password)
_ensure_hooks(dev)
return dev
async def _setup_can_500k(dev: CarBusDevice, channel: int) -> None:
await dev.open_can_channel(channel=channel, nominal_bitrate=500_000, fd=False)
await dev.set_std_id_filter(
channel=1,
index=0,
can_id=0x700,
mask=0x700,
)
await dev.ensure_terminator(channel=1, enabled=True)
async def _pump(
name: str,
src: CarBusDevice,
src_ch: int,
dst: CarBusDevice,
dst_ch: int,
stop: asyncio.Event,
) -> None:
try:
while not stop.is_set():
ch, msg = await src.receive_can()
if ch != src_ch:
continue
await dst.send_can(msg, channel=dst_ch, confirm=False, echo=False)
except asyncio.CancelledError:
raise
except Exception as e:
log.exception("[%s] stopped by error: %r", name, e)
finally:
stop.set()
async def main_async() -> None:
ap = argparse.ArgumentParser(description="Simple CAN bridge local<->remote via relay (no filters)")
# defaults чтобы запускать из IDE
ap.add_argument("--local-port", default="COM6")
ap.add_argument("--local-baudrate", type=int, default=115200)
ap.add_argument("--local-channel", type=int, default=1)
ap.add_argument("--relay", default="185.42.26.80:9000")
ap.add_argument("--serial", type=int, default=5957)
ap.add_argument("--password", default="1234")
ap.add_argument("--remote-channel", type=int, default=1)
ap.add_argument("--log-level", default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"])
args = ap.parse_args()
logging.basicConfig(
level=getattr(logging, args.log_level),
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
stop = asyncio.Event()
local: Optional[CarBusDevice] = None
remote: Optional[CarBusDevice] = None
try:
log.info("Open local device %s ...", args.local_port)
local = await _open_local(args.local_port, args.local_baudrate)
await _setup_can_500k(local, args.local_channel)
log.info("Local CAN ready: ch=%d @ 500k", args.local_channel)
log.info("Open remote device via relay %s (serial=%d) ...", args.relay, args.serial)
remote = await _open_remote(args.relay, args.serial, args.password)
await _setup_can_500k(remote, args.remote_channel)
log.info("Remote CAN ready: ch=%d @ 500k", args.remote_channel)
t1 = asyncio.create_task(
_pump("local->remote", local, args.local_channel, remote, args.remote_channel, stop),
name="pump_local_remote",
)
t2 = asyncio.create_task(
_pump("remote->local", remote, args.remote_channel, local, args.local_channel, stop),
name="pump_remote_local",
)
log.info("CAN bridge running. Ctrl+C to stop.")
await asyncio.Event().wait()
except KeyboardInterrupt:
pass
finally:
stop.set()
# аккуратно гасим
for dev in (remote, local):
if dev is None:
continue
try:
await dev.close()
except Exception:
pass
log.info("CAN bridge stopped.")
if __name__ == "__main__":
asyncio.run(main_async())
+2 -2
View File
@@ -25,7 +25,7 @@ async def main(is_debug=False):
channel=1,
can_id=0x100,
data=b"\x00" * 8,
period_s=0.001,
period_s=0.1,
modify=mod)
sender.add(
@@ -33,7 +33,7 @@ async def main(is_debug=False):
channel=1,
can_id=0x123,
data=b"\x01\x02\x03\x04\x05\x06\x07\x08",
period_s=0.03,
period_s=0.05,
)
try: