Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

Node.js 和 树莓派 - 带 WebSocket 的 Web 服务器


什么是 WebSocket?

WebSocket 允许通过 Web 实时进行双向通信。

WebSocket 可以与普通的 HTTP 服务器一起运行。您可以点击网页浏览器中的按钮,并启用树莓派的 GPIO,从而打开您家中的灯。所有这些都在实时进行,并且通信是双向的!

在本节中,我们将设置一个带 WebSocket 的 Web 服务器。然后创建一个浏览器 UI 来与我们之前的示例交互,即 用按钮控制 LED 的开关


我需要什么?

本教程需要树莓派。在我们的示例中,我们使用树莓派 3,但本教程应该适用于大多数版本。

您需要

点击上面列表中的链接查看不同组件的描述。

注意:您需要的电阻可能与我们使用的不同,具体取决于您使用的 LED 类型。大多数小型 LED 只需要一个小电阻,大约 200-500 欧姆。电阻的具体值通常不是关键,但电阻值越小,LED 的亮度越高。

与我们之前的示例相比,我们唯一需要新增的是设置 Web 服务器,以及安装 socket.io 模块。


树莓派和 Node.js 的 Web 服务器

根据本 Node.js 教程中之前的章节,让我们设置一个可以提供 HTML 文件的 Web 服务器。

在我们的 "nodetest" 目录中,创建一个新目录,我们可以用来存放静态 html 文件

pi@w3demopi:~/nodetest $ mkdir public

现在让我们设置一个 Web 服务器。创建一个 Node.js 文件,它打开请求的文件并将内容返回给客户端。如果出现错误,则抛出 404 错误。

pi@w3demopi:~/nodetest $ nano webserver.js

webserver.js

var http = require('http').createServer(handler); // 导入 http 服务器,并使用 handler() 函数创建服务器
var fs = require('fs'); // 导入文件系统模块

http.listen(8080); // 监听端口 8080

function handler (req, res) { // 创建服务器
  fs.readFile(__dirname + '/public/index.html', function(err, data) { // 读取 public 文件夹中的 index.html 文件
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'}); // 错误时显示 404
      return res.end("404 Not Found");
    }
    res.writeHead(200, {'Content-Type': 'text/html'}); // 写入 HTML
    res.write(data); // 写入来自 index.html 的数据
    return res.end();
  });
}

转到 "public" 文件夹

pi@w3demopi:~/nodetest $ cd public

并创建一个 HTML 文件,index.html

pi@w3demopi:~/nodetest/public $ nano index.html

index.html

<!DOCTYPE html>
<html>
<body>

<h1>控制 LED 灯</h1>
<input id="light" type="checkbox">LED

</body>
</html>

此文件目前没有功能。现在它只是一个占位符。让我们看看 Web 服务器是否正常工作

pi@w3demopi:~/nodetest/public $ cd ..
pi@w3demopi:~/nodetest $ node webserver.js

使用 http://[RaspberryPi_IP]:8080/ 在浏览器中打开网站。

Web 服务器现在应该已经启动并运行,我们可以继续进行 WebSocket 部分。


为 Node.js 安装 socket.io

在 Web 服务器设置完毕后,更新您的树莓派系统包到最新版本。

更新您的系统包列表

pi@w3demopi:~ $ sudo apt-get update

将所有已安装的包升级到最新版本

pi@w3demopi:~ $ sudo apt-get dist-upgrade

定期执行此操作将使您的树莓派安装保持最新。

要下载并安装最新版本的 socket.io,请使用以下命令

pi@w3demopi:~ $ npm install socket.io --save


在 Web 服务器中添加 WebSocket

现在我们可以使用 WebSocket 在应用程序中。让我们更新我们的 index.html 文件

index.html

<!DOCTYPE html>
<html>
<body>

<h1>控制 LED 灯</h1>
<p><input type="checkbox" id="light"></p>

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> <!-- 包含 socket.io 客户端脚本 -->
<script>
var socket = io(); // 加载 socket.io-client 并连接到提供页面的主机
window.addEventListener("load", function(){ // 页面加载时
  var lightbox = document.getElementById("light");
  lightbox.addEventListener("change", function() { // 添加复选框更改时的事件监听器
    socket.emit("light", Number(this.checked)); // 将按钮状态发送到服务器(作为 1 或 0)
  });
});
socket.on('light', function (data) { // 从客户端获取按钮状态
  document.getElementById("light").checked = data; // 根据树莓派的按钮更改复选框
  socket.emit("light", data); // 将按钮状态发送回服务器
});
</script>

</body>
</html>

以及我们的 webserver.js 文件

webserver.js

var http = require('http').createServer(handler); // 导入 http 服务器,并使用 handler() 函数创建服务器
var fs = require('fs'); // 导入文件系统模块
var io = require('socket.io')(http) // 导入 socket.io 模块并将 http 对象(服务器)传递给它

http.listen(8080); // 监听端口 8080

function handler (req, res) { // 创建服务器
  fs.readFile(__dirname + '/public/index.html', function(err, data) { // 读取 public 文件夹中的 index.html 文件
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'}); // 错误时显示 404
      return res.end("404 Not Found");
    }
    res.writeHead(200, {'Content-Type': 'text/html'}); // 写入 HTML
    res.write(data); // 写入来自 index.html 的数据
    return res.end();
  });
}

io.sockets.on('connection', function (socket) {// WebSocket 连接
  var lightvalue = 0; // 用于当前状态的静态变量
  socket.on('light', function(data) { // 从客户端获取灯开关状态
    lightvalue = data;
    if (lightvalue) {
      console.log(lightvalue); // 打开或关闭 LED,目前我们只会在 console.log 中显示它
    }
  });
});

让我们测试服务器

pi@w3demopi:~ $ node webserver.js

使用 http://[RaspberryPi_IP]:8080/ 在浏览器中打开网站。

现在服务器应该将复选框的所有更改输出到树莓派的控制台。

客户端正在将更改发送到服务器,服务器正在响应。

让我们添加 按钮控制的 LED,它来自上一章。


添加硬件并向客户端发送响应

让我们再次更新我们的 webserver.js 文件。我们将使用上一章“按钮控制的 LED”中的大部分代码。

webserver.js

var http = require('http').createServer(handler); // 导入 http 服务器,并使用 handler() 函数创建服务器
var fs = require('fs'); // 导入文件系统模块
var io = require('socket.io')(http) // 导入 socket.io 模块并将 http 对象(服务器)传递给它
var Gpio = require('onoff').Gpio; // 导入 onoff 以与 GPIO 交互
var LED = new Gpio(4, 'out'); // 使用 GPIO 引脚 4 作为输出
var pushButton = new Gpio(17, 'in', 'both'); // 使用 GPIO 引脚 17 作为输入,以及 "both" 按下和松开按钮,应该处理

http.listen(8080); // 监听端口 8080

function handler (req, res) { // 创建服务器
  fs.readFile(__dirname + '/public/index.html', function(err, data) { // 读取 public 文件夹中的 index.html 文件
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'}); // 错误时显示 404
      return res.end("404 Not Found");
    }
    res.writeHead(200, {'Content-Type': 'text/html'}); // 写入 HTML
    res.write(data); // 写入来自 index.html 的数据
    return res.end();
  });
}

io.sockets.on('connection', function (socket) {// WebSocket 连接
  var lightvalue = 0; // 用于当前状态的静态变量
  pushButton.watch(function (err, value) { // 监控 pushButton 的硬件中断
    if (err) { // 如果发生错误
      console.error('发生了错误', err); // 将错误消息输出到控制台
      return;
    }
    lightvalue = value;
    socket.emit('light', lightvalue); // 将按钮状态发送到客户端
  });
  socket.on('light', function(data) { // 从客户端获取灯开关状态
    lightvalue = data;
    if (lightvalue != LED.readSync()) { // 只有在状态发生更改时才更改 LED
      LED.writeSync(lightvalue); // 打开或关闭 LED
    }
  });
});

process.on('SIGINT', function () { // 按下 Ctrl+C
  LED.writeSync(0); // 关闭 LED
  LED.unexport(); // 取消导出 LED GPIO 以释放资源
  pushButton.unexport(); // 取消导出按钮 GPIO 以释放资源
  process.exit(); // 完全退出
});

让我们测试服务器

pi@w3demopi:~ $ node webserver.js

使用 http://[RaspberryPi_IP]:8080/ 在浏览器中打开网站。

现在服务器应该将复选框的所有更改输出到树莓派的控制台。

客户端正在将更改发送到服务器,服务器正在响应。

使用 Ctrl+c 结束程序。


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
[email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
[email protected]

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2024 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.