1.物联网云平台

为了先树立物联网平台通信过程的意识,为之后自己编写物联网云平台提供借鉴,我们该篇教程中使用的物联网云平台是阿里云的物联网套件(现已更名物联网平台)。阿里云收费规则是每月前100万条消息数免费赠送,所以这对于我们个人使用已绰绰有余。

如何开启阿里云物联网平台服务以及基础配置可参见产品手册

这里我们使用的协议为MQTT,关于MQTT协议,可参见博主的另一篇科普文MQTT初探。阿里云在MQTT消息发送接收的基本流程如下:

阿里云物联网平台架构.jpg

  • 在设备上报发布数据时,需要在阿里云开启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");
    }
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,其它的就不多说了。我自己设计的最后界面如下。

阿里云物联网平台架构.jpg

3.总结

至此,就可以通过手机远程控制空调啦~

后续的文章将介绍如何定时开启关闭空调,以及搭建自己的物联网云平台。