騰訊IOT安卓開發初探

騰訊IOT 安卓開發初探

目的:將Andorid端做爲一個物聯網設備(device),而後將其安卓設備上面的數據發送到騰訊雲IOT開發平臺上。(這裏咱們將手機上面的GPS經緯度發送到騰訊雲IOT平臺上)。java

騰訊IOT開發平臺:https://console.cloud.tencent.com/iotexplorerandroid

騰訊IOT Java SDK GitHub:https://github.com/tencentyun/iot-device-javagit

開發工具:Android Studiogithub

代碼Github:android_test_iot_for_tecentjson

Tecent IOT 開發平臺的使用

開發平臺的官方參考文檔網址:https://cloud.tencent.com/document/product/1081,不過我的以爲其文檔對於Java SDK的描述不夠詳細,須要去看其 Demo 源碼才能明白其工做流程。小程序

騰訊雲IOT開發平臺的項目結構以下所示:分爲兩層——項目產品。用在使用其平臺的時候,既須要建立project,也須要建立product。微信小程序

咱們能夠將項目理解爲智能家居整個系統,所以在項目中有不少產品,好比說智能空調,智能報警器等等產品。服務器

新建項目

新建項目,項目名稱隨意就行,建立好項目後,進入項目,而後建立產品。微信

建立產品

建立產品的選項以下:app

  • 設備:由於咱們是準備將安卓終端做爲一臺設備來使用的,所以,咱們應該選擇」設備「,固然,若是咱們是準備將它做爲網關,則看着選就好了。
  • 認證方式:認證方式選擇密鑰認證,這樣在代碼中間直接寫設備的密碼就行,比證書稍微方便一點(不過實際上證書方便一點)。
  • 數據協議:使用數據模板便可。

添加自定義功能

物聯網設備,之因此叫物聯網,是由於你們想把傳感器得到的數據放在雲端,或者經過雲端去控制物聯網設備。那麼放什麼數據,控制什麼功能,則須要咱們去定義。在騰訊IOT中,可使用新建功能定義這些功能。

點擊進入產品,選擇新建功能

自定義功能咱們只須要兩個功能:

  • 經度:position_x
  • 緯度:position_y

創建經度以下,在功能類型中選擇屬性,數據類型咱們選擇浮點型。(經度和緯度的範圍都在-180.0 ~180.0 )

同理將緯度配置爲position_y,功能類型爲屬性,數據類型一樣爲浮點型,範圍爲-180.0 ~180.0 。

關於功能類型的不一樣,能夠參考下面的表格。

如下來自官方文檔

功能元素 功能描述 功能標識符
屬性 用於描述設備的實時狀態,支持讀取和設置,如模式、亮度、開關等。 PropertiesId
事件 用於描述設備運行時的事件,包括告警、信息和故障等三種事件類型,可添加多個輸出參數,如環境傳感器檢測到空氣質量不好,空調異常告警等。 EventId
行爲 用於描述複雜的業務邏輯,可添加多個調用參數和返回參數,用於讓設備執行某項特定的任務,例如,開鎖動做須要知道是哪一個用戶在什麼時間開鎖,鎖的狀態如何等。 ActionId

點擊下一步,進入設備開發。

設備開發

由於咱們使用的是Java SDK進行開發,沒有使用模組也沒有基於OS開發,所以直接點擊下一步。

image-20210106165342612

點擊下一步就到了微信小程序配置。

微信小程序配置

騰訊IOT平臺相比較於其餘平臺,有一個很大的特色就是能夠很好的支持小程序。也就是說,在開發的階段,就可使用小程序去驗證設備的功能。而且這個微信小程序不須要本身寫樣式代碼,只須要進行簡單的配置,就能夠直接從小程序上面看到物聯網設備的數據。

由於這裏咱們使用的數據很簡單,只有經度和緯度兩個數據,因此隨便配置一下面板便可。

面板配置

這裏面板類型選擇標準面板,而後配置一下模板樣式(配置長按鈕稍微好看一點),配置完效果圖如右邊所示。

新建設備

新建設備`的意義:建立一個設備表明啓動了一個帳號(這個設備會提供一個密鑰),咱們的設備使用這個密鑰,就可讓咱們的設備鏈接騰訊雲IOT平臺進行數據交互。

新建設備的步驟以下所示:

使用設備

點擊test_device,進入設備管理。

設備管理界面以下所示:

  • 設備信息:這裏面是設備的一些基本屬性,其中經過設備名稱設備密鑰,和產品ID就能夠惟必定位一個設備,而後對其進行操做。

  • 設備日誌:設備日誌裏面保存着設備的上行和下行數據。

  • 在線調試:經過在線調試,咱們能夠模擬設備的行爲,或者對設備下發命令。

🆗,以上的全部就是騰訊IOT平臺的介紹,經過上面的操做,就能夠建立一個設備,得到其name,key,id,而後對其進行開發了。

安卓開發

安卓開發實現的效果很簡單,就是實現一個頁面展現經緯度,而後將經緯度數據上傳到騰訊IOT平臺就行。

前置配置

安卓開發,建立一個Android Studio項目,而後在APP的build gradle 中加入騰訊IOT的SDK

implementation 'com.tencent.iot.explorer:explorer-device-android:3.2.0'

而後新建兩個JSON文件(必作!!!!!),data.json ,表明的是設備的屬性(這個文件的來源會在後面解釋),而後是app-config.json,這個表明的是設備的配置(來源後文解釋)。

data.json

data.json 文件必定要放在安卓的assets目錄下,安卓如何添加assets目錄能夠看《Android studio 添加assets文件夾》。data.json須要存放一些數據。這個數據實際上就是自定義功能的數據,複製以後粘貼到data.json文件中。

app-config.json

app-config.json文件的位置必定不要放錯,它與src是同級目錄,在app的下一級目錄。

app-config裏面是device的信息,數據內容以下:

{
  "PRODUCT_ID":        "產品ID",
  "DEVICE_NAME":       "設備名稱",
  "DEVICE_PSK":        "設備密鑰",
  "SUB_PRODUCT_ID":    "",
  "SUB_DEV_NAME":      "",
  "SUB_DEV_PSK":       "",
  "SUB_PRODUCT_ID2":   "",
  "SUB_DEV_NAME2":     "",
  "SUB_DEV_PSK2":      ""
}

來源:

image-20210106185636326

權限配置

位置權限,和聯網權限。在AndroidManifest.xml中添加以下權限。值得注意的是,位置權限在安卓版本比較高的設備中,須要使用代碼申請位置權限。

<!--    位置權限-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!--    聯網權限-->
    <uses-permission android:name="android.permission.INTERNET" />

鏈接平臺代碼

經過官方提供的SDK,接入騰訊IOT平臺實現設備鏈接和數據上傳。代碼以下所示,具體的含義寫在註釋中。在使用中,咱們就能夠經過實例化IotCloudUtil,而後使用connect()函數來實現鏈接和propertyReport函數來實現上傳數據。

package cc.weno.data_template;


import com.tencent.iot.explorer.device.android.common.Status;
import com.tencent.iot.explorer.device.android.data_template.TXDataTemplateClient;
import com.tencent.iot.explorer.device.android.data_template.TXDataTemplateDownStreamCallBack;
import com.tencent.iot.explorer.device.android.mqtt.TXMqttActionCallBack;
import com.tencent.iot.explorer.device.android.mqtt.TXMqttRequest;
import com.tencent.iot.explorer.device.android.utils.AsymcSslUtils;

import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONObject;

import java.util.concurrent.atomic.AtomicInteger;

import cc.weno.location.MainActivity;


/**
 * 鏈接雲平臺的類
 *
 * @author XiaoHui
 */
public class IotCloudUtil {

    /**
     * 服務器網址
     */
    public static String mBrokerURL = "ssl://iotcloud-mqtt.gz.tencentdevices.com:8883";
    /**
     * 產品ID
     */
    public static String mProductID = "9JXQQW7SR5";
    /**
     * 設備名稱
     */
    public static String mDevName = "test_device";
    /**
     * 設備密鑰
     */
    public static String mDevPSK = "pCIUP7zhTp7snmfxb/72+g==";
    /**
     * data.json的名字
     */
    public static String mJsonFileName = "data.json";
    /**
     * MQTTAction的回調
     */
    private TXMqttActionCallBack mMqttActionCallBack = null;
    /**
     * 下行消息的回調
     */
    private TXDataTemplateDownStreamCallBack mDownStreamCallBack = null;

    /**
     * MQTT鏈接實例
     */
    private TXDataTemplateClient mMqttConnection;
    /**
     * Activity實例
     */
    private MainActivity context;

    /**
     * 請求ID
     */
    private static AtomicInteger requestID = new AtomicInteger(199);


    public IotCloudUtil(MainActivity context) {
        this.context = context;
        mDownStreamCallBack = new MyDownCallback();
        mMqttActionCallBack = new MyMQttCallBack();
    }

    /**
     * 創建MQTT鏈接
     */
    public void connect() {
        // 建立鏈接client
        mMqttConnection = new TXDataTemplateClient(context, mBrokerURL, mProductID, mDevName, mDevPSK,
                null, null, mMqttActionCallBack,
                mJsonFileName, mDownStreamCallBack);
        // 設置鏈接參數
        MqttConnectOptions options = new MqttConnectOptions();
        // 鏈接超時
        options.setConnectionTimeout(8);
        // 保持活躍的時間間隔
        options.setKeepAliveInterval(240);
        // 是否自動重連
        options.setAutomaticReconnect(true);
        // 由於咱們是使用密鑰登陸,因此須要設置這個
        options.setSocketFactory(AsymcSslUtils.getSocketFactory());
        // 創建Request請求
        TXMqttRequest mqttRequest = new TXMqttRequest("connect", requestID.getAndIncrement());
        // 創建鏈接
        mMqttConnection.connect(options, mqttRequest);
    }

    /**
     * 斷開MQTT鏈接
     */
    public void disconnect() {
        TXMqttRequest mqttRequest = new TXMqttRequest("disconnect", requestID.getAndIncrement());
        mMqttConnection.disConnect(mqttRequest);
    }

    /**
     * 發送消息
     *
     * @param property 消息內容
     * @param metadata 屬性的metadata,目前只包含各個屬性對應的時間戳,能夠爲NULL
     * @return 狀態
     */
    public Status propertyReport(JSONObject property, JSONObject metadata) {
        return mMqttConnection.propertyReport(property, metadata);
    }


    /**
     * MQTT的回調函數,暫時不考慮
     */
    public static class MyMQttCallBack extends TXMqttActionCallBack {

        @Override
        public void onConnectCompleted(Status status, boolean reconnect, Object userContext, String msg) {

        }

        @Override
        public void onConnectionLost(Throwable cause) {

        }

        @Override
        public void onDisconnectCompleted(Status status, Object userContext, String msg) {
        }

        @Override
        public void onPublishCompleted(Status status, IMqttToken token, Object userContext, String errMsg) {
        }

        @Override
        public void onSubscribeCompleted(Status status, IMqttToken asyncActionToken, Object userContext, String errMsg) {

        }

        @Override
        public void onMessageReceived(final String topic, final MqttMessage message) {
        }
    }

    /**
     * 實現下行消息處理的回調接口,暫時不考慮
     */
    private static class MyDownCallback extends TXDataTemplateDownStreamCallBack {

        @Override
        public void onReplyCallBack(String msg) {
        }

        @Override
        public void onGetStatusReplyCallBack(JSONObject data) {

        }

        @Override
        public JSONObject onControlCallBack(JSONObject msg) {

            return null;
        }

        @Override
        public JSONObject onActionCallBack(String actionId, JSONObject params) {

            return null;
        }
    }

}

安卓頁面配置

安卓頁面很簡單,就是展現經度和緯度的數據。

頁面代碼以下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:text="x軸:" />

    <TextView
        android:id="@+id/x_position"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="100dp"
        android:text="0.00" />

    <TextView

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="100dp"
        android:text="y軸:" />

    <TextView

        android:id="@+id/y_position"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="100dp"
        android:layout_marginTop="100dp"

        android:text="0.00" />

</RelativeLayout>

Activity代碼

在MainActivity,咱們要實現以下的功能,申請位置權限,得到經緯度的數據,而後進行頁面展現,最後將數據上傳到雲平臺。

package cc.weno.location;

import android.Manifest;
import android.location.Location;
import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.tencent.iot.explorer.device.android.common.Status;

import org.json.JSONException;
import org.json.JSONObject;

import cc.weno.data_template.IotCloudUtil;


/**
 * 主頁面,進行展現以及發送數據
 *
 * @author XiaoHui
 */
public class MainActivity extends AppCompatActivity {
    /**
     * 展現經度
     */
    private TextView xPositionView;
    /**
     * 展現緯度
     */
    private TextView yPositionView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        xPositionView = findViewById(R.id.x_position);
        yPositionView = findViewById(R.id.y_position);
        // 基本上如今的安卓機都須要申請位置權限了
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        // 得到位置數據而且發送數據到雲平臺
        getAndSendLocation();
    }

    private void getAndSendLocation() {
        // 得到GPS工具類
        GPSUtils gpsUtil = GPSUtils.getInstance(this);
        // 得到位置
        Location location = gpsUtil.getLocation();

        double positionX = location.getLatitude();
        double positionY = location.getLongitude();
        // 在手機頁面上展現
        xPositionView.setText(String.valueOf(positionX));
        yPositionView.setText(String.valueOf(positionY));
        // IotCloudUtil
        IotCloudUtil iotCloudUtil = new IotCloudUtil(this);
        // 鏈接雲平臺
        iotCloudUtil.connect();

        // 等待幾秒鐘,鏈接成功
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 調用發送數據的函數須要傳入JsonObject類型的數據
        JSONObject property = new JSONObject();
        try {
            property.put("position_x", (float) positionX);
            property.put("position_y", (float) positionY);
            // 發送數據
            Status status = iotCloudUtil.propertyReport(property, null);
            if (status == Status.OK){
                // 發送成功
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

其中GPS工具就不進行介紹了,由於其不是重點,關於具體的代碼能夠參考GitHub

微信小程序使用

前面咱們說了,能夠是用微信小程序對開發的物聯網設備進行開發調試,而後咱們在以下的頁面獲得設備的二維碼。

而後打開」騰訊連連「小程序,對二維碼進行掃描,便可將設備加入。

而後咱們運行安卓程序,自動向騰訊IOT平臺發送經緯度數據,而後在微信小程序上就能夠看到最新的數據。

中間存在些許偏差,多是由於double轉float的精度緣由致使的。

總結

經過上面的操做咱們建立了一個安卓程序,而後可以在微信小程序上面看到安卓設備的經緯度。歸咎於原理,就是MQTT協議。使用平臺提供的SDK,讓開發者省下了大量花費在通訊協議上面的時間。然而,咱們仍是應該去關注MQTT協議自己。知其然,更要知其因此然。

參考

  1. Github:android_test_iot_for_tecent

  2. 物聯網開發平臺使用文檔:物聯網開發平臺 - 文檔中心 - 騰訊雲 (tencent.com)

  3. Github:iot-device-java

相關文章
相關標籤/搜索