diff --git a/AndroidTemplate/.gitignore b/AndroidTemplate/.gitignore
new file mode 100644
index 0000000..39fb081
--- /dev/null
+++ b/AndroidTemplate/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild
diff --git a/AndroidTemplate/.idea/gradle.xml b/AndroidTemplate/.idea/gradle.xml
new file mode 100644
index 0000000..f44e04a
--- /dev/null
+++ b/AndroidTemplate/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/.idea/misc.xml b/AndroidTemplate/.idea/misc.xml
new file mode 100644
index 0000000..ba7052b
--- /dev/null
+++ b/AndroidTemplate/.idea/misc.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/.idea/modules.xml b/AndroidTemplate/.idea/modules.xml
new file mode 100644
index 0000000..1d34556
--- /dev/null
+++ b/AndroidTemplate/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/.idea/runConfigurations.xml b/AndroidTemplate/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/AndroidTemplate/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/app/.gitignore b/AndroidTemplate/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/AndroidTemplate/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/AndroidTemplate/app/build.gradle b/AndroidTemplate/app/build.gradle
new file mode 100644
index 0000000..ac690c9
--- /dev/null
+++ b/AndroidTemplate/app/build.gradle
@@ -0,0 +1,31 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 26
+ defaultConfig {
+ applicationId "com.example.UserSoftwareAndroidTemplate"
+ minSdkVersion 19
+ targetSdkVersion 26
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ buildToolsVersion '27.0.0'
+}
+
+dependencies {
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ implementation 'com.android.support:appcompat-v7:26.1.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ implementation 'com.android.support:design:26.1.0'
+ implementation 'com.android.support:support-v4:26.1.0'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.1'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+}
diff --git a/AndroidTemplate/app/proguard-rules.pro b/AndroidTemplate/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/AndroidTemplate/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
diff --git a/AndroidTemplate/app/src/androidTest/java/com/example/UserSoftwareAndroidTemplate/ExampleInstrumentedTest.java b/AndroidTemplate/app/src/androidTest/java/com/example/UserSoftwareAndroidTemplate/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..32ea99b
--- /dev/null
+++ b/AndroidTemplate/app/src/androidTest/java/com/example/UserSoftwareAndroidTemplate/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.example.UserSoftwareAndroidTemplate;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.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 Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.example.UserSoftwareAndroidTemplate", appContext.getPackageName());
+ }
+}
diff --git a/AndroidTemplate/app/src/main/AndroidManifest.xml b/AndroidTemplate/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3f6dd97
--- /dev/null
+++ b/AndroidTemplate/app/src/main/AndroidManifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/BasicFramework/SoftBasic.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/BasicFramework/SoftBasic.java
new file mode 100644
index 0000000..190c047
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/BasicFramework/SoftBasic.java
@@ -0,0 +1,13 @@
+package com.example.HslCommunication.BasicFramework;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ * 静态类,提供许多程序运行的方法
+ */
+
+public class SoftBasic {
+
+
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/BasicFramework/SystemVersion.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/BasicFramework/SystemVersion.java
new file mode 100644
index 0000000..b1a2aed
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/BasicFramework/SystemVersion.java
@@ -0,0 +1,156 @@
+package com.example.HslCommunication.BasicFramework;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ */
+
+public class SystemVersion {
+
+ ///
+ /// 根据格式化字符串的版本号初始化
+ ///
+ /// 格式化的字符串,例如:1.0.0或1.0.0.0503
+ public SystemVersion(String VersionString)
+ {
+ String[] temp = VersionString.split("\\.");
+ if (temp.length >= 3)
+ {
+ m_MainVersion = Integer.parseInt(temp[0]);
+ m_SecondaryVersion = Integer.parseInt(temp[1]);
+ m_EditVersion = Integer.parseInt(temp[2]);
+
+ if (temp.length >= 4)
+ {
+ m_InnerVersion = Integer.parseInt(temp[3]);
+ }
+ }
+ }
+ ///
+ /// 根据指定的数字实例化一个对象
+ ///
+ /// 主版本
+ /// 次版本
+ /// 修订版
+ public SystemVersion(int main, int sec, int edit)
+ {
+ m_MainVersion = main;
+ m_SecondaryVersion = sec;
+ m_EditVersion = edit;
+ }
+ ///
+ /// 根据指定的数字实例化一个对象
+ ///
+ /// 主版本
+ /// 次版本
+ /// 修订版
+ /// 内部版本号
+ public SystemVersion(int main, int sec, int edit, int inner)
+ {
+ m_MainVersion = main;
+ m_SecondaryVersion = sec;
+ m_EditVersion = edit;
+ m_InnerVersion = inner;
+ }
+ private int m_MainVersion = 2;
+ ///
+ /// 主版本
+ ///
+ public int MainVersion()
+ {
+ return m_MainVersion;
+ }
+ private int m_SecondaryVersion = 0;
+ ///
+ /// 次版本
+ ///
+ public int SecondaryVersion() {
+ return m_SecondaryVersion;
+ }
+
+ private int m_EditVersion = 0;
+ ///
+ /// 修订版
+ ///
+ public int EditVersion() {
+ return m_EditVersion;
+ }
+ private int m_InnerVersion = 0;
+ ///
+ /// 内部版本号,或者是版本号表示为年月份+内部版本的表示方式
+ ///
+ public int InnerVersion()
+ {
+ return m_InnerVersion;
+ }
+
+ ///
+ /// 根据格式化为支持返回的不同信息的版本号
+ /// C返回1.0.0.0
+ /// N返回1.0.0
+ /// S返回1.0
+ ///
+ /// 格式化信息
+ ///
+ public String toString(String format)
+ {
+ if(format == "C")
+ {
+ return MainVersion()+"."+SecondaryVersion()+"."+EditVersion()+"."+InnerVersion();
+ }
+
+ if(format == "N")
+ {
+ return MainVersion()+"."+SecondaryVersion()+"."+EditVersion();
+ }
+
+ if(format == "S")
+ {
+ return MainVersion()+"."+SecondaryVersion();
+ }
+
+ return toString();
+ }
+
+
+
+ @Override
+ public String toString() {
+ if(InnerVersion() == 0)
+ {
+ return MainVersion()+"."+SecondaryVersion()+"."+EditVersion();
+ }
+ else
+ {
+ return MainVersion()+"."+SecondaryVersion()+"."+EditVersion()+"."+InnerVersion();
+ }
+ }
+
+
+ public boolean IsSameVersion(SystemVersion sv)
+ {
+ if(this.m_MainVersion!=sv.m_MainVersion)
+ {
+ return false;
+ }
+
+ if(this.m_SecondaryVersion!=sv.m_SecondaryVersion)
+ {
+ return false;
+ }
+
+ if(this.m_EditVersion!=sv.m_EditVersion)
+ {
+ return false;
+ }
+
+ if(this.m_InnerVersion!=sv.m_InnerVersion)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslCommunicationCode.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslCommunicationCode.java
new file mode 100644
index 0000000..0c9d55b
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslCommunicationCode.java
@@ -0,0 +1,100 @@
+package com.example.HslCommunication.Core.Net;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class HslCommunicationCode {
+
+
+ ///
+ /// 规定所有的网络传输指令头都为32字节
+ ///
+ public static final int HeadByteLength = 32;
+
+
+ ///
+ /// 用于心跳程序的暗号信息
+ ///
+ public static final int Hsl_Protocol_Check_Secends = 1;
+ ///
+ /// 客户端退出消息
+ ///
+ public static final int Hsl_Protocol_Client_Quit = 2;
+ ///
+ /// 因为客户端达到上限而拒绝登录
+ ///
+ public static final int Hsl_Protocol_Client_Refuse_Login = 3;
+ ///
+ /// 允许客户端登录到服务器
+ ///
+ public static final int Hsl_Protocol_Client_Allow_Login = 4;
+
+
+
+
+ ///
+ /// 说明发送的只是文本信息
+ ///
+ public static final int Hsl_Protocol_User_String = 1001;
+ ///
+ /// 发送的数据就是普通的字节数组
+ ///
+ public static final int Hsl_Protocol_User_Bytes = 1002;
+ ///
+ /// 发送的数据就是普通的图片数据
+ ///
+ public static final int Hsl_Protocol_User_Bitmap = 1003;
+ ///
+ /// 发送的数据是一条异常的数据,字符串为异常消息
+ ///
+ public static final int Hsl_Protocol_User_Exception = 1004;
+
+
+
+
+ ///
+ /// 请求文件下载的暗号
+ ///
+ public static final int Hsl_Protocol_File_Download = 2001;
+ ///
+ /// 请求文件上传的暗号
+ ///
+ public static final int Hsl_Protocol_File_Upload = 2002;
+ ///
+ /// 请求删除文件的暗号
+ ///
+ public static final int Hsl_Protocol_File_Delete = 2003;
+ ///
+ /// 文件校验成功
+ ///
+ public static final int Hsl_Protocol_File_Check_Right = 2004;
+ ///
+ /// 文件校验失败
+ ///
+ public static final int Hsl_Protocol_File_Check_Error = 2005;
+ ///
+ /// 文件保存失败
+ ///
+ public static final int Hsl_Protocol_File_Save_Error = 2006;
+ ///
+ /// 请求文件列表的暗号
+ ///
+ public static final int Hsl_Protocol_File_Directory_Files = 2007;
+ ///
+ /// 请求子文件的列表暗号
+ ///
+ public static final int Hsl_Protocol_File_Directories = 2008;
+
+
+
+
+ ///
+ /// 不压缩数据字节
+ ///
+ public static final int Hsl_Protocol_NoZipped = 3001;
+ ///
+ /// 压缩数据字节
+ ///
+ public static final int Hsl_Protocol_Zipped = 3002;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslSecurity.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslSecurity.java
new file mode 100644
index 0000000..6bcb592
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslSecurity.java
@@ -0,0 +1,35 @@
+package com.example.HslCommunication.Core.Net;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class HslSecurity {
+
+
+ ///
+ /// 加密方法,只对当前的程序集开放
+ ///
+ /// 等待加密的数据
+ /// 加密后的数据
+ public static byte[] ByteEncrypt(byte[] enBytes) {
+ if (enBytes == null) return null;
+ byte[] result = new byte[enBytes.length];
+ for (int i = 0; i < enBytes.length; i++) {
+ result[i] = (byte) (enBytes[i] ^ 0xB5);
+ }
+ return result;
+ }
+
+
+ ///
+ /// 解密方法,只对当前的程序集开放
+ ///
+ /// 等待解密的数据
+ /// 解密后的数据
+ public static byte[] ByteDecrypt(byte[] deBytes) {
+ return ByteEncrypt(deBytes);
+ }
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslZipped.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslZipped.java
new file mode 100644
index 0000000..6e46f33
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/HslZipped.java
@@ -0,0 +1,64 @@
+package com.example.HslCommunication.Core.Net;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class HslZipped {
+
+
+ /***
+ * 压缩GZip
+ *
+ * @param data
+ * @return
+ */
+ public static byte[] CompressBytes(byte[] data) {
+ byte[] b = null;
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ GZIPOutputStream gzip = new GZIPOutputStream(bos);
+ gzip.write(data);
+ gzip.finish();
+ gzip.close();
+ b = bos.toByteArray();
+ bos.close();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return b;
+ }
+
+ /***
+ * 解压GZip
+ *
+ * @param data
+ * @return
+ */
+ public static byte[] Decompress(byte[] data) {
+ byte[] b = null;
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ GZIPInputStream gzip = new GZIPInputStream(bis);
+ byte[] buf = new byte[1024];
+ int num = -1;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ while ((num = gzip.read(buf, 0, buf.length)) != -1) {
+ baos.write(buf, 0, num);
+ }
+ b = baos.toByteArray();
+ baos.flush();
+ baos.close();
+ gzip.close();
+ bis.close();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return b;
+ }
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetBase.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetBase.java
new file mode 100644
index 0000000..178a153
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetBase.java
@@ -0,0 +1,320 @@
+package com.example.HslCommunication.Core.Net;
+import android.util.Log;
+
+import com.example.HslCommunication.Core.Types.HslTimeOut;
+import com.example.HslCommunication.Core.Types.OperateResult;
+import com.example.HslCommunication.Core.Utilities.boolWithBytes;
+import com.example.HslCommunication.Core.Utilities.boolWithSocket;
+import com.example.HslCommunication.Log.LogUtil;
+import com.example.HslCommunication.Resources.StringResources;
+
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.UUID;
+
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ * 该类提供基础的网络操作服务,读写字节流,读写文件流
+ */
+
+
+
+public abstract class NetBase {
+
+ ///
+ /// 用于通信工作的核心对象
+ ///
+ protected Socket WorkSocket = null;
+ ///
+ /// 分次接收的数据长度
+ ///
+ public int SegmentationLength = 1024;
+
+ ///
+ /// 检查超时的子线程
+ ///
+ ///
+ public void ThreadPoolCheckConnect(Object obj) {
+ HslTimeOut timeout = (HslTimeOut) obj;
+ if (timeout != null) {
+ NetSupport.ThreadPoolCheckConnect(timeout, ConnectTimeout);
+ }
+ }
+
+
+ ///
+ /// 网络访问中的超时时间,单位:毫秒,默认值5000
+ ///
+ public int ConnectTimeout = 5000;
+
+ ///
+ /// 当前对象的身份令牌,用来在网络通信中双向认证的依据
+ ///
+ public UUID KeyToken = UUID.randomUUID();
+
+
+ /****************************************************************************
+ *
+ * 1. 创建并连接套接字
+ * 2. 接收指定长度的字节数据
+ * 3. 发送字节数据到套接字
+ * 4. 检查对方是否接收完成
+ * 5. 检查头子节令牌是否通过
+ * 6. 将文件流写入套接字
+ * 7. 从套接字接收文件流
+ *
+ ****************************************************************************/
+
+
+ ///
+ /// 创建socket对象并尝试连接终结点,如果异常,则结束通信
+ ///
+ /// 网络套接字
+ /// 网络终结点
+ /// 结果对象
+ ///
+ ///
+ protected boolWithSocket CreateSocketAndConnect(
+ String ipAddress,
+ int port,
+ OperateResult result
+ ) {
+ boolWithSocket value = new boolWithSocket();
+ try {
+ // create the socket object
+ value.Socket = new Socket(ipAddress, port);
+ value.Result = true;
+ return value;
+ } catch (Exception ex) {
+ result.Message = StringResources.ConnectedFailed;
+ LogUtil.LogE("CreateSocketAndConnect", StringResources.ConnectedFailed, ex);
+ CloseSocket(value.Socket);
+ return value;
+ }
+ }
+
+
+ ///
+ /// 仅仅接收一定长度的字节数据,如果异常,则结束通信
+ ///
+ /// 套接字
+ /// 字节数据
+ /// 长度
+ /// 结果对象
+ /// 接收状态
+ /// 是否根据百分比报告进度
+ /// 是否回发进度
+ /// 是否进行超时检查
+ /// 假设发生异常,应该携带什么信息
+ ///
+ protected boolWithBytes ReceiveBytesFromSocket(
+ Socket socket,
+ int length,
+ OperateResult result,
+ ProgressReport receiveStatus,
+ boolean reportByPercent,
+ boolean response,
+ boolean checkTimeOut,
+ String exceptionMessage
+ ) {
+ boolWithBytes value = new boolWithBytes();
+
+ try {
+ value.Content = NetSupport.ReadBytesFromSocket(socket, length, receiveStatus, reportByPercent, response);
+ } catch (Exception ex) {
+ CloseSocket(socket);
+ result.Message = CombineExceptionString(exceptionMessage, ex.getMessage());
+ LogUtil.LogE("ReceiveBytesFromSocket", exceptionMessage, ex);
+ Log.e("接收数据异常", "ReceiveBytesFromSocket: ", ex);
+ return value;
+ }
+ value.Result = true;
+ return value;
+ }
+
+ ///
+ /// 仅仅将数据发送到socket对象上去,如果异常,则结束通信
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected boolean SendBytesToSocket(
+ Socket socket,
+ byte[] send,
+ OperateResult result,
+ String exceptionMessage
+ ) {
+ try {
+ DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+ output.write(send);
+ } catch (Exception ex) {
+ result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
+ LogUtil.LogE("SendBytesToSocket", exceptionMessage, ex);
+ CloseSocket(socket);
+ send = null;
+ return false;
+ }
+ return true;
+ }
+
+
+ ///
+ /// 确认对方是否已经接收完成数据,如果异常,则结束通信
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected boolean CheckRomoteReceived(
+ Socket socket,
+ long length,
+ ProgressReport report,
+ OperateResult result,
+ String exceptionMessage
+ ) {
+ try {
+ NetSupport.CheckSendBytesReceived(socket, length, report, true);
+ return true;
+ } catch (Exception ex) {
+ result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
+ LogUtil.LogE("CheckRomoteReceived", exceptionMessage, ex);
+ CloseSocket(socket);
+ return false;
+ }
+ }
+
+
+ ///
+ /// 检查令牌是否正确,如果不正确,结束网络通信
+ ///
+ /// 套接字
+ /// 头子令
+ /// 令牌
+ /// 结果对象
+ ///
+ protected boolean CheckTokenPermission(
+ Socket socket,
+ byte[] head,
+ UUID token,
+ OperateResult result
+ ) {
+ if (NetSupport.CheckTokenEquel(head, KeyToken)) {
+ return true;
+ } else {
+ result.Message = StringResources.TokenCheckFailed;
+ LogUtil.LogE("CheckTokenPermission", StringResources.TokenCheckFailed + " Ip:" + socket.getInetAddress().toString());
+ CloseSocket(socket);
+ return false;
+ }
+ }
+
+ ///
+ /// 将文件数据发送至套接字,如果结果异常,则结束通讯
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected boolean SendFileStreamToSocket(
+ Socket socket,
+ String filename,
+ long filelength,
+ OperateResult result,
+ ProgressReport report,
+ String exceptionMessage
+ ) {
+ try {
+ InputStream inputStream = new BufferedInputStream(new FileInputStream(filename));
+ NetSupport.WriteSocketFromStream(socket, inputStream, filelength, report, true);
+ inputStream.close();
+ return true;
+ } catch (Exception ex) {
+ CloseSocket(socket);
+ LogUtil.LogE("SendFileStreamToSocket", exceptionMessage, ex);
+ result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
+ return false;
+ }
+ }
+
+
+ ///
+ /// 从套接字中接收一个文件数据,如果结果异常,则结束通讯
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected boolean ReceiveFileSteamFromSocket(
+ Socket socket,
+ String filename,
+ long receive,
+ ProgressReport report,
+ OperateResult result,
+ String exceptionMessage
+ ) {
+ try {
+ OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filename));
+ NetSupport.WriteStreamFromSocket(socket, outputStream, receive, report, true);
+ outputStream.close();
+ return true;
+ } catch (Exception ex) {
+ result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
+ LogUtil.LogE("ReceiveFileSteamFromSocket", exceptionMessage, ex);
+ CloseSocket(socket);
+ return false;
+ }
+ }
+
+ ///
+ /// 获取错误的用于显示的信息
+ ///
+ ///
+ ///
+ ///
+ protected String CombineExceptionString(String message, String exception) {
+ return message + "\r\n原因:" + exception;
+ }
+
+
+
+ protected void CloseSocket(Socket socket) {
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (Exception ex2) {
+ LogUtil.LogE("CloseSocket","",ex2);
+ }
+ }
+ }
+
+
+ protected void ThreadSleep(int milltime)
+ {
+ try
+ {
+ Thread.sleep(milltime);
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetShareBase.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetShareBase.java
new file mode 100644
index 0000000..4855159
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetShareBase.java
@@ -0,0 +1,681 @@
+package com.example.HslCommunication.Core.Net;
+
+import android.util.Log;
+
+import com.example.HslCommunication.Core.Types.OperateResult;
+import com.example.HslCommunication.Core.Utilities.boolWith2Bytes;
+import com.example.HslCommunication.Core.Utilities.boolWithBytes;
+import com.example.HslCommunication.Core.Utilities.boolWithIntByte;
+import com.example.HslCommunication.Core.Utilities.boolWithIntString;
+import com.example.HslCommunication.Core.Utilities.Utilities;
+import com.example.HslCommunication.Log.LogUtil;
+import com.example.HslCommunication.Resources.StringResources;
+
+
+import java.net.Socket;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public abstract class NetShareBase extends NetBase {
+
+
+ ///
+ /// [自校验] 发送字节数据并确认对方接收完成数据,如果结果异常,则结束通讯
+ ///
+ /// 网络套接字
+ /// 头指令
+ /// 用户指令
+ /// 发送的数据
+ /// 用于返回的结果
+ /// 发送的进度报告
+ /// 失败时存储的额外描述信息
+ ///
+ protected boolean SendBaseAndCheckReceive(
+ Socket socket,
+ int headcode,
+ int customer,
+ byte[] send,
+ OperateResult result,
+ ProgressReport sendReport,
+ String failedString
+ )
+ {
+ // 数据处理
+ send = NetSupport.CommandBytes(headcode, customer, KeyToken, send);
+
+ Log.i(Utilities.bytes2HexString(send), "SendBaseAndCheckReceive: ");
+
+ // 发送数据
+ if (!SendBytesToSocket(
+ socket, // 套接字
+ send, // 发送的字节数据
+ result, // 结果信息对象
+ failedString // 异常附加对象
+ ))
+ {
+ send = null;
+ return false;
+ }
+
+ // 确认对方是否接收完成
+ int remoteReceive = send.length - HslCommunicationCode.HeadByteLength;
+ Log.i("等待接收数据", "SendBaseAndCheckReceive: ");
+
+ if (!CheckRomoteReceived(
+ socket, // 套接字
+ remoteReceive, // 对方需要接收的长度
+ sendReport, // 发送进度报告
+ result, // 结果信息对象
+ failedString // 异常附加信息
+ ))
+ {
+ send = null;
+ return false;
+ }
+
+ Log.i("对方接收成功", "SendBaseAndCheckReceive: ");
+ // 对方接收成功
+ send = null;
+ return true;
+ }
+
+ ///
+ /// [自校验] 发送字节数据并确认对方接收完成数据,如果结果异常,则结束通讯
+ ///
+ /// 网络套接字
+ /// 用户指令
+ /// 发送的数据
+ /// 用于返回的结果
+ /// 发送的进度报告
+ /// 异常时记录到日志的附加信息
+ ///
+ protected boolean SendBytesAndCheckReceive(
+ Socket socket,
+ int customer,
+ byte[] send,
+ OperateResult result,
+ ProgressReport sendReport,
+ String failedString
+ )
+ {
+ if (SendBaseAndCheckReceive(
+ socket, // 套接字
+ HslCommunicationCode.Hsl_Protocol_User_Bytes, // 指示字节数组
+ customer, // 用户数据
+ send, // 发送数据,该数据还要经过处理
+ result, // 结果消息对象
+ sendReport, // 发送的进度报告
+ failedString // 错误的额外描述
+ ))
+ {
+ return true;
+ }
+ else
+ {
+ LogUtil.LogE("SendBytesAndCheckReceive",failedString);
+ return false;
+ }
+ }
+
+ ///
+ /// [自校验] 直接发送字符串数据并确认对方接收完成数据,如果结果异常,则结束通讯
+ ///
+ /// 网络套接字
+ /// 用户指令
+ /// 发送的数据
+ /// 用于返回的结果
+ /// 发送的进度报告
+ ///
+ ///
+ protected boolean SendStringAndCheckReceive(
+ Socket socket,
+ int customer,
+ String send,
+ OperateResult result,
+ ProgressReport sendReport,
+ String failedString
+ )
+ {
+ byte[] data =null;
+
+ if(send == null ||send.length() <= 0)
+ {
+
+ }
+ else
+ {
+ data = send.getBytes();
+ }
+
+ if (!SendBaseAndCheckReceive(
+ socket, // 套接字
+ HslCommunicationCode.Hsl_Protocol_User_String, // 指示字符串数据
+ customer, // 用户数据
+ data, // 字符串的数据
+ result, // 结果消息对象
+ sendReport, // 发送的进度报告
+ failedString // 错误的额外描述
+ ))
+ {
+ return false;
+ }
+ return true;
+ }
+
+/*
+ ///
+ /// [自校验] 将文件数据发送至套接字,具体发送细节将在继承类中实现,如果结果异常,则结束通讯
+ ///
+ /// 套接字
+ /// 文件名称,文件必须存在
+ /// 远程端的文件名称
+ /// 文件的额外标签
+ /// 文件的上传人
+ /// 操作结果对象
+ /// 发送进度报告
+ ///
+ ///
+ protected boolean SendFileAndCheckReceive(
+ Socket socket,
+ String filename,
+ String servername,
+ String filetag,
+ String fileupload,
+ OperateResult result,
+ ProgressReport sendReport,
+ String failedString
+ )
+ {
+ // 发送文件名,大小,标签
+ File info = new File(filename);
+
+ //FileInfo info = new FileInfo(filename);
+
+ if (!info.exists())
+ {
+ // 如果文件不存在
+ if (!SendStringAndCheckReceive(socket, 0, "", result, null, failedString)) return false;
+ else
+ {
+ result.Message = "找不到该文件,请重新确认文件!";
+ CloseSocket(socket);
+ return false;
+ }
+ }
+
+ // 文件存在的情况
+ Newtonsoft.Json.Linq.JObject json = new Newtonsoft.Json.Linq.JObject
+ {
+ { "FileName", new Newtonsoft.Json.Linq.JValue(servername) },
+ { "FileSize", new Newtonsoft.Json.Linq.JValue(info.Length) },
+ { "FileTag", new Newtonsoft.Json.Linq.JValue(filetag) },
+ { "FileUpload", new Newtonsoft.Json.Linq.JValue(fileupload) }
+ };
+
+ if (!SendStringAndCheckReceive(socket, 1, json.ToString(), result, null, failedString)) return false;
+
+
+ if (!SendFileStreamToSocket(socket, filename, info.Length, result, sendReport, failedString))
+ {
+ return false;
+ }
+
+ // 检查接收
+ // if (!CheckRomoteReceived(socket, info.Length, sendReport, result, failedString))
+ // {
+ // return false;
+ // }
+
+ return true;
+ }
+
+ ///
+ /// [自校验] 将流数据发送至套接字,具体发送细节将在继承类中实现,如果结果异常,则结束通讯
+ ///
+ /// 套接字
+ /// 文件名称,文件必须存在
+ /// 远程端的文件名称
+ /// 文件的额外标签
+ /// 文件的上传人
+ /// 操作结果对象
+ /// 发送进度报告
+ ///
+ ///
+ protected boolean SendFileAndCheckReceive(
+ Socket socket,
+ Stream stream,
+ String servername,
+ String filetag,
+ String fileupload,
+ OperateResult result,
+ ProgressReport sendReport,
+ String failedString
+ )
+ {
+ // 文件存在的情况
+ Newtonsoft.Json.Linq.JObject json = new Newtonsoft.Json.Linq.JObject
+ {
+ { "FileName", new Newtonsoft.Json.Linq.JValue(servername) },
+ { "FileSize", new Newtonsoft.Json.Linq.JValue(stream.Length) },
+ { "FileTag", new Newtonsoft.Json.Linq.JValue(filetag) },
+ { "FileUpload", new Newtonsoft.Json.Linq.JValue(fileupload) }
+ };
+
+ if (!SendStringAndCheckReceive(socket, 1, json.ToString(), result, null, failedString)) return false;
+
+
+ try
+ {
+ NetSupport.WriteSocketFromStream(socket, stream, stream.Length, sendReport, true);
+ }
+ catch(Exception ex)
+ {
+ CloseSocket(socket);
+ if(LogNet!=null) LogNet.WriteException(failedString, ex);
+ result.Message = CombineExceptionString(failedString, ex.getLocalizedMessage());
+ return false;
+ }
+
+ // 检查接收
+ // if (!CheckRomoteReceived(socket, info.Length, sendReport, result, failedString))
+ // {
+ // return false;
+ // }
+
+ return true;
+ }*/
+
+
+
+
+ ///
+ /// [自校验] 接收一条完整的同步数据,包含头子节和内容字节,基础的数据,如果结果异常,则结束通讯
+ ///
+ /// 套接字
+ /// 头子节
+ /// 内容字节
+ /// 结果
+ /// 接收进度反馈
+ /// 失败时用于显示的字符串
+ ///
+ /// result
+ protected boolWith2Bytes ReceiveAndCheckBytes(
+ Socket socket,
+ OperateResult result,
+ ProgressReport receiveReport,
+ String failedString
+ )
+ {
+ boolWith2Bytes value2=new boolWith2Bytes();
+
+ // 30秒超时接收验证
+// HslTimeOut hslTimeOut = new HslTimeOut()
+// {
+// DelayTime = 30000,
+// IsSuccessful = false,
+// StartTime = DateTime.Now,
+// WorkSocket = socket,
+// };
+//
+// ThreadPool.QueueUserWorkItem(new WaitCallback(NetSupport.ThreadPoolCheckTimeOut), hslTimeOut);
+
+ Log.i("准备接收头指令", "ReceiveAndCheckBytes: ");
+
+ boolWithBytes value = ReceiveBytesFromSocket(
+ socket, // 套接字
+ HslCommunicationCode.HeadByteLength, // 头指令长度
+ result, // 结果消息对象
+ null, // 不报告进度
+ false, // 报告是否按照百分比报告
+ false, // 不回发接收长度
+ true, // 检查是否超时
+ failedString // 异常时的附加文本描述
+ );
+
+ if(!value.Result)
+ {
+ return value2;
+ }
+
+ value2.Content = value.Content;
+
+ Log.i("准备检查令牌", "ReceiveAndCheckBytes: ");
+
+ // 检查令牌
+ if (!CheckTokenPermission(socket, value.Content, KeyToken, result))
+ {
+ Log.i("令牌检查失败", "ReceiveAndCheckBytes: ");
+ result.Message = StringResources.TokenCheckFailed;
+ return value2;
+ }
+
+ // 接收内容
+ byte[] buffer = new byte[4];
+ buffer[0]=value.Content[28];
+ buffer[1]=value.Content[29];
+ buffer[2]=value.Content[30];
+ buffer[3]=value.Content[31];
+ int contentLength = Utilities.bytes2Int(buffer);
+
+ Log.i("准备接收内容,长度为:"+contentLength, "ReceiveAndCheckBytes: ");
+
+ value =ReceiveBytesFromSocket(
+ socket, // 套接字
+ contentLength, // 内容数据长度
+ result, // 结果消息对象
+ receiveReport, // 接收进度报告委托
+ true, // 按照百分比进行报告数据
+ true, // 回发已经接收的数据长度
+ false, // 不进行超时检查
+ failedString // 异常时附加的文本描述
+ );
+
+ if(!value.Result)
+ {
+ return value2;
+ }
+ Log.i("内容接收成功", "ReceiveAndCheckBytes: ");
+
+ value2.Content2 = NetSupport.CommandAnalysis(value2.Content, value.Content);
+ value2.Result=true;
+ return value2;
+ }
+
+
+
+ ///
+ /// [自校验] 从网络中接收一个字符串数据,如果结果异常,则结束通讯
+ ///
+ /// 套接字
+ /// 接收的用户数据
+ /// 接收的字节数据
+ /// 结果信息对象
+ /// 接收数据时的进度报告
+ /// 失败时记录日志的字符串
+ ///
+ protected boolWithIntString ReceiveStringFromSocket(
+ Socket socket,
+ OperateResult result,
+ ProgressReport receiveReport,
+ String failedString
+ )
+ {
+ boolWithIntString valueString = new boolWithIntString();
+
+ boolWith2Bytes value2Bytes = ReceiveAndCheckBytes(socket,result, receiveReport, failedString);
+
+ if (!value2Bytes.Result)
+ {
+ return valueString;
+ }
+
+ // check
+
+ byte[] buffer = new byte[4];
+ buffer[0]=value2Bytes.Content[0];
+ buffer[1]=value2Bytes.Content[1];
+ buffer[2]=value2Bytes.Content[2];
+ buffer[3]=value2Bytes.Content[3];
+ if (Utilities.bytes2Int(buffer) != HslCommunicationCode.Hsl_Protocol_User_String)
+ {
+ result.Message = "数据头校验失败!";
+ LogUtil.LogE("ReceiveStringFromSocket","数据头校验失败!");
+ CloseSocket(socket);
+ return valueString;
+ }
+
+ buffer[0]=value2Bytes.Content[4];
+ buffer[1]=value2Bytes.Content[5];
+ buffer[2]=value2Bytes.Content[6];
+ buffer[3]=value2Bytes.Content[7];
+ // 分析数据
+ valueString.DataInt = Utilities.bytes2Int(buffer);
+ valueString.DataString = Utilities.byte2String(value2Bytes.Content2);
+ valueString.Result = true;
+ return valueString;
+ }
+
+ ///
+ /// [自校验] 从网络中接收一串字节数据,如果结果异常,则结束通讯
+ ///
+ /// 套接字
+ /// 接收的用户数据
+ /// 接收的字节数据
+ /// 结果信息对象
+ /// 失败时记录日志的字符串
+ ///
+ protected boolWithIntByte ReceiveContentFromSocket(
+ Socket socket,
+ OperateResult result,
+ ProgressReport receiveReport,
+ String failedString
+ )
+ {
+
+ boolWithIntByte value = new boolWithIntByte();
+
+ boolWith2Bytes value2Bytes = ReceiveAndCheckBytes(socket,result,null, failedString);
+
+ if (!value2Bytes.Result)
+ {
+ return value;
+ }
+
+ byte[] buffer = new byte[4];
+ buffer[0]=value2Bytes.Content[0];
+ buffer[1]=value2Bytes.Content[1];
+ buffer[2]=value2Bytes.Content[2];
+ buffer[3]=value2Bytes.Content[3];
+ if (Utilities.bytes2Int(buffer) != HslCommunicationCode.Hsl_Protocol_User_String)
+ {
+ result.Message = "数据头校验失败!";
+ LogUtil.LogE("ReceiveContentFromSocket","数据头校验失败!");
+ CloseSocket(socket);
+ return value;
+ }
+
+ buffer[0]=value2Bytes.Content[4];
+ buffer[1]=value2Bytes.Content[5];
+ buffer[2]=value2Bytes.Content[6];
+ buffer[3]=value2Bytes.Content[7];
+ // 分析数据
+ value.DataInt = Utilities.bytes2Int(buffer);
+ value.Content = value2Bytes.Content2;
+ value.Result = true;
+ return value;
+ }
+
+/*
+
+ ///
+ /// [自校验] 从套接字中接收文件头信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected bool ReceiveFileHeadFromSocket(
+ Socket socket,
+ out string filename,
+ out long size,
+ out string filetag,
+ out string fileupload,
+ OperateResult result,
+ string failedString = null
+ )
+ {
+ // 先接收文件头信息
+ if (!ReceiveStringFromSocket(socket, out int customer, out string filehead, result, null, failedString))
+ {
+ filename = null;
+ size = 0;
+ filetag = null;
+ fileupload = null;
+ return false;
+ }
+
+ // 判断文件是否存在
+ if (customer == 0)
+ {
+ LogNet?.WriteWarn("对方文件不存在,无法接收!");
+ result.Message = StringResources.FileNotExist;
+ filename = null;
+ size = 0;
+ filetag = null;
+ fileupload = null;
+ socket?.Close();
+ return false;
+ }
+
+ // 提取信息
+ Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(filehead);
+ filename = SoftBasic.GetValueFromJsonObject(json, "FileName", "");
+ size = SoftBasic.GetValueFromJsonObject(json, "FileSize", 0L);
+ filetag = SoftBasic.GetValueFromJsonObject(json, "FileTag", "");
+ fileupload = SoftBasic.GetValueFromJsonObject(json, "FileUpload", "");
+
+ return true;
+ }
+
+
+ ///
+ /// [自校验] 从网络中接收一个文件,如果结果异常,则结束通讯
+ ///
+ /// 网络套接字
+ /// 接收文件后保存的文件名
+ /// 文件在对方电脑上的文件名
+ /// 文件大小
+ /// 文件的标识
+ /// 文件的上传人
+ /// 结果信息对象
+ /// 接收进度报告
+ /// 失败时的记录日志字符串
+ ///
+ protected bool ReceiveFileFromSocket(
+ Socket socket,
+ string savename,
+ out string filename,
+ out long size,
+ out string filetag,
+ out string fileupload,
+ OperateResult result,
+ Action receiveReport,
+ string failedString = null
+ )
+ {
+ // 先接收文件头信息
+ if (!ReceiveFileHeadFromSocket(
+ socket,
+ out filename,
+ out size,
+ out filetag,
+ out fileupload,
+ result,
+ failedString
+ ))
+ {
+ return false;
+ }
+
+ //// 先接收文件头信息
+ //if (!ReceiveStringFromSocket(socket, out int customer, out string filehead, result, null, failedString))
+ //{
+ // filename = null;
+ // size = 0;
+ // filetag = null;
+ // fileupload = null;
+ // return false;
+ //}
+
+ //// 判断文件是否存在
+ //if (customer == 0)
+ //{
+ // LogNet?.WriteWarn("对方文件不存在,无法接收!");
+ // result.Message = StringResources.FileNotExist;
+ // filename = null;
+ // size = 0;
+ // filetag = null;
+ // fileupload = null;
+ // socket?.Close();
+ // return false;
+ //}
+
+ //// 提取信息
+ //Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(filehead);
+ //filename = SoftBasic.GetValueFromJsonObject(json, "FileName", "");
+ //size = SoftBasic.GetValueFromJsonObject(json, "FileSize", 0L);
+ //filetag = SoftBasic.GetValueFromJsonObject(json, "FileTag", "");
+ //fileupload = SoftBasic.GetValueFromJsonObject(json, "FileUpload", "");
+
+ // 接收文件消息
+ if (!ReceiveFileSteamFromSocket(socket, savename, size, receiveReport, result, failedString))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// [自校验] 从网络中接收一个文件,写入数据流,如果结果异常,则结束通讯
+ ///
+ /// 网络套接字
+ /// 等待写入的数据流
+ /// 文件在对方电脑上的文件名
+ /// 文件大小
+ /// 文件的标识
+ /// 文件的上传人
+ /// 结果信息对象
+ /// 接收进度报告
+ /// 失败时的记录日志字符串
+ ///
+ protected bool ReceiveFileFromSocket(
+ Socket socket,
+ Stream stream,
+ out string filename,
+ out long size,
+ out string filetag,
+ out string fileupload,
+ OperateResult result,
+ Action receiveReport,
+ string failedString = null
+ )
+ {
+ // 先接收文件头信息
+ if (!ReceiveFileHeadFromSocket(
+ socket,
+ out filename,
+ out size,
+ out filetag,
+ out fileupload,
+ result,
+ failedString
+ ))
+ {
+ return false;
+ }
+
+
+ try
+ {
+ NetSupport.WriteStreamFromSocket(socket, stream, size, receiveReport, true);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ result.Message = ex.Message;
+ socket?.Close();
+ return false;
+ }
+ }
+*/
+
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetSupport.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetSupport.java
new file mode 100644
index 0000000..1a528d8
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/NetSupport.java
@@ -0,0 +1,338 @@
+package com.example.HslCommunication.Core.Net;
+
+import com.example.HslCommunication.Core.Types.HslTimeOut;
+import com.example.HslCommunication.Core.Utilities.Utilities;
+
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Date;
+import java.io.DataInputStream;
+import java.util.UUID;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class NetSupport {
+
+ private static final int SocketBufferSize = 4096;
+
+
+
+ public static void ThreadPoolCheckConnect(HslTimeOut timeout, int millisecond) {
+ while (!timeout.IsSuccessful) {
+ if ((new Date().getTime() - timeout.StartTime.getTime()) > millisecond) {
+ // 连接超时或是验证超时
+ if (!timeout.IsSuccessful) {
+ try {
+ if (timeout.WorkSocket != null) {
+ timeout.WorkSocket.close();
+ }
+ } catch (java.io.IOException ex) {
+ // 不处理,放弃
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ public static boolean IsTwoBytesEquel(byte[] b1, int start1, byte[] b2, int start2, int length) {
+ if (b1 == null || b2 == null) return false;
+ for (int i = 0; i < length; i++) {
+ if (b1[i + start1] != b2[i + start2]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean CheckTokenEquel(byte[] head, UUID token)
+ {
+ return IsTwoBytesEquel(head, 12, Utilities.UUID2Byte(token), 0, 16);
+ }
+
+
+
+ public static byte[] ReadBytesFromSocket(Socket socket, int receive, ProgressReport report, boolean reportByPercent, boolean response) throws java.io.IOException
+ {
+ byte[] bytes_receive = new byte[receive];
+ int count_receive = 0;
+ long percent = 0;
+
+ DataInputStream input = new DataInputStream(socket.getInputStream());
+ DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+
+ while (count_receive < receive) {
+ // 分割成4KB来接收数据
+ int receive_length = 0;
+ if ((receive - count_receive) >= SocketBufferSize) {
+ receive_length = SocketBufferSize;
+ } else {
+ receive_length = (receive - count_receive);
+ }
+
+ count_receive += input.read(bytes_receive, count_receive, receive_length);
+
+ if (reportByPercent) {
+ long percentCurrent = (long) count_receive * 100 / receive;
+ if (percent != percentCurrent) {
+ percent = percentCurrent;
+ // 报告进度
+ if (report != null) report.Report(count_receive, receive);
+ }
+ } else {
+ // 报告进度
+ if (report != null) report.Report(count_receive, receive);
+ }
+
+ // 回发进度
+ if (response) output.write(Utilities.long2Bytes((long) count_receive));
+ }
+
+ return bytes_receive;
+ }
+
+
+
+ public static byte[] ReadBytesFromSocket(Socket socket, int receive) throws java.io.IOException {
+ return ReadBytesFromSocket(socket, receive, null, false, false);
+ }
+
+
+
+ ///
+ /// 读取套接字并且写入流
+ ///
+ /// 文件流
+ /// 连接的套接字
+ /// 返回的文件长度
+ /// 发送的进度报告
+ ///
+ public static void WriteStreamFromSocket(Socket socket, OutputStream stream, long receive, ProgressReport report, boolean reportByPercent) throws java.io.IOException
+ {
+ byte[] buffer = new byte[SocketBufferSize];
+ long count_receive = 0;
+ long percent = 0;
+
+ DataInputStream input = new DataInputStream(socket.getInputStream());
+ DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+
+ while (count_receive < receive)
+ {
+ // 分割成4KB来接收数据
+ int current = input.read(buffer, 0, SocketBufferSize);
+
+ count_receive += current;
+ stream.write(buffer, 0, current);
+ if (reportByPercent)
+ {
+ long percentCurrent = count_receive * 100 / receive;
+ if (percent != percentCurrent)
+ {
+ percent = percentCurrent;
+ // 报告进度
+ if (report != null) report.Report(count_receive, receive);
+ }
+ }
+ else
+ {
+ // 报告进度
+ if (report != null) report.Report(count_receive, receive);
+ }
+ // 回发进度
+ output.write(Utilities.long2Bytes(count_receive));
+ }
+ buffer = null;
+ }
+
+
+
+
+ ///
+ /// 读取流并将数据写入socket
+ ///
+ /// 文件流
+ /// 连接的套接字
+ /// 返回的文件长度
+ /// 发送的进度报告
+ ///
+ public static void WriteSocketFromStream(Socket socket, InputStream stream, long length, ProgressReport report, boolean reportByPercent) throws java.io.IOException
+ {
+ byte[] buffer = new byte[SocketBufferSize];
+ long count_send = 0;
+ long percent = 0;
+
+ DataInputStream input = new DataInputStream(socket.getInputStream());
+ DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+
+ while (count_send < length)
+ {
+ int count = stream.read(buffer, 0, SocketBufferSize);
+ count_send += count;
+
+
+ output.write(buffer, 0, count);
+
+ while (count_send != Utilities.bytes2Long(ReadBytesFromSocket(socket, 8)));
+
+ long received = count_send;
+
+ if (reportByPercent)
+ {
+ long percentCurrent = received * 100 / length;
+ if (percent != percentCurrent)
+ {
+ percent = percentCurrent;
+ // 报告进度
+ if (report != null) report.Report(received, length);
+ }
+ }
+ else
+ {
+ // 报告进度
+ if (report != null) report.Report(received, length);
+ }
+
+ // 双重接收验证
+ if (count == 0)
+ {
+ break;
+ }
+ }
+
+ buffer = null;
+ }
+
+
+
+ public static void CheckSendBytesReceived(Socket socket, long length, ProgressReport report, boolean reportByPercent) throws java.io.IOException
+ {
+ long remoteNeedReceive = 0;
+ long percent = 0;
+
+ // 确认服务器的数据是否接收完成
+ while (remoteNeedReceive < length)
+ {
+ remoteNeedReceive = Utilities.bytes2Long(ReadBytesFromSocket(socket, 8));
+ if (reportByPercent)
+ {
+ long percentCurrent = remoteNeedReceive * 100 / length;
+ if (percent != percentCurrent)
+ {
+ percent = percentCurrent;
+ // 报告进度
+ if (report != null) report.Report(remoteNeedReceive, length);
+ }
+ }
+ else
+ {
+ // 报告进度
+ if (report != null) report.Report(remoteNeedReceive, length);
+ }
+ }
+ }
+
+
+ /*
+
+ 发送字节数据的最终命令
+
+ */
+
+ public static byte[] CommandBytes(int customer, UUID token, byte[] data)
+ {
+ return CommandBytes(HslCommunicationCode.Hsl_Protocol_User_Bytes, customer, token, data);
+ }
+
+
+ /*
+
+ 生成发送文本数据的最终命令
+
+ */
+
+ public static byte[] CommandBytes(int customer, UUID token, String data)
+ {
+ if (data == null) return CommandBytes(HslCommunicationCode.Hsl_Protocol_User_String, customer, token, null);
+ else return CommandBytes(HslCommunicationCode.Hsl_Protocol_User_String, customer, token, Utilities.string2Byte(data));
+ }
+
+ /*
+
+ 生成最终的发送命令
+
+ */
+
+ public static byte[] CommandBytes(int command, int customer, UUID token, byte[] data)
+ {
+ byte[] _temp = null;
+ int _zipped = HslCommunicationCode.Hsl_Protocol_NoZipped;
+ int _sendLength = 0;
+ if (data == null)
+ {
+ _temp = new byte[HslCommunicationCode.HeadByteLength];
+ }
+ else
+ {
+ // 加密
+ data = HslSecurity.ByteEncrypt(data);
+ if (data.length > 10240)
+ {
+ // 10K以上的数据,进行数据压缩
+ data = HslZipped.CompressBytes(data);
+ _zipped = HslCommunicationCode.Hsl_Protocol_Zipped;
+ }
+ _temp = new byte[HslCommunicationCode.HeadByteLength + data.length];
+ _sendLength = data.length;
+ }
+
+ Utilities.int2Bytes(command);
+
+ System.arraycopy(Utilities.int2Bytes(command),0,_temp,0,4);
+ System.arraycopy(Utilities.int2Bytes(customer),0,_temp,4,4);
+ System.arraycopy(Utilities.int2Bytes(_zipped),0,_temp,8,4);
+ System.arraycopy(Utilities.UUID2Byte(token),0,_temp,12,16);
+ System.arraycopy(Utilities.int2Bytes(_sendLength),0,_temp,28,4);
+ if (_sendLength > 0)
+ {
+ System.arraycopy(data,0,_temp,32,_sendLength);
+ }
+ return _temp;
+ }
+
+
+ /*
+
+ 从接收的数据命令开始解析
+
+ */
+
+ public static byte[] CommandAnalysis(byte[] head, byte[] content)
+ {
+ if (content != null)
+ {
+ byte[] buffer = new byte[4];
+ buffer[0] = head[8];
+ buffer[1] = head[9];
+ buffer[2] = head[10];
+ buffer[3] = head[11];
+
+ int _zipped = Utilities.bytes2Int(buffer);
+ // 先进行解压
+ if (_zipped == HslCommunicationCode.Hsl_Protocol_Zipped)
+ {
+ content = HslZipped.Decompress(content);
+ }
+ // 进行解密
+ return HslSecurity.ByteDecrypt(content);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/ProgressReport.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/ProgressReport.java
new file mode 100644
index 0000000..29b7a7e
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Net/ProgressReport.java
@@ -0,0 +1,16 @@
+package com.example.HslCommunication.Core.Net;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+
+public abstract class ProgressReport {
+
+
+ public void Report(long current,long totle)
+ {
+
+ }
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/HslTimeOut.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/HslTimeOut.java
new file mode 100644
index 0000000..83db408
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/HslTimeOut.java
@@ -0,0 +1,26 @@
+package com.example.HslCommunication.Core.Types;
+
+import java.net.Socket;
+import java.util.Date;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class HslTimeOut {
+
+
+ public HslTimeOut()
+ {
+ StartTime = new Date();
+ IsSuccessful = false;
+ }
+
+ public Date StartTime=null;
+
+ public boolean IsSuccessful=false;
+
+ public int DelayTime=5000;
+
+ public Socket WorkSocket=null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/NetHandle.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/NetHandle.java
new file mode 100644
index 0000000..4ddad35
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/NetHandle.java
@@ -0,0 +1,109 @@
+package com.example.HslCommunication.Core.Types;
+
+import com.example.HslCommunication.Core.Utilities.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public final class NetHandle {
+
+
+ ///
+ /// 初始化一个暗号对象
+ ///
+ public NetHandle(int value)
+ {
+ byte[] buffer = Utilities.int2Bytes(value);
+
+ m_CodeMajor = buffer[3];
+ m_CodeMinor = buffer[2];
+ m_CodeIdentifier = Utilities.byte2Short(buffer,0);
+
+
+ m_CodeValue = value;
+ }
+
+
+ ///
+ /// 根据三个值来初始化暗号对象
+ ///
+ /// 主暗号
+ /// 次暗号
+ /// 暗号编号
+ public NetHandle(int major, int minor, int identifier)
+ {
+ m_CodeValue = 0;
+
+ byte[] buffer_major=Utilities.int2Bytes(major);
+ byte[] buffer_minor=Utilities.int2Bytes(minor);
+ byte[] buffer_identifier=Utilities.int2Bytes(identifier);
+
+ m_CodeMajor = buffer_major[0];
+ m_CodeMinor = buffer_minor[0];
+ m_CodeIdentifier = Utilities.byte2Short(buffer_identifier,0);
+
+ byte[] buffer = new byte[4];
+ buffer[3] = m_CodeMajor;
+ buffer[2] = m_CodeMinor;
+ buffer[1] = buffer_identifier[1];
+ buffer[0] = buffer_identifier[0];
+
+ m_CodeValue = Utilities.bytes2Int(buffer);
+ }
+
+
+ ///
+ /// 完整的暗号值
+ ///
+ private int m_CodeValue;
+
+ ///
+ /// 主暗号分类0-255
+ ///
+ private byte m_CodeMajor;
+
+ ///
+ /// 次要的暗号分类0-255
+ ///
+ private byte m_CodeMinor;
+
+ ///
+ /// 暗号的编号分类0-65535
+ ///
+ private short m_CodeIdentifier;
+
+
+
+ ///
+ /// 完整的暗号值
+ ///
+ public int get_CodeValue(){
+ return m_CodeValue;
+ }
+
+ ///
+ /// 主暗号分类0-255
+ ///
+ public byte get_CodeMajor() {
+ return m_CodeMajor;
+ }
+
+ ///
+ /// 次要的暗号分类0-255
+ ///
+ public byte get_CodeMinor() {
+ return m_CodeMinor;
+ }
+
+ ///
+ /// 暗号的编号分类0-65535
+ ///
+ public short get_CodeIdentifier() {
+ return m_CodeIdentifier;
+ }
+
+
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResult.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResult.java
new file mode 100644
index 0000000..d5d8874
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResult.java
@@ -0,0 +1,38 @@
+package com.example.HslCommunication.Core.Types;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class OperateResult {
+
+ ///
+ /// 指示本次访问是否成功
+ ///
+ public boolean IsSuccess =false;
+
+
+ ///
+ /// 具体的错误描述
+ ///
+ public String Message = "Unknown Errors";
+ ///
+ /// 具体的错误代码
+ ///
+ public int ErrorCode = 10000;
+
+ ///
+ /// 消息附带的额外信息
+ ///
+ public Object Tag =null;
+
+ ///
+ /// 获取错误代号及文本描述
+ ///
+ ///
+ public String ToMessageShowString()
+ {
+ return "错误代码:"+ErrorCode +"\r\n错误信息:"+Message;
+ }
+
+}
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResultBytes.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResultBytes.java
new file mode 100644
index 0000000..bc2d1ba
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResultBytes.java
@@ -0,0 +1,9 @@
+package com.example.HslCommunication.Core.Types;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+public class OperateResultBytes extends OperateResult {
+ public byte[] Content =null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResultString.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResultString.java
new file mode 100644
index 0000000..7f7bea9
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Types/OperateResultString.java
@@ -0,0 +1,11 @@
+package com.example.HslCommunication.Core.Types;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+
+
+public class OperateResultString extends OperateResult {
+ public String Content = null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/Utilities.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/Utilities.java
new file mode 100644
index 0000000..f4c2fd8
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/Utilities.java
@@ -0,0 +1,172 @@
+package com.example.HslCommunication.Core.Utilities;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * Created by DATHLIN on 2017/11/1.
+ */
+
+
+
+public class Utilities {
+
+ public static byte[] int2Bytes(int num) {
+ byte[] byteNum = new byte[4];
+ for (int ix = 0; ix < 4; ++ix) {
+ int offset = 32 - (ix + 1) * 8;
+ byteNum[3-ix] = (byte) ((num >> offset) & 0xff);
+ }
+ return byteNum;
+ }
+
+ public static int bytes2Int(byte[] byteNum) {
+ int num = 0;
+ for (int ix = 0; ix < 4; ++ix) {
+ num <<= 8;
+ num |= (byteNum[3-ix] & 0xff);
+ }
+ return num;
+ }
+
+ public static byte int2OneByte(int num) {
+ return (byte) (num & 0x000000ff);
+ }
+
+ public static int oneByte2Int(byte byteNum) {
+ //针对正数的int
+ return byteNum > 0 ? byteNum : (128 + (128 + byteNum));
+ }
+
+ public static byte[] long2Bytes(long num) {
+ byte[] byteNum = new byte[8];
+ for (int ix = 0; ix < 8; ++ix) {
+ int offset = 64 - (ix + 1) * 8;
+ byteNum[7-ix] = (byte) ((num >> offset) & 0xff);
+ }
+ return byteNum;
+ }
+
+ public static long bytes2Long(byte[] byteNum) {
+ long num = 0;
+ for (int ix = 0; ix < 8; ++ix) {
+ num <<= 8;
+ num |= (byteNum[7-ix] & 0xff);
+ }
+ return num;
+ }
+
+ public static UUID Byte2UUID(byte[] data) {
+ if (data.length != 16) {
+ throw new IllegalArgumentException("Invalid UUID byte[]");
+ }
+ long msb = 0;
+ long lsb = 0;
+ for (int i = 0; i < 8; i++)
+ msb = (msb << 8) | (data[i] & 0xff);
+ for (int i = 8; i < 16; i++)
+ lsb = (lsb << 8) | (data[i] & 0xff);
+
+ return new UUID(msb, lsb);
+ }
+
+ public static byte[] UUID2Byte(UUID uuid) {
+ ByteArrayOutputStream ba = new ByteArrayOutputStream(16);
+ DataOutputStream da = new DataOutputStream(ba);
+ try {
+ da.writeLong(uuid.getMostSignificantBits());
+ da.writeLong(uuid.getLeastSignificantBits());
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ byte[] buffer = ba.toByteArray();
+ // 进行错位
+ byte temp=buffer[0];
+ buffer[0] = buffer[3];
+ buffer[3] =temp;
+ temp=buffer[1];
+ buffer[1]=buffer[2];
+ buffer[2]=temp;
+
+ temp = buffer[4];
+ buffer[4]=buffer[5];
+ buffer[5] =temp;
+
+ temp = buffer[6];
+ buffer[6]=buffer[7];
+ buffer[7] =temp;
+
+ return buffer;
+ }
+
+ public static short byte2Short(byte[] b, int index) {
+ return (short) (((b[index + 0] << 8) | b[index + 1] & 0xff));
+ }
+
+
+ public static byte[] short2Byte(short s) {
+ byte[] targets = new byte[2];
+ for (int i = 0; i < 2; i++) {
+ int offset = (targets.length - 1 - i) * 8;
+ targets[1-i] = (byte) ((s >>> offset) & 0xff);
+ }
+ return targets;
+ }
+
+ public static byte[] string2Byte(String str) {
+ if (str == null) {
+ return null;
+ }
+ byte[] byteArray;
+ try {
+ byteArray = str.getBytes("unicode");
+ } catch (Exception ex) {
+ byteArray = str.getBytes();
+ }
+
+ for(int i=0;i>> 4 & 0xf];
+ buf[index++] = HEX_CHAR[b & 0xf];
+ }
+
+ return new String(buf);
+ }
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWith2Bytes.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWith2Bytes.java
new file mode 100644
index 0000000..e036dd1
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWith2Bytes.java
@@ -0,0 +1,9 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public class boolWith2Bytes extends boolWithBytes {
+ public byte[] Content2=null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithBytes.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithBytes.java
new file mode 100644
index 0000000..63d3173
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithBytes.java
@@ -0,0 +1,14 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+
+public class boolWithBytes extends boolWithNone {
+
+
+ public byte[] Content=null;
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithIntByte.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithIntByte.java
new file mode 100644
index 0000000..70b0d63
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithIntByte.java
@@ -0,0 +1,9 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public class boolWithIntByte extends boolWithBytes {
+ public int DataInt=0;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithIntString.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithIntString.java
new file mode 100644
index 0000000..733e027
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithIntString.java
@@ -0,0 +1,14 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public class boolWithIntString extends boolWithNone {
+
+
+ public int DataInt=0;
+
+
+ public String DataString=null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithNone.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithNone.java
new file mode 100644
index 0000000..139ba50
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithNone.java
@@ -0,0 +1,23 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/3.
+ */
+
+
+
+
+/*
+*
+* 结果类的基础,提供一个boolen
+*
+*
+* */
+
+public class boolWithNone {
+
+ /*
+ 返回真还是否
+ */
+ public boolean Result = false;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithSiemens.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithSiemens.java
new file mode 100644
index 0000000..10bf9cc
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithSiemens.java
@@ -0,0 +1,16 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/3.
+ */
+
+public class boolWithSiemens extends boolWithNone {
+
+
+ public byte type=0;
+
+ public int startAddress=0;
+
+ public short dbAddress=0;
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithSocket.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithSocket.java
new file mode 100644
index 0000000..adc5303
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithSocket.java
@@ -0,0 +1,11 @@
+package com.example.HslCommunication.Core.Utilities;
+
+import java.net.Socket;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ */
+
+public class boolWithSocket extends boolWithNone {
+ public Socket Socket=null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithString.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithString.java
new file mode 100644
index 0000000..cab278b
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Core/Utilities/boolWithString.java
@@ -0,0 +1,10 @@
+package com.example.HslCommunication.Core.Utilities;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public class boolWithString extends boolWithNone {
+
+ public String Content=null;
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/AsyncStateOne.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/AsyncStateOne.java
new file mode 100644
index 0000000..4edfd73
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/AsyncStateOne.java
@@ -0,0 +1,135 @@
+package com.example.HslCommunication.Enthernet;
+
+import com.example.HslCommunication.Core.Net.HslCommunicationCode;
+
+import java.net.Socket;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ */
+
+public class AsyncStateOne {
+
+
+ ///
+ /// 实例化一个对象
+ ///
+ public AsyncStateOne() {
+ ClientUniqueID = UUID.randomUUID().toString();
+ }
+
+ ///
+ /// IP地址
+ ///
+ private String IpAddress = "";
+
+ public String getIpAddress() {
+ return IpAddress;
+ }
+
+ private void setIpAddress(String ipAddress) {
+ IpAddress = ipAddress;
+ }
+
+
+ /*
+ 端口号
+ */
+ private int IpPort = 10000;
+
+ public int getIpPort() {
+ return IpPort;
+ }
+
+ private void setIpPort(int ipPort) {
+ IpPort = ipPort;
+ }
+
+
+ /*
+ 登录的别名
+ */
+ private String LoginAlias = "";
+
+ public String getLoginAlias() {
+ return LoginAlias;
+ }
+
+ public void setLoginAlias(String loginAlias) {
+ LoginAlias = loginAlias;
+ }
+
+
+ /*
+ 心跳验证的时间点
+ */
+ private Date HeartTime=new Date();
+ public Date getHeartTime() {
+ return HeartTime;
+ }
+
+ public void setHeartTime(Date heartTime) {
+ HeartTime = heartTime;
+ }
+
+
+ /*
+ 客户端类别
+ */
+ private String ClientType="";
+ public void setClientType(String clientType) {
+ ClientType = clientType;
+ }
+
+
+ public String getClientType() {
+ return ClientType;
+ }
+
+
+ /*
+ 客户端的唯一标识
+ */
+ private String ClientUniqueID="";
+ public String getClientUniqueID() {
+ return ClientUniqueID;
+ }
+
+ public void setClientUniqueID(String clientUniqueID) {
+ ClientUniqueID = clientUniqueID;
+ }
+
+
+
+ ///
+ /// 指令头缓存
+ ///
+ byte[] BytesHead = new byte[HslCommunicationCode.HeadByteLength];
+ ///
+ /// 已经接收的指令头长度
+ ///
+ int AlreadyReceivedHead = 0;
+ ///
+ /// 数据内容缓存
+ ///
+ byte[] BytesContent = null;
+ ///
+ /// 已经接收的数据内容长度
+ ///
+ int AlreadyReceivedContent = 0;
+
+ ///
+ /// 清除本次的接收内容
+ ///
+ void Clear() {
+ BytesHead = new byte[HslCommunicationCode.HeadByteLength];
+ AlreadyReceivedHead = 0;
+ BytesContent = null;
+ AlreadyReceivedContent = 0;
+ }
+
+
+ Socket WorkSocket=null;
+}
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/NetComplexClient.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/NetComplexClient.java
new file mode 100644
index 0000000..008759c
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/NetComplexClient.java
@@ -0,0 +1,442 @@
+package com.example.HslCommunication.Enthernet;
+
+import com.example.HslCommunication.Core.Net.HslCommunicationCode;
+import com.example.HslCommunication.Core.Net.NetShareBase;
+import com.example.HslCommunication.Core.Net.NetSupport;
+import com.example.HslCommunication.Core.Types.NetHandle;
+import com.example.HslCommunication.Core.Types.OperateResult;
+import com.example.HslCommunication.Core.Utilities.Utilities;
+import com.example.HslCommunication.Core.Utilities.boolWith2Bytes;
+import com.example.HslCommunication.Core.Utilities.boolWithSocket;
+import com.example.HslCommunication.Log.LogUtil;
+import com.example.HslCommunication.Resources.StringResources;
+
+import java.net.Socket;
+import java.util.Date;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ */
+
+public class NetComplexClient extends NetShareBase {
+
+
+
+ ///
+ /// 客户端的核心连接块
+ ///
+ private AsyncStateOne stateone = new AsyncStateOne();
+ ///
+ /// 客户端系统是否启动
+ ///
+ public boolean Is_Client_Start = false;
+
+ ///
+ /// 重连接失败的次数
+ ///
+ public int Connect_Failed_Count = 0;
+ ///
+ /// 指示客户端是否处于正在连接服务器中
+ ///
+ private boolean Is_Client_Connecting = false;
+ ///
+ /// 登录服务器的判断锁
+ ///
+ private Object lock_connecting = new Object();
+ ///
+ /// 客户端登录的标识名称,可以为ID号,也可以为登录名
+ ///
+ public String ClientAlias = "";
+ ///
+ /// 远程服务器的IP地址和端口
+ ///
+ public String ServerIp = "127.0.0.1";
+ /*
+ 远程服务器的端口
+ */
+ public int ServerPort = 10000;
+
+ ///
+ /// 服务器的时间,自动实现和服务器同步
+ ///
+ private Date ServerTime = new Date();
+ ///
+ /// 系统与服务器的延时时间,单位毫秒
+ ///
+ private int DelayTime =0;
+
+
+
+ public void LoginSuccess()
+ {
+
+ }
+
+ public void LoginFailed(int times)
+ {
+
+ }
+
+ public void MessageAlerts(String msg)
+ {
+
+ }
+
+ public void BeforReConnected()
+ {
+
+ }
+
+ public void AcceptString(NetHandle handle, String msg)
+ {
+
+ }
+
+ public void AcceptByte( NetHandle handle, byte[] msg)
+ {
+
+ }
+
+
+ private boolean IsQuie = false;
+
+ ///
+ /// 关闭该客户端引擎
+ ///
+ public void ClientClose() {
+ IsQuie = true;
+ if (Is_Client_Start)
+ SendBytes(stateone, NetSupport.CommandBytes(HslCommunicationCode.Hsl_Protocol_Client_Quit, 0, KeyToken, null));
+
+ if (thread_heart_check != null) thread_heart_check.interrupt();
+ Is_Client_Start = false;
+
+
+ ThreadSleep(10);
+
+ CloseSocket(stateone.WorkSocket);
+ LogUtil.LogD("ClientClose","Client Close.");
+ }
+ ///
+ /// 启动客户端引擎,连接服务器系统
+ ///
+ public void ClientStart()
+ {
+ if (Is_Client_Start) return;
+ Thread thread_login = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ThreadLogin();
+ }
+ });
+ thread_login.start();
+ LogUtil.LogD("ClientStart","Client Start.");
+
+ if (thread_heart_check == null)
+ {
+ thread_heart_check = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ThreadHeartCheck();
+ }
+ });
+ thread_heart_check.start();
+ }
+ }
+ private void ThreadLogin()
+ {
+ synchronized (lock_connecting)
+ {
+ if (Is_Client_Connecting) return;
+ Is_Client_Connecting = true;
+ }
+
+
+ if (Connect_Failed_Count == 0)
+ {
+ MessageAlerts("正在连接服务器...");
+ }
+ else
+ {
+ int count = 10;
+ while (count > 0)
+ {
+ if (IsQuie) return;
+ MessageAlerts("连接断开,等待" + count-- + "秒后重新连接");
+ ThreadSleep(1000);
+ }
+ MessageAlerts("正在尝试第" + Connect_Failed_Count + "次连接服务器...");
+ }
+
+
+ stateone.setHeartTime(new Date());
+ LogUtil.LogD("ThreadLogin","Begin Connect Server, Times: " + Connect_Failed_Count);
+
+
+ OperateResult result = new OperateResult();
+
+ Socket socket=null;
+ boolWithSocket valueSocket = CreateSocketAndConnect(ServerIp,ServerPort,result);
+ if(!valueSocket.Result)
+ {
+ Connect_Failed_Count++;
+ Is_Client_Connecting = false;
+ LoginFailed(Connect_Failed_Count);
+ LogUtil.LogW("ThreadLogin","Connected Failed, Times: " + Connect_Failed_Count);
+ // 连接失败,重新连接服务器
+ ReconnectServer();
+ return;
+ }
+
+ socket = valueSocket.Socket;
+
+ // 连接成功,发送数据信息
+ if(!SendStringAndCheckReceive(
+ socket,
+ 1,
+ ClientAlias,
+ result,
+ null,
+ null
+ ))
+ {
+ Connect_Failed_Count++;
+ Is_Client_Connecting = false;
+ LogUtil.LogD("ThreadLogin","Login Server Failed, Times: " + Connect_Failed_Count);
+ LoginFailed(Connect_Failed_Count);
+ // 连接失败,重新连接服务器
+ ReconnectServer();
+ return;
+ }
+
+ // 登录成功
+ Connect_Failed_Count = 0;
+ //stateone.IpEndPoint = (IPEndPoint)socket.RemoteEndPoint;
+ stateone.setClientType(ClientAlias);
+ stateone.WorkSocket = socket;
+ //stateone.WorkSocket.BeginReceive(stateone.BytesHead, stateone.AlreadyReceivedHead,
+ //stateone.BytesHead.Length - stateone.AlreadyReceivedHead, SocketFlags.None,
+ //new AsyncCallback(HeadReceiveCallback), stateone);
+
+ Thread receive = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ThreadReceiveBackground();
+ }
+ });
+ receive.start();
+
+
+
+ // 发送一条验证消息
+ byte[] bytesTemp = new byte[16];
+
+ //BitConverter.GetBytes(DateTime.Now.Ticks).CopyTo(bytesTemp, 0);
+ SendBytes(stateone, NetSupport.CommandBytes(HslCommunicationCode.Hsl_Protocol_Check_Secends, 0, KeyToken, bytesTemp));
+
+
+ stateone.setHeartTime(new Date());
+ Is_Client_Start = true;
+ LoginSuccess();
+
+ LogUtil.LogD("ThreadLogin","Login Server Success, Times: " + Connect_Failed_Count);
+
+ Is_Client_Connecting = false;
+
+ ThreadSleep(1000);
+ }
+
+
+
+ private void ThreadReceiveBackground()
+ {
+ while (true)
+ {
+ OperateResult result = new OperateResult();
+ boolWith2Bytes value = ReceiveAndCheckBytes(stateone.WorkSocket, result, null,null);
+
+ if (!value.Result)
+ {
+ continue;
+ }
+
+ // 数据处理
+ byte[] buffer1= new byte[4];
+ buffer1[0] = value.Content[0];
+ buffer1[1] = value.Content[1];
+ buffer1[2] = value.Content[2];
+ buffer1[3] = value.Content[3];
+
+ byte[] buffer2= new byte[4];
+ buffer2[0] = value.Content[4];
+ buffer2[1] = value.Content[5];
+ buffer2[2] = value.Content[6];
+ buffer2[3] = value.Content[7];
+
+ int protocol = Utilities.bytes2Int(buffer1);
+ int customer = Utilities.bytes2Int(buffer2);
+
+ DataProcessingCenter(null,protocol,customer,value.Content2);
+ }
+ }
+
+
+ // private bool Is_reconnect_server = false;
+ // private object lock_reconnect_server = new object();
+
+
+ private void ReconnectServer()
+ {
+ // 是否连接服务器中,已经在连接的话,则不再连接
+ if (Is_Client_Connecting) return;
+ // 是否退出了系统,退出则不再重连
+ if (IsQuie) return;
+
+ LogUtil.LogI("ReconnectServer","Prepare ReConnect Server.");
+
+ // 触发连接失败,重连系统前错误
+ BeforReConnected();
+ CloseSocket(stateone.WorkSocket);
+
+ Thread thread_login = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ThreadLogin();
+ }
+ });
+ thread_login.start();
+ }
+
+
+ ///
+ /// 通信出错后的处理
+ ///
+ ///
+ ///
+ void SocketReceiveException(AsyncStateOne receive, Exception ex)
+ {
+ if (ex.getMessage().contains(StringResources.SocketRemoteCloseException))
+ {
+ // 异常掉线
+ ReconnectServer();
+ }
+ else
+ {
+ // MessageAlerts?.Invoke("数据接收出错:" + ex.Message);
+ }
+
+ LogUtil.LogD("SocketReceiveException","Socket Excepiton Occured.");
+ }
+
+
+ ///
+ /// 服务器端用于数据发送文本的方法
+ ///
+ /// 用户自定义的命令头
+ /// 发送的文本
+ public void Send(NetHandle customer, String str)
+ {
+ if (Is_Client_Start)
+ {
+ SendBytes(stateone, NetSupport.CommandBytes(customer.get_CodeValue(), KeyToken, str));
+ }
+ }
+ ///
+ /// 服务器端用于发送字节的方法
+ ///
+ /// 用户自定义的命令头
+ /// 实际发送的数据
+ public void Send(NetHandle customer, byte[] bytes)
+ {
+ if (Is_Client_Start)
+ {
+ SendBytes(stateone, NetSupport.CommandBytes(customer.get_CodeValue(), KeyToken, bytes));
+ }
+ }
+
+ private void SendBytes(final AsyncStateOne stateone, final byte[] content)
+ {
+ Thread thread_login = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ stateone.WorkSocket.getOutputStream().write(content);
+ } catch (Exception ex) {
+
+ }
+ }
+ });
+ thread_login.start();
+ //SendBytesAsync(stateone, content);
+ }
+
+ ///
+ /// 客户端的数据处理中心
+ ///
+ ///
+ ///
+ ///
+ ///
+ void DataProcessingCenter(AsyncStateOne receive, int protocol, int customer, byte[] content)
+ {
+ if (protocol == HslCommunicationCode.Hsl_Protocol_Check_Secends)
+ {
+ //Date dt = new Date(BitConverter.ToInt64(content, 0));
+ //ServerTime = new Date(BitConverter.ToInt64(content, 8));
+ //DelayTime = (int)(new Date() - dt).TotalMilliseconds;
+ stateone.setHeartTime(new Date());
+ // MessageAlerts?.Invoke("心跳时间:" + DateTime.Now.ToString());
+ }
+ else if (protocol == HslCommunicationCode.Hsl_Protocol_Client_Quit)
+ {
+ // 申请了退出
+ }
+ else if (protocol == HslCommunicationCode.Hsl_Protocol_User_Bytes)
+ {
+ // 接收到字节数据
+ AcceptByte(new NetHandle(customer), content);
+ }
+ else if (protocol == HslCommunicationCode.Hsl_Protocol_User_String)
+ {
+ // 接收到文本数据
+ String str = Utilities.byte2String(content);
+ AcceptString(new NetHandle(customer), str);
+ }
+ }
+
+
+ private Thread thread_heart_check = null;
+
+ ///
+ /// 心跳线程的方法
+ ///
+ private void ThreadHeartCheck()
+ {
+
+ ThreadSleep(2000);
+ while (true)
+ {
+ ThreadSleep(1000);
+
+ if (!IsQuie)
+ {
+ byte[] send = new byte[16];
+ System.arraycopy(Utilities.long2Bytes(new Date().getTime()),0,send,0,8);
+ SendBytes(stateone, NetSupport.CommandBytes(HslCommunicationCode.Hsl_Protocol_Check_Secends, 0, KeyToken, send));
+ double timeSpan = (new Date().getTime() - stateone.getHeartTime().getTime())/1000;
+ if (timeSpan > 1 * 8)//8次没有收到失去联系
+ {
+ LogUtil.LogD("ThreadHeartCheck","Heart Check Failed int "+timeSpan+" Seconds.");
+ ReconnectServer();
+ ThreadSleep(1000);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/NetSimplifyClient.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/NetSimplifyClient.java
new file mode 100644
index 0000000..1b0d31e
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Enthernet/NetSimplifyClient.java
@@ -0,0 +1,137 @@
+package com.example.HslCommunication.Enthernet;
+
+import com.example.HslCommunication.Core.Net.HslCommunicationCode;
+import com.example.HslCommunication.Core.Net.NetShareBase;
+import com.example.HslCommunication.Core.Net.ProgressReport;
+import com.example.HslCommunication.Core.Utilities.boolWith2Bytes;
+import com.example.HslCommunication.Core.Utilities.Utilities;
+import com.example.HslCommunication.Core.Types.NetHandle;
+import com.example.HslCommunication.Core.Types.OperateResultBytes;
+import com.example.HslCommunication.Core.Types.OperateResultString;
+import com.example.HslCommunication.Core.Utilities.boolWithSocket;
+import com.example.HslCommunication.Resources.StringResources;
+
+import java.io.InputStream;
+import java.net.Socket;
+import java.util.UUID;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public final class NetSimplifyClient extends NetShareBase {
+
+
+
+ ///
+ /// 实例化一个客户端的对象,用于和服务器通信
+ ///
+ public NetSimplifyClient(String ipAddress, int port, UUID token)
+ {
+ m_ipAddress = ipAddress;
+ m_port = port;
+ KeyToken = token;
+ }
+
+ private String m_ipAddress="127.0.0.1";
+ private int m_port=10000;
+
+ ///
+ /// 客户端向服务器进行请求,请求字符串数据
+ ///
+ /// 用户的指令头
+ /// 发送数据
+ /// 发送数据时的进度报告
+ /// 接收数据时的进度报告
+ ///
+ public OperateResultString ReadFromServer(
+ NetHandle customer,
+ String send,
+ ProgressReport sendStatus,
+ ProgressReport receiveStatus
+ )
+ {
+ OperateResultString result = new OperateResultString();
+ byte[] data = Utilities.string2Byte(send);
+ OperateResultBytes temp = ReadFromServerBase(HslCommunicationCode.Hsl_Protocol_User_String, customer.get_CodeValue(), data, sendStatus, receiveStatus);
+ result.IsSuccess = temp.IsSuccess;
+ result.ErrorCode = temp.ErrorCode;
+ result.Message = temp.Message;
+ if (temp.IsSuccess)
+ {
+ result.Content = Utilities.byte2String(temp.Content);
+ }
+ temp = null;
+ return result;
+ }
+
+
+ ///
+ /// 客户端向服务器进行请求,请求字节数据
+ ///
+ /// 用户的指令头
+ ///
+ /// 发送数据的进度报告
+ /// 接收数据的进度报告
+ ///
+ public OperateResultBytes ReadFromServer(
+ NetHandle customer,
+ byte[] send,
+ ProgressReport sendStatus,
+ ProgressReport receiveStatus
+ )
+ {
+ return ReadFromServerBase(HslCommunicationCode.Hsl_Protocol_User_Bytes, customer.get_CodeValue(), send, sendStatus, receiveStatus);
+ }
+
+ ///
+ /// 需要发送的底层数据
+ ///
+ /// 数据的指令头
+ /// 用户的指令头
+ /// 需要发送的底层数据
+ /// 发送状态的进度报告,用于显示上传进度
+ /// 接收状态的进度报告,用于显示下载进度
+ ///
+ private OperateResultBytes ReadFromServerBase(
+ int headcode,
+ int customer,
+ byte[] send,
+ ProgressReport sendStatus,
+ ProgressReport receiveStatus)
+ {
+ OperateResultBytes result = new OperateResultBytes();
+
+ // 创建并连接套接字
+ Socket socket=null;
+ boolWithSocket valueSocket=CreateSocketAndConnect(m_ipAddress, m_port,result);
+ if(!valueSocket.Result)
+ {
+ return result;
+ }
+
+ socket = valueSocket.Socket;
+
+ // 发送并检查数据是否发送完成
+ if (!SendBaseAndCheckReceive(socket, headcode, customer, send, result, sendStatus,null))
+ {
+ return result;
+ }
+
+ // 接收头数据和内容数据
+
+ boolWith2Bytes value = ReceiveAndCheckBytes(socket, result, receiveStatus,null);
+
+ if (!value.Result)
+ {
+ return result;
+ }
+
+ CloseSocket(socket);
+ result.Content = value.Content2;
+ result.IsSuccess = true;
+ return result;
+ }
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Log/LogUtil.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Log/LogUtil.java
new file mode 100644
index 0000000..bf11119
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Log/LogUtil.java
@@ -0,0 +1,68 @@
+package com.example.HslCommunication.Log;
+
+import android.util.Log;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ * 一个扩展的日志工具,用来实现对记录日志的特殊处理,屏蔽操作
+ */
+
+public class LogUtil {
+
+ public static final int VerBose = 1;
+
+ public static final int Debug = 2;
+
+ public static final int Info = 3;
+
+ public static final int Warn = 4;
+
+ public static final int Error = 5;
+
+ public static final int Nothing = 6;
+
+ public static int Level = VerBose;
+
+ /*
+ 记录零碎的日志
+ */
+ public static void LogV(String tag, String msg) {
+ if (Level <= VerBose) Log.v(tag, msg);
+ }
+
+ /*
+ 记录调试日志
+ */
+ public static void LogD(String tag, String msg) {
+ if (Level <= Debug) Log.d(tag, msg);
+ }
+
+ /*
+ 记录信息日志
+ */
+ public static void LogI(String tag, String msg) {
+ if (Level <= Info) Log.i(tag, msg);
+ }
+
+ /*
+ 记录警告日志
+ */
+ public static void LogW(String tag, String msg) {
+ if (Level <= Warn) Log.w(tag, msg);
+ }
+
+ /*
+ 记录一般错误日志
+ */
+ public static void LogE(String tag, String msg) {
+ if (Level <= Error) Log.e(tag, msg);
+ }
+
+ /*
+ 记录带信息异常的错误日志
+ */
+ public static void LogE(String tag, String msg, Exception ex) {
+ if (Level <= Error) Log.e(tag, msg, ex);
+ }
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/PlcNetBase.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/PlcNetBase.java
new file mode 100644
index 0000000..90a403e
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/PlcNetBase.java
@@ -0,0 +1,72 @@
+package com.example.HslCommunication.Profinet;
+
+import com.example.HslCommunication.Core.Net.NetBase;
+
+/**
+ * Created by DATHLIN on 2017/11/3.
+ */
+
+public abstract class PlcNetBase extends NetBase {
+
+
+ protected int m_PortRead = 1000;
+ protected int m_PortReadBackup = -1;
+ protected boolean m_IsPortNormal = true;
+ protected int m_PortWrite = 1001;
+
+
+
+ ///
+ /// 获取访问的端口号
+ ///
+ ///
+ protected int GetPort()
+ {
+ if (m_PortReadBackup <= 0) return m_PortRead;
+ return m_IsPortNormal ? m_PortRead : m_PortReadBackup;
+ }
+ ///
+ /// 更换端口号
+ ///
+ protected void ChangePort()
+ {
+ m_IsPortNormal = !m_IsPortNormal;
+ }
+
+
+ public void setPortRead(int value) {
+ m_PortRead = value;
+ }
+
+
+ public int getPortRead()
+ {
+ return m_PortRead;
+ }
+
+
+ ///
+ /// 控制字节长度,超出选择截断,不够补零
+ ///
+ /// 字节数据
+ /// 最终需要的目标长度
+ /// 处理后的数据
+ protected byte[] ManageBytesLength(byte[] bytes, int length)
+ {
+ if (bytes == null) return null;
+ byte[] temp = new byte[length];
+ if (length > bytes.length)
+ {
+ System.arraycopy(bytes, 0, temp, 0, bytes.length);
+ }
+ else
+ {
+ System.arraycopy(bytes, 0, temp, 0, length);
+ }
+ return temp;
+ }
+
+
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/SiemensPLCS.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/SiemensPLCS.java
new file mode 100644
index 0000000..d5dd1b1
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/SiemensPLCS.java
@@ -0,0 +1,11 @@
+package com.example.HslCommunication.Profinet;
+
+/**
+ * Created by DATHLIN on 2017/11/3.
+ */
+
+public enum SiemensPLCS {
+ S1200,
+ S300,
+ Smart200,
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/SiemensTcpNet.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/SiemensTcpNet.java
new file mode 100644
index 0000000..4ef28f6
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Profinet/SiemensTcpNet.java
@@ -0,0 +1,780 @@
+package com.example.HslCommunication.Profinet;
+
+import com.example.HslCommunication.Core.Net.NetSupport;
+import com.example.HslCommunication.Core.Types.OperateResult;
+import com.example.HslCommunication.Core.Types.OperateResultBytes;
+import com.example.HslCommunication.Core.Utilities.Utilities;
+import com.example.HslCommunication.Core.Utilities.boolWithBytes;
+import com.example.HslCommunication.Core.Utilities.boolWithSiemens;
+import com.example.HslCommunication.Core.Utilities.boolWithSocket;
+
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.ArrayList;
+
+/**
+ * Created by DATHLIN on 2017/11/3.
+ */
+
+public final class SiemensTcpNet extends PlcNetBase {
+
+ ///
+ /// 实例化一个数据通信的对象,需要指定访问哪种Plc
+ ///
+ ///
+ public SiemensTcpNet(SiemensPLCS siemens)
+ {
+ m_PortRead = 102;
+ m_PortWrite = 102;
+ CurrentPlc = siemens;
+
+ switch (siemens)
+ {
+ case S1200: plcHead1[18] = 1; break;
+ case S300: plcHead1[18] = 2; break;
+ case Smart200:plcHead1[18] = 1; break;
+ default: plcHead1[18] = 3; break;
+ }
+ }
+
+
+ ///
+ /// 可以手动设置PLC类型,用来测试原本不支持的数据访问功能
+ ///
+ ///
+ public void SetPlcType(byte type)
+ {
+ plcHead1[18] = type;
+ }
+
+ private String ipAddress="";
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+
+ private boolWithBytes ReceiveBytesFromSocket(Socket socket)
+ {
+ boolWithBytes value =new boolWithBytes();
+ try
+ {
+ // 先接收4个字节的数据
+ byte[] head = NetSupport.ReadBytesFromSocket(socket, 4);
+ int receive = head[2] * 256 + head[3];
+ value.Content = new byte[receive];
+ System.arraycopy(head,0,value.Content,0, 4);
+ byte[] data = NetSupport.ReadBytesFromSocket(socket, receive - 4);
+ System.arraycopy(data,0,value.Content,4,data.length);
+ value.Result=true;
+ return value;
+ }
+ catch(Exception ex)
+ {
+ CloseSocket(socket);
+ return value;
+ }
+ }
+
+ private boolean SendBytesToSocket(Socket socket, byte[] data)
+ {
+ try
+ {
+ if (data != null)
+ {
+ OutputStream outputStream = socket.getOutputStream();
+ outputStream.write(data);
+ }
+ return true;
+ }
+ catch(Exception ex)
+ {
+ CloseSocket(socket);
+ return false;
+ }
+ }
+
+
+ private int CalculateAddressStarted(String address)
+ {
+ if (address.indexOf('.') < 0)
+ {
+ return Integer.parseInt(address) * 8;
+ }
+ else
+ {
+ String[] temp = address.split("\\.");
+ return Integer.parseInt(temp[0]) * 8 + Integer.parseInt(temp[1]);
+ }
+ }
+
+ ///
+ /// 解析数据地址
+ ///
+ /// 数据地址
+ /// 类型
+ /// 其实地址
+ /// DB块地址
+ /// 结果数据对象
+ ///
+ private boolWithSiemens AnalysisAddress(String address, OperateResult result)
+ {
+ boolWithSiemens value = new boolWithSiemens();
+ try
+ {
+ value.dbAddress = 0;
+ if (address.charAt(0) == 'I')
+ {
+ value.type = -127;
+ value.startAddress = CalculateAddressStarted(address.substring(1));
+ }
+ else if (address.charAt(0) == 'Q')
+ {
+ value.type = -126;
+ value.startAddress = CalculateAddressStarted(address.substring(1));
+ }
+ else if (address.charAt(0) == 'M')
+ {
+ value.type = -125;
+ value.startAddress = CalculateAddressStarted(address.substring(1));
+ }
+ else if (address.charAt(0) == 'D' || address.substring(0, 2) == "DB")
+ {
+ value.type = -124;
+ String[] adds = address.split("\\.");
+ if (address.charAt(1) == 'B')
+ {
+ value.dbAddress = Short.parseShort(adds[0].substring(2));
+ }
+ else
+ {
+ value.dbAddress = Short.parseShort(adds[0].substring(1));
+ }
+
+ value.startAddress = CalculateAddressStarted(address.substring(address.indexOf('.') + 1));
+ }
+ else
+ {
+ result.Message = "不支持的数据类型";
+ value.type = 0;
+ value.startAddress = 0;
+ value.dbAddress = 0;
+ return value;
+ }
+ }
+ catch (Exception ex)
+ {
+ result.Message = ex.getMessage();
+ return value;
+ }
+
+ value.Result=true;
+ return value;
+ }
+
+ private boolean InitilizationConnect(Socket socket,OperateResult result)
+ {
+ // 发送初始化信息
+ if(!SendBytesToSocket(socket,plcHead1))
+ {
+ result.Message = "初始化信息发送失败";
+ return false;
+ }
+
+ if(!ReceiveBytesFromSocket(socket).Result)
+ {
+ result.Message = "初始化信息接收失败";
+ return false;
+ }
+
+ if(!SendBytesToSocket(socket,plcHead2))
+ {
+ result.Message = "初始化信息发送失败";
+ return false;
+ }
+
+ if(!ReceiveBytesFromSocket(socket).Result)
+ {
+ result.Message = "初始化信息接收失败";
+ return false;
+ }
+
+ return true;
+ }
+
+
+ ///
+ /// 从PLC读取数据,地址格式为I100,Q100,DB20.100,M100,以字节为单位
+ ///
+ /// 起始地址,格式为I100,M100,Q100,DB20.100
+ /// 读取的数量,以字节为单位
+ ///
+ public OperateResultBytes ReadFromPLC(String address, short count)
+ {
+ return ReadFromPLC(new String[] { address }, new short[] { count });
+ }
+
+
+ ///
+ /// 一次性从PLC获取所有的数据,按照先后顺序返回一个统一的Buffer,需要按照顺序处理,两个数组长度必须一致
+ ///
+ /// 起始地址数组
+ /// 数据长度数组
+ ///
+ public OperateResultBytes ReadFromPLC(String[] address, short[] count)
+ {
+ OperateResultBytes result = new OperateResultBytes();
+
+ if (address == null)
+ {
+ result.Message = "地址不能为空";
+ return result;
+ }
+
+
+ if (count == null)
+ {
+ result.Message = "数量不能为空";
+ return result;
+ }
+ if (address.length != count.length) {
+ result.Message = "两个参数的个数不统一";
+ return result;
+ }
+
+ Socket socket;
+ boolWithSocket value = CreateSocketAndConnect(ipAddress,getPortRead(), result);
+ if (!value.Result)
+ {
+ ChangePort();
+ return result;
+ }
+
+ socket = value.Socket;
+ if (!InitilizationConnect(socket, result))
+ {
+ return result;
+ }
+
+
+ // 分批次进行读取,计算总批次
+ int times = address.length / 255;
+ if (address.length % 255 > 0)
+ {
+ times++;
+ }
+
+ // 缓存所有批次的结果
+ ArrayList arrays_bytes = new ArrayList();
+
+ for (int jj = 0; jj < times; jj++)
+ {
+ // 计算本批次需要读取的数据
+ int startIndex = jj * 255;
+ int readCount = address.length - startIndex;
+ if (readCount > 255)
+ {
+ readCount = 255;
+ }
+
+ byte[] _PLCCommand = new byte[19 + readCount * 12];
+ // 报文头
+ _PLCCommand[0] = 0x03;
+ _PLCCommand[1] = 0x00;
+ // 长度
+ _PLCCommand[2] = (byte)(_PLCCommand.length / 256);
+ _PLCCommand[3] = (byte)(_PLCCommand.length % 256);
+ // 固定
+ _PLCCommand[4] = 0x02;
+ _PLCCommand[5] = -16;
+ _PLCCommand[6] = -128;
+ _PLCCommand[7] = 0x32;
+ // 命令:发
+ _PLCCommand[8] = 0x01;
+ // 标识序列号
+ _PLCCommand[9] = 0x00;
+ _PLCCommand[10] = 0x00;
+ _PLCCommand[11] = 0x00;
+ _PLCCommand[12] = 0x01;
+ // 命令数据总长度
+ _PLCCommand[13] = (byte)((_PLCCommand.length - 17) / 256);
+ _PLCCommand[14] = (byte)((_PLCCommand.length - 17) % 256);
+
+ _PLCCommand[15] = 0x00;
+ _PLCCommand[16] = 0x00;
+
+ // 命令起始符
+ _PLCCommand[17] = 0x04;
+ // 读取数据块个数
+ _PLCCommand[18] = (byte)readCount;
+
+ int receiveCount = 0;
+ for (int ii = 0; ii < readCount; ii++)
+ {
+ receiveCount += count[ii + 255 * jj];
+
+ boolWithSiemens siemens = AnalysisAddress(address[ii + 255 * jj], result);
+ // 填充数据
+ if (!siemens.Result)
+ {
+ CloseSocket(socket);
+ return result;
+ }
+
+ // 读取地址的前缀
+ _PLCCommand[19 + ii * 12] = 0x12;
+ _PLCCommand[20 + ii * 12] = 0x0A;
+ _PLCCommand[21 + ii * 12] = 0x10;
+ _PLCCommand[22 + ii * 12] = 0x02;
+ // 访问数据的个数
+ _PLCCommand[23 + ii * 12] = (byte)(count[ii + 255 * jj] / 256);
+ _PLCCommand[24 + ii * 12] = (byte)(count[ii + 255 * jj] % 256);
+ // DB块编号,如果访问的是DB块的话
+ _PLCCommand[25 + ii * 12] = (byte)(siemens.dbAddress / 256);
+ _PLCCommand[26 + ii * 12] = (byte)(siemens.dbAddress % 256);
+ // 访问数据类型
+ _PLCCommand[27 + ii * 12] = siemens.type;
+ // 偏移位置
+ _PLCCommand[28 + ii * 12] = (byte)(siemens.startAddress / 256 / 256);
+ _PLCCommand[29 + ii * 12] = (byte)(siemens.startAddress / 256);
+ _PLCCommand[30 + ii * 12] = (byte)(siemens.startAddress % 256);
+ }
+
+
+ if (!SendBytesToSocket(socket, _PLCCommand))
+ {
+ result.Message = "发送读取信息失败";
+ return result;
+ }
+
+ boolWithBytes content=ReceiveBytesFromSocket(socket);
+ if (!content.Result)
+ {
+ result.Message = "接收信息失败";
+ return result;
+ }
+
+ if (content.Content.length != receiveCount + readCount * 4 + 21)
+ {
+ CloseSocket(socket);
+ result.Message = "数据长度校验失败";
+ result.Content = content.Content;
+ return result;
+ }
+
+ // 分次读取成功
+ byte[] buffer = new byte[receiveCount];
+ int kk = 21;
+ int ll = 0;
+ for (int ii = 0; ii < readCount; ii++)
+ {
+ // 将数据挪回正确的地方
+ System.arraycopy(content, kk + 4, buffer, ll, count[ii + 255 * jj]);
+ kk += count[ii + 255 * jj] + 4;
+ ll += count[ii + 255 * jj];
+ }
+ arrays_bytes.add(buffer);
+ }
+
+
+ if (arrays_bytes.size() == 1)
+ {
+ result.Content = arrays_bytes.get(0);
+ }
+ else
+ {
+ int length = 0;
+ int offset = 0;
+
+ // 获取长度并生成缓冲数据
+
+ for(int ii=0;ii
+ /// 将数据写入到PLC数据,地址格式为I100,Q100,DB20.100,M100,以字节为单位
+ ///
+ /// 起始地址,格式为I100,M100,Q100,DB20.100
+ /// 写入的数据,长度根据data的长度来指示
+ ///
+ public OperateResult WriteIntoPLC(String address, byte[] data)
+ {
+ OperateResult result = new OperateResult();
+
+
+ Socket socket;
+ boolWithSocket value = CreateSocketAndConnect(ipAddress,getPortRead(), result);
+ if (!value.Result)
+ {
+ ChangePort();
+ return result;
+ }
+
+ socket = value.Socket;
+ if (!InitilizationConnect(socket, result))
+ {
+ return result;
+ }
+
+
+ if (data == null) data = new byte[0];
+
+ boolWithSiemens siemens = AnalysisAddress(address, result);
+ // 填充数据
+ if (!siemens.Result)
+ {
+ CloseSocket(socket);
+ return result;
+ }
+
+
+ byte[] _PLCCommand = new byte[35 + data.length];
+ _PLCCommand[0] = 0x03;
+ _PLCCommand[1] = 0x00;
+ // 长度
+ _PLCCommand[2] = (byte)((35 + data.length) / 256);
+ _PLCCommand[3] = (byte)((35 + data.length) % 256);
+ // 固定
+ _PLCCommand[4] = 0x02;
+ _PLCCommand[5] = -16;
+ _PLCCommand[6] = -128;
+ _PLCCommand[7] = 0x32;
+ // 命令 发
+ _PLCCommand[8] = 0x01;
+ // 标识序列号
+ _PLCCommand[9] = 0x00;
+ _PLCCommand[10] = 0x00;
+ _PLCCommand[11] = 0x00;
+ _PLCCommand[12] = 0x01;
+ // 固定
+ _PLCCommand[13] = 0x00;
+ _PLCCommand[14] = 0x0E;
+ // 写入长度+4
+ _PLCCommand[15] = (byte)((4 + data.length) / 256);
+ _PLCCommand[16] = (byte)((4 + data.length) % 256);
+ // 命令起始符
+ _PLCCommand[17] = 0x05;
+ // 写入数据块个数
+ _PLCCommand[18] = 0x01;
+ // 固定,返回数据长度
+ _PLCCommand[19] = 0x12;
+ _PLCCommand[20] = 0x0A;
+ _PLCCommand[21] = 0x10;
+ // 写入方式,1是按位,2是按字
+ _PLCCommand[22] = 0x02;
+ // 写入数据的个数
+ _PLCCommand[23] = (byte)(data.length / 256);
+ _PLCCommand[24] = (byte)(data.length % 256);
+ // DB块编号,如果访问的是DB块的话
+ _PLCCommand[25] = (byte)(siemens.dbAddress / 256);
+ _PLCCommand[26] = (byte)(siemens.dbAddress % 256);
+ // 写入数据的类型
+ _PLCCommand[27] = siemens.type;
+ // 偏移位置
+ _PLCCommand[28] = (byte)(siemens.startAddress / 256 / 256);;
+ _PLCCommand[29] = (byte)(siemens.startAddress / 256);
+ _PLCCommand[30] = (byte)(siemens.startAddress % 256);
+ // 按字写入
+ _PLCCommand[31] = 0x00;
+ _PLCCommand[32] = 0x04;
+ // 按位计算的长度
+ _PLCCommand[33] = (byte)(data.length * 8 / 256);
+ _PLCCommand[34] = (byte)(data.length * 8 % 256);
+
+ System.arraycopy(data,0,_PLCCommand,35,data.length);
+
+ if(!SendBytesToSocket(socket,_PLCCommand))
+ {
+ result.Message = "发送写入信息失败";
+ return result;
+ }
+
+ boolWithBytes value2=ReceiveBytesFromSocket(socket);
+ if (!value2.Result)
+ {
+ result.Message = "接收信息失败";
+ return result;
+ }
+
+ if (value2.Content[value2.Content.length - 1] != 0xFF)
+ {
+ // 写入异常
+ CloseSocket(socket);
+ result.Message = "写入数据异常";
+ return result;
+ }
+
+ CloseSocket(socket);
+ result.IsSuccess = true;
+ return result;
+ }
+
+
+ ///
+ /// 写入PLC的一个位,例如"M100.6","I100.7","Q100.0","DB20.100.0",如果只写了"M100"默认为"M100.0
+ ///
+ ///
+ ///
+ ///
+ public OperateResult WriteIntoPLC(String address, boolean data)
+ {
+ OperateResult result = new OperateResult();
+
+ Socket socket;
+ boolWithSocket value = CreateSocketAndConnect(getIpAddress(),m_PortWrite, result);
+ if (!value.Result)
+ {
+ ChangePort();
+ return result;
+ }
+
+ socket = value.Socket;
+ if (!InitilizationConnect(socket, result))
+ {
+ return result;
+ }
+
+
+
+ byte[] buffer = new byte[1];
+ buffer[0] = data ? (byte)0x01 : (byte)0x00;
+
+ boolWithSiemens siemens = AnalysisAddress(address, result);
+ // 填充数据
+ if (!siemens.Result)
+ {
+ CloseSocket(socket);
+ return result;
+ }
+
+
+
+ byte[] _PLCCommand = new byte[35 + buffer.length];
+ _PLCCommand[0] = 0x03;
+ _PLCCommand[1] = 0x00;
+ // 长度
+ _PLCCommand[2] = (byte)((35 + buffer.length) / 256);
+ _PLCCommand[3] = (byte)((35 + buffer.length) % 256);
+ // 固定
+ _PLCCommand[4] = 0x02;
+ _PLCCommand[5] = -16;
+ _PLCCommand[6] = -128;
+ _PLCCommand[7] = 0x32;
+ // 命令 发
+ _PLCCommand[8] = 0x01;
+ // 标识序列号
+ _PLCCommand[9] = 0x00;
+ _PLCCommand[10] = 0x00;
+ _PLCCommand[11] = 0x00;
+ _PLCCommand[12] = 0x01;
+ // 固定
+ _PLCCommand[13] = 0x00;
+ _PLCCommand[14] = 0x0E;
+ // 写入长度+4
+ _PLCCommand[15] = (byte)((4 + buffer.length) / 256);
+ _PLCCommand[16] = (byte)((4 + buffer.length) % 256);
+ // 命令起始符
+ _PLCCommand[17] = 0x05;
+ // 写入数据块个数
+ _PLCCommand[18] = 0x01;
+ _PLCCommand[19] = 0x12;
+ _PLCCommand[20] = 0x0A;
+ _PLCCommand[21] = 0x10;
+ // 写入方式,1是按位,2是按字
+ _PLCCommand[22] = 0x01;
+ // 写入数据的个数
+ _PLCCommand[23] = (byte)(buffer.length / 256);
+ _PLCCommand[24] = (byte)(buffer.length % 256);
+ // DB块编号,如果访问的是DB块的话
+ _PLCCommand[25] = (byte)(siemens.dbAddress / 256);
+ _PLCCommand[26] = (byte)(siemens.dbAddress % 256);
+ // 写入数据的类型
+ _PLCCommand[27] = siemens.type;
+ // 偏移位置
+ _PLCCommand[28] = (byte)(siemens.startAddress / 256 / 256);
+ _PLCCommand[29] = (byte)(siemens.startAddress / 256);
+ _PLCCommand[30] = (byte)(siemens.startAddress % 256);
+ // 按位写入
+ _PLCCommand[31] = 0x00;
+ _PLCCommand[32] = 0x03;
+ // 按位计算的长度
+ _PLCCommand[33] = (byte)(buffer.length / 256);
+ _PLCCommand[34] = (byte)(buffer.length % 256);
+
+ System.arraycopy(buffer,0,_PLCCommand,35,buffer.length);
+
+ if(!SendBytesToSocket(socket,_PLCCommand))
+ {
+ result.Message = "发送写入信息失败";
+ return result;
+ }
+
+ boolWithBytes value2=ReceiveBytesFromSocket(socket);
+ if (!value2.Result)
+ {
+ result.Message = "接收信息失败";
+ return result;
+ }
+
+ if (value2.Content[value2.Content.length - 1] != 0xFF)
+ {
+ // 写入异常
+ CloseSocket(socket);
+ result.Message = "写入数据异常";
+ return result;
+ }
+
+ CloseSocket(socket);
+ result.IsSuccess = true;
+ return result;
+ }
+
+ ///
+ /// 从返回的西门子数组中获取short数组数据,已经内置高地位转换
+ ///
+ ///
+ ///
+ public short[] GetArrayFromBytes(byte[] bytes)
+ {
+ short[] temp = new short[bytes.length / 2];
+ for (int i = 0; i < temp.length; i++)
+ {
+ byte[] buffer = new byte[2];
+ buffer[0] = bytes[i * 2 + 1];
+ buffer[1] = bytes[i * 2];
+ temp[i] = Utilities.byte2Short(buffer, 0);
+ }
+ return temp;
+ }
+
+ ///
+ /// 从返回的西门子数组中获取int数组数据,已经内置高地位转换
+ ///
+ ///
+ ///
+ public int[] GetIntArrayFromBytes(byte[] bytes)
+ {
+ int[] temp = new int[bytes.length / 4];
+ for (int i = 0; i < temp.length; i++)
+ {
+ byte[] buffer = new byte[4];
+ buffer[0] = bytes[i * 4 + 0];
+ buffer[1] = bytes[i * 4 + 1];
+ buffer[2] = bytes[i * 4 + 2];
+ buffer[3] = bytes[i * 4 + 3];
+ temp[i] = Utilities.bytes2Int(buffer);
+ }
+ return temp;
+ }
+
+ ///
+ /// 根据索引位转换获取short数据
+ ///
+ ///
+ ///
+ ///
+ public short GetShortFromBytes(byte[] content, int index)
+ {
+ byte[] buffer = new byte[2];
+ buffer[0] = content[index + 0];
+ buffer[1] = content[index + 1];
+ return Utilities.byte2Short(buffer,0);
+ }
+
+
+ ///
+ /// 根据索引位转换获取int数据
+ ///
+ ///
+ ///
+ ///
+ public int GetIntFromBytes(byte[] content, int index)
+ {
+ byte[] buffer = new byte[4];
+ buffer[0] = content[index + 0];
+ buffer[1] = content[index + 1];
+ buffer[2] = content[index + 2];
+ buffer[3] = content[index + 3];
+ return Utilities.bytes2Int(buffer);
+ }
+
+ private byte[] plcHead1 =
+ {
+ 0x03, // 报文头
+ 0x00,
+ 0x00, // 数据长度
+ 0x16,
+ 0x11,
+ -32,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x00,
+ -63,
+ 0x02,
+ 0x10,
+ 0x00,
+ -62,
+ 0x02,
+ 0x03,
+ 0x01, // 指示cpu
+ -64,
+ 0x01,
+ 0x0A
+ };
+ private byte[] plcHead2 =
+ {
+ 0x03,
+ 0x00,
+ 0x00,
+ 0x19,
+ 0x02,
+ -16,
+ -128,
+ 0x32,
+ 0x01,
+ 0x00,
+ 0x00,
+ -52,
+ -63,
+ 0x00,
+ 0x08,
+ 0x00,
+ 0x00,
+ -16,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x00,
+ 0x01,
+ 0x03,
+ -64
+ };
+
+ private SiemensPLCS CurrentPlc = SiemensPLCS.S1200;
+
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Resources/StringResources.java b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Resources/StringResources.java
new file mode 100644
index 0000000..f005a31
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/HslCommunication/Resources/StringResources.java
@@ -0,0 +1,95 @@
+package com.example.HslCommunication.Resources;
+
+/**
+ * Created by DATHLIN on 2017/11/2.
+ */
+
+public class StringResources {
+
+
+ /***********************************************************************************
+ *
+ * 一般的错误信息
+ *
+ ************************************************************************************/
+
+
+ public static final String ConnectedFailed = "连接失败";
+ public static final String UnknownError = "未知错误";
+ public static final String ErrorCode = "错误代号";
+ public static final String TextDescription = "文本描述";
+ public static final String ExceptionMessage = "错误信息:";
+ public static final String ExceptionStackTrace = "错误堆栈:";
+ public static final String ExceptopnTargetSite = "错误方法:";
+ public static final String ExceprionCustomer = "用户自定义方法出错:";
+
+
+
+ /***********************************************************************************
+ *
+ * 系统相关的错误信息
+ *
+ ************************************************************************************/
+
+ public static final String SystemInstallOperater = "安装新系统:IP为";
+ public static final String SystemUpdateOperater = "更新新系统:IP为";
+
+
+ /***********************************************************************************
+ *
+ * 套接字相关的信息描述
+ *
+ ************************************************************************************/
+
+ public static final String SocketIOException = "套接字传送数据异常:";
+ public static final String SocketSendException = "同步数据发送异常:";
+ public static final String SocketHeadReceiveException = "指令头接收异常:";
+ public static final String SocketContentReceiveException = "内容数据接收异常:";
+ public static final String SocketContentRemoteReceiveException = "对方内容数据接收异常:";
+ public static final String SocketAcceptCallbackException = "异步接受传入的连接尝试";
+ public static final String SocketReAcceptCallbackException = "重新异步接受传入的连接尝试";
+ public static final String SocketSendAsyncException = "异步数据发送出错:";
+ public static final String SocketEndSendException = "异步数据结束挂起发送出错";
+ public static final String SocketReceiveException = "异步数据发送出错:";
+ public static final String SocketEndReceiveException = "异步数据结束接收指令头出错";
+ public static final String SocketRemoteCloseException = "远程主机强迫关闭了一个现有的连接";
+
+
+ /***********************************************************************************
+ *
+ * 文件相关的信息
+ *
+ ************************************************************************************/
+
+
+ public static final String FileDownloadSuccess = "文件下载成功";
+ public static final String FileDownloadFailed = "文件下载异常";
+ public static final String FileUploadFailed = "文件上传异常";
+ public static final String FileUploadSuccess = "文件上传成功";
+ public static final String FileDeleteFailed = "文件删除异常";
+ public static final String FileDeleteSuccess = "文件删除成功";
+ public static final String FileReceiveFailed = "确认文件接收异常";
+ public static final String FileNotExist = "文件不存在";
+ public static final String FileSaveFailed = "文件存储失败";
+ public static final String FileLoadFailed = "文件加载失败";
+ public static final String FileSendClientFailed = "文件发送的时候发生了异常";
+ public static final String FileWriteToNetFailed = "文件写入网络异常";
+ public static final String FileReadFromNetFailed = "从网络读取文件异常";
+
+ /***********************************************************************************
+ *
+ * 服务器的引擎相关数据
+ *
+ ************************************************************************************/
+
+ public static final String TokenCheckFailed = "接收验证令牌不一致";
+ public static final String TokenCheckTimeout = "接收验证超时:";
+ public static final String NetClientAliasFailed = "客户端的别名接收失败:";
+ public static final String NetEngineStart = "启动引擎";
+ public static final String NetEngineClose = "关闭引擎";
+ public static final String NetClientOnline = "上线";
+ public static final String NetClientOffline = "下线";
+ public static final String NetClientBreak = "异常掉线";
+ public static final String NetClientFull = "服务器承载上限,收到超出的请求连接。";
+ public static final String NetClientLoginFailed = "客户端登录中错误:";
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/CommonHeadCode/SimplifyHeadCode.java b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/CommonHeadCode/SimplifyHeadCode.java
new file mode 100644
index 0000000..d348e3a
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/CommonHeadCode/SimplifyHeadCode.java
@@ -0,0 +1,60 @@
+package com.example.UserSoftwareAndroidTemplate.CommonHeadCode;
+
+import com.example.HslCommunication.Core.Types.NetHandle;
+
+/**
+ * Created by hsl20 on 2017/11/5.
+ */
+
+public class SimplifyHeadCode {
+
+
+ public static NetHandle 维护检查 = new NetHandle(1, 1, 1);
+ public static NetHandle 更新检查 = new NetHandle(1, 1, 2);
+ public static NetHandle 参数下载 = new NetHandle(1, 1, 3);
+ public static NetHandle 账户检查 = new NetHandle(1, 1, 4);
+ public static NetHandle 密码修改 = new NetHandle(1, 1, 5);
+ public static NetHandle 更细账户 = new NetHandle(1, 1, 6);
+ public static NetHandle 获取账户 = new NetHandle(1, 1, 7);
+ public static NetHandle 更新公告 = new NetHandle(1, 1, 8);
+ public static NetHandle 注册账号 = new NetHandle(1, 1, 9);
+ public static NetHandle 更新版本 = new NetHandle(1, 1, 10);
+ public static NetHandle 请求文件 = new NetHandle(1, 1, 11);
+ public static NetHandle 意见反馈 = new NetHandle(1, 1, 12);
+ public static NetHandle 群发消息 = new NetHandle(1, 1, 13);
+ public static NetHandle 异常消息 = new NetHandle(1, 1, 14);
+ public static NetHandle 性能计数 = new NetHandle(1, 1, 15);
+ public static NetHandle 上传头像MD5 = new NetHandle(1, 1, 16);
+ public static NetHandle 请求分厂 = new NetHandle(1, 1, 17);
+ public static NetHandle 上传分厂 = new NetHandle(1, 1, 18);
+ public static NetHandle 请求信任客户端 = new NetHandle(1, 1, 19);
+ public static NetHandle 上传信任客户端 = new NetHandle(1, 1, 20);
+ public static NetHandle 请求一般配置 = new NetHandle(1, 1, 21);
+ public static NetHandle 上传一般配置 = new NetHandle(1, 1, 22);
+ public static NetHandle 请求角色配置 = new NetHandle(1, 1, 23);
+ public static NetHandle 上传角色配置 = new NetHandle(1, 1, 24);
+ public static NetHandle 检查角色权限 = new NetHandle(1, 1, 25);
+
+
+
+
+
+ public static NetHandle 网络日志查看 = new NetHandle(1, 2, 1);//1.2.开头的是日志请求和清空
+ public static NetHandle 网络日志清空 = new NetHandle(1, 2, 2);
+ public static NetHandle 同步日志查看 = new NetHandle(1, 2, 3);
+ public static NetHandle 同步日志清空 = new NetHandle(1, 2, 4);
+ public static NetHandle 更新日志查看 = new NetHandle(1, 2, 5);
+ public static NetHandle 更新日志清空 = new NetHandle(1, 2, 6);
+ public static NetHandle 运行日志查看 = new NetHandle(1, 2, 7);
+ public static NetHandle 运行日志清空 = new NetHandle(1, 2, 8);
+ public static NetHandle 文件日志查看 = new NetHandle(1, 2, 9);
+ public static NetHandle 文件日志清空 = new NetHandle(1, 2, 10);
+ public static NetHandle 反馈日志查看 = new NetHandle(1, 2, 11);
+ public static NetHandle 反馈日志清空 = new NetHandle(1, 2, 12);
+ public static NetHandle UDP日志查看 = new NetHandle(1, 2, 13);
+ public static NetHandle UDP日志清空 = new NetHandle(1, 2, 14);
+ public static NetHandle 客户端日志查看 = new NetHandle(1, 2, 15);
+ public static NetHandle 客户端日志清空 = new NetHandle(1, 2, 16);
+ public static NetHandle 头像日志查看 = new NetHandle(1, 2, 17);
+ public static NetHandle 头像日志清空 = new NetHandle(1, 2, 18);
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/LoginSupport/SplashActivity.java b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/LoginSupport/SplashActivity.java
new file mode 100644
index 0000000..db4f8d1
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/LoginSupport/SplashActivity.java
@@ -0,0 +1,136 @@
+package com.example.UserSoftwareAndroidTemplate.LoginSupport;
+
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.HslCommunication.BasicFramework.SystemVersion;
+import com.example.HslCommunication.Core.Types.NetHandle;
+import com.example.HslCommunication.Core.Types.OperateResultString;
+import com.example.UserSoftwareAndroidTemplate.CommonHeadCode.SimplifyHeadCode;
+import com.example.UserSoftwareAndroidTemplate.MainActivity;
+import com.example.UserSoftwareAndroidTemplate.R;
+import com.example.UserSoftwareAndroidTemplate.UserClient;
+
+
+public class SplashActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_splash);
+
+ TextView mVersionNameText = (TextView) findViewById(R.id.TextVersionInfo);
+ mVersionNameText.setText("Version: " + UserClient.CurrentVersion.toString());
+
+ new AsyncTask() {
+
+
+ @Override
+ protected Integer doInBackground(Void... voids) {
+ int result;
+ long startTime = System.currentTimeMillis();
+ result = loadingCache();
+ long loadingTime = System.currentTimeMillis() - startTime;
+ if (loadingTime < SHOW_TIME_MIN) {
+ try {
+ Thread.sleep(SHOW_TIME_MIN - loadingTime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(Integer result) {
+ if (result > 0) {
+ Intent intent = new Intent(SplashActivity.this, MainActivity.class);
+ //intent.setClassName(SplashActivity.this, getString(R.string.));
+ startActivity(intent);
+ finish();
+ //两个参数分别表示进入的动画,退出的动画
+ overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
+ }
+ }
+
+ ;
+ }.execute(new Void[]{});
+
+ }
+
+ private static final int SHOW_TIME_MIN = 3000;
+ private static final int FAILURE = 0; // 失败
+ private static final int SUCCESS = 1; // 成功
+ private static final int OFFLINE = 2; // 如果支持离线阅读,进入离线模式
+
+
+ private Handler handler=new Handler(){
+ /**重写handleMessage方法*/
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.arg1 == 1) {
+ Toast.makeText(SplashActivity.this, msg.obj.toString(), Toast.LENGTH_SHORT).show();
+ }
+ }
+ };
+
+
+ private void MessageShow(String message)
+ {
+ Message msg = new Message();
+ msg.arg1=1;
+ msg.obj = message;
+ handler.sendMessage(msg);
+ }
+
+
+ private int loadingCache() {
+
+ // 第一步请求维护状态
+ OperateResultString result=UserClient.Client.ReadFromServer(SimplifyHeadCode.维护检查,"",null,null);
+ if(!result.IsSuccess){
+ MessageShow(result.ToMessageShowString());
+ return FAILURE;
+ }
+
+ if(!result.Content.equals("1")) {
+ MessageShow(result.Content.substring(1));
+ return FAILURE;
+ }
+
+
+ // 第二步检查账户
+
+
+
+
+
+
+ // 第三步检查版本
+ result=UserClient.Client.ReadFromServer(SimplifyHeadCode.维护检查,"",null,null);
+ if(!result.IsSuccess){
+ MessageShow(result.ToMessageShowString());
+ return FAILURE;
+ }
+
+ SystemVersion sv=new SystemVersion(result.Content);
+ if(!UserClient.CurrentVersion.IsSameVersion(sv)) return FAILURE;
+
+
+ // 下载服务器数据
+
+
+ return SUCCESS;
+ }
+
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/MainActivity.java b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/MainActivity.java
new file mode 100644
index 0000000..afd1b10
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/MainActivity.java
@@ -0,0 +1,83 @@
+package com.example.UserSoftwareAndroidTemplate;
+
+import android.os.Handler;
+import android.os.Message;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.text.method.ScrollingMovementMethod;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.HslCommunication.Core.Types.NetHandle;
+import com.example.HslCommunication.Core.Types.OperateResultString;
+import com.example.HslCommunication.Enthernet.NetSimplifyClient;
+
+import java.util.UUID;
+
+public class MainActivity extends AppCompatActivity {
+
+ public MainActivity()
+ {
+
+ }
+
+
+
+
+
+ private Handler handler=new Handler(){
+ /**重写handleMessage方法*/
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.arg1 == 1) {
+
+ // 说明是一个网络的请求访问
+ OperateResultString result = (OperateResultString) msg.obj;
+ if (result.IsSuccess) {
+ TextView textView = (TextView) findViewById(R.id.textViewMain);
+ textView.setText(result.Content);
+ } else {
+ Toast.makeText(MainActivity.this, result.ToMessageShowString(), Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+ };
+
+
+ /**
+ * 网络操作相关的子线程
+ */
+ Runnable networkTask = new Runnable() {
+
+ @Override
+ public void run() {
+ // 在这里进行网络请求相关操作
+ Message msg = new Message();
+ OperateResultString result = UserClient.Client.ReadFromServer(new NetHandle(1,2, 15),"",null,null);
+ msg.arg1=1;
+ msg.obj = result;
+ handler.sendMessage(msg);
+ }
+ };
+
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ Button button1 = (Button) findViewById(R.id.button);
+ button1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ new Thread(networkTask).start();
+ }});
+
+ TextView textView = (TextView) findViewById(R.id.textViewMain);
+ textView.setMovementMethod(new ScrollingMovementMethod());
+ }
+}
diff --git a/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/UserClient.java b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/UserClient.java
new file mode 100644
index 0000000..fc6cf84
--- /dev/null
+++ b/AndroidTemplate/app/src/main/java/com/example/UserSoftwareAndroidTemplate/UserClient.java
@@ -0,0 +1,33 @@
+package com.example.UserSoftwareAndroidTemplate;
+
+import com.example.HslCommunication.BasicFramework.SystemVersion;
+import com.example.HslCommunication.Enthernet.NetSimplifyClient;
+
+import java.util.UUID;
+
+/**
+ * Created by hsl20 on 2017/11/4.
+ */
+
+public class UserClient {
+
+
+ public static SystemVersion CurrentVersion= new SystemVersion("1.0.0.171026");
+
+
+
+ public static String ServerIp="117.48.203.204";
+ public static int PortSecondary=14568;
+ public static UUID Token=UUID.fromString("1275BB9A-14B2-4A96-9673-B0AF0463D474");
+
+
+
+
+
+
+
+
+
+ public static NetSimplifyClient Client=new NetSimplifyClient(ServerIp,PortSecondary,Token);
+
+}
diff --git a/AndroidTemplate/app/src/main/res/anim/fade_in.xml b/AndroidTemplate/app/src/main/res/anim/fade_in.xml
new file mode 100644
index 0000000..3a7854d
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/anim/fade_in.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/res/anim/fade_out.xml b/AndroidTemplate/app/src/main/res/anim/fade_out.xml
new file mode 100644
index 0000000..55885fa
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/anim/fade_out.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/AndroidTemplate/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AndroidTemplate/app/src/main/res/drawable/ic_launcher_background.xml b/AndroidTemplate/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AndroidTemplate/app/src/main/res/layout/activity_main.xml b/AndroidTemplate/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..1d5560c
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/AndroidTemplate/app/src/main/res/layout/activity_splash.xml b/AndroidTemplate/app/src/main/res/layout/activity_splash.xml
new file mode 100644
index 0000000..2e5d9c7
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/layout/activity_splash.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AndroidTemplate/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/AndroidTemplate/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/AndroidTemplate/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher.png b/AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a2f5908
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1b52399
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher.png b/AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ff10afd
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..115a4c7
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dcd3cd8
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..459ca60
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8ca12fe
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e19b41
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b824ebd
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..4c19a13
Binary files /dev/null and b/AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/AndroidTemplate/app/src/main/res/values/attrs.xml b/AndroidTemplate/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..7ce840e
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/values/attrs.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
diff --git a/AndroidTemplate/app/src/main/res/values/colors.xml b/AndroidTemplate/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..227fd33
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/values/colors.xml
@@ -0,0 +1,8 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
+ #66000000
+
diff --git a/AndroidTemplate/app/src/main/res/values/dimens.xml b/AndroidTemplate/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..59a0b0c
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+
+ 16dp
+
diff --git a/AndroidTemplate/app/src/main/res/values/strings.xml b/AndroidTemplate/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3d1c279
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+ 软件系统安卓端模版
+ SplashActivity
+
+ LoadingActivity
+ Dummy Button
+ DUMMY\nCONTENT
+
diff --git a/AndroidTemplate/app/src/main/res/values/styles.xml b/AndroidTemplate/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..21184e4
--- /dev/null
+++ b/AndroidTemplate/app/src/main/res/values/styles.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AndroidTemplate/app/src/test/java/com/example/UserSoftwareAndroidTemplate/ExampleUnitTest.java b/AndroidTemplate/app/src/test/java/com/example/UserSoftwareAndroidTemplate/ExampleUnitTest.java
new file mode 100644
index 0000000..ce511d3
--- /dev/null
+++ b/AndroidTemplate/app/src/test/java/com/example/UserSoftwareAndroidTemplate/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.example.UserSoftwareAndroidTemplate;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/AndroidTemplate/build.gradle b/AndroidTemplate/build.gradle
new file mode 100644
index 0000000..020eae2
--- /dev/null
+++ b/AndroidTemplate/build.gradle
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.0.0'
+
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/AndroidTemplate/gradle.properties b/AndroidTemplate/gradle.properties
new file mode 100644
index 0000000..766b2f9
--- /dev/null
+++ b/AndroidTemplate/gradle.properties
@@ -0,0 +1,17 @@
+# 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=-Xmx512m
+
+# 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
diff --git a/AndroidTemplate/gradle/wrapper/gradle-wrapper.jar b/AndroidTemplate/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/AndroidTemplate/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/AndroidTemplate/gradle/wrapper/gradle-wrapper.properties b/AndroidTemplate/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3a32211
--- /dev/null
+++ b/AndroidTemplate/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sun Oct 29 15:00:29 CST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https://services.gradle.org/distributions/gradle-4.3-rc-4-all.zip
\ No newline at end of file
diff --git a/AndroidTemplate/gradlew b/AndroidTemplate/gradlew
new file mode 100644
index 0000000..9d82f78
--- /dev/null
+++ b/AndroidTemplate/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# 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
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# 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
+
+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" ] ; 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, switch paths to Windows format before running java
+if $cygwin ; 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=$((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
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/AndroidTemplate/gradlew.bat b/AndroidTemplate/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/AndroidTemplate/gradlew.bat
@@ -0,0 +1,90 @@
+@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
+
+@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=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@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 init
+
+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 init
+
+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
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+: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 %CMD_LINE_ARGS%
+
+: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/AndroidTemplate/settings.gradle b/AndroidTemplate/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/AndroidTemplate/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/HslCommunicationNetTestTool/Form1.Designer.cs b/HslCommunicationNetTestTool/Form1.Designer.cs
index e4a4816..5af443d 100644
--- a/HslCommunicationNetTestTool/Form1.Designer.cs
+++ b/HslCommunicationNetTestTool/Form1.Designer.cs
@@ -47,7 +47,11 @@
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+ this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
+ this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();
this.panel1.SuspendLayout();
+ this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// userButton1
@@ -88,7 +92,7 @@
treeNode1.Text = "NetSimplifyClient";
this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
treeNode1});
- this.treeView1.Size = new System.Drawing.Size(254, 614);
+ this.treeView1.Size = new System.Drawing.Size(254, 601);
this.treeView1.TabIndex = 2;
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
//
@@ -113,7 +117,7 @@
this.panel1.Controls.Add(this.label1);
this.panel1.Location = new System.Drawing.Point(280, 56);
this.panel1.Name = "panel1";
- this.panel1.Size = new System.Drawing.Size(779, 613);
+ this.panel1.Size = new System.Drawing.Size(779, 601);
this.panel1.TabIndex = 3;
//
// userButton4
@@ -175,7 +179,7 @@
this.textBox3.Multiline = true;
this.textBox3.Name = "textBox3";
this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
- this.textBox3.Size = new System.Drawing.Size(702, 327);
+ this.textBox3.Size = new System.Drawing.Size(702, 315);
this.textBox3.TabIndex = 7;
//
// label4
@@ -254,11 +258,34 @@
this.label7.TabIndex = 4;
this.label7.Text = "选中连接:";
//
+ // statusStrip1
+ //
+ this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.toolStripStatusLabel1,
+ this.toolStripStatusLabel2});
+ this.statusStrip1.Location = new System.Drawing.Point(0, 661);
+ this.statusStrip1.Name = "statusStrip1";
+ this.statusStrip1.Size = new System.Drawing.Size(1072, 22);
+ this.statusStrip1.TabIndex = 5;
+ this.statusStrip1.Text = "statusStrip1";
+ //
+ // toolStripStatusLabel1
+ //
+ this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
+ this.toolStripStatusLabel1.Size = new System.Drawing.Size(92, 17);
+ this.toolStripStatusLabel1.Text = "十六进制命令:";
+ //
+ // toolStripStatusLabel2
+ //
+ this.toolStripStatusLabel2.Name = "toolStripStatusLabel2";
+ this.toolStripStatusLabel2.Size = new System.Drawing.Size(0, 17);
+ //
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1072, 683);
+ this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.label7);
this.Controls.Add(this.panel1);
this.Controls.Add(this.treeView1);
@@ -271,6 +298,8 @@
this.Load += new System.EventHandler(this.Form1_Load);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
+ this.statusStrip1.ResumeLayout(false);
+ this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -296,5 +325,8 @@
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label7;
private HslCommunication.Controls.UserButton userButton4;
+ private System.Windows.Forms.StatusStrip statusStrip1;
+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel2;
}
}
\ No newline at end of file
diff --git a/HslCommunicationNetTestTool/Form1.cs b/HslCommunicationNetTestTool/Form1.cs
index db911cd..cd75f84 100644
--- a/HslCommunicationNetTestTool/Form1.cs
+++ b/HslCommunicationNetTestTool/Form1.cs
@@ -153,6 +153,7 @@ namespace HslCommunicationNetTestTool
}
label_timeSpend.Text = (DateTime.Now - start).TotalSeconds.ToString("F3");
+
}
catch(Exception ex)
{
diff --git a/HslCommunicationNetTestTool/Form1.resx b/HslCommunicationNetTestTool/Form1.resx
index 7080a7d..d26a846 100644
--- a/HslCommunicationNetTestTool/Form1.resx
+++ b/HslCommunicationNetTestTool/Form1.resx
@@ -117,4 +117,7 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 17, 17
+
\ No newline at end of file