├── .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 |
--------------------------------------------------------------------------------