From c584c193d5dd4290bcbeddd434e1d642db59eb13 Mon Sep 17 00:00:00 2001
From: JLChen <551775569@qq.com>
Date: 星期二, 09 十一月 2021 17:25:59 +0800
Subject: [PATCH] 2021-11-09 1.更新

---
 HDLSDK/app/src/main/AndroidManifest.xml                                                  |   33 
 HDLSDK/hdl-connect/.gitignore                                                            |    1 
 HDLSDK/config.gradle                                                                     |    7 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java                       |  327 +++
 HDLSDK/app/src/main/res/layout/activity_main.xml                                         |   79 
 HDLSDK/app/src/main/res/layout/demo_item.xml                                             |   28 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/ClientPool.java                |   57 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/HDLSdk.java                           |   30 
 HDLSDK/.idea/jarRepositories.xml                                                         |   55 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IpUtils.java                    |   72 
 HDLSDK/hdl-connect/src/androidTest/java/com/hdl/sdk/connect/ExampleInstrumentedTest.java |   26 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/ConnectStatusListener.java   |   27 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/SendListener.java            |   11 
 HDLSDK/hdl-common/src/main/AndroidManifest.xml                                           |    5 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessageToByteEncoder.java       |   24 
 HDLSDK/app/src/main/res/values/colors.xml                                                |   10 
 HDLSDK/app/src/main/java/com/hdl/hdlsdk/App.java                                         |   24 
 HDLSDK/hdl-common/consumer-rules.pro                                                     |    0 
 HDLSDK/hdl-socket/proguard-rules.pro                                                     |   21 
 HDLSDK/app/src/main/res/drawable-v24/ic_launcher_foreground.xml                          |   30 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleMessage.java             |   10 
 HDLSDK/app/.gitignore                                                                    |    1 
 HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp                               |    0 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IMessagePipeLine.java           |   11 
 HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml                          |    5 
 HDLSDK/.gitignore                                                                        |   15 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IdUtils.java                    |   12 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleFlow.java                |   12 
 HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp                            |    0 
 HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoBean.java                                    |   28 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketRequest.java                    |   34 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/utils/ProtocolParse.java            |   74 
 HDLSDK/gradle.properties                                                                 |   19 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLSocket.java                      |  650 +++++++
 HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher.webp                                     |    0 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ThreadToolUtils.java            |   72 
 HDLSDK/hdl-connect/src/test/java/com/hdl/sdk/connect/ExampleUnitTest.java                |   17 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyUpRequest.java         |   50 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/annotation/ConnectStatus.java         |   31 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/config/TopicConstant.java             |   52 
 HDLSDK/app/src/main/res/values-night/themes.xml                                          |   16 
 HDLSDK/hdl-connect/consumer-rules.pro                                                    |    0 
 HDLSDK/hdl-common/src/test/java/com/hdl/sdk/common/ExampleUnitTest.java                  |   17 
 HDLSDK/hdl-socket/consumer-rules.pro                                                     |    0 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/DeviceControlRequest.java      |   51 
 HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoAdapter.java                                 |   26 
 HDLSDK/app/src/main/res/values/themes.xml                                                |   16 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalResponse.java         |   38 
 HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp                              |    0 
 HDLSDK/hdl-socket/src/main/AndroidManifest.xml                                           |    5 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/ParameterizedTypeImpl.java |   46 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/LogUtils.java                   |   51 
 HDLSDK/hdl-socket/README.md                                                              |    8 
 HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java                                |  144 +
 HDLSDK/hdl-common/build.gradle                                                           |   34 
 HDLSDK/hdl-socket/build.gradle                                                           |   33 
 HDLSDK/gradle/wrapper/gradle-wrapper.jar                                                 |    0 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java            |  132 +
 HDLSDK/.idea/misc.xml                                                                    |   17 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/UdpClient.java                 |  206 ++
 HDLSDK/hdl-connect/src/main/AndroidManifest.xml                                          |    5 
 HDLSDK/app/src/androidTest/java/com/hdl/hdlsdk/ExampleInstrumentedTest.java              |   26 
 HDLSDK/hdl-socket/src/test/java/com/hdl/sdk/socket/ExampleUnitTest.java                  |   17 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java                  |  134 +
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/FunctionAttributeRequest.java  |   24 
 HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp                                  |    0 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkResponse.java              |   55 
 HDLSDK/.idea/gradle.xml                                                                  |   24 
 HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp                                   |    0 
 HDLSDK/build.gradle                                                                      |   30 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalRequest.java          |   47 
 HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml                                |    5 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkRequest.java               |   64 
 HDLSDK/hdl-socket/.gitignore                                                             |    1 
 HDLSDK/gradle/wrapper/gradle-wrapper.properties                                          |    6 
 HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher.webp                                    |    0 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/IClient.java                   |   37 
 HDLSDK/app/src/main/res/drawable/ic_launcher_background.xml                              |  170 ++
 .gitignore                                                                               |   81 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/IHDLClient.java                       |   52 
 HDLSDK/gradlew.bat                                                                       |   89 +
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java    |   81 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/GsonConvert.java           |   55 
 HDLSDK/settings.gradle                                                                   |    6 
 HDLSDK/.idea/.gitignore                                                                  |    3 
 HDLSDK/hdl-connect/proguard-rules.pro                                                    |   21 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/TcpClient.java                 |  176 ++
 HDLSDK/app/src/test/java/com/hdl/hdlsdk/ExampleUnitTest.java                             |   17 
 HDLSDK/app/src/main/res/values/strings.xml                                               |    3 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventListener.java              |   10 
 HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/SPUtils.java                    |  151 +
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/ByteToMessageDecoder.java       |   20 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyReadRequest.java       |   17 
 HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher.webp                                     |    0 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageEncoder.java    |   16 
 HDLSDK/.idea/compiler.xml                                                                |    6 
 HDLSDK/hdl-common/proguard-rules.pro                                                     |   21 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketOptions.java                    |  130 +
 HDLSDK/app/build.gradle                                                                  |   43 
 HDLSDK/gradlew                                                                           |  185 ++
 HDLSDK/app/proguard-rules.pro                                                            |   21 
 HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessagePipeLine.java            |   51 
 HDLSDK/hdl-connect/build.gradle                                                          |   34 
 HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp                             |    0 
 HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/GatewaySearchBean.java         |  102 +
 HDLSDK/hdl-socket/src/androidTest/java/com/hdl/sdk/socket/ExampleInstrumentedTest.java   |   26 
 HDLSDK/hdl-common/.gitignore                                                             |    1 
 HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp                               |    0 
 HDLSDK/hdl-common/src/androidTest/java/com/hdl/sdk/common/ExampleInstrumentedTest.java   |   26 
 109 files changed, 4,887 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index 3a36c6e..110ac68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,15 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/android
+# Edit at https://www.toptal.com/developers/gitignore?templates=android
+
+### Android ###
 # Built application files
 *.apk
+*.aar
 *.ap_
+*.aab
 
-# Files for the Dalvik VM
+# Files for the ART/Dalvik VM
 *.dex
 
 # Java class files
@@ -11,6 +18,9 @@
 # Generated files
 bin/
 gen/
+out/
+#  Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
 
 # Gradle files
 .gradle/
@@ -22,5 +32,72 @@
 # Proguard folder generated by Eclipse
 proguard/
 
-#Log Files
+# Log Files
 *.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/jarRepositories.xml
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+# Android Profiling
+*.hprof
+
+### Android Patch ###
+gen-external-apklibs
+output.json
+
+# Replacement of .externalNativeBuild directories introduced
+# with Android Studio 3.5.
+
+# End of https://www.toptal.com/developers/gitignore/api/android
\ No newline at end of file
diff --git a/HDLSDK/.gitignore b/HDLSDK/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/HDLSDK/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/HDLSDK/.idea/.gitignore b/HDLSDK/.idea/.gitignore
new file mode 100644
index 0000000..eaf91e2
--- /dev/null
+++ b/HDLSDK/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/HDLSDK/.idea/compiler.xml b/HDLSDK/.idea/compiler.xml
new file mode 100644
index 0000000..7d7ec2e
--- /dev/null
+++ b/HDLSDK/.idea/compiler.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <bytecodeTargetLevel target="11" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/HDLSDK/.idea/gradle.xml b/HDLSDK/.idea/gradle.xml
new file mode 100644
index 0000000..7e69409
--- /dev/null
+++ b/HDLSDK/.idea/gradle.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleMigrationSettings" migrationVersion="1" />
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="testRunner" value="PLATFORM" />
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/hdl-common" />
+            <option value="$PROJECT_DIR$/hdl-connect" />
+            <option value="$PROJECT_DIR$/hdl-socket" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+        <option name="useQualifiedModuleNames" value="true" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/HDLSDK/.idea/jarRepositories.xml b/HDLSDK/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fbe72e2
--- /dev/null
+++ b/HDLSDK/.idea/jarRepositories.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven" />
+      <option name="name" value="maven" />
+      <option name="url" value="https://maven.aliyun.com/repository/central" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven2" />
+      <option name="name" value="maven2" />
+      <option name="url" value="https://maven.aliyun.com/repository/google" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven5" />
+      <option name="name" value="maven5" />
+      <option name="url" value="https://maven.aliyun.com/repository/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven4" />
+      <option name="name" value="maven4" />
+      <option name="url" value="https://maven.aliyun.com/repository/gradle-plugin" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven3" />
+      <option name="name" value="maven3" />
+      <option name="url" value="https://maven.aliyun.com/repository/jcenter" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven9" />
+      <option name="name" value="maven9" />
+      <option name="url" value="https://jitpack.io" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven8" />
+      <option name="name" value="maven8" />
+      <option name="url" value="https://maven.aliyun.com/repository/public" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="Google" />
+      <option name="name" value="Google" />
+      <option name="url" value="https://dl.google.com/dl/android/maven2/" />
+    </remote-repository>
+  </component>
+</project>
\ No newline at end of file
diff --git a/HDLSDK/.idea/misc.xml b/HDLSDK/.idea/misc.xml
new file mode 100644
index 0000000..2f09a86
--- /dev/null
+++ b/HDLSDK/.idea/misc.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DesignSurface">
+    <option name="filePathToZoomLevelMap">
+      <map>
+        <entry key="..\:/job/me/Android/HDLSDK/app/src/main/res/layout/activity_main.xml" value="0.1" />
+        <entry key="..\:/job/me/Android/HDLSDK/app/src/main/res/layout/demo_item.xml" value="0.28958333333333336" />
+      </map>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/HDLSDK/app/.gitignore b/HDLSDK/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/HDLSDK/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/HDLSDK/app/build.gradle b/HDLSDK/app/build.gradle
new file mode 100644
index 0000000..22b041f
--- /dev/null
+++ b/HDLSDK/app/build.gradle
@@ -0,0 +1,43 @@
+plugins {
+    id 'com.android.application'
+}
+
+android {
+    compileSdk 31
+
+    defaultConfig {
+        applicationId "com.hdl.hdlsdk"
+        minSdk 21
+        targetSdk 31
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+
+    implementation 'androidx.appcompat:appcompat:1.3.1'
+    implementation 'com.google.android.material:material:1.4.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
+
+    testImplementation 'junit:junit:4.+'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+
+    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
+
+    implementation project(path: ':hdl-connect')
+}
\ No newline at end of file
diff --git a/HDLSDK/app/proguard-rules.pro b/HDLSDK/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/HDLSDK/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/HDLSDK/app/src/androidTest/java/com/hdl/hdlsdk/ExampleInstrumentedTest.java b/HDLSDK/app/src/androidTest/java/com/hdl/hdlsdk/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..4f7fa58
--- /dev/null
+++ b/HDLSDK/app/src/androidTest/java/com/hdl/hdlsdk/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.hdl.hdlsdk;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.hdl.hdlsdk", appContext.getPackageName());
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/AndroidManifest.xml b/HDLSDK/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c9d8256
--- /dev/null
+++ b/HDLSDK/app/src/main/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.hdl.hdlsdk">
+
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
+    <uses-permission
+        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+        tools:ignore="ScopedStorage" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+    <application
+        android:allowBackup="true"
+        android:name=".App"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.HDLSDK">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/java/com/hdl/hdlsdk/App.java b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/App.java
new file mode 100644
index 0000000..86fe706
--- /dev/null
+++ b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/App.java
@@ -0,0 +1,24 @@
+package com.hdl.hdlsdk;
+
+import android.app.Application;
+
+import com.hdl.sdk.common.HDLSdk;
+import com.hdl.sdk.connect.HDLSocket;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class App extends Application {
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        HDLSdk.getInstance().init(this);
+    }
+
+    @Override
+    public void onTerminate() {
+        super.onTerminate();
+
+    }
+}
diff --git a/HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoAdapter.java b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoAdapter.java
new file mode 100644
index 0000000..18f6d76
--- /dev/null
+++ b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoAdapter.java
@@ -0,0 +1,26 @@
+package com.hdl.hdlsdk;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.chad.library.adapter.base.BaseMultiItemQuickAdapter;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+
+import java.util.List;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class DemoAdapter extends BaseMultiItemQuickAdapter<DemoBean, BaseViewHolder> {
+
+    public DemoAdapter(@Nullable List<DemoBean> data) {
+        super(data);
+        addItemType(0,R.layout.demo_item);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder baseViewHolder, DemoBean demoBean) {
+        baseViewHolder.setText(R.id.tv_title,demoBean.getName());
+    }
+}
diff --git a/HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoBean.java b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoBean.java
new file mode 100644
index 0000000..ad185fa
--- /dev/null
+++ b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/DemoBean.java
@@ -0,0 +1,28 @@
+package com.hdl.hdlsdk;
+
+import com.chad.library.adapter.base.entity.MultiItemEntity;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class DemoBean implements MultiItemEntity {
+
+    private String name;
+
+    public DemoBean(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public int getItemType() {
+        return 0;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
new file mode 100644
index 0000000..31d24e3
--- /dev/null
+++ b/HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -0,0 +1,144 @@
+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.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.Manifest;
+import android.app.Instrumentation;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+
+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.TopicConstant;
+import com.hdl.sdk.common.utils.IdUtils;
+import com.hdl.sdk.common.utils.IpUtils;
+import com.hdl.sdk.connect.HDLSocket;
+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;
+
+public class MainActivity extends AppCompatActivity {
+
+    private DemoAdapter demoAdapter;
+    private RecyclerView rv;
+    private TextView tv;
+    private TextView responseTv;
+
+
+
+    @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));
+
+        ActivityResultLauncher<String[]> launcher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
+            @Override
+            public void onActivityResult(Map<String, Boolean> result) {
+
+            }
+        });
+
+        launcher.launch(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE});
+
+        final List<DemoBean> 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("璇诲彇鐘舵��"));
+        demoAdapter = new DemoAdapter(beans);
+        rv.setAdapter(demoAdapter);
+
+
+        final SocketOptions options = new SocketOptions();
+
+        MessagePipeLine pipeLine = new MessagePipeLine();
+        pipeLine.add(new LinkMessageDecoder());
+        pipeLine.add(new LinkMessageEncoder());
+        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:
+                        tv.setText("鎼滅储缃戝叧涓�");
+                        responseTv.setText("");
+
+                        HDLSocket.getInstance().searchGateway(new HDLSocket.CallBack() {
+                            @Override
+                            public void onError(String error) {
+                                tv.setText("缃戝叧鑾峰彇澶辫触");
+                            }
+
+                            @Override
+                            public void onResponse(String data) {
+                                tv.setText("鑾峰彇缃戝叧鎴愬姛");
+                                responseTv.setText(data);
+                            }
+                        });
+
+                        break;
+                    case 1:
+
+                        tv.setText("鑾峰彇鍔熻兘鍒楄〃涓�");
+                        responseTv.setText("");
+                        HDLSocket.getInstance().getFunctionList(new HDLSocket.CallBack() {
+                            @Override
+                            public void onError(String error) {
+                                tv.setText(error);
+                            }
+
+                            @Override
+                            public void onResponse(String data) {
+                                tv.setText("鑾峰彇鍔熻兘鍒楄〃鎴愬姛");
+                                responseTv.setText(data);
+                            }
+                        });
+                        break;
+                    case 2:
+                        //鍔熻兘灞炴�ц鍙�
+                      //  HDLSocket.getInstance().getFunctionAttribute();
+
+                        break;
+                    case 3:
+                        //璁惧鎺у埗
+                         // HDLSocket.getInstance().propertyDown();
+                        break;
+                    case 4:
+                        //鐘舵�佷笂鎶�
+                        //HDLSocket.getInstance().propertyUp();
+                        break;
+                    case 5:
+                        //璇诲彇鐘舵��
+                        // HDLSocket.getInstance().propertyRead();
+                        break;
+                }
+            }
+        });
+    }
+
+}
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/HDLSDK/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/HDLSDK/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="85.84757"
+                android:endY="92.4963"
+                android:startX="42.9492"
+                android:startY="49.59793"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+</vector>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/drawable/ic_launcher_background.xml b/HDLSDK/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/HDLSDK/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#3DDC84"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/HDLSDK/app/src/main/res/layout/activity_main.xml b/HDLSDK/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..6fa6c2b
--- /dev/null
+++ b/HDLSDK/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout 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"
+    tools:context=".MainActivity">
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rv"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/scrollView"
+        app:layout_constraintHorizontal_weight="1"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <View
+        android:layout_width="1dp"
+        android:layout_height="0dp"
+        android:background="#f4f4f4"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/scrollView"
+        app:layout_constraintStart_toEndOf="@id/rv"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.core.widget.NestedScrollView
+        android:id="@+id/scrollView"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_weight="2"
+        app:layout_constraintStart_toEndOf="@id/rv"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingStart="10dp"
+                android:text="褰撳墠鐘舵�侊細" />
+
+            <TextView
+                android:id="@+id/state_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:text="鏈搷浣�" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="2dp"
+                android:background="#f5f5f5" />
+
+            <TextView
+                android:paddingStart="10dp"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:text="鍝嶅簲锛�" />
+
+            <TextView
+                android:id="@+id/response_tv"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp" />
+
+
+        </LinearLayout>
+    </androidx.core.widget.NestedScrollView>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/layout/demo_item.xml b/HDLSDK/app/src/main/res/layout/demo_item.xml
new file mode 100644
index 0000000..84a9aed
--- /dev/null
+++ b/HDLSDK/app/src/main/res/layout/demo_item.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="40dp">
+
+    <TextView
+        android:id="@+id/tv_title"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:gravity="center"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="1dp"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="10dp"
+        android:background="#f5f5f5"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..c209e78
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..b2dfe3d
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..4f0f1d6
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..62b611d
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..948a307
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..1b9a695
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..28d4b77
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9287f50
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..aa7d642
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9126ae3
--- /dev/null
+++ b/HDLSDK/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Binary files differ
diff --git a/HDLSDK/app/src/main/res/values-night/themes.xml b/HDLSDK/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..ab52aa6
--- /dev/null
+++ b/HDLSDK/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Theme.HDLSDK" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/purple_200</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/black</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/teal_200</item>
+        <item name="colorSecondaryVariant">@color/teal_200</item>
+        <item name="colorOnSecondary">@color/black</item>
+        <!-- Status bar color. -->
+        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
+        <!-- Customize your theme here. -->
+    </style>
+</resources>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/values/colors.xml b/HDLSDK/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/HDLSDK/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="purple_200">#FFBB86FC</color>
+    <color name="purple_500">#FF6200EE</color>
+    <color name="purple_700">#FF3700B3</color>
+    <color name="teal_200">#FF03DAC5</color>
+    <color name="teal_700">#FF018786</color>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+</resources>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/values/strings.xml b/HDLSDK/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..192b55f
--- /dev/null
+++ b/HDLSDK/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">HDLSDK</string>
+</resources>
\ No newline at end of file
diff --git a/HDLSDK/app/src/main/res/values/themes.xml b/HDLSDK/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..dcf7fa1
--- /dev/null
+++ b/HDLSDK/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Theme.HDLSDK" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/purple_500</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/white</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/teal_200</item>
+        <item name="colorSecondaryVariant">@color/teal_700</item>
+        <item name="colorOnSecondary">@color/black</item>
+        <!-- Status bar color. -->
+        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
+        <!-- Customize your theme here. -->
+    </style>
+</resources>
\ No newline at end of file
diff --git a/HDLSDK/app/src/test/java/com/hdl/hdlsdk/ExampleUnitTest.java b/HDLSDK/app/src/test/java/com/hdl/hdlsdk/ExampleUnitTest.java
new file mode 100644
index 0000000..eceb1d2
--- /dev/null
+++ b/HDLSDK/app/src/test/java/com/hdl/hdlsdk/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.hdl.hdlsdk;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/build.gradle b/HDLSDK/build.gradle
new file mode 100644
index 0000000..1755efa
--- /dev/null
+++ b/HDLSDK/build.gradle
@@ -0,0 +1,30 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+apply from: "config.gradle"
+buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath "com.android.tools.build:gradle:4.2.2"
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+
+allprojects {
+    repositories {
+        maven { url 'https://maven.aliyun.com/repository/google' }
+        maven { url 'https://maven.aliyun.com/repository/jcenter' }
+        maven { url 'https://maven.aliyun.com/repository/public' }
+        google()
+        maven { url "https://jitpack.io" }
+    }
+}
+
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/HDLSDK/config.gradle b/HDLSDK/config.gradle
new file mode 100644
index 0000000..582d32b
--- /dev/null
+++ b/HDLSDK/config.gradle
@@ -0,0 +1,7 @@
+ext {
+    minSdkVersion = 16
+    targetSdkVersion = 31
+    compileSdkVersion = 31
+    versionName = "1.0.0"
+
+}
\ No newline at end of file
diff --git a/HDLSDK/gradle.properties b/HDLSDK/gradle.properties
new file mode 100644
index 0000000..52f5917
--- /dev/null
+++ b/HDLSDK/gradle.properties
@@ -0,0 +1,19 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
\ No newline at end of file
diff --git a/HDLSDK/gradle/wrapper/gradle-wrapper.jar b/HDLSDK/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
--- /dev/null
+++ b/HDLSDK/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/HDLSDK/gradle/wrapper/gradle-wrapper.properties b/HDLSDK/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e85e154
--- /dev/null
+++ b/HDLSDK/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Sep 15 00:34:41 CST 2021
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/HDLSDK/gradlew b/HDLSDK/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/HDLSDK/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=`expr $i + 1`
+    done
+    case $i in
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/HDLSDK/gradlew.bat b/HDLSDK/gradlew.bat
new file mode 100644
index 0000000..ac1b06f
--- /dev/null
+++ b/HDLSDK/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/HDLSDK/hdl-common/.gitignore b/HDLSDK/hdl-common/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/HDLSDK/hdl-common/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/HDLSDK/hdl-common/build.gradle b/HDLSDK/hdl-common/build.gradle
new file mode 100644
index 0000000..673c577
--- /dev/null
+++ b/HDLSDK/hdl-common/build.gradle
@@ -0,0 +1,34 @@
+plugins {
+    id 'com.android.library'
+}
+
+android {
+    compileSdkVersion rootProject.compileSdkVersion
+
+    defaultConfig {
+        minSdkVersion rootProject.minSdkVersion
+        targetSdkVersion rootProject.targetSdkVersion
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+    api 'com.google.code.gson:gson:2.8.8'
+    api 'androidx.annotation:annotation:1.2.0'
+    api 'androidx.collection:collection:1.1.0'
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-common/consumer-rules.pro b/HDLSDK/hdl-common/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/HDLSDK/hdl-common/consumer-rules.pro
diff --git a/HDLSDK/hdl-common/proguard-rules.pro b/HDLSDK/hdl-common/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/HDLSDK/hdl-common/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/HDLSDK/hdl-common/src/androidTest/java/com/hdl/sdk/common/ExampleInstrumentedTest.java b/HDLSDK/hdl-common/src/androidTest/java/com/hdl/sdk/common/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..46d814a
--- /dev/null
+++ b/HDLSDK/hdl-common/src/androidTest/java/com/hdl/sdk/common/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.hdl.sdk.common;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.hdl.sdk.common.test", appContext.getPackageName());
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-common/src/main/AndroidManifest.xml b/HDLSDK/hdl-common/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ea4c4f9
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.hdl.sdk.common">
+
+</manifest>
\ No newline at end of file
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/HDLSdk.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/HDLSdk.java
new file mode 100644
index 0000000..120fc9d
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/HDLSdk.java
@@ -0,0 +1,30 @@
+package com.hdl.sdk.common;
+
+import android.content.Context;
+
+/**
+ * Created by Tong on 2021/9/28.
+ */
+public class HDLSdk {
+
+    private Context context;
+
+    private HDLSdk() {
+    }
+
+    private static class SingletonInstance {
+        private static final HDLSdk INSTANCE = new HDLSdk();
+    }
+
+    public static HDLSdk getInstance() {
+        return SingletonInstance.INSTANCE;
+    }
+
+    public void init(Context context) {
+        this.context = context.getApplicationContext();
+    }
+
+    public Context getContext() {
+        return context;
+    }
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/IHDLClient.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/IHDLClient.java
new file mode 100644
index 0000000..5c6007f
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/IHDLClient.java
@@ -0,0 +1,52 @@
+package com.hdl.sdk.common;
+
+/**
+ * Created by Tong on 2021/9/28.
+ * 鍖呭惈鎵�鏈夋搷浣�
+ */
+public interface IHDLClient {
+
+
+    /**
+     * 鎼滅储缃戝叧
+     */
+    void searchGateway();
+
+
+    /**
+     * 鑾峰彇缃戝叧璇︾粏淇℃伅
+     */
+    void getGatewayInfo();
+
+    /**
+     * 鑾峰彇璁惧鍒楄〃
+     */
+    void getDeviceList();
+
+    /**
+     * 鑾峰彇鍔熻兘鍒楄〃
+     */
+    void getFunctionList();
+
+    /**
+     * 鑾峰彇鍔熻兘灞炴��
+     */
+    void getFunctionAttribute();
+
+    /**
+     * 璁惧鎺у埗
+     */
+    void deviceControl();
+
+    /**
+     * 鑾峰彇璁惧鐘舵��
+     */
+    void getDeviceStatus();
+
+    /**
+     * 鏀瑰彉璁惧鐘舵��
+     */
+    void changeDeviceStatus();
+
+
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/config/TopicConstant.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/config/TopicConstant.java
new file mode 100644
index 0000000..ace530f
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/config/TopicConstant.java
@@ -0,0 +1,52 @@
+package com.hdl.sdk.common.config;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public class TopicConstant {
+
+    //鎼滅储缃戝叧
+    public static final String GATEWAY_SEARCH = "/user/all/custom/gateway/search";
+
+    //鎼滅储缃戝叧鍝嶅簲
+    public static final String GATEWAY_SEARCH_REPLY = "/user/all/custom/gateway/search_reply";
+
+    //缃戝叧璇︾粏淇℃伅鑾峰彇s=gw_id
+    public static final String GATEWAY_INFO = "/user/%s/custom/gateway/get";
+
+    //鑾峰彇鐗╃悊璁惧鍒楄〃
+    public static final String GET_DEVICE_LIST = " /user/%s/custom/device/list/get";
+
+    //鑾峰彇鐗╃悊璁惧鍒楄〃鍝嶅簲
+    public static final String GET_DEVICE_LIST_REPLY = " /user/%s/custom/device/list/get_reply";
+
+    //鑾峰彇鍔熻兘鍒楄〃
+    public static final String GET_FUNCTION_LIST = "/user/%s/custom/function/list/get";
+
+    //鑾峰彇鍔熻兘鍝嶅簲
+    public static final String GET_FUNCTION_LIST_REPLY = "/user/%s/custom/function/list/get_reply";
+
+    //鍔熻兘灞炴�ц鍙�
+    public static final String GET_FUNCTION_ATTRIBUTE = "/user/%s/custom/function/attribute/get";
+
+    //鍔熻兘灞炴�у搷搴�
+    public static final String GET_FUNCTION_ATTRIBUTE_REPLY = "/user/%s/custom/function/attribute/get_reply";
+
+    //鎺у埗
+    public static final String PROPERTY_DOWN = "/base/%s/thing/property/down";
+
+    //鎺у埗鍝嶅簲
+    public static final String PROPERTY_DOWN_REPLY = "/base/%s/thing/property/down_reply";
+
+    //鐘舵�佷笂鎶�
+    public static final String PROPERTY_UP = "/base/%s/thing/property/up";
+
+    //鐘舵�佷笂鎶ュ搷搴�
+    public static final String PROPERTY_UP_REPLY = "/base/%s/thing/property/up_reply";
+
+    //璇诲彇鐘舵��
+    public static final String PROPERTY_READ = "/base/%s/thing/property/read";
+
+    //璇诲彇鐘舵�佸搷搴�
+    public static final String PROPERTY_READ_REPLY = "/base/%s/thing/property/read_reply";
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java
new file mode 100644
index 0000000..b17b3a8
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java
@@ -0,0 +1,132 @@
+package com.hdl.sdk.common.event;
+
+import androidx.annotation.NonNull;
+import androidx.collection.ArrayMap;
+
+
+import com.hdl.sdk.common.utils.ThreadToolUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+
+
+/**
+ * Created by Tong on 2021/9/22.
+ * 浜嬩欢鍒嗗彂
+ */
+public class EventDispatcher {
+
+    private static final ArrayMap<Object, List<EventListener>> EVENT = new ArrayMap<>();
+
+    private static final ArrayMap<EventListener, Integer> TYPE = new ArrayMap<>();
+
+    private static final int MAIN_TYPE = 0;
+    private static final int IO_TYPE = 1;
+
+    private static final ExecutorService ioThread = ThreadToolUtils.getInstance().newFixedThreadPool(2);
+
+    private EventDispatcher() {
+    }
+
+    private static class SingletonInstance {
+        private static final EventDispatcher INSTANCE = new EventDispatcher();
+    }
+
+    public static EventDispatcher getInstance() {
+        return SingletonInstance.INSTANCE;
+    }
+
+    public synchronized void register(Object tag, EventListener listener) {
+        if (!EVENT.containsKey(tag)) {
+            EVENT.put(tag, new ArrayList<>());
+        }
+        List<EventListener> events = EVENT.get(tag);
+        if (events != null && !events.contains(listener)) {
+            events.add(listener);
+        }
+        TYPE.put(listener, MAIN_TYPE);
+    }
+
+    public synchronized void registerIo(Object tag, EventListener listener) {
+        if (!EVENT.containsKey(tag)) {
+            EVENT.put(tag, new ArrayList<>());
+        }
+        List<EventListener> events = EVENT.get(tag);
+        if (events != null && !events.contains(listener)) {
+            events.add(listener);
+        }
+        TYPE.put(listener, IO_TYPE);
+    }
+
+    public synchronized void remove(Object tag) {
+        ioThread.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    if (EVENT.containsKey(tag)) {
+                        List<EventListener> list = EVENT.get(tag);
+                        for (EventListener eventListener : list) {
+                            TYPE.remove(eventListener);
+                        }
+                        EVENT.remove(tag);
+                    }
+                } catch (Exception ignored) {
+
+                }
+
+            }
+        });
+    }
+
+    public synchronized void remove(Object tag, EventListener listener) {
+        ioThread.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    if (EVENT.containsKey(tag)) {
+                        List<EventListener> ev = EVENT.get(tag);
+                        if (ev != null && !ev.isEmpty()) {
+                            TYPE.remove(listener);
+                            ev.remove(listener);
+                        }
+                    }
+                } catch (Exception ignored) {
+
+                }
+
+            }
+        });
+    }
+
+    public synchronized void post(Object tag, @NonNull Object o) {
+        if (EVENT.containsKey(tag)) {
+            List<EventListener> list = EVENT.get(tag);
+            if (list != null && !list.isEmpty()) {
+                for (EventListener listener : list) {
+                    ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (listener != null) {
+                                listener.onMessage(o);
+                            }
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    public synchronized void clear() {
+        EVENT.clear();
+        TYPE.clear();
+    }
+
+    public synchronized void release() {
+        clear();
+        ioThread.shutdownNow();
+    }
+
+
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventListener.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventListener.java
new file mode 100644
index 0000000..eb82740
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/event/EventListener.java
@@ -0,0 +1,10 @@
+package com.hdl.sdk.common.event;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public interface EventListener {
+
+    void onMessage(Object msg);
+
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java
new file mode 100644
index 0000000..ff641db
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java
@@ -0,0 +1,134 @@
+package com.hdl.sdk.common.utils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by Tong on 2021/9/23.
+ */
+public class ByteUtils {
+
+    public static byte[] toByteArray(List<Byte> list) {
+        Byte[] temps = list.toArray(new Byte[0]);
+        byte[] result = new byte[temps.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = temps[i];
+        }
+        return result;
+
+    }
+
+    public static List<Byte> toByteList(byte[] bytes) {
+        final List<Byte> list = new ArrayList<>();
+        for (byte aByte : bytes) {
+            list.add(aByte);
+        }
+        return list;
+
+    }
+
+    public static byte[] getRangeBytes(List<Byte> list, int start, int end) {
+        Byte[] temps = Arrays.copyOfRange(list.toArray(new Byte[0]), start, end);
+        byte[] result = new byte[temps.length];
+        for (int i = 0; i < temps.length; i++) {
+            result[i] = temps[i];
+        }
+        return result;
+
+    }
+
+    /**
+     * 鎷兼帴byte
+     */
+    public static byte[] concatBytes(byte[] bt1, byte[] bt2) {
+        if (bt1 == null) {
+            return bt2;
+        }
+        if (bt2 == null) {
+            return bt1;
+        }
+        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;
+    }
+
+
+    public boolean endWith(Byte[] src, byte[] target) {
+        if (src.length < target.length) {
+            return false;
+        }
+        for (int i = 0; i < target.length; i++) {
+            if (target[target.length - i - 1] != src[src.length - i - 1]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    public static int byteIndexOf(byte[] searched, byte[] find, int start) {
+        boolean matched;
+        int end = find.length - 1;
+        int skip = 0;
+        for (int index = start; index <= searched.length - find.length; ++index) {
+            matched = true;
+            if (find[0] != searched[index] || find[end] != searched[index + end]) continue;
+            else skip++;
+            if (end > 10)
+                if (find[skip] != searched[index + skip] || find[end - skip] != searched[index + end - skip])
+                    continue;
+                else skip++;
+            for (int subIndex = skip; subIndex < find.length - skip; ++subIndex) {
+                if (find[subIndex] != searched[index + subIndex]) {
+                    matched = false;
+                    break;
+                }
+            }
+            if (matched) {
+                return index;
+            }
+        }
+        return -1;
+
+    }
+
+    public static int getByteIndexOf(byte[] sources, byte[] src) {
+        return getByteIndexOf(sources, src, 0, sources.length);
+    }
+
+    //鍒ゆ柇涓�涓猙yte鏁板�煎湪鍙﹀涓�涓猙yte鏁扮粍涓搴旂殑娓告爣鍊�
+    public static int getByteIndexOf(byte[] sources, byte[] src, int startIndex) {
+        return getByteIndexOf(sources, src, startIndex, sources.length);
+    }
+
+
+    //鍒ゆ柇涓�涓猙yte鏁板�煎湪鍙﹀涓�涓猙yte鏁扮粍涓搴旂殑娓告爣鍊硷紝鎸囧畾寮�濮嬬殑娓告爣鍜岀粨鏉熺殑娓告爣浣嶇疆
+    public static int getByteIndexOf(byte[] sources, byte[] src, int startIndex, int endIndex) {
+
+        if (sources == null || src == null || sources.length == 0 || src.length == 0) {
+            return -1;
+        }
+
+        if (endIndex > sources.length) {
+            endIndex = sources.length;
+        }
+
+        int i, j;
+        for (i = startIndex; i < endIndex; i++) {
+            if (sources[i] == src[0] && i + src.length < endIndex) {
+                for (j = 1; j < src.length; j++) {
+                    if (sources[i + j] != src[j]) {
+                        break;
+                    }
+                }
+
+                if (j == src.length) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IdUtils.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IdUtils.java
new file mode 100644
index 0000000..97181a7
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IdUtils.java
@@ -0,0 +1,12 @@
+package com.hdl.sdk.common.utils;
+
+import java.util.UUID;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class IdUtils {
+    public static String getUUId() {
+        return UUID.randomUUID().toString().replaceAll("-", "");
+    }
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IpUtils.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IpUtils.java
new file mode 100644
index 0000000..f35cfb9
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/IpUtils.java
@@ -0,0 +1,72 @@
+package com.hdl.sdk.common.utils;
+
+import android.content.Context;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+
+import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+/**
+ * Created by Tong on 2021/9/27.
+ */
+public class IpUtils {
+
+    /**
+     * @return 骞挎挱鍦板潃
+     */
+    public static String getBroadcastAddress() {
+        try {
+            for (Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
+                 niEnum.hasMoreElements(); ) {
+                NetworkInterface ni = niEnum.nextElement();
+                if (!ni.isLoopback()) {
+                    for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
+                        if (interfaceAddress.getBroadcast() != null) {
+                            return interfaceAddress.getBroadcast().toString().substring(1);
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            e.printStackTrace();
+        }
+        return "255.255.255.255";
+    }
+
+    public static String getIP(Context application) {
+        WifiManager wifiManager = (WifiManager) application.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+        if (!wifiManager.isWifiEnabled()) {
+            try {
+                for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
+                    NetworkInterface intf = en.nextElement();
+                    for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+                        InetAddress inetAddress = enumIpAddr.nextElement();
+                        if (!inetAddress.isLoopbackAddress()) {
+                            return inetAddress.getHostAddress();
+                        }
+                    }
+                }
+            } catch (SocketException e) {
+                e.printStackTrace();
+            }
+        } else {
+            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+            int ipAddress = wifiInfo.getIpAddress();
+            return intToIp(ipAddress);
+        }
+        return null;
+    }
+
+
+    private static String intToIp(int i) {
+
+        return (i & 0xFF) + "." +
+                ((i >> 8) & 0xFF) + "." +
+                ((i >> 16) & 0xFF) + "." +
+                (i >> 24 & 0xFF);
+    }
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/LogUtils.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/LogUtils.java
new file mode 100644
index 0000000..22ab283
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/LogUtils.java
@@ -0,0 +1,51 @@
+package com.hdl.sdk.common.utils;
+
+/**
+ * Created by Tong on 2021/9/23.
+ */
+public class LogUtils {
+
+    private static final String TAG = "HDLSocket";
+
+    private boolean isEnabled = true;
+
+
+    private LogUtils() {
+    }
+
+    private static class SingletonInstance {
+        private static final LogUtils INSTANCE = new LogUtils();
+    }
+
+    public static LogUtils getInstance() {
+        return SingletonInstance.INSTANCE;
+    }
+
+    public boolean isEnabled() {
+        return isEnabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        isEnabled = enabled;
+    }
+
+    public static void d(String tag, String msg) {
+
+    }
+
+    public static void e(String tag, String msg) {
+
+    }
+
+    public static void w(String tag, String msg) {
+
+    }
+
+    public static void v(String tag, String msg) {
+
+    }
+
+    public static void i(String tag, String msg) {
+
+    }
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/SPUtils.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/SPUtils.java
new file mode 100644
index 0000000..bbdd808
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/SPUtils.java
@@ -0,0 +1,151 @@
+package com.hdl.sdk.common.utils;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import androidx.annotation.NonNull;
+
+import com.hdl.sdk.common.HDLSdk;
+
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Created by Tong on 2021/9/28.
+ */
+public class SPUtils {
+    private static final String APP_PREFERENCES_KEY = "profile";
+    private static final SharedPreferences PREFERENCES =
+            HDLSdk.getInstance().getContext().getApplicationContext().getSharedPreferences(APP_PREFERENCES_KEY, Context.MODE_PRIVATE);
+
+    private static SharedPreferences getAppPreference() {
+        return PREFERENCES;
+    }
+
+
+    //======閫氱敤瀛樺偍========
+    public static void put(@NonNull final String key, final String value) {
+        getAppPreference().edit().putString(key, value).apply();
+    }
+
+
+    public static String getString(@NonNull final String key) {
+        return getString(key, "");
+    }
+
+
+    public static String getString(@NonNull final String key, final String defaultValue) {
+        return getAppPreference().getString(key, defaultValue);
+    }
+
+
+    public static void put(@NonNull final String key, final int value) {
+        put(key, value, false);
+    }
+
+
+    public static void put(@NonNull final String key, final int value, final boolean isCommit) {
+        getAppPreference().edit().putInt(key, value).apply();
+    }
+
+
+    public static int getInt(@NonNull final String key) {
+        return getInt(key, -1);
+    }
+
+
+    public static int getInt(@NonNull final String key, final int defaultValue) {
+        return getAppPreference().getInt(key, defaultValue);
+    }
+
+
+    public static void put(@NonNull final String key, final long value) {
+        getAppPreference().edit().putLong(key, value).apply();
+    }
+
+
+    public static long getLong(@NonNull final String key) {
+        return getLong(key, -1L);
+    }
+
+
+    public static long getLong(@NonNull final String key, final long defaultValue) {
+        return getAppPreference().getLong(key, defaultValue);
+    }
+
+
+    public static void put(@NonNull final String key, final float value) {
+        getAppPreference().edit().putFloat(key, value).apply();
+    }
+
+
+    public static float getFloat(@NonNull final String key) {
+        return getFloat(key, -1f);
+    }
+
+
+    public static float getFloat(@NonNull final String key, final float defaultValue) {
+        return getAppPreference().getFloat(key, defaultValue);
+    }
+
+
+    public static void put(@NonNull final String key, final boolean value) {
+        getAppPreference().edit().putBoolean(key, value).apply();
+    }
+
+
+    public static boolean getBoolean(@NonNull final String key) {
+        return getBoolean(key, false);
+    }
+
+
+    public static boolean getBoolean(@NonNull final String key, final boolean defaultValue) {
+        return getAppPreference().getBoolean(key, defaultValue);
+    }
+
+
+    public static void put(@NonNull final String key,
+                           final Set<String> value
+    ) {
+
+        getAppPreference().edit().putStringSet(key, value).apply();
+
+    }
+
+
+    public static Set<String> getStringSet(@NonNull final String key) {
+        return getStringSet(key, Collections.<String>emptySet());
+    }
+
+
+    public static Set<String> getStringSet(@NonNull final String key,
+                                           final Set<String> defaultValue) {
+        return getAppPreference().getStringSet(key, defaultValue);
+    }
+
+
+    public static Map<String, ?> getAll() {
+        return getAppPreference().getAll();
+    }
+
+
+    public static boolean contains(@NonNull final String key) {
+        return getAppPreference().contains(key);
+    }
+
+
+    public static void remove(@NonNull final String key) {
+        getAppPreference().edit().remove(key).apply();
+    }
+
+    public static void clear() {
+        getAppPreference()
+                .edit()
+                .clear()
+                .apply();
+    }
+
+
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ThreadToolUtils.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ThreadToolUtils.java
new file mode 100644
index 0000000..d42da84
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/ThreadToolUtils.java
@@ -0,0 +1,72 @@
+package com.hdl.sdk.common.utils;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * Created by Tong on 2021/9/15.
+ */
+public class ThreadToolUtils {
+
+    private final Handler uiHandler = new Handler(Looper.getMainLooper());
+
+    //cpu 鏈�澶х嚎绋嬪绾抽噺
+    private final int coreSize = Runtime.getRuntime().availableProcessors() + 1;
+
+    private ThreadToolUtils() {
+    }
+
+    private static class SingletonInstance {
+        private static final ThreadToolUtils INSTANCE = new ThreadToolUtils();
+    }
+
+    public static ThreadToolUtils getInstance() {
+        return SingletonInstance.INSTANCE;
+    }
+
+
+    /**
+     * 绾跨▼鏁伴噺鍥哄畾鐨勭嚎绋嬫睜
+     */
+    public ExecutorService newFixedThreadPool(int size) {
+        if (size == 0 || coreSize < size) {
+            return Executors.newFixedThreadPool(coreSize);
+        }
+        return Executors.newFixedThreadPool(size);
+    }
+
+    /**
+     * 瀹氭椂浠诲姟绾跨▼姹�
+     */
+    public ScheduledExecutorService newScheduledThreadPool(int size) {
+        if (size == 0 || coreSize < size) {
+            return Executors.newScheduledThreadPool(coreSize);
+        }
+        return Executors.newScheduledThreadPool(size);
+    }
+
+    /**
+     * 鍗曚竴绾跨▼
+     */
+    public ExecutorService newSingleThreadPool() {
+        return Executors.newSingleThreadExecutor();
+    }
+
+
+    public ExecutorService newCachedThreadPool() {
+        return Executors.newCachedThreadPool();
+    }
+
+    /**
+     * 鍒囨崲鍥炰富绾跨▼
+     */
+    public void runOnUiThread(Runnable run) {
+        uiHandler.post(run);
+    }
+
+
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/GsonConvert.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/GsonConvert.java
new file mode 100644
index 0000000..f38cfa9
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/GsonConvert.java
@@ -0,0 +1,55 @@
+package com.hdl.sdk.common.utils.gson;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+
+/**
+ * Created by Tong on 2021/9/8.
+ */
+public class GsonConvert {
+
+    private static Gson gson = null;
+
+    public static Gson getGson() {
+        if (gson == null) {
+            synchronized (GsonConvert.class) {
+                if (gson == null) {
+                    gson = new GsonBuilder()
+                            .setPrettyPrinting()
+                            .disableHtmlEscaping()
+                            .registerTypeAdapter(String.class, new StringTypeAdapter())
+                            .create();
+                }
+            }
+        }
+        return gson;
+    }
+
+    private static class StringTypeAdapter implements JsonSerializer<String>, JsonDeserializer<String> {
+        @Override
+        public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+                throws JsonParseException {
+            if (json instanceof JsonPrimitive) {
+                return json.getAsString();
+            } else {
+                return json.toString();
+            }
+        }
+
+        @Override
+        public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
+            return new JsonPrimitive(src);
+        }
+    }
+
+
+}
diff --git a/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/ParameterizedTypeImpl.java b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/ParameterizedTypeImpl.java
new file mode 100644
index 0000000..fd122d8
--- /dev/null
+++ b/HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/utils/gson/ParameterizedTypeImpl.java
@@ -0,0 +1,46 @@
+package com.hdl.sdk.common.utils.gson;
+
+
+import androidx.annotation.NonNull;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Created by Tong on 2021/9/17.
+ */
+public class ParameterizedTypeImpl implements ParameterizedType {
+
+    private final Type[] actualTypeArguments;
+    private final Type rawType;
+    private final Type ownerType;
+
+    public ParameterizedTypeImpl(Type rawType, Type[] actualTypeArguments, Type ownerType) {
+        this.ownerType = ownerType;
+        this.rawType = rawType;
+        this.actualTypeArguments = actualTypeArguments;
+    }
+
+    public static Type getType(Type rawType, Type[] actualTypeArguments) {
+        return new ParameterizedTypeImpl(rawType, actualTypeArguments, null);
+    }
+
+    @NonNull
+    @Override
+    public Type[] getActualTypeArguments() {
+        return actualTypeArguments;
+    }
+
+
+    @NonNull
+    @Override
+    public Type getRawType() {
+        return rawType;
+    }
+
+
+    @Override
+    public Type getOwnerType() {
+        return ownerType;
+    }
+}
diff --git a/HDLSDK/hdl-common/src/test/java/com/hdl/sdk/common/ExampleUnitTest.java b/HDLSDK/hdl-common/src/test/java/com/hdl/sdk/common/ExampleUnitTest.java
new file mode 100644
index 0000000..6e8323f
--- /dev/null
+++ b/HDLSDK/hdl-common/src/test/java/com/hdl/sdk/common/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.hdl.sdk.common;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-connect/.gitignore b/HDLSDK/hdl-connect/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/HDLSDK/hdl-connect/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/HDLSDK/hdl-connect/build.gradle b/HDLSDK/hdl-connect/build.gradle
new file mode 100644
index 0000000..74a62e0
--- /dev/null
+++ b/HDLSDK/hdl-connect/build.gradle
@@ -0,0 +1,34 @@
+plugins {
+    id 'com.android.library'
+}
+
+android {
+    compileSdkVersion rootProject.compileSdkVersion
+
+    defaultConfig {
+        minSdkVersion rootProject.minSdkVersion
+        targetSdkVersion rootProject.targetSdkVersion
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+    api project(path: ':hdl-socket')
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation 'com.google.android.material:material:1.3.0'
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-connect/consumer-rules.pro b/HDLSDK/hdl-connect/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/HDLSDK/hdl-connect/consumer-rules.pro
diff --git a/HDLSDK/hdl-connect/proguard-rules.pro b/HDLSDK/hdl-connect/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/HDLSDK/hdl-connect/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/HDLSDK/hdl-connect/src/androidTest/java/com/hdl/sdk/connect/ExampleInstrumentedTest.java b/HDLSDK/hdl-connect/src/androidTest/java/com/hdl/sdk/connect/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..32322d2
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/androidTest/java/com/hdl/sdk/connect/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.hdl.sdk.connect;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.hdl.sdk.connect.test", appContext.getPackageName());
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-connect/src/main/AndroidManifest.xml b/HDLSDK/hdl-connect/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c3b028e
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.hdl.sdk.connect">
+
+</manifest>
\ No newline at end of file
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLSocket.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLSocket.java
new file mode 100644
index 0000000..00cb3a2
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLSocket.java
@@ -0,0 +1,650 @@
+package com.hdl.sdk.connect;
+
+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;
+import com.hdl.sdk.common.event.EventDispatcher;
+import com.hdl.sdk.common.event.EventListener;
+import com.hdl.sdk.common.utils.IdUtils;
+import com.hdl.sdk.common.utils.IpUtils;
+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.BaseLocalRequest;
+import com.hdl.sdk.connect.bean.BaseLocalResponse;
+import com.hdl.sdk.connect.bean.DeviceControlRequest;
+import com.hdl.sdk.connect.bean.FunctionAttributeRequest;
+import com.hdl.sdk.connect.bean.GatewaySearchBean;
+import com.hdl.sdk.connect.bean.LinkRequest;
+import com.hdl.sdk.connect.bean.LinkResponse;
+import com.hdl.sdk.connect.bean.PropertyReadRequest;
+import com.hdl.sdk.connect.bean.PropertyUpRequest;
+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.TcpClient;
+import com.hdl.sdk.socket.client.UdpClient;
+import com.hdl.sdk.socket.codec.MessagePipeLine;
+import com.hdl.sdk.socket.listener.ConnectStatusListener;
+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;
+
+/**
+ * Created by Tong on 2021/9/26.
+ * 1銆侀�氳繃Udp 缁勬挱鎴栬�呭箍鎾悳绱㈢綉鍏�
+ * 2銆侀�氳繃Udp 鑾峰彇Tcp ip 绔彛缁熶竴8586
+ */
+public class HDLSocket {
+
+    private static final String GATEWAY_KEY = "gateway_key";
+    private static final String TCP_IP_KEY = "tcp_ip_key";
+    private String gatewayId;
+
+    public interface CallBack {
+
+        void onError(String error);
+
+        void onResponse(String data);
+
+    }
+
+    /**
+     * udp榛樿缁勬挱ip
+     */
+    private static final String UDP_GROUP_IP = "239.0.168.188";
+
+    /**
+     * udp榛樿绔彛
+     */
+    private static final int UDP_PORT = 8585;
+
+    /**
+     * tcp榛樿绔彛
+     */
+    private static final int TCP_PORT = 8586;
+
+    private String tcpIp;
+    private int tcpPort;
+
+    private int udpPort;
+    private String udpIp;
+
+    private static SocketBoot updBoot;
+    private SocketBoot tcpBoot;
+
+    private ConnectStatusListener statusListener;
+
+    private EventListener searchEvent;
+    private CallBack searchCallBack;
+    private ScheduledExecutorService searchGatewayThread;
+    private final AtomicInteger searchCount = new AtomicInteger(0);
+
+    private HDLSocket() {
+        statusListener = new ConnectStatusListener() {
+            @Override
+            public void onConnecting() {
+
+            }
+
+            @Override
+            public void onConnected() {
+
+            }
+
+            @Override
+            public void onConnectFailed() {
+
+            }
+        };
+        searchEvent = new EventListener() {
+            @Override
+            public void onMessage(Object msg) {
+                try {
+                    if (msg instanceof LinkResponse) {
+                        LinkResponse linkResponse = (LinkResponse) msg;
+                        String data = linkResponse.getData();
+                        if (!TextUtils.isEmpty(data)) {
+                            final BaseLocalResponse<GatewaySearchBean> response = GsonConvert.getGson().fromJson(data, new TypeToken<BaseLocalResponse<GatewaySearchBean>>() {
+                            }.getType());
+                            GatewaySearchBean searchBean = response.getObjects();
+                            if (searchBean != null) {
+                                gatewayId = searchBean.getGatewayId();
+                                if (!TextUtils.isEmpty(gatewayId)) {
+                                    SPUtils.put(GATEWAY_KEY, gatewayId);
+                                }
+                                tcpIp = searchBean.getIp_address();
+                                if (!TextUtils.isEmpty(tcpIp)) {
+                                    SPUtils.put(TCP_IP_KEY, tcpIp);
+                                }
+                            }
+
+                            if (searchCallBack != null) {
+                                searchCallBack.onResponse(linkResponse.toString());
+                            }
+                        }
+
+                    }
+                } catch (Exception e) {
+                    if (searchCallBack != null) {
+                        searchCallBack.onError("瑙f瀽澶辫触");
+                    }
+                }
+
+
+            }
+        };
+    }
+
+    private static class SingletonInstance {
+        private static final HDLSocket INSTANCE = new HDLSocket();
+    }
+
+    public static HDLSocket getInstance() {
+        return SingletonInstance.INSTANCE;
+    }
+
+
+    private SocketOptions getUdpOptions() {
+        final SocketOptions options = new SocketOptions();
+        final MessagePipeLine pipeLine = new MessagePipeLine();
+        pipeLine.add(new LinkMessageDecoder());
+        pipeLine.add(new LinkMessageEncoder());
+        options.setHandleMessage(pipeLine);
+        options.setEnabledHeartbeat(false);
+        return options;
+    }
+
+    private SocketOptions getTcpOptions() {
+        final SocketOptions options = new SocketOptions();
+        final MessagePipeLine pipeLine = new MessagePipeLine();
+        pipeLine.add(new LinkMessageDecoder());
+        pipeLine.add(new LinkMessageEncoder());
+        options.setHandleMessage(pipeLine);
+        options.setEnabledHeartbeat(false);
+        return options;
+    }
+
+    private int getUdpPort() {
+        return UDP_PORT;
+    }
+
+    public int getTcpPort() {
+        return TCP_PORT;
+    }
+
+    public String getTcpIp() {
+        if (!TextUtils.isEmpty(tcpIp)) {
+            return tcpIp;
+        }
+        return SPUtils.getString(TCP_IP_KEY, "");
+    }
+
+    public String getGatewayId() {
+        if (!TextUtils.isEmpty(gatewayId)) {
+            return gatewayId;
+        }
+        return SPUtils.getString(GATEWAY_KEY, "");
+    }
+
+
+    private String getUdpIp() {
+        if (TextUtils.isEmpty(udpIp)) {
+            udpIp = UDP_GROUP_IP;
+        }
+        return udpIp;
+    }
+
+    public void searchGateway() {
+        searchGateway(null);
+    }
+
+    /**
+     * 缁勬挱鎼滅储
+     */
+    public void searchGateway(CallBack callBack) {
+        this.searchCallBack = callBack;
+
+        if (searchGatewayThread != null) {
+            searchGatewayThread.shutdownNow();
+        }
+
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                while (TextUtils.isEmpty(gatewayId)) {
+                    //鎼滅储缃戝叧
+                    searchGateway(IdUtils.getUUId(), searchEvent);
+                    try {
+                        Thread.sleep(1000L);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }).start();
+    }
+
+
+    /**
+     * 閫氳繃缁勬挱鎼滅储缃戝叧
+     */
+    public void searchGateway(String msgId, EventListener eventListener) {
+        searchGateway(getUdpIp(), getUdpPort(), msgId, eventListener);
+    }
+
+    /**
+     * 閫氳繃骞挎挱鎼滅储缃戝叧
+     */
+    public void searchGatewayByBroadcast(String msgId, EventListener eventListener) {
+        searchGateway(IpUtils.getBroadcastAddress(), getUdpPort(), msgId, eventListener);
+    }
+
+    /**
+     * 榛樿鏄粍鎾悳绱㈢綉鍏�
+     */
+    public void searchGateway(String ip, int port, String msgId, EventListener eventListener) {
+
+        if (updBoot == null) {
+            updBoot = UdpClient.init(ip, port, getUdpOptions());
+            updBoot.connect();
+        }
+
+
+        String time = String.valueOf(System.currentTimeMillis());
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.addProperty("id", msgId);
+        jsonObject.addProperty("time_stamp", time);
+
+        EventDispatcher.getInstance().registerIo(TopicConstant.GATEWAY_SEARCH_REPLY, eventListener);
+        LinkRequest message = new LinkRequest(TopicConstant.GATEWAY_SEARCH,
+                jsonObject.toString());
+
+        try {
+            updBoot.sendMsg(message.toString().getBytes("utf-8"));
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+
+    /**
+     * 鑾峰彇璁惧鍒楄〃
+     */
+    public void getDeviceList(CallBack callBack) {
+        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
+            String time = String.valueOf(System.currentTimeMillis());
+            JsonObject jsonObject = new JsonObject();
+            jsonObject.addProperty("id", IdUtils.getUUId());
+            jsonObject.addProperty("time_stamp", time);
+
+            String topic = String.format(TopicConstant.GET_DEVICE_LIST, getGatewayId());
+
+            LinkRequest message = new LinkRequest(topic,
+                    jsonObject.toString());
+
+            String replyTopic = String.format(TopicConstant.GET_DEVICE_LIST_REPLY, getGatewayId());
+            try {
+                sendMsg(message.toString().getBytes("utf-8"), replyTopic, callBack, new SendListener() {
+                    @Override
+                    public void onSucceed() {
+
+                    }
+
+                    @Override
+                    public void onError() {
+                        if (callBack != null) {
+                            callBack.onError("鑾峰彇璁惧鍒楄〃澶辫触");
+                        }
+                    }
+                });
+            } catch (UnsupportedEncodingException e) {
+                if (callBack != null) {
+                    callBack.onError("鑾峰彇璁惧鍒楄〃澶辫触");
+                }
+            }
+        } else {
+            if (callBack != null) {
+                callBack.onError("ip鍦板潃涓㈠け");
+            }
+        }
+    }
+
+
+    /**
+     * 鑾峰彇鍔熻兘鍒楄〃
+     */
+    public void getFunctionList(CallBack callBack) {
+        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
+            String time = String.valueOf(System.currentTimeMillis());
+            JsonObject jsonObject = new JsonObject();
+            jsonObject.addProperty("id", IdUtils.getUUId());
+            jsonObject.addProperty("time_stamp", time);
+
+            String topic = String.format(TopicConstant.GET_FUNCTION_LIST, getGatewayId());
+
+            LinkRequest message = new LinkRequest(topic,
+                    jsonObject.toString());
+
+            String replyTopic = String.format(TopicConstant.GET_FUNCTION_LIST_REPLY, getGatewayId());
+            try {
+                sendMsg(message.toString().getBytes("utf-8"), replyTopic, callBack, new SendListener() {
+                    @Override
+                    public void onSucceed() {
+
+                    }
+
+                    @Override
+                    public void onError() {
+                        if (callBack != null) {
+                            callBack.onError("鑾峰彇鍔熻兘鍒楄〃澶辫触");
+                        }
+                    }
+                });
+            } catch (UnsupportedEncodingException e) {
+                if (callBack != null) {
+                    callBack.onError("鑾峰彇鍔熻兘鍒楄〃澶辫触");
+                }
+            }
+        } else {
+            if (callBack != null) {
+                callBack.onError("ip鍦板潃涓㈠け");
+            }
+        }
+    }
+
+
+    /**
+     * 鑾峰彇鍔熻兘灞炴��
+     *
+     * @param callBack
+     * @param sid
+     */
+    public void getFunctionAttribute(CallBack callBack, String... sid) {
+        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
+            String time = String.valueOf(System.currentTimeMillis());
+
+            final BaseLocalResponse<List<FunctionAttributeRequest>> data = new BaseLocalResponse<>();
+            data.setId(IdUtils.getUUId());
+            data.setTime_stamp(time);
+            List<FunctionAttributeRequest> list = new ArrayList<>();
+            for (String s : sid) {
+                list.add(new FunctionAttributeRequest(s));
+            }
+            data.setObjects(list);
+
+            String topic = String.format(TopicConstant.GET_FUNCTION_ATTRIBUTE, getGatewayId());
+            LinkRequest message = new LinkRequest(topic,
+                    GsonConvert.getGson().toJson(data));
+
+            String replyTopic = String.format(TopicConstant.GET_FUNCTION_ATTRIBUTE_REPLY, getGatewayId());
+            try {
+                sendMsg(message.toString().getBytes("utf-8"), replyTopic, callBack, new SendListener() {
+                    @Override
+                    public void onSucceed() {
+
+                    }
+
+                    @Override
+                    public void onError() {
+                        if (callBack != null) {
+                            callBack.onError("鑾峰彇鍔熻兘灞炴�уけ璐�");
+                        }
+                    }
+                });
+            } catch (UnsupportedEncodingException e) {
+                if (callBack != null) {
+                    callBack.onError("鑾峰彇鍔熻兘灞炴�уけ璐�");
+                }
+            }
+        } else {
+            if (callBack != null) {
+                callBack.onError("ip鍦板潃涓㈠け");
+            }
+        }
+    }
+
+    /**
+     * 璁惧鎺у埗
+     */
+    public void propertyDown(List<DeviceControlRequest> request, CallBack callBack) {
+
+        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
+            String time = String.valueOf(System.currentTimeMillis());
+
+            final BaseLocalResponse<List<DeviceControlRequest>> data = new BaseLocalResponse<>();
+            data.setId(IdUtils.getUUId());
+            data.setTime_stamp(time);
+            data.setObjects(request);
+
+
+            String topic = String.format(TopicConstant.PROPERTY_DOWN, getGatewayId());
+            LinkRequest message = new LinkRequest(topic,
+                    GsonConvert.getGson().toJson(request));
+
+            String replyTopic = String.format(TopicConstant.PROPERTY_DOWN_REPLY, getGatewayId());
+            try {
+                sendMsg(message.toString().getBytes("utf-8"), replyTopic, callBack, new SendListener() {
+                    @Override
+                    public void onSucceed() {
+
+                    }
+
+                    @Override
+                    public void onError() {
+                        if (callBack != null) {
+                            callBack.onError("鎺у埗鎸囦护鍙戦�佸け璐�");
+                        }
+                    }
+                });
+            } catch (UnsupportedEncodingException e) {
+                if (callBack != null) {
+                    callBack.onError("鎺у埗鎸囦护鍙戦�佸け璐�");
+                }
+            }
+        } else {
+            if (callBack != null) {
+                callBack.onError("鎺у埗鎸囦护鍙戦�佸け璐�");
+            }
+        }
+
+    }
+
+    /**
+     * 鐘舵�佷笂鎶�
+     */
+    public void propertyUp(List<PropertyUpRequest> request, CallBack callBack) {
+        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
+            String time = String.valueOf(System.currentTimeMillis());
+
+            final BaseLocalResponse<List<PropertyUpRequest>> data = new BaseLocalResponse<>();
+            data.setId(IdUtils.getUUId());
+            data.setTime_stamp(time);
+            data.setObjects(request);
+
+
+            String topic = String.format(TopicConstant.PROPERTY_UP, getGatewayId());
+            LinkRequest message = new LinkRequest(topic,
+                    GsonConvert.getGson().toJson(request));
+
+            String replyTopic = String.format(TopicConstant.PROPERTY_UP_REPLY, getGatewayId());
+            try {
+                sendMsg(message.toString().getBytes("utf-8"), replyTopic, callBack, new SendListener() {
+                    @Override
+                    public void onSucceed() {
+
+                    }
+
+                    @Override
+                    public void onError() {
+                        if (callBack != null) {
+                            callBack.onError("鎸囦护鍙戦�佸け璐�");
+                        }
+                    }
+                });
+            } catch (UnsupportedEncodingException e) {
+                if (callBack != null) {
+                    callBack.onError("鎸囦护鍙戦�佸け璐�");
+                }
+            }
+        } else {
+            if (callBack != null) {
+                callBack.onError("鎸囦护鍙戦�佸け璐�");
+            }
+        }
+    }
+
+    /**
+     * 璇诲彇鐘舵��
+     */
+    public void propertyRead(List<PropertyReadRequest> request, CallBack callBack) {
+        if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) {
+            String time = String.valueOf(System.currentTimeMillis());
+
+            final BaseLocalResponse<List<PropertyReadRequest>> data = new BaseLocalResponse<>();
+            data.setId(IdUtils.getUUId());
+            data.setTime_stamp(time);
+            data.setObjects(request);
+
+
+            String topic = String.format(TopicConstant.PROPERTY_READ, getGatewayId());
+            LinkRequest message = new LinkRequest(topic,
+                    GsonConvert.getGson().toJson(request));
+
+            String replyTopic = String.format(TopicConstant.PROPERTY_READ_REPLY, getGatewayId());
+            try {
+                sendMsg(message.toString().getBytes("utf-8"), replyTopic, callBack, new SendListener() {
+                    @Override
+                    public void onSucceed() {
+
+                    }
+
+                    @Override
+                    public void onError() {
+                        if (callBack != null) {
+                            callBack.onError("鎸囦护鍙戦�佸け璐�");
+                        }
+                    }
+                });
+            } catch (UnsupportedEncodingException e) {
+                if (callBack != null) {
+                    callBack.onError("鎸囦护鍙戦�佸け璐�");
+                }
+            }
+        } else {
+            if (callBack != null) {
+                callBack.onError("鎸囦护鍙戦�佸け璐�");
+            }
+        }
+    }
+
+    public SocketBoot getTcp() throws RuntimeException {
+        if (TextUtils.isEmpty(getTcpIp())) {
+            throw new RuntimeException("璇锋悳绱㈢綉鍏�");
+        }
+        if (tcpBoot == null) {
+            tcpBoot = TcpClient.init(getTcpIp(), getTcpPort(), getTcpOptions());
+        }
+        return tcpBoot;
+    }
+
+    /**
+     * 娓呯┖缂撳瓨
+     */
+    public void clearCache() {
+        SPUtils.remove(TCP_IP_KEY);
+        SPUtils.remove(GATEWAY_KEY);
+    }
+
+
+    /**
+     * 鍙戦�佹寚浠�
+     * 1绉掓病鍝嶅簲灏辫浠栭噸鏂板彂閫�,閲嶈瘯3娆�
+     */
+    public void sendMsg(byte[] data, String eventTag, CallBack callBack, SendListener sendListener) {
+
+        try {
+            final AtomicInteger sendCount = new AtomicInteger(0);
+
+            final ScheduledExecutorService threadPool = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
+            final EventListener eventListener = new EventListener() {
+                @Override
+                public void onMessage(Object msg) {
+                    if (msg instanceof LinkResponse) {
+
+                        if (callBack != null) {
+                            callBack.onResponse(msg.toString());
+                        }
+                        threadPool.shutdownNow();
+                    }
+                }
+            };
+
+            threadPool.scheduleWithFixedDelay(new Runnable() {
+                @Override
+                public void run() {
+                    if (sendCount.get() < 3) {
+                        sendCount.set(sendCount.get() + 1);
+                        getTcp().sendMsg(data);
+                    } else {
+                        threadPool.shutdownNow();
+                        EventDispatcher.getInstance().remove(eventTag, eventListener);
+                        ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
+                            @Override
+                            public void run() {
+                                if (callBack != null) {
+                                    callBack.onError("鍙戦�佸け璐�");
+                                }
+                            }
+                        });
+                    }
+                }
+            }, 1000, 500, TimeUnit.MILLISECONDS);
+            EventDispatcher.getInstance().register(eventTag, eventListener);
+            getTcp().sendMsg(data, new SendListener() {
+                @Override
+                public void onSucceed() {
+                    if (sendListener != null) {
+                        sendListener.onSucceed();
+                    }
+                }
+
+                @Override
+                public void onError() {
+                    if (sendListener != null) {
+                        sendListener.onError();
+                    }
+                }
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+            ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (callBack != null) {
+                        callBack.onError("鍙戦�佸け璐�");
+                    }
+                }
+            });
+        }
+
+    }
+
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalRequest.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalRequest.java
new file mode 100644
index 0000000..d2ae00f
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalRequest.java
@@ -0,0 +1,47 @@
+package com.hdl.sdk.connect.bean;
+
+import java.io.Serializable;
+
+/**
+ * Created by Tong on 2021/9/29.
+ */
+public class BaseLocalRequest<T> implements Serializable {
+
+
+    private String id;
+    private String code;
+    private String time_stamp;
+    private T objects;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getTime_stamp() {
+        return time_stamp;
+    }
+
+    public void setTime_stamp(String time_stamp) {
+        this.time_stamp = time_stamp;
+    }
+
+    public T getObjects() {
+        return objects;
+    }
+
+    public void setObjects(T objects) {
+        this.objects = objects;
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalResponse.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalResponse.java
new file mode 100644
index 0000000..0a664a2
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/BaseLocalResponse.java
@@ -0,0 +1,38 @@
+package com.hdl.sdk.connect.bean;
+
+import java.io.Serializable;
+
+/**
+ * Created by Tong on 2021/9/29.
+ */
+public class BaseLocalResponse<T> implements Serializable {
+
+
+    private String id;
+    private String time_stamp;
+    private T objects;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getTime_stamp() {
+        return time_stamp;
+    }
+
+    public void setTime_stamp(String time_stamp) {
+        this.time_stamp = time_stamp;
+    }
+
+    public T getObjects() {
+        return objects;
+    }
+
+    public void setObjects(T objects) {
+        this.objects = objects;
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/DeviceControlRequest.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/DeviceControlRequest.java
new file mode 100644
index 0000000..275b7fc
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/DeviceControlRequest.java
@@ -0,0 +1,51 @@
+package com.hdl.sdk.connect.bean;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class DeviceControlRequest implements Serializable {
+
+    private String sid;
+    private List<StatusBean> status;
+
+    public String getSid() {
+        return sid;
+    }
+
+    public void setSid(String sid) {
+        this.sid = sid;
+    }
+
+    public List<StatusBean> getStatus() {
+        return status;
+    }
+
+    public void setStatus(List<StatusBean> status) {
+        this.status = status;
+    }
+
+    public static class StatusBean implements Serializable {
+        private String key;
+        private String value;
+
+        public String getKey() {
+            return key;
+        }
+
+        public void setKey(String key) {
+            this.key = key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/FunctionAttributeRequest.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/FunctionAttributeRequest.java
new file mode 100644
index 0000000..03ad699
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/FunctionAttributeRequest.java
@@ -0,0 +1,24 @@
+package com.hdl.sdk.connect.bean;
+
+import java.io.Serializable;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class FunctionAttributeRequest implements Serializable {
+
+    private String sid;
+
+    public FunctionAttributeRequest(String sid) {
+        this.sid = sid;
+    }
+
+    public String getSid() {
+        return sid;
+    }
+
+    public void setSid(String sid) {
+        this.sid = sid;
+    }
+
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/GatewaySearchBean.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/GatewaySearchBean.java
new file mode 100644
index 0000000..f3585fc
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/GatewaySearchBean.java
@@ -0,0 +1,102 @@
+package com.hdl.sdk.connect.bean;
+
+import java.io.Serializable;
+
+/**
+ * Created by Tong on 2021/9/29.
+ * 缃戝叧鎼滅储
+ */
+public class GatewaySearchBean implements Serializable {
+
+
+    private String device_model;
+    private String device_name;
+    private String device_mac;
+    private String gatewayId;
+    private String gatewayType;
+    private String gateway_type;
+    private String oid;
+    private String ip_address;
+    private String access_mode;
+    private String master;
+
+    public String getDevice_model() {
+        return device_model;
+    }
+
+    public void setDevice_model(String device_model) {
+        this.device_model = device_model;
+    }
+
+    public String getDevice_name() {
+        return device_name;
+    }
+
+    public void setDevice_name(String device_name) {
+        this.device_name = device_name;
+    }
+
+    public String getDevice_mac() {
+        return device_mac;
+    }
+
+    public void setDevice_mac(String device_mac) {
+        this.device_mac = device_mac;
+    }
+
+    public String getGatewayId() {
+        return gatewayId;
+    }
+
+    public void setGatewayId(String gatewayId) {
+        this.gatewayId = gatewayId;
+    }
+
+    public String getGatewayType() {
+        return gatewayType;
+    }
+
+    public void setGatewayType(String gatewayType) {
+        this.gatewayType = gatewayType;
+    }
+
+    public String getGateway_type() {
+        return gateway_type;
+    }
+
+    public void setGateway_type(String gateway_type) {
+        this.gateway_type = gateway_type;
+    }
+
+    public String getOid() {
+        return oid;
+    }
+
+    public void setOid(String oid) {
+        this.oid = oid;
+    }
+
+    public String getIp_address() {
+        return ip_address;
+    }
+
+    public void setIp_address(String ip_address) {
+        this.ip_address = ip_address;
+    }
+
+    public String getAccess_mode() {
+        return access_mode;
+    }
+
+    public void setAccess_mode(String access_mode) {
+        this.access_mode = access_mode;
+    }
+
+    public String getMaster() {
+        return master;
+    }
+
+    public void setMaster(String master) {
+        this.master = master;
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkRequest.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkRequest.java
new file mode 100644
index 0000000..3634ce4
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkRequest.java
@@ -0,0 +1,64 @@
+package com.hdl.sdk.connect.bean;
+
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Created by Tong on 2021/9/29.
+ */
+public class LinkRequest {
+    private String topic;
+    private String data;
+    private int length;
+
+    public LinkRequest() {
+    }
+
+    public LinkRequest(String topic, String data) {
+        this.topic = topic;
+        setData(data);
+    }
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    public void setData(String data) {
+        this.data = data;
+        if (!TextUtils.isEmpty(data)) {
+            setLength(data.length());
+        } else {
+            setLength(0);
+        }
+
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    private void setLength(int length) {
+        this.length = length;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "Topic:" +
+                getTopic() +
+                "\r\n" +
+                "Length:" +
+                getLength() +
+                "\r\n\r\n" +
+                getData();
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkResponse.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkResponse.java
new file mode 100644
index 0000000..b35dcfc
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkResponse.java
@@ -0,0 +1,55 @@
+package com.hdl.sdk.connect.bean;
+
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+import com.hdl.sdk.common.utils.gson.GsonConvert;
+
+import java.io.Serializable;
+
+/**
+ * Created by Tong on 2021/9/27.
+ */
+public class LinkResponse implements Serializable {
+
+    private String topic;
+    private String data;
+    private int length;
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    public void setData(String data) {
+        this.data = data;
+        if (!TextUtils.isEmpty(data)) {
+            setLength(data.length());
+        } else {
+            setLength(0);
+        }
+
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    private void setLength(int length) {
+        this.length = length;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return GsonConvert.getGson().toJson(this);
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyReadRequest.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyReadRequest.java
new file mode 100644
index 0000000..43ddfdb
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyReadRequest.java
@@ -0,0 +1,17 @@
+package com.hdl.sdk.connect.bean;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class PropertyReadRequest {
+
+    private String sid;
+
+    public String getSid() {
+        return sid;
+    }
+
+    public void setSid(String sid) {
+        this.sid = sid;
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyUpRequest.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyUpRequest.java
new file mode 100644
index 0000000..61d660c
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/PropertyUpRequest.java
@@ -0,0 +1,50 @@
+package com.hdl.sdk.connect.bean;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class PropertyUpRequest implements Serializable {
+
+    private String sid;
+    private List<StatusBean> status;
+
+    public String getSid() {
+        return sid;
+    }
+
+    public void setSid(String sid) {
+        this.sid = sid;
+    }
+
+    public List<StatusBean> getStatus() {
+        return status;
+    }
+
+    public void setStatus(List<StatusBean> status) {
+        this.status = status;
+    }
+
+    public static class StatusBean implements Serializable{
+        private String key;
+        private String value;
+
+        public String getKey() {
+            return key;
+        }
+
+        public void setKey(String key) {
+            this.key = key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java
new file mode 100644
index 0000000..26679ab
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java
@@ -0,0 +1,81 @@
+package com.hdl.sdk.connect.protocol;
+
+
+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.ProtocolParse;
+import com.hdl.sdk.socket.codec.ByteToMessageDecoder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Tong on 2021/9/22.
+ * link鍗忚绮樺寘鎷嗗寘
+ */
+public class LinkMessageDecoder extends ByteToMessageDecoder<LinkResponse> {
+
+    private final List<Byte> bytes;
+
+    private final byte[] head = "Topic:".getBytes();
+    private final byte[] body = "\r\n\r\n".getBytes();
+
+    public LinkMessageDecoder() {
+        this.bytes = new ArrayList<>();
+    }
+
+    @Override
+    protected LinkResponse decoder(Object msg) throws Exception {
+        LinkResponse response = new LinkResponse();
+        if (msg instanceof byte[]) {
+            //瑙f瀽娴�
+            byte[] data = (byte[]) msg;
+            bytes.addAll(ByteUtils.toByteList(data));
+
+            byte[] byteArray = ByteUtils.toByteArray(bytes);
+            int headIndex = ByteUtils.getByteIndexOf(byteArray, head);
+            if (headIndex > 0) {
+                //绉诲姩鍒癶ead 寮�濮嬩綅缃�
+                bytes.subList(0, headIndex).clear();
+                byteArray = ByteUtils.toByteArray(bytes);
+            }
+
+            int bodyIndex = ByteUtils.getByteIndexOf(byteArray, body);
+            if (bodyIndex < 0) {
+                //澶撮儴鏈幏鍙栧畬鎴�
+                return null;
+            }
+            int bodyStartIndex = bodyIndex + body.length;
+
+            //瑙f瀽澶撮儴
+            ProtocolParse parse = new ProtocolParse(byteArray);
+            response.setTopic(parse.getTopic());
+
+            int bodyLength = parse.getLength();
+            if (bodyLength > 0) {
+                if (byteArray.length >= bodyLength + bodyStartIndex) {
+                    byte[] body = ByteUtils.getRangeBytes(bytes, bodyStartIndex, bodyStartIndex + bodyLength);
+                    response.setData(new String(body, "utf-8"));
+
+                    if (byteArray.length >= bodyLength + bodyStartIndex) {
+                        //淇濆瓨浣欑暀
+                        byte[] remaining = ByteUtils.getRangeBytes(bytes, bodyStartIndex + bodyLength, byteArray.length);
+                        bytes.clear();
+                        for (byte b : remaining) {
+                            bytes.add(b);
+                        }
+                    }
+                    //瑙f瀽瀹屾垚,topic鍙戦�佷竴娆�
+                    EventDispatcher.getInstance().post(response.getTopic(), response);
+                    return response;
+                }
+            } else if (bodyLength == 0) {
+                //body涓虹┖
+                return response;
+            }
+
+        }
+        return null;
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageEncoder.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageEncoder.java
new file mode 100644
index 0000000..d24f715
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageEncoder.java
@@ -0,0 +1,16 @@
+package com.hdl.sdk.connect.protocol;
+
+
+import com.hdl.sdk.socket.codec.MessageToByteEncoder;
+
+/**
+ * Created by Tong on 2021/9/22.
+ * link鍗忚鍚堝寘
+ */
+public class LinkMessageEncoder extends MessageToByteEncoder {
+
+    @Override
+    protected byte[] encode(byte[] data) throws Exception {
+        return data;
+    }
+}
diff --git a/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/utils/ProtocolParse.java b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/utils/ProtocolParse.java
new file mode 100644
index 0000000..d29c09d
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/utils/ProtocolParse.java
@@ -0,0 +1,74 @@
+package com.hdl.sdk.connect.utils;
+
+import android.text.TextUtils;
+
+/**
+ * Created by Tong on 2021/9/22.
+ * 瑙f瀽Link鍗忚
+ */
+public class ProtocolParse {
+
+    private String topic;
+    private int length;
+    private int dataIndex;
+
+    public ProtocolParse(byte[] bytes) {
+        parse(bytes);
+    }
+
+    private void parse(byte[] bytes) {
+        try {
+            String[] split = new String(bytes, "utf-8").split("\r\n");
+            setTopic(parseTopic(split));
+            setLength(parseLength(split));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static String parseTopic(String[] bytes) {
+        try {
+            for (String s : bytes) {
+                if (s.startsWith("Topic:")) {
+                    return s.replace("Topic:", "");
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private static int parseLength(String[] bytes) {
+        try {
+            for (String s : bytes) {
+                if (!TextUtils.isEmpty(s) && s.startsWith("Length:")) {
+                    return Integer.parseInt(s.replace("Length:", ""));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return -1;
+    }
+
+
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    public void setLength(int length) {
+        this.length = length;
+    }
+
+
+}
diff --git a/HDLSDK/hdl-connect/src/test/java/com/hdl/sdk/connect/ExampleUnitTest.java b/HDLSDK/hdl-connect/src/test/java/com/hdl/sdk/connect/ExampleUnitTest.java
new file mode 100644
index 0000000..652b170
--- /dev/null
+++ b/HDLSDK/hdl-connect/src/test/java/com/hdl/sdk/connect/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.hdl.sdk.connect;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-socket/.gitignore b/HDLSDK/hdl-socket/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/HDLSDK/hdl-socket/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/HDLSDK/hdl-socket/README.md b/HDLSDK/hdl-socket/README.md
new file mode 100644
index 0000000..40be08b
--- /dev/null
+++ b/HDLSDK/hdl-socket/README.md
@@ -0,0 +1,8 @@
+# hdl-socket搴�
+
+##璇存槑
+tcp+udp 閫氱敤灏佽,瀹炵幇鍩烘湰杩炴帴
+
+##鐢ㄦ硶
+1銆佸垱寤篢cp瀵硅薄
+2銆佸垱寤篣dp瀵硅薄
diff --git a/HDLSDK/hdl-socket/build.gradle b/HDLSDK/hdl-socket/build.gradle
new file mode 100644
index 0000000..ecffc90
--- /dev/null
+++ b/HDLSDK/hdl-socket/build.gradle
@@ -0,0 +1,33 @@
+plugins {
+    id 'com.android.library'
+}
+
+android {
+    compileSdkVersion rootProject.compileSdkVersion
+
+    defaultConfig {
+        minSdkVersion rootProject.minSdkVersion
+        targetSdkVersion rootProject.targetSdkVersion
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+    api project(path: ':hdl-common')
+
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-socket/consumer-rules.pro b/HDLSDK/hdl-socket/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/HDLSDK/hdl-socket/consumer-rules.pro
diff --git a/HDLSDK/hdl-socket/proguard-rules.pro b/HDLSDK/hdl-socket/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/HDLSDK/hdl-socket/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/HDLSDK/hdl-socket/src/androidTest/java/com/hdl/sdk/socket/ExampleInstrumentedTest.java b/HDLSDK/hdl-socket/src/androidTest/java/com/hdl/sdk/socket/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..903bb2e
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/androidTest/java/com/hdl/sdk/socket/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.hdl.sdk.socket;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.hdl.sdk.socket.test", appContext.getPackageName());
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/hdl-socket/src/main/AndroidManifest.xml b/HDLSDK/hdl-socket/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..92ea344
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.hdl.sdk.socket">
+
+</manifest>
\ No newline at end of file
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java
new file mode 100644
index 0000000..a66c148
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java
@@ -0,0 +1,327 @@
+package com.hdl.sdk.socket;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.collection.ArrayMap;
+
+import com.hdl.sdk.common.utils.ThreadToolUtils;
+import com.hdl.sdk.socket.annotation.ConnectStatus;
+import com.hdl.sdk.socket.client.IClient;
+import com.hdl.sdk.socket.listener.SendListener;
+
+import java.net.ConnectException;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Created by Tong on 2021/9/26.
+ * Tcp/Udp 鍚姩鍣�
+ */
+public class SocketBoot {
+
+    private ExecutorService connectThread;
+    private ScheduledExecutorService heartbeatThread;
+    private ExecutorService sendThread;
+    private ExecutorService receiveThread;
+    private ScheduledExecutorService delayThread;
+
+    private final IClient client;
+
+    /**
+     * socket鏄惁鍦ㄨ繍琛�
+     */
+    private final AtomicBoolean isRun = new AtomicBoolean(false);
+
+    private final AtomicBoolean isOpenRetry = new AtomicBoolean(false);
+
+    private final AtomicInteger resendCount = new AtomicInteger(0);
+
+    private final BlockingQueue<SocketRequest> mMessageQueue = new LinkedBlockingDeque<>();
+
+    private final ArrayMap<String, SendListener> sendMap = new ArrayMap<>();
+
+    public SocketBoot(IClient client) {
+        this.client = client;
+    }
+
+    public ScheduledExecutorService getHeartBeat() {
+        if (heartbeatThread == null) {
+            heartbeatThread = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
+        }
+        return heartbeatThread;
+    }
+
+    public void connect() {
+        resendCount.set(0);
+        resetConnect(true);
+        isOpenRetry.set(true);
+    }
+
+    public synchronized void resetConnect(boolean isFirst) {
+        final int maxRetry = client.getOptions().getMaxRetry();
+        if (maxRetry == 0 && resendCount.get() > 0 ||
+                (maxRetry > 0 && maxRetry + 1 < resendCount.get())) {
+            Log.d("====", "===閲嶈繛娆℃暟杈惧埌鏈�澶�==");
+            return;
+        }
+        if (!client.isConnect()) {
+            if (connectThread == null) {
+                connectThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
+            }
+            connectThread.execute(new Runnable() {
+                @Override
+                public void run() {
+                    client.onConnectStatus(ConnectStatus.CONNECTING);
+                    if (!isFirst) {
+                        try {
+                            resendCount.set(resendCount.get() + 1);
+                            Thread.sleep(300L);
+                            Log.d("====", "==閲嶈繛绗�" + resendCount + "娆�==");
+                        } catch (Exception ignored) {
+                        }
+                    }
+                    try {
+                        client.connect();
+                        isRun.set(true);
+                        if (client.isConnect()) {
+                            Log.d("====", "====杩炴帴鎴愬姛====");
+                            startHeartbeat();
+
+                            initSendThread();
+                            initReceiveThread();
+
+                            client.onConnectStatus(ConnectStatus.CONNECTED);
+                            resendCount.set(0);
+                        } else {
+                            throw new ConnectException();
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        Log.d("====", "===杩炴帴澶辫触===" + e);
+                        //鍐嶅垽鏂竴涓嬫湁娌℃湁杩炴帴
+                        if (!client.isConnect()) {
+                            isRun.set(false);
+                            client.onConnectStatus(ConnectStatus.DISCONNECT);
+                            stopHeartbeat();
+                            disconnectError();
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    public void initSendThread() {
+        if (sendThread == null) {
+            sendThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
+        }
+        sendThread.execute(new Runnable() {
+            @Override
+            public void run() {
+                while (isRun.get()) {
+                    if (client.isConnect()) {
+                        Log.d("=====", "==鍙戦�佹暟鎹�==");
+                        try {
+                            SocketRequest socketRequest = mMessageQueue.take();
+                            final String action = socketRequest.getAction();
+                            try {
+                                client.sendMsg(socketRequest.getData());
+                                if (!TextUtils.isEmpty(action)) {
+                                    SendListener sendListener = sendMap.get(action);
+                                    if (sendListener != null) {
+                                        sendListener.onSucceed();
+                                    }
+                                }
+                            } catch (Exception e) {
+                                if (!TextUtils.isEmpty(action)) {
+                                    SendListener sendListener = sendMap.get(action);
+                                    if (sendListener != null) {
+                                        sendListener.onError();
+                                    }
+                                }
+
+                                stopHeartbeat();
+                                if (sendThread != null) {
+                                    sendThread.shutdownNow();
+                                }
+                                if (isRun.get()) {
+                                    disconnectError();
+                                }
+
+                            }
+                        } catch (InterruptedException ignored) {
+
+                        }
+
+                    }
+
+                }
+                Log.d("=====", "==鍙戦�佺嚎绋嬪叧闂�==");
+            }
+        });
+
+    }
+
+    public void initReceiveThread() {
+        if (receiveThread == null) {
+            receiveThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
+        }
+        receiveThread.execute(new Runnable() {
+            @Override
+            public void run() {
+                while (isRun.get()) {
+                    if (client.isConnect()) {
+                        try {
+                            //璇诲彇鏁版嵁
+                            client.onHandleResponse();
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            Log.d("====", "鏂紑杩炴帴" + e.getMessage());
+                            disconnectError();
+                        }
+                    }
+                }
+            }
+        });
+
+    }
+
+
+    public void startHeartbeat() {
+        if (heartbeatThread != null) {
+            heartbeatThread.shutdownNow();
+            heartbeatThread = null;
+        }
+        if (client.getOptions() == null || client.getOptions().getHeartbeatTimeInterval() <= 0 || !client.getOptions().isEnabledHeartbeat()) {
+            return;
+        }
+        getHeartBeat().scheduleWithFixedDelay(new Runnable() {
+            @Override
+            public void run() {
+                if (isRun.get()) {
+                    Log.d("====", "===鍙戦�佸績璺冲寘===");
+                    if (client.getOptions() != null) {
+                        final byte[] heartBeat = client.getOptions().getHeartbeatData();
+                        if (heartBeat != null) {
+                            sendMsg(heartBeat, false, null);
+                        } else {
+                            sendMsg(new byte[0], false, null);
+                        }
+                    }
+                }
+            }
+        }, client.getOptions().getHeartbeatTimeInterval(), client.getOptions().getHeartbeatTimeInterval(), TimeUnit.MILLISECONDS);
+    }
+
+    public void stopHeartbeat() {
+        if (heartbeatThread != null) {
+            heartbeatThread.shutdownNow();
+            heartbeatThread = null;
+        }
+    }
+
+    public void sendMsg(byte[] msg) {
+        sendMsg(msg, true, null);
+    }
+
+    public void sendMsg(byte[] msg, SendListener listener) {
+        sendMsg(msg, true, listener);
+    }
+
+    /**
+     * @param listener 涓�鑸儏鍐垫棤闇�鐩戝惉
+     */
+    private void sendMsg(byte[] msg, boolean isRefreshRetry, SendListener listener) {
+        if (isRefreshRetry) {
+            //閲嶇疆杩炴帴娆℃暟
+            resendCount.set(0);
+        }
+        try {
+            SocketRequest request = new SocketRequest(msg);
+            if (listener != null && !TextUtils.isEmpty(request.getAction())) {
+                sendMap.put(request.getAction(), listener);
+            }
+            mMessageQueue.put(request);
+        } catch (InterruptedException ignored) {
+
+        }
+        if (!client.isConnect()) {
+            resetConnect(false);
+        }
+
+    }
+
+    /**
+     * 鍙戠敓閿欒锛岄噸杩�
+     */
+    private void disconnectError() {
+        disconnect();
+        isRun.set(false);
+        if (isOpenRetry.get()) {
+            if (delayThread != null) {
+                delayThread.shutdownNow();
+            }
+            delayThread = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
+            delayThread.schedule(new Runnable() {
+                @Override
+                public void run() {
+                    if (!client.isConnect() && isOpenRetry.get()) {
+                        resetConnect(false);
+                    }
+
+                }
+            }, 3000, TimeUnit.MILLISECONDS);
+        }
+
+    }
+
+    private synchronized void disconnect() {
+        if (client.isConnect()) {
+            client.disconnect();
+            //鏂紑杩炴帴
+            client.onConnectStatus(ConnectStatus.DISCONNECT);
+        }
+    }
+
+    public synchronized void close() {
+        isOpenRetry.set(false);
+        isRun.set(false);
+        if (connectThread != null) {
+            connectThread.shutdownNow();
+            connectThread = null;
+        }
+        if (heartbeatThread != null) {
+            heartbeatThread.shutdownNow();
+            heartbeatThread = null;
+        }
+        if (sendThread != null) {
+            sendThread.shutdownNow();
+            sendThread = null;
+        }
+        if (receiveThread != null) {
+            receiveThread.shutdownNow();
+            receiveThread = null;
+        }
+        sendMap.clear();
+        client.disconnect();
+        mMessageQueue.clear();
+
+    }
+
+    public synchronized void release() {
+        close();
+        if (client != null && client.getOptions() != null) {
+            client.getOptions().clearConnectStatusListener();
+        }
+    }
+
+    public boolean isConnect() {
+        return client.isConnect();
+    }
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketOptions.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketOptions.java
new file mode 100644
index 0000000..83a3bc5
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketOptions.java
@@ -0,0 +1,130 @@
+package com.hdl.sdk.socket;
+
+
+import com.hdl.sdk.socket.codec.IHandleMessage;
+import com.hdl.sdk.socket.listener.ConnectStatusListener;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Tong on 2021/9/22.
+ * socket閰嶇疆
+ */
+public class SocketOptions {
+
+    //璁剧疆璇诲彇缂撳瓨
+    private int readMaxBufferSize = 512;
+
+    //鍙戦�佸績璺冲寘
+    private boolean isEnabledHeartbeat = true;
+
+    //蹇冭烦鍖�
+    private byte[] heartbeatData;
+
+    //蹇冭烦鍖呮椂闂撮棿闅�
+    private long heartbeatTimeInterval = 300L;
+
+    //澶勭悊鏁版嵁
+    private IHandleMessage handleMessage;
+
+    //鐩戝惉鐘舵��
+    private List<ConnectStatusListener> mConnectStatusListener;
+
+    //鏈�澶ч噸杩炴鏁�,灏忎簬0鏃犻檺娆℃暟,绛変簬0涓嶉噸杩�
+    private int maxRetry = -1;
+
+    private boolean isTcpNoDelay;
+    private boolean isReuseAddress;
+    //淇濇寔娲诲姩鐘舵��
+    private boolean isKeepAlive;
+    private boolean isOOBInline;
+    private int sendBufferSize;
+    private int receiveBufferSize;
+    private int soTimeout;
+    private boolean soLinger;
+
+
+    public IHandleMessage getHandleMessage() {
+        return handleMessage;
+    }
+
+    public void setHandleMessage(IHandleMessage handleMessage) {
+        this.handleMessage = handleMessage;
+    }
+
+    public boolean isEnabledHeartbeat() {
+        return isEnabledHeartbeat;
+    }
+
+    public void setEnabledHeartbeat(boolean enabledHeartbeat) {
+        isEnabledHeartbeat = enabledHeartbeat;
+    }
+
+    public byte[] getHeartbeatData() {
+        return heartbeatData;
+    }
+
+    public void setHeartbeatData(byte[] heartbeatData) {
+        this.heartbeatData = heartbeatData;
+    }
+
+    public void setHeartbeatData(String heartbeatData) {
+        try {
+            this.heartbeatData = heartbeatData.getBytes("utf-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public long getHeartbeatTimeInterval() {
+        return heartbeatTimeInterval;
+    }
+
+    public void setHeartbeatTimeInterval(long heartbeatTimeInterval) {
+        this.heartbeatTimeInterval = heartbeatTimeInterval;
+    }
+
+    public void clearConnectStatusListener() {
+        if (mConnectStatusListener != null && !mConnectStatusListener.isEmpty()) {
+            mConnectStatusListener.clear();
+        }
+    }
+
+    public void addConnectStatusListener(ConnectStatusListener connectStatusListener) {
+        if (mConnectStatusListener == null) {
+            mConnectStatusListener = new ArrayList<>();
+        }
+        mConnectStatusListener.add(connectStatusListener);
+    }
+
+    public void removeConnectStatusListener(ConnectStatusListener connectStatusListener) {
+        if (mConnectStatusListener != null) {
+            mConnectStatusListener.remove(connectStatusListener);
+        }
+    }
+
+
+    public List<ConnectStatusListener> getConnectStatusListener() {
+        return mConnectStatusListener;
+    }
+
+
+    public int getMaxRetry() {
+        return maxRetry;
+    }
+
+    public void setMaxRetry(int maxRetry) {
+        this.maxRetry = maxRetry;
+    }
+
+    public int getReadMaxBufferSize() {
+        return readMaxBufferSize;
+    }
+
+    public void setReadMaxBufferSize(int readMaxBufferSize) {
+        this.readMaxBufferSize = readMaxBufferSize;
+    }
+
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketRequest.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketRequest.java
new file mode 100644
index 0000000..924719e
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketRequest.java
@@ -0,0 +1,34 @@
+package com.hdl.sdk.socket;
+
+import java.util.UUID;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public class SocketRequest {
+
+    private String action;
+
+    private byte[] data;
+
+    public SocketRequest(byte[] data) {
+        this.data = data;
+        action = UUID.randomUUID().toString();
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    public void setData(byte[] data) {
+        this.data = data;
+    }
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/annotation/ConnectStatus.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/annotation/ConnectStatus.java
new file mode 100644
index 0000000..2ec7809
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/annotation/ConnectStatus.java
@@ -0,0 +1,31 @@
+package com.hdl.sdk.socket.annotation;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+@Target({ElementType.TYPE_PARAMETER, ElementType.PARAMETER})
+@IntDef({ConnectStatus.CONNECTING,
+        ConnectStatus.CONNECTED,
+        ConnectStatus.DISCONNECT})
+public @interface ConnectStatus {
+
+    /**
+     * 杩炴帴涓�
+     */
+    int CONNECTING = 0;
+
+    /**
+     * 杩炴帴鎴愬姛
+     */
+    int CONNECTED = 1;
+
+    /**
+     * 杩炴帴鍏抽棴
+     */
+    int DISCONNECT = 2;
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/ClientPool.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/ClientPool.java
new file mode 100644
index 0000000..9faeeb1
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/ClientPool.java
@@ -0,0 +1,57 @@
+package com.hdl.sdk.socket.client;
+
+import android.net.Uri;
+
+
+import androidx.collection.ArrayMap;
+
+import java.net.DatagramSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+/**
+ * Created by Tong on 2021/10/8.
+ */
+public class ClientPool {
+
+    private final ArrayMap<String, Socket> mTcpPool = new ArrayMap<>();
+    private final ArrayMap<String, DatagramSocket> mUdpPool = new ArrayMap<>();
+
+    private ClientPool() {
+    }
+
+    private static class SingletonInstance {
+        private static final ClientPool INSTANCE = new ClientPool();
+    }
+
+    public static ClientPool getInstance() {
+        return SingletonInstance.INSTANCE;
+    }
+
+    public Socket getTcpSocket(String ip, int port) {
+        final StringBuilder key = new StringBuilder();
+        key.append(ip).append(":").append(port);
+        if (mTcpPool.containsKey(key)) {
+            Socket socket = mTcpPool.get(key);
+            if (socket != null && !socket.isClosed()) {
+                return socket;
+            }
+
+        }
+        return new Socket();
+    }
+
+    public DatagramSocket getUdpSocket(String ip, int port) throws SocketException {
+        final StringBuilder key = new StringBuilder();
+        key.append(ip).append(":").append(port);
+        if (mUdpPool.containsKey(key)) {
+            DatagramSocket socket = mUdpPool.get(key);
+            if (socket != null && !socket.isClosed()) {
+                return socket;
+            }
+
+        }
+        return new DatagramSocket(port);
+    }
+
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/IClient.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/IClient.java
new file mode 100644
index 0000000..e768514
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/IClient.java
@@ -0,0 +1,37 @@
+package com.hdl.sdk.socket.client;
+
+
+import com.hdl.sdk.socket.SocketOptions;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public interface IClient {
+
+    void connect() throws Exception;
+
+    void disconnect();
+
+    /**
+     * 鏄惁宸茬粡杩炴帴
+     */
+    boolean isConnect();
+
+
+    SocketOptions getOptions();
+
+    /**
+     * 鐩戝惉鏁版嵁
+     */
+    void onHandleResponse() throws Exception;
+
+    /**
+     * 鍙戦�佹秷鎭�
+     */
+    void sendMsg(byte[] msg) throws Exception;
+
+    /**
+     * 杩炴帴鐘舵��
+     */
+    void onConnectStatus(int status);
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/TcpClient.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/TcpClient.java
new file mode 100644
index 0000000..51a03d8
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/TcpClient.java
@@ -0,0 +1,176 @@
+package com.hdl.sdk.socket.client;
+
+
+
+import com.hdl.sdk.common.utils.ThreadToolUtils;
+import com.hdl.sdk.socket.SocketBoot;
+import com.hdl.sdk.socket.SocketOptions;
+import com.hdl.sdk.socket.annotation.ConnectStatus;
+import com.hdl.sdk.socket.codec.IHandleMessage;
+import com.hdl.sdk.socket.listener.ConnectStatusListener;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.List;
+
+
+/**
+ * Created by Tong on 2021/9/15.
+ */
+public final class TcpClient implements IClient {
+
+    private SocketOptions socketOptions;
+
+    private final String ip;
+    private final int port;
+
+    private Socket mSocket;
+
+    private byte[] readBuffer;
+
+    private TcpClient(String ip, int port, SocketOptions socketOptions) {
+        this.socketOptions = socketOptions;
+        this.ip = ip;
+        this.port = port;
+    }
+
+    public static SocketBoot init(String ip, int port, SocketOptions options) {
+        return new SocketBoot(new TcpClient(ip, port, options));
+    }
+
+
+    @Override
+    public void connect() throws Exception {
+        mSocket = getSocket();
+        SocketOptions options = getOptions();
+        mSocket.connect(new InetSocketAddress(ip, port));
+        mSocket.setTcpNoDelay(true);
+        mSocket.setReuseAddress(true);
+        mSocket.setKeepAlive(true);
+        readBuffer = new byte[options.getReadMaxBufferSize()];
+    }
+
+
+    @Override
+    public void disconnect() {
+        if (mSocket != null) {
+            try {
+                mSocket.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    public boolean isConnect() {
+        if (mSocket == null) {
+            return false;
+        }
+
+        return mSocket.isConnected() && !mSocket.isClosed();
+    }
+
+
+    @Override
+    public synchronized SocketOptions getOptions() {
+        if (socketOptions == null) {
+            socketOptions = new SocketOptions();
+        }
+        return socketOptions;
+    }
+
+    @Override
+    public void onHandleResponse() throws Exception {
+        final InputStream stream = getInputStream();
+
+        if (stream != null && getOptions() != null) {
+            readBuffer = new byte[1024];
+            while ((getInputStream().read(readBuffer)) != -1) {
+                IHandleMessage handleMessage = getOptions().getHandleMessage();
+                if (handleMessage != null) {
+                    handleMessage.read(readBuffer);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void sendMsg(byte[] msg) throws Exception {
+        final OutputStream outputStream = getOutStream();
+        if (outputStream != null && getOptions() != null) {
+            try {
+                IHandleMessage handleMessage = getOptions().getHandleMessage();
+                handleMessage.write(handleMessage.write(msg));
+                getOutStream().write(msg);
+
+            } finally {
+                outputStream.flush();
+            }
+        }
+    }
+
+
+    /**
+     * 澶勭悊杩炴帴鐘舵��
+     */
+    public void onConnectStatus(int status) {
+        ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final List<ConnectStatusListener> list = getOptions().getConnectStatusListener();
+                if (list != null && !list.isEmpty()) {
+                    for (ConnectStatusListener listener : list) {
+                        switch (status) {
+                            case ConnectStatus
+                                    .CONNECTING:
+                                listener.onConnecting();
+                                break;
+                            case ConnectStatus
+                                    .CONNECTED:
+                                listener.onConnected();
+                                break;
+                            case ConnectStatus
+                                    .DISCONNECT:
+                                listener.onConnectFailed();
+                                break;
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+
+    private synchronized Socket getSocket() {
+        return new Socket();
+    }
+
+    private InputStream getInputStream() {
+        if (mSocket != null && mSocket.isConnected() && !mSocket.isClosed()) {
+            try {
+                return mSocket.getInputStream();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+
+    private OutputStream getOutStream() {
+        if (mSocket != null && mSocket.isConnected() && !mSocket.isClosed()) {
+            try {
+                return mSocket.getOutputStream();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/UdpClient.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/UdpClient.java
new file mode 100644
index 0000000..fc81bb6
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/UdpClient.java
@@ -0,0 +1,206 @@
+package com.hdl.sdk.socket.client;
+
+
+import android.util.Log;
+
+import com.hdl.sdk.common.HDLSdk;
+import com.hdl.sdk.common.utils.IpUtils;
+import com.hdl.sdk.common.utils.ThreadToolUtils;
+import com.hdl.sdk.socket.SocketBoot;
+import com.hdl.sdk.socket.SocketOptions;
+import com.hdl.sdk.socket.annotation.ConnectStatus;
+import com.hdl.sdk.socket.codec.IHandleMessage;
+import com.hdl.sdk.socket.listener.ConnectStatusListener;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+
+/**
+ * Created by Tong on 2021/9/15.
+ * 缁勬挱闇�瑕乤ndroid.permission.CHANGE_WIFI_MULTICAST_STATE鏉冮檺
+ * MulticastSocket
+ */
+public class UdpClient implements IClient {
+
+    private static DatagramSocket mSocket;
+
+    private DatagramPacket receivePacket;
+
+    private final int BUFFER = 4 * 1024;
+
+    private final byte[] receiveByte;
+
+    private final String ip;
+
+    private final int port;
+
+    private int monitorPort;
+    private int sendPort;
+
+    private SocketOptions socketOptions;
+
+    private final AtomicBoolean isConnect = new AtomicBoolean(false);
+
+    /**
+     * @param sendPort -1 琛ㄧず闅忔満绔彛
+     */
+    private UdpClient(String ip, int port, int monitorPort, int sendPort, SocketOptions socketOptions) {
+        this.socketOptions = socketOptions;
+        this.ip = ip;
+        this.port = port;
+        this.sendPort = sendPort;
+        this.monitorPort = monitorPort;
+        this.receiveByte = new byte[BUFFER];
+    }
+
+    public UdpClient(String ip, int port) {
+        this.ip = ip;
+        this.port = port;
+        this.receiveByte = new byte[BUFFER];
+    }
+
+    public static SocketBoot init(String ip, int port, int monitorPort, int sendPort, SocketOptions options) {
+        return new SocketBoot(new UdpClient(ip, port, monitorPort, sendPort, options));
+    }
+
+    public static SocketBoot init(String ip, int port, int monitorPort, SocketOptions options) {
+        return init(ip, port, monitorPort, -1, options);
+    }
+
+    public static SocketBoot init(String ip, int port, SocketOptions options) {
+        return init(ip, port, port, -1, options);
+    }
+
+    @Override
+    public void connect() throws Exception {
+
+        try {
+            mSocket = ClientPool.getInstance().getUdpSocket(ip, monitorPort);
+            mSocket.setBroadcast(true);
+            mSocket.setReuseAddress(true);
+
+            isConnect.set(true);
+            if (receivePacket == null) {
+                receivePacket = new DatagramPacket(receiveByte, BUFFER);
+            }
+        } catch (Exception e) {
+            isConnect.set(false);
+            throw e;
+        }
+
+
+    }
+
+    @Override
+    public void disconnect() {
+        if (mSocket != null) {
+            mSocket.close();
+        }
+        isConnect.set(false);
+    }
+
+    @Override
+    public boolean isConnect() {
+        return isConnect.get();
+    }
+
+    @Override
+    public synchronized SocketOptions getOptions() {
+        if (socketOptions == null) {
+            socketOptions = new SocketOptions();
+        }
+        return socketOptions;
+    }
+
+    @Override
+    public void onHandleResponse() throws Exception {
+        if (receivePacket == null || mSocket == null) {
+            return;
+        }
+        try {
+            mSocket.receive(receivePacket);
+        } catch (IOException e) {
+            e.printStackTrace();
+            isConnect.set(false);
+        }
+        if (receivePacket.getLength() == 0) {
+            return;
+        }
+        //鎺掗櫎鑷繁鍙戝嚭鍘荤殑
+        try {
+            if (receivePacket.getAddress().getHostAddress()
+                    .equals(IpUtils.getIP(HDLSdk.getInstance().getContext()))) {
+                return;
+            }
+        } catch (Exception ignored) {
+
+        }
+
+        IHandleMessage handleMessage = getOptions().getHandleMessage();
+        if (handleMessage != null) {
+            handleMessage.read(receivePacket.getData());
+        }
+        final String receive = new String(receivePacket.getData(), 0, receivePacket.getLength());
+
+        Log.d("---->", receive + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
+
+        //閲嶇疆闀垮害
+        if (receivePacket != null) {
+            receivePacket.setLength(BUFFER);
+        }
+    }
+
+    @Override
+    public void sendMsg(byte[] msg) throws Exception {
+        if (msg == null) {
+            msg = new byte[1];
+        }
+        InetAddress serverAddress = InetAddress.getByName(ip);
+        final DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, serverAddress, port);
+        if (sendPort < 0) {
+            final DatagramSocket sendSocket = new DatagramSocket();
+            sendSocket.send(sendPacket);
+            sendSocket.close();
+        } else if (sendPort == monitorPort) {
+            mSocket.send(sendPacket);
+        } else {
+            final DatagramSocket sendSocket = new DatagramSocket(sendPort);
+            sendSocket.send(sendPacket);
+            sendSocket.close();
+        }
+
+    }
+
+    @Override
+    public void onConnectStatus(int status) {
+        ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final List<ConnectStatusListener> list = getOptions().getConnectStatusListener();
+                if (list != null && !list.isEmpty()) {
+                    for (ConnectStatusListener listener : list) {
+                        switch (status) {
+                            case ConnectStatus
+                                    .CONNECTING:
+                                listener.onConnecting();
+                                break;
+                            case ConnectStatus
+                                    .CONNECTED:
+                                listener.onConnected();
+                                break;
+                            case ConnectStatus
+                                    .DISCONNECT:
+                                listener.onConnectFailed();
+                                break;
+                        }
+                    }
+                }
+            }
+        });
+    }
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/ByteToMessageDecoder.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/ByteToMessageDecoder.java
new file mode 100644
index 0000000..ec8da44
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/ByteToMessageDecoder.java
@@ -0,0 +1,20 @@
+package com.hdl.sdk.socket.codec;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public abstract class ByteToMessageDecoder<T> implements IHandleFlow<T> {
+
+    protected abstract T decoder(Object msg)
+            throws Exception;
+
+    @Override
+    public final T read(Object data) throws Exception {
+        return decoder(data);
+    }
+
+    @Override
+    public final byte[] write(byte[] data) {
+        return data;
+    }
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleFlow.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleFlow.java
new file mode 100644
index 0000000..ef62efe
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleFlow.java
@@ -0,0 +1,12 @@
+package com.hdl.sdk.socket.codec;
+
+/**
+ * Created by Tong on 2021/9/23.
+ */
+public interface IHandleFlow<T> {
+
+    T read(Object data) throws Exception;
+
+    byte[] write(byte[] data) throws Exception;
+
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleMessage.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleMessage.java
new file mode 100644
index 0000000..3234d83
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IHandleMessage.java
@@ -0,0 +1,10 @@
+package com.hdl.sdk.socket.codec;
+
+/**
+ * Created by Tong on 2021/9/27.
+ */
+public interface IHandleMessage {
+    void read(byte[] data) throws Exception;
+
+    byte[] write(byte[] data) throws Exception;
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IMessagePipeLine.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IMessagePipeLine.java
new file mode 100644
index 0000000..5acb78a
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/IMessagePipeLine.java
@@ -0,0 +1,11 @@
+package com.hdl.sdk.socket.codec;
+
+/**
+ * Created by Tong on 2021/9/23.
+ */
+public interface IMessagePipeLine {
+
+    void add(IHandleFlow flow);
+
+    void clear();
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessagePipeLine.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessagePipeLine.java
new file mode 100644
index 0000000..b5e8195
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessagePipeLine.java
@@ -0,0 +1,51 @@
+package com.hdl.sdk.socket.codec;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Created by Tong on 2021/9/23.
+ */
+public class MessagePipeLine implements IMessagePipeLine, IHandleMessage {
+
+    public final static List<IHandleFlow> queue = new ArrayList<>();
+
+    @Override
+    public void add(IHandleFlow flow) {
+        queue.add(flow);
+    }
+
+    @Override
+    public synchronized void clear() {
+        queue.clear();
+    }
+
+    @Override
+    public void read(byte[] data) throws Exception {
+        Object out = data;
+        for (int i = 0; i < queue.size(); i++) {
+            IHandleFlow flow = queue.get(i);
+            Object read = flow.read(out);
+            try {
+                out = Objects.requireNonNull(read);
+            } catch (Exception ignored) {
+            }
+        }
+    }
+
+    @Override
+    public byte[] write(byte[] data) throws Exception {
+        byte[] out = data;
+        for (int i = 0; i < queue.size(); i++) {
+            IHandleFlow flow = queue.get(i);
+            byte[] write = flow.write(out);
+            try {
+                out = Objects.requireNonNull(write);
+            } catch (Exception ignored) {
+
+            }
+        }
+        return new byte[0];
+    }
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessageToByteEncoder.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessageToByteEncoder.java
new file mode 100644
index 0000000..13a8201
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/codec/MessageToByteEncoder.java
@@ -0,0 +1,24 @@
+package com.hdl.sdk.socket.codec;
+
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public abstract class MessageToByteEncoder implements IHandleFlow {
+
+
+    protected abstract byte[] encode(byte[] data)
+            throws Exception;
+
+    @Override
+    public final Object read(Object data) {
+        return data;
+    }
+
+    @Override
+    public byte[] write(byte[] data) throws Exception {
+        return encode(data);
+    }
+
+
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/ConnectStatusListener.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/ConnectStatusListener.java
new file mode 100644
index 0000000..17ac30f
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/ConnectStatusListener.java
@@ -0,0 +1,27 @@
+package com.hdl.sdk.socket.listener;
+
+/**
+ * Created by Tong on 2021/9/22.
+ * 杩炴帴鐘舵��
+ */
+public interface ConnectStatusListener {
+
+    /**
+     * 杩炴帴涓�
+     */
+    default void onConnecting() {
+    }
+
+    /**
+     * 杩炴帴鎴愬姛
+     */
+    default void onConnected() {
+    }
+
+    /**
+     * 杩炴帴澶辫触
+     */
+    default void onConnectFailed() {
+    }
+
+}
diff --git a/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/SendListener.java b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/SendListener.java
new file mode 100644
index 0000000..9ecb288
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/listener/SendListener.java
@@ -0,0 +1,11 @@
+package com.hdl.sdk.socket.listener;
+
+/**
+ * Created by Tong on 2021/9/22.
+ */
+public interface SendListener {
+
+    void onSucceed();
+
+    void onError();
+}
diff --git a/HDLSDK/hdl-socket/src/test/java/com/hdl/sdk/socket/ExampleUnitTest.java b/HDLSDK/hdl-socket/src/test/java/com/hdl/sdk/socket/ExampleUnitTest.java
new file mode 100644
index 0000000..a59034b
--- /dev/null
+++ b/HDLSDK/hdl-socket/src/test/java/com/hdl/sdk/socket/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.hdl.sdk.socket;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/HDLSDK/settings.gradle b/HDLSDK/settings.gradle
new file mode 100644
index 0000000..5a72944
--- /dev/null
+++ b/HDLSDK/settings.gradle
@@ -0,0 +1,6 @@
+
+include ':app'
+include ':hdl-socket'
+include ':hdl-connect'
+include ':hdl-common'
+

--
Gitblit v1.8.0