在全球智能手机市场里,谷歌开发的Android移动操作系统市场占有率已经高达90%。随着物联网智能硬件升级,也逐渐成为智能摄像头,智能对讲门禁,人脸识别闸机,智能电视,智能广告屏等 IoT 设备的首选操作系统。
《物联网开发实战》本期为大家详细讲解 Android 设备通过 MQTT 协议接入阿里云 IoT 物联网平台的完整过程。
目录:
阿里云 IoT 物联网云端开发
使用Android Studio开发设备端程序
联机运行,日志详解
IoT 物联网平台
1.免费开通阿里云 IoT物联网云服务:
https://www.aliyun.com/product/iot-deviceconnect
2.创建产品,选择自定义品类,直连设备:
3.添加产品功能定义,我们以采集Android设备的硬件厂商、型号、Android版本、SDK版本信息为例:
物模型属性通信Topic和Payload如下:
// 属性上报 Topic:/sys/{productKey}/{deviceName}/thing/event/property/post// 属性 Payload:{ "id":123452452, "version":"1.0", "params":{ "brand":"HUAWEI", "model":"ELE-AL00", "android":"10", "sdk":29 }, "method":"thing.event.property.post"}
参考文档:
https://help.aliyun.com/document\_detail/89301.html
4.注册设备,此时设备为未激活状态。
点击DeviceSecret的查看,获取身份三元组。
Android 设备开发
5.Android应用程序依赖
Gradle 配置:
repositories { maven { url "https://repo.eclipse.org/content/repositories/paho-releases/" }}dependencies { implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.2' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'}
MANIFEST 配置:
<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><application> <!-- Mqtt Service --> <service android:name="org.eclipse.paho.android.service.MqttService" /></application>
6.设备三元组生成MQTT 的CONNECT参数转换工具
import javax.crypto.Mac;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;import java.util.Arrays;import java.util.Map;/** * AliyunIoTSignUtil */public class AliyunIoTSignUtil { public static String sign(Map<String, String> params, String deviceSecret, String signMethod) { //将参数Key按字典顺序排序 String[] sortedKeys = params.keySet().toArray(new String[] {}); Arrays.sort(sortedKeys); //生成规范化请求字符串 StringBuilder canonicalizedQueryString = new StringBuilder(); for (String key : sortedKeys) { if ("sign".equalsIgnoreCase(key)) { continue; } canonicalizedQueryString.append(key).append(params.get(key)); } try { String key = deviceSecret; return encryptHMAC(signMethod,canonicalizedQueryString.toString(), key); } catch (Exception e) { throw new RuntimeException(e); } } /** * HMACSHA1加密 * */ public static String encryptHMAC(String signMethod,String content, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), signMethod); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); byte[] data = mac.doFinal(content.getBytes("utf-8")); return bytesToHexString(data); } public static final String bytesToHexString(byte[] bArray) { StringBuffer sb = new StringBuffer(bArray.length); String sTemp; for (int i = 0; i < bArray.length; i++) { sTemp = Integer.toHexString(0xFF & bArray[i]); if (sTemp.length() < 2) { sb.append(0); } sb.append(sTemp.toUpperCase()); } return sb.toString(); }}
7.设备发起建立 MQTT 连接
public void connectMqtt(String url, String clientId, String mqttUsername, String mqttPassword) throws Exception { mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), url, clientId); MqttConnectOptions connOpts = new MqttConnectOptions(); // MQTT 3.1.1 connOpts.setMqttVersion(4); connOpts.setAutomaticReconnect(true); connOpts.setCleanSession(true); connOpts.setUserName(mqttUsername); connOpts.setPassword(mqttPassword.toCharArray()); connOpts.setKeepAliveInterval(60); mqttAndroidClient.setCallback(new MqttCallbackExtended() { @Override public void connectComplete(boolean reconnect, String serverURI) { postTopic(); } @Override public void connectionLost(Throwable cause) { Log.d(TAG, "connectionLost " + cause.getMessage()); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { Log.d(TAG, "messageArrived topic=" + topic+", message=" + new String(message.getPayload())); //此处为收到的云端数据 } @Override public void deliveryComplete(IMqttDeliveryToken token) { Log.d(TAG, "deliveryComplete token=" + token.toString()); } }); mqttAndroidClient.connect(connOpts,null, new IMqttActionListener(){ @Override public void onSuccess(IMqttToken asyncActionToken) { Log.d(TAG, "connect 回调 连接成功"); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.d(TAG, "connect 回调 onFailure,原因 exception=" + exception.toString()); } }); }
8.设备上报物模型属性信息
public void postTopic(){ JSONObject params = new JSONObject(); params.put("brand",Build.BRAND); params.put("model",Build.MODEL); params.put("android",Build.VERSION.RELEASE); params.put("sdk",Build.VERSION.SDK_INT); JSONObject payload = new JSONObject(); payload.put("id",System.currentTimeMillis()); payload.put("version","1.0"); payload.put("params",params); payload.put("method","thing.event.property.post"); MqttMessage message = new MqttMessage(); message.setPayload(payload.toString().getBytes("utf-8")); message.setQos(0); mqttAndroidClient.publish(postTopic, message);}
联机运行
9.编译并部署程序到手机
10.查看设备详情,状态变为在线,物模型数据可以查看到Android设备的信息
11.日志服务查看属性上报完整日志:
通过观察日志,我们了解到物模型属性上报包含三个步骤:
设备publish数据到IoT平台
IoT物联网平台按照预先定义的物模型校验并存储数据
IoT物联网平台给设备响应物模型属性reply消息
完整源码获取方式:
本文分享自微信公众号 - IoT物联网技术(IoT-Tech-Expo)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。