562935844@qq.com
2023-04-04 86116427931cc724ae1e3105738a34e0619ca287
增加网关未上云密钥为空的问题处理
21个文件已添加
1个文件已删除
36个文件已修改
3311 ■■■■ 已修改文件
HDLSDK/.idea/gradle.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/release/output-metadata.json 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/AndroidManifest.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/java/com/hdl/hdlsdk/device/DevicesListActivity.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/java/com/hdl/hdlsdk/device/DevicesListAdapter.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/res/layout/activity_main.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/res/values/strings.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/build.gradle 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/com.hdl.sdk/build.gradle 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/config.gradle 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/gradle.properties 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/build.gradle 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/libs/hxhttp_1.0.4_230201.aar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/HDLSdk.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/config/TopicConstant.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/exception/HDLLinkCode.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/IpUtils.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLLink.java 172 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/AuthenticateRequest.java 269 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/DeviceAuthRequest.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/GatewayInfoRequest.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/ListOidRequest.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/ListUploadRequest.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/AuthenticateResponse.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/DeviceInfoResponse.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/NetworkAccessBroadcastResponse.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/BaseCallBack.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/BaseInfo.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/CallBackListener.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/CloudLinkCode.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/GsonUtils.java 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HDLException.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HDLResponse.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HdlCloudApi.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HdlCloudController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/MD5Utils.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/ParameterizedTypeImpl.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/interceptor/EncryptInterceptor.java 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/interceptor/SmartHeader.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/interceptor/SmartHeaderInterceptor.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/config/HDLLinkConfig.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java 114 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLAuthSocket.java 218 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/UdpClient.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO.rar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/.idea/gradle.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/.idea/misc.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/build.gradle 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.0.20.aar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.1.0.aar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/src/main/AndroidManifest.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/src/main/java/com/hdl/hdlsdk/MainActivity.java 240 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/src/main/res/layout/activity_main.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/config.gradle 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/.idea/gradle.xml
@@ -7,6 +7,7 @@
        <option name="testRunner" value="GRADLE" />
        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="gradleJvm" value="JDK" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
HDLSDK/app/release/output-metadata.json
New file
@@ -0,0 +1,18 @@
{
  "version": 2,
  "artifactType": {
    "type": "APK",
    "kind": "Directory"
  },
  "applicationId": "com.hdl.hdlsdk",
  "variantName": "processReleaseResources",
  "elements": [
    {
      "type": "SINGLE",
      "filters": [],
      "versionCode": 1,
      "versionName": "1.0",
      "outputFile": "app-release.apk"
    }
  ]
}
HDLSDK/app/src/main/AndroidManifest.xml
@@ -10,6 +10,7 @@
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEM"/>
    <application
        android:name=".App"
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -1,5 +1,16 @@
package com.hdl.hdlsdk;
import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
@@ -9,47 +20,29 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.hdl.hdlsdk.device.DevicesListActivity;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.event.EventListener;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.IpUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.LinkRequest;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
import com.hdl.sdk.connect.bean.request.BroadcastRequest;
import com.hdl.sdk.connect.bean.request.PropertyReadRequest;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.request.ListUploadRequest;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.response.GatewaySearchBean;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack;
import com.hdl.sdk.connect.cloud.CallBackListener;
import com.hdl.sdk.connect.cloud.HDLException;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.connect.socket.HDLAuthSocket;
import com.hdl.sdk.connect.socket.HDLSocket;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.protocol.LinkMessageDecoder;
import com.hdl.sdk.connect.protocol.LinkMessageEncoder;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.codec.MessagePipeLine;
import java.util.Base64;
import com.hdl.sdk.connect.utils.AesUtil;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -59,9 +52,6 @@
import java.util.List;
import java.util.Map;
import static com.hdl.sdk.common.config.TopicConstant.GATEWAY_SEARCH_REPLY;
import static java.util.Base64.*;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
@@ -69,34 +59,168 @@
    private RecyclerView rv;
    private TextView tv;
    private TextView responseTv;
    private EditText editText;
    boolean isOn;
    private EventListener allTopicsListener;
    private String testLightSid = "0001010D48C71B02020100010101";
    private String secret = "";
    @Override
    protected void onDestroy() {
        super.onDestroy();
        removeAllTopicsListener();
    }
void init() {
//    HDLLinkConfig.getInstance().setLocalSecret("7d04c4e3c2b7d600");
//    HDLLinkConfig.getInstance().setGatewayId("1473119283609321473");
//    HDLLinkConfig.getInstance().setLocalEncrypt(true);
}
    @RequiresApi(api = Build.VERSION_CODES.O)
    void initDeviceInfo() {
        AuthenticateRequest.AuthenticateDeviceInfoBean infoBean = new AuthenticateRequest.AuthenticateDeviceInfoBean();
        infoBean.setDeviceMAC("f2c5d8bad48f");
        infoBean.setIPMAC("f2c5d8bad48f");
        infoBean.setDeviceName("音乐播放器");//设备名字
        infoBean.setDeviceModel("MCLog.431");//设备型号
        infoBean.setAccessMode("WIFI");
        infoBean.setIPGateway("192.168.1.1");
        infoBean.setIPAddress("192.168.1.103");
        infoBean.setGateway_type("screen.touch");
        infoBean.setHw_version("HW2.0");
        infoBean.setFw_version("Fw1.0");
        infoBean.setOID("010105000000FE11");//每个设备oid都要不一样
        infoBean.setSid("110105000000FE08110100000011");//每个设备的sid都要不一样
        infoBean.setSupplier("JINMAOYUN");
        HDLLinkConfig.getInstance().setDeviceInfoBean(infoBean);
    }
    void applyDeviceSecret() {
        tv.setText("开始申请设备密钥...");
        responseTv.setText("");
//        //正式服务器
        String appKey = "i8hR07jzrIS";//appkey
        String appSecret = "BmnJ8RWTtaVEBk24zPPF4UMwfYu0lAWU";//appsecret
        //测试服务器
//        String appKey ="FcRyUJlLJFF";
//        String appSecret = "wz8wn75ABidx8vXcFGUotqhwFkTaYvvJ";
//        String appKey = "L2OZliZRxHc";
//        String appSecret = "aCIWSvJDOukXfx3kivsKW11x9xdR3IbV";
        String supplier = "JINMAOYUN";//厂商
//        String mac = "AA00000000000100";//设备唯一MAC地址
        String mac = editText.getText().toString();
        String spk = "screen.touch";//产品spk
        if (TextUtils.isEmpty(mac)) {
            Toast.makeText(this, "mac不能为空!", Toast.LENGTH_SHORT).show();
            return;
        }
        HDLLink.getInstance().applyDeviceSecret(this, appKey, appSecret, supplier, mac, spk, new CallBackListener() {
            @Override
            public void onError(HDLException e) {
                tv.setText("申请失败");
                responseTv.setText(e.getMsg());
                secret = "";
            }
            @Override
            public void onSuccess(String msg) {
                tv.setText("申请成功");
                responseTv.setText(msg.toString());
                secret = msg.toString();
            }
        });
    }
    /**
     * 入网认证
     */
    void sendAuthenticateRequest() {
        tv.setText("开始入网认证...");
        responseTv.setText("");
        //认证提交参数准备
//
//        //测试服务器
//        String spkStr = "music.standard";//产品spk
//        String macStr = "AA000000000000AF";//设备唯一MAC地址
//        String secret = "44b360eb74b7ba64";//通过spk和mac提交云端认证后分配的secret
//        正式服务器
        String spkStr = "screen.touch";//产品spk
//        String macStr = "AA00000000000100";//设备唯一MAC地址
        String macStr = editText.getText().toString();//设备唯一MAC地址
//        String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret
        String mac_key = stringToMD5(stringToMD5(macStr + secret));
        String versionString = "HDL_V1.0.1";//
        String time = String.valueOf(System.currentTimeMillis());
        HDLLinkConfig.getInstance().getDeviceInfoBean().setDeviceMAC(macStr);
//        HDLLinkConfig.getInstance().setCurrentGateway(infoBean);
        //1.设置认证信息
        AuthenticateRequest.RequestBean requestBean = new AuthenticateRequest.RequestBean();
        requestBean.setMAC(macStr);
        requestBean.setSupplier("JINMAOYUN");
        requestBean.setFirmwareVersion(versionString);
        requestBean.setHardwareModel("1956F");
//        HDLLinkConfig.getInstance().setRequestBean(requestBean);
        AuthenticateRequest.AuthBean authbean = new AuthenticateRequest.AuthBean();
        authbean.setSpk(spkStr);
        authbean.setMACKey(mac_key);
        authbean.setRequest(requestBean);
        HDLLinkConfig.getInstance().setAuthBean(authbean);
        //HDLLinkConfig.getInstance().getDeviceInfoBean()这个初始化的时候要先设置好
        AuthenticateRequest request = new AuthenticateRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), authbean);
        HDLLink.getInstance().startAuthenticateRequest(request, new HDLLinkCallBack() {
            @Override
            public void onError(HDLLinkException e) {
                tv.setText("认证失败" + e.getCode());
                responseTv.setText(e.getMsg());
                Log.e(TAG, "onError: 认证失败 " + e.getCode());
            }
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public void onSuccess(String msg) {
                tv.setText("认证成功");
                responseTv.setText(msg.toString());
            }
        });
    }
    public void UploadDeviceAuth(String mac, String result, String message, String auth_code) {
        //将认证结果上报给网关
        HDLLink.getInstance().UploadDeviceAuth(mac, result, message, auth_code, new HDLLinkCallBack() {
            @Override
            public void onSuccess(String s) {
                tv.setText("上报结果成功");
                responseTv.setText(s.toString());
            }
            @Override
            public void onError(HDLLinkException e) {
                tv.setText("上报结果失败");
                responseTv.setText(e.getMsg());
                Log.i(TAG, "onError: 上报结果失败");
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        responseTv = findViewById(R.id.response_tv);
        editText = findViewById(R.id.edittext);
        tv = findViewById(R.id.state_tv);
        rv = findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
         init();
        selectnetwork();
        checkIfCertified();
        initDeviceInfo();//初始化基本信息,非常重要,认证时要用
        initDeviceInfo();//初始化
        registerAllTopicsListener();
        ActivityResultLauncher<String[]> launcher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
@@ -108,9 +232,11 @@
        launcher.launch(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE});
        final List<DemoBean> beans = new ArrayList<>();
        final List<DemoBean> beans = new ArrayList<DemoBean>();
        beans.add(new DemoBean("申请设备密钥"));
        beans.add(new DemoBean("入网认证"));
        beans.add(new DemoBean("搜索指定网关是否在线"));
        beans.add(new DemoBean("上报oid列表"));
        beans.add(new DemoBean("获取功能列表"));
        beans.add(new DemoBean("功能属性读取"));
        beans.add(new DemoBean("设备控制"));
@@ -122,6 +248,7 @@
        beans.add(new DemoBean("TCP发送"));
        beans.add(new DemoBean("UDP发送,监听主题回复,带重发带回调"));
        beans.add(new DemoBean("TCP发送,监听主题回复,带重发带回调"));
        beans.add(new DemoBean("退网"));
        demoAdapter = new DemoAdapter(beans);
        rv.setAdapter(demoAdapter);
@@ -137,56 +264,68 @@
            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                switch (position) {
                    case 0:
                        //申请设备密钥
                        applyDeviceSecret();
                        break;
                    case 1:
                        //入网认证
                        sendAuthenticateRequest();
                        break;
                    case 1:
                    case 2:
                        //搜索网关
                        searchGatewayBroadcast();
                        break;
                    case 2:
                    case 3:
                        //上报oid列表
                        UploadOidList();
                        break;
                    case 4:
                        //获取功能列表
                        getFunctionList();
                        break;
                    case 3:
                    case 5:
                        //功能属性读取
                        getFunctionAttribute();
                        break;
                    case 4:
                    case 6:
                        //设备控制
                        controlDecide();
                        break;
                    case 5:
                    case 7:
                        //读取状态
                        propertyRead();
                        break;
                    case 6:
                    case 8:
                        //获取场景列表
                        getSceneList();
                        break;
                    case 7:
                        //获取场景列表
                    case 9:
                        //场景控制
                        controlScene();
                        break;
                    case 8:
                    case 10:
                        //功能列表
                        startDevicesListActivity();
                        break;
                    case 9:
                    case 11:
                        //UDP发送
                        udpSend();
                        break;
                    case 10:
                    case 12:
                        //TCP发送
                        tcpSend();
                        break;
                    case 11:
                    case 13:
                        //UDP发送,监听主题回复,带重发带回调
                        udpSendWithCallback();
                        break;
                    case 12:
                    case 14:
                        //TCP发送,监听主题回复,带重发带回调
                        tcpSendWithCallback();
                        break;
                    case 15:
                        //退网
                        deleteNetwork();
                        break;
                }
            }
@@ -196,6 +335,10 @@
    public void showToast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }
    void selectnetwork() {
        HDLLink.getInstance().selectNetwork("wlan0");
    }
    /**
@@ -216,7 +359,6 @@
            @Override
            public void onMessage(Object msg) {
                LinkResponse response = (LinkResponse) msg;
                handleLinkResponse(response);
            }
        };
        HDLLink.getInstance().registerAllTopicsListener(allTopicsListener);
@@ -265,74 +407,6 @@
        HDLLink.getInstance().removeAllTopicsListener(allTopicsListener);
    }
    void initDeviceInfo()
    {
        AuthenticateRequest.AuthenticateDeviceInfoBean infoBean = new AuthenticateRequest.AuthenticateDeviceInfoBean();
        infoBean.setDeviceMAC("AA00000000000100");
        infoBean.setIPMAC("AA00000000000100");
        infoBean.setDeviceName("音乐播放器");//设备名字
        infoBean.setDeviceModel("MCLog.431");//设备型号
        infoBean.setAccessMode("WIFI");
        infoBean.setIPGateway("192.168.1.1");
        infoBean.setIPAddress("192.168.1.116");
        infoBean.setGateway_type("music.standard");
        infoBean.setHw_version("HW2.0");
        infoBean.setFw_version("Fw1.0");
        infoBean.setOID("010105000000FE11");//每个设备oid都要不一样
        infoBean.setSid("110105000000FE08110100000011");//每个设备的sid都要不一样
        HDLLinkConfig.getInstance().setDeviceInfoBean(infoBean);
    }
    /**
     * 入网认证
     */
    void sendAuthenticateRequest() {
        tv.setText("开始入网认证...");
        //认证提交参数准备
//        测试服务
//        String spkStr = "ir.module";//产品spk
//        String macStr = "AA000000000000AF";//设备唯一MAC地址
//        String secret = "44b360eb74b7ba64";//通过spk和mac提交云端认证后分配的secret
//        正式服务器
        String spkStr = "screen.mirror";//产品spk
        String macStr = "AA00000000000100";//设备唯一MAC地址
        String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret
        String mac_key = stringToMD5(stringToMD5(macStr + secret));
        String versionString = "HDL_V1.0.1";//
        String time = String.valueOf(System.currentTimeMillis());
        HDLLinkConfig.getInstance().getDeviceInfoBean().setDeviceMAC(macStr);
        //1.设置认证信息
        AuthenticateRequest.RequestBean requestBean = new AuthenticateRequest.RequestBean();
        requestBean.setMAC(macStr);
        requestBean.setSupplier("WISE");
        requestBean.setFirmwareVersion(versionString);
        requestBean.setHardwareModel("1956F");
        AuthenticateRequest.AuthBean authbean = new AuthenticateRequest.AuthBean();
        authbean.setSpk(spkStr);
        authbean.setMACKey(mac_key);
        authbean.setRequest(requestBean);
        //HDLLinkConfig.getInstance().getDeviceInfoBean()这个初始化的时候要先设置好
        AuthenticateRequest request = new AuthenticateRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), authbean);
        HDLLink.getInstance().startAuthenticateRequest(request, new HDLLinkCallBack() {
            @Override
            public void onError(HDLLinkException e) {
                tv.setText("认证失败");
                responseTv.setText(e.getMsg());
                Log.i("TAG", "onError: 认证失败");
            }
            @Override
            public void onSuccess(String msg) {
                tv.setText("认证成功");
                responseTv.setText(msg.toString());
                Log.i("TAG", "onSuccess: 认证成功");
            }
        });
    }
    String stringToMD5(String text) {
        byte[] hash;
@@ -362,6 +436,7 @@
     */
    void searchGatewayBroadcast() {
        tv.setText("搜索网关中...");
        responseTv.setText("");
        HDLLink.getInstance().searchGatewayBroadcast(new HDLAuthSocket.SearchGatewayCallBack() {
            @Override
            public void onError(HDLLinkException e) {
@@ -404,6 +479,7 @@
     */
    void getFunctionAttribute() {
        tv.setText("功能属性读取");
        responseTv.setText("");
        List<String> sids = new ArrayList<>();
        sids.add(testLightSid);
        HDLLink.getInstance().getFunctionAttribute(sids, new HDLLinkCallBack() {
@@ -425,6 +501,7 @@
     */
    void propertyRead() {
        tv.setText("读取状态中...");
        responseTv.setText("");
        List<String> list = new ArrayList<>();
        list.add(testLightSid);//要读取设备的sid
        HDLLink.getInstance().propertyRead(list, new HDLLinkCallBack() {
@@ -448,6 +525,7 @@
     */
    void controlDecide() {
        tv.setText("控制设备");
        responseTv.setText("");
        isOn = !isOn;
        List<DeviceControlRequest> requestList = new ArrayList<>();
        DeviceControlRequest request = new DeviceControlRequest();
@@ -477,6 +555,7 @@
     */
    void getSceneList() {
        tv.setText("读取场景列表");
        responseTv.setText("");
        HDLLink.getInstance().getSceneList(new HDLLinkCallBack() {
            @Override
            public void onSuccess(String msg) {
@@ -499,6 +578,7 @@
     */
    void controlScene() {
        tv.setText("场景控制");
        responseTv.setText("");
        //控制场景sid列表,支持批量控制
        List<String> sids = new ArrayList<>();
        isOn = !isOn;
@@ -531,6 +611,7 @@
     */
    private void tcpSend() {
        tv.setText("TCP发送 只发一次,不监听回复,不重发");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr);
@@ -541,6 +622,7 @@
     */
    private void udpSend() {
        tv.setText("UDP发送 只发一次,不监听回复,不重发");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr);
@@ -573,6 +655,7 @@
     */
    private void udpSendWithCallback() {
        tv.setText("UDP发送,监听主题回复,带重发带回调");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr, new HDLLinkResponseCallBack() {
@@ -594,6 +677,7 @@
     */
    private void tcpSendWithCallback() {
        tv.setText("TCP发送,监听主题回复,带重发带回调");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr, new HDLLinkCallBack() {
@@ -609,4 +693,54 @@
            }
        });
    }
    private void deleteNetwork() {
        tv.setText("退网");
        responseTv.setText("");
        String oid = HDLLinkConfig.getInstance().getDeviceInfoBean().getOID();
        HDLLink.getInstance().deleteNetwork(oid, false, new HDLLinkCallBack() {
            @Override
            public void onSuccess(String msg) {
                responseTv.setText(msg);
                //退网成功,删除数据
            }
            @Override
            public void onError(HDLLinkException e) {
                responseTv.setText(e.getMsg());
            }
        });
    }
    /**
     * 上报oid列表
     */
    private void UploadOidList() {
        tv.setText("上报oid列表...");
        responseTv.setText("");
        //1.设置设备信息
        AuthenticateRequest.AuthenticateDeviceInfoBean authenticateDeviceInfoBean = HDLLinkConfig.getInstance().getDeviceInfoBean();
        ListUploadRequest request = new ListUploadRequest();
        request.setOid(authenticateDeviceInfoBean.getOID());
        request.setDevice_name(authenticateDeviceInfoBean.getDeviceName());
        request.setDevice_model(authenticateDeviceInfoBean.getDeviceModel());
        request.setDevice_mac(authenticateDeviceInfoBean.getDeviceMAC());
        request.setSrc("LINK");//来自哪个驱动,如Link设备没有则填"LINK"
        request.setFrom(authenticateDeviceInfoBean.getOID());//来自哪个网关,如果时Link网络设备,则填自身oid;如果是驱动则不需要此字段
        HDLLink.getInstance().UploadOidList(request, new HDLLinkCallBack() {
            @Override
            public void onError(HDLLinkException error) {
                tv.setText(error.getMsg());
            }
            @Override
            public void onSuccess(String data) {
                tv.setText("上报oid列表成功");
                responseTv.setText(data);
            }
        });
    }
}
HDLSDK/app/src/main/java/com/hdl/hdlsdk/device/DevicesListActivity.java
@@ -1,24 +1,20 @@
package com.hdl.hdlsdk.device;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.reflect.TypeToken;
import com.hdl.hdlsdk.DemoAdapter;
import com.hdl.hdlsdk.R;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.response.GatewaySearchBean;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import java.util.ArrayList;
HDLSDK/app/src/main/java/com/hdl/hdlsdk/device/DevicesListAdapter.java
@@ -9,24 +9,13 @@
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseMultiItemQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.hdl.hdlsdk.DemoBean;
import com.hdl.hdlsdk.R;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import java.util.ArrayList;
import java.util.List;
HDLSDK/app/src/main/res/layout/activity_main.xml
@@ -40,10 +40,20 @@
            android:layout_height="match_parent"
            android:orientation="vertical">
            <EditText
                android:id="@+id/edittext"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingStart="10dp"
                android:hint="请输入mac"
                android:text="f2c5d8bad48f"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingStart="10dp"
                android:layout_marginTop="@dimen/dp_10"
                android:text="当前状态:" />
            <TextView
HDLSDK/app/src/main/res/values/strings.xml
@@ -1,3 +1,4 @@
<resources>
    <string name="app_name">HDLSDK</string>
    <string name="http_unknown">未知网络错误,请稍后再试</string>
</resources>
HDLSDK/build.gradle
@@ -3,7 +3,13 @@
buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url = uri("https://plugins.gradle.org/m2/") }
        maven {
            url "https://jitpack.io"
        }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.2"
@@ -18,8 +24,20 @@
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url = uri("https://plugins.gradle.org/m2/") }
        google()
        jcenter()
        mavenCentral()
        maven { url "https://jitpack.io" }
        maven {
            credentials {
                username rootProject.ext.ALIYUN_USER_NAME
                password rootProject.ext.ALIYUN_PASSWORD
            }
            url 'https://packages.aliyun.com/maven/repository/2012126-release-Mc0DNo/'
        }
    }
}
HDLSDK/com.hdl.sdk/build.gradle
@@ -1,6 +1,6 @@
//打包的
apply plugin: 'com.android.library'
apply plugin:'com.kezong.fat-aar'
apply plugin: 'com.kezong.fat-aar'
android {
    compileSdkVersion rootProject.compileSdkVersion
@@ -9,7 +9,7 @@
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 2
        versionName "1.0.15"
        versionName "1.1.0"
    }
    buildTypes {
        debug {
@@ -27,14 +27,32 @@
    implementation fileTree(include: ['*.jar'], dir: 'libs')
//    embed 'com.ezviz.sdk:ezviz-sdk:4.16.1'
//    embed(name: 'hdl-common-release',ext: 'aar')
//    embed(name: 'hdl-connect-release',ext: 'aar')
//    embed(name: 'hdl-socket-release',ext: 'aar')
    embed 'com.hdl.hdlhttp:hxhttp:1.0.4'
//    embed project(path: ':hdl-common', configuration:'default')
    embed project(path: ':hdl-connect', configuration:'default')
//    embed project(path: ':hdl-socket', configuration:'default')
//    api 'androidx.appcompat:appcompat:1.3.1'
//    api 'com.google.android.material:material:1.4.0'
    embed 'com.squareup.okhttp3:okhttp:4.9.1'
    embed 'com.squareup.okhttp3:logging-interceptor:4.9.1'
    embed 'com.squareup.okio:okio:2.8.0'
    //retrofit
    embed 'com.squareup.retrofit2:retrofit:2.9.0'
    embed 'com.squareup.retrofit2:converter-scalars:2.9.0'
    embed 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
    embed 'io.reactivex.rxjava3:rxandroid:3.0.0'
    embed 'io.reactivex.rxjava3:rxjava:3.1.1'
    embed 'com.google.code.gson:gson:2.8.8'
    embed 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
    embed 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
    embed 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2'
    embed 'org.reactivestreams:reactive-streams:1.0.3'
//    embed(name: 'hxhttp_1.0.4_230201',ext: 'aar')
    embed project(path: ':hdl-connect', configuration: 'default')
}
//打包的
@@ -43,7 +61,7 @@
    repositories {
        google()
        jcenter()
        maven {url "https://plugins.gradle.org/m2/"}
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
@@ -52,16 +70,15 @@
    }
}
//allprojects {
//    repositories {
//        flatDir{
//            dirs 'libs'
//        }
//        google()
//        jcenter()
//    }
//}
allprojects {
    repositories {
        flatDir {
            dirs 'libs'
        }
        google()
        jcenter()
    }
}
////运行的
HDLSDK/config.gradle
@@ -1,5 +1,8 @@
ext {
    minSdkVersion = 16
    minSdkVersion = 21
    targetSdkVersion = 31
    compileSdkVersion = 31
    ALIYUN_USER_NAME = "611f24277cbfb3c62b5b1d4f"
    ALIYUN_PASSWORD = "sJA([gwZJ5Y0"
}
HDLSDK/gradle.properties
@@ -14,6 +14,6 @@
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
#android.useAndroidX=true
android.useAndroidX=true
### Automatically convert third-party libraries to use AndroidX
#android.enableJetifier=true
android.enableJetifier=true
HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java
@@ -147,7 +147,7 @@
                                        listener.onMessage(o);
                                    }
                                } catch (Exception e) {
                                    LogUtils.e("post异常1:" + e.getMessage());
//                                    LogUtils.e("post异常1:" + e.getMessage());
                                }
                            }
                        });
HDLSDK/hdl-connect/build.gradle
@@ -9,7 +9,7 @@
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 2
        versionName "1.0.21"
        versionName "1.1.0"
        consumerProguardFiles "consumer-rules.pro"
    }
@@ -27,6 +27,11 @@
}
dependencies {
//    api project(path: ':hdl-socket')
//    implementation fileTree(include: ['*.jar'], dir: 'libs')
    api 'com.hdl.hdlhttp:hxhttp:1.0.4'
    api 'com.squareup.okhttp3:logging-interceptor:4.9.1'
//    embed(name: 'hxhttp_1.0.4_230201',ext: 'aar')
    api 'com.google.code.gson:gson:2.8.8'
}
HDLSDK/hdl-connect/libs/hxhttp_1.0.4_230201.aar
Binary files differ
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/HDLSdk.java
@@ -32,7 +32,7 @@
        return version;
    }
    private String version = "1.0.22";
    private String version = "1.1.0";
    private HDLSdk() {
    }
@@ -47,6 +47,7 @@
    public void init(Context context) {
        this.context = context.getApplicationContext();
        HDLAuthSocket.getInstance().init();
        HDLSocket.getInstance().broadcastRequest();
        LogUtils.i("HDLSdk Version:" + version);
    }
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/config/TopicConstant.java
@@ -14,6 +14,9 @@
    //设备入网和认证响应
    public static final String DEIVCE_AUTH_REQUEST_REPLY = "/user/all/custom/device/network_access/request_reply";
    //入网认证结果反馈
    public static final String DEIVCE_AUTH_RESULT_NOTIFY = "/user/%s/custom/device/auth/result_notify";
    //搜索网关
    public static final String GATEWAY_SEARCH = "/user/all/custom/gateway/search";
@@ -83,19 +86,38 @@
    /**
     * 设备连接TCP之前广播
     */
    public static final String BROADCAST="/user/all/custom/gateway/broadcast";
    public static final String BROADCAST = "/user/all/custom/gateway/broadcast";
    /**
     * 主网关回复
     */
    public static final String BROADCAST_REPLY="/user/all/custom/gateway/broadcast_reply";
    public static final String BROADCAST_REPLY = "/user/all/custom/gateway/broadcast_reply";
    public static final String LINK_BROADCAST = "/user/all/custom/gateway/broadcast_reply";
    /**
     * 心跳检测
     */
    public static final String HEARTBEAT="/user/%s/custom/gateway/heartbeat";
    public static final String HEARTBEAT = "/user/%s/custom/gateway/heartbeat";
    /**
     * 心跳检测回复
     */
    public static final String HEARTBEAT_REPLY="/user/%s/custom/gateway/heartbeat_reply";
    public static final String HEARTBEAT_REPLY = "/user/%s/custom/gateway/heartbeat_reply";
    //通知删除并退网子设备
    public static final String DELETE_REQUEST = "/base/%s/thing/topo/delete/request";
    //网关响应退网通知
    public static final String DELETE_NOTIFY_REPLY = "/base/%s/thing/topo/delete/notify_reply";
    //网关物理删除(退网)子设备后上报
    public static final String DELETE_UP = "/base/%s/thing/topo/delete/up";
    //驱动上报oid列表
    public static final String LIST_UPLOAD = "/user/%s/custom/device/list/upload";
    //驱动上报oid列表回复
    public static final String LIST_UPLOAD_REPLY = "/user/%s/custom/device/list/upload_reply";
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java
@@ -147,7 +147,7 @@
                                        listener.onMessage(o);
                                    }
                                } catch (Exception e) {
                                    LogUtils.e("post异常1:" + e.getMessage());
//                                    LogUtils.e("post异常1:" + e.getMessage());
                                }
                            }
                        });
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/exception/HDLLinkCode.java
@@ -7,6 +7,8 @@
 */
public enum HDLLinkCode {
    HDL_AUTH_124013_ERROR(124013,"该MAC对应的设备密钥不存在"),
    HDL_AUTH_124015_ERROR(124015,"设备厂家不匹配"),
    HDL_DATA_ERROR(-2000,"参数异常"),
    HDL_DATA_NULL_ERROR(-2001,"参数不能为空"),
    HDL_AUTH_ERROR(-2002,"认证失败"),
@@ -19,7 +21,8 @@
    HDL_GET_DEVICE_LIST_ERROR(-2100,"获取设备列表失败"),
    HDL_GET_FUNCTION_LIST_ERROR(-2101,"获取功能列表失败"),
    HDL_GET_FUNCTION_PROPERTIES_ERROR(-2102,"获取功能属性失败"),
    HDL_CONTROL_FAILURE_ERROR(-2103,"控制失败");
    HDL_CONTROL_FAILURE_ERROR(-2103,"控制失败"),
    HDL_UPLOAD_GATEWAYINFO_FAILURE_ERROR(-2104,"上报失败");
    private String msg;
    private int code;
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/IpUtils.java
@@ -3,6 +3,10 @@
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Log;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import java.net.InetAddress;
import java.net.InterfaceAddress;
@@ -15,10 +19,10 @@
 */
public class IpUtils {
    /**
     * @return 广播地址
     */
    public static String getBroadcastAddress() {
//    /**
//     * @return 广播地址
//     */
    /*public static String getBroadcastAddress() {
//        try {
//            for (Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
//                 niEnum.hasMoreElements(); ) {
@@ -34,6 +38,45 @@
//        } catch (SocketException e) {
//            e.printStackTrace();
//        }
        return "255.255.255.255";
    }*/
    /**
     * @return 广播地址
     */
    public static synchronized String getBroadcastAddress() {
        try {
            if (!TextUtils.isEmpty(HDLLinkConfig.getInstance().getNetworkName())) {
                for (Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
                     niEnum.hasMoreElements(); ) {
                    NetworkInterface ni = niEnum.nextElement();
                    if (!ni.isLoopback() && ni.getName().equalsIgnoreCase(HDLLinkConfig.getInstance().getNetworkName())) {
                        for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
                            if (interfaceAddress.getBroadcast() != null) {
                                Log.d("TAG", "----->ni.getName()= " + ni.getName() + " ip= " + interfaceAddress.getBroadcast().toString().substring(1));
                                return interfaceAddress.getBroadcast().toString().substring(1);
                            }
                        }
                    }
                }
                for (Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
                     niEnum.hasMoreElements(); ) {
                    NetworkInterface ni = niEnum.nextElement();
                    if (!ni.isLoopback()) {
                        for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
                            if (interfaceAddress.getBroadcast() != null) {
                                Log.d("TAG", "----->ip= " + interfaceAddress.getBroadcast().toString().substring(1));
                                return interfaceAddress.getBroadcast().toString().substring(1);
                            }
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return "255.255.255.255";
    }
@@ -86,4 +129,107 @@
                ((i >> 16) & 0xFF) + "." +
                (i >> 24 & 0xFF);
    }
    private static String getWifiManagerAddress(Context context) {
        try {
            if (context != null) {
                WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                if (wifiManager != null && wifiManager.isWifiEnabled()) {
                    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                    int ipAddress = wifiInfo.getIpAddress();
                    return intToIp(ipAddress);
                }
            }
        } catch (Exception ignored) {
        }
        return null;
    }
    public static String getWifiIpV4Address(Context context) {
        try {
            //直接从wifiManager获取
            String managerAddress = getWifiManagerAddress(context);
            if (!TextUtils.isEmpty(managerAddress)) {
                return managerAddress;
            }
            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
            while (enumeration.hasMoreElements()) {
                NetworkInterface network = enumeration.nextElement();
                if (network == null || network.isVirtual() || !network.isUp() || network.isLoopback() || !network.getName().equalsIgnoreCase("eth0")) {
                    continue;
                } else {
                    Enumeration<InetAddress> addresses = network.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress address = addresses.nextElement();
                        if (!address.isLoopbackAddress() && !address.isAnyLocalAddress()
                                && !address.isLinkLocalAddress()) {
                            String hostAddress = address.getHostAddress();
                            if (hostAddress != null) {
                                boolean isIPv4 = hostAddress.indexOf(':') < 0;
                                if (isIPv4) return hostAddress;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static String getEth0IpV4Address() {
        try {
            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
            while (enumeration.hasMoreElements()) {
                NetworkInterface network = enumeration.nextElement();
                if (network == null || network.isVirtual() || !network.isUp() || network.isLoopback() || !network.getName().equalsIgnoreCase("eth0")) {
                    continue;
                } else {
                    Enumeration<InetAddress> addresses = network.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress address = addresses.nextElement();
                        if (!address.isLoopbackAddress() && !address.isAnyLocalAddress()
                                && !address.isLinkLocalAddress()) {
                            String hostAddress = address.getHostAddress();
                            if (hostAddress != null) {
                                boolean isIPv4 = hostAddress.indexOf(':') < 0;
                                if (isIPv4) return hostAddress;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * @return 获取全部有效ip地址, 优先返回有线ip
     */
    public static String getIpV4Address(Context context) {
        try {
            String eth0IpV4Address = getEth0IpV4Address();
            if (!TextUtils.isEmpty(eth0IpV4Address)) {
                return eth0IpV4Address;
            }
            String wifiIpV4Address = getWifiIpV4Address(context);
            if (!TextUtils.isEmpty(wifiIpV4Address)) {
                return wifiIpV4Address;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLLink.java
@@ -1,10 +1,20 @@
package com.hdl.sdk.connect;
import android.content.Context;
import com.hdl.hdlhttp.HxHttpConfig;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.connect.bean.request.DeviceAuthRequest;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.request.ListUploadRequest;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack;
import com.hdl.sdk.connect.cloud.CallBackListener;
import com.hdl.sdk.connect.cloud.HdlCloudApi;
import com.hdl.sdk.connect.cloud.HdlCloudController;
import com.hdl.sdk.connect.cloud.interceptor.EncryptInterceptor;
import com.hdl.sdk.connect.cloud.interceptor.SmartHeaderInterceptor;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.common.event.EventDispatcher;
import com.hdl.sdk.common.event.EventListener;
@@ -15,6 +25,9 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
import io.reactivex.rxjava3.disposables.Disposable;
import okhttp3.logging.HttpLoggingInterceptor;
/**
 * Created by jlchen on 11/15/21.
 *
@@ -24,13 +37,16 @@
    /**
     * instance
     */
    private  static final HDLLink instance=new HDLLink();
    private static final HDLLink instance = new HDLLink();
    private String appKey, appSecret;
    /**
     * getInstance
     *
     * @return HDLLink
     */
    public static  HDLLink getInstance() {
    public static HDLLink getInstance() {
//        if (instance == null) {
//            synchronized (HDLLink.class) {
//                if (instance == null) {
@@ -41,19 +57,38 @@
        return instance;
    }
    public String getAppKey() {
        return appKey;
    }
    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }
    public String getAppSecret() {
        return appSecret;
    }
    public void setAppSecret(String appSecret) {
        this.appSecret = appSecret;
    }
    /**
     * 注册所有主题消息的监听
     *
     * @param listener
     */
    public synchronized void registerAllTopicsListener(EventListener listener){
    public synchronized void registerAllTopicsListener(EventListener listener) {
        EventDispatcher.getInstance().registerAllTopicsListener(listener);
    }
    /**
     * 取消所有主题消息的监听
     *
     * @param listener
     */
    public synchronized void removeAllTopicsListener(EventListener listener) {
        if(listener == null) return;
        if (listener == null) return;
        EventDispatcher.getInstance().removeAllTopicsListener(listener);
    }
@@ -61,10 +96,15 @@
    /**
     * 检测是否已经认证过
     * 认证通过才能进行设备控制
     *
     * @return
     */
    public boolean checkIfCertified(){
    public boolean checkIfCertified() {
        return HDLLinkConfig.getInstance().checkIfCertified();
    }
    public void selectNetwork(String networkName) {
        HDLLinkConfig.getInstance().setNetworkName(networkName);
    }
    /**
@@ -75,7 +115,7 @@
     */
    public void startAuthenticateRequest(AuthenticateRequest request, HDLLinkCallBack callBack) {
        LogUtils.i("发送认证请求");
        HDLAuthSocket.getInstance().startAuthenticateRequest(request,callBack);
        HDLAuthSocket.getInstance().startAuthenticateRequest(request, callBack);
    }
    /**
@@ -89,26 +129,62 @@
        HDLAuthSocket.getInstance().sendAuthenticateRequest(ip, request, callBack);
    }
    //    /**
//     * 开始搜索所有网关,有网关回复就回调,上层自己做去重判断
//     *
//     * @param callBack 回调
//     */
//    public void startSearchAllGateway(HDLAuthSocket.SearchGatewayCallBack callBack) {
//
//    }
//
//    /**
//     * 暂停搜索网关
//     */
//    public void endSearchAllGateway() {
//
//    }
    /**
     * 入网认证结果反馈
     *
     * @param mac       mac
     * @param result    结果0/-1
     * @param message   认证信息
     * @param auth_code 云端认证code
     * @param callBack  结果回调
     */
    public void UploadDeviceAuth(String mac, String result, String message, String auth_code, HDLLinkCallBack callBack) {
        HDLSocket.getInstance().UploadDeviceAuth(mac, result, message, auth_code, callBack);
    }
    /**
     * 申请设备密钥(根据设备MAC)
     *
     * @param supplier 厂商
     * @param mac      设备mac
     * @param spk      设备spk
     * @param callBack 结果回调
     */
    public void applyDeviceSecret(Context context, String appKey, String appSecret, String supplier, String mac, String spk, CallBackListener callBack) {
        LogUtils.i("申请设备密钥");
        HxHttpConfig.getInstance().init(context, HdlCloudApi.BASE_CHINA_URL)
                .addInterceptor(
                        new EncryptInterceptor(),
                        new SmartHeaderInterceptor());
        this.appKey = appKey;
        this.appSecret = appSecret;
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.BODY);
        HxHttpConfig.getInstance()
                //.addInterceptor(new HttpCacheInterceptor())
                .addInterceptor(httpLoggingInterceptor).ignoreSSL();
        HdlCloudController.applyDeviceSecret(supplier, mac, spk, callBack);
    }
    /**
     * 通知删除并退网子设备
     *
     * @param oid      从网关(设备)oid
     * @param isForce  是否强制退网
     * @param callBack 结果回调
     */
    public void deleteNetwork(String oid, boolean isForce, HDLLinkCallBack callBack) {
        HDLSocket.getInstance().deleteNetwork(oid, isForce, callBack);
    }
    /***********************三方设备请先认证成功 再调用下面的接口和网关通信****************************/
    /**
     * 组播搜索指定网关是否在线,搜索到则返回指定的网关对象
     * @param callBack  回调
     *
     * @param callBack 回调
     */
    public void searchGatewayMulticast(HDLAuthSocket.SearchGatewayCallBack callBack) {
        HDLAuthSocket.getInstance().searchGatewayMulticast(callBack);
@@ -116,7 +192,8 @@
    /**
     * 组播搜索指定网关是否在线,搜索到则返回指定的网关对象
     * @param callBack  回调
     *
     * @param callBack 回调
     */
    public void searchGatewayBroadcast(HDLAuthSocket.SearchGatewayCallBack callBack) {
        HDLAuthSocket.getInstance().searchGatewayBroadcast(callBack);
@@ -148,7 +225,8 @@
    /**
     * 设备控制
     * @param request 控制状态参数
     *
     * @param request  控制状态参数
     * @param callBack 结果回调
     */
    public void propertyDown(List<DeviceControlRequest> request, HDLLinkCallBack callBack) {
@@ -157,7 +235,8 @@
    /**
     * 读取状态
     * @param sids 请求参数 指定读取的设备sid列表
     *
     * @param sids     请求参数 指定读取的设备sid列表
     * @param callBack 回调
     */
    public void propertyRead(List<String> sids, HDLLinkCallBack callBack) {
@@ -173,7 +252,8 @@
    /**
     * 场景控制
     * @param sids 场景sid列表
     *
     * @param sids     场景sid列表
     * @param callBack 回调
     */
    public void controlScene(List<String> sids, HDLLinkCallBack callBack) {
@@ -181,25 +261,37 @@
    }
    /**
     * 上报oid列表
     *
     * @param request  设备信息
     * @param callBack 回调
     */
    public void UploadOidList(ListUploadRequest request, HDLLinkCallBack callBack) {
        HDLSocket.getInstance().UploadOidList(request, callBack);
    }
    /**
     * 通用UDP发送指令
     * 1秒没响应就让他重新发送,重试3次
     * @param topic 发送数据
     * @param bodyStr body内容
     *
     * @param topic    发送数据
     * @param bodyStr  body内容
     * @param callBack 回调
     */
    public void udpSendMsg(String topic, String bodyStr, HDLLinkResponseCallBack callBack) {
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,false, callBack);
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr, false, callBack);
    }
    /**
     * 通用广播UDP发送指令
     * 1秒没响应就让他重新发送,重试3次
     * @param topic 发送数据
     * @param bodyStr body内容
     *
     * @param topic    发送数据
     * @param bodyStr  body内容
     * @param callBack 回调
     */
    public void udpBroadcastSendMsg(String topic, String bodyStr, HDLLinkResponseCallBack callBack) {
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,true, callBack);
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr, true, callBack);
    }
    /**
@@ -218,28 +310,28 @@
    /**
     * 通用发送指令 只发一次,不监听回复,不重发
     *
     * @param topic    发送数据
     * @param bodyStr  回复的主题
     * @param topic   发送数据
     * @param bodyStr 回复的主题
     */
    public void udpSendMsg(String topic, String bodyStr) {
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,false);
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr, false);
    }
    /**
     * 通用广播发送指令 只发一次,不监听回复,不重发
     *
     * @param topic    发送数据
     * @param bodyStr  回复的主题
     * @param topic   发送数据
     * @param bodyStr 回复的主题
     */
    public void udpBroadcastSendMsg(String topic, String bodyStr) {
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,true);
        HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr, true);
    }
    /**
     * 通用TCP发送指令 只发一次,不监听回复,不重发
     *
     * @param topic    发送数据
     * @param bodyStr  回复的主题
     * @param topic   发送数据
     * @param bodyStr 回复的主题
     */
    public void tcpSendMsg(String topic, String bodyStr) {
        HDLAuthSocket.getInstance();//通过这个可以先初始化UDP监听事件
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/AuthenticateRequest.java
@@ -1,5 +1,7 @@
package com.hdl.sdk.connect.bean.request;
import com.hdl.sdk.common.utils.SPUtils;
import java.io.Serializable;
/**
@@ -15,17 +17,37 @@
    private AuthenticateDeviceInfoBean objects;//当前设备基本信息
    private AuthBean auth;//认证信息
    public String getID() { return id; }
    public void setID(String value) { this.id = value; }
    public String getID() {
        return id;
    }
    public String getTimeStamp() { return time_stamp; }
    public void setTimeStamp(String value) { this.time_stamp = value; }
    public void setID(String value) {
        this.id = value;
    }
    public AuthenticateDeviceInfoBean getObjects() { return objects; }
    public void setObjects(AuthenticateDeviceInfoBean value) { this.objects = value; }
    public String getTimeStamp() {
        return time_stamp;
    }
    public AuthBean getAuth() { return auth; }
    public void setAuth(AuthBean value) { this.auth = value; }
    public void setTimeStamp(String value) {
        this.time_stamp = value;
    }
    public AuthenticateDeviceInfoBean getObjects() {
        return objects;
    }
    public void setObjects(AuthenticateDeviceInfoBean value) {
        this.objects = value;
    }
    public AuthBean getAuth() {
        return auth;
    }
    public void setAuth(AuthBean value) {
        this.auth = value;
    }
    public AuthenticateRequest(String id, String time_stamp, AuthenticateDeviceInfoBean objects, AuthBean auth) {
        this.id = id;
@@ -53,39 +75,58 @@
        /**
         * MAC key
         *
         * @return
         */
        public String getMACKey() { return mac_key; }
        public String getMACKey() {
            return mac_key;
        }
        /**
         * MACkey
         *
         * @param value
         */
        public void setMACKey(String value) { this.mac_key = value; }
        public void setMACKey(String value) {
            this.mac_key = value;
            SPUtils.put("auth_mackey_key", mac_key);
        }
        /**
         * SPK
         *
         * @return
         */
        public String getSpk() { return spk; }
        public String getSpk() {
            return spk;
        }
        /**
         * SPK
         *
         * @param value
         */
        public void setSpk(String value) { this.spk = value; }
        public void setSpk(String value) {
            this.spk = value;
        }
        public RequestBean getRequest() { return request; }
        public void setRequest(RequestBean value) { this.request = value; }
        public RequestBean getRequest() {
            return request;
        }
        public void setRequest(RequestBean value) {
            this.request = value;
        }
        public AuthBean() {
        }
        /**
         *  认证信息
         * 认证信息
         *
         * @param mac_key mac key
         * @param spk 产品spk
         * @param spk     产品spk
         * @param request 请求对象
         */
        public AuthBean(String mac_key, String spk, RequestBean request) {
@@ -95,12 +136,17 @@
        }
    }
    public static class RequestBean implements Serializable{
    public static class RequestBean implements Serializable {
        private String mac;//设备mac
        private String supplier;//厂家
        private String hardware_model;//设备型号
        private String firmware_version;//程序版本
        public RequestBean(){};
        public RequestBean() {
        }
        ;
        public RequestBean(String mac, String supplier, String hardware_model, String firmware_version) {
            this.mac = mac;
            this.supplier = supplier;
@@ -110,54 +156,78 @@
        /**
         * 设备MAC
         *
         * @return
         */
        public String getMAC() { return mac; }
        public String getMAC() {
            return mac;
        }
        /**
         * 设备MAC
         *
         * @param value
         */
        public void setMAC(String value) { this.mac = value; }
        public void setMAC(String value) {
            this.mac = value;
        }
        /**
         * 厂家
         *
         * @return
         */
        public String getSupplier() { return supplier; }
        public String getSupplier() {
            return supplier;
        }
        /**
         * 厂家
         *
         * @param value
         */
        public void setSupplier(String value) { this.supplier = value; }
        public void setSupplier(String value) {
            this.supplier = value;
        }
        /**
         * 硬件版本
         *
         * @return
         */
        public String getHardwareModel() { return hardware_model; }
        public String getHardwareModel() {
            return hardware_model;
        }
        /**
         * 硬件版本
         *
         * @param value
         */
        public void setHardwareModel(String value) { this.hardware_model = value; }
        public void setHardwareModel(String value) {
            this.hardware_model = value;
        }
        /**
         * 软件版本
         *
         * @return
         */
        public String getFirmwareVersion() { return firmware_version; }
        public String getFirmwareVersion() {
            return firmware_version;
        }
        /**
         * 软件版本
         *
         * @param value
         */
        public void setFirmwareVersion(String value) { this.firmware_version = value; }
        public void setFirmwareVersion(String value) {
            this.firmware_version = value;
        }
    }
    public static class AuthenticateDeviceInfoBean implements Serializable{
    public static class AuthenticateDeviceInfoBean implements Serializable {
        private String oid;//设备的Oid
        private String device_mac;//设备的Mac
        private String device_name;//
@@ -173,148 +243,232 @@
        private String gateway_type;
        private String hw_version;
        private String fw_version;
        private String supplier;//厂商
        public String getOID() { return oid; }
        public String getSupplier() {
            return supplier;
        }
        public void setSupplier(String supplier) {
            this.supplier = supplier;
        }
        public String getOID() {
            return oid;
        }
        /**
         * 设备Oid
         *
         * @param value
         */
        public void setOID(String value) { this.oid = value; }
        public void setOID(String value) {
            this.oid = value;
        }
        public String getDeviceMAC() { return device_mac; }
        public String getDeviceMAC() {
            return device_mac;
        }
        /**
         * 设备Mac
         *
         * @param value
         */
        public void setDeviceMAC(String value) { this.device_mac = value; }
        public void setDeviceMAC(String value) {
            this.device_mac = value;
        }
        /**
         * 设备名
         *
         * @return
         */
        public String getDeviceName() { return device_name; }
        public String getDeviceName() {
            return device_name;
        }
        /**
         * 设备名
         *
         * @param value
         */
        public void setDeviceName(String value) { this.device_name = value; }
        public void setDeviceName(String value) {
            this.device_name = value;
        }
        /**
         * 设备型号
         *
         * @return
         */
        public String getDeviceModel() { return device_model; }
        public String getDeviceModel() {
            return device_model;
        }
        /**
         * 设备型号
         *
         * @param value
         */
        public void setDeviceModel(String value) { this.device_model = value; }
        public void setDeviceModel(String value) {
            this.device_model = value;
        }
        /**
         * 连接类型,有线还是无线
         *
         * @return
         */
        public String getAccessMode() { return access_mode; }
        public String getAccessMode() {
            return access_mode;
        }
        /**
         * 连接类型,有线还是无线
         *
         * @param value
         */
        public void setAccessMode(String value) { this.access_mode = value; }
        public void setAccessMode(String value) {
            this.access_mode = value;
        }
        /**
         * 设备sid
         *
         * @return
         */
        public String getSid() { return sid; }
        public String getSid() {
            return sid;
        }
        /**
         * 设备sid
         *
         * @param value
         */
        public void setSid(String value) { this.sid = value; }
        public void setSid(String value) {
            this.sid = value;
        }
        /**
         * 设备IPMAC
         *
         * @return
         */
        public String getIPMAC() { return ip_mac; }
        public String getIPMAC() {
            return ip_mac;
        }
        /**
         * 设备IPMAC
         *
         * @param value
         */
        public void setIPMAC(String value) { this.ip_mac = value; }
        public void setIPMAC(String value) {
            this.ip_mac = value;
        }
        /**
         * 设备IP地址
         *
         * @return
         */
        public String getIPAddress() { return ip_address; }
        public String getIPAddress() {
            return ip_address;
        }
        /**
         * 设备IP地址
         *
         * @param value
         */
        public void setIPAddress(String value) { this.ip_address = value; }
        public void setIPAddress(String value) {
            this.ip_address = value;
        }
        /**
         * 子网掩码
         *
         * @return
         */
        public String getNetmask() { return netmask; }
        public String getNetmask() {
            return netmask;
        }
        /**
         * 子网掩码
         *
         * @param value
         */
        public void setNetmask(String value) { this.netmask = value; }
        public void setNetmask(String value) {
            this.netmask = value;
        }
        /**
         * 网关IP
         *
         * @return
         */
        public String getIPGateway() { return ip_gateway; }
        public String getIPGateway() {
            return ip_gateway;
        }
        /**
         * 网关IP
         *
         * @param value
         */
        public void setIPGateway(String value) { this.ip_gateway = value; }
        public void setIPGateway(String value) {
            this.ip_gateway = value;
        }
        /**
         * DNS1
         *
         * @return
         */
        public String getDns1() { return dns1; }
        public String getDns1() {
            return dns1;
        }
        /**
         * DNS1
         *
         * @param value
         */
        public void setDns1(String value) { this.dns1 = value; }
        public void setDns1(String value) {
            this.dns1 = value;
        }
        /**
         * DNS2
         *
         * @return
         */
        public String getDns2() { return dns2; }
        public String getDns2() {
            return dns2;
        }
        /**
         * DNS2
         *
         * @param value
         */
        public void setDns2(String value) { this.dns2 = value; }
        public void setDns2(String value) {
            this.dns2 = value;
        }
        public VersionBean[] getVersions() {return null;  }
        public void setVersions(VersionBean[] value) {  }
        public VersionBean[] getVersions() {
            return null;
        }
        public void setVersions(VersionBean[] value) {
        }
        /**
         * 网关类型
         *
         * @return
         */
        public String getGateway_type() {
@@ -323,6 +477,7 @@
        /**
         * 网关类型
         *
         * @param gateway_type
         */
        public void setGateway_type(String gateway_type) {
@@ -331,6 +486,7 @@
        /**
         * 硬件版本
         *
         * @return
         */
        public String getHw_version() {
@@ -338,7 +494,8 @@
        }
        /**
         *硬件版本
         * 硬件版本
         *
         * @param
         */
        public void setHw_version(String hw_version) {
@@ -348,6 +505,7 @@
        /**
         * 固件版本
         *
         * @return
         */
        public String getFw_version() {
@@ -356,6 +514,7 @@
        /**
         * 固件版本
         *
         * @param fw_version
         */
        public void setFw_version(String fw_version) {
@@ -363,7 +522,7 @@
        }
    }
    public static class VersionBean implements Serializable{
    public static class VersionBean implements Serializable {
        private String module;
        private String version;
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/DeviceAuthRequest.java
New file
@@ -0,0 +1,48 @@
package com.hdl.sdk.connect.bean.request;
import java.io.Serializable;
import java.util.List;
/**
 * Created by panlili on 2023/1/31
 * description:
 */
public class DeviceAuthRequest {
    private String mac;//mac
    private String result;//0为成功,-1为失败
    private String message;//success
    private String auth_code;//云端认证返回的code
    public String getMac() {
        return mac;
    }
    public void setMac(String mac) {
        this.mac = mac;
    }
    public String getResult() {
        return result;
    }
    public void setResult(String result) {
        this.result = result;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public String getAuth_code() {
        return auth_code;
    }
    public void setAuth_code(String auth_code) {
        this.auth_code = auth_code;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/GatewayInfoRequest.java
New file
@@ -0,0 +1,129 @@
package com.hdl.sdk.connect.bean.request;
import java.io.Serializable;
import java.util.List;
/**
 * Created by panlili on 2023/1/31
 * description:
 */
public class GatewayInfoRequest {
    private String device_model;
    private String device_mac;//设备的Mac
    private String device_name;
    private String gateway_type;//这里填spk
    private String access_mode;
    private String oid;//设备的Oid
    private String sid;//设备的sid
    private String supplier;//厂商
    private String hw_version;
    private String fw_version;
    private String ip_address;
    private String master;
    private boolean isLocalEncrypt;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getDevice_name() {
        return device_name;
    }
    public void setDevice_name(String device_name) {
        this.device_name = device_name;
    }
    public String getDevice_model() {
        return device_model;
    }
    public void setDevice_model(String device_model) {
        this.device_model = device_model;
    }
    public String getDevice_mac() {
        return device_mac;
    }
    public void setDevice_mac(String device_mac) {
        this.device_mac = device_mac;
    }
    public String getGateway_type() {
        return gateway_type;
    }
    public void setGateway_type(String gateway_type) {
        this.gateway_type = gateway_type;
    }
    public String getAccess_mode() {
        return access_mode;
    }
    public void setAccess_mode(String access_mode) {
        this.access_mode = access_mode;
    }
    public String getSid() {
        return sid;
    }
    public void setSid(String sid) {
        this.sid = sid;
    }
    public String getSupplier() {
        return supplier;
    }
    public void setSupplier(String supplier) {
        this.supplier = supplier;
    }
    public String getHw_version() {
        return hw_version;
    }
    public void setHw_version(String hw_version) {
        this.hw_version = hw_version;
    }
    public String getFw_version() {
        return fw_version;
    }
    public void setFw_version(String fw_version) {
        this.fw_version = fw_version;
    }
    public String getIp_address() {
        return ip_address;
    }
    public void setIp_address(String ip_address) {
        this.ip_address = ip_address;
    }
    public String getMaster() {
        return master;
    }
    public void setMaster(String master) {
        this.master = master;
    }
    public boolean isLocalEncrypt() {
        return isLocalEncrypt;
    }
    public void setLocalEncrypt(boolean localEncrypt) {
        isLocalEncrypt = localEncrypt;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/ListOidRequest.java
New file
@@ -0,0 +1,29 @@
package com.hdl.sdk.connect.bean.request;
import java.io.Serializable;
/**
 * Created by Tong on 2022/09/23.
 */
public class ListOidRequest implements Serializable {
    private String oid;
    private String mac;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getMac() {
        return mac;
    }
    public void setMac(String mac) {
        this.mac = mac;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/ListUploadRequest.java
New file
@@ -0,0 +1,127 @@
package com.hdl.sdk.connect.bean.request;
import java.io.Serializable;
import java.util.List;
/**
 * Created by panlili on 2023/1/31
 * description:
 */
public class ListUploadRequest {
    private String oid;//设备的Oid
    private String device_name;
    private String device_model;
    private String device_mac;//设备的Mac
    private String addresses;//驱动用的私有地址,如没有则空着就可以
    private String driver_code;//驱动用的id,如没有则空着就可以
    private String src;//来自哪个驱动,如Link设备没有则填"LINK"
    private String from;//来自哪个网关,如果时Link网络设备,则填自身oid;如果是驱动则不需要此字段
    private List<ImageInfo> image_info;
    public String getOid() {
        return oid;
    }
    public void setOid(String oid) {
        this.oid = oid;
    }
    public String getDevice_name() {
        return device_name;
    }
    public void setDevice_name(String device_name) {
        this.device_name = device_name;
    }
    public String getDevice_model() {
        return device_model;
    }
    public void setDevice_model(String device_model) {
        this.device_model = device_model;
    }
    public String getDevice_mac() {
        return device_mac;
    }
    public void setDevice_mac(String device_mac) {
        this.device_mac = device_mac;
    }
    public String getAddresses() {
        return addresses;
    }
    public void setAddresses(String addresses) {
        this.addresses = addresses;
    }
    public String getDriver_code() {
        return driver_code;
    }
    public void setDriver_code(String driver_code) {
        this.driver_code = driver_code;
    }
    public String getSrc() {
        return src;
    }
    public void setSrc(String src) {
        this.src = src;
    }
    public String getFrom() {
        return from;
    }
    public void setFrom(String from) {
        this.from = from;
    }
    public List<ImageInfo> getImage_info() {
        return image_info;
    }
    public void setImage_info(List<ImageInfo> image_info) {
        this.image_info = image_info;
    }
    public static class ImageInfo implements Serializable {
        //镜像号,用于升级匹配
        private String image_info;
        private String hw_version;
        private String fw_version;
        public String getImage_info() {
            return image_info;
        }
        public void setImage_info(String image_info) {
            this.image_info = image_info;
        }
        public String getHw_version() {
            return hw_version;
        }
        public void setHw_version(String hw_version) {
            this.hw_version = hw_version;
        }
        public String getFw_version() {
            return fw_version;
        }
        public void setFw_version(String fw_version) {
            this.fw_version = fw_version;
        }
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/AuthenticateResponse.java
@@ -11,21 +11,35 @@
    private String code;
    private GatewayObjects objects;
    private Auth auth;
    private String ip_address;
    public String getCode() { return code; }
    public void setCode(String value) { this.code = value; }
    public GatewayObjects getObjects() { return objects; }
    public void setObjects(GatewayObjects value) { this.objects = value; }
    public void setObjects(GatewayObjects value) {
        this.objects = value;
    }
    public Auth getAuth() { return auth; }
    public void setAuth(Auth value) { this.auth = value; }
    public String getIp_address() {
        return ip_address;
    }
    public void setIp_address(String ip_address) {
        this.ip_address = ip_address;
    }
    public class Auth implements Serializable {
        private String localSecret;
        public String getLocalSecret() { return localSecret; }
        public void setLocalSecret(String value) { this.localSecret = value; }
        public void setLocalSecret(String value) {
            this.localSecret = value;
        }
    }
    public class GatewayObjects implements Serializable  {
@@ -34,10 +48,14 @@
        private String oid;
        public String getIPAddress() { return ip_address; }
        public void setIPAddress(String value) { this.ip_address = value; }
        public void setIPAddress(String value) {
            this.ip_address = value;
        }
        public String getGatewayID() { return gatewayId; }
        public void setGatewayID(String value) { this.gatewayId = value; }
        public void setGatewayID(String value) {
            this.gatewayId = value;
        }
        public String getOID() { return oid; }
        public void setOID(String value) { this.oid = value; }
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/DeviceInfoResponse.java
@@ -24,6 +24,7 @@
        private String oid;
        private String homeId;
        private String mac;
        private String LocalSecret;
        public String getIPAddress() {
            return ip_address;
@@ -64,6 +65,14 @@
        public void setMac(String mac) {
            this.mac = mac;
        }
        public String getLocalSecret() {
            return LocalSecret;
        }
        public void setLocalSecret(String localSecret) {
            LocalSecret = localSecret;
        }
    }
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/NetworkAccessBroadcastResponse.java
@@ -18,5 +18,4 @@
    public String getHomeID() { return homeId; }
    public void setHomeID(String value) { this.homeId = value; }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/BaseCallBack.java
New file
@@ -0,0 +1,10 @@
package com.hdl.sdk.connect.cloud;
/**
 * Created by Tong on 2021/11/8.
 */
public interface BaseCallBack {
    void onError(HDLException e);
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/BaseInfo.java
New file
@@ -0,0 +1,48 @@
package com.hdl.sdk.connect.cloud;
import java.io.Serializable;
/**
 * @Author : Zoro.
 * @Date : 2019/6/9.
 * @Describe :
 */
public class BaseInfo<T> implements Serializable {
    private int code;
    private T data;
    private String message;
    public BaseInfo(int code, T data) {
        this.code = code;
        this.data = data;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public T getData() {
        return data;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public void setData(T data) {
        this.data = data;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/CallBackListener.java
New file
@@ -0,0 +1,8 @@
package com.hdl.sdk.connect.cloud;
/**
 * Created by panlili on 2022/5/17.
 */
public interface CallBackListener extends BaseCallBack {
    void onSuccess(String message);
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/CloudLinkCode.java
New file
@@ -0,0 +1,46 @@
package com.hdl.sdk.connect.cloud;
/**
 * Created by Tong on 2021/11/2.
 */
public @interface CloudLinkCode {
    //成功
    int SUCCEED = 0;
    //系统繁忙
    int SYSTEM_BUSY = 1;
    //系统维护 2
    //服务异常 3
    //签名错误 4
    //参数异常 5
    //token超时
    int TOKEN_TIMEOUT = 10001;
    //10002 重新登录
    int Re_Login = 10002;
    //token不合法
    int TOKEN_NOT_STANDARD = 10003;
    //缺少token参数
    int NO_TOKEN = 10004;
    //用户名或者密码错误 10008
    //用户已被禁用 10009
    //10010    用户不存在
    //10012    用户已存在,不能重复注册
    //10404    住宅唯一标识不存在
    //10506    网关不存在
    //10805    设备不存在
    //12005    应用不存在
    //20000    控制失败
    //20001    网关离线
    //20002    设备离线
    //20101    spk不支持该功能属性
    //20102    spk不支持该功能属性值
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/GsonUtils.java
New file
@@ -0,0 +1,247 @@
package com.hdl.sdk.connect.cloud;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
/**
 * Created by Tong on 2021/11/10.
 */
public class GsonUtils {
    private static Gson gson;
    public static <T> T copy(Object o, Class<T> type) {
        return copy(o, TypeToken.get(type));
    }
    public static <T> T copy(Object o, TypeToken<T> type) {
        return copy(o, type.getType());
    }
    public static <T> T copy(Object o, Type type) {
        try {
            Gson gson = getGson();
            return gson.fromJson(gson.toJson(o), type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static <T> T fromJson(String json, Type type) {
        try {
            Gson gson = getGson();
            return gson.fromJson(json, type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static <T> T fromJson(String json, Class<T> type) {
        try {
            Gson gson = getGson();
            return gson.fromJson(json, type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static <T> T fromJson(String json) {
        try {
            Gson gson = getGson();
            return gson.fromJson(json, new TypeToken<T>() {
            }.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static String toJson(Object object) {
        try {
            return getGson().toJson(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static Type getType(@NonNull final Type rawType, @NonNull final Type... typeArguments) {
        return TypeToken.getParameterized(rawType, typeArguments).getType();
    }
    public static Gson getGson() {
        if (gson == null) {
            gson = new GsonBuilder()
                    .disableHtmlEscaping()
                    .registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory())
                    .registerTypeAdapter(String.class, new StringAdapter())
                    .registerTypeAdapter(Integer.class, new IntegerDefaultAdapter())
                    .registerTypeAdapter(Double.class, new DoubleDefaultAdapter())
                    .registerTypeAdapter(Long.class, new LongDefaultAdapter())
                    .create();
        }
        return gson;
    }
    /**
     *
     * @param o
     * @param <T>
     * @return
     */
    public static <T> JsonArray toJsonArray(Object o) {
        try {
            return getGson().fromJson(GsonUtils.toJson(o), new TypeToken<JsonArray>() {
            }.getType());
        } catch (Exception e) {
            return null;
        }
    }
    private static class StringAdapter implements JsonSerializer<String>, JsonDeserializer<String> {
        @Override
        public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            if (json instanceof JsonPrimitive) {
                return json.getAsString();
            } else {
                return json.toString();
            }
        }
        @Override
        public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }
    private static class IntegerDefaultAdapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
        @Override
        public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            try {
                if (json.getAsString().equals("") || json.getAsString().equals("null")) {
                    return 0;
                }
            } catch (Exception ignore) {
            }
            try {
                return json.getAsInt();
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }
        @Override
        public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }
    private static class DoubleDefaultAdapter implements JsonSerializer<Double>, JsonDeserializer<Double> {
        @Override
        public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                if (json.getAsString().equals("") || json.getAsString().equals("null")) {
                    return 0.00;
                }
            } catch (Exception ignore) {
            }
            try {
                return json.getAsDouble();
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }
        @Override
        public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }
    private static class LongDefaultAdapter implements JsonSerializer<Long>, JsonDeserializer<Long> {
        @Override
        public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            try {
                if (json.getAsString().equals("") || json.getAsString().equals("null")) {
                    return 0L;
                }
            } catch (Exception ignore) {
            }
            try {
                return json.getAsLong();
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }
        @Override
        public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }
    private static class NullStringToEmptyAdapterFactory implements TypeAdapterFactory {
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            Class<T> rawType = (Class<T>) type.getRawType();
            if (rawType != String.class) {
                return null;
            }
            return (TypeAdapter<T>) new StringNullAdapter();
        }
    }
    public static class StringNullAdapter extends TypeAdapter<String> {
        @Override
        public String read(JsonReader reader) throws IOException {
            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull();
                return "";
            }
            return reader.nextString();
        }
        @Override
        public void write(JsonWriter writer, String value) throws IOException {
            if (value == null) {
                writer.nullValue();
                return;
            }
            writer.value(value);
        }
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HDLException.java
New file
@@ -0,0 +1,114 @@
package com.hdl.sdk.connect.cloud;
import android.text.TextUtils;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.hdl.hdlhttp.callback.HxException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Created by Tong on 2021/11/8.
 */
public class HDLException extends RuntimeException {
    private int code;
    private String msg;
    @Retention(RetentionPolicy.SOURCE)
    @Target({ElementType.FIELD, ElementType.PARAMETER})
    @IntDef({
            ErrorCode.UNKNOWN,
            ErrorCode.PARSE_ERROR,
            ErrorCode.NETWORK_ERROR,
            ErrorCode.HTTP_ERROR,
            ErrorCode.SSL_ERROR,
            ErrorCode.TIMEOUT_ERROR
    })
    public @interface ErrorCode {
        //未知错误
        int UNKNOWN = -40000;
        //解析错误
        int PARSE_ERROR = -40001;
        //网络错误
        int NETWORK_ERROR = -40002;
        //协议出错
        int HTTP_ERROR = -40003;
        //证书出错
        int SSL_ERROR = -40004;
        //连接超时
        int TIMEOUT_ERROR = -40005;
    }
    private int getHxToErrorCode(@HxException.ErrorCode int hxCode) {
        switch (hxCode) {
            case HxException.ErrorCode.UNKNOWN:
                return ErrorCode.UNKNOWN;
            case HxException.ErrorCode.PARSE_ERROR:
                return ErrorCode.PARSE_ERROR;
            case HxException.ErrorCode.NETWORK_ERROR:
                return ErrorCode.NETWORK_ERROR;
            case HxException.ErrorCode.HTTP_ERROR:
                return ErrorCode.HTTP_ERROR;
            case HxException.ErrorCode.SSL_ERROR:
                return ErrorCode.SSL_ERROR;
            case HxException.ErrorCode.TIMEOUT_ERROR:
                return ErrorCode.TIMEOUT_ERROR;
        }
        return ErrorCode.NETWORK_ERROR;
    }
    public HDLException(HxException exception) {
        this.code = getHxToErrorCode(exception.getCode());
        this.msg = exception.getMsg();
    }
    public HDLException(int code, String msg) {
        this.code = code;
        this.msg = msg;
        if (!TextUtils.isEmpty(msg)) {
            this.msg = msg;
        } else {
//            this.msg = HxHttpConfig.getInstance().getString(R.string.network_error);
            this.msg = "网络发生异常,请稍后再试";
        }
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    @Override
    public String toString() {
        return "HDLException{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                '}';
    }
    @Nullable
    @Override
    public String getMessage() {
        return msg;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HDLResponse.java
New file
@@ -0,0 +1,51 @@
package com.hdl.sdk.connect.cloud;
import com.hdl.hdlhttp.callback.HxException;
import com.hdl.hdlhttp.response.GsonSubscribe;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
 * Created by Tong on 2021/11/8.
 */
public abstract class HDLResponse<K> extends GsonSubscribe<BaseInfo<K>> {
    public abstract void onResponse(K response);
    public abstract void onFailure(HDLException e);
    @Override
    public void onNext(String s) {
        try {
            Type type = getClass().getGenericSuperclass();
            if (type instanceof ParameterizedType) {
                Type[] types = ((ParameterizedType) type).getActualTypeArguments();
                ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl(BaseInfo.class, types, BaseInfo.class);
                BaseInfo<K> data = GsonUtils.fromJson(s,parameterizedType);
                onSuccess(data);
            }
        } catch (Exception e) {
            e.printStackTrace();
            this.onError(HxException.handleException(e));
        }
    }
    @Override
    public final void onSuccess(BaseInfo<K> response) {
        if (response.getCode() == CloudLinkCode.SUCCEED) {
            onResponse(response.getData());
        } else {
            onFailure(new HDLException(response.getCode(), response.getMessage()));
        }
    }
    @Override
    public final void onError(HxException e) {
        onFailure(new HDLException(e));
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HdlCloudApi.java
New file
@@ -0,0 +1,18 @@
package com.hdl.sdk.connect.cloud;
/**
 * Created by panlili on 2023/1/30
 * description:
 */
public class HdlCloudApi {
    //正式环境
    public static final String BASE_CHINA_URL = "https://china-gateway.hdlcontrol.com";
    //测试环境
//    public static final String BASE_CHINA_URL = "https://test-gz.hdlcontrol.com";
    //申请设备密钥(根据设备MAC)
    public static final String APPLY_DEVICE_SECRET = "/smart-open/third/device/authByMac";
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/HdlCloudController.java
New file
@@ -0,0 +1,38 @@
package com.hdl.sdk.connect.cloud;
import com.hdl.hdlhttp.HxHttp;
import io.reactivex.rxjava3.disposables.Disposable;
/**
 * Created by panlili on 2023/1/30
 * description:
 */
public class HdlCloudController {
    public static Disposable applyDeviceSecret(String supplier, String mac, String spk, CallBackListener callBack) {
        return HxHttp.builder()
                .url(HdlCloudApi.BASE_CHINA_URL + HdlCloudApi.APPLY_DEVICE_SECRET)
                .params("supplier", supplier)
                .params("mac", mac)
                .params("spk", spk)
                .build()
                .post()
                .subscribeWith(new HDLResponse<String>() {
                    @Override
                    public void onResponse(String response) {
                        if (callBack != null) {
                            callBack.onSuccess(response);
                        }
                    }
                    @Override
                    public void onFailure(HDLException e) {
                        if (callBack != null) {
                            callBack.onError(e);
                        }
                    }
                });
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/MD5Utils.java
New file
@@ -0,0 +1,121 @@
package com.hdl.sdk.connect.cloud;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
 * Created by Tong on 2021/11/3.
 */
public final class MD5Utils {
    /**
     * MD5转字符串
     */
    public static String encodeMD5(String s) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(s.getBytes("UTF-8"));
            byte[] messageDigest = digest.digest();
            return toHexString(messageDigest);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }
    private static String toHexString(byte[] keyData) {
        if (keyData == null) {
            return null;
        }
        int expectedStringLen = keyData.length * 2;
        StringBuilder sb = new StringBuilder(expectedStringLen);
        for (byte keyDatum : keyData) {
            String hexStr = Integer.toString(keyDatum & 0x00FF, 16);
            if (hexStr.length() == 1) {
                hexStr = "0" + hexStr;
            }
            sb.append(hexStr);
        }
        return sb.toString();
    }
    /**
     * MD5转字符串
     * 额外值
     */
    public static String encodeMD52(String s) {
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] btInput = s.getBytes("utf-8");
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(btInput);
            byte[] md = digest.digest();
            int j = md.length;
            char[] str = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * MD5文件转字符串
     */
    public static String encodeMD5(File f) {
        if (!f.isFile()) {
            return null;
        }
        MessageDigest digest;
        byte[] buffer = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            FileInputStream in = new FileInputStream(f);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16);
    }
    public static String encrypt(String raw) {
        String md5Str = raw;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5"); // 创建一个MD5算法对象
            md.update(raw.getBytes()); // 给算法对象加载待加密的原始数据
            byte[] encryContext = md.digest(); // 调用digest方法完成哈希计算
            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < encryContext.length; offset++) {
                i = encryContext[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i)); // 把字节数组逐位转换为十六进制数
            }
            md5Str = buf.toString(); // 拼装加密字符串
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return md5Str.toUpperCase(); // 输出大写的加密串
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/ParameterizedTypeImpl.java
New file
@@ -0,0 +1,43 @@
package com.hdl.sdk.connect.cloud;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
 * Created by Tong on 2021/11/8.
 */
public class ParameterizedTypeImpl implements ParameterizedType, Serializable {
    private final Type[] actualTypeArguments;
    private final Type ownerType;
    private final Type rawType;
    /**
     * @param rawType             原始类型
     * @param actualTypeArguments 实际的泛型参数类型
     * @param ownerType           拥有者类型
     */
    public ParameterizedTypeImpl(Type rawType, Type[] actualTypeArguments, Type ownerType) {
        this.actualTypeArguments = actualTypeArguments;
        this.ownerType = ownerType;
        this.rawType = rawType;
    }
    @Override
    public Type[] getActualTypeArguments() {
        return actualTypeArguments;
    }
    @Override
    public Type getOwnerType() {
        return ownerType;
    }
    @Override
    public Type getRawType() {
        return rawType;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/interceptor/EncryptInterceptor.java
New file
@@ -0,0 +1,175 @@
package com.hdl.sdk.connect.cloud.interceptor;
import android.net.Uri;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.cloud.GsonUtils;
import com.hdl.sdk.connect.cloud.MD5Utils;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
/**
 * Created by Tong on 2021/11/4.
 * 加密并自动补充参数,appKey、timestamp
 * 只支持表单、json
 * 最终json方式提交
 */
public class EncryptInterceptor implements Interceptor {
    @NonNull
    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Request request = chain.request();
        Headers headers = request.headers();
        if (!isIgnoreSignHeader(headers)) {
            return chain.proceed(encrypt(request));
        }
        return chain.proceed(request);
    }
    /**
     * 添加sign字段
     */
    private Request encrypt(Request request) {
        final String timestamp = String.valueOf(System.currentTimeMillis());
        final String appKey = HDLLink.getInstance().getAppKey();
        final String appSecret = HDLLink.getInstance().getAppSecret();
        final JsonObject json = getBodyJson(request);
        if (json != null) {
            json.addProperty("appKey", appKey);
            json.addProperty("timestamp", timestamp);
            json.addProperty("sign", getSign(json, appSecret));
            final RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json;charset=UTF-8"));
            return request.newBuilder().post(requestBody)
                    .build();
        }
        return request;
    }
    /**
     * 需要按字母排序
     *
     * @param json 所有字段使用urlParameter拼接,除了appSecret
     */
    private String getSign(JsonObject json, String appSecret) {
        String builder = jsonToUrlParameter(json) +
                appSecret;
        return MD5Utils.encodeMD5(builder);
    }
    /**
     * 是否忽略自定义的加密头
     */
    private boolean isIgnoreSignHeader(Headers headers) {
        String signHeader = headers.get(SmartHeader.IGNORE_SIGN_HEADER);
        return !TextUtils.isEmpty(signHeader);
    }
    private JsonObject getBodyJson(Request request) {
        RequestBody body = request.body();
        if (body instanceof FormBody) {
            JsonObject object = new JsonObject();
            FormBody formBody = (FormBody) body;
            for (int i = 0; i < formBody.size(); i++) {
                object.addProperty(formBody.name(i), formBody.value(i));
            }
            return object;
        } else {
            //json格式
            try {
                String bodyString = getBodyString(request);
                if (!TextUtils.isEmpty(bodyString)) {
                    final JsonElement parseString = JsonParser.parseString(bodyString);
                    return parseString.getAsJsonObject();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    private String getBodyString(Request request) {
        try {
            RequestBody body = request.body();
            if (body != null) {
                Buffer buffer = new Buffer();
                body.writeTo(buffer);
                Charset charset = Charset.forName("UTF-8");
                MediaType contentType = body.contentType();
                charset = contentType.charset(charset);
                return buffer.readString(charset);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    private String jsonToUrlParameter(JsonObject object) {
        final Map<String, String> map = GsonUtils.getGson().fromJson(object, new TypeToken<Map<String, String>>() {
        }.getType());
        final Uri.Builder builder = new Uri.Builder();
        List<String> list = new ArrayList<>(map.keySet());
        Collections.sort(list);
        for (String key : list) {
            String value = map.get(key);
            if (valueNeedSign(value)) {
                builder.appendQueryParameter(key, value);
            }
        }
        return builder.build().getQuery();
    }
    /**
     * 判断当前值是否需要参与签名,保持跟云端一致
     * 空字符串不参与
     * 数组,集合不参与
     *
     * @return ture 需要加密
     */
    private static boolean valueNeedSign(String valueStr) {
        try {
            if (TextUtils.isEmpty(valueStr)) return false;
            final char[] strChar = URLDecoder.decode(valueStr, "utf-8")
                    .substring(0, 1).toCharArray();
            final char firstChar = strChar[0];
            return firstChar != '{' && firstChar != '[';
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/interceptor/SmartHeader.java
New file
@@ -0,0 +1,16 @@
package com.hdl.sdk.connect.cloud.interceptor;
/**
 * Created by Tong on 2021/11/8.
 * 拦截器标识
 */
public class SmartHeader {
    //默认携带加密、解密以及时间戳,使用"IGNORE_SIGN_HEADER"可以屏蔽
    public static final String IGNORE_SIGN_HEADER = "IgnoreSignHeader";
    //在刷新Token
    public static final String REFRESH_TOKEN_HEADER = "RefreshTokenHeader";
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/cloud/interceptor/SmartHeaderInterceptor.java
New file
@@ -0,0 +1,27 @@
package com.hdl.sdk.connect.cloud.interceptor;
import androidx.annotation.NonNull;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
/**
 * Created by Tong on 2021/11/9.
 * 删除自定义头
 */
public class SmartHeaderInterceptor implements Interceptor {
    @NonNull
    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Request request = chain.request().newBuilder()
                .removeHeader(SmartHeader.IGNORE_SIGN_HEADER)
                .removeHeader(SmartHeader.REFRESH_TOKEN_HEADER).build();
        return chain.proceed(request);
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/config/HDLLinkConfig.java
@@ -24,8 +24,11 @@
    private String gatewayId;
    private String ipAddress;
    private GatewaySearchBean currentGateway;//当前网关
    private String networkName;
    private AuthenticateRequest.AuthenticateDeviceInfoBean deviceInfoBean;//当前设备基本信息
    private AuthenticateRequest.RequestBean requestBean;//当前设备基本信息
    private AuthenticateRequest.AuthBean authBean;//当前设备认证信息
    /**
     * instance
@@ -105,9 +108,10 @@
     */
    public boolean checkIfCertified() {
        //localSecret不为空并且长度等于16 网关id不能为空
        return !TextUtils.isEmpty(localSecret)
                && localSecret.length() == 16
                && !TextUtils.isEmpty(gatewayId);
        return !TextUtils.isEmpty(gatewayId);
//        return !TextUtils.isEmpty(localSecret)
//                && localSecret.length() == 16
//                && !TextUtils.isEmpty(gatewayId);
    }
    public void setLocalSecret(String localSecret) {
@@ -131,6 +135,14 @@
    }
    public void setIpAddress(String ipAddress){
        this.ipAddress = ipAddress;
    }
    public String getNetworkName() {
        return networkName;
    }
    public void setNetworkName(String networkName) {
        this.networkName = networkName;
    }
    public GatewaySearchBean getCurrentGateway() {
@@ -181,4 +193,20 @@
    public void setDeviceInfoBean(AuthenticateRequest.AuthenticateDeviceInfoBean deviceInfoBean) {
        this.deviceInfoBean = deviceInfoBean;
    }
    public AuthenticateRequest.RequestBean getRequestBean() {
        return requestBean;
    }
    public void setRequestBean(AuthenticateRequest.RequestBean requestBean) {
        this.requestBean = requestBean;
    }
    public AuthenticateRequest.AuthBean getAuthBean() {
        return authBean;
    }
    public void setAuthBean(AuthenticateRequest.AuthBean authBean) {
        this.authBean = authBean;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java
@@ -2,18 +2,34 @@
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.google.gson.reflect.TypeToken;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.event.EventDispatcher;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.ByteUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.SPUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
import com.hdl.sdk.connect.bean.response.DeviceInfoResponse;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.connect.socket.HDLAuthSocket;
import com.hdl.sdk.connect.socket.HDLSocket;
import com.hdl.sdk.connect.utils.AesUtil;
import com.hdl.sdk.socket.codec.ByteToMessageDecoder;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import kotlin.ParameterName;
/**
 * Created by Tong on 2021/9/22.
@@ -112,6 +128,7 @@
    }
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected synchronized LinkResponse decoder(Object msg, String ipaddress) throws Exception {
        if (msg instanceof byte[]) {
@@ -176,6 +193,42 @@
                String bodyString = new String(body, "utf-8");
                response.setData(bodyString);
                LogUtils.i("接收到数据:" + response.getTopic() + "\r\n" + response.getData());
                String receivetopic = String.format(TopicConstant.LINK_BROADCAST, HDLLinkConfig.getInstance().getGatewayId());
                if (response.getTopic().equals("/user/all/custom/gateway/search")) {
                    HDLAuthSocket.getInstance().UploadGatewayInfo(new HDLLinkCallBack() {
                        @Override
                        public void onSuccess(String msg) {
                            LogUtils.i("UploadGatewayInfo onSucceed");
                        }
                        @Override
                        public void onError(HDLLinkException e) {
                            LogUtils.i("UploadGatewayInfo onError");
                        }
                    });
                } else if (response.getTopic().equals(receivetopic)) {
                    try {
                        DeviceInfoResponse deviceInfoResponse = GsonConvert.getGson().fromJson(response.getData(), new TypeToken<DeviceInfoResponse>() {
                        }.getType());
                        if (!TextUtils.isEmpty(deviceInfoResponse.getObjects().getLocalSecret())) {
                            byte[] baseBytes = Base64.getDecoder().decode(deviceInfoResponse.getObjects().getLocalSecret());
                            String mackey = "";
                            if (!TextUtils.isEmpty(SPUtils.getString("auth_mackey_key", ""))) {
                                mackey = SPUtils.getString("auth_mackey_key", "");
                                byte[] bodyBytes = AesUtil.aesDecrypt(baseBytes, mackey.substring(mackey.length() - 16));
                                String localSecret = new String(bodyBytes, "utf-8");
                                Log.d("panlili", "LinkMessageDecoder.java:----->localSecret= " + localSecret);
                                HDLLinkConfig.getInstance().setLocalSecret(localSecret);
                            }
                        }
                    } catch (Exception e) {
                        LogUtils.i("LinkMessageDecoder.java:getLocalSecret----->e= " + e.getMessage());
                    }
                }
                //非正常数据,返回
                if (!((bodyString.startsWith("{") && bodyString.endsWith("}"))
                        || (bodyString.startsWith("[") && bodyString.endsWith("]")))) {
@@ -185,67 +238,6 @@
                EventDispatcher.getInstance().post(response.getTopic(), response);
            }
            return null;
//            //解析流
//            byte[] data = (byte[]) msg;
//            bytes.addAll(ByteUtils.toByteList(data));
//
//            byte[] byteArray = ByteUtils.toByteArray(bytes);
//            int headIndex = ByteUtils.getByteIndexOf(byteArray, head);
//            if (headIndex > 0) {
//                //移动到head 开始位置
//                bytes.subList(0, headIndex).clear();
//                byteArray = ByteUtils.toByteArray(bytes);
//            }
//
//            int bodyIndex = ByteUtils.getByteIndexOf(byteArray, body);
//            if (bodyIndex < 0) {
//                //头部未获取完成
//                return null;
//            }
//            int bodyStartIndex = bodyIndex + body.length;
//
//            //解析头部
//            ProtocolParse parse = new ProtocolParse(byteArray);
//            response.setTopic(parse.getTopic());
//
//            int bodyLength = parse.getLength();
//            if (bodyLength > 0) {
//                if (byteArray.length >= bodyLength + bodyStartIndex) {
//                    byte[] body = ByteUtils.getRangeBytes(bytes, bodyStartIndex, bodyStartIndex + bodyLength);
//
//                    if (HDLLinkConfig.getInstance().ifNeedEncrypt(response.getTopic())) {
//                        //需要解密
//                        byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret());
////                        byte[] bodyBytes = AESUtils.decryptAES(body,AuthenticateConfig.getInstance().getLocalSecret());
//                        if (bodyBytes != null) {
//                            response.setData(new String(bodyBytes, "utf-8"));
////                            LogUtils.i("TAG", "解密 主题:"+response.getTopic()+ " body: "+response.getData());
//                        } else {
//                            //解密失败,返回原数据
//                            response.setData(new String(body, "utf-8"));
//                        }
//
//                    } else {
//                        response.setData(new String(body, "utf-8"));
//                    }
//
//                    if (byteArray.length >= bodyLength + bodyStartIndex) {
//                        //保存余留
//                        byte[] remaining = ByteUtils.getRangeBytes(bytes, bodyStartIndex + bodyLength, byteArray.length);
//                        bytes.clear();
//                        for (byte b : remaining) {
//                            bytes.add(b);
//                        }
//                    }
//                    //解析完成,topic发送一次
//                    EventDispatcher.getInstance().post(response.getTopic(), response);
//                    return response;
//                }
//            } else if (bodyLength == 0) {
//                //body为空
//                return response;
//            }
        }
        return null;
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLAuthSocket.java
@@ -1,33 +1,38 @@
package com.hdl.sdk.connect.socket;
import static com.hdl.sdk.common.config.TopicConstant.DEIVCE_AUTH_REQUEST;
import android.text.TextUtils;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.hdl.sdk.common.HDLSdk;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.event.EventDispatcher;
import com.hdl.sdk.common.event.EventListener;
import com.hdl.sdk.common.exception.HDLLinkCode;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.IpUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.bean.LinkRequest;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.request.GatewayInfoRequest;
import com.hdl.sdk.connect.bean.response.AuthenticateResponse;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.response.GatewaySearchBean;
import com.hdl.sdk.connect.bean.response.NetworkAccessBroadcastResponse;
import com.hdl.sdk.connect.callback.BaseCallBack;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.IpUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.response.GatewaySearchBean;
import com.hdl.sdk.connect.bean.LinkRequest;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.protocol.LinkMessageDecoder;
import com.hdl.sdk.connect.protocol.LinkMessageEncoder;
import com.hdl.sdk.socket.client.UdpClient;
@@ -35,12 +40,9 @@
import com.hdl.sdk.socket.udp.UdpSocketBoot;
import com.hdl.sdk.socket.udp.UdpSocketOptions;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static com.hdl.sdk.common.config.TopicConstant.DEIVCE_AUTH_REQUEST;
/**
 * Created by jlchen on 11/11/21.
@@ -68,7 +70,7 @@
    /**
     * instance
     */
    private  static final HDLAuthSocket instance=new HDLAuthSocket();
    private static final HDLAuthSocket instance = new HDLAuthSocket();
    private HDLAuthSocket() {
        initListenerGatewayEvent();
@@ -84,7 +86,7 @@
     *
     * @return HDLAuthSocket
     */
    public  static HDLAuthSocket getInstance() {
    public static HDLAuthSocket getInstance() {
//        if (instance == null) {
//            synchronized (HDLAuthSocket.class) {
//        if (instance == null) {
@@ -119,10 +121,14 @@
                LogUtils.i("初始化Socket udp");
            }
        } catch (Exception e) {
              LogUtils.e("初始化Socket udp异常"+e.getMessage());
            LogUtils.e("初始化Socket udp异常" + e.getMessage());
        }
        return udpSocketBoot;
    }
    public void init() {
        getUdpBoot();
    }
    /**
@@ -148,6 +154,7 @@
                    //移除监听
                    EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_AUTH_BROADCAST);
                    LogUtils.i("网关入网广播IP: " + bean.getIPAddress());
                    HDLLinkConfig.getInstance().setIpAddress(bean.getIPAddress());
                    String ipStr = bean.getIPAddress();
                    if (!TextUtils.isEmpty(ipStr)) {
                        sendAuthenticateRequest(ipStr, request, callBack);
@@ -164,6 +171,64 @@
    public void endAuthenticateRequest() {
        //移除监听
        EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_AUTH_BROADCAST);
    }
    /**
     * 上报从网关信息
     *
     * @param callBack 回调
     */
    public void UploadGatewayInfo(HDLLinkCallBack callBack) {
        String time = String.valueOf(System.currentTimeMillis());
        final BaseLocalResponse<GatewayInfoRequest> data = new BaseLocalResponse<>();
        data.setId(IdUtils.getUUId());
        data.setTime_stamp(time);
        final GatewayInfoRequest request = new GatewayInfoRequest();
        AuthenticateRequest.AuthenticateDeviceInfoBean authenticateDeviceInfoBean = HDLLinkConfig.getInstance().getDeviceInfoBean();
        request.setDevice_model(authenticateDeviceInfoBean.getDeviceModel());
        request.setDevice_mac(authenticateDeviceInfoBean.getDeviceMAC());
        request.setDevice_name(authenticateDeviceInfoBean.getDeviceName());
        request.setGateway_type(authenticateDeviceInfoBean.getGateway_type());
        request.setAccess_mode(authenticateDeviceInfoBean.getAccessMode());
        request.setOid(authenticateDeviceInfoBean.getOID());
        request.setSid(authenticateDeviceInfoBean.getSid());
        request.setSupplier(authenticateDeviceInfoBean.getSupplier());
        if (authenticateDeviceInfoBean.getSupplier() == null) {
            AuthenticateRequest.RequestBean requestBean = HDLLinkConfig.getInstance().getRequestBean();
            request.setSupplier(requestBean.getSupplier());
        }
        request.setHw_version(authenticateDeviceInfoBean.getHw_version());
        request.setFw_version(HDLSdk.getInstance().getVersion());//sdk版本
        request.setIp_address(authenticateDeviceInfoBean.getIPAddress());
        request.setMaster("false");
        request.setLocalEncrypt(false);
        data.setObjects(request);
        String topic = HDLLinkConfig.getInstance().getFullTopic(TopicConstant.GATEWAY_SEARCH_REPLY);
        LinkRequest message = new LinkRequest(topic,
                GsonConvert.getGson().toJson(data));
        String ip = IpUtils.getBroadcastAddress();
        HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() {
            @Override
            public void onSucceed(Object msg) {
                if (callBack == null) return;
                callBack.onSuccess("上报成功");
                LogUtils.i("UploadGatewayInfo onSucceed = " + msg);
            }
            @Override
            public void onFailure() {
                if (callBack == null) return;
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UPLOAD_GATEWAYINFO_FAILURE_ERROR));
                LogUtils.i("UploadGatewayInfo onFailure");
            }
        });
    }
    /**
@@ -200,25 +265,105 @@
                                gatewayId = bean.getObjects().getGatewayID();
                                ipAddress = bean.getObjects().getIPAddress();
                            }
                            if (ipAddress == null) {
                                ipAddress = bean.getIp_address();
                            }
                            HDLLinkConfig.getInstance().setAuthBean(request.getAuth());
                            //判断网关是否已经注册到云端
                            if (TextUtils.isEmpty(localSecret) || TextUtils.isEmpty(gatewayId)) {
                            Log.d("panlili", "HDLAuthSocket.java:onSucceed-----> " + localSecret);
                            if (TextUtils.isEmpty(localSecret) && TextUtils.isEmpty(gatewayId)) {
                                //认证失败,网关未注册到云端
                                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_ERROR_GATEWAY_NOT_REGISTERED));
                            } else {
                                HDLLinkConfig.getInstance().saveConfig(localSecret, gatewayId, ipAddress);
                                HDLLinkConfig.getInstance().setRequestBean(request.getAuth().getRequest());
                                callBack.onSuccess("认证成功");
//                                UploadDeviceAuth(request.getObjects().getDeviceMAC(), "0", "success", bean.getCode(), null);
                            }
                        } else if (bean.getCode().equals("14013")){
                        } else if (bean.getCode().equals("14013")) {
                            //认证失败,该MAC对应的设备密钥不存在
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_MAC_KEY_ERROR_));
                        } else{
//                            UploadDeviceAuth(request.getObjects().getDeviceMAC(), "-1", "fail", bean.getCode(), null);
                        } else if (bean.getCode().equals("124013")) {
                            //认证失败,该MAC对应的设备密钥不存在
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_124013_ERROR));
                        } else if (bean.getCode().equals("124015")) {
                            //认证失败,设备厂家不匹配
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_124015_ERROR));
                        } else {
                            //认证失败,错误码:
                            LogUtils.e("认证失败,错误码:" + bean.getCode());
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_ERROR));
//                            UploadDeviceAuth(request.getObjects().getDeviceMAC(), "-1", "fail", bean.getCode(), null);
                        }
                    } else {
                        callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_ERROR));
                    }
                } catch (Exception e) {
                    callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_ERROR));
                }
            }
            @Override
            public void onFailure() {
                LogUtils.i(TAG, "onFailure: ");
                if (callBack == null) return;
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_TIMEOUT_ERROR));
            }
        });
    }
    public void UploadDeviceAuth(String mac, String result, String message, String auth_code, HDLLinkCallBack callBack) {
        HDLSocket.getInstance().UploadDeviceAuth(mac, result, message, auth_code, new HDLLinkCallBack() {
            @Override
            public void onSuccess(String msg) {
                if (callBack != null) {
                    callBack.onSuccess(msg);
                }
                LogUtils.i(TAG, "onSuccess: " + msg);
            }
            @Override
            public void onError(HDLLinkException e) {
                if (callBack != null) {
                    callBack.onError(e);
                }
                LogUtils.i(TAG, "onError: " + e.getMsg() + " " + e.getCode());
            }
        });
    }
    public void linkBroadcast(String oid, HDLLinkCallBack callBack) {
        if (TextUtils.isEmpty(oid)) {
            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_NULL_ERROR));
        }
        Gson gs = new Gson();
        JsonArray jsonArray = new JsonArray();
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("oid", oid);
        jsonArray.add(jsonObject);
        String requestStr = gs.toJson(jsonArray);
        String topic = String.format(TopicConstant.LINK_BROADCAST, HDLLinkConfig.getInstance().getDeviceInfoBean().getOID());
        LinkRequest message = new LinkRequest(topic, requestStr);
        String ip = IpUtils.getBroadcastAddress();
        HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() {
            @Override
            public void onSucceed(Object msg) {
                if (callBack == null) return;
                try {
                    callBack.onSuccess("更新成功");
                    LogUtils.i(TAG, "onSucceed: msg= " + msg);
                } catch (Exception e) {
                    callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_ERROR));
                }
@@ -362,12 +507,12 @@
     * 通用发送指令
     * 1秒没响应就让他重新发送,重试3次
     *
     * @param topic    发送数据
     * @param bodyStr  回复的主题
     * @param topic     发送数据
     * @param bodyStr   回复的主题
     * @param broadcast 是否要广播
     * @param callBack 回调
     * @param callBack  回调
     */
    public void udpSendMsg(String topic, String bodyStr,boolean broadcast,  HDLLinkResponseCallBack callBack) {
    public void udpSendMsg(String topic, String bodyStr, boolean broadcast, HDLLinkResponseCallBack callBack) {
        if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_NULL_ERROR));
@@ -384,7 +529,7 @@
        LinkRequest message = new LinkRequest(topic, bodyStr);
        String ip = HDLLinkConfig.getInstance().getIpAddress();
        if(broadcast) {
        if (broadcast) {
            ip = IpUtils.getBroadcastAddress();
        }
        HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() {
@@ -406,13 +551,13 @@
    /**
     * 通用发送指令 只发一次,不监听回复,不重发
     *
     * @param topic   发送数据
     * @param bodyStr 回复的主题
     * @param topic     发送数据
     * @param bodyStr   回复的主题
     * @param broadcast 是否广播
     */
    public void udpSendMsg(String topic, String bodyStr,boolean broadcast) {
    public void udpSendMsg(String topic, String bodyStr, boolean broadcast) {
        if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) {
            LogUtils.e( "参数不能为空,不能发送UDP数据");
            LogUtils.e("参数不能为空,不能发送UDP数据");
            return;
        }
        if (!HDLLinkConfig.getInstance().checkIfCertified()) {
@@ -421,7 +566,7 @@
        }
        LinkRequest message = new LinkRequest(topic, bodyStr);
        String ip = HDLLinkConfig.getInstance().getIpAddress();
        if(broadcast) {
        if (broadcast) {
            ip = IpUtils.getBroadcastAddress();
        }
        HdlSocketHelper.sendUdpOne(getUdpBoot(), ip, UDP_PORT, message);
@@ -495,9 +640,10 @@
                            final BaseLocalResponse<GatewaySearchBean> response = GsonConvert.getGson().fromJson(data, new TypeToken<BaseLocalResponse<GatewaySearchBean>>() {
                            }.getType());
                            GatewaySearchBean searchBean = response.getObjects();
                            if (searchBean != null && !TextUtils.isEmpty(searchBean.getGatewayId())) {
                                searchBean.setIp_address(linkResponse.getSource_ipAddress());
                                if (searchBean.getGatewayId().contains(searchGatewayId)&&!TextUtils.isEmpty(searchGatewayId)) {
                                if (searchBean.getGatewayId().contains(searchGatewayId) && !TextUtils.isEmpty(searchGatewayId)) {
                                    removeSearchGatewayEvent();//移除搜索网关监听
                                    isSearchGatewaySuccess.set(true);//搜索成功标记
                                    searchGatewayCount.set(11);//次数标记
@@ -510,7 +656,7 @@
                        }
                    }
                } catch (Exception e) {
                    LogUtils.i("panlili:" + e.toString());
                }
            }
        };
@@ -536,8 +682,9 @@
                                //主网关并且是当前绑定的网关
                                if ("true".equals(gateway.getMaster().toLowerCase()) && gateway.getGatewayId().equals(HDLLinkConfig.getInstance().getGatewayId())) {
                                    HDLLinkConfig.getInstance().setCurrentGateway(gateway);//设置当前网关
                                    if(!TextUtils.isEmpty( gateway.getIp_address())) {
                                    if (!TextUtils.isEmpty(gateway.getIp_address())) {
                                        HDLLinkConfig.getInstance().setIpAddress(gateway.getIp_address());
                                        LogUtils.i("接收到网关信息:" + HDLLinkConfig.getInstance().getIpAddress());
                                    }
                                    //更新当前网关的信息
                                    HDLLinkConfig.getInstance().reSaveConfig();
@@ -546,7 +693,7 @@
                        }
                    }
                } catch (Exception e) {
                    LogUtils.i("panlili:" + e.toString());
                }
            }
        };
@@ -595,7 +742,8 @@
                        LogUtils.e("搜索网关", "搜索10次,指定网关都没回复,回调超时");
                        //搜索10次,指定网关都没回复,回调超时
                        callBackSearchGatewayTimeout();
                    }catch (Exception e){}
                    } catch (Exception e) {
                    }
                }
            }
        }).start();
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java
@@ -1,10 +1,14 @@
package com.hdl.sdk.connect.socket;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.hdl.sdk.common.HDLSdk;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.event.EventDispatcher;
import com.hdl.sdk.common.event.EventListener;
@@ -17,7 +21,12 @@
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.LoginRequest;
import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
import com.hdl.sdk.connect.bean.request.BroadcastRequest;
import com.hdl.sdk.connect.bean.request.DeviceAuthRequest;
import com.hdl.sdk.connect.bean.request.GatewayInfoRequest;
import com.hdl.sdk.connect.bean.request.ListOidRequest;
import com.hdl.sdk.connect.bean.request.ListUploadRequest;
import com.hdl.sdk.connect.bean.response.AuthenticateResponse;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
@@ -31,6 +40,7 @@
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.connect.protocol.LinkMessageDecoder;
import com.hdl.sdk.connect.protocol.LinkMessageEncoder;
import com.hdl.sdk.connect.utils.AesUtil;
import com.hdl.sdk.socket.SocketBoot;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.client.IHeartbeat;
@@ -40,6 +50,7 @@
import com.hdl.sdk.socket.listener.SendListener;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -95,7 +106,7 @@
                        Thread.sleep(1000);
//                        LogUtils.i("checkIfCertified=" + HDLLink.getInstance().checkIfCertified() + " getTcp().connected=" + getTcp().connected);
                        try {
                            if (!HDLLink.getInstance().checkIfCertified() || getTcp().connected) {
                            if (!HDLLink.getInstance().checkIfCertified() || (!TextUtils.isEmpty(getTcpIp()) && getTcp().connected)) {
                                continue;
                            }
                        } catch (Exception e) {
@@ -109,24 +120,28 @@
                        }
                        BroadcastRequest request = new BroadcastRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), "200");
                        HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true, new HDLLinkResponseCallBack() {
                            @RequiresApi(api = Build.VERSION_CODES.O)
                            @Override
                            public void onSuccess(LinkResponse msg) {
                                getTcp();
                                String data = msg.getData();
                                if (!TextUtils.isEmpty(data)) {
                                    DeviceInfoResponse response = GsonConvert.getGson().fromJson(data, new TypeToken<DeviceInfoResponse>() {
                                    }.getType());
                                    HDLLinkConfig.getInstance().setIpAddress(response.getObjects().getIPAddress());
                                    LogUtils.i("---getIpAddress=" + HDLLinkConfig.getInstance().getIpAddress());
                                    HDLLinkConfig.getInstance().reSaveConfig();
                                }
                                isBroadcast = true;
                                getTcp();
                                LogUtils.i("广播信息给主网关成功!");
                            }
                            @Override
                            public void onError(HDLLinkException e) {
                                isBroadcast = false;
                                LogUtils.i("广播信息给主网关失败!");
                                LogUtils.i("广播信息给主网关失败!---onError=" + e.toString());
                            }
                        });
//                        HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true);
@@ -470,6 +485,10 @@
                    jsonObject.addProperty("id", IdUtils.getUUId());
                    jsonObject.addProperty("time_stamp", time);
                    if (HDLLinkConfig.getInstance().getRequestBean() != null) {
                        jsonObject.addProperty("mac", HDLLinkConfig.getInstance().getRequestBean().getMAC());
                    }
                    String topic = String.format(TopicConstant.HEARTBEAT, HDLLinkConfig.getInstance().getDeviceInfoBean().getOID());
                    LinkRequest message = new LinkRequest(topic,
@@ -574,6 +593,114 @@
    }
    /**
     * 上报oid列表
     *
     * @param request  设备信息
     * @param callBack 回调
     */
    public void UploadOidList(ListUploadRequest request, HDLLinkCallBack callBack) {
        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
            String time = String.valueOf(System.currentTimeMillis());
            final BaseLocalResponse<List<ListUploadRequest>> data = new BaseLocalResponse<>();
            data.setId(IdUtils.getUUId());
            data.setTime_stamp(time);
            List<ListUploadRequest> list = new ArrayList<>();
            list.add(request);
            data.setObjects(list);
            String topic = String.format(TopicConstant.LIST_UPLOAD, getGatewayId());
            LinkRequest message = new LinkRequest(topic,
                    GsonConvert.getGson().toJson(data));
            String replyTopic = topic + "_reply";
            try {
                sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() {
                    @Override
                    public void onSucceed() {
                    }
                    @Override
                    public void onError() {
                        if (callBack != null) {
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
                        }
                    }
                });
            } catch (Exception e) {
                if (callBack != null) {
                    callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
                }
            }
        } else {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
            }
        }
    }
    /**
     * 上报入网认证结果
     *
     * @param mac       mac
     * @param result    结果0/-1
     * @param message   认证信息
     * @param auth_code 云端认证code
     * @param callBack  结果回调
     */
    public void UploadDeviceAuth(String mac, String result, String message, String auth_code, HDLLinkCallBack callBack) {
        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
            String time = String.valueOf(System.currentTimeMillis());
            final BaseLocalResponse<List<DeviceAuthRequest>> data = new BaseLocalResponse<>();
            data.setId(IdUtils.getUUId());
            data.setTime_stamp(time);
            DeviceAuthRequest deviceAuthRequest = new DeviceAuthRequest();
            deviceAuthRequest.setMac(mac);
            deviceAuthRequest.setResult(result);
            deviceAuthRequest.setMessage(message);
            deviceAuthRequest.setAuth_code(auth_code);
            List<DeviceAuthRequest> list = new ArrayList<>();
            list.add(deviceAuthRequest);
            data.setObjects(list);
            String topic = String.format(TopicConstant.DEIVCE_AUTH_RESULT_NOTIFY, getGatewayId());
            LinkRequest linkRequest = new LinkRequest(topic,
                    GsonConvert.getGson().toJson(data));
            String replyTopic = topic + "_reply";
            try {
                sendMsg(linkRequest.getSendBytes(), replyTopic, callBack, new SendListener() {
                    @Override
                    public void onSucceed() {
                    }
                    @Override
                    public void onError() {
                        if (callBack != null) {
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
                        }
                    }
                });
            } catch (Exception e) {
                if (callBack != null) {
                    callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
                }
            }
        } else {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
            }
        }
    }
    /**
     * tcp登录方便获取状态
     *
     * @param clientType 客户端类型
@@ -607,6 +734,70 @@
                @Override
                public void onSucceed() {
                    LogUtils.i("tcpLogin onSucceed");
                }
                @Override
                public void onError() {
                    if (callBack != null) {
                        callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
                    }
                }
            });
        } catch (Exception e) {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
            }
        }
    }
    /**
     * 通知删除并退网子设备
     *
     * @param oid      从网关(设备)oid
     * @param isForce  是否强制退网
     * @param callBack 结果回调
     */
    public void deleteNetwork(String oid, boolean isForce, HDLLinkCallBack callBack) {
        if (TextUtils.isEmpty(oid)) {
            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_NULL_ERROR));
        }
        final String msgId = IdUtils.getUUId();
        String time = String.valueOf(System.currentTimeMillis());
        final BaseLocalResponse<List<ListOidRequest>> data = new BaseLocalResponse<>();
        data.setId(msgId);
        data.setTime_stamp(time);
        final ListOidRequest request = new ListOidRequest();
        request.setOid(oid);
        List<ListOidRequest> list = new ArrayList<>();
        list.add(request);
        data.setObjects(list);
        String topic = String.format(TopicConstant.DELETE_REQUEST, HDLLinkConfig.getInstance().getGatewayId());
        LinkRequest message = new LinkRequest(topic,
                GsonConvert.getGson().toJson(data));
        String replyTopic = topic + "_reply";
        if (isForce) {//强制退网,不等网关回复直接清除数据
            HDLLinkConfig.getInstance().clearConfig();
        }
        try {
            sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() {
                @Override
                public void onSucceed() {
                    if (callBack == null) return;
                    try {
                        callBack.onSuccess("退网成功");
                        HDLLinkConfig.getInstance().clearConfig();
                    } catch (Exception e) {
                        callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_ERROR));
                    }
                }
                @Override
@@ -672,7 +863,7 @@
    public void tcpSendMsg(String topic, String bodyStr) {
        try {
            if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) {
                LogUtils.e("udpSendMsg", "参数不能为空");
                LogUtils.e("tcpSendMsg", "参数不能为空");
                return;
            }
            LinkRequest message = new LinkRequest(topic, bodyStr);
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/UdpClient.java
@@ -150,7 +150,7 @@
        }
        try {
            LogUtils.i("接收到Udp数据包,网络地址:" + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
//            LogUtils.i("接收到Udp数据包,网络地址:" + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
            IHandleMessage handleMessage = getOptions().getHandleMessage();
            if (handleMessage != null) {
HDLSDK_DEMO.rar
Binary files differ
HDLSDK_DEMO/.idea/gradle.xml
@@ -7,6 +7,7 @@
        <option name="testRunner" value="GRADLE" />
        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="gradleJvm" value="1.8" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
HDLSDK_DEMO/.idea/misc.xml
@@ -3,6 +3,7 @@
  <component name="DesignSurface">
    <option name="filePathToZoomLevelMap">
      <map>
        <entry key="..\:/HDL/ProjectCode/HDLSDK/HDLSDK_A_Android/HDLSDK_DEMO/app/src/main/res/layout/activity_main.xml" value="0.3538301198540907" />
        <entry key="..\:/job/me/Android/HDLSDK/app/src/main/res/layout/activity_main.xml" value="0.1" />
        <entry key="..\:/job/me/Android/HDLSDK/app/src/main/res/layout/demo_item.xml" value="0.28958333333333336" />
      </map>
HDLSDK_DEMO/app/build.gradle
@@ -38,7 +38,7 @@
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
    implementation 'com.google.code.gson:gson:2.8.8'
//    implementation 'com.google.code.gson:gson:2.8.8'
//    implementation project(path: ':hdl-connect')
    implementation files('libs\\com.hdl.sdk-v1.0.20.aar')
    implementation files('libs\\com.hdl.sdk-v1.1.0.aar')
}
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.0.20.aar
Binary files differ
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.1.0.aar
Binary files differ
HDLSDK_DEMO/app/src/main/AndroidManifest.xml
@@ -29,6 +29,7 @@
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
HDLSDK_DEMO/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -1,5 +1,15 @@
package com.hdl.hdlsdk;
import android.Manifest;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
@@ -8,43 +18,28 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.hdl.hdlsdk.device.DevicesListActivity;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.event.EventListener;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.IpUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.LinkRequest;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
import com.hdl.sdk.connect.bean.request.PropertyReadRequest;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.request.ListUploadRequest;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.response.GatewaySearchBean;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack;
import com.hdl.sdk.connect.cloud.CallBackListener;
import com.hdl.sdk.connect.cloud.HDLException;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.connect.socket.HDLAuthSocket;
import com.hdl.sdk.connect.socket.HDLSocket;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.protocol.LinkMessageDecoder;
import com.hdl.sdk.connect.protocol.LinkMessageEncoder;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.codec.MessagePipeLine;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -53,8 +48,6 @@
import java.util.List;
import java.util.Map;
import static com.hdl.sdk.common.config.TopicConstant.GATEWAY_SEARCH_REPLY;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
@@ -62,9 +55,11 @@
    private RecyclerView rv;
    private TextView tv;
    private TextView responseTv;
    private EditText editText;
    boolean isOn;
    private EventListener allTopicsListener;
    private String testLightSid = "0001010D48C71B02020100010101";
    private String secret = "";
    @Override
    protected void onDestroy() {
@@ -72,22 +67,64 @@
        removeAllTopicsListener();
    }
    void initDeviceInfo()
    {
    void initDeviceInfo() {
        AuthenticateRequest.AuthenticateDeviceInfoBean infoBean = new AuthenticateRequest.AuthenticateDeviceInfoBean();
        infoBean.setDeviceMAC("AA00000000000100");
        infoBean.setIPMAC("AA00000000000100");
        infoBean.setDeviceMAC("f2c5d8bad48f");
        infoBean.setIPMAC("f2c5d8bad48f");
        infoBean.setDeviceName("音乐播放器");//设备名字
        infoBean.setDeviceModel("MCLog.431");//设备型号
        infoBean.setAccessMode("WIFI");
        infoBean.setIPGateway("192.168.1.1");
        infoBean.setIPAddress("192.168.1.116");
        infoBean.setGateway_type("music.standard");
        infoBean.setIPAddress("192.168.1.103");
        infoBean.setGateway_type("screen.touch");
        infoBean.setHw_version("HW2.0");
        infoBean.setFw_version("Fw1.0");
        infoBean.setOID("010105000000FE11");//每个设备oid都要不一样
        infoBean.setSid("110105000000FE08110100000011");//每个设备的sid都要不一样
        infoBean.setSupplier("JINMAOYUN");
        HDLLinkConfig.getInstance().setDeviceInfoBean(infoBean);
    }
    void applyDeviceSecret() {
        tv.setText("开始申请设备密钥...");
        responseTv.setText("");
//        //正式服务器
        String appKey = "i8hR07jzrIS";//appkey
        String appSecret = "BmnJ8RWTtaVEBk24zPPF4UMwfYu0lAWU";//appsecret
        //测试服务器
//        String appKey ="FcRyUJlLJFF";
//        String appSecret = "wz8wn75ABidx8vXcFGUotqhwFkTaYvvJ";
//        String appKey = "L2OZliZRxHc";
//        String appSecret = "aCIWSvJDOukXfx3kivsKW11x9xdR3IbV";
        String supplier = "JINMAOYUN";//厂商
//        String mac = "AA00000000000100";//设备唯一MAC地址
        String mac = editText.getText().toString();
        String spk = "screen.touch";//产品spk
        if (TextUtils.isEmpty(mac)) {
            Toast.makeText(this, "mac不能为空!", Toast.LENGTH_SHORT).show();
            return;
        }
        HDLLink.getInstance().applyDeviceSecret(this, appKey, appSecret, supplier, mac, spk, new CallBackListener() {
            @Override
            public void onError(HDLException e) {
                tv.setText("申请失败");
                responseTv.setText(e.getMsg());
                secret = "";
            }
            @Override
            public void onSuccess(String msg) {
                tv.setText("申请成功");
                responseTv.setText(msg.toString());
                secret = msg.toString();
            }
        });
    }
    /**
@@ -95,29 +132,34 @@
     */
    void sendAuthenticateRequest() {
        tv.setText("开始入网认证...");
        responseTv.setText("");
        //认证提交参数准备
//
//        //测试服务
//        String spkStr = "ir.module";//产品spk
//        //测试服务器
//        String spkStr = "music.standard";//产品spk
//        String macStr = "AA000000000000AF";//设备唯一MAC地址
//        String secret = "44b360eb74b7ba64";//通过spk和mac提交云端认证后分配的secret
//        正式服务器
        String spkStr = "screen.mirror";//产品spk
        String macStr = "AA00000000000100";//设备唯一MAC地址
        String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret
        String spkStr = "screen.touch";//产品spk
//        String macStr = "AA00000000000100";//设备唯一MAC地址
        String macStr = editText.getText().toString();//设备唯一MAC地址
//        String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret
        String mac_key = stringToMD5(stringToMD5(macStr + secret));
        String versionString = "HDL_V1.0.1";//
        String time = String.valueOf(System.currentTimeMillis());
        HDLLinkConfig.getInstance().getDeviceInfoBean().setDeviceMAC(macStr);
//        HDLLinkConfig.getInstance().setCurrentGateway(infoBean);
        //1.设置认证信息
        AuthenticateRequest.RequestBean requestBean = new AuthenticateRequest.RequestBean();
        requestBean.setMAC(macStr);
        requestBean.setSupplier("WISE");
        requestBean.setSupplier("JINMAOYUN");
        requestBean.setFirmwareVersion(versionString);
        requestBean.setHardwareModel("1956F");
//        HDLLinkConfig.getInstance().setRequestBean(requestBean);
        AuthenticateRequest.AuthBean authbean = new AuthenticateRequest.AuthBean();
        authbean.setSpk(spkStr);
        authbean.setMACKey(mac_key);
@@ -127,9 +169,9 @@
        HDLLink.getInstance().startAuthenticateRequest(request, new HDLLinkCallBack() {
            @Override
            public void onError(HDLLinkException e) {
                tv.setText("认证失败");
                tv.setText("认证失败" + e.getCode());
                responseTv.setText(e.getMsg());
                Log.i("TAG", "onError: 认证失败");
                Log.e(TAG, "onError: 认证失败 " + e.getCode());
            }
            @Override
@@ -140,16 +182,36 @@
        });
    }
    public void UploadDeviceAuth(String mac, String result, String message, String auth_code) {
        //将认证结果上报给网关
        HDLLink.getInstance().UploadDeviceAuth(mac, result, message, auth_code, new HDLLinkCallBack() {
            @Override
            public void onSuccess(String s) {
                tv.setText("上报结果成功");
                responseTv.setText(s.toString());
            }
            @Override
            public void onError(HDLLinkException e) {
                tv.setText("上报结果失败");
                responseTv.setText(e.getMsg());
                Log.i(TAG, "onError: 上报结果失败");
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        responseTv = findViewById(R.id.response_tv);
        editText = findViewById(R.id.edittext);
        tv = findViewById(R.id.state_tv);
        rv = findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        selectnetwork();
        checkIfCertified();
        initDeviceInfo();//初始化
        registerAllTopicsListener();
@@ -163,9 +225,11 @@
        launcher.launch(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE});
        final List<DemoBean> beans = new ArrayList<>();
        final List<DemoBean> beans = new ArrayList<DemoBean>();
        beans.add(new DemoBean("申请设备密钥"));
        beans.add(new DemoBean("入网认证"));
        beans.add(new DemoBean("搜索指定网关是否在线"));
        beans.add(new DemoBean("上报oid列表"));
        beans.add(new DemoBean("获取功能列表"));
        beans.add(new DemoBean("功能属性读取"));
        beans.add(new DemoBean("设备控制"));
@@ -177,6 +241,7 @@
        beans.add(new DemoBean("TCP发送"));
        beans.add(new DemoBean("UDP发送,监听主题回复,带重发带回调"));
        beans.add(new DemoBean("TCP发送,监听主题回复,带重发带回调"));
        beans.add(new DemoBean("退网"));
        demoAdapter = new DemoAdapter(beans);
        rv.setAdapter(demoAdapter);
@@ -192,56 +257,68 @@
            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                switch (position) {
                    case 0:
                        //申请设备密钥
                        applyDeviceSecret();
                        break;
                    case 1:
                        //入网认证
                        sendAuthenticateRequest();
                        break;
                    case 1:
                    case 2:
                        //搜索网关
                        searchGatewayBroadcast();
                        break;
                    case 2:
                    case 3:
                        //上报oid列表
                        UploadOidList();
                        break;
                    case 4:
                        //获取功能列表
                        getFunctionList();
                        break;
                    case 3:
                    case 5:
                        //功能属性读取
                        getFunctionAttribute();
                        break;
                    case 4:
                    case 6:
                        //设备控制
                        controlDecide();
                        break;
                    case 5:
                    case 7:
                        //读取状态
                        propertyRead();
                        break;
                    case 6:
                    case 8:
                        //获取场景列表
                        getSceneList();
                        break;
                    case 7:
                        //获取场景列表
                    case 9:
                        //场景控制
                        controlScene();
                        break;
                    case 8:
                    case 10:
                        //功能列表
                        startDevicesListActivity();
                        break;
                    case 9:
                    case 11:
                        //UDP发送
                        udpSend();
                        break;
                    case 10:
                    case 12:
                        //TCP发送
                        tcpSend();
                        break;
                    case 11:
                    case 13:
                        //UDP发送,监听主题回复,带重发带回调
                        udpSendWithCallback();
                        break;
                    case 12:
                    case 14:
                        //TCP发送,监听主题回复,带重发带回调
                        tcpSendWithCallback();
                        break;
                    case 15:
                        //退网
                        deleteNetwork();
                        break;
                }
            }
@@ -251,6 +328,10 @@
    public void showToast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }
    void selectnetwork() {
        HDLLink.getInstance().selectNetwork("wlan0");
    }
    /**
@@ -320,7 +401,6 @@
    }
    String stringToMD5(String text) {
        byte[] hash;
        try {
@@ -349,6 +429,7 @@
     */
    void searchGatewayBroadcast() {
        tv.setText("搜索网关中...");
        responseTv.setText("");
        HDLLink.getInstance().searchGatewayBroadcast(new HDLAuthSocket.SearchGatewayCallBack() {
            @Override
            public void onError(HDLLinkException e) {
@@ -391,6 +472,7 @@
     */
    void getFunctionAttribute() {
        tv.setText("功能属性读取");
        responseTv.setText("");
        List<String> sids = new ArrayList<>();
        sids.add(testLightSid);
        HDLLink.getInstance().getFunctionAttribute(sids, new HDLLinkCallBack() {
@@ -412,6 +494,7 @@
     */
    void propertyRead() {
        tv.setText("读取状态中...");
        responseTv.setText("");
        List<String> list = new ArrayList<>();
        list.add(testLightSid);//要读取设备的sid
        HDLLink.getInstance().propertyRead(list, new HDLLinkCallBack() {
@@ -435,6 +518,7 @@
     */
    void controlDecide() {
        tv.setText("控制设备");
        responseTv.setText("");
        isOn = !isOn;
        List<DeviceControlRequest> requestList = new ArrayList<>();
        DeviceControlRequest request = new DeviceControlRequest();
@@ -464,6 +548,7 @@
     */
    void getSceneList() {
        tv.setText("读取场景列表");
        responseTv.setText("");
        HDLLink.getInstance().getSceneList(new HDLLinkCallBack() {
            @Override
            public void onSuccess(String msg) {
@@ -486,6 +571,7 @@
     */
    void controlScene() {
        tv.setText("场景控制");
        responseTv.setText("");
        //控制场景sid列表,支持批量控制
        List<String> sids = new ArrayList<>();
        isOn = !isOn;
@@ -518,6 +604,7 @@
     */
    private void tcpSend() {
        tv.setText("TCP发送 只发一次,不监听回复,不重发");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr);
@@ -528,6 +615,7 @@
     */
    private void udpSend() {
        tv.setText("UDP发送 只发一次,不监听回复,不重发");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr);
@@ -560,6 +648,7 @@
     */
    private void udpSendWithCallback() {
        tv.setText("UDP发送,监听主题回复,带重发带回调");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr, new HDLLinkResponseCallBack() {
@@ -581,6 +670,7 @@
     */
    private void tcpSendWithCallback() {
        tv.setText("TCP发送,监听主题回复,带重发带回调");
        responseTv.setText("");
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr, new HDLLinkCallBack() {
@@ -596,4 +686,54 @@
            }
        });
    }
    private void deleteNetwork() {
        tv.setText("退网");
        responseTv.setText("");
        String oid = HDLLinkConfig.getInstance().getDeviceInfoBean().getOID();
        HDLLink.getInstance().deleteNetwork(oid, false, new HDLLinkCallBack() {
            @Override
            public void onSuccess(String msg) {
                responseTv.setText(msg);
                //退网成功,删除数据
            }
            @Override
            public void onError(HDLLinkException e) {
                responseTv.setText(e.getMsg());
            }
        });
    }
    /**
     * 上报oid列表
     */
    private void UploadOidList() {
        tv.setText("上报oid列表...");
        responseTv.setText("");
        //1.设置设备信息
        AuthenticateRequest.AuthenticateDeviceInfoBean authenticateDeviceInfoBean = HDLLinkConfig.getInstance().getDeviceInfoBean();
        ListUploadRequest request = new ListUploadRequest();
        request.setOid(authenticateDeviceInfoBean.getOID());
        request.setDevice_name(authenticateDeviceInfoBean.getDeviceName());
        request.setDevice_model(authenticateDeviceInfoBean.getDeviceModel());
        request.setDevice_mac(authenticateDeviceInfoBean.getDeviceMAC());
        request.setSrc("LINK");//来自哪个驱动,如Link设备没有则填"LINK"
        request.setFrom(authenticateDeviceInfoBean.getOID());//来自哪个网关,如果时Link网络设备,则填自身oid;如果是驱动则不需要此字段
        HDLLink.getInstance().UploadOidList(request, new HDLLinkCallBack() {
            @Override
            public void onError(HDLLinkException error) {
                tv.setText(error.getMsg());
            }
            @Override
            public void onSuccess(String data) {
                tv.setText("上报oid列表成功");
                responseTv.setText(data);
            }
        });
    }
}
HDLSDK_DEMO/app/src/main/res/layout/activity_main.xml
@@ -40,10 +40,20 @@
            android:layout_height="match_parent"
            android:orientation="vertical">
            <EditText
                android:id="@+id/edittext"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingStart="10dp"
                android:hint="请输入mac"
                android:text="f2c5d8bad48f"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingStart="10dp"
                android:layout_marginTop="@dimen/dp_10"
                android:text="当前状态:" />
            <TextView
HDLSDK_DEMO/config.gradle
@@ -1,5 +1,5 @@
ext {
    minSdkVersion = 16
    minSdkVersion = 21
    targetSdkVersion = 31
    compileSdkVersion = 31
    versionName = "1.0.0"