├── .gitattributes ├── CanBus-Monitor ├── CanMonitor │ ├── CanDisplay │ │ ├── Arduino Libraries.7z │ │ └── CanDisplay.7z │ └── CanHacker │ │ ├── CANHackerV2.00.01.zip │ │ └── CanHacker.7z └── README.md ├── CanHacker-V2.00.01 ├── CanHacker │ ├── CANHackerV2.00.01.zip │ └── CanHacker.7z └── README.md ├── README.md ├── arduino-canhacker ├── .project ├── .settings │ └── org.eclipse.core.resources.prefs ├── CanHacker.cpp ├── CanHacker.h ├── CanHackerLineReader.cpp ├── CanHackerLineReader.h ├── LICENSE.md ├── README.md ├── docs │ ├── en │ │ ├── README.md │ │ └── protocol.md │ └── ru │ │ ├── README.md │ │ └── protocol.md ├── examples │ ├── bluetooth_hc05 │ │ └── bluetooth_hc05 │ │ │ └── bluetooth_hc05.ino │ ├── leonardo_cdc │ │ └── leonardo_cdc │ │ │ └── leonardo_cdc.ino │ ├── softwareserial_debug │ │ └── softwareserial_debug │ │ │ └── softwareserial_debug.ino │ └── usb_cdc │ │ └── usb_cdc │ │ └── usb_cdc.ino ├── lib.cpp └── lib.h └── canDrive ├── .gitignore ├── 01_canSniffer_Arduino ├── MCP2515.cpp ├── MCP2515.h └── canSniffer │ └── canSniffer.ino ├── 02_canSniffer_GUI ├── FileLoader.py ├── HideOldPackets.py ├── SerialReader.py ├── SerialWriter.py ├── canSniffer.ui ├── canSniffer_ui.py ├── main.py ├── main.spec ├── requirements.txt ├── save │ ├── decodedPackets.csv │ └── labelDict.csv └── ui_converter.py ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /CanBus-Monitor/CanMonitor/CanDisplay/Arduino Libraries.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garymeg/CanBus_Hacking/18991be3254cf21c9bff34c6ae7a150792801901/CanBus-Monitor/CanMonitor/CanDisplay/Arduino Libraries.7z -------------------------------------------------------------------------------- /CanBus-Monitor/CanMonitor/CanDisplay/CanDisplay.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garymeg/CanBus_Hacking/18991be3254cf21c9bff34c6ae7a150792801901/CanBus-Monitor/CanMonitor/CanDisplay/CanDisplay.7z -------------------------------------------------------------------------------- /CanBus-Monitor/CanMonitor/CanHacker/CANHackerV2.00.01.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garymeg/CanBus_Hacking/18991be3254cf21c9bff34c6ae7a150792801901/CanBus-Monitor/CanMonitor/CanHacker/CANHackerV2.00.01.zip -------------------------------------------------------------------------------- /CanBus-Monitor/CanMonitor/CanHacker/CanHacker.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garymeg/CanBus_Hacking/18991be3254cf21c9bff34c6ae7a150792801901/CanBus-Monitor/CanMonitor/CanHacker/CanHacker.7z -------------------------------------------------------------------------------- /CanBus-Monitor/README.md: -------------------------------------------------------------------------------- 1 | # CanBus-Monitor -------------------------------------------------------------------------------- /CanHacker-V2.00.01/CanHacker/CANHackerV2.00.01.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garymeg/CanBus_Hacking/18991be3254cf21c9bff34c6ae7a150792801901/CanHacker-V2.00.01/CanHacker/CANHackerV2.00.01.zip -------------------------------------------------------------------------------- /CanHacker-V2.00.01/CanHacker/CanHacker.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garymeg/CanBus_Hacking/18991be3254cf21c9bff34c6ae7a150792801901/CanHacker-V2.00.01/CanHacker/CanHacker.7z -------------------------------------------------------------------------------- /CanHacker-V2.00.01/README.md: -------------------------------------------------------------------------------- 1 | # CanHacker-V2.00.01 2 | Windows CanBus Sniffer Software (Requires Arduino and mcp2515 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CanBus_Hacking 2 | Hacking a Vehicles CanBus 3 | Here is some software to read the vehicle canbus using arduino and mcp2515 4 | this should help you Identify the available PID's and filter out ones your not interested in 5 | -------------------------------------------------------------------------------- /arduino-canhacker/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | arduino-canhacker 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /arduino-canhacker/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /arduino-canhacker/CanHacker.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * CanHacker.cpp 3 | * 4 | * Created on: 17 ���. 2015 �. 5 | * Author: Dmitry 6 | */ 7 | #include 8 | #include 9 | #include 10 | 11 | #include "CanHacker.h" 12 | #include "lib.h" 13 | 14 | const char hex_asc_upper[] = "0123456789ABCDEF"; 15 | 16 | #define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0F)] 17 | #define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xF0) >> 4] 18 | 19 | static inline void put_hex_byte(char *buf, __u8 byte) 20 | { 21 | buf[0] = hex_asc_upper_hi(byte); 22 | buf[1] = hex_asc_upper_lo(byte); 23 | } 24 | 25 | static inline void _put_id(char *buf, int end_offset, canid_t id) 26 | { 27 | /* build 3 (SFF) or 8 (EFF) digit CAN identifier */ 28 | while (end_offset >= 0) { 29 | buf[end_offset--] = hex_asc_upper[id & 0xF]; 30 | id >>= 4; 31 | } 32 | } 33 | 34 | #define put_sff_id(buf, id) _put_id(buf, 2, id) 35 | #define put_eff_id(buf, id) _put_id(buf, 7, id) 36 | 37 | CanHacker::CanHacker(Stream *stream, Stream *debugStream, uint8_t cs) { 38 | _stream = stream; 39 | _debugStream = debugStream; 40 | 41 | writeDebugStream(F("Initialization\n")); 42 | 43 | _cs = cs; 44 | mcp2515 = new MCP2515(_cs); 45 | mcp2515->reset(); 46 | mcp2515->setConfigMode(); 47 | } 48 | 49 | CanHacker::~CanHacker() { 50 | delete mcp2515; 51 | } 52 | 53 | Stream *CanHacker::getInterfaceStream() { 54 | return _stream; 55 | } 56 | 57 | void CanHacker::setClock(CAN_CLOCK clock){ 58 | canClock = clock; 59 | } 60 | 61 | CanHacker::ERROR CanHacker::connectCan() { 62 | MCP2515::ERROR error = mcp2515->setBitrate(bitrate, canClock); 63 | if (error != MCP2515::ERROR_OK) { 64 | writeDebugStream(F("setBitrate error:\n")); 65 | writeDebugStream((int)error); 66 | writeDebugStream("\n"); 67 | return ERROR_MCP2515_INIT_BITRATE; 68 | } 69 | 70 | if (_loopback) { 71 | error = mcp2515->setLoopbackMode(); 72 | } else if (_listenOnly) { 73 | error = mcp2515->setListenOnlyMode(); 74 | } else { 75 | error = mcp2515->setNormalMode(); 76 | } 77 | 78 | if (error != MCP2515::ERROR_OK) { 79 | return ERROR_MCP2515_INIT_SET_MODE; 80 | } 81 | 82 | _isConnected = true; 83 | return ERROR_OK; 84 | } 85 | 86 | CanHacker::ERROR CanHacker::disconnectCan() { 87 | _isConnected = false; 88 | mcp2515->setConfigMode(); 89 | return ERROR_OK; 90 | } 91 | 92 | bool CanHacker::isConnected() { 93 | return _isConnected; 94 | } 95 | 96 | CanHacker::ERROR CanHacker::writeCan(const struct can_frame *frame) { 97 | if (mcp2515->sendMessage(frame) != MCP2515::ERROR_OK) { 98 | return ERROR_MCP2515_SEND; 99 | } 100 | 101 | return ERROR_OK; 102 | } 103 | 104 | CanHacker::ERROR CanHacker::pollReceiveCan() { 105 | if (!isConnected()) { 106 | return ERROR_OK; 107 | } 108 | 109 | while (mcp2515->checkReceive()) { 110 | struct can_frame frame; 111 | if (mcp2515->readMessage(&frame) != MCP2515::ERROR_OK) { 112 | return ERROR_MCP2515_READ; 113 | } 114 | 115 | ERROR error = receiveCanFrame(&frame); 116 | if (error != ERROR_OK) { 117 | return error; 118 | } 119 | } 120 | 121 | return ERROR_OK; 122 | } 123 | 124 | CanHacker::ERROR CanHacker::receiveCan(const MCP2515::RXBn rxBuffer) { 125 | if (!isConnected()) { 126 | return ERROR_OK; 127 | } 128 | 129 | struct can_frame frame; 130 | MCP2515::ERROR result = mcp2515->readMessage(rxBuffer, &frame); 131 | if (result == MCP2515::ERROR_NOMSG) { 132 | return ERROR_OK; 133 | } 134 | 135 | if (result != MCP2515::ERROR_OK) { 136 | return ERROR_MCP2515_READ; 137 | } 138 | 139 | return receiveCanFrame(&frame); 140 | } 141 | 142 | MCP2515 *CanHacker::getMcp2515() { 143 | return mcp2515; 144 | } 145 | 146 | uint16_t CanHacker::getTimestamp() { 147 | return millis() % TIMESTAMP_LIMIT; 148 | } 149 | 150 | CanHacker::ERROR CanHacker::receiveSetBitrateCommand(const char *buffer, const int length) { 151 | if (isConnected()) { 152 | writeDebugStream(F("Bitrate command cannot be called while connected\n")); 153 | writeStream(BEL); 154 | return ERROR_CONNECTED; 155 | } 156 | 157 | if (length < 2) { 158 | writeStream(BEL); 159 | writeDebugStream(F("Bitrate command must by 2 bytes long\n")); 160 | writeDebugStream((const uint8_t*)buffer, length); 161 | writeDebugStream('\n'); 162 | return ERROR_INVALID_COMMAND; 163 | } 164 | switch(buffer[1]) { 165 | case '0': 166 | writeDebugStream(F("Set bitrate 10KBPS\n")); 167 | bitrate = CAN_10KBPS; 168 | break; 169 | case '1': 170 | writeDebugStream(F("Set bitrate 20KBPS\n")); 171 | bitrate = CAN_20KBPS; 172 | break; 173 | case '2': 174 | writeDebugStream(F("Set bitrate 50KBPS\n")); 175 | bitrate = CAN_50KBPS; 176 | break; 177 | case '3': 178 | writeDebugStream(F("Set bitrate 100KBPS\n")); 179 | bitrate = CAN_100KBPS; 180 | break; 181 | case '4': 182 | writeDebugStream(F("Set bitrate 125KBPS\n")); 183 | bitrate = CAN_125KBPS; 184 | break; 185 | case '5': 186 | writeDebugStream(F("Set bitrate 250KBPS\n")); 187 | bitrate = CAN_250KBPS; 188 | break; 189 | case '6': 190 | writeDebugStream(F("Set bitrate 500KBPS\n")); 191 | bitrate = CAN_500KBPS; 192 | break; 193 | case '7': 194 | writeDebugStream(F("Bitrate 7 is not supported\n")); 195 | writeDebugStream((const uint8_t*)buffer, length); 196 | writeDebugStream('\n'); 197 | writeStream(BEL); 198 | return ERROR_INVALID_COMMAND; 199 | break; 200 | case '8': 201 | writeDebugStream(F("Set bitrate 1000KBPS\n")); 202 | bitrate = CAN_1000KBPS; 203 | break; 204 | default: 205 | writeDebugStream(F("Unexpected bitrate\n")); 206 | writeDebugStream((const uint8_t*)buffer, length); 207 | writeDebugStream('\n'); 208 | writeStream(BEL); 209 | return ERROR_INVALID_COMMAND; 210 | break; 211 | } 212 | 213 | return writeStream(CR); 214 | } 215 | 216 | CanHacker::ERROR CanHacker::processInterrupt() { 217 | if (!isConnected()) { 218 | return ERROR_OK; 219 | writeDebugStream(F("Process interrupt while not connected\n")); 220 | return ERROR_NOT_CONNECTED; 221 | } 222 | 223 | uint8_t irq = mcp2515->getInterrupts(); 224 | 225 | if (irq & MCP2515::CANINTF_ERRIF) { 226 | // reset RXnOVR errors 227 | mcp2515->clearRXnOVR(); 228 | } 229 | 230 | if (irq & MCP2515::CANINTF_RX0IF) { 231 | ERROR error = receiveCan(MCP2515::RXB0); 232 | if (error != ERROR_OK) { 233 | return error; 234 | } 235 | } 236 | 237 | if (irq & MCP2515::CANINTF_RX1IF) { 238 | ERROR error = receiveCan(MCP2515::RXB1); 239 | if (error != ERROR_OK) { 240 | return error; 241 | } 242 | } 243 | 244 | /*if (irq & (MCP2515::CANINTF_TX0IF | MCP2515::CANINTF_TX1IF | MCP2515::CANINTF_TX2IF)) { 245 | _debugStream->print("MCP_TXxIF\r\n"); 246 | //stopAndBlink(1); 247 | }*/ 248 | 249 | 250 | 251 | if (irq & MCP2515::CANINTF_WAKIF) { 252 | _debugStream->print(F("MCP_WAKIF\r\n")); 253 | mcp2515->clearInterrupts(); 254 | } 255 | 256 | if (irq & MCP2515::CANINTF_ERRIF) { 257 | _debugStream->print(F("ERRIF\r\n")); 258 | 259 | //return ERROR_MCP2515_MERRF; 260 | mcp2515->clearMERR(); 261 | } 262 | 263 | if (irq & MCP2515::CANINTF_MERRF) { 264 | _debugStream->print(F("MERRF\r\n")); 265 | 266 | //return ERROR_MCP2515_MERRF; 267 | mcp2515->clearInterrupts(); 268 | } 269 | 270 | return ERROR_OK; 271 | } 272 | 273 | CanHacker::ERROR CanHacker::setFilter(const uint32_t filter) { 274 | if (isConnected()) { 275 | writeDebugStream(F("Filter cannot be set while connected\n")); 276 | return ERROR_CONNECTED; 277 | } 278 | 279 | MCP2515::RXF filters[] = {MCP2515::RXF0, MCP2515::RXF1, MCP2515::RXF2, MCP2515::RXF3, MCP2515::RXF4, MCP2515::RXF5}; 280 | for (int i=0; i<6; i++) { 281 | MCP2515::ERROR result = mcp2515->setFilter(filters[i], false, filter); 282 | if (result != MCP2515::ERROR_OK) { 283 | return ERROR_MCP2515_FILTER; 284 | } 285 | } 286 | 287 | return ERROR_OK; 288 | } 289 | 290 | CanHacker::ERROR CanHacker::setFilterMask(const uint32_t mask) { 291 | if (isConnected()) { 292 | writeDebugStream(F("Filter mask cannot be set while connected\n")); 293 | return ERROR_CONNECTED; 294 | } 295 | 296 | MCP2515::MASK masks[] = {MCP2515::MASK0, MCP2515::MASK1}; 297 | for (int i=0; i<2; i++) { 298 | MCP2515::ERROR result = mcp2515->setFilterMask(masks[i], false, mask); 299 | if (result != MCP2515::ERROR_OK) { 300 | return ERROR_MCP2515_FILTER; 301 | } 302 | } 303 | 304 | return ERROR_OK; 305 | } 306 | 307 | CanHacker::ERROR CanHacker::writeStream(const char character) { 308 | char str[2]; 309 | str[0] = character; 310 | str[1] = '\0'; 311 | return writeStream(str); 312 | } 313 | 314 | CanHacker::ERROR CanHacker::writeStream(const char *buffer) { 315 | /*if (_stream->availableForWrite() < strlen(buffer)) { 316 | return ERROR_SERIAL_TX_OVERRUN; 317 | }*/ 318 | size_t printed = _stream->print(buffer); 319 | if (printed != strlen(buffer)) { 320 | return ERROR_SERIAL_TX_OVERRUN; 321 | } 322 | return ERROR_OK; 323 | } 324 | 325 | CanHacker::ERROR CanHacker::writeDebugStream(const char character) { 326 | if (_debugStream != NULL) { 327 | _debugStream->write(character); 328 | } 329 | return ERROR_OK; 330 | } 331 | 332 | CanHacker::ERROR CanHacker::writeDebugStream(const char *buffer) { 333 | if (_debugStream != NULL) { 334 | _debugStream->print(buffer); 335 | } 336 | return ERROR_OK; 337 | } 338 | 339 | CanHacker::ERROR CanHacker::writeDebugStream(const __FlashStringHelper *ifsh) { 340 | if (_debugStream != NULL) { 341 | _debugStream->print(ifsh); 342 | } 343 | return ERROR_OK; 344 | } 345 | 346 | CanHacker::ERROR CanHacker::writeDebugStream(const uint8_t *buffer, size_t size) { 347 | if (_debugStream != NULL) { 348 | _debugStream->write(buffer, size); 349 | } 350 | return ERROR_OK; 351 | } 352 | 353 | CanHacker::ERROR CanHacker::writeDebugStream(const int buffer) { 354 | if (_debugStream != NULL) { 355 | _debugStream->print(buffer); 356 | } 357 | return ERROR_OK; 358 | } 359 | 360 | CanHacker::ERROR CanHacker::receiveCommand(const char *buffer, const int length) { 361 | switch (buffer[0]) { 362 | case COMMAND_GET_SERIAL: { 363 | return writeStream(CANHACKER_SERIAL_RESPONSE); 364 | } 365 | 366 | case COMMAND_GET_SW_VERSION: { 367 | return writeStream(CANHACKER_SW_VERSION_RESPONSE); 368 | } 369 | 370 | case COMMAND_GET_VERSION: { 371 | return writeStream(CANHACKER_VERSION_RESPONSE); 372 | } 373 | 374 | case COMMAND_SEND_11BIT_ID: 375 | case COMMAND_SEND_29BIT_ID: 376 | case COMMAND_SEND_R11BIT_ID: 377 | case COMMAND_SEND_R29BIT_ID: 378 | return receiveTransmitCommand(buffer, length); 379 | 380 | case COMMAND_CLOSE_CAN_CHAN: 381 | return receiveCloseCommand(buffer, length); 382 | 383 | case COMMAND_OPEN_CAN_CHAN: 384 | return receiveOpenCommand(buffer, length); 385 | 386 | case COMMAND_SET_BITRATE: 387 | return receiveSetBitrateCommand(buffer, length); 388 | 389 | case COMMAND_SET_ACR: 390 | return receiveSetAcrCommand(buffer, length); 391 | 392 | case COMMAND_SET_AMR: 393 | return receiveSetAmrCommand(buffer, length); 394 | 395 | case COMMAND_SET_BTR: { 396 | if (isConnected()) { 397 | writeStream(BEL); 398 | writeDebugStream(F("SET_BTR command cannot be called while connected\n")); 399 | return ERROR_CONNECTED; 400 | } 401 | writeDebugStream(F("SET_BTR not supported\n")); 402 | return writeStream(CR); 403 | } 404 | 405 | case COMMAND_LISTEN_ONLY: 406 | return receiveListenOnlyCommand(buffer, length); 407 | 408 | case COMMAND_TIME_STAMP: 409 | return receiveTimestampCommand(buffer, length); 410 | 411 | case COMMAND_WRITE_REG: 412 | case COMMAND_READ_REG: { 413 | return writeStream(CR); 414 | } 415 | 416 | case COMMAND_READ_STATUS: 417 | case COMMAND_READ_ECR: 418 | case COMMAND_READ_ALCR: { 419 | if (!isConnected()) { 420 | writeDebugStream(F("Read status, ecr, alcr while not connected\n")); 421 | writeStream(BEL); 422 | return ERROR_NOT_CONNECTED; 423 | } 424 | return writeStream(CR); 425 | } 426 | 427 | default: { 428 | writeStream(BEL); 429 | writeDebugStream(F("Unknown command received\n")); 430 | writeDebugStream((const uint8_t*)buffer, length); 431 | writeDebugStream('\n'); 432 | return ERROR_UNKNOWN_COMMAND; 433 | } 434 | } 435 | } 436 | 437 | CanHacker::ERROR CanHacker::receiveCanFrame(const struct can_frame *frame) { 438 | char out[35]; 439 | ERROR error = createTransmit(frame, out, 35); 440 | if (error != ERROR_OK) { 441 | return error; 442 | } 443 | return writeStream(out); 444 | } 445 | 446 | CanHacker::ERROR CanHacker::parseTransmit(const char *buffer, int length, struct can_frame *frame) { 447 | if (length < MIN_MESSAGE_LENGTH) { 448 | writeDebugStream(F("Transmit message lenght < minimum\n")); 449 | writeDebugStream((const uint8_t*)buffer, length); 450 | writeDebugStream('\n'); 451 | return ERROR_INVALID_COMMAND; 452 | } 453 | 454 | int isExended = 0; 455 | int isRTR = 0; 456 | 457 | switch (buffer[0]) { 458 | case 't': 459 | break; 460 | case 'T': 461 | isExended = 1; 462 | break; 463 | case 'r': 464 | isRTR = 1; 465 | break; 466 | case 'R': 467 | isExended = 1; 468 | isRTR = 1; 469 | break; 470 | default: 471 | writeDebugStream(F("Unexpected type of transmit command\n")); 472 | writeDebugStream((const uint8_t*)buffer, length); 473 | writeDebugStream('\n'); 474 | return ERROR_INVALID_COMMAND; 475 | 476 | } 477 | 478 | int offset = 1; 479 | 480 | canid_t id = 0; 481 | int idChars = isExended ? 8 : 3; 482 | for (int i=0; ican_id = id; 493 | 494 | __u8 dlc = hexCharToByte(buffer[offset++]); 495 | if (dlc > 8) { 496 | writeDebugStream(F("DLC > 8\n")); 497 | writeDebugStream((const uint8_t*)buffer, length); 498 | writeDebugStream('\n'); 499 | return ERROR_INVALID_COMMAND; 500 | } 501 | if (dlc == 0) { 502 | writeDebugStream(F("DLC = 0\n")); 503 | writeDebugStream((const uint8_t*)buffer, length); 504 | writeDebugStream('\n'); 505 | return ERROR_INVALID_COMMAND; 506 | } 507 | frame->can_dlc = dlc; 508 | 509 | if (!isRTR) { 510 | for (int i=0; idata[i] = hexCharToByte(loHex) + (hexCharToByte(hiHex) << 4); 514 | } 515 | } 516 | 517 | return ERROR_OK; 518 | } 519 | 520 | CanHacker::ERROR CanHacker::createTransmit(const struct can_frame *frame, char *buffer, const int length) { 521 | int offset; 522 | int len = frame->can_dlc; 523 | 524 | int isRTR = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; 525 | 526 | if (frame->can_id & CAN_ERR_FLAG) { 527 | return ERROR_ERROR_FRAME_NOT_SUPPORTED; 528 | } else if (frame->can_id & CAN_EFF_FLAG) { 529 | buffer[0] = isRTR ? 'R' : 'T'; 530 | put_eff_id(buffer+1, frame->can_id & CAN_EFF_MASK); 531 | offset = 9; 532 | } else { 533 | buffer[0] = isRTR ? 'r' : 't'; 534 | put_sff_id(buffer+1, frame->can_id & CAN_SFF_MASK); 535 | offset = 4; 536 | } 537 | 538 | buffer[offset++] = hex_asc_upper_lo(frame->can_dlc); 539 | 540 | if (!isRTR) { 541 | int i; 542 | for (i = 0; i < len; i++) { 543 | put_hex_byte(buffer + offset, frame->data[i]); 544 | offset += 2; 545 | } 546 | } 547 | 548 | if (_timestampEnabled) { 549 | uint16_t ts = getTimestamp(); 550 | put_hex_byte(buffer + offset, ts >> 8); 551 | offset += 2; 552 | put_hex_byte(buffer + offset, ts); 553 | offset += 2; 554 | } 555 | 556 | buffer[offset++] = CR; 557 | buffer[offset] = '\0'; 558 | 559 | if (offset >= length) { 560 | return ERROR_BUFFER_OVERFLOW; 561 | } 562 | 563 | return ERROR_OK; 564 | } 565 | 566 | CanHacker::ERROR CanHacker::sendFrame(const struct can_frame *frame) { 567 | return writeCan(frame); 568 | } 569 | 570 | CanHacker::ERROR CanHacker::receiveTransmitCommand(const char *buffer, const int length) { 571 | if (!isConnected()) { 572 | writeDebugStream(F("Transmit command while not connected\n")); 573 | return ERROR_NOT_CONNECTED; 574 | } 575 | 576 | if (_listenOnly) { 577 | return ERROR_LISTEN_ONLY; 578 | } 579 | 580 | struct can_frame frame; 581 | ERROR error = parseTransmit(buffer, length, &frame); 582 | if (error != ERROR_OK) { 583 | return error; 584 | } 585 | error = writeCan(&frame); 586 | if (error != ERROR_OK) { 587 | return error; 588 | } 589 | 590 | return writeStream(CR); 591 | } 592 | 593 | CanHacker::ERROR CanHacker::receiveTimestampCommand(const char *buffer, const int length) { 594 | if (length != 2) { 595 | writeStream(BEL); 596 | writeDebugStream(F("Timestamp command must be 2 bytes long\n")); 597 | writeDebugStream((const uint8_t*)buffer, length); 598 | writeDebugStream('\n'); 599 | return ERROR_INVALID_COMMAND; 600 | } 601 | switch (buffer[1]) { 602 | case '0': 603 | _timestampEnabled = false; 604 | return writeStream(CR); 605 | case '1': 606 | _timestampEnabled = true; 607 | return writeStream(CR); 608 | default: 609 | writeStream(BEL); 610 | writeDebugStream(F("Timestamp cammand must have value 0 or 1\n")); 611 | writeDebugStream((const uint8_t*)buffer, length); 612 | writeDebugStream('\n'); 613 | return ERROR_INVALID_COMMAND; 614 | } 615 | 616 | return ERROR_OK; 617 | } 618 | 619 | CanHacker::ERROR CanHacker::receiveCloseCommand(const char *buffer, const int length) { 620 | writeDebugStream(F("receiveCloseCommand\n")); 621 | 622 | if (length < 1) { 623 | return ERROR_INVALID_COMMAND; 624 | } 625 | 626 | if (buffer[0] != COMMAND_CLOSE_CAN_CHAN) { 627 | return ERROR_INVALID_COMMAND; 628 | } 629 | 630 | if (!isConnected()) { 631 | return writeStream(BEL); 632 | } 633 | ERROR error = disconnectCan(); 634 | if (error != ERROR_OK) { 635 | return error; 636 | } 637 | return writeStream(CR); 638 | } 639 | 640 | CanHacker::ERROR CanHacker::receiveOpenCommand(const char *buffer, const int length) { 641 | 642 | if (length != 1) { 643 | return ERROR_INVALID_COMMAND; 644 | } 645 | 646 | if (buffer[0] != COMMAND_OPEN_CAN_CHAN) { 647 | return ERROR_INVALID_COMMAND; 648 | } 649 | 650 | writeDebugStream(F("receiveOpenCommand\n")); 651 | ERROR error = connectCan(); 652 | if (error != ERROR_OK) { 653 | return error; 654 | } 655 | return writeStream(CR); 656 | } 657 | 658 | CanHacker::ERROR CanHacker::receiveListenOnlyCommand(const char *buffer, const int length) { 659 | 660 | if (length != 1) { 661 | return ERROR_INVALID_COMMAND; 662 | } 663 | 664 | if (buffer[0] != COMMAND_LISTEN_ONLY) { 665 | return ERROR_INVALID_COMMAND; 666 | } 667 | 668 | writeDebugStream(F("receiveListenOnlyCommand\n")); 669 | if (isConnected()) { 670 | writeStream(BEL); 671 | writeDebugStream(F("ListenOnly command cannot be called while connected\n")); 672 | return ERROR_CONNECTED; 673 | } 674 | _listenOnly = true; 675 | return writeStream(CR); 676 | } 677 | 678 | CanHacker::ERROR CanHacker::receiveSetAcrCommand(const char *buffer, const int length) { 679 | if (length != 9) { 680 | writeStream(BEL); 681 | writeDebugStream(F("ACR command must by 9 bytes long\n")); 682 | writeDebugStream((const uint8_t*)buffer, length); 683 | writeDebugStream('\n'); 684 | return ERROR_INVALID_COMMAND; 685 | } 686 | uint32_t id = 0; 687 | for (int i=1; i<=8; i++) { 688 | id <<= 4; 689 | id += hexCharToByte(buffer[i]); 690 | } 691 | 692 | bool beenConnected = isConnected(); 693 | ERROR error; 694 | 695 | if (beenConnected) { 696 | error = disconnectCan(); 697 | if (error != ERROR_OK) { 698 | return error; 699 | } 700 | } 701 | 702 | error = setFilter(id); 703 | if (error != ERROR_OK) { 704 | return error; 705 | } 706 | 707 | if (beenConnected) { 708 | error = connectCan(); 709 | if (error != ERROR_OK) { 710 | return error; 711 | } 712 | } 713 | 714 | return writeStream(CR); 715 | } 716 | 717 | CanHacker::ERROR CanHacker::receiveSetAmrCommand(const char *buffer, const int length) { 718 | if (length != 9) { 719 | writeStream(BEL); 720 | writeDebugStream(F("AMR command must by 9 bytes long\n")); 721 | writeDebugStream((const uint8_t*)buffer, length); 722 | writeDebugStream('\n'); 723 | return ERROR_INVALID_COMMAND; 724 | } 725 | uint32_t id = 0; 726 | for (int i=1; i<=8; i++) { 727 | id <<= 4; 728 | id += hexCharToByte(buffer[i]); 729 | } 730 | 731 | bool beenConnected = isConnected(); 732 | ERROR error; 733 | 734 | if (beenConnected) { 735 | error = disconnectCan(); 736 | if (error != ERROR_OK) { 737 | return error; 738 | } 739 | } 740 | 741 | error = setFilterMask(id); 742 | if (error != ERROR_OK) { 743 | return error; 744 | } 745 | 746 | if (beenConnected) { 747 | error = connectCan(); 748 | if (error != ERROR_OK) { 749 | return error; 750 | } 751 | } 752 | 753 | return writeStream(CR); 754 | } 755 | 756 | CanHacker::ERROR CanHacker::enableLoopback() { 757 | if (isConnected()) { 758 | writeDebugStream(F("Loopback cannot be changed while connected\n")); 759 | return ERROR_CONNECTED; 760 | } 761 | 762 | _loopback = true; 763 | 764 | return ERROR_OK; 765 | } 766 | 767 | CanHacker::ERROR CanHacker::disableLoopback() { 768 | if (isConnected()) { 769 | writeDebugStream(F("Loopback cannot be changed while connected\n")); 770 | return ERROR_CONNECTED; 771 | } 772 | 773 | _loopback = false; 774 | 775 | return ERROR_OK; 776 | } 777 | -------------------------------------------------------------------------------- /arduino-canhacker/CanHacker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CanHacker.h 3 | * 4 | * Author: Dmitry 5 | */ 6 | 7 | #ifndef CANHACKER_H_ 8 | #define CANHACKER_H_ 9 | 10 | #include 11 | #include 12 | 13 | #define CAN_MIN_DLEN 1 14 | #define HEX_PER_BYTE 2 15 | #define MIN_MESSAGE_DATA_HEX_LENGTH CAN_MIN_DLEN * HEX_PER_BYTE 16 | #define MAX_MESSAGE_DATA_HEX_LENGTH CAN_MAX_DLEN * HEX_PER_BYTE 17 | #define MIN_MESSAGE_LENGTH 5 18 | 19 | #define CANHACKER_CMD_MAX_LENGTH 26 20 | 21 | #define CANHACKER_SERIAL_RESPONSE "N0001\r" 22 | #define CANHACKER_SW_VERSION_RESPONSE "v0107\r" 23 | #define CANHACKER_VERSION_RESPONSE "V1010\r" 24 | 25 | class CanHacker { 26 | public: 27 | enum ERROR { 28 | ERROR_OK, 29 | ERROR_CONNECTED, 30 | ERROR_NOT_CONNECTED, 31 | ERROR_UNKNOWN_COMMAND, 32 | ERROR_INVALID_COMMAND, 33 | ERROR_ERROR_FRAME_NOT_SUPPORTED, 34 | ERROR_BUFFER_OVERFLOW, 35 | ERROR_SERIAL_TX_OVERRUN, 36 | ERROR_LISTEN_ONLY, 37 | ERROR_MCP2515_INIT, 38 | ERROR_MCP2515_INIT_CONFIG, 39 | ERROR_MCP2515_INIT_BITRATE, 40 | ERROR_MCP2515_INIT_SET_MODE, 41 | ERROR_MCP2515_SEND, 42 | ERROR_MCP2515_READ, 43 | ERROR_MCP2515_FILTER, 44 | ERROR_MCP2515_ERRIF, 45 | ERROR_MCP2515_MERRF 46 | }; 47 | 48 | CanHacker(Stream *stream, Stream *debugStream, uint8_t cs); 49 | ~CanHacker(); 50 | void setClock(const CAN_CLOCK clock); 51 | ERROR receiveCommand(const char *buffer, const int length); 52 | ERROR receiveCanFrame(const struct can_frame *frame); 53 | ERROR sendFrame(const struct can_frame *); 54 | ERROR enableLoopback(); 55 | ERROR disableLoopback(); 56 | ERROR pollReceiveCan(); 57 | ERROR receiveCan(const MCP2515::RXBn rxBuffer); 58 | MCP2515 *getMcp2515(); 59 | ERROR processInterrupt(); 60 | Stream *getInterfaceStream(); 61 | 62 | private: 63 | 64 | static const char CR = '\r'; 65 | static const char BEL = 7; 66 | static const uint16_t TIMESTAMP_LIMIT = 0xEA60; 67 | 68 | CAN_CLOCK canClock = MCP_16MHZ; 69 | bool _timestampEnabled = false; 70 | bool _listenOnly = false; 71 | bool _loopback = false; 72 | uint8_t _cs; 73 | MCP2515 *mcp2515; 74 | CAN_SPEED bitrate; 75 | bool _isConnected = false; 76 | Stream *_stream; 77 | Stream *_debugStream; 78 | 79 | enum /*class*/ COMMAND : char { 80 | COMMAND_SET_BITRATE = 'S', // set CAN bit rate 81 | COMMAND_SET_BTR = 's', // set CAN bit rate via 82 | COMMAND_OPEN_CAN_CHAN = 'O', // open CAN channel 83 | COMMAND_CLOSE_CAN_CHAN = 'C', // close CAN channel 84 | COMMAND_SEND_11BIT_ID = 't', // send CAN message with 11bit ID 85 | COMMAND_SEND_29BIT_ID = 'T', // send CAN message with 29bit ID 86 | COMMAND_SEND_R11BIT_ID = 'r', // send CAN remote message with 11bit ID 87 | COMMAND_SEND_R29BIT_ID = 'R', // send CAN remote message with 29bit ID 88 | COMMAND_READ_STATUS = 'F', // read status flag byte 89 | COMMAND_SET_ACR = 'M', // set Acceptance Code Register 90 | COMMAND_SET_AMR = 'm', // set Acceptance Mask Register 91 | COMMAND_GET_VERSION = 'V', // get hardware and software version 92 | COMMAND_GET_SW_VERSION = 'v', // get software version only 93 | COMMAND_GET_SERIAL = 'N', // get device serial number 94 | COMMAND_TIME_STAMP = 'Z', // toggle time stamp setting 95 | COMMAND_READ_ECR = 'E', // read Error Capture Register 96 | COMMAND_READ_ALCR = 'A', // read Arbritation Lost Capture Register 97 | COMMAND_READ_REG = 'G', // read register conten from SJA1000 98 | COMMAND_WRITE_REG = 'W', // write register content to SJA1000 99 | COMMAND_LISTEN_ONLY = 'L' // switch to listen only mode 100 | }; 101 | 102 | ERROR parseTransmit(const char *buffer, int length, struct can_frame *frame); 103 | ERROR createTransmit(const struct can_frame *frame, char *buffer, const int length); 104 | 105 | uint16_t getTimestamp(); 106 | ERROR setFilter(const uint32_t filter); 107 | ERROR setFilterMask(const uint32_t mask); 108 | 109 | ERROR connectCan(); 110 | ERROR disconnectCan(); 111 | bool isConnected(); 112 | ERROR writeCan(const struct can_frame *); 113 | ERROR writeStream(const char character); 114 | ERROR writeStream(const char *buffer); 115 | ERROR writeDebugStream(const char character); 116 | ERROR writeDebugStream(const char *buffer); 117 | ERROR writeDebugStream(const int buffer); 118 | ERROR writeDebugStream(const uint8_t *buffer, size_t size); 119 | ERROR writeDebugStream(const __FlashStringHelper *ifsh); 120 | 121 | ERROR receiveSetBitrateCommand(const char *buffer, const int length); 122 | ERROR receiveTransmitCommand(const char *buffer, const int length); 123 | ERROR receiveTimestampCommand(const char *buffer, const int length); 124 | ERROR receiveCloseCommand(const char *buffer, const int length); 125 | ERROR receiveOpenCommand(const char *buffer, const int length); 126 | ERROR receiveListenOnlyCommand(const char *buffer, const int length); 127 | ERROR receiveSetAcrCommand(const char *buffer, const int length); 128 | ERROR receiveSetAmrCommand(const char *buffer, const int length); 129 | }; 130 | 131 | #endif /* CANHACKER_H_ */ 132 | -------------------------------------------------------------------------------- /arduino-canhacker/CanHackerLineReader.cpp: -------------------------------------------------------------------------------- 1 | #include "CanHackerLineReader.h" 2 | 3 | CanHackerLineReader::CanHackerLineReader(CanHacker *vCanHacker) { 4 | _canHacker = vCanHacker; 5 | index = 0; 6 | memset(buffer, 0, sizeof(buffer)); 7 | } 8 | 9 | CanHacker::ERROR CanHackerLineReader::processChar(char rxChar) { 10 | switch (rxChar) { 11 | case '\r': 12 | case '\n': 13 | if (index > 0) { 14 | buffer[index] = '\0'; 15 | 16 | CanHacker::ERROR error = _canHacker->receiveCommand(buffer, index); 17 | index = 0; 18 | if (error != CanHacker::ERROR_OK) { 19 | return error; 20 | } 21 | } 22 | break; 23 | 24 | case '\0': 25 | break; 26 | 27 | default: 28 | if (index < COMMAND_MAX_LENGTH) { 29 | buffer[index++] = rxChar; 30 | } else { 31 | index = 0; 32 | return CanHacker::ERROR_INVALID_COMMAND; 33 | } 34 | break; 35 | } 36 | return CanHacker::ERROR_OK; 37 | } 38 | 39 | CanHacker::ERROR CanHackerLineReader::process() { 40 | Stream *stream = _canHacker->getInterfaceStream(); 41 | while (stream->available()) { 42 | CanHacker::ERROR error = processChar(stream->read()); 43 | if (error != CanHacker::ERROR_OK) { 44 | return error; 45 | } 46 | } 47 | 48 | return CanHacker::ERROR_OK; 49 | } 50 | -------------------------------------------------------------------------------- /arduino-canhacker/CanHackerLineReader.h: -------------------------------------------------------------------------------- 1 | #ifndef CANHACKERLINEREADER_H_ 2 | #define CANHACKERLINEREADER_H_ 3 | 4 | #include "CanHacker.h" 5 | 6 | class CanHackerLineReader { 7 | private: 8 | static const int COMMAND_MAX_LENGTH = 30; // not including \r\0 9 | 10 | CanHacker *_canHacker; 11 | char buffer[COMMAND_MAX_LENGTH + 2]; 12 | int index; 13 | Stream *_stream; 14 | public: 15 | CanHackerLineReader(CanHacker *vCanHacker); 16 | CanHacker::ERROR processChar(char rxChar); 17 | CanHacker::ERROR process(); 18 | }; 19 | 20 | #endif /* CANHACKERLINEREADER_H_ */ 21 | -------------------------------------------------------------------------------- /arduino-canhacker/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Dmitry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /arduino-canhacker/README.md: -------------------------------------------------------------------------------- 1 | # CanHacker (lawicel) CAN adapter on Arduino + MCP2515 2 | 3 | Use that [Library](https://github.com/autowp/arduino-mcp2515) to communicate with MCP2515 4 | 5 | ## Features 6 | 7 | Implement communication with CAN bus via MCP2515 by CanHacker (lawicel) protocol. 8 | 9 | - send & receive can frames 10 | - supports standart (11 bit) & extended (29 bit) frames 11 | - supports remote frames (RTR) 12 | - supports filter by ID (mask + code) 13 | - interface using [Stream](https://www.arduino.cc/en/Reference/Stream): ability to work with Serial, SoftwareSerial, Ethernet and other 14 | - supported can baudrates from 10Kbps up to 1Mbps 15 | - supported modules with different oscillators (8, 16, 20 MHz), 16 MHz is default, use setClock if your oscillator is not 16MHz 16 | - support [CanHacker](http://www.mictronics.de/projects/usb-can-bus/) (application for Windows) 17 | - support [CANreader](https://github.com/autowp/CANreader) (application for Android) 18 | 19 | ## Documentation 20 | 21 | [English](docs/en/) 22 | 23 | [Русский](docs/ru/) 24 | 25 | ## Library Installation 26 | 27 | 1. Install [MCP2515 Library](https://github.com/autowp/arduino-mcp2515) 28 | 2. Download the ZIP file from https://github.com/autowp/arduino-canhacker/archive/master.zip 29 | 3. From the Arduino IDE: Sketch -> Include Library... -> Add .ZIP Library... 30 | 4. Restart the Arduino IDE to see the new "canhacker" library with examples 31 | 32 | Testes with Arduino Nano. 33 | On Arduino Uno have problem with too long boot period and losing first command 34 | 35 | ## Contributing 36 | 37 | Feel free to open issues, create pull requests and other contributions 38 | -------------------------------------------------------------------------------- /arduino-canhacker/docs/en/README.md: -------------------------------------------------------------------------------- 1 | # CanHacker (lawicel) CAN adapter on Arduino + MCP2515 2 | 3 | Use that [Library](https://github.com/autowp/arduino-mcp2515) to communicate with MCP2515 4 | 5 | ## Features 6 | 7 | Implement communication with CAN bus via MCP2515 by CanHacker (lawicel) protocol. 8 | 9 | - send & receive can frames 10 | - supports standart (11 bit) & extended (29 bit) frames 11 | - supports remote frames (RTR) 12 | - supports filter by ID (mask + code) 13 | - interface using [Stream](https://www.arduino.cc/en/Reference/Stream): ability to work with Serial, SoftwareSerial, Ethernet and other 14 | - supported can baudrates from 10Kbps up to 1Mbps 15 | - supported modules with different oscillators (8, 16, 20 MHZ), 16 MHZ is default, use setClock if your oscillator is not 16MHZ 16 | - support [CanHacker](http://www.mictronics.de/projects/usb-can-bus/) (application for Windows) 17 | - support [CANreader](https://github.com/autowp/CANreader) (application for Android) 18 | 19 | ## Library Installation 20 | 21 | 1. Install [MCP2515 Library](https://github.com/autowp/arduino-mcp2515) 22 | 2. Download the ZIP file from https://github.com/autowp/arduino-canhacker/archive/master.zip 23 | 3. From the Arduino IDE: Sketch -> Include Library... -> Add .ZIP Library... 24 | 4. Restart the Arduino IDE to see the new "canhacker" library with examples 25 | 26 | Testes with Arduino Nano. 27 | On Arduino Uno when works with CanHacker for windows have problem with too long boot period and losing first command 28 | 29 | ## Usage 30 | 31 | Example 32 | 33 | ``` 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | const int SPI_CS_PIN = 10; 44 | const int INT_PIN = 2; 45 | 46 | CanHackerLineReader *lineReader = NULL; 47 | CanHacker *canHacker = NULL; 48 | 49 | void setup() { 50 | Serial.begin(115200); 51 | while (!Serial); 52 | SPI.begin(); 53 | 54 | Stream *interfaceStream = &Serial; 55 | 56 | canHacker = new CanHacker(interfaceStream, NULL, SPI_CS_PIN); 57 | lineReader = new CanHackerLineReader(canHacker); 58 | 59 | pinMode(INT_PIN, INPUT); 60 | } 61 | 62 | void loop() { 63 | canHacker->processInterrupt(); 64 | lineReader->process(); 65 | } 66 | ``` 67 | 68 | ## Protocol 69 | 70 | Protocol CanHacker (lawicel) described in [CanHacker for Windows documentation](http://www.mictronics.de/projects/usb-can-bus/) 71 | 72 | Library implements it partially. [Suported commands listed here](protocol.md). 73 | 74 | ## Contributing 75 | 76 | Feel free to open issues, create pull requests and other contributions 77 | -------------------------------------------------------------------------------- /arduino-canhacker/docs/en/protocol.md: -------------------------------------------------------------------------------- 1 | Protocol CanHacker (lawicel) described in [CanHacker for Windows documentation](http://www.mictronics.de/projects/usb-can-bus/) 2 | 3 | Library implements it partially. Suported commands listed below. 4 | 5 | ### `C[CR]` 6 | 7 | This command switches the CAN controller from operational in reset mode. The 8 | controller is no longer involved in bus activities. 9 | 10 | Command is only active if controller was set to operational mode with command `O` before. 11 | 12 | Return: [CR] or [BEL] 13 | 14 | ### `L[CR]` 15 | 16 | This command will switch the CAN controller in Listen Only mode. No channel open 17 | command (`O`) is required after issuing `L`. 18 | 19 | Use the close channel command `C` to return to reset mode. 20 | 21 | Return: [CR] 22 | 23 | ### `Mxxxxxxxx[CR]` 24 | 25 | Set acceptance code. This command works only if controller in reset mode. 26 | 27 | xxxxxxxx - Acceptance Code in hexadecimal 28 | 29 | Default value after power-up is 0x00000000 to receive all frames. 30 | 31 | Return: [CR] or [BEL] 32 | 33 | ### `mxxxxxxxx[CR]` 34 | 35 | Set acceptance mask. This command works only if controller is setup with command `S` and in reset mode. 36 | 37 | xxxxxxxx - Acceptance Mask in hexadecimal 38 | 39 | Default value after power-up is 0xFFFFFFFF to receive all frames. 40 | 41 | Return [CR] or [BEL] 42 | 43 | ### `N[CR]` 44 | 45 | Read serial number from device. 46 | 47 | Return: Nxxxx[CR] 48 | 49 | xxxx - Serial number in alphanumeric characters. 50 | 51 | ### `O[CR]` 52 | 53 | This command switches the CAN controller from reset in operational mode. The controller is then involved in bus activities. It works only if the initiated with `S` command before, or controller was set to reset mode with command `C`. 54 | 55 | Return: [CR] or [BEL] 56 | 57 | ### `riiiL [CR]` 58 | 59 | This command transmits a standard remote 11 Bit CAN frame. It works only if 60 | controller is in operational mode after command `O`. 61 | 62 | ``` 63 | iii - Identifier in hexadecimal (000-7FF) 64 | L - Data length code (0-8) 65 | ``` 66 | 67 | Return: [CR] or [BEL] 68 | 69 | ### `RiiiiiiiiL [CR]` 70 | 71 | This command transmits an extended remote 29 Bit CAN frame. It works only if 72 | controller is in operational mode after command `O`. 73 | 74 | ``` 75 | iiiiiiii - Identifier in hexadecimal (00000000-1FFFFFFF) 76 | L - Data length code (0-8) 77 | ``` 78 | 79 | Return: [CR] or [BEL] 80 | 81 | ### `Sn[CR]` 82 | 83 | This command will set the CAN controller to a predefined standard bit rate. 84 | It works only after power up or if controller is in reset mode after command `C`. 85 | 86 | The following bit rates are available: 87 | 88 | ``` 89 | S0 - 10Kbps 90 | S1 - 20Kbps 91 | S2 - 50Kbps 92 | S3 - 100Kbps 93 | S4 - 125Kbps 94 | S5 - 250Kbps 95 | S6 - 500Kbps 96 | S7 - 800Kbps 97 | S8 - 1Mbps 98 | ``` 99 | 100 | Return: [CR] or [BEL] 101 | 102 | ### `tiiiLDDDDDDDDDDDDDDDD[CR]` 103 | 104 | This command transmits a standard 11 Bit CAN frame. It works only if controller is in operational mode after command `O`. 105 | 106 | ``` 107 | iii - Identifier in hexadecimal (000-7FF) 108 | L - Data length code (0-8) 109 | DD - Data byte value in hexadecimal (00-FF). Number of given data bytes will be 110 | checked against given data length code. 111 | ``` 112 | 113 | Return: [CR] or [BEL] 114 | 115 | ### `TiiiiiiiiLDDDDDDDDDDDDDDDD[CR]` 116 | 117 | This command transmits an extended 29 Bit CAN frame. It works only if controller is in operational mode after command `O`. 118 | ``` 119 | iiiiiiii - Identifier in hexadecimal (00000000-1FFFFFFF) 120 | L - Data length code (0-8) 121 | DD - Data byte value in hexadecimal (00-FF). Number of given data bytes will be checked against given data length code. 122 | ``` 123 | 124 | Return: [CR] or [BEL] 125 | 126 | ### `V[CR]` 127 | 128 | Read hardware and firmware version from device. 129 | Return: Vhhff[CR] 130 | 131 | ``` 132 | hh - hardware version 133 | ff - firmware version 134 | ``` 135 | 136 | ### `v[CR]` 137 | 138 | Read detailed firmware version from device. 139 | Return: vmami[CR] 140 | 141 | ``` 142 | ma - major version number 143 | mi - minor version number 144 | ``` 145 | 146 | ### `Zv[CR]` 147 | 148 | This command will toggle the time stamp setting for receiving frames. Time stamping is disabled by default. 149 | 150 | If time stamping is enabled for received frames, an incoming frame includes 2 more bytes at the end which is a time stamp in milliseconds. 151 | 152 | The time stamp starts at 0x0000 and overflows at 0xEA5F which is equal to 59999ms. 153 | 154 | Each increment time stamp indicates 1ms within the 60000ms frame. 155 | 156 | ### Incoming messages 157 | 158 | All incoming frames are sent after successful receiving, optional with time stamp. 159 | 160 | No polling is needed. They will be sent in the following format: 161 | 162 | 11 bit ID Frame 163 | ``` 164 | tiiiLDDDDDDDDDDDDDDDD[ssss][CR] 165 | ``` 166 | 167 | 11 bit ID Remote Frame 168 | ``` 169 | riiiL[ssss][CR] 170 | ``` 171 | 172 | 29 bit ID Frame 173 | ``` 174 | TiiiiiiiiLDDDDDDDDDDDDDDDD[ssss][CR] 175 | ``` 176 | 177 | 29 bit ID Remote Frame 178 | ``` 179 | RiiiiiiiiL[ssss][CR] 180 | ``` 181 | 182 | ``` 183 | r - Identifier for Remote 11 bit frame 184 | R - Idenifier for Remote 29 bit frame 185 | t - Identifier for 11 bit frame 186 | T - Idenifier for 29 bit frame 187 | i - ID bytes (000-7FF) or (00000000-1FFFFFFF) 188 | L - Data length code (0-8) 189 | DD - Data bytes (00-FF) 190 | ssss - Optinal time stamp (0000-EA5F) 191 | ``` -------------------------------------------------------------------------------- /arduino-canhacker/docs/ru/README.md: -------------------------------------------------------------------------------- 1 | # CanHacker (lawicel) CAN адаптер на Arduino + MCP2515 2 | 3 | Используется эту [Библиотеку](https://github.com/autowp/arduino-mcp2515) для связи с MCP2515 4 | 5 | ## Возможности 6 | 7 | Резлизует взаимодействие с CAN шиной через микросхему MCP2515 по протоколу CanHacker (lawicel). 8 | 9 | - передача и прием can фреймов 10 | - поддержка стандартных (11 бит) и расширенных (29 бит) фреймов 11 | - поддержка remote фреймов (RTR) 12 | - поддержка фильтра по ID (маска + код) 13 | - интерфейс, работающий со [Stream](https://www.arduino.cc/en/Reference/Stream): возможность работы с Serial, SoftwareSerial, Ethernet и другими интерфейсами 14 | - поддерживаемые скорости can шины от 10Kbps до 1Mbps 15 | - поддерживаются модули с разными кварцами - 8, 16, 20 МГц. По умолчанию установлена частота 16 МГц, используйте функцию setClock если у вас модуль с другим кварцем. 16 | - поддержка [CanHacker](http://www.mictronics.de/projects/usb-can-bus/) (приложение для Windows) 17 | - поддержка [CANreader](https://github.com/autowp/CANreader) (приложение для Android) 18 | 19 | ## Установка библиотеки 20 | 21 | 1. Установите [библиотеку MCP2515](https://github.com/autowp/arduino-mcp2515) 22 | 2. Скачайте ZIP архив https://github.com/autowp/arduino-canhacker/archive/master.zip 23 | 3. В меню Arduino IDE: Sketch -> Include Library... -> Add .ZIP Library... 24 | 4. Перезапустите Arduino IDE, чтобы увидеть "canhacker" в списке библиотек и примеров 25 | 26 | Протестировано с Arduino Nano. 27 | На Arduino Uno при работе через CanHacker для Windows, есть проблема с слишком долгой перезагрузкой и потерей первой комманды 28 | 29 | ## Использование 30 | 31 | Пример 32 | 33 | ``` 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | const int SPI_CS_PIN = 10; 44 | const int INT_PIN = 2; 45 | 46 | CanHackerLineReader *lineReader = NULL; 47 | CanHacker *canHacker = NULL; 48 | 49 | void setup() { 50 | Serial.begin(115200); 51 | while (!Serial); 52 | SPI.begin(); 53 | softwareSerial.begin(115200); 54 | 55 | Stream *interfaceStream = &Serial; 56 | 57 | canHacker = new CanHacker(interfaceStream, null, SPI_CS_PIN); 58 | lineReader = new CanHackerLineReader(canHacker); 59 | 60 | pinMode(INT_PIN, INPUT); 61 | } 62 | 63 | void loop() { 64 | canHacker->processInterrupt(); 65 | lineReader->process(); 66 | } 67 | ``` 68 | 69 | ## Протокол 70 | 71 | Протокол CanHacker (lawicel) описан в [документации к приложению CanHacker](http://www.mictronics.de/projects/usb-can-bus/) 72 | 73 | Библиотека реализует его не полностью. [Поддерживаемые комманды приведены здесь](protocol.md). 74 | 75 | ## Содействие 76 | 77 | Приветствуются любые способы участия в коде. -------------------------------------------------------------------------------- /arduino-canhacker/docs/ru/protocol.md: -------------------------------------------------------------------------------- 1 | Протокол CanHacker (lawicel) описан в [документации к приложению CanHacker](http://www.mictronics.de/projects/usb-can-bus/) 2 | 3 | Библиотека реализует его не полностью. Поддерживаемые комманды приведены ниже. 4 | 5 | ### `C[CR]` 6 | 7 | Эта команда переключает CAN контроллер из операционного режима в режим сброса. Контроллер более не вовлечен в какое-либо взаимодействие с CAN. 8 | 9 | Комманда доступна только в операционном режиме, запущеннос командой `O` ранее. 10 | 11 | Возвращает: [CR] или [BEL] 12 | 13 | ### `L[CR]` 14 | 15 | Эта комманда переключает CAN controller в режим Только Чтение. Комманда открытия канала (`O`) не требуется после исполнения `L`. 16 | 17 | Используйте `C` для возврата в режим сброса. 18 | 19 | Возвращает: [CR] 20 | 21 | ### `Mxxxxxxxx[CR]` 22 | 23 | Установить код фильтра. Эта комманда доступна только в режиме сброса. 24 | 25 | xxxxxxxx - код в hexadecimal 26 | 27 | Значение по-уолчанию после загузки 0x00000000 для приема всех сообщений. 28 | 29 | Возвращает: [CR] или [BEL] 30 | 31 | ### `mxxxxxxxx[CR]` 32 | 33 | Установить маску фильтра. Эта комманда доступна только в режиме сброса. 34 | 35 | xxxxxxxx - маска в hexadecimal 36 | 37 | Значение по-уолчанию после загузки 0xFFFFFFFF для приема всех сообщений. 38 | 39 | Возвращает: [CR] или [BEL] 40 | 41 | ### `N[CR]` 42 | 43 | Серийный номер устройства. 44 | 45 | Возвращает: Nxxxx[CR] 46 | 47 | xxxx - серийный номер в цифро-алфавитных символах. 48 | 49 | ### `O[CR]` 50 | 51 | Эта комманда переключает CAN контроллер из режима сброса в операциооный режим. Контроллер вовлечен во взаимодействие с CAN. Комманда достуна только после установки скорости коммандой `S` ранее или контроллер переведен в режим сброса коммандой `C`. 52 | 53 | Возвращает: [CR] or [BEL] 54 | 55 | ### `riiiL [CR]` 56 | 57 | Комманда пердает стандартный remote 11 Bit CAN фрейм. Комманда доступна только в операционном режиме после исполнения комманды `O`. 58 | 59 | ``` 60 | iii - идентификатор в hexadecimal (000-7FF) 61 | L - код длины сообщения (0-8) 62 | ``` 63 | 64 | Возвращает: [CR] или [BEL] 65 | 66 | ### `RiiiiiiiiL [CR]` 67 | 68 | Комманда пердает расширенный remote 29 Bit CAN фрейм. Комманда доступна только в операционном режиме после исполнения комманды `O`. 69 | 70 | ``` 71 | iiiiiiii - идентификатор в hexadecimal (00000000-1FFFFFFF) 72 | L - код длины сообщения (0-8) 73 | ``` 74 | 75 | Возвращает: [CR] или [BEL] 76 | 77 | ### `Sn[CR]` 78 | 79 | Эта комманда устанавливает скорость CAN в одно из предопределеных состояний. 80 | Команда доступна после включения или после перевода конроллера в режим сброса командой `C`. 81 | 82 | Следующие скорости доступны: 83 | 84 | ``` 85 | S0 - 10Kbps 86 | S1 - 20Kbps 87 | S2 - 50Kbps 88 | S3 - 100Kbps 89 | S4 - 125Kbps 90 | S5 - 250Kbps 91 | S6 - 500Kbps 92 | S7 - 800Kbps 93 | S8 - 1Mbps 94 | ``` 95 | 96 | Возвращает: [CR] или [BEL] 97 | 98 | ### `tiiiLDDDDDDDDDDDDDDDD[CR]` 99 | 100 | Комманда пердает стандартный 11 Bit CAN фрейм. Комманда доступна только в операционном режиме после исполнения комманды `O`. 101 | 102 | ``` 103 | iii - идентификатор в hexadecimal (000-7FF) 104 | L - код длины сообщения (0-8) 105 | DD - Байт данных в hexadecimal (00-FF). Количество байт должно соответствовать коду длины сообщения 106 | ``` 107 | 108 | Возвращает: [CR] или [BEL] 109 | 110 | ### `TiiiiiiiiLDDDDDDDDDDDDDDDD[CR]` 111 | 112 | Комманда пердает расширенный 29 Bit CAN фрейм. Комманда доступна только в операционном режиме после исполнения комманды `O`. 113 | ``` 114 | iiiiiiii - идентификатор в hexadecimal (00000000-1FFFFFFF) 115 | L - код длины сообщения (0-8) 116 | DD - Байт данных в hexadecimal (00-FF). Количество байт должно соответствовать коду длины сообщения 117 | ``` 118 | 119 | Возвращает: [CR] или [BEL] 120 | 121 | ### `V[CR]` 122 | 123 | Чтение версии программного обеспечения и платы 124 | 125 | Возвращает: Vhhff[CR] 126 | 127 | ``` 128 | hh - версия платы 129 | ff - версия программного обеспечения 130 | ``` 131 | 132 | ### `v[CR]` 133 | 134 | Чтение подробной версии программного обеспечения 135 | 136 | Возвращает: vmami[CR] 137 | 138 | ``` 139 | ma - мажорный номер версии 140 | mi - минорный номер версии 141 | ``` 142 | 143 | ### `Zv[CR]` 144 | 145 | Эта комманда включает или выключает метки времени в получаемых сообщениях. По-умолчнию - выключено. 146 | 147 | Если метки времени включены, получаемые сообщения содержат дополнительные 2 байта на конце, в которых закодирована временная метка в миллисекнудах. 148 | 149 | Счетчик времени начинается с 0x0000 и переполняется на 0xEA5F, что эквивалентно 59999мс. 150 | 151 | Каждый инкремент временной метки соответствует 1мс из 60000мс окна. 152 | 153 | ### Входящие фреймы 154 | 155 | Все вхоядщие фреймы передаются сразу после получения, опционально с временной меткой. 156 | 157 | Опрос не требуется. Отправляются в следующем формате: 158 | 159 | 11 bit ID фрейм 160 | ``` 161 | tiiiLDDDDDDDDDDDDDDDD[ssss][CR] 162 | ``` 163 | 164 | 11 bit ID Remote фрейм 165 | ``` 166 | riiiL[ssss][CR] 167 | ``` 168 | 169 | 29 bit ID фрейм 170 | ``` 171 | TiiiiiiiiLDDDDDDDDDDDDDDDD[ssss][CR] 172 | ``` 173 | 174 | 29 bit ID Remote фрейм 175 | ``` 176 | RiiiiiiiiL[ssss][CR] 177 | ``` 178 | 179 | ``` 180 | r - идентификатор для Remote 11 bit фрейма 181 | R - идентификатор для Remote 29 bit фрейма 182 | t - идентификатор для 11 bit фрейма 183 | T - идентификатор для 29 bit фрейма 184 | i - идентификатор (000-7FF) или (00000000-1FFFFFFF) 185 | L - код длины (0-8) 186 | DD - байты данных (00-FF) 187 | ssss - опциональная метка времени (0000-EA5F) 188 | ``` 189 | -------------------------------------------------------------------------------- /arduino-canhacker/examples/bluetooth_hc05/bluetooth_hc05/bluetooth_hc05.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | const int SPI_CS_PIN = 53; // 10 by default, 53 on mega 11 | const int INT_PIN = 2; 12 | 13 | CanHackerLineReader *lineReader = NULL; 14 | CanHacker *canHacker = NULL; 15 | 16 | void setup() { 17 | Serial.begin(115200); 18 | while (!Serial); 19 | Serial1.begin(57600); 20 | while (!Serial1); 21 | SPI.begin(); 22 | 23 | Stream *interfaceStream = &Serial1; 24 | Stream *debugStream = &Serial; 25 | 26 | 27 | canHacker = new CanHacker(interfaceStream, debugStream, SPI_CS_PIN); 28 | //canHacker->enableLoopback(); // uncomment this for loopback 29 | lineReader = new CanHackerLineReader(canHacker); 30 | 31 | pinMode(INT_PIN, INPUT); 32 | } 33 | 34 | void loop() { 35 | CanHacker::ERROR error; 36 | 37 | if (digitalRead(INT_PIN) == LOW) { 38 | error = canHacker->processInterrupt(); 39 | handleError(error); 40 | } 41 | 42 | error = lineReader->process(); 43 | handleError(error); 44 | } 45 | 46 | void handleError(const CanHacker::ERROR error) { 47 | 48 | switch (error) { 49 | case CanHacker::ERROR_OK: 50 | case CanHacker::ERROR_UNKNOWN_COMMAND: 51 | case CanHacker::ERROR_NOT_CONNECTED: 52 | case CanHacker::ERROR_MCP2515_ERRIF: 53 | case CanHacker::ERROR_INVALID_COMMAND: 54 | return; 55 | 56 | default: 57 | break; 58 | } 59 | 60 | Serial.print("Failure (code "); 61 | Serial.print((int)error); 62 | Serial.println(")"); 63 | 64 | digitalWrite(SPI_CS_PIN, HIGH); 65 | pinMode(LED_BUILTIN, OUTPUT); 66 | 67 | while (1) { 68 | int c = (int)error; 69 | for (int i=0; i 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | const int SPI_CS_PIN = 10; 11 | const int INT_PIN = 3; 12 | 13 | 14 | CanHackerLineReader *lineReader = NULL; 15 | CanHacker *canHacker = NULL; 16 | 17 | void setup() { 18 | Serial.begin(115200); 19 | SPI.begin(); 20 | 21 | canHacker = new CanHacker(&Serial, NULL, SPI_CS_PIN); 22 | canHacker->enableLoopback(); // Enable Loopback mode for offline tests 23 | lineReader = new CanHackerLineReader(canHacker); 24 | 25 | pinMode(INT_PIN, INPUT); 26 | } 27 | 28 | void loop() { 29 | if (digitalRead(INT_PIN) == LOW) { 30 | canHacker->processInterrupt(); 31 | } 32 | if (Serial.available()) { 33 | lineReader->process(); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /arduino-canhacker/examples/softwareserial_debug/softwareserial_debug/softwareserial_debug.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | const int SPI_CS_PIN = 10; 12 | const int INT_PIN = 2; 13 | 14 | const int SS_RX_PIN = 3; 15 | const int SS_TX_PIN = 4; 16 | 17 | CanHackerLineReader *lineReader = NULL; 18 | CanHacker *canHacker = NULL; 19 | 20 | SoftwareSerial softwareSerial(SS_RX_PIN, SS_TX_PIN); 21 | 22 | void handleError(const CanHacker::ERROR error); 23 | 24 | void setup() { 25 | Serial.begin(115200); 26 | SPI.begin(); 27 | softwareSerial.begin(115200); 28 | 29 | Stream *interfaceStream = &Serial; 30 | Stream *debugStream = &softwareSerial; 31 | 32 | 33 | canHacker = new CanHacker(interfaceStream, debugStream, SPI_CS_PIN); 34 | canHacker->enableLoopback(); // remove to disable loopback test mode 35 | lineReader = new CanHackerLineReader(canHacker); 36 | 37 | pinMode(INT_PIN, INPUT); 38 | } 39 | 40 | void loop() { 41 | CanHacker::ERROR error; 42 | 43 | if (digitalRead(INT_PIN) == LOW) { 44 | error = canHacker->processInterrupt(); 45 | handleError(error); 46 | } 47 | 48 | // uncomment that lines for Leonardo, Pro Micro or Esplora 49 | // error = lineReader->process(); 50 | // handleError(error); 51 | } 52 | 53 | // serialEvent handler not supported by Leonardo, Pro Micro and Esplora 54 | void serialEvent() { 55 | CanHacker::ERROR error = lineReader->process(); 56 | handleError(error); 57 | } 58 | 59 | void handleError(const CanHacker::ERROR error) { 60 | 61 | switch (error) { 62 | case CanHacker::ERROR_OK: 63 | case CanHacker::ERROR_UNKNOWN_COMMAND: 64 | case CanHacker::ERROR_NOT_CONNECTED: 65 | case CanHacker::ERROR_MCP2515_ERRIF: 66 | case CanHacker::ERROR_INVALID_COMMAND: 67 | return; 68 | 69 | default: 70 | break; 71 | } 72 | 73 | softwareSerial.print("Failure (code "); 74 | softwareSerial.print((int)error); 75 | softwareSerial.println(")"); 76 | 77 | while (1) { 78 | delay(2000); 79 | } ; 80 | } 81 | -------------------------------------------------------------------------------- /arduino-canhacker/examples/usb_cdc/usb_cdc/usb_cdc.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | const int SPI_CS_PIN = 10; 11 | const int INT_PIN = 2; 12 | 13 | CanHackerLineReader *lineReader = NULL; 14 | CanHacker *canHacker = NULL; 15 | 16 | void setup() { 17 | Serial.begin(115200); 18 | SPI.begin(); 19 | 20 | canHacker = new CanHacker(&Serial, NULL, SPI_CS_PIN); 21 | lineReader = new CanHackerLineReader(canHacker); 22 | 23 | pinMode(INT_PIN, INPUT); 24 | } 25 | 26 | void loop() { 27 | if (digitalRead(INT_PIN) == LOW) { 28 | canHacker->processInterrupt(); 29 | } 30 | 31 | // uncomment that lines for Leonardo, Pro Micro or Esplora 32 | // if (Serial.available()) { 33 | // lineReader->process(); 34 | // } 35 | } 36 | 37 | // serialEvent handler not supported by Leonardo, Pro Micro and Esplora 38 | void serialEvent() { 39 | lineReader->process(); 40 | } 41 | -------------------------------------------------------------------------------- /arduino-canhacker/lib.cpp: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | unsigned char hexCharToByte(char hex) 4 | { 5 | unsigned char result = 0; 6 | if (hex >= 0x30 && hex <= 0x39) { 7 | result = hex - 0x30; 8 | } else if (hex >= 0x41 && hex <= 0x46) { 9 | result = hex - 0x41 + 0x0A; 10 | } else if (hex >= 0x61 && hex <= 0x66) { 11 | result = hex - 0x61 + 0x0A; 12 | } 13 | return result; 14 | } 15 | 16 | uint8_t ascii2byte (uint8_t *val) { 17 | uint8_t temp = *val; 18 | if (temp > 0x60) temp -= 0x27; // convert chars a-f 19 | else if (temp > 0x40) temp -= 0x07; // convert chars A-F 20 | temp -= 0x30; // convert chars 0-9 21 | return temp & 0x0F; 22 | } 23 | 24 | uint8_t nibble2ascii(uint8_t nibble) { 25 | uint8_t tmp = nibble & 0x0f; 26 | return tmp < 10 ? tmp + 48 : tmp + 55; 27 | } 28 | -------------------------------------------------------------------------------- /arduino-canhacker/lib.h: -------------------------------------------------------------------------------- 1 | #ifndef LIB_H_ 2 | #define LIB_H_ 3 | 4 | #include 5 | 6 | unsigned char hexCharToByte(char hex); 7 | 8 | uint8_t ascii2byte (uint8_t * val); 9 | 10 | uint8_t nibble2ascii(uint8_t nibble); 11 | 12 | #endif /* LIB_H_ */ 13 | -------------------------------------------------------------------------------- /canDrive/.gitignore: -------------------------------------------------------------------------------- 1 | /02_canSniffer_GUI/venv 2 | /02_canSniffer_GUI/.idea 3 | /02_canSniffer_GUI/__pycache__ 4 | /02_canSniffer_GUI/build 5 | /02_canSniffer_GUI/dist 6 | -------------------------------------------------------------------------------- /canDrive/01_canSniffer_Arduino/MCP2515.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef ARDUINO_ARCH_ESP32 5 | 6 | #include "MCP2515.h" 7 | 8 | #define REG_BFPCTRL 0x0c 9 | #define REG_TXRTSCTRL 0x0d 10 | 11 | #define REG_CANCTRL 0x0f 12 | 13 | #define REG_CNF3 0x28 14 | #define REG_CNF2 0x29 15 | #define REG_CNF1 0x2a 16 | 17 | #define REG_CANINTE 0x2b 18 | #define REG_CANINTF 0x2c 19 | 20 | #define FLAG_RXnIE(n) (0x01 << n) 21 | #define FLAG_RXnIF(n) (0x01 << n) 22 | #define FLAG_TXnIF(n) (0x04 << n) 23 | 24 | #define REG_RXFnSIDH(n) (0x00 + (n * 4)) 25 | #define REG_RXFnSIDL(n) (0x01 + (n * 4)) 26 | #define REG_RXFnEID8(n) (0x02 + (n * 4)) 27 | #define REG_RXFnEID0(n) (0x03 + (n * 4)) 28 | 29 | #define REG_RXMnSIDH(n) (0x20 + (n * 0x04)) 30 | #define REG_RXMnSIDL(n) (0x21 + (n * 0x04)) 31 | #define REG_RXMnEID8(n) (0x22 + (n * 0x04)) 32 | #define REG_RXMnEID0(n) (0x23 + (n * 0x04)) 33 | 34 | #define REG_TXBnCTRL(n) (0x30 + (n * 0x10)) 35 | #define REG_TXBnSIDH(n) (0x31 + (n * 0x10)) 36 | #define REG_TXBnSIDL(n) (0x32 + (n * 0x10)) 37 | #define REG_TXBnEID8(n) (0x33 + (n * 0x10)) 38 | #define REG_TXBnEID0(n) (0x34 + (n * 0x10)) 39 | #define REG_TXBnDLC(n) (0x35 + (n * 0x10)) 40 | #define REG_TXBnD0(n) (0x36 + (n * 0x10)) 41 | 42 | #define REG_RXBnCTRL(n) (0x60 + (n * 0x10)) 43 | #define REG_RXBnSIDH(n) (0x61 + (n * 0x10)) 44 | #define REG_RXBnSIDL(n) (0x62 + (n * 0x10)) 45 | #define REG_RXBnEID8(n) (0x63 + (n * 0x10)) 46 | #define REG_RXBnEID0(n) (0x64 + (n * 0x10)) 47 | #define REG_RXBnDLC(n) (0x65 + (n * 0x10)) 48 | #define REG_RXBnD0(n) (0x66 + (n * 0x10)) 49 | 50 | #define FLAG_IDE 0x08 51 | #define FLAG_SRR 0x10 52 | #define FLAG_RTR 0x40 53 | #define FLAG_EXIDE 0x08 54 | 55 | #define FLAG_RXM0 0x20 56 | #define FLAG_RXM1 0x40 57 | 58 | 59 | MCP2515Class::MCP2515Class() : 60 | CANControllerClass(), 61 | _spiSettings(10E6, MSBFIRST, SPI_MODE0), 62 | _csPin(MCP2515_DEFAULT_CS_PIN), 63 | _intPin(MCP2515_DEFAULT_INT_PIN), 64 | _clockFrequency(MCP2515_DEFAULT_CLOCK_FREQUENCY) 65 | { 66 | } 67 | 68 | MCP2515Class::~MCP2515Class() 69 | { 70 | } 71 | 72 | int MCP2515Class::begin(long baudRate) 73 | { 74 | CANControllerClass::begin(baudRate); 75 | 76 | pinMode(_csPin, OUTPUT); 77 | 78 | // start SPI 79 | SPI.begin(); 80 | 81 | reset(); 82 | 83 | writeRegister(REG_CANCTRL, 0x80); 84 | if (readRegister(REG_CANCTRL) != 0x80) { 85 | return 0; 86 | } 87 | 88 | const struct { 89 | long clockFrequency; 90 | long baudRate; 91 | uint8_t cnf[3]; 92 | } CNF_MAPPER[] = { 93 | { (long)8E6, (long)1000E3, { 0x00, 0x80, 0x00 } }, 94 | { (long)8E6, (long)500E3, { 0x00, 0x90, 0x02 } }, 95 | { (long)8E6, (long)250E3, { 0x00, 0xb1, 0x05 } }, 96 | { (long)8E6, (long)200E3, { 0x00, 0xb4, 0x06 } }, 97 | { (long)8E6, (long)125E3, { 0x01, 0xb1, 0x05 } }, 98 | { (long)8E6, (long)100E3, { 0x01, 0xb4, 0x06 } }, 99 | { (long)8E6, (long)95E3, { 0x01, 0xed, 0x87 } }, 100 | { (long)8E6, (long)83E3, { 0x01, 0xfe, 0x87 } }, 101 | { (long)8E6, (long)80E3, { 0x01, 0xbf, 0x07 } }, 102 | { (long)8E6, (long)50E3, { 0x03, 0xb4, 0x06 } }, 103 | { (long)8E6, (long)40E3, { 0x03, 0xbf, 0x07 } }, 104 | { (long)8E6, (long)33E3, { 0x85, 0xf6, 0x84 } }, 105 | { (long)8E6, (long)20E3, { 0x07, 0xbf, 0x07 } }, 106 | { (long)8E6, (long)10E3, { 0x0f, 0xbf, 0x07 } }, 107 | { (long)8E6, (long)5E3, { 0x1f, 0xbf, 0x07 } }, 108 | 109 | { (long)16E6, (long)1000E3, { 0x00, 0xd0, 0x82 } }, 110 | { (long)16E6, (long)500E3, { 0x00, 0xf0, 0x86 } }, 111 | { (long)16E6, (long)250E3, { 0x41, 0xf1, 0x85 } }, 112 | { (long)16E6, (long)200E3, { 0x01, 0xfa, 0x87 } }, 113 | { (long)16E6, (long)125E3, { 0x03, 0xf0, 0x86 } }, 114 | { (long)16E6, (long)100E3, { 0x03, 0xfa, 0x87 } }, 115 | { (long)16E6, (long)80E3, { 0x03, 0xff, 0x87 } }, 116 | { (long)16E6, (long)50E3, { 0x07, 0xfa, 0x87 } }, 117 | { (long)16E6, (long)40E3, { 0x07, 0xff, 0x87 } }, 118 | { (long)16E6, (long)33E3, { 0x4e, 0xe5, 0x83 } }, 119 | { (long)16E6, (long)20E3, { 0x0f, 0xff, 0x87 } }, 120 | { (long)16E6, (long)10E3, { 0x1f, 0xff, 0x87 } }, 121 | { (long)16E6, (long)5E3, { 0x3f, 0xff, 0x87 } }, 122 | }; 123 | 124 | const uint8_t* cnf = NULL; 125 | 126 | for (unsigned int i = 0; i < (sizeof(CNF_MAPPER) / sizeof(CNF_MAPPER[0])); i++) { 127 | if (CNF_MAPPER[i].clockFrequency == _clockFrequency && CNF_MAPPER[i].baudRate == baudRate) { 128 | cnf = CNF_MAPPER[i].cnf; 129 | break; 130 | } 131 | } 132 | 133 | if (cnf == NULL) { 134 | return 0; 135 | } 136 | 137 | writeRegister(REG_CNF1, cnf[0]); 138 | writeRegister(REG_CNF2, cnf[1]); 139 | writeRegister(REG_CNF3, cnf[2]); 140 | 141 | writeRegister(REG_CANINTE, FLAG_RXnIE(1) | FLAG_RXnIE(0)); 142 | writeRegister(REG_BFPCTRL, 0x00); 143 | writeRegister(REG_TXRTSCTRL, 0x00); 144 | writeRegister(REG_RXBnCTRL(0), FLAG_RXM1 | FLAG_RXM0); 145 | writeRegister(REG_RXBnCTRL(1), FLAG_RXM1 | FLAG_RXM0); 146 | 147 | writeRegister(REG_CANCTRL, 0x00); 148 | if (readRegister(REG_CANCTRL) != 0x00) { 149 | return 0; 150 | } 151 | 152 | return 1; 153 | } 154 | 155 | void MCP2515Class::end() 156 | { 157 | SPI.end(); 158 | 159 | CANControllerClass::end(); 160 | } 161 | 162 | int MCP2515Class::endPacket() 163 | { 164 | if (!CANControllerClass::endPacket()) { 165 | return 0; 166 | } 167 | 168 | int n = 0; 169 | 170 | if (_txExtended) { 171 | writeRegister(REG_TXBnSIDH(n), _txId >> 21); 172 | writeRegister(REG_TXBnSIDL(n), (((_txId >> 18) & 0x07) << 5) | FLAG_EXIDE | ((_txId >> 16) & 0x03)); 173 | writeRegister(REG_TXBnEID8(n), (_txId >> 8) & 0xff); 174 | writeRegister(REG_TXBnEID0(n), _txId & 0xff); 175 | } else { 176 | writeRegister(REG_TXBnSIDH(n), _txId >> 3); 177 | writeRegister(REG_TXBnSIDL(n), _txId << 5); 178 | writeRegister(REG_TXBnEID8(n), 0x00); 179 | writeRegister(REG_TXBnEID0(n), 0x00); 180 | } 181 | 182 | if (_txRtr) { 183 | writeRegister(REG_TXBnDLC(n), 0x40 | _txLength); 184 | } else { 185 | writeRegister(REG_TXBnDLC(n), _txLength); 186 | 187 | for (int i = 0; i < _txLength; i++) { 188 | writeRegister(REG_TXBnD0(n) + i, _txData[i]); 189 | } 190 | } 191 | 192 | writeRegister(REG_TXBnCTRL(n), 0x08); 193 | 194 | bool aborted = false; 195 | 196 | while (readRegister(REG_TXBnCTRL(n)) & 0x08) { 197 | if (readRegister(REG_TXBnCTRL(n)) & 0x10) { 198 | // abort 199 | aborted = true; 200 | 201 | modifyRegister(REG_CANCTRL, 0x10, 0x10); 202 | } 203 | 204 | yield(); 205 | } 206 | 207 | if (aborted) { 208 | // clear abort command 209 | modifyRegister(REG_CANCTRL, 0x10, 0x00); 210 | } 211 | 212 | modifyRegister(REG_CANINTF, FLAG_TXnIF(n), 0x00); 213 | 214 | return (readRegister(REG_TXBnCTRL(n)) & 0x70) ? 0 : 1; 215 | } 216 | 217 | int MCP2515Class::parsePacket() 218 | { 219 | int n; 220 | 221 | uint8_t intf = readRegister(REG_CANINTF); 222 | 223 | if (intf & FLAG_RXnIF(0)) { 224 | n = 0; 225 | } else if (intf & FLAG_RXnIF(1)) { 226 | n = 1; 227 | } else { 228 | _rxId = -1; 229 | _rxExtended = false; 230 | _rxRtr = false; 231 | _rxLength = 0; 232 | return 0; 233 | } 234 | 235 | _rxExtended = (readRegister(REG_RXBnSIDL(n)) & FLAG_IDE) ? true : false; 236 | 237 | uint32_t idA = ((readRegister(REG_RXBnSIDH(n)) << 3) & 0x07f8) | ((readRegister(REG_RXBnSIDL(n)) >> 5) & 0x07); 238 | if (_rxExtended) { 239 | uint32_t idB = (((uint32_t)(readRegister(REG_RXBnSIDL(n)) & 0x03) << 16) & 0x30000) | ((readRegister(REG_RXBnEID8(n)) << 8) & 0xff00) | readRegister(REG_RXBnEID0(n)); 240 | 241 | _rxId = (idA << 18) | idB; 242 | _rxRtr = (readRegister(REG_RXBnDLC(n)) & FLAG_RTR) ? true : false; 243 | } else { 244 | _rxId = idA; 245 | _rxRtr = (readRegister(REG_RXBnSIDL(n)) & FLAG_SRR) ? true : false; 246 | } 247 | _rxDlc = readRegister(REG_RXBnDLC(n)) & 0x0f; 248 | _rxIndex = 0; 249 | 250 | if (_rxRtr) { 251 | _rxLength = 0; 252 | } else { 253 | _rxLength = _rxDlc; 254 | 255 | for (int i = 0; i < _rxLength; i++) { 256 | _rxData[i] = readRegister(REG_RXBnD0(n) + i); 257 | } 258 | } 259 | 260 | modifyRegister(REG_CANINTF, FLAG_RXnIF(n), 0x00); 261 | 262 | return _rxDlc; 263 | } 264 | 265 | void MCP2515Class::onReceive(void(*callback)(int)) 266 | { 267 | CANControllerClass::onReceive(callback); 268 | 269 | pinMode(_intPin, INPUT); 270 | 271 | if (callback) { 272 | SPI.usingInterrupt(digitalPinToInterrupt(_intPin)); 273 | attachInterrupt(digitalPinToInterrupt(_intPin), MCP2515Class::onInterrupt, LOW); 274 | } else { 275 | detachInterrupt(digitalPinToInterrupt(_intPin)); 276 | #ifdef SPI_HAS_NOTUSINGINTERRUPT 277 | SPI.notUsingInterrupt(digitalPinToInterrupt(_intPin)); 278 | #endif 279 | } 280 | } 281 | 282 | int MCP2515Class::filter(int id, int mask) 283 | { 284 | id &= 0x7ff; 285 | mask &= 0x7ff; 286 | 287 | // config mode 288 | writeRegister(REG_CANCTRL, 0x80); 289 | if (readRegister(REG_CANCTRL) != 0x80) { 290 | return 0; 291 | } 292 | 293 | for (int n = 0; n < 2; n++) { 294 | // standard only 295 | writeRegister(REG_RXBnCTRL(n), FLAG_RXM0); 296 | writeRegister(REG_RXBnCTRL(n), FLAG_RXM0); 297 | 298 | writeRegister(REG_RXMnSIDH(n), mask >> 3); 299 | writeRegister(REG_RXMnSIDL(n), mask << 5); 300 | writeRegister(REG_RXMnEID8(n), 0); 301 | writeRegister(REG_RXMnEID0(n), 0); 302 | } 303 | 304 | for (int n = 0; n < 6; n++) { 305 | writeRegister(REG_RXFnSIDH(n), id >> 3); 306 | writeRegister(REG_RXFnSIDL(n), id << 5); 307 | writeRegister(REG_RXFnEID8(n), 0); 308 | writeRegister(REG_RXFnEID0(n), 0); 309 | } 310 | 311 | // normal mode 312 | writeRegister(REG_CANCTRL, 0x00); 313 | if (readRegister(REG_CANCTRL) != 0x00) { 314 | return 0; 315 | } 316 | 317 | return 1; 318 | } 319 | 320 | int MCP2515Class::filterExtended(long id, long mask) 321 | { 322 | id &= 0x1FFFFFFF; 323 | mask &= 0x1FFFFFFF; 324 | 325 | // config mode 326 | writeRegister(REG_CANCTRL, 0x80); 327 | if (readRegister(REG_CANCTRL) != 0x80) { 328 | return 0; 329 | } 330 | 331 | for (int n = 0; n < 2; n++) { 332 | // extended only 333 | writeRegister(REG_RXBnCTRL(n), FLAG_RXM1); 334 | writeRegister(REG_RXBnCTRL(n), FLAG_RXM1); 335 | 336 | writeRegister(REG_RXMnSIDH(n), mask >> 21); 337 | writeRegister(REG_RXMnSIDL(n), (((mask >> 18) & 0x03) << 5) | FLAG_EXIDE | ((mask >> 16) & 0x03)); 338 | writeRegister(REG_RXMnEID8(n), (mask >> 8) & 0xff); 339 | writeRegister(REG_RXMnEID0(n), mask & 0xff); 340 | } 341 | 342 | for (int n = 0; n < 6; n++) { 343 | writeRegister(REG_RXFnSIDH(n), id >> 21); 344 | writeRegister(REG_RXFnSIDL(n), (((id >> 18) & 0x03) << 5) | FLAG_EXIDE | ((id >> 16) & 0x03)); 345 | writeRegister(REG_RXFnEID8(n), (id >> 8) & 0xff); 346 | writeRegister(REG_RXFnEID0(n), id & 0xff); 347 | } 348 | 349 | // normal mode 350 | writeRegister(REG_CANCTRL, 0x00); 351 | if (readRegister(REG_CANCTRL) != 0x00) { 352 | return 0; 353 | } 354 | 355 | return 1; 356 | } 357 | 358 | int MCP2515Class::observe() 359 | { 360 | writeRegister(REG_CANCTRL, 0x80); 361 | if (readRegister(REG_CANCTRL) != 0x80) { 362 | return 0; 363 | } 364 | 365 | return 1; 366 | } 367 | 368 | int MCP2515Class::loopback() 369 | { 370 | writeRegister(REG_CANCTRL, 0x40); 371 | if (readRegister(REG_CANCTRL) != 0x40) { 372 | return 0; 373 | } 374 | 375 | return 1; 376 | } 377 | 378 | int MCP2515Class::sleep() 379 | { 380 | writeRegister(REG_CANCTRL, 0x01); 381 | if (readRegister(REG_CANCTRL) != 0x01) { 382 | return 0; 383 | } 384 | 385 | return 1; 386 | } 387 | 388 | int MCP2515Class::wakeup() 389 | { 390 | writeRegister(REG_CANCTRL, 0x00); 391 | if (readRegister(REG_CANCTRL) != 0x00) { 392 | return 0; 393 | } 394 | 395 | return 1; 396 | } 397 | 398 | void MCP2515Class::setPins(int cs, int irq) 399 | { 400 | _csPin = cs; 401 | _intPin = irq; 402 | } 403 | 404 | void MCP2515Class::setSPIFrequency(uint32_t frequency) 405 | { 406 | _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); 407 | } 408 | 409 | void MCP2515Class::setClockFrequency(long clockFrequency) 410 | { 411 | _clockFrequency = clockFrequency; 412 | } 413 | 414 | void MCP2515Class::dumpRegisters(Stream& out) 415 | { 416 | for (int i = 0; i < 128; i++) { 417 | byte b = readRegister(i); 418 | 419 | out.print("0x"); 420 | if (i < 16) { 421 | out.print('0'); 422 | } 423 | out.print(i, HEX); 424 | out.print(": 0x"); 425 | if (b < 16) { 426 | out.print('0'); 427 | } 428 | out.println(b, HEX); 429 | } 430 | } 431 | 432 | void MCP2515Class::reset() 433 | { 434 | SPI.beginTransaction(_spiSettings); 435 | digitalWrite(_csPin, LOW); 436 | SPI.transfer(0xc0); 437 | digitalWrite(_csPin, HIGH); 438 | SPI.endTransaction(); 439 | 440 | delayMicroseconds(10); 441 | } 442 | 443 | void MCP2515Class::handleInterrupt() 444 | { 445 | if (readRegister(REG_CANINTF) == 0) { 446 | return; 447 | } 448 | 449 | while (parsePacket()) { 450 | _onReceive(available()); 451 | } 452 | } 453 | 454 | uint8_t MCP2515Class::readRegister(uint8_t address) 455 | { 456 | uint8_t value; 457 | 458 | SPI.beginTransaction(_spiSettings); 459 | digitalWrite(_csPin, LOW); 460 | SPI.transfer(0x03); 461 | SPI.transfer(address); 462 | value = SPI.transfer(0x00); 463 | digitalWrite(_csPin, HIGH); 464 | SPI.endTransaction(); 465 | 466 | return value; 467 | } 468 | 469 | void MCP2515Class::modifyRegister(uint8_t address, uint8_t mask, uint8_t value) 470 | { 471 | SPI.beginTransaction(_spiSettings); 472 | digitalWrite(_csPin, LOW); 473 | SPI.transfer(0x05); 474 | SPI.transfer(address); 475 | SPI.transfer(mask); 476 | SPI.transfer(value); 477 | digitalWrite(_csPin, HIGH); 478 | SPI.endTransaction(); 479 | } 480 | 481 | void MCP2515Class::writeRegister(uint8_t address, uint8_t value) 482 | { 483 | SPI.beginTransaction(_spiSettings); 484 | digitalWrite(_csPin, LOW); 485 | SPI.transfer(0x02); 486 | SPI.transfer(address); 487 | SPI.transfer(value); 488 | digitalWrite(_csPin, HIGH); 489 | SPI.endTransaction(); 490 | } 491 | 492 | void MCP2515Class::onInterrupt() 493 | { 494 | CAN.handleInterrupt(); 495 | } 496 | 497 | MCP2515Class CAN; 498 | 499 | #endif -------------------------------------------------------------------------------- /canDrive/01_canSniffer_Arduino/MCP2515.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef ARDUINO_ARCH_ESP32 5 | 6 | #ifndef MCP2515_H 7 | #define MCP2515_H 8 | 9 | #include 10 | 11 | #include "CANController.h" 12 | 13 | #define MCP2515_DEFAULT_CLOCK_FREQUENCY 8e6 14 | 15 | #if defined(ARDUINO_ARCH_SAMD) && defined(PIN_SPI_MISO) && defined(PIN_SPI_MOSI) && defined(PIN_SPI_SCK) && (PIN_SPI_MISO == 10) && (PIN_SPI_MOSI == 8) && (PIN_SPI_SCK == 9) 16 | // Arduino MKR board: MKR CAN shield CS is pin 3, INT is pin 7 17 | #define MCP2515_DEFAULT_CS_PIN 3 18 | #define MCP2515_DEFAULT_INT_PIN 7 19 | #else 20 | #define MCP2515_DEFAULT_CS_PIN 10 21 | #define MCP2515_DEFAULT_INT_PIN 2 22 | #endif 23 | 24 | class MCP2515Class : public CANControllerClass { 25 | 26 | public: 27 | MCP2515Class(); 28 | virtual ~MCP2515Class(); 29 | 30 | virtual int begin(long baudRate); 31 | virtual void end(); 32 | 33 | virtual int endPacket(); 34 | 35 | virtual int parsePacket(); 36 | 37 | virtual void onReceive(void(*callback)(int)); 38 | 39 | using CANControllerClass::filter; 40 | virtual int filter(int id, int mask); 41 | using CANControllerClass::filterExtended; 42 | virtual int filterExtended(long id, long mask); 43 | 44 | virtual int observe(); 45 | virtual int loopback(); 46 | virtual int sleep(); 47 | virtual int wakeup(); 48 | 49 | void setPins(int cs = MCP2515_DEFAULT_CS_PIN, int irq = MCP2515_DEFAULT_INT_PIN); 50 | void setSPIFrequency(uint32_t frequency); 51 | void setClockFrequency(long clockFrequency); 52 | 53 | void dumpRegisters(Stream& out); 54 | 55 | private: 56 | void reset(); 57 | 58 | void handleInterrupt(); 59 | 60 | uint8_t readRegister(uint8_t address); 61 | void modifyRegister(uint8_t address, uint8_t mask, uint8_t value); 62 | void writeRegister(uint8_t address, uint8_t value); 63 | 64 | static void onInterrupt(); 65 | 66 | private: 67 | SPISettings _spiSettings; 68 | int _csPin; 69 | int _intPin; 70 | long _clockFrequency; 71 | }; 72 | 73 | extern MCP2515Class CAN; 74 | 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /canDrive/01_canSniffer_Arduino/canSniffer/canSniffer.ino: -------------------------------------------------------------------------------- 1 | // Developer: 2 | // Adam Varga, 2020, All rights reserved. 3 | // Licence: 4 | // Licenced under the MIT licence. See LICENCE file in the project root. 5 | // Usage of this code: 6 | // This code creates the interface between the car 7 | // and the canSniffer_GUI application. If the RANDOM_CAN 8 | // define is set to 1, this code is generating random 9 | // CAN packets in order to test the higher level code. 10 | // The received packets will be echoed back. If the 11 | // RANDOM_CAN define is set to 0, the CAN_SPEED define 12 | // has to match the speed of the desired CAN channel in 13 | // order to receive and transfer from and to the CAN bus. 14 | // Serial speed is 250000baud <- might need to be increased. 15 | // Required arduino packages: 16 | // - CAN by Sandeep Mistry (https://github.com/sandeepmistry/arduino-CAN) 17 | // Required modifications: 18 | // - MCP2515.h: 16e6 clock frequency reduced to 8e6 (depending on MCP2515 clock) 19 | // - MCP2515.cpp: extend CNF_MAPPER with your desired CAN speeds 20 | //------------------------------------------------------------------------------ 21 | #include 22 | //------------------------------------------------------------------------------ 23 | // Settings 24 | #define RANDOM_CAN 1 25 | #define CAN_SPEED (33E3) //LOW=33E3, MID=95E3, HIGH=500E3 (for Vectra) 26 | //------------------------------------------------------------------------------ 27 | // Inits, globals 28 | typedef struct { 29 | unsigned int id; 30 | byte rtr; 31 | byte ide; 32 | byte dlc; 33 | byte dataArray[20]; 34 | } packet_t; 35 | 36 | const char SEPARATOR = ','; 37 | const char TERMINATOR = '\n'; 38 | const char RXBUF_LEN = 100; 39 | //------------------------------------------------------------------------------ 40 | // Printing a packet to serial 41 | void printHex(int num) { 42 | if (num < 0x10) { 43 | Serial.print("0"); 44 | } 45 | Serial.print(num, HEX); 46 | } 47 | 48 | void printPacket(packet_t * packet) { 49 | // packet format (hex string): [ID],[RTR],[IDE],[DATABYTES 0..8B]\n 50 | // example: 014A,00,00,1A002B003C004D\n 51 | printHex(packet->id); 52 | Serial.print(SEPARATOR); 53 | printHex(packet->rtr); 54 | Serial.print(SEPARATOR); 55 | printHex(packet->ide); 56 | Serial.print(SEPARATOR); 57 | // DLC is determinded by number of data bytes, format: [00] 58 | for (int i = 0; i < packet->dlc; i++) { 59 | printHex(packet->dataArray[i]); 60 | } 61 | Serial.print(TERMINATOR); 62 | } 63 | //------------------------------------------------------------------------------ 64 | // CAN packet simulator 65 | void CANsimulate(void) { 66 | packet_t txPacket; 67 | 68 | int sampleIdList[] = {0x110, 0x115, 0x23A, 0x257, 0x501, 0x601, 0x621}; 69 | int idIndex = random (sizeof(sampleIdList) / sizeof(sampleIdList[0])); 70 | int sampleData[] = {0xA, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F, 0xA0, 0xB1}; 71 | 72 | txPacket.id = sampleIdList[idIndex]; 73 | txPacket.ide = txPacket.id > 2047 ? 1 : 0; 74 | txPacket.rtr = random(2); 75 | txPacket.dlc = random(1, 9); 76 | 77 | for (int i = 0; i < txPacket.dlc ; i++) { 78 | int changeByte = random(4); 79 | if (changeByte == 0) { 80 | sampleData[i] = random(256); 81 | } 82 | txPacket.dataArray[i] = sampleData[i]; 83 | } 84 | 85 | printPacket(&txPacket); 86 | } 87 | //------------------------------------------------------------------------------ 88 | // CAN RX, TX 89 | void onCANReceive(int packetSize) { 90 | // received a CAN packet 91 | packet_t rxPacket; 92 | rxPacket.id = CAN.packetId(); 93 | rxPacket.rtr = CAN.packetRtr() ? 1 : 0; 94 | rxPacket.ide = CAN.packetExtended() ? 1 : 0; 95 | rxPacket.dlc = CAN.packetDlc(); 96 | byte i = 0; 97 | while (CAN.available()) { 98 | rxPacket.dataArray[i++] = CAN.read(); 99 | if (i >= (sizeof(rxPacket.dataArray) / (sizeof(rxPacket.dataArray[0])))) { 100 | break; 101 | } 102 | } 103 | printPacket(&rxPacket); 104 | } 105 | 106 | void sendPacketToCan(packet_t * packet) { 107 | for (int retries = 10; retries > 0; retries--) { 108 | bool rtr = packet->rtr ? true : false; 109 | CAN.beginPacket(packet->id, packet->dlc, rtr); 110 | CAN.write(packet->dataArray, packet->dlc); 111 | if (CAN.endPacket()) { 112 | // success 113 | break; 114 | } else if (retries <= 1) { 115 | return; 116 | } 117 | } 118 | } 119 | //------------------------------------------------------------------------------ 120 | // Serial parser 121 | char getNum(char c) { 122 | if (c >= '0' && c <= '9') { return c - '0'; } 123 | if (c >= 'a' && c <= 'f') { return c - 'a' + 10; } 124 | if (c >= 'A' && c <= 'F') { return c - 'A' + 10; } 125 | return 0; 126 | } 127 | 128 | char * strToHex(char * str, byte * hexArray, byte * len) { 129 | byte *ptr = hexArray; 130 | char * idx; 131 | for (idx = str ; *idx != SEPARATOR && *idx != TERMINATOR; ++idx, ++ptr ) { 132 | *ptr = (getNum( *idx++ ) << 4) + getNum( *idx ); 133 | } 134 | *len = ptr - hexArray; 135 | return idx; 136 | } 137 | 138 | void rxParse(char * buf, int len) { 139 | packet_t rxPacket; 140 | char * ptr = buf; 141 | // All elements have to have leading zero! 142 | 143 | // ID 144 | byte idTempArray[4], tempLen; 145 | ptr = strToHex(ptr, idTempArray, &tempLen); 146 | rxPacket.id = 0; 147 | for (int i = 0; i < tempLen; i++) { 148 | rxPacket.id |= idTempArray[i] << ((tempLen - i - 1) * 8); 149 | } 150 | 151 | // RTR 152 | ptr = strToHex(ptr + 1, &rxPacket.rtr, &tempLen); 153 | 154 | // IDE 155 | ptr = strToHex(ptr + 1, &rxPacket.ide, &tempLen); 156 | 157 | // DATA 158 | ptr = strToHex(ptr + 1, rxPacket.dataArray, &rxPacket.dlc); 159 | 160 | #if RANDOM_CAN == 1 161 | // echo back 162 | printPacket(&rxPacket); 163 | #else 164 | sendPacketToCan(&rxPacket); 165 | #endif 166 | } 167 | 168 | void RXcallback(void) { 169 | static int rxPtr = 0; 170 | static char rxBuf[RXBUF_LEN]; 171 | 172 | while (Serial.available() > 0) { 173 | if (rxPtr >= RXBUF_LEN) { 174 | rxPtr = 0; 175 | } 176 | char c = Serial.read(); 177 | rxBuf[rxPtr++] = c; 178 | if (c == TERMINATOR) { 179 | rxParse(rxBuf, rxPtr); 180 | rxPtr = 0; 181 | } 182 | } 183 | } 184 | 185 | //------------------------------------------------------------------------------ 186 | // Setup 187 | void setup() { 188 | Serial.begin(250000); 189 | while (!Serial) { 190 | ; // wait for serial port to connect. Needed for native USB port only 191 | } 192 | 193 | #if RANDOM_CAN == 1 194 | randomSeed(12345); 195 | Serial.println("randomCAN Started"); 196 | #else 197 | if (!CAN.begin(CAN_SPEED)) { 198 | Serial.println("Starting CAN failed!"); 199 | while (1); 200 | } 201 | // register the receive callback 202 | CAN.onReceive(onCANReceive); 203 | Serial.println("CAN RX TX Started"); 204 | #endif 205 | } 206 | //------------------------------------------------------------------------------ 207 | // Main 208 | void loop() { 209 | RXcallback(); 210 | #if RANDOM_CAN == 1 211 | CANsimulate(); 212 | delay(100); 213 | #endif 214 | } 215 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/FileLoader.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QThread, pyqtSignal 2 | import csv 3 | 4 | 5 | class FileLoaderThread(QThread): 6 | newRowSignal = pyqtSignal(list) 7 | loadingFinishedSignal = pyqtSignal() 8 | path = None 9 | delayMs = 0 10 | 11 | def __init__(self): 12 | super(FileLoaderThread, self).__init__() 13 | self.isRunning = False 14 | 15 | def enable(self, path, delayMs): 16 | self.isRunning = True 17 | self.path = path 18 | self.delayMs = delayMs 19 | 20 | def stop(self): 21 | self.isRunning = False 22 | self.path = None 23 | 24 | def run(self): 25 | while self.isRunning: 26 | if self.path is not None: 27 | try: 28 | with open(str(self.path), 'r') as stream: 29 | for rowData in csv.reader(stream): 30 | if not self.isRunning: 31 | break 32 | self.newRowSignal.emit(rowData) 33 | self.msleep(self.delayMs) 34 | self.loadingFinishedSignal.emit() 35 | except OSError: 36 | print("file not found: " + self.path) 37 | self.stop() 38 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/HideOldPackets.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QThread, pyqtSignal 2 | 3 | 4 | class HideOldPacketsThread(QThread): 5 | hideOldPacketsSignal = pyqtSignal() 6 | 7 | def __init__(self): 8 | super(HideOldPacketsThread, self).__init__() 9 | self.isRunning = False 10 | self.period = 5 11 | 12 | def stop(self): 13 | self.isRunning = False 14 | 15 | def enable(self, _period): 16 | self.isRunning = True 17 | self.period = _period 18 | 19 | def run(self): 20 | while self.isRunning: 21 | self.sleep(self.period) 22 | self.hideOldPacketsSignal.emit() 23 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/SerialReader.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QThread, pyqtSignal 2 | import serial 3 | 4 | 5 | class SerialReaderThread(QThread): 6 | receivedPacketSignal = pyqtSignal(str) 7 | buf = bytearray() 8 | 9 | def __init__(self, serial=None): 10 | super(SerialReaderThread, self).__init__() 11 | self.serial = serial 12 | self.isRunning = False 13 | 14 | def stop(self): 15 | self.isRunning = False 16 | 17 | def run(self): 18 | self.isRunning = True 19 | while self.isRunning: 20 | # Because of the high transmission speed, we shouldn't assume that the internal serial buffer 21 | # will only contain one package at a time, so I split that buffer by end line characters. 22 | i = self.buf.find(b"\n") 23 | if i >= 0: 24 | r = self.buf[:i + 1] 25 | self.buf = self.buf[i + 1:] 26 | # print(r.decode("utf-8")) 27 | try: 28 | decodedData = r.decode("utf-8") 29 | self.receivedPacketSignal.emit(decodedData) 30 | except UnicodeDecodeError as e: 31 | print(e) 32 | try: 33 | incomingBytesNum = max(1, min(2048, self.serial.in_waiting)) 34 | data = self.serial.read(incomingBytesNum) 35 | except serial.SerialException as e: 36 | print(e) 37 | pass 38 | # There is no new data from serial port 39 | except TypeError as e: 40 | # Disconnect of USB->UART occured 41 | print("Serial disconnected") 42 | print(e) 43 | self.port.close() 44 | else: 45 | if len(data): 46 | self.buf.extend(data) 47 | self.msleep(100) -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/SerialWriter.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QThread, pyqtSignal 2 | import queue 3 | 4 | 5 | class SerialWriterThread(QThread): 6 | packetSentSignal = pyqtSignal() 7 | writerQ = queue.Queue() 8 | tempQ = queue.Queue() 9 | repeatedWriteDelay = 0 10 | normalWriteDelay = 0 11 | 12 | def __init__(self, serial=None): 13 | super(SerialWriterThread, self).__init__() 14 | self.serial = serial 15 | self.isRunning = False 16 | 17 | def clearQueues(self): 18 | self.writerQ.queue.clear() 19 | self.tempQ.queue.clear() 20 | 21 | def stop(self): 22 | self.isRunning = False 23 | self.clearQueues() 24 | 25 | def write(self, packet): 26 | self.writerQ.put(packet) 27 | 28 | def setRepeatedWriteDelay(self, delay): 29 | self.repeatedWriteDelay = delay 30 | with self.tempQ.mutex: 31 | self.tempQ.queue.clear() 32 | 33 | def setNormalWriteDelay(self, delay): 34 | self.normalWriteDelay = delay 35 | 36 | def run(self): 37 | self.isRunning = True 38 | while self.isRunning: 39 | if not self.writerQ.empty(): 40 | element = self.writerQ.get() 41 | if isinstance(element, list): 42 | num = self.serial.write(bytearray(element)) 43 | #print(bytearray(element)) 44 | else: 45 | num = self.serial.write(element.encode("utf-8")) 46 | #print(element.encode("utf-8")) 47 | 48 | if self.normalWriteDelay != 0: 49 | self.msleep(self.normalWriteDelay) 50 | self.normalWriteDelay = 0 51 | 52 | if self.repeatedWriteDelay != 0: 53 | self.tempQ.put(element) 54 | 55 | self.packetSentSignal.emit() 56 | else: 57 | if self.repeatedWriteDelay != 0 and not self.tempQ.empty(): 58 | self.msleep(self.repeatedWriteDelay) 59 | while not self.tempQ.empty(): 60 | self.writerQ.put(self.tempQ.get()) 61 | else: 62 | self.msleep(1) 63 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/canSniffer_ui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'canSniffer.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.1 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_MainWindow(object): 15 | def setupUi(self, MainWindow): 16 | MainWindow.setObjectName("MainWindow") 17 | MainWindow.setWindowModality(QtCore.Qt.NonModal) 18 | MainWindow.setEnabled(True) 19 | MainWindow.resize(1202, 788) 20 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 21 | sizePolicy.setHorizontalStretch(0) 22 | sizePolicy.setVerticalStretch(0) 23 | sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) 24 | MainWindow.setSizePolicy(sizePolicy) 25 | self.centralwidget = QtWidgets.QWidget(MainWindow) 26 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 27 | sizePolicy.setHorizontalStretch(0) 28 | sizePolicy.setVerticalStretch(0) 29 | sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth()) 30 | self.centralwidget.setSizePolicy(sizePolicy) 31 | self.centralwidget.setObjectName("centralwidget") 32 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget) 33 | self.verticalLayout_3.setObjectName("verticalLayout_3") 34 | self.verticalLayout = QtWidgets.QVBoxLayout() 35 | self.verticalLayout.setObjectName("verticalLayout") 36 | self.upperHoriz = QtWidgets.QHBoxLayout() 37 | self.upperHoriz.setObjectName("upperHoriz") 38 | self.groupBox = QtWidgets.QGroupBox(self.centralwidget) 39 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 40 | sizePolicy.setHorizontalStretch(0) 41 | sizePolicy.setVerticalStretch(0) 42 | sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth()) 43 | self.groupBox.setSizePolicy(sizePolicy) 44 | self.groupBox.setMinimumSize(QtCore.QSize(250, 20)) 45 | font = QtGui.QFont() 46 | font.setPointSize(10) 47 | self.groupBox.setFont(font) 48 | self.groupBox.setObjectName("groupBox") 49 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox) 50 | self.horizontalLayout_3.setContentsMargins(-1, 1, -1, 1) 51 | self.horizontalLayout_3.setObjectName("horizontalLayout_3") 52 | self.portScanButton = QtWidgets.QPushButton(self.groupBox) 53 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 54 | sizePolicy.setHorizontalStretch(0) 55 | sizePolicy.setVerticalStretch(0) 56 | sizePolicy.setHeightForWidth(self.portScanButton.sizePolicy().hasHeightForWidth()) 57 | self.portScanButton.setSizePolicy(sizePolicy) 58 | self.portScanButton.setMinimumSize(QtCore.QSize(0, 20)) 59 | font = QtGui.QFont() 60 | font.setPointSize(11) 61 | self.portScanButton.setFont(font) 62 | self.portScanButton.setObjectName("portScanButton") 63 | self.horizontalLayout_3.addWidget(self.portScanButton) 64 | self.portSelectorComboBox = QtWidgets.QComboBox(self.groupBox) 65 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 66 | sizePolicy.setHorizontalStretch(0) 67 | sizePolicy.setVerticalStretch(0) 68 | sizePolicy.setHeightForWidth(self.portSelectorComboBox.sizePolicy().hasHeightForWidth()) 69 | self.portSelectorComboBox.setSizePolicy(sizePolicy) 70 | self.portSelectorComboBox.setMinimumSize(QtCore.QSize(0, 20)) 71 | font = QtGui.QFont() 72 | font.setPointSize(11) 73 | self.portSelectorComboBox.setFont(font) 74 | self.portSelectorComboBox.setObjectName("portSelectorComboBox") 75 | self.horizontalLayout_3.addWidget(self.portSelectorComboBox) 76 | self.portConnectButton = QtWidgets.QPushButton(self.groupBox) 77 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 78 | sizePolicy.setHorizontalStretch(0) 79 | sizePolicy.setVerticalStretch(0) 80 | sizePolicy.setHeightForWidth(self.portConnectButton.sizePolicy().hasHeightForWidth()) 81 | self.portConnectButton.setSizePolicy(sizePolicy) 82 | self.portConnectButton.setMinimumSize(QtCore.QSize(0, 20)) 83 | font = QtGui.QFont() 84 | font.setPointSize(11) 85 | self.portConnectButton.setFont(font) 86 | self.portConnectButton.setObjectName("portConnectButton") 87 | self.horizontalLayout_3.addWidget(self.portConnectButton) 88 | self.portDisconnectButton = QtWidgets.QPushButton(self.groupBox) 89 | self.portDisconnectButton.setEnabled(False) 90 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 91 | sizePolicy.setHorizontalStretch(0) 92 | sizePolicy.setVerticalStretch(0) 93 | sizePolicy.setHeightForWidth(self.portDisconnectButton.sizePolicy().hasHeightForWidth()) 94 | self.portDisconnectButton.setSizePolicy(sizePolicy) 95 | self.portDisconnectButton.setMinimumSize(QtCore.QSize(0, 20)) 96 | font = QtGui.QFont() 97 | font.setPointSize(11) 98 | self.portDisconnectButton.setFont(font) 99 | self.portDisconnectButton.setObjectName("portDisconnectButton") 100 | self.horizontalLayout_3.addWidget(self.portDisconnectButton) 101 | self.upperHoriz.addWidget(self.groupBox) 102 | self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget) 103 | font = QtGui.QFont() 104 | font.setPointSize(10) 105 | self.groupBox_5.setFont(font) 106 | self.groupBox_5.setObjectName("groupBox_5") 107 | self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.groupBox_5) 108 | self.horizontalLayout_6.setContentsMargins(-1, 1, -1, 1) 109 | self.horizontalLayout_6.setObjectName("horizontalLayout_6") 110 | self.horizontalLayout_5 = QtWidgets.QHBoxLayout() 111 | self.horizontalLayout_5.setObjectName("horizontalLayout_5") 112 | self.label_3 = QtWidgets.QLabel(self.groupBox_5) 113 | self.label_3.setEnabled(False) 114 | font = QtGui.QFont() 115 | font.setPointSize(11) 116 | self.label_3.setFont(font) 117 | self.label_3.setObjectName("label_3") 118 | self.horizontalLayout_5.addWidget(self.label_3) 119 | self.activeChannelComboBox = QtWidgets.QComboBox(self.groupBox_5) 120 | self.activeChannelComboBox.setEnabled(False) 121 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 122 | sizePolicy.setHorizontalStretch(0) 123 | sizePolicy.setVerticalStretch(0) 124 | sizePolicy.setHeightForWidth(self.activeChannelComboBox.sizePolicy().hasHeightForWidth()) 125 | self.activeChannelComboBox.setSizePolicy(sizePolicy) 126 | self.activeChannelComboBox.setMinimumSize(QtCore.QSize(0, 0)) 127 | font = QtGui.QFont() 128 | font.setPointSize(10) 129 | self.activeChannelComboBox.setFont(font) 130 | self.activeChannelComboBox.setObjectName("activeChannelComboBox") 131 | self.activeChannelComboBox.addItem("") 132 | self.activeChannelComboBox.addItem("") 133 | self.activeChannelComboBox.addItem("") 134 | self.horizontalLayout_5.addWidget(self.activeChannelComboBox) 135 | self.horizontalLayout_6.addLayout(self.horizontalLayout_5) 136 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 137 | self.horizontalLayout_2.setSpacing(0) 138 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 139 | self.label = QtWidgets.QLabel(self.groupBox_5) 140 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 141 | sizePolicy.setHorizontalStretch(0) 142 | sizePolicy.setVerticalStretch(0) 143 | sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) 144 | self.label.setSizePolicy(sizePolicy) 145 | self.label.setMinimumSize(QtCore.QSize(88, 0)) 146 | font = QtGui.QFont() 147 | font.setPointSize(11) 148 | self.label.setFont(font) 149 | self.label.setObjectName("label") 150 | self.horizontalLayout_2.addWidget(self.label) 151 | self.playbackDelaySpinBox = QtWidgets.QSpinBox(self.groupBox_5) 152 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 153 | sizePolicy.setHorizontalStretch(0) 154 | sizePolicy.setVerticalStretch(0) 155 | sizePolicy.setHeightForWidth(self.playbackDelaySpinBox.sizePolicy().hasHeightForWidth()) 156 | self.playbackDelaySpinBox.setSizePolicy(sizePolicy) 157 | self.playbackDelaySpinBox.setMinimumSize(QtCore.QSize(20, 20)) 158 | font = QtGui.QFont() 159 | font.setPointSize(10) 160 | self.playbackDelaySpinBox.setFont(font) 161 | self.playbackDelaySpinBox.setMaximum(999) 162 | self.playbackDelaySpinBox.setProperty("value", 0) 163 | self.playbackDelaySpinBox.setObjectName("playbackDelaySpinBox") 164 | self.horizontalLayout_2.addWidget(self.playbackDelaySpinBox) 165 | self.horizontalLayout_6.addLayout(self.horizontalLayout_2) 166 | self.autoclearCheckBox = QtWidgets.QCheckBox(self.groupBox_5) 167 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 168 | sizePolicy.setHorizontalStretch(0) 169 | sizePolicy.setVerticalStretch(0) 170 | sizePolicy.setHeightForWidth(self.autoclearCheckBox.sizePolicy().hasHeightForWidth()) 171 | self.autoclearCheckBox.setSizePolicy(sizePolicy) 172 | font = QtGui.QFont() 173 | font.setPointSize(11) 174 | self.autoclearCheckBox.setFont(font) 175 | self.autoclearCheckBox.setLayoutDirection(QtCore.Qt.RightToLeft) 176 | self.autoclearCheckBox.setChecked(True) 177 | self.autoclearCheckBox.setObjectName("autoclearCheckBox") 178 | self.horizontalLayout_6.addWidget(self.autoclearCheckBox) 179 | self.showSendingTableCheckBox = QtWidgets.QCheckBox(self.groupBox_5) 180 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 181 | sizePolicy.setHorizontalStretch(0) 182 | sizePolicy.setVerticalStretch(0) 183 | sizePolicy.setHeightForWidth(self.showSendingTableCheckBox.sizePolicy().hasHeightForWidth()) 184 | self.showSendingTableCheckBox.setSizePolicy(sizePolicy) 185 | font = QtGui.QFont() 186 | font.setPointSize(11) 187 | self.showSendingTableCheckBox.setFont(font) 188 | self.showSendingTableCheckBox.setLayoutDirection(QtCore.Qt.RightToLeft) 189 | self.showSendingTableCheckBox.setObjectName("showSendingTableCheckBox") 190 | self.horizontalLayout_6.addWidget(self.showSendingTableCheckBox) 191 | self.groupModeCheckBox = QtWidgets.QCheckBox(self.groupBox_5) 192 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 193 | sizePolicy.setHorizontalStretch(0) 194 | sizePolicy.setVerticalStretch(0) 195 | sizePolicy.setHeightForWidth(self.groupModeCheckBox.sizePolicy().hasHeightForWidth()) 196 | self.groupModeCheckBox.setSizePolicy(sizePolicy) 197 | font = QtGui.QFont() 198 | font.setPointSize(11) 199 | self.groupModeCheckBox.setFont(font) 200 | self.groupModeCheckBox.setLayoutDirection(QtCore.Qt.RightToLeft) 201 | self.groupModeCheckBox.setChecked(True) 202 | self.groupModeCheckBox.setObjectName("groupModeCheckBox") 203 | self.horizontalLayout_6.addWidget(self.groupModeCheckBox) 204 | self.line_6 = QtWidgets.QFrame(self.groupBox_5) 205 | self.line_6.setFrameShape(QtWidgets.QFrame.VLine) 206 | self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken) 207 | self.line_6.setObjectName("line_6") 208 | self.horizontalLayout_6.addWidget(self.line_6) 209 | self.hideControlsButton = QtWidgets.QPushButton(self.groupBox_5) 210 | self.hideControlsButton.setMaximumSize(QtCore.QSize(100, 16777215)) 211 | font = QtGui.QFont() 212 | font.setPointSize(11) 213 | self.hideControlsButton.setFont(font) 214 | self.hideControlsButton.setObjectName("hideControlsButton") 215 | self.horizontalLayout_6.addWidget(self.hideControlsButton) 216 | self.upperHoriz.addWidget(self.groupBox_5) 217 | self.verticalLayout.addLayout(self.upperHoriz) 218 | self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget) 219 | self.groupBox_4.setMinimumSize(QtCore.QSize(0, 50)) 220 | font = QtGui.QFont() 221 | font.setPointSize(10) 222 | self.groupBox_4.setFont(font) 223 | self.groupBox_4.setObjectName("groupBox_4") 224 | self.horizontalLayout_15 = QtWidgets.QHBoxLayout(self.groupBox_4) 225 | self.horizontalLayout_15.setContentsMargins(-1, 1, -1, 1) 226 | self.horizontalLayout_15.setObjectName("horizontalLayout_15") 227 | self.stopSniffingButton = QtWidgets.QPushButton(self.groupBox_4) 228 | self.stopSniffingButton.setEnabled(False) 229 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 230 | sizePolicy.setHorizontalStretch(0) 231 | sizePolicy.setVerticalStretch(0) 232 | sizePolicy.setHeightForWidth(self.stopSniffingButton.sizePolicy().hasHeightForWidth()) 233 | self.stopSniffingButton.setSizePolicy(sizePolicy) 234 | self.stopSniffingButton.setMinimumSize(QtCore.QSize(0, 20)) 235 | font = QtGui.QFont() 236 | font.setPointSize(11) 237 | self.stopSniffingButton.setFont(font) 238 | self.stopSniffingButton.setObjectName("stopSniffingButton") 239 | self.horizontalLayout_15.addWidget(self.stopSniffingButton) 240 | self.startSniffingButton = QtWidgets.QPushButton(self.groupBox_4) 241 | self.startSniffingButton.setEnabled(False) 242 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 243 | sizePolicy.setHorizontalStretch(0) 244 | sizePolicy.setVerticalStretch(0) 245 | sizePolicy.setHeightForWidth(self.startSniffingButton.sizePolicy().hasHeightForWidth()) 246 | self.startSniffingButton.setSizePolicy(sizePolicy) 247 | self.startSniffingButton.setMinimumSize(QtCore.QSize(0, 20)) 248 | font = QtGui.QFont() 249 | font.setPointSize(11) 250 | self.startSniffingButton.setFont(font) 251 | self.startSniffingButton.setObjectName("startSniffingButton") 252 | self.horizontalLayout_15.addWidget(self.startSniffingButton) 253 | self.line = QtWidgets.QFrame(self.groupBox_4) 254 | self.line.setMaximumSize(QtCore.QSize(16777215, 20)) 255 | self.line.setFrameShape(QtWidgets.QFrame.VLine) 256 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 257 | self.line.setObjectName("line") 258 | self.horizontalLayout_15.addWidget(self.line) 259 | self.loadSessionFromFileButton = QtWidgets.QPushButton(self.groupBox_4) 260 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 261 | sizePolicy.setHorizontalStretch(0) 262 | sizePolicy.setVerticalStretch(0) 263 | sizePolicy.setHeightForWidth(self.loadSessionFromFileButton.sizePolicy().hasHeightForWidth()) 264 | self.loadSessionFromFileButton.setSizePolicy(sizePolicy) 265 | self.loadSessionFromFileButton.setMinimumSize(QtCore.QSize(0, 20)) 266 | font = QtGui.QFont() 267 | font.setPointSize(11) 268 | self.loadSessionFromFileButton.setFont(font) 269 | self.loadSessionFromFileButton.setObjectName("loadSessionFromFileButton") 270 | self.horizontalLayout_15.addWidget(self.loadSessionFromFileButton) 271 | self.abortSessionLoadingButton = QtWidgets.QPushButton(self.groupBox_4) 272 | self.abortSessionLoadingButton.setEnabled(False) 273 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 274 | sizePolicy.setHorizontalStretch(0) 275 | sizePolicy.setVerticalStretch(0) 276 | sizePolicy.setHeightForWidth(self.abortSessionLoadingButton.sizePolicy().hasHeightForWidth()) 277 | self.abortSessionLoadingButton.setSizePolicy(sizePolicy) 278 | self.abortSessionLoadingButton.setMinimumSize(QtCore.QSize(0, 20)) 279 | font = QtGui.QFont() 280 | font.setPointSize(11) 281 | self.abortSessionLoadingButton.setFont(font) 282 | self.abortSessionLoadingButton.setObjectName("abortSessionLoadingButton") 283 | self.horizontalLayout_15.addWidget(self.abortSessionLoadingButton) 284 | self.verticalLayout.addWidget(self.groupBox_4) 285 | self.line_4 = QtWidgets.QFrame(self.centralwidget) 286 | self.line_4.setFrameShape(QtWidgets.QFrame.HLine) 287 | self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken) 288 | self.line_4.setObjectName("line_4") 289 | self.verticalLayout.addWidget(self.line_4) 290 | self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) 291 | self.tabWidget.setEnabled(True) 292 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) 293 | sizePolicy.setHorizontalStretch(0) 294 | sizePolicy.setVerticalStretch(0) 295 | sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) 296 | self.tabWidget.setSizePolicy(sizePolicy) 297 | self.tabWidget.setMinimumSize(QtCore.QSize(0, 0)) 298 | font = QtGui.QFont() 299 | font.setPointSize(10) 300 | self.tabWidget.setFont(font) 301 | self.tabWidget.setObjectName("tabWidget") 302 | self.tab = QtWidgets.QWidget() 303 | self.tab.setObjectName("tab") 304 | self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.tab) 305 | self.horizontalLayout_4.setObjectName("horizontalLayout_4") 306 | self.mainMessageTableWidget = QtWidgets.QTableWidget(self.tab) 307 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) 308 | sizePolicy.setHorizontalStretch(0) 309 | sizePolicy.setVerticalStretch(0) 310 | sizePolicy.setHeightForWidth(self.mainMessageTableWidget.sizePolicy().hasHeightForWidth()) 311 | self.mainMessageTableWidget.setSizePolicy(sizePolicy) 312 | self.mainMessageTableWidget.setMinimumSize(QtCore.QSize(0, 0)) 313 | self.mainMessageTableWidget.setAutoScroll(True) 314 | self.mainMessageTableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) 315 | self.mainMessageTableWidget.setAlternatingRowColors(True) 316 | self.mainMessageTableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) 317 | self.mainMessageTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) 318 | self.mainMessageTableWidget.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) 319 | self.mainMessageTableWidget.setShowGrid(True) 320 | self.mainMessageTableWidget.setGridStyle(QtCore.Qt.DotLine) 321 | self.mainMessageTableWidget.setObjectName("mainMessageTableWidget") 322 | self.mainMessageTableWidget.setColumnCount(13) 323 | self.mainMessageTableWidget.setRowCount(0) 324 | item = QtWidgets.QTableWidgetItem() 325 | item.setTextAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom) 326 | self.mainMessageTableWidget.setHorizontalHeaderItem(0, item) 327 | item = QtWidgets.QTableWidgetItem() 328 | item.setTextAlignment(QtCore.Qt.AlignCenter) 329 | self.mainMessageTableWidget.setHorizontalHeaderItem(1, item) 330 | item = QtWidgets.QTableWidgetItem() 331 | item.setTextAlignment(QtCore.Qt.AlignCenter) 332 | self.mainMessageTableWidget.setHorizontalHeaderItem(2, item) 333 | item = QtWidgets.QTableWidgetItem() 334 | item.setTextAlignment(QtCore.Qt.AlignCenter) 335 | self.mainMessageTableWidget.setHorizontalHeaderItem(3, item) 336 | item = QtWidgets.QTableWidgetItem() 337 | item.setTextAlignment(QtCore.Qt.AlignCenter) 338 | self.mainMessageTableWidget.setHorizontalHeaderItem(4, item) 339 | item = QtWidgets.QTableWidgetItem() 340 | item.setTextAlignment(QtCore.Qt.AlignCenter) 341 | self.mainMessageTableWidget.setHorizontalHeaderItem(5, item) 342 | item = QtWidgets.QTableWidgetItem() 343 | item.setTextAlignment(QtCore.Qt.AlignCenter) 344 | self.mainMessageTableWidget.setHorizontalHeaderItem(6, item) 345 | item = QtWidgets.QTableWidgetItem() 346 | item.setTextAlignment(QtCore.Qt.AlignCenter) 347 | self.mainMessageTableWidget.setHorizontalHeaderItem(7, item) 348 | item = QtWidgets.QTableWidgetItem() 349 | item.setTextAlignment(QtCore.Qt.AlignCenter) 350 | self.mainMessageTableWidget.setHorizontalHeaderItem(8, item) 351 | item = QtWidgets.QTableWidgetItem() 352 | item.setTextAlignment(QtCore.Qt.AlignCenter) 353 | self.mainMessageTableWidget.setHorizontalHeaderItem(9, item) 354 | item = QtWidgets.QTableWidgetItem() 355 | item.setTextAlignment(QtCore.Qt.AlignCenter) 356 | self.mainMessageTableWidget.setHorizontalHeaderItem(10, item) 357 | item = QtWidgets.QTableWidgetItem() 358 | item.setTextAlignment(QtCore.Qt.AlignCenter) 359 | self.mainMessageTableWidget.setHorizontalHeaderItem(11, item) 360 | item = QtWidgets.QTableWidgetItem() 361 | item.setTextAlignment(QtCore.Qt.AlignCenter) 362 | self.mainMessageTableWidget.setHorizontalHeaderItem(12, item) 363 | self.mainMessageTableWidget.verticalHeader().setStretchLastSection(False) 364 | self.horizontalLayout_4.addWidget(self.mainMessageTableWidget) 365 | self.scrollArea_2 = QtWidgets.QScrollArea(self.tab) 366 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 367 | sizePolicy.setHorizontalStretch(0) 368 | sizePolicy.setVerticalStretch(0) 369 | sizePolicy.setHeightForWidth(self.scrollArea_2.sizePolicy().hasHeightForWidth()) 370 | self.scrollArea_2.setSizePolicy(sizePolicy) 371 | self.scrollArea_2.setMinimumSize(QtCore.QSize(320, 0)) 372 | self.scrollArea_2.setWidgetResizable(True) 373 | self.scrollArea_2.setObjectName("scrollArea_2") 374 | self.scrollAreaWidgetContents_3 = QtWidgets.QWidget() 375 | self.scrollAreaWidgetContents_3.setGeometry(QtCore.QRect(0, 0, 311, 548)) 376 | self.scrollAreaWidgetContents_3.setObjectName("scrollAreaWidgetContents_3") 377 | self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents_3) 378 | self.verticalLayout_10.setObjectName("verticalLayout_10") 379 | self.clearTableButton = QtWidgets.QPushButton(self.scrollAreaWidgetContents_3) 380 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 381 | sizePolicy.setHorizontalStretch(0) 382 | sizePolicy.setVerticalStretch(0) 383 | sizePolicy.setHeightForWidth(self.clearTableButton.sizePolicy().hasHeightForWidth()) 384 | self.clearTableButton.setSizePolicy(sizePolicy) 385 | self.clearTableButton.setMinimumSize(QtCore.QSize(0, 20)) 386 | font = QtGui.QFont() 387 | font.setPointSize(11) 388 | self.clearTableButton.setFont(font) 389 | self.clearTableButton.setObjectName("clearTableButton") 390 | self.verticalLayout_10.addWidget(self.clearTableButton) 391 | self.groupBox_9 = QtWidgets.QGroupBox(self.scrollAreaWidgetContents_3) 392 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 393 | sizePolicy.setHorizontalStretch(0) 394 | sizePolicy.setVerticalStretch(0) 395 | sizePolicy.setHeightForWidth(self.groupBox_9.sizePolicy().hasHeightForWidth()) 396 | self.groupBox_9.setSizePolicy(sizePolicy) 397 | self.groupBox_9.setMinimumSize(QtCore.QSize(0, 0)) 398 | self.groupBox_9.setMaximumSize(QtCore.QSize(16777215, 16777215)) 399 | font = QtGui.QFont() 400 | font.setPointSize(10) 401 | self.groupBox_9.setFont(font) 402 | self.groupBox_9.setFlat(False) 403 | self.groupBox_9.setObjectName("groupBox_9") 404 | self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.groupBox_9) 405 | self.verticalLayout_13.setObjectName("verticalLayout_13") 406 | self.highlightNewIdCheckBox = QtWidgets.QCheckBox(self.groupBox_9) 407 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 408 | sizePolicy.setHorizontalStretch(0) 409 | sizePolicy.setVerticalStretch(0) 410 | sizePolicy.setHeightForWidth(self.highlightNewIdCheckBox.sizePolicy().hasHeightForWidth()) 411 | self.highlightNewIdCheckBox.setSizePolicy(sizePolicy) 412 | self.highlightNewIdCheckBox.setMinimumSize(QtCore.QSize(0, 20)) 413 | font = QtGui.QFont() 414 | font.setPointSize(11) 415 | self.highlightNewIdCheckBox.setFont(font) 416 | self.highlightNewIdCheckBox.setObjectName("highlightNewIdCheckBox") 417 | self.verticalLayout_13.addWidget(self.highlightNewIdCheckBox) 418 | self.highlightNewDataCheckBox = QtWidgets.QCheckBox(self.groupBox_9) 419 | self.highlightNewDataCheckBox.setEnabled(True) 420 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 421 | sizePolicy.setHorizontalStretch(0) 422 | sizePolicy.setVerticalStretch(0) 423 | sizePolicy.setHeightForWidth(self.highlightNewDataCheckBox.sizePolicy().hasHeightForWidth()) 424 | self.highlightNewDataCheckBox.setSizePolicy(sizePolicy) 425 | self.highlightNewDataCheckBox.setMinimumSize(QtCore.QSize(0, 20)) 426 | font = QtGui.QFont() 427 | font.setPointSize(11) 428 | self.highlightNewDataCheckBox.setFont(font) 429 | self.highlightNewDataCheckBox.setObjectName("highlightNewDataCheckBox") 430 | self.verticalLayout_13.addWidget(self.highlightNewDataCheckBox) 431 | self.horizontalLayout_10 = QtWidgets.QHBoxLayout() 432 | self.horizontalLayout_10.setContentsMargins(-1, 0, -1, -1) 433 | self.horizontalLayout_10.setSpacing(0) 434 | self.horizontalLayout_10.setObjectName("horizontalLayout_10") 435 | self.hideOldPacketsCheckBox = QtWidgets.QCheckBox(self.groupBox_9) 436 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 437 | sizePolicy.setHorizontalStretch(0) 438 | sizePolicy.setVerticalStretch(0) 439 | sizePolicy.setHeightForWidth(self.hideOldPacketsCheckBox.sizePolicy().hasHeightForWidth()) 440 | self.hideOldPacketsCheckBox.setSizePolicy(sizePolicy) 441 | self.hideOldPacketsCheckBox.setMinimumSize(QtCore.QSize(0, 20)) 442 | font = QtGui.QFont() 443 | font.setPointSize(11) 444 | self.hideOldPacketsCheckBox.setFont(font) 445 | self.hideOldPacketsCheckBox.setObjectName("hideOldPacketsCheckBox") 446 | self.horizontalLayout_10.addWidget(self.hideOldPacketsCheckBox) 447 | self.hideOldPeriod = QtWidgets.QSpinBox(self.groupBox_9) 448 | self.hideOldPeriod.setEnabled(False) 449 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 450 | sizePolicy.setHorizontalStretch(0) 451 | sizePolicy.setVerticalStretch(0) 452 | sizePolicy.setHeightForWidth(self.hideOldPeriod.sizePolicy().hasHeightForWidth()) 453 | self.hideOldPeriod.setSizePolicy(sizePolicy) 454 | font = QtGui.QFont() 455 | font.setPointSize(10) 456 | self.hideOldPeriod.setFont(font) 457 | self.hideOldPeriod.setProperty("value", 5) 458 | self.hideOldPeriod.setObjectName("hideOldPeriod") 459 | self.horizontalLayout_10.addWidget(self.hideOldPeriod) 460 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 461 | self.horizontalLayout_10.addItem(spacerItem) 462 | self.verticalLayout_13.addLayout(self.horizontalLayout_10) 463 | self.showOnlyIdsCheckBox = QtWidgets.QCheckBox(self.groupBox_9) 464 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 465 | sizePolicy.setHorizontalStretch(0) 466 | sizePolicy.setVerticalStretch(0) 467 | sizePolicy.setHeightForWidth(self.showOnlyIdsCheckBox.sizePolicy().hasHeightForWidth()) 468 | self.showOnlyIdsCheckBox.setSizePolicy(sizePolicy) 469 | self.showOnlyIdsCheckBox.setMinimumSize(QtCore.QSize(0, 20)) 470 | font = QtGui.QFont() 471 | font.setPointSize(11) 472 | self.showOnlyIdsCheckBox.setFont(font) 473 | self.showOnlyIdsCheckBox.setObjectName("showOnlyIdsCheckBox") 474 | self.verticalLayout_13.addWidget(self.showOnlyIdsCheckBox) 475 | self.showOnlyIdsLineEdit = QtWidgets.QLineEdit(self.groupBox_9) 476 | self.showOnlyIdsLineEdit.setEnabled(False) 477 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 478 | sizePolicy.setHorizontalStretch(0) 479 | sizePolicy.setVerticalStretch(0) 480 | sizePolicy.setHeightForWidth(self.showOnlyIdsLineEdit.sizePolicy().hasHeightForWidth()) 481 | self.showOnlyIdsLineEdit.setSizePolicy(sizePolicy) 482 | self.showOnlyIdsLineEdit.setMinimumSize(QtCore.QSize(0, 20)) 483 | self.showOnlyIdsLineEdit.setMaximumSize(QtCore.QSize(16777215, 16777215)) 484 | font = QtGui.QFont() 485 | font.setPointSize(10) 486 | self.showOnlyIdsLineEdit.setFont(font) 487 | self.showOnlyIdsLineEdit.setObjectName("showOnlyIdsLineEdit") 488 | self.verticalLayout_13.addWidget(self.showOnlyIdsLineEdit) 489 | self.hideIdsCheckBox = QtWidgets.QCheckBox(self.groupBox_9) 490 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 491 | sizePolicy.setHorizontalStretch(0) 492 | sizePolicy.setVerticalStretch(0) 493 | sizePolicy.setHeightForWidth(self.hideIdsCheckBox.sizePolicy().hasHeightForWidth()) 494 | self.hideIdsCheckBox.setSizePolicy(sizePolicy) 495 | self.hideIdsCheckBox.setMinimumSize(QtCore.QSize(0, 20)) 496 | font = QtGui.QFont() 497 | font.setPointSize(11) 498 | self.hideIdsCheckBox.setFont(font) 499 | self.hideIdsCheckBox.setObjectName("hideIdsCheckBox") 500 | self.verticalLayout_13.addWidget(self.hideIdsCheckBox) 501 | self.hideIdsLineEdit = QtWidgets.QLineEdit(self.groupBox_9) 502 | self.hideIdsLineEdit.setEnabled(False) 503 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 504 | sizePolicy.setHorizontalStretch(0) 505 | sizePolicy.setVerticalStretch(0) 506 | sizePolicy.setHeightForWidth(self.hideIdsLineEdit.sizePolicy().hasHeightForWidth()) 507 | self.hideIdsLineEdit.setSizePolicy(sizePolicy) 508 | self.hideIdsLineEdit.setMinimumSize(QtCore.QSize(0, 20)) 509 | self.hideIdsLineEdit.setMaximumSize(QtCore.QSize(16777215, 16777215)) 510 | font = QtGui.QFont() 511 | font.setPointSize(10) 512 | self.hideIdsLineEdit.setFont(font) 513 | self.hideIdsLineEdit.setObjectName("hideIdsLineEdit") 514 | self.verticalLayout_13.addWidget(self.hideIdsLineEdit) 515 | self.hideAllPacketsButton = QtWidgets.QPushButton(self.groupBox_9) 516 | self.hideAllPacketsButton.setEnabled(False) 517 | self.hideAllPacketsButton.setMinimumSize(QtCore.QSize(0, 20)) 518 | font = QtGui.QFont() 519 | font.setPointSize(11) 520 | self.hideAllPacketsButton.setFont(font) 521 | self.hideAllPacketsButton.setObjectName("hideAllPacketsButton") 522 | self.verticalLayout_13.addWidget(self.hideAllPacketsButton) 523 | self.verticalLayout_10.addWidget(self.groupBox_9) 524 | self.groupBox_8 = QtWidgets.QGroupBox(self.scrollAreaWidgetContents_3) 525 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 526 | sizePolicy.setHorizontalStretch(0) 527 | sizePolicy.setVerticalStretch(0) 528 | sizePolicy.setHeightForWidth(self.groupBox_8.sizePolicy().hasHeightForWidth()) 529 | self.groupBox_8.setSizePolicy(sizePolicy) 530 | self.groupBox_8.setMinimumSize(QtCore.QSize(0, 0)) 531 | self.groupBox_8.setMaximumSize(QtCore.QSize(16777215, 16777215)) 532 | font = QtGui.QFont() 533 | font.setPointSize(10) 534 | self.groupBox_8.setFont(font) 535 | self.groupBox_8.setAutoFillBackground(False) 536 | self.groupBox_8.setFlat(False) 537 | self.groupBox_8.setObjectName("groupBox_8") 538 | self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.groupBox_8) 539 | self.verticalLayout_12.setObjectName("verticalLayout_12") 540 | self.horizontalLayout_7 = QtWidgets.QHBoxLayout() 541 | self.horizontalLayout_7.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) 542 | self.horizontalLayout_7.setSpacing(2) 543 | self.horizontalLayout_7.setObjectName("horizontalLayout_7") 544 | self.saveSelectedIdInDictButton = QtWidgets.QPushButton(self.groupBox_8) 545 | self.saveSelectedIdInDictButton.setEnabled(True) 546 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 547 | sizePolicy.setHorizontalStretch(0) 548 | sizePolicy.setVerticalStretch(0) 549 | sizePolicy.setHeightForWidth(self.saveSelectedIdInDictButton.sizePolicy().hasHeightForWidth()) 550 | self.saveSelectedIdInDictButton.setSizePolicy(sizePolicy) 551 | self.saveSelectedIdInDictButton.setMinimumSize(QtCore.QSize(0, 20)) 552 | self.saveSelectedIdInDictButton.setMaximumSize(QtCore.QSize(16777215, 20)) 553 | font = QtGui.QFont() 554 | font.setPointSize(11) 555 | self.saveSelectedIdInDictButton.setFont(font) 556 | self.saveSelectedIdInDictButton.setObjectName("saveSelectedIdInDictButton") 557 | self.horizontalLayout_7.addWidget(self.saveSelectedIdInDictButton) 558 | self.saveIdToDictLineEdit = QtWidgets.QLineEdit(self.groupBox_8) 559 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) 560 | sizePolicy.setHorizontalStretch(0) 561 | sizePolicy.setVerticalStretch(0) 562 | sizePolicy.setHeightForWidth(self.saveIdToDictLineEdit.sizePolicy().hasHeightForWidth()) 563 | self.saveIdToDictLineEdit.setSizePolicy(sizePolicy) 564 | self.saveIdToDictLineEdit.setMinimumSize(QtCore.QSize(0, 0)) 565 | self.saveIdToDictLineEdit.setMaximumSize(QtCore.QSize(50, 25)) 566 | font = QtGui.QFont() 567 | font.setPointSize(10) 568 | self.saveIdToDictLineEdit.setFont(font) 569 | self.saveIdToDictLineEdit.setObjectName("saveIdToDictLineEdit") 570 | self.horizontalLayout_7.addWidget(self.saveIdToDictLineEdit) 571 | self.saveLabelToDictLineEdit = QtWidgets.QLineEdit(self.groupBox_8) 572 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 573 | sizePolicy.setHorizontalStretch(0) 574 | sizePolicy.setVerticalStretch(0) 575 | sizePolicy.setHeightForWidth(self.saveLabelToDictLineEdit.sizePolicy().hasHeightForWidth()) 576 | self.saveLabelToDictLineEdit.setSizePolicy(sizePolicy) 577 | self.saveLabelToDictLineEdit.setMinimumSize(QtCore.QSize(20, 0)) 578 | self.saveLabelToDictLineEdit.setMaximumSize(QtCore.QSize(100, 25)) 579 | font = QtGui.QFont() 580 | font.setPointSize(10) 581 | self.saveLabelToDictLineEdit.setFont(font) 582 | self.saveLabelToDictLineEdit.setObjectName("saveLabelToDictLineEdit") 583 | self.horizontalLayout_7.addWidget(self.saveLabelToDictLineEdit) 584 | self.verticalLayout_12.addLayout(self.horizontalLayout_7) 585 | self.line_5 = QtWidgets.QFrame(self.groupBox_8) 586 | self.line_5.setFrameShape(QtWidgets.QFrame.HLine) 587 | self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken) 588 | self.line_5.setObjectName("line_5") 589 | self.verticalLayout_12.addWidget(self.line_5) 590 | self.addToDecodedPushButton = QtWidgets.QPushButton(self.groupBox_8) 591 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 592 | sizePolicy.setHorizontalStretch(0) 593 | sizePolicy.setVerticalStretch(0) 594 | sizePolicy.setHeightForWidth(self.addToDecodedPushButton.sizePolicy().hasHeightForWidth()) 595 | self.addToDecodedPushButton.setSizePolicy(sizePolicy) 596 | self.addToDecodedPushButton.setMinimumSize(QtCore.QSize(0, 20)) 597 | self.addToDecodedPushButton.setMaximumSize(QtCore.QSize(16777215, 20)) 598 | font = QtGui.QFont() 599 | font.setPointSize(11) 600 | self.addToDecodedPushButton.setFont(font) 601 | self.addToDecodedPushButton.setLayoutDirection(QtCore.Qt.LeftToRight) 602 | self.addToDecodedPushButton.setObjectName("addToDecodedPushButton") 603 | self.verticalLayout_12.addWidget(self.addToDecodedPushButton) 604 | self.verticalLayout_10.addWidget(self.groupBox_8) 605 | self.groupBox_7 = QtWidgets.QGroupBox(self.scrollAreaWidgetContents_3) 606 | font = QtGui.QFont() 607 | font.setPointSize(10) 608 | self.groupBox_7.setFont(font) 609 | self.groupBox_7.setObjectName("groupBox_7") 610 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_7) 611 | self.verticalLayout_4.setObjectName("verticalLayout_4") 612 | self.saveSessionToFileButton = QtWidgets.QPushButton(self.groupBox_7) 613 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 614 | sizePolicy.setHorizontalStretch(0) 615 | sizePolicy.setVerticalStretch(0) 616 | sizePolicy.setHeightForWidth(self.saveSessionToFileButton.sizePolicy().hasHeightForWidth()) 617 | self.saveSessionToFileButton.setSizePolicy(sizePolicy) 618 | self.saveSessionToFileButton.setMinimumSize(QtCore.QSize(0, 20)) 619 | self.saveSessionToFileButton.setMaximumSize(QtCore.QSize(16777215, 20)) 620 | font = QtGui.QFont() 621 | font.setPointSize(11) 622 | self.saveSessionToFileButton.setFont(font) 623 | self.saveSessionToFileButton.setObjectName("saveSessionToFileButton") 624 | self.verticalLayout_4.addWidget(self.saveSessionToFileButton) 625 | self.line_2 = QtWidgets.QFrame(self.groupBox_7) 626 | self.line_2.setFrameShape(QtWidgets.QFrame.HLine) 627 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 628 | self.line_2.setObjectName("line_2") 629 | self.verticalLayout_4.addWidget(self.line_2) 630 | self.playbackMainTableButton = QtWidgets.QPushButton(self.groupBox_7) 631 | self.playbackMainTableButton.setEnabled(True) 632 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 633 | sizePolicy.setHorizontalStretch(0) 634 | sizePolicy.setVerticalStretch(0) 635 | sizePolicy.setHeightForWidth(self.playbackMainTableButton.sizePolicy().hasHeightForWidth()) 636 | self.playbackMainTableButton.setSizePolicy(sizePolicy) 637 | self.playbackMainTableButton.setMinimumSize(QtCore.QSize(0, 20)) 638 | self.playbackMainTableButton.setMaximumSize(QtCore.QSize(16777215, 20)) 639 | font = QtGui.QFont() 640 | font.setFamily("MS Shell Dlg 2") 641 | font.setPointSize(11) 642 | self.playbackMainTableButton.setFont(font) 643 | self.playbackMainTableButton.setObjectName("playbackMainTableButton") 644 | self.verticalLayout_4.addWidget(self.playbackMainTableButton) 645 | self.stopPlayBackButton = QtWidgets.QPushButton(self.groupBox_7) 646 | self.stopPlayBackButton.setMinimumSize(QtCore.QSize(0, 20)) 647 | font = QtGui.QFont() 648 | font.setPointSize(11) 649 | self.stopPlayBackButton.setFont(font) 650 | self.stopPlayBackButton.setObjectName("stopPlayBackButton") 651 | self.verticalLayout_4.addWidget(self.stopPlayBackButton) 652 | self.playBackProgressBar = QtWidgets.QProgressBar(self.groupBox_7) 653 | self.playBackProgressBar.setMinimumSize(QtCore.QSize(0, 20)) 654 | self.playBackProgressBar.setProperty("value", 0) 655 | self.playBackProgressBar.setTextVisible(True) 656 | self.playBackProgressBar.setObjectName("playBackProgressBar") 657 | self.verticalLayout_4.addWidget(self.playBackProgressBar) 658 | self.verticalLayout_10.addWidget(self.groupBox_7) 659 | spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 660 | self.verticalLayout_10.addItem(spacerItem1) 661 | self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_3) 662 | self.horizontalLayout_4.addWidget(self.scrollArea_2) 663 | self.verticalLayout_9 = QtWidgets.QVBoxLayout() 664 | self.verticalLayout_9.setContentsMargins(0, -1, -1, -1) 665 | self.verticalLayout_9.setObjectName("verticalLayout_9") 666 | self.horizontalLayout_4.addLayout(self.verticalLayout_9) 667 | self.tabWidget.addTab(self.tab, "") 668 | self.tab_3 = QtWidgets.QWidget() 669 | self.tab_3.setObjectName("tab_3") 670 | self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.tab_3) 671 | self.horizontalLayout_13.setObjectName("horizontalLayout_13") 672 | self.horizontalLayout_12 = QtWidgets.QHBoxLayout() 673 | self.horizontalLayout_12.setObjectName("horizontalLayout_12") 674 | self.decodedMessagesTableWidget = QtWidgets.QTableWidget(self.tab_3) 675 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) 676 | sizePolicy.setHorizontalStretch(0) 677 | sizePolicy.setVerticalStretch(0) 678 | sizePolicy.setHeightForWidth(self.decodedMessagesTableWidget.sizePolicy().hasHeightForWidth()) 679 | self.decodedMessagesTableWidget.setSizePolicy(sizePolicy) 680 | self.decodedMessagesTableWidget.setMinimumSize(QtCore.QSize(0, 0)) 681 | self.decodedMessagesTableWidget.setAutoScroll(True) 682 | self.decodedMessagesTableWidget.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked) 683 | self.decodedMessagesTableWidget.setAlternatingRowColors(True) 684 | self.decodedMessagesTableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) 685 | self.decodedMessagesTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) 686 | self.decodedMessagesTableWidget.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) 687 | self.decodedMessagesTableWidget.setShowGrid(True) 688 | self.decodedMessagesTableWidget.setGridStyle(QtCore.Qt.DotLine) 689 | self.decodedMessagesTableWidget.setObjectName("decodedMessagesTableWidget") 690 | self.decodedMessagesTableWidget.setColumnCount(13) 691 | self.decodedMessagesTableWidget.setRowCount(0) 692 | item = QtWidgets.QTableWidgetItem() 693 | item.setTextAlignment(QtCore.Qt.AlignCenter) 694 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(0, item) 695 | item = QtWidgets.QTableWidgetItem() 696 | item.setTextAlignment(QtCore.Qt.AlignCenter) 697 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(1, item) 698 | item = QtWidgets.QTableWidgetItem() 699 | item.setTextAlignment(QtCore.Qt.AlignCenter) 700 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(2, item) 701 | item = QtWidgets.QTableWidgetItem() 702 | item.setTextAlignment(QtCore.Qt.AlignCenter) 703 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(3, item) 704 | item = QtWidgets.QTableWidgetItem() 705 | item.setTextAlignment(QtCore.Qt.AlignCenter) 706 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(4, item) 707 | item = QtWidgets.QTableWidgetItem() 708 | item.setTextAlignment(QtCore.Qt.AlignCenter) 709 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(5, item) 710 | item = QtWidgets.QTableWidgetItem() 711 | item.setTextAlignment(QtCore.Qt.AlignCenter) 712 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(6, item) 713 | item = QtWidgets.QTableWidgetItem() 714 | item.setTextAlignment(QtCore.Qt.AlignCenter) 715 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(7, item) 716 | item = QtWidgets.QTableWidgetItem() 717 | item.setTextAlignment(QtCore.Qt.AlignCenter) 718 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(8, item) 719 | item = QtWidgets.QTableWidgetItem() 720 | item.setTextAlignment(QtCore.Qt.AlignCenter) 721 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(9, item) 722 | item = QtWidgets.QTableWidgetItem() 723 | item.setTextAlignment(QtCore.Qt.AlignCenter) 724 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(10, item) 725 | item = QtWidgets.QTableWidgetItem() 726 | item.setTextAlignment(QtCore.Qt.AlignCenter) 727 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(11, item) 728 | item = QtWidgets.QTableWidgetItem() 729 | item.setTextAlignment(QtCore.Qt.AlignCenter) 730 | self.decodedMessagesTableWidget.setHorizontalHeaderItem(12, item) 731 | self.decodedMessagesTableWidget.verticalHeader().setStretchLastSection(False) 732 | self.horizontalLayout_12.addWidget(self.decodedMessagesTableWidget) 733 | self.groupBox_2 = QtWidgets.QGroupBox(self.tab_3) 734 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 735 | sizePolicy.setHorizontalStretch(0) 736 | sizePolicy.setVerticalStretch(0) 737 | sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth()) 738 | self.groupBox_2.setSizePolicy(sizePolicy) 739 | self.groupBox_2.setMinimumSize(QtCore.QSize(250, 0)) 740 | self.groupBox_2.setObjectName("groupBox_2") 741 | self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupBox_2) 742 | self.verticalLayout_6.setObjectName("verticalLayout_6") 743 | self.deleteDecodedPacketLinePushButton = QtWidgets.QPushButton(self.groupBox_2) 744 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 745 | sizePolicy.setHorizontalStretch(0) 746 | sizePolicy.setVerticalStretch(0) 747 | sizePolicy.setHeightForWidth(self.deleteDecodedPacketLinePushButton.sizePolicy().hasHeightForWidth()) 748 | self.deleteDecodedPacketLinePushButton.setSizePolicy(sizePolicy) 749 | self.deleteDecodedPacketLinePushButton.setMinimumSize(QtCore.QSize(0, 0)) 750 | self.deleteDecodedPacketLinePushButton.setMaximumSize(QtCore.QSize(16777215, 16777215)) 751 | font = QtGui.QFont() 752 | font.setPointSize(11) 753 | self.deleteDecodedPacketLinePushButton.setFont(font) 754 | self.deleteDecodedPacketLinePushButton.setObjectName("deleteDecodedPacketLinePushButton") 755 | self.verticalLayout_6.addWidget(self.deleteDecodedPacketLinePushButton) 756 | self.sendSelectedDecodedPacketButton = QtWidgets.QPushButton(self.groupBox_2) 757 | self.sendSelectedDecodedPacketButton.setMinimumSize(QtCore.QSize(0, 0)) 758 | self.sendSelectedDecodedPacketButton.setMaximumSize(QtCore.QSize(300, 16777215)) 759 | font = QtGui.QFont() 760 | font.setPointSize(11) 761 | self.sendSelectedDecodedPacketButton.setFont(font) 762 | self.sendSelectedDecodedPacketButton.setObjectName("sendSelectedDecodedPacketButton") 763 | self.verticalLayout_6.addWidget(self.sendSelectedDecodedPacketButton) 764 | spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding) 765 | self.verticalLayout_6.addItem(spacerItem2) 766 | self.horizontalLayout_12.addWidget(self.groupBox_2) 767 | self.horizontalLayout_13.addLayout(self.horizontalLayout_12) 768 | self.tabWidget.addTab(self.tab_3, "") 769 | self.tab_2 = QtWidgets.QWidget() 770 | self.tab_2.setObjectName("tab_2") 771 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.tab_2) 772 | self.horizontalLayout.setObjectName("horizontalLayout") 773 | self.idLabelDictTable = QtWidgets.QTableWidget(self.tab_2) 774 | self.idLabelDictTable.setAlternatingRowColors(True) 775 | self.idLabelDictTable.setObjectName("idLabelDictTable") 776 | self.idLabelDictTable.setColumnCount(2) 777 | self.idLabelDictTable.setRowCount(0) 778 | item = QtWidgets.QTableWidgetItem() 779 | item.setTextAlignment(QtCore.Qt.AlignCenter) 780 | self.idLabelDictTable.setHorizontalHeaderItem(0, item) 781 | item = QtWidgets.QTableWidgetItem() 782 | item.setTextAlignment(QtCore.Qt.AlignCenter) 783 | self.idLabelDictTable.setHorizontalHeaderItem(1, item) 784 | self.horizontalLayout.addWidget(self.idLabelDictTable) 785 | self.groupBox_6 = QtWidgets.QGroupBox(self.tab_2) 786 | self.groupBox_6.setMinimumSize(QtCore.QSize(250, 0)) 787 | font = QtGui.QFont() 788 | font.setPointSize(10) 789 | self.groupBox_6.setFont(font) 790 | self.groupBox_6.setObjectName("groupBox_6") 791 | self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.groupBox_6) 792 | self.verticalLayout_8.setObjectName("verticalLayout_8") 793 | self.verticalLayout_5 = QtWidgets.QVBoxLayout() 794 | self.verticalLayout_5.setObjectName("verticalLayout_5") 795 | self.gridLayout_4 = QtWidgets.QGridLayout() 796 | self.gridLayout_4.setObjectName("gridLayout_4") 797 | self.checkBox_6 = QtWidgets.QCheckBox(self.groupBox_6) 798 | self.checkBox_6.setEnabled(True) 799 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 800 | sizePolicy.setHorizontalStretch(0) 801 | sizePolicy.setVerticalStretch(0) 802 | sizePolicy.setHeightForWidth(self.checkBox_6.sizePolicy().hasHeightForWidth()) 803 | self.checkBox_6.setSizePolicy(sizePolicy) 804 | font = QtGui.QFont() 805 | font.setPointSize(11) 806 | self.checkBox_6.setFont(font) 807 | self.checkBox_6.setObjectName("checkBox_6") 808 | self.gridLayout_4.addWidget(self.checkBox_6, 0, 0, 1, 1) 809 | self.verticalLayout_5.addLayout(self.gridLayout_4) 810 | self.line_3 = QtWidgets.QFrame(self.groupBox_6) 811 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 812 | sizePolicy.setHorizontalStretch(0) 813 | sizePolicy.setVerticalStretch(0) 814 | sizePolicy.setHeightForWidth(self.line_3.sizePolicy().hasHeightForWidth()) 815 | self.line_3.setSizePolicy(sizePolicy) 816 | self.line_3.setFrameShape(QtWidgets.QFrame.HLine) 817 | self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken) 818 | self.line_3.setObjectName("line_3") 819 | self.verticalLayout_5.addWidget(self.line_3) 820 | self.clearLabelDictButton = QtWidgets.QPushButton(self.groupBox_6) 821 | self.clearLabelDictButton.setEnabled(False) 822 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 823 | sizePolicy.setHorizontalStretch(0) 824 | sizePolicy.setVerticalStretch(0) 825 | sizePolicy.setHeightForWidth(self.clearLabelDictButton.sizePolicy().hasHeightForWidth()) 826 | self.clearLabelDictButton.setSizePolicy(sizePolicy) 827 | font = QtGui.QFont() 828 | font.setPointSize(11) 829 | self.clearLabelDictButton.setFont(font) 830 | self.clearLabelDictButton.setObjectName("clearLabelDictButton") 831 | self.verticalLayout_5.addWidget(self.clearLabelDictButton) 832 | spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding) 833 | self.verticalLayout_5.addItem(spacerItem3) 834 | self.verticalLayout_8.addLayout(self.verticalLayout_5) 835 | self.horizontalLayout.addWidget(self.groupBox_6) 836 | self.tabWidget.addTab(self.tab_2, "") 837 | self.verticalLayout.addWidget(self.tabWidget) 838 | self.sendingGroupBox = QtWidgets.QGroupBox(self.centralwidget) 839 | self.sendingGroupBox.setEnabled(True) 840 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 841 | sizePolicy.setHorizontalStretch(0) 842 | sizePolicy.setVerticalStretch(0) 843 | sizePolicy.setHeightForWidth(self.sendingGroupBox.sizePolicy().hasHeightForWidth()) 844 | self.sendingGroupBox.setSizePolicy(sizePolicy) 845 | self.sendingGroupBox.setMinimumSize(QtCore.QSize(0, 0)) 846 | self.sendingGroupBox.setMaximumSize(QtCore.QSize(16777215, 16777215)) 847 | font = QtGui.QFont() 848 | font.setPointSize(10) 849 | self.sendingGroupBox.setFont(font) 850 | self.sendingGroupBox.setLayoutDirection(QtCore.Qt.LeftToRight) 851 | self.sendingGroupBox.setObjectName("sendingGroupBox") 852 | self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.sendingGroupBox) 853 | self.horizontalLayout_11.setObjectName("horizontalLayout_11") 854 | self.txTable = QtWidgets.QTableWidget(self.sendingGroupBox) 855 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) 856 | sizePolicy.setHorizontalStretch(0) 857 | sizePolicy.setVerticalStretch(0) 858 | sizePolicy.setHeightForWidth(self.txTable.sizePolicy().hasHeightForWidth()) 859 | self.txTable.setSizePolicy(sizePolicy) 860 | self.txTable.setMaximumSize(QtCore.QSize(16777215, 100)) 861 | self.txTable.setEditTriggers(QtWidgets.QAbstractItemView.AnyKeyPressed|QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed|QtWidgets.QAbstractItemView.SelectedClicked) 862 | self.txTable.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) 863 | self.txTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) 864 | self.txTable.setRowCount(0) 865 | self.txTable.setObjectName("txTable") 866 | self.txTable.setColumnCount(4) 867 | item = QtWidgets.QTableWidgetItem() 868 | self.txTable.setHorizontalHeaderItem(0, item) 869 | item = QtWidgets.QTableWidgetItem() 870 | self.txTable.setHorizontalHeaderItem(1, item) 871 | item = QtWidgets.QTableWidgetItem() 872 | self.txTable.setHorizontalHeaderItem(2, item) 873 | item = QtWidgets.QTableWidgetItem() 874 | self.txTable.setHorizontalHeaderItem(3, item) 875 | self.txTable.horizontalHeader().setSortIndicatorShown(False) 876 | self.horizontalLayout_11.addWidget(self.txTable) 877 | self.verticalLayout_2 = QtWidgets.QVBoxLayout() 878 | self.verticalLayout_2.setContentsMargins(-1, -1, 10, -1) 879 | self.verticalLayout_2.setObjectName("verticalLayout_2") 880 | self.newTxTableRow = QtWidgets.QPushButton(self.sendingGroupBox) 881 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 882 | sizePolicy.setHorizontalStretch(0) 883 | sizePolicy.setVerticalStretch(0) 884 | sizePolicy.setHeightForWidth(self.newTxTableRow.sizePolicy().hasHeightForWidth()) 885 | self.newTxTableRow.setSizePolicy(sizePolicy) 886 | self.newTxTableRow.setMinimumSize(QtCore.QSize(0, 0)) 887 | self.newTxTableRow.setMaximumSize(QtCore.QSize(16777215, 20)) 888 | font = QtGui.QFont() 889 | font.setPointSize(11) 890 | self.newTxTableRow.setFont(font) 891 | self.newTxTableRow.setObjectName("newTxTableRow") 892 | self.verticalLayout_2.addWidget(self.newTxTableRow) 893 | self.removeTxTableRow = QtWidgets.QPushButton(self.sendingGroupBox) 894 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 895 | sizePolicy.setHorizontalStretch(0) 896 | sizePolicy.setVerticalStretch(0) 897 | sizePolicy.setHeightForWidth(self.removeTxTableRow.sizePolicy().hasHeightForWidth()) 898 | self.removeTxTableRow.setSizePolicy(sizePolicy) 899 | self.removeTxTableRow.setMinimumSize(QtCore.QSize(250, 0)) 900 | self.removeTxTableRow.setMaximumSize(QtCore.QSize(150, 20)) 901 | font = QtGui.QFont() 902 | font.setPointSize(11) 903 | self.removeTxTableRow.setFont(font) 904 | self.removeTxTableRow.setObjectName("removeTxTableRow") 905 | self.verticalLayout_2.addWidget(self.removeTxTableRow) 906 | self.sendTxTableButton = QtWidgets.QCommandLinkButton(self.sendingGroupBox) 907 | self.sendTxTableButton.setEnabled(False) 908 | self.sendTxTableButton.setMaximumSize(QtCore.QSize(16777215, 30)) 909 | font = QtGui.QFont() 910 | font.setPointSize(11) 911 | self.sendTxTableButton.setFont(font) 912 | self.sendTxTableButton.setObjectName("sendTxTableButton") 913 | self.verticalLayout_2.addWidget(self.sendTxTableButton) 914 | self.horizontalLayout_14 = QtWidgets.QHBoxLayout() 915 | self.horizontalLayout_14.setObjectName("horizontalLayout_14") 916 | self.repeatedDelayCheckBox = QtWidgets.QCheckBox(self.sendingGroupBox) 917 | font = QtGui.QFont() 918 | font.setPointSize(11) 919 | self.repeatedDelayCheckBox.setFont(font) 920 | self.repeatedDelayCheckBox.setObjectName("repeatedDelayCheckBox") 921 | self.horizontalLayout_14.addWidget(self.repeatedDelayCheckBox) 922 | self.repeatTxDelayValue = QtWidgets.QSpinBox(self.sendingGroupBox) 923 | font = QtGui.QFont() 924 | font.setPointSize(10) 925 | self.repeatTxDelayValue.setFont(font) 926 | self.repeatTxDelayValue.setMaximum(9999) 927 | self.repeatTxDelayValue.setProperty("value", 100) 928 | self.repeatTxDelayValue.setObjectName("repeatTxDelayValue") 929 | self.horizontalLayout_14.addWidget(self.repeatTxDelayValue) 930 | self.verticalLayout_2.addLayout(self.horizontalLayout_14) 931 | self.horizontalLayout_11.addLayout(self.verticalLayout_2) 932 | self.verticalLayout.addWidget(self.sendingGroupBox) 933 | self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget) 934 | self.groupBox_3.setMinimumSize(QtCore.QSize(0, 50)) 935 | font = QtGui.QFont() 936 | font.setPointSize(10) 937 | self.groupBox_3.setFont(font) 938 | self.groupBox_3.setObjectName("groupBox_3") 939 | self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_3) 940 | self.gridLayout_3.setContentsMargins(-1, 0, -1, 1) 941 | self.gridLayout_3.setObjectName("gridLayout_3") 942 | self.txDataRadioButton = QtWidgets.QRadioButton(self.groupBox_3) 943 | self.txDataRadioButton.setEnabled(False) 944 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 945 | sizePolicy.setHorizontalStretch(0) 946 | sizePolicy.setVerticalStretch(0) 947 | sizePolicy.setHeightForWidth(self.txDataRadioButton.sizePolicy().hasHeightForWidth()) 948 | self.txDataRadioButton.setSizePolicy(sizePolicy) 949 | self.txDataRadioButton.setMinimumSize(QtCore.QSize(0, 20)) 950 | font = QtGui.QFont() 951 | font.setPointSize(10) 952 | self.txDataRadioButton.setFont(font) 953 | self.txDataRadioButton.setCheckable(True) 954 | self.txDataRadioButton.setAutoExclusive(True) 955 | self.txDataRadioButton.setObjectName("txDataRadioButton") 956 | self.gridLayout_3.addWidget(self.txDataRadioButton, 0, 4, 1, 1) 957 | self.snifferMsgPlainTextEdit = QtWidgets.QPlainTextEdit(self.groupBox_3) 958 | self.snifferMsgPlainTextEdit.setEnabled(False) 959 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 960 | sizePolicy.setHorizontalStretch(0) 961 | sizePolicy.setVerticalStretch(0) 962 | sizePolicy.setHeightForWidth(self.snifferMsgPlainTextEdit.sizePolicy().hasHeightForWidth()) 963 | self.snifferMsgPlainTextEdit.setSizePolicy(sizePolicy) 964 | self.snifferMsgPlainTextEdit.setMinimumSize(QtCore.QSize(300, 25)) 965 | self.snifferMsgPlainTextEdit.setMaximumSize(QtCore.QSize(16777215, 25)) 966 | font = QtGui.QFont() 967 | font.setPointSize(10) 968 | self.snifferMsgPlainTextEdit.setFont(font) 969 | self.snifferMsgPlainTextEdit.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 970 | self.snifferMsgPlainTextEdit.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 971 | self.snifferMsgPlainTextEdit.setObjectName("snifferMsgPlainTextEdit") 972 | self.gridLayout_3.addWidget(self.snifferMsgPlainTextEdit, 0, 10, 1, 1) 973 | self.serialConnectedCheckBox = QtWidgets.QCheckBox(self.groupBox_3) 974 | self.serialConnectedCheckBox.setEnabled(False) 975 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 976 | sizePolicy.setHorizontalStretch(0) 977 | sizePolicy.setVerticalStretch(0) 978 | sizePolicy.setHeightForWidth(self.serialConnectedCheckBox.sizePolicy().hasHeightForWidth()) 979 | self.serialConnectedCheckBox.setSizePolicy(sizePolicy) 980 | self.serialConnectedCheckBox.setMinimumSize(QtCore.QSize(0, 20)) 981 | font = QtGui.QFont() 982 | font.setPointSize(10) 983 | self.serialConnectedCheckBox.setFont(font) 984 | self.serialConnectedCheckBox.setCheckable(True) 985 | self.serialConnectedCheckBox.setChecked(False) 986 | self.serialConnectedCheckBox.setTristate(False) 987 | self.serialConnectedCheckBox.setObjectName("serialConnectedCheckBox") 988 | self.gridLayout_3.addWidget(self.serialConnectedCheckBox, 0, 2, 1, 1) 989 | self.label_2 = QtWidgets.QLabel(self.groupBox_3) 990 | self.label_2.setEnabled(False) 991 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 992 | sizePolicy.setHorizontalStretch(0) 993 | sizePolicy.setVerticalStretch(0) 994 | sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) 995 | self.label_2.setSizePolicy(sizePolicy) 996 | self.label_2.setMinimumSize(QtCore.QSize(0, 20)) 997 | font = QtGui.QFont() 998 | font.setPointSize(10) 999 | self.label_2.setFont(font) 1000 | self.label_2.setObjectName("label_2") 1001 | self.gridLayout_3.addWidget(self.label_2, 0, 9, 1, 1) 1002 | self.rxDataRadioButton = QtWidgets.QRadioButton(self.groupBox_3) 1003 | self.rxDataRadioButton.setEnabled(False) 1004 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 1005 | sizePolicy.setHorizontalStretch(0) 1006 | sizePolicy.setVerticalStretch(0) 1007 | sizePolicy.setHeightForWidth(self.rxDataRadioButton.sizePolicy().hasHeightForWidth()) 1008 | self.rxDataRadioButton.setSizePolicy(sizePolicy) 1009 | self.rxDataRadioButton.setMinimumSize(QtCore.QSize(0, 20)) 1010 | font = QtGui.QFont() 1011 | font.setPointSize(10) 1012 | self.rxDataRadioButton.setFont(font) 1013 | self.rxDataRadioButton.setMouseTracking(False) 1014 | self.rxDataRadioButton.setCheckable(True) 1015 | self.rxDataRadioButton.setAutoExclusive(True) 1016 | self.rxDataRadioButton.setObjectName("rxDataRadioButton") 1017 | self.gridLayout_3.addWidget(self.rxDataRadioButton, 0, 3, 1, 1) 1018 | self.packageCounterLabel = QtWidgets.QLabel(self.groupBox_3) 1019 | self.packageCounterLabel.setEnabled(False) 1020 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 1021 | sizePolicy.setHorizontalStretch(0) 1022 | sizePolicy.setVerticalStretch(0) 1023 | sizePolicy.setHeightForWidth(self.packageCounterLabel.sizePolicy().hasHeightForWidth()) 1024 | self.packageCounterLabel.setSizePolicy(sizePolicy) 1025 | self.packageCounterLabel.setMinimumSize(QtCore.QSize(0, 20)) 1026 | font = QtGui.QFont() 1027 | font.setPointSize(10) 1028 | self.packageCounterLabel.setFont(font) 1029 | self.packageCounterLabel.setObjectName("packageCounterLabel") 1030 | self.gridLayout_3.addWidget(self.packageCounterLabel, 0, 6, 1, 1) 1031 | self.package_2 = QtWidgets.QLabel(self.groupBox_3) 1032 | self.package_2.setEnabled(False) 1033 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 1034 | sizePolicy.setHorizontalStretch(0) 1035 | sizePolicy.setVerticalStretch(0) 1036 | sizePolicy.setHeightForWidth(self.package_2.sizePolicy().hasHeightForWidth()) 1037 | self.package_2.setSizePolicy(sizePolicy) 1038 | self.package_2.setMinimumSize(QtCore.QSize(0, 20)) 1039 | font = QtGui.QFont() 1040 | font.setPointSize(10) 1041 | self.package_2.setFont(font) 1042 | self.package_2.setObjectName("package_2") 1043 | self.gridLayout_3.addWidget(self.package_2, 0, 5, 1, 1) 1044 | self.showControlsButton = QtWidgets.QPushButton(self.groupBox_3) 1045 | font = QtGui.QFont() 1046 | font.setPointSize(11) 1047 | self.showControlsButton.setFont(font) 1048 | self.showControlsButton.setObjectName("showControlsButton") 1049 | self.gridLayout_3.addWidget(self.showControlsButton, 0, 12, 1, 1) 1050 | spacerItem4 = QtWidgets.QSpacerItem(40, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 1051 | self.gridLayout_3.addItem(spacerItem4, 0, 7, 1, 1) 1052 | self.line_7 = QtWidgets.QFrame(self.groupBox_3) 1053 | self.line_7.setFrameShape(QtWidgets.QFrame.VLine) 1054 | self.line_7.setFrameShadow(QtWidgets.QFrame.Sunken) 1055 | self.line_7.setObjectName("line_7") 1056 | self.gridLayout_3.addWidget(self.line_7, 0, 11, 1, 1) 1057 | self.verticalLayout.addWidget(self.groupBox_3) 1058 | self.verticalLayout_3.addLayout(self.verticalLayout) 1059 | MainWindow.setCentralWidget(self.centralwidget) 1060 | 1061 | self.retranslateUi(MainWindow) 1062 | self.tabWidget.setCurrentIndex(0) 1063 | self.showOnlyIdsCheckBox.clicked['bool'].connect(self.showOnlyIdsLineEdit.setEnabled) 1064 | self.hideIdsCheckBox.clicked['bool'].connect(self.hideIdsLineEdit.setEnabled) 1065 | self.checkBox_6.clicked['bool'].connect(self.clearLabelDictButton.setEnabled) 1066 | self.hideOldPacketsCheckBox.clicked['bool'].connect(self.hideOldPeriod.setEnabled) 1067 | self.showSendingTableCheckBox.clicked['bool'].connect(self.sendingGroupBox.hide) 1068 | self.hideControlsButton.pressed.connect(self.groupBox_4.hide) 1069 | self.hideControlsButton.pressed.connect(self.groupBox_5.hide) 1070 | self.hideControlsButton.pressed.connect(self.groupBox.hide) 1071 | self.hideControlsButton.pressed.connect(self.line_4.hide) 1072 | self.hideControlsButton.pressed.connect(self.showControlsButton.show) 1073 | self.showControlsButton.pressed.connect(self.showControlsButton.hide) 1074 | self.showControlsButton.pressed.connect(self.line_4.show) 1075 | self.showControlsButton.pressed.connect(self.groupBox_4.show) 1076 | self.showControlsButton.pressed.connect(self.groupBox_5.show) 1077 | self.showControlsButton.pressed.connect(self.groupBox.show) 1078 | self.hideIdsCheckBox.clicked['bool'].connect(self.hideAllPacketsButton.setEnabled) 1079 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 1080 | 1081 | def retranslateUi(self, MainWindow): 1082 | _translate = QtCore.QCoreApplication.translate 1083 | MainWindow.setWindowTitle(_translate("MainWindow", "CanSniffer # canDrive 2020")) 1084 | self.groupBox.setTitle(_translate("MainWindow", "Serial connection")) 1085 | self.portScanButton.setText(_translate("MainWindow", "Scan")) 1086 | self.portConnectButton.setText(_translate("MainWindow", "Connect")) 1087 | self.portDisconnectButton.setText(_translate("MainWindow", "Disconnect")) 1088 | self.groupBox_5.setTitle(_translate("MainWindow", "Options")) 1089 | self.label_3.setText(_translate("MainWindow", "Active channel")) 1090 | self.activeChannelComboBox.setItemText(0, _translate("MainWindow", "CAN_L")) 1091 | self.activeChannelComboBox.setItemText(1, _translate("MainWindow", "CAN_M")) 1092 | self.activeChannelComboBox.setItemText(2, _translate("MainWindow", "CAN_H")) 1093 | self.label.setText(_translate("MainWindow", "Playback delay ")) 1094 | self.autoclearCheckBox.setText(_translate("MainWindow", "Auto clear")) 1095 | self.showSendingTableCheckBox.setText(_translate("MainWindow", "Show TX table")) 1096 | self.groupModeCheckBox.setText(_translate("MainWindow", "Group packages")) 1097 | self.hideControlsButton.setText(_translate("MainWindow", "Hide Controls")) 1098 | self.groupBox_4.setTitle(_translate("MainWindow", "Actions")) 1099 | self.stopSniffingButton.setText(_translate("MainWindow", "Stop sniffing")) 1100 | self.startSniffingButton.setText(_translate("MainWindow", "Start sniffing")) 1101 | self.loadSessionFromFileButton.setText(_translate("MainWindow", "Load session from file")) 1102 | self.abortSessionLoadingButton.setText(_translate("MainWindow", "Abort session loading")) 1103 | self.mainMessageTableWidget.setSortingEnabled(False) 1104 | item = self.mainMessageTableWidget.horizontalHeaderItem(0) 1105 | item.setText(_translate("MainWindow", "TimeStamp (s)")) 1106 | item = self.mainMessageTableWidget.horizontalHeaderItem(1) 1107 | item.setText(_translate("MainWindow", "ID (hex)")) 1108 | item = self.mainMessageTableWidget.horizontalHeaderItem(2) 1109 | item.setText(_translate("MainWindow", "RTR (hex)")) 1110 | item = self.mainMessageTableWidget.horizontalHeaderItem(3) 1111 | item.setText(_translate("MainWindow", "IDE (hex)")) 1112 | item = self.mainMessageTableWidget.horizontalHeaderItem(4) 1113 | item.setText(_translate("MainWindow", "DLC (hex)")) 1114 | item = self.mainMessageTableWidget.horizontalHeaderItem(5) 1115 | item.setText(_translate("MainWindow", "D0")) 1116 | item = self.mainMessageTableWidget.horizontalHeaderItem(6) 1117 | item.setText(_translate("MainWindow", "D1")) 1118 | item = self.mainMessageTableWidget.horizontalHeaderItem(7) 1119 | item.setText(_translate("MainWindow", "D2")) 1120 | item = self.mainMessageTableWidget.horizontalHeaderItem(8) 1121 | item.setText(_translate("MainWindow", "D3")) 1122 | item = self.mainMessageTableWidget.horizontalHeaderItem(9) 1123 | item.setText(_translate("MainWindow", "D4")) 1124 | item = self.mainMessageTableWidget.horizontalHeaderItem(10) 1125 | item.setText(_translate("MainWindow", "D5")) 1126 | item = self.mainMessageTableWidget.horizontalHeaderItem(11) 1127 | item.setText(_translate("MainWindow", "D6")) 1128 | item = self.mainMessageTableWidget.horizontalHeaderItem(12) 1129 | item.setText(_translate("MainWindow", "D7")) 1130 | self.clearTableButton.setText(_translate("MainWindow", "Clear table")) 1131 | self.groupBox_9.setTitle(_translate("MainWindow", "Filters")) 1132 | self.highlightNewIdCheckBox.setText(_translate("MainWindow", "Highlight new packets")) 1133 | self.highlightNewDataCheckBox.setText(_translate("MainWindow", "Highlight new data")) 1134 | self.hideOldPacketsCheckBox.setText(_translate("MainWindow", "Hide packets older than (s):")) 1135 | self.showOnlyIdsCheckBox.setText(_translate("MainWindow", "Show packets with the following IDs:")) 1136 | self.showOnlyIdsLineEdit.setPlaceholderText(_translate("MainWindow", "ID1 ID2 ...")) 1137 | self.hideIdsCheckBox.setText(_translate("MainWindow", "Hide packets with the following IDs:")) 1138 | self.hideIdsLineEdit.setPlaceholderText(_translate("MainWindow", "ID1 ID2 ...")) 1139 | self.hideAllPacketsButton.setText(_translate("MainWindow", "Hide all packets")) 1140 | self.groupBox_8.setTitle(_translate("MainWindow", "Decoding")) 1141 | self.saveSelectedIdInDictButton.setText(_translate("MainWindow", "Save to Dict")) 1142 | self.saveIdToDictLineEdit.setPlaceholderText(_translate("MainWindow", "ID")) 1143 | self.saveLabelToDictLineEdit.setPlaceholderText(_translate("MainWindow", "LABEL")) 1144 | self.addToDecodedPushButton.setText(_translate("MainWindow", "Add selected to decoded list")) 1145 | self.groupBox_7.setTitle(_translate("MainWindow", "Session window")) 1146 | self.saveSessionToFileButton.setText(_translate("MainWindow", "Save session to file")) 1147 | self.playbackMainTableButton.setText(_translate("MainWindow", "Playback all messages")) 1148 | self.stopPlayBackButton.setText(_translate("MainWindow", "Stop playback")) 1149 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Message window")) 1150 | self.decodedMessagesTableWidget.setSortingEnabled(True) 1151 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(0) 1152 | item.setText(_translate("MainWindow", "Label")) 1153 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(1) 1154 | item.setText(_translate("MainWindow", "ID (hex)")) 1155 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(2) 1156 | item.setText(_translate("MainWindow", "RTR (hex)")) 1157 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(3) 1158 | item.setText(_translate("MainWindow", "IDE (hex)")) 1159 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(4) 1160 | item.setText(_translate("MainWindow", "DLC (i)")) 1161 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(5) 1162 | item.setText(_translate("MainWindow", "D0")) 1163 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(6) 1164 | item.setText(_translate("MainWindow", "D1")) 1165 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(7) 1166 | item.setText(_translate("MainWindow", "D2")) 1167 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(8) 1168 | item.setText(_translate("MainWindow", "D3")) 1169 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(9) 1170 | item.setText(_translate("MainWindow", "D4")) 1171 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(10) 1172 | item.setText(_translate("MainWindow", "D5")) 1173 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(11) 1174 | item.setText(_translate("MainWindow", "D6")) 1175 | item = self.decodedMessagesTableWidget.horizontalHeaderItem(12) 1176 | item.setText(_translate("MainWindow", "D7")) 1177 | self.groupBox_2.setTitle(_translate("MainWindow", "Operations")) 1178 | self.deleteDecodedPacketLinePushButton.setText(_translate("MainWindow", "Delete selected line")) 1179 | self.sendSelectedDecodedPacketButton.setText(_translate("MainWindow", "Send selected packet")) 1180 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Decoded messages")) 1181 | self.idLabelDictTable.setSortingEnabled(True) 1182 | item = self.idLabelDictTable.horizontalHeaderItem(0) 1183 | item.setText(_translate("MainWindow", "ID")) 1184 | item = self.idLabelDictTable.horizontalHeaderItem(1) 1185 | item.setText(_translate("MainWindow", "Label")) 1186 | self.groupBox_6.setTitle(_translate("MainWindow", "Operations")) 1187 | self.checkBox_6.setText(_translate("MainWindow", "Enable table editing")) 1188 | self.clearLabelDictButton.setText(_translate("MainWindow", "Clear Dictionary")) 1189 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Label dictionary")) 1190 | self.sendingGroupBox.setTitle(_translate("MainWindow", "Sending")) 1191 | self.txTable.setSortingEnabled(False) 1192 | item = self.txTable.horizontalHeaderItem(0) 1193 | item.setText(_translate("MainWindow", "ID (hex)")) 1194 | item = self.txTable.horizontalHeaderItem(1) 1195 | item.setText(_translate("MainWindow", "RTR (hex)")) 1196 | item = self.txTable.horizontalHeaderItem(2) 1197 | item.setText(_translate("MainWindow", "IDE (hex)")) 1198 | item = self.txTable.horizontalHeaderItem(3) 1199 | item.setText(_translate("MainWindow", "Data (hex)")) 1200 | self.newTxTableRow.setText(_translate("MainWindow", "Add new row")) 1201 | self.removeTxTableRow.setText(_translate("MainWindow", "Remove selected row")) 1202 | self.sendTxTableButton.setText(_translate("MainWindow", "Send selected commands")) 1203 | self.repeatedDelayCheckBox.setText(_translate("MainWindow", "Repeated Delay")) 1204 | self.groupBox_3.setTitle(_translate("MainWindow", "Status")) 1205 | self.txDataRadioButton.setText(_translate("MainWindow", "Transmitting data")) 1206 | self.serialConnectedCheckBox.setText(_translate("MainWindow", "Conntected to sniffer")) 1207 | self.label_2.setText(_translate("MainWindow", "Packet from Sniffer:")) 1208 | self.rxDataRadioButton.setText(_translate("MainWindow", "Receiving data")) 1209 | self.packageCounterLabel.setText(_translate("MainWindow", "0")) 1210 | self.package_2.setText(_translate("MainWindow", "Package count:")) 1211 | self.showControlsButton.setText(_translate("MainWindow", "Show Controls")) 1212 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/main.py: -------------------------------------------------------------------------------- 1 | # canDrive @ 2020 2 | # To create a one-file executable, call: pyinstaller -F main.spec 3 | #---------------------------------------------------------------- 4 | import serial 5 | import canSniffer_ui 6 | from PyQt5.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QHeaderView, QFileDialog, QRadioButton 7 | from PyQt5.QtWidgets import QVBoxLayout, QSizeGrip 8 | from PyQt5.QtCore import Qt 9 | from PyQt5.QtGui import QColor 10 | import serial.tools.list_ports 11 | 12 | import sys 13 | import os 14 | import time 15 | import qtmodern 16 | from qtmodern import styles 17 | from qtmodern import windows 18 | import csv 19 | 20 | import HideOldPackets 21 | import SerialReader 22 | import SerialWriter 23 | import FileLoader 24 | 25 | 26 | class canSnifferGUI(QMainWindow, canSniffer_ui.Ui_MainWindow): 27 | def __init__(self): 28 | super(canSnifferGUI, self).__init__() 29 | self.setupUi(self) 30 | self.portScanButton.clicked.connect(self.scanPorts) 31 | self.portConnectButton.clicked.connect(self.serialPortConnect) 32 | self.portDisconnectButton.clicked.connect(self.serialPortDisconnect) 33 | self.startSniffingButton.clicked.connect(self.startSniffing) 34 | self.stopSniffingButton.clicked.connect(self.stopSniffing) 35 | self.saveSelectedIdInDictButton.clicked.connect(self.saveIdLabelToDictCallback) 36 | self.saveSessionToFileButton.clicked.connect(self.saveSessionToFile) 37 | self.loadSessionFromFileButton.clicked.connect(self.loadSessionFromFile) 38 | self.showOnlyIdsLineEdit.textChanged.connect(self.showOnlyIdsTextChanged) 39 | self.hideIdsLineEdit.textChanged.connect(self.hideIdsTextChanged) 40 | self.clearLabelDictButton.clicked.connect(self.clearLabelDict) 41 | self.serialController = serial.Serial() 42 | self.mainMessageTableWidget.cellClicked.connect(self.cellWasClicked) 43 | self.newTxTableRow.clicked.connect(self.newTxTableRowCallback) 44 | self.removeTxTableRow.clicked.connect(self.removeTxTableRowCallback) 45 | self.sendTxTableButton.clicked.connect(self.sendTxTableCallback) 46 | self.abortSessionLoadingButton.clicked.connect(self.abortSessionLoadingCallback) 47 | self.showSendingTableCheckBox.clicked.connect(self.showSendingTableButtonCallback) 48 | self.addToDecodedPushButton.clicked.connect(self.addToDecodedCallback) 49 | self.deleteDecodedPacketLinePushButton.clicked.connect(self.deleteDecodedLineCallback) 50 | self.decodedMessagesTableWidget.itemChanged.connect(self.decodedTableItemChangedCallback) 51 | self.clearTableButton.clicked.connect(self.clearTableCallback) 52 | self.sendSelectedDecodedPacketButton.clicked.connect(self.sendDecodedPacketCallback) 53 | self.playbackMainTableButton.clicked.connect(self.playbackMainTableCallback) 54 | self.stopPlayBackButton.clicked.connect(self.stopPlayBackCallback) 55 | self.hideAllPacketsButton.clicked.connect(self.hideAllPackets) 56 | self.showControlsButton.hide() 57 | 58 | self.serialWriterThread = SerialWriter.SerialWriterThread(self.serialController) 59 | self.serialReaderThread = SerialReader.SerialReaderThread(self.serialController) 60 | self.serialReaderThread.receivedPacketSignal.connect(self.serialPacketReceiverCallback) 61 | self.fileLoaderThread = FileLoader.FileLoaderThread() 62 | self.fileLoaderThread.newRowSignal.connect(self.mainTablePopulatorCallback) 63 | self.fileLoaderThread.loadingFinishedSignal.connect(self.fileLoadingFinishedCallback) 64 | self.hideOldPacketsThread = HideOldPackets.HideOldPacketsThread() 65 | self.hideOldPacketsThread.hideOldPacketsSignal.connect(self.hideOldPacketsCallback) 66 | 67 | self.stopPlayBackButton.setVisible(False) 68 | self.playBackProgressBar.setVisible(False) 69 | self.sendingGroupBox.hide() 70 | self.hideOldPacketsThread.enable(5) 71 | self.hideOldPacketsThread.start() 72 | 73 | self.scanPorts() 74 | self.startTime = 0 75 | self.receivedPackets = 0 76 | self.playbackMainTableIndex = 0 77 | self.labelDictFile = None 78 | self.idDict = dict([]) 79 | self.showOnlyIdsSet = set([]) 80 | self.hideIdsSet = set([]) 81 | self.idLabelDict = dict() 82 | self.isInited = False 83 | self.init() 84 | 85 | if not os.path.exists("save"): 86 | os.makedirs("save") 87 | 88 | for i in range(5, self.mainMessageTableWidget.columnCount()): 89 | self.mainMessageTableWidget.setColumnWidth(i, 32) 90 | for i in range(5, self.mainMessageTableWidget.columnCount()): 91 | self.decodedMessagesTableWidget.setColumnWidth(i, 32) 92 | self.decodedMessagesTableWidget.setColumnWidth(1, 150) 93 | self.decodedMessagesTableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) 94 | self.txTable.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch) 95 | self.showFullScreen() 96 | 97 | def stopPlayBackCallback(self): 98 | try: 99 | self.serialWriterThread.packetSentSignal.disconnect() 100 | except: 101 | pass 102 | self.serialWriterThread.clearQueues() 103 | self.playbackMainTableButton.setVisible(True) 104 | self.stopPlayBackButton.setVisible(False) 105 | self.playBackProgressBar.setVisible(False) 106 | 107 | def setRadioButton(self, radioButton:QRadioButton, mode): 108 | radioButton.setAutoExclusive(False) 109 | if mode == 0: 110 | radioButton.setChecked(False) 111 | if mode == 1: 112 | radioButton.setChecked(True) 113 | if mode == 2: 114 | radioButton.setChecked(not radioButton.isChecked()) 115 | radioButton.setAutoExclusive(True) 116 | QApplication.processEvents() 117 | 118 | def playbackMainTable1Packet(self): 119 | row = self.playbackMainTableIndex 120 | 121 | if row < 0: 122 | self.stopPlayBackCallback() 123 | return 124 | maxRows = self.mainMessageTableWidget.rowCount() 125 | txBuf = "" 126 | id = ((self.mainMessageTableWidget.item(row, 1).text()).split(" "))[0] 127 | if len(id) % 2: 128 | txBuf += '0' 129 | txBuf += id + ',' + self.mainMessageTableWidget.item(row, 2).text() + ',' + \ 130 | self.mainMessageTableWidget.item(row, 3).text() + ',' 131 | for i in range(5, self.mainMessageTableWidget.columnCount()): 132 | txBuf += self.mainMessageTableWidget.item(row, i).text() 133 | txBuf += '\n' 134 | if row < maxRows - 1: 135 | dt = float(self.mainMessageTableWidget.item(row, 0).text()) - float( 136 | self.mainMessageTableWidget.item(row + 1, 0).text()) 137 | dt = abs(int(dt * 1000)) 138 | self.serialWriterThread.setNormalWriteDelay(dt) 139 | self.playBackProgressBar.setValue(int((maxRows - row) / maxRows * 100)) 140 | self.playbackMainTableIndex -= 1 141 | 142 | self.serialWriterThread.write(txBuf) 143 | 144 | def playbackMainTableCallback(self): 145 | self.playbackMainTableButton.setVisible(False) 146 | self.stopPlayBackButton.setVisible(True) 147 | self.playBackProgressBar.setVisible(True) 148 | self.playbackMainTableIndex = self.mainMessageTableWidget.rowCount() - 1 149 | self.serialWriterThread.setRepeatedWriteDelay(0) 150 | print('playing back...') 151 | self.serialWriterThread.packetSentSignal.connect(self.playbackMainTable1Packet) 152 | self.playbackMainTable1Packet() 153 | 154 | def clearTableCallback(self): 155 | self.idDict.clear() 156 | self.mainMessageTableWidget.setRowCount(0) 157 | 158 | def sendDecodedPacketCallback(self): 159 | self.newTxTableRowCallback() 160 | newRow = 0 161 | decodedCurrentRow = self.decodedMessagesTableWidget.currentRow() 162 | newId = str(self.decodedMessagesTableWidget.item(decodedCurrentRow, 1).text()).split(" ") 163 | newItem = QTableWidgetItem(newId[0]) 164 | self.txTable.setItem(newRow, 0, QTableWidgetItem(newItem)) 165 | for i in range(1, 3): 166 | self.txTable.setItem(newRow, i, self.decodedMessagesTableWidget.item(decodedCurrentRow, i+1)) 167 | newData = "" 168 | for i in range(int(self.decodedMessagesTableWidget.item(decodedCurrentRow, 4).text())): 169 | newData += str(self.decodedMessagesTableWidget.item(decodedCurrentRow, 5 + i).text()) 170 | self.txTable.setItem(newRow, 3, QTableWidgetItem(newData)) 171 | self.txTable.selectRow(newRow) 172 | if self.sendTxTableButton.isEnabled(): 173 | self.sendTxTableCallback() 174 | 175 | def decodedTableItemChangedCallback(self): 176 | if self.isInited: 177 | self.saveTableToFile(self.decodedMessagesTableWidget, "save/decodedPackets.csv") 178 | 179 | def deleteDecodedLineCallback(self): 180 | self.decodedMessagesTableWidget.removeRow(self.decodedMessagesTableWidget.currentRow()) 181 | 182 | def addToDecodedCallback(self): 183 | newRow = self.decodedMessagesTableWidget.rowCount() 184 | self.decodedMessagesTableWidget.insertRow(newRow) 185 | for i in range(1, self.decodedMessagesTableWidget.columnCount()): 186 | new_item = QTableWidgetItem(self.mainMessageTableWidget.item(self.mainMessageTableWidget.currentRow(), i)) 187 | self.decodedMessagesTableWidget.setItem(newRow, i, new_item) 188 | 189 | def showSendingTableButtonCallback(self): 190 | if self.showSendingTableCheckBox.isChecked(): 191 | self.sendingGroupBox.show() 192 | else: 193 | self.sendingGroupBox.hide() 194 | 195 | def hideAllPackets(self): 196 | text = "" 197 | for id in self.idDict: 198 | text += id + " " 199 | self.hideIdsLineEdit.setText(text) 200 | self.clearTableCallback() 201 | 202 | def hideOldPacketsCallback(self): 203 | if not self.hideOldPacketsCheckBox.isChecked(): 204 | return 205 | if not self.groupModeCheckBox.isChecked(): 206 | return 207 | for i in range(self.mainMessageTableWidget.rowCount()): 208 | if self.mainMessageTableWidget.isRowHidden(i): 209 | continue 210 | packetTime = float(self.mainMessageTableWidget.item(i, 0).text()) 211 | if (time.time() - self.startTime) - packetTime > self.hideOldPeriod.value(): 212 | # print("Hiding: " + str(self.mainMessageTableWidget.item(i,1).text())) 213 | # print(time.time() - self.start_time) 214 | self.mainMessageTableWidget.setRowHidden(i, True) 215 | 216 | def sendTxTableCallback(self): 217 | self.setRadioButton(self.txDataRadioButton, 2) 218 | for row in range(self.txTable.rowCount()): 219 | if self.txTable.item(row, 0).isSelected(): 220 | txBuf = "" 221 | for i in range(self.txTable.columnCount()): 222 | subStr = self.txTable.item(row, i).text() + "," 223 | if not len(subStr) % 2: 224 | subStr = '0' + subStr 225 | txBuf += subStr 226 | txBuf = txBuf[:-1] + '\n' 227 | if self.repeatedDelayCheckBox.isChecked(): 228 | self.serialWriterThread.setRepeatedWriteDelay(self.repeatTxDelayValue.value()) 229 | else: 230 | self.serialWriterThread.setRepeatedWriteDelay(0) 231 | self.serialWriterThread.write(txBuf) 232 | 233 | def fileLoadingFinishedCallback(self): 234 | self.abortSessionLoadingButton.setEnabled(False) 235 | 236 | def abortSessionLoadingCallback(self): 237 | self.fileLoaderThread.stop() 238 | self.abortSessionLoadingButton.setEnabled(False) 239 | 240 | def removeTxTableRowCallback(self): 241 | try: 242 | self.txTable.removeRow(self.txTable.currentRow()) 243 | except: 244 | print('cannot remove') 245 | 246 | def newTxTableRowCallback(self): 247 | newRow = 0 248 | self.txTable.insertRow(newRow) 249 | self.txTable.setItem(newRow, 1, QTableWidgetItem("00")) 250 | self.txTable.setItem(newRow, 2, QTableWidgetItem("00")) 251 | 252 | def showOnlyIdsTextChanged(self): 253 | self.showOnlyIdsSet.clear() 254 | self.showOnlyIdsSet = set(self.showOnlyIdsLineEdit.text().split(" ")) 255 | 256 | def hideIdsTextChanged(self): 257 | self.hideIdsSet.clear() 258 | self.hideIdsSet = set(self.hideIdsLineEdit.text().split(" ")) 259 | 260 | def init(self): 261 | self.loadTableFromFile(self.decodedMessagesTableWidget, "save/decodedPackets.csv") 262 | self.loadTableFromFile(self.idLabelDictTable, "save/labelDict.csv") 263 | for row in range(self.idLabelDictTable.rowCount()): 264 | self.idLabelDict[str(self.idLabelDictTable.item(row, 0).text())] = \ 265 | str(self.idLabelDictTable.item(row, 1).text()) 266 | self.isInited = True 267 | 268 | def clearLabelDict(self): 269 | self.idLabelDictTable.setRowCount(0) 270 | self.saveTableToFile(self.idLabelDictTable, "save/labelDict.csv") 271 | 272 | def saveTableToFile(self, table, path): 273 | if path is None: 274 | path, _ = QFileDialog.getSaveFileName(self, 'Save File', './save', 'CSV(*.csv)') 275 | if path != '': 276 | with open(str(path), 'w', newline='') as stream: 277 | writer = csv.writer(stream) 278 | for row in range(table.rowCount()-1, -1, -1): 279 | rowData = [] 280 | for column in range(table.columnCount()): 281 | item = table.item(row, column) 282 | if item is not None: 283 | rowData.append(str(item.text())) 284 | else: 285 | rowData.append('') 286 | writer.writerow(rowData) 287 | 288 | def mainTablePopulatorCallback(self, rowData): 289 | self.setRadioButton(self.rxDataRadioButton, 2) 290 | 291 | if self.showOnlyIdsCheckBox.isChecked(): 292 | if str(rowData[1]) not in self.showOnlyIdsSet: 293 | return 294 | if self.hideIdsCheckBox.isChecked(): 295 | if str(rowData[1]) in self.hideIdsSet: 296 | return 297 | 298 | newId = str(rowData[1]) 299 | 300 | row = 0 # self.mainMessageTableWidget.rowCount() 301 | if self.groupModeCheckBox.isChecked(): 302 | if newId in self.idDict.keys(): 303 | row = self.idDict[newId] 304 | else: 305 | row = self.mainMessageTableWidget.rowCount() 306 | self.mainMessageTableWidget.insertRow(row) 307 | else: 308 | self.mainMessageTableWidget.insertRow(row) 309 | 310 | if self.mainMessageTableWidget.isRowHidden(row): 311 | self.mainMessageTableWidget.setRowHidden(row, False) 312 | 313 | for i in range(self.mainMessageTableWidget.columnCount()): 314 | if i < len(rowData): 315 | data = str(rowData[i]) 316 | item = self.mainMessageTableWidget.item(row, i) 317 | newItem = QTableWidgetItem(data) 318 | if item: 319 | if item.text() != data: 320 | if self.highlightNewDataCheckBox.isChecked() and \ 321 | self.groupModeCheckBox.isChecked() and \ 322 | i > 4: 323 | newItem.setBackground(QColor(104, 37, 98)) 324 | else: 325 | if self.highlightNewDataCheckBox.isChecked() and \ 326 | self.groupModeCheckBox.isChecked() and \ 327 | i > 4: 328 | newItem.setBackground(QColor(104, 37, 98)) 329 | else: 330 | newItem = QTableWidgetItem() 331 | self.mainMessageTableWidget.setItem(row, i, newItem) 332 | 333 | isFamiliar = False 334 | 335 | if self.highlightNewIdCheckBox.isChecked(): 336 | if newId not in self.idDict.keys(): 337 | for j in range(3): 338 | self.mainMessageTableWidget.item(row, j).setBackground(QColor(52, 44, 124)) 339 | 340 | self.idDict[newId] = row 341 | 342 | if newId in self.idLabelDict.keys(): 343 | value = newId + " (" + self.idLabelDict[newId] + ")" 344 | self.mainMessageTableWidget.setItem(row, 1, QTableWidgetItem(value)) 345 | isFamiliar = True 346 | 347 | for i in range(self.mainMessageTableWidget.columnCount()): 348 | if (isFamiliar or (newId.find("(") >= 0)) and i < 3: 349 | self.mainMessageTableWidget.item(row, i).setBackground(QColor(53, 81, 52)) 350 | 351 | self.mainMessageTableWidget.item(row, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) 352 | 353 | self.receivedPackets = self.receivedPackets + 1 354 | self.packageCounterLabel.setText(str(self.receivedPackets)) 355 | 356 | 357 | def loadTableFromFile(self, table, path): 358 | if path is None: 359 | path, _ = QFileDialog.getOpenFileName(self, 'Open File', './save', 'CSV(*.csv)') 360 | if path != '': 361 | if table == self.mainMessageTableWidget: 362 | self.fileLoaderThread.start() 363 | self.fileLoaderThread.enable(path, self.playbackDelaySpinBox.value()) 364 | self.abortSessionLoadingButton.setEnabled(True) 365 | return True 366 | try: 367 | with open(str(path), 'r') as stream: 368 | for rowData in csv.reader(stream): 369 | row = table.rowCount() 370 | table.insertRow(row) 371 | for i in range(len(rowData)): 372 | if len(rowData[i]): 373 | item = QTableWidgetItem(str(rowData[i])) 374 | if not (table == self.decodedMessagesTableWidget and i == 0): 375 | item.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) 376 | table.setItem(row, i, item) 377 | except OSError: 378 | print("file not found: " + path) 379 | 380 | def loadSessionFromFile(self): 381 | if self.autoclearCheckBox.isChecked(): 382 | self.idDict.clear() 383 | self.mainMessageTableWidget.setRowCount(0) 384 | self.loadTableFromFile(self.mainMessageTableWidget, None) 385 | 386 | def saveSessionToFile(self): 387 | self.saveTableToFile(self.mainMessageTableWidget, None) 388 | 389 | def cellWasClicked(self): 390 | self.saveIdToDictLineEdit.setText(self.mainMessageTableWidget.item(self.mainMessageTableWidget.currentRow(), 1).text()) 391 | 392 | def saveIdLabelToDictCallback(self): 393 | if (not self.saveIdToDictLineEdit.text()) or (not self.saveLabelToDictLineEdit.text()): 394 | return 395 | newRow = self.idLabelDictTable.rowCount() 396 | self.idLabelDictTable.insertRow(newRow) 397 | widgetItem = QTableWidgetItem() 398 | widgetItem.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) 399 | widgetItem.setText(self.saveIdToDictLineEdit.text()) 400 | self.idLabelDictTable.setItem(newRow, 0, QTableWidgetItem(widgetItem)) 401 | widgetItem.setText(self.saveLabelToDictLineEdit.text()) 402 | self.idLabelDictTable.setItem(newRow, 1, QTableWidgetItem(widgetItem)) 403 | self.idLabelDict[str(self.saveIdToDictLineEdit.text())] = str(self.saveLabelToDictLineEdit.text()) 404 | self.saveIdToDictLineEdit.setText('') 405 | self.saveLabelToDictLineEdit.setText('') 406 | self.saveTableToFile(self.idLabelDictTable, "save/labelDict.csv") 407 | 408 | def startSniffing(self): 409 | if self.autoclearCheckBox.isChecked(): 410 | self.idDict.clear() 411 | self.mainMessageTableWidget.setRowCount(0) 412 | self.startSniffingButton.setEnabled(False) 413 | self.stopSniffingButton.setEnabled(True) 414 | self.sendTxTableButton.setEnabled(True) 415 | self.activeChannelComboBox.setEnabled(False) 416 | 417 | txBuf = [0x42, self.activeChannelComboBox.currentIndex()] # TX FORWARDER 418 | self.serialWriterThread.write(txBuf) 419 | txBuf = [0x41, 1 << self.activeChannelComboBox.currentIndex()] # RX FORWARDER 420 | self.serialWriterThread.write(txBuf) 421 | 422 | self.startTime = time.time() 423 | 424 | def stopSniffing(self): 425 | self.startSniffingButton.setEnabled(True) 426 | self.stopSniffingButton.setEnabled(False) 427 | self.sendTxTableButton.setEnabled(False) 428 | self.activeChannelComboBox.setEnabled(True) 429 | self.setRadioButton(self.rxDataRadioButton, 0) 430 | 431 | def serialPacketReceiverCallback(self, packet): 432 | if self.startSniffingButton.isEnabled(): 433 | return 434 | packetSplit = packet[:-1].split(',') 435 | 436 | if len(packetSplit) != 4: 437 | print("wrong packet!" + packet) 438 | self.snifferMsgPlainTextEdit.document().setPlainText(packet) 439 | return 440 | 441 | rowData = [str(time.time() - self.startTime)[:7]] # timestamp 442 | rowData += packetSplit[0:3] # IDE, RTR, EXT 443 | DLC = len(packetSplit[3]) // 2 444 | rowData.append(str("{:02X}".format(DLC))) # DLC 445 | if DLC > 0: 446 | rowData += [packetSplit[3][i:i + 2] for i in range(0, len(packetSplit[3]), 2)] # data 447 | 448 | self.mainTablePopulatorCallback(rowData) 449 | 450 | def serialPortConnect(self): 451 | try: 452 | self.serialController.port = self.portSelectorComboBox.currentText() 453 | self.serialController.baudrate = 250000 454 | self.serialController.open() 455 | self.serialReaderThread.start() 456 | self.serialWriterThread.start() 457 | self.serialConnectedCheckBox.setChecked(True) 458 | self.portDisconnectButton.setEnabled(True) 459 | self.portConnectButton.setEnabled(False) 460 | self.startSniffingButton.setEnabled(True) 461 | self.stopSniffingButton.setEnabled(False) 462 | except serial.SerialException as e: 463 | print('Error opening port: ' + str(e)) 464 | 465 | def serialPortDisconnect(self): 466 | if self.stopSniffingButton.isEnabled(): 467 | self.stopSniffing() 468 | try: 469 | self.serialReaderThread.stop() 470 | self.serialWriterThread.stop() 471 | self.portDisconnectButton.setEnabled(False) 472 | self.portConnectButton.setEnabled(True) 473 | self.startSniffingButton.setEnabled(False) 474 | self.serialConnectedCheckBox.setChecked(False) 475 | self.serialController.close() 476 | except serial.SerialException as e: 477 | print('Error closing port: ' + str(e)) 478 | 479 | def scanPorts(self): 480 | comPorts = serial.tools.list_ports.comports() 481 | nameList = list(port.device for port in comPorts) 482 | for name in nameList: 483 | self.portSelectorComboBox.addItem(name) 484 | 485 | 486 | def exception_hook(exctype, value, traceback): 487 | print(exctype, value, traceback) 488 | sys._excepthook(exctype, value, traceback) 489 | sys.exit(1) 490 | 491 | def main(): 492 | # excepthook redirect 493 | sys._excepthook = sys.excepthook 494 | sys.excepthook = exception_hook 495 | 496 | # creating app 497 | app = QApplication(sys.argv) 498 | gui = canSnifferGUI() 499 | 500 | #applying dark theme 501 | qtmodern.styles.dark(app) 502 | darked_gui = qtmodern.windows.ModernWindow(gui) 503 | 504 | # adding a grip to the top left corner to make the frameless window resizable 505 | layout = QVBoxLayout() 506 | sizegrip = QSizeGrip(darked_gui) 507 | sizegrip.setMaximumSize(30, 30) 508 | layout.addWidget(sizegrip, 50, Qt.AlignBottom | Qt.AlignRight) 509 | darked_gui.setLayout(layout) 510 | 511 | #starting the app 512 | darked_gui.show() 513 | app.exec_() 514 | 515 | 516 | if __name__ == "__main__": 517 | main() 518 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/main.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | import os 3 | from PyInstaller.utils.hooks import collect_data_files 4 | 5 | spec_root = os.path.abspath(SPECPATH) 6 | qtmodern_data = collect_data_files('qtmodern') 7 | 8 | block_cipher = None 9 | 10 | a = Analysis(['main.py'], 11 | pathex=[spec_root], 12 | binaries=[], 13 | datas= qtmodern_data, 14 | hiddenimports=['PyQt5', 'Pyserial', 'PyQt5-tools', 'qtmodern'], 15 | hookspath=[], 16 | runtime_hooks=[], 17 | excludes=[], 18 | win_no_prefer_redirects=False, 19 | win_private_assemblies=False, 20 | cipher=block_cipher, 21 | noarchive=False) 22 | pyz = PYZ(a.pure, a.zipped_data, 23 | cipher=block_cipher) 24 | exe = EXE(pyz, 25 | a.scripts, 26 | a.binaries, 27 | a.zipfiles, 28 | a.datas, 29 | [], 30 | name='main', 31 | debug=False, 32 | bootloader_ignore_signals=False, 33 | strip=False, 34 | upx=True, 35 | upx_exclude=[], 36 | runtime_tmpdir=None, 37 | console=False ) 38 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/requirements.txt: -------------------------------------------------------------------------------- 1 | PySerial 2 | PyQt5 3 | PyQt5-tools 4 | qtmodern -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/save/decodedPackets.csv: -------------------------------------------------------------------------------- 1 | cabin light on,252,00,00,08,07,AE,03,80,00,00,00,00 2 | front left window up,259,00,00,08,04,AE,02,08,08,00,00,00 3 | front left window down,259,00,00,08,04,AE,02,08,10,00,00,00 4 | front left window stop,259,00,00,08,04,AE,02,08,00,00,00,00 5 | rear right door,230 (RearLeftDoor),00,00,05,00,10,10,00,00,,, 6 | exit test mode,255,00,00,08,02,AA,00,00,00,00,00,00 7 | fuel indicator min,255,00,00,08,07,AE,01,04,04,00,82,00 8 | windows locked,415 (RightWindow),00,00,05,80,00,00,00,00,,, 9 | windows not locked (idle),415 (RightWindow),00,00,05,00,00,00,00,00,,, 10 | right mirror left,405 (FrontLeftDoor),00,00,06,00,01,00,10,00,00,, 11 | right mirror right,405 (FrontLeftDoor),00,00,06,00,02,00,10,00,00,, 12 | right mirror up,405 (FrontLeftDoor),00,00,06,00,04,00,10,00,00,, 13 | righ mirror down,405 (FrontLeftDoor),00,00,06,00,08,00,10,00,00,, 14 | left mirror active,405 (FrontLeftDoor),00,00,06,00,00,00,08,00,00,, 15 | right mirror active,405 (FrontLeftDoor),00,00,06,00,00,00,10,00,00,, 16 | rear left window up,415 (RightWindow),00,00,05,00,00,20,1B,F0,,, 17 | rear left window down,415 (RightWindow),00,00,05,00,00,40,1B,F0,,, 18 | rear right window,415 (RightWindow),00,00,05,00,00,02,1B,F0,,, 19 | rear right window up,415 (RightWindow),00,00,05,00,00,04,1B,F0,,, 20 | front right window up,415 (RightWindow),00,00,05,00,02,00,1B,F0,,, 21 | front right window down,415 (RightWindow),00,00,05,00,04,00,1B,F0,,, 22 | right window idle,415 (RightWindow),00,00,05,00,00,00,00,00,,, 23 | rear left door close,230 (RearLeftDoor),00,00,05,00,00,00,00,00,,, 24 | rear left door open,230 (RearLeftDoor),00,00,05,00,40,00,00,00,,, 25 | front right close,420 (FrontRightDoor),00,00,05,00,00,00,00,00,,, 26 | front right open,420 (FrontRightDoor),00,00,05,00,00,40,00,00,,, 27 | front left open,405 (FrontLeftDoor),00,00,06,00,00,20,00,00,00,, 28 | front left close,405 (FrontLeftDoor),00,00,06,00,00,00,00,00,00,, 29 | lights low beam,350 (FrontFogLight),00,00,02,06,00,,,,,, 30 | lights off,23A (LightSwitch),00,00,03,00,00,00,,,,, 31 | lights pos indicator,23A (LightSwitch),00,00,03,00,20,00,,,,, 32 | lights low beam,23A (LightSwitch),00,00,03,00,A0,00,,,,, 33 | lights auto,23A (LightSwitch),00,00,03,04,00,00,,,,, 34 | lights high beam,350 (FrontFogLight),00,00,02,46,00,,,,,, 35 | turning light left,260 (TurningLight),00,00,03,25,40,80,,,,, 36 | turning light right,260 (TurningLight),00,00,03,3A,40,80,,,,, 37 | jam indicator,260 (TurningLight),00,00,03,1F,40,80,,,,, 38 | turning light idle,260 (TurningLight),00,00,03,00,40,80,,,,, 39 | window cleaner roller min,175 (WheelJoys),00,00,08,00,00,00,00,33,00,00,00 40 | window cleaner roller max,175 (WheelJoys),00,00,08,00,00,00,00,CC,00,00,00 41 | break idle,360 (Break),00,00,03,00,00,00,,,,, 42 | break pushed,360 (Break),00,00,03,00,00,40,,,,, 43 | Pedals idle(d2 increment),115 (Pedals),00,00,03,20,FF,50,,,,, 44 | Pedals break,115 (Pedals),00,00,03,28,FF,60,,,,, 45 | Pedals clutch,115 (Pedals),00,00,03,24,FF,10,,,,, 46 | handbreak released,220 (Handbreak),00,00,01,08,,,,,,, 47 | handbreak locked,220 (Handbreak),00,00,01,18,,,,,,, 48 | window heating,23A (LightSwitch),00,00,03,00,03,00,,,,, 49 | 850,108 (RPM),00,00,08,11,0D,44,00,00,00,00,00 50 | 1500,108 (RPM),00,00,08,21,18,78,00,00,00,00,00 51 | AC ON,155 (Climate),00,00,03,80,00,30,,,,, 52 | AC OFF,155 (Climate),00,00,03,00,00,2C,,,,, 53 | wheel right vol down,175 (WheelJoys),00,00,08,00,00,00,00,CC,02,00,1F 54 | wheel right vol up,175 (WheelJoys),00,00,08,00,00,00,00,CC,01,00,01 55 | wheel right btn down,175 (WheelJoys),00,00,08,00,00,00,00,CC,05,00,00 56 | wheel right btn up,175 (WheelJoys),00,00,08,00,00,00,00,CC,04,00,00 57 | wheel left select up,175 (WheelJoys),00,00,08,00,00,00,00,CC,10,1F,00 58 | wheel left select down,175 (WheelJoys),00,00,08,00,00,00,00,CC,20,01,00 59 | wheel left select push,175 (WheelJoys),00,00,08,00,00,00,00,CC,30,00,00 60 | wheel left lower btn,175 (WheelJoys),00,00,08,00,00,00,00,CC,50,00,00 61 | wheel left upper btn,175 (WheelJoys),00,00,08,00,00,00,00,CC,40,00,00 62 | doors locked,230 (RearLeftDoor),00,00,05,05,00,00,00,00,,, 63 | dorrs unlocked,230 (RearLeftDoor),00,00,05,00,00,00,00,00,,, 64 | trunk unlock short,405 (FrontLeftDoor),00,00,06,00,00,00,04,00,00,, 65 | trunk unlock long,405 (FrontLeftDoor),00,00,06,00,00,00,06,00,00,, 66 | wheel joys idle,175 (WheelJoys),00,00,08,00,00,00,00,CC,00,00,00 67 | right front window up btn,415 (RightWindow),00,00,05,00,00,00,00,00,,, 68 | right front window down btn,415 (RightWindow),00,00,05,00,04,00,1B,F0,,, 69 | right rear window down btn,415 (RightWindow),00,00,05,00,00,04,1B,F0,,, 70 | right rear window up btn,415 (RightWindow),00,00,05,00,00,02,1B,F0,,, 71 | left rear window down btn,415 (RightWindow),00,00,05,00,00,40,1B,F0,,, 72 | left rear window up btn,415 (RightWindow),00,00,05,00,00,20,1B,F0,,, 73 | brightness_value(0-ff),235 (brightness),00,00,02,00,6A,,,,,, 74 | front fog on,350 (FrontFogLight),00,00,02,26,00,,,,,, 75 | front fog off,350 (FrontFogLight),00,00,02,06,00,,,,,, 76 | MSpeed middle knob left,201,00,00,03,08,6A,FF,,,,, 77 | MSpeed middle knob right,201,00,00,03,08,6A,01,,,,, 78 | MSpeed middle knob pushed_D2:inkrement,201,00,00,03,01,6B,2A,,,,, 79 | MSpeed NAVI btn,201,00,00,03,01,E0,0B,,,,, 80 | RPM,255,00,00,08,07,AE,01,02,02,00,17,70 81 | RPM,255,00,00,08,07,AE,01,01,01,00,00,F9 82 | coolant,255,00,00,08,07,AE,01,08,08,00,A7,00 83 | fuel indicator max,255,08,07,AE,01,04,04,00,28,00,, 84 | symbol test lock,255,00,00,08,07,AE,06,01,01,00,08,00 85 | front right window full down,258,00,00,08,04,AE,02,08,08,00,00,00 86 | front right window full up,258,00,00,08,04,AE,02,08,10,00,00,00 87 | position indicator light test ON,253 (UEC),00,00,08,06,AE,02,0C,00,0C,00,00 88 | position indicator light test OFF,253 (UEC),00,00,08,06,AE,02,0C,00,00,00,00 89 | low beam light test ON,253 (UEC),00,00,08,06,AE,02,C0,00,C0,00,00 90 | low beam light test ON,253 (UEC),00,00,08,06,AE,02,C0,00,00,00,00 91 | fog light test ON,253 (UEC),00,00,08,06,AE,02,00,0C,00,0C,00 92 | fog light test OFF,253 (UEC),00,00,08,06,AE,02,00,0C,00,00,00 93 | high beam light test ON,253 (UEC),00,00,08,06,AE,02,30,00,30,00,00 94 | high beam light test OFF,253 (UEC),00,00,08,06,AE,02,30,00,00,00,00 95 | turning light test ON,253 (UEC),00,00,08,06,AE,02,03,00,03,00,00 96 | turning light test OFF,253 (UEC),00,00,08,06,AE,02,03,00,00,00,00 97 | open - only front left,160 (Remote),00,00,04,01,10,7D,28,,,, 98 | doors close,160 (Remote),00,00,04,01,40,7D,28,,,, 99 | all doors open,160 (Remote),00,00,04,01,20,7D,28,,,, 100 | long press close,160 (Remote),00,00,04,01,C0,7D,28,,,, 101 | long press open,160 (Remote),00,00,04,01,30,7D,28,,,, 102 | trunk open 1x,160 (Remote),00,00,04,01,04,7D,28,,,, 103 | trunk open 2x,160 (Remote),00,00,04,01,08,7D,28,,,, 104 | trunk open long press,160 (Remote),00,00,04,01,0C,7D,28,,,, 105 | Immo ignition,621 (Immo),00,00,08,00,48,50,00,00,00,00,00 106 | before ignition,621 (Immo),00,00,08,00,20,00,00,00,00,00,00 107 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/save/labelDict.csv: -------------------------------------------------------------------------------- 1 | 201,BC_inc 2 | 621,Immo 3 | 160,Remote 4 | 257,SDM 5 | 252,BCM 6 | 254,REC 7 | 253,UEC 8 | 155,Climate 9 | 108,RPM 10 | 220,Handbreak 11 | 115,Pedals 12 | 360,Break 13 | 260,Turninglight 14 | 175,WheelJoys 15 | 415,RightWindow 16 | 235,Brightness 17 | 350,FrontFogLight 18 | 23A,LightSwitch 19 | 500,WheelPos? 20 | 420,FrontRightDoor 21 | 405,FrontLeftDoor 22 | 230,RearLeftDoor 23 | 4E8,REC 24 | 506,BCM 25 | -------------------------------------------------------------------------------- /canDrive/02_canSniffer_GUI/ui_converter.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | subprocess.check_output(['pyuic5', '-o', 'canSniffer_ui.py', 'canSniffer.ui']) 4 | -------------------------------------------------------------------------------- /canDrive/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Adam Varga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /canDrive/README.md: -------------------------------------------------------------------------------- 1 | # canDrive 2 | Tools for hacking your car. Please concider checking out the tutorials made about this project: 3 | https://www.youtube.com/playlist?list=PLNiFaO8hU1z0o_6DSxk-jcVAM3UCUR-pY 4 | 5 | I've created this google sheet, so everybody can freely add their decoded IDs and packets, so it's easier for the community to collaborate: 6 | https://docs.google.com/spreadsheets/d/1eBKiTwEE6aPnfw2EfSHItLeMz00fJq0Y0L99Ym7fKwU/edit?usp=sharing 7 | 8 | # Content 9 | - 01_canSniffer_Arduino: This code runs on your arduino sniffer device and creates an interface between the car and the GUI. 10 | - 02_canSniffer_GUI: Powerful and easy-to-use graphical sniffer application used for reverse engineering CAN packets. 11 | # Description 12 | ##### 01_canSniffer_Arduino 13 | This code creates the interface between the car and the canSniffer_GUI application. If the RANDOM_CAN define is set to 1, this code is generating random CAN packets in order to test the higher level code. The received packets will be echoed back. If the RANDOM_CAN define is set to 0, the CAN_SPEED define has to match the speed of the desired CAN channel in order to receive and transfer from and to the CAN bus. 14 | Required arduino packages: 15 | - CAN by Sandeep Mistry (https:github.com/sandeepmistry/arduino-CAN) 16 | 17 | Required modifications: 18 | - MCP2515.h: 16e6 clock frequency reduced to 8e6 (depending on MCP2515 clock) 19 | - MCP2515.cpp: extend CNF_MAPPER with your desired CAN speeds 20 | 21 | ##### 02_canSniffer_GUI 22 | Python 3 is required for this project, 3.8 is preferred. This project contains my decoded packets in save/decodedPackets.csv. The required python packages can be installed with: 23 | ```sh 24 | $ pip install -r requirements.txt 25 | ``` 26 | # To be uploaded 27 | - Hardware files for the custom OBD2 module. 28 | - Firmware projects for the custom OBD2 module. 29 | - Source code for the mobile application. 30 | --------------------------------------------------------------------------------