├── Colorer.py ├── README.md ├── Robotell_USB-CAN.txt ├── extmask.sh ├── stdmask.sh ├── transmit.sh └── usb-can.py /Colorer.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import logging 3 | # now we patch Python code to add color support to logging.StreamHandler 4 | def add_coloring_to_emit_windows(fn): 5 | # add methods we need to the class 6 | def _out_handle(self): 7 | import ctypes 8 | return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE) 9 | out_handle = property(_out_handle) 10 | 11 | def _set_color(self, code): 12 | import ctypes 13 | # Constants from the Windows API 14 | self.STD_OUTPUT_HANDLE = -11 15 | hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE) 16 | ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code) 17 | 18 | setattr(logging.StreamHandler, '_set_color', _set_color) 19 | 20 | def new(*args): 21 | FOREGROUND_BLUE = 0x0001 # text color contains blue. 22 | FOREGROUND_GREEN = 0x0002 # text color contains green. 23 | FOREGROUND_RED = 0x0004 # text color contains red. 24 | FOREGROUND_INTENSITY = 0x0008 # text color is intensified. 25 | FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED 26 | # winbase.h 27 | STD_INPUT_HANDLE = -10 28 | STD_OUTPUT_HANDLE = -11 29 | STD_ERROR_HANDLE = -12 30 | 31 | # wincon.h 32 | FOREGROUND_BLACK = 0x0000 33 | FOREGROUND_BLUE = 0x0001 34 | FOREGROUND_GREEN = 0x0002 35 | FOREGROUND_CYAN = 0x0003 36 | FOREGROUND_RED = 0x0004 37 | FOREGROUND_MAGENTA = 0x0005 38 | FOREGROUND_YELLOW = 0x0006 39 | FOREGROUND_GREY = 0x0007 40 | FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified. 41 | 42 | BACKGROUND_BLACK = 0x0000 43 | BACKGROUND_BLUE = 0x0010 44 | BACKGROUND_GREEN = 0x0020 45 | BACKGROUND_CYAN = 0x0030 46 | BACKGROUND_RED = 0x0040 47 | BACKGROUND_MAGENTA = 0x0050 48 | BACKGROUND_YELLOW = 0x0060 49 | BACKGROUND_GREY = 0x0070 50 | BACKGROUND_INTENSITY = 0x0080 # background color is intensified. 51 | 52 | levelno = args[1].levelno 53 | if(levelno>=50): 54 | color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY 55 | elif(levelno>=40): 56 | color = FOREGROUND_RED | FOREGROUND_INTENSITY 57 | elif(levelno>=30): 58 | color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY 59 | elif(levelno>=20): 60 | color = FOREGROUND_GREEN 61 | elif(levelno>=10): 62 | color = FOREGROUND_MAGENTA 63 | #color = FOREGROUND_WHITE 64 | else: 65 | color = FOREGROUND_WHITE 66 | args[0]._set_color(color) 67 | 68 | ret = fn(*args) 69 | args[0]._set_color( FOREGROUND_WHITE ) 70 | #print "after" 71 | return ret 72 | return new 73 | 74 | def add_coloring_to_emit_ansi(fn): 75 | # add methods we need to the class 76 | def new(*args): 77 | levelno = args[1].levelno 78 | if(levelno>=50): 79 | color = '\x1b[31m' # red 80 | elif(levelno>=40): 81 | color = '\x1b[31m' # red 82 | elif(levelno>=30): 83 | color = '\x1b[33m' # yellow 84 | elif(levelno>=20): 85 | color = '\x1b[32m' # green 86 | elif(levelno>=10): 87 | color = '\x1b[96m' # lightcyan 88 | #color = '\x1b[36m' # cyan 89 | #color = '\x1b[35m' # pink 90 | else: 91 | color = '\x1b[0m' # normal 92 | args[1].msg = color + args[1].msg + '\x1b[0m' # normal 93 | #print "after" 94 | return fn(*args) 95 | return new 96 | 97 | import platform 98 | if platform.system()=='Windows': 99 | # Windows does not support ANSI escapes and we are using API calls to set the console color 100 | logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit) 101 | else: 102 | # all non-Windows platforms are supporting ANSI escapes so we use them 103 | logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit) 104 | #log = logging.getLogger() 105 | #log.addFilter(log_filter()) 106 | #//hdlr = logging.StreamHandler() 107 | #//hdlr.setFormatter(formatter()) 108 | 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Robotell-USB-CAN-Python 2 | Python program for Robotell USB-CAN Adapter 3 | 4 | 5 | # Background 6 | I've bought a Robotell USB-CAN Adapter from AliExpress. 7 | ![USB-CAN Adapter](https://user-images.githubusercontent.com/6020549/86798040-52d73e80-c0ab-11ea-802c-93aa918e1067.JPG) 8 | 9 | The Windows application is published [here](https://www.amobbs.com/thread-4651667-1-1.html). 10 | The link described as "ourdev_627692IXWNNX.rar" in the page is the Windows application. 11 | But I can't understand Chinese. 12 | 13 | So, I analyzed the communication message that flows through USB and created a new application with Python. 14 | 15 | # Software Requiment 16 | - pyserial 17 | ``` 18 | $ sudo apt install python3-pip python3-setuptools 19 | $ python3 -m pip install pyserial 20 | ``` 21 | 22 | - socat 23 | ``` 24 | $ sudo apt install socat 25 | ``` 26 | 27 | # How to use 28 | ``` 29 | $ git clone https://github.com/nopnop2002/Robotell-USB-CAN-Python 30 | $ cd Robotell-USB-CAN-Python 31 | $ python ./usb-can.py --help 32 | usage: usb-can.py [-h] [-p PORT] [-s SPEED] [-u UDP] 33 | [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}] 34 | 35 | optional arguments: 36 | -h, --help show this help message and exit 37 | -p PORT, --port PORT open port 38 | -s SPEED, --speed SPEED 39 | can bit rate 40 | -u UDP, --udp UDP UDP receive port 41 | -l {DEBUG,INFO,WARNING,ERROR,CRITICAL}, --log {DEBUG,INFO,WARNING,ERROR,CRITICAL} 42 | Set the logging level 43 | ``` 44 | 45 | - port 46 | Communication port. 47 | Default is /dev/ttyUSB0. 48 | __Be sure to specify the correct port in Windows 10.__ 49 | 50 | - speed 51 | CAN bit rate. 52 | Default is 500Kbps. 53 | Supporting speed is 1M/800K/500K/400K/250K/125K/100K. 54 | 55 | - udp 56 | UDP port number for receiving commands from the outside. 57 | Default is 8200 58 | 59 | - log 60 | Log level. 61 | Default is WARNING. 62 | 63 | # Information of the USB-CAN Adapter 64 | These displays are internal information of the USB-CAN Adapter, not CAN FRAME. 65 | 66 | - BAUDRATE is the current speed. 67 | 0x20-0xA1-0x07-0x00 is 0x0007A120(=500,000) 68 | 69 | - VERSION is firmware version. 70 | 71 | - FILTERxx is the current receive filter setting. 72 | The initial value enables reception of all CAN FRAMEs. 73 | 74 | ``` 75 | BAUDRATE ID: 0x01FFFED0 DLC: 4 Data: 0x20 0xA1 0x07 0x00 76 | VERSION ID: 0x01FFFFE0 DLC: 8 Data: 0x01 0x00 0x00 0x00 0xC5 0x24 0x00 0x08 77 | CPUINFO0 ID: 0x01FFFFF0 DLC: 8 Data: 0x57 0xFF 0x73 0x06 0x67 0x75 0x54 0x55 78 | CPUINFO1 ID: 0x01FFFFF1 DLC: 8 Data: 0x11 0x30 0x17 0x67 0x00 0x00 0x00 0x00 79 | ABOM ID: 0x01FFFEB0 DLC: 8 Data: 0x00 0x00 0x00 0x00 0xC5 0x24 0x00 0x08 80 | ART ID: 0x01FFFEA0 DLC: 8 Data: 0x00 0x00 0x00 0x00 0xC5 0x24 0x00 0x08 81 | FILTER00 ID: 0x01FFFEE0 DLC: 8 Data: 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 82 | FILTER01 ID: 0x01FFFEE1 DLC: 8 Data: 0x00 0x00 0x00 0xC0 0x00 0x00 0x00 0x00 83 | FILTER02 ID: 0x01FFFEE2 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 84 | FILTER03 ID: 0x01FFFEE3 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 85 | FILTER04 ID: 0x01FFFEE4 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 86 | FILTER05 ID: 0x01FFFEE5 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 87 | FILTER06 ID: 0x01FFFEE6 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 88 | FILTER07 ID: 0x01FFFEE7 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 89 | FILTER08 ID: 0x01FFFEE8 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 90 | FILTER09 ID: 0x01FFFEE9 DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 91 | FILTER10 ID: 0x01FFFEEA DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 92 | FILTER11 ID: 0x01FFFEEB DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 93 | FILTER12 ID: 0x01FFFEEC DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 94 | FILTER13 ID: 0x01FFFEED DLC: 8 Data: 0xFF 0xFF 0xFF 0x5F 0xFF 0xFF 0xFF 0x1F 95 | FILTER14 ID: 0x01FFFEEE DLC: 8 Data: 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00 96 | FILTER15 ID: 0x01FFFEEF DLC: 8 Data: 0xFF 0xFF 0xFF 0xBF 0xFF 0xFF 0xFF 0xFF 97 | ``` 98 | 99 | # CAN transmission data 100 | This tool accepts data to send via UDP Broadcast. 101 | Open a new terminal and execute the following command: 102 | ``` 103 | $ chmod 777 transmit.sh 104 | $ vi transmit.sh 105 | 106 | Please change if necessary. 107 | 108 | $ ./transmit.sh 109 | ``` 110 | 111 | # CAN receive filter settings(Standard Frame) 112 | This tool accepts filter to set via UDP Broadcast. 113 | Open a new terminal and execute the following command: 114 | ``` 115 | $ chmod 777 stdmask.sh 116 | $ vi stdmask.sh 117 | 118 | Please change if necessary. 119 | 120 | $ ./stdmask.sh 121 | ``` 122 | 123 | # CAN receive filter settings(Extended Frame) 124 | This tool accepts filter to set via UDP Broadcast. 125 | Open a new terminal and execute the following command: 126 | ``` 127 | $ chmod 777 extmask.sh 128 | $ vi extmask.sh 129 | 130 | Please change if necessary. 131 | 132 | $ ./extmask.sh 133 | ``` 134 | 135 | # Running on Ubuntu 18.04.4 136 | ![USBCAN-python-1](https://user-images.githubusercontent.com/6020549/86798048-55399880-c0ab-11ea-844d-5823554deff7.jpg) 137 | 138 | # Running on Windows10 139 | ![USBCAN-python-Windows](https://user-images.githubusercontent.com/6020549/86865771-9dd46e80-c10a-11ea-9a17-962add35e729.jpg) 140 | 141 | # Trouble shooting 142 | Change the log level when the program starts. 143 | You can see receive & transmit packet. 144 | ![USB-CAN -python-LogLevel](https://user-images.githubusercontent.com/6020549/86876808-74bed880-c120-11ea-85d1-6502682dbbdf.jpg) 145 | 146 | # Using ESP32 147 | The ESP32 includes a CAN controller that supports the CAN 2.0B specification standard frame format (11-bit ID) and extended frame format (29-bit ID). 148 | With the ESP32, you can use Windows applications. 149 | https://github.com/nopnop2002/esp-idf-CANBus-Monitor 150 | -------------------------------------------------------------------------------- /Robotell_USB-CAN.txt: -------------------------------------------------------------------------------- 1 | STM32 Flash Memory MAP 2 | 3 | --- CAN_ADDR_START --- 4 | [0] = 0xaaaaaaaa 5 | --- CAN_ADDR_BAUD --- 6 | [1] = 500,000 // Baudrate 7 | --- CAN_ADDR_FILTER 0 --- 8 | [2] = 0x01 : CAN_FILTER_EN | CAN_FORMAT_STD 9 | [3] = 0 : Id 10 | [4] = 0 : Mask 11 | --- CAN_ADDR_FILTER 1 --- 12 | [5] = 0x03 : CAN_FILTER_EN | CAN_FORMAT_EXT 13 | [6] = 0 : Id 14 | [7] = 0 : Mask 15 | --- CAN_ADDR_FILTER 2 --- 16 | [8] = 0x02 : CAN_FILTER_DIS | CAN_FORMAT_EXT 17 | [9] = 0x1FFFFFFF 18 | [10] = 0x1FFFFFFF 19 | --- CAN_ADDR_FILTER 3 --- 20 | [11]-[13] = Same as Mask2 21 | --- CAN_ADDR_FILTER 4 --- 22 | [14]-[16] = Same as Mask2 23 | --- CAN_ADDR_FILTER 5 --- 24 | [17]-[19] = Same as Mask2 25 | --- CAN_ADDR_FILTER 6 --- 26 | [20]-[22] = Same as Mask2 27 | --- CAN_ADDR_FILTER 7 --- 28 | [23]-[25] = Same as Mask2 29 | --- CAN_ADDR_FILTER 8 --- 30 | [26]-[28] = Same as Mask2 31 | --- CAN_ADDR_FILTER 9 --- 32 | [29]-[31] = Same as Mask2 33 | --- CAN_ADDR_FILTER 10 --- 34 | [32]-[34] = Same as Mask2 35 | --- CAN_ADDR_FILTER 11 --- 36 | [35]-[37] = Same as Mask2 37 | --- CAN_ADDR_FILTER 12 --- 38 | [38]-[40] = Same as Mask2 39 | --- CAN_ADDR_FILTER 13 --- 40 | [41]-[43] = Same as Mask2 41 | --- CAN_ADDR_ABOM --- 42 | [44] = False 43 | --- CAN_ADDR_ART --- 44 | [45] = False 45 | --- CAN_ADDR_VER --- 46 | [46] = 1 47 | 48 | 49 | 50 | USB CAN Adapter Communication Format 51 | 52 | * Inquiry about MCU side information 53 | Inquire using the following CAN-ID. 54 | 55 | #define CAN_BAUDRATE_ID 0x01fffed0 56 | #define CAN_CPU_INFO0_ID 0x01fffff0 57 | #define CAN_CPU_INFO1_ID (CAN_CPU_INFO0_ID + 1) 58 | #define CAN_VERSION_ID 0x01ffffe0 59 | #define CAN_INIT_ID 0x01fffeff // Clean Flash(500,000 bps/mask 0x0000) 60 | #define CAN_FILTER_BASE_ID 0x01fffeeX // X=0-F(Mask Index) 61 | #define CAN_ABOM_ID 0x01fffeb0 62 | #define CAN_ART_ID 0x01fffea0 63 | #define CAN_RESET_ID 0x01fffec0 // Reset 64 | 65 | c=0xAA 66 | c=0xAA 67 | c=0xD0 : (Inquire-ID >> 0) & 0xFF 68 | c=0xFE : (Inquire-ID >> 8) & 0xFF 69 | c=0xFF : (Inquire-ID >> 16) & 0xFF 70 | c=0x01 : (Inquire-ID >> 24) & 0xFF 71 | c=0x00 : Not use 72 | c=0x00 : Not use 73 | c=0x00 : Not use 74 | c=0x00 : Not use 75 | c=0x00 : Not use 76 | c=0x00 : Not use 77 | c=0x00 : Not use 78 | c=0x00 : Not use 79 | c=0x00 : Not use 80 | c=0xFF : Must be 0xFF 81 | c=0x01 : Must be 0x01 82 | c=0x00 : Request Type(0:Set/1:Inquiry) 83 | c=0x66 : CRC 84 | c=0x55 85 | c=0x55 86 | 87 | ** Inquiry VERSION 88 | [AA AA E0 FF FF 01 00 00 00 00 00 00 00 00 00 FF 01 00 DF 55 55] 89 | 90 | ** Inquiry CPU_INFO0 91 | [AA AA F0 FF FF 01 00 00 00 00 00 00 00 00 00 FF 01 00 EF 55 55] 92 | 93 | ** Inquiry CPU_INFO1 94 | [AA AA F1 FF FF 01 00 00 00 00 00 00 00 00 00 FF 01 00 F0 55 55] 95 | 96 | ** Inquiry ABOM 97 | [AA AA B0 FE FF 01 00 00 00 00 00 00 00 00 00 FF 01 00 AE 55 55] 98 | 99 | ** Inquiry ART 100 | [AA AA A0 FE FF 01 00 00 00 00 00 00 00 00 00 FF 01 00 97 55 55] 101 | 102 | ** Inquiry BAUDRATE 103 | [AA AA D0 FE FF 01 00 00 00 00 00 00 00 00 00 FF 01 01 CE 55 55] 104 | 105 | ** Inquiry MASK 106 | [AA AA E0 FE FF 01 00 00 00 80 00 00 00 00 08 FF 01 00 66 55 55] 107 | [AA AA E1 FE FF 01 00 00 00 C0 00 00 00 00 08 FF 01 00 A7 55 55] 108 | [AA AA E2 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 60 55 55] 109 | [AA AA E3 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 61 55 55] 110 | [AA AA E4 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 62 55 55] 111 | [AA AA E5 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 63 55 55] 112 | [AA AA E6 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 64 55 55] 113 | [AA AA E7 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 65 55 55] 114 | [AA AA E8 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 66 55 55] 115 | [AA AA E9 FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 67 55 55] 116 | [AA AA EA FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 68 55 55] 117 | [AA AA EB FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 69 55 55] 118 | [AA AA EC FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 6A 55 55] 119 | [AA AA ED FE FF 01 FF FF FF 5F FF FF FF 1F 08 FF 01 00 6B 55 55] 120 | [AA AA EE FE FF 01 00 00 00 00 01 00 00 00 08 FF 01 00 F5 55 55] 121 | [AA AA EF FE FF 01 FF FF FF FF FF FF FF FF 08 FF 01 00 ED 55 55] 122 | 123 | * Set BAUDRATE(1,000,000bps) 124 | c=0xAA 125 | c=0xAA 126 | c=0xD0 : CAN_BAUDRATE_ID 127 | c=0xFE : CAN_BAUDRATE_ID 128 | c=0xFF : CAN_BAUDRATE_ID 129 | c=0x01 : CAN_BAUDRATE_ID 130 | c=0x40 : Speed 131 | c=0x42 : Speed 132 | c=0x0F : Speed 133 | c=0x00 : Speed(0x000f4240=1,000,000) 134 | c=0x01 : Not use 135 | c=0x02 : Not use 136 | c=0x00 : Not use 137 | c=0x00 : Not use 138 | c=0x04 : Frame Data Length 139 | c=0xFF : System Message(Must be 0xFF) 140 | c=0x01 : Must be Extended Frame 141 | c=0x00 : Request Type(0:Set/1:Read) 142 | c=0x66 : CRC 143 | c=0x55 144 | c=0x55 145 | 146 | 147 | * Set BAUDRATE(800,000bps) 148 | c=0xAA 149 | c=0xAA 150 | c=0xD0 : CAN_BAUDRATE_ID 151 | c=0xFE : CAN_BAUDRATE_ID 152 | c=0xFF : CAN_BAUDRATE_ID 153 | c=0x01 : CAN_BAUDRATE_ID 154 | c=0x00 : Speed 155 | c=0x35 : Speed 156 | c=0x0C : Speed 157 | c=0x00 : Speed(0x000c3500=800,000) 158 | c=0x01 : Not use 159 | c=0x02 : Not use 160 | c=0x00 : Not use 161 | c=0x00 : Not use 162 | c=0x04 : Frame Data Length 163 | c=0xFF : System Message(Must be 0xFF) 164 | c=0x01 : Must be Extended Frame 165 | c=0x00 : Request Type(0:Set/1:Read) 166 | c=0x16 : CRC 167 | c=0x55 168 | c=0x55 169 | 170 | * Set BAUDRATE(500,000bps) 171 | c=0xAA 172 | c=0xAA 173 | c=0xD0 : 174 | c=0xFE : 175 | c=0xFF : 176 | c=0x01 : 177 | c=0x20 : speed 178 | c=0xA1 : speed 179 | c=0x07 : speed 180 | c=0x00 : speed(0x0007a120=500,000) 181 | c=0x01 182 | c=0x02 183 | c=0x00 184 | c=0x00 185 | c=0x04 186 | c=0xFF 187 | c=0x01 188 | c=0x00 189 | c=0x9D 190 | c=0x55 191 | c=0x55 192 | 193 | * Return 194 | [AA AA D0 FE FF 01 20 A1 07 00 01 02 00 00 04 FF 01 01 9E 55 55 ] 195 | 196 | * Set BAUDRATE(400,000bps) 197 | c=0xAA 198 | c=0xAA 199 | c=0xD0 200 | c=0xFE 201 | c=0xFF 202 | c=0x01 203 | c=0x80 : speed 204 | c=0x1A : speed 205 | c=0x06 : speed 206 | c=0x00 : speed(0x00061A80=400,000) 207 | c=0x01 208 | c=0x02 209 | c=0x00 210 | c=0x00 211 | c=0x04 212 | c=0xFF 213 | c=0x01 214 | c=0x00 215 | c=0x75 216 | c=0x55 217 | c=0x55 218 | 219 | 220 | * Set BAUDRATE(250,000bps) 221 | c=0xAA 222 | c=0xAA 223 | c=0xD0 224 | c=0xFE 225 | c=0xFF 226 | c=0x01 227 | c=0x90 : speed 228 | c=0xD0 : speed 229 | c=0x03 : speed 230 | c=0x00 : speed(0x0003D090=250,000) 231 | c=0x01 232 | c=0x02 233 | c=0x00 234 | c=0x00 235 | c=0x04 236 | c=0xFF 237 | c=0x01 238 | c=0x00 239 | c=0x38 240 | c=0x55 241 | c=0x55 242 | 243 | 244 | * Set BAUDRATE(125,000bps) 245 | c=0xAA 246 | c=0xAA 247 | c=0xD0 248 | c=0xFE 249 | c=0xFF 250 | c=0x01 251 | c=0x48 : speed 252 | c=0xE8 : speed 253 | c=0x01 : speed 254 | c=0x00 : speed(0x0001E848=125,000) 255 | c=0x01 256 | c=0x02 257 | c=0x00 258 | c=0x00 259 | c=0x04 260 | c=0xFF 261 | c=0x01 262 | c=0x00 263 | c=0x06 264 | c=0x55 265 | c=0x55 266 | 267 | 268 | * Set BAUDRATE(100,000bps) 269 | c=0xAA 270 | c=0xAA 271 | c=0xD0 272 | c=0xFE 273 | c=0xFF 274 | c=0x01 275 | c=0xA0 : speed 276 | c=0x86 : speed 277 | c=0x01 : speed 278 | c=0x00 : speed(0x000186A0=100,000) 279 | c=0x01 280 | c=0x02 281 | c=0x00 282 | c=0x00 283 | c=0x04 284 | c=0xFF 285 | c=0x01 286 | c=0x00 287 | c=0xFC 288 | c=0x55 289 | c=0x55 290 | 291 | 292 | 293 | 294 | 295 | 296 | * Set Receive Filter (Std format) 297 | [00] 0xAA : Start Mark[1] 298 | [01] 0xAA : Start mark[2] 299 | ---- Start of CRC Calculate ---- 300 | [02] 0xEn : Mask Number(0-15) 301 | [03] 0x00 302 | [04] 0x00 303 | [05] 0x00 304 | [06] 0x0F : (Id >> 0) & 0xFF 305 | [07] 0x01 : (Id >> 8) & 0xFF 306 | [08] 0x00 : (Id >> 16) & 0xFF 307 | [09] 0x80 : (Id >> 24) & 0xFF + Enable(0x80) 308 | [10] 0x10 : (Mask >> 0) & 0xFF 309 | [11] 0x0F : (Mask >> 8) & 0xFF 310 | [12] 0x00 : (Mask >> 16) & 0xFF 311 | [13] 0x00 : (Mask >> 24) & 0xFF 312 | [14] 0x08 : Frame Data jLength 313 | [15] 0xFF : System Message(Must be 0xFF) 314 | [16] 0x01 : Must be Extended Frame 315 | [17] 0x00 : Must be 0(0:Set/1:Read) 316 | ---- End of CRC Calculate ---- 317 | [18] 0xA2 : CRC(8 bits) 318 | [19] 0x55 : End Mark[0] 319 | [20] 0x55 : End mark[1] 320 | 321 | 322 | 323 | * Set Receive Filter (Ext format) 324 | [00] 0xAA : Start Mark[1] 325 | [01] 0xAA : Start mark[2] 326 | ---- Start of CRC Calculate ---- 327 | [02] 0x0x : Mask Number(0-15) 328 | [03] 0x00 329 | [04] 0x00 330 | [05] 0x00 331 | [06] 0x78 : (Id >> 0) & 0xFF 332 | [07] 0x56 : (Id >> 8) & 0xFF 333 | [08] 0x34 : (Id >> 16) & 0xFF 334 | [09] 0x12 : (Id >> 24) & 0xFF + Enable(0x80) 335 | [10] 0x78 : (Mask >> 0) & 0xFF 336 | [11] 0x56 : (Mask >> 8) & 0xFF 337 | [12] 0x34 : (Mask >> 16) & 0xFF 338 | [13] 0x12 : (Mask >> 24) & 0xFF + Extende(0x40) 339 | [14] 0x08 : Frame Data Length 340 | [15] 0xFF : System Message(Must be 0xFF) 341 | [16] 0x01 : Must be Extended Frame 342 | [17] 0x00 : Must be 0(0:Set/1:Read) 343 | ---- End of CRC Calculate ---- 344 | [18] 0xA2 : CRC(8 bits) 345 | [19] 0x55 : End Mark[0] 346 | [20] 0x55 : End mark[1] 347 | 348 | 349 | 350 | * CAN Frame Receive Format 351 | [00] 0xAA : Start Mark[1] 352 | [01] 0xAA : Start mark[2] 353 | [02] 0x78 : (Frame ID & 0xFF) >> 0 354 | [03] 0x56 : (Frame ID & 0xFF00) >> 8 355 | [04] 0x34 : (Frame ID & 0xFF0000) >> 16 356 | [05] 0x12 : (Frame ID & 0xFF000000) >> 24(0x12345678) 357 | [06] 0x11 : Frame Data[0] 358 | [07] 0x22 : Frame Data[1] 359 | [08] 0x33 : Frame Data[2] 360 | [09] 0x44 : Frame Data[3] 361 | [10] 0x00 : Frame Data[4] 362 | [11] 0x00 : Frame Data[5] 363 | [12] 0x00 : Frame Data[6] 364 | [13] 0x00 : Frame Data[70] 365 | [14] c=04 : Frame Data Length 366 | [15] c=00 : Message Type (00:Can Message/FF:System Message like BAUDRATE set) 367 | [16] 0x01 : CAN Frame Type (0:Standard/1:Extended) 368 | [17] 0x01 : CAN Request Type (0:Data frame/1:Remote frame) 369 | [18] 0x3F : CRC 370 | [19] 0x55 : 371 | [20] 0x55 : 372 | 373 | 374 | * Receive example 375 | 376 | [AA AA 02 01 00 00 01 02 00 00 00 00 00 00 02 00 00 00 FF 55 55] 377 | ID = 0x00000102 378 | Data = 01 02 00 00 00 00 00 00 379 | Length = 02 380 | Type = Standard Data Frame 381 | 382 | [AA AA 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF 55 55] 383 | ID = 0x00000102 384 | Data = 00 00 00 00 00 00 00 00 385 | Length = 00 386 | Type = Standard Remote Frame 387 | 388 | [AA AA 61 00 00 10 10 11 12 13 14 15 00 00 06 00 01 00 E7 55 55] 389 | ID = 0x10000061 390 | Data = 10 11 12 13 14 15 00 00 391 | Length = 06 392 | Type = Extended Data Frame 393 | 394 | [AA AA 61 00 00 10 00 00 00 00 00 00 00 00 00 00 01 01 E7 55 55] 395 | ID = 0x10000061 396 | Data = 00 00 00 00 00 00 00 00 397 | Length = 00 398 | Type = Extended Remote Frame 399 | 400 | 401 | * Insert Frame Control Code 402 | ** There is neither 0xA5 / 0xAA / 0x55 403 | ** Packet is 21 Bytes 404 | [00] 0xAA : Start Mark[1] 405 | [01] 0xAA : Start mark[2] 406 | ---- Start of CRC Calculate ---- 407 | [02] 0x0B : Frame ID[3] 408 | [03] 0x00 : Frame ID[2] 409 | [04] 0x00 : Frame ID[1] 410 | [05] 0x10 : Frame ID[0] 411 | [06] 0x10 : Frame Data[0] 412 | [07] 0x11 : Frame Data[1] 413 | [08] 0x12 : Frame Data[2] 414 | [09] 0x13 : Frame Data[3] 415 | [10] 0x14 : Frame Data[4] 416 | [11] 0x15 : Frame Data[5] 417 | [12] 0x16 : Frame Data[6] 418 | [13] 0x00 : Frame Data[7] 419 | [14] 0x00 : Frame Data Length 420 | [15] 0x00 : Message Type (00:Can Message) 421 | [16] 0x01 : CAN Frame type (0:Standard/1:Extended) 422 | [17] 0x01 : CAN Request Type (0:Data frame/1:Remote request frame) 423 | ---- End of CRC Calculate ---- 424 | [18] 0xA2 : CRC(8 bits) 425 | [19] 0x55 : End Mark[0] 426 | [20] 0x55 : End mark[1] 427 | 428 | ** CRC calcurate 429 | Simple addition 430 | 431 | |----------------------------------------------------| Range of CRC 432 | [170, 170, 7, 1, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 8, 0, 0, 0, 172, 85, 85] 433 | 434 | 435 | ** If there is 0xA5 / 0xAA / 0x55 in the CRC calculation range, insert FrameCtrl(0xA5) 436 | FrameCtrl is not included in crc calculation. 437 | 438 | [00] 0xAA : Start Mark[1] 439 | [01] 0xAA : Start mark[2] 440 | ---- Start of CRC Calculate ---- 441 | [02] 0x0B : Frame ID[3] 442 | [03] 0x00 : Frame ID[2] 443 | [04] 0x00 : Frame ID[1] 444 | [05] 0x10 : Frame ID[0] 445 | [06] 0xA5 : FrameCtrl ---> Inserted (not included in crc calculation) 446 | [07] 0x55 : Frame Data[0] ---> Ctrl Code 447 | [08] 0x11 : Frame Data[1] 448 | [09] 0x12 : Frame Data[2] 449 | [10] 0xA5 : FrameCtrl ---> Inserted (not included in crc calculation) 450 | [11] 0xAA : Frame Data[3] ---> Ctrl Code 451 | [12] 0x14 : Frame Data[4] 452 | [13] 0x15 : Frame Data[5] 453 | [14] 0x16 : Frame Data[6] 454 | [15] 0x00 : Frame Data[7] 455 | [16] 0x00 : Frame Data Length 456 | [17] 0x00 : Message Type (00:Can Message) 457 | [18] 0x01 : CAN Frame type (0:Standard/1:Extended) 458 | [19] 0x01 : CAN Request Type (0:Data frame/1:Remote request frame) 459 | ---- End of CRC Calculate ---- 460 | [20] 0xA2 : CRC(8 bits) 461 | [21] 0x55 : End Mark[0] 462 | [22] 0x55 : End mark[1] 463 | 464 | Example 465 | |---------------------------------------------------| Range of CRC 466 | [AA AA 02 01 00 00 A5 A5 A5 55 00 00 00 00 00 00 02 00 00 00 FF 55 55] 467 | CRC = 0x02+0x01+0xA5+0x55+0x02 = 0xFF 468 | 469 | 470 | 471 | ** If CRC is 0xA5 / 0xAA / 0x55, insert FrameCtrl(0xA5) 472 | [00] 0xAA : Start Mark[1] 473 | [01] 0xAA : Start mark[2] 474 | ---- Start of CRC Calculate ---- 475 | [02] 0x0B : Frame ID[3] 476 | [03] 0x00 : Frame ID[2] 477 | [04] 0x00 : Frame ID[1] 478 | [05] 0x10 : Frame ID[0] 479 | [06] 0x10 : Frame Data[0] 480 | [07] 0x11 : Frame Data[1] 481 | [08] 0x12 : Frame Data[2] 482 | [09] 0x13 : Frame Data[3] 483 | [10] 0x14 : Frame Data[4] 484 | [11] 0x15 : Frame Data[5] 485 | [12] 0x16 : Frame Data[6] 486 | [13] 0x00 : Frame Data[7] 487 | [14] 0x00 : Frame Data Length 488 | [15] 0x00 : Message Type (00:Can Message) 489 | [16] 0x01 : CAN Frame type (0:Standard/1:Extended) 490 | [17] 0x01 : CAN Request Type (0:Data frame/1:Remote request frame) 491 | ---- End of CRC Calculate ---- 492 | [18] 0xA5 : FrameCtrl ---> Inserted 493 | [19] 0xA5 : CRC(8 bits) ---> Real CRC 494 | [20] 0x55 : End Mark[0] 495 | [21] 0x55 : End mark[1] 496 | 497 | 498 | -------------------------------------------------------------------------------- /extmask.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # index 4 | # index of filter(0-15) 5 | # id 6 | # filter id 7 | # mask 8 | # filter mask 9 | # type 10 | # std : for Standard frame 11 | # ext : for Extended frame 12 | # status 13 | # Enable : Enable filter 14 | # disable : Disable filter 15 | 16 | # Enable 0x00000103 and 0x00000106 17 | json=$(cat << EOS 18 | { 19 | "request": "Filter", 20 | "index": 0, 21 | "id": "0x00000103", 22 | "mask": "0x000001FF", 23 | "type": "ext", 24 | "status": "Enable" 25 | } 26 | EOS 27 | ) 28 | 29 | echo "$json" 30 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 31 | 32 | json=$(cat << EOS 33 | { 34 | "request": "Filter", 35 | "index": 1, 36 | "id": "0x00000106", 37 | "mask": "0x000001FF", 38 | "type": "ext", 39 | "status": "Enable" 40 | } 41 | EOS 42 | ) 43 | 44 | echo "$json" 45 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 46 | 47 | 48 | -------------------------------------------------------------------------------- /stdmask.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # index 4 | # index of filter(0-15) 5 | # id 6 | # filter id 7 | # mask 8 | # filter mask 9 | # type 10 | # std : for Standard frame 11 | # ext : for Extended frame 12 | # status 13 | # Enable : Enable filter 14 | # disable : Disable filter 15 | 16 | # Enable 0x103 and 0x106 17 | json=$(cat << EOS 18 | { 19 | "request": "Filter", 20 | "index": 0, 21 | "id": "0x103", 22 | "mask": "0x1FF", 23 | "type": "std", 24 | "status": "Enable" 25 | } 26 | EOS 27 | ) 28 | 29 | echo "$json" 30 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 31 | 32 | json=$(cat << EOS 33 | { 34 | "request": "Filter", 35 | "index": 1, 36 | "id": "0x106", 37 | "mask": "0x1FF", 38 | "type": "std", 39 | "status": "Enable" 40 | } 41 | EOS 42 | ) 43 | 44 | echo "$json" 45 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 46 | 47 | 48 | -------------------------------------------------------------------------------- /transmit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # send Standard data frame 4 | 5 | json=$(cat << EOS 6 | { 7 | "request": "Transmit", 8 | "id": "0x123", 9 | "type": "stdData", 10 | "data": [1,2] 11 | } 12 | EOS 13 | ) 14 | 15 | echo "$json" 16 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 17 | 18 | # send Extended data frame 19 | 20 | json=$(cat << EOS 21 | { 22 | "request": "Transmit", 23 | "id": "0x123", 24 | "type": "extData", 25 | "data": [10,11,12,13] 26 | } 27 | EOS 28 | ) 29 | 30 | echo "$json" 31 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 32 | 33 | # send Standard remote frame 34 | 35 | json=$(cat << EOS 36 | { 37 | "request": "Transmit", 38 | "id": "0xF23", 39 | "type": "stdRemote" 40 | } 41 | EOS 42 | ) 43 | 44 | echo "$json" 45 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 46 | 47 | # send Extended remote frame 48 | 49 | json=$(cat << EOS 50 | { 51 | "request": "Transmit", 52 | "id": "0xF23", 53 | "type": "extRemote" 54 | } 55 | EOS 56 | ) 57 | 58 | echo "$json" 59 | echo "$json" | socat - udp-datagram:255.255.255.255:8200,broadcast 60 | -------------------------------------------------------------------------------- /usb-can.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import serial 4 | import struct 5 | import logging 6 | import Colorer 7 | import argparse 8 | from socket import socket, AF_INET, SOCK_DGRAM 9 | import threading 10 | import json 11 | 12 | # Timer Thread 13 | class TimerThread(threading.Thread): 14 | def __init__(self, ACTIVE, INTERVAL): 15 | threading.Thread.__init__(self) 16 | self.timerFlag = False 17 | self.interval = INTERVAL 18 | self.active = ACTIVE 19 | 20 | def run(self): 21 | while True: 22 | #print("Timer={} active={}".format(time.time(), self.active)) 23 | if self.active == True: self.timerFlag = True 24 | time.sleep(self.interval) 25 | 26 | # UDP Receive Thread 27 | class ServerThread(threading.Thread): 28 | def __init__(self, PORT): 29 | threading.Thread.__init__(self) 30 | # line information 31 | self.HOST = "" 32 | self.PORT = PORT 33 | self.BUFSIZE = 1024 34 | self.ADDR = ("", self.PORT) 35 | 36 | # bind 37 | self.udpServSock = socket(AF_INET, SOCK_DGRAM) 38 | self.udpServSock.bind(self.ADDR) 39 | self.interrupt = False 40 | 41 | def run(self): 42 | while True: 43 | try: 44 | #packet, self.addr = self.udpServSock.recvfrom(self.BUFSIZE) # Receive Data 45 | packet, addr = self.udpServSock.recvfrom(self.BUFSIZE) # Receive Data 46 | logging.debug("addr={}".format(addr)) 47 | logging.debug("recvfrom packet={}".format(packet)) 48 | self.packet = packet.decode() 49 | json_dict = json.loads(self.packet) # If parsing fails, go to exception 50 | logging.debug("json_dict={}".format(json_dict)) 51 | self.addrFrom = addr[0] 52 | self.portFrom = addr[1] 53 | logging.debug("self.addrFrom={} self.portFrom={}".format(self.addrFrom, self.portFrom)) 54 | self.request = json_dict["request"].lower() 55 | if (self.request == "transmit"): 56 | self.id = json_dict["id"] 57 | self.type = json_dict["type"].lower() 58 | logging.debug("self.request={} self.id={} self.type={}".format(self.request, self.id, self.type)) 59 | if (self.type == "stddata"): 60 | self.data = json_dict["data"] 61 | logging.debug("self.data={} len={}".format(self.data, len(self.data)), self.type) 62 | self.interrupt = True 63 | if (self.type == "extdata"): 64 | self.data = json_dict["data"] 65 | logging.debug("self.data={} len={}".format(self.data, len(self.data))) 66 | self.interrupt = True 67 | if (self.type == "stdremote"): self.interrupt = True 68 | if (self.type == "extremote"): self.interrupt = True 69 | if (self.request == "filter"): 70 | self.index = json_dict["index"] 71 | self.id = json_dict["id"] 72 | self.mask = json_dict["mask"] 73 | self.type = json_dict["type"] 74 | self.status = json_dict["status"] 75 | logging.info("request={} index={} id={} mask={} type={} status{}".format(self.request, self.index, self.id, self.mask, self.type, self.status)) 76 | self.interrupt = True 77 | except: 78 | logging.error("json parse fail {}".format(self.packet)) 79 | pass 80 | 81 | 82 | class ParseClass(object): 83 | def __init__(self): 84 | #print("__init__") 85 | self.buffer = [] 86 | self.status = 0 87 | 88 | def parseData(self, ch): 89 | logging.debug("ch=0x{:02x} {} status={} len={}".format(ch, ch, self.status, len(self.buffer))) 90 | if (self.status == 0): 91 | #print("self.status == 0") 92 | if (ch == 0xAA): 93 | self.status = 1 94 | self.buffer = [] 95 | self.crc = 0 96 | self.buffer.append(ch) 97 | #print("self.buffer={}".format(self.buffer)) 98 | return [] 99 | 100 | elif (self.status == 1): 101 | #print("self.status == 1") 102 | if (ch == 0xAA): 103 | self.status = 2 104 | self.buffer.append(ch) 105 | #print("self.buffer={}".format(self.buffer)) 106 | else: 107 | self.buffer = [] 108 | self.status = 0 109 | return [] 110 | 111 | elif (self.status == 2): 112 | #print("self.status == 2") 113 | #print("self.buffer={}".format(self.buffer)) 114 | if (len(self.buffer) == 18): 115 | if (ch == 0xA5): # FrameCtrl,Next character is true CRC. 116 | self.status = 3 117 | else: 118 | self.crc = self.crc & 0xff 119 | #print("self.crc={:x} ch={:x}".format(self.crc,ch)) 120 | if (self.crc != ch): 121 | logging.warning("Invalid CRC(status=2) {:02x} {:02x} {}".format(self.crc, ch, self.buffer)) 122 | self.status = 0 123 | else: 124 | self.status = 8 125 | self.buffer.append(ch) 126 | else: 127 | if (ch == 0xA5): # FrameCtrl,Skip this character 128 | self.status = 4 129 | else: 130 | self.crc = self.crc + ch 131 | self.buffer.append(ch) 132 | return [] 133 | 134 | elif (self.status == 3): 135 | #print("self.status == 3") 136 | self.crc = self.crc & 0xff 137 | #print("self.crc={:x} ch={:x}".format(self.crc,ch)) 138 | if (self.crc != ch): 139 | logging.warning("Invalid CRC(status=3) {:02x} {:02x} {}".format(self.crc, ch, self.buffer)) 140 | self.status = 0 141 | else: 142 | self.status = 8 143 | self.buffer.append(ch) 144 | return [] 145 | 146 | elif (self.status == 4): 147 | #print("self.status == 4") 148 | self.crc = self.crc + ch 149 | self.buffer.append(ch) 150 | self.status = 2 151 | return [] 152 | 153 | elif (self.status == 8): 154 | #print("self.status == 8") 155 | if (ch == 0x55): 156 | self.buffer.append(ch) 157 | self.status = 9 158 | else: 159 | logging.warning("invalid Packet (status=4)") 160 | self.status = 0 161 | return [] 162 | 163 | elif (self.status == 9): 164 | #print("self.status == 9") 165 | if (ch == 0x55): 166 | self.buffer.append(ch) 167 | self.status = 9 168 | if (len(self.buffer) == 21): 169 | logging.debug("self.buffer={}".format(self.buffer)) 170 | self.status = 0 171 | return self.buffer 172 | else: 173 | logging.warning("invalid Packet (status=9)") 174 | self.status = 0 175 | else: 176 | logging.warning("invalid Packet (status=3)") 177 | self.status = 0 178 | return [] 179 | 180 | # This is old version 181 | def _setTransmitMsg(id, rtr, ext, len, buf): 182 | sendData = [0xAA, 0xAA, 0x78, 0x56, 0x34, 0x12, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3F, 0x55, 0x55, 0xF0] 183 | idStr = "{:08x}".format(id) 184 | logging.debug("idStr={}".format(idStr)) 185 | if (ext == 0): 186 | sendData[2] = int(idStr[6:8],16) 187 | sendData[3] = int(idStr[4:6],16) & 0x7 188 | sendData[4] = 0 189 | sendData[5] = 0 190 | logging.debug("id={:02x}{:02x}".format(sendData[2], sendData[3])) 191 | else: 192 | sendData[2] = int(idStr[6:8],16) 193 | sendData[3] = int(idStr[4:6],16) 194 | sendData[4] = int(idStr[2:4],16) 195 | sendData[5] = int(idStr[0:2],16) & 0x1F 196 | logging.debug("id={:02x}{:02x}".format(sendData[2], sendData[3])) 197 | for x in range(len): 198 | sendData[x+6] = buf[x] 199 | sendData[14] = len # Frame Data Length 200 | sendData[16] = ext # Standard/Extended frame 201 | sendData[17] = rtr # Data/Request frame 202 | sendData[18] = sum(sendData[2:18]) & 0xff 203 | print("old:crc={:2x}".format(sendData[18])) 204 | print("old:sendData={}".format(sendData)) 205 | return sendData 206 | 207 | USART_FRAMECTRL = 0xA5 208 | USART_FRAMEHEAD = 0xAA 209 | USART_FRAMETAIL = 0x55 210 | 211 | def insertCtrl(buffer, ch): 212 | result = buffer 213 | #print("insertCtrl ch={:02x}".format(ch)) 214 | if (ch == USART_FRAMECTRL or ch == USART_FRAMEHEAD or ch == USART_FRAMETAIL): 215 | result.append(USART_FRAMECTRL) 216 | return result 217 | 218 | def setFilterMsg(filterIndex, filterId, filterMask, frameType, filterStatus): 219 | #sendData = [0xAA, 0xAA, 0xEx, 0xFE, 0xFF, 0x01, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3F, 0x55, 0x55, 0xF0] 220 | #print("sendData={}".format(sendData)) 221 | 222 | if (filterIndex > 15): 223 | logging.waring("filterIndex {} is too large.".format(filterIndex)) 224 | return [] 225 | 226 | if (frameType.lower() != "std" and frameType.lower() != "ext"): 227 | logging.waring("frameType {} is invalid.".format(frameType)) 228 | return [] 229 | 230 | if (filterStatus.lower() != "enable" and filterStatus.lower() != "disable"): 231 | logging.waring("filterStatus {} is invalid.".format(filterStatus)) 232 | return [] 233 | 234 | sendData = [0xAA, 0xAA] 235 | id = 0xE0 + filterIndex 236 | sendData.append(id) 237 | crc = id 238 | id = 0xFE 239 | crc = crc + id 240 | sendData.append(id) 241 | id = 0xFF 242 | crc = crc + id 243 | sendData.append(id) 244 | id = 0x01 245 | crc = crc + id 246 | sendData.append(id) 247 | 248 | idStr = "{:08x}".format(filterId) 249 | if (frameType.lower() == "std"): 250 | id = int(idStr[6:8],16) 251 | sendData = insertCtrl(sendData, id) 252 | sendData.append(id) 253 | crc = crc + id 254 | id = int(idStr[4:6],16) & 0x7 255 | sendData = insertCtrl(sendData, id) 256 | sendData.append(id) 257 | crc = crc + id 258 | sendData.append(0) 259 | id = 0 # Disable 260 | if (filterStatus.lower() == "enable"): id = 0x80 # Enable 261 | sendData.append(id) 262 | crc = crc + id 263 | logging.debug("id={:02x}{:02x}".format(sendData[2], sendData[3])) 264 | else: 265 | id = int(idStr[6:8],16) 266 | sendData = insertCtrl(sendData, id) 267 | sendData.append(id) 268 | crc = crc + id 269 | id = int(idStr[4:6],16) 270 | sendData = insertCtrl(sendData, id) 271 | sendData.append(id) 272 | crc = crc + id 273 | id = int(idStr[2:4],16) 274 | sendData = insertCtrl(sendData, id) 275 | sendData.append(id) 276 | crc = crc + id 277 | id = int(idStr[0:2],16) & 0x1F 278 | if (filterStatus.lower() == "enable"): id = 0x80 # Enable 279 | sendData = insertCtrl(sendData, id) 280 | sendData.append(id) 281 | crc = crc + id 282 | logging.debug("id={:02x}{:02x}".format(sendData[2], sendData[3])) 283 | 284 | filterMaskStr = "{:08x}".format(filterMask) 285 | mask = int(filterMaskStr[6:8],16) 286 | sendData = insertCtrl(sendData, mask) 287 | sendData.append(mask) 288 | crc = crc + mask 289 | mask = int(filterMaskStr[4:6],16) 290 | sendData = insertCtrl(sendData, mask) 291 | sendData.append(mask) 292 | crc = crc + mask 293 | mask = int(filterMaskStr[2:4],16) 294 | sendData = insertCtrl(sendData, mask) 295 | sendData.append(mask) 296 | crc = crc + mask 297 | mask = int(filterMaskStr[0:2],16) & 0x1F 298 | if (frameType.lower() == "ext"): 299 | mask = mask + 0x40 # Extended 300 | sendData = insertCtrl(sendData, mask) 301 | sendData.append(mask) 302 | crc = crc + mask 303 | 304 | len = 8 305 | sendData.append(len) # Frame Data Length 306 | crc = crc + len 307 | req = 0xFF 308 | sendData.append(req) 309 | crc = crc + req 310 | ext = 1 311 | sendData.append(ext) # Standard/Extended frame 312 | crc = crc + ext 313 | rtr = 0 # Set 314 | sendData.append(rtr) # Set/Read 315 | crc = crc + rtr 316 | crc = crc & 0xff 317 | logging.debug("crc={:2x}".format(crc)) 318 | sendData = insertCtrl(sendData, crc) 319 | sendData.append(crc) 320 | sendData.append(0x55) 321 | sendData.append(0x55) 322 | logging.debug("sendData={}".format(sendData)) 323 | return sendData 324 | 325 | def setTransmitMsg(id, rtr, ext, len, buf): 326 | #sendData = [0xAA, 0xAA, 0x78, 0x56, 0x34, 0x12, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3F, 0x55, 0x55, 0xF0] 327 | #print("sendData={}".format(sendData)) 328 | 329 | sendData = [0xAA, 0xAA] 330 | idStr = "{:08x}".format(id) 331 | logging.debug("idStr={}".format(idStr)) 332 | crc = 0 333 | if (ext == 0): 334 | id = int(idStr[6:8],16) 335 | sendData = insertCtrl(sendData, id) 336 | sendData.append(id) 337 | crc = crc + id 338 | id = int(idStr[4:6],16) & 0x7 339 | sendData = insertCtrl(sendData, id) 340 | sendData.append(id) 341 | crc = crc + id 342 | sendData.append(0) 343 | sendData.append(0) 344 | logging.debug("id={:02x}{:02x}".format(sendData[2], sendData[3])) 345 | else: 346 | id = int(idStr[6:8],16) 347 | sendData = insertCtrl(sendData, id) 348 | sendData.append(id) 349 | crc = crc + id 350 | id = int(idStr[4:6],16) 351 | sendData = insertCtrl(sendData, id) 352 | sendData.append(id) 353 | crc = crc + id 354 | id = int(idStr[2:4],16) 355 | sendData = insertCtrl(sendData, id) 356 | sendData.append(id) 357 | crc = crc + id 358 | id = int(idStr[0:2],16) & 0x1F 359 | sendData = insertCtrl(sendData, id) 360 | sendData.append(id) 361 | crc = crc + id 362 | logging.debug("id={:02x}{:02x}".format(sendData[2], sendData[3])) 363 | for x in range(len): 364 | sendData = insertCtrl(sendData, buf[x]) 365 | sendData.append(buf[x]) 366 | crc = crc + buf[x] 367 | if (len < 8): 368 | for x in range(8-len): 369 | sendData.append(0) 370 | sendData.append(len) # Frame Data Length 371 | crc = crc + len 372 | sendData.append(0) 373 | sendData.append(ext) # Standard/Extended frame 374 | crc = crc + ext 375 | sendData.append(rtr) # Data/Request frame 376 | crc = crc + rtr 377 | crc = crc & 0xff 378 | logging.debug("crc={:2x}".format(crc)) 379 | sendData = insertCtrl(sendData, crc) 380 | sendData.append(crc) 381 | sendData.append(0x55) 382 | sendData.append(0x55) 383 | #sendData.append(0xF0) 384 | logging.debug("sendData={}".format(sendData)) 385 | return sendData 386 | 387 | # https://qiita.com/mml/items/ccc66ecc46d8299b3346 388 | def sendMsg( buf ): 389 | while True: 390 | if ser.out_waiting == 0: 391 | break 392 | for b in buf: 393 | a = struct.pack( "B", b ) 394 | ser.write(a) 395 | ser.flush() 396 | 397 | def initId(): 398 | data = [0xAA, 0xAA, 0xFF, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0xFF, 0x01, 0x00, 0x66, 0x55, 0x55] 399 | 400 | data[18]=sum(data[2:18]) & 0xFF 401 | #print("data[18]={:02x}".format(data[18])) 402 | sendMsg(data) 403 | 404 | 405 | def readInfo(id): 406 | data = [0xAA, 0xAA, 0xE0, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x66, 0x55, 0x55] 407 | idStr = "{:08x}".format(id) 408 | #print("idStr={}".format(idStr)) 409 | data[2] = int(idStr[6:8],16) 410 | data[3] = int(idStr[4:6],16) 411 | data[4] = int(idStr[2:4],16) 412 | data[5] = int(idStr[0:2],16) 413 | data[18]=sum(data[2:18]) & 0xFF 414 | #print("data={:02x}{:02x}{:02x}{:02x}".format(data[2], data[3], data[4], data[5])) 415 | sendMsg(data) 416 | 417 | 418 | def readFilter(index): 419 | data = [0xAA, 0xAA, 0xE0, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x66, 0x55, 0x55] 420 | 421 | #print("index={}".format(index)) 422 | data[2] = 0xE0 + index 423 | data[18]=sum(data[2:18]) & 0xFF 424 | #print("data4[18]={:2x}".format(data4[18])) 425 | sendMsg(data) 426 | 427 | def setSpeed(speed): 428 | logging.info("speed={}".format(speed)) 429 | speed1000 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0x40, 0x42, 0x0F, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0x66, 0x55, 0x55] 430 | 431 | speed800 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0x00, 0x35, 0x0C, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0x16, 0x55, 0x55] 432 | 433 | speed500 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0x20, 0xA1, 0x07, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0x9D, 0x55, 0x55] 434 | 435 | speed400 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0x80, 0x1A, 0x06, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0x75, 0x55, 0x55] 436 | 437 | speed250 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0x90, 0xD0, 0x03, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0x38, 0x55, 0x55] 438 | 439 | speed125 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0x48, 0xE8, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0x06, 0x55, 0x55] 440 | 441 | speed100 = [0xAA, 0xAA, 0xD0, 0xFE, 0xFF, 0x01, 0xA0, 0x86, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x04, 0xFF, 0x01, 0x00, 0xFC, 0x55, 0x55] 442 | 443 | 444 | if (speed == 1000000): 445 | sendMsg(speed1000) 446 | return True 447 | elif (speed == 800000): 448 | sendMsg(speed800) 449 | return True 450 | elif (speed == 500000): 451 | sendMsg(speed500) 452 | return True 453 | elif (speed == 400000): 454 | sendMsg(speed400) 455 | return True 456 | elif (speed == 250000): 457 | sendMsg(speed250) 458 | return True 459 | elif (speed == 125000): 460 | sendMsg(speed125) 461 | return True 462 | elif (speed == 100000): 463 | sendMsg(speed100) 464 | return True 465 | else: 466 | return False 467 | 468 | 469 | def loggingFrame(header, buffer): 470 | message = header 471 | message = message + "[" 472 | for x in range(len(buffer)): 473 | message = message + "{:02x}".format(buffer[x]).upper() 474 | if (x != len(buffer)-1): message = message + " " 475 | message = message + "]" 476 | logging.info(message) 477 | 478 | def printFrame(buffer): 479 | logging.debug("buffer={}".format(buffer)) 480 | if (buffer[16] == 0): # Standard frame 481 | receiveId = (buffer[3] << 8) + buffer[2] 482 | else: # Extended frame 483 | receiveId = (buffer[5] << 24) + (buffer[4] << 16) + (buffer[3] << 8) + buffer[2] 484 | logging.debug("receiveId=0x{:X}".format(receiveId)) 485 | if (buffer[15] == 0xFF): 486 | if (receiveId == 0x01fffed0): 487 | message = "BAUDRATE ID: 0x" 488 | elif (receiveId == 0x01fffff0): 489 | message = "CPUINFO0 ID: 0x" 490 | elif (receiveId == 0x01fffff1): 491 | message = "CPUINFO1 ID: 0x" 492 | elif (receiveId == 0x01ffffe0): 493 | message = "VERSION ID: 0x" 494 | elif (receiveId == 0x01fffeff): 495 | message = "INIT ID: 0x" 496 | elif (receiveId == 0x01fffeb0): 497 | message = "ABOM ID: 0x" 498 | elif (receiveId == 0x01fffea0): 499 | message = "ART ID: 0x" 500 | elif ((receiveId & 0x01fffff0) == 0x01fffee0): 501 | index = receiveId & 0xf 502 | message = "FILTER{:02d} ID: 0x".format(index) 503 | message = message + "{:02x}".format(buffer[5]).upper() 504 | message = message + "{:02x}".format(buffer[4]).upper() 505 | message = message + "{:02x}".format(buffer[3]).upper() 506 | message = message + "{:02x}".format(buffer[2]).upper() 507 | message = message + " DLC: " 508 | message = message + "{:01n}".format(buffer[14]) 509 | message = message + " Data:" 510 | for x in range(buffer[14]): 511 | #print ("x={}".format(x)) 512 | message = message + " 0x" 513 | message = message + "{:02x}".format(buffer[x+6]).upper() 514 | else: 515 | if (buffer[16] == 0): 516 | message = "Standard ID: 0x" 517 | message = message + "{:01x}".format(buffer[3]).upper() 518 | message = message + "{:02x}".format(buffer[2]).upper() 519 | message = message + " DLC: " 520 | else: 521 | message = "Extended ID: 0x" 522 | message = message + "{:02x}".format(buffer[5]).upper() 523 | message = message + "{:02x}".format(buffer[4]).upper() 524 | message = message + "{:02x}".format(buffer[3]).upper() 525 | message = message + "{:02x}".format(buffer[2]).upper() 526 | message = message + " DLC: " 527 | message = message + "{:01n}".format(buffer[14]) 528 | message = message + " Data:" 529 | if (buffer[17] == 0): 530 | for x in range(buffer[14]): 531 | #print ("x={}".format(x)) 532 | message = message + " 0x" 533 | message = message + "{:02x}".format(buffer[x+6]).upper() 534 | else: 535 | message = message + " REMOTE REQUEST FRAME" 536 | print(message) 537 | return receiveId 538 | 539 | 540 | format="%(asctime)s [%(filename)s:%(lineno)d] %(levelname)-8s %(message)s" 541 | #logging.basicConfig(level=logging.DEBUG, format=format) 542 | #logging.basicConfig(level=logging.WARNING, format=format) 543 | 544 | parser = argparse.ArgumentParser() 545 | parser.add_argument("-p", "--port", help="open port") 546 | parser.add_argument("-s", "--speed", help="can bit rate", type=int) 547 | parser.add_argument("-u", "--udp", help="UDP receive port", type=int) 548 | parser.add_argument("-l", "--log", dest="logLevel", choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], help="Set the logging level") 549 | 550 | args = parser.parse_args() 551 | device = "/dev/ttyUSB0" 552 | speed = 500000 553 | udpPort = 8200 554 | 555 | if args.port: 556 | print("args.port={}".format(args.port)) 557 | device = args.port 558 | if args.speed: 559 | print("args.speed={}".format(args.speed)) 560 | speed = args.speed 561 | if args.udp: 562 | print("args.udp={}".format(args.udp)) 563 | udpPort = args.udp 564 | if args.logLevel: 565 | level=getattr(logging, args.logLevel) 566 | print("logLevel set to {}".format(level)) 567 | #logging.basicConfig(level=getattr(logging, args.logLevel)) 568 | logging.basicConfig(level=getattr(logging, args.logLevel), format=format) 569 | else: 570 | print("logLevel set to {}".format(logging.WARNING)) 571 | logging.basicConfig(level=logging.WARNING, format=format) 572 | 573 | if (speed != 1000000 and speed != 500000 and speed != 400000 and speed != 250000 and speed != 125000 and speed != 100000): 574 | logging.error("This speed {} is not supported.".format(speed)) 575 | sys.exit() 576 | 577 | ''' 578 | ser = serial.Serial( 579 | port = "/dev/ttyUSB0", 580 | baudrate = 115200, 581 | #parity = serial.PARITY_NONE, 582 | #bytesize = serial.EIGHTBITS, 583 | #stopbits = serial.STOPBITS_ONE, 584 | #timeout = None, 585 | #xonxoff = 0, 586 | #rtscts = 0, 587 | ) 588 | ''' 589 | ser = serial.Serial( 590 | port = device, 591 | baudrate = 115200, 592 | #parity = serial.PARITY_NONE, 593 | #bytesize = serial.EIGHTBITS, 594 | #stopbits = serial.STOPBITS_ONE, 595 | #timeout = None, 596 | #xonxoff = 0, 597 | #rtscts = 0, 598 | ) 599 | 600 | 601 | # Start Timer thread (Timer is not use) 602 | timer = TimerThread(ACTIVE=True, INTERVAL=5) 603 | timer.setDaemon(True) 604 | timer.start() 605 | 606 | # Start UDP Receive hread 607 | #udp = ServerThread(PORT=8200) 608 | udp = ServerThread(PORT=udpPort) 609 | udp.setDaemon(True) 610 | udp.start() 611 | 612 | 613 | buffer = [] 614 | parse = ParseClass() 615 | receiveId = 0x01FFFFFF 616 | 617 | while True: 618 | if (receiveId == 0x01FFFFFF): 619 | initId() 620 | receiveId = 0 621 | elif (receiveId == 0x01FFFEFF): 622 | setSpeed(speed) 623 | receiveId = 0 624 | elif (receiveId == 0x01FFFED0): 625 | readInfo(0x01FFFFE0) 626 | receiveId = 0 627 | elif (receiveId == 0x01FFFFE0): 628 | readInfo(0x01FFFFF0) 629 | receiveId = 0 630 | elif (receiveId == 0x01FFFFF0): 631 | readInfo(0x01FFFFF1) 632 | receiveId = 0 633 | elif (receiveId == 0x01FFFFF1): 634 | readInfo(0x01FFFEB0) 635 | receiveId = 0 636 | elif (receiveId == 0x01FFFEB0): 637 | readInfo(0x01FFFEA0) 638 | receiveId = 0 639 | elif (receiveId == 0x01FFFEA0): 640 | readFilter(0) 641 | receiveId = 0 642 | elif ((receiveId & 0x01FFFFF0) == 0x01FFFEE0): 643 | index = receiveId & 0xf 644 | #print("index={}".format(index)) 645 | if (index != 15): 646 | readFilter(index+1) 647 | receiveId = 0 648 | else: 649 | receiveId = 0xFFFFFFFF 650 | 651 | if timer.timerFlag is True: 652 | #print("timeFlag") 653 | timer.timerFlag = False 654 | """ 655 | sendData = [0xAA, 0xAA, 0x78, 0x56, 0x34, 0x12, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3F, 0x55, 0x55, 0xF0] 656 | sendData[16] =1 # Standard frame 657 | sendData[17] =0 # Data frame 658 | sendData[18] = sum(sendData[2:18]) & 0xff 659 | print("sendData[18]={:2x}".format(sendData[18])) 660 | frameId = 0xF23 661 | frameRequest = 0 662 | frameType = 1 663 | frameLength = 4 664 | frameData = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88] 665 | sendData = setTransmitMsg(frameId, frameRequest, frameType, frameLength, frameData) 666 | sendMsg(sendData) 667 | """ 668 | 669 | if udp.interrupt is True: 670 | logging.info("udp interrupt request={}".format(udp.request)) 671 | if (udp.request == "transmit"): 672 | logging.debug("id={} type={}".format(udp.id, udp.type)) 673 | frameId = int(udp.id, 16) 674 | logging.debug("frameId={:x}".format(frameId)) 675 | if (udp.type == "stddata"): 676 | frameRequest = 0 677 | frameType = 0 678 | frameLength = len(udp.data) 679 | if (udp.type == "extdata"): 680 | frameRequest = 0 681 | frameType = 1 682 | frameLength = len(udp.data) 683 | if (udp.type == "stdremote"): 684 | frameRequest = 1 685 | frameType = 0 686 | frameLength = 0 687 | if (udp.type == "extremote"): 688 | frameRequest = 1 689 | frameType = 1 690 | frameLength = 0 691 | frameData = [] 692 | for x in range(frameLength): 693 | logging.debug("udp.data={}".format(udp.data[x])) 694 | frameData.append(udp.data[x]) 695 | logging.debug("frameData={}".format(frameData)) 696 | sendData = setTransmitMsg(frameId, frameRequest, frameType, frameLength, frameData) 697 | sendMsg(sendData) 698 | logging.info("Transmit={}".format(sendData)) 699 | loggingFrame("Transmit=", sendData) 700 | udp.interrupt = False 701 | 702 | if (udp.request == "filter"): 703 | logging.info("index={} id={} mask={} type={} status={}".format(udp.index, udp.id, udp.mask, udp.type, udp.status)) 704 | filterIndex = int(udp.index) 705 | filterId = int(udp.id,16) 706 | filterMask = int(udp.mask,16) 707 | frameType = udp.type 708 | filterStatus = udp.status 709 | logging.debug("filterIndex={} filterId=0x{:x} filterMask=0x{:x} frameType={} filterStatus={}".format(filterIndex, filterId, filterMask, frameType, filterStatus)) 710 | sendData = setFilterMsg(filterIndex, filterId, filterMask, frameType, filterStatus) 711 | if (len(sendData) > 0): 712 | sendMsg(sendData) 713 | logging.info("Mask={}".format(sendData)) 714 | loggingFrame("Mask=", sendData) 715 | udp.interrupt = False 716 | 717 | if ser.in_waiting > 0: 718 | recv_data = ser.read(1) 719 | #print(type(recv_data)) 720 | a = struct.unpack_from("B",recv_data ,0) 721 | #print( a ) 722 | #print(type(a)) 723 | #print( a[0] ) 724 | b = a[0] 725 | #print(type(b)) 726 | #logging.debug("b={:02x}".format(b)) 727 | 728 | buffer = parse.parseData(b) 729 | if (len(buffer) > 0): 730 | #logging.info("Receive={}".format(buffer)) 731 | loggingFrame("Receive=", buffer) 732 | #print("receiveId={:x}".format(receiveId)) 733 | if (receiveId == 0xFFFFFFFF): 734 | printFrame(buffer) 735 | else: 736 | receiveId = printFrame(buffer) 737 | 738 | 739 | --------------------------------------------------------------------------------