add src
This commit is contained in:
32
scripts/monitor_can.sh
Normal file
32
scripts/monitor_can.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
# Мониторинг CAN трафика с фильтрацией OBD2
|
||||
|
||||
INTERFACE=${1:-vcan0}
|
||||
|
||||
echo "=== CAN Monitor (OBD2) ==="
|
||||
echo "Interface: $INTERFACE"
|
||||
echo "Filtering: 7DF (requests) and 7E8 (responses)"
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo ""
|
||||
|
||||
# Проверка candump
|
||||
if ! command -v candump &> /dev/null; then
|
||||
echo "Error: candump not found. Install can-utils:"
|
||||
echo " sudo apt install can-utils"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Мониторинг с фильтром
|
||||
candump "$INTERFACE" | grep -E "(7DF|7E8)" | while read line; do
|
||||
timestamp=$(date +"%H:%M:%S.%3N")
|
||||
|
||||
# Парсинг и форматирование
|
||||
if echo "$line" | grep -q "7DF"; then
|
||||
# Запрос
|
||||
pid=$(echo "$line" | awk '{print $3}' | cut -c5-6)
|
||||
echo "[$timestamp] REQUEST -> PID: 0x$pid"
|
||||
elif echo "$line" | grep -q "7E8"; then
|
||||
# Ответ
|
||||
echo "[$timestamp] RESPONSE <- $line"
|
||||
fi
|
||||
done
|
||||
62
scripts/setup_can.sh
Normal file
62
scripts/setup_can.sh
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
# Скрипт настройки CAN интерфейсов на Raspberry Pi 5 с 2CH CAN HAT
|
||||
|
||||
set -e
|
||||
|
||||
BITRATE=${1:-500000}
|
||||
|
||||
echo "=== CAN Interface Setup ==="
|
||||
echo "Bitrate: $BITRATE bps"
|
||||
echo ""
|
||||
|
||||
# Проверка прав
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root (sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Загрузка модулей
|
||||
echo "[1/4] Loading kernel modules..."
|
||||
modprobe can
|
||||
modprobe can_raw
|
||||
modprobe mcp251x 2>/dev/null || true # Для SPI CAN контроллеров
|
||||
|
||||
# Настройка can0
|
||||
echo "[2/4] Configuring can0..."
|
||||
if ip link show can0 &>/dev/null; then
|
||||
ip link set can0 down 2>/dev/null || true
|
||||
ip link set can0 type can bitrate $BITRATE
|
||||
ip link set can0 up
|
||||
echo " can0: UP at $BITRATE bps"
|
||||
else
|
||||
echo " can0: Not found (skipping)"
|
||||
fi
|
||||
|
||||
# Настройка can1
|
||||
echo "[3/4] Configuring can1..."
|
||||
if ip link show can1 &>/dev/null; then
|
||||
ip link set can1 down 2>/dev/null || true
|
||||
ip link set can1 type can bitrate $BITRATE
|
||||
ip link set can1 up
|
||||
echo " can1: UP at $BITRATE bps"
|
||||
else
|
||||
echo " can1: Not found (skipping)"
|
||||
fi
|
||||
|
||||
# Создание vcan0 для тестирования
|
||||
echo "[4/4] Creating virtual CAN (vcan0)..."
|
||||
modprobe vcan
|
||||
if ! ip link show vcan0 &>/dev/null; then
|
||||
ip link add dev vcan0 type vcan
|
||||
fi
|
||||
ip link set vcan0 up
|
||||
echo " vcan0: UP (virtual)"
|
||||
|
||||
echo ""
|
||||
echo "=== Status ==="
|
||||
ip -details link show type can 2>/dev/null || echo "No physical CAN interfaces"
|
||||
ip -details link show type vcan 2>/dev/null || echo "No virtual CAN interfaces"
|
||||
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
echo "You can now run: python src/main.py -i can1 -s city"
|
||||
157
scripts/test_obd2.py
Normal file
157
scripts/test_obd2.py
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Тестовый скрипт для проверки OBD2 эмулятора.
|
||||
Отправляет OBD2 запросы и выводит ответы.
|
||||
"""
|
||||
import argparse
|
||||
import sys
|
||||
import time
|
||||
|
||||
try:
|
||||
import can
|
||||
except ImportError:
|
||||
print("Error: python-can not installed. Run: pip install python-can")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# OBD2 PIDs для тестирования
|
||||
TEST_PIDS = [
|
||||
(0x00, "Supported PIDs [01-20]"),
|
||||
(0x05, "Coolant Temperature"),
|
||||
(0x0C, "Engine RPM"),
|
||||
(0x0D, "Vehicle Speed"),
|
||||
(0x0F, "Intake Air Temperature"),
|
||||
(0x11, "Throttle Position"),
|
||||
(0x2F, "Fuel Tank Level"),
|
||||
(0x46, "Ambient Temperature"),
|
||||
]
|
||||
|
||||
|
||||
def decode_pid(pid: int, data: bytes) -> str:
|
||||
"""Декодировать значение PID."""
|
||||
if len(data) < 1:
|
||||
return "No data"
|
||||
|
||||
if pid == 0x00:
|
||||
# Supported PIDs bitmap
|
||||
if len(data) >= 4:
|
||||
mask = int.from_bytes(data[:4], "big")
|
||||
supported = []
|
||||
for i in range(32):
|
||||
if mask & (1 << (31 - i)):
|
||||
supported.append(f"{i+1:02X}")
|
||||
return f"PIDs: {', '.join(supported[:10])}..."
|
||||
return f"Raw: {data.hex()}"
|
||||
|
||||
elif pid == 0x05 or pid == 0x0F or pid == 0x46:
|
||||
# Temperature: A - 40
|
||||
return f"{data[0] - 40} °C"
|
||||
|
||||
elif pid == 0x0C:
|
||||
# RPM: (A*256 + B) / 4
|
||||
if len(data) >= 2:
|
||||
rpm = (data[0] * 256 + data[1]) / 4
|
||||
return f"{rpm:.0f} rpm"
|
||||
|
||||
elif pid == 0x0D:
|
||||
# Speed: A
|
||||
return f"{data[0]} km/h"
|
||||
|
||||
elif pid == 0x11 or pid == 0x2F:
|
||||
# Percentage: A * 100 / 255
|
||||
return f"{data[0] * 100 / 255:.1f} %"
|
||||
|
||||
return f"Raw: {data.hex()}"
|
||||
|
||||
|
||||
def send_obd2_request(bus: can.Bus, pid: int, timeout: float = 1.0) -> bytes | None:
|
||||
"""Отправить OBD2 запрос и получить ответ."""
|
||||
# Формируем запрос Mode 01
|
||||
request = can.Message(
|
||||
arbitration_id=0x7DF,
|
||||
data=[0x02, 0x01, pid, 0x00, 0x00, 0x00, 0x00, 0x00],
|
||||
is_extended_id=False
|
||||
)
|
||||
|
||||
# Отправляем
|
||||
bus.send(request)
|
||||
|
||||
# Ждём ответ
|
||||
start = time.time()
|
||||
while time.time() - start < timeout:
|
||||
msg = bus.recv(timeout=0.1)
|
||||
if msg is None:
|
||||
continue
|
||||
|
||||
# Проверяем, что это ответ от ECU
|
||||
if msg.arbitration_id == 0x7E8:
|
||||
data = bytes(msg.data)
|
||||
# Проверяем формат ответа
|
||||
if len(data) >= 3 and data[1] == 0x41 and data[2] == pid:
|
||||
# Возвращаем данные (без заголовка)
|
||||
return data[3:3 + data[0] - 2]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Test OBD2 Emulator")
|
||||
parser.add_argument(
|
||||
"-i", "--interface",
|
||||
default="vcan0",
|
||||
help="CAN interface [default: vcan0]"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c", "--continuous",
|
||||
action="store_true",
|
||||
help="Continuous mode (loop forever)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--interval",
|
||||
type=float,
|
||||
default=1.0,
|
||||
help="Interval between requests in continuous mode [default: 1.0]"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
print(f"=== OBD2 Emulator Test ===")
|
||||
print(f"Interface: {args.interface}")
|
||||
print("")
|
||||
|
||||
try:
|
||||
bus = can.Bus(interface="socketcan", channel=args.interface)
|
||||
except Exception as e:
|
||||
print(f"Error: Failed to connect to {args.interface}: {e}")
|
||||
print("Make sure the interface is up: sudo ip link set vcan0 up")
|
||||
return 1
|
||||
|
||||
try:
|
||||
while True:
|
||||
print(f"Timestamp: {time.strftime('%H:%M:%S')}")
|
||||
print("-" * 50)
|
||||
|
||||
for pid, name in TEST_PIDS:
|
||||
data = send_obd2_request(bus, pid)
|
||||
if data:
|
||||
value = decode_pid(pid, data)
|
||||
print(f" PID {pid:02X} ({name}): {value}")
|
||||
else:
|
||||
print(f" PID {pid:02X} ({name}): No response")
|
||||
|
||||
print("")
|
||||
|
||||
if not args.continuous:
|
||||
break
|
||||
|
||||
time.sleep(args.interval)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nStopped")
|
||||
finally:
|
||||
bus.shutdown()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user