From c467e0946194c2a6f735fe63aceb782d23442f92 Mon Sep 17 00:00:00 2001 From: zmt Date: Thu, 7 Apr 2022 16:23:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96tcp=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uniplugin_module/.gitignore | 0 uniplugin_module/build.gradle | 4 + uniplugin_module/proguard-rules.pro | 0 uniplugin_module/src/main/AndroidManifest.xml | 17 +- .../java/io/dcloud/uniplugin/MainActivity.java | 455 +++++++++++++++++++++ .../io/dcloud/uniplugin/NativePageActivity.java | 4 +- .../main/java/io/dcloud/uniplugin/TestModule.java | 4 +- .../java/io/dcloud/uniplugin/mqtt/MQTTRequest.java | 49 +++ .../java/io/dcloud/uniplugin/mqtt/MQTTSample.java | 403 ++++++++++++++++++ .../src/main/res/layout/activity_main.xml | 84 ++++ uniplugin_module/src/main/res/values/strings.xml | 0 .../main/java/io/dcloud/zmt_module/TcpServer.java | 33 +- .../java/io/dcloud/zmt_module/Zmt_AppProxy.java | 8 +- .../main/java/io/dcloud/zmt_module/zmtClass.java | 7 +- 14 files changed, 1049 insertions(+), 19 deletions(-) mode change 100755 => 100644 uniplugin_module/.gitignore mode change 100755 => 100644 uniplugin_module/build.gradle mode change 100755 => 100644 uniplugin_module/proguard-rules.pro mode change 100755 => 100644 uniplugin_module/src/main/AndroidManifest.xml create mode 100644 uniplugin_module/src/main/java/io/dcloud/uniplugin/MainActivity.java mode change 100755 => 100644 uniplugin_module/src/main/java/io/dcloud/uniplugin/NativePageActivity.java mode change 100755 => 100644 uniplugin_module/src/main/java/io/dcloud/uniplugin/TestModule.java create mode 100644 uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTRequest.java create mode 100644 uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTSample.java create mode 100644 uniplugin_module/src/main/res/layout/activity_main.xml mode change 100755 => 100644 uniplugin_module/src/main/res/values/strings.xml diff --git a/uniplugin_module/.gitignore b/uniplugin_module/.gitignore old mode 100755 new mode 100644 diff --git a/uniplugin_module/build.gradle b/uniplugin_module/build.gradle old mode 100755 new mode 100644 index e71646a..e393406 --- a/uniplugin_module/build.gradle +++ b/uniplugin_module/build.gradle @@ -28,6 +28,7 @@ repositories { } dependencies { + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' compileOnly fileTree(dir: 'libs', include: ['*.jar']) compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar']) @@ -42,4 +43,7 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'*/ + + // 腾讯mqtt + implementation 'com.tencent.iot.hub:hub-device-android:3.3.5' } diff --git a/uniplugin_module/proguard-rules.pro b/uniplugin_module/proguard-rules.pro old mode 100755 new mode 100644 diff --git a/uniplugin_module/src/main/AndroidManifest.xml b/uniplugin_module/src/main/AndroidManifest.xml old mode 100755 new mode 100644 index c35b57d..821efc4 --- a/uniplugin_module/src/main/AndroidManifest.xml +++ b/uniplugin_module/src/main/AndroidManifest.xml @@ -1,7 +1,12 @@ + - - - - + package="uni.dcloud.io.uniplugin_module"> + + + + + + + \ No newline at end of file diff --git a/uniplugin_module/src/main/java/io/dcloud/uniplugin/MainActivity.java b/uniplugin_module/src/main/java/io/dcloud/uniplugin/MainActivity.java new file mode 100644 index 0000000..38468bb --- /dev/null +++ b/uniplugin_module/src/main/java/io/dcloud/uniplugin/MainActivity.java @@ -0,0 +1,455 @@ +package io.dcloud.uniplugin; + + +import android.app.Activity; +import android.content.Context; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import com.tencent.iot.hub.device.android.core.util.TXLog; +import com.tencent.iot.hub.device.java.core.common.Status; +import com.tencent.iot.hub.device.java.core.log.TXMqttLogCallBack; +import com.tencent.iot.hub.device.java.core.mqtt.TXMqttActionCallBack; + +import org.eclipse.paho.client.mqttv3.IMqttToken; +import org.eclipse.paho.client.mqttv3.MqttMessage; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import io.dcloud.uniplugin.mqtt.MQTTRequest; +import io.dcloud.uniplugin.mqtt.MQTTSample; +import uni.dcloud.io.uniplugin_module.R; + +public class MainActivity extends Activity { + + private Context mContext; + + // Default testing parameters + private String mBrokerURL = null; //传入null,即使用腾讯云物联网通信默认地址 "${ProductId}.iotcloud.tencentdevices.com:8883" https://cloud.tencent.com/document/product/634/32546 + private String mProductID = "BE8N7UZ7OF";// + private String mDevName = "pad20220105";//BuildConfig.DEVICE_NAME; + private String mDevPSK = "7udrYcfTVThbzdMlLT9fHQ==";//BuildConfig.DEVICE_PSK; //若使用证书验证,设为null + private String mSubProductID = null;//BuildConfig.SUB_PRODUCT_ID; // If you wont test gateway, let this to be null + private String mSubDevName = null;//BuildConfig.SUB_DEV_NAME; + private String mSubDevPsk = null;//BuildConfig.SUB_DEVICE_PSK; + private String mTestTopic = "BE8N7UZ7OF/pad20220105/data";//BuildConfig.TEST_TOPIC; // productID/DeviceName/TopicName + private String mDevCertName = null;//"YOUR_DEVICE_NAME_cert.crt"; + private String mDevKeyName = null;//"YOUR_DEVICE_NAME_private.key"; + private String mProductKey = null;//BuildConfig.PRODUCT_KEY; // Used for dynamic register + private String mDevCert = ""; // Cert String + private String mDevPriv = ""; // Priv String + + + private static final String TAG = "TXMQTT"; + private MQTTSample mMQTTSample; + private TextView mLogInfoText; + private volatile boolean mIsConnected; //是否连接 + + private Button statusBtn, connectBtn, disconnectBtn, subscribeBtn, unSubscribeBtn, publishBtn, clearBtn; + + + /**日志保存的路径*/ + private final static String mLogPath = Environment.getExternalStorageDirectory().getPath() + "/tencent/"; + + private AtomicInteger temperature = new AtomicInteger(0); + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + mContext = this; + + mLogInfoText =(TextView)findViewById(R.id.tv1); + statusBtn = (Button)findViewById(R.id.btn1); + connectBtn = (Button)findViewById(R.id.btn2); + disconnectBtn = (Button)findViewById(R.id.btn3); + subscribeBtn = (Button)findViewById(R.id.btn4); + unSubscribeBtn = (Button)findViewById(R.id.btn5); + publishBtn = (Button)findViewById(R.id.btn6); + clearBtn = (Button)findViewById(R.id.btn7); + + + + + statusBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(mIsConnected){ + Log.d(TAG, "连接成功"); + Toast.makeText(mContext,"连接成功",Toast.LENGTH_LONG).show(); + }else { + Log.d(TAG, "连接失败"); + Toast.makeText(MainActivity.this,"连接失败",Toast.LENGTH_LONG).show(); + } + + } + }); + + connectBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getConnect(); + } + }); + disconnectBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + closeConnection(); + } + }); + subscribeBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getSubscribe(); + } + }); + unSubscribeBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getUnSubscribe(); + } + }); + publishBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getPublish(); + } + }); + + clearBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mLogInfoText.setText(""); + } + }); + + } + + + //MQTT 认证连接 + public void getConnect(){ + mMQTTSample = new MQTTSample(mContext, new SelfMqttActionCallBack(), mBrokerURL, mProductID, mDevName, mDevPSK, + mDevCert, mDevPriv, mSubProductID, mSubDevName, mTestTopic, null, null, true, new SelfMqttLogCallBack()); + mMQTTSample.setSubDevPsk(mSubDevPsk); + mMQTTSample.connect(); + } + + //断开 MQTT 连接 + public void closeConnection() { + if (mMQTTSample == null) + return; + mMQTTSample.disconnect(); + } + + //订阅主题 + public void getSubscribe(){ + // 在腾讯云控制台增加自定义主题(权限为订阅和发布):custom_data,用于接收IoT服务端转发的自定义数据。 + // 本例中,发布的自定义数据,IoT服务端会在发给当前设备。 + if (mMQTTSample == null) + return; + mMQTTSample.subscribeTopic(); + } + + //取消订阅主题 + public void getUnSubscribe(){ + // 在腾讯云控制台增加自定义主题(权限为订阅和发布):custom_data,用于接收IoT服务端转发的自定义数据。 + // 本例中,发布的自定义数据,IoT服务端会在发给当前设备。 + if (mMQTTSample == null) + return; + mMQTTSample.unSubscribeTopic(); + } + + // 发布主题 + public void getPublish(){ + if (mMQTTSample == null)return; + + // 要发布的数据 + Map data = new HashMap(); + // 车辆类型 + data.put("car_type", "suv"); + // 车辆油耗 + data.put("oil_consumption", "6.6"); + // 车辆最高速度 + data.put("maximum_speed", "205"); + // 温度信息 + data.put("temperature", String.valueOf(temperature.getAndIncrement())); + + // 需先在腾讯云控制台,增加自定义主题: data,用于更新自定义数据 + mMQTTSample.publishTopic("data", data); + } + + /** + * 实现TXMqttActionCallBack回调接口 + */ + private class SelfMqttActionCallBack extends TXMqttActionCallBack { + + @Override + public void onConnectCompleted(Status status, boolean reconnect, Object userContext, String msg, Throwable cause) { + //MQTT Connect完成回调 + String userContextInfo = ""; + if (userContext instanceof MQTTRequest) { + userContextInfo = userContext.toString(); + } + String logInfo = String.format("onConnectCompleted, status[%s], reconnect[%b], userContext[%s], msg[%s]", + status.name(), reconnect, userContextInfo, msg); + printLogInfo(TAG, logInfo, mLogInfoText, TXLog.LEVEL_INFO); + mIsConnected = true; + } + + @Override + public void onConnectionLost(Throwable cause) { + //MQTT连接断开回调 + String logInfo = String.format("onConnectionLost, cause[%s]", cause.toString()); + printLogInfo(TAG, logInfo, mLogInfoText, TXLog.LEVEL_INFO); + } + + @Override + public void onDisconnectCompleted(Status status, Object userContext, String msg, Throwable cause) { + //MQTT Disconnect完成回调 + String userContextInfo = ""; + if (userContext instanceof MQTTRequest) { + userContextInfo = userContext.toString(); + } + String logInfo = String.format("onDisconnectCompleted, status[%s], userContext[%s], msg[%s]", status.name(), userContextInfo, msg); + printLogInfo(TAG, logInfo, mLogInfoText, TXLog.LEVEL_INFO); + mIsConnected = false; + } + + @Override + public void onPublishCompleted(Status status, IMqttToken token, Object userContext, String errMsg, Throwable cause) { + // 发布消息完成回调 + String userContextInfo = ""; + if (userContext instanceof MQTTRequest) { + userContextInfo = userContext.toString(); + } + String logInfo = String.format("onPublishCompleted, status[%s], topics[%s], userContext[%s], errMsg[%s]", + status.name(), Arrays.toString(token.getTopics()), userContextInfo, errMsg); + printLogInfo(TAG, logInfo, mLogInfoText,-1); + } + + @Override + public void onSubscribeCompleted(Status status, IMqttToken asyncActionToken, Object userContext, String errMsg, Throwable cause) { + //订阅主题完成的回调 + String userContextInfo = ""; + if (userContext instanceof MQTTRequest) { + userContextInfo = userContext.toString(); + } + String logInfo = String.format("onSubscribeCompleted, status[%s], topics[%s], userContext[%s], errMsg[%s]", + status.name(), Arrays.toString(asyncActionToken.getTopics()), userContextInfo, errMsg); + if (Status.ERROR == status) { + //失败的 + printLogInfo(TAG, logInfo, mLogInfoText, TXLog.LEVEL_ERROR); + Log.d(TAG, "订阅主题--失败的:"+ logInfo ); + } else { + //成功的 + printLogInfo(TAG, logInfo, mLogInfoText, -1); + Log.d(TAG, "订阅主题--成功的:"+ logInfo ); + + } + } + + @Override + public void onUnSubscribeCompleted(Status status, IMqttToken asyncActionToken, Object userContext, String errMsg, Throwable cause) { + //取消订阅主题完成回调 + String userContextInfo = ""; + if (userContext instanceof MQTTRequest) { + userContextInfo = userContext.toString(); + } + String logInfo = String.format("onUnSubscribeCompleted, status[%s], topics[%s], userContext[%s], errMsg[%s]", + status.name(), Arrays.toString(asyncActionToken.getTopics()), userContextInfo, errMsg); + printLogInfo(TAG, logInfo, mLogInfoText,-1); + } + + @Override + public void onMessageReceived(final String topic, final MqttMessage message) { + // 收到订阅主题的消息Push 即收到云中控下发的消息 + String logInfo = String.format("receive command, topic[%s], message[%s]", topic, message.toString()); + printLogInfo(TAG, logInfo, mLogInfoText, -1); + + Log.d(TAG, "收到订阅主题的消息: "+ message.toString()); + } + } + + /** + * 打印日志信息 + * + * @param logInfo + */ + protected void printLogInfo(final String tag, final String logInfo, final TextView textView, int logLevel) { + switch (logLevel) { + case TXLog.LEVEL_DEBUG: + TXLog.d(tag, logInfo); + break; + + case TXLog.LEVEL_INFO: + TXLog.i(tag, logInfo); + break; + + case TXLog.LEVEL_ERROR: + TXLog.e(tag, logInfo); + break; + + default: + TXLog.d(tag, logInfo); + break; + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + textView.append("==> " + logInfo + "\n\n"); + } + }); + } + + /** + * 实现TXMqttLogCallBack回调接口 + */ + private class SelfMqttLogCallBack extends TXMqttLogCallBack { + + @Override + public String setSecretKey() { + String secertKey; + if (mDevPSK != null && mDevPSK.length() != 0) { //密钥认证 + secertKey = mDevPSK; + secertKey = secertKey.length() > 24 ? secertKey.substring(0,24) : secertKey; + return secertKey; + } else { + StringBuilder builder = new StringBuilder(); + if (mDevPriv != null && mDevPriv.length() != 0) { //动态注册, 从DevPriv中读取 + builder.append(mDevPriv); + } else { //证书认证,从证书文件中读取 + AssetManager assetManager = mContext.getAssets(); + if (assetManager == null) { + return null; + } + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(assetManager.open(mDevKeyName))); + String str; + while((str = reader.readLine()) != null){ + builder.append(str); + } + } catch (IOException e) { + printLogInfo(TAG, "Get Private Key failed, cannot open Private Key Files.",mLogInfoText, -1); + return null; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + String privateKey = builder.toString(); + if (privateKey.contains("-----BEGIN PRIVATE KEY-----")) { + secertKey = privateKey; + } else { + secertKey = null; + printLogInfo(TAG,"Invaild Private Key File.", mLogInfoText,-1); + } + } + return secertKey; + } + + @Override + public void printDebug(String message){ + printLogInfo(TAG, message, mLogInfoText, -1); + //TXLog.d(TAG,message); + } + + @Override + public boolean saveLogOffline(String log){ + //判断SD卡是否可用 + if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + printLogInfo(TAG, "saveLogOffline not ready", mLogInfoText, -1); + return false; + } + + String logFilePath = mLogPath + mProductID + mDevName + ".log"; + + TXLog.i(TAG, "Save log to %s", logFilePath); + + try { + BufferedWriter wLog = new BufferedWriter(new FileWriter(new File(logFilePath), true)); + wLog.write(log); + wLog.flush(); + wLog.close(); + return true; + } catch (IOException e) { + String logInfo = String.format("Save log to [%s] failed, check the Storage permission!", logFilePath); + printLogInfo(TAG,logInfo, mLogInfoText, -1); + e.printStackTrace(); + return false; + } + } + + @Override + public String readOfflineLog(){ + //判断SD卡是否可用 + if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + printLogInfo(TAG, "readOfflineLog not ready", mLogInfoText, -1); + return null; + } + + String logFilePath = mLogPath + mProductID + mDevName + ".log"; + + TXLog.i(TAG, "Read log from %s", logFilePath); + + try { + BufferedReader logReader = new BufferedReader(new FileReader(logFilePath)); + StringBuilder offlineLog = new StringBuilder(); + int data; + while (( data = logReader.read()) != -1 ) { + offlineLog.append((char)data); + } + logReader.close(); + return offlineLog.toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public boolean delOfflineLog(){ + + //判断SD卡是否可用 + if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + printLogInfo(TAG, "delOfflineLog not ready", mLogInfoText, -1); + return false; + } + + String logFilePath = mLogPath + mProductID + mDevName + ".log"; + + File file = new File(logFilePath); + if (file.exists() && file.isFile()) { + if (file.delete()) { + return true; + } + } + return false; + } + + } +} \ No newline at end of file diff --git a/uniplugin_module/src/main/java/io/dcloud/uniplugin/NativePageActivity.java b/uniplugin_module/src/main/java/io/dcloud/uniplugin/NativePageActivity.java old mode 100755 new mode 100644 index 04afdf6..5b7e2c2 --- a/uniplugin_module/src/main/java/io/dcloud/uniplugin/NativePageActivity.java +++ b/uniplugin_module/src/main/java/io/dcloud/uniplugin/NativePageActivity.java @@ -17,13 +17,13 @@ public class NativePageActivity extends Activity { TextView textView = new TextView(this); textView.setTextColor(Color.BLACK); textView.setTextSize(30); - textView.setText("点击我将返回 并携带参数返回1"); + textView.setText("点击我将返回 并携带参数返回"); rootView.addView(textView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300)); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); - intent.putExtra("respond", "我是原生页面1"); + intent.putExtra("respond", "我是原生页面"); setResult(TestModule.REQUEST_CODE, intent); finish(); } diff --git a/uniplugin_module/src/main/java/io/dcloud/uniplugin/TestModule.java b/uniplugin_module/src/main/java/io/dcloud/uniplugin/TestModule.java old mode 100755 new mode 100644 index 7856920..824044f --- a/uniplugin_module/src/main/java/io/dcloud/uniplugin/TestModule.java +++ b/uniplugin_module/src/main/java/io/dcloud/uniplugin/TestModule.java @@ -22,7 +22,7 @@ public class TestModule extends UniModule { Log.e(TAG, "testAsyncFunc--"+options); if(callback != null) { JSONObject data = new JSONObject(); - data.put("code", "success1"); + data.put("code", "success"); callback.invoke(data); //callback.invokeAndKeepAlive(data); } @@ -48,7 +48,7 @@ public class TestModule extends UniModule { @UniJSMethod (uiThread = true) public void gotoNativePage(){ if(mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) { - Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class); + Intent intent = new Intent(mUniSDKInstance.getContext(), MainActivity.class); ((Activity)mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE); } } diff --git a/uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTRequest.java b/uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTRequest.java new file mode 100644 index 0000000..4055150 --- /dev/null +++ b/uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTRequest.java @@ -0,0 +1,49 @@ +package io.dcloud.uniplugin.mqtt; + + +public class MQTTRequest { + + private static final String TAG = MQTTRequest.class.getSimpleName(); + + /** + * 请求类型 + */ + private String requestType = ""; + + /** + * 请求ID + */ + private int requestId = 0; + + public MQTTRequest() { + } + + public MQTTRequest(String requestType, int requestId) { + this.requestType = requestType; + this.requestId = requestId; + } + + public String getRequestType() { + return requestType; + } + + public void setRequestType(String requestType) { + this.requestType = requestType; + } + + public int getRequestId() { + return requestId; + } + + public void setRequestId(int requestId) { + this.requestId = requestId; + } + + @Override + public String toString() { + return "MQTTRequest{" + + "requestType='" + requestType + '\'' + + ", requestId=" + requestId + + '}'; + } +} diff --git a/uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTSample.java b/uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTSample.java new file mode 100644 index 0000000..ffb0621 --- /dev/null +++ b/uniplugin_module/src/main/java/io/dcloud/uniplugin/mqtt/MQTTSample.java @@ -0,0 +1,403 @@ +package io.dcloud.uniplugin.mqtt; + +import android.content.Context; +import android.os.Environment; +import android.util.Log; + +import com.tencent.iot.hub.device.android.core.gateway.TXGatewayConnection; +import com.tencent.iot.hub.device.android.core.util.AsymcSslUtils; +import com.tencent.iot.hub.device.android.core.util.TXLog; +import com.tencent.iot.hub.device.java.core.log.TXMqttLogCallBack; +import com.tencent.iot.hub.device.java.core.mqtt.TXMqttActionCallBack; +import com.tencent.iot.hub.device.java.core.mqtt.TXMqttConstants; +import com.tencent.iot.hub.device.java.core.mqtt.TXOTACallBack; +import com.tencent.iot.hub.device.java.core.mqtt.TXOTAConstansts; + +import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.ByteArrayInputStream; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + + +public class MQTTSample { + + private static final String TAG = "TXMQTT"; + // Default Value, should be changed in testing + private String mBrokerURL = null; //传入null,即使用腾讯云物联网通信默认地址 "${ProductId}.iotcloud.tencentdevices.com:8883" https://cloud.tencent.com/document/product/634/32546 + private String mProductID = "PRODUCT-ID"; + private String mDevName = "DEVICE-NAME"; + private String mDevPSK = "DEVICE-SECRET"; + + private String mDevCertName = "DEVICE_CERT-NAME "; + private String mDevKeyName = "DEVICE_KEY-NAME "; + + private String mSubProductID = "SUBDEV_PRODUCT-ID"; + private String mSubDevName = "SUBDEV_DEV-NAME"; + private String mSubDevPsk = "SUBDEV_DEVICE-SECRET"; + private String mTestTopic = "TEST_TOPIC_WITH_SUB_PUB"; + private String mDevCert; + private String mDevPriv; + + private boolean mMqttLogFlag; + private TXMqttLogCallBack mMqttLogCallBack; + + private Context mContext; + private String path2Store = ""; + + private TXMqttActionCallBack mMqttActionCallBack; + + /** + * MQTT连接实例 + */ + private TXGatewayConnection mMqttConnection; + + /** + * 请求ID + */ + private static AtomicInteger requestID = new AtomicInteger(0); + + public MQTTSample(Context context, TXMqttLogCallBack logCallBack, TXMqttActionCallBack callBack) { + mContext = context; + mMqttActionCallBack = callBack; + } + + public MQTTSample(Context context, TXMqttActionCallBack callBack, String brokerURL, String productId, + String devName, String devPSK, String subProductID, String subDevName, String testTopic, String devCertName, String devKeyName, + Boolean mqttLogFlag, TXMqttLogCallBack logCallBack) { + mBrokerURL = brokerURL; + mProductID = productId; + mDevName = devName; + mDevPSK = devPSK; + mSubProductID = subProductID; + mSubDevName = subDevName; + mTestTopic = testTopic; + mDevCertName = devCertName; + mDevKeyName = devKeyName; + + mMqttLogFlag = mqttLogFlag; + mMqttLogCallBack = logCallBack; + + mContext = context; + mMqttActionCallBack = callBack; + } + + public MQTTSample(Context context, TXMqttActionCallBack callBack, String brokerURL, String productId, + String devName, String devPsk, String devCert, String devPriv, String subProductID, String subDevName, String testTopic, String devCertName, String devKeyName, + Boolean mqttLogFlag, TXMqttLogCallBack logCallBack) { + mBrokerURL = brokerURL; + mProductID = productId; + mDevName = devName; + mDevPSK = devPsk; + mDevCert = devCert; + mDevPriv = devPriv; + mSubProductID = subProductID; + mSubDevName = subDevName; + mTestTopic = testTopic; + mDevCertName = devCertName; + mDevKeyName = devKeyName; + + mMqttLogFlag = mqttLogFlag; + mMqttLogCallBack = logCallBack; + + mContext = context; + mMqttActionCallBack = callBack; + path2Store = mContext.getCacheDir().getAbsolutePath(); + } + + public MQTTSample(Context context, TXMqttActionCallBack callBack, String brokerURL, String productId, + String devName, String devPsk, String devCert, String devPriv, String subProductID, String subDevName, String subDevPsk, String testTopic, String devCertName, String devKeyName, + Boolean mqttLogFlag, TXMqttLogCallBack logCallBack) { + this(context, callBack, brokerURL, productId, devName, devPsk, devCert, devPriv, subProductID, subDevName, testTopic, devCertName, devKeyName, mqttLogFlag, logCallBack); + mSubDevPsk = subDevPsk; + } + + public void setSubDevPsk(String val) { + mSubDevPsk = val; + } + + + public MQTTSample(Context context, TXMqttActionCallBack callBack, String brokerURL, String productId, + String devName, String devPSK, String subProductID, String subDevName, String testTopic) { + mBrokerURL = brokerURL; + mProductID = productId; + mDevName = devName; + mDevPSK = devPSK; + mSubProductID = subProductID; + mSubDevName = subDevName; + mTestTopic = testTopic; + + mContext = context; + mMqttActionCallBack = callBack; + } + + private TXOTACallBack oTACallBack = new TXOTACallBack() { + + @Override + public void onReportFirmwareVersion(int resultCode, String version, String resultMsg) { + + } + + @Override + public boolean onLastestFirmwareReady(String url, String md5, String version) { + System.out.println("onLastestFirmwareReady url=" + url + " version " + version); + mMqttConnection.gatewayDownSubdevApp(url, path2Store + "/" + md5, md5, version); + return true; // false 自动触发下载升级文件 true 需要手动触发下载升级文件 + } + + @Override + public void onDownloadProgress(int percent, String version) { + mMqttConnection.gatewaySubdevReportProgress(percent, version); + } + + @Override + public void onDownloadCompleted(String outputFile, String version) { + mMqttConnection.gatewaySubdevReportStart(version); + mMqttConnection.gatewaySubdevReportSuccess(version); + } + + @Override + public void onDownloadFailure(int errCode, String version) { + mMqttConnection.gatewaySubdevReportFail(errCode, "", version); + } + }; + + /** + * 建立MQTT连接 + */ + public void connect() { + mMqttConnection = new TXGatewayConnection(mContext, mBrokerURL, mProductID, mDevName, mDevPSK,null,null ,mMqttLogFlag, mMqttLogCallBack, mMqttActionCallBack); + mMqttConnection.setSubDevName(mSubDevName); + mMqttConnection.setSubDevProductKey(mSubDevPsk); + mMqttConnection.setSubProductID(mSubProductID); + MqttConnectOptions options = new MqttConnectOptions(); + options.setConnectionTimeout(8); + options.setKeepAliveInterval(240); + options.setAutomaticReconnect(true); + + if (mDevPriv != null && mDevCert != null && mDevPriv.length() != 0 && mDevCert.length() != 0) { + TXLog.i(TAG, "Using cert stream " + mDevPriv + " " + mDevCert); + options.setSocketFactory(AsymcSslUtils.getSocketFactoryByStream(new ByteArrayInputStream(mDevCert.getBytes()), new ByteArrayInputStream(mDevPriv.getBytes()))); + } else if (mDevPSK != null && mDevPSK.length() != 0){ + TXLog.i(TAG, "Using PSK"); +// options.setSocketFactory(AsymcSslUtils.getSocketFactory()); 如果您使用的是3.3.0及以下版本的 hub-device-android sdk,由于密钥认证默认配置的ssl://的url,请添加此句setSocketFactory配置。 + } else { + TXLog.i(TAG, "Using cert assets file"); + options.setSocketFactory(AsymcSslUtils.getSocketFactoryByAssetsFile(mContext, mDevCertName, mDevKeyName)); + } + + MQTTRequest mqttRequest = new MQTTRequest("connect", requestID.getAndIncrement()); + mMqttConnection.connect(options, mqttRequest); + + DisconnectedBufferOptions bufferOptions = new DisconnectedBufferOptions(); + bufferOptions.setBufferEnabled(true); + bufferOptions.setBufferSize(1024); + bufferOptions.setDeleteOldestMessages(true); + mMqttConnection.setBufferOpts(bufferOptions); + } + + /** + * 断开MQTT连接 + */ + public void disconnect() { + MQTTRequest mqttRequest = new MQTTRequest("disconnect", requestID.getAndIncrement()); + mMqttConnection.disConnect(mqttRequest); + } + + public void setSubdevOnline() { + // set subdev online + mMqttConnection.gatewaySubdevOnline(mSubProductID, mSubDevName); + } + + public void setSubDevOffline() { + mMqttConnection.gatewaySubdevOffline(mSubProductID, mSubDevName); + } + + public void setSubDevBinded() { + mMqttConnection.gatewayBindSubdev(mSubProductID, mSubDevName, mSubDevPsk); + } + + public void setSubDevUnbinded() { + mMqttConnection.gatewayUnbindSubdev(mSubProductID, mSubDevName); + } + + public void checkSubdevRelation() { + mMqttConnection.getGatewaySubdevRealtion(); + } + + public void getRemoteConfig() { + mMqttConnection.getRemoteConfig(); + } + + public void concernRemoteConfig() { + mMqttConnection.concernConfig(); + } + + public void reportSubDevVersion(String version) { + mMqttConnection.gatewaySubdevReportVer(version); + } + + public void subscribeNTPTopic() { + // QOS等级 + int qos = TXMqttConstants.QOS1; + // 用户上下文(请求实例) + MQTTRequest mqttRequest = new MQTTRequest("subscribeNTPTopic", requestID.getAndIncrement()); + mMqttConnection.subscribeNTPTopic(qos, mqttRequest); + } + + public void getNTPService() { + mMqttConnection.getNTPService(); + } + + public void initOTA() { + TXLog.e(TAG, "path2Store " + path2Store); + mMqttConnection.initOTA(path2Store, oTACallBack); + } + + /** + * 订阅广播主题 + */ + public void subscribeBroadCastTopic() { + // 用户上下文(请求实例) + MQTTRequest mqttRequest = new MQTTRequest("subscribeTopic", requestID.getAndIncrement()); + // 订阅广播主题 + mMqttConnection.subscribeBroadcastTopic(TXMqttConstants.QOS1, mqttRequest); + } + + /** + * 订阅主题 + * + */ + public void subscribeTopic() { + // 主题 + String topic = mTestTopic; + // QOS等级 + int qos = TXMqttConstants.QOS1; + // 用户上下文(请求实例) + MQTTRequest mqttRequest = new MQTTRequest("subscribeTopic", requestID.getAndIncrement()); + + Log.d(TAG, "sub topic is " + topic); + + // 订阅主题 + mMqttConnection.subscribe(topic, qos, mqttRequest); + + } + + /** + * 取消订阅主题 + * + */ + public void unSubscribeTopic() { + // 主题 + String topic = mTestTopic; + // 用户上下文(请求实例) + MQTTRequest mqttRequest = new MQTTRequest("unSubscribeTopic", requestID.getAndIncrement()); + Log.d(TAG, "Start to unSubscribe" + topic); + // 取消订阅主题 + mMqttConnection.unSubscribe(topic, mqttRequest); + } + + /** + * 发布主题 + */ + public void publishTopic(String topicName, Map data) { + // 主题 + String topic = mTestTopic; + // MQTT消息 + MqttMessage message = new MqttMessage(); + + JSONObject jsonObject = new JSONObject(); + try { + for (Map.Entry entrys : data.entrySet()) { + jsonObject.put(entrys.getKey(), entrys.getValue()); + } + } catch (JSONException e) { + TXLog.e(TAG, e, "pack json data failed!"); + } + message.setQos(TXMqttConstants.QOS1); + message.setPayload(jsonObject.toString().getBytes()); + + // 用户上下文(请求实例) + MQTTRequest mqttRequest = new MQTTRequest("publishTopic", requestID.getAndIncrement()); + + Log.d(TAG, "pub topic " + topic + message); + // 发布主题 + mMqttConnection.publish(topic, message, mqttRequest); + + } + + /** + * 订阅RRPC主题 + * + */ + public void subscribeRRPCTopic() { + // 用户上下文(请求实例) + MQTTRequest mqttRequest = new MQTTRequest("subscribeTopic", requestID.getAndIncrement()); + // 订阅主题 + mMqttConnection.subscribeRRPCTopic(TXMqttConstants.QOS0, mqttRequest); + + } + + /** + * 生成一条日志 + * @param logLevel 日志级别: + * 错误:TXMqttLogConstants.LEVEL_ERROR + * 警告:TXMqttLogConstants.LEVEL_WARN + * 通知:TXMqttLogConstants.LEVEL_INFO + * 调试:TXMqttLogConstants.LEVEL_DEBUG + * @param tag + * @param format + * @param obj + */ + public void mLog(int logLevel, final String tag,final String format, final Object... obj) { + if (mMqttLogFlag) + mMqttConnection.mLog(logLevel, tag, format, obj); + } + + /** + * 发起一次日志上传 + */ + public void uploadLog() { + mMqttConnection.uploadLog(); + } + + public void checkFirmware() { + + mMqttConnection.initOTA(Environment.getExternalStorageDirectory().getAbsolutePath(), new TXOTACallBack() { + @Override + public void onReportFirmwareVersion(int resultCode, String version, String resultMsg) { + TXLog.e(TAG, "onReportFirmwareVersion:" + resultCode + ", version:" + version + ", resultMsg:" + resultMsg); + } + + @Override + public boolean onLastestFirmwareReady(String url, String md5, String version) { + TXLog.e(TAG, "MQTTSample onLastestFirmwareReady"); + return false; + } + + @Override + public void onDownloadProgress(int percent, String version) { + TXLog.e(TAG, "onDownloadProgress:" + percent); + } + + @Override + public void onDownloadCompleted(String outputFile, String version) { + TXLog.e(TAG, "onDownloadCompleted:" + outputFile + ", version:" + version); + + mMqttConnection.reportOTAState(TXOTAConstansts.ReportState.DONE, 0, "OK", version); + } + + @Override + public void onDownloadFailure(int errCode, String version) { + TXLog.e(TAG, "onDownloadFailure:" + errCode); + + mMqttConnection.reportOTAState(TXOTAConstansts.ReportState.FAIL, errCode, "FAIL", version); + } + }); + mMqttConnection.reportCurrentFirmwareVersion("0.0.1"); + } +} diff --git a/uniplugin_module/src/main/res/layout/activity_main.xml b/uniplugin_module/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..2a24e27 --- /dev/null +++ b/uniplugin_module/src/main/res/layout/activity_main.xml @@ -0,0 +1,84 @@ + + + +