Advertisement
Guest User

e87 KCan Message Parser

a guest
May 21st, 2016
431
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 24.00 KB | None | 0 0
  1. #!/usr/bin/env python
  2. #
  3. # BMW e87 CAN Lib-ish thingy
  4. #
  5. #
  6. ### Working (or close to) ###
  7. #  - RPM
  8. #  - Speed
  9. #  - Throttle Position
  10. #  - Coolant Temperature
  11. #  - Steering Wheel Position
  12. #
  13. #  - Key Status
  14. #  - Engine Status
  15. #
  16. #  - Reverse Gear / Light
  17. #  - Handbrake Status
  18. #
  19. #  - Brake Light
  20. #  - Dip/Main/Full Beams
  21. #  - Front/Rear Fog Lights
  22. #  - Turn signals/ Hazard lights
  23. #
  24. #  - Odometer
  25. #  - Average Speed
  26. #  - Average Fuel Level
  27. #  - Average Fuel Consumation
  28. #  - Range (Expected range with current fuel/consumation)
  29. #
  30. #  - SZL buttons
  31. #  - Window position
  32. #  - Open Door Alarm
  33. #  - Door Open/Close Lock/Unlock Status
  34. #
  35. #  - Rear Wiper Status
  36. #  - Front Wipers Speed / Status
  37. #
  38. #  - Outside Temp
  39. #  - Rear Demister Status
  40. #  - Internal Temp / Internal Light
  41. #  - Aircondition Left/Right Temperature Setting
  42. #
  43. #  - Individual Wheel Speed
  44. #
  45. #  - Production Date
  46. #  - Last Battery Reset
  47.  
  48.  
  49. import re
  50. import os
  51. import sys
  52.  
  53.  
  54. __version__ = '0.99.11'
  55. __license__ = 'GPLv3'
  56.  
  57.  
  58. # Expected message syntax:
  59. #  ID       HEX (11bit long value)
  60. #  RTR      Integer (0 or 1)
  61. #  Len      Integer (message len)
  62. #  Data     HEX (Up to 8 bytes)
  63. #
  64. #   ID    RTR       Len        Data
  65. # ID: fff -0- Data: [8] ff ff ff ff ff ff ff ff
  66. # ID: fff -0- Data: [3] ff ff ff
  67. #
  68. # Change 'msg_match' regex for another syntax
  69. msg_match = r'ID: (\w+) -(\d{1})- Data: \[(\d{1})\] (.+)'
  70. split_match = r'ID.*ID.* Data.*'
  71.  
  72.  
  73. class CanMsg(object):
  74.     def __init__(self, debug=False):
  75.         self.mid = 0
  76.         self.rtr = 0
  77.         self.mlen = 0
  78.         self.debug = debug
  79.         self.message = []
  80.  
  81.     def check_id(self, mid):
  82.         try:
  83.             mid = int(mid, 16)
  84.             if mid > 0xFFF:
  85.                 return False
  86.             return True
  87.         except:
  88.             return False
  89.  
  90.     def check_msg(self, m, l):
  91.         try:
  92.             msg = m.split()
  93.             for n in xrange(0, len(msg)):
  94.                 msg[n] = int(msg[n], 16)
  95.             if int(l) <> len(msg):
  96.                 return False
  97.             return msg
  98.         except:
  99.             return False
  100.  
  101.     def null(self):
  102.         self.mid = 0
  103.         self.rtr = 0
  104.         self.mlen = 0
  105.         self.message = []
  106.  
  107.     def parse(self, m):
  108.         matchObj = re.match(msg_match, m, re.I)
  109.         if matchObj:
  110.             match_array = matchObj.groups()
  111.             if len(match_array) > 4:
  112.                 # This means multiple messages with no \n to split 'em
  113.                 # So we'll work only with the last one in the line.
  114.                 # (Others are usualy only partaly recived)
  115.                 return self.parse('ID: ' + m.split('ID:')[-1])
  116.             if self.check_id(match_array[0]):
  117.                 self.mid = int(match_array[0], 16)
  118.             if self.check_id(match_array[1]):
  119.                 self.rtr = int(match_array[1])
  120.             if self.check_id(match_array[2]):
  121.                 self.mlen = int(match_array[2])
  122.             self.message = self.check_msg(
  123.                 match_array[3], match_array[2])
  124.             if self.mid and self.mlen and self.message:
  125.                 return True
  126.         return False
  127.  
  128.  
  129. class CarStatus(object):
  130.     def __init__(self, debug=False):
  131.         # Debug
  132.         self.debug = debug
  133.         # Main dict
  134.         self.mdict = {}
  135.         # Unknown IDs
  136.         self.uids = {}
  137.         # Time & Date
  138.         self.['hours'] = 1
  139.         self.['minutes'] = 0
  140.         self.['seconds'] = 0
  141.         self.['day'] = 1
  142.         self.['month'] = 1
  143.         self.['year'] = 2015
  144.         self.result = {}
  145.  
  146.     def get(self, arg):
  147.         if arg in self.mdict:
  148.             return self.mdict[arg]
  149.  
  150.     def set(self, var, val):
  151.         change = True
  152.         if var in self.mdict:
  153.             if self.mdict[var] == val:
  154.                 change = False
  155.         self.mdict[var] = val
  156.         self.result[var] = [val, change]
  157.  
  158.     def decode_vin(self, msg):
  159.         try: vin = map(chr, msg[::-1])
  160.         except: return
  161.         self.set('vin', vin)
  162.  
  163.     def get_time(self):
  164.         return '%s:%s:%s' % (self.mdict['hours'],
  165.             self.mdict['minutes'], self.mdict['seconds'])
  166.  
  167.     def get_date(self):
  168.         return '%s.%s.%s' % (self.mdict['day'],
  169.             self.mdict['month'], self.mdict['year'])
  170.  
  171.     def add_second(self):
  172.         # We sync the clock every 30s, so even
  173.         # if we go to hours=25 it will be fixed fast
  174.         # Its just a waste of time to go futher
  175.         if self.mdict['seconds'] == 59:
  176.             if self.mdict['minutes'] == 59:
  177.                 self.mdict['hours'] += 1
  178.                 self.mdict['minutes'] = 0
  179.                 self.mdict['seconds'] = 0
  180.             else:
  181.                 self.mdict['minutes'] += 1
  182.                 self.mdict['seconds'] = 0
  183.         else:
  184.             self.mdict['seconds'] += 1
  185.         return
  186.  
  187.     def msg(self, m):
  188.         self.result = {}
  189.         # Message sanity checks
  190.         if not (hasattr(m, 'mid') and hasattr(m, 'mlen')):
  191.             return False
  192.         if m.mlen < 1:
  193.             return False
  194.  
  195.         if (m.mid == 0x130) and (m.mlen > 1):
  196.             # ID: 100110000
  197.             bmsg0 = biny(m.message[0], 8)
  198.             self.set('engine_ready', bmsg[5])
  199.             self.set('engine_running', bmsg[3])
  200.             if m.message[1] == 0:
  201.                 self.set('key', 0)
  202.             else:
  203.                 self.set('key', 1)
  204.             # Other parts of the message are part of
  205.             # the ignition sequence. For more info check:
  206.             # http://www.loopybunny.co.uk/CarPC/can/130.html
  207.         elif (m.mid == 0x1B4) and (m.mlen > 1):
  208.             # ID : 110110100
  209.             self.mph = (((m.message[1] - 0xC0) * 256 ) + m.message[0]) / 16
  210.             self.kph = (self.mph * 1.61)
  211.             self.set('kph', self.kph)
  212.             # Unchecked!
  213.             if m.message[5] == 50:
  214.                 self.set('handbrake', 1)
  215.             elif m.message[5] == 48:
  216.                 self.set('handbrake', 0)
  217.         elif (m.mid == 0x1D0):
  218.             # ID: 111010000
  219.             # http://www.loopybunny.co.uk/CarPC/can/1D0.html
  220.             # Clutch status and (glow plugs?) data avaiable in this message.
  221.             self.set('coolant_temp', (m.message[0] - 48))
  222.         elif (m.mid == 0x1D6) and (m.mlen > 1):
  223.             # ID: 111010110
  224.             if (m.message[0] == 0xC0) and (m.mlen > 1):
  225.                 if m.message[1] == 0xD:
  226.                     self.set('voice_button', 1)
  227.                 elif m.message[1] == 0x1C:
  228.                     self.set('rotate', 1)
  229.                 elif m.message[1] == 0x4C:
  230.                     self.set('disk_button', 1)
  231.             elif (m.message[0] == 0xC1) and (m.message[1] == 0xC):
  232.                 self.set('telephone_button', 1)
  233.             elif (m.message[0] == 0xC4) and (m.message[1] == 0xC):
  234.                 self.set('volumedown_down', 1)
  235.             elif (m.message[0] == 0xC8) and (m.message[1] == 0xC):
  236.                 self.set('volumeup_button', 1)
  237.             elif (m.message[0] == 0xD0) and (m.message[1] == 0xC):
  238.                 self.set('down_button', 1)
  239.             elif (m.message[0] == 0xE0) and (m.message[1] == 0xC):
  240.                 self.set('up_button', 1)
  241.         elif (m.mid == 0x1F6) and (m.mlen > 1):
  242.             # ID: 111110110
  243.             if m.message[0] == 0x80:
  244.                 self.set('hazard_lights', 0)
  245.                 self.set('left_turnsignal', 0)
  246.                 self.set('right_turnsignal', 0)
  247.             elif (m.message[0] == 0x91):
  248.                 self.set('left_turnsignal', 1)
  249.             elif (m.message[0] == 0xA1):
  250.                 self.set('right_turnsignal', 1)
  251.             elif (m.message[0] == 0xB1):
  252.                 self.set('hazard_lights', 1)
  253.         elif (m.mid == 0x1EE):
  254.             # ID: 111101110
  255.             # Light Stick position
  256.             # http://www.loopybunny.co.uk/CarPC/can/1EE.html
  257.             if m.message[0] == 0x00:
  258.                 self.set('full_beam', 0)
  259.                 self.set('left_turnsignal', 0)
  260.                 self.set('right_turnsignal', 0)
  261.             elif m.message[0] == 0x02:
  262.                 self.set('left_turnsignal', 0)
  263.                 self.set('right_turnsignal', 1)
  264.             elif m.message[0] == 0x08:
  265.                 self.set('left_turnsignal', 1)
  266.                 self.set('right_turnsignal', 0)
  267.             elif m.message[0] == 0x10:
  268.                 self.set('full_beam', 1)
  269.             elif m.message[0] == 0x01:
  270.                 self.set('right_blink', 1)
  271.             elif m.message[0] == 0x04:
  272.                 self.set('left_blink', 1)
  273.             elif m.message[0] == 0x20:
  274.                 self.set('full_beam', 0)
  275.                 self.set('beam_flash', 1)
  276.         elif (m.mid == 0x24B):
  277.             # ID: 1001001011
  278.             if m.message[0]:
  279.                 self.set('door_alarm', 1)
  280.             else:
  281.                 self.set('door_alarm', 0)
  282.         elif (m.mid == 0x202):
  283.             # ID: 1000000010
  284.             # http://www.loopybunny.co.uk/CarPC/can/202.html
  285.             self.dashboard_dimmer = int((255 - m.message[0]) / 25)
  286.             self.set('dashboard_dimmer', self.dashboard_dimmer) # Umh?
  287.         elif (m.mid == 0x21A) and (m.mlen > 1):
  288.             # ID: 1000011010
  289.             # http://www.loopybunny.co.uk/CarPC/can/21A.html
  290.             bmsg1 = biny(m.message[0], 8)
  291.             bmsg2 = biny(m.message[1], 8)
  292.             self.set('rear_fog', bmsg1[1])
  293.             self.set('dip_beam', bmsg1[5])
  294.             self.set('main_beam', bmsg1[7])
  295.             self.set('front_fog', bmsg1[2])
  296.             self.set('brake_light', bmsg1[0])
  297.             self.set('dashboard_light', bmsg2[6])
  298.         elif m.mid == 0x1E3:
  299.             # ID: 111100011
  300.             # Internal light switch
  301.             # http://www.loopybunny.co.uk/CarPC/can/1E3.html
  302.             # Send Can-Bus command:- ID:1E3, Length:02, DATA:F1 FF.
  303.             # 50mS later send the command again:- ID:1E3, Length:02, DATA:F1 FF.
  304.             # Finally send Can-Bus command:- ID:1E3, Length:02, DATA:F0 FF.
  305.             pass
  306.         elif (m.mid == 0x328) and (m.mlen > 5):
  307.             # ID: 1100101000
  308.             pd = '0x%s%s%s%s' % (m.message[3], m.message[2],
  309.                                  m.message[1], m.message[0])
  310.             br = '0x%s%s' % (m.message[5], m.message[4])
  311.             # Battery reset is in days since 01/01/2000
  312.             # Production date is seconds since the production date
  313.             self.set('battery_reset', int(br, 16))
  314.             self.set('production_date', (int(pd, 16)/(60*24)))
  315.         elif (m.mid == 0x246) and m.mlen:
  316.             # ID: 1001000110
  317.             # Check message for more AC information
  318.             if m.message[0] == 0x3F:
  319.                 self.set('rear_demister', 0)
  320.             elif m.message[0] == 0x7F:
  321.                 self.set('rear_demister', 1)
  322.         elif m.mid == 0x26E:
  323.             # ID: 1001101110
  324.             # Key relayed stuff...
  325.             # We already know key status from 0x130
  326.             # Maybe move here if it helps filtering?
  327.             pass
  328.         elif m.mid == 0x2A6:
  329.             # ID: 1010100110
  330.             # Wipers Stick
  331.             # More info: http://www.loopybunny.co.uk/CarPC/can/2A6.html
  332.             if m.message[0] == 0x00:
  333.                 self.set('wipers', 0)
  334.                 self.set('rear_wiper', 0)
  335.             elif (m.message[0] == 0x01) and (m.mlen > 1):
  336.                 self.set('wipers', 1)
  337.                 self.set('wipers_speed', (m.message[1] - 247))
  338.             elif (m.message[0] in [0x40, 0x81, 0x10]) and (m.mlen > 1):
  339.                 self.set('rear_wiper', 1)
  340.             elif (m.message[0] == 0x08) and (m.mlen > 1):
  341.                 self.set('wipers_single', 1)
  342.         elif (m.mid == 0x2CA):
  343.             # ID: 1011001010
  344.             self.set('outside_temp',((m.message[0] - 80) / 2))
  345.         elif (m.mid == 0x2E6) and (m.mlen == 8):
  346.             # ID: 1011100110
  347.             self.set('left_temp', (m.message[7] / 2.0))
  348.             self.set('fan_speed', (m.message[5]))
  349.         elif (m.mid == 0x2EA) and (m.mlen == 8):
  350.             # ID: 1011101010
  351.             self.set('right_temp', (m.message[7] / 2.0))
  352.         elif (m.mid == 0x366) and (m.mlen > 2):
  353.             # ID: 1101100110
  354.             etemp = (m.message[0] - 80) / 2.0
  355.             erange = '0x%s%s' % (hex(m.message[2])[2:], hex(m.message[1])[2:])
  356.             self.set('external_temp', etemp)
  357.             self.set('range0', int(erange, 16)/16)
  358.         elif (m.mid == 0x330) and (m.mlen == 8):
  359.             # ID: 1100110000
  360.             odm = '0x%s%s%s'  % (hex(m.message[2])[2:].upper().rjust(2), \
  361.                                     hex(m.message[1])[2:].upper().rjust(2), \
  362.                                     hex(m.message[0])[2:].upper().rjust(2))
  363.             odm = odm.replace(' ', '0')
  364.             range0 = '0x%s%s' % (hex(m.message[7])[2:].upper().rjust(2), \
  365.                                  hex(m.message[6])[2:].upper().rjust(2))
  366.             range0 = range0.replace(' ', '0')
  367.             self.set('odometer', int(odm, 16))
  368.             self.set('avr_fuel', m.message[3])
  369.             self.set('range', int(range0, 16) / 16)
  370.         elif (m.mid == 0x34F):
  371.             # ID: 1101001111
  372.             if m.message[0] == 0xFE:
  373.                 self.set('handbrake', 1)
  374.             elif m.message[0] == 0xFD:
  375.                 self.set('handbrake', 0)
  376.         elif (m.mid == 0x2FC) and (m.mlen > 2):
  377.             # ID: 1011111100
  378.             # Doors
  379.             bmsg = biny(m.message[1], 8)
  380.             bmsg2= biny(m.message[2], 8)
  381.             result.append(self.set('rr_door', bmsg[1]))
  382.             result.append(self.set('rl_door', bmsg[3]))
  383.             result.append(self.set('fr_door', bmsg[5]))
  384.             result.append(self.set('fl_door', bmsg[7]))
  385.             # Bonnet & Boot
  386.             # It appears e87 dosnt have hood status here
  387.             # It is probably populated by another message.
  388.             #result.append(self.set('bonnet_open', bmsg2[1]))
  389.             result.append(self.set('boot_open', bmsg2[7]))
  390.         #elif (m.mid == 0x2D6) and (m.mlen > 1):
  391.          # Looks like e87 donst use this for message for
  392.          # the aircondition status...probably another message?
  393.         elif (m.mid == 0x32E) and (m.mlen > 3):
  394.             # ID: 1100101110
  395.             self.internal_light = m.message[0]
  396.             self.set('internal_temp', ((m.message[3] / 10.0) + 6))
  397.         elif (m.mid == 0x349) and (m.mlen > 3):
  398.             # ID : 1101001001
  399.             self.left_fuel  = binc(m.message[0], m.message[1]) / 160
  400.             self.right_fuel = binc(m.message[2], m.message[3]) / 160
  401.         elif (m.mid == 0x362) and (m.mlen > 2):
  402.             # ID : 1101100010
  403.             # Constant: 235.214
  404.             hb, lb = hl_bits(m.message[1])
  405.             afc = binc(m.message[2], hb)
  406.             akmph = binc(m.message[0], lb)
  407.             # Fuel consumation error!!! close but ...
  408.             self.set('avr_fc', afc / 10.0)
  409.             self.set('avr_speed', akmph / 10.0)
  410.             self.set('avr_fc100', round((235.214 / self.avr_fc), 2))
  411.         elif (m.mid == 0x380) and (m.mlen == 7):
  412.             # ID: 1110000000
  413.             self.decode_vin(m.message)
  414.         elif m.mid == 0xF2:
  415.             # ID: 0011110010
  416.             if m.message[0] == 241:
  417.                 self.set('boot_locked', 0)
  418.             elif m.message[0] > 241:
  419.                 self.set('boot_locked', 1)
  420. #            if m.message[3] == 192:
  421. #                result.append(self.set('boot_open', 0))
  422. #            elif m.message[3] == 193:
  423. #                result.append(self.set('boot_open', 1))
  424.         elif m.mid == 0xEE:
  425.             # ID: 0011101110
  426.             if m.message[0] == 0x81:
  427.                 self.set('rl_lock', 0)
  428.             elif m.message[0] > 0x81:
  429.                 self.set('rl_lock', 1)
  430. #            if m.message[3] == 0xFC:
  431. #                result.append(self.set('rl_door', 1))
  432. #            elif m.message[3] == 0xFD:
  433. #                result.append(self.set('rl_door', 0))
  434.         elif m.mid == 0xEA:
  435.             # ID: 0011101010
  436.             if m.message[0] == 0x81:
  437.                 self.set('rr_lock', 0)
  438.             elif m.message[0] > 0x81:
  439.                 self.set('rr_lock', 1)
  440. #            if m.message[3] == 0xFC:
  441. #                result.append(self.set('rr_door', 1))
  442. #            elif m.message[3] == 0xFD:
  443. #                result.append(self.set('rr_door', 0))
  444.         elif m.mid == 0xE6:
  445.             # ID: 11100110
  446.             if m.message[0] == 0x81:
  447.                 self.set('fr_lock', 0)
  448.             elif m.message[0] > 0x81:
  449.                 self.set('fr_lock', 1)
  450. #            if m.message[3] == 0xFC:
  451. #                result.append(self.set('fr_door', 1))
  452. #            elif m.message[3] == 0xFD:
  453. #                result.append(self.set('fr_door', 0))
  454.         elif m.mid == 0xE2:
  455.             # ID: 0011100010
  456.             if m.message[0] == 0x81:
  457.                 self.set('fl_lock', 0)
  458.             elif m.message[0] > 0x81:
  459.                 self.set('fl_lock', 1)
  460. #            if m.message[3] == 0xFC:
  461. #                result.append(self.set('fl_door', 1))
  462. #            elif m.message[3] == 0xFD:
  463. #                result.append(self.set('fl_door', 0))
  464.         elif (m.mid == 0x3B0):
  465.             # ID: 1110110000
  466.             if m.message[0] == 0xFD:
  467.                 self.set('reverse', 0)
  468.             elif m.message[0] == 0xFE:
  469.                 self.set('reverse', 1)
  470.         elif (m.mid == 0x3B6):
  471.             # ID: 1110110110
  472.             # e87 Front Windows Position
  473.             # is (0-95), for rear - 0-85?
  474.             #
  475.             # On more info how to emulate button press
  476.             # http://www.loopybunny.co.uk/CarPC/can/0FA.html
  477.             self.set('fl_window', m.message[0])
  478.         elif (m.mid == 0x3B7):
  479.             self.set('rl_window', m.message[0])
  480.         elif (m.mid == 0x3B8):
  481.             self.set('fr_window', m.message[0])
  482.         elif (m.mid == 0x3B9):
  483.             self.set('rr_window', m.message[0])
  484.         elif (m.mid == 0x2F8) and (m.mlen > 6):
  485.             # ID: 1011111000
  486.             hb, lb = hl_bits(m.message[4])
  487.             month = '0x%s' % hb
  488.             month = int(month, 16)
  489.             year = binc(m.message[5], m.message[6])
  490.             self.set('day', m.message[3])
  491.             self.set('month', month)
  492.             self.set('hours', m.message[0])
  493.             self.set('minutes', m.message[1])
  494.             self.set('seconds', m.message[2])
  495.             self.set('year', year)
  496.         elif m.mid == 0x2B6:
  497.             # ID: 1010110110
  498.             # Not yet sure what this message is
  499.             # But its transmitted every 1 seconds, so i'll use it
  500.             # to keep track the clock in check.
  501.             self.add_second()
  502.         elif (m.mid == 0x3B4) and (m.mlen > 1):
  503.             # ID: 1110110100
  504.             # Seems like constant for e87...
  505.             # Check for this elsewhere
  506.             pass
  507.             #cv = (((m.message[1] - 240) * 256) + m.message[0]) / 68
  508.             #self.set('voltage', cv)
  509.         elif (m.mid == 0x581) and (m.mlen > 3):
  510.             # ID: 10110000001
  511.             if m.message[3] == 0x28:
  512.                 self.set('seat_belt_alarm', 0)
  513.         elif (m.mid == 0x394) and (m.mlen > 3):
  514.             # ID: 1110010100
  515.             if m.message[3] == 0x29:
  516.                 self.set('seat_belt_alarm', 1)
  517.         elif (m.mid == 0xA8) and (m.mlen == 8):
  518.             # ID: 0010101000
  519.             # Trorque dosnt seem to be computable
  520.             # the way its on e83 :( Gatta find it!
  521.             self.set('brake_power', m.message[7])
  522.             torque = ((m.message[2] * 256) + m.message[1]) / 32
  523. #            self.set('torque', torque/100.0)
  524. #            self.calc_kw()
  525.             if m.message[5] == 0xF0:
  526.                 self.set('clutch', 0)
  527.             elif m.message[5] == 0xF1:
  528.                 self.set('clutch', 1)
  529.             if m.message[7] > 20:
  530.                 self.set('brakes', 1)
  531.             else:
  532.                 self.set('brakes', 0)
  533.         elif (m.mid == 0xAA) and (m.mlen > 6):
  534.             # ID: 0010101010
  535.             rpm = binc(m.message[4], m.message[5]) / 4
  536.             throttle = binc(m.message[2], m.message[3]) / 256
  537.             self.set('rpm', rpm)
  538.             self.set('throttle', throttle)
  539.         elif (m.mid == 0xC8) and (m.mlen > 1):
  540.             # ID: 11001000
  541.             bm = binc(m.message[0], m.message[1])
  542.             if (bm / 23) > 360:
  543.                 wheel_position = (bm - 65535) / 23
  544.             else:
  545.                 wheel_position = bm/23
  546.             if (wheel_position < 360) and (wheel_position > -360):
  547.                 self.set('wheel_position', wheel_position)
  548.             else:
  549.                 # Make sure we're not comming here
  550.                 print 'ERR-wheel_position %s' % wheel_position
  551.         elif (m.mid == 0xCE) and (m.mlen == 8):
  552.             # ID: 11001110
  553.             # 1.6 to get in km/h not mph
  554.             self.set('fl_wheel', (binc(m.message[0], m.message[1]) / 24 * 1.6))
  555.             self.set('fr_wheel', (binc(m.message[3], m.message[3]) / 24 * 1.6))
  556.             self.set('rl_wheel', (binc(m.message[4], m.message[5]) / 24 * 1.6))
  557.             self.set('rr_wheel', (binc(m.message[6], m.message[7]) / 24 * 1.6))
  558.         elif (m.mid == 0x2A0):
  559.             # ID: 1010100000
  560.             # http://www.e90post.com/forums/showpost.php?p=14513521&postcount=114
  561.             # ID:2A0 [8] DATA:88 88 80 0 16 40 86 0
  562.             # I've been able to open the trunk.
  563.             # Hope this is helpful for somebody.
  564.             #
  565.             # ID: 2a0 -0- Data: [8]  88 88 88 1 2c 40 6 0
  566.             # This should be normal status?
  567.             # Inspect more
  568.             pass
  569.         elif (m.mid == 0x2F0):
  570.             pass  # ID: 2f0 -0- Data: [2]  f7 fc
  571.         elif (m.mid == 0x23A):
  572.             # Ispect more
  573.             print 'ID: 0x23A', m.message
  574.         elif (m.mid == 0x2F4):
  575.             pass  # ID: 2f4 -0- Data: [4]  cf ff ff ff
  576.         elif (m.mid == 0x2F6):
  577.             pass  # ID: 2f6 -0- Data: [2]  0 f5
  578.         elif (m.mid == 0x2FA):
  579.             pass  # ID: 2fa -0- Data: [5]  fd 8 ff ff ff
  580.         elif (m.mid == 0x311):
  581.             pass  # ID: 311 -0- Data: [2]  0 f0
  582.         elif (m.mid == 0x335):
  583.             pass  # Sensor data?! Inspect more
  584.         elif (m.mid == 0x367):
  585.             pass  # Sensor data?! Inspect more
  586.         elif (m.mid == 0x35C):
  587.             pass  # ID: 35c -0- Data: [4]  ff f0 ff a0
  588.         elif (m.mid == 0x3B3):
  589.             pass  # ID: 3b3 -0- Data: [6]  11 c8 0 0 0 f0
  590.         elif (m.mid == 0x3BD):
  591.             pass  # ID: 3bd -0- Data: [2]  fd ff
  592.         elif (m.mid == 0x3BE):
  593.             pass  # ID: 3be -0- Data: [2]  fe ff
  594.         elif (m.mid == 0x360):
  595.             pass  # ID: 360 -0- Data: [7]  ff ff ff ff ff ff ff
  596.         elif (m.mid == 0x364):
  597.             pass  # ID: 364 -0- Data: [7]  ff ff ff ff ff ff ff
  598.         elif (m.mid == 0x35E):
  599.             pass  # ID: 35e -0- Data: [8]  ff ff ff ff ff ff ff ff
  600.         elif (m.mid == 0xD7):
  601.             pass  # Seat belt & airbag alarm stuff?
  602.         elif (m.mid == 0xC0):
  603.             pass  # ABS Module "all ok" ?
  604.         elif (m.mid == 0xC4):
  605.             pass  # Same as 0xC8 (not sent as often thou)
  606.         elif (m.mid == 0x2BA):
  607.             pass  # Counter (Toggle / Heartbeat)
  608.         elif (m.mid == 0x19E):
  609.             # Get brake pressure?
  610.             pass  # ABS Stuff http://www.loopybunny.co.uk/CarPC/can/19E.html
  611.         elif (m.mid == 0x7C3):
  612.            pass   # Keyfob (security, comfort and CBS data). # To inspect more...
  613.         elif (m.mid == 0x1A6):
  614.            pass  # Speed used by instrument cluster (offsets)
  615.         else:
  616.             idstr = str(hex(m.mid))
  617.             if idstr in self.uids:
  618.                 self.uids[idstr] += 1
  619.             else:
  620.                 self.uids[idstr] = 1
  621.        
  622.         return self.result
  623.  
  624.     def unknown_ids(self):
  625.         return self.uids
  626.  
  627.     def calc_kw(self):
  628.         # (RPM * Torque) / (60 / 2Pi) / 1000
  629.         self.kw = ((self.rpm * self.torque) * 9.54) / 1000
  630.  
  631. def binc(i, n):
  632.     return (n * 256) + i
  633.  
  634. def biny(i, l):
  635.     return format(i, 'b').zfill(l)
  636.  
  637. def hl_bits(i):
  638.     bb = hex(i)[2:]
  639.     return int(bb[0], 16), int(bb[1], 16)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement