29个文件已添加
19个文件已修改
1 文件已重命名
| | |
| | | android:exported="false" |
| | | android:windowSoftInputMode="adjustPan|stateHidden" /> |
| | | |
| | | <activity |
| | | android:name=".SourceBindActivity" |
| | | android:exported="false" |
| | | android:windowSoftInputMode="adjustPan|stateHidden" /> |
| | | |
| | | </application> |
| | | |
| | | </manifest> |
| | |
| | | package com.hdl.hdlsdk; |
| | | |
| | | import android.app.Application; |
| | | import android.util.Log; |
| | | |
| | | import com.hdl.sdk.common.HDLSdk; |
| | | import com.hdl.sdk.common.event.EventListener; |
| | | import com.hdl.sdk.common.utils.LogUtils; |
| | | import com.hdl.sdk.connect.HDLLink; |
| | | import com.hdl.sdk.connect.bean.LinkResponse; |
| | | import com.hdl.sdk.connect.cloud.broadcast.GlobalBroadcastManager; |
| | | import com.hdl.sdk.sourceos.OsManager; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/10/8. |
| | |
| | | public class App extends Application { |
| | | |
| | | private String deviceStatusUpdateTopic; |
| | | |
| | | @Override |
| | | public void onCreate() { |
| | | super.onCreate(); |
| | |
| | | //控制SDK日志打印 |
| | | HDLSdk.getInstance().setLogEnabled(true); |
| | | |
| | | //source系统接口初始化 |
| | | OsManager.init(this); |
| | | |
| | | //appkey:ryfElI3tVOT |
| | | //appsecret:AKIn7s1A2YnNvAZRtL8FQxzp0R2KUpIY |
| | | HDLLink.getInstance().initCloud(this, "ryfElI3tVOT", "AKIn7s1A2YnNvAZRtL8FQxzp0R2KUpIY"); |
| | | |
| | | //注册全局广播,刷新token |
| | | GlobalBroadcastManager.registerGlobalBroadcast(this); |
| | | } |
| | | |
| | | @Override |
| | |
| | | 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.SPUtils; |
| | | 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.request.ListSidRequest; |
| | | import com.hdl.sdk.connect.bean.request.ListUploadRequest; |
| | | import com.hdl.sdk.connect.bean.response.BaseLocalResponse; |
| | | import com.hdl.sdk.connect.bean.response.BindInfoBean; |
| | | import com.hdl.sdk.connect.bean.response.GatewaySearchBean; |
| | | import com.hdl.sdk.connect.bean.response.UpdateInfo; |
| | | import com.hdl.sdk.connect.callback.HDLLinkCallBack; |
| | |
| | | import com.hdl.sdk.connect.cloud.CallBackListener; |
| | | import com.hdl.sdk.connect.cloud.CheckAppVersionListener; |
| | | import com.hdl.sdk.connect.cloud.HDLException; |
| | | import com.hdl.sdk.connect.cloud.bean.GatewayInfo; |
| | | import com.hdl.sdk.connect.cloud.listener.GatewayListener; |
| | | import com.hdl.sdk.connect.cloud.listener.SibichiListener; |
| | | import com.hdl.sdk.connect.cloud.bean.AiLoginInfo; |
| | | import com.hdl.sdk.connect.config.HDLLinkConfig; |
| | | import com.hdl.sdk.connect.socket.HDLAuthSocket; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.security.MessageDigest; |
| | |
| | | private List<SceneBean> sceneList = new ArrayList<>(); |
| | | private List<SceneDetailBean> sceneDetailList = new ArrayList<>(); |
| | | private List<SceneDetailBean> roomSceneList = new ArrayList<>(); |
| | | private GatewayInfo gatewayInfo; |
| | | |
| | | 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(); |
| | |
| | | Toast.makeText(this, "mac不能为空!", Toast.LENGTH_SHORT).show(); |
| | | return; |
| | | } |
| | | |
| | | HDLLink.getInstance().applyDeviceSecret(this, appKey, appSecret, supplier, mac, spk, new CallBackListener() { |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().applyDeviceSecret(supplier, mac, spk, new CallBackListener() { |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("申请失败"); |
| | |
| | | tv.setText("开始检测更新..."); |
| | | responseTv.setText(""); |
| | | |
| | | // //正式服务器 |
| | | String appKey = "i8hR07jzrIS";//appkey |
| | | String appSecret = "BmnJ8RWTtaVEBk24zPPF4UMwfYu0lAWU";//appsecret |
| | | |
| | | String appCode = "1697150870315999233";//appCode |
| | | |
| | | HDLLink.getInstance().checkAppVersion(this, appKey, appSecret, getAppVersionName(this), appCode, new CheckAppVersionListener() { |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().checkAppVersion(getAppVersionName(this), appCode, new CheckAppVersionListener() { |
| | | @Override |
| | | public void onSuccess(UpdateInfo info) { |
| | | tv.setText("有新更新"); |
| | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("检测更新失败"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | void getSibichiToken() { |
| | | tv.setText("获取思必驰token..."); |
| | | responseTv.setText(""); |
| | | |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | String clientId = "4ED634B5A7AD97A770A52AC00FF43805";//思必驰clientId |
| | | |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().getSibichiToken(bindInfoBean.getHomeId(), clientId, new SibichiListener() { |
| | | @Override |
| | | public void onSuccess(AiLoginInfo info) { |
| | | tv.setText("思必驰token"); |
| | | responseTv.setText(info.toString()); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("获取思必驰token失败"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | void syncMainGateway() { |
| | | tv.setText("获取主网关信息..."); |
| | | responseTv.setText(""); |
| | | |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | if (bindInfoBean == null) { |
| | | Toast.makeText(this, "请先扫码绑定住宅!", Toast.LENGTH_SHORT).show(); |
| | | return; |
| | | } |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().syncMainGateway(bindInfoBean.getHomeId(), new GatewayListener() { |
| | | @Override |
| | | public void onSuccess(GatewayInfo info) { |
| | | tv.setText("获取主网关信息"); |
| | | responseTv.setText(info.toString()); |
| | | if (info != null) { |
| | | HDLLinkConfig.getInstance().setGatewayId(info.getGatewayId()); |
| | | //HDLLinkConfig.getInstance().setIpAddress(info.ip); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("获取主网关信息失败"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | |
| | | |
| | | selectnetwork(); |
| | | checkIfCertified(); |
| | | initDeviceInfo();//初始化 |
| | | //initDeviceInfo();//不走从机入网的方式不需要初始化 |
| | | registerAllTopicsListener(); |
| | | HDLLink.getInstance().setDeleteNetworkListener(new DeleteNetworkListener() { |
| | | @Override |
| | |
| | | beans.add(new DemoBean("获取房间场景列表")); |
| | | beans.add(new DemoBean("获取自动化列表")); |
| | | beans.add(new DemoBean("⾃动化启⽤禁⽤")); |
| | | beans.add(new DemoBean("生成二维码绑定住宅")); |
| | | beans.add(new DemoBean("获取思必驰token")); |
| | | beans.add(new DemoBean("获取网关信息")); |
| | | demoAdapter = new DemoAdapter(beans); |
| | | rv.setAdapter(demoAdapter); |
| | | |
| | |
| | | case 19: |
| | | //⾃动化启⽤禁⽤ |
| | | editEnableLogic(); |
| | | break; |
| | | case 20: |
| | | //生成二维码绑定住宅 |
| | | startSourceBindActivity(); |
| | | break; |
| | | case 21: |
| | | //获取思必驰token |
| | | getSibichiToken(); |
| | | break; |
| | | case 22: |
| | | //获取网关信息 |
| | | syncMainGateway(); |
| | | break; |
| | | } |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | void initLink() { |
| | | //step1:先生成二维码,用onpro扫码绑定住宅获取住宅信息 |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | if (bindInfoBean != null) { |
| | | HDLLinkConfig.getInstance().setHomeId(bindInfoBean.getHomeId()); |
| | | HDLLinkConfig.getInstance().setLocalSecret(bindInfoBean.getLocalSecret()); |
| | | |
| | | } |
| | | //step2:再获取网关信息 |
| | | if (gatewayInfo != null) { |
| | | HDLLinkConfig.getInstance().setGatewayId(gatewayInfo.getGatewayId());//当前主网关id |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 入网认证 |
| | | */ |
| | |
| | | tv.setText("开始入网认证..."); |
| | | //认证提交参数准备 |
| | | |
| | | // 测试服务 |
| | | // String spkStr = "ir.module";//产品spk |
| | | // String macStr = "AA000000000000AF";//设备唯一MAC地址 |
| | | // String secret = "44b360eb74b7ba64";//通过spk和mac提交云端认证后分配的secret |
| | | |
| | | // 正式服务器 |
| | | //正式服务器 |
| | | String spkStr = "screen.mirror";//产品spk |
| | | String macStr = "f2c5d8bad48f";//设备唯一MAC地址 |
| | | // String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret |
| | | |
| | | String mac_key = stringToMD5(stringToMD5(macStr + secret)); |
| | | String versionString = "HDL_V1.0.1";// |
| | |
| | | tv.setText("设备功能属性读取"); |
| | | responseTv.setText(""); |
| | | List<String> sids = new ArrayList<>(); |
| | | sids.add(testLightSid); |
| | | if (devicesList.size() != 0) { |
| | | sids.add(devicesList.get(0).getSid()); |
| | | } else { |
| | | sids.add(testLightSid); |
| | | } |
| | | |
| | | HDLLink.getInstance().getFunctionAttribute(sids, new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String msg) { |
| | |
| | | tv.setText("读取状态中..."); |
| | | responseTv.setText(""); |
| | | List<String> list = new ArrayList<>(); |
| | | list.add(testLightSid);//要读取设备的sid |
| | | if (devicesList.size() != 0) { |
| | | list.add(devicesList.get(0).getSid()); |
| | | } else { |
| | | list.add(testLightSid);//要读取设备的sid |
| | | } |
| | | HDLLink.getInstance().propertyRead(list, new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String data) { |
| | |
| | | isOn = !isOn; |
| | | List<DeviceControlRequest> requestList = new ArrayList<>(); |
| | | DeviceControlRequest request = new DeviceControlRequest(); |
| | | request.setSid(testLightSid); |
| | | if (devicesList.size() != 0) { |
| | | request.setSid(devicesList.get(0).getSid()); |
| | | } else { |
| | | request.setSid(testLightSid);//要读取设备的sid |
| | | } |
| | | List<DeviceControlRequest.StatusBean> statusBeanList = new ArrayList<>(); |
| | | DeviceControlRequest.StatusBean bean = new DeviceControlRequest.StatusBean(); |
| | | bean.setKey("on_off"); |
| | |
| | | startActivity(intent); |
| | | } |
| | | |
| | | void startSourceBindActivity() { |
| | | Intent intent = new Intent(this, SourceBindActivity.class); |
| | | startActivity(intent); |
| | | } |
| | | |
| | | /** |
| | | * TCP发送 只发一次,不监听回复,不重发 |
| | | */ |
New file |
| | |
| | | package com.hdl.hdlsdk; |
| | | |
| | | import android.annotation.SuppressLint; |
| | | import android.os.Bundle; |
| | | import android.widget.TextView; |
| | | import android.widget.Toast; |
| | | |
| | | import androidx.appcompat.app.AppCompatActivity; |
| | | |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.connect.bean.response.BindInfoBean; |
| | | import com.hdl.sdk.connect.config.HDLLinkConfig; |
| | | import com.hdl.sdk.sourceos.bind.BaseEvent; |
| | | import com.hdl.sdk.sourceos.bind.BindAuthEvent; |
| | | import com.hdl.sdk.sourceos.bind.BindHomeService; |
| | | import com.hdl.sdk.sourceos.bind.EventType; |
| | | import com.hdl.sdk.sourceos.qrcode.QRCode; |
| | | import com.hdl.sdk.sourceos.qrcode.QrCodeView; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | import org.greenrobot.eventbus.EventBus; |
| | | import org.greenrobot.eventbus.Subscribe; |
| | | import org.greenrobot.eventbus.ThreadMode; |
| | | |
| | | public class SourceBindActivity extends AppCompatActivity { |
| | | |
| | | private static final String TAG = "SourceBindActivity"; |
| | | private QrCodeView qrcodeView; |
| | | private TextView responseTv; |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | setContentView(R.layout.activity_source_bind); |
| | | registerEventBus(); |
| | | initView(); |
| | | } |
| | | |
| | | @SuppressLint("WrongConstant") |
| | | private void initView() { |
| | | qrcodeView = findViewById(R.id.qrcode_view); |
| | | responseTv = findViewById(R.id.response_tv); |
| | | createBindQRCodeInfo(); |
| | | } |
| | | |
| | | private void createBindQRCodeInfo() { |
| | | final String time = String.valueOf(System.currentTimeMillis()); |
| | | String info = QRCode.createBindQRCodeInfo(time); |
| | | qrcodeView.setContent(info); |
| | | |
| | | //开始轮询 |
| | | BindHomeService.getInstance().startQuery(time); |
| | | } |
| | | |
| | | /** |
| | | * 绑定成功通知事件 |
| | | * |
| | | * @param event |
| | | */ |
| | | @Subscribe(threadMode = ThreadMode.MAIN) |
| | | public void onEventMessage(BaseEvent event) { |
| | | switch (event.getEventType()) { |
| | | case EventType.ON_PLUS_BINDING_TYPE: |
| | | if (event instanceof BindAuthEvent) { |
| | | int action = ((BindAuthEvent) event).getAction(); |
| | | if (action == BindAuthEvent.ON_PLUS_BINDING_SUCCEED_ACTION) { |
| | | //on+绑定成功 |
| | | Toast.makeText(this, "绑定成功", Toast.LENGTH_SHORT).show(); |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | responseTv.setText(bindInfoBean.toString()); |
| | | |
| | | if (bindInfoBean != null) { |
| | | HDLLinkConfig.getInstance().setHomeId(bindInfoBean.getHomeId()); |
| | | HDLLinkConfig.getInstance().setLocalSecret(bindInfoBean.getLocalSecret()); |
| | | } |
| | | } else if (action == BindAuthEvent.ON_PLUS_BINDING_TIMEOUT_ACTION) { |
| | | //on+绑定超时 |
| | | Toast.makeText(this, "绑定超时", Toast.LENGTH_SHORT).show(); |
| | | } else if (action == BindAuthEvent.ON_PLUS_BINDING_ERROR_ACTION) { |
| | | //网络错误 |
| | | //Toast.makeText(this, "网络异常", Toast.LENGTH_SHORT).show(); |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | | protected void unregisterEventBus() { |
| | | if (EventBus.getDefault().isRegistered(this)) { |
| | | EventBus.getDefault().unregister(this); |
| | | } |
| | | } |
| | | |
| | | protected void registerEventBus() { |
| | | if (!EventBus.getDefault().isRegistered(this)) { |
| | | EventBus.getDefault().register(this); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | super.onDestroy(); |
| | | unregisterEventBus(); |
| | | BindHomeService.getInstance().stopQuery(); |
| | | } |
| | | } |
| | |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| | | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REBOOT, Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST); |
| | | } |
| | | //系统接口初始化 |
| | | OsManager.init(SourceTestActivity.this); |
| | | |
| | | OsManager.addEventListener(eventListener); |
| | | |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | xmlns:app="http://schemas.android.com/apk/res-auto" |
| | | xmlns:tools="http://schemas.android.com/tools" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:orientation="vertical" |
| | | tools:context=".SourceBindActivity"> |
| | | |
| | | <com.hdl.sdk.sourceos.qrcode.QrCodeView |
| | | android:id="@+id/qrcode_view" |
| | | android:layout_width="125dp" |
| | | android:layout_height="125dp" |
| | | android:layout_alignParentBottom="true" |
| | | android:layout_centerHorizontal="true" |
| | | android:layout_marginStart="28dp" |
| | | android:layout_marginTop="28dp" |
| | | android:padding="3dp" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/response_tv" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:padding="3dp" |
| | | android:layout_marginTop="28dp" /> |
| | | |
| | | </LinearLayout> |
| | |
| | | defaultConfig { |
| | | minSdkVersion rootProject.minSdkVersion |
| | | targetSdkVersion rootProject.targetSdkVersion |
| | | versionCode 8 |
| | | versionName "1.2.0" |
| | | versionCode 9 |
| | | versionName "1.2.1" |
| | | |
| | | consumerProguardFiles "consumer-rules.pro" |
| | | } |
| | |
| | | api files('libs/hdlSDK_V1.0.7.jar') |
| | | |
| | | api 'com.google.code.gson:gson:2.8.8' |
| | | //二维码 |
| | | api 'com.google.zxing:core:3.4.1' |
| | | //事件总线 |
| | | api 'org.greenrobot:eventbus:3.2.0' |
| | | } |
| | |
| | | import com.hdl.sdk.connect.cloud.CheckAppVersionListener; |
| | | 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.cloud.listener.GatewayListener; |
| | | import com.hdl.sdk.connect.cloud.listener.SibichiListener; |
| | | import com.hdl.sdk.connect.config.HDLCloudConfig; |
| | | import com.hdl.sdk.connect.config.HDLLinkConfig; |
| | | import com.hdl.sdk.connect.socket.HDLAuthSocket; |
| | | import com.hdl.sdk.connect.socket.HDLSocket; |
| | |
| | | * @param spk 设备spk |
| | | * @param callBack 结果回调 |
| | | */ |
| | | public void applyDeviceSecret(Context context, String appKey, String appSecret, String supplier, String mac, String spk, CallBackListener callBack) { |
| | | public void applyDeviceSecret(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 appKey appKey |
| | | * @param appSecret appSecret |
| | | * @param versionCode 当前版本 |
| | | * @param appCode appCode |
| | | * @param listener 结果回调 |
| | | */ |
| | | public void checkAppVersion(Context context, String appKey, String appSecret, String versionCode, String appCode, CheckAppVersionListener listener) { |
| | | public void checkAppVersion(String versionCode, String appCode, CheckAppVersionListener listener) { |
| | | LogUtils.i("检测更新"); |
| | | HxHttpConfig.getInstance().init(context, HdlCloudApi.BASE_CHINA_URL) |
| | | .addInterceptor( |
| | | new EncryptInterceptor(), |
| | | new SmartHeaderInterceptor()); |
| | | this.appKey = appKey; |
| | | this.appSecret = appSecret; |
| | | HdlCloudController.checkAppVersion(versionCode, appCode, listener); |
| | | } |
| | | |
| | | /** |
| | | * 初始化云端 |
| | | */ |
| | | public void initCloud(Context context, String appKey, String appSecret) { |
| | | |
| | | HDLCloudConfig.getInstance().init(context, appKey, appSecret, HdlCloudApi.BASE_CHINA_URL); |
| | | |
| | | HxHttpConfig.getInstance().ignoreSSL(); |
| | | |
| | | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); |
| | | httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.BODY); |
| | | HxHttpConfig.getInstance().addInterceptor(httpLoggingInterceptor); |
| | | |
| | | HxHttpConfig.getInstance() |
| | | //.addInterceptor(new HttpCacheInterceptor()) |
| | | .addInterceptor(httpLoggingInterceptor).ignoreSSL(); |
| | | } |
| | | |
| | | HdlCloudController.checkAppVersion(versionCode, appCode, listener); |
| | | /** |
| | | * 获取思必驰token |
| | | * |
| | | * @param homeId homeId |
| | | * @param clientId clientId |
| | | * @param listener 结果回调 |
| | | */ |
| | | public void getSibichiToken(String homeId, String clientId, SibichiListener listener) { |
| | | LogUtils.i("获取思必驰token"); |
| | | HdlCloudController.getSibichiToken(homeId, clientId, listener); |
| | | } |
| | | |
| | | /** |
| | | * 获取主网关信息 |
| | | * |
| | | * @param homeId homeId |
| | | * @param listener 结果回调 |
| | | */ |
| | | public void syncMainGateway(String homeId, GatewayListener listener) { |
| | | LogUtils.i("获取主网关信息"); |
| | | HdlCloudController.syncMainGateway(homeId, listener); |
| | | } |
| | | |
| | | /** |
New file |
| | |
| | | package com.hdl.sdk.connect.bean.response; |
| | | |
| | | import android.text.TextUtils; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/14. |
| | | * on+扫码绑定 |
| | | */ |
| | | public class BindInfoBean implements Serializable { |
| | | |
| | | private String homeId; |
| | | private String homeName; |
| | | private String token; |
| | | private String expiresIn; |
| | | private Long expiration; |
| | | private String refreshToken; |
| | | private String refreshExpiresIn; |
| | | private Long refreshExpiration; |
| | | //社区编号 |
| | | private String communityCode; |
| | | private String communityId; |
| | | |
| | | private String houseCode; |
| | | |
| | | private String groupName; |
| | | //期/区 号 |
| | | private String groupNum; |
| | | |
| | | private String buildName; |
| | | //楼栋号 |
| | | private String buildNum; |
| | | //楼层号 |
| | | private String floorNum; |
| | | private String floorName; |
| | | |
| | | private String houseNo; |
| | | //单元名称 |
| | | private String unitName; |
| | | //单元号 |
| | | private String unitNum; |
| | | private String localSecret; |
| | | //小区维度 本地密钥 |
| | | private String communityLocalSecret; |
| | | //设备分机号 |
| | | private String deviceNumber; |
| | | |
| | | //项目类型 |
| | | private String projectType; |
| | | |
| | | private String userId; |
| | | |
| | | //空间编号 用于跟门口机通讯,不包含分机号 |
| | | public String getHomeId() { |
| | | return homeId; |
| | | } |
| | | |
| | | public void setHomeId(String homeId) { |
| | | this.homeId = homeId; |
| | | |
| | | } |
| | | |
| | | public String getHomeName() { |
| | | return homeName; |
| | | } |
| | | |
| | | public void setHomeName(String homeName) { |
| | | this.homeName = homeName; |
| | | } |
| | | |
| | | public String getToken() { |
| | | return token; |
| | | } |
| | | |
| | | public void setToken(String token) { |
| | | this.token = token; |
| | | } |
| | | |
| | | public String getExpiresIn() { |
| | | return expiresIn; |
| | | } |
| | | |
| | | public void setExpiresIn(String expiresIn) { |
| | | this.expiresIn = expiresIn; |
| | | } |
| | | |
| | | public Long getExpiration() { |
| | | return expiration; |
| | | } |
| | | |
| | | public void setExpiration(Long expiration) { |
| | | this.expiration = expiration; |
| | | } |
| | | |
| | | public String getRefreshToken() { |
| | | return refreshToken; |
| | | } |
| | | |
| | | public void setRefreshToken(String refreshToken) { |
| | | this.refreshToken = refreshToken; |
| | | } |
| | | |
| | | public String getRefreshExpiresIn() { |
| | | return refreshExpiresIn; |
| | | } |
| | | |
| | | public void setRefreshExpiresIn(String refreshExpiresIn) { |
| | | this.refreshExpiresIn = refreshExpiresIn; |
| | | } |
| | | |
| | | public Long getRefreshExpiration() { |
| | | return refreshExpiration; |
| | | } |
| | | |
| | | public void setRefreshExpiration(Long refreshExpiration) { |
| | | this.refreshExpiration = refreshExpiration; |
| | | } |
| | | |
| | | public String getCommunityCode() { |
| | | return communityCode; |
| | | } |
| | | |
| | | public void setCommunityCode(String communityCode) { |
| | | this.communityCode = communityCode; |
| | | } |
| | | |
| | | public String getCommunityId() { |
| | | return communityId; |
| | | } |
| | | |
| | | public void setCommunityId(String communityId) { |
| | | this.communityId = communityId; |
| | | } |
| | | |
| | | |
| | | public String getHouseCode() { |
| | | return houseCode; |
| | | } |
| | | |
| | | public void setHouseCode(String houseCode) { |
| | | this.houseCode = houseCode; |
| | | } |
| | | |
| | | public String getGroupName() { |
| | | return groupName; |
| | | } |
| | | |
| | | public void setGroupName(String groupName) { |
| | | this.groupName = groupName; |
| | | } |
| | | |
| | | public String getGroupNum() { |
| | | return groupNum; |
| | | } |
| | | |
| | | public void setGroupNum(String groupNum) { |
| | | this.groupNum = groupNum; |
| | | } |
| | | |
| | | public String getBuildName() { |
| | | return buildName; |
| | | } |
| | | |
| | | public void setBuildName(String buildName) { |
| | | this.buildName = buildName; |
| | | } |
| | | |
| | | public String getBuildNum() { |
| | | return buildNum; |
| | | } |
| | | |
| | | public void setBuildNum(String buildNum) { |
| | | this.buildNum = buildNum; |
| | | } |
| | | |
| | | public String getHouseNo() { |
| | | return houseNo; |
| | | } |
| | | |
| | | public void setHouseNo(String houseNo) { |
| | | this.houseNo = houseNo; |
| | | } |
| | | |
| | | public String getUnitName() { |
| | | return unitName; |
| | | } |
| | | |
| | | public void setUnitName(String unitName) { |
| | | this.unitName = unitName; |
| | | } |
| | | |
| | | public String getUnitNum() { |
| | | return unitNum; |
| | | } |
| | | |
| | | public void setUnitNum(String unitNum) { |
| | | this.unitNum = unitNum; |
| | | } |
| | | |
| | | public String getLocalSecret() { |
| | | return localSecret; |
| | | } |
| | | |
| | | public void setLocalSecret(String localSecret) { |
| | | this.localSecret = localSecret; |
| | | } |
| | | |
| | | public String getCommunityLocalSecret() { |
| | | return communityLocalSecret; |
| | | } |
| | | |
| | | public void setCommunityLocalSecret(String communityLocalSecret) { |
| | | this.communityLocalSecret = communityLocalSecret; |
| | | } |
| | | |
| | | public String getDeviceNumber() { |
| | | return deviceNumber; |
| | | } |
| | | |
| | | public void setDeviceNumber(String deviceNumber) { |
| | | this.deviceNumber = deviceNumber; |
| | | } |
| | | |
| | | public String getUserId() { |
| | | return userId; |
| | | } |
| | | |
| | | public void setUserId(String userId) { |
| | | this.userId = userId; |
| | | } |
| | | |
| | | public String getFloorNum() { |
| | | return floorNum; |
| | | } |
| | | |
| | | public void setFloorNum(String floorNum) { |
| | | this.floorNum = floorNum; |
| | | } |
| | | |
| | | public String getFloorName() { |
| | | return floorName; |
| | | } |
| | | |
| | | public void setFloorName(String floorName) { |
| | | this.floorName = floorName; |
| | | } |
| | | |
| | | |
| | | public String getProjectType() { |
| | | return projectType; |
| | | } |
| | | |
| | | public void setProjectType(String projectType) { |
| | | this.projectType = projectType; |
| | | } |
| | | |
| | | /** |
| | | * @return 空间编号,没有分机号 |
| | | */ |
| | | public String getSpaceCode() { |
| | | return generateSpaceCode(); |
| | | } |
| | | |
| | | /** |
| | | * 生成空间编号 |
| | | */ |
| | | public String generateSpaceCode() { |
| | | StringBuilder builder = new StringBuilder(); |
| | | //期/区 号 |
| | | if (!TextUtils.isEmpty(groupNum)) { |
| | | builder.append("-").append(groupNum); |
| | | } |
| | | //楼栋号 |
| | | if (!TextUtils.isEmpty(buildNum)) { |
| | | builder.append("-").append(buildNum); |
| | | } |
| | | //单元号 |
| | | if (!TextUtils.isEmpty(unitNum)) { |
| | | builder.append("-").append(unitNum); |
| | | } |
| | | //楼层号 |
| | | if (!TextUtils.isEmpty(floorNum)) { |
| | | builder.append("-").append(floorNum); |
| | | } |
| | | //门牌号 |
| | | if (!TextUtils.isEmpty(houseNo)) { |
| | | builder.append("-").append(houseNo); |
| | | } |
| | | |
| | | /*//分机号 肯定得有 |
| | | if (TextUtils.isEmpty(deviceNumber)) { |
| | | //空的话,用唯一码吧 |
| | | Log.i("info", "分机号为空:用唯一码"); |
| | | deviceNumber = DeviceUtils.getUniqueCode(); |
| | | } |
| | | builder.append("~").append(deviceNumber);*/ |
| | | |
| | | |
| | | String code = builder.toString(); |
| | | int index = code.indexOf("-"); |
| | | if (index != -1) { |
| | | code = code.substring(index + 1); |
| | | } |
| | | return code; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "BindInfoBean{" + |
| | | "homeId='" + homeId + '\'' + |
| | | ", homeName='" + homeName + '\'' + |
| | | ", token='" + token + '\'' + |
| | | ", expiresIn='" + expiresIn + '\'' + |
| | | ", expiration=" + expiration + |
| | | ", refreshToken='" + refreshToken + '\'' + |
| | | ", refreshExpiresIn='" + refreshExpiresIn + '\'' + |
| | | ", refreshExpiration=" + refreshExpiration + |
| | | ", communityCode='" + communityCode + '\'' + |
| | | ", communityId='" + communityId + '\'' + |
| | | ", houseCode='" + houseCode + '\'' + |
| | | ", groupName='" + groupName + '\'' + |
| | | ", groupNum='" + groupNum + '\'' + |
| | | ", buildName='" + buildName + '\'' + |
| | | ", buildNum='" + buildNum + '\'' + |
| | | ", floorNum='" + floorNum + '\'' + |
| | | ", floorName='" + floorName + '\'' + |
| | | ", houseNo='" + houseNo + '\'' + |
| | | ", unitName='" + unitName + '\'' + |
| | | ", unitNum='" + unitNum + '\'' + |
| | | ", localSecret='" + localSecret + '\'' + |
| | | ", communityLocalSecret='" + communityLocalSecret + '\'' + |
| | | ", deviceNumber='" + deviceNumber + '\'' + |
| | | ", projectType='" + projectType + '\'' + |
| | | ", userId='" + userId + '\'' + |
| | | '}'; |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/2. |
| | | */ |
| | | public @interface CloudCode { |
| | | |
| | | //成功 |
| | | 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不支持该功能属性值 |
| | | |
| | | //10009 用户 |
| | | |
| | | //10401 住宅交付了 |
| | | |
| | | //10041 : RefreshToken 数据错误 |
| | | //10042 : RefreshToken 过期 |
| | | //10043 : RefreshToken 解析错误 |
| | | |
| | | |
| | | // 10003 : 不合法的token,请认真比对token的签名 |
| | | // 10004 : 缺少token参数 |
| | | // 10006 : 解析用户身份错误,请重新登录 |
| | | // 10009 : |
| | | |
| | | //125102思必驰授权 |
| | | } |
| | |
| | | public class HdlCloudApi { |
| | | |
| | | //正式环境 |
| | | // public static final String BASE_CHINA_URL = "https://china-gateway.hdlcontrol.com"; |
| | | public static final String BASE_CHINA_URL = "https://china-gateway.hdlcontrol.com"; |
| | | |
| | | //测试环境 |
| | | public static final String BASE_CHINA_URL = "https://test-gz.hdlcontrol.com"; |
| | | // public static final String BASE_CHINA_URL = "https://test-gz.hdlcontrol.com"; |
| | | |
| | | //登陆刷新token |
| | | public static final String LOGIN = "/smart-footstone/member/oauth/login"; |
| | | |
| | | //申请设备密钥(根据设备MAC) |
| | | public static final String APPLY_DEVICE_SECRET = "/smart-open/third/device/authByMac"; |
| | |
| | | //检查app是否更新 |
| | | public static final String CHECK_APP_VERSION_URL = "/basis-footstone/app/appVersion/check"; |
| | | |
| | | //获取思必驰token |
| | | public static final String GET_SIBICHI_TOKEN = "/smart-footstone/thirdToken/aiSpeechToken"; |
| | | |
| | | //验证是否on+是否绑定source |
| | | public static final String IS_BIND_URL = "/home-wisdom/source/screen/home/isBind"; |
| | | |
| | | //获取网关列表 |
| | | public static final String GET_GATEWAY_LIST = "/home-wisdom/app/gateway/getGatewayList"; |
| | | |
| | | } |
| | |
| | | package com.hdl.sdk.connect.cloud; |
| | | |
| | | import com.hdl.hdlhttp.HxHttp; |
| | | import com.hdl.hdlhttp.HxHttpBuilder; |
| | | import com.hdl.sdk.connect.bean.response.UpdateInfo; |
| | | import com.hdl.sdk.connect.cloud.bean.AiLoginInfo; |
| | | import com.hdl.sdk.connect.cloud.bean.GatewayInfo; |
| | | import com.hdl.sdk.connect.cloud.listener.GatewayListListener; |
| | | import com.hdl.sdk.connect.cloud.listener.GatewayListener; |
| | | import com.hdl.sdk.connect.cloud.listener.SibichiListener; |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.reactivex.rxjava3.disposables.Disposable; |
| | | |
| | |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 获取思必驰token |
| | | * |
| | | * @return |
| | | */ |
| | | public static Disposable getSibichiToken(String homeId, String clientId, SibichiListener listener) { |
| | | return HxHttp.builder() |
| | | .url(HdlCloudApi.GET_SIBICHI_TOKEN) |
| | | .params("homeId", homeId) |
| | | .params("clientId", clientId) |
| | | .build() |
| | | .post() |
| | | .subscribeWith(new HDLResponse<AiLoginInfo>() { |
| | | @Override |
| | | public void onResponse(AiLoginInfo response) { |
| | | listener.onSuccess(response); |
| | | } |
| | | |
| | | @Override |
| | | public void onFailure(HDLException e) { |
| | | listener.onError(e); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 获取主网关 |
| | | */ |
| | | public static Disposable syncMainGateway(String homeId, GatewayListener listener) { |
| | | return syncGatewayList(homeId, new GatewayListListener() { |
| | | @Override |
| | | public void onSuccess(List<GatewayInfo> info) { |
| | | if (listener != null) { |
| | | if (info == null || info.isEmpty()) { |
| | | listener.onError(new HDLException(-5000, "搜索网关失败")); |
| | | } else { |
| | | listener.onSuccess(info.get(0)); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | if (listener != null) { |
| | | listener.onError(e); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 同步获取网关列表 |
| | | */ |
| | | public static Disposable syncGatewayList(String homeId, GatewayListListener listener) { |
| | | HxHttpBuilder httpBuilder = HxHttp.builder() |
| | | .params("homeId", homeId) |
| | | .url(HdlCloudApi.GET_GATEWAY_LIST); |
| | | return httpBuilder.build().post().subscribeWith(new HDLResponse<List<GatewayInfo>>() { |
| | | @Override |
| | | public void onResponse(List<GatewayInfo> response) { |
| | | if (listener != null) { |
| | | listener.onSuccess(response); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onFailure(HDLException e) { |
| | | if (listener != null) { |
| | | listener.onError(e); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.bean; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * Created by Tong on 2024/12/10. |
| | | * 思必驰 |
| | | */ |
| | | public class AiLoginInfo implements Serializable { |
| | | private String accessToken; |
| | | private long expiration; |
| | | private String refreshToken; |
| | | private long refreshExpiration; |
| | | private String headerPrefix; |
| | | private String name; |
| | | private String account; |
| | | private String userPhone; |
| | | private String tenantId; |
| | | private String userId; |
| | | private String role; |
| | | private Integer expiresIn; |
| | | |
| | | /** |
| | | * 接口验证token |
| | | */ |
| | | public String getAccessToken() { |
| | | return accessToken == null ? "" : accessToken; |
| | | } |
| | | |
| | | public void setAccessToken(String accessToken) { |
| | | this.accessToken = accessToken; |
| | | } |
| | | |
| | | /** |
| | | * token过期时间戳 |
| | | */ |
| | | public long getExpiration() { |
| | | return expiration; |
| | | } |
| | | |
| | | public void setExpiration(long expiration) { |
| | | this.expiration = expiration; |
| | | } |
| | | |
| | | /** |
| | | * refreshToken过期时间戳 |
| | | */ |
| | | public long getRefreshExpiration() { |
| | | return refreshExpiration; |
| | | } |
| | | |
| | | public void setRefreshExpiration(long refreshExpiration) { |
| | | this.refreshExpiration = refreshExpiration; |
| | | } |
| | | |
| | | /** |
| | | * 刷新token需要使用 |
| | | */ |
| | | public String getRefreshToken() { |
| | | return refreshToken == null ? "" : refreshToken; |
| | | } |
| | | |
| | | public void setRefreshToken(String refreshToken) { |
| | | this.refreshToken = refreshToken; |
| | | } |
| | | |
| | | /** |
| | | * token类型 |
| | | */ |
| | | public String getHeaderPrefix() { |
| | | return headerPrefix == null ? "" : headerPrefix; |
| | | } |
| | | |
| | | public void setHeaderPrefix(String headerPrefix) { |
| | | this.headerPrefix = headerPrefix; |
| | | } |
| | | |
| | | /** |
| | | * 用户真实姓名(没有认证房屋情况下建议使用account) |
| | | */ |
| | | public String getName() { |
| | | return name == null ? "" : name; |
| | | } |
| | | |
| | | public void setName(String name) { |
| | | this.name = name; |
| | | } |
| | | |
| | | /** |
| | | * 登录账号 |
| | | */ |
| | | public String getAccount() { |
| | | return account == null ? "" : account; |
| | | } |
| | | |
| | | public void setAccount(String account) { |
| | | this.account = account; |
| | | } |
| | | |
| | | /** |
| | | * 用户手机号码 老版本使用邮箱注册会没有 |
| | | */ |
| | | public String getUserPhone() { |
| | | return userPhone == null ? "" : userPhone; |
| | | } |
| | | |
| | | public void setUserPhone(String userPhone) { |
| | | this.userPhone = userPhone; |
| | | } |
| | | |
| | | public String getTenantId() { |
| | | return tenantId == null ? "" : tenantId; |
| | | } |
| | | |
| | | public void setTenantId(String tenantId) { |
| | | this.tenantId = tenantId; |
| | | } |
| | | |
| | | /** |
| | | * 用户ID |
| | | */ |
| | | public String getUserId() { |
| | | return userId == null ? "" : userId; |
| | | } |
| | | |
| | | public void setUserId(String userId) { |
| | | this.userId = userId; |
| | | } |
| | | |
| | | public String getRole() { |
| | | return role == null ? "" : role; |
| | | } |
| | | |
| | | public void setRole(String role) { |
| | | this.role = role; |
| | | } |
| | | |
| | | public Integer getExpiresIn() { |
| | | return expiresIn; |
| | | } |
| | | |
| | | public void setExpiresIn(Integer expiresIn) { |
| | | this.expiresIn = expiresIn; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "AiLoginInfo{" + |
| | | "accessToken='" + accessToken + '\'' + |
| | | ", expiration=" + expiration + |
| | | ", refreshToken='" + refreshToken + '\'' + |
| | | ", refreshExpiration=" + refreshExpiration + |
| | | ", headerPrefix='" + headerPrefix + '\'' + |
| | | ", name='" + name + '\'' + |
| | | ", account='" + account + '\'' + |
| | | ", userPhone='" + userPhone + '\'' + |
| | | ", tenantId='" + tenantId + '\'' + |
| | | ", userId='" + userId + '\'' + |
| | | ", role='" + role + '\'' + |
| | | ", expiresIn=" + expiresIn + |
| | | '}'; |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.bean; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/12/7. |
| | | * 网关信息 |
| | | */ |
| | | public class GatewayInfo implements Serializable { |
| | | |
| | | private String gatewayId; |
| | | private String aesKey; |
| | | private Integer deviceId; |
| | | private Integer encryptionType; |
| | | private String gatewayType; |
| | | private String groupName; |
| | | private String homeId; |
| | | private String mac; |
| | | private String primaryKey; |
| | | private String projectName; |
| | | private Integer subnetId; |
| | | private String userName; |
| | | private String gatewayStatus; |
| | | private String modifyTime; |
| | | private String localSecret; |
| | | private String lastHeartbeatTime; |
| | | |
| | | public String getGatewayId() { |
| | | return gatewayId; |
| | | } |
| | | |
| | | public void setGatewayId(String gatewayId) { |
| | | this.gatewayId = gatewayId; |
| | | } |
| | | |
| | | public String getAesKey() { |
| | | return aesKey; |
| | | } |
| | | |
| | | public void setAesKey(String aesKey) { |
| | | this.aesKey = aesKey; |
| | | } |
| | | |
| | | public Integer getDeviceId() { |
| | | return deviceId; |
| | | } |
| | | |
| | | public void setDeviceId(Integer deviceId) { |
| | | this.deviceId = deviceId; |
| | | } |
| | | |
| | | public Integer getEncryptionType() { |
| | | return encryptionType; |
| | | } |
| | | |
| | | public void setEncryptionType(Integer encryptionType) { |
| | | this.encryptionType = encryptionType; |
| | | } |
| | | |
| | | public String getGatewayType() { |
| | | return gatewayType; |
| | | } |
| | | |
| | | public void setGatewayType(String gatewayType) { |
| | | this.gatewayType = gatewayType; |
| | | } |
| | | |
| | | public String getGroupName() { |
| | | return groupName; |
| | | } |
| | | |
| | | public void setGroupName(String groupName) { |
| | | this.groupName = groupName; |
| | | } |
| | | |
| | | public String getHomeId() { |
| | | return homeId; |
| | | } |
| | | |
| | | public void setHomeId(String homeId) { |
| | | this.homeId = homeId; |
| | | } |
| | | |
| | | public String getMac() { |
| | | return mac; |
| | | } |
| | | |
| | | public void setMac(String mac) { |
| | | this.mac = mac; |
| | | } |
| | | |
| | | public String getPrimaryKey() { |
| | | return primaryKey; |
| | | } |
| | | |
| | | public void setPrimaryKey(String primaryKey) { |
| | | this.primaryKey = primaryKey; |
| | | } |
| | | |
| | | public String getProjectName() { |
| | | return projectName; |
| | | } |
| | | |
| | | public void setProjectName(String projectName) { |
| | | this.projectName = projectName; |
| | | } |
| | | |
| | | public Integer getSubnetId() { |
| | | return subnetId; |
| | | } |
| | | |
| | | public void setSubnetId(Integer subnetId) { |
| | | this.subnetId = subnetId; |
| | | } |
| | | |
| | | public String getUserName() { |
| | | return userName; |
| | | } |
| | | |
| | | public void setUserName(String userName) { |
| | | this.userName = userName; |
| | | } |
| | | |
| | | public String getGatewayStatus() { |
| | | return gatewayStatus; |
| | | } |
| | | |
| | | public void setGatewayStatus(String gatewayStatus) { |
| | | this.gatewayStatus = gatewayStatus; |
| | | } |
| | | |
| | | public String getModifyTime() { |
| | | return modifyTime; |
| | | } |
| | | |
| | | public void setModifyTime(String modifyTime) { |
| | | this.modifyTime = modifyTime; |
| | | } |
| | | |
| | | public String getLocalSecret() { |
| | | return localSecret; |
| | | } |
| | | |
| | | public void setLocalSecret(String localSecret) { |
| | | this.localSecret = localSecret; |
| | | } |
| | | |
| | | public String getLastHeartbeatTime() { |
| | | return lastHeartbeatTime; |
| | | } |
| | | |
| | | public void setLastHeartbeatTime(String lastHeartbeatTime) { |
| | | this.lastHeartbeatTime = lastHeartbeatTime; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "GatewayInfo{" + |
| | | "gatewayId='" + gatewayId + '\'' + |
| | | ", aesKey='" + aesKey + '\'' + |
| | | ", deviceId=" + deviceId + |
| | | ", encryptionType=" + encryptionType + |
| | | ", gatewayType='" + gatewayType + '\'' + |
| | | ", groupName='" + groupName + '\'' + |
| | | ", homeId='" + homeId + '\'' + |
| | | ", mac='" + mac + '\'' + |
| | | ", primaryKey='" + primaryKey + '\'' + |
| | | ", projectName='" + projectName + '\'' + |
| | | ", subnetId=" + subnetId + |
| | | ", userName='" + userName + '\'' + |
| | | ", gatewayStatus='" + gatewayStatus + '\'' + |
| | | ", modifyTime='" + modifyTime + '\'' + |
| | | ", localSecret='" + localSecret + '\'' + |
| | | ", lastHeartbeatTime='" + lastHeartbeatTime + '\'' + |
| | | '}'; |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.broadcast; |
| | | |
| | | import android.content.BroadcastReceiver; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | import android.text.TextUtils; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/9. |
| | | * 网络请求广播 |
| | | * 需要应用层注册 |
| | | */ |
| | | public abstract class CloudBroadcast extends BroadcastReceiver { |
| | | |
| | | public static final String KEY_API_CODE = "key_api_code"; |
| | | public static final String KEY_API_MESSAGE = "key_api_message"; |
| | | |
| | | @Override |
| | | public final void onReceive(Context context, Intent intent) { |
| | | if (intent == null) return; |
| | | String action = intent.getAction(); |
| | | if (action != null && !TextUtils.isEmpty(action)) { |
| | | switch (action) { |
| | | case CloudBroadcastAction.REFRESH_TOKEN_INVALID_ACTION: |
| | | onLogOut(); |
| | | break; |
| | | case CloudBroadcastAction.API_ERROR_ACTION: |
| | | try { |
| | | final String message = intent.getStringExtra(KEY_API_MESSAGE); |
| | | final int code = intent.getIntExtra(KEY_API_CODE, -1); |
| | | onOtherError(code, message); |
| | | } catch (Exception e) { |
| | | onOtherError(-1, e.getMessage()); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 登录失效 |
| | | */ |
| | | public void onLogOut() { |
| | | //会频繁收到 |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 消息 |
| | | * |
| | | * @param code code |
| | | * @param message 消息 |
| | | */ |
| | | public void onOtherError(int code, String message) { |
| | | |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.broadcast; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/8. |
| | | */ |
| | | public class CloudBroadcastAction { |
| | | |
| | | //token刷新了 |
| | | public static final String REFRESH_TOKEN_ACTION = "hdl.cloud.broadcast.action.REFRESH_TOKEN"; |
| | | |
| | | //刷新token失效了 |
| | | public static final String REFRESH_TOKEN_INVALID_ACTION = "hdl.cloud.broadcast.action.REFRESH_TOKEN_INVALID"; |
| | | |
| | | //非0且不是刷新token,error |
| | | public static final String API_ERROR_ACTION = "hdl.cloud.broadcast.action.Api_Error"; |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.broadcast; |
| | | |
| | | import android.app.Application; |
| | | import android.content.IntentFilter; |
| | | |
| | | |
| | | /** |
| | | * Created by Tong on 2023/05/06. |
| | | * 需要注册全局广播代码放这里 |
| | | */ |
| | | public class GlobalBroadcastManager { |
| | | |
| | | |
| | | /** |
| | | * 注册全局广播 |
| | | */ |
| | | public static void registerGlobalBroadcast(Application app) { |
| | | registerCloudBroadcast(app); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 注册接口返回的广播 |
| | | */ |
| | | private static void registerCloudBroadcast(Application application) { |
| | | |
| | | HDLCloudBroadcast hdlCloudBroadcast = new HDLCloudBroadcast(); |
| | | IntentFilter filter = new IntentFilter(); |
| | | |
| | | filter.addAction(CloudBroadcastAction.REFRESH_TOKEN_INVALID_ACTION); |
| | | filter.addAction(CloudBroadcastAction.REFRESH_TOKEN_ACTION); |
| | | application.registerReceiver(hdlCloudBroadcast, filter); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.broadcast; |
| | | |
| | | import android.text.TextUtils; |
| | | import android.util.Log; |
| | | |
| | | import com.hdl.sdk.connect.bean.response.BindInfoBean; |
| | | import com.hdl.sdk.connect.cloud.HDLException; |
| | | import com.hdl.sdk.connect.cloud.HDLResponse; |
| | | import com.hdl.sdk.connect.config.HDLCloudConfig; |
| | | import com.hdl.sdk.sourceos.bind.BindHomeService; |
| | | import com.hdl.sdk.sourceos.qrcode.QRCode; |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.Future; |
| | | |
| | | /** |
| | | * Created by Tong on 2022/2/12. |
| | | * token失效处理 |
| | | */ |
| | | public class HDLCloudBroadcast extends CloudBroadcast { |
| | | |
| | | private final ExecutorService service = Executors.newSingleThreadExecutor(); |
| | | |
| | | private volatile Future<?> mBindTokenTask; |
| | | |
| | | private static final String TAG = HDLCloudBroadcast.class.getSimpleName(); |
| | | |
| | | /** |
| | | * 登录失效了 |
| | | */ |
| | | @Override |
| | | public void onLogOut() { |
| | | super.onLogOut(); |
| | | refreshBindingToken(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 刷新绑定Token |
| | | */ |
| | | public void refreshBindingToken() { |
| | | Log.e(TAG, "refreshBindingToken"); |
| | | if (mBindTokenTask != null) { |
| | | try { |
| | | mBindTokenTask.cancel(true); |
| | | } catch (Throwable e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | final String code = QRCode.getBindQRCode(); |
| | | if (!TextUtils.isEmpty(code)) { |
| | | String[] split = code.split("_"); |
| | | if (split.length == 3) { |
| | | try { |
| | | mBindTokenTask = service.submit(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | try { |
| | | //防止频繁休眠10秒 |
| | | Thread.sleep(10 * 1000); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | |
| | | BindHomeService.isBind(split[0], split[1], split[2], new HDLResponse<BindInfoBean>() { |
| | | @Override |
| | | public void onResponse(BindInfoBean response) { |
| | | if (response != null) { |
| | | HDLCloudConfig.getInstance().setToken(response.getToken()); |
| | | HDLCloudConfig.getInstance().setRefreshToken(response.getRefreshToken()); |
| | | } |
| | | Log.e(TAG, "refreshBindingToken---> succeed"); |
| | | } |
| | | |
| | | @Override |
| | | public void onFailure(HDLException e) { |
| | | Log.e(TAG, "refreshBindingToken error---> " + e); |
| | | /*if (e instanceof ApiException) { |
| | | if (e.getCode() != CloudCode.NO_TOKEN) { |
| | | |
| | | } |
| | | |
| | | }*/ |
| | | } |
| | | }); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void onOtherError(int code, String message) { |
| | | super.onOtherError(code, message); |
| | | |
| | | Log.d(TAG, "onOtherError: code" + code + "," + message); |
| | | |
| | | if (code == 125102 || code == 10401) { |
| | | //思必驰失效了, 住宅和当前用户不匹配 |
| | | Log.d(TAG, "onOtherError: 思必驰失效了"); |
| | | |
| | | refreshBindingToken(); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.hdl.sdk.connect.HDLLink; |
| | | import com.hdl.sdk.connect.cloud.GsonUtils; |
| | | import com.hdl.sdk.connect.cloud.MD5Utils; |
| | | import com.hdl.sdk.connect.config.HDLCloudConfig; |
| | | |
| | | import java.io.IOException; |
| | | import java.net.URLDecoder; |
| | |
| | | */ |
| | | 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 String appKey = HDLCloudConfig.getInstance().getAppKey(); |
| | | final String appSecret = HDLCloudConfig.getInstance().getAppSecret(); |
| | | final JsonObject json = getBodyJson(request); |
| | | if (json != null) { |
| | | json.addProperty("appKey", appKey); |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.interceptor; |
| | | |
| | | import android.content.Intent; |
| | | import android.text.TextUtils; |
| | | import android.util.Log; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | |
| | | import com.google.gson.JsonObject; |
| | | import com.google.gson.JsonParser; |
| | | import com.hdl.hdlhttp.HxHttpConfig; |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.connect.cloud.CloudCode; |
| | | import com.hdl.sdk.connect.cloud.HdlCloudApi; |
| | | import com.hdl.sdk.connect.cloud.broadcast.CloudBroadcast; |
| | | import com.hdl.sdk.connect.cloud.broadcast.CloudBroadcastAction; |
| | | import com.hdl.sdk.connect.config.HDLCloudConfig; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | import java.io.IOException; |
| | | import java.nio.charset.Charset; |
| | | |
| | | import okhttp3.Headers; |
| | | import okhttp3.Interceptor; |
| | | import okhttp3.MediaType; |
| | | import okhttp3.OkHttpClient; |
| | | import okhttp3.Request; |
| | | import okhttp3.RequestBody; |
| | | import okhttp3.Response; |
| | | import okhttp3.ResponseBody; |
| | | import okio.Buffer; |
| | | import okio.BufferedSource; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/2. |
| | | */ |
| | | public class HdlLoginInterceptor implements Interceptor { |
| | | |
| | | @NonNull |
| | | @Override |
| | | public Response intercept(@NonNull Chain chain) throws IOException { |
| | | Request request = chain.request(); |
| | | if (!isRefreshTokenHeader(request.headers())) { |
| | | String token = HDLCloudConfig.getInstance().getToken(); |
| | | if (!TextUtils.isEmpty(token)) { |
| | | Request processRequest = addToken(request, token); |
| | | Response processResponse = chain.proceed(processRequest); |
| | | return disposeToken(chain, processRequest, processResponse); |
| | | } else { |
| | | //没有缓存token处理 |
| | | Response response = chain.proceed(request); |
| | | //是否需要token,需要则广播 |
| | | ResponseBody responseBody = response.body(); |
| | | if (401 == response.code() || 402 == response.code() || 403 == response.code()) { |
| | | //网络校验异常,需要token |
| | | final Intent intent = new Intent(); |
| | | intent.setAction(CloudBroadcastAction.REFRESH_TOKEN_INVALID_ACTION); |
| | | sendBroadcast(intent); |
| | | |
| | | } else if (responseBody != null && response.isSuccessful()) { |
| | | try { |
| | | MediaType mediaType = responseBody.contentType(); |
| | | if (mediaType != null) { |
| | | String type = mediaType.toString(); |
| | | |
| | | //json类型才处理 |
| | | if (!TextUtils.isEmpty(type) && type.contains("json")) { |
| | | |
| | | BufferedSource source = responseBody.source(); |
| | | |
| | | source.request(Long.MAX_VALUE); |
| | | |
| | | Buffer buffer = source.getBuffer().clone(); |
| | | String respString = buffer.readString(Charset.defaultCharset()); |
| | | JsonObject object = JsonParser.parseString(respString).getAsJsonObject(); |
| | | int code = object.get("code").getAsInt(); |
| | | if (isTokenLoseByCode(code)) { |
| | | //token失效了,需要token |
| | | final Intent intent = new Intent(); |
| | | intent.setAction(CloudBroadcastAction.REFRESH_TOKEN_INVALID_ACTION); |
| | | sendBroadcast(intent); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | |
| | | return response; |
| | | } |
| | | } |
| | | return chain.proceed(request); |
| | | } |
| | | |
| | | @NonNull |
| | | private Response disposeToken(Chain chain, Request request, Response response) { |
| | | try { |
| | | if (401 == response.code() || 402 == response.code() || 403 == response.code()) { |
| | | final String token = refreshToken(); |
| | | if (!TextUtils.isEmpty(token)) { |
| | | return chain.proceed(addToken(request, token)); |
| | | } |
| | | //网络异常不需要重置token |
| | | |
| | | } else if (response.isSuccessful()) { |
| | | ResponseBody responseBody = response.body(); |
| | | if (responseBody != null) { |
| | | MediaType mediaType = responseBody.contentType(); |
| | | if (mediaType != null) { |
| | | String type = mediaType.toString(); |
| | | //json类型才处理 |
| | | if (!TextUtils.isEmpty(type) && type.contains("json")) { |
| | | BufferedSource source = responseBody.source(); |
| | | source.request(Long.MAX_VALUE); |
| | | Buffer buffer = source.getBuffer().clone(); |
| | | String respString = buffer.readString(Charset.defaultCharset()); |
| | | JsonObject object = JsonParser.parseString(respString).getAsJsonObject(); |
| | | |
| | | int code = -1; |
| | | try { |
| | | if (object != null) { |
| | | code = object.get("code").getAsInt(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | String message = ""; |
| | | try { |
| | | if (object != null && object.has("message")) { |
| | | message = object.get("message").getAsString(); |
| | | if (TextUtils.isEmpty(message)) { |
| | | message = ""; |
| | | } |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | if (isTokenLoseByCode(code)) { |
| | | //刷新token |
| | | final String token = refreshToken(); |
| | | if (!TextUtils.isEmpty(token)) { |
| | | Response newResponse = chain.proceed(addToken(request, token)); |
| | | |
| | | //token更新了 |
| | | final Intent intent = new Intent(); |
| | | intent.setAction(CloudBroadcastAction.REFRESH_TOKEN_ACTION); |
| | | sendBroadcast(intent); |
| | | |
| | | return newResponse; |
| | | } else { |
| | | //清空token |
| | | HDLCloudConfig.getInstance().setToken(""); |
| | | HDLCloudConfig.getInstance().setRefreshToken(""); |
| | | |
| | | //token刷新失败,通知token失效了 |
| | | final Intent intent = new Intent(); |
| | | intent.setAction(CloudBroadcastAction.REFRESH_TOKEN_INVALID_ACTION); |
| | | sendBroadcast(intent); |
| | | } |
| | | } else { |
| | | try { |
| | | //其他异常情况 |
| | | final Intent intent = new Intent(); |
| | | intent.setAction(CloudBroadcastAction.API_ERROR_ACTION); |
| | | intent.putExtra(CloudBroadcast.KEY_API_CODE, code); |
| | | intent.putExtra(CloudBroadcast.KEY_API_MESSAGE, message); |
| | | sendBroadcast(intent); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | buffer.clear(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | Log.d("HDL===>", "disposeToken: 失败," + e); |
| | | } |
| | | return response; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 根据code判断token是否失效 |
| | | * |
| | | * @param code 业务code |
| | | * @return ture 失效 |
| | | */ |
| | | private boolean isTokenLoseByCode(int code) { |
| | | return CloudCode.TOKEN_TIMEOUT == code || |
| | | CloudCode.TOKEN_NOT_STANDARD == code || |
| | | CloudCode.NO_TOKEN == code; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 是否存在刷新头 |
| | | */ |
| | | private boolean isRefreshTokenHeader(Headers headers) { |
| | | String signHeader = headers.get(SmartHeader.REFRESH_TOKEN_HEADER); |
| | | return !TextUtils.isEmpty(signHeader); |
| | | } |
| | | |
| | | private Request addToken(Request request, String token) { |
| | | return request.newBuilder() |
| | | .removeHeader("Authorization") |
| | | .build() |
| | | .newBuilder() |
| | | .method(request.method(), request.body()) |
| | | .addHeader("Authorization", HDLCloudConfig.getInstance().getTokenHeaderPrefix() + token) |
| | | .build(); |
| | | } |
| | | |
| | | /** |
| | | * 拦截器EncryptInterceptor会处理加密 |
| | | * |
| | | * @return token |
| | | */ |
| | | private String refreshToken() { |
| | | final String cacheRefreshToken = SPUtils.getString(SPKey.REFRESH_TOKEN); |
| | | if (TextUtils.isEmpty(cacheRefreshToken)) { |
| | | return null; |
| | | } |
| | | final OkHttpClient client = HxHttpConfig.getInstance().getClient(); |
| | | |
| | | Request.Builder builder = new Request.Builder(); |
| | | |
| | | final JsonObject json = new JsonObject(); |
| | | json.addProperty("refreshToken", cacheRefreshToken); |
| | | json.addProperty("grantType", "refresh_token"); |
| | | |
| | | final RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json;charset=UTF-8")); |
| | | builder.post(requestBody); |
| | | builder.url(HDLCloudConfig.getInstance().getBaseUrl() + HdlCloudApi.LOGIN); |
| | | builder.addHeader(SmartHeader.REFRESH_TOKEN_HEADER, "0"); |
| | | try { |
| | | Response response = client.newCall(builder.build()).execute(); |
| | | if (response.isSuccessful()) { |
| | | ResponseBody responseBody = response.body(); |
| | | if (responseBody != null) { |
| | | BufferedSource source = responseBody.source(); |
| | | source.request(Long.MAX_VALUE); |
| | | Buffer buffer = source.getBuffer().clone(); |
| | | String respString = buffer.readString(Charset.defaultCharset()); |
| | | |
| | | JsonObject object = JsonParser.parseString(respString).getAsJsonObject(); |
| | | JsonObject dataJson = object.get("data").getAsJsonObject(); |
| | | String accessToken = dataJson.get("accessToken").getAsString(); |
| | | String refreshToken = dataJson.get("refreshToken").getAsString(); |
| | | if (!TextUtils.isEmpty(accessToken)) { |
| | | HDLCloudConfig.getInstance().setToken(accessToken); |
| | | } |
| | | if (!TextUtils.isEmpty(refreshToken)) { |
| | | HDLCloudConfig.getInstance().setRefreshToken(refreshToken); |
| | | } |
| | | return accessToken; |
| | | |
| | | } |
| | | } else { |
| | | Log.d("OKHTTP===>", "refreshToken: 失败了"); |
| | | } |
| | | } catch (Exception ignored) { |
| | | Log.d("OKHTTP===>", "refreshToken: 失败,异常"); |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | |
| | | private void sendBroadcast(Intent intent) { |
| | | HDLCloudConfig.getInstance().getContext().sendBroadcast(intent); |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.listener; |
| | | |
| | | import com.hdl.sdk.connect.cloud.BaseCallBack; |
| | | import com.hdl.sdk.connect.cloud.bean.GatewayInfo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/12/7. |
| | | * 网关列表 |
| | | */ |
| | | public interface GatewayListListener extends BaseCallBack { |
| | | void onSuccess(List<GatewayInfo> info); |
| | | } |
| | | |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.listener; |
| | | |
| | | import com.hdl.sdk.connect.cloud.BaseCallBack; |
| | | import com.hdl.sdk.connect.cloud.bean.GatewayInfo; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/12/7. |
| | | */ |
| | | public interface GatewayListener extends BaseCallBack { |
| | | void onSuccess(GatewayInfo info); |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.cloud.listener; |
| | | |
| | | |
| | | import com.hdl.sdk.connect.cloud.BaseCallBack; |
| | | import com.hdl.sdk.connect.cloud.bean.AiLoginInfo; |
| | | |
| | | /** |
| | | * Created by Zoro |
| | | * Created on 2021/11/26 |
| | | * description: |
| | | */ |
| | | public interface SibichiListener extends BaseCallBack { |
| | | void onSuccess(AiLoginInfo info); |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.connect.config; |
| | | |
| | | import android.content.Context; |
| | | import android.text.TextUtils; |
| | | |
| | | import com.hdl.hdlhttp.HxHttpConfig; |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.connect.cloud.interceptor.EncryptInterceptor; |
| | | import com.hdl.sdk.connect.cloud.interceptor.HdlLoginInterceptor; |
| | | import com.hdl.sdk.connect.cloud.interceptor.SmartHeaderInterceptor; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | import okhttp3.Interceptor; |
| | | import okhttp3.logging.HttpLoggingInterceptor; |
| | | |
| | | /** |
| | | * Created by panlili on 2025/3/4 |
| | | * description: |
| | | */ |
| | | public class HDLCloudConfig { |
| | | |
| | | private String mBaseUrl; |
| | | |
| | | private String mDefBaseUrl; |
| | | |
| | | private String mLanguage; |
| | | |
| | | private static final String DEF_TOKEN_HEADER_PREFIX = "Bearer "; |
| | | |
| | | private HDLCloudConfig() { |
| | | } |
| | | |
| | | private static class SingletonInstance { |
| | | private static final HDLCloudConfig INSTANCE = new HDLCloudConfig(); |
| | | } |
| | | |
| | | public static HDLCloudConfig getInstance() { |
| | | return SingletonInstance.INSTANCE; |
| | | } |
| | | |
| | | private Context context; |
| | | |
| | | private String appKey, appSecret; |
| | | |
| | | private String token, refreshToken; |
| | | |
| | | private String tokenHeaderPrefix = DEF_TOKEN_HEADER_PREFIX; |
| | | |
| | | public Context getContext() { |
| | | return context; |
| | | } |
| | | |
| | | public void init(Context context, String appKey, String appSecret, String url) { |
| | | this.context = context; |
| | | HxHttpConfig.getInstance().init(context, url) |
| | | .addInterceptor( |
| | | new HdlLoginInterceptor(), |
| | | new EncryptInterceptor(), |
| | | new SmartHeaderInterceptor()); |
| | | this.mBaseUrl = url; |
| | | this.mDefBaseUrl = url; |
| | | this.appKey = appKey; |
| | | this.appSecret = appSecret; |
| | | setBaseUrl(url); |
| | | } |
| | | |
| | | public void addInterceptor(Interceptor... interceptors) { |
| | | HxHttpConfig.getInstance().addInterceptor(interceptors); |
| | | } |
| | | |
| | | |
| | | public String getBaseUrl() { |
| | | if (TextUtils.isEmpty(mBaseUrl)) { |
| | | mBaseUrl = SPUtils.getString(SPKey.BASE_URL, ""); |
| | | } |
| | | return mBaseUrl; |
| | | } |
| | | |
| | | public void setBaseUrl(String mBaseUrl) { |
| | | this.mBaseUrl = mBaseUrl; |
| | | HxHttpConfig.getInstance().init(context,mBaseUrl); |
| | | SPUtils.put(SPKey.BASE_URL, mBaseUrl); |
| | | } |
| | | |
| | | public String getDefBaseUrl() { |
| | | return mDefBaseUrl; |
| | | } |
| | | |
| | | public void setDefBaseUrl(String mDefBaseUrl) { |
| | | this.mDefBaseUrl = mDefBaseUrl; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | public synchronized String getToken() { |
| | | if (TextUtils.isEmpty(token)) { |
| | | token = SPUtils.getString(SPKey.TOKEN); |
| | | } |
| | | return token; |
| | | |
| | | } |
| | | |
| | | public synchronized void setToken(String token) { |
| | | this.token = token; |
| | | SPUtils.put(SPKey.TOKEN, token); |
| | | } |
| | | |
| | | public synchronized String getRefreshToken() { |
| | | if (TextUtils.isEmpty(refreshToken)) { |
| | | refreshToken = SPUtils.getString(SPKey.REFRESH_TOKEN); |
| | | } |
| | | return refreshToken; |
| | | } |
| | | |
| | | public synchronized void setRefreshToken(String refreshToken) { |
| | | this.refreshToken = refreshToken; |
| | | SPUtils.put(SPKey.REFRESH_TOKEN, refreshToken); |
| | | } |
| | | |
| | | public String getTokenHeaderPrefix() { |
| | | return tokenHeaderPrefix; |
| | | } |
| | | |
| | | public void setTokenHeaderPrefix(String tokenHeaderPrefix) { |
| | | this.tokenHeaderPrefix = tokenHeaderPrefix; |
| | | } |
| | | |
| | | |
| | | public String getLanguage() { |
| | | return mLanguage; |
| | | } |
| | | |
| | | public void setLanguage(String mLanguage) { |
| | | this.mLanguage = mLanguage; |
| | | } |
| | | } |
| | |
| | | private static final String AUTHENTICATE_IS_LS_KEY = "auth_isls_key"; |
| | | public static final String AUTHENTICATE_IS_DEVICEINFO_KEY = "auth_deviceinfo_key"; |
| | | |
| | | public static final String GATEWAY_REMOTEINFO_KEY="gateway_remoteinfo_key"; |
| | | public static final String GATEWAY_REMOTEINFO_KEY = "gateway_remoteinfo_key"; |
| | | private static final String GATEWAY_PARENTOID_KEY = "gateway_parentoiid_key"; |
| | | |
| | | private String localSecret;//本地加密密钥 |
| | |
| | | /** |
| | | * instance |
| | | */ |
| | | private static final HDLLinkConfig instance=new HDLLinkConfig(); |
| | | private HDLLinkConfig() |
| | | { |
| | | private static final HDLLinkConfig instance = new HDLLinkConfig(); |
| | | |
| | | private HDLLinkConfig() { |
| | | loadConfig(); |
| | | } |
| | | |
| | |
| | | * |
| | | * @return AuthenticateConfig |
| | | */ |
| | | public static HDLLinkConfig getInstance() { |
| | | public static HDLLinkConfig getInstance() { |
| | | // if (instance == null) { |
| | | // synchronized (HDLLinkConfig.class) { |
| | | // if (instance == null) { |
| | |
| | | this.gatewayId = ""; |
| | | this.ipAddress = ""; |
| | | this.localSecret = ""; |
| | | this.homeId=""; |
| | | this.homeId = ""; |
| | | SPUtils.remove(AUTHENTICATE_LS_KEY); |
| | | SPUtils.remove(AUTHENTICATE_GATEWAYID_KEY); |
| | | SPUtils.remove(AUTHENTICATE_IPADDRESS_KEY); |
| | |
| | | public String getGatewayId() { |
| | | return gatewayId; |
| | | } |
| | | |
| | | public void setGatewayId(String gatewayId) { |
| | | this.gatewayId=gatewayId; |
| | | this.gatewayId = gatewayId; |
| | | } |
| | | |
| | | public String getIpAddress() { |
| | | return ipAddress; |
| | | } |
| | | public void setIpAddress(String ipAddress){ |
| | | |
| | | public void setIpAddress(String ipAddress) { |
| | | this.ipAddress = ipAddress; |
| | | } |
| | | |
| | |
| | | |
| | | public AuthenticateRequest.AuthenticateDeviceInfoBean getDeviceInfoBean() { |
| | | AuthenticateRequest.AuthenticateDeviceInfoBean infoBean = (AuthenticateRequest.AuthenticateDeviceInfoBean) SPUtils.getSerializableEntity(AUTHENTICATE_IS_DEVICEINFO_KEY); |
| | | if(infoBean==null){ |
| | | infoBean= new AuthenticateRequest.AuthenticateDeviceInfoBean(); |
| | | if (infoBean == null) { |
| | | infoBean = new AuthenticateRequest.AuthenticateDeviceInfoBean(); |
| | | } |
| | | return infoBean; |
| | | } |
| | |
| | |
|
| | | 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.HDLLink;
|
| | | import com.hdl.sdk.connect.bean.LinkResponse;
|
| | | import com.hdl.sdk.connect.bean.request.AuthenticateRequest;
|
| | | import com.hdl.sdk.connect.bean.response.DeviceDeleteResponse;
|
| | | 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.connect.utils.ByteBufferUtils;
|
| | | import com.hdl.sdk.socket.codec.ByteToMessageDecoder;
|
| | |
|
| | | import java.nio.ByteBuffer;
|
| | | import java.nio.charset.StandardCharsets;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | import android.util.Base64;
|
| | |
|
| | | import kotlin.ParameterName;
|
| | |
|
| | | /**
|
| | | * Created by Tong on 2021/9/22.
|
| | |
| | | if (broadcast) { |
| | | ip = IpUtils.getBroadcastAddress(); |
| | | } |
| | | HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message,"", 1, new HdlSocketHelper.HdlSocketListener() { |
| | | HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, "", 1, new HdlSocketHelper.HdlSocketListener() { |
| | | @Override |
| | | public void onSucceed(Object msg) { |
| | | if (callBack == null) return; |
| | |
| | | HDLLinkConfig.getInstance().setCurrentGateway(searchBean);//设置当前网关 |
| | | if (mSearchGatewayCallBack != null) { |
| | | mSearchGatewayCallBack.onSuccess(searchBean); |
| | | HDLSocket.getInstance().isBroadcast = true; |
| | | HDLSocket.getInstance().getTcp(); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.hdl.sdk.socket.listener.ConnectStatusListener;
|
| | | import com.hdl.sdk.socket.listener.SendListener;
|
| | |
|
| | | import java.lang.reflect.Method;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | | import java.util.concurrent.ScheduledExecutorService;
|
| | |
| | | @Override
|
| | | public void heartbeat() {
|
| | |
|
| | | if (HDLLinkConfig.getInstance().getDeviceInfoBean() == null || HDLLinkConfig.getInstance().getDeviceInfoBean().getOID() == null) {
|
| | | LogUtils.i("DeviceInfoBean为空,需要设置才能正常心跳");
|
| | | return;
|
| | | }
|
| | |
|
| | | String time = String.valueOf(System.currentTimeMillis());
|
| | | JsonObject jsonObject = new JsonObject();
|
| | | jsonObject.addProperty("id", IdUtils.getUUId());
|
| | | jsonObject.addProperty("time_stamp", time);
|
| | | if (HDLLinkConfig.getInstance().getDeviceInfoBean().getOID() == null) {
|
| | | //不走从机入网,通过gatewayId发送
|
| | | if (HDLLinkConfig.getInstance().getGatewayId() == null) {
|
| | | return;
|
| | | }
|
| | | String topic = String.format(TopicConstant.HEARTBEAT, HDLLinkConfig.getInstance().getGatewayId());
|
| | | LinkRequest message = new LinkRequest(topic,
|
| | | jsonObject.toString());
|
| | | sendMsg(message.getSendBytes(), null, null, null);
|
| | |
|
| | | if (HDLLinkConfig.getInstance().getRequestBean() != null) {
|
| | | jsonObject.addProperty("mac", HDLLinkConfig.getInstance().getRequestBean().getMAC());
|
| | | } else {
|
| | | if (HDLLinkConfig.getInstance().getRequestBean() != null) {
|
| | | jsonObject.addProperty("mac", HDLLinkConfig.getInstance().getRequestBean().getMAC());
|
| | | }
|
| | | //走从机入网,通过oid发送
|
| | | String topic = String.format(TopicConstant.HEARTBEAT, HDLLinkConfig.getInstance().getDeviceInfoBean().getOID());
|
| | | LinkRequest message = new LinkRequest(topic,
|
| | | jsonObject.toString());
|
| | | sendMsg(message.getSendBytes(), null, null, null);
|
| | | }
|
| | |
|
| | | String topic = String.format(TopicConstant.HEARTBEAT, HDLLinkConfig.getInstance().getDeviceInfoBean().getOID());
|
| | |
|
| | | LinkRequest message = new LinkRequest(topic,
|
| | | jsonObject.toString());
|
| | | sendMsg(message.getSendBytes(), null, null, null);
|
| | | }
|
| | | });
|
| | | }
|
| | |
| | | public void run() { |
| | | while (true) { |
| | | try { |
| | | // LogUtils.i("initConnectThread: connected=" + connected + " isBroadcast=" + HDLSocket.getInstance().isBroadcast); |
| | | LogUtils.i("initConnectThread: connected=" + connected + " isBroadcast=" + HDLSocket.getInstance().isBroadcast); |
| | | if (!connected && HDLSocket.getInstance().isBroadcast) { |
| | | reconect(); |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.bind; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/12. |
| | | */ |
| | | public interface BaseEvent extends Serializable { |
| | | |
| | | @EventType |
| | | String getEventType(); |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.bind; |
| | | |
| | | /** |
| | | * Created by Tong on 2022/3/23. |
| | | * 扫码绑定事件 |
| | | */ |
| | | public class BindAuthEvent implements BaseEvent { |
| | | |
| | | |
| | | //on+绑定成功 |
| | | public static final int ON_PLUS_BINDING_SUCCEED_ACTION = 0; |
| | | |
| | | //on+绑定超时 |
| | | public static final int ON_PLUS_BINDING_TIMEOUT_ACTION = 1; |
| | | |
| | | //网络异常 |
| | | public static final int ON_PLUS_BINDING_ERROR_ACTION = 2; |
| | | |
| | | private int action; |
| | | |
| | | public BindAuthEvent(int action) { |
| | | this.action = action; |
| | | } |
| | | |
| | | @Override |
| | | public String getEventType() { |
| | | return EventType.ON_PLUS_BINDING_TYPE; |
| | | } |
| | | |
| | | public int getAction() { |
| | | return action; |
| | | } |
| | | |
| | | public void setAction(int action) { |
| | | this.action = action; |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.bind; |
| | | |
| | | import android.text.TextUtils; |
| | | |
| | | import com.hdl.hdlhttp.HxHttp; |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.connect.bean.response.BindInfoBean; |
| | | import com.hdl.sdk.connect.cloud.HDLException; |
| | | import com.hdl.sdk.connect.cloud.HDLResponse; |
| | | import com.hdl.sdk.connect.cloud.HdlCloudApi; |
| | | import com.hdl.sdk.connect.config.HDLCloudConfig; |
| | | import com.hdl.sdk.connect.config.HDLLinkConfig; |
| | | import com.hdl.sdk.sourceos.Rk3566Manager; |
| | | import com.hdl.sdk.sourceos.qrcode.QRCode; |
| | | import com.hdl.sdk.sourceos.utils.DeviceUtils; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | import com.hdl.sdk.sourceos.utils.thread.ThreadUtils; |
| | | |
| | | import org.greenrobot.eventbus.EventBus; |
| | | |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | | import io.reactivex.rxjava3.disposables.CompositeDisposable; |
| | | import io.reactivex.rxjava3.disposables.Disposable; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/11. |
| | | * on+是否绑定 |
| | | * 1、绑定成功需要查询住宅信息 |
| | | * 2、扫码3分钟超时 |
| | | */ |
| | | public class BindHomeService { |
| | | |
| | | private ScheduledExecutorService queryThread; |
| | | |
| | | private final CompositeDisposable compositeDisposable = new CompositeDisposable(); |
| | | |
| | | //最大时间 |
| | | private static final long MAX_TIME = 3 * 60 * 1000; |
| | | |
| | | //上一次执行时间 |
| | | private final AtomicLong lastTime = new AtomicLong(0); |
| | | |
| | | private BindHomeService() { |
| | | } |
| | | |
| | | private static class SingletonInstance { |
| | | private static final BindHomeService INSTANCE = new BindHomeService(); |
| | | } |
| | | |
| | | public static BindHomeService getInstance() { |
| | | return SingletonInstance.INSTANCE; |
| | | } |
| | | |
| | | /** |
| | | * 轮询是否绑定 |
| | | * |
| | | * @param timestamp 时间戳 |
| | | */ |
| | | public void startQuery(String timestamp) { |
| | | stopQuery(); |
| | | lastTime.set(System.currentTimeMillis()); |
| | | String packageName = Rk3566Manager.getInstance().getContext().getPackageName(); |
| | | String unique = DeviceUtils.getUniqueCode(); |
| | | queryThread = ThreadUtils.newScheduledThreadPool(1); |
| | | queryThread.scheduleWithFixedDelay(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | long timeMillis = System.currentTimeMillis(); |
| | | if (timeMillis - lastTime.get() < MAX_TIME) { |
| | | compositeDisposable.add(isBind(packageName, unique, timestamp)); |
| | | } else { |
| | | //超时了 |
| | | EventBus.getDefault().post(new BindAuthEvent(BindAuthEvent.ON_PLUS_BINDING_TIMEOUT_ACTION)); |
| | | stopQuery(); |
| | | } |
| | | |
| | | } |
| | | }, 0L, 800L, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | /** |
| | | * 停止查询 |
| | | */ |
| | | public void stopQuery() { |
| | | lastTime.set(0); |
| | | if (queryThread != null && !queryThread.isShutdown()) { |
| | | queryThread.shutdownNow(); |
| | | } |
| | | if (!compositeDisposable.isDisposed()) { |
| | | compositeDisposable.dispose(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 通过保存的code查询是否绑定 |
| | | * |
| | | * @param bindCode 保存的code查询是否绑定 |
| | | * @return |
| | | */ |
| | | public static Disposable isBindByCode(String bindCode) { |
| | | if (TextUtils.isEmpty(bindCode)) return null; |
| | | String[] code = bindCode.split("_"); |
| | | if (code.length < 3) { |
| | | return null; |
| | | } |
| | | String packageName = code[0]; |
| | | String unique = code[1]; |
| | | String timestamp = code[2]; |
| | | return isBind(packageName, unique, timestamp); |
| | | } |
| | | |
| | | public static Disposable isBind(String timestamp) { |
| | | String packageName = Rk3566Manager.getInstance().getContext().getPackageName(); |
| | | String unique = DeviceUtils.getUniqueCode(); |
| | | return isBind(packageName, unique, timestamp); |
| | | } |
| | | |
| | | /** |
| | | * @param timestamp 时间戳 |
| | | * @param packageName 包名 |
| | | * @param unique 序列号 |
| | | * @return |
| | | */ |
| | | public static Disposable isBind(String packageName, String unique, String timestamp) { |
| | | return isBind(packageName, unique, timestamp, new HDLResponse<BindInfoBean>() { |
| | | @Override |
| | | public void onResponse(BindInfoBean response) { |
| | | handleBind(response, timestamp); |
| | | } |
| | | |
| | | @Override |
| | | public void onFailure(HDLException e) { |
| | | //网络异常、或者接口报错 |
| | | EventBus.getDefault().post(new BindAuthEvent(BindAuthEvent.ON_PLUS_BINDING_ERROR_ACTION)); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @param timestamp 时间戳 |
| | | * @param packageName 包名 |
| | | * @param unique 序列号 |
| | | * @return |
| | | */ |
| | | public static Disposable isBind(String packageName, String unique, String timestamp, HDLResponse<BindInfoBean> response) { |
| | | return HxHttp.builder() |
| | | .url(HdlCloudApi.IS_BIND_URL) |
| | | .params("packageName", packageName) |
| | | .params("unique", unique) |
| | | .params("qrcodeTimestamp", timestamp) |
| | | .build() |
| | | .executePost() |
| | | .subscribeWith(response); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 处理绑定 |
| | | * |
| | | * @param response 返回 |
| | | * @param timestamp 时间戳 |
| | | */ |
| | | private static void handleBind(BindInfoBean response, String timestamp) { |
| | | if (!TextUtils.isEmpty(response.getHomeId())) { |
| | | |
| | | SPUtils.saveSerializableEntity(SPKey.BIND_HOME_INFO, response); |
| | | SPUtils.put(SPKey.BIND_CODE, QRCode.createBindQRCodeInfo(timestamp)); |
| | | |
| | | HDLCloudConfig.getInstance().setToken(response.getToken()); |
| | | HDLCloudConfig.getInstance().setRefreshToken(response.getRefreshToken()); |
| | | |
| | | EventBus.getDefault().post(new BindAuthEvent(BindAuthEvent.ON_PLUS_BINDING_SUCCEED_ACTION)); |
| | | |
| | | getInstance().stopQuery(); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.bind; |
| | | |
| | | |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | import androidx.annotation.StringDef; |
| | | |
| | | import java.lang.annotation.Retention; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/8. |
| | | */ |
| | | @StringDef({ |
| | | EventType.TEST_TYPE, |
| | | EventType.ON_PLUS_BINDING_TYPE |
| | | |
| | | }) |
| | | @Retention(SOURCE) |
| | | public @interface EventType { |
| | | |
| | | //测试数据 |
| | | String TEST_TYPE = "event_test_type"; |
| | | |
| | | //on+绑定成功 |
| | | String ON_PLUS_BINDING_TYPE = "event_on_plus_binding_type"; |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.qrcode; |
| | | |
| | | import android.net.Uri; |
| | | import android.text.TextUtils; |
| | | |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.sourceos.Rk3566Manager; |
| | | import com.hdl.sdk.sourceos.utils.DeviceUtils; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/8. |
| | | */ |
| | | public class QRCode { |
| | | |
| | | private static final String SOURCE_SCHEME = "source"; |
| | | //绑定source |
| | | private static final String BIND_HOST = "bind"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * @return source://bind/包名_序列号_时间戳 |
| | | */ |
| | | public static String getBindQRCodeInfo() { |
| | | return SPUtils.getString(SPKey.BIND_CODE); |
| | | } |
| | | |
| | | /** |
| | | * @return 包名_序列号_时间戳 |
| | | */ |
| | | public static String getBindQRCode(String code) { |
| | | if (!TextUtils.isEmpty(code)) { |
| | | Uri uri = Uri.parse(code); |
| | | return uri.getLastPathSegment(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * @return 包名_序列号_时间戳 |
| | | */ |
| | | public static String getBindQRCode() { |
| | | String info = QRCode.getBindQRCodeInfo(); |
| | | return getBindQRCode(info); |
| | | } |
| | | |
| | | /** |
| | | * 序列号android10 会获取不到 |
| | | * |
| | | * @return 获取绑定二维码信息, source://bind/包名_序列号_时间戳 |
| | | */ |
| | | public static String createBindQRCodeInfo(String time) { |
| | | final String packageName = Rk3566Manager.getInstance().getContext().getPackageName(); |
| | | final String deviceId = DeviceUtils.getUniqueCode(); |
| | | final String builder = packageName + |
| | | "_" + |
| | | deviceId + |
| | | "_" + |
| | | time; |
| | | final Uri uri = new Uri.Builder().scheme(SOURCE_SCHEME).authority(BIND_HOST) |
| | | .appendPath(builder).build(); |
| | | return uri.toString(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.qrcode; |
| | | |
| | | import android.graphics.Bitmap; |
| | | import android.text.TextUtils; |
| | | |
| | | import com.google.zxing.BarcodeFormat; |
| | | import com.google.zxing.EncodeHintType; |
| | | import com.google.zxing.MultiFormatWriter; |
| | | import com.google.zxing.WriterException; |
| | | import com.google.zxing.common.BitMatrix; |
| | | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/8. |
| | | * 二维码 |
| | | */ |
| | | public class QRCodeUtils { |
| | | |
| | | |
| | | /** |
| | | * 生成二维码 |
| | | */ |
| | | public static Bitmap createQRCode(String txt, int width, int height, int margin) throws WriterException { |
| | | Bitmap bitmap = Bitmap.createBitmap(width, height, |
| | | Bitmap.Config.ARGB_8888); |
| | | createQRCode(bitmap, txt, width, height, margin); |
| | | return bitmap; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 生成二维码 |
| | | */ |
| | | public static void createQRCode(Bitmap bitmap, String txt, int width, int height, int margin) throws WriterException { |
| | | |
| | | if (TextUtils.isEmpty(txt)) { |
| | | return; |
| | | } |
| | | |
| | | Map<EncodeHintType, Object> hints = new HashMap<>(); |
| | | hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); |
| | | hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); |
| | | if (margin >= 0) { |
| | | hints.put(EncodeHintType.MARGIN, margin); |
| | | } |
| | | |
| | | |
| | | // 生成二维矩阵 |
| | | BitMatrix matrix = new MultiFormatWriter().encode(txt, |
| | | BarcodeFormat.QR_CODE, width, height, hints); |
| | | |
| | | // 二维矩阵转为一维像素数组,也就是一直横着排了 |
| | | int[] pixels = new int[width * height]; |
| | | for (int y = 0; y < height; y++) { |
| | | for (int x = 0; x < width; x++) { |
| | | if (matrix.get(x, y)) { |
| | | pixels[y * width + x] = 0xff000000; |
| | | } else { |
| | | pixels[y * width + x] = 0xffffffff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | bitmap.setPixels(pixels, 0, width, 0, 0, width, height); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.qrcode; |
| | | |
| | | import android.content.Context; |
| | | import android.graphics.Bitmap; |
| | | import android.graphics.Canvas; |
| | | import android.graphics.Color; |
| | | import android.graphics.Paint; |
| | | import android.graphics.PorterDuff; |
| | | import android.util.AttributeSet; |
| | | import android.view.View; |
| | | |
| | | import androidx.annotation.Nullable; |
| | | import androidx.annotation.Px; |
| | | |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/12/2. |
| | | * 二维码View |
| | | */ |
| | | public class QrCodeView extends View { |
| | | |
| | | private static final int DEF_MARGIN = 0; |
| | | |
| | | private int mWidth; |
| | | private int mHeight; |
| | | private String mContent; |
| | | private int mMargin = DEF_MARGIN; |
| | | |
| | | private Bitmap drawBitmap; |
| | | |
| | | private Canvas drawCanvas; |
| | | |
| | | |
| | | private Paint paint; |
| | | |
| | | private final AtomicBoolean isDraw = new AtomicBoolean(false); |
| | | private DrawThread mDrawThread; |
| | | |
| | | public QrCodeView(Context context) { |
| | | this(context, null); |
| | | } |
| | | |
| | | public QrCodeView(Context context, @Nullable AttributeSet attrs) { |
| | | this(context, attrs, 0); |
| | | } |
| | | |
| | | public QrCodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { |
| | | super(context, attrs, defStyleAttr); |
| | | init(); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onDraw(Canvas canvas) { |
| | | super.onDraw(canvas); |
| | | if (drawBitmap != null) { |
| | | canvas.drawBitmap(drawBitmap, getPaddingLeft(), getPaddingTop(), paint); |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
| | | super.onSizeChanged(w, h, oldw, oldh); |
| | | mHeight = h - getPaddingTop() - getPaddingBottom(); |
| | | mWidth = w - getPaddingStart() - getPaddingEnd(); |
| | | |
| | | if (drawBitmap == null || (drawBitmap.isRecycled() || drawBitmap.getWidth() != mWidth || drawBitmap.getHeight() != mHeight)) { |
| | | drawBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); |
| | | drawCanvas = new Canvas(drawBitmap); |
| | | startDraw(); |
| | | } |
| | | } |
| | | |
| | | |
| | | public void setContent(String content) { |
| | | setContent(content, DEF_MARGIN); |
| | | } |
| | | |
| | | public void setContent(String content, @Px int margin) { |
| | | this.mContent = content; |
| | | startDraw(); |
| | | this.mMargin = margin; |
| | | } |
| | | |
| | | public String getContent() { |
| | | return mContent; |
| | | } |
| | | |
| | | public void startDraw() { |
| | | if (mContent == null || isDraw.get()) return; |
| | | isDraw.set(true); |
| | | mDrawThread = new DrawThread(); |
| | | mDrawThread.start(); |
| | | } |
| | | |
| | | private void init() { |
| | | paint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| | | } |
| | | |
| | | |
| | | private class DrawThread extends Thread { |
| | | @Override |
| | | public void run() { |
| | | while (isDraw.get()) |
| | | try { |
| | | if (drawCanvas != null) { |
| | | |
| | | drawCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); |
| | | int size = Math.min(mHeight, mWidth); |
| | | QRCodeUtils.createQRCode(drawBitmap, mContent, size, size, mMargin); |
| | | postInvalidate(); |
| | | isDraw.set(false); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | if (isDraw.get()) { |
| | | try { |
| | | Thread.sleep(200L); |
| | | } catch (Exception ignore) { |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onDetachedFromWindow() { |
| | | super.onDetachedFromWindow(); |
| | | if (drawBitmap != null) { |
| | | drawBitmap.recycle(); |
| | | } |
| | | isDraw.set(false); |
| | | if (mDrawThread != null) { |
| | | mDrawThread.interrupt(); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.utils; |
| | | |
| | | import static android.content.Context.WIFI_SERVICE; |
| | | |
| | | import android.annotation.SuppressLint; |
| | | import android.content.ContentResolver; |
| | | import android.content.Context; |
| | | import android.content.pm.PackageInfo; |
| | | import android.content.pm.PackageManager; |
| | | import android.net.wifi.WifiInfo; |
| | | import android.net.wifi.WifiManager; |
| | | import android.os.Build; |
| | | import android.provider.Settings; |
| | | import android.text.TextUtils; |
| | | |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.sourceos.OsManager; |
| | | import com.hdl.sdk.sourceos.Rk3566Manager; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.net.InetAddress; |
| | | import java.net.NetworkInterface; |
| | | import java.net.SocketException; |
| | | import java.util.Enumeration; |
| | | import java.util.UUID; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/11/8. |
| | | * ACCESS_WIFI_STATE |
| | | */ |
| | | public class DeviceUtils { |
| | | |
| | | public static final String ANDROID_DEVICE_ID_KEY = "android_device_id_key"; |
| | | |
| | | /** |
| | | * @return 获取设备ID,Android10 只能用uuid生成了 |
| | | */ |
| | | public static String getUniqueDeviceId() { |
| | | String deviceId = SPUtils.getString(ANDROID_DEVICE_ID_KEY); |
| | | if (!TextUtils.isEmpty(deviceId)) { |
| | | return deviceId; |
| | | } |
| | | deviceId = getDeviceId(); |
| | | SPUtils.put(ANDROID_DEVICE_ID_KEY, deviceId); |
| | | return deviceId; |
| | | } |
| | | |
| | | private static String getDeviceId() { |
| | | String deviceId; |
| | | try { |
| | | |
| | | deviceId = getOsMacAddress(); |
| | | if (!TextUtils.isEmpty(deviceId)) { |
| | | return deviceId; |
| | | } |
| | | |
| | | deviceId = getMacAddress(); |
| | | if (!TextUtils.isEmpty(deviceId)) { |
| | | return deviceId; |
| | | } |
| | | |
| | | /*deviceId = getIMEI(); |
| | | if (!TextUtils.isEmpty(deviceId)) { |
| | | return deviceId; |
| | | }*/ |
| | | |
| | | deviceId = getAndroidId(); |
| | | if (!TextUtils.isEmpty(deviceId)) { |
| | | return deviceId; |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | |
| | | deviceId = getUUid("", ""); |
| | | return deviceId; |
| | | } |
| | | |
| | | /** |
| | | * 需要系统权限 |
| | | * READ_PRIVILEGED_PHONE_STATE |
| | | */ |
| | | /*private static String getIMEI(Context context) { |
| | | try { |
| | | TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE); |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
| | | return tm.getImei(); |
| | | } else { |
| | | return tm.getDeviceId(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | }*/ |
| | | private static String getAndroidId() { |
| | | try { |
| | | ContentResolver contentResolver = Rk3566Manager.getInstance().getContext().getApplicationContext().getContentResolver(); |
| | | return Settings.System.getString(contentResolver, Settings.Secure.ANDROID_ID); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | public static String getUUid(String prefix, String id) { |
| | | if (id.equals("")) { |
| | | return prefix + UUID.randomUUID().toString().replace("-", ""); |
| | | } |
| | | return prefix + UUID.nameUUIDFromBytes(id.getBytes()).toString().replace("-", ""); |
| | | } |
| | | |
| | | public static InetAddress getInetAddress() { |
| | | try { |
| | | Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); |
| | | while (nis.hasMoreElements()) { |
| | | NetworkInterface ni = nis.nextElement(); |
| | | // To prevent phone of xiaomi return "10.0.2.15" |
| | | if (!ni.isUp()) continue; |
| | | Enumeration<InetAddress> addresses = ni.getInetAddresses(); |
| | | while (addresses.hasMoreElements()) { |
| | | InetAddress inetAddress = addresses.nextElement(); |
| | | if (!inetAddress.isLoopbackAddress()) { |
| | | String hostAddress = inetAddress.getHostAddress(); |
| | | if (hostAddress.indexOf(':') < 0) return inetAddress; |
| | | } |
| | | } |
| | | } |
| | | } catch (SocketException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | public static String getMacAddressByWifiInfo() { |
| | | try { |
| | | final WifiManager wifi = (WifiManager) Rk3566Manager.getInstance().getContext().getApplicationContext() |
| | | .getSystemService(WIFI_SERVICE); |
| | | if (wifi != null) { |
| | | final WifiInfo info = wifi.getConnectionInfo(); |
| | | if (info != null) { |
| | | @SuppressLint({"HardwareIds", "MissingPermission"}) |
| | | String macAddress = info.getMacAddress(); |
| | | if (!TextUtils.isEmpty(macAddress)) { |
| | | return macAddress; |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return "02:00:00:00:00:00"; |
| | | } |
| | | |
| | | /** |
| | | * 从有线网卡获取mac |
| | | * |
| | | * @return 有线网关mac |
| | | */ |
| | | private static String getMacAddressByEthInterface() { |
| | | try { |
| | | Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); |
| | | while (nis.hasMoreElements()) { |
| | | NetworkInterface ni = nis.nextElement(); |
| | | if (ni == null || !ni.getName().equalsIgnoreCase("eth0")) continue; |
| | | byte[] macBytes = ni.getHardwareAddress(); |
| | | if (macBytes != null && macBytes.length > 0) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (byte b : macBytes) { |
| | | sb.append(String.format("%02x:", b)); |
| | | } |
| | | return sb.substring(0, sb.length() - 1); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return "02:00:00:00:00:00"; |
| | | } |
| | | |
| | | |
| | | public static String getMacAddressByNetworkInterface() { |
| | | try { |
| | | Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); |
| | | while (nis.hasMoreElements()) { |
| | | NetworkInterface ni = nis.nextElement(); |
| | | if (ni == null || !ni.getName().equalsIgnoreCase("wlan0")) continue; |
| | | byte[] macBytes = ni.getHardwareAddress(); |
| | | if (macBytes != null && macBytes.length > 0) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (byte b : macBytes) { |
| | | sb.append(String.format("%02x:", b)); |
| | | } |
| | | return sb.substring(0, sb.length() - 1); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return "02:00:00:00:00:00"; |
| | | } |
| | | |
| | | private static String getMacAddressByInetAddress() { |
| | | try { |
| | | InetAddress inetAddress = getInetAddress(); |
| | | if (inetAddress != null) { |
| | | NetworkInterface ni = NetworkInterface.getByInetAddress(inetAddress); |
| | | if (ni != null) { |
| | | byte[] macBytes = ni.getHardwareAddress(); |
| | | if (macBytes != null && macBytes.length > 0) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (byte b : macBytes) { |
| | | sb.append(String.format("%02x:", b)); |
| | | } |
| | | return sb.substring(0, sb.length() - 1); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return "02:00:00:00:00:00"; |
| | | } |
| | | |
| | | |
| | | private static boolean isAddressNotInExcepts(final String address, final String... excepts) { |
| | | if (TextUtils.isEmpty(address)) { |
| | | return false; |
| | | } |
| | | if ("02:00:00:00:00:00".equals(address)) { |
| | | return false; |
| | | } |
| | | if (excepts == null || excepts.length == 0) { |
| | | return true; |
| | | } |
| | | for (String filter : excepts) { |
| | | if (filter != null && filter.equals(address)) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public static String getMacAddress(final String... excepts) { |
| | | |
| | | String macAddress = getMacAddressByEthInterface(); |
| | | if (isAddressNotInExcepts(macAddress, excepts)) { |
| | | return macAddress; |
| | | } |
| | | |
| | | macAddress = getMacAddressByNetworkInterface(); |
| | | if (isAddressNotInExcepts(macAddress, excepts)) { |
| | | return macAddress; |
| | | } |
| | | macAddress = getMacAddressByInetAddress(); |
| | | if (isAddressNotInExcepts(macAddress, excepts)) { |
| | | return macAddress; |
| | | } |
| | | macAddress = getMacAddressByWifiInfo(); |
| | | if (isAddressNotInExcepts(macAddress, excepts)) { |
| | | return macAddress; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 获取设备的固件系统版本 |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getBuilderNumberDisplay() { |
| | | return Build.DISPLAY; |
| | | } |
| | | |
| | | /** |
| | | * 设备名 |
| | | **/ |
| | | public static String getDeviceName() { |
| | | return Build.DEVICE; |
| | | } |
| | | |
| | | /** |
| | | * 获取手机Android 版本 |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getDeviceAndroidVersion() { |
| | | return Build.VERSION.RELEASE; |
| | | } |
| | | |
| | | // /** |
| | | // * 获取设备序列号 |
| | | // * |
| | | // * @return the serial of device |
| | | // */ |
| | | // @SuppressLint("HardwareIds") |
| | | // public static String getDeviceSerial() { |
| | | // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { |
| | | // try { |
| | | // return Build.getSerial(); |
| | | // } catch (SecurityException e) { |
| | | // e.printStackTrace(); |
| | | // return ""; |
| | | // } |
| | | // } |
| | | // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? Build.getSerial() : Build.SERIAL; |
| | | // } |
| | | |
| | | /** |
| | | * 获取手机序列号 |
| | | * |
| | | * @return 手机序列号 |
| | | */ |
| | | @SuppressLint({"NewApi", "MissingPermission"}) |
| | | public static String getSerialNumber() { |
| | | String serial = ""; |
| | | try { |
| | | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+ |
| | | serial = Build.getSerial(); |
| | | } else {//8.0- |
| | | Class<?> c = Class.forName("android.os.SystemProperties"); |
| | | Method get = c.getMethod("get", String.class); |
| | | serial = (String) get.invoke(c, "ro.serialno"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return serial; |
| | | } |
| | | |
| | | /** |
| | | * 获取APP版本 |
| | | * |
| | | * @param context |
| | | * @return |
| | | */ |
| | | public static String getAppVersionName(Context context) { |
| | | String versionName = "0"; |
| | | try { |
| | | PackageManager packageManager = context.getPackageManager(); |
| | | PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); |
| | | versionName = packageInfo.versionName; |
| | | if (TextUtils.isEmpty(versionName)) { |
| | | versionName = "0"; |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return versionName; |
| | | } |
| | | |
| | | /** |
| | | * 从系统api中获取mac |
| | | * |
| | | * @return |
| | | */ |
| | | private static String getOsMacAddress() { |
| | | String macAddress = OsManager.getEthMacAddress(); |
| | | if (isAddressNotInExcepts(macAddress)) { |
| | | return macAddress; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取唯一码 |
| | | */ |
| | | public static String getUniqueCode() { |
| | | return getUniqueDeviceId().replaceAll(":", ""); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.utils; |
| | | |
| | | /** |
| | | * Created by panlili on 2025/3/4 |
| | | * description: |
| | | */ |
| | | public class SPKey { |
| | | |
| | | // 绑定码 source://bind/包名_序列号_时间戳 |
| | | public static final String BIND_CODE = "bind_qr_code_info"; |
| | | |
| | | public static final String BASE_URL = "base_url"; |
| | | public static final String TOKEN = "cloud_storage_token"; |
| | | |
| | | public static final String REFRESH_TOKEN = "cloud_storage_refresh_token"; |
| | | |
| | | public static final String BIND_HOME_INFO = "bind_home_info"; |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.utils.thread; |
| | | |
| | | import android.os.Build; |
| | | import android.os.Handler; |
| | | import android.os.Looper; |
| | | import android.os.Message; |
| | | import android.os.MessageQueue; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.LinkedList; |
| | | import java.util.concurrent.Executor; |
| | | |
| | | |
| | | /** |
| | | * Created by Tong on 2023/01/03. |
| | | */ |
| | | public class MainThreadExecutor implements Executor { |
| | | |
| | | private final LinkedList<Runnable> mQueue = new LinkedList<>(); |
| | | |
| | | private final IdleHandlerImpl mHandler = new IdleHandlerImpl(Looper.getMainLooper()); |
| | | |
| | | private final Handler mainHandler = new Handler(Looper.getMainLooper()); |
| | | |
| | | private MessageQueue mMessageQueue; |
| | | |
| | | private MainThreadExecutor() { |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| | | mMessageQueue = Looper.getMainLooper().getQueue(); |
| | | } else { |
| | | try { |
| | | Method getQueue = Looper.class.getDeclaredMethod("getQueue"); |
| | | mMessageQueue = (MessageQueue) getQueue.invoke(Looper.getMainLooper()); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private static class SingletonInstance { |
| | | private static final MainThreadExecutor INSTANCE = new MainThreadExecutor(); |
| | | } |
| | | |
| | | public static MainThreadExecutor getInstance() { |
| | | return SingletonInstance.INSTANCE; |
| | | } |
| | | |
| | | |
| | | private class IdleHandlerImpl extends Handler implements MessageQueue.IdleHandler { |
| | | |
| | | public IdleHandlerImpl(@NonNull Looper looper) { |
| | | super(looper); |
| | | } |
| | | |
| | | @Override |
| | | public void handleMessage(Message msg) { |
| | | Runnable r; |
| | | synchronized (mQueue) { |
| | | if (mQueue.size() == 0) { |
| | | return; |
| | | } |
| | | r = mQueue.removeFirst(); |
| | | } |
| | | r.run(); |
| | | synchronized (mQueue) { |
| | | scheduleNextLocked(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public boolean queueIdle() { |
| | | handleMessage(null); |
| | | //ture执行多次,false执行一次 |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private static class IdleRunnable implements Runnable { |
| | | Runnable mRunnable; |
| | | |
| | | IdleRunnable(Runnable r) { |
| | | mRunnable = r; |
| | | } |
| | | |
| | | public void run() { |
| | | mRunnable.run(); |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void execute(Runnable command) { |
| | | if (Looper.getMainLooper() == Looper.myLooper()) { |
| | | command.run(); |
| | | } else { |
| | | mainHandler.post(command); |
| | | } |
| | | } |
| | | |
| | | |
| | | public void post(Runnable runnable) { |
| | | synchronized (mQueue) { |
| | | mQueue.add(runnable); |
| | | if (mQueue.size() == 1) { |
| | | scheduleNextLocked(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void postIdle(final Runnable runnable) { |
| | | post(new IdleRunnable(runnable)); |
| | | } |
| | | |
| | | public void postIdle(final Runnable runnable, long delayMillis) { |
| | | mHandler.postDelayed(runnable, delayMillis); |
| | | } |
| | | |
| | | public void cancelAll() { |
| | | synchronized (mQueue) { |
| | | mQueue.clear(); |
| | | } |
| | | } |
| | | |
| | | public void flush() { |
| | | LinkedList<Runnable> queue; |
| | | synchronized (mQueue) { |
| | | queue = new LinkedList<>(mQueue); |
| | | mQueue.clear(); |
| | | } |
| | | for (Runnable r : queue) { |
| | | r.run(); |
| | | } |
| | | } |
| | | |
| | | private void scheduleNextLocked() { |
| | | if (mQueue.size() > 0) { |
| | | Runnable peek = mQueue.getFirst(); |
| | | if (peek instanceof IdleRunnable) { |
| | | if (mMessageQueue != null) { |
| | | mMessageQueue.addIdleHandler(mHandler); |
| | | } |
| | | |
| | | } else { |
| | | mHandler.sendEmptyMessage(1); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.hdl.sdk.sourceos.utils.thread; |
| | | |
| | | import java.util.concurrent.ThreadFactory; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | | /** |
| | | * Created by Tong on 2023/05/09. |
| | | */ |
| | | public abstract class RenameThreadFactory implements ThreadFactory { |
| | | |
| | | private static final AtomicInteger poolNumber = new AtomicInteger(1); |
| | | private final ThreadGroup group; |
| | | private final AtomicInteger threadNumber = new AtomicInteger(1); |
| | | |
| | | public abstract String getName(int poolNumber, int threadNumber); |
| | | |
| | | private Thread.UncaughtExceptionHandler exceptionHandler; |
| | | |
| | | public RenameThreadFactory() { |
| | | SecurityManager s = System.getSecurityManager(); |
| | | this.group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); |
| | | } |
| | | |
| | | |
| | | public RenameThreadFactory(Thread.UncaughtExceptionHandler exceptionHandler) { |
| | | this.exceptionHandler = exceptionHandler; |
| | | SecurityManager s = System.getSecurityManager(); |
| | | this.group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); |
| | | } |
| | | |
| | | public Thread newThread(Runnable r) { |
| | | Thread t = new Thread(this.group, r, this.getName(poolNumber.getAndIncrement(), this.threadNumber.getAndIncrement()), 0L); |
| | | if (t.isDaemon()) { |
| | | t.setDaemon(false); |
| | | } |
| | | |
| | | if (t.getPriority() != Thread.NORM_PRIORITY) { |
| | | t.setPriority(Thread.NORM_PRIORITY); |
| | | } |
| | | if (exceptionHandler != null) { |
| | | t.setUncaughtExceptionHandler(exceptionHandler); |
| | | } |
| | | |
| | | |
| | | return t; |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package com.hdl.sdk.sourceos.utils.thread; |
| | | |
| | | import android.os.Handler; |
| | | import android.os.Looper; |
| | | import android.util.ArrayMap; |
| | | |
| | | import java.util.Timer; |
| | | import java.util.TimerTask; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.LinkedBlockingQueue; |
| | | import java.util.concurrent.RejectedExecutionHandler; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | |
| | | /** |
| | | * Created by Tong on 2021/10/21. |
| | | */ |
| | | public class ThreadUtils { |
| | | |
| | | private static final Handler uiHandler = new Handler(Looper.getMainLooper()); |
| | | |
| | | private static final ArrayMap<Integer, ExecutorService> mThreadPools = new ArrayMap<>(); |
| | | |
| | | //后台处理线程池 |
| | | private static final int IO_TYPE = 0; |
| | | |
| | | //分发线程池 |
| | | private static final int DISPENSE_TYPE = 1; |
| | | |
| | | private static final Timer TIMER = new Timer(); |
| | | |
| | | //cpu 最大线程容纳量 |
| | | private static final int coreSize = Runtime.getRuntime().availableProcessors() + 1; |
| | | private static final int maxCoreSize = 2 * Runtime.getRuntime().availableProcessors() + 1; |
| | | |
| | | |
| | | private volatile static ThreadUtils INSTANCE = null; |
| | | |
| | | private ThreadUtils() { |
| | | } |
| | | |
| | | public static ThreadUtils getInstance() { |
| | | if (INSTANCE == null) { |
| | | synchronized (ThreadUtils.class) { |
| | | if (INSTANCE == null) { |
| | | INSTANCE = new ThreadUtils(); |
| | | } |
| | | } |
| | | } |
| | | return INSTANCE; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @return 单线程,无限长度队列,会在调用线程执行,频繁用到这个线程说明并发超级多 |
| | | */ |
| | | private ExecutorService getSingleThread() { |
| | | if (!mThreadPools.isEmpty() && mThreadPools.containsKey(DISPENSE_TYPE)) { |
| | | ExecutorService thread = mThreadPools.get(DISPENSE_TYPE); |
| | | if (thread != null && !thread.isShutdown()) { |
| | | return thread; |
| | | } |
| | | } |
| | | final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(1, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new RenameThreadFactory() { |
| | | |
| | | @Override |
| | | public String getName(int poolNumber, int threadNumber) { |
| | | return "app_dispense_" + poolNumber + "_" + threadNumber; |
| | | } |
| | | }, new ThreadPoolExecutor.DiscardPolicy()); |
| | | |
| | | poolExecutor.allowCoreThreadTimeOut(true); |
| | | |
| | | mThreadPools.put(DISPENSE_TYPE, poolExecutor); |
| | | return poolExecutor; |
| | | } |
| | | |
| | | /** |
| | | * 维护 cpu 最大线程容纳量+队列1024 用完在单线程调用 |
| | | */ |
| | | private ExecutorService getIOThread() { |
| | | if (!mThreadPools.isEmpty() && mThreadPools.containsKey(IO_TYPE)) { |
| | | ExecutorService thread = mThreadPools.get(IO_TYPE); |
| | | if (thread != null && !thread.isShutdown()) { |
| | | return thread; |
| | | } |
| | | } |
| | | final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(coreSize, coreSize, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024), new RenameThreadFactory() { |
| | | @Override |
| | | public String getName(int poolNumber, int threadNumber) { |
| | | return "app_io_" + poolNumber + "_" + threadNumber; |
| | | } |
| | | //满了,就使用备份线程池,会oom,使用task会捕抓异常 |
| | | }, new BackgroundRunsPolicy()); |
| | | |
| | | poolExecutor.allowCoreThreadTimeOut(true); |
| | | |
| | | mThreadPools.put(IO_TYPE, poolExecutor); |
| | | return poolExecutor; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 线程数量固定的线程池 |
| | | */ |
| | | public static ExecutorService newFixedThreadPool(int size) { |
| | | if (size == 0 || coreSize < size) { |
| | | return Executors.newFixedThreadPool(coreSize); |
| | | } |
| | | return Executors.newFixedThreadPool(size); |
| | | } |
| | | |
| | | /** |
| | | * 定时任务线程池 |
| | | */ |
| | | public static ScheduledExecutorService newScheduledThreadPool(int size) { |
| | | if (size == 0 || coreSize < size) { |
| | | return Executors.newScheduledThreadPool(coreSize); |
| | | } |
| | | return Executors.newScheduledThreadPool(size); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 切换回主线程 |
| | | */ |
| | | public static void runOnUiThread(Runnable run) { |
| | | if (Looper.getMainLooper() == Looper.myLooper()) { |
| | | try { |
| | | run.run(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } else { |
| | | try { |
| | | uiHandler.post(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | run.run(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 延时更新Ui |
| | | */ |
| | | public static void runOnUiThreadDelay(Runnable run, long delayMillis) { |
| | | uiHandler.postDelayed(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | run.run(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }, delayMillis); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 后台耗时任务 |
| | | */ |
| | | public static void runAsyncThread(Runnable run) { |
| | | try { |
| | | getInstance().getIOThread().execute(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | run.run(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 删除后台任务 |
| | | */ |
| | | public static void removeTask(Task task) { |
| | | if (task == null) { |
| | | return; |
| | | } |
| | | try { |
| | | task.cancel(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 有休眠 |
| | | * 后台耗时延迟任务 |
| | | */ |
| | | public static void runAsyncThread(Runnable run, long time) { |
| | | try { |
| | | final TimerTask timerTask = new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | ExecutorService thread = getInstance().getIOThread(); |
| | | if (!thread.isShutdown()) { |
| | | thread.execute(run); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | }; |
| | | TIMER.schedule(timerTask, time); |
| | | } catch (Throwable e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | } |
| | | |
| | | public abstract static class Task implements ITask { |
| | | |
| | | private Thread thread; |
| | | |
| | | public abstract void doInBackground(); |
| | | |
| | | private final AtomicBoolean isCancel = new AtomicBoolean(); |
| | | |
| | | public Task() { |
| | | isCancel.set(false); |
| | | } |
| | | |
| | | @Override |
| | | public void run() { |
| | | thread = Thread.currentThread(); |
| | | try { |
| | | if (!isCancel.get()) { |
| | | doInBackground(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | onError(e); |
| | | } |
| | | thread = null; |
| | | } |
| | | |
| | | public void cancel() { |
| | | try { |
| | | isCancel.set(true); |
| | | if (thread != null) { |
| | | thread.interrupt(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onError(Throwable t) { |
| | | t.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | |
| | | public interface ITask extends Runnable { |
| | | void onError(Throwable t); |
| | | } |
| | | |
| | | |
| | | public static class BackgroundRunsPolicy implements RejectedExecutionHandler { |
| | | |
| | | public BackgroundRunsPolicy() { |
| | | } |
| | | |
| | | public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { |
| | | if (!e.isShutdown()) { |
| | | try { |
| | | backgroundRun(r); |
| | | } catch (Exception e1) { |
| | | if (r instanceof ITask) { |
| | | ((ITask) r).onError(e1); |
| | | } else { |
| | | throw e1; |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void backgroundRun(Runnable runnable) { |
| | | getInstance().getSingleThread().execute(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | runnable.run(); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6' |
| | | // implementation 'com.google.code.gson:gson:2.8.8' |
| | | implementation files('libs\\com.hdl.sdk-v1.2.0.aar') |
| | | implementation files('libs\\com.hdl.sdk-v1.2.1.aar') |
| | | |
| | | //二维码 |
| | | implementation 'com.google.zxing:core:3.4.1' |
| | | //事件总线 |
| | | implementation 'org.greenrobot:eventbus:3.2.0' |
| | | } |
| | |
| | | android:exported="false"
|
| | | android:windowSoftInputMode="adjustPan|stateHidden" />
|
| | |
|
| | | <activity
|
| | | android:name=".SourceBindActivity"
|
| | | android:exported="false"
|
| | | android:windowSoftInputMode="adjustPan|stateHidden" />
|
| | |
|
| | | </application>
|
| | |
|
| | | </manifest> |
| | |
| | | package com.hdl.hdlsdk;
|
| | |
|
| | | import android.app.Application;
|
| | | import android.util.Log;
|
| | |
|
| | | import com.hdl.sdk.common.HDLSdk;
|
| | | import com.hdl.sdk.common.event.EventListener;
|
| | | import com.hdl.sdk.common.utils.LogUtils;
|
| | | import com.hdl.sdk.connect.HDLLink;
|
| | | import com.hdl.sdk.connect.bean.LinkResponse;
|
| | | import com.hdl.sdk.connect.cloud.broadcast.GlobalBroadcastManager;
|
| | | import com.hdl.sdk.sourceos.OsManager;
|
| | |
|
| | | /**
|
| | | * Created by Tong on 2021/10/8.
|
| | |
| | | public class App extends Application {
|
| | |
|
| | | private String deviceStatusUpdateTopic;
|
| | |
|
| | | @Override
|
| | | public void onCreate() {
|
| | | super.onCreate();
|
| | |
| | | //控制SDK日志打印
|
| | | HDLSdk.getInstance().setLogEnabled(true);
|
| | |
|
| | | //source系统接口初始化
|
| | | OsManager.init(this);
|
| | |
|
| | | //appkey:ryfElI3tVOT
|
| | | //appsecret:AKIn7s1A2YnNvAZRtL8FQxzp0R2KUpIY
|
| | | HDLLink.getInstance().initCloud(this, "ryfElI3tVOT", "AKIn7s1A2YnNvAZRtL8FQxzp0R2KUpIY");
|
| | |
|
| | | //注册全局广播,刷新token
|
| | | GlobalBroadcastManager.registerGlobalBroadcast(this);
|
| | | }
|
| | |
|
| | | @Override
|
| | |
| | | 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.SPUtils; |
| | | 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.request.ListSidRequest; |
| | | import com.hdl.sdk.connect.bean.request.ListUploadRequest; |
| | | import com.hdl.sdk.connect.bean.response.BaseLocalResponse; |
| | | import com.hdl.sdk.connect.bean.response.BindInfoBean; |
| | | import com.hdl.sdk.connect.bean.response.GatewaySearchBean; |
| | | import com.hdl.sdk.connect.bean.response.UpdateInfo; |
| | | import com.hdl.sdk.connect.callback.HDLLinkCallBack; |
| | |
| | | import com.hdl.sdk.connect.cloud.CallBackListener; |
| | | import com.hdl.sdk.connect.cloud.CheckAppVersionListener; |
| | | import com.hdl.sdk.connect.cloud.HDLException; |
| | | import com.hdl.sdk.connect.cloud.bean.GatewayInfo; |
| | | import com.hdl.sdk.connect.cloud.listener.GatewayListener; |
| | | import com.hdl.sdk.connect.cloud.listener.SibichiListener; |
| | | import com.hdl.sdk.connect.cloud.bean.AiLoginInfo; |
| | | import com.hdl.sdk.connect.config.HDLLinkConfig; |
| | | import com.hdl.sdk.connect.socket.HDLAuthSocket; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.security.MessageDigest; |
| | |
| | | private List<SceneBean> sceneList = new ArrayList<>(); |
| | | private List<SceneDetailBean> sceneDetailList = new ArrayList<>(); |
| | | private List<SceneDetailBean> roomSceneList = new ArrayList<>(); |
| | | private GatewayInfo gatewayInfo; |
| | | |
| | | 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(); |
| | |
| | | Toast.makeText(this, "mac不能为空!", Toast.LENGTH_SHORT).show(); |
| | | return; |
| | | } |
| | | |
| | | HDLLink.getInstance().applyDeviceSecret(this, appKey, appSecret, supplier, mac, spk, new CallBackListener() { |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().applyDeviceSecret(supplier, mac, spk, new CallBackListener() { |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("申请失败"); |
| | |
| | | tv.setText("开始检测更新..."); |
| | | responseTv.setText(""); |
| | | |
| | | // //正式服务器 |
| | | String appKey = "i8hR07jzrIS";//appkey |
| | | String appSecret = "BmnJ8RWTtaVEBk24zPPF4UMwfYu0lAWU";//appsecret |
| | | |
| | | String appCode = "1697150870315999233";//appCode |
| | | |
| | | HDLLink.getInstance().checkAppVersion(this, appKey, appSecret, getAppVersionName(this), appCode, new CheckAppVersionListener() { |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().checkAppVersion(getAppVersionName(this), appCode, new CheckAppVersionListener() { |
| | | @Override |
| | | public void onSuccess(UpdateInfo info) { |
| | | tv.setText("有新更新"); |
| | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("检测更新失败"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | void getSibichiToken() { |
| | | tv.setText("获取思必驰token..."); |
| | | responseTv.setText(""); |
| | | |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | String clientId = "4ED634B5A7AD97A770A52AC00FF43805";//思必驰clientId |
| | | |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().getSibichiToken(bindInfoBean.getHomeId(), clientId, new SibichiListener() { |
| | | @Override |
| | | public void onSuccess(AiLoginInfo info) { |
| | | tv.setText("思必驰token"); |
| | | responseTv.setText(info.toString()); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("获取思必驰token失败"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | void syncMainGateway() { |
| | | tv.setText("获取主网关信息..."); |
| | | responseTv.setText(""); |
| | | |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | if (bindInfoBean == null) { |
| | | Toast.makeText(this, "请先扫码绑定住宅!", Toast.LENGTH_SHORT).show(); |
| | | return; |
| | | } |
| | | //调用云端接口需初始化HDLLink.getInstance().initCloud(); |
| | | HDLLink.getInstance().syncMainGateway(bindInfoBean.getHomeId(), new GatewayListener() { |
| | | @Override |
| | | public void onSuccess(GatewayInfo info) { |
| | | tv.setText("获取主网关信息"); |
| | | responseTv.setText(info.toString()); |
| | | if (info != null) { |
| | | HDLLinkConfig.getInstance().setGatewayId(info.getGatewayId()); |
| | | //HDLLinkConfig.getInstance().setIpAddress(info.ip); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLException e) { |
| | | tv.setText("获取主网关信息失败"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | |
| | | |
| | | selectnetwork(); |
| | | checkIfCertified(); |
| | | initDeviceInfo();//初始化 |
| | | //initDeviceInfo();//不走从机入网的方式不需要初始化 |
| | | registerAllTopicsListener(); |
| | | HDLLink.getInstance().setDeleteNetworkListener(new DeleteNetworkListener() { |
| | | @Override |
| | |
| | | beans.add(new DemoBean("获取房间场景列表")); |
| | | beans.add(new DemoBean("获取自动化列表")); |
| | | beans.add(new DemoBean("⾃动化启⽤禁⽤")); |
| | | beans.add(new DemoBean("生成二维码绑定住宅")); |
| | | beans.add(new DemoBean("获取思必驰token")); |
| | | beans.add(new DemoBean("获取网关信息")); |
| | | demoAdapter = new DemoAdapter(beans); |
| | | rv.setAdapter(demoAdapter); |
| | | |
| | |
| | | case 19: |
| | | //⾃动化启⽤禁⽤ |
| | | editEnableLogic(); |
| | | break; |
| | | case 20: |
| | | //生成二维码绑定住宅 |
| | | startSourceBindActivity(); |
| | | break; |
| | | case 21: |
| | | //获取思必驰token |
| | | getSibichiToken(); |
| | | break; |
| | | case 22: |
| | | //获取网关信息 |
| | | syncMainGateway(); |
| | | break; |
| | | } |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | void initLink() { |
| | | //step1:先生成二维码,用onpro扫码绑定住宅获取住宅信息 |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | if (bindInfoBean != null) { |
| | | HDLLinkConfig.getInstance().setHomeId(bindInfoBean.getHomeId()); |
| | | HDLLinkConfig.getInstance().setLocalSecret(bindInfoBean.getLocalSecret()); |
| | | |
| | | } |
| | | //step2:再获取网关信息 |
| | | if (gatewayInfo != null) { |
| | | HDLLinkConfig.getInstance().setGatewayId(gatewayInfo.getGatewayId());//当前主网关id |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 入网认证 |
| | | */ |
| | |
| | | tv.setText("开始入网认证..."); |
| | | //认证提交参数准备 |
| | | |
| | | // 测试服务 |
| | | // String spkStr = "ir.module";//产品spk |
| | | // String macStr = "AA000000000000AF";//设备唯一MAC地址 |
| | | // String secret = "44b360eb74b7ba64";//通过spk和mac提交云端认证后分配的secret |
| | | |
| | | // 正式服务器 |
| | | //正式服务器 |
| | | String spkStr = "screen.mirror";//产品spk |
| | | String macStr = "f2c5d8bad48f";//设备唯一MAC地址 |
| | | // String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret |
| | | |
| | | String mac_key = stringToMD5(stringToMD5(macStr + secret)); |
| | | String versionString = "HDL_V1.0.1";// |
| | |
| | | tv.setText("设备功能属性读取"); |
| | | responseTv.setText(""); |
| | | List<String> sids = new ArrayList<>(); |
| | | sids.add(testLightSid); |
| | | if (devicesList.size() != 0) { |
| | | sids.add(devicesList.get(0).getSid()); |
| | | } else { |
| | | sids.add(testLightSid); |
| | | } |
| | | |
| | | HDLLink.getInstance().getFunctionAttribute(sids, new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String msg) { |
| | |
| | | tv.setText("读取状态中..."); |
| | | responseTv.setText(""); |
| | | List<String> list = new ArrayList<>(); |
| | | list.add(testLightSid);//要读取设备的sid |
| | | if (devicesList.size() != 0) { |
| | | list.add(devicesList.get(0).getSid()); |
| | | } else { |
| | | list.add(testLightSid);//要读取设备的sid |
| | | } |
| | | HDLLink.getInstance().propertyRead(list, new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String data) { |
| | |
| | | isOn = !isOn; |
| | | List<DeviceControlRequest> requestList = new ArrayList<>(); |
| | | DeviceControlRequest request = new DeviceControlRequest(); |
| | | request.setSid(testLightSid); |
| | | if (devicesList.size() != 0) { |
| | | request.setSid(devicesList.get(0).getSid()); |
| | | } else { |
| | | request.setSid(testLightSid);//要读取设备的sid |
| | | } |
| | | List<DeviceControlRequest.StatusBean> statusBeanList = new ArrayList<>(); |
| | | DeviceControlRequest.StatusBean bean = new DeviceControlRequest.StatusBean(); |
| | | bean.setKey("on_off"); |
| | |
| | | startActivity(intent); |
| | | } |
| | | |
| | | void startSourceBindActivity() { |
| | | Intent intent = new Intent(this, SourceBindActivity.class); |
| | | startActivity(intent); |
| | | } |
| | | |
| | | /** |
| | | * TCP发送 只发一次,不监听回复,不重发 |
| | | */ |
New file |
| | |
| | | package com.hdl.hdlsdk; |
| | | |
| | | import android.annotation.SuppressLint; |
| | | import android.os.Bundle; |
| | | import android.widget.TextView; |
| | | import android.widget.Toast; |
| | | |
| | | import androidx.appcompat.app.AppCompatActivity; |
| | | |
| | | import com.hdl.sdk.common.utils.SPUtils; |
| | | import com.hdl.sdk.connect.bean.response.BindInfoBean; |
| | | import com.hdl.sdk.connect.config.HDLLinkConfig; |
| | | import com.hdl.sdk.sourceos.bind.BaseEvent; |
| | | import com.hdl.sdk.sourceos.bind.BindAuthEvent; |
| | | import com.hdl.sdk.sourceos.bind.BindHomeService; |
| | | import com.hdl.sdk.sourceos.bind.EventType; |
| | | import com.hdl.sdk.sourceos.qrcode.QRCode; |
| | | import com.hdl.sdk.sourceos.qrcode.QrCodeView; |
| | | import com.hdl.sdk.sourceos.utils.SPKey; |
| | | |
| | | import org.greenrobot.eventbus.EventBus; |
| | | import org.greenrobot.eventbus.Subscribe; |
| | | import org.greenrobot.eventbus.ThreadMode; |
| | | |
| | | public class SourceBindActivity extends AppCompatActivity { |
| | | |
| | | private static final String TAG = "SourceBindActivity"; |
| | | private QrCodeView qrcodeView; |
| | | private TextView responseTv; |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | setContentView(R.layout.activity_source_bind); |
| | | registerEventBus(); |
| | | initView(); |
| | | } |
| | | |
| | | @SuppressLint("WrongConstant") |
| | | private void initView() { |
| | | qrcodeView = findViewById(R.id.qrcode_view); |
| | | responseTv = findViewById(R.id.response_tv); |
| | | createBindQRCodeInfo(); |
| | | } |
| | | |
| | | private void createBindQRCodeInfo() { |
| | | final String time = String.valueOf(System.currentTimeMillis()); |
| | | String info = QRCode.createBindQRCodeInfo(time); |
| | | qrcodeView.setContent(info); |
| | | |
| | | //开始轮询 |
| | | BindHomeService.getInstance().startQuery(time); |
| | | } |
| | | |
| | | /** |
| | | * 绑定成功通知事件 |
| | | * |
| | | * @param event |
| | | */ |
| | | @Subscribe(threadMode = ThreadMode.MAIN) |
| | | public void onEventMessage(BaseEvent event) { |
| | | switch (event.getEventType()) { |
| | | case EventType.ON_PLUS_BINDING_TYPE: |
| | | if (event instanceof BindAuthEvent) { |
| | | int action = ((BindAuthEvent) event).getAction(); |
| | | if (action == BindAuthEvent.ON_PLUS_BINDING_SUCCEED_ACTION) { |
| | | //on+绑定成功 |
| | | Toast.makeText(this, "绑定成功", Toast.LENGTH_SHORT).show(); |
| | | BindInfoBean bindInfoBean = (BindInfoBean) SPUtils.getSerializableEntity(SPKey.BIND_HOME_INFO); |
| | | responseTv.setText(bindInfoBean.toString()); |
| | | |
| | | if (bindInfoBean != null) { |
| | | HDLLinkConfig.getInstance().setHomeId(bindInfoBean.getHomeId()); |
| | | HDLLinkConfig.getInstance().setLocalSecret(bindInfoBean.getLocalSecret()); |
| | | } |
| | | } else if (action == BindAuthEvent.ON_PLUS_BINDING_TIMEOUT_ACTION) { |
| | | //on+绑定超时 |
| | | Toast.makeText(this, "绑定超时", Toast.LENGTH_SHORT).show(); |
| | | } else if (action == BindAuthEvent.ON_PLUS_BINDING_ERROR_ACTION) { |
| | | //网络错误 |
| | | //Toast.makeText(this, "网络异常", Toast.LENGTH_SHORT).show(); |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | | protected void unregisterEventBus() { |
| | | if (EventBus.getDefault().isRegistered(this)) { |
| | | EventBus.getDefault().unregister(this); |
| | | } |
| | | } |
| | | |
| | | protected void registerEventBus() { |
| | | if (!EventBus.getDefault().isRegistered(this)) { |
| | | EventBus.getDefault().register(this); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | super.onDestroy(); |
| | | unregisterEventBus(); |
| | | BindHomeService.getInstance().stopQuery(); |
| | | } |
| | | } |
| | |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| | | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REBOOT, Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST); |
| | | } |
| | | //系统接口初始化 |
| | | OsManager.init(SourceTestActivity.this); |
| | | |
| | | OsManager.addEventListener(eventListener); |
| | | |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | xmlns:app="http://schemas.android.com/apk/res-auto" |
| | | xmlns:tools="http://schemas.android.com/tools" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:orientation="vertical" |
| | | tools:context=".SourceBindActivity"> |
| | | |
| | | <com.hdl.sdk.sourceos.qrcode.QrCodeView |
| | | android:id="@+id/qrcode_view" |
| | | android:layout_width="125dp" |
| | | android:layout_height="125dp" |
| | | android:layout_alignParentBottom="true" |
| | | android:layout_centerHorizontal="true" |
| | | android:layout_marginStart="28dp" |
| | | android:layout_marginTop="28dp" |
| | | android:padding="3dp" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/response_tv" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:padding="3dp" |
| | | android:layout_marginTop="28dp" /> |
| | | |
| | | </LinearLayout> |