js原生 WebSocket API 与 WebSocketsServer.h 的通信(nodemcu-32s 和 javascript 通信)

前言

当需要手机连接开发板(nodemcu)的wifi,并且和它进行数据通信时,就需要用到本文内容。

本文使用 nodemcu 搭建一个 http 服务和一个webSocket服务,前者用于提供web页面,后者用于在页面中和开发板进行实时通信。

nodemcu http和wss服务搭建

下面代码在 Arduino IDE 中编译。

c 复制代码
#include <WiFiClient.h>        // 调用WiFiClient库,用于建立wifi连接
#include <ESP8266WebServer.h>  // 调用WebServer库,用于构建html页面
#include <WebSocketsServer.h>  // 用于构建ws服务
#include <Arduino_JSON.h>

// wifi 账号密码 
String wifi_name = "test";
String wifi_pwd = "12345678";


// 建立WebServer,端口为80
ESP8266WebServer server(80);
// socket 服务
WebSocketsServer webSocket = WebSocketsServer(81);
#define USE_SERIAL Serial

// 处理接到的消息,代码中演示 json 解析方法
void msg_cb(uint8_t* payload) {
  JSONVar infosObj = JSON.parse((char*)payload);  // 将 payload 转换为 char*
  // if (JSON.typeof(infosObj) == "undefined") {
  //   return;
  // }
  //if (infosObj.hasOwnProperty("dj_deg")) { 
  //   dj_deg = (int)infosObj["dj_deg"]; 
  //} 
}

void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) {
  switch (type) {
    case WStype_DISCONNECTED:
      USE_SERIAL.printf("[%u] Disconnected!\n", num);
      break;
    case WStype_CONNECTED:
      {
        IPAddress ip = webSocket.remoteIP(num);
        USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);

        // send message to client
        webSocket.sendTXT(num, "Connected");
      }
      break;
    case WStype_TEXT:
      USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 
      msg_cb(payload);

      // send message to client
      // webSocket.sendTXT(num, "message here");
      // send data to all connected clients
      // webSocket.broadcastTXT("message here");
      break;
    case WStype_BIN:
      USE_SERIAL.printf("[%u] get binary length: %u\n", num, length);
      hexdump(payload, length);

      // send message to client
      // webSocket.sendBIN(num, payload, length);
      break;
  }
}

// http 服务 "/" 路由处理函数,返回一个 html 文件
// 这页面文件会直接写到代码中,也可以使用 `FS.h` 存入闪存。
void ctrl_page() {
  String content = "<!DOCTYPE html><html lang='en'><head><meta charset='UTF-8'><meta name='viewport'content='width=device-width, initial-scale=1.0'><title>测试</title><style>body{margin:0;padding:0;width:100%;height:100%}</style></head><body><input id='dj_range'type='range'min='0'max='180'step='1'value='90'style='width: 100%;margin: 50px 0px;'></body></html><script>var server='ws://192.168.4.1:81';var socket=new WebSocket(server);socket.onopen=function(event){console.log('WebSocket 连接已建立');document.querySelector('#dj_range').addEventListener('input',function(e){var val=Number(e.target.value);socket.send(JSON.stringify({dj_deg:val}))})};socket.onmessage=function(event){console.log('收到消息:',event.data)};socket.onclose=function(event){console.log('WebSocket 连接已关闭')};socket.onerror=function(error){console.error('WebSocket 发生错误:',error)};</script>";
  server.send(200, "text/html", content);
}

// 对外接口
void initServer() {
  // 手机控制页面
  server.on("/", ctrl_page); 
  server.begin();
}

void setup() {
  Serial.begin(115200);  // 初始化串口,波特率为 115200
  WiFi.mode(WIFI_AP);                // 将WiFi模式设为AP
  WiFi.softAP(wifi_name, wifi_pwd);  // 开启热点
  
 
  IPAddress ip = WiFi.softAPIP();
  String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
  String httpUrl = "http://" + ipStr;
  Serial.println("AP IP:");
  Serial.println(ipStr);
  
  // http 服务
  initServer();
    
  // ws 服务
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

void loop() {

  // 处理客户端请求
  server.handleClient();

  webSocket.loop();
}

页面代码

页面代码最后写完后压缩后,放到了上面代码中。

需要注意的是这里用不了 socket.io.js 这个很棒的插件。因为这个插件太大了,放板子里太多余,所以需要手写 js 提供的 api, 详细学习见: developer.mozilla.org/en-US/docs/...

html 文件压缩工具:www.jyshare.com/front-end/4...

html 复制代码
<!DOCTYPE html>
<html lang='en'>

<head>
    <meta charset='UTF-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <title>测试</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>

    <input id='dj_range' type='range' min='0' max='180' step='1' value='90' style='width: 100%;margin: 50px 0px;'>
</body>

</html>
<script>
    // 板子的ip
    var server = 'ws://192.168.4.1:81';
    // 创建 WebSocket 连接
    var socket = new WebSocket(server);

    // 当连接建立时
    socket.onopen = function (event) {
        console.log('WebSocket 连接已建立');

        document.querySelector('#dj_range').addEventListener('input', function (e) {
            var val = Number(e.target.value);
            // 发送 Socket.IO 握手消息
            socket.send(JSON.stringify({ dj_deg: val }));
        })

    };

    // 当收到消息时
    socket.onmessage = function (event) {
        console.log('收到消息:', event.data);
    };

    // 当连接关闭时
    socket.onclose = function (event) {
        console.log('WebSocket 连接已关闭');
    };

    // 当发生错误时
    socket.onerror = function (error) {
        console.error('WebSocket 发生错误:', error);
    };
</script> 

效果

拖动页面滚动条,板子会实时收到消息。

相关推荐
Inhand陈工11 分钟前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
大鱼>12 分钟前
大语言模型+物联网:LLM理解物理世界
物联网·struts·语言模型·多模态·aiot
果丁智能19 分钟前
物联网智能锁赋能集中式住宿:身份核验与远程权限管控的全链路技术实践
大数据·人工智能·物联网·智能家居
触底反弹38 分钟前
🚀 手把手用 HTML5 Canvas 从零打造飞机大战游戏,代码全开源!
前端·javascript·canvas
DJ斯特拉39 分钟前
axios快速使用
开发语言·前端·javascript
智通42 分钟前
可取消的异步任务与 AbortController
javascript
国产化创客1 小时前
ESP32 CameraWebServer 原生摄像头项目全解析
物联网·开源·嵌入式·实时音视频·智能硬件
Hilaku1 小时前
AI 写代码越快,为什么 Code Review 越不能省?
前端·javascript·程序员
谁似人间西林客2 小时前
数据智能怎么赋能工业制造?物联网场景落地方法解析
物联网·制造
InHand云飞小白2 小时前
无人值守站点网络困境?工业级路由器IR315破解连接难题
网络·物联网·4g·工业路由器·4g路由器·iiot·蜂窝路由器