1.物联网云平台
为了先树立物联网平台通信过程的意识,为之后自己编写物联网云平台提供借鉴,我们该篇教程中使用的物联网云平台是阿里云的物联网套件(现已更名物联网平台)。阿里云收费规则是每月前100万条消息数免费赠送
,所以这对于我们个人使用已绰绰有余。
如何开启阿里云物联网平台服务以及基础配置可参见产品手册。
这里我们使用的协议为MQTT,关于MQTT协议,可参见博主的另一篇科普文MQTT初探。阿里云在MQTT消息发送接收的基本流程如下:
- 在设备上报发布数据时,需要在阿里云开启MNS(消息中间件服务),上报的数据将暂存在消息队列中,用户需要自己去取出数据,或添加规则引擎,触发消息转发;
- 在控制端发布数据到设备端时,控制端不需要运行MQTT客户端,可以通过云端API请求到阿里云MQTT服务器代理,由代理将消息下发至设备端。
- 如果控制端在发送数据后希望得到设备端的返回消息,整个流程只需要在设备接收到消息后发布一则消息即可(阿里云已封装该topic,不需用户自己去消息队列中取设备返回的数据)。
2.实战
准备:这里设备端就是我们前几篇文章中的树莓派红外遥控系统
,控制端是我们的手机安卓客户端
,我们需要实现由安卓手机远程控制红外发射。
注意:本以为安卓客户端直接使用物联网云平台的云端API java库,直接调用就可以实现消息发布,但是too naive了,这个java库中的HttpClient
版本与安卓系统的HttpClient
版本冲突,无法运行或者编译(貌似Android Studio可以配置使用哪个库,博主使用的是eclipse就不便尝试了)。所以下文中博主将通过自己的VPS运行PHP做代理,来调用云端API。
(1)树莓派运行阿里云平台SDK
首先,我们需要对mqtt运行的示例代码进行修改,文件为:iotkit-embedded-master/sample/mqtt/mqtt-example.c
,修改两处。
- 订阅的主题,先在阿里云管理平台处新增主题
air_condition
; - 再在代码中修改主题为
"/"PRODUCT_KEY"/"DEVICE_NAME"/air_condition"
,如下:
32 /* These are pre-defined topics */
33 #define TOPIC_UPDATE "/"PRODUCT_KEY"/"DEVICE_NAME"/update"
34 #define TOPIC_ERROR "/"PRODUCT_KEY"/"DEVICE_NAME"/update/error"
35 #define TOPIC_GET "/"PRODUCT_KEY"/"DEVICE_NAME"/get"
36 #define TOPIC_DATA "/"PRODUCT_KEY"/"DEVICE_NAME"/air_condition"
- 默认
mqtt-example.c
中运行完就直接退出了,我们需要将它设置成死循环等待,修改mqtt_client
函数中代码如下:
206 /* Subscribe the specific topic */
207 rc = IOT_MQTT_Subscribe(pclient, TOPIC_DATA, IOTX_MQTT_QOS1, _demo_message_arrive, NULL);
208 if (rc < 0) {
209 IOT_MQTT_Destroy(&pclient);
210 EXAMPLE_TRACE("IOT_MQTT_Subscribe() failed, rc = %d", rc);
211 rc = -1;
212 goto do_exit;
213 }
214
215 HAL_SleepMs(1000);
216
217 do {
218 IOT_MQTT_Yield(pclient, 200);
219
220 HAL_SleepMs(500);
221 } while (1);
- 最后,在接收消息的地方添加处理流程,对接收的消息进行判断,根据消息内容调用空调控制可执行文件,修改的函数为
_demo_message_arrive
。这里需要注意可执行文件的路径,我这里是将可执行文件链接在了/bin
目录下,实际情况需要自己修改。
static void _demo_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
/* print topic name and topic message */
EXAMPLE_TRACE("----");
EXAMPLE_TRACE("Topic: '%.*s' (Length: %d)",
ptopic_info->topic_len,
ptopic_info->ptopic,
ptopic_info->topic_len);
EXAMPLE_TRACE("Payload: '%.*s' (Length: %d)",
ptopic_info->payload_len,
ptopic_info->payload,
ptopic_info->payload_len);
EXAMPLE_TRACE("----");
if(0 == strncmp(ptopic_info->payload, "on", 2))
{
system("aircontrol n");
}
else if(0 == strncmp(ptopic_info->payload, "off", 3))
{
system("aircontrol f");
}
- 直接在树莓派上编译(或者在PC上交叉编译)SDK即可,参考建立设备与平台的连接。编译完成后运行
iotkit-embedded/output/release/bin/mqtt-example
这里是前台运行,终端关闭程序就停止了。如果想开启后后台运行,可以在/etc/rc.local
文件中添加
/自己的路径/iotkit-embedded/output/release/bin/mqtt-example &
(2)php端的发布接口
设备端OK后,我们接下来增加控制端。控制端为VPS,为了便于访问,使用的语言为PHP
。云端SDK不需安装只需下载后放在目录下即可,创建文件iot.php
,添加代码如下,配置可执行权限后通过url即可访问,GET参数决定了发布的内容。
<?php
include_once 'aliyun-php-sdk-core/Config.php';
use \Iot\Request\V20170420 as Iot;
if(!isset($_GET['action']))
{
return;
}
$action = $_GET['action'];
$accessKeyId = "XXXaccessKeyId XXX";
$accessSecret = "XXXaccessSecret XXX";
$iClientProfile = DefaultProfile::getProfile("cn-shanghai", $accessKeyId, $accessSecret);
$client = new DefaultAcsClient($iClientProfile);
$request = new Iot\PubRequest();
$request->setProductKey("XXXProductKeyXXX");
$request->setMessageContent(base64_encode($action)); //hello world Base64 String.
$request->setTopicFullName("/XXXProductKeyXXX/raspberry/air_condition");
$response = $client->getAcsResponse($request);
print_r($response);
(3)安卓端通过访问PHP端发布消息
安卓端比较简单,就添加个界面里面放个按钮,按钮按下访问上面php文件的url,根据开关的不同状态携带不同的GET参数。这里网络访问库使用的是okhttp
,其它的就不多说了。我自己设计的最后界面如下。
3.总结
至此,就可以通过手机远程控制空调啦~
后续的文章将介绍如何定时开启关闭空调,以及搭建自己的物联网云平台。