成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Python實現CAN報文轉換工具教程

瀏覽:93日期:2022-07-26 13:01:46

一、CAN報文簡介

CAN是控制器局域網絡(Controller Area Network, CAN)的簡稱,是由以研發和生產汽車電子產品著稱的德國BOSCH公司開發的,并最終成為國際標準(ISO 11898),是國際上應用最廣泛的現場總線之一。 在北美和西歐,CAN總線協議已經成為汽車計算機控制系統和嵌入式工業控制局域網的標準總線,并且擁有以CAN為底層協議專為大型貨車和重工機械車輛設計的J1939協議。

CAN總線以報文為單位進行數據傳送。CAN報文按照幀格式可分為標準幀和擴展幀,標準幀是具有11位標識符的CAN幀,擴展幀是具有29位標識符的CAN幀。按照幀類型可分為:1.從發送節點向其它節點發送數據;2.遠程幀:向其它節點請求發送具有同一識別符的數據幀;3.錯誤幀:指明已檢測到總線錯誤;4.過載幀:過載幀用以在數據幀(或遠程幀)之間提供一附加的延時。共有兩種編碼格式:Intel格式和Motorola格式,在編碼優缺點上,Motorola格式與Intel格式并沒有孰優孰劣之分,只不過根據設計者的習慣,由用戶自主選擇罷了。當然,對于使用者來講,在進行解析之前,就必須要知道編碼的格式是哪一種,否則,就不能保證正確地解析信號的含義。以下就以8位字節編碼方式的CAN總線信號為例,詳細分析一下兩者之間的區別。

Intel編碼格式

當一個信號的數據長度不超過1個字節(8位)并且信號在一個字節內實現(即該信號沒有跨字節實現):該信號的高位(S_msb)將被放在該字節的高位,信號的低位(S_lsb)將被放在該字節的低位。

當一個信號的數據長度超過1個字節(8位)或者數據長度不超過一個字節但是采用跨字節方式實現時:該信號的高位(S_msb)將被放在高字節(MSB)的高位,信號的低位(S_lsb)將被放在低字節(LSB)的低位。

Motorola編碼格式

當一個信號的數據長度不超過1個字節(8位)并且信號在一個字節內實現(即該信號沒有跨字節實現):該信號的高位(S_msb)將被放在該字節的高位,信號的低位(S_lsb)將被放在該字節的低位。

當一個信號的數據長度超過1個字節(8位)或者數據長度不超過一個字節但是采用跨字節方式實現時:該信號的高位(S_msb)將被放在低字節(MSB)的高位,信號的低位(S_lsb)將被放在高字節(LSB)的低位。

可以看出,當一個信號的數據長度不超過1Byte時,Intel與Motorola兩種格式的編碼結果沒有什么不同,完全一樣。當信號的數據長度超過1Byte時,兩者的編碼結果出現了明顯的不同。

二、CAN報文轉換工具需求分析

1、 支持標準幀的CAN報文的轉換,擴展幀暫不支持

2、 CAN報文支持Intel、motorola兩種編碼,先支持motorola格式,后期追加Intel格式

3、 工具具有一定的容錯處理能力、報告生成能力

4、 制定統一格式,方便使用者修改測試腳本

5、增加交互模式,鍵盤輸入,控制臺輸出;例如:

提示語:startBit:length:minValue:maxValue:setValue

輸入:35:1:0:1:1

或:35:1:::1

控制臺輸出:00 00 00 00 08 00 00 00

Intel和Motorola編碼舉例:

Python實現CAN報文轉換工具教程

三、交互模式

代碼如下:

import sysprint('----------------歡迎使用CAN報文轉換工具交互模式----------------')print('請輸入CAN信號,格式為:startBit:length:minValue:maxValue:setValue')print('例如:32:1:0:1:1')print('或者省略minValue和maxValue:35:1:::1')print('信號輸入結束請再按一次回車') #十進制轉換成二進制listdef octToBin(octNum, bit): while(octNum != 0): bit.append(octNum%2) octNum = int(octNum/2) for i in range(64-len(bit)): bit.append(0) sig = []startBit = []length = []setValue = []#輸入CAN信號while True: input_str = input() if not len(input_str): break if(input_str.count(':')<4): print('輸入格式錯誤,參數缺少setValue,請重新輸入!') continue if(input_str.split(':')[4]==''): print('setValue參數不能為空,請重新輸入!') continue sig.append(input_str)#解析CAN信號for i in range(len(sig)): startBit.append(int(sig[i].split(':')[0])) length.append(int(sig[i].split(':')[1])) setValue.append(int(sig[i].split(':')[4]))#CAN數組存放CAN報文值 CAN = []for i in range(64): CAN.append(-1)for i in range(len(startBit)): #長度超過1Byte的情況,暫不支持 if(length[i]>16): print('CAN信號長度超過2Byte,暫不支持!!!') sys.stdin.readline() sys.exit() #長度未超過1Byte的情況且未跨字節的信號 if((startBit[i]%8 + length[i])<=8): for j in range(length[i]): bit = [] #setValue的二進制值按字節位從低到高填 octToBin(setValue[i],bit) #填滿字節長度值 if(CAN[startBit[i]+j]==-1): CAN[startBit[i]+j] = bit[j] #字節存在沖突 else: print(sig[i] + '字節位存在沖突,生成CAN報文失?。。?!') sys.stdin.readline() sys.exit() #跨字節的信號 else: #高位位數和低位位數 highLen = 8 - startBit[i]%8 lowLen = length[i] - highLen bit = [] #setValue的二進制值按字節位從低到高填 octToBin(setValue[i],bit) #先填進信號的高位 for j1 in range(highLen): if(CAN[startBit[i]+j1]==-1): CAN[startBit[i]+j1] = bit[j1] #字節存在沖突 else: print(sig[i] + '字節位存在沖突,生成CAN報文失?。。?!') sys.stdin.readline() sys.exit() #再填進信號的低位 for j2 in range(lowLen): if(CAN[(int(startBit[i]/8)-1)*8+j2]==-1): CAN[(int(startBit[i]/8)-1)*8+j2] = bit[highLen+j2] #字節存在沖突 else: print(sig[i] + '字節位存在沖突,生成CAN報文失敗!?。?) sys.stdin.readline() sys.exit()#剩余位默認值設為0for i in range(64): if(CAN[i]==-1): CAN[i] = 0#----------------將二進制list每隔8位轉換成十六進制輸出----------------#其中,map()將list中的數字轉成字符串,按照Motorola格式每隔8位采用了逆序# ’’.join()將二進制list轉換成二進制字符串,int()將二進制字符串轉換成十進制#hex()再將十進制轉換成十六進制,upper()轉換成大寫,兩個lstrip()將'0X'刪除,#zfill()填充兩位,輸出不換行,以空格分隔print(hex(int(’’.join(map(str,CAN[7::-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[15:7:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[23:15:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[31:23:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[39:31:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[47:39:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[55:47:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='')print(hex(int(’’.join(map(str,CAN[63:55:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2))

運行截圖:

Python實現CAN報文轉換工具教程

錯誤提示:

Python實現CAN報文轉換工具教程

四、配置項模式

配置文件如下:

##注釋::start#編碼格式:0=Intel;1=MotorolaencodeType=1#幀格式:0=標準幀;1=擴展幀;canMode=0#幀類型:0=數據幀;...canType=0#默認初始值(0~1)defaultValue=0#MSG定義msgName=BCM_FrP01msgID=0x2CD#長度(BYTE)msgLength=8#signal定義#sigName=name:startBit:length:minValue:maxValue:setValue#sigName=ReverseSw:25:6:0:1:13#sigName=Trunk_BackDoor_Sts:33:2:0:1:2#sigName=DRVUnlockState:37:2:0:1:3#sigName=HeadLampLowBeam:40:8:0:1:60#sigName=HoodStatus:51:1:0:1:0#sigName=HeadLampHighBeam:52:1:0:1:0#sigName=RLDoorStatus:59:1:0:1:0#sigName=RRDoorStatus:58:1:0:1:0#sigName=PsgDoorStatus:57:2:0:1:0sigName=One:0:8:0:255:165sigName=Two:24:12:0:4095:1701sigName=Three:54:5:0:31:25::end::start#編碼格式:0=Intel;1=MotorolaencodeType=1#幀格式:0=標準幀;1=擴展幀;canMode=0#幀類型:0=數據幀;...canType=0#默認初始值(0~1)defaultValue=0#MSG定義msgName=BCM_FrPmsgID=0x2CD#長度(BYTE)msgLength=8#signal定義#sigName=name:startBit:length:minValue:maxValue:setValue#sigName=ReverseSw:25:6:0:1:13#sigName=Trunk_BackDoor_Sts:33:2:0:1:2#sigName=DRVUnlockState:37:2:0:1:3#sigName=HeadLampLowBeam:40:8:0:1:60#sigName=HoodStatus:51:1:0:1:0#sigName=HeadLampHighBeam:52:1:0:1:0#sigName=RLDoorStatus:59:1:0:1:0#sigName=RRDoorStatus:58:1:0:1:0#sigName=PsgDoorStatus:57:2:0:1:0sigName=One:35:1:0:1:1::end

代碼如下:

#!/usr/bin/pythondefaultValue = 0sigName = []startBit = []length = []minValue = []maxValue = []setValue = []#CAN數組存放CAN報文值CAN = []logFile = open('log.txt','w')def parseConfig(): config = open('Config.txt','r') count = 0 isError = False for line in config: line = line.strip() #注釋 if(line.find('#')>=0): continue #開始標記 elif(line.find('::start')>=0): count = count + 1 isError = False if(count>1): sigName.clear() startBit.clear() length.clear() setValue.clear() continue else: continue elif(isError == True): continue #編碼格式 elif(line.find('encodeType')>=0): encodeType = line.split('=')[1] if(encodeType != '1'): isError = True print(str(count) + '. CAN報文生成失?。。?!目前僅支持Motorola編碼格式,暫不支持Intel編碼格式!') logFile.write('%d. CAN報文生成失?。。。∧壳皟H支持Motorola編碼格式,暫不支持Intel編碼格式!n' % count) continue #幀格式 elif(line.find('canMode')>=0): canMode = line.split('=')[1] if(canMode != '0'): isError = True print(str(count) + '. CAN報文生成失?。。。∧壳皟H支持標準幀,暫不支持擴展幀!') logFile.write('%d. CAN報文生成失?。。?!目前僅支持標準幀,暫不支持擴展幀!n' % count) continue #幀類型 elif(line.find('canType')>=0): canType = line.split('=')[1] if(canType != '0'): isError = True print(str(count) + '. CAN報文生成失?。。?!目前僅支持數據幀,暫不支持其他幀!') logFile.write('%d. CAN報文生成失?。。。∧壳皟H支持數據幀,暫不支持其他幀!n' % count) continue #默認初始值 elif(line.find('defaultValue')>=0): global defaultValue defaultValue = int(line.split('=')[1]) #MSG名稱 elif(line.find('msgName')>=0): msgName = line.split('=')[1] #MSGID elif(line.find('msgID')>=0): msgID = line.split('=')[1] #MSG長度 elif(line.find('msgLength')>=0): msgLength = line.split('=')[1] #signal定義 elif(line.find('sigName')>=0): sigName.append(line.split(':')[0].split('=')[1]) startBit.append(int(line.split(':')[1])) length.append(int(line.split(':')[2])) #minValue.append(int(line.split(':')[3])) #maxValue.append(int(line.split(':')[4])) setValue.append(int(line.split(':')[5])) elif(line.find('::end')>=0): rV,errMsg = getCANMessage() if(rV == '-1'): isError = True print(str(count) + '. CAN報文生成失?。。。? + errMsg) logFile.write('%d. CAN報文生成失?。。?!%sn' % (count,errMsg)) continue print(str(count) + '. CAN報文生成成功!??!') logFile.write('%d. CAN報文生成成功?。?!n' % count) #----------------------------輸出標題信息---------------------------- print('msgNamettmsgIDttmsgLenttmsgData') logFile.write('msgNamettmsgIDttmsgLenttmsgDatan') if(len(msgName)<8): print(msgName + 'tt',end='') logFile.write('%stt' % msgName) else: print(msgName + 't',end='') logFile.write('%st' % msgName) print(msgID + 'tt',end='') logFile.write('%stt' % msgID) print(msgLength + 'tt',end='') logFile.write('%stt' % msgLength) #----------------將二進制list每隔8位轉換成十六進制輸出---------------- #其中,map()將list中的數字轉成字符串,按照Motorola格式每隔8位采用了逆序 # ’’.join()將二進制list轉換成二進制字符串,int()將二進制字符串轉換成十進制 #hex()再將十進制轉換成十六進制,upper()轉換成大寫,兩個lstrip()將'0X'刪除, #zfill()填充兩位,輸出不換行,以空格分隔 print(hex(int(’’.join(map(str,CAN[7::-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[15:7:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[23:15:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[31:23:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[39:31:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[47:39:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[55:47:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2) + ' ',end='') print(hex(int(’’.join(map(str,CAN[63:55:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[7::-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[15:7:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[23:15:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[31:23:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[39:31:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[47:39:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%s ' % hex(int(’’.join(map(str,CAN[55:47:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) logFile.write('%sn' % hex(int(’’.join(map(str,CAN[63:55:-1])),2)).upper().lstrip('0').lstrip('X').zfill(2)) config.close() #十進制轉換成二進制list def octToBin(octNum, bit): while(octNum != 0): bit.append(octNum%2) octNum = int(octNum/2) for i in range(64-len(bit)): bit.append(0) #獲取CAN報文值def getCANMessage(): CAN.clear() for i in range(64): CAN.append(-1) for i in range(len(startBit)): #長度超過1Byte的情況,暫不支持 if(length[i]>16): errMsg = ' CAN信號長度超過2Byte,暫不支持?。。? #print(sigName[i] + errMsg) return '-1',errMsg #長度未超過1Byte的情況且未跨字節的信號 if((startBit[i]%8 + length[i])<=8): for j in range(length[i]): bit = [] #setValue的二進制值按字節位從低到高填 octToBin(setValue[i],bit) #填滿字節長度值 if(CAN[startBit[i]+j]==-1): CAN[startBit[i]+j] = bit[j] #字節存在沖突 else: errMsg = ' 字節位存在沖突,生成CAN報文失?。。?!' #print(sigName[i] + errMsg) return '-1',errMsg #跨字節的信號 else: #高位位數和低位位數 highLen = 8 - startBit[i]%8 lowLen = length[i] - highLen bit = [] #setValue的二進制值按字節位從低到高填 octToBin(setValue[i],bit) #先填進信號的高位 for j1 in range(highLen): if(CAN[startBit[i]+j1]==-1): CAN[startBit[i]+j1] = bit[j1] #字節存在沖突 else: errMsg = ' 字節位存在沖突,生成CAN報文失敗?。?!' #print(sigName[i] + errMsg) return '-1',errMsg #再填進信號的低位 for j2 in range(lowLen): if(CAN[(int(startBit[i]/8)-1)*8+j2]==-1): CAN[(int(startBit[i]/8)-1)*8+j2] = bit[highLen+j2] #字節存在沖突 else: errMsg = ' 字節位存在沖突,生成CAN報文失敗?。?!' #print(sigName[i] + errMsg) return '-1',errMsg #剩余位設為默認值 for i in range(64): if(CAN[i]==-1): CAN[i] = defaultValue #若無錯誤則返回正確值 return '0','success!' if __name__ == '__main__': #調用parseConfig()函數開始執行程序 parseConfig()

運行結果:

1. CAN報文生成成功?。?!msgNamemsgIDmsgLenmsgDataBCM_FrP010x2CD8A5 00 06 A5 00 06 40 002. CAN報文生成成功!??!msgNamemsgIDmsgLenmsgDataBCM_FrP0x2CD800 00 00 00 08 00 00 00

以上這篇Python實現CAN報文轉換工具教程就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Python 編程
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
三级久久三级久久久| 在线观看网站黄不卡| 亚洲精品乱码久久久久久蜜桃麻豆| 国产精品亚洲欧美| 日韩av一区二区三区四区| 国产一区自拍视频| 中文字幕视频一区| 在线观看日韩毛片| 色94色欧美sute亚洲13| 一个色在线综合| 激情欧美日韩一区| 亚洲欧洲色图综合| 欧美午夜国产| 久久久久久久久99精品| 亚洲va国产va欧美va观看| 亚洲黑丝在线| 欧美日韩国产欧美日美国产精品| 1024亚洲合集| 亚洲人妖在线| 中文字幕欧美区| 国产综合久久久久久久久久久久| 亚洲影音一区| 国产精品色噜噜| 成人av在线播放网址| 欧美在线观看视频一区二区三区 | 欧美精品日韩一本| 午夜视频一区二区| 亚洲视频播放| 中文字幕亚洲一区二区va在线| 成人av在线电影| 欧美人xxxx| 美女脱光内衣内裤视频久久网站 | 亚洲成人www| 国产主播精品| 欧美一激情一区二区三区| 日韩黄色在线观看| 亚洲色诱最新| 亚洲欧美在线视频观看| 97国产精品videossex| 欧美一卡二卡在线| 日日夜夜精品视频免费| 亚洲一区二区毛片| 亚洲天堂免费在线观看视频| 91麻豆免费在线观看| 欧美一区二区三区电影| 久久91精品久久久久久秒播| 久久久久久黄| 亚洲一区二区三区视频在线播放 | 亚洲精品九九| 亚洲欧洲av一区二区三区久久| 91亚洲男人天堂| 欧美α欧美αv大片| 国产高清精品网站| 欧美日韩成人一区| 乱一区二区av| 在线影视一区二区三区| 亚洲v日本v欧美v久久精品| 一本久道久久综合狠狠爱| 亚洲少妇最新在线视频| 黑人一区二区| 成人免费在线播放视频| 99热这里只有成人精品国产| 曰韩精品一区二区| 国产色综合网| 亚洲综合色网站| 免费一级欧美片在线播放| 亚洲午夜羞羞片| 一本久久a久久精品亚洲| 亚洲男人天堂av网| 亚洲午夜一级| 中文字幕在线播放不卡一区| 国产精品啊啊啊| 日本一区二区三区在线不卡| 91浏览器入口在线观看| 国产欧美一区二区精品仙草咪| 午夜久久99| 久久亚洲一级片| 92国产精品观看| 久久久久久日产精品| 色综合天天综合给合国产| 欧美国产一区在线| 精品动漫3d一区二区三区免费版 | 日韩一区二区三区电影在线观看 | 欧美日韩在线播| 国产在线播放一区二区三区| 91精品婷婷国产综合久久| 国产成人欧美日韩在线电影| 久久综合色天天久久综合图片| 99亚偷拍自图区亚洲| 国产色产综合产在线视频| 亚洲欧美综合国产精品一区| 国产农村妇女精品| 99精品国产福利在线观看免费 | 一区二区三区四区激情| 国产日韩欧美| 亚洲综合激情网| 久久久成人网| 午夜影视日本亚洲欧洲精品| 日韩欧美中文字幕精品| 午夜精品一区二区三区四区| 亚洲精品国产第一综合99久久| 久久激情中文| 精品一区二区三区在线视频| 日韩精品一区国产麻豆| 欧美国产激情| 国产精品福利一区| 久久xxxx精品视频| 国产原创一区二区| 久久网站最新地址| 亚洲人久久久| 理论电影国产精品| www日韩大片| 亚洲精品一区二区三| 日韩精彩视频在线观看| 91精品国产福利| 欧美日韩三区| 日韩精品电影在线观看| 日韩午夜激情免费电影| 午夜天堂精品久久久久| 午夜久久久久久| 欧美日韩不卡一区二区| 女人天堂亚洲aⅴ在线观看| 一区二区在线观看av| 欧美在线影院一区二区| 99久久婷婷国产综合精品电影 | 九一九一国产精品| 久久久av毛片精品| 国产模特精品视频久久久久| 国产精品18久久久久久久网站| 国产精品久久久久久久岛一牛影视 | 欧美亚洲国产一卡| 欧美在线1区| 日韩精品视频网| 国产午夜精品在线观看| 久久国产主播| 色综合一区二区| 亚洲第一福利一区| 精品国产乱码久久久久久闺蜜| 国产视频亚洲| 国产a视频精品免费观看| 国产精品社区| 成人动漫av在线| 一区二区三区在线观看网站| 欧美精品v国产精品v日韩精品| 国内在线观看一区二区三区| 裸体歌舞表演一区二区| 成人免费在线播放视频| 欧美日韩中文精品| 在线免费高清一区二区三区| 国产综合久久久久影院| 亚洲欧美另类久久久精品| 欧美日韩国产大片| 亚洲网站啪啪| 久久99热这里只有精品| 国产精品狼人久久影院观看方式| 99vv1com这只有精品| 日本亚洲视频在线| 久久午夜色播影院免费高清| 亚洲一区二区三区欧美| a亚洲天堂av| 日韩电影免费一区| 国产精品久久久久久久久晋中 | 亚洲欧洲韩国日本视频| 色av综合在线| 91视视频在线观看入口直接观看www | 97久久精品人人做人人爽50路| 视频一区欧美精品| 中文字幕欧美三区| 日韩一级高清毛片| 色噜噜偷拍精品综合在线| 国内成+人亚洲| 成人免费观看男女羞羞视频| 亚洲一区二区三区自拍| 精品sm捆绑视频| 欧美视频一区二区三区在线观看| 亚洲视频碰碰| 成人av在线网站| 精品在线观看免费| 亚洲国产综合在线| 中文字幕精品一区二区三区精品| 欧美日韩在线观看一区二区| 亚洲精品1区| 欧美成人一品| 国产成人av影院| 亚洲h精品动漫在线观看| 日本一区二区动态图| 欧美一区二区二区| 欧美午夜电影在线播放| 国产美女在线精品免费观看| 不卡在线观看av| 久久97超碰国产精品超碰| 亚洲成国产人片在线观看| 亚洲免费视频成人| 精品sm在线观看| 日韩一区二区高清| 欧美日本一区二区在线观看| 久久精品国产第一区二区三区最新章节 | 欧美日韩一卡| 99国产一区二区三精品乱码| 韩国精品久久久|