HDLSDK/app/src/main/java/com/hdl/hdlsdk/App.java
@@ -1,9 +1,11 @@ package com.hdl.hdlsdk; import android.app.Application; import android.util.Log; import com.hdl.sdk.common.HDLSdk; import com.hdl.sdk.connect.HDLSocket; import com.hdl.sdk.common.event.EventListener; import com.hdl.sdk.connect.HDLLink; /** * Created by Tong on 2021/10/8. @@ -14,6 +16,12 @@ public void onCreate() { super.onCreate(); HDLSdk.getInstance().init(this); HDLLink.getInstance().registerAllTopicsListener(new EventListener() { @Override public void onMessage(Object msg) { Log.i("TAG", "AllTopicsListener onMessage: "+msg.toString()); } }); } @Override HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -9,7 +9,6 @@ import androidx.recyclerview.widget.RecyclerView; import android.Manifest; import android.app.Instrumentation; import android.os.Bundle; import android.util.Log; import android.view.View; @@ -17,24 +16,15 @@ import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.listener.OnItemClickListener; import com.google.gson.JsonObject; import com.hdl.sdk.common.config.AuthenticateConfig; import com.hdl.sdk.common.config.TopicConstant; import com.hdl.sdk.common.utils.IdUtils; import com.hdl.sdk.common.utils.IpUtils; import com.hdl.sdk.connect.HDLAuthSocket; import com.hdl.sdk.connect.HDLSocket; import com.hdl.sdk.connect.socket.HDLAuthSocket; import com.hdl.sdk.connect.socket.HDLSocket; import com.hdl.sdk.connect.bean.DeviceControlRequest; import com.hdl.sdk.connect.bean.GatewaySearchBean; import com.hdl.sdk.connect.bean.LinkRequest; import com.hdl.sdk.connect.protocol.LinkMessageDecoder; import com.hdl.sdk.connect.protocol.LinkMessageEncoder; import com.hdl.sdk.socket.SocketBoot; import com.hdl.sdk.socket.SocketOptions; import com.hdl.sdk.socket.client.UdpClient; import com.hdl.sdk.socket.codec.MessagePipeLine; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Map; HDLSDK/hdl-common/build.gradle
@@ -31,4 +31,5 @@ api 'com.google.code.gson:gson:2.8.8' api 'androidx.annotation:annotation:1.2.0' api 'androidx.collection:collection:1.1.0' // api project(path: ':hdl-connect') } HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/config/AuthenticateConfig.java
@@ -4,8 +4,6 @@ import com.hdl.sdk.common.utils.SPUtils; import static com.hdl.sdk.common.config.TopicConstant.DEIVCE_AUTH_REQUEST; import static com.hdl.sdk.common.config.TopicConstant.GATEWAY_SEARCH; /** * Created by jlchen on 11/11/21. @@ -118,8 +116,9 @@ */ public boolean ifNeedEncrypt(String topicStr){ //过滤相关需要加密的主题 return (!topicStr.contains(DEIVCE_AUTH_REQUEST) //入网认证 && !topicStr.contains(GATEWAY_SEARCH) //搜索网关主题 return (!topicStr.contains(TopicConstant.GATEWAY_AUTH_BROADCAST) //网关广播入网指令 && !topicStr.contains(TopicConstant.DEIVCE_AUTH_REQUEST) //入网认证 && !topicStr.contains(TopicConstant.GATEWAY_SEARCH) //搜索网关主题 && isLocalEncrypt//启用加密标志 ); } HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java
@@ -18,6 +18,8 @@ */ public class EventDispatcher { private static final List<EventListener> ALL_TOPICS_EVENT = new ArrayList<>();//所有主题消息 private static final ArrayMap<Object, List<EventListener>> EVENT = new ArrayMap<>(); private static final ArrayMap<EventListener, Integer> TYPE = new ArrayMap<>(); @@ -100,6 +102,7 @@ }); } public synchronized void post(Object tag, @NonNull Object o) { if (EVENT.containsKey(tag)) { List<EventListener> list = EVENT.get(tag); @@ -116,9 +119,55 @@ } } } //所有主题的Listener通知 if (ALL_TOPICS_EVENT != null && !ALL_TOPICS_EVENT.isEmpty()) { for (EventListener listener : ALL_TOPICS_EVENT) { ThreadToolUtils.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (listener != null) { listener.onMessage(o); } } }); } } } /** * 注册所有主题消息的监听 * @param listener */ public synchronized void registerAllTopicsListener(EventListener listener) { if (ALL_TOPICS_EVENT != null && !ALL_TOPICS_EVENT.contains(listener)) { ALL_TOPICS_EVENT.add(listener); } TYPE.put(listener, MAIN_TYPE); } /** * 取消所有主题消息的监听 * @param listener */ public synchronized void removeAllTopicsListener(EventListener listener) { ioThread.execute(new Runnable() { @Override public void run() { try { if (ALL_TOPICS_EVENT != null && !ALL_TOPICS_EVENT.isEmpty()) { TYPE.remove(listener); ALL_TOPICS_EVENT.remove(listener); } } catch (Exception ignored) { } } }); } public synchronized void clear() { ALL_TOPICS_EVENT.clear(); EVENT.clear(); TYPE.clear(); } HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java
@@ -1,5 +1,6 @@ package com.hdl.sdk.common.utils; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -131,4 +132,20 @@ } return -1; } /** * 字符串to Bytes * @param str 字符串 * @return */ public static byte[] stringToBytes(String str) { try { // 使用指定的字符集将此字符串编码为byte序列并存到一个byte数组中 return str.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return new byte[]{}; } } HDLSDK/hdl-connect/build.gradle
@@ -32,7 +32,7 @@ implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.3.0' //加密 implementation 'cn.hutool:hutool-all:5.6.5' implementation 'org.bouncycastle:bcprov-jdk15on:1.60' // //加密 // implementation 'cn.hutool:hutool-all:5.6.5' // implementation 'org.bouncycastle:bcprov-jdk15on:1.60' } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLLink.java
New file @@ -0,0 +1,70 @@ package com.hdl.sdk.connect; import com.hdl.sdk.common.config.AuthenticateConfig; import com.hdl.sdk.common.event.EventDispatcher; import com.hdl.sdk.common.event.EventListener; import com.hdl.sdk.connect.bean.AuthenticateRequest; import com.hdl.sdk.connect.socket.HDLAuthSocket; /** * Created by jlchen on 11/15/21. * * @Description : HDLLink */ public class HDLLink { /** * instance */ private volatile static HDLLink instance; /** * getInstance * * @return HDLLink */ public static synchronized HDLLink getInstance() { if (instance == null) { synchronized (HDLLink.class) { if (instance == null) { instance = new HDLLink(); } } } return instance; } /** * 注册所有主题消息的监听 * @param listener */ public synchronized void registerAllTopicsListener(EventListener listener){ EventDispatcher.getInstance().registerAllTopicsListener(listener); } /** * 取消所有主题消息的监听 * @param listener */ public synchronized void removeAllTopicsListener(EventListener listener) { EventDispatcher.getInstance().removeAllTopicsListener(listener); } /** * 检测是否已经认证过 * 认证通过才能进行设备控制 * @return */ public boolean checkIfCertified(){ return AuthenticateConfig.getInstance().checkIfCertified(); } /** * 发送入网及认证请求 * * @param ip 网关IP * @param request 认证请求信息 * @param callBack 结果回调 */ public void sendAuthenticateRequest(String ip, AuthenticateRequest request, HDLAuthSocket.CallBack callBack) { HDLAuthSocket.getInstance().sendAuthenticateRequest(ip,request,callBack); } } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkRequest.java
@@ -1,18 +1,16 @@ package com.hdl.sdk.connect.bean; import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; import com.hdl.sdk.common.config.AuthenticateConfig; import com.hdl.sdk.common.utils.ByteUtils; import com.hdl.sdk.connect.utils.AESUtils; import com.hdl.sdk.connect.utils.AesUtil; import java.io.UnsupportedEncodingException; import static com.hdl.sdk.common.config.TopicConstant.DEIVCE_AUTH_REQUEST; import static com.hdl.sdk.common.config.TopicConstant.GATEWAY_SEARCH; //import com.hdl.sdk.connect.utils.AesUtil; /** * Created by Tong on 2021/9/29. @@ -47,7 +45,6 @@ this.data = data; if (!TextUtils.isEmpty(data)) { setLength(getBytesLength(data)); // setLength(data.length()); } else { setLength(0); } @@ -74,32 +71,13 @@ getData(); } private static byte[] stringToBytes(String str) { try { // 使用指定的字符集将此字符串编码为byte序列并存到一个byte数组中 return str.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return new byte[]{}; } private int getBytesLength(String str){ return stringToBytes(str).length; return ByteUtils.stringToBytes(str).length; } /** * 合并数组 * @param bt1 * @param bt2 * @return */ public static byte[] byteMerger(byte[] bt1, byte[] bt2){ byte[] bt3 = new byte[bt1.length + bt2.length]; System.arraycopy(bt1, 0, bt3, 0, bt1.length); System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length); return bt3; } /** * 获取发送数据byte * @@ -110,11 +88,12 @@ //判断是否需要加密 if (AuthenticateConfig.getInstance().ifNeedEncrypt(topic)) { //需要加密 byte[] dataBytes = AesUtil.aesEncrypt(stringToBytes(data), AuthenticateConfig.getInstance().getLocalSecret()); byte[] dataBytes = AesUtil.aesEncrypt(ByteUtils.stringToBytes(data), AuthenticateConfig.getInstance().getLocalSecret()); // byte[] dataBytes = AESUtils.encryptAES(stringToBytes(data), AuthenticateConfig.getInstance().getLocalSecret()); String headString = "Topic:" + getTopic() + "\r\n" + "Length:" + dataBytes.length + "\r\n" + "\r\n"; // byte[] headBytes = headString.getBytes("utf-8"); byte[] headBytes = headString.getBytes(); byte[] sendBytes = byteMerger(headBytes, dataBytes); byte[] headBytes = headString.getBytes("utf-8"); byte[] sendBytes = ByteUtils.concatBytes(headBytes, dataBytes); return sendBytes; } else { return this.toString().getBytes("utf-8"); HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java
@@ -1,12 +1,11 @@ package com.hdl.sdk.connect.protocol; import android.util.Log; import com.hdl.sdk.common.config.AuthenticateConfig; import com.hdl.sdk.common.event.EventDispatcher; import com.hdl.sdk.common.utils.ByteUtils; import com.hdl.sdk.connect.bean.LinkResponse; import com.hdl.sdk.connect.utils.AESUtils; import com.hdl.sdk.connect.utils.AesUtil; import com.hdl.sdk.connect.utils.ProtocolParse; import com.hdl.sdk.socket.codec.ByteToMessageDecoder; @@ -64,13 +63,12 @@ if(AuthenticateConfig.getInstance().ifNeedEncrypt(response.getTopic())){ //需要解密 byte[] bodyBytes = AesUtil.aesDecrypt(body,AuthenticateConfig.getInstance().getLocalSecret()); // byte[] bodyBytes = AESUtils.decryptAES(body,AuthenticateConfig.getInstance().getLocalSecret()); response.setData(new String(bodyBytes, "utf-8")); Log.i("TAG", "decoder: "); // Log.i("TAG", "解密 主题:"+response.getTopic()+ " body: "+response.getData()); }else{ response.setData(new String(body, "utf-8")); } if (byteArray.length >= bodyLength + bodyStartIndex) { //保存余留 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLAuthSocket.java
File was renamed from HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLAuthSocket.java @@ -1,4 +1,4 @@ package com.hdl.sdk.connect; package com.hdl.sdk.connect.socket; import android.text.TextUtils; import android.util.Log; @@ -267,9 +267,9 @@ String topic = String.format(TopicConstant.PROPERTY_DOWN, "1406844230123372545"); LinkRequest message = new LinkRequest(topic, GsonConvert.getGson().toJson(request)); GsonConvert.getGson().toJson(data)); Log.i("TAG", "propertyDown: " + message.getData()); // Log.i("TAG", "propertyDown: " + message.toString()); String ip = IpUtils.getBroadcastAddress(); HdlSocketHelper.send(getUdpBoot(ip), message, null); @@ -299,4 +299,7 @@ return hex.toString(); } } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java
File was renamed from HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLSocket.java @@ -1,11 +1,7 @@ package com.hdl.sdk.connect; package com.hdl.sdk.connect.socket; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.hdl.sdk.common.config.TopicConstant; @@ -16,8 +12,6 @@ import com.hdl.sdk.common.utils.SPUtils; import com.hdl.sdk.common.utils.ThreadToolUtils; import com.hdl.sdk.common.utils.gson.GsonConvert; import com.hdl.sdk.connect.bean.AuthenticateRequest; import com.hdl.sdk.connect.bean.BaseLocalRequest; import com.hdl.sdk.connect.bean.BaseLocalResponse; import com.hdl.sdk.connect.bean.DeviceControlRequest; import com.hdl.sdk.connect.bean.FunctionAttributeRequest; @@ -37,11 +31,8 @@ import com.hdl.sdk.socket.listener.SendListener; import java.io.UnsupportedEncodingException; import java.lang.reflect.ParameterizedType; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HdlSocketHelper.java
File was renamed from HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HdlSocketHelper.java @@ -1,4 +1,4 @@ package com.hdl.sdk.connect; package com.hdl.sdk.connect.socket; import android.text.TextUtils; HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/utils/AESUtils.java
File was deleted HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/utils/AesUtil.java
@@ -3,22 +3,16 @@ import com.hdl.sdk.common.utils.LogUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.Security; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import cn.hutool.core.util.HexUtil; /** * Aes 加解密工具类 @@ -28,13 +22,13 @@ */ public class AesUtil { private static final String CIPHER_INSTANCE = "AES/ECB/PKCS5Padding"; private static final String CIPHER_INSTANCE = "AES/CBC/PKCS7Padding"; private static final String AES_ALGORITHM = "AES"; static { //AES/CBC/PKCS7Padding 依赖 Security.addProvider(new BouncyCastleProvider()); } // static { // //AES/CBC/PKCS7Padding 依赖 // Security.addProvider(new BouncyCastleProvider()); // } /** * AES加密 @@ -44,7 +38,7 @@ * @throws Exception */ public static byte[] aesEncrypt(byte[] content, String key) { return encrypt(content, key.getBytes(), "AES/CBC/PKCS7Padding", true, null); return encrypt(content, key.getBytes(), CIPHER_INSTANCE, true, null); } /** @@ -55,52 +49,9 @@ * @throws Exception */ public static byte[] aesDecrypt(byte[] content, String key) { return decrypt(content, key.getBytes(), "AES/CBC/PKCS7Padding", true, null); return decrypt(content, key.getBytes(), CIPHER_INSTANCE, true, null); } /** * 加密 * * @param content 待加密字符串 * @param keyHex aesKye的hexStr * @return */ public static String encrypt(String content, String keyHex) { return HexUtil.encodeHexStr(encrypt(content.getBytes(), HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null)); } /** * 加密 * * @param content 待加密字符串 * @param key 密钥 * @return */ public static String encrypt(String content, byte[] key) { return HexUtil.encodeHexStr(encrypt(content.getBytes(), key, CIPHER_INSTANCE, false, null)); } /** * 加密 * * @param content 待加密字符串 * @param keyHex aesKye的hexStr * @return */ public static byte[] encryptReturnByte(String content, String keyHex) { return encrypt(content.getBytes(), HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null); } /** * 加密 * * @param content 待加密字符串 * @param key 密钥 * @return */ public static byte[] encryptReturnByte(String content, byte[] key) { return encrypt(content.getBytes(), key, CIPHER_INSTANCE, false, null); } /** * 加密 @@ -149,51 +100,6 @@ /** * 解密 * * @param contentHex 待解密待字符串hexStr * @param keyHex desKye的hexStr * @return */ public static String decrypt(String contentHex, String keyHex) { return new String(decrypt(HexUtil.decodeHex(contentHex), HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null)); } /** * 解密 * * @param contentHex 待解密待字符串hexStr * @param key 密钥 * @return */ public static String decrypt(String contentHex, byte[] key) { return new String(decrypt(HexUtil.decodeHex(contentHex), key, CIPHER_INSTANCE, false, null)); } /** * 解密 * * @param content 待解密待内容 * @param keyHex 密钥 * @return */ public static String decrypt(byte[] content, String keyHex) { return new String(decrypt(content, HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null)); } /** * 解密 * * @param content 待解密待内容 * @param key 密钥 * @return */ public static String decrypt(byte[] content, byte[] key) { return new String(decrypt(content, key, CIPHER_INSTANCE, false, null)); } /** * 解密 * * @param contentByte 待解密待字符串hexStr * @param contentByte 密钥 * @param cipherInstance AES算法填充方式 @@ -235,51 +141,4 @@ return null; } public static void main(String[] args) { // jiemi(); //jiami(); } public static void jiami() { String key = "1f6714fc-fb9b-4a"; String content = "{\"id\":\"123\",\"objects\":[{\"sid\":\"0001011565879801020200010101\",\"type\":\"PWD\",\"local_id\":\"2\"}],\"time_stamp\":\"1603281282000\"}"; byte[] res = aesEncrypt(content.getBytes(), key); System.out.println(HexUtil.encodeHexStr(res)); } // /** // * // * @param str // * @param houseId // * @return // */ // public static String jiemi(byte[] str, String houseId) { // byte[] rs = aesDecrypt(str, HouseIdSecretUtil.getSecret(houseId)); // String content = new String(rs); // return content; // } // public static void main(String[] args) { // try { // //第一步: 生成KEY // //KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM); // //keyGenerator.init(256); // //第二步: 产生密钥 // //SecretKey secretKey = keyGenerator.generateKey(); // //第三步: 获取密钥 // //byte[] keyBytes = secretKey.getEncoded(); // //System.out.println(byteArrayToHexStr(keyBytes)); // String src = "aaaaaaaaaVVVVaaaAAAA无"; // String pwd = "41151AF257BFDB7859EEC62FB341EE95EE42E648FE24E1F8CE8DADE287CC1E5C"; // String mw = encrypt(src,pwd); // System.out.println("mw:"+mw); // String jm = decrypt(mw,pwd); // System.out.println("jm:"+jm); // // }catch (Exception e){ // // } // // } }