在《DIY 物联网 4 - 遥控控制风扇》中实现了用空调遥控来控制一台普通的风扇,沿着上一章的基础,这一章我们来一个更酷的:用手机控制风扇。
开发板和手机通讯的方式
上一章我们实现遥控控制风扇,实际上是根据遥控红外信号指令控制连接风扇的继电器开关,现在我们要实现手机控制风扇,把遥控红外指令换成
手机发出的指令就能控制风扇了。我们能想到的几种方式:
- 蓝牙通讯:
利用手机的蓝牙功能,连接开发板,发送蓝牙信号,但是有个缺点是不好扩展,不能实现远程控制。
- 网络通讯:
利用开发板的网络访问能力,实现和手机的网络对接。网络通讯可以是简单的 HTTP 协议,也可以使用 TCP 协议,网络连接模型有两种方式:
直连模式:
控制端(手机)直接和开发板进行网络通讯,这只方式只能在局域网中使用,因为公网访问需要为开发板申请公网 ip 不太现实。
服务器中转模式:
控制端和开发板都能连上云服务,通过服务器实现交互。这种方式不仅能实现通讯控制、还能采集各端的数据、对数据进行分析,这就是 万物连接+大数据的基本模型,当然个人实现成本太大。服务 IoT 的云平台已经有了,阿里云就有这部分的服务。
直连模式实现
作为学习我们先用最简单的连接方式:直连模式。在 Ruff 启动并启动 WIFI 热点之后进入 console.ruff.io ,配置
开发板的网络访问能力,然后就可以对 Ruff 进行网络编程了,Ruff 提供了丰富的 API 满足网络通讯的需求,详细可以了解官方 API 文档:https://ruff.io/zh-cn/api/http.html。现在我们在 Ruff 实现一个 httpServer 的程序:
httpControl.js
'use strict';
function createServer(callback) {
var PORT = 3000;
var http = require('http');
var url=require('url');
var queryString = require("querystring");
var datas={};
var server = http.createServer(function (request, response) {
var query=url.parse(request.url).query;
datas = queryString.parse(query);
callback.exeCmd(datas.cmd);
response.write(callback.getRelayStatus()? 'true':'false');
response.end();
});
server.listen(PORT);
console.log("Server runing at port: " + PORT + ".");
}
module.exports.listenCMD = createServer;
这里我们把对 http 的实现简单封装成一个模块,共其他模块使用。逻辑很简单:在 3000 端口监听网络请求,并解析请求参数,把请求参数传入回调函数供调用方使用, 最后把继电器的开关状态响应到客户端。接着上一章的基础,我们来修改 index.js:
var netControl = require('./netcontrol');
var relayOpen = false;
function controlRelay(open){
if (open) {
$('#relay').turnOn(function () {
// 打开继电器成功的回调函数
console.log('turn on');
});
} else {
$('#relay').turnOff(function () {
// 关闭继电器成功的回调函数
console.log('turn off');
});
}
relayOpen = open;
}
$.ready(function (error) {
if (error) {
console.log(error);
return;
}
netControl.listenCMD({
exeCmd:function (cmd) {
if (cmd === 'openRelay') {
controlRelay(true)
} else {
controlRelay(false)
}
},
getRelayStatus: function () {
return relayOpen;
}
});
});
$.end(function () {
$('#relay').turnOff(function () {
console.log('turn off');
});
});
客户端实现
客户端实现很简单,就一个简单的静态 html ,提供两个按钮:开和关,按钮被点击的时候向开发板发起 http 请求,你要知道开发板的内内网 ip,访问 192.168.78.1 ,可以看到你的开发板的网络配置包括 ip。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
button {
width: 100%;
height: 100px;
color: aliceblue;
font-size: 50px;
padding: 16px;
}
</style>
</head>
<body>
<div id="status"></div>
<button style="background: darkgreen" onclick="onButtonClick('openRelay')">打开风扇</button>
<button style="background: orangered" onclick="onButtonClick('offRelay')">关闭风扇</button>
</body>
<script>
function post(url, content, callback) {
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
callback(null,xmlhttp.responseText);
} else {
};
};
xmlhttp.open("POST",url,true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(content);
}
function onButtonClick(cmd){
// 192.168.1.109 替换成你自己的 ip
post('http://192.168.1.109:3000?cmd=' + cmd,'',function (err,res) {
alert(res);
document.getElementById('status').innerHTML = res;
})
}
</script>
</html>