前语

当需求手机衔接开发板(nodemcu)的wifi,而且和它进行数据通讯时,就需求用到本文内容。

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

nodemcu http和wss服务树立

下面代码在 Arduino IDE 中编译。

#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: %sn", 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: %sn", 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: %un", 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…

<!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> 

作用

拖动页面滚动条,板子会实时收到音讯。

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