65.9K
CodeProject 正在变化。 阅读更多。
Home

NodeMCU 和 Wi-Fi 远程控制应用程序,用于手机

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2019年1月6日

CPOL

7分钟阅读

viewsIcon

41788

downloadIcon

1024

关于如何开发用于手机的 Wi-Fi 遥控 HTML5 应用程序,并将其与 NodeMCU 和兼容设备 (ESP8266 / ESP32) 一起用于物联网应用的步骤指南。

引言

如今,在物联网应用中使用手机作为遥控器已成为一种普遍做法,为此,存在多种开发替代方案,例如:

我们将在此展示的是一种使用 HTML5 和一些已知技术来开发原生移动应用程序的替代解决方案,例如:

  • JQuery:一个 JavaScript 库,可以方便地操作网页中的元素和事件。
  • Onsen UI:一个响应式的 CSS 组件框架,用于使用 HTML5、CSS、JavaScript 等技术开发移动 Web 应用程序
  • PhoneGap:一个用于从 Web 应用程序生成混合移动应用程序的框架。

混合移动应用程序是将原生组件和 Web 组件结合在一起的应用程序。

从用户的角度来看,混合应用程序与原生应用程序完全相同。但是,在内部,混合应用程序使用一个 WebView 组件,其中包含应用程序的大部分内容和逻辑。

项目

为了测试上述工具,我们将开发一个小型项目,如下所示:

  • 一个连接到三个 LED 的 NodeMCU 板。
  • 该板将连接到Wi-Fi 网络并运行一个Web 服务器,该服务器将等待客户端的请求。
  • 客户端将是我们的手机上的遥控应用程序,它将显示一个屏幕来控制三个 LED。LED 1 和 2 可以通过按钮打开关闭。而 LED 3,我们将通过滑块控制其亮度。

注意:为了更好地了解,请参阅下方我们项目已正常工作的图像和视频。

≈ 点击此处观看视频演示 ≈

Mobile remote control screen

手机遥控屏幕

第一步:原型

组装我们的实验需要以下组件:

  • 面包板
  • NodeMCU 或兼容卡 (Wemos, MKR1000, ESP8266 Standalone)
  • 三个彩色 LED
  • 三个 220 欧姆电阻
  • 跳线

组装效果图如下:

第二步:NodeMCU Sketch

我们的 sketch 的基本功能是连接到 Wi-Fi 网络并创建一个 Web 服务器,该服务器将等待并响应带有 LED 控制命令的请求。
我们将使用 Arduino 自带的 IDE 进行开发。如果您还没有这样做,则需要用 ESP8266 软件配置环境。要做到这一点,请按照本文的步骤操作:使用 Arduino IDE 编程 ESP NodeMCU

现在我们来看带有注释的源代码:

wifi_rc.ino

/*
NodeMCU Web server for wi-fi remote control
2019, José Augusto Cintra
www.josecintra.com/blog
*/
#include <esp8266wifi.h>
#include <wificlient.h>
#include <esp8266wifimulti.h> 
#include <esp8266mdns.h>
#include <esp8266webserver.h>

ESP8266WiFiMulti wifiMulti;     // For multiple wi-fi configuration
ESP8266WebServer server(80);    // Create a webserver object that 
                                // listens for HTTP request on port 80

// function prototypes for HTTP handlers
void handleRoot();              
void handleRequest();
void handleNotFound();

void setup(void){
  delay(1000);
  pinMode(5, OUTPUT);          //Led 1
  pinMode(4, OUTPUT);          //Led 2
  digitalWrite(5, 0);
  digitalWrite(4, 0);

  analogWriteRange(100);       //Led 3 (PWM) 
  analogWrite(0, 0);
  
  Serial.begin(9600);          //Start the Serial communication to send messages 
                               //to the computer
  delay(10);
  Serial.println('\n');

  wifiMulti.addAP("ssid1", "password1");   //add Wi-Fi networks you want to connect to
  wifiMulti.addAP("ssid2", "password2");

  Serial.println("Connecting ...");
  int i = 0;
  while (wifiMulti.run() != WL_CONNECTED) { //Wait for the Wi-Fi to connect: 
                                            //scan for Wi-Fi networks, and connect to 
                                            //the strongest of the networks above
    delay(250);
    Serial.print('.');
  }
  Serial.println('\n');
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());              // Tell us what network we're connected to
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());           // Send the IP address of the ESP8266 
                                            // to the computer

  if (MDNS.begin("esp8266")) {              // Start the mDNS responder for esp8266.local
    Serial.println("mDNS responder started");
  } else {
    Serial.println("Error setting up MDNS responder!");
  }

  server.on("/", HTTP_GET, handleRoot);     // Call the 'handleRoot' function 
                                            // when a client requests URI "/"
  server.on("/command", HTTP_POST, handleRequest); // Call the 'handRequest' function 
                                                   // when a POST request is made 
                                                   // to URI "/command"
  server.onNotFound(handleNotFound);        // When a client requests an unknown URI 

  server.begin();                           // Actually start the server
  Serial.println("HTTP server started");
  return;
}

void loop(void){
  server.handleClient();                    // Listen for HTTP requests from clients
  return;
}

void handleRoot() {                         // When URI / is requested, 
                                            // send a standard web page 
  server.send(200, "text/html", "Wi-fi Remote Control Example");
  return;
}

void handleNotFound(){
  server.send(404, "text/plain", "404: Not found"); // Send HTTP status 404 
               // (Not Found) when there's no handler for the URI in the request
  return;
}

void handleRequest() { // If a POST request is made to URI /command
  // Validate parameters
  if(!server.hasArg("pin") || !server.hasArg("value") || server.arg("pin") == NULL || 
                              server.arg("value") == NULL) { 
    server.send(400, "text/plain", "400: Invalid Request"); // The request is invalid, 
                                                            // so send HTTP status 400
    return;
  }
  
  // Get the parameters: pin and value
  String temp = "";
  temp = server.arg("pin"); 
  int pin = temp.toInt();
  temp = server.arg("value"); 
  int value = temp.toInt();

  Serial.println(pin);
  Serial.println(value);
  if (pin >= 0 && pin < 17 && value >= 0 && value <= 100) {
    if (pin == 0) {
      analogWrite(pin, value);
    } else {
      digitalWrite(pin, value);
    }
  }
  server.send(200, "text/html", "Wi-fi Remote Control Example");
  return;
}

关注点

  • WiFiMulti 库允许您配置多个 Wi-Fi 网络的身份验证,从而轻松连接。请根据您的网络替换 ssidpassword
  • mDNS 库允许为 Esp 本地网络命名一个 DNS。在这种情况下,我们不使用此功能,因为 Android 不支持它。
  • handleClient 方法启动一个循环,充当 Web 请求的监听器。
  • 有三个函数负责处理来自手机的请求:
    • 当 URI 未找到时,将触发 handleNotFound 函数。
    • 当收到标准的 GET 请求时,将触发 handleRoot function。在我们的情况下,此类响应被忽略。
    • server.on 条件触发的 handleRequest 函数负责处理由手机上的遥控器触发的 POST 请求。此时,我们将验证从遥控器发送的参数并采取适当的行动。

第三步:Web 应用

要开发遥控应用程序,我们需要下载 JQueryOnsenUI 库,并根据下面描述的结构将它们解压到相应的文件夹中:

  • app
    config.xml
    ← Phonegap 配置文件的位置
    • www
      index.html
      ← 主 HTML 文件
      • 资源文件
        • img ← 应用图标在此处
          icon-128.png
          icon-256.png
        • js
          wifi_rc.js
          ← 包含应用逻辑的 Js 文件
        • lib
          • Jquery ← 在此处解压 Jquery
          • Onsenui ← 在此处解压 Onsenui

此时,我们将关注 index.htmlwifi_rc.js 文件,它们负责我们遥控器的呈现和编程,如下所示:

index.html

<!--
  Wi-fi Remote Control with JQuery and Onsen UI
  Demo by José Cintra
  www.josecintra.com/blog
-->

<!DOCTYPE html>
<html lang="pt-br">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, 
          initial-scale=1, shrink-to-fit=no">
    <meta name="Author" content="José Cintra"
    <link rel="stylesheet" href="assets/lib/OnsenUI/css/onsenui.min.css">
    <link rel="stylesheet" href="assets/lib/OnsenUI/css/onsen-css-components.min.css">
  </head>

  <body>

  <ons-page modifier="material">

    <ons-toolbar modifier="material">
      <div class="center"><strong>Wi-Fi Remote Control</strong></div>
    </ons-toolbar>
    <br/>
    <ons-card modifier="material">

      <div class="content">
        <ons-list modifier="material">

          <ons-list-item modifier="material">
            <div class="center" >
              <strong>LED 1 &nbsp;</strong> <label id="led1v">OFF</label>
            </div>
            <div class="right">
              <ons-switch id="led1" class="sw" modifier="material"></ons-switch>&nbsp;
            </div>
          </ons-list-item >
          <ons-list-item modifier="material">
            <div class="center" >
              <strong>LED 2 &nbsp;</strong> <label id="led2v">OFF</label>
            </div>
            <div class="right">
              <ons-switch id="led2" class="sw" modifier="material"></ons-switch>
            </div>
          </ons-list-item>
          <ons-list-item modifier="material">
            <div class="center">
              <strong>LED 3 &nbsp;</strong> <label id="led3v">0</label>%
            </div>
            <div class="right">
              <ons-range id="led3" class="rg" modifier="material" 
               style="width: 100%;" value="0" max = "100" ></ons-range>
            </div>
          </ons-list-item>
        </ons-list>
      </div>
    </ons-card>

  </ons-page>

  <!-- Javascript -->
  <script src="assets/lib/OnsenUI/js/onsenui.min.js"></script>
  <script src="assets/lib/jquery/jquery-3.3.1.min.js"></script>
  <script src="assets/js/wifi_rc.js"></script>

</body>

</html>

wifi_rc.js

//
/* 
  Wi-fi Remote Control with JQuery and Onsen UI
  Demo by José Cintra
  www.josecintra.com/blog
*/

$(function () {

  // Server address and pin numbers of the board (ESP8266/32 and compatibles)
  let addr = "http://192.168.0.33/command"; 
  let pins = new Map([
    [ '#led1', '05' ],
    [ '#led2', '04' ],
    [ '#led3', '00' ], 
  ]);
   
  // Click Event on switch Class
  $('.sw').on('click', function (e) { 
    let onoff = ['OFF','ON'];
    let id = "#" + $(this).attr("id");          // Get the id of the control
    let pin = pins.get(id);                     // Pin number
    let value = String(+$(id).prop('checked')); // On or Off
    $(id + 'v').html(onoff[value]); 
    sendAjax(addr, pin, value);
  });

  // Input event on range class
  $('.rg').on('input', function (e) {
    let id = "#" + $(this).attr("id");          // Get the id of the control
    let value = String($(id).val());            // Input range
    $(id + 'v').html(value);                    // Notification
  });
  $('.rg').on('change', function (e) {
    let id = "#" + $(this).attr("id");          // Get the id of the control
    let pin = pins.get(id);                     // Pin number
    let value = String($(id).val());            // Input range
    sendAjax(addr, pin, value);
  });
});

function sendAjax(addr, p, v) {
  $.ajax({
    method: "POST",
    url: addr,
    data: {pin: p, value: v}
  });
}

关注点

  1. index.html 文件包含了应用程序的整个呈现部分,其中使用了 OnsenUI 框架提供的 CSS 元素。
  2. LED 1 和 LED 2 将由开关按钮控制,LED 3 将由 range 控件控制。重要的是要注意将在 JS 脚本中使用的 idclass 属性。
  3. wifi_rc.js 文件的 JavaScript 代码采用 ES6 标准。
  4. wifi_rc.js 文件中的 function() 事件仅在页面加载后发生一次。在这里,我们编程响应控件事件的操作。
  5. 为了表示 NodeMCU 中的引脚编号,我们使用 MAP 结构。这些信息将与控件的值一起传递给 sendAjax 方法,并发送到板的 Web 服务器。

第四步:手机应用程序

最后,在这一步,我们将生成可以安装在手机上的移动应用程序。为了使我们的 HTML5 应用程序能够作为原生应用安装,您需要使用 Phonegap 构建工具。
最简单的方法是使用 Phonegap Build云编译服务

步骤如下:

  1. Phonegap Build 服务中创建一个账户,选择付费或免费套餐。
  2. 创建将显示在手机上的应用程序图标。
  3. 创建一个 config.xml 文件并进行必要的设置。
  4. 压缩所有文件并上传进行编译。
  5. 请求应用程序编译。
  6. 选择所需的平台(Android、iPhone 或 Microsoft)并下载该平台的编译后的应用程序。

注意:图标文件必须是 png 格式,尺寸为 128 × 128 和 256 × 256。

以下是一个 config.xml 文件的示例:

config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<widget id="com.josecintra.wifi_rc" version="1.0.0" 
 xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="https://cordova.net.cn/ns/1.0">
    <name>Wi-fi Remote Control</name>
    <description>Example of building a wi-fi remote control with 
     HTML5/JQuery/Onsen UI and Phonegap. It will be used to control IoT devices, 
     such as NodeMCU and compatibles</description>
    <author href="http://www.josecintra.com/blog" 
     email="josecintra@josecintra.com">Jose Cintra</author>

    <icon src="www/assets/img/icon-256.png" width="256" 
          height="256" density="xxxhdpi" />
    <icon src="www/assets/img/icon-128.png" width="128" 
          height="128" density="xhdpi" />

    <preference name="android-targetSdkVersion" value="26" />

    <preference name="orientation" value="portrait" />
    <preference name="fullscreen" value="true" />
    <preference name="DisallowOverscroll" value="true" />
    
    <config-file parent="UIStatusBarHidden" platform="ios" 
                 target="*-Info.plist"><true/></config-file>
    <config-file parent="UIViewControllerBasedStatusBarAppearance" 
                 platform="ios" target="*-Info.plist"><false/></config-file>

    <preference name="deployment-target" value="10.0" />
    <preference name="android-minSdkVersion" value="21" />
    <access origin="*" />

    <plugin name="cordova-custom-config" />
    <plugin name="cordova-plugin-file" />
    <plugin name="cordova-plugin-media" />
    <plugin name="cordova-plugin-statusbar" />
    <plugin name="cordova-plugin-whitelist" />

    <engine name="ios" />
    <engine name="android" />
</widget>

关注点

config.xml 文件包含生成应用程序所需的所有信息。其中,我们重点介绍:

  • name:应用程序的名称。
  • description:应用程序的描述。
  • author:关于应用程序作者的信息。
  • icon:将标识手机上应用程序的图标的名称。
  • orientation:应用程序可以显示为portrait(竖屏)或landscape(横屏)模式。如果未设置此参数,应用程序将适应手机的倾斜。
  • access origin:定义应用程序可以访问的 URL。

除了这些之外,还有几十种其他设置。一个重要的点是选择插件,这些插件允许您为应用程序添加额外功能,例如访问相机、GPS 和手机的其他原生功能。有关构建过程的更多详细信息,请参阅此链接

第五步:安装应用程序

在上一步中,我们生成了一个可以安装在手机上或在应用商店中供下载的应用程序。在我们的例子中,我们生成了一个扩展名为 apk 的Android 应用程序

为了在不通过应用商店的情况下在手机上测试此应用,我们需要将 Android 配置为允许安装“未知来源”的应用。通常,此选项在安全部分。
之后,只需将应用程序复制到您的手机即可。这可以通过多种方式完成,例如 USB、Kies、Wi-Fi 或通过 Internet 链接。Android 本身将负责安装。

接下来是什么?

这是一个简单的物联网设备 Wi-Fi 遥控教学示例。此示例可以通过多种方式进行改进:

结束语

感谢阅读!
本教程中的所有文件都可以在 GitHub 上找到。啊!别忘了在 NodeMCU sketch 中配置您的 Wi-Fi 的 ssidpassword...

您可以在此处找到本文的葡萄牙语版本。

历史

  • 2019 年 1 月 6 日:初始版本
© . All rights reserved.