mirror of
https://github.com/controllerzz/carbus_lib.git
synced 2026-07-11 06:20:13 +03:00
update 0.1.9
This commit is contained in:
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user