第11章:JavaScript/Node.js 物联网应用
JavaScript 已经不仅仅是浏览器的语言。通过 Node.js,它征服了服务器端;通过 Johnny-Five 等库,它甚至能控制硬件。JS 的事件驱动模型天然契合物联网的异步通信需求。
11.1 Node.js 后端开发
物联网平台需要处理海量并发连接,Node.js 的非阻塞 I/O 在这方面表现出色。
实战:构建一个简单的 HTTP 接收服务
使用 Express 框架接收传感器上传的数据。
const express = require('express');
const app = express();
app.use(express.json());
// 接收 POST 请求
app.post('/api/data', (req, res) => {
const { deviceId, temp, humidity } = req.body;
console.log(`Device: ${deviceId}, Temp: ${temp}, Hum: ${humidity}`);
// TODO: 保存到数据库
res.json({ status: 'success' });
});
app.listen(3000, () => {
console.log('IoT Server running on port 3000');
});11.2 前端可视化 (Dashboard)
物联网的一大价值在于数据可视化。我们将使用 ECharts 展示实时数据。
HTML/JS 代码片段
<div id="chart" style="width: 600px;height:400px;"></div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script>
var myChart = echarts.init(document.getElementById('chart'));
var option = {
title: { text: '实时温度监控' },
xAxis: { type: 'category', data: [] },
yAxis: { type: 'value' },
series: [{ data: [], type: 'line' }]
};
// 模拟实时数据更新
setInterval(function () {
var now = new Date().toLocaleTimeString();
var temp = (Math.random() * 10 + 20).toFixed(1);
option.xAxis.data.push(now);
option.series[0].data.push(temp);
// 保持最近 10 个数据点
if (option.xAxis.data.length > 10) {
option.xAxis.data.shift();
option.series[0].data.shift();
}
myChart.setOption(option);
}, 2000);
</script>11.3 Johnny-Five 硬件控制
Johnny-Five 是最流行的 JS 机器人编程框架,它运行在上位机(电脑/树莓派),通过 Firmata 协议控制 Arduino。
- 安装:
npm install johnny-five - 准备:在 Arduino 上烧录 "StandardFirmata" 示例程序。
代码实现:JS 控制 LED 闪烁
const { Board, Led } = require("johnny-five");
const board = new Board();
board.on("ready", () => {
const led = new Led(13);
led.blink(500); // 500ms 闪烁一次
console.log("LED is blinking!");
});11.4 项目实战:实时监控仪表盘
我们将整合 Node.js 后端、MQTT 和 Socket.io,实现一个网页端实时显示的温度监控系统。
架构
- 传感器 -> (MQTT) -> Node.js 服务器
- Node.js 服务器 -> (WebSocket) -> 浏览器前端
后端代码 (server.js)
const mqtt = require('mqtt');
const io = require('socket.io')(3001, {
cors: { origin: "*" }
});
const client = mqtt.connect('mqtt://broker.emqx.io');
client.on('connect', () => {
client.subscribe('home/livingroom/temp');
});
client.on('message', (topic, message) => {
const val = message.toString();
console.log(`MQTT received: ${val}`);
// 广播给所有连接的浏览器客户端
io.emit('temp_update', { value: val, time: new Date() });
});
console.log("Gateway started...");前端有了,后端有了,硬件也有了。但数据存在哪里呢?下一章我们将探讨数据处理与存储。