]> Zhao Yanbai Git Server - acecode.git/commitdiff
...
authorAceVest <zhaoyanbai@126.com>
Sun, 17 Jan 2021 12:36:20 +0000 (20:36 +0800)
committerAceVest <zhaoyanbai@126.com>
Sun, 17 Jan 2021 12:36:20 +0000 (20:36 +0800)
projects/audio_stream/audioweb/canvas.html [new file with mode: 0644]
projects/audio_stream/audioweb/go.mod [new file with mode: 0644]
projects/audio_stream/audioweb/go.sum [new file with mode: 0644]
projects/audio_stream/audioweb/main.go [new file with mode: 0644]
projects/audio_stream/esp32audio/esp32audio.ino [new file with mode: 0644]
projects/esp32_video_stream/esp32cam/esp32cam.ino

diff --git a/projects/audio_stream/audioweb/canvas.html b/projects/audio_stream/audioweb/canvas.html
new file mode 100644 (file)
index 0000000..06d1810
--- /dev/null
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+
+<head>
+    <meta charset="utf-8">
+    <title>CANVAS VIDEO</title>
+    <style>
+        #Video {
+            border: 1px solid red;
+        }
+    </style>
+</head>
+
+<body>
+    <canvas id="Video" width="120" height="160"></canvas>
+    <pre id="Stat"></pre>
+    <pre id="Msg"></pre>
+
+    <script>
+        var ws;
+        var wsURL = "ws://127.0.0.1/stream";
+        var canvas = document.getElementById('Video');
+        var ctx = canvas.getContext('2d'); 
+
+        var frameCount = 0;
+        var totalBytes = 0;
+        window.setInterval(function() {
+            fps = frameCount;
+            bytes = totalBytes;
+
+            frameCount = 0;
+            totalBytes = 0;
+            
+            var Stat = document.getElementById('Stat');
+            Stat.innerHTML = "当前帧率: " + fps + " fps, 带宽:" + (bytes*8.0/(1024.0*1024.0)).toFixed(1) + " Mbps";
+        },1000)
+
+        function Msg(...args) {
+            msg = args.join('');
+            console.log(msg);
+
+            var Msg = document.getElementById('Msg');
+            contents = Msg.innerHTML;
+            contents += msg;
+            slice = contents.split('\n').slice(-5);
+            msg = slice.join('\n')+'\n';
+            Msg.innerHTML = msg;
+        }
+    
+        function initWebsocket() {
+            ws = new WebSocket(wsURL);
+            ws.SendCmd = function(req) {
+                req = JSON.stringify(req);
+                ws.send(req);
+            }
+    
+            ws.onopen = function () {
+                Msg("websocket opened");
+            };
+    
+            ws.onerror = function (event) {
+                Msg("websocket error: " + event);
+            };
+    
+            ws.onclose = function (event) {
+                Msg("websocket closed with code: " + event.code + " reason: " + event.reason);
+            };
+    
+            ws.onmessage = function (event) {
+                imageData = event.data;
+                frameCount++;
+                totalBytes += imageData.size;
+                Msg("frame data len: ", imageData.size);
+                var image = new Image();
+                image.src = URL.createObjectURL(imageData);
+                image.onload = () => {
+                    URL.revokeObjectURL(image.src);
+                    ctx.save();
+                    ctx.translate(60, 80);
+                    ctx.rotate(90*(Math.PI/180));
+                    ctx.translate(-80, -60);
+                    ctx.drawImage(image, 0, 0);
+                    ctx.restore();
+                }
+            };
+        }
+
+        initWebsocket();
+    </script>
+</body>
+
+</html>
diff --git a/projects/audio_stream/audioweb/go.mod b/projects/audio_stream/audioweb/go.mod
new file mode 100644 (file)
index 0000000..89d2f2a
--- /dev/null
@@ -0,0 +1,5 @@
+module audioweb
+
+go 1.13
+
+require github.com/gorilla/websocket v1.4.2
diff --git a/projects/audio_stream/audioweb/go.sum b/projects/audio_stream/audioweb/go.sum
new file mode 100644 (file)
index 0000000..85efffd
--- /dev/null
@@ -0,0 +1,2 @@
+github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
diff --git a/projects/audio_stream/audioweb/main.go b/projects/audio_stream/audioweb/main.go
new file mode 100644 (file)
index 0000000..e0ece94
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: main.go
+ *      Author: Zhao Yanbai
+ *              2021-01-16 23:01:01 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+package main
+
+import (
+       "fmt"
+       "html/template"
+       "log"
+       "net/http"
+       "time"
+
+       "github.com/gorilla/websocket"
+)
+
+var upgrader = websocket.Upgrader{
+       ReadBufferSize:  102400,
+       WriteBufferSize: 102400,
+
+       // 解决跨域问题
+       CheckOrigin: func(r *http.Request) bool {
+               return true
+       },
+}
+
+var frameChan chan []byte
+
+func init() {
+       frameChan = make(chan []byte, 8)
+}
+
+const (
+       partBOUNDARY      = "123456789000000000000987654321"
+       streamContentType = "multipart/x-mixed-replace;boundary=" + partBOUNDARY
+       streamBoundary    = "\r\n--" + partBOUNDARY + "\r\n"
+       streamPart        = "Content-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n"
+)
+
+func watchHandler(w http.ResponseWriter, r *http.Request) {
+       var err error
+       w.Header().Set("Content-Type", streamContentType)
+       w.Header().Set("Access-Control-Allow-Origin", "*")
+
+       flusher, _ := w.(http.Flusher)
+
+       for i := 0; ; i++ {
+               var data []byte
+               select {
+               case data = <-frameChan:
+                       fmt.Fprintf(w, "%v", streamBoundary)
+                       fmt.Fprintf(w, streamPart, i)
+                       _, err = w.Write(data)
+                       flusher.Flush()
+                       if err != nil {
+                               break
+                       }
+               default:
+                       continue
+               }
+
+       }
+}
+
+func audioHandler(w http.ResponseWriter, r *http.Request) {
+       var err error
+       var ws *websocket.Conn
+
+       log.Printf("audio\n")
+       ws, err = upgrader.Upgrade(w, r, nil)
+       if err != nil {
+               log.Printf("err: %v", err)
+               return
+       }
+
+       defer ws.Close()
+
+       for {
+               t, p, e := ws.ReadMessage()
+               log.Printf("type %v data len %v err %v", t, len(p), e)
+               if e != nil {
+                       break
+               }
+
+               if len(p) < 100 {
+                       continue
+               }
+
+
+        /*
+        data := make([]byte, len(p)/2, len(p)/2)
+        k := 0
+        for i :=0; i<len(p); i++ {
+            if (i / 2) % 2 == 1 {
+                continue
+            }
+
+            data[k] = p[i]
+            k++
+        }*/
+
+               select {
+               case frameChan <- p:
+                       log.Printf("put frame")
+
+            err = ws.WriteMessage(websocket.BinaryMessage, []byte{'1'})
+            if err != nil {
+                log.Printf("write to arduino error: %v", err)
+                //break
+            }
+               default:
+                       log.Printf("drop frame")
+               }
+
+       }
+}
+
+func streamHandler(w http.ResponseWriter, r *http.Request) {
+       var err error
+       var ws *websocket.Conn
+
+       log.Printf("stream\n")
+
+       ws, err = upgrader.Upgrade(w, r, nil)
+       if err != nil {
+               log.Printf("err: %v", err)
+               return
+       }
+
+       defer ws.Close()
+
+       for {
+               var data []byte
+               select {
+               case data = <-frameChan:
+        //case <-time.After(1 * time.Millisecond):
+        default:
+            time.Sleep(10 * time.Millisecond)
+                       continue
+               }
+
+               err = ws.WriteMessage(websocket.BinaryMessage, data)
+               if err != nil {
+                       break
+               }
+       }
+}
+
+func canvasHandler(w http.ResponseWriter, r *http.Request) {
+       tmpl := template.Must(template.ParseFiles("./canvas.html"))
+       var data = map[string]interface{}{}
+       tmpl.Execute(w, data)
+}
+
+func main() {
+       defer fmt.Println("Program Exited...")
+
+       m := http.NewServeMux()
+       m.HandleFunc("/watch", watchHandler)
+       m.HandleFunc("/audio", audioHandler)
+       m.HandleFunc("/canvas", canvasHandler)
+       m.HandleFunc("/stream", streamHandler)
+       server := http.Server{
+               Addr:    ":80",
+               Handler: m,
+       }
+
+       server.ListenAndServe()
+}
diff --git a/projects/audio_stream/esp32audio/esp32audio.ino b/projects/audio_stream/esp32audio/esp32audio.ino
new file mode 100644 (file)
index 0000000..3ad6715
--- /dev/null
@@ -0,0 +1,143 @@
+#include <ArduinoWebsockets.h>
+#include <WiFi.h>
+#include <WiFiMulti.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/i2s.h"
+#include "esp_system.h"
+
+#define SAMPLE_RATE (8000)
+
+using namespace websockets;
+
+typedef struct {
+  const char *name;
+  const char *pwd;
+} WiFiItem_t;
+
+const char* websockets_server_host = "10.0.0.6";
+const uint16_t websockets_server_port = 80;
+
+WiFiItem_t WiFiTable[] = {
+  { "WiFiName1", "" },
+  { "WiFiName2", "12345678" },
+  { "WiFiName3", "87654321" }
+};
+
+const unsigned int WiFiCnt = sizeof(WiFiTable) / sizeof(WiFiItem_t);
+
+WebsocketsClient client;
+WiFiMulti wifiMulti;
+
+
+void setup_wifi() {
+
+  for (uint8_t t = 3; t > 0; t--) {
+    Serial.printf("[SETUP] WAIT %d...\n", t);
+    Serial.flush();
+    delay(1000);
+  }
+
+
+  for (uint8_t i = 0; i < WiFiCnt; i++) {
+    Serial.printf("Add AP %s %s\n", WiFiTable[i].name, WiFiTable[i].pwd);
+    wifiMulti.addAP(WiFiTable[i].name, WiFiTable[i].pwd);
+  }
+
+}
+
+
+
+void setup_max9841() {
+  i2s_config_t i2s_config = {
+    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN),
+    .sample_rate = SAMPLE_RATE,
+    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
+    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
+    .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
+    .intr_alloc_flags = 0,
+    .dma_buf_count = 16,
+    .dma_buf_len = 60
+  };
+
+
+  Serial.println("using ADC_builtin");
+  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
+
+  // GPIO36, VP
+  i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0);
+}
+
+const int audioBufSize = 1024;
+char audioBufA[audioBufSize];
+//char audioBufB[audioBufSize];
+char *curtAudioBuf = audioBufA;
+
+
+bool webSocketConnected = false;
+
+void capture_audio(void *args) {
+  //while(1) {
+    i2s_read_bytes(I2S_NUM_0, (char *)curtAudioBuf, audioBufSize, portMAX_DELAY);
+
+    // 只要单声道数据
+    uint16_t *buf = (uint16_t *)curtAudioBuf;
+    int to = 0;
+    for (int i = 0; i < audioBufSize / 2; i += 2) {
+      buf[to] = buf[i];
+      to++;
+    }
+    if (webSocketConnected && client.available()) {
+      Serial.println("before send");
+      client.sendBinary((const char *)curtAudioBuf, audioBufSize / 2);
+      Serial.println("read and send audio data");
+    } else {
+      if(!webSocketConnected) {
+        Serial.println("websocket not connected");
+      }
+      if(client.available()) {
+        Serial.println("client not available");
+      }
+    }
+  //}
+}
+
+
+
+void setup() {
+  Serial.begin(115200);
+
+  setup_max9841();
+
+  setup_wifi();
+}
+
+void loop() {
+
+  uint8_t wifiState = wifiMulti.run();
+  if ((wifiState != WL_CONNECTED)) {
+    Serial.printf("[WiFi] connected to wifi failed. ret %d\n", wifiState);
+    delay(1000);
+    return;
+  }
+
+  if (client.available()) {
+    capture_audio(0);
+    client.poll();
+  } else {
+    Serial.println("Connected to Wifi, Connecting to server.");
+
+    webSocketConnected = client.connect(websockets_server_host, websockets_server_port, "/audio");
+    if (webSocketConnected) {
+      Serial.println("Connected!");
+    } else {
+      Serial.println("Not Connected!");
+    }
+
+    // run callback when messages are received
+    client.onMessage([&](WebsocketsMessage message) {
+      Serial.print("Got Message: ");
+      Serial.println(message.data());
+    });
+  }
+}
index e75acc52f6a81bb3063fba330b9a5a800bbf55fe..b450b346c9a5e70c52a2d2e002e50c79e09c32fa 100644 (file)
@@ -14,7 +14,6 @@ const char* websockets_server_host = "10.0.0.6";
 const uint16_t websockets_server_port = 80;
 
 WiFiItem_t WiFiTable[] = {
-  { "AceNetGear2G", "acewifipwdis123" },
   { "WiFiName1", "" },
   { "WiFiName2", "12345678" },
   { "WiFiName3", "87654321" }