mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-01 03:43:46 +08:00
Merge commit 'c251b312d87d26b5ed347b267f6f1570793f9b91' as 'panda'
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/python
|
||||
import requests
|
||||
import json
|
||||
from automated.helpers import _connect_wifi
|
||||
from panda import Panda
|
||||
from nose.tools import assert_equal
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Fetching latest firmware from github.com/commaai/panda-artifacts")
|
||||
r = requests.get("https://raw.githubusercontent.com/commaai/panda-artifacts/master/latest.json")
|
||||
latest_version = json.loads(r.text)['version']
|
||||
|
||||
for p in Panda.list():
|
||||
dongle_id, pw = Panda(p).get_serial()
|
||||
print dongle_id, pw
|
||||
assert(dongle_id.isalnum())
|
||||
_connect_wifi(dongle_id, pw)
|
||||
|
||||
r = requests.get("http://192.168.0.10/")
|
||||
print r.text
|
||||
wifi_dongle_id = r.text.split("ssid: panda-")[1].split("<br/>")[0]
|
||||
st_version = r.text.split("st version:")[1].strip().split("<br/>")[0]
|
||||
esp_version = r.text.split("esp version:")[1].strip().split("<br/>")[0]
|
||||
|
||||
assert_equal(str(dongle_id), wifi_dongle_id)
|
||||
assert_equal(latest_version, st_version)
|
||||
assert_equal(latest_version, esp_version)
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
from panda import build_st
|
||||
|
||||
def test_build_legacy():
|
||||
build_st("obj/comma.bin", "Makefile.legacy")
|
||||
|
||||
def test_build_bootstub_legacy():
|
||||
build_st("obj/bootstub.comma.bin", "Makefile.legacy")
|
||||
|
||||
def test_build_panda():
|
||||
build_st("obj/panda.bin")
|
||||
|
||||
def test_build_bootstub_panda():
|
||||
build_st("obj/bootstub.panda.bin")
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import os
|
||||
from panda import Panda
|
||||
|
||||
def test_recover():
|
||||
p = Panda()
|
||||
p.recover()
|
||||
|
||||
def test_flash():
|
||||
p = Panda()
|
||||
p.flash()
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from panda import Panda
|
||||
from nose.tools import timed, assert_equal, assert_less, assert_greater
|
||||
from helpers import time_many_sends, connect_wo_esp
|
||||
|
||||
SPEED_NORMAL = 500
|
||||
SPEED_GMLAN = 33.3
|
||||
|
||||
def test_can_loopback():
|
||||
p = connect_wo_esp()
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# enable CAN loopback mode
|
||||
p.set_can_loopback(True)
|
||||
|
||||
if p.legacy:
|
||||
busses = [0,1]
|
||||
else:
|
||||
busses = [0,1,2]
|
||||
|
||||
for bus in busses:
|
||||
# set bus 0 speed to 250
|
||||
p.set_can_speed_kbps(bus, 250)
|
||||
|
||||
# send a message on bus 0
|
||||
p.can_send(0x1aa, "message", bus)
|
||||
|
||||
# confirm receive both on loopback and send receipt
|
||||
time.sleep(0.05)
|
||||
r = p.can_recv()
|
||||
sr = filter(lambda x: x[3] == 0x80 | bus, r)
|
||||
lb = filter(lambda x: x[3] == bus, r)
|
||||
assert len(sr) == 1
|
||||
assert len(lb) == 1
|
||||
|
||||
# confirm data is correct
|
||||
assert 0x1aa == sr[0][0] == lb[0][0]
|
||||
assert "message" == sr[0][2] == lb[0][2]
|
||||
|
||||
def test_safety_nooutput():
|
||||
p = connect_wo_esp()
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_NOOUTPUT)
|
||||
|
||||
# enable CAN loopback mode
|
||||
p.set_can_loopback(True)
|
||||
|
||||
# send a message on bus 0
|
||||
p.can_send(0x1aa, "message", 0)
|
||||
|
||||
# confirm receive nothing
|
||||
time.sleep(0.05)
|
||||
r = p.can_recv()
|
||||
assert len(r) == 0
|
||||
|
||||
def test_reliability():
|
||||
p = connect_wo_esp()
|
||||
|
||||
LOOP_COUNT = 100
|
||||
MSG_COUNT = 100
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p.set_can_loopback(True)
|
||||
p.set_can_speed_kbps(0, 1000)
|
||||
|
||||
addrs = range(100, 100+MSG_COUNT)
|
||||
ts = [(j, 0, "\xaa"*8, 0) for j in addrs]
|
||||
|
||||
# 100 loops
|
||||
for i in range(LOOP_COUNT):
|
||||
st = time.time()
|
||||
|
||||
p.can_send_many(ts)
|
||||
|
||||
r = []
|
||||
while len(r) < 200 and (time.time() - st) < 0.5:
|
||||
r.extend(p.can_recv())
|
||||
|
||||
sent_echo = filter(lambda x: x[3] == 0x80, r)
|
||||
loopback_resp = filter(lambda x: x[3] == 0, r)
|
||||
|
||||
assert_equal(sorted(map(lambda x: x[0], loopback_resp)), addrs)
|
||||
assert_equal(sorted(map(lambda x: x[0], sent_echo)), addrs)
|
||||
assert_equal(len(r), 200)
|
||||
|
||||
# take sub 20ms
|
||||
et = (time.time()-st)*1000.0
|
||||
assert_less(et, 20)
|
||||
|
||||
sys.stdout.write("P")
|
||||
sys.stdout.flush()
|
||||
|
||||
def test_throughput():
|
||||
p = connect_wo_esp()
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# enable CAN loopback mode
|
||||
p.set_can_loopback(True)
|
||||
|
||||
for speed in [100,250,500,750,1000]:
|
||||
# set bus 0 speed to speed
|
||||
p.set_can_speed_kbps(0, speed)
|
||||
time.sleep(0.05)
|
||||
|
||||
comp_kbps = time_many_sends(p, 0)
|
||||
|
||||
# bit count from https://en.wikipedia.org/wiki/CAN_bus
|
||||
saturation_pct = (comp_kbps/speed) * 100.0
|
||||
assert_greater(saturation_pct, 80)
|
||||
assert_less(saturation_pct, 100)
|
||||
|
||||
print("loopback 100 messages at speed %d, comp speed is %.2f, percent %.2f" % (speed, comp_kbps, saturation_pct))
|
||||
|
||||
def test_gmlan():
|
||||
p = connect_wo_esp()
|
||||
|
||||
if p.legacy:
|
||||
return
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# enable CAN loopback mode
|
||||
p.set_can_loopback(True)
|
||||
|
||||
p.set_can_speed_kbps(1, SPEED_NORMAL)
|
||||
p.set_can_speed_kbps(2, SPEED_NORMAL)
|
||||
p.set_can_speed_kbps(3, SPEED_GMLAN)
|
||||
|
||||
# set gmlan on CAN2
|
||||
for bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3, Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]:
|
||||
p.set_gmlan(bus)
|
||||
comp_kbps_gmlan = time_many_sends(p, 3)
|
||||
assert_greater(comp_kbps_gmlan, 0.8 * SPEED_GMLAN)
|
||||
assert_less(comp_kbps_gmlan, 1.0 * SPEED_GMLAN)
|
||||
|
||||
p.set_gmlan(None)
|
||||
comp_kbps_normal = time_many_sends(p, bus)
|
||||
assert_greater(comp_kbps_normal, 0.8 * SPEED_NORMAL)
|
||||
assert_less(comp_kbps_normal, 1.0 * SPEED_NORMAL)
|
||||
|
||||
print("%d: %.2f kbps vs %.2f kbps" % (bus, comp_kbps_gmlan, comp_kbps_normal))
|
||||
|
||||
def test_gmlan_bad_toggle():
|
||||
p = connect_wo_esp()
|
||||
|
||||
if p.legacy:
|
||||
return
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# enable CAN loopback mode
|
||||
p.set_can_loopback(True)
|
||||
|
||||
# GMLAN_CAN2
|
||||
for bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]:
|
||||
p.set_gmlan(bus)
|
||||
comp_kbps_gmlan = time_many_sends(p, 3)
|
||||
assert_greater(comp_kbps_gmlan, 0.6 * SPEED_GMLAN)
|
||||
assert_less(comp_kbps_gmlan, 1.0 * SPEED_GMLAN)
|
||||
|
||||
# normal
|
||||
for bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]:
|
||||
p.set_gmlan(None)
|
||||
comp_kbps_normal = time_many_sends(p, bus)
|
||||
assert_greater(comp_kbps_normal, 0.6 * SPEED_NORMAL)
|
||||
assert_less(comp_kbps_normal, 1.0 * SPEED_NORMAL)
|
||||
|
||||
|
||||
# this will fail if you have hardware serial connected
|
||||
def test_serial_debug():
|
||||
p = connect_wo_esp()
|
||||
junk = p.serial_read(Panda.SERIAL_DEBUG)
|
||||
p.call_control_api(0xc0)
|
||||
assert(p.serial_read(Panda.SERIAL_DEBUG).startswith("can "))
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
from __future__ import print_function
|
||||
import os
|
||||
from panda import Panda
|
||||
from helpers import connect_wifi
|
||||
import requests
|
||||
|
||||
def test_get_serial():
|
||||
p = Panda()
|
||||
print(p.get_serial())
|
||||
|
||||
def test_get_serial_in_flash_mode():
|
||||
p = Panda()
|
||||
p.reset(enter_bootstub=True)
|
||||
assert(p.bootstub)
|
||||
print(p.get_serial())
|
||||
p.reset()
|
||||
|
||||
def test_connect_wifi():
|
||||
connect_wifi()
|
||||
|
||||
def test_flash_wifi():
|
||||
Panda.flash_ota_wifi()
|
||||
connect_wifi()
|
||||
|
||||
def test_wifi_flash_st():
|
||||
Panda.flash_ota_st()
|
||||
|
||||
def test_webpage_fetch():
|
||||
r = requests.get("http://192.168.0.10/")
|
||||
print(r.text)
|
||||
|
||||
assert "This is your comma.ai panda" in r.text
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
from __future__ import print_function
|
||||
import time
|
||||
from panda import Panda
|
||||
from helpers import time_many_sends, connect_wifi
|
||||
from nose.tools import timed, assert_equal, assert_less, assert_greater
|
||||
|
||||
def test_get_serial_wifi():
|
||||
connect_wifi()
|
||||
|
||||
p = Panda("WIFI")
|
||||
print(p.get_serial())
|
||||
|
||||
def test_throughput():
|
||||
p = Panda()
|
||||
|
||||
# enable output mode
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# enable CAN loopback mode
|
||||
p.set_can_loopback(True)
|
||||
|
||||
p = Panda("WIFI")
|
||||
|
||||
for speed in [100,250,500,750,1000]:
|
||||
# set bus 0 speed to speed
|
||||
p.set_can_speed_kbps(0, speed)
|
||||
time.sleep(0.05)
|
||||
|
||||
comp_kbps = time_many_sends(p, 0)
|
||||
|
||||
# bit count from https://en.wikipedia.org/wiki/CAN_bus
|
||||
saturation_pct = (comp_kbps/speed) * 100.0
|
||||
#assert_greater(saturation_pct, 80)
|
||||
#assert_less(saturation_pct, 100)
|
||||
|
||||
print("WIFI loopback 100 messages at speed %d, comp speed is %.2f, percent %.2f" % (speed, comp_kbps, saturation_pct))
|
||||
|
||||
def test_recv_only():
|
||||
p = Panda()
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p.set_can_loopback(True)
|
||||
pwifi = Panda("WIFI")
|
||||
|
||||
# TODO: msg_count=1000 drops packets, is this fixable?
|
||||
for msg_count in [10,100,200]:
|
||||
speed = 500
|
||||
p.set_can_speed_kbps(0, speed)
|
||||
comp_kbps = time_many_sends(p, 0, pwifi, msg_count)
|
||||
saturation_pct = (comp_kbps/speed) * 100.0
|
||||
|
||||
print("HT WIFI loopback %d messages at speed %d, comp speed is %.2f, percent %.2f" % (msg_count, speed, comp_kbps, saturation_pct))
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import time
|
||||
from helpers import time_many_sends, connect_wifi
|
||||
from panda import Panda, PandaWifiStreaming
|
||||
from nose.tools import timed, assert_equal, assert_less, assert_greater
|
||||
|
||||
def test_udp_doesnt_drop():
|
||||
connect_wifi()
|
||||
|
||||
p = Panda()
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p.set_can_loopback(True)
|
||||
|
||||
pwifi = PandaWifiStreaming()
|
||||
while 1:
|
||||
if len(pwifi.can_recv()) == 0:
|
||||
break
|
||||
|
||||
for msg_count in [1, 100]:
|
||||
for i in range({1: 0x80, 100: 0x20}[msg_count]):
|
||||
pwifi.kick()
|
||||
|
||||
speed = 500
|
||||
p.set_can_speed_kbps(0, speed)
|
||||
comp_kbps = time_many_sends(p, 0, pwifi, msg_count=msg_count, msg_id=0x100+i)
|
||||
saturation_pct = (comp_kbps/speed) * 100.0
|
||||
|
||||
if msg_count == 1:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
print("UDP WIFI loopback %d messages at speed %d, comp speed is %.2f, percent %.2f" % (msg_count, speed, comp_kbps, saturation_pct))
|
||||
assert_greater(saturation_pct, 40)
|
||||
assert_less(saturation_pct, 100)
|
||||
print("")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,669 @@
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import socket
|
||||
import select
|
||||
import pytest
|
||||
import struct
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
import elm_car_simulator
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", ".."))
|
||||
from panda import Panda
|
||||
|
||||
def elm_connect():
|
||||
s = socket.create_connection(("192.168.0.10", 35000))
|
||||
s.setblocking(0)
|
||||
return s
|
||||
|
||||
def read_or_fail(s):
|
||||
ready = select.select([s], [], [], 4)
|
||||
assert ready[0], "Socket did not receive data within the timeout duration."
|
||||
return s.recv(1000)
|
||||
|
||||
def sendrecv(s, dat):
|
||||
s.send(dat)
|
||||
return read_or_fail(s)
|
||||
|
||||
def send_compare(s, dat, ret, timeout=4):
|
||||
s.send(dat)
|
||||
res = b''
|
||||
while ret.startswith(res) and ret != res:
|
||||
print("Waiting")
|
||||
ready = select.select([s], [], [], timeout)
|
||||
if not ready[0]:
|
||||
print("current recv data:", repr(res))
|
||||
break;
|
||||
res += s.recv(1000)
|
||||
#print("final recv data: '%s'" % repr(res))
|
||||
assert ret == res#, "Data does not agree (%s) (%s)"%(repr(ret), repr(res))
|
||||
|
||||
def sync_reset(s):
|
||||
s.send("ATZ\r")
|
||||
res = b''
|
||||
while not res.endswith("ELM327 v1.5\r\r>"):
|
||||
res += read_or_fail(s)
|
||||
print("Reset response is '%s'" % repr(res))
|
||||
|
||||
def test_reset():
|
||||
s = socket.create_connection(("192.168.0.10", 35000))
|
||||
s.setblocking(0)
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
def test_elm_cli():
|
||||
s = elm_connect()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
|
||||
send_compare(s, b'ATI\r', b'ATI\rELM327 v1.5\r\r>')
|
||||
|
||||
#Test Echo Off
|
||||
#Expected to be misimplimentation, but this is how the reference device behaved.
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') #Here is the odd part
|
||||
send_compare(s, b'ATE0\r', b'OK\r\r>') #Should prob show this immediately
|
||||
send_compare(s, b'ATI\r', b'ELM327 v1.5\r\r>')
|
||||
|
||||
#Test Newline On
|
||||
send_compare(s, b'ATL1\r', b'OK\r\n\r\n>')
|
||||
send_compare(s, b'ATI\r', b'ELM327 v1.5\r\n\r\n>')
|
||||
send_compare(s, b'ATL0\r', b'OK\r\r>')
|
||||
send_compare(s, b'ATI\r', b'ELM327 v1.5\r\r>')
|
||||
|
||||
send_compare(s, b'ATI\r', b'ELM327 v1.5\r\r>') #Test repeat command no echo
|
||||
send_compare(s, b'\r', b'ELM327 v1.5\r\r>')
|
||||
|
||||
send_compare(s, b'aTi\r', b'ELM327 v1.5\r\r>') #Test different case
|
||||
|
||||
send_compare(s, b' a T i\r', b'ELM327 v1.5\r\r>') #Test with white space
|
||||
|
||||
send_compare(s, b'ATCATHAT\r', b'?\r\r>') #Test Invalid AT command
|
||||
|
||||
send_compare(s, b'01 00 00 00 00 00 00 00\r', b'?\r\r>') #Test Invalid (too long) OBD command
|
||||
send_compare(s, b'01 GZ\r', b'?\r\r>') #Test Invalid (Non hex chars) OBD command
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
def test_elm_setget_protocol():
|
||||
s = elm_connect()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>") # Set auto
|
||||
send_compare(s, b'ATDP\r', b"AUTO\r\r>")
|
||||
send_compare(s, b'ATDPN\r', b"A0\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP6\r', b"OK\r\r>") # Set protocol
|
||||
send_compare(s, b'ATDP\r', b"ISO 15765-4 (CAN 11/500)\r\r>")
|
||||
send_compare(s, b'ATDPN\r', b"6\r\r>")
|
||||
|
||||
send_compare(s, b'ATSPA6\r', b"OK\r\r>") # Set auto with protocol default
|
||||
send_compare(s, b'ATDP\r', b"AUTO, ISO 15765-4 (CAN 11/500)\r\r>")
|
||||
send_compare(s, b'ATDPN\r', b"A6\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP7\r', b"OK\r\r>")
|
||||
send_compare(s, b'ATDP\r', b"ISO 15765-4 (CAN 29/500)\r\r>")
|
||||
send_compare(s, b'ATDPN\r', b"7\r\r>") #Test Does not accept invalid protocols
|
||||
send_compare(s, b'ATSPD\r', b"?\r\r>")
|
||||
send_compare(s, b'ATDP\r', b"ISO 15765-4 (CAN 29/500)\r\r>")
|
||||
send_compare(s, b'ATDPN\r', b"7\r\r>")
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
def test_elm_protocol_failure():
|
||||
s = elm_connect()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>")
|
||||
send_compare(s, b'0100\r', b"SEARCHING...\rUNABLE TO CONNECT\r\r>", timeout=10)
|
||||
|
||||
send_compare(s, b'ATSP1\r', b"OK\r\r>")
|
||||
send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP2\r', b"OK\r\r>")
|
||||
send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP3\r', b"OK\r\r>")
|
||||
send_compare(s, b'0100\r', b"BUS INIT: ...ERROR\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP4\r', b"OK\r\r>")
|
||||
send_compare(s, b'0100\r', b"BUS INIT: ...ERROR\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP5\r', b"OK\r\r>")
|
||||
send_compare(s, b'0100\r', b"BUS INIT: ERROR\r\r>")
|
||||
|
||||
#send_compare(s, b'ATSP6\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
#
|
||||
#send_compare(s, b'ATSP7\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
#
|
||||
#send_compare(s, b'ATSP8\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
#
|
||||
#send_compare(s, b'ATSP9\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
#
|
||||
#send_compare(s, b'ATSPA\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
#
|
||||
#send_compare(s, b'ATSPB\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
#
|
||||
#send_compare(s, b'ATSPC\r', b"OK\r\r>")
|
||||
#send_compare(s, b'0100\r', b"NO DATA\r\r>")
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
def test_elm_protocol_autodetect_ISO14230_KWP_FAST():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, can=False)#, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATH0\r', b'OK\r\r>') # Headers ON
|
||||
send_compare(s, b'ATS0\r', b"OK\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>")
|
||||
send_compare(s, b'010D\r', b"SEARCHING...\r410D53\r\r>", timeout=10)
|
||||
send_compare(s, b'ATDPN\r', b"A5\r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_basic_send_lin():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, can=False)#, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATSP5\r', b"ATSP5\rOK\r\r>") # Set Proto
|
||||
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'0100\r', b"BUS INIT: OK\r41 00 FF FF FF FE \r\r>")
|
||||
send_compare(s, b'010D\r', b"41 0D 53 \r\r>")
|
||||
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces Off
|
||||
send_compare(s, b'0100\r', b"4100FFFFFFFE\r\r>")
|
||||
send_compare(s, b'010D\r', b"410D53\r\r>")
|
||||
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Spaces Off Headers On
|
||||
send_compare(s, b'0100\r', b"86F1104100FFFFFFFEC3\r\r>")
|
||||
send_compare(s, b'010D\r', b"83F110410D5325\r\r>")
|
||||
|
||||
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces On Headers On
|
||||
send_compare(s, b'0100\r', b"86 F1 10 41 00 FF FF FF FE C3 \r\r>")
|
||||
send_compare(s, b'010D\r', b"83 F1 10 41 0D 53 25 \r\r>")
|
||||
|
||||
send_compare(s, b'1F00\r', b"NO DATA\r\r>") # Unhandled msg, no response.
|
||||
|
||||
# Repeat last check to see if it still works after NO DATA was received
|
||||
send_compare(s, b'0100\r', b"86 F1 10 41 00 FF FF FF FE C3 \r\r>")
|
||||
send_compare(s, b'010D\r', b"83 F1 10 41 0D 53 25 \r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_send_lin_multiline_msg():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, can=False)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATSP5\r', b"OK\r\r>") # Set Proto
|
||||
|
||||
send_compare(s, b'0902\r', # headers OFF, Spaces ON
|
||||
b"BUS INIT: OK\r"
|
||||
"49 02 01 00 00 00 31 \r"
|
||||
"49 02 02 44 34 47 50 \r"
|
||||
"49 02 03 30 30 52 35 \r"
|
||||
"49 02 04 35 42 31 32 \r"
|
||||
"49 02 05 33 34 35 36 \r\r>")
|
||||
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'0902\r', # Headers OFF, Spaces OFF
|
||||
b"49020100000031\r"
|
||||
"49020244344750\r"
|
||||
"49020330305235\r"
|
||||
"49020435423132\r"
|
||||
"49020533343536\r\r>")
|
||||
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
|
||||
send_compare(s, b'0902\r', # Headers ON, Spaces OFF
|
||||
b"87F1104902010000003105\r"
|
||||
"87F11049020244344750E4\r"
|
||||
"87F11049020330305235BD\r"
|
||||
"87F11049020435423132B1\r"
|
||||
"87F11049020533343536AA\r\r>")
|
||||
|
||||
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces ON
|
||||
send_compare(s, b'0902\r', # Headers ON, Spaces ON
|
||||
b"87 F1 10 49 02 01 00 00 00 31 05 \r"
|
||||
"87 F1 10 49 02 02 44 34 47 50 E4 \r"
|
||||
"87 F1 10 49 02 03 30 30 52 35 BD \r"
|
||||
"87 F1 10 49 02 04 35 42 31 32 B1 \r"
|
||||
"87 F1 10 49 02 05 33 34 35 36 AA \r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_send_lin_multiline_msg_throughput():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, can=False, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATSP5\r', b"ATSP5\rOK\r\r>") # Set Proto
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'ATH0\r', b'OK\r\r>') # Headers OFF
|
||||
|
||||
send_compare(s, b'09fc\r', # headers OFF, Spaces OFF
|
||||
b"BUS INIT: OK\r" +
|
||||
b''.join((b'49FC' + hex(num+1)[2:].upper().zfill(2) +
|
||||
b'AAAA' + hex(num+1)[2:].upper().zfill(4) + b'\r'
|
||||
for num in range(80))) +
|
||||
b"\r>",
|
||||
timeout=10
|
||||
)
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_panda_safety_mode_KWPFast():
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
p_car = Panda(serial) # Configure this so the messages will send
|
||||
p_car.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p_car.kline_drain()
|
||||
|
||||
p_elm = Panda("WIFI")
|
||||
p_elm.set_safety_mode(0xE327);
|
||||
|
||||
def get_checksum(dat):
|
||||
result = 0
|
||||
result += sum(map(ord, dat)) if isinstance(b'dat', str) else sum(dat)
|
||||
return struct.pack("B", result % 0x100)
|
||||
|
||||
def timed_recv_check(p, bus, goodmsg):
|
||||
t = time.time()
|
||||
msg = bytearray()
|
||||
|
||||
while time.time()-t < 0.5 and len(msg) != len(goodmsg):
|
||||
msg += p._handle.controlRead(Panda.REQUEST_OUT, 0xe0, bus, 0, len(goodmsg)-len(msg))
|
||||
#print("Received", repr(msg))
|
||||
if msg == goodmsg:
|
||||
return True
|
||||
time.sleep(0.01)
|
||||
return False
|
||||
|
||||
def kline_send(p, x, bus=2):
|
||||
p.kline_drain(bus=bus)
|
||||
p._handle.bulkWrite(2, chr(bus).encode()+x)
|
||||
return timed_recv_check(p, bus, x)
|
||||
|
||||
def did_send(priority, toaddr, fromaddr, dat, bus=2, checkbyte=None):
|
||||
msgout = struct.pack("BBB", priority | len(dat), toaddr, fromaddr) + dat
|
||||
msgout += get_checksum(msgout) if checkbyte is None else checkbyte
|
||||
print("Sending", hex(priority), hex(toaddr), hex(fromaddr), repr(msgout))
|
||||
|
||||
if not kline_send(p_elm, msgout, bus=bus):
|
||||
return False
|
||||
return timed_recv_check(p_car, bus, msgout)
|
||||
|
||||
assert not did_send(0xC0, 0x33, 0xF1, b'\x01\x0F', bus=3) #wrong bus
|
||||
assert not did_send(0xC0, 0x33, 0xF1, b'') #wrong length
|
||||
assert not did_send(0xB0, 0x33, 0xF1, b'\x01\x0E') #bad priority
|
||||
assert not did_send(0xC0, 0x00, 0xF1, b'\x01\x0D') #bad addr
|
||||
assert not did_send(0xC0, 0x33, 0x00, b'\x01\x0C') #bad addr
|
||||
|
||||
assert did_send(0xC0, 0x33, 0xF1, b'\x01\x0B') #good! (obd func req)
|
||||
|
||||
def test_elm_lin_keepalive():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, can=False, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATSP5\r', b"ATSP5\rOK\r\r>") # Set Proto
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'ATH0\r', b'OK\r\r>') # Headers OFF
|
||||
|
||||
send_compare(s, b'0100\r', b"BUS INIT: OK\r4100FFFFFFFE\r\r>")
|
||||
assert sim.lin_active
|
||||
time.sleep(6)
|
||||
assert sim.lin_active
|
||||
|
||||
send_compare(s, b'ATPC\r', b"OK\r\r>") #STOP KEEPALIVE
|
||||
assert sim.lin_active
|
||||
time.sleep(6)
|
||||
assert not sim.lin_active
|
||||
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
#////////////
|
||||
def test_elm_protocol_autodetect_ISO15765():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
|
||||
send_compare(s, b'ATS0\r', b"OK\r\r>")
|
||||
|
||||
sim.can_mode_11b()
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>")
|
||||
send_compare(s, b'010D\r', b"SEARCHING...\r7E803410D53\r\r>", timeout=10)
|
||||
send_compare(s, b'ATDPN\r', b"A6\r\r>")
|
||||
|
||||
sim.can_mode_29b()
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>")
|
||||
send_compare(s, b'010D\r', b"SEARCHING...\r18DAF11003410D53\r\r>", timeout=10)
|
||||
send_compare(s, b'ATDPN\r', b"A7\r\r>")
|
||||
|
||||
sim.change_can_baud(250)
|
||||
|
||||
sim.can_mode_11b()
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>")
|
||||
send_compare(s, b'010D\r', b"SEARCHING...\r7E803410D53\r\r>", timeout=10)
|
||||
send_compare(s, b'ATDPN\r', b"A8\r\r>")
|
||||
|
||||
sim.can_mode_29b()
|
||||
send_compare(s, b'ATSP0\r', b"OK\r\r>")
|
||||
send_compare(s, b'010D\r', b"SEARCHING...\r18DAF11003410D53\r\r>", timeout=10)
|
||||
send_compare(s, b'ATDPN\r', b"A9\r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_basic_send_can():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATSP6\r', b"ATSP6\rOK\r\r>") # Set Proto
|
||||
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'0100\r', b"41 00 FF FF FF FE \r\r>")
|
||||
send_compare(s, b'010D\r', b"41 0D 53 \r\r>")
|
||||
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces Off
|
||||
send_compare(s, b'0100\r', b"4100FFFFFFFE\r\r>")
|
||||
send_compare(s, b'010D\r', b"410D53\r\r>")
|
||||
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Spaces Off Headers On
|
||||
send_compare(s, b'0100\r', b"7E8064100FFFFFFFE\r\r>")
|
||||
send_compare(s, b'010D\r', b"7E803410D53\r\r>")
|
||||
|
||||
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces On Headers On
|
||||
send_compare(s, b'0100\r', b"7E8 06 41 00 FF FF FF FE \r\r>")
|
||||
send_compare(s, b'010D\r', b"7E8 03 41 0D 53 \r\r>")
|
||||
|
||||
send_compare(s, b'1F00\r', b"NO DATA\r\r>") # Unhandled msg, no response.
|
||||
|
||||
# Repeat last check to see if it still works after NO DATA was received
|
||||
send_compare(s, b'0100\r', b"7E8 06 41 00 FF FF FF FE \r\r>")
|
||||
send_compare(s, b'010D\r', b"7E8 03 41 0D 53 \r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_send_can_multimsg():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
|
||||
|
||||
send_compare(s, b'ATSP6\r', b"OK\r\r>") # Set Proto ISO 15765-4 (CAN 11/500)
|
||||
sim.can_add_extra_noise(b'\x03\x41\x0D\xFA', addr=0x7E9)# Inject message into the stream
|
||||
send_compare(s, b'010D\r',
|
||||
b"7E8 03 41 0D 53 \r"
|
||||
"7E9 03 41 0D FA \r\r>") # Check it was ignored.
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
"""The ability to correctly filter out messages with the wrong PID is not
|
||||
implemented correctly in the reference device."""
|
||||
def test_elm_can_check_mode_pid():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'ATH0\r', b'OK\r\r>') # Headers OFF
|
||||
|
||||
send_compare(s, b'ATSP6\r', b"OK\r\r>") # Set Proto ISO 15765-4 (CAN 11/500)
|
||||
sim.can_add_extra_noise(b'\x03\x41\x0E\xFA')# Inject message into the stream
|
||||
send_compare(s, b'010D\r', b"410D53\r\r>") # Check it was ignored.
|
||||
send_compare(s, b'0100\r', b"4100FFFFFFFE\r\r>") # Check it was ignored again.
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_send_can_multiline_msg():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATSP6\r', b"ATSP6\rOK\r\r>") # Set Proto
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
|
||||
send_compare(s, b'0902\r', # headers OFF, Spaces ON
|
||||
b"014 \r"
|
||||
"0: 49 02 01 31 44 34 \r"
|
||||
"1: 47 50 30 30 52 35 35 \r"
|
||||
"2: 42 31 32 33 34 35 36 \r\r>")
|
||||
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'0902\r', # Headers OFF, Spaces OFF
|
||||
b"014\r"
|
||||
"0:490201314434\r"
|
||||
"1:47503030523535\r"
|
||||
"2:42313233343536\r\r>")
|
||||
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
|
||||
send_compare(s, b'0902\r', # Headers ON, Spaces OFF
|
||||
b"7E81014490201314434\r"
|
||||
"7E82147503030523535\r"
|
||||
"7E82242313233343536\r\r>")
|
||||
|
||||
send_compare(s, b'ATS1\r', b'OK\r\r>') # Spaces ON
|
||||
send_compare(s, b'0902\r', # Headers ON, Spaces ON
|
||||
b"7E8 10 14 49 02 01 31 44 34 \r"
|
||||
"7E8 21 47 50 30 30 52 35 35 \r"
|
||||
"7E8 22 42 31 32 33 34 35 36 \r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_send_can_multiline_msg_throughput():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATSP6\r', b"ATSP6\rOK\r\r>") # Set Proto
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
|
||||
|
||||
rows = 584
|
||||
send_compare(s, b'09ff\r', # headers ON, Spaces OFF
|
||||
("7E8" + "1" + hex((rows*7)+6)[2:].upper().zfill(3) + "49FF01"+"AA0000\r" +
|
||||
"".join(
|
||||
("7E82"+hex((num+1)%0x10)[2:].upper()+("AA"*5) +
|
||||
hex(num+1)[2:].upper().zfill(4) + "\r" for num in range(rows))
|
||||
) + "\r>").encode(),
|
||||
timeout=10
|
||||
)
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_interrupted_obd_cmd_resets_state():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False, silent=True)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
s.send(b"09fd\r")
|
||||
ready = select.select([s], [], [], 4)
|
||||
assert ready[0], "Socket did not receive data within the timeout duration."
|
||||
s.send(b"ATI\r")
|
||||
|
||||
assert b"236\r0:49FD01AAAAAA\r" in s.recv(10000)
|
||||
|
||||
#Will likely have to be improved to scan for STOPPED if the FW gets more responsive.
|
||||
ready = select.select([s], [], [], 4)
|
||||
assert ready[0], "Socket did not receive data within the timeout duration."
|
||||
|
||||
assert b"STOPPED" in s.recv(10000)
|
||||
|
||||
sim.set_enable(False)
|
||||
send_compare(s, b'09fd\r', b"NO DATA\r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_can_baud():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
sim = elm_car_simulator.ELMCarSimulator(serial, lin=False)
|
||||
sim.start()
|
||||
|
||||
try:
|
||||
sync_reset(s)
|
||||
send_compare(s, b'ATE0\r', b'ATE0\rOK\r\r>') # Echo OFF
|
||||
send_compare(s, b'ATS0\r', b'OK\r\r>') # Spaces OFF
|
||||
send_compare(s, b'ATH1\r', b'OK\r\r>') # Headers ON
|
||||
|
||||
send_compare(s, b'ATSP6\r', b"OK\r\r>") # Set Proto ISO 15765-4 (CAN 11/500)
|
||||
send_compare(s, b'0100\r', b"7E8064100FFFFFFFE\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP8\r', b"OK\r\r>") # Set Proto ISO 15765-4 (CAN 11/250)
|
||||
send_compare(s, b'0100\r', b"CAN ERROR\r\r>")
|
||||
|
||||
sim.change_can_baud(250)
|
||||
|
||||
send_compare(s, b'ATSP6\r', b"OK\r\r>") # Set Proto ISO 15765-4 (CAN 11/500)
|
||||
send_compare(s, b'0100\r', b"CAN ERROR\r\r>")
|
||||
|
||||
send_compare(s, b'ATSP8\r', b"OK\r\r>") # Set Proto ISO 15765-4 (CAN 11/250)
|
||||
send_compare(s, b'0100\r', b"7E8064100FFFFFFFE\r\r>")
|
||||
finally:
|
||||
sim.stop()
|
||||
sim.join()
|
||||
s.close()
|
||||
|
||||
def test_elm_panda_safety_mode_ISO15765():
|
||||
s = elm_connect()
|
||||
serial = os.getenv("CANSIMSERIAL") if os.getenv("CANSIMSERIAL") else None
|
||||
p_car = Panda(serial) # Configure this so the messages will send
|
||||
p_car.set_can_speed_kbps(0, 500)
|
||||
p_car.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
p_elm = Panda("WIFI")
|
||||
p_elm.set_safety_mode(0xE327);
|
||||
|
||||
#sim = elm_car_simulator.ELMCarSimulator(serial, lin=False)
|
||||
#sim.start()
|
||||
|
||||
def did_send(p, addr, dat, bus):
|
||||
p.can_send(addr, dat, bus)
|
||||
t = time.time()
|
||||
while time.time()-t < 0.5:
|
||||
msg = p.can_recv()
|
||||
for addrin, _, datin, busin in msg:
|
||||
if (0x80 | bus) == busin and addr == addrin and datin == dat:
|
||||
return True
|
||||
time.sleep(0.01)
|
||||
return False
|
||||
|
||||
try:
|
||||
sync_reset(s) # Reset elm (which requests the ELM327 safety mode)
|
||||
|
||||
#29 bit
|
||||
assert not did_send(p_elm, 0x18DB33F1, b'\x02\x01\x00\x00\x00\x00\x00\x00', 1) #wrong canid
|
||||
assert not did_send(p_elm, 0x18DB33F1, b'\x02\x01\x00', 0) #wrong length
|
||||
assert not did_send(p_elm, 0x10000000, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr
|
||||
assert not did_send(p_elm, 0x18DAF133, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr (phy addr)
|
||||
assert not did_send(p_elm, 0x18DAF000, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr
|
||||
assert not did_send(p_elm, 0x18DAF1F3, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr! (phys rsp to elm)
|
||||
|
||||
assert did_send(p_elm, 0x18DB33F1, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #good! (obd func req)
|
||||
assert did_send(p_elm, 0x18DA10F1, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #good! (phys response)
|
||||
|
||||
#11 bit
|
||||
assert not did_send(p_elm, 0X7DF, b'\x02\x01\x00\x00\x00\x00\x00\x00', 1) #wrong canid
|
||||
assert not did_send(p_elm, 0X7DF, b'\x02\x01\x00', 0) #wrong length
|
||||
assert not did_send(p_elm, 0xAA, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr
|
||||
assert not did_send(p_elm, 0x7DA, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr (phy addr)
|
||||
assert not did_send(p_elm, 0x7E8, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #bad addr (sending 'response')
|
||||
|
||||
assert did_send(p_elm, 0x7DF, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #good! (obd func req)
|
||||
assert did_send(p_elm, 0x7E1, b'\x02\x01\x00\x00\x00\x00\x00\x00', 0) #good! (phys response)
|
||||
|
||||
finally:
|
||||
s.close()
|
||||
@@ -0,0 +1,75 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import random
|
||||
import subprocess
|
||||
from panda import Panda
|
||||
from nose.tools import timed, assert_equal, assert_less, assert_greater
|
||||
|
||||
def connect_wo_esp():
|
||||
# connect to the panda
|
||||
p = Panda()
|
||||
|
||||
# power down the ESP
|
||||
p.set_esp_power(False)
|
||||
|
||||
# clear old junk
|
||||
while len(p.can_recv()) > 0:
|
||||
pass
|
||||
|
||||
return p
|
||||
|
||||
def connect_wifi():
|
||||
p = Panda()
|
||||
dongle_id, pw = p.get_serial()
|
||||
assert(dongle_id.isalnum())
|
||||
_connect_wifi(dongle_id, pw)
|
||||
|
||||
def _connect_wifi(dongle_id, pw):
|
||||
ssid = str("panda-" + dongle_id)
|
||||
|
||||
print("WIFI: connecting to %s" % ssid)
|
||||
|
||||
if sys.platform == "darwin":
|
||||
os.system("networksetup -setairportnetwork en0 %s %s" % (ssid, pw))
|
||||
else:
|
||||
cnt = 0
|
||||
MAX_TRIES = 10
|
||||
while cnt < MAX_TRIES:
|
||||
print "WIFI: scanning %d" % cnt
|
||||
os.system("nmcli device wifi rescan")
|
||||
wifi_scan = filter(lambda x: ssid in x, subprocess.check_output(["nmcli","dev", "wifi", "list"]).split("\n"))
|
||||
if len(wifi_scan) != 0:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
# MAX_TRIES tries, ~10 seconds max
|
||||
cnt += 1
|
||||
assert cnt < MAX_TRIES
|
||||
os.system("nmcli d wifi connect %s password %s" % (ssid, pw))
|
||||
|
||||
# TODO: confirm that it's connected to the right panda
|
||||
|
||||
def time_many_sends(p, bus, precv=None, msg_count=100, msg_id=None):
|
||||
if precv == None:
|
||||
precv = p
|
||||
if msg_id == None:
|
||||
msg_id = random.randint(0x100, 0x200)
|
||||
|
||||
st = time.time()
|
||||
p.can_send_many([(msg_id, 0, "\xaa"*8, bus)]*msg_count)
|
||||
r = []
|
||||
|
||||
while len(r) < (msg_count*2) and (time.time() - st) < 3:
|
||||
r.extend(precv.can_recv())
|
||||
|
||||
sent_echo = filter(lambda x: x[3] == 0x80 | bus and x[0] == msg_id, r)
|
||||
loopback_resp = filter(lambda x: x[3] == bus and x[0] == msg_id, r)
|
||||
|
||||
assert_equal(len(sent_echo), msg_count)
|
||||
assert_equal(len(loopback_resp), msg_count)
|
||||
|
||||
et = (time.time()-st)*1000.0
|
||||
comp_kbps = (1+11+1+1+1+4+8*8+15+1+1+1+7)*msg_count / et
|
||||
|
||||
return comp_kbps
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
from panda import Panda
|
||||
|
||||
# fake
|
||||
def sec_since_boot():
|
||||
return time.time()
|
||||
|
||||
def can_printer():
|
||||
p = Panda()
|
||||
|
||||
start = sec_since_boot()
|
||||
lp = sec_since_boot()
|
||||
msgs = defaultdict(list)
|
||||
canbus = int(os.getenv("CAN", 0))
|
||||
while True:
|
||||
can_recv = p.can_recv()
|
||||
for address, _, dat, src in can_recv:
|
||||
if src == canbus:
|
||||
msgs[address].append(dat)
|
||||
|
||||
if sec_since_boot() - lp > 0.1:
|
||||
dd = chr(27) + "[2J"
|
||||
dd += "%5.2f\n" % (sec_since_boot() - start)
|
||||
for k,v in sorted(zip(msgs.keys(), map(lambda x: x[-1].encode("hex"), msgs.values()))):
|
||||
dd += "%s(%6d) %s\n" % ("%04X(%4d)" % (k,k),len(msgs[k]), v)
|
||||
print(dd)
|
||||
lp = sec_since_boot()
|
||||
|
||||
if __name__ == "__main__":
|
||||
can_printer()
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import select
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
from panda import Panda
|
||||
|
||||
setcolor = ["\033[1;32;40m", "\033[1;31;40m"]
|
||||
unsetcolor = "\033[00m"
|
||||
|
||||
if __name__ == "__main__":
|
||||
port_number = int(os.getenv("PORT", 0))
|
||||
claim = os.getenv("CLAIM") is not None
|
||||
|
||||
serials = Panda.list()
|
||||
if os.getenv("SERIAL"):
|
||||
serials = filter(lambda x: x==os.getenv("SERIAL"), serials)
|
||||
|
||||
pandas = list(map(lambda x: Panda(x, claim=claim), serials))
|
||||
|
||||
if os.getenv("BAUD") is not None:
|
||||
for panda in pandas:
|
||||
panda.set_uart_baud(port_number, int(os.getenv("BAUD")))
|
||||
|
||||
while True:
|
||||
for i, panda in enumerate(pandas):
|
||||
while True:
|
||||
ret = panda.serial_read(port_number)
|
||||
if len(ret) > 0:
|
||||
sys.stdout.write(setcolor[i] + str(ret) + unsetcolor)
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
break
|
||||
if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
|
||||
ln = sys.stdin.readline()
|
||||
if claim:
|
||||
panda.serial_write(port_number, ln)
|
||||
time.sleep(0.01)
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from panda import Panda
|
||||
Panda().set_esp_power(False)
|
||||
|
||||
Executable
+325
@@ -0,0 +1,325 @@
|
||||
#!/usr/bin/env python
|
||||
"""Used to Reverse/Test ELM protocol auto detect and OBD message response without a car."""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import os
|
||||
import struct
|
||||
import binascii
|
||||
import time
|
||||
import threading
|
||||
from collections import deque
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
from panda import Panda
|
||||
|
||||
def lin_checksum(dat):
|
||||
return sum(dat) % 0x100
|
||||
|
||||
class ELMCarSimulator():
|
||||
def __init__(self, sn, silent=False, can_kbaud=500,
|
||||
can=True, can11b=True, can29b=True,
|
||||
lin=True):
|
||||
self.__p = Panda(sn if sn else Panda.list()[0])
|
||||
self.__on = True
|
||||
self.__stop = False
|
||||
self.__silent = silent
|
||||
|
||||
self.__lin_timer = None
|
||||
self.__lin_active = False
|
||||
self.__lin_enable = lin
|
||||
self.__lin_monitor_thread = threading.Thread(target=self.__lin_monitor)
|
||||
|
||||
self.__can_multipart_data = None
|
||||
self.__can_kbaud = can_kbaud
|
||||
self.__can_extra_noise_msgs = deque()
|
||||
self.__can_enable = can
|
||||
self.__can11b = can11b
|
||||
self.__can29b = can29b
|
||||
self.__can_monitor_thread = threading.Thread(target=self.__can_monitor)
|
||||
|
||||
@property
|
||||
def panda(self):
|
||||
return self.__p
|
||||
|
||||
def stop(self):
|
||||
if self.__lin_timer:
|
||||
self.__lin_timer.cancel()
|
||||
self.__lin_timeout_handler()
|
||||
|
||||
self.__stop = True
|
||||
|
||||
def join(self):
|
||||
if self.__lin_monitor_thread.is_alive():
|
||||
self.__lin_monitor_thread.join()
|
||||
if self.__can_monitor_thread.is_alive():
|
||||
self.__can_monitor_thread.join()
|
||||
if self.__p:
|
||||
print("closing handle")
|
||||
self.__p.close()
|
||||
|
||||
def set_enable(self, on):
|
||||
self.__on = on
|
||||
|
||||
def start(self):
|
||||
self.panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
if self.__lin_enable:
|
||||
self.__lin_monitor_thread.start()
|
||||
if self.__can_enable:
|
||||
self.__can_monitor_thread.start()
|
||||
|
||||
#########################
|
||||
# LIN related functions #
|
||||
#########################
|
||||
|
||||
def __lin_monitor(self):
|
||||
print("STARTING LIN THREAD")
|
||||
self.panda.set_uart_baud(2, 10400)
|
||||
self.panda.kline_drain() # Toss whatever was already there
|
||||
|
||||
lin_buff = bytearray()
|
||||
|
||||
while not self.__stop:
|
||||
lin_msg = self.panda.serial_read(2)
|
||||
if not lin_msg:
|
||||
continue
|
||||
|
||||
lin_buff += lin_msg
|
||||
#print(" ** Buff", lin_buff)
|
||||
if lin_buff.endswith(b'\x00\xc1\x33\xf1\x81\x66'): # Leading 0 is wakeup
|
||||
lin_buff = bytearray()
|
||||
self.__lin_active = True
|
||||
print("GOT LIN (KWP FAST) WAKEUP SIGNAL")
|
||||
self._lin_send(0x10, b'\xC1\x8F\xE9')
|
||||
self.__reset_lin_timeout()
|
||||
continue
|
||||
if self.__lin_active:
|
||||
msglen = lin_buff[0] & 0x7
|
||||
if lin_buff[0] & 0xF8 not in (0x80, 0xC0):
|
||||
print("Invalid bytes at start of message")
|
||||
print(" BUFF", lin_buff)
|
||||
continue
|
||||
if len(lin_buff) < msglen + 4: continue
|
||||
if lin_checksum(lin_buff[:-1]) != lin_buff[-1]: continue
|
||||
self.__lin_process_msg(lin_buff[0] & 0xF8, #Priority
|
||||
lin_buff[1], lin_buff[2], lin_buff[3:-1])
|
||||
lin_buff = bytearray()
|
||||
|
||||
def _lin_send(self, to_addr, msg):
|
||||
if not self.__silent:
|
||||
print(" LIN Reply (%x)" % to_addr, binascii.hexlify(msg))
|
||||
|
||||
PHYS_ADDR = 0x80
|
||||
FUNC_ADDR = 0xC0
|
||||
RECV = 0xF1
|
||||
SEND = 0x33 # Car OBD Functional Address
|
||||
headers = struct.pack("BBB", PHYS_ADDR | len(msg), RECV, to_addr)
|
||||
if not self.__silent:
|
||||
print(" Sending LIN", binascii.hexlify(headers+msg),
|
||||
hex(sum(bytearray(headers+msg))%0x100))
|
||||
self.panda.kline_send(headers + msg)
|
||||
|
||||
def __reset_lin_timeout(self):
|
||||
if self.__lin_timer:
|
||||
self.__lin_timer.cancel()
|
||||
self.__lin_timer = threading.Timer(5, self.__lin_timeout_handler)
|
||||
self.__lin_timer.start()
|
||||
|
||||
def __lin_timeout_handler(self):
|
||||
print("LIN TIMEOUT")
|
||||
self.__lin_timer = None
|
||||
self.__lin_active = False
|
||||
|
||||
@property
|
||||
def lin_active(self):
|
||||
return self.__lin_active
|
||||
|
||||
def __lin_process_msg(self, priority, toaddr, fromaddr, data):
|
||||
self.__reset_lin_timeout()
|
||||
|
||||
if not self.__silent and data != b'\x3E':
|
||||
print("LIN MSG", "Addr:", hex(toaddr), "obdLen:", len(data),
|
||||
binascii.hexlify(data))
|
||||
|
||||
outmsg = None
|
||||
#if data == b'\x3E':
|
||||
# print("KEEP ALIVE")
|
||||
#el
|
||||
if len(data) > 1:
|
||||
outmsg = self._process_obd(data[0], data[1])
|
||||
|
||||
if outmsg:
|
||||
obd_header = struct.pack("BB", 0x40 | data[0], data[1])
|
||||
if len(outmsg) <= 5:
|
||||
self._lin_send(0x10, obd_header + outmsg)
|
||||
else:
|
||||
first_msg_len = min(4, len(outmsg)%4) or 4
|
||||
self._lin_send(0x10, obd_header + b'\x01' +
|
||||
b'\x00'*(4-first_msg_len) +
|
||||
outmsg[:first_msg_len])
|
||||
|
||||
for num, i in enumerate(range(first_msg_len, len(outmsg), 4)):
|
||||
self._lin_send(0x10, obd_header +
|
||||
struct.pack('B', (num+2)%0x100) + outmsg[i:i+4])
|
||||
|
||||
#########################
|
||||
# CAN related functions #
|
||||
#########################
|
||||
|
||||
def __can_monitor(self):
|
||||
print("STARTING CAN THREAD")
|
||||
self.panda.set_can_speed_kbps(0, self.__can_kbaud)
|
||||
self.panda.can_recv() # Toss whatever was already there
|
||||
|
||||
while not self.__stop:
|
||||
for address, ts, data, src in self.panda.can_recv():
|
||||
if self.__on and src is 0 and len(data) == 8 and data[0] >= 2:
|
||||
if not self.__silent:
|
||||
print("Processing CAN message", src, hex(address), binascii.hexlify(data))
|
||||
self.__can_process_msg(data[1], data[2], address, ts, data, src)
|
||||
elif not self.__silent:
|
||||
print("Rejecting CAN message", src, hex(address), binascii.hexlify(data))
|
||||
|
||||
def can_mode_11b(self):
|
||||
self.__can11b = True
|
||||
self.__can29b = False
|
||||
|
||||
def can_mode_29b(self):
|
||||
self.__can11b = False
|
||||
self.__can29b = True
|
||||
|
||||
def can_mode_11b_29b(self):
|
||||
self.__can11b = True
|
||||
self.__can29b = True
|
||||
|
||||
def change_can_baud(self, kbaud):
|
||||
self.__can_kbaud = kbaud
|
||||
self.panda.set_can_speed_kbps(0, self.__can_kbaud)
|
||||
|
||||
def can_add_extra_noise(self, noise_msg, addr=None):
|
||||
self.__can_extra_noise_msgs.append((addr, noise_msg))
|
||||
|
||||
def _can_send(self, addr, msg):
|
||||
if not self.__silent:
|
||||
print(" CAN Reply (%x)" % addr, binascii.hexlify(msg))
|
||||
self.panda.can_send(addr, msg + b'\x00'*(8-len(msg)), 0)
|
||||
if self.__can_extra_noise_msgs:
|
||||
noise = self.__can_extra_noise_msgs.popleft()
|
||||
self.panda.can_send(noise[0] if noise[0] is not None else addr,
|
||||
noise[1] + b'\x00'*(8-len(noise[1])), 0)
|
||||
|
||||
def _can_addr_matches(self, addr):
|
||||
if self.__can11b and (addr == 0x7DF or (addr & 0x7F8) == 0x7E0):
|
||||
return True
|
||||
if self.__can29b and (addr == 0x18db33f1 or (addr & 0x1FFF00FF) == 0x18da00f1):
|
||||
return True
|
||||
return False
|
||||
|
||||
def __can_process_msg(self, mode, pid, address, ts, data, src):
|
||||
if not self.__silent:
|
||||
print("CAN MSG", binascii.hexlify(data[1:1+data[0]]),
|
||||
"Addr:", hex(address), "Mode:", hex(mode)[2:].zfill(2),
|
||||
"PID:", hex(pid)[2:].zfill(2), "canLen:", len(data),
|
||||
binascii.hexlify(data))
|
||||
|
||||
if self._can_addr_matches(address) and len(data) == 8:
|
||||
outmsg = None
|
||||
if data[:3] == b'\x30\x00\x00' and len(self.__can_multipart_data):
|
||||
if not self.__silent:
|
||||
print("Request for more data");
|
||||
outaddr = 0x7E8 if address == 0x7DF or address == 0x7E0 else 0x18DAF110
|
||||
msgnum = 1
|
||||
while(self.__can_multipart_data):
|
||||
datalen = min(7, len(self.__can_multipart_data))
|
||||
msgpiece = struct.pack("B", 0x20 | msgnum) + self.__can_multipart_data[:datalen]
|
||||
self._can_send(outaddr, msgpiece)
|
||||
self.__can_multipart_data = self.__can_multipart_data[7:]
|
||||
msgnum = (msgnum+1)%0x10
|
||||
time.sleep(0.01)
|
||||
|
||||
else:
|
||||
outmsg = self._process_obd(mode, pid)
|
||||
|
||||
if outmsg:
|
||||
outaddr = 0x7E8 if address == 0x7DF or address == 0x7E0 else 0x18DAF110
|
||||
|
||||
if len(outmsg) <= 5:
|
||||
self._can_send(outaddr,
|
||||
struct.pack("BBB", len(outmsg)+2, 0x40|data[1], pid) + outmsg)
|
||||
else:
|
||||
first_msg_len = min(3, len(outmsg)%7)
|
||||
payload_len = len(outmsg)+3
|
||||
msgpiece = struct.pack("BBBBB", 0x10 | ((payload_len>>8)&0xF),
|
||||
payload_len&0xFF,
|
||||
0x40|data[1], pid, 1) + outmsg[:first_msg_len]
|
||||
self._can_send(outaddr, msgpiece)
|
||||
self.__can_multipart_data = outmsg[first_msg_len:]
|
||||
|
||||
#########################
|
||||
# General OBD functions #
|
||||
#########################
|
||||
|
||||
def _process_obd(self, mode, pid):
|
||||
if mode == 0x01: # Mode: Show current data
|
||||
if pid == 0x00: #List supported things
|
||||
return b"\xff\xff\xff\xfe"#b"\xBE\x1F\xB8\x10" #Bitfield, random features
|
||||
elif pid == 0x01: # Monitor Status since DTC cleared
|
||||
return b"\x00\x00\x00\x00" #Bitfield, random features
|
||||
elif pid == 0x04: # Calculated engine load
|
||||
return b"\x2f"
|
||||
elif pid == 0x05: # Engine coolant temperature
|
||||
return b"\x3c"
|
||||
elif pid == 0x0B: # Intake manifold absolute pressure
|
||||
return b"\x90"
|
||||
elif pid == 0x0C: # Engine RPM
|
||||
return b"\x1A\xF8"
|
||||
elif pid == 0x0D: # Vehicle Speed
|
||||
return b"\x53"
|
||||
elif pid == 0x10: # MAF air flow rate
|
||||
return b"\x01\xA0"
|
||||
elif pid == 0x11: # Throttle Position
|
||||
return b"\x90"
|
||||
elif pid == 0x33: # Absolute Barometric Pressure
|
||||
return b"\x90"
|
||||
elif mode == 0x09: # Mode: Request vehicle information
|
||||
if pid == 0x02: # Show VIN
|
||||
return b"1D4GP00R55B123456"
|
||||
if pid == 0xFC: # test long multi message. Ligned up for LIN responses
|
||||
return b''.join((struct.pack(">BBH", 0xAA, 0xAA, num+1) for num in range(80)))
|
||||
if pid == 0xFD: # test long multi message
|
||||
parts = (b'\xAA\xAA\xAA' + struct.pack(">I", num) for num in range(80))
|
||||
return b'\xAA\xAA\xAA' + b''.join(parts)
|
||||
if pid == 0xFE: # test very long multi message
|
||||
parts = (b'\xAA\xAA\xAA' + struct.pack(">I", num) for num in range(584))
|
||||
return b'\xAA\xAA\xAA' + b''.join(parts) + b'\xAA'
|
||||
if pid == 0xFF:
|
||||
return b'\xAA\x00\x00' +\
|
||||
b"".join(((b'\xAA'*5)+struct.pack(">H", num+1) for num in range(584)))
|
||||
#return b"\xAA"*100#(0xFFF-3)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
serial = os.getenv("SERIAL") if os.getenv("SERIAL") else None
|
||||
kbaud = int(os.getenv("CANKBAUD")) if os.getenv("CANKBAUD") else 500
|
||||
bitwidth = int(os.getenv("CANBITWIDTH")) if os.getenv("CANBITWIDTH") else 0
|
||||
canenable = bool(int(os.getenv("CANENABLE"))) if os.getenv("CANENABLE") else True
|
||||
linenable = bool(int(os.getenv("LINENABLE"))) if os.getenv("LINENABLE") else True
|
||||
sim = ELMCarSimulator(serial, can_kbaud=kbaud, can=canenable, lin=linenable)
|
||||
if(bitwidth == 0):
|
||||
sim.can_mode_11b_29b()
|
||||
if(bitwidth == 11):
|
||||
sim.can_mode_11b()
|
||||
if(bitwidth == 29):
|
||||
sim.can_mode_29b()
|
||||
|
||||
import signal
|
||||
def signal_handler(signal, frame):
|
||||
print('\nShutting down simulator')
|
||||
sim.stop()
|
||||
sim.join()
|
||||
sys.exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
sim.start()
|
||||
|
||||
signal.pause()
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import socket
|
||||
import threading
|
||||
import select
|
||||
|
||||
class Reader(threading.Thread):
|
||||
def __init__(self, s, *args, **kwargs):
|
||||
super(Reader, self).__init__(*args, **kwargs)
|
||||
self._s = s
|
||||
self.__stop = False
|
||||
|
||||
def stop(self):
|
||||
self.__stop = True
|
||||
|
||||
def run(self):
|
||||
while not self.__stop:
|
||||
s.recv(1000)
|
||||
|
||||
def read_or_fail(s):
|
||||
ready = select.select([s], [], [], 4)
|
||||
assert ready[0], "Socket did not receive data within the timeout duration."
|
||||
return s.recv(1000)
|
||||
|
||||
def send_msg(s, msg):
|
||||
s.send(msg)
|
||||
res = b''
|
||||
while not res.endswith(">"):
|
||||
res += read_or_fail(s)
|
||||
return res
|
||||
|
||||
if __name__ == "__main__":
|
||||
s = socket.create_connection(("192.168.0.10", 35000))
|
||||
#t1 = Reader(s)
|
||||
#t1.start()
|
||||
send_msg(s, b"ATZ\r")
|
||||
send_msg(s, b"ATL1\r")
|
||||
print(send_msg(s, b"ATE0\r"))
|
||||
print(send_msg(s, b"ATS0\r"))
|
||||
print(send_msg(s, b"ATSP6\r"))
|
||||
|
||||
print("\nLOOP\n")
|
||||
|
||||
while True:
|
||||
print(send_msg(s, b"0100\r"))
|
||||
print(send_msg(s, b"010d\r"))
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
cd ../board
|
||||
make clean
|
||||
|
||||
while true; do
|
||||
make ota
|
||||
sleep 10
|
||||
done
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
from panda import Panda
|
||||
|
||||
if __name__ == "__main__":
|
||||
for p in Panda.list():
|
||||
pp = Panda(p)
|
||||
print("%s: %s" % (pp.get_serial()[0], pp.get_version()))
|
||||
|
||||
|
||||
Executable
+127
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import random
|
||||
import argparse
|
||||
|
||||
from hexdump import hexdump
|
||||
from itertools import permutations
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
from panda import Panda
|
||||
|
||||
def get_test_string():
|
||||
return b"test"+os.urandom(10)
|
||||
|
||||
def run_test(sleep_duration):
|
||||
pandas = Panda.list()
|
||||
print(pandas)
|
||||
|
||||
if len(pandas) == 0:
|
||||
print("NO PANDAS")
|
||||
assert False
|
||||
|
||||
if len(pandas) == 1:
|
||||
# if we only have one on USB, assume the other is on wifi
|
||||
pandas.append("WIFI")
|
||||
run_test_w_pandas(pandas, sleep_duration)
|
||||
|
||||
def run_test_w_pandas(pandas, sleep_duration):
|
||||
h = list(map(lambda x: Panda(x), pandas))
|
||||
print("H", h)
|
||||
|
||||
for hh in h:
|
||||
hh.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# test both directions
|
||||
for ho in permutations(range(len(h)), r=2):
|
||||
print("***************** TESTING", ho)
|
||||
|
||||
panda0, panda1 = h[ho[0]], h[ho[1]]
|
||||
|
||||
if(panda0._serial == "WIFI"):
|
||||
print(" *** Can not send can data over wifi panda. Skipping! ***")
|
||||
continue
|
||||
|
||||
# **** test health packet ****
|
||||
print("health", ho[0], h[ho[0]].health())
|
||||
|
||||
# **** test K/L line loopback ****
|
||||
for bus in [2,3]:
|
||||
# flush the output
|
||||
h[ho[1]].kline_drain(bus=bus)
|
||||
|
||||
# send the characters
|
||||
st = get_test_string()
|
||||
st = b"\xaa"+chr(len(st)+3).encode()+st
|
||||
h[ho[0]].kline_send(st, bus=bus, checksum=False)
|
||||
|
||||
# check for receive
|
||||
ret = h[ho[1]].kline_drain(bus=bus)
|
||||
|
||||
print("ST Data:")
|
||||
hexdump(st)
|
||||
print("RET Data:")
|
||||
hexdump(ret)
|
||||
assert st == ret
|
||||
print("K/L pass", bus, ho, "\n")
|
||||
time.sleep(sleep_duration)
|
||||
|
||||
# **** test can line loopback ****
|
||||
for bus, gmlan in [(0, False), (1, False), (2, False), (1, True), (2, True)]:
|
||||
print("\ntest can", bus)
|
||||
# flush
|
||||
cans_echo = panda0.can_recv()
|
||||
cans_loop = panda1.can_recv()
|
||||
|
||||
panda0.set_gmlan(None)
|
||||
panda1.set_gmlan(None)
|
||||
|
||||
if gmlan is True:
|
||||
panda0.set_gmlan(bus)
|
||||
panda1.set_gmlan(bus)
|
||||
bus = 3
|
||||
|
||||
# send the characters
|
||||
at = random.randint(1, 2000)
|
||||
st = get_test_string()[0:8]
|
||||
panda0.can_send(at, st, bus)
|
||||
time.sleep(0.1)
|
||||
|
||||
# check for receive
|
||||
cans_echo = panda0.can_recv()
|
||||
cans_loop = panda1.can_recv()
|
||||
|
||||
print("Bus", bus, "echo", cans_echo, "loop", cans_loop)
|
||||
|
||||
assert len(cans_echo) == 1
|
||||
assert len(cans_loop) == 1
|
||||
|
||||
assert cans_echo[0][0] == at
|
||||
assert cans_loop[0][0] == at
|
||||
|
||||
assert cans_echo[0][2] == st
|
||||
assert cans_loop[0][2] == st
|
||||
|
||||
assert cans_echo[0][3] == 0x80 | bus
|
||||
if cans_loop[0][3] != bus:
|
||||
print("EXPECTED %d GOT %d" % (bus, cans_loop[0][3]))
|
||||
assert cans_loop[0][3] == bus
|
||||
|
||||
print("CAN pass", bus, ho)
|
||||
time.sleep(sleep_duration)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-n", type=int, help="Number of test iterations to run")
|
||||
parser.add_argument("-sleep", type=int, help="Sleep time between tests", default=0)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.n is None:
|
||||
while True:
|
||||
run_test(sleep_duration=args.sleep)
|
||||
else:
|
||||
for i in range(args.n):
|
||||
run_test(sleep_duration=args.sleep)
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
rm -f /tmp/dump_bootstub
|
||||
rm -f /tmp/dump_main
|
||||
dfu-util -a 0 -s 0x08000000 -U /tmp/dump_bootstub
|
||||
dfu-util -a 0 -s 0x08004000 -U /tmp/dump_main
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
import time
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
from panda import Panda
|
||||
|
||||
if __name__ == "__main__":
|
||||
if os.getenv("WIFI") is not None:
|
||||
p = Panda("WIFI")
|
||||
else:
|
||||
p = Panda()
|
||||
print(p.get_serial())
|
||||
print(p.health())
|
||||
|
||||
t1 = time.time()
|
||||
for i in range(100):
|
||||
p.get_serial()
|
||||
t2 = time.time()
|
||||
print("100 requests took %.2f ms" % ((t2-t1)*1000))
|
||||
|
||||
p.set_controls_allowed(True)
|
||||
|
||||
a = 0
|
||||
while True:
|
||||
# flood
|
||||
msg = b"\xaa"*4 + struct.pack("I", a)
|
||||
p.can_send(0xaa, msg, 0)
|
||||
p.can_send(0xaa, msg, 1)
|
||||
p.can_send(0xaa, msg, 4)
|
||||
time.sleep(0.01)
|
||||
|
||||
dat = p.can_recv()
|
||||
if len(dat) > 0:
|
||||
print(dat)
|
||||
a += 1
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
import time
|
||||
from tqdm import tqdm
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
|
||||
from panda import Panda, PandaWifiStreaming
|
||||
|
||||
# test throughput between USB and wifi
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(Panda.list())
|
||||
p_out = Panda("108018800f51363038363036")
|
||||
print(p_out.get_serial())
|
||||
#p_in = Panda("02001b000f51363038363036")
|
||||
p_in = Panda("WIFI")
|
||||
print(p_in.get_serial())
|
||||
|
||||
p_in = PandaWifiStreaming()
|
||||
|
||||
#while True:
|
||||
# p_in.can_recv()
|
||||
#sys.exit(0)
|
||||
|
||||
p_out.set_controls_allowed(True)
|
||||
|
||||
set_out, set_in = set(), set()
|
||||
|
||||
# drain
|
||||
p_out.can_recv()
|
||||
p_in.can_recv()
|
||||
|
||||
BATCH_SIZE = 16
|
||||
for a in tqdm(range(0, 10000, BATCH_SIZE)):
|
||||
for b in range(0, BATCH_SIZE):
|
||||
msg = b"\xaa"*4 + struct.pack("I", a+b)
|
||||
if a%1 == 0:
|
||||
p_out.can_send(0xaa, msg, 0)
|
||||
|
||||
dat_out, dat_in = p_out.can_recv(), p_in.can_recv()
|
||||
if len(dat_in) != 0:
|
||||
print(len(dat_in))
|
||||
|
||||
num_out = [struct.unpack("I", i[4:])[0] for _, _, i, _ in dat_out]
|
||||
num_in = [struct.unpack("I", i[4:])[0] for _, _, i, _ in dat_in]
|
||||
|
||||
set_in.update(num_in)
|
||||
set_out.update(num_out)
|
||||
|
||||
# swag
|
||||
print("waiting for packets")
|
||||
time.sleep(2.0)
|
||||
dat_in = p_in.can_recv()
|
||||
print(len(dat_in))
|
||||
num_in = [struct.unpack("I", i[4:])[0] for _, _, i, _ in dat_in]
|
||||
set_in.update(num_in)
|
||||
|
||||
if len(set_out - set_in):
|
||||
print("MISSING %d" % len(set_out - set_in))
|
||||
if len(set_out - set_in) < 256:
|
||||
print(map(hex, sorted(list(set_out - set_in))))
|
||||
Reference in New Issue
Block a user