各位好,我是老码农,今天咱们聊聊怎么把Vue这个前端小清新,嫁接到硬邦邦的物联网设备里,让它俩产生爱情的火花。别怕,其实没那么玄乎,老码农保证把这事儿讲得像唠家常一样。
开场白:Vue和IoT,看似八竿子打不着?
Vue,前端框架,长在浏览器里,负责貌美如花,展示数据、处理交互。IoT,物联网,扎根在各种设备里,负责辛勤劳作,采集数据、控制硬件。
表面上看,一个在云端,一个在田间地头,风马牛不相及。但实际上,很多物联网应用都需要一个用户界面,用来展示设备状态、配置参数、进行远程控制。而Vue,就是这个界面的完美人选。
第一幕:选个靠谱的硬件载体
首先,得有个能跑Vue的家伙。别指望在洗衣机上直接跑,那不现实。我们需要一个具备一定计算能力和网络连接能力的设备,比如:
- 树莓派 (Raspberry Pi): 便宜、强大、社区活跃,简直是IoT界的瑞士军刀。
- ESP32/ESP8266: 体积小、功耗低,适合资源受限的场景,但跑Vue有点吃力,需要一些优化。
- 其他嵌入式Linux设备: 各种ARM架构的开发板,选择丰富,根据需求选择。
咱们今天就拿树莓派开刀,因为它最容易上手,而且能满足大部分IoT应用的需求。
第二幕:Vue项目,搭个架子先
在你的电脑上,用Vue CLI创建一个新的项目:
vue create my-iot-app
一路回车选择默认配置,或者根据自己的喜好配置。
然后,进入项目目录:
cd my-iot-app
第三幕:通信桥梁,Node.js来帮忙
Vue是前端,硬件是后端,它们之间需要一座桥梁。Node.js,就是这座桥梁的最佳人选。它能用JavaScript写后端代码,而且Node.js的生态系统里有很多IoT相关的库,能方便地与硬件设备通信。
-
安装Node.js: 确保你的树莓派上已经安装了Node.js。
-
创建API: 在Vue项目的
public
目录下(如果没有就创建一个),创建一个api
文件夹,然后在里面创建一个server.js
文件。这个文件就是我们的Node.js服务器。// api/server.js const http = require('http'); const fs = require('fs'); const path = require('path'); const hostname = '0.0.0.0'; // 监听所有IP const port = 3000; const server = http.createServer((req, res) => { // 允许跨域请求 (CORS) res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.statusCode = 200; res.end(); return; } const url = req.url; if (url === '/api/temperature') { // 模拟读取温度数据 const temperature = Math.floor(Math.random() * 30 + 10); // 10-40度 res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ temperature: temperature })); } else if (url === '/api/led') { // 模拟控制LED if (req.method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { try { const data = JSON.parse(body); const ledState = data.state; // 在这里模拟控制LED的代码,例如写入文件 // fs.writeFileSync('/path/to/led/control', ledState ? '1' : '0'); console.log('LED State:', ledState); res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ message: 'LED control success', state: ledState })); } catch (error) { res.statusCode = 400; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ error: 'Invalid JSON' })); } }); } else { res.statusCode = 405; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ error: 'Method Not Allowed' })); } } else { res.statusCode = 404; res.setHeader('Content-Type', 'text/plain'); res.end('Not Found'); } }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
这个
server.js
模拟了两个API接口:/api/temperature
: 返回一个随机温度值。/api/led
: 接收一个POST请求,包含LED的状态(state: true/false
),并模拟控制LED。
重要提示: 在真实的IoT应用中,你需要将这些API接口与你的硬件设备连接起来。例如,你可以使用Node.js的
serialport
库来读取串口数据,或者使用rpio
库来控制GPIO引脚。 -
启动Node.js服务器: 在
api
目录下,运行:node server.js
你应该能在控制台上看到
Server running at http://0.0.0.0:3000/
这样的信息。
第四幕:Vue,冲啊!调用API,展示数据
现在,我们可以回到Vue项目,调用刚刚创建的API接口,展示数据,并进行控制。
-
安装Axios: 在Vue项目中,安装Axios,一个用于发送HTTP请求的库:
npm install axios
-
修改组件: 修改
src/components/HelloWorld.vue
组件,添加以下代码:<template> <div class="hello"> <h1>{{ msg }}</h1> <p>当前温度:{{ temperature }} °C</p> <button @click="toggleLed"> {{ ledState ? '关闭LED' : '打开LED' }} </button> </div> </template> <script> import axios from 'axios'; export default { name: 'HelloWorld', props: { msg: String }, data() { return { temperature: 0, ledState: false, }; }, mounted() { this.getTemperature(); }, methods: { async getTemperature() { try { const response = await axios.get('http://localhost:3000/api/temperature'); this.temperature = response.data.temperature; } catch (error) { console.error('获取温度失败:', error); } }, async toggleLed() { try { const response = await axios.post('http://localhost:3000/api/led', { state: !this.ledState }); this.ledState = response.data.state; } catch (error) { console.error('控制LED失败:', error); } }, }, }; </script> <style scoped> .hello { text-align: center; } </style>
这段代码做了以下事情:
- 使用
axios.get
请求/api/temperature
接口,获取温度数据,并更新temperature
变量。 - 使用
axios.post
请求/api/led
接口,发送LED状态,并更新ledState
变量。 - 在模板中,展示温度数据,并根据
ledState
变量显示不同的按钮文字。
- 使用
-
运行Vue项目: 在Vue项目根目录下,运行:
npm run serve
你应该能在浏览器中看到一个简单的界面,显示当前的温度,并有一个按钮可以控制LED。
第五幕:部署到树莓派,让它真正跑起来
现在,我们需要把Vue项目部署到树莓派上,让它真正跑起来。
-
构建Vue项目: 在Vue项目根目录下,运行:
npm run build
这会在项目根目录下创建一个
dist
文件夹,里面包含了编译后的静态文件。 -
上传文件: 将
dist
文件夹中的所有文件,以及api
文件夹(包含server.js
文件),上传到树莓派的某个目录,例如/home/pi/iot-app
。 -
安装serve (可选): 如果你不想配置Nginx等Web服务器,可以使用
serve
这个简单的HTTP服务器来提供静态文件服务。在树莓派上安装:npm install -g serve
-
启动服务: 在树莓派的
/home/pi/iot-app
目录下,分别启动Node.js服务器和serve
:node api/server.js & serve -s dist -l 5000 &
node api/server.js &
在后台运行Node.js服务器。serve -s dist -l 5000 &
在后台运行serve
,将dist
文件夹作为静态文件目录,监听5000端口。
-
访问应用: 在浏览器中输入树莓派的IP地址,加上5000端口,例如
http://192.168.1.100:5000
,你应该就能看到运行在树莓派上的Vue应用了。
第六幕:与硬件通信,玩点真的
前面我们只是模拟了温度数据和LED控制。现在,让我们来玩点真的,把Vue应用与真实的硬件设备连接起来。
-
连接硬件: 假设我们使用一个DHT11温湿度传感器和一个LED灯。将DHT11的数据引脚连接到树莓派的GPIO4,将LED的正极通过一个限流电阻连接到树莓派的GPIO17,负极接地。
-
安装rpio: 在树莓派上安装
rpio
库,用于控制GPIO引脚:npm install rpio
-
修改server.js: 修改
api/server.js
文件,使用rpio
库读取DHT11的温度数据,并控制LED的开关:// api/server.js const http = require('http'); const rpio = require('rpio'); const hostname = '0.0.0.0'; const port = 3000; const DHT11_PIN = 4; // DHT11数据引脚连接到GPIO4 const LED_PIN = 17; // LED连接到GPIO17 // 初始化GPIO rpio.open(LED_PIN, rpio.OUTPUT, rpio.LOW); // 初始化LED为关闭状态 function readDHT11() { // 这里需要使用一个DHT11的Node.js库来读取数据 // 因为直接使用rpio读取DHT11数据比较复杂 // 可以考虑使用 `node-dht-sensor` 或 `dht-sensor` // 这里为了简化,我们仍然使用模拟数据 const temperature = Math.floor(Math.random() * 30 + 10); // 10-40度 const humidity = Math.floor(Math.random() * 80 + 20); // 20-100% return { temperature, humidity }; } const server = http.createServer((req, res) => { // 允许跨域请求 (CORS) res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.statusCode = 200; res.end(); return; } const url = req.url; if (url === '/api/temperature') { // 读取温度数据 const { temperature, humidity } = readDHT11(); res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ temperature: temperature, humidity: humidity })); } else if (url === '/api/led') { // 控制LED if (req.method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { try { const data = JSON.parse(body); const ledState = data.state; // 控制LED rpio.write(LED_PIN, ledState ? rpio.HIGH : rpio.LOW); console.log('LED State:', ledState); res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ message: 'LED control success', state: ledState })); } catch (error) { res.statusCode = 400; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ error: 'Invalid JSON' })); } }); } else { res.statusCode = 405; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ error: 'Method Not Allowed' })); } } else { res.statusCode = 404; res.setHeader('Content-Type', 'text/plain'); res.end('Not Found'); } }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
重要提示: 由于
rpio
库需要root权限才能访问GPIO引脚,所以你需要使用sudo
命令来启动Node.js服务器:sudo node api/server.js &
-
修改Vue组件: 修改
src/components/HelloWorld.vue
组件,添加湿度数据的展示:<template> <div class="hello"> <h1>{{ msg }}</h1> <p>当前温度:{{ temperature }} °C</p> <p>当前湿度:{{ humidity }} %</p> <button @click="toggleLed"> {{ ledState ? '关闭LED' : '打开LED' }} </button> </div> </template> <script> import axios from 'axios'; export default { name: 'HelloWorld', props: { msg: String }, data() { return { temperature: 0, humidity: 0, ledState: false, }; }, mounted() { this.getTemperature(); }, methods: { async getTemperature() { try { const response = await axios.get('http://localhost:3000/api/temperature'); this.temperature = response.data.temperature; this.humidity = response.data.humidity; } catch (error) { console.error('获取温度失败:', error); } }, async toggleLed() { try { const response = await axios.post('http://localhost:3000/api/led', { state: !this.ledState }); this.ledState = response.data.state; } catch (error) { console.error('控制LED失败:', error); } }, }, }; </script> <style scoped> .hello { text-align: center; } </style>
现在,当你访问Vue应用时,你应该能看到真实的温度和湿度数据,并且可以控制LED的开关了。
总结:Vue + IoT,无限可能
今天我们只是简单地演示了如何将Vue应用集成到物联网设备中,并与硬件设备进行通信。实际上,Vue和IoT的结合,可以创造出无限的可能性。
应用场景 | 描述 |
---|---|
智能家居 | 使用Vue构建用户界面,控制家中的灯光、电器、窗帘等。 |
工业自动化 | 使用Vue构建监控面板,实时显示生产线上的各种数据,并进行远程控制。 |
农业物联网 | 使用Vue构建农场管理系统,监控土壤湿度、温度、光照等数据,并进行自动灌溉、施肥等操作。 |
智能交通 | 使用Vue构建车载信息系统,显示车辆状态、导航信息、交通路况等。 |
医疗健康 | 使用Vue构建远程医疗监控系统,实时监测患者的生理指标,并进行远程诊断。 |
当然,在实际应用中,你还需要考虑很多因素,例如:
- 安全性: 保护设备和数据的安全,防止恶意攻击。
- 稳定性: 确保设备能够长时间稳定运行。
- 可维护性: 方便对设备进行远程维护和升级。
但总的来说,Vue和IoT的结合,是一种非常有前景的技术方向。希望今天的讲座能给你带来一些启发,让你也能创造出属于自己的物联网应用。
老码农就讲到这里,祝大家编程愉快! 各位下次再见!