整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          通過MQTT將ESP32-CAM圖像流傳輸?shù)蕉鄠€瀏覽器

          本教程中,您將學習如何使用 MQTT(消息隊列遙測傳輸)從 ESP32-CAM 板上發(fā)布圖像到多個瀏覽器客戶端。這個設(shè)置將使您能夠創(chuàng)建一個類似于實時視頻流的平臺,可以被無限數(shù)量的用戶查看。

          先決條件

          在深入學習之前,請確保您已完成以下先決條件教程:

          • 您的第一個 Xedge32 項目:本教程涵蓋了 ESP32 上運行 Xedge32 的基本設(shè)置和配置說明。
          • 您的第一個 MQTT Lua 程序:本教程介紹了 MQTT 的基礎(chǔ)知識以及如何編寫一個簡單的 Lua 程序來與 MQTT 進行交互。

          通過在這些基礎(chǔ)教程中獲得的知識,您將更好地能夠跟隨本教程。

          通過 MQTT 發(fā)布 ESP32-CAM 圖像

          在 MQTT CAM 代碼中,我們的主要重點是發(fā)布圖像而不訂閱其他事件。這個發(fā)布操作由一個定時器事件管理,根據(jù)指定的間隔發(fā)布圖像。

          設(shè)置定時器

          首先,讓我們創(chuàng)建一個定時器對象。這個定時器將在特定間隔觸發(fā) publishImage 函數(shù)。

          timer = ba.timer(publishImage)

          要與 ESP32 相機進行交互,可以這樣初始化一個相機對象:

          cam = esp32.cam(cfg)

          cfg 參數(shù)代表一個配置表。重要: 確保它與您特定的 ESP32-CAM 模塊的設(shè)置匹配。有關(guān)詳細信息,請參閱 Lua CAM API。

          處理 MQTT 連接狀態(tài)

          要監(jiān)視 MQTT 連接,使用以下回調(diào)函數(shù):

          local function onstatus(type, code, status)
             if "mqtt" == type and "connect" == code and 0 == status.reasoncode then
                timer:set(300, false, true)  -- 每 300 毫秒激活定時器
                return true  -- 接受連接
             end
             timer:cancel()
             return true  -- 繼續(xù)嘗試
          end

          上述函數(shù)在成功建立 MQTT 連接時啟動定時器。如果連接斷開,它會取消定時器,但會繼續(xù)嘗試重新連接。

          通過定時器回調(diào)發(fā)布圖像

          圖像發(fā)布機制的核心是定時器回調(diào)函數(shù) publishImage。這個函數(shù)使用相機對象捕獲圖像,并通過 MQTT 發(fā)布。定時器邏輯支持各種定時器類型。特別是,這個版本作為 Lua 協(xié)程(類似于線程)運行。在這個協(xié)程中,它不斷循環(huán)并休眠,持續(xù)時間由 coroutine.yield(true) 定義。

          function publishImage()
             local busy = false
             while true do
                if mqtt:status() < 2 and not busy then
                   busy = true -- 線程忙碌
                   ba.thread.run(function()
                      local image = cam:read()
                      mqtt:publish(topic, image)
                      busy = false -- 不再運行
                   end)
                end
                coroutine.yield(true)  -- 休眠
             end
          end

          上述函數(shù)通過不在 MQTT 客戶端的發(fā)送隊列中填充兩個圖像來維護流程控制。cam:read 函數(shù)可能耗時,不是在人類時間上,而是在微控制器操作上。因此,我們將從 CAM 對象讀取的任務轉(zhuǎn)移到一個單獨的線程。雖然這一步并不是嚴格必要的,但它增強了在從 CAM 讀取的同時處理多個操作的應用程序的性能。要深入了解線程的復雜性,建議參考Barracuda App Server 關(guān)于線程的文檔。

          完整的 MQTT CAM 代碼如下:

          local topic = "/xedge32/espcam/USA/92629"
          local broker = "broker.hivemq.com"
          
          -- 'FREENOVE ESP32-S3 WROOM' CAM 板的設(shè)置
          local cfg={
             d0=11, d1=9, d2=8, d3=10, d4=12, d5=18, d6=17, d7=16,
             xclk=15, pclk=13, vsync=6, href=7, sda=4, scl=5, pwdn=-1,
             reset=-1, freq="20000000", frame="HD"
          }
          
          -- 打開相機
          local cam,err=esp32.cam(cfg)
          assert(cam, err) -- 如果 'cfg' 不正確,會拋出錯誤
          
          local timer -- 定時器對象;在下面設(shè)置。
          
          -- MQTT 連接/斷開回調(diào)
          local function onstatus(type,code,status)
             -- 如果連接到代理成功
             if "mqtt" == type and "connect" == code and 0 == status.reasoncode then
                timer:set(300,false,true) -- 每 300 毫秒激活定時器
                trace"Connected"
                return true -- 接受連接
             end
             timer:cancel()
             trace("Disconnect or connect failed",type,code)
             return true -- 繼續(xù)嘗試
          end
          
          -- 創(chuàng)建 MQTT 客戶端
          local mqtt=require("mqttc").create(broker,onstatus)
          
          -- 每 300 毫秒激活的定時器協(xié)程函數(shù)
          function publishImage()
             local busy=false
             while true do
                --trace(mqtt:status(), busy)
                -- 流程控制:如果排隊的 MQTT 消息少于 2 條
                if mqtt:status() < 2 and not busy then
                   busy=true
                   ba.thread.run(function()
                      local image,err=cam:read()
                      if image then
                         mqtt:publish(topic,image)
                      else
                         trace("cam:read()",err)
                      end
                      busy=false
                   end)
                end
                coroutine.yield(true) -- 休眠
             end
          end
          timer = ba.timer(publishImage)

          雖然我們已經(jīng)涵蓋了程序的大部分功能,但還有一些方面尚未涉及:

          • 主題和代理配置:local topic = "/xedge32/espcam/USA/92629":設(shè)置圖像將被發(fā)布到的 MQTT 主題。將此主題更改為您的地址。local broker = "broker.hivemq.com":指定 MQTT 代理的地址。此示例中使用公共的 HiveMQ 代理。
          • ESP32 相機配置(cfg): 這個塊設(shè)置了 ESP32 CAM 板的特定引腳配置和設(shè)置。用適合您硬件的設(shè)置替換這些設(shè)置。
          • 創(chuàng)建 MQTT 客戶端: MQTT 客戶端是通過 require("mqttc").create(broker, onstatus) 函數(shù)創(chuàng)建的,傳入代理地址和 onstatus 回調(diào)。
          • 為 publishImage 創(chuàng)建定時器對象: 通過調(diào)用 ba.timer 并傳入 publishImage 回調(diào)來創(chuàng)建定時器,它將在固定間隔內(nèi)激活。這是不斷捕獲和發(fā)布圖像的機制。

          使用 JavaScript 驅(qū)動的 HTML 客戶端訂閱 CAM 圖像

          要可視化由 ESP32 相機發(fā)布的圖像,您可以使用一個 HTML 客戶端。以下客戶端將訂閱相機發(fā)布圖像的相同 MQTT 主題。該客戶端純粹在您的 Web 瀏覽器中運行,不需要任何服務器設(shè)置。

          完整的 HTML 客戶端代碼如下:

          <!DOCTYPE html>
          <html lang="en">
          <head>
            <title>Cam Images Over MQTT</title>
            <script data-fr-src="https://cdnjs.cloudflare.com/ajax/libs/mqtt/5.0.0-beta.3/mqtt.min.js"></script>
          <script>
          
          const topic="/xedge32/espcam/USA/92629";
          const broker="broker.hivemq.com";
          
          window.addEventListener("load", (event) => {
              let img = document.getElementById("image");
              let msg = document.getElementById("msg");
              let frameCounter=0;
              const options = {
                  clean: true,
                  connectTimeout: 4000,
                  port: 8884 // 安全的 WebSocket 端口
              };
              const client = mqtt.connect("mqtts://"+broker+"/mqtt",options);
          
              client.on('connect', function () {
                  msg.textContent="Connected; Waiting for images...";
                  client.subscribe(topic);
              });
          
              client.on("message", (topic, message) => {
                  const blob = new Blob([message], { type: 'image/jpeg' });
                  img.src = URL.createObjectURL(blob);
                  frameCounter++;
                  msg.textContent = `Frames: ${frameCounter}`;
              });
          });
          </script>
          </head>
          <body>
              <h2>Cam Images Over MQTT</h2>
             <div id="image-container">
              <img id="image"/>
            </div>
              <p id="msg">Connecting...</p>
          </body>
          </html>

          MQTT JavaScript 客戶端

          在 HTML 文件的頂部,導入 MQTT JavaScript 庫以啟用 MQTT 功能。這在 <script data-fr-src=".......mqtt.min.js"></script> 行中找到。

          頁面布局

          HTML 主體包含一個 id 為 "image-container" 的 <div> 元素,用于容納傳入的圖像,以及一個 id 為 "msg" 的 <p> 元素,用作狀態(tài)消息的占位符。

          MQTT 配置

          在 JavaScript 部分,定義了兩個常量 topic 和 broker。這些必須與您的 mqttcam.xlua 文件中的主題和代理配置相對應。

          連接到 MQTT 代理

          客戶端使用 mqtt.connect() 方法向指定的代理發(fā)起 MQTT 連接。它使用安全的 WebSocket 端口 8884 進行連接。

          處理傳入消息

          在成功連接后,客戶端訂閱主題。預期在此主題上的任何傳入消息都將是二進制 JPEG 圖像。消息將被轉(zhuǎn)換為 Blob,并顯示為圖像元素的源。

          幀計數(shù)器

          frameCounter 變量計算傳入幀(或圖像)的數(shù)量,并將此計數(shù)顯示為圖像下方的文本消息。

          通過在 Web 瀏覽器中打開此 HTML 文件,您將能夠?qū)崟r可視化被發(fā)布到指定 MQTT 主題的圖像。

          準備代碼

          步驟 1:準備 Lua 腳本如下

          1. 如在教程您的第一個 Xedge32 項目中所述,當 Xedge32 驅(qū)動的 ESP32 運行時,使用瀏覽器導航到 Xedge IDE。
          2. 創(chuàng)建一個名為 "cam" 的新 Xedge 應用程序,并啟用 LSP。
          3. 展開左側(cè)面板樹視圖中可見的 cam 應用程序。
          4. 右鍵單擊 cam 應用程序,然后在上下文菜單中單擊 新建文件。
          5. 輸入 camtest.lsp,然后點擊 Enter。
          6. 打開 GitHub 上的 camtest.lsp 文件,然后單擊 復制原始文件 按鈕。
          7. 轉(zhuǎn)到 Xedge IDE 瀏覽器窗口,將內(nèi)容粘貼到 camtest.lsp 文件中。
          8. 重要: 調(diào)整 camtest.lsp 中的 cfg 設(shè)置,以匹配您特定的 ESP32 CAM 板設(shè)置。有關(guān)詳細信息,請參閱 Lua CAM API。
          9. 點擊保存,然后點擊打開以測試您的相機設(shè)置。確保在繼續(xù)之前看到 LSP 腳本生成的圖像。
          10. 右鍵單擊 cam 應用程序,然后在上下文菜單中單擊 新建文件。
          11. 輸入 mqttcam.xlua,然后點擊 Enter。
          12. 打開 GitHub 上的 mqttcam.xlua 文件,然后單擊 復制原始文件 按鈕。
          13. 轉(zhuǎn)到 Xedge IDE 瀏覽器窗口,將內(nèi)容粘貼到 mqttcam.xlua 文件中。
          14. 使用 Xedge 編輯器,從 camtest.lsp 復制 cfg 設(shè)置,并將其替換為步驟 9 中測試的設(shè)置。
          15. 點擊 保存并運行 按鈕以保存并啟動示例。

          步驟 2:準備 HTML/JS 文件如下

          1. 下載 mqttcam.html,在任何編輯器中打開文件,并確保 HTML 文件中的主題與您在 Lua 腳本中設(shè)置的主題相匹配。
          2. 保存 mqttcam.html 文件。
          3. 打開 mqttcam.html:雙擊 mqttcam.html 文件,或?qū)⑵渫戏诺綖g覽器中。注意:此文件設(shè)計為直接從文件系統(tǒng)打開。您不需要 Web 服務器來托管此文件。
          4. 觀察輸出:網(wǎng)頁將顯示由 ESP32 CAM 發(fā)布的圖像。接收到的幀數(shù)將顯示在圖像下方。
            SELECT * FROM potential_issues;

          ESP32 CAM板的潛在問題及解決方案

          ESP32 CAM板因其多功能性和價格實惠而廣受認可。然而,它們并非沒有挑戰(zhàn)。用戶在使用ESP32 CAM板時可能會面臨的一個重要問題是攝像頭讀取操作與內(nèi)置WiFi模塊之間的干擾。讓我們深入了解一下具體情況:

          問題:干擾和WiFi信號衰減

          當ESP32 CAM板在運行時,特別是在攝像頭的讀取操作期間,會產(chǎn)生噪音。這種噪音會干擾內(nèi)置WiFi,導致:

          • 信號范圍減小: WiFi有效傳輸和接收數(shù)據(jù)的距離明顯減少。
          • 吞吐量降低: WiFi網(wǎng)絡(luò)傳輸數(shù)據(jù)的速度和效率會受到相當大的影響。

          解決方案

          為了解決這些問題,請考慮以下解決方案:

          1. 使用帶有外置天線的CAM板: 幾種ESP32 CAM板配備了或支持使用外置天線。通過使用這樣的板并連接外置天線,您可以增強WiFi信號強度和范圍,減輕攝像頭操作造成的一些干擾。
          2. 集成W5500以太網(wǎng)芯片: 如果您的應用需要穩(wěn)定和強大的數(shù)據(jù)傳輸,請考慮集成W5500以太網(wǎng)芯片。通過使用以太網(wǎng)而不是WiFi,您可以有效地避開與ESP32 CAM板上的WiFi相關(guān)的干擾問題。Xedge32配備了集成的以太網(wǎng)驅(qū)動程序。當與支持它的硬件配對使用時,比如W5500芯片,它可以實現(xiàn)平穩(wěn)且無干擾的數(shù)據(jù)傳輸,確保您的應用保持穩(wěn)定和高效。

          總之,雖然ESP32 CAM板是適用于多種應用的優(yōu)秀工具,但了解其局限性并知道如何規(guī)避這些局限性以確保最佳性能是至關(guān)重要的。

          參考資料

          • Lua MQTT API
          • Lua timer API
          • Lua CAM API```

          現(xiàn)目標:

          1. 可以一次選取多個圖片上傳;
          2. 上傳的圖片可以拖動排序;
          3. 點擊圖片提示刪除彈窗,確認后刪除該圖片;
          4. 點擊上傳按鈕圖標,即可瀏覽圖片,隱藏選擇文件的文本框;
          5. 選擇圖片以后自動上傳;
          6. 拖拽排序的時候使用transition-group,實現(xiàn)動畫效果;

          圖1 多圖上傳效果


          1、html代碼

          <tr class=''>
          <td width="90" align="right">相關(guān)多圖</td>
          <td >
          <div class='yllist yllist_x_duotu'>
          <dl>
          <!--存放上傳的圖片-->
          <transition-group name="list">
          <dd   v-for="(item,index) in listData " draggable="true" :key="item" 
          	@click="del(index)" 
          	@mouseover="showzz(1,index)"  
          	@mouseleave="showzz(0,index)" 
          	@dragstart="drag($event,index)" 
          	@drop="drop($event,index)"
          	@dragover='allowDrop($event)'
          	>
              <img :src="item.picpath">
              <div class='zzz none'  :class="{'nonone':item.shs==1}">
              <div class='zzimg '><i class="fa fa-trash-o" aria-hidden="true"></i></div>
          	</div>
          </dd>
          <!--結(jié)束-->
          </transition-group>
          <dd  @click="upbtn"  class='btnclass'><i class="fa fa-camera-retro" aria-hidden="true"></i>
          <input type='file' id='multiple' accept="image/*"   multiple="multiple" style='display:none' @change="autoup"  name="ss">
          </dd>
          </dl>
          <div class='clear'></div>
          <div>
          <span class='itemms'>說明:可以拖動改變順序</span>
          </div>
          </div>
          </td>
          </tr>

          說明:

          @click="del(index)" 點擊刪除圖片 index為數(shù)組的索引 點擊的是第幾個圖片

          @mouseover="showzz(1,index)" 鼠標放到上邊 出現(xiàn)遮罩層 垃圾桶

          @mouseleave="showzz(0,index)" 鼠標離開 遮罩層消失

          @dragstart="drag($event,index)" 以下三個 用于拖拽排序

          @drop="drop($event,index)"

          @dragover='allowDrop($event)'

          draggable="true" 設(shè)置為true 可以拖動

          :key="item" 這里的key 要注意不能等于 index,要不然沒有動畫效果

          img src的屬性 是 :src="item.picpath" 不能是src={{item.picpath}}

          <div class='zzz none' :class="{'nonone':item.shs==1}"> 設(shè)置遮罩層 shs=1的時候顯示

          上傳的選擇框設(shè)置為display:none隱藏

          transition-group用法:

          <transition-group name="list"> 實現(xiàn)拖拽的動畫效果 后邊的name可以隨意寫 ,但是要和css的.list-move {transition: transform 0.3s;} 【上邊自定義的name,我這里是list】-move 設(shè)置該css 動畫的時間

          2、js代碼

          new Vue({
              el: '#app',
              data(){
          		  tagslist:[
          		    '網(wǎng)站開發(fā)',//存放的標簽
          			  '網(wǎng)站建設(shè)'
          		  ],
          		  tagsdt:"",  //綁定的標簽文本框
          		  tagindex:"",//刪除標簽的序號(索引)
          		  listData: [
          				  /*
          			      {'picpath':'/public/upload/image/20211107/1.jpg',shs:0}
          			      
          				  shs   顯示遮罩層 ,垃圾桶刪除標志,0  不顯示   1顯示
          				  */
          		  ],
                file:"file",      //用于切換 file  text  實現(xiàn)同一個圖片可以連續(xù)上傳
          		  tis:'',           //提示內(nèi)容
          		  showzzc:0,         //彈出框的顯示,隱藏 。0 隱藏  1顯示
          		  showts:0,          //1 彈出提示操作框  2 彈出提示確認框 
          		  lisindex:"",      //記錄圖片的索引
          		  datameth:""       //根據(jù)這里的參數(shù)操作不同的方法
          		 }
              },
              methods:{
          	  tags:function(){
          		  if(this.tagsdt){
          		      this.tagslist.push(this.tagsdt); 
          		  }
          		  this.tagsdt="";
          	  },
          	  deltag:function(f){
          		  this.showzzc=1;
          		  this.showts=1;
          		  this.tagindex=f;
          		  this.datameth='tag';
          	  },
          	  hidetc:function(){
          		  this.showzzc=0;
          	  },
           	   del:function(key){
          			this.showzzc=1;
          			this.showts=1;
          			this.lisindex=key;
          			this.datameth="delpic";
          			//this.listData.splice(key, 1);
          		},
          	  isdelc:function(){
          			if(this.datameth=="delpic"){
          		        this.listData.splice(this.lisindex, 1); 
          			}
          			if(this.datameth=="tag"){
          		        this.tagslist.splice(this.tagindex, 1); 
          			}
          			this.showzzc=0;
          	  }, 
            	showzz:function(meth,key){
          			//console.log(this.listData[key].shs);
          			if(!this.listData[key].shs){
          			    this.$set(this.listData[key],'shs',0);
          			}
          			this.listData[key].shs=meth;
          	  }, 
          	  upbtn:function(){
          		  document.getElementById("multiple").click();
          	  },
          	  autoup:function(){
          		  let that=this;
                that.file="text";  //切換text  file
          		  let ups=document.getElementById( "multiple");
          		  let formdata = new FormData();
          		  if(ups.files[0]){
          			  if(ups.files.length>4){
          				  this.showzzc=1;
          				  this.showts=2;
          				  this.tis="一次最多可以選擇4張圖片上傳!";
                    that.file="file";
          				  return false;
          			  }
                  for(m=0;m<=ups.files.length-1;m++){
          			      formdata.append("file", ups.files[m]);
          			      axios.post("/api/uppic", formdata)
          					  .then(function (response) {
          					    if(response.data.error=='0000'){
          							    that.listData.push(response.data.pic);
                            that.file="file";//重新切換為file
          							  //console.log(JSON.stringify(that.listData));
          						  }else{
          							  that.showzzc=1;
          							  that.showts=2;
          							  that.tis=response.data.msg;
                          that.file="file";
          							  return false;
          						  }
          					  })
          					  .catch(function (error) {
          						  console.log(error);
          					  });
                    }
          			    console.log(ups.outerHTML);
          		  }  
              }
          })

          注意:上傳圖片以后一定要that.file="file",切換回file,不然會出現(xiàn)只能上傳一次,下次選擇當前圖片不能上傳的情況。

          1. 去掉js中的for循環(huán)和html的multiple="multiple"選擇多個圖片,就是單圖的上傳;
          2. 因為刪除彈出提示的地方有2個,實際可能更多,在點擊確認的時候不知道操作哪個刪除,所以點刪除圖片或者是點刪除信息標簽的時候,向datameth賦不同的值,這樣我們點擊彈窗的確認,讀取datameth的值,使用if判斷,就可以知道要刪除圖片還是刪除標簽;
          3. 上傳圖片,刪除圖片用到的彈窗,在前邊十七章有說明;

          上邊的上傳是選取多個然后for循環(huán)逐個上傳的,也可以file使用數(shù)組file[]批量提交,如下:

          for(m=0;m<=ups.files.length-1;m++){
          			      formdata.append("file[]", ups.files[m]);
          }
          axios.post("/api/uppic", formdata)

          但是這樣做的話,后臺使用

          foreach($_FILES as $k=>$v){
          }

          得到的$v['name']就是數(shù)組,需要我們再次for循環(huán),得到單個的圖片信息,返回以后的信息因為是數(shù)組,push只能一次追加一個,就只能再次循環(huán),感覺很麻煩還不如開始就循環(huán),一個一個的上傳。

          3、信息標簽html

          <tr class=''>
          <td width="90" align="right">信息標簽</td>
          <td>
          <div class="layui-input-inline tagslist" >
              <span class='tagspan' v-for="(tag,key) in tagslist"   :key="key" @click="deltag(key)">{{tag}}</span>
          </div>
          <input type="text"  class='inpMain' id='tags' style='width:150px;'  @blur="tags" v-model="tagsdt" /> <span class='itemms'>點擊標簽可以刪除</span>
           <span class='itemms'></span>
          </td>
          </tr>

          輸入文本框綁定tagsdt,當我們鼠標離開該文本框的時候,通過blur使用tags方法讀取綁定的tagsdt,可以獲得輸入的內(nèi)容,這里需要判斷是否為空,如果不為空再push進數(shù)組:this.tagslist.push(this.tagsdt);

          4、php后端代碼

          foreach($_FILES as $k=>$v){
                 $v['name'],$v['size'],$v['tem_name']
            就是圖片的基本信息,使用move_uploaded_file移動到指定文件夾
            			$imags['picpath']=$path;
          				$imags['shs']=0;
          }
          exit(json_encode(array('error'=>'0000','pic'=>$imags),JSON_UNESCAPED_UNICODE));

          move_uploaded_file用法:

          當前文件:$v["tmp_name"],

          目標文件:ROOT_PATH.$images_dir.$newname

          move_uploaded_file($v["tmp_name"], ROOT_PATH.$images_dir.$newname);

          再次強調(diào)上傳圖片,要驗證圖片的安全性,防止圖片木馬!

          tml+js+php異步上傳圖片,不刷新頁面,圖片用的是選擇了就自動上傳,好處就是不用刷新頁面。

          前端就是 input標簽,沒有form表單,用form表單的稍微有點差異,大家可以去百度

          我是需要服務端返回我圖片存儲的地址,每次只上傳一張,不是php的原生上傳,代碼稍微有一點不一樣。代碼可能不規(guī)范,匆忙寫的。理解理解。

          方法有很多種,大家可以參考。互相交流謝謝。


          主站蜘蛛池模板: 无码精品人妻一区二区三区中 | 日本免费一区二区三区四区五六区 | 中文人妻无码一区二区三区| 视频一区在线免费观看| 午夜精品一区二区三区在线观看| 一区二区三区四区国产| 激情内射日本一区二区三区| 精品人妻系列无码一区二区三区 | 色欲AV无码一区二区三区| 国产日韩AV免费无码一区二区三区| 中文字幕一区二区三区精华液 | 国产成人AV区一区二区三| 亚洲日本一区二区一本一道 | 91精品国产一区| 在线观看一区二区三区视频| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 中文字幕一区二区三区精华液| 日韩精品无码一区二区三区不卡| 九九无码人妻一区二区三区| 精品国产免费一区二区三区| 国产精品福利一区二区| 国产99精品一区二区三区免费| 精品视频一区二区三三区四区 | 一区二区三区免费精品视频| 蜜桃视频一区二区三区在线观看| 国产成人高清视频一区二区 | 国产一区二区视频免费| 亚洲av无码一区二区三区乱子伦| 蜜臀AV无码一区二区三区| 台湾无码AV一区二区三区| 国产精品无码一区二区三区不卡| 99国产精品一区二区| 国产成人欧美一区二区三区 | 亚洲AV无码一区二区三区性色 | 91在线视频一区| 国产一区二区视频在线观看| 国内精品视频一区二区八戒| 无码人妻精品一区二区| 国产福利电影一区二区三区久久久久成人精品综合 | 波多野结衣一区二区三区高清av| 日韩精品一区二区三区中文|