【MQTT学习】lesson10:实战 IoT+AI - 1

在接下来的课程里,我们来完成一个 IoT+AI 的实战项目。本节课核心内容:

  • 如何在 MQTT 里面传输大文件
  • 消息去重
  • 消息数据编码
  • 实现 Android 发布端
  • 发布识别结果

10.1 如何在 MQTT 里面传输大文件

我们前面提到过,一个 MQTT 数据包最大可以达到约 256M,所以对于传输图片的需求,最简单直接的方式就把图片数据直接包含在 PUBLISH 包里面进行传输。

还有一种更好的做法。在发布数据之前,先把图片上传到云端的某个图片存储里,然后 PUBLISH 包里面只包含图片的 URL,当订阅端接收这个数据之后,它再通过图片的 URL 来获取图片。这样的做法较前面有几个优点。

  • 对订阅端来说,它可以在有需要的时候再下载图片数据,而第一种做法,每次都必须接收图片的全部数据。
  • 这种做法可以处理文件大于 256M 的情况,而第一种做法,必须把文件分割为多个 PUBLISH 包,订阅端接收后再重新组合,非常麻烦。
  • 节省带宽,如果图片数据直接放在 PUBLISH 包中,那么 Broker 就需要预留相对大的带宽。目前在中国,带宽还是比较贵的。PUBLISH 包中只包含 URL 的话,每一个 PUBLISH 包都很小,那么 Broker 的带宽需求就很小了。虽然上传图片也需要带宽,但是如果你使用云存储,比如阿里云 OSS、七牛等,从它们那里购买上传和下载图片的带宽要便宜很多。同时,这些云存储服务商建设了很多 CDN,通常上传和下载图片比直接通过 PUBLISH 包传输要快一些。
  • 节约存储和处理能力,因为 Broker 需要存储 Client 未接收的消息,所以如果图片包含在 PUBLISH 包里面,Broker 需要预留相当的存储空间;而使用云存储的话,存储的成本比自建要便宜得多。

在这个实战项目里,我们用第二种方式来传输图片,使用七牛作为图片存储。

10.2 消息去重

为了兼顾效率和可靠性,我们使用 QoS1 来传输消息。QoS1 有一个问题,就是可能会收到重复的消息,所以需要在应用里面手动对消息进行去重。

我们可以在消息数据里面带一个唯一的消息 ID,通常是 UUID。订阅端需要保存已接收消息的 ID,当收到新消息的时候,通过消息的 ID 来判断是否是重复的消息,如果是,则丢弃。

10.3 消息数据编码

我们需要对消息数据进行编码,方便订阅端对数据进行解析。通常可以使用 JSON 格式,如果设备的计算和存储能力有限,也可以使用 Protocol Buffer 这类对内存消耗更少、解析更快的编码方式。

这个项目里面,我们使用 JSON 作为数据编码格式。一个消息数据格式如下:

{'id': <消息 ID>, timestamp:<UNIX 时间戳>, image_url: <图片>, objects:[图片中物体名称的数组]}

接下来我们先来实现数据的发布端。

10.4 实现 Android 发布端

10.4.1 连接到 Broker

首先包含 MQTT Android 库的依赖:

repositories {
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
    }
}


dependencies {
    compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
}

接下来连接到 Broker,注意这里使用 AndriodID 作为 Client Identifier 的一部分,保证 Client Identifier 不会冲突:

String clientId = "client_" + Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
            mqttAsyncClient = new MqttAsyncClient("tcp://iot.eclipse.org:1883", clientId, 
                    new MqttDefaultFilePersistence(getApplicationContext().getApplicationInfo().dataDir));
            mqttAsyncClient.connect(null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "已连接到 Broker", Toast.LENGTH_LONG).show();
                        }
                    });
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, final Throwable exception) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "连接 Broker 失败:" + exception.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    });
                }
            });

10.4.2 上传图片

首先包含七牛安卓库的依赖:

compile 'com.qiniu:qiniu-android-sdk:7.3.+'

然后上传图片:

uploadManager.put(getBytesFromBitmap(image), null, upToken, new UpCompletionHandler() {
            @Override
            public void complete(String key, ResponseInfo info, JSONObject response) {
                 if(info.isOK()){
                    //上传成功以后 PUBLISH
                 }
            }
        }, null);

10.5 发布识别结果

最后,在图片上传成功以后,将识别结果发布到“front_door/detection/objects”这个主题:

JSONObject jsonMesssage = new JSONObject();
                         jsonMesssage.put("id", randomUUID());
                         jsonMesssage.put("timestamp", timestamp);
                         jsonMesssage.put("objects", objects);
                         jsonMesssage.put("image_url", "http://" + QINIU_DOMAIN + "\\" + response.getString("key"));
                         mqttAsyncClient.publish("front_door/detection/objects", new MqttMessage(jsonMesssage.toString().getBytes()));

10.6 小结

本节课我们完成了 Android 发布端的代码,你可以在 https://github.com/sufish/object_detection_mqtt 找到全部代码。

相关资料

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻量级通信协议。在IoT项目中,MQTT协议可以用于控制远程外围设备,例如传感器、执行器等。 以下是使用MQTT协议控制IoT项目中远程外围设备的步骤: 1. 安装MQTT服务器:首先,需要安装一个MQTT服务器,例如Mosquitto或者EMQ。这个服务器将作为消息代理,接收来自发布者的消息,并将其传递给相应的订阅者。 2. 编写发布者代码:发布者是发送消息的设备或应用程序。在IoT项目中,发布者可以是传感器或者其他执行器。将你的设备连接到MQTT服务器,并通过发布者代码发送消息。 3. 编写订阅者代码:订阅者是接收消息的设备或应用程序。在IoT项目中,订阅者可以是控制设备的应用程序。将你的设备连接到MQTT服务器,并通过订阅者代码接收消息。 4. 订阅主题:发布者和订阅者需要共享主题。主题是一种标识符,用于将消息路由到正确的订阅者。在IoT项目中,主题可以是传感器的名称、执行器的名称或者其他标识符。在代码中,使用主题来指定要发布或订阅的消息。 5. 发送和接收消息:在代码中,使用MQTT客户端库来发送和接收消息。发布者将消息发送到指定的主题,订阅者将接收到该主题的消息。 使用MQTT协议可以轻松地控制IoT项目中的远程外围设备。通过发布者和订阅者代码,可以发送和接收消息,并将其路由到正确的设备。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值