diff --git a/.gitignore b/.gitignore index d18402de39..5eb52dcca3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ *.pyc +*.os +*.tmp .*.swp +can/*.so +can/build/ +can/obj/ +can/packer_pyx.cpp +can/parser_pyx.cpp +can/packer_impl.cpp diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..e105313756 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +from ubuntu:16.04 + +RUN apt-get update && apt-get install -y libzmq3-dev clang wget git autoconf libtool curl make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" +RUN pyenv install 3.7.3 +RUN pyenv global 3.7.3 +RUN pyenv rehash + +COPY requirements.txt /tmp/ +RUN pip install -r /tmp/requirements.txt + +ENV PYTHONPATH=/project + +# TODO: Add tag to cereal +RUN git clone https://github.com/commaai/cereal.git /project/cereal +RUN /project/cereal/install_capnp.sh + +WORKDIR /project + +COPY SConstruct . +COPY . /project/opendbc + +RUN scons -c && scons -j$(nproc) diff --git a/README.md b/README.md index eec42dfefa..c11cf3fdcf 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ For example: SG_ VEHICLE_SPEED : 7|15@0+ (0.01,0) [0|250] "kph" PCM ``` -- Signal's size: always use the smallest amount of bits possible. For example, let's say I'm reverse engineering the gas pedal position and I've determined that it's in a 3 bytes message. For 0% pedal position I read a message value of `0x00 0x00 0x00`, while for 100% of pedal position I read `0x64 0x00 0x00`: clearly, the gas pedal position is within the first byte of the message and I might be tempted to define the signal `GAS_POS` as: +- Signal size: always use the smallest amount of bits possible. For example, let's say I'm reverse engineering the gas pedal position and I've determined that it's in a 3 bytes message. For 0% pedal position I read a message value of `0x00 0x00 0x00`, while for 100% of pedal position I read `0x64 0x00 0x00`: clearly, the gas pedal position is within the first byte of the message and I might be tempted to define the signal `GAS_POS` as: ``` SG_ GAS_POS : 7|8@0+ (1,0) [0|100] "%" PCM ``` diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000000..b051d182e1 --- /dev/null +++ b/SConstruct @@ -0,0 +1,57 @@ +import os +import subprocess + +zmq = 'zmq' +arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() + +cereal_dir = Dir('.') + +cpppath = [ + '#', + '#cereal', + "#cereal/messaging", + "#opendbc/can", + '/usr/lib/include', +] + +AddOption('--test', + action='store_true', + help='build test files') + +AddOption('--asan', + action='store_true', + help='turn on ASAN') + +ccflags_asan = ["-fsanitize=address", "-fno-omit-frame-pointer"] if GetOption('asan') else [] +ldflags_asan = ["-fsanitize=address"] if GetOption('asan') else [] + +env = Environment( + ENV=os.environ, + CC='clang', + CXX='clang++', + CCFLAGS=[ + "-g", + "-fPIC", + "-O2", + "-Werror=implicit-function-declaration", + "-Werror=incompatible-pointer-types", + "-Werror=int-conversion", + "-Werror=return-type", + "-Werror=format-extra-args", + ] + ccflags_asan, + LDFLAGS=ldflags_asan, + LINKFLAGS=ldflags_asan, + + CFLAGS="-std=gnu11", + CXXFLAGS="-std=c++14", + CPPPATH=cpppath, +) + +Export('env', 'zmq', 'arch') + +cereal = [File('#cereal/libcereal.a')] +messaging = [File('#cereal/libmessaging.a')] +Export('cereal', 'messaging') + +SConscript(['cereal/SConscript']) +SConscript(['opendbc/can/SConscript']) diff --git a/acura_ilx_2016_can_generated.dbc b/acura_ilx_2016_can_generated.dbc index 2a2a941a59..76444138d3 100644 --- a/acura_ilx_2016_can_generated.dbc +++ b/acura_ilx_2016_can_generated.dbc @@ -271,8 +271,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/acura_rdx_2018_can_generated.dbc b/acura_rdx_2018_can_generated.dbc index 48c9b3967d..233ece8ffc 100644 --- a/acura_rdx_2018_can_generated.dbc +++ b/acura_rdx_2018_can_generated.dbc @@ -259,8 +259,8 @@ BO_ 392 GEARBOX: 6 XXX SG_ GEAR : 36|5@0+ (1,0) [0|31] "" EON BO_ 399 STEER_STATUS: 6 EPS - SG_ STEER_TORQUE_SENSOR : 7|12@0- (1,0) [-2047.5|2047.5] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|12@0- (-1,0) [-2047.5|2047.5] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 35|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 36|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..3841610a6a --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,16 @@ +pr: none + +pool: + vmImage: 'ubuntu-16.04' +steps: +- script: | + set -e + docker build -t opendbc . + displayName: 'Build' +- script: | + docker run opendbc bash -c "python -m unittest discover opendbc" + displayName: 'Unit tests' +- script: | + docker run opendbc bash -c "cd opendbc/can/tests/linter_python; PYTHONPATH=/ ./flake8_opendbc.sh" + docker run opendbc bash -c "cd opendbc/can/tests/linter_python; PYTHONPATH=/ ./pylint_opendbc.sh" + displayName: 'Python linter' diff --git a/can/SConscript b/can/SConscript new file mode 100644 index 0000000000..94a45ea185 --- /dev/null +++ b/can/SConscript @@ -0,0 +1,27 @@ +Import('env', 'cereal') + +import os +from opendbc.can.process_dbc import process + +dbcs = [] +for x in sorted(os.listdir('../')): + if x.endswith(".dbc"): + def compile_dbc(target, source, env): + process(source[0].path, target[0].path) + in_fn = [os.path.join('../', x), 'dbc_template.cc'] + out_fn = os.path.join('dbc_out', x.replace(".dbc", ".cc")) + dbc = env.Command(out_fn, in_fn, compile_dbc) + dbcs.append(dbc) + + +libdbc = env.SharedLibrary('libdbc', ["dbc.cc", "parser.cc", "packer.cc", "common.cc"]+dbcs, LIBS=["capnp", "kj"]) + +# packer +env.Command(['packer_pyx.so'], + [libdbc, 'packer_pyx.pyx', 'packer_pyx_setup.py'], + "cd opendbc/can && python3 packer_pyx_setup.py build_ext --inplace") + +# parser +env.Command(['parser_pyx.so'], + [libdbc, cereal, 'parser_pyx_setup.py', 'parser_pyx.pyx', 'common.pxd'], + "cd opendbc/can && python3 parser_pyx_setup.py build_ext --inplace") diff --git a/can/__init__.py b/can/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/can/can_define.py b/can/can_define.py new file mode 100644 index 0000000000..12c2d58b20 --- /dev/null +++ b/can/can_define.py @@ -0,0 +1,2 @@ +from opendbc.can.parser_pyx import CANDefine # pylint: disable=no-name-in-module, import-error +assert CANDefine diff --git a/can/common.cc b/can/common.cc new file mode 100644 index 0000000000..5a131eb6c7 --- /dev/null +++ b/can/common.cc @@ -0,0 +1,165 @@ +#include "common.h" + +unsigned int honda_checksum(unsigned int address, uint64_t d, int l) { + d >>= ((8-l)*8); // remove padding + d >>= 4; // remove checksum + + int s = 0; + while (address) { s += (address & 0xF); address >>= 4; } + while (d) { s += (d & 0xF); d >>= 4; } + s = 8-s; + s &= 0xF; + + return s; +} + +unsigned int toyota_checksum(unsigned int address, uint64_t d, int l) { + d >>= ((8-l)*8); // remove padding + d >>= 8; // remove checksum + + unsigned int s = l; + while (address) { s += address & 0xff; address >>= 8; } + while (d) { s += d & 0xff; d >>= 8; } + + return s & 0xFF; +} + +// Static lookup table for fast computation of CRC8 poly 0x2F, aka 8H2F/AUTOSAR +uint8_t crc8_lut_8h2f[256]; + +void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]) { + uint8_t crc; + int i, j; + + for (i = 0; i < 256; i++) { + crc = i; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) + crc = (uint8_t)((crc << 1) ^ poly); + else + crc <<= 1; + } + crc_lut[i] = crc; + } +} + +void init_crc_lookup_tables() { + // At init time, set up static lookup tables for fast CRC computation. + + gen_crc_lookup_table(0x2F, crc8_lut_8h2f); // CRC-8 8H2F/AUTOSAR for Volkswagen +} + +unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l) { + // Volkswagen uses standard CRC8 8H2F/AUTOSAR, but they compute it with + // a magic variable padding byte tacked onto the end of the payload. + // https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_CRCLibrary.pdf + + uint8_t *dat = (uint8_t *)&d; + uint8_t crc = 0xFF; // Standard init value for CRC8 8H2F/AUTOSAR + + // CRC the payload first, skipping over the first byte where the CRC lives. + for (int i = 1; i < l; i++) { + crc ^= dat[i]; + crc = crc8_lut_8h2f[crc]; + } + + // Look up and apply the magic final CRC padding byte, which permutes by CAN + // address, and additionally (for SOME addresses) by the message counter. + uint8_t counter = dat[1] & 0x0F; + switch(address) { + case 0x86: // LWI_01 Steering Angle + crc ^= (uint8_t[]){0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86}[counter]; + break; + case 0x9F: // EPS_01 Electric Power Steering + crc ^= (uint8_t[]){0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5}[counter]; + break; + case 0xAD: // Getriebe_11 Automatic Gearbox + crc ^= (uint8_t[]){0x3F,0x69,0x39,0xDC,0x94,0xF9,0x14,0x64,0xD8,0x6A,0x34,0xCE,0xA2,0x55,0xB5,0x2C}[counter]; + break; + case 0xFD: // ESP_21 Electronic Stability Program + crc ^= (uint8_t[]){0xB4,0xEF,0xF8,0x49,0x1E,0xE5,0xC2,0xC0,0x97,0x19,0x3C,0xC9,0xF1,0x98,0xD6,0x61}[counter]; + break; + case 0x106: // ESP_05 Electronic Stability Program + crc ^= (uint8_t[]){0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07}[counter]; + break; + case 0x117: // ACC_10 Automatic Cruise Control + crc ^= (uint8_t[]){0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC}[counter]; + break; + case 0x122: // ACC_06 Automatic Cruise Control + crc ^= (uint8_t[]){0x37,0x7D,0xF3,0xA9,0x18,0x46,0x6D,0x4D,0x3D,0x71,0x92,0x9C,0xE5,0x32,0x10,0xB9}[counter]; + break; + case 0x126: // HCA_01 Heading Control Assist + crc ^= (uint8_t[]){0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA}[counter]; + break; + case 0x12B: // GRA_ACC_01 Steering wheel controls for ACC + crc ^= (uint8_t[]){0x6A,0x38,0xB4,0x27,0x22,0xEF,0xE1,0xBB,0xF8,0x80,0x84,0x49,0xC7,0x9E,0x1E,0x2B}[counter]; + break; + case 0x187: // EV_Gearshift "Gear" selection data for EVs with no gearbox + crc ^= (uint8_t[]){0x7F,0xED,0x17,0xC2,0x7C,0xEB,0x44,0x21,0x01,0xFA,0xDB,0x15,0x4A,0x6B,0x23,0x05}[counter]; + break; + case 0x30C: // ACC_02 Automatic Cruise Control + crc ^= (uint8_t[]){0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}[counter]; + break; + case 0x3C0: // Klemmen_Status_01 ignition and starting status + crc ^= (uint8_t[]){0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3}[counter]; + break; + case 0x65D: // ESP_20 Electronic Stability Program + crc ^= (uint8_t[]){0xAC,0xB3,0xAB,0xEB,0x7A,0xE1,0x3B,0xF7,0x73,0xBA,0x7C,0x9E,0x06,0x5F,0x02,0xD9}[counter]; + break; + default: // As-yet undefined CAN message, CRC check expected to fail + printf("Attempt to CRC check undefined Volkswagen message 0x%02X\n", address); + crc ^= (uint8_t[]){0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}[counter]; + break; + } + crc = crc8_lut_8h2f[crc]; + + return crc ^ 0xFF; // Return after standard final XOR for CRC8 8H2F/AUTOSAR +} + + +unsigned int pedal_checksum(uint64_t d, int l) { + uint8_t crc = 0xFF; + uint8_t poly = 0xD5; // standard crc8 + + d >>= ((8-l)*8); // remove padding + d >>= 8; // remove checksum + + uint8_t *dat = (uint8_t *)&d; + + int i, j; + for (i = 0; i < l - 1; i++) { + crc ^= dat[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) { + crc = (uint8_t)((crc << 1) ^ poly); + } + else { + crc <<= 1; + } + } + } + return crc; +} + + +uint64_t read_u64_be(const uint8_t* v) { + return (((uint64_t)v[0] << 56) + | ((uint64_t)v[1] << 48) + | ((uint64_t)v[2] << 40) + | ((uint64_t)v[3] << 32) + | ((uint64_t)v[4] << 24) + | ((uint64_t)v[5] << 16) + | ((uint64_t)v[6] << 8) + | (uint64_t)v[7]); +} + +uint64_t read_u64_le(const uint8_t* v) { + return ((uint64_t)v[0] + | ((uint64_t)v[1] << 8) + | ((uint64_t)v[2] << 16) + | ((uint64_t)v[3] << 24) + | ((uint64_t)v[4] << 32) + | ((uint64_t)v[5] << 40) + | ((uint64_t)v[6] << 48) + | ((uint64_t)v[7] << 56)); +} diff --git a/can/common.h b/can/common.h new file mode 100644 index 0000000000..4d0e14cbc9 --- /dev/null +++ b/can/common.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include "common_dbc.h" +#include +#include "cereal/gen/cpp/log.capnp.h" + +#define MAX_BAD_COUNTER 5 + +// Helper functions +unsigned int honda_checksum(unsigned int address, uint64_t d, int l); +unsigned int toyota_checksum(unsigned int address, uint64_t d, int l); +void init_crc_lookup_tables(); +unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l); +unsigned int pedal_checksum(uint64_t d, int l); +uint64_t read_u64_be(const uint8_t* v); +uint64_t read_u64_le(const uint8_t* v); + +class MessageState { +public: + uint32_t address; + unsigned int size; + + std::vector parse_sigs; + std::vector vals; + + uint16_t ts; + uint64_t seen; + uint64_t check_threshold; + + uint8_t counter; + uint8_t counter_fail; + + bool parse(uint64_t sec, uint16_t ts_, uint8_t * dat); + bool update_counter_generic(int64_t v, int cnt_size); +}; + +class CANParser { +private: + const int bus; + + const DBC *dbc = NULL; + std::unordered_map message_states; + +public: + bool can_valid = false; + uint64_t last_sec = 0; + + CANParser(int abus, const std::string& dbc_name, + const std::vector &options, + const std::vector &sigoptions); + void UpdateCans(uint64_t sec, const capnp::List::Reader& cans); + void UpdateValid(uint64_t sec); + void update_string(std::string data, bool sendcan); + std::vector query_latest(); +}; + +class CANPacker { +private: + const DBC *dbc = NULL; + std::map, Signal> signal_lookup; + std::map message_lookup; + +public: + CANPacker(const std::string& dbc_name); + uint64_t pack(uint32_t address, const std::vector &signals, int counter); +}; diff --git a/can/common.pxd b/can/common.pxd new file mode 100644 index 0000000000..e07e0b35c7 --- /dev/null +++ b/can/common.pxd @@ -0,0 +1,82 @@ +# distutils: language = c++ +#cython: language_level=3 + +from libc.stdint cimport uint32_t, uint64_t, uint16_t +from libcpp.vector cimport vector +from libcpp.map cimport map +from libcpp.string cimport string +from libcpp.unordered_set cimport unordered_set +from libcpp cimport bool + + +cdef extern from "common_dbc.h": + ctypedef enum SignalType: + DEFAULT, + HONDA_CHECKSUM, + HONDA_COUNTER, + TOYOTA_CHECKSUM, + PEDAL_CHECKSUM, + PEDAL_COUNTER, + VOLKSWAGEN_CHECKSUM, + VOLKSWAGEN_COUNTER + + cdef struct Signal: + const char* name + int b1, b2, bo + bool is_signed + double factor, offset + SignalType type + + cdef struct Msg: + const char* name + uint32_t address + unsigned int size + size_t num_sigs + const Signal *sigs + + cdef struct Val: + const char* name + uint32_t address + const char* def_val + const Signal *sigs + + cdef struct DBC: + const char* name + size_t num_msgs + const Msg *msgs + const Val *vals + size_t num_vals + + cdef struct SignalParseOptions: + uint32_t address + const char* name + double default_value + + + cdef struct MessageParseOptions: + uint32_t address + int check_frequency + + cdef struct SignalValue: + uint32_t address + uint16_t ts + const char* name + double value + + cdef struct SignalPackValue: + const char * name + double value + + +cdef extern from "common.h": + cdef const DBC* dbc_lookup(const string); + + cdef cppclass CANParser: + bool can_valid + CANParser(int, string, vector[MessageParseOptions], vector[SignalParseOptions]) + void update_string(string, bool) + vector[SignalValue] query_latest() + + cdef cppclass CANPacker: + CANPacker(string) + uint64_t pack(uint32_t, vector[SignalPackValue], int counter) diff --git a/can/common_dbc.h b/can/common_dbc.h new file mode 100644 index 0000000000..ae6f443ec9 --- /dev/null +++ b/can/common_dbc.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include + +#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) + +struct SignalPackValue { + const char* name; + double value; +}; + +struct SignalParseOptions { + uint32_t address; + const char* name; + double default_value; +}; + +struct MessageParseOptions { + uint32_t address; + int check_frequency; +}; + +struct SignalValue { + uint32_t address; + uint16_t ts; + const char* name; + double value; +}; + +enum SignalType { + DEFAULT, + HONDA_CHECKSUM, + HONDA_COUNTER, + TOYOTA_CHECKSUM, + PEDAL_CHECKSUM, + PEDAL_COUNTER, + VOLKSWAGEN_CHECKSUM, + VOLKSWAGEN_COUNTER, +}; + +struct Signal { + const char* name; + int b1, b2, bo; + bool is_signed; + double factor, offset; + bool is_little_endian; + SignalType type; +}; + +struct Msg { + const char* name; + uint32_t address; + unsigned int size; + size_t num_sigs; + const Signal *sigs; +}; + +struct Val { + const char* name; + uint32_t address; + const char* def_val; + const Signal *sigs; +}; + +struct DBC { + const char* name; + size_t num_msgs; + const Msg *msgs; + const Val *vals; + size_t num_vals; +}; + +const DBC* dbc_lookup(const std::string& dbc_name); + +void dbc_register(const DBC* dbc); + +#define dbc_init(dbc) \ +static void __attribute__((constructor)) do_dbc_init_ ## dbc(void) { \ + dbc_register(&dbc); \ +} diff --git a/can/dbc.cc b/can/dbc.cc new file mode 100644 index 0000000000..6587de7fe0 --- /dev/null +++ b/can/dbc.cc @@ -0,0 +1,31 @@ +#include + +#include "common_dbc.h" + +namespace { + +std::vector& get_dbcs() { + static std::vector vec; + return vec; +} + +} + +const DBC* dbc_lookup(const std::string& dbc_name) { + for (const auto& dbci : get_dbcs()) { + if (dbc_name == dbci->name) { + return dbci; + } + } + return NULL; +} + +void dbc_register(const DBC* dbc) { + get_dbcs().push_back(dbc); +} + +extern "C" { + const DBC* dbc_lookup(const char* dbc_name) { + return dbc_lookup(std::string(dbc_name)); + } +} diff --git a/can/dbc.py b/can/dbc.py new file mode 100755 index 0000000000..ed5ea74851 --- /dev/null +++ b/can/dbc.py @@ -0,0 +1,275 @@ +import re +import os +import struct +import sys +import numbers +from collections import namedtuple, defaultdict + +def int_or_float(s): + # return number, trying to maintain int format + if s.isdigit(): + return int(s, 10) + else: + return float(s) + +DBCSignal = namedtuple( + "DBCSignal", ["name", "start_bit", "size", "is_little_endian", "is_signed", + "factor", "offset", "tmin", "tmax", "units"]) + + +class dbc(): + def __init__(self, fn): + self.name, _ = os.path.splitext(os.path.basename(fn)) + with open(fn, encoding="ascii") as f: + self.txt = f.readlines() + self._warned_addresses = set() + + # regexps from https://github.com/ebroecker/canmatrix/blob/master/canmatrix/importdbc.py + bo_regexp = re.compile(r"^BO\_ (\w+) (\w+) *: (\w+) (\w+)") + sg_regexp = re.compile(r"^SG\_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*)") + sgm_regexp = re.compile(r"^SG\_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*)") + val_regexp = re.compile(r"VAL\_ (\w+) (\w+) (\s*[-+]?[0-9]+\s+\".+?\"[^;]*)") + + # A dictionary which maps message ids to tuples ((name, size), signals). + # name is the ASCII name of the message. + # size is the size of the message in bytes. + # signals is a list signals contained in the message. + # signals is a list of DBCSignal in order of increasing start_bit. + self.msgs = {} + + # A dictionary which maps message ids to a list of tuples (signal name, definition value pairs) + self.def_vals = defaultdict(list) + + # lookup to bit reverse each byte + self.bits_index = [(i & ~0b111) + ((-i-1) & 0b111) for i in range(64)] + + for l in self.txt: + l = l.strip() + + if l.startswith("BO_ "): + # new group + dat = bo_regexp.match(l) + + if dat is None: + print("bad BO {0}".format(l)) + + name = dat.group(2) + size = int(dat.group(3)) + ids = int(dat.group(1), 0) # could be hex + if ids in self.msgs: + sys.exit("Duplicate address detected %d %s" % (ids, self.name)) + + self.msgs[ids] = ((name, size), []) + + if l.startswith("SG_ "): + # new signal + dat = sg_regexp.match(l) + go = 0 + if dat is None: + dat = sgm_regexp.match(l) + go = 1 + + if dat is None: + print("bad SG {0}".format(l)) + + sgname = dat.group(1) + start_bit = int(dat.group(go+2)) + signal_size = int(dat.group(go+3)) + is_little_endian = int(dat.group(go+4))==1 + is_signed = dat.group(go+5)=='-' + factor = int_or_float(dat.group(go+6)) + offset = int_or_float(dat.group(go+7)) + tmin = int_or_float(dat.group(go+8)) + tmax = int_or_float(dat.group(go+9)) + units = dat.group(go+10) + + self.msgs[ids][1].append( + DBCSignal(sgname, start_bit, signal_size, is_little_endian, + is_signed, factor, offset, tmin, tmax, units)) + + if l.startswith("VAL_ "): + # new signal value/definition + dat = val_regexp.match(l) + + if dat is None: + print("bad VAL {0}".format(l)) + + ids = int(dat.group(1), 0) # could be hex + sgname = dat.group(2) + defvals = dat.group(3) + + defvals = defvals.replace("?",r"\?") #escape sequence in C++ + defvals = defvals.split('"')[:-1] + + # convert strings to UPPER_CASE_WITH_UNDERSCORES + defvals[1::2] = [d.strip().upper().replace(" ","_") for d in defvals[1::2]] + defvals = '"'+"".join(str(i) for i in defvals)+'"' + + self.def_vals[ids].append((sgname, defvals)) + + for msg in self.msgs.values(): + msg[1].sort(key=lambda x: x.start_bit) + + self.msg_name_to_address = {} + for address, m in self.msgs.items(): + name = m[0][0] + self.msg_name_to_address[name] = address + + def lookup_msg_id(self, msg_id): + if not isinstance(msg_id, numbers.Number): + msg_id = self.msg_name_to_address[msg_id] + return msg_id + + def reverse_bytes(self, x): + return ((x & 0xff00000000000000) >> 56) | \ + ((x & 0x00ff000000000000) >> 40) | \ + ((x & 0x0000ff0000000000) >> 24) | \ + ((x & 0x000000ff00000000) >> 8) | \ + ((x & 0x00000000ff000000) << 8) | \ + ((x & 0x0000000000ff0000) << 24) | \ + ((x & 0x000000000000ff00) << 40) | \ + ((x & 0x00000000000000ff) << 56) + + def encode(self, msg_id, dd): + """Encode a CAN message using the dbc. + + Inputs: + msg_id: The message ID. + dd: A dictionary mapping signal name to signal data. + """ + msg_id = self.lookup_msg_id(msg_id) + + msg_def = self.msgs[msg_id] + size = msg_def[0][1] + + result = 0 + for s in msg_def[1]: + ival = dd.get(s.name) + if ival is not None: + + ival = (ival / s.factor) - s.offset + ival = int(round(ival)) + + if s.is_signed and ival < 0: + ival = (1 << s.size) + ival + + if s.is_little_endian: + shift = s.start_bit + else: + b1 = (s.start_bit // 8) * 8 + (-s.start_bit - 1) % 8 + shift = 64 - (b1 + s.size) + + mask = ((1 << s.size) - 1) << shift + dat = (ival & ((1 << s.size) - 1)) << shift + + if s.is_little_endian: + mask = self.reverse_bytes(mask) + dat = self.reverse_bytes(dat) + + result &= ~mask + result |= dat + + result = struct.pack('>Q', result) + return result[:size] + + def decode(self, x, arr=None, debug=False): + """Decode a CAN message using the dbc. + + Inputs: + x: A collection with elements (address, time, data), where address is + the CAN address, time is the bus time, and data is the CAN data as a + hex string. + arr: Optional list of signals which should be decoded and returned. + debug: True to print debugging statements. + + Returns: + A tuple (name, data), where name is the name of the CAN message and data + is the decoded result. If arr is None, data is a dict of properties. + Otherwise data is a list of the same length as arr. + + Returns (None, None) if the message could not be decoded. + """ + + if arr is None: + out = {} + else: + out = [None]*len(arr) + + msg = self.msgs.get(x[0]) + if msg is None: + if x[0] not in self._warned_addresses: + #print("WARNING: Unknown message address {}".format(x[0])) + self._warned_addresses.add(x[0]) + return None, None + + name = msg[0][0] + if debug: + print(name) + + st = x[2].ljust(8, b'\x00') + le, be = None, None + + for s in msg[1]: + if arr is not None and s[0] not in arr: + continue + + start_bit = s[1] + signal_size = s[2] + little_endian = s[3] + signed = s[4] + factor = s[5] + offset = s[6] + + if little_endian: + if le is None: + le = struct.unpack("Q", st)[0] + tmp = be + b1 = (start_bit // 8) * 8 + (-start_bit - 1) % 8 + shift_amount = 64 - (b1 + signal_size) + + if shift_amount < 0: + continue + + tmp = (tmp >> shift_amount) & ((1 << signal_size) - 1) + if signed and (tmp >> (signal_size - 1)): + tmp -= (1 << signal_size) + + tmp = tmp * factor + offset + + # if debug: + # print("%40s %2d %2d %7.2f %s" % (s[0], s[1], s[2], tmp, s[-1])) + + if arr is None: + out[s[0]] = tmp + else: + out[arr.index(s[0])] = tmp + return name, out + + def get_signals(self, msg): + msg = self.lookup_msg_id(msg) + return [sgs.name for sgs in self.msgs[msg][1]] + + +if __name__ == "__main__": + from opendbc import DBC_PATH + + dbc_test = dbc(os.path.join(DBC_PATH, 'toyota_prius_2017_pt_generated.dbc')) + msg = ('STEER_ANGLE_SENSOR', {'STEER_ANGLE': -6.0, 'STEER_RATE': 4, 'STEER_FRACTION': -0.2}) + encoded = dbc_test.encode(*msg) + decoded = dbc_test.decode((0x25, 0, encoded)) + assert decoded == msg + + dbc_test = dbc(os.path.join(DBC_PATH, 'hyundai_santa_fe_2019_ccan.dbc')) + decoded = dbc_test.decode((0x2b0, 0, "\xfa\xfe\x00\x07\x12")) + assert abs(decoded[1]['SAS_Angle'] - (-26.2)) < 0.001 + + msg = ('SAS11', {'SAS_Stat': 7.0, 'MsgCount': 0.0, 'SAS_Angle': -26.200000000000003, 'SAS_Speed': 0.0, 'CheckSum': 0.0}) + encoded = dbc_test.encode(*msg) + decoded = dbc_test.decode((0x2b0, 0, encoded)) + + assert decoded == msg diff --git a/can/dbc_out/.gitignore b/can/dbc_out/.gitignore new file mode 100644 index 0000000000..4625581a85 --- /dev/null +++ b/can/dbc_out/.gitignore @@ -0,0 +1,2 @@ +*.cc + diff --git a/can/dbc_out/.gitkeep b/can/dbc_out/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/can/dbc_template.cc b/can/dbc_template.cc new file mode 100644 index 0000000000..f9540fcee9 --- /dev/null +++ b/can/dbc_template.cc @@ -0,0 +1,81 @@ +#include "common_dbc.h" + +namespace { + +{% for address, msg_name, msg_size, sigs in msgs %} +const Signal sigs_{{address}}[] = { + {% for sig in sigs %} + { + {% if sig.is_little_endian %} + {% set b1 = sig.start_bit %} + {% else %} + {% set b1 = (sig.start_bit//8)*8 + (-sig.start_bit-1) % 8 %} + {% endif %} + .name = "{{sig.name}}", + .b1 = {{b1}}, + .b2 = {{sig.size}}, + .bo = {{64 - (b1 + sig.size)}}, + .is_signed = {{"true" if sig.is_signed else "false"}}, + .factor = {{sig.factor}}, + .offset = {{sig.offset}}, + .is_little_endian = {{"true" if sig.is_little_endian else "false"}}, + {% if checksum_type == "honda" and sig.name == "CHECKSUM" %} + .type = SignalType::HONDA_CHECKSUM, + {% elif checksum_type == "honda" and sig.name == "COUNTER" %} + .type = SignalType::HONDA_COUNTER, + {% elif checksum_type == "toyota" and sig.name == "CHECKSUM" %} + .type = SignalType::TOYOTA_CHECKSUM, + {% elif checksum_type == "volkswagen" and sig.name == "CHECKSUM" %} + .type = SignalType::VOLKSWAGEN_CHECKSUM, + {% elif checksum_type == "volkswagen" and sig.name == "COUNTER" %} + .type = SignalType::VOLKSWAGEN_COUNTER, + {% elif address in [512, 513] and sig.name == "CHECKSUM_PEDAL" %} + .type = SignalType::PEDAL_CHECKSUM, + {% elif address in [512, 513] and sig.name == "COUNTER_PEDAL" %} + .type = SignalType::PEDAL_COUNTER, + {% else %} + .type = SignalType::DEFAULT, + {% endif %} + }, + {% endfor %} +}; +{% endfor %} + +const Msg msgs[] = { +{% for address, msg_name, msg_size, sigs in msgs %} + {% set address_hex = "0x%X" % address %} + { + .name = "{{msg_name}}", + .address = {{address_hex}}, + .size = {{msg_size}}, + .num_sigs = ARRAYSIZE(sigs_{{address}}), + .sigs = sigs_{{address}}, + }, +{% endfor %} +}; + +const Val vals[] = { +{% for address, sig in def_vals %} + {% for sg_name, def_val in sig %} + {% set address_hex = "0x%X" % address %} + { + .name = "{{sg_name}}", + .address = {{address_hex}}, + .def_val = {{def_val}}, + .sigs = sigs_{{address}}, + }, + {% endfor %} +{% endfor %} +}; + +} + +const DBC {{dbc.name}} = { + .name = "{{dbc.name}}", + .num_msgs = ARRAYSIZE(msgs), + .msgs = msgs, + .vals = vals, + .num_vals = ARRAYSIZE(vals), +}; + +dbc_init({{dbc.name}}) diff --git a/can/packer.cc b/can/packer.cc new file mode 100644 index 0000000000..fb81952768 --- /dev/null +++ b/can/packer.cc @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include + +#include "common.h" + +#define WARN printf + +// this is the same as read_u64_le, but uses uint64_t as in/out +uint64_t ReverseBytes(uint64_t x) { + return ((x & 0xff00000000000000ull) >> 56) | + ((x & 0x00ff000000000000ull) >> 40) | + ((x & 0x0000ff0000000000ull) >> 24) | + ((x & 0x000000ff00000000ull) >> 8) | + ((x & 0x00000000ff000000ull) << 8) | + ((x & 0x0000000000ff0000ull) << 24) | + ((x & 0x000000000000ff00ull) << 40) | + ((x & 0x00000000000000ffull) << 56); +} + +uint64_t set_value(uint64_t ret, Signal sig, int64_t ival){ + int shift = sig.is_little_endian? sig.b1 : sig.bo; + uint64_t mask = ((1ULL << sig.b2)-1) << shift; + uint64_t dat = (ival & ((1ULL << sig.b2)-1)) << shift; + if (sig.is_little_endian) { + dat = ReverseBytes(dat); + mask = ReverseBytes(mask); + } + ret &= ~mask; + ret |= dat; + return ret; +} + +CANPacker::CANPacker(const std::string& dbc_name) { + dbc = dbc_lookup(dbc_name); + assert(dbc); + + for (int i=0; inum_msgs; i++) { + const Msg* msg = &dbc->msgs[i]; + message_lookup[msg->address] = *msg; + for (int j=0; jnum_sigs; j++) { + const Signal* sig = &msg->sigs[j]; + signal_lookup[std::make_pair(msg->address, std::string(sig->name))] = *sig; + } + } + init_crc_lookup_tables(); +} + +uint64_t CANPacker::pack(uint32_t address, const std::vector &signals, int counter) { + uint64_t ret = 0; + for (const auto& sigval : signals) { + std::string name = std::string(sigval.name); + double value = sigval.value; + + auto sig_it = signal_lookup.find(std::make_pair(address, name)); + if (sig_it == signal_lookup.end()) { + WARN("undefined signal %s - %d\n", name.c_str(), address); + continue; + } + auto sig = sig_it->second; + + int64_t ival = (int64_t)(round((value - sig.offset) / sig.factor)); + if (ival < 0) { + ival = (1ULL << sig.b2) + ival; + } + + ret = set_value(ret, sig, ival); + } + + if (counter >= 0){ + auto sig_it = signal_lookup.find(std::make_pair(address, "COUNTER")); + if (sig_it == signal_lookup.end()) { + WARN("COUNTER not defined\n"); + return ret; + } + auto sig = sig_it->second; + + if ((sig.type != SignalType::HONDA_COUNTER) && (sig.type != SignalType::VOLKSWAGEN_COUNTER)) { + WARN("COUNTER signal type not valid\n"); + } + + ret = set_value(ret, sig, counter); + } + + auto sig_it_checksum = signal_lookup.find(std::make_pair(address, "CHECKSUM")); + if (sig_it_checksum != signal_lookup.end()) { + auto sig = sig_it_checksum->second; + if (sig.type == SignalType::HONDA_CHECKSUM) { + unsigned int chksm = honda_checksum(address, ret, message_lookup[address].size); + ret = set_value(ret, sig, chksm); + } else if (sig.type == SignalType::TOYOTA_CHECKSUM) { + unsigned int chksm = toyota_checksum(address, ret, message_lookup[address].size); + ret = set_value(ret, sig, chksm); + } else if (sig.type == SignalType::VOLKSWAGEN_CHECKSUM) { + // FIXME: Hackish fix for an endianness issue. The message is in reverse byte order + // until later in the pack process. Checksums can be run backwards, CRCs not so much. + // The correct fix is unclear but this works for the moment. + unsigned int chksm = volkswagen_crc(address, ReverseBytes(ret), message_lookup[address].size); + ret = set_value(ret, sig, chksm); + } else { + //WARN("CHECKSUM signal type not valid\n"); + } + } + + return ret; +} diff --git a/can/packer.py b/can/packer.py new file mode 100644 index 0000000000..fc22cce005 --- /dev/null +++ b/can/packer.py @@ -0,0 +1,3 @@ +# pylint: skip-file +from opendbc.can.packer_pyx import CANPacker +assert CANPacker diff --git a/can/packer_pyx.pyx b/can/packer_pyx.pyx new file mode 100644 index 0000000000..00f83eca65 --- /dev/null +++ b/can/packer_pyx.pyx @@ -0,0 +1,67 @@ +# distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + +from libc.stdint cimport uint32_t, uint64_t +from libcpp.vector cimport vector +from libcpp.map cimport map +from libcpp.string cimport string +from libcpp cimport bool +from posix.dlfcn cimport dlopen, dlsym, RTLD_LAZY + +from common cimport CANPacker as cpp_CANPacker +from common cimport dbc_lookup, SignalPackValue, DBC + + +cdef class CANPacker: + cdef: + cpp_CANPacker *packer + const DBC *dbc + map[string, (int, int)] name_to_address_and_size + map[int, int] address_to_size + + def __init__(self, dbc_name): + self.packer = new cpp_CANPacker(dbc_name) + self.dbc = dbc_lookup(dbc_name) + + num_msgs = self.dbc[0].num_msgs + for i in range(num_msgs): + msg = self.dbc[0].msgs[i] + self.name_to_address_and_size[string(msg.name)] = (msg.address, msg.size) + self.address_to_size[msg.address] = msg.size + + cdef uint64_t pack(self, addr, values, counter): + cdef vector[SignalPackValue] values_thing + cdef SignalPackValue spv + + names = [] + + for name, value in values.iteritems(): + n = name.encode('utf8') + names.append(n) # TODO: find better way to keep reference to temp string arround + + spv.name = n + spv.value = value + values_thing.push_back(spv) + + return self.packer.pack(addr, values_thing, counter) + + cdef inline uint64_t ReverseBytes(self, uint64_t x): + return (((x & 0xff00000000000000ull) >> 56) | + ((x & 0x00ff000000000000ull) >> 40) | + ((x & 0x0000ff0000000000ull) >> 24) | + ((x & 0x000000ff00000000ull) >> 8) | + ((x & 0x00000000ff000000ull) << 8) | + ((x & 0x0000000000ff0000ull) << 24) | + ((x & 0x000000000000ff00ull) << 40) | + ((x & 0x00000000000000ffull) << 56)) + + cpdef make_can_msg(self, name_or_addr, bus, values, counter=-1): + cdef int addr, size + if type(name_or_addr) == int: + addr = name_or_addr + size = self.address_to_size[name_or_addr] + else: + addr, size = self.name_to_address_and_size[name_or_addr.encode('utf8')] + cdef uint64_t val = self.pack(addr, values, counter) + val = self.ReverseBytes(val) + return [addr, 0, (&val)[:size], bus] diff --git a/can/packer_pyx_setup.py b/can/packer_pyx_setup.py new file mode 100644 index 0000000000..6f7a47d0ae --- /dev/null +++ b/can/packer_pyx_setup.py @@ -0,0 +1,60 @@ +import os +import sysconfig +import subprocess +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + +from Cython.Build import cythonize +from Cython.Distutils import build_ext + +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../")) + + +def get_ext_filename_without_platform_suffix(filename): + name, ext = os.path.splitext(filename) + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + + if ext_suffix == ext: + return filename + + ext_suffix = ext_suffix.replace(ext, '') + idx = name.find(ext_suffix) + + if idx == -1: + return filename + else: + return name[:idx] + ext + + +class BuildExtWithoutPlatformSuffix(build_ext): + def get_ext_filename(self, ext_name): + filename = super().get_ext_filename(ext_name) + return get_ext_filename_without_platform_suffix(filename) + + +sourcefiles = ['packer_pyx.pyx'] +extra_compile_args = ["-std=c++11"] +ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg + +if ARCH == "aarch64": + extra_compile_args += ["-Wno-deprecated-register"] + + +setup(name='CAN packer', + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, + ext_modules=cythonize( + Extension( + "packer_pyx", + language="c++", + sources=sourcefiles, + extra_compile_args=extra_compile_args, + include_dirs=[ + BASEDIR, + os.path.join(BASEDIR, 'phonelibs', 'capnp-cpp/include'), + ], + extra_link_args=[ + os.path.join(BASEDIR, 'opendbc', 'can', 'libdbc.so'), + ], + ) + ), + nthreads=4, +) diff --git a/can/parser.cc b/can/parser.cc new file mode 100644 index 0000000000..69fe3747a2 --- /dev/null +++ b/can/parser.cc @@ -0,0 +1,239 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "common.h" + +#define DEBUG(...) +// #define DEBUG printf +#define INFO printf + + +bool MessageState::parse(uint64_t sec, uint16_t ts_, uint8_t * dat) { + uint64_t dat_le = read_u64_le(dat); + uint64_t dat_be = read_u64_be(dat); + + for (int i=0; i < parse_sigs.size(); i++) { + auto& sig = parse_sigs[i]; + int64_t tmp; + + if (sig.is_little_endian){ + tmp = (dat_le >> sig.b1) & ((1ULL << sig.b2)-1); + } else { + tmp = (dat_be >> sig.bo) & ((1ULL << sig.b2)-1); + } + + if (sig.is_signed) { + tmp -= (tmp >> (sig.b2-1)) ? (1ULL << sig.b2) : 0; //signed + } + + DEBUG("parse 0x%X %s -> %lld\n", address, sig.name, tmp); + + if (sig.type == SignalType::HONDA_CHECKSUM) { + if (honda_checksum(address, dat_be, size) != tmp) { + INFO("0x%X CHECKSUM FAIL\n", address); + return false; + } + } else if (sig.type == SignalType::HONDA_COUNTER) { + if (!update_counter_generic(tmp, sig.b2)) { + return false; + } + } else if (sig.type == SignalType::TOYOTA_CHECKSUM) { + if (toyota_checksum(address, dat_be, size) != tmp) { + INFO("0x%X CHECKSUM FAIL\n", address); + return false; + } + } else if (sig.type == SignalType::VOLKSWAGEN_CHECKSUM) { + if (volkswagen_crc(address, dat_le, size) != tmp) { + INFO("0x%X CRC FAIL\n", address); + return false; + } + } else if (sig.type == SignalType::VOLKSWAGEN_COUNTER) { + if (!update_counter_generic(tmp, sig.b2)) { + return false; + } + } else if (sig.type == SignalType::PEDAL_CHECKSUM) { + if (pedal_checksum(dat_be, size) != tmp) { + INFO("0x%X PEDAL CHECKSUM FAIL\n", address); + return false; + } + } else if (sig.type == SignalType::PEDAL_COUNTER) { + if (!update_counter_generic(tmp, sig.b2)) { + return false; + } + } + + vals[i] = tmp * sig.factor + sig.offset; + } + ts = ts_; + seen = sec; + + return true; +} + + +bool MessageState::update_counter_generic(int64_t v, int cnt_size) { + uint8_t old_counter = counter; + counter = v; + if (((old_counter+1) & ((1 << cnt_size) -1)) != v) { + counter_fail += 1; + if (counter_fail > 1) { + INFO("0x%X COUNTER FAIL %d -- %d vs %d\n", address, counter_fail, old_counter, (int)v); + } + if (counter_fail >= MAX_BAD_COUNTER) { + return false; + } + } else if (counter_fail > 0) { + counter_fail--; + } + return true; +} + + +CANParser::CANParser(int abus, const std::string& dbc_name, + const std::vector &options, + const std::vector &sigoptions) + : bus(abus) { + + dbc = dbc_lookup(dbc_name); + assert(dbc); + init_crc_lookup_tables(); + + for (const auto& op : options) { + MessageState state = { + .address = op.address, + // .check_frequency = op.check_frequency, + }; + + // msg is not valid if a message isn't received for 10 consecutive steps + if (op.check_frequency > 0) { + state.check_threshold = (1000000000ULL / op.check_frequency) * 10; + } + + + const Msg* msg = NULL; + for (int i=0; inum_msgs; i++) { + if (dbc->msgs[i].address == op.address) { + msg = &dbc->msgs[i]; + break; + } + } + if (!msg) { + fprintf(stderr, "CANParser: could not find message 0x%X in DBC %s\n", op.address, dbc_name.c_str()); + assert(false); + } + + state.size = msg->size; + + // track checksums and counters for this message + for (int i=0; inum_sigs; i++) { + const Signal *sig = &msg->sigs[i]; + if (sig->type != SignalType::DEFAULT) { + state.parse_sigs.push_back(*sig); + state.vals.push_back(0); + } + } + + // track requested signals for this message + for (const auto& sigop : sigoptions) { + if (sigop.address != op.address) continue; + + for (int i=0; inum_sigs; i++) { + const Signal *sig = &msg->sigs[i]; + if (strcmp(sig->name, sigop.name) == 0 + && sig->type == SignalType::DEFAULT) { + state.parse_sigs.push_back(*sig); + state.vals.push_back(sigop.default_value); + break; + } + } + + } + + message_states[state.address] = state; + } +} + +void CANParser::UpdateCans(uint64_t sec, const capnp::List::Reader& cans) { + int msg_count = cans.size(); + uint64_t p; + + DEBUG("got %d messages\n", msg_count); + + // parse the messages + for (int i = 0; i < msg_count; i++) { + auto cmsg = cans[i]; + if (cmsg.getSrc() != bus) { + // DEBUG("skip %d: wrong bus\n", cmsg.getAddress()); + continue; + } + auto state_it = message_states.find(cmsg.getAddress()); + if (state_it == message_states.end()) { + // DEBUG("skip %d: not specified\n", cmsg.getAddress()); + continue; + } + + if (cmsg.getDat().size() > 8) continue; //shouldnt ever happen + uint8_t dat[8] = {0}; + memcpy(dat, cmsg.getDat().begin(), cmsg.getDat().size()); + + state_it->second.parse(sec, cmsg.getBusTime(), dat); + } +} + +void CANParser::UpdateValid(uint64_t sec) { + can_valid = true; + for (const auto& kv : message_states) { + const auto& state = kv.second; + if (state.check_threshold > 0 && (sec - state.seen) > state.check_threshold) { + if (state.seen > 0) { + DEBUG("0x%X TIMEOUT\n", state.address); + } + can_valid = false; + } + } +} + +void CANParser::update_string(std::string data, bool sendcan) { + // format for board, make copy due to alignment issues, will be freed on out of scope + auto amsg = kj::heapArray((data.length() / sizeof(capnp::word)) + 1); + memcpy(amsg.begin(), data.data(), data.length()); + + // extract the messages + capnp::FlatArrayMessageReader cmsg(amsg); + cereal::Event::Reader event = cmsg.getRoot(); + + last_sec = event.getLogMonoTime(); + + auto cans = sendcan? event.getSendcan() : event.getCan(); + UpdateCans(last_sec, cans); + + UpdateValid(last_sec); +} + + +std::vector CANParser::query_latest() { + std::vector ret; + + for (const auto& kv : message_states) { + const auto& state = kv.second; + if (last_sec != 0 && state.seen != last_sec) continue; + + for (int i=0; iself.address_to_msg_name[cv.address].c_str() + cv_name = cv.name + + self.vl[cv.address][cv_name] = cv.value + self.ts[cv.address][cv_name] = cv.ts + + self.vl[name][cv_name] = cv.value + self.ts[name][cv_name] = cv.ts + + updated_val.insert(cv.address) + + return updated_val + + def update_string(self, dat, sendcan=False): + self.can.update_string(dat, sendcan) + return self.update_vl() + + def update_strings(self, strings, sendcan=False): + updated_vals = set() + + for s in strings: + updated_val = self.update_string(s, sendcan) + updated_vals.update(updated_val) + + return updated_vals + +cdef class CANDefine(): + cdef: + const DBC *dbc + + cdef public: + dict dv + string dbc_name + + def __init__(self, dbc_name): + self.dbc_name = dbc_name + self.dbc = dbc_lookup(dbc_name) + + num_vals = self.dbc[0].num_vals + + address_to_msg_name = {} + + num_msgs = self.dbc[0].num_msgs + for i in range(num_msgs): + msg = self.dbc[0].msgs[i] + name = msg.name.decode('utf8') + address = msg.address + address_to_msg_name[address] = name + + dv = defaultdict(dict) + + for i in range(num_vals): + val = self.dbc[0].vals[i] + + sgname = val.name.decode('utf8') + address = val.address + def_val = val.def_val.decode('utf8') + + #separate definition/value pairs + def_val = def_val.split() + values = [int(v) for v in def_val[::2]] + defs = def_val[1::2] + + if address not in dv: + dv[address] = {} + msgname = address_to_msg_name[address] + dv[msgname] = {} + + # two ways to lookup: address or msg name + dv[address][sgname] = dict(zip(values, defs)) + dv[msgname][sgname] = dv[address][sgname] + + self.dv = dict(dv) diff --git a/can/parser_pyx_setup.py b/can/parser_pyx_setup.py new file mode 100644 index 0000000000..8ce6e7e7b4 --- /dev/null +++ b/can/parser_pyx_setup.py @@ -0,0 +1,59 @@ +import os +import subprocess +import sysconfig +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + +from Cython.Build import cythonize +from Cython.Distutils import build_ext + +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../")) + + +def get_ext_filename_without_platform_suffix(filename): + name, ext = os.path.splitext(filename) + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + + if ext_suffix == ext: + return filename + + ext_suffix = ext_suffix.replace(ext, '') + idx = name.find(ext_suffix) + + if idx == -1: + return filename + else: + return name[:idx] + ext + + +class BuildExtWithoutPlatformSuffix(build_ext): + def get_ext_filename(self, ext_name): + filename = super().get_ext_filename(ext_name) + return get_ext_filename_without_platform_suffix(filename) + + +sourcefiles = ['parser_pyx.pyx'] +extra_compile_args = ["-std=c++11"] +ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg + +if ARCH == "aarch64": + extra_compile_args += ["-Wno-deprecated-register"] + +setup(name='CAN parser', + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, + ext_modules=cythonize( + Extension( + "parser_pyx", + language="c++", + sources=sourcefiles, + extra_compile_args=extra_compile_args, + include_dirs=[ + BASEDIR, + os.path.join(BASEDIR, 'phonelibs', 'capnp-cpp/include'), + ], + extra_link_args=[ + os.path.join(BASEDIR, 'opendbc', 'can', 'libdbc.so'), + ], + ) + ), + nthreads=4, +) diff --git a/can/process_dbc.py b/can/process_dbc.py new file mode 100755 index 0000000000..a1c91a8978 --- /dev/null +++ b/can/process_dbc.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +from __future__ import print_function +import os +import sys + +import jinja2 + +from collections import Counter +from opendbc.can.dbc import dbc + +def process(in_fn, out_fn): + dbc_name = os.path.split(out_fn)[-1].replace('.cc', '') + #print("processing %s: %s -> %s" % (dbc_name, in_fn, out_fn)) + + template_fn = os.path.join(os.path.dirname(__file__), "dbc_template.cc") + + with open(template_fn, "r") as template_f: + template = jinja2.Template(template_f.read(), trim_blocks=True, lstrip_blocks=True) + + can_dbc = dbc(in_fn) + + msgs = [(address, msg_name, msg_size, sorted(msg_sigs, key=lambda s: s.name not in ("COUNTER", "CHECKSUM"))) # process counter and checksums first + for address, ((msg_name, msg_size), msg_sigs) in sorted(can_dbc.msgs.items()) if msg_sigs] + + def_vals = {a: sorted(set(b)) for a, b in can_dbc.def_vals.items()} # remove duplicates + def_vals = sorted(def_vals.items()) + + if can_dbc.name.startswith(("honda_", "acura_")): + checksum_type = "honda" + checksum_size = 4 + counter_size = 2 + checksum_start_bit = 3 + counter_start_bit = 5 + little_endian = False + elif can_dbc.name.startswith(("toyota_", "lexus_")): + checksum_type = "toyota" + checksum_size = 8 + counter_size = None + checksum_start_bit = 7 + counter_start_bit = None + little_endian = False + elif can_dbc.name.startswith(("vw_", "volkswagen_", "audi_", "seat_", "skoda_")): + checksum_type = "volkswagen" + checksum_size = 8 + counter_size = 4 + checksum_start_bit = 0 + counter_start_bit = 0 + little_endian = True + else: + checksum_type = None + checksum_size = None + counter_size = None + checksum_start_bit = None + counter_start_bit = None + little_endian = None + + # sanity checks on expected COUNTER and CHECKSUM rules, as packer and parser auto-compute those signals + for address, msg_name, msg_size, sigs in msgs: + dbc_msg_name = dbc_name + " " + msg_name + for sig in sigs: + if checksum_type is not None: + # checksum rules + if sig.name == "CHECKSUM": + if sig.size != checksum_size: + sys.exit("%s: CHECKSUM is not %d bits long" % (dbc_msg_name, checksum_size)) + if sig.start_bit % 8 != checksum_start_bit: + sys.exit("%s: CHECKSUM starts at wrong bit" % dbc_msg_name) + if little_endian != sig.is_little_endian: + sys.exit("%s: CHECKSUM has wrong endianess" % dbc_msg_name) + # counter rules + if sig.name == "COUNTER": + if counter_size is not None and sig.size != counter_size: + sys.exit("%s: COUNTER is not %d bits long" % (dbc_msg_name, counter_size)) + if counter_start_bit is not None and sig.start_bit % 8 != counter_start_bit: + print(counter_start_bit, sig.start_bit) + sys.exit("%s: COUNTER starts at wrong bit" % dbc_msg_name) + if little_endian != sig.is_little_endian: + sys.exit("%s: COUNTER has wrong endianess" % dbc_msg_name) + # pedal rules + if address in [0x200, 0x201]: + if sig.name == "COUNTER_PEDAL" and sig.size != 4: + sys.exit("%s: PEDAL COUNTER is not 4 bits long" % dbc_msg_name) + if sig.name == "CHECKSUM_PEDAL" and sig.size != 8: + sys.exit("%s: PEDAL CHECKSUM is not 8 bits long" % dbc_msg_name) + + # Fail on duplicate message names + c = Counter([msg_name for address, msg_name, msg_size, sigs in msgs]) + for name, count in c.items(): + if count > 1: + sys.exit("%s: Duplicate message name in DBC file %s" % (dbc_name, name)) + + parser_code = template.render(dbc=can_dbc, checksum_type=checksum_type, msgs=msgs, def_vals=def_vals, len=len) + + with open(out_fn, "w") as out_f: + out_f.write(parser_code) + +def main(): + if len(sys.argv) != 3: + print("usage: %s dbc_directory output_filename" % (sys.argv[0],)) + sys.exit(0) + + dbc_dir = sys.argv[1] + out_fn = sys.argv[2] + + dbc_name = os.path.split(out_fn)[-1].replace('.cc', '') + in_fn = os.path.join(dbc_dir, dbc_name + '.dbc') + + process(in_fn, out_fn) + +if __name__ == '__main__': + main() + diff --git a/can/tests/.gitignore b/can/tests/.gitignore new file mode 100644 index 0000000000..192fb0945e --- /dev/null +++ b/can/tests/.gitignore @@ -0,0 +1 @@ +*.bz2 diff --git a/can/tests/__init__.py b/can/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/can/tests/linter_python/.pylintrc b/can/tests/linter_python/.pylintrc new file mode 100644 index 0000000000..64a55daf8f --- /dev/null +++ b/can/tests/linter_python/.pylintrc @@ -0,0 +1,585 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist=scipy + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. +jobs=4 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=print-statement, + parameter-unpacking, + unpacking-in-except, + old-raise-syntax, + backtick, + long-suffix, + old-ne-operator, + old-octal-literal, + import-star-module-level, + non-ascii-bytes-literal, + raw-checker-failed, + bad-inline-option, + locally-disabled, + locally-enabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + apply-builtin, + basestring-builtin, + buffer-builtin, + cmp-builtin, + coerce-builtin, + execfile-builtin, + file-builtin, + long-builtin, + raw_input-builtin, + reduce-builtin, + standarderror-builtin, + unicode-builtin, + xrange-builtin, + coerce-method, + delslice-method, + getslice-method, + setslice-method, + no-absolute-import, + old-division, + dict-iter-method, + dict-view-method, + next-method-called, + metaclass-assignment, + indexing-exception, + raising-string, + reload-builtin, + oct-method, + hex-method, + nonzero-method, + cmp-method, + input-builtin, + round-builtin, + intern-builtin, + unichr-builtin, + map-builtin-not-iterating, + zip-builtin-not-iterating, + range-builtin-not-iterating, + filter-builtin-not-iterating, + using-cmp-argument, + eq-without-hash, + div-method, + idiv-method, + rdiv-method, + exception-message-attribute, + invalid-str-codec, + sys-max-int, + bad-python3-import, + deprecated-string-function, + deprecated-str-translate-call, + deprecated-itertools-function, + deprecated-types-field, + next-method-defined, + dict-items-not-iterating, + dict-keys-not-iterating, + dict-values-not-iterating, + bad-indentation, + line-too-long, + missing-docstring, + multiple-statements, + bad-continuation, + invalid-name, + too-many-arguments, + too-many-locals, + superfluous-parens, + bad-whitespace, + too-many-instance-attributes, + wrong-import-position, + ungrouped-imports, + wrong-import-order, + protected-access, + trailing-whitespace, + too-many-branches, + too-few-public-methods, + too-many-statements, + trailing-newlines, + attribute-defined-outside-init, + too-many-return-statements, + too-many-public-methods, + unused-argument, + old-style-class, + no-init, + len-as-condition, + unneeded-not, + no-self-use, + multiple-imports, + no-else-return, + logging-not-lazy, + fixme, + redefined-outer-name, + unused-variable, + unsubscriptable-object, + expression-not-assigned, + too-many-boolean-expressions, + consider-using-ternary, + invalid-unary-operand-type, + relative-import, + deprecated-lambda + + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=c-extension-no-member + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=optparse.Values,sys.exit + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=capnp.* cereal.* pygame.* zmq.* setproctitle.* smbus2.* usb1.* serial.* cv2.* + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules=flask setproctitle usb1 flask.ext.socketio smbus2 usb1.* + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma, + dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[BASIC] + +# Naming style matching correct argument names +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style +#argument-rgx= + +# Naming style matching correct attribute names +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Naming style matching correct class attribute names +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style +#class-attribute-rgx= + +# Naming style matching correct class names +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming-style +#class-rgx= + +# Naming style matching correct constant names +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma +good-names=i, + j, + k, + ex, + Run, + _ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming style matching correct inline iteration names +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style +#inlinevar-rgx= + +# Naming style matching correct method names +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style +#method-rgx= + +# Naming style matching correct module names +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style +#variable-rgx= + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/can/tests/linter_python/flake8_opendbc.sh b/can/tests/linter_python/flake8_opendbc.sh new file mode 100755 index 0000000000..66402b2367 --- /dev/null +++ b/can/tests/linter_python/flake8_opendbc.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +RESULT=$(python3 -m flake8 --select=F $(find ../../../ -type f | grep "\.py$")) +if [[ $RESULT ]]; then + echo "Pyflakes found errors in the code. Please fix and try again" + echo "$RESULT" + exit 1 +fi diff --git a/can/tests/linter_python/pylint_opendbc.sh b/can/tests/linter_python/pylint_opendbc.sh new file mode 100755 index 0000000000..c2e7efc804 --- /dev/null +++ b/can/tests/linter_python/pylint_opendbc.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +python3 -m pylint --disable=R,C,W $(find ../../../ -type f | grep "\.py$") + +exit_status=$? +(( res = exit_status & 3 )) + +if [[ $res != 0 ]]; then + echo "Pylint found errors in the code. Please fix and try again" + exit 1 +fi diff --git a/can/tests/test_define.py b/can/tests/test_define.py new file mode 100644 index 0000000000..d9a6f7d671 --- /dev/null +++ b/can/tests/test_define.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.can.can_define import CANDefine + + +class TestCADNDefine(unittest.TestCase): + def test_civic(self): + + dbc_file = "honda_civic_touring_2016_can_generated" + defs = CANDefine(dbc_file) + + self.assertDictEqual(defs.dv[399], defs.dv['STEER_STATUS']) + self.assertDictEqual(defs.dv[399], + {'STEER_STATUS': + {6: 'TMP_FAULT', + 5: 'FAULT_1', + 4: 'NO_TORQUE_ALERT_2', + 3: 'LOW_SPEED_LOCKOUT', + 2: 'NO_TORQUE_ALERT_1', + 0: 'NORMAL'} + } + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/can/tests/test_packer_parser.py b/can/tests/test_packer_parser.py new file mode 100644 index 0000000000..1c28e8867c --- /dev/null +++ b/can/tests/test_packer_parser.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +import unittest + +from opendbc.can.parser import CANParser +from opendbc.can.packer import CANPacker +import cereal.messaging as messaging + + +# Python implementation so we don't have to depend on boardd +def can_list_to_can_capnp(can_msgs, msgtype='can'): + dat = messaging.new_message() + dat.init(msgtype, len(can_msgs)) + + for i, can_msg in enumerate(can_msgs): + if msgtype == 'sendcan': + cc = dat.sendcan[i] + else: + cc = dat.can[i] + + cc.address = can_msg[0] + cc.busTime = can_msg[1] + cc.dat = bytes(can_msg[2]) + cc.src = can_msg[3] + + return dat.to_bytes() + + +class TestCanParserPacker(unittest.TestCase): + def test_civic(self): + + dbc_file = "honda_civic_touring_2016_can_generated" + + signals = [ + ("STEER_TORQUE", "STEERING_CONTROL", 0), + ("STEER_TORQUE_REQUEST", "STEERING_CONTROL", 0), + ] + checks = [] + + parser = CANParser(dbc_file, signals, checks, 0) + packer = CANPacker(dbc_file) + + idx = 0 + + for steer in range(-256, 255): + for active in [1, 0]: + values = { + "STEER_TORQUE": steer, + "STEER_TORQUE_REQUEST": active, + } + + msgs = packer.make_can_msg("STEERING_CONTROL", 0, values, idx) + bts = can_list_to_can_capnp([msgs]) + + parser.update_string(bts) + + self.assertAlmostEqual(parser.vl["STEERING_CONTROL"]["STEER_TORQUE"], steer) + self.assertAlmostEqual(parser.vl["STEERING_CONTROL"]["STEER_TORQUE_REQUEST"], active) + self.assertAlmostEqual(parser.vl["STEERING_CONTROL"]["COUNTER"], idx % 4) + + idx += 1 + + def test_subaru(self): + # Subuaru is little endian + + dbc_file = "subaru_global_2017" + + signals = [ + ("Counter", "ES_LKAS", 0), + ("LKAS_Output", "ES_LKAS", 0), + ("LKAS_Request", "ES_LKAS", 0), + ("SET_1", "ES_LKAS", 0), + + ] + + checks = [] + + parser = CANParser(dbc_file, signals, checks, 0) + packer = CANPacker(dbc_file) + + idx = 0 + + for steer in range(-256, 255): + for active in [1, 0]: + values = { + "Counter": idx, + "LKAS_Output": steer, + "LKAS_Request": active, + "SET_1": 1 + } + + msgs = packer.make_can_msg("ES_LKAS", 0, values) + bts = can_list_to_can_capnp([msgs]) + parser.update_string(bts) + + self.assertAlmostEqual(parser.vl["ES_LKAS"]["LKAS_Output"], steer) + self.assertAlmostEqual(parser.vl["ES_LKAS"]["LKAS_Request"], active) + self.assertAlmostEqual(parser.vl["ES_LKAS"]["SET_1"], 1) + self.assertAlmostEqual(parser.vl["ES_LKAS"]["Counter"], idx % 16) + + idx += 1 + + +if __name__ == "__main__": + unittest.main() diff --git a/generator/honda/_bosch_2018.dbc b/generator/honda/_bosch_2018.dbc index 648f4b310c..19585529f0 100644 --- a/generator/honda/_bosch_2018.dbc +++ b/generator/honda/_bosch_2018.dbc @@ -91,8 +91,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/acura_ilx_2016_can.dbc b/generator/honda/acura_ilx_2016_can.dbc index e45426b3a6..df77448204 100644 --- a/generator/honda/acura_ilx_2016_can.dbc +++ b/generator/honda/acura_ilx_2016_can.dbc @@ -26,8 +26,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/acura_rdx_2018_can.dbc b/generator/honda/acura_rdx_2018_can.dbc index 87389f8b2c..2fccfd1b2e 100644 --- a/generator/honda/acura_rdx_2018_can.dbc +++ b/generator/honda/acura_rdx_2018_can.dbc @@ -14,8 +14,8 @@ BO_ 392 GEARBOX: 6 XXX SG_ GEAR : 36|5@0+ (1,0) [0|31] "" EON BO_ 399 STEER_STATUS: 6 EPS - SG_ STEER_TORQUE_SENSOR : 7|12@0- (1,0) [-2047.5|2047.5] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|12@0- (-1,0) [-2047.5|2047.5] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 35|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 36|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_civic_touring_2016_can.dbc b/generator/honda/honda_civic_touring_2016_can.dbc index 1a7579d2a2..2cce31609d 100644 --- a/generator/honda/honda_civic_touring_2016_can.dbc +++ b/generator/honda/honda_civic_touring_2016_can.dbc @@ -31,8 +31,8 @@ BO_ 330 STEERING_SENSORS: 8 EPS SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_crv_touring_2016_can.dbc b/generator/honda/honda_crv_touring_2016_can.dbc index 3d9b48ab71..b41171d434 100644 --- a/generator/honda/honda_crv_touring_2016_can.dbc +++ b/generator/honda/honda_crv_touring_2016_can.dbc @@ -8,8 +8,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 6 EPS - SG_ STEER_TORQUE_SENSOR : 7|12@0- (1,0) [-2047.5|2047.5] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|12@0- (-1,0) [-2047.5|2047.5] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_CONTROL_ACTIVE : 36|1@0+ (1,0) [0|1] "" EON SG_ STEER_STATUS : 35|4@0+ (1,0) [0|15] "" EON SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_fit_ex_2018_can.dbc b/generator/honda/honda_fit_ex_2018_can.dbc index ce02d4cf8a..9c2bf64b5a 100644 --- a/generator/honda/honda_fit_ex_2018_can.dbc +++ b/generator/honda/honda_fit_ex_2018_can.dbc @@ -26,8 +26,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_fit_hybrid_2018_can.dbc b/generator/honda/honda_fit_hybrid_2018_can.dbc index 6b0a896b71..4ad9f2a062 100644 --- a/generator/honda/honda_fit_hybrid_2018_can.dbc +++ b/generator/honda/honda_fit_hybrid_2018_can.dbc @@ -26,8 +26,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_odyssey_exl_2018.dbc b/generator/honda/honda_odyssey_exl_2018.dbc index fb54a29abc..8f04548910 100644 --- a/generator/honda/honda_odyssey_exl_2018.dbc +++ b/generator/honda/honda_odyssey_exl_2018.dbc @@ -18,8 +18,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_odyssey_extreme_edition_2018_china_can.dbc b/generator/honda/honda_odyssey_extreme_edition_2018_china_can.dbc index 2d0d7e2b5d..7927f8c80f 100644 --- a/generator/honda/honda_odyssey_extreme_edition_2018_china_can.dbc +++ b/generator/honda/honda_odyssey_extreme_edition_2018_china_can.dbc @@ -11,8 +11,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-2985|2985] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-2985|2985] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ CHECKSUM : 51|4@0+ (1,0) [0|15] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON SG_ STEER_STATUS : 43|4@0+ (1,0) [0|15] "" EON diff --git a/generator/honda/honda_pilot_touring_2017_can.dbc b/generator/honda/honda_pilot_touring_2017_can.dbc index 779cd66f5b..ea9ec39644 100644 --- a/generator/honda/honda_pilot_touring_2017_can.dbc +++ b/generator/honda/honda_pilot_touring_2017_can.dbc @@ -26,8 +26,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/generator/honda/honda_ridgeline_black_edition_2017_can.dbc b/generator/honda/honda_ridgeline_black_edition_2017_can.dbc index d070d314d5..cec7a08e7d 100644 --- a/generator/honda/honda_ridgeline_black_edition_2017_can.dbc +++ b/generator/honda/honda_ridgeline_black_edition_2017_can.dbc @@ -21,8 +21,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_accord_lx15t_2018_can_generated.dbc b/honda_accord_lx15t_2018_can_generated.dbc index 5b095ae793..0cf9ea5662 100644 --- a/honda_accord_lx15t_2018_can_generated.dbc +++ b/honda_accord_lx15t_2018_can_generated.dbc @@ -95,8 +95,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_accord_s2t_2018_can_generated.dbc b/honda_accord_s2t_2018_can_generated.dbc index 12a2b889fd..770cfdf1fd 100644 --- a/honda_accord_s2t_2018_can_generated.dbc +++ b/honda_accord_s2t_2018_can_generated.dbc @@ -95,8 +95,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_civic_hatchback_ex_2017_can_generated.dbc b/honda_civic_hatchback_ex_2017_can_generated.dbc index cfc8a6e48d..06c6edabdf 100644 --- a/honda_civic_hatchback_ex_2017_can_generated.dbc +++ b/honda_civic_hatchback_ex_2017_can_generated.dbc @@ -95,8 +95,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_civic_touring_2016_can_generated.dbc b/honda_civic_touring_2016_can_generated.dbc index 22f4a0b9fc..cb83511b3d 100644 --- a/honda_civic_touring_2016_can_generated.dbc +++ b/honda_civic_touring_2016_can_generated.dbc @@ -164,7 +164,7 @@ BO_ 780 ACC_HUD: 8 ADAS SG_ BOH : 38|1@0+ (1,0) [0|1] "" BDY SG_ ACC_PROBLEM : 37|1@0+ (1,0) [0|1] "" BDY SG_ FCM_OFF : 36|1@0+ (1,0) [0|1] "" BDY - SG_ BOH_2 : 35|1@0+ (1,0) [0|1] "" BDY + SG_ FCM_OFF_2 : 35|1@0+ (1,0) [0|1] "" BDY SG_ FCM_PROBLEM : 34|1@0+ (1,0) [0|1] "" BDY SG_ RADAR_OBSTRUCTED : 33|1@0+ (1,0) [0|1] "" BDY SG_ ENABLE_MINI_CAR : 32|1@0+ (1,0) [0|1] "" BDY @@ -174,10 +174,12 @@ BO_ 780 ACC_HUD: 8 ADAS SG_ BOH_4 : 42|1@0+ (1,0) [0|3] "" BDY SG_ BOH_5 : 41|1@0+ (1,0) [0|3] "" BDY SG_ CRUISE_CONTROL_LABEL : 40|1@0+ (1,0) [0|3] "" BDY - SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY - SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY SG_ SET_ME_X01_2 : 55|1@0+ (1,0) [0|1] "" BDY + SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY + SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY + SG_ CHIME : 51|3@0+ (1,0) [0|1] "" BDY SG_ SET_ME_X01 : 48|1@0+ (1,0) [0|1] "" BDY + SG_ ICONS : 63|2@0+ (1,0) [0|1] "" BDY SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" BDY @@ -276,8 +278,8 @@ BO_ 330 STEERING_SENSORS: 8 EPS SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_clarity_hybrid_2018_can.dbc b/honda_clarity_hybrid_2018_can.dbc index 3d46f52cd5..dfd30ff79c 100644 --- a/honda_clarity_hybrid_2018_can.dbc +++ b/honda_clarity_hybrid_2018_can.dbc @@ -91,8 +91,8 @@ BO_ 380 POWERTRAIN_DATA2: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" NEO BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" NEO - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" NEO + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" NEO + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" NEO SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" NEO SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" NEO SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" NEO diff --git a/honda_crv_ex_2017_can_generated.dbc b/honda_crv_ex_2017_can_generated.dbc index f8b6846c53..7aa93a9635 100644 --- a/honda_crv_ex_2017_can_generated.dbc +++ b/honda_crv_ex_2017_can_generated.dbc @@ -95,8 +95,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_crv_hybrid_2019_can_generated.dbc b/honda_crv_hybrid_2019_can_generated.dbc index eba7e72a22..5d3e81ecbd 100644 --- a/honda_crv_hybrid_2019_can_generated.dbc +++ b/honda_crv_hybrid_2019_can_generated.dbc @@ -95,8 +95,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_crv_touring_2016_can_generated.dbc b/honda_crv_touring_2016_can_generated.dbc index 9b5075ba62..dca4299487 100644 --- a/honda_crv_touring_2016_can_generated.dbc +++ b/honda_crv_touring_2016_can_generated.dbc @@ -253,8 +253,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 6 EPS - SG_ STEER_TORQUE_SENSOR : 7|12@0- (1,0) [-2047.5|2047.5] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|12@0- (-1,0) [-2047.5|2047.5] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_CONTROL_ACTIVE : 36|1@0+ (1,0) [0|1] "" EON SG_ STEER_STATUS : 35|4@0+ (1,0) [0|15] "" EON SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON diff --git a/honda_fit_ex_2018_can_generated.dbc b/honda_fit_ex_2018_can_generated.dbc index de9aca953f..df5fc95910 100644 --- a/honda_fit_ex_2018_can_generated.dbc +++ b/honda_fit_ex_2018_can_generated.dbc @@ -271,8 +271,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_fit_hybrid_2018_can_generated.dbc b/honda_fit_hybrid_2018_can_generated.dbc index 8d3db09ec4..3490737c8e 100644 --- a/honda_fit_hybrid_2018_can_generated.dbc +++ b/honda_fit_hybrid_2018_can_generated.dbc @@ -265,8 +265,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_insight_ex_2019_can_generated.dbc b/honda_insight_ex_2019_can_generated.dbc index 92fc0b50ac..890ae8a2e6 100644 --- a/honda_insight_ex_2019_can_generated.dbc +++ b/honda_insight_ex_2019_can_generated.dbc @@ -95,8 +95,8 @@ BO_ 380 POWERTRAIN_DATA: 8 PCM SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_odyssey_exl_2018_generated.dbc b/honda_odyssey_exl_2018_generated.dbc index 2899dba670..ae0394d5a6 100644 --- a/honda_odyssey_exl_2018_generated.dbc +++ b/honda_odyssey_exl_2018_generated.dbc @@ -263,8 +263,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_odyssey_extreme_edition_2018_china_can_generated.dbc b/honda_odyssey_extreme_edition_2018_china_can_generated.dbc index f8565c03b0..01b2b6f468 100644 --- a/honda_odyssey_extreme_edition_2018_china_can_generated.dbc +++ b/honda_odyssey_extreme_edition_2018_china_can_generated.dbc @@ -256,8 +256,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-2985|2985] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-2985|2985] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ CHECKSUM : 51|4@0+ (1,0) [0|15] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON SG_ STEER_STATUS : 43|4@0+ (1,0) [0|15] "" EON diff --git a/honda_pilot_touring_2017_can_generated.dbc b/honda_pilot_touring_2017_can_generated.dbc index 223aa1b27a..fbd8326096 100644 --- a/honda_pilot_touring_2017_can_generated.dbc +++ b/honda_pilot_touring_2017_can_generated.dbc @@ -271,8 +271,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/honda_ridgeline_black_edition_2017_can_generated.dbc b/honda_ridgeline_black_edition_2017_can_generated.dbc index 8572b0b5ed..ebf8e3098e 100644 --- a/honda_ridgeline_black_edition_2017_can_generated.dbc +++ b/honda_ridgeline_black_edition_2017_can_generated.dbc @@ -266,8 +266,8 @@ BO_ 342 STEERING_SENSORS: 6 EPS SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON BO_ 399 STEER_STATUS: 7 EPS - SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON - SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_TORQUE_MOTOR : 23|16@0- (-1,0) [-31000|31000] "tbd" EON SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..c1ac27ec92 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +Cython==0.29.14 +flake8==3.7.9 +Jinja2==2.10.3 +pycapnp==0.6.4 +pylint==2.4.3 +pyyaml==5.1.2 +scons==3.1.1 diff --git a/subaru_outback_2015_eyesight.dbc b/subaru_outback_2015_eyesight.dbc index 2f79655850..dd1d5422c5 100644 --- a/subaru_outback_2015_eyesight.dbc +++ b/subaru_outback_2015_eyesight.dbc @@ -33,47 +33,47 @@ NS_ : BS_: -BU_: XXX +BU_: XXX 0 BO_ 2 Steering: 8 XXX - SG_ NEW_SIGNAL_1 : 31|4@0- (1,0) [0|65535] "" XXX - SG_ Counter : 25|3@1+ (1,0) [0|15] "" XXX - SG_ Checksum : 32|8@1+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_2 : 22|3@0+ (1,0) [0|7] "" XXX - SG_ NEW_SIGNAL_6 : 24|1@1+ (1,0) [0|3] "" XXX SG_ Steering_Angle : 7|16@0- (0.1,0) [-500|500] "degree" XXX + SG_ NEW_SIGNAL_6 : 24|1@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 22|3@0+ (1,0) [0|7] "" XXX + SG_ Counter : 27|3@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 31|4@0- (1,0) [0|65535] "" XXX + SG_ Checksum : 39|8@0+ (1,0) [0|255] "" XXX BO_ 208 G_Sensor: 8 XXX SG_ NEW_SIGNAL_3 : 32|8@1+ (1,0) [0|255] "" XXX - SG_ Steering_Angle : 0|16@1- (1,0) [0|65535] "" XXX - SG_ NEW_SIGNAL_1 : 47|8@0+ (1,0) [0|255] "" XXX SG_ _Latitudinal : 16|16@1- (0.0035,1) [0|65535] "" XXX SG_ _Longitudinal : 48|16@1- (0.000035,0) [0|255] "" XXX + SG_ Steering_Angle : 0|16@1- (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_1 : 40|8@1+ (1,0) [0|255] "" XXX BO_ 209 Brake_Pedal: 8 XXX SG_ NEW_SIGNAL_1 : 26|1@1+ (1,0) [0|3] "" XXX - SG_ Brake_Pedal : 23|8@0+ (1,0) [0|255] "" XXX SG_ NEW_SIGNAL_2 : 31|1@1+ (1,0) [0|255] "" XXX + SG_ Brake_Pedal : 16|8@1+ (1,0) [0|255] "" XXX SG_ Speed : 0|16@1+ (0.05625,0) [0|255] "KPH" XXX BO_ 210 Brake_2: 8 XXX - SG_ NEW_SIGNAL_1 : 46|1@0+ (1,0) [0|4294967295] "" XXX - SG_ NEW_SIGNAL_2 : 39|3@0+ (1,0) [0|7] "" XXX SG_ Right_Brake : 48|8@1+ (1,0) [0|255] "" XXX - SG_ Left_Brake : 63|8@0+ (1,0) [0|255] "" XXX SG_ Brake_Light : 35|1@1+ (1,0) [0|15] "" XXX SG_ Brake_Related : 36|1@1+ (1,0) [0|255] "" XXX + SG_ Left_Brake : 56|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 46|1@1+ (1,0) [0|4294967295] "" XXX + SG_ NEW_SIGNAL_2 : 37|3@1+ (1,0) [0|7] "" XXX BO_ 211 Brake_Type: 8 XXX - SG_ NEW_SIGNAL_4 : 28|4@1+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_3 : 7|1@0+ (1,0) [0|4294967295] "" XXX + SG_ NEW_SIGNAL_3 : 7|1@1+ (1,0) [0|4294967295] "" XXX SG_ NEW_SIGNAL_2 : 16|4@1+ (1,0) [0|15] "" XXX - SG_ Speed_Counter : 39|8@0+ (1,0) [0|15] "" XXX - SG_ Counter : 55|8@0+ (1,0) [0|255] "" XXX - SG_ Brake_Light : 21|1@0+ (1,0) [0|3] "" XXX - SG_ Brake_Cruise_On : 42|1@0+ (1,0) [0|3] "" XXX - SG_ Brake_Pedal_On : 46|1@0+ (1,0) [0|3] "" XXX + SG_ Brake_Light : 21|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_4 : 28|4@1+ (1,0) [0|15] "" XXX + SG_ Speed_Counter : 32|8@1+ (1,0) [0|15] "" XXX + SG_ Brake_Cruise_On : 42|1@1+ (1,0) [0|3] "" XXX + SG_ Brake_Pedal_On : 46|1@1+ (1,0) [0|3] "" XXX + SG_ Counter : 48|8@1+ (1,0) [0|255] "" XXX BO_ 212 Wheel_Speeds: 8 XXX SG_ FL : 0|16@1+ (0.0592,0) [2|255] "KPH" XXX @@ -85,72 +85,71 @@ BO_ 320 Throttle: 8 XXX SG_ Off_Throttle_2 : 56|1@1+ (1,0) [0|3] "" XXX SG_ Throttle_Combo : 40|8@1+ (1,0) [0|255] "" XXX SG_ Engine_RPM : 16|14@1+ (1,0) [0|15] "" XXX - SG_ Off_Throttle : 30|1@0+ (1,0) [0|3] "" XXX - SG_ Throttle_Cruise : 39|8@0+ (1,0) [0|255] "" XXX - SG_ Throttle_Body_ : 55|8@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_3 : 63|1@0+ (1,0) [0|15] "" XXX - SG_ Not_Full_Throttle : 14|1@0+ (1,0) [0|15] "" XXX - SG_ Counter : 8|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 63|1@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 61|1@1+ (1,0) [0|3] "" XXX + SG_ Throttle_Body_ : 48|8@1+ (1,0) [0|255] "" XXX + SG_ Throttle_Cruise : 32|8@1+ (1,0) [0|255] "" XXX + SG_ Off_Throttle : 30|1@1+ (1,0) [0|3] "" XXX SG_ Throttle_Pedal : 0|8@1+ (0.392157,0) [0|255] "" XXX + SG_ Counter : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Not_Full_Throttle : 14|1@1+ (1,0) [0|15] "" XXX -BO_ 321 undefined: 8 XXX +BO_ 321 Engine: 8 XXX SG_ NEW_SIGNAL_7 : 59|2@1+ (1,0) [0|63] "" XXX - SG_ NEW_SIGNAL_6 : 46|1@0+ (1,0) [0|3] "" XXX SG_ NEW_SIGNAL_2 : 47|1@1+ (1,0) [0|15] "" XXX SG_ NEW_SIGNAL_5 : 48|4@1+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_3 : 54|2@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_8 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ Wheel_Torque : 16|12@1+ (1,0) [0|255] "" XXX SG_ Engine_RPM : 32|12@1+ (1,0) [0|8191] "" XXX + SG_ NEW_SIGNAL_3 : 53|2@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 46|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_8 : 28|4@1+ (1,0) [0|15] "" XXX + SG_ Engine_Stop : 15|1@1+ (1,0) [0|3] "" XXX SG_ Engine_Torque : 0|15@1+ (1,0) [0|255] "" XXX - SG_ Wheel_Torque : 16|12@1+ (1,0) [0|255] "" XXX - SG_ Engine_Stop : 15|1@0+ (1,0) [0|3] "" XXX BO_ 324 CruiseControl: 8 XXX - SG_ Cruise_On : 48|1@0+ (1,0) [0|3] "" XXX SG_ OnOffButton : 2|1@1+ (1,0) [0|3] "" XXX - SG_ SET_BUTTON : 3|1@0+ (1,0) [0|3] "" XXX - SG_ RES_BUTTON : 4|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_6 : 50|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_4 : 28|5@0+ (1,0) [0|16777215] "" XXX + SG_ SET_BUTTON : 3|1@1+ (1,0) [0|3] "" XXX + SG_ RES_BUTTON : 4|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 8|1@1+ (1,0) [0|255] "" XXX + SG_ Button : 13|1@1+ (1,0) [0|3] "" XXX SG_ NEW_SIGNAL_9 : 15|1@1+ (1,0) [0|127] "" XXX - SG_ NEW_SIGNAL_2 : 8|1@0+ (1,0) [0|255] "" XXX - SG_ Cruise_Activated : 49|1@0+ (1,0) [0|7] "" XXX - SG_ Brake_Pedal_On : 51|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_1 : 23|8@0+ (1,-124) [0|255] "" XXX - SG_ Button : 13|1@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_1 : 16|8@1+ (1,-124) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 24|5@1+ (1,0) [0|16777215] "" XXX + SG_ Cruise_On : 48|1@1+ (1,0) [0|3] "" XXX + SG_ Cruise_Activated : 49|1@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_6 : 50|1@1+ (1,0) [0|3] "" XXX + SG_ Brake_Pedal_On : 51|1@1+ (1,0) [0|3] "" XXX BO_ 328 Transmission: 8 XXX - SG_ Counter : 11|4@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_7 : 63|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_4 : 15|4@0+ (1,0) [0|15] "" XXX SG_ Paddle_Shift : 60|2@1+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_1 : 31|1@0+ (1,0) [0|3] "" XXX - SG_ Transmission_Engine : 16|15@1+ (1,0) [0|65535] "" XXX - SG_ NEW_SIGNAL_5 : 43|1@0+ (1,0) [0|65535] "" XXX SG_ Gear : 48|4@1+ (1,0) [0|15] "" XXX SG_ Gear_2 : 52|4@1+ (1,0) [0|15] "" XXX SG_ Manual_Gear : 4|4@1+ (1,0) [0|255] "" XXX + SG_ Transmission_Engine : 16|15@1+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_7 : 63|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 43|1@1+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_1 : 31|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_4 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Counter : 8|4@1+ (1,0) [0|255] "" XXX BO_ 329 CVT_Ratio: 8 XXX - SG_ NEW_SIGNAL_2 : 31|8@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_3 : 40|8@1+ (1,0) [0|255] "" XXX SG_ NEW_SIGNAL_4 : 0|8@1+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_5 : 11|4@0+ (1,0) [0|65535] "" XXX - SG_ NEW_SIGNAL_1 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 8|4@1+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 40|8@1+ (1,0) [0|255] "" XXX BO_ 336 Brake_Pressure: 8 XXX SG_ Brake_Pressure_Right : 0|8@1+ (1,0) [0|15] "" XXX - SG_ Brake_Pressure_Left : 15|8@0+ (1,0) [0|255] "" XXX + SG_ Brake_Pressure_Left : 8|8@1+ (1,0) [0|255] "" XXX BO_ 338 Stalk: 8 XXX - SG_ Wiper : 62|1@0+ (1,0) [0|3] "" XXX - SG_ brake_light : 52|1@0+ (1,0) [0|3] "" XXX - SG_ Headlights : 59|1@0+ (1,0) [0|3] "" XXX SG_ Runlights : 58|1@1+ (1,0) [0|3] "" XXX - SG_ Highbeam : 60|1@0+ (1,0) [0|3] "" XXX - SG_ Counter : 15|4@0+ (1,0) [0|15] "" XXX - -BO_ 342 NEW_MSG_2: 8 XXX + SG_ Wiper : 62|1@1+ (1,0) [0|3] "" XXX + SG_ Highbeam : 60|1@1+ (1,0) [0|3] "" XXX + SG_ Headlights : 59|1@1+ (1,0) [0|3] "" XXX + SG_ brake_light : 52|1@1+ (1,0) [0|3] "" XXX + SG_ Counter : 12|4@1+ (1,0) [0|15] "" XXX BO_ 346 Counter_3: 8 XXX SG_ Counter : 0|4@1+ (1,0) [0|15] "" XXX @@ -160,36 +159,40 @@ BO_ 346 Counter_3: 8 XXX BO_ 352 ES_Brake: 8 XXX SG_ Counter : 48|3@1+ (1,0) [0|7] "" XXX SG_ Checksum : 56|8@1+ (1,0) [0|7] "" XXX - SG_ Brake_On : 22|1@0+ (1,0) [0|3] "" XXX - SG_ Brake_Light : 20|1@0+ (1,0) [0|2047] "" XXX - SG_ Cruise_Activated : 23|1@0+ (1,0) [0|3] "" XXX SG_ Brake_Pressure : 0|16@1+ (1,0) [0|255] "" XXX - SG_ ES_Error : 21|1@0+ (1,0) [0|7] "" XXX + SG_ Cruise_Activated : 23|1@1+ (1,0) [0|3] "" XXX + SG_ Brake_On : 22|1@1+ (1,0) [0|3] "" XXX + SG_ ES_Error : 21|1@1+ (1,0) [0|7] "" XXX + SG_ Brake_Light : 20|1@1+ (1,0) [0|2047] "" XXX BO_ 353 ES_CruiseThrottle: 8 XXX - SG_ Throttle_Cruise : 0|12@1+ (1,0) [0|255] "" XXX - SG_ Counter_1 : 46|3@0+ (1,0) [0|15] "" XXX - SG_ Wheel_stop : 22|1@0+ (1,0) [0|3] "" XXX - SG_ CloseDistance : 24|8@1+ (1,0) [0|255] "" XXX - SG_ Unknown : 18|1@1+ (1,0) [0|7] "" XXX - SG_ Button_Speed_Down : 49|1@1+ (1,0) [0|3] "" XXX - SG_ Button_Resume : 50|1@1+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_3_Blank : 15|4@0+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_2_Blank : 48|1@1+ (1,0) [0|3] "" XXX SG_ Checksum : 56|8@1+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_9 : 17|1@1+ (1,0) [0|3] "" XXX - SG_ Cruise_Activatedish : 16|1@1+ (1,0) [0|7] "" XXX - SG_ NEW_SIGNAL_6_Blank : 23|1@0+ (1,0) [0|7] "" XXX - SG_ DistanceSwap : 21|1@0+ (1,0) [0|3] "" XXX - SG_ Brake_On : 20|1@0+ (1,0) [0|7] "" XXX + SG_ Button : 48|3@1+ (1,0) [0|3] "" XXX SG_ ES_Error : 42|1@1+ (1,0) [0|3] "" XXX + SG_ Standstill_2 : 41|1@1+ (1,0) [0|3] "" XXX + SG_ Standstill : 22|1@1+ (1,0) [0|3] "" XXX + SG_ Unknown : 18|1@1+ (1,0) [0|7] "" XXX + SG_ Brake_On : 20|1@1+ (1,0) [0|7] "" XXX + SG_ DistanceSwap : 21|1@1+ (1,0) [0|3] "" XXX + SG_ Counter : 44|3@1+ (1,0) [0|15] "" XXX + SG_ SET_0_1 : 32|9@1+ (1,0) [0|255] "" XXX + SG_ CloseDistance : 24|8@1+ (0.0196,0) [0|255] "m" XXX + SG_ SET_0_2 : 51|5@1+ (1,0) [0|31] "" XXX + SG_ SET_0_3 : 47|1@1+ (1,0) [0|3] "" XXX + SG_ SET_0_4 : 43|1@1+ (1,0) [0|3] "" XXX + SG_ SET_1 : 23|1@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_1 : 19|1@1+ (1,0) [0|1] "" XXX + SG_ Throttle_Cruise : 0|12@1+ (1,0) [0|255] "" XXX + SG_ SET_2 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Cruise_Activatedish : 16|1@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_9 : 17|1@1+ (1,0) [0|3] "" XXX BO_ 354 ES_RPM: 8 XXX SG_ Counter : 48|3@1+ (1,0) [0|7] "" XXX - SG_ Cruise_Activated : 9|1@0+ (1,0) [0|3] "" XXX - SG_ Checksum : 39|8@0+ (1,0) [0|65535] "" XXX SG_ RPM : 16|16@1+ (1,0) [0|255] "" XXX SG_ Brake : 8|1@1+ (1,0) [0|7] "" XXX + SG_ Cruise_Activated : 9|1@1+ (1,0) [0|3] "" XXX + SG_ Checksum : 32|8@1+ (1,0) [0|65535] "" XXX BO_ 356 ES_LKAS: 8 XXX SG_ Checksum : 56|8@1+ (1,0) [0|255] "" XXX @@ -198,39 +201,39 @@ BO_ 356 ES_LKAS: 8 XXX SG_ LKAS_Command : 8|13@1- (-1,0) [-4096|4096] "" XXX BO_ 358 ES_DashStatus: 8 XXX - SG_ Counter : 39|3@0+ (1,0) [0|7] "" XXX - SG_ Obstacle_Distance : 48|4@1+ (1,0) [0|15] "" XXX - SG_ Cruise_Off : 22|1@0+ (1,0) [0|3] "" XXX - SG_ Car_Follow : 46|1@1+ (1,0) [0|255] "" XXX - SG_ Driver_Input : 20|1@0+ (1,0) [0|15] "" XXX + SG_ Not_Ready_Startup : 0|3@1+ (1,0) [0|7] "" XXX + SG_ 3SecondDisengage : 12|2@1+ (1,0) [0|3] "" XXX + SG_ Disengage_Alert : 14|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_On : 16|1@1+ (1,0) [0|7] "" XXX + SG_ Cruise_Activated : 17|1@1+ (1,0) [0|3] "" XXX SG_ WHEELS_MOVING_2015 : 19|1@1+ (1,0) [0|3] "" XXX - SG_ Untitled_Blank : 18|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_6_Blank : 21|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_5_Blank : 33|1@1+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_4_Blank : 34|1@1+ (1,0) [0|7] "" XXX - SG_ NEW_SIGNAL_1 : 35|1@0+ (1,0) [0|31] "" XXX - SG_ Steep_Hill_Disengage : 44|1@0+ (1,0) [0|3] "" XXX + SG_ Driver_Input : 20|1@1+ (1,0) [0|15] "" XXX SG_ ES_Error : 32|1@1+ (1,0) [0|3] "" XXX - SG_ Cruise_Activated : 17|1@1+ (1,0) [0|3] "" XXX - SG_ Cruise_On : 16|1@1+ (1,0) [0|7] "" XXX - SG_ Disengage_Alert : 15|2@0+ (1,0) [0|3] "" XXX - SG_ 3SecondDisengage : 13|2@0+ (1,0) [0|3] "" XXX - SG_ Not_Ready_Startup : 0|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_5_Blank : 33|1@1+ (1,0) [0|3] "" XXX + SG_ Cruise_On_2 : 34|1@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_1 : 35|1@1+ (1,0) [0|31] "" XXX + SG_ Counter : 37|3@1+ (1,0) [0|7] "" XXX + SG_ Steep_Hill_Disengage : 44|1@1+ (1,0) [0|3] "" XXX + SG_ Lead_Car : 46|1@1+ (1,0) [0|255] "" XXX SG_ Cruise_Set_Speed : 24|8@1+ (1,0) [0|255] "" XXX + SG_ Distance_Bars : 21|3@1+ (1,0) [0|3] "" XXX + SG_ Untitled_Blank_2 : 18|1@1+ (1,0) [0|3] "" XXX + SG_ Obstacle_Distance : 48|4@1+ (5,0) [0|15] "m" XXX BO_ 359 ES_LDW: 8 XXX - SG_ All_depart_2015 : 0|1@1+ (1,0) [0|255] "" XXX - SG_ LKAS_Inactive_2017 : 36|1@1+ (1,0) [0|3] "" XXX - SG_ LKAS_Steer_Active_2017 : 37|1@0+ (1,0) [0|3] "" XXX - SG_ Right_Line_2017 : 24|1@1+ (1,0) [0|7] "" XXX SG_ Left_Line_2017 : 25|1@1+ (1,0) [0|3] "" XXX - SG_ Sig2All_Depart : 28|1@0+ (1,0) [0|3] "" XXX - SG_ Sig1All_Depart : 31|1@0+ (1,0) [0|15] "" XXX SG_ Sig1Right_Depart : 48|1@1+ (1,0) [0|3] "" XXX - SG_ Sig1Right_Depart_Front : 49|1@1+ (1,0) [0|3] "" XXX SG_ Sig2Right_Depart : 50|1@1+ (1,0) [0|7] "" XXX - SG_ Left_Depart_Front : 51|1@0+ (1,0) [0|3] "" XXX - SG_ Sig3All_Depart : 52|1@0+ (1,0) [0|3] "" XXX + SG_ LKAS_Inactive_2017 : 36|1@1+ (1,0) [0|3] "" XXX + SG_ Sig1Right_Depart_Front : 49|1@1+ (1,0) [0|3] "" XXX + SG_ Sig3All_Depart : 52|1@1+ (1,0) [0|3] "" XXX + SG_ Left_Depart_Front : 51|1@1+ (1,0) [0|3] "" XXX + SG_ Alerts : 48|5@1+ (1,0) [0|3] "" XXX + SG_ LKAS_Active : 37|1@1+ (1,0) [0|3] "" XXX + SG_ Sig1All_Depart : 31|1@1+ (1,0) [0|15] "" XXX + SG_ Sig2All_Depart : 28|1@1+ (1,0) [0|3] "" XXX + SG_ Right_Line_2017 : 24|1@1+ (1,0) [0|7] "" XXX + SG_ All_depart_2015 : 0|1@1+ (1,0) [0|255] "" XXX BO_ 392 Counter_0: 8 XXX SG_ Counter : 16|4@1+ (1,0) [0|15] "" XXX @@ -238,62 +241,56 @@ BO_ 392 Counter_0: 8 XXX BO_ 554 NEW_MSG_3: 8 XXX SG_ Counter : 0|4@1+ (1,0) [0|255] "" XXX -BO_ 604 undefined: 8 XXX - BO_ 640 NEW_MSG_10: 8 XXX - SG_ NEW_SIGNAL_2 : 24|8@1+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_4 : 54|2@0+ (1,0) [0|15] "" XXX - SG_ Counter : 8|4@1+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_3 : 34|2@0+ (1,0) [0|63] "" XXX - SG_ NEW_SIGNAL_1 : 47|8@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_5 : 39|1@0+ (1,0) [0|3] "" XXX SG_ NEW_SIGNAL_6 : 0|1@1+ (1,0) [0|7] "" XXX - SG_ NEW_SIGNAL_7 : 38|1@0+ (1,0) [0|3] "" XXX + SG_ Counter : 8|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 33|2@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_7 : 38|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 39|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_1 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 53|2@1+ (1,0) [0|15] "" XXX BO_ 642 Dashlights: 8 XXX SG_ NEW_SIGNAL_2 : 32|1@1+ (1,0) [0|15] "" XXX - SG_ Counter : 15|4@0+ (1,0) [0|15] "" XXX - SG_ NEW_SIGNAL_1 : 0|12@1+ (1,0) [0|255] "" XXX SG_ NEW_SIGNAL_3 : 34|2@1+ (1,0) [0|3] "" XXX - SG_ LEFT_BLINKER : 44|1@0+ (1,0) [0|3] "" XXX - SG_ RIGHT_BLINKER : 45|1@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_1 : 0|12@1+ (1,0) [0|255] "" XXX + SG_ Counter : 12|4@1+ (1,0) [0|15] "" XXX + SG_ RIGHT_BLINKER : 45|1@1+ (1,0) [0|3] "" XXX + SG_ LEFT_BLINKER : 44|1@1+ (1,0) [0|3] "" XXX SG_ SEATBELT_FL : 40|1@1+ (1,0) [0|3] "" XXX BO_ 644 NEW_MSG_8: 8 XXX SG_ Counter : 8|4@1+ (1,0) [0|15] "" XXX -BO_ 805 undefined: 8 XXX - BO_ 880 Steer_Torque_2: 8 XXX + SG_ Steering_Voltage_Flat : 0|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 8|1@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 30|1@1+ (1,0) [0|3] "" XXX + SG_ Steer_Torque_Sensor : 32|8@1- (-1,0) [0|255] "" XXX SG_ Counter : 40|4@1+ (1,0) [0|15] "" XXX SG_ NEW_SIGNAL_3 : 48|4@1- (1,0) [0|15] "" XXX - SG_ Steering_Voltage_Flat : 7|8@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_1 : 8|1@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_2 : 30|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_4_2017 : 52|1@0+ (1,0) [0|3] "" XXX - SG_ NEW_SIGNAL_5_2017 : 54|1@0+ (1,0) [0|3] "" XXX - SG_ Steer_Torque_Sensor : 32|8@1- (-1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4_2017 : 52|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5_2017 : 54|1@1+ (1,0) [0|3] "" XXX BO_ 881 Steering_Torque: 8 XXX SG_ Steering_Motor_Flat : 0|10@1+ (32,0) [0|16500] "" XXX SG_ Steer_Torque_Output : 16|11@1- (-32,0) [-16500|16500] "" XXX - SG_ Steer_Torque_Sensor : 29|11@1- (8,0) [-8500|-8500] "" XXX - SG_ Steering_Angle : 40|16@1- (-0.026,0) [-600|600] "" XXX SG_ LKA_Lockout : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Steer_Torque_Sensor : 29|11@1- (8,0) [-8500|-8500] "" XXX + SG_ Steering_Angle : 40|16@1- (-0.033,0) [-600|600] "" XXX BO_ 882 Counter: 8 XXX - SG_ Counter : 15|4@0+ (1,0) [0|31] "" XXX SG_ Something : 16|2@1+ (1,0) [0|255] "" XXX + SG_ Counter : 12|4@1+ (1,0) [0|31] "" XXX BO_ 884 BodyInfo: 8 XXX - SG_ DOOR_OPEN_FR : 24|1@0+ (1,0) [0|1] "" XXX - SG_ DOOR_OPEN_FL : 25|1@0+ (1,0) [0|1] "" XXX - SG_ DOOR_OPEN_RL : 26|1@0+ (1,0) [0|1] "" XXX - SG_ DOOR_OPEN_RR : 27|1@0+ (1,0) [0|1] "" XXX - SG_ DOOR_OPEN_Hatch : 28|1@0+ (1,0) [0|1] "" XXX - SG_ _UNKNOWN : 2|3@0+ (1,0) [0|1] "" XXX - -BO_ 886 undefined: 8 XXX + SG_ DOOR_OPEN_Hatch : 28|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 27|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 26|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FL : 25|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 24|1@1+ (1,0) [0|1] "" XXX + SG_ _UNKNOWN : 0|3@1+ (1,0) [0|1] "" XXX BO_ 864 Engine_Temp: 8 XXX SG_ NEW_SIGNAL_1 : 32|8@1+ (1,0) [0|255] "" XXX @@ -309,22 +306,22 @@ BO_ 865 NEW_MSG_16: 8 XXX SG_ NEW_SIGNAL_2 : 12|1@1+ (1,0) [0|255] "" XXX BO_ 866 Fuel__: 8 XXX - SG_ NEW_SIGNAL_2 : 55|8@0+ (1,0) [0|16777215] "" XXX - SG_ NEW_SIGNAL_3 : 35|4@0+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_4 : 47|8@0+ (1,0) [0|1] "" XXX SG_ NEW_SIGNAL_1 : 0|16@1+ (1,0) [0|255] "" XXX - SG_ NEW_SIGNAL_5 : 24|1@0+ (1,0) [0|32767] "" XXX + SG_ NEW_SIGNAL_5 : 24|1@1+ (1,0) [0|32767] "" XXX + SG_ NEW_SIGNAL_3 : 32|4@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 40|8@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 48|8@1+ (1,0) [0|16777215] "" XXX BO_ 872 NEW_MSG_15: 8 XXX - SG_ NEW_SIGNAL_1 : 31|8@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_1 : 24|8@1+ (1,0) [0|65535] "" XXX BO_ 977 NEW_MSG_12: 8 XXX SG_ NEW_SIGNAL_1 : 0|8@1+ (1,0) [0|255] "" XXX SG_ NEW_SIGNAL_2 : 16|12@1+ (1,0) [0|255] "" XXX BO_ 1632 Huge_Counter: 8 XXX - SG_ NEW_SIGNAL_1 : 31|8@0+ (1,0) [0|255] "" XXX SG_ Counter : 55|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 31|8@0+ (1,0) [0|255] "" XXX BO_ 1745 NEW_MSG_11: 8 XXX SG_ NEW_SIGNAL_1 : 24|6@1+ (1,0) [0|255] "" XXX @@ -332,8 +329,8 @@ BO_ 1745 NEW_MSG_11: 8 XXX SG_ NEW_SIGNAL_3 : 0|8@1+ (1,0) [0|255] "" XXX BO_ 1786 NEW_MSG_9: 8 XXX - SG_ Counter : 3|4@0+ (1,0) [0|255] "" XXX SG_ NEW_SIGNAL_2 : 8|16@1+ (1,0) [0|15] "" XXX + SG_ Counter : 0|4@1+ (1,0) [0|255] "" XXX @@ -346,26 +343,28 @@ CM_ SG_ 320 Off_Throttle_2 "Less sensitive"; CM_ SG_ 320 Throttle_Body_ "Throttle related"; CM_ SG_ 328 Gear "15 = P, 14 = R, 0 = N, 1-6=gear"; CM_ SG_ 328 Gear_2 "15 = P, 14 = R, 0 = N, 1-6=gear"; -CM_ SG_ 353 NEW_SIGNAL_3_Blank "always 2"; -CM_ SG_ 353 NEW_SIGNAL_2_Blank "0"; -CM_ SG_ 353 NEW_SIGNAL_9 "flipped around quick engagement"; -CM_ SG_ 353 NEW_SIGNAL_6_Blank "always 1"; +CM_ SG_ 353 Button "1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 resume deep"; CM_ SG_ 353 Brake_On "long activatedish"; +CM_ SG_ 353 SET_1 "always 1"; +CM_ SG_ 353 SET_2 ""; +CM_ SG_ 353 NEW_SIGNAL_9 "flipped around quick engagement"; CM_ SG_ 354 RPM "20hz version of Transmission_Engine under Transmission"; -CM_ SG_ 358 Car_Follow "front car detected"; -CM_ SG_ 358 ES_Error "No engagement until restart"; -CM_ SG_ 358 Cruise_Activated "is 1 when cruise is able to go"; -CM_ SG_ 358 Disengage_Alert "seatbelt and steep hill disengage"; CM_ SG_ 358 3SecondDisengage "seatbelt disengage"; -CM_ SG_ 359 All_depart_2015 "always 1 on 2017"; -CM_ SG_ 359 LKAS_Inactive_2017 "1 when not steering, 0 when lkas steering"; -CM_ SG_ 359 Sig2All_Depart "Left and right depart"; -CM_ SG_ 359 Sig1All_Depart "Left and right depart"; +CM_ SG_ 358 Disengage_Alert "seatbelt and steep hill disengage"; +CM_ SG_ 358 Cruise_Activated "is 1 when cruise is able to go"; +CM_ SG_ 358 ES_Error "No engagement until restart"; +CM_ SG_ 358 Lead_Car "front car detected"; CM_ SG_ 359 Sig1Right_Depart "right depart, hill steep and seatbelt disengage"; +CM_ SG_ 359 LKAS_Inactive_2017 "1 when not steering, 0 when lkas steering"; CM_ SG_ 359 Sig1Right_Depart_Front "object in front, right depart, hill steep and seatbelt disengage alert "; CM_ SG_ 359 Left_Depart_Front "warning after acceleration into car in front and left depart"; +CM_ SG_ 359 Alerts "2 = lead beep"; +CM_ SG_ 359 Sig1All_Depart "Left and right depart"; +CM_ SG_ 359 Sig2All_Depart "Left and right depart"; +CM_ SG_ 359 All_depart_2015 "always 1 on 2017"; CM_ SG_ 642 Counter "Affected by signals"; CM_ SG_ 642 RIGHT_BLINKER "0 off, 2 right, 1 left"; +CM_ SG_ 642 SEATBELT_FL ""; CM_ SG_ 880 Steering_Voltage_Flat "receives later than 371"; CM_ SG_ 880 NEW_SIGNAL_1 "0 in 2017"; CM_ SG_ 880 NEW_SIGNAL_4_2017 "1 in 2017";