You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							95 lines
						
					
					
						
							2.8 KiB
						
					
					
				
			
		
		
	
	
							95 lines
						
					
					
						
							2.8 KiB
						
					
					
				#!/usr/bin/env python
 | 
						|
import time
 | 
						|
from common.realtime import sec_since_boot
 | 
						|
import selfdrive.messaging as messaging
 | 
						|
from selfdrive.boardd.boardd import can_list_to_can_capnp
 | 
						|
 | 
						|
def get_vin(logcan, sendcan):
 | 
						|
 | 
						|
  # works on standard 11-bit addresses for diagnostic. Tested on Toyota and Subaru;
 | 
						|
  # Honda uses the extended 29-bit addresses, and unfortunately only works from OBDII
 | 
						|
  query_msg = [[0x7df, 0, '\x02\x09\x02'.ljust(8, "\x00"), 0],
 | 
						|
               [0x7e0, 0, '\x30'.ljust(8, "\x00"), 0]]
 | 
						|
 | 
						|
  cnts = [1, 2]  # Number of messages to wait for at each iteration
 | 
						|
  vin_valid = True
 | 
						|
 | 
						|
  dat = []
 | 
						|
  for i in range(len(query_msg)):
 | 
						|
    cnt = 0
 | 
						|
    sendcan.send(can_list_to_can_capnp([query_msg[i]], msgtype='sendcan'))
 | 
						|
    got_response = False
 | 
						|
    t_start = sec_since_boot()
 | 
						|
    while sec_since_boot() - t_start < 0.05 and not got_response:
 | 
						|
      for a in messaging.drain_sock(logcan):
 | 
						|
        for can in a.can:
 | 
						|
          if can.src == 0 and can.address == 0x7e8:
 | 
						|
            vin_valid = vin_valid and is_vin_response_valid(can.dat, i, cnt)
 | 
						|
            dat += can.dat[2:] if i == 0 else can.dat[1:]
 | 
						|
            cnt += 1
 | 
						|
            if cnt == cnts[i]:
 | 
						|
              got_response = True
 | 
						|
      time.sleep(0.01)
 | 
						|
 | 
						|
  return "".join(dat[3:]) if vin_valid else ""
 | 
						|
 | 
						|
"""
 | 
						|
if 'vin' not in gctx:
 | 
						|
  print "getting vin"
 | 
						|
  gctx['vin'] = query_vin()[3:]
 | 
						|
  print "got VIN %s" % (gctx['vin'],)
 | 
						|
  cloudlog.info("got VIN %s" % (gctx['vin'],))
 | 
						|
 | 
						|
# *** determine platform based on VIN ****
 | 
						|
if vin.startswith("19UDE2F36G"):
 | 
						|
  print "ACURA ILX 2016"
 | 
						|
  self.civic = False
 | 
						|
else:
 | 
						|
  # TODO: add Honda check explicitly
 | 
						|
  print "HONDA CIVIC 2016"
 | 
						|
  self.civic = True
 | 
						|
 | 
						|
# *** special case VIN of Acura test platform
 | 
						|
if vin == "19UDE2F36GA001322":
 | 
						|
  print "comma.ai test platform detected"
 | 
						|
  # it has a gas interceptor and a torque mod
 | 
						|
  self.torque_mod = True
 | 
						|
"""
 | 
						|
 | 
						|
 | 
						|
# sanity checks on response messages from vin query
 | 
						|
def is_vin_response_valid(can_dat, step, cnt):
 | 
						|
 | 
						|
  can_dat = [ord(i) for i in can_dat]
 | 
						|
 | 
						|
  if len(can_dat) != 8:
 | 
						|
    # ISO-TP meesages are all 8 bytes
 | 
						|
    return False
 | 
						|
 | 
						|
  if step == 0:
 | 
						|
    # VIN does not fit in a single message and it's 20 bytes of data
 | 
						|
    if can_dat[0] != 0x10 or can_dat[1] != 0x14:
 | 
						|
       return False
 | 
						|
 | 
						|
  if step == 1 and cnt == 0:
 | 
						|
    # first response after a CONTINUE query is sent
 | 
						|
    if can_dat[0] != 0x21:
 | 
						|
       return False
 | 
						|
 | 
						|
  if step == 1 and cnt == 1:
 | 
						|
    # second response after a CONTINUE query is sent
 | 
						|
    if can_dat[0] != 0x22:
 | 
						|
       return False
 | 
						|
 | 
						|
  return True
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
  import zmq
 | 
						|
  from selfdrive.services import service_list
 | 
						|
  context = zmq.Context()
 | 
						|
  logcan = messaging.sub_sock(context, service_list['can'].port)
 | 
						|
  sendcan = messaging.pub_sock(context, service_list['sendcan'].port)
 | 
						|
  time.sleep(1.)   # give time to sendcan socket to start
 | 
						|
 | 
						|
  print get_vin(logcan, sendcan)
 | 
						|
 |