package com.hdl.hdlsdk; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.Manifest; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.listener.OnItemClickListener; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.hdl.hdlsdk.device.DevicesListActivity; import com.hdl.sdk.common.config.TopicConstant; import com.hdl.sdk.common.event.EventListener; import com.hdl.sdk.common.exception.HDLLinkException; import com.hdl.sdk.common.utils.IdUtils; import com.hdl.sdk.common.utils.IpUtils; import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.common.utils.gson.GsonConvert; import com.hdl.sdk.connect.HDLLink; import com.hdl.sdk.connect.bean.LinkRequest; import com.hdl.sdk.connect.bean.LinkResponse; import com.hdl.sdk.connect.bean.request.AuthenticateRequest; import com.hdl.sdk.connect.bean.request.BroadcastRequest; import com.hdl.sdk.connect.bean.request.PropertyReadRequest; import com.hdl.sdk.connect.bean.response.BaseLocalResponse; import com.hdl.sdk.connect.bean.response.GatewaySearchBean; import com.hdl.sdk.connect.callback.HDLLinkCallBack; import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack; import com.hdl.sdk.connect.config.HDLLinkConfig; import com.hdl.sdk.connect.socket.HDLAuthSocket; import com.hdl.sdk.connect.socket.HDLSocket; import com.hdl.sdk.connect.bean.request.DeviceControlRequest; import com.hdl.sdk.connect.protocol.LinkMessageDecoder; import com.hdl.sdk.connect.protocol.LinkMessageEncoder; import com.hdl.sdk.socket.SocketOptions; import com.hdl.sdk.socket.codec.MessagePipeLine; import java.util.Base64; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.Map; import static com.hdl.sdk.common.config.TopicConstant.GATEWAY_SEARCH_REPLY; import static java.util.Base64.*; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private DemoAdapter demoAdapter; private RecyclerView rv; private TextView tv; private TextView responseTv; boolean isOn; private EventListener allTopicsListener; private String testLightSid = "0001010D48C71B02020100010101"; @Override protected void onDestroy() { super.onDestroy(); removeAllTopicsListener(); } void init() { // HDLLinkConfig.getInstance().setLocalSecret("7d04c4e3c2b7d600"); // HDLLinkConfig.getInstance().setGatewayId("1473119283609321473"); // HDLLinkConfig.getInstance().setLocalEncrypt(true); } @RequiresApi(api = Build.VERSION_CODES.O) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); responseTv = findViewById(R.id.response_tv); tv = findViewById(R.id.state_tv); rv = findViewById(R.id.rv); rv.setLayoutManager(new LinearLayoutManager(this)); init(); checkIfCertified(); initDeviceInfo();//初始化基本信息,非常重要,认证时要用 registerAllTopicsListener(); ActivityResultLauncher launcher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback>() { @Override public void onActivityResult(Map result) { } }); launcher.launch(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}); final List beans = new ArrayList<>(); beans.add(new DemoBean("入网认证")); beans.add(new DemoBean("搜索指定网关是否在线")); beans.add(new DemoBean("获取功能列表")); beans.add(new DemoBean("功能属性读取")); beans.add(new DemoBean("设备控制")); beans.add(new DemoBean("读取状态")); beans.add(new DemoBean("获取场景列表")); beans.add(new DemoBean("场景控制")); beans.add(new DemoBean("设备功能列表")); beans.add(new DemoBean("UDP发送")); beans.add(new DemoBean("TCP发送")); beans.add(new DemoBean("UDP发送,监听主题回复,带重发带回调")); beans.add(new DemoBean("TCP发送,监听主题回复,带重发带回调")); demoAdapter = new DemoAdapter(beans); rv.setAdapter(demoAdapter); // final SocketOptions options = new SocketOptions(); // // MessagePipeLine pipeLine = new MessagePipeLine(); // options.setHandleMessage(pipeLine); // options.setEnabledHeartbeat(false); demoAdapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) { switch (position) { case 0: //入网认证 sendAuthenticateRequest(); break; case 1: //搜索网关 searchGatewayBroadcast(); break; case 2: //获取功能列表 getFunctionList(); break; case 3: //功能属性读取 getFunctionAttribute(); break; case 4: //设备控制 controlDecide(); break; case 5: //读取状态 propertyRead(); break; case 6: //获取场景列表 getSceneList(); break; case 7: //获取场景列表 controlScene(); break; case 8: //功能列表 startDevicesListActivity(); break; case 9: //UDP发送 udpSend(); break; case 10: //TCP发送 tcpSend(); break; case 11: //UDP发送,监听主题回复,带重发带回调 udpSendWithCallback(); break; case 12: //TCP发送,监听主题回复,带重发带回调 tcpSendWithCallback(); break; } } }); } public void showToast(String text) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } /** * 检测是否认证过 */ void checkIfCertified() { boolean isCertified = HDLLink.getInstance().checkIfCertified(); String mes = isCertified ? "已经认证过" : "未认证"; showToast(mes); tv.setText(mes); } /** * 注册所有主题数据的监听 */ void registerAllTopicsListener() { allTopicsListener = new EventListener() { @Override public void onMessage(Object msg) { LinkResponse response = (LinkResponse) msg; handleLinkResponse(response); } }; HDLLink.getInstance().registerAllTopicsListener(allTopicsListener); } /** * 处理收到的主题 * * @param response */ private void handleLinkResponse(LinkResponse response) { //网关搜索回复 if (response.getTopic().contains("/user/all/custom/gateway/search_reply")) { String data = response.getData(); if (!TextUtils.isEmpty(data)) { Log.i("handleLinkResponse", "data:" + data); final BaseLocalResponse bean = GsonConvert.getGson().fromJson(data, new TypeToken>() { }.getType()); GatewaySearchBean searchBean = bean.getObjects(); Log.i("handleLinkResponse", "GatewaySearchBean: " + searchBean.getGatewayId()); } } else { //其它主题 } } private GatewaySearchBean getGatewaySearchBean(Object msg) { GatewaySearchBean searchBean = null; if (msg instanceof LinkResponse) { LinkResponse linkResponse = (LinkResponse) msg; String data = linkResponse.getData(); if (!TextUtils.isEmpty(data)) { final BaseLocalResponse response = GsonConvert.getGson().fromJson(data, new TypeToken>() { }.getType()); searchBean = response.getObjects(); } } return searchBean; } /** * 移除所有主题数据的监听 */ void removeAllTopicsListener() { HDLLink.getInstance().removeAllTopicsListener(allTopicsListener); } void initDeviceInfo() { AuthenticateRequest.AuthenticateDeviceInfoBean infoBean = new AuthenticateRequest.AuthenticateDeviceInfoBean(); infoBean.setDeviceMAC("AA00000000000100"); infoBean.setIPMAC("AA00000000000100"); infoBean.setDeviceName("音乐播放器");//设备名字 infoBean.setDeviceModel("MCLog.431");//设备型号 infoBean.setAccessMode("WIFI"); infoBean.setIPGateway("192.168.1.1"); infoBean.setIPAddress("192.168.1.116"); infoBean.setGateway_type("music.standard"); infoBean.setHw_version("HW2.0"); infoBean.setFw_version("Fw1.0"); infoBean.setOID("010105000000FE11");//每个设备oid都要不一样 infoBean.setSid("110105000000FE08110100000011");//每个设备的sid都要不一样 HDLLinkConfig.getInstance().setDeviceInfoBean(infoBean); } /** * 入网认证 */ void sendAuthenticateRequest() { tv.setText("开始入网认证..."); //认证提交参数准备 // 测试服务 // String spkStr = "ir.module";//产品spk // String macStr = "AA000000000000AF";//设备唯一MAC地址 // String secret = "44b360eb74b7ba64";//通过spk和mac提交云端认证后分配的secret // 正式服务器 String spkStr = "screen.mirror";//产品spk String macStr = "AA00000000000100";//设备唯一MAC地址 String secret = "e186beeb7974998e";//通过spk和mac提交云端认证后分配的secret String mac_key = stringToMD5(stringToMD5(macStr + secret)); String versionString = "HDL_V1.0.1";// String time = String.valueOf(System.currentTimeMillis()); HDLLinkConfig.getInstance().getDeviceInfoBean().setDeviceMAC(macStr); //1.设置认证信息 AuthenticateRequest.RequestBean requestBean = new AuthenticateRequest.RequestBean(); requestBean.setMAC(macStr); requestBean.setSupplier("WISE"); requestBean.setFirmwareVersion(versionString); requestBean.setHardwareModel("1956F"); AuthenticateRequest.AuthBean authbean = new AuthenticateRequest.AuthBean(); authbean.setSpk(spkStr); authbean.setMACKey(mac_key); authbean.setRequest(requestBean); //HDLLinkConfig.getInstance().getDeviceInfoBean()这个初始化的时候要先设置好 AuthenticateRequest request = new AuthenticateRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), authbean); HDLLink.getInstance().startAuthenticateRequest(request, new HDLLinkCallBack() { @Override public void onError(HDLLinkException e) { tv.setText("认证失败"); responseTv.setText(e.getMsg()); Log.i("TAG", "onError: 认证失败"); } @Override public void onSuccess(String msg) { tv.setText("认证成功"); responseTv.setText(msg.toString()); } }); } String stringToMD5(String text) { byte[] hash; try { hash = MessageDigest.getInstance("MD5").digest(text.getBytes("UTF-8")); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } StringBuilder hex = new StringBuilder(hash.length * 2); for (byte b : hash) { if ((b & 0xFF) < 0x10) hex.append("0"); hex.append(Integer.toHexString(b & 0xFF)); } return hex.toString(); } /** * 如果已经认证后,搜索指定网关是否在线 * 广播搜索认证过的网关是否在线 */ void searchGatewayBroadcast() { tv.setText("搜索网关中..."); HDLLink.getInstance().searchGatewayBroadcast(new HDLAuthSocket.SearchGatewayCallBack() { @Override public void onError(HDLLinkException e) { tv.setText("网关不在线"); responseTv.setText(e.getMsg()); } @Override public void onSuccess(GatewaySearchBean gatewaySearchBean) { tv.setText("网关在线"); responseTv.setText("搜索成功 网关id:" + gatewaySearchBean.getGatewayId()); // LogUtils.i("TAG", "onSuccess: 搜索成功:"+gatewaySearchBean.getGatewayId()); } }); } /** * 获取功能列表 */ void getFunctionList() { tv.setText("获取功能列表中..."); responseTv.setText(""); HDLLink.getInstance().getFunctionList(new HDLLinkCallBack() { @Override public void onError(HDLLinkException error) { tv.setText(error.getMsg()); } @Override public void onSuccess(String data) { tv.setText("获取功能列表成功"); responseTv.setText(data); } }); } /** * 功能属性读取 * 支持批量读取 */ void getFunctionAttribute() { tv.setText("功能属性读取"); List sids = new ArrayList<>(); sids.add(testLightSid); HDLLink.getInstance().getFunctionAttribute(sids, new HDLLinkCallBack() { @Override public void onSuccess(String msg) { responseTv.setText(msg); } @Override public void onError(HDLLinkException e) { responseTv.setText(e.getMsg()); } }); } /** * 读取设备状态 * 支持批量读取 */ void propertyRead() { tv.setText("读取状态中..."); List list = new ArrayList<>(); list.add(testLightSid);//要读取设备的sid HDLLink.getInstance().propertyRead(list, new HDLLinkCallBack() { @Override public void onSuccess(String data) { tv.setText("读取成功"); responseTv.setText(data); } @Override public void onError(HDLLinkException e) { tv.setText("读取失败"); responseTv.setText(e.getMsg()); } }); } /** * 控制失败 * 回复响应code为200 代表执行成功 */ void controlDecide() { tv.setText("控制设备"); isOn = !isOn; List requestList = new ArrayList<>(); DeviceControlRequest request = new DeviceControlRequest(); request.setSid(testLightSid); List statusBeanList = new ArrayList<>(); DeviceControlRequest.StatusBean bean = new DeviceControlRequest.StatusBean(); bean.setKey("on_off"); bean.setValue(isOn ? "on" : "off"); statusBeanList.add(bean); request.setStatus(statusBeanList); requestList.add(request); HDLLink.getInstance().propertyDown(requestList, new HDLLinkCallBack() { @Override public void onSuccess(String data) { responseTv.setText(data); } @Override public void onError(HDLLinkException e) { responseTv.setText(e.getMsg()); } }); } /** * 获取场景列表 */ void getSceneList() { tv.setText("读取场景列表"); HDLLink.getInstance().getSceneList(new HDLLinkCallBack() { @Override public void onSuccess(String msg) { responseTv.setText(msg); } @Override public void onError(HDLLinkException e) { responseTv.setText(e.getMsg()); } }); } //场景列表 // {"id":"8a5eaa143ce943b987b577df5a66759b","time_stamp":"1637040217235","objects":[{"sid":"04010560D2C7170A0A0100000000","name":"回家模式","status":"off","group":"255","delay":"0","modify_time":"1634871490"},{"sid":"04010560D2C76E0A0A0100010000","name":"离家模式","status":"off","group":"255","delay":"0","modify_time":"1634785823"}]} /** * 控制场景 * 执行成功的话 响应code为200 */ void controlScene() { tv.setText("场景控制"); //控制场景sid列表,支持批量控制 List sids = new ArrayList<>(); isOn = !isOn; if (isOn) { sids.add("04010560D2C7170A0A0100000000"); } else { sids.add("04010560D2C76E0A0A0100010000"); } HDLLink.getInstance().controlScene(sids, new HDLLinkCallBack() { @Override public void onSuccess(String msg) { responseTv.setText(msg); } @Override public void onError(HDLLinkException e) { responseTv.setText(e.getMsg()); } }); } void startDevicesListActivity() { Intent intent = new Intent(this, DevicesListActivity.class); startActivity(intent); } /** * TCP发送 只发一次,不监听回复,不重发 */ private void tcpSend() { tv.setText("TCP发送 只发一次,不监听回复,不重发"); String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); String bodyStr = getPropertyDownBodyStr(); HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr); } /** * UDP只发一次,不监听回复,不重发 */ private void udpSend() { tv.setText("UDP发送 只发一次,不监听回复,不重发"); String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); String bodyStr = getPropertyDownBodyStr(); HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr); } private String getPropertyDownBodyStr() { isOn = !isOn; List requestList = new ArrayList<>(); DeviceControlRequest request = new DeviceControlRequest(); request.setSid(testLightSid); List statusBeanList = new ArrayList<>(); DeviceControlRequest.StatusBean bean = new DeviceControlRequest.StatusBean(); bean.setKey("on_off"); bean.setValue(isOn ? "on" : "off"); statusBeanList.add(bean); request.setStatus(statusBeanList); requestList.add(request); String time = String.valueOf(System.currentTimeMillis()); final BaseLocalResponse> data = new BaseLocalResponse<>(); data.setId(IdUtils.getUUId()); data.setTime_stamp(time); data.setObjects(requestList); return GsonConvert.getGson().toJson(data); } /** * UDP发送,监听主题回复,带重发带回调 */ private void udpSendWithCallback() { tv.setText("UDP发送,监听主题回复,带重发带回调"); String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); String bodyStr = getPropertyDownBodyStr(); HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr, new HDLLinkResponseCallBack() { @Override public void onSuccess(LinkResponse msg) { Log.i("udpSendWithCallback", "udpSendWithCallback"); responseTv.setText(GsonConvert.getGson().toJson(msg)); } @Override public void onError(HDLLinkException e) { responseTv.setText(e.getMsg()); } }); } /** * TCP发送,监听主题回复,带重发带回调 */ private void tcpSendWithCallback() { tv.setText("TCP发送,监听主题回复,带重发带回调"); String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); String bodyStr = getPropertyDownBodyStr(); HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr, new HDLLinkCallBack() { @Override public void onSuccess(String msg) { Log.i("tcpSendWithCallback", "tcpSendWithCallback"); responseTv.setText(msg); } @Override public void onError(HDLLinkException e) { responseTv.setText(e.getMsg()); } }); } }