#
luxiaotao1123
2020-08-04 6abc20e29568c129f4ca71eccec9310534a8c779
#
6个文件已修改
34个文件已添加
6个文件已删除
37 文件已重命名
7891 ■■■■■ 已修改文件
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftBasic.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftIncrementCount.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftSecurity.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftZipped.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/BasicFramework/SystemVersion.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Address/DeviceAddressBase.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/FetchWriteMessage.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/FinsMessage.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/HslMessage.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/INetMessage.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/MelsecA1EBinaryMessage.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/MelsecQnA3EAsciiMessage.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/MelsecQnA3EBinaryMessage.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/ModbusTcpMessage.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/IMessage/S7Message.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/HslProtocol.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/IReadWriteNet.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/NetHandle.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkBase.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkDeviceBase.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkDoubleBase.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkXBase.java 735 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/StateOne/AlienSession.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Net/StateOne/AppSession.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Security/HslSecurity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ByteTransformBase.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ByteTransformHelper.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/DataFormat.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/IByteTransform.java 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/RegularByteTransform.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ReverseBytesTransform.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ReverseWordTransform.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperate.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperateExOne.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperateExThree.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperateExTwo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/FunctionOperate.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/FunctionOperateExOne.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/HslTimeOut.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/IDataTransfer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResult.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExFour.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExOne.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExThree.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExTwo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Enthernet/ComplexNet/NetComplexClient.java 472 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Enthernet/FileNet/FileBaseInfo.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Enthernet/PushNet/NetPushClient.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Enthernet/SimplifyNet/NetSimplifyClient.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Language/DefaultLanguage.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Language/English.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/LogNet/Core/GenerateMode.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/LogNet/Core/HslMessageDegree.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/LogNet/Core/HslMessageItem.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/LogNet/Core/ILogNet.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/ModBus/ModbusAddress.java 277 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/ModBus/ModbusInfo.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/ModBus/ModbusTcpNet.java 494 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecA1EDataType.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecA1ENet.java 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecHelper.java 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecMcAsciiNet.java 413 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecMcDataType.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecMcNet.java 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Omron/OmronFinsDataType.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Omron/OmronFinsNet.java 529 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Siemens/SiemensFetchWriteNet.java 330 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Siemens/SiemensPLCS.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Profinet/Siemens/SiemensS7Net.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/Utilities.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/Main.java 376 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/AuthController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/gateway/Test.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/gateway/core/IReadWriteNet.java 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/gateway/pipeline/Bootstrap.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/gateway/pipeline/HandlerInitializer.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/gateway/pipeline/PipelineBootstrap.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/gateway/pipeline/PipelineProperties.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/common.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/console.html 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/crn.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftBasic.java
File was renamed from src/main/java/com/zy/gateway/core/base/SoftBasic.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.base;
package com.zy.common.HslCommunication.BasicFramework;
import java.io.ByteArrayOutputStream;
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftIncrementCount.java
New file
@@ -0,0 +1,52 @@
package com.zy.common.HslCommunication.BasicFramework;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 一个简单的不持久化的序号自增类,采用线程安全实现,并允许指定最大数字,到达后清空从指定数开始
 */
public class SoftIncrementCount {
    /**
     * 实例化一个自增信息的对象,包括最大值
     * @param max 数据的最大值,必须指定
     * @param start 数据的起始值,默认为0
     */
    public SoftIncrementCount( long max, long start )
    {
        this.start = start;
        this.max = max;
        current = start;
        hybirdLock = new ReentrantLock();
    }
    private long start = 0;
    private long current = 0;
    private long max = Long.MAX_VALUE;
    private Lock hybirdLock;
    /**
     * 获取自增信息
     * @return 值
     */
    public long GetCurrentValue( )
    {
        long value = 0;
        hybirdLock.lock( );
        value = current;
        current++;
        if (current > max)
        {
            current = 0;
        }
        hybirdLock.unlock( );
        return value;
    }
}
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftSecurity.java
New file
@@ -0,0 +1,8 @@
package com.zy.common.HslCommunication.BasicFramework;
public class SoftSecurity {
}
src/main/java/com/zy/common/HslCommunication/BasicFramework/SoftZipped.java
File was renamed from src/main/java/com/zy/gateway/core/base/SoftZipped.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.base;
package com.zy.common.HslCommunication.BasicFramework;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
src/main/java/com/zy/common/HslCommunication/BasicFramework/SystemVersion.java
New file
@@ -0,0 +1,214 @@
package com.zy.common.HslCommunication.BasicFramework;
/**
 * 系统的版本类
 */
public class SystemVersion {
    /**
     * 根据格式化字符串的版本号初始化
     * @param VersionString 格式化的字符串,例如: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]);
            }
        }
    }
    /**
     * 根据指定的数字实例化一个对象
     * @param main 主版本
     * @param sec 次版本
     * @param edit 修订版
     */
    public SystemVersion(int main, int sec, int edit)
    {
        m_MainVersion = main;
        m_SecondaryVersion = sec;
        m_EditVersion = edit;
    }
    /**
     * 根据指定的数字实例化一个对象
     * @param main 主版本
     * @param sec 次版本
     * @param edit 修订版
     * @param inner 内部版本号
     */
    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;
    /**
     * 主版本
     * @return int数据
     */
    public int MainVersion()
    {
        return m_MainVersion;
    }
    private int m_SecondaryVersion = 0;
    /**
     * 次版本
     * @return int数据
     */
    public int SecondaryVersion() {
        return m_SecondaryVersion;
    }
    private int m_EditVersion = 0;
    /**
     * 修订版
     * @return int数据
     */
    public int EditVersion() {
        return m_EditVersion;
    }
    private int m_InnerVersion = 0;
    /**
     * 内部版本号,或者是版本号表示为年月份+内部版本的表示方式
     * @return int数据
     */
    public int InnerVersion()
    {
        return m_InnerVersion;
    }
    /**
     * 根据格式化为支持返回的不同信息的版本号
     * C返回1.0.0.0
     * N返回1.0.0
     * S返回1.0
     * @param format 格式化信息
     * @return 字符串数据
     */
    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();
    }
    /**
     * 版本信息
     * @return 字符串数据
     */
    @Override
    public String toString() {
        if(InnerVersion() == 0)
        {
            return MainVersion()+"."+SecondaryVersion()+"."+EditVersion();
        }
        else
        {
            return MainVersion()+"."+SecondaryVersion()+"."+EditVersion()+"."+InnerVersion();
        }
    }
    /**
     * 判断版本是否一致
     * @param sv 对比的版本
     * @return 是否一致
     */
    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;
    }
    /**
     * 判断是不是小于指定的版本
     * @param sv 对比的版本
     * @return 是否小于
     */
    public boolean IsSmallerThan(SystemVersion sv) {
        if (this.m_MainVersion < sv.m_MainVersion) {
            return true;
        }
        else if(this.m_MainVersion > sv.m_MainVersion) {
            return false;
        }
        if (this.m_SecondaryVersion < sv.m_SecondaryVersion) {
            return true;
        }
        else if (this.m_SecondaryVersion > sv.m_SecondaryVersion) {
            return false;
        }
        if (this.m_EditVersion < sv.m_EditVersion) {
            return true;
        }
        else if (this.m_EditVersion > sv.m_EditVersion) {
            return false;
        }
        if (this.m_InnerVersion < sv.m_InnerVersion) {
            return true;
        }
        else if (this.m_InnerVersion > sv.m_InnerVersion) {
            return false;
        }
        return false;
    }
}
src/main/java/com/zy/common/HslCommunication/Core/Address/DeviceAddressBase.java
New file
@@ -0,0 +1,49 @@
package com.zy.common.HslCommunication.Core.Address;
/**
 * 所有通信类的地址基类
 */
public class DeviceAddressBase {
    /**
     * 获取地址信息
     * @return
     */
    public int getAddress() {
        return Address;
    }
    /**
     * 设置地址信息
     * @param address
     */
    public void setAddress(int address) {
        Address = address;
    }
    /**
     * 起始地址
     */
    private int Address = 0;
    /**
     * 解析字符串的地址
     *
     * @param address
     */
    public void AnalysisAddress(String address) {
        Address = Integer.parseInt(address);
    }
    /**
     * 返回表示当前对象的字符串
     * @return 字符串
     */
    @Override
    public String toString() {
        return String.valueOf(Address);
    }
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/FetchWriteMessage.java
New file
@@ -0,0 +1,125 @@
package com.zy.common.HslCommunication.Core.IMessage;
public class FetchWriteMessage implements INetMessage
{
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 16;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes(){
        if(HeadBytes == null) return 0;
        if(SendBytes == null) return 16;
        if(HeadBytes[5]==0x04)
        {
            return 0;
        }
        else {
            return (HeadBytes[12] & 0xff) * 256 + (HeadBytes[13] & 0xff);
        }
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token)
    {
        if(HeadBytes == null) return false;
        if(HeadBytes[0]==0x53 && HeadBytes[1] == 0x35){
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return HeadBytes[3];
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/FinsMessage.java
New file
@@ -0,0 +1,124 @@
package com.zy.common.HslCommunication.Core.IMessage;
import com.zy.common.HslCommunication.Utilities;
public class FinsMessage implements INetMessage
{
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 8;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes(){
        if(HeadBytes == null) return 0;
        byte[] buffer = new byte[4];
        buffer[0] = HeadBytes[7];
        buffer[1] = HeadBytes[6];
        buffer[2] = HeadBytes[5];
        buffer[3] = HeadBytes[4];
        return Utilities.getInt(buffer,0);
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token)
    {
        if(HeadBytes == null) return false;
        if(HeadBytes[0] == 0x46 && HeadBytes[1] == 0x49 && HeadBytes[2] == 0x4E && HeadBytes[3] == 0x53){
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return 0;
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/HslMessage.java
New file
@@ -0,0 +1,118 @@
package com.zy.common.HslCommunication.Core.IMessage;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Utilities;
/**
 * 本组件系统使用的默认的消息规则,说明解析和反解析规则的
 */
public class HslMessage implements INetMessage
{
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 32;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes(){
        if(HeadBytes == null) return 0;
        if(HeadBytes.length != 32) return 0;
        return Utilities.getInt(HeadBytes,28);
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token){
        return SoftBasic.IsTwoBytesEquel(HeadBytes,12,token,0,16);
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return Utilities.getInt(HeadBytes,0);
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/INetMessage.java
File was renamed from src/main/java/com/zy/gateway/core/domain/siemens/INetMessage.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain.siemens;
package com.zy.common.HslCommunication.Core.IMessage;
/**
 * 本系统的消息类,包含了各种解析规则,数据信息提取规则
src/main/java/com/zy/common/HslCommunication/Core/IMessage/MelsecA1EBinaryMessage.java
New file
@@ -0,0 +1,142 @@
package com.zy.common.HslCommunication.Core.IMessage;
public class MelsecA1EBinaryMessage implements INetMessage {
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 2;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes(){
        if(HeadBytes == null) return 0;
        int contentLength = 0;
        if (HeadBytes[1] == 0x5B)
        {
            contentLength = 2; //结束代码 + 0x00
            return contentLength;
        }
        else
        {
            int length = (SendBytes[10] % 2 == 0) ? SendBytes[10] : SendBytes[10] + 1;
            switch (HeadBytes[0])
            {
                case (byte) 0x80: //位单位成批读出后,回复副标题
                    contentLength = length / 2;
                    break;
                case (byte) 0x81: //字单位成批读出后,回复副标题
                    contentLength = SendBytes[10] * 2;
                    break;
                case (byte) 0x82: //位单位成批写入后,回复副标题
                    break;
                case (byte) 0x83: //字单位成批写入后,回复副标题
                    break;
                default:
                    break;
            }
            // 在A兼容1E协议中,写入值后,若不发生异常,只返回副标题 + 结束代码(0x00)
            // 这已经在协议头部读取过了,后面要读取的长度为0(contentLength=0)
        }
        return contentLength;
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token)
    {
        if (HeadBytes != null)
        {
            if ((HeadBytes[0] - SendBytes[0]) == (byte) 0x80) { return true; }
        }
        return false;
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return 0;
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/MelsecQnA3EAsciiMessage.java
New file
@@ -0,0 +1,124 @@
package com.zy.common.HslCommunication.Core.IMessage;
import com.zy.common.HslCommunication.Utilities;
public class MelsecQnA3EAsciiMessage implements INetMessage
{
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 18;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes(){
        if(HeadBytes == null) return 0;
        byte[] buffer = new byte[4];
        buffer[0] = HeadBytes[14];
        buffer[1] = HeadBytes[15];
        buffer[2] = HeadBytes[16];
        buffer[3] = HeadBytes[17];
        return Integer.parseInt(Utilities.getString(buffer,"ascii"),16);
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token)
    {
        if(HeadBytes == null) return false;
        if(HeadBytes[0] == (byte)'D' && HeadBytes[1] == (byte)'0' && HeadBytes[2] == (byte)'0' && HeadBytes[3] == (byte)'0'){
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return 0;
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/MelsecQnA3EBinaryMessage.java
New file
@@ -0,0 +1,117 @@
package com.zy.common.HslCommunication.Core.IMessage;
public class MelsecQnA3EBinaryMessage implements INetMessage
{
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 9;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes(){
        if(HeadBytes == null) return 0;
        return (HeadBytes[7]&0xff) + (HeadBytes[8]&0xff)*256;
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token)
    {
        if(HeadBytes == null) return false;
        if((HeadBytes[0]&0xff)==0xd0 && HeadBytes[1] == 0x00){
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return 0;
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/ModbusTcpMessage.java
New file
@@ -0,0 +1,134 @@
package com.zy.common.HslCommunication.Core.IMessage;
/**
 * Modbus Tcp协议的消息对象,用来确定接收规则的
 */
public class ModbusTcpMessage implements INetMessage
{
    /**
     * 消息头的指令长度
     */
    public int ProtocolHeadBytesLength(){
        return 8;
    }
    /**
     * 从当前的头子节文件中提取出接下来需要接收的数据长度
     * @return 返回接下来的数据内容长度
     */
    public int GetContentLengthByHeadBytes() {
        if (HeadBytes == null) return 0;
        if (HeadBytes.length >= ProtocolHeadBytesLength()) {
            int length = (HeadBytes[4] & 0xff) * 256 + (HeadBytes[5] & 0xff);
            if (length == 0) {
                byte[] buffer = new byte[ProtocolHeadBytesLength() - 1];
                for (int i = 0; i < buffer.length; i++) {
                    buffer[i] = HeadBytes[i + 1];
                }
                HeadBytes = buffer;
                return (HeadBytes[5] & 0xff) * 256 + (HeadBytes[6] & 0xff) - 1;
            } else {
                return length - 2;
            }
        }
        return 0;
    }
    /**
     * 检查头子节的合法性
     * @param token 特殊的令牌,有些特殊消息的验证
     * @return 是否合法的验证
     */
    public boolean CheckHeadBytesLegal(byte[] token)
    {
        if(HeadBytes == null) return false;
        if(HeadBytes[2]==0x00 && HeadBytes[3] == 0x00){
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * 获取头子节里的消息标识
     * @return
     */
    public int GetHeadBytesIdentity(){
        return 0;
    }
    /**
     * 获取消息头字节
     *
     * @return
     */
    @Override
    public byte[] getHeadBytes() {
        return HeadBytes;
    }
    /**
     * 获取消息内容字节
     *
     * @return
     */
    @Override
    public byte[] getContentBytes() {
        return ContentBytes;
    }
    /**
     * 获取发送的消息
     *
     * @return
     */
    @Override
    public byte[] getSendBytes() {
        return SendBytes;
    }
    /**
     * 设置消息头子节
     * @param headBytes 字节数据
     */
    public void setHeadBytes(byte[] headBytes){
        HeadBytes = headBytes;
    }
    /**
     * 设置消息内容字节
     * @param contentBytes 内容字节
     */
    public void setContentBytes(byte[] contentBytes){
        ContentBytes = contentBytes;
    }
    /**
     * 设置发送的字节信息
     * @param sendBytes 发送的字节信息
     */
    public void setSendBytes(byte[] sendBytes){
        SendBytes = sendBytes;
    }
    private byte[] HeadBytes = null;
    private byte[] ContentBytes = null;
    private byte[] SendBytes = null;
}
src/main/java/com/zy/common/HslCommunication/Core/IMessage/S7Message.java
File was renamed from src/main/java/com/zy/gateway/core/domain/siemens/S7Message.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain.siemens;
package com.zy.common.HslCommunication.Core.IMessage;
public class S7Message implements INetMessage {
src/main/java/com/zy/common/HslCommunication/Core/Net/HslProtocol.java
File was renamed from src/main/java/com/zy/gateway/core/net/HslProtocol.java
@@ -1,8 +1,8 @@
package com.zy.gateway.core.net;
package com.zy.common.HslCommunication.Core.Net;
import com.zy.gateway.core.base.HslSecurity;
import com.zy.gateway.core.base.SoftZipped;
import com.zy.gateway.core.utils.Utilities;
import com.zy.common.HslCommunication.BasicFramework.*;
import com.zy.common.HslCommunication.Core.Security.HslSecurity;
import com.zy.common.HslCommunication.Utilities;
import java.util.UUID;
src/main/java/com/zy/common/HslCommunication/Core/Net/IReadWriteNet.java
File was renamed from src/main/java/com/zy/gateway/core/net/IReadWriteNet.java
@@ -1,8 +1,8 @@
package com.zy.gateway.core.net;
package com.zy.common.HslCommunication.Core.Net;
import com.zy.gateway.core.domain.IDataTransfer;
import com.zy.gateway.core.domain.OperateResult;
import com.zy.gateway.core.domain.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.IDataTransfer;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
/**
 * 所有设备交互类的统一的读写接口
@@ -15,7 +15,7 @@
     * @param length 数据长度
     * @return 带有成功标识的byte[]数组
     */
    OperateResultExOne<byte[]> Read(String address, short length);
    OperateResultExOne<byte[]> Read(String address, short length );
    /**
     * 读取16位的有符号整型
@@ -30,7 +30,7 @@
     * @param length 读取的数组长度
     * @return 带有成功标识的short数组
     */
    OperateResultExOne<short []> ReadInt16(String address, short length);
    OperateResultExOne<short []> ReadInt16( String address, short length );
    /**
     * 读取32位的有符号整型
@@ -45,7 +45,7 @@
     * @param length 数组长度
     * @return 带成功标志的结果数据对象
     */
    OperateResultExOne<int[]> ReadInt32(String address, short length);
    OperateResultExOne<int[]> ReadInt32( String address, short length );
    /**
     * 读取64位的有符号整型
@@ -60,7 +60,7 @@
     * @param length 数组长度
     * @return 带成功标志的结果数据对象
     */
    OperateResultExOne<long[]> ReadInt64(String address, short length);
    OperateResultExOne<long[]> ReadInt64( String address, short length );
    /**
     * 读取单浮点精度的数据
@@ -75,7 +75,7 @@
     * @param length 数组长度
     * @return 带成功标志的结果数据对象
     */
    OperateResultExOne<float[]> ReadFloat(String address, short length);
    OperateResultExOne<float[]> ReadFloat( String address, short length );
    /**
     * 读取双浮点精度的数据
@@ -91,7 +91,7 @@
     * @param length 数组长度
     * @return 带成功标志的结果数据对象
     */
    OperateResultExOne<double[]> ReadDouble(String address, short length);
    OperateResultExOne<double[]> ReadDouble( String address, short length );
    /**
     * 读取字符串数据
@@ -108,7 +108,7 @@
     * @param <T> 自定义的类型
     * @return 带有成功标识的自定义类型数据
     */
    <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address, Class<T> tClass);
    <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address,Class<T> tClass);
src/main/java/com/zy/common/HslCommunication/Core/Net/NetHandle.java
New file
@@ -0,0 +1,116 @@
package com.zy.common.HslCommunication.Core.Net;
import com.zy.common.HslCommunication.Utilities;
/**
 * 用于通信过程中的暗号对象
 */
public final class NetHandle {
    /**
     * 初始化一个暗号对象
     * @param value int值
     */
    public NetHandle(int value)
    {
        byte[] buffer = Utilities.getBytes(value);
        m_CodeMajor = buffer[3];
        m_CodeMinor = buffer[2];
        m_CodeIdentifier = Utilities.getShort(buffer,0);
        m_CodeValue = value;
    }
    /**
     * 根据三个值来初始化暗号对象
     * @param major 主暗号
     * @param minor 主暗号
     * @param identifier 暗号编号
     */
    public NetHandle(int major, int minor, int identifier)
    {
        m_CodeValue = 0;
        byte[] buffer_major=Utilities.getBytes(major);
        byte[] buffer_minor=Utilities.getBytes(minor);
        byte[] buffer_identifier=Utilities.getBytes(identifier);
        m_CodeMajor = buffer_major[0];
        m_CodeMinor = buffer_minor[0];
        m_CodeIdentifier = Utilities.getShort(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.getInt(buffer,0);
    }
    /**
     * 完整的暗号值
     */
    private int m_CodeValue;
    /**
     * 主暗号分类0-255
     */
    private byte m_CodeMajor;
    /**
     * 次要的暗号分类0-255
     */
    private byte m_CodeMinor;
    /**
     * 暗号的编号分类0-65535
     */
    private short m_CodeIdentifier;
    /**
     * 获取完整的暗号值
     * @return
     */
    public int get_CodeValue(){
        return  m_CodeValue;
    }
    /**
     * 获取主暗号分类0-255
     * @return 主暗号
     */
    public byte get_CodeMajor() {
        return m_CodeMajor;
    }
    /**
     * 获取次要的暗号分类0-255
     * @return 次暗号
     */
    public byte get_CodeMinor() {
        return m_CodeMinor;
    }
    /**
     * 获取暗号的编号分类0-65535
     * @return 编号分类
     */
    public short get_CodeIdentifier() {
        return m_CodeIdentifier;
    }
}
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkBase.java
File was renamed from src/main/java/com/zy/gateway/core/net/NetworkBase.java
@@ -1,12 +1,12 @@
package com.zy.gateway.core.net;
package com.zy.common.HslCommunication.Core.Net.NetworkBase;
import com.zy.gateway.core.StringResources;
import com.zy.gateway.core.domain.HslTimeOut;
import com.zy.gateway.core.domain.OperateResult;
import com.zy.gateway.core.domain.OperateResultExOne;
import com.zy.gateway.core.domain.siemens.INetMessage;
import com.zy.gateway.core.log.ILogNet;
import com.zy.gateway.core.utils.Utilities;
import com.zy.common.HslCommunication.Core.IMessage.INetMessage;
import com.zy.common.HslCommunication.Core.Types.HslTimeOut;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.LogNet.Core.ILogNet;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
import java.io.DataOutputStream;
import java.io.IOException;
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkDeviceBase.java
File was renamed from src/main/java/com/zy/gateway/core/net/NetworkDeviceBase.java
@@ -1,12 +1,13 @@
package com.zy.gateway.core.net;
package com.zy.common.HslCommunication.Core.Net.NetworkBase;
import com.zy.gateway.core.base.SoftBasic;
import com.zy.gateway.core.domain.IDataTransfer;
import com.zy.gateway.core.domain.OperateResult;
import com.zy.gateway.core.domain.OperateResultExOne;
import com.zy.gateway.core.domain.siemens.INetMessage;
import com.zy.gateway.core.transfer.IByteTransform;
import com.zy.gateway.core.utils.Utilities;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.IMessage.INetMessage;
import com.zy.common.HslCommunication.Core.Net.IReadWriteNet;
import com.zy.common.HslCommunication.Core.Transfer.IByteTransform;
import com.zy.common.HslCommunication.Core.Types.IDataTransfer;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Utilities;
/**
@@ -62,7 +63,7 @@
     * @param <T> 类型名称
     * @return 带有成功标识的结果对象
     */
    public <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address , Class<T> tClass)
    public <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address ,Class<T> tClass)
    {
        OperateResultExOne<T> result = new OperateResultExOne<T>();
        T Content;
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkDoubleBase.java
File was renamed from src/main/java/com/zy/gateway/core/net/NetworkDoubleBase.java
@@ -1,14 +1,14 @@
package com.zy.gateway.core.net;
package com.zy.common.HslCommunication.Core.Net.NetworkBase;
import com.zy.gateway.core.StringResources;
import com.zy.gateway.core.base.SoftBasic;
import com.zy.gateway.core.domain.OperateResult;
import com.zy.gateway.core.domain.OperateResultExOne;
import com.zy.gateway.core.domain.OperateResultExTwo;
import com.zy.gateway.core.domain.siemens.INetMessage;
import com.zy.gateway.core.net.session.AlienSession;
import com.zy.gateway.core.transfer.ByteTransformHelper;
import com.zy.gateway.core.transfer.IByteTransform;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.IMessage.INetMessage;
import com.zy.common.HslCommunication.Core.Net.StateOne.AlienSession;
import com.zy.common.HslCommunication.Core.Transfer.ByteTransformHelper;
import com.zy.common.HslCommunication.Core.Transfer.IByteTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.StringResources;
import java.lang.reflect.ParameterizedType;
import java.net.Socket;
@@ -20,7 +20,7 @@
 * @param <TNetMessage> 消息类的类型
 * @param <TTransform> 转换类的类型
 */
public class NetworkDoubleBase<TNetMessage extends INetMessage,TTransform extends IByteTransform> extends NetworkBase
public class NetworkDoubleBase<TNetMessage extends INetMessage  ,TTransform extends IByteTransform> extends NetworkBase
{
    /**
     * 默认的无参构造函数
src/main/java/com/zy/common/HslCommunication/Core/Net/NetworkBase/NetworkXBase.java
New file
@@ -0,0 +1,735 @@
package com.zy.common.HslCommunication.Core.Net.NetworkBase;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.Net.HslProtocol;
import com.zy.common.HslCommunication.Core.Net.StateOne.AppSession;
import com.zy.common.HslCommunication.Core.Types.*;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
/**
 * 客户端服务器的共享基类
 */
public class NetworkXBase extends NetworkBase
{
    /**
     * 默认的无参构造方法
     */
    public NetworkXBase()
    {
    }
    /**
     * 发送数据的方法
     * @param session 通信用的核心对象
     * @param content 完整的字节信息
     */
    void SendBytesAsync(AppSession session, byte[] content )
    {
        if (content == null) return;
        try
        {
            // 进入发送数据的锁,然后开启异步的数据发送
            session.getHybirdLockSend().lock();
            OutputStream outputStream = session.getWorkSocket().getOutputStream();
            outputStream.write(content);
        }
        catch (Exception ex)
        {
            if (!ex.getMessage().contains( StringResources.Language.SocketRemoteCloseException() ))
            {
                if(LogNet!=null) LogNet.WriteException( toString( ), StringResources.Language.SocketSendException(), ex );
            }
        }
        finally {
            session.getHybirdLockSend().unlock();
        }
    }
    private Thread thread;  // 后台线程
    /**
     * 开始接受数据
     * @param session 会话信息
     */
    protected void BeginReceiveBackground(AppSession session){
        thread = new Thread(){
            @Override
            public void run(){
                while (true){
                    OperateResultExOne<byte[]> readHeadBytes = Receive(session.getWorkSocket(),HslProtocol.HeadByteLength);
                    if(!readHeadBytes.IsSuccess){
                        SocketReceiveException( session );
                        return;
                    }
                    int length = Utilities.getInt(readHeadBytes.Content,28);
                    OperateResultExOne<byte[]> readContent = Receive(session.getWorkSocket(),length);
                    if(!readContent.IsSuccess){
                        SocketReceiveException( session );
                        return;
                    }
                    if (CheckRemoteToken( readHeadBytes.Content ))
                    {
                        byte[] head = readHeadBytes.Content;
                        byte[] content = HslProtocol.CommandAnalysis(head,readContent.Content);
                        int protocol = Utilities.getInt( head, 0 );
                        int customer = Utilities.getInt( head, 4 );
                        DataProcessingCenter(session,protocol,customer,content);
                    }
                    else {
                        if(LogNet!=null) LogNet.WriteWarn( toString( ), StringResources.Language.TokenCheckFailed() );
                        AppSessionRemoteClose( session );
                    }
                }
            }
        };
        thread.start();
    }
    /**
     * 数据处理中心,应该继承重写
     * @param session 连接状态
     * @param protocol 协议头
     * @param customer 用户自定义
     * @param content 数据内容
     */
    protected void DataProcessingCenter( AppSession session, int protocol, int customer, byte[] content ) {
    }
    /**
     * 检查当前的头子节信息的令牌是否是正确的
     * @param headBytes 头子节数据
     * @return 令牌是验证成功
     */
    protected boolean CheckRemoteToken( byte[] headBytes )
    {
        return SoftBasic.IsTwoBytesEquel( headBytes,12, Utilities.UUID2Byte(Token),0,16 );
    }
    /**
     * 接收出错的时候进行处理
     * @param session 会话内容
     */
    protected void SocketReceiveException( AppSession session ) {
    }
    /**
     * 当远端的客户端关闭连接时触发
     * @param session 会话内容
     */
    protected void AppSessionRemoteClose( AppSession session ) {
    }
    /**
     * [自校验] 发送字节数据并确认对方接收完成数据,如果结果异常,则结束通讯
     * @param socket 网络套接字
     * @param headcode 头指令
     * @param customer 用户指令
     * @param send 发送的数据
     * @return 是否发送成功
     */
    protected OperateResult SendBaseAndCheckReceive(Socket socket, int headcode, int customer, byte[] send )
    {
        // 数据处理
        send = HslProtocol.CommandBytes( headcode, customer, Token, send );
        OperateResult sendResult = Send( socket, send );
        if(!sendResult.IsSuccess) return sendResult;
        // 检查对方接收完成
        OperateResultExOne<Long> checkResult = ReceiveLong( socket );
        if(!checkResult.IsSuccess) return checkResult;
        // 检查长度接收
        if (checkResult.Content != send.length)
        {
            CloseSocket(socket);
            return new OperateResult(StringResources.Language.CommandLengthCheckFailed());
        }
        return checkResult;
    }
    /**
     * [自校验] 发送字节数据并确认对方接收完成数据,如果结果异常,则结束通讯
     * @param socket 网络套接字
     * @param customer 用户指令
     * @param send 发送的数据
     * @return 是否发送成功
     */
    protected OperateResult SendBytesAndCheckReceive( Socket socket, int customer, byte[] send )
    {
        return SendBaseAndCheckReceive( socket, HslProtocol.ProtocolUserBytes, customer, send );
    }
    /**
     * [自校验] 直接发送字符串数据并确认对方接收完成数据,如果结果异常,则结束通讯
     * @param socket 网络套接字
     * @param customer 用户指令
     * @param send 发送的数据
     * @return 是否发送成功
     */
    protected OperateResult SendStringAndCheckReceive( Socket socket, int customer, String send )
    {
        byte[] data =(send == null || send.isEmpty() ) ? null : Utilities.string2Byte( send );
        return SendBaseAndCheckReceive( socket, HslProtocol.ProtocolUserString, customer, data );
    }
    /// <summary>
    /// [自校验] 将文件数据发送至套接字,如果结果异常,则结束通讯
    /// </summary>
    /// <param name="socket">网络套接字</param>
    /// <param name="filename">完整的文件路径</param>
    /// <param name="filelength">文件的长度</param>
    /// <param name="report">进度报告器</param>
    /// <returns>是否发送成功</returns>
//    protected OperateResult SendFileStreamToSocket( Socket socket, String filename, long filelength, BiConsumer<Long, Long> report )
//    {
//        try
//        {
//            OperateResult result = null;
//            FileInputStream
//            using (FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read ))
//            {
//                result = SendStream( socket, fs, filelength, report, true );
//            }
//            return result;
//        }
//        catch (Exception ex)
//        {
//            socket?.Close( );
//            LogNet?.WriteException( ToString( ), ex );
//            return new OperateResult( )
//            {
//                Message = ex.Message
//            };
//        }
//    }
    /// <summary>
    /// [自校验] 将文件数据发送至套接字,具体发送细节将在继承类中实现,如果结果异常,则结束通讯
    /// </summary>
    /// <param name="socket">套接字</param>
    /// <param name="filename">文件名称,文件必须存在</param>
    /// <param name="servername">远程端的文件名称</param>
    /// <param name="filetag">文件的额外标签</param>
    /// <param name="fileupload">文件的上传人</param>
    /// <param name="sendReport">发送进度报告</param>
    /// <returns>是否发送成功</returns>
//    protected OperateResult SendFileAndCheckReceive(
//            Socket socket,
//            String filename,
//            String servername,
//            String filetag,
//            String fileupload,
//            BiConsumer<Long, Long> sendReport
//    )
//    {
//        // 发送文件名,大小,标签
//        File file = new File(filename);
//
//        if (!file.exists())
//        {
//            // 如果文件不存在
//            OperateResult stringResult = SendStringAndCheckReceive( socket, 0, "" );
//            if (!stringResult.IsSuccess)
//            {
//                return stringResult;
//            }
//            else
//            {
//                CloseSocket(socket);
//                OperateResult result = new OperateResult();
//                result.Message = StringResources.FileNotExist;
//                return  result;
//            }
//        }
//
//        // 文件存在的情况
//        Newtonsoft.Json.Linq.JObject json = new Newtonsoft.Json.Linq.JObject
//        {
//            { "FileName", new Newtonsoft.Json.Linq.JValue(servername) },
//            { "FileSize", new Newtonsoft.Json.Linq.JValue(file.length()) },
//            { "FileTag", new Newtonsoft.Json.Linq.JValue(filetag) },
//            { "FileUpload", new Newtonsoft.Json.Linq.JValue(fileupload) }
//        };
//
//        // 先发送文件的信息到对方
//        OperateResult sendResult = SendStringAndCheckReceive( socket, 1, json.ToString( ) );
//        if (!sendResult.IsSuccess)
//        {
//            return sendResult;
//        }
//
//        // 最后发送
//        return SendFileStreamToSocket( socket, filename, file.length(), sendReport );
//    }
    /// <summary>
    /// [自校验] 将流数据发送至套接字,具体发送细节将在继承类中实现,如果结果异常,则结束通讯
    /// </summary>
    /// <param name="socket">套接字</param>
    /// <param name="stream">文件名称,文件必须存在</param>
    /// <param name="servername">远程端的文件名称</param>
    /// <param name="filetag">文件的额外标签</param>
    /// <param name="fileupload">文件的上传人</param>
    /// <param name="sendReport">发送进度报告</param>
    /// <returns></returns>
//    protected OperateResult SendFileAndCheckReceive(
//            Socket socket,
//            Stream stream,
//            String servername,
//            String filetag,
//            String fileupload,
//            BiConsumer<Long, Long> sendReport
//    )
//    {
//        // 文件存在的情况
//        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) }
//        };
//
//
//        // 发送文件信息
//        OperateResult fileResult = SendStringAndCheckReceive( socket, 1, json.ToString( ) );
//        if (!fileResult.IsSuccess) return fileResult;
//
//
//        return SendStream( socket, stream, stream.count(), sendReport, true );
//    }
    /**
     * [自校验] 接收一条完整的同步数据,包含头子节和内容字节,基础的数据,如果结果异常,则结束通讯
     * @param socket 套接字
     * @param timeout 超时时间设置,如果为负数,则不检查超时
     * @return 接收的结果数据
     */
    protected OperateResultExTwo<byte[], byte[]> ReceiveAndCheckBytes( Socket socket, int timeout ) {
        // 30秒超时接收验证
        HslTimeOut hslTimeOut = new HslTimeOut();
        hslTimeOut.DelayTime = timeout;
        hslTimeOut.IsSuccessful = false;
        hslTimeOut.StartTime = new Date();
        hslTimeOut.WorkSocket = socket;
        //if (timeout > 0) ThreadPool.QueueUserWorkItem( new WaitCallback( ThreadPoolCheckTimeOut ), hslTimeOut );
        // 接收头指令
        OperateResultExOne<byte[]> headResult = Receive(socket, HslProtocol.HeadByteLength, timeout);
        if (!headResult.IsSuccess) {
            hslTimeOut.IsSuccessful = true;
            return OperateResultExTwo.<byte[],byte[]>CreateFailedResult(headResult);
        }
        hslTimeOut.IsSuccessful = true;
        // 检查令牌
        if (!CheckRemoteToken(headResult.Content)) {
            CloseSocket(socket);
            return new OperateResultExTwo<>(StringResources.Language.TokenCheckFailed());
        }
        int contentLength = Utilities.getInt(headResult.Content, HslProtocol.HeadByteLength - 4);
        // 接收内容
        OperateResultExOne<byte[]> contentResult = Receive(socket, contentLength);
        if (!contentResult.IsSuccess) return OperateResultExTwo.CreateFailedResult(contentResult);
        // 返回成功信息
        OperateResult checkResult = SendLong(socket, HslProtocol.HeadByteLength + contentLength);
        if (!checkResult.IsSuccess)  return OperateResultExTwo.CreateFailedResult(checkResult);
        byte[] head = headResult.Content;
        byte[] content = contentResult.Content;
        content = HslProtocol.CommandAnalysis(head, content);
        return OperateResultExTwo.CreateSuccessResult(head, content);
    }
    /**
     * [自校验] 从网络中接收一个字符串数据,如果结果异常,则结束通讯
     * @param socket 套接字
     * @return 接收的结果数据
     */
    protected OperateResultExTwo<Integer, String> ReceiveStringContentFromSocket( Socket socket ) {
        OperateResultExTwo<byte[], byte[]> receive = ReceiveAndCheckBytes(socket, 10000);
        if (!receive.IsSuccess) return OperateResultExTwo.CreateFailedResult(receive);
        // 检查是否是字符串信息
        if (Utilities.getInt(receive.Content1, 0) != HslProtocol.ProtocolUserString) {
            if (LogNet != null) LogNet.WriteError(toString(), StringResources.Language.CommandHeadCodeCheckFailed());
            CloseSocket(socket);
            return new OperateResultExTwo<>(StringResources.Language.CommandHeadCodeCheckFailed());
        }
        if (receive.Content2 == null) receive.Content2 = new byte[0];
        // 分析数据
        return OperateResultExTwo.CreateSuccessResult(Utilities.getInt(receive.Content1, 4), Utilities.byte2String(receive.Content2));
    }
    /**
     * [自校验] 从网络中接收一串字节数据,如果结果异常,则结束通讯
     * @param socket 套接字
     * @return 结果数据对象
     */
    protected OperateResultExTwo<Integer, byte[]> ReceiveBytesContentFromSocket( Socket socket )
    {
        OperateResultExTwo<byte[], byte[]> receive = ReceiveAndCheckBytes( socket, 10000 );
        if (!receive.IsSuccess) return OperateResultExTwo.CreateFailedResult(receive);
        // 检查是否是字节信息
        if (Utilities.getInt( receive.Content1, 0 ) != HslProtocol.ProtocolUserBytes)
        {
            if(LogNet!=null) LogNet.WriteError( toString( ), StringResources.Language.CommandHeadCodeCheckFailed() );
            CloseSocket(socket);
            return new OperateResultExTwo<>(StringResources.Language.CommandHeadCodeCheckFailed());
        }
        // 分析数据
        return OperateResultExTwo.CreateSuccessResult( Utilities.getInt( receive.Content1, 4 ), receive.Content2 );
    }
    /// <summary>
    /// [自校验] 从套接字中接收文件头信息
    /// </summary>
    /// <param name="socket"></param>
    /// <returns></returns>
//    protected OperateResult<FileBaseInfo> ReceiveFileHeadFromSocket( Socket socket )
//    {
//        // 先接收文件头信息
//        OperateResult<int, string> receiveString = ReceiveStringContentFromSocket( socket );
//        if (!receiveString.IsSuccess) return OperateResult.CreateFailedResult<FileBaseInfo>( receiveString );
//
//        // 判断文件是否存在
//        if (receiveString.Content1 == 0)
//        {
//            socket?.Close( );
//            LogNet?.WriteWarn( ToString( ), "对方文件不存在,无法接收!" );
//            return new OperateResult<FileBaseInfo>( )
//            {
//                Message = StringResources.FileNotExist
//            };
//        }
//
//        OperateResult<FileBaseInfo> result = new OperateResult<FileBaseInfo>( );
//        result.Content = new FileBaseInfo( );
//        try
//        {
//            // 提取信息
//            Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse( receiveString.Content2 );
//            result.Content.Name = SoftBasic.GetValueFromJsonObject( json, "FileName", "" );
//            result.Content.Size = SoftBasic.GetValueFromJsonObject( json, "FileSize", 0L );
//            result.Content.Tag = SoftBasic.GetValueFromJsonObject( json, "FileTag", "" );
//            result.Content.Upload = SoftBasic.GetValueFromJsonObject( json, "FileUpload", "" );
//            result.IsSuccess = true;
//        }
//        catch (Exception ex)
//        {
//            socket?.Close( );
//            result.Message = "提取信息失败," + ex.Message;
//        }
//
//        return result;
//    }
    /// <summary>
    /// [自校验] 从网络中接收一个文件,如果结果异常,则结束通讯
    /// </summary>
    /// <param name="socket">网络套接字</param>
    /// <param name="savename">接收文件后保存的文件名</param>
    /// <param name="receiveReport">接收进度报告</param>
    /// <returns></returns>
//    protected OperateResult<FileBaseInfo> ReceiveFileFromSocket( Socket socket, string savename, Action<long, long> receiveReport )
//    {
//        // 先接收文件头信息
//        OperateResult<FileBaseInfo> fileResult = ReceiveFileHeadFromSocket( socket );
//        if (!fileResult.IsSuccess) return fileResult;
//
//        try
//        {
//            using (FileStream fs = new FileStream( savename, FileMode.Create, FileAccess.Write ))
//            {
//                WriteStream( socket, fs, fileResult.Content.Size, receiveReport, true );
//            }
//            return fileResult;
//        }
//        catch (Exception ex)
//        {
//            LogNet?.WriteException( ToString( ), ex );
//            socket?.Close( );
//            return new OperateResult<FileBaseInfo>( )
//            {
//                Message = ex.Message
//            };
//        }
//    }
    /// <summary>
    /// [自校验] 从网络中接收一个文件,写入数据流,如果结果异常,则结束通讯,参数顺序文件名,文件大小,文件标识,上传人
    /// </summary>
    /// <param name="socket">网络套接字</param>
    /// <param name="stream">等待写入的数据流</param>
    /// <param name="receiveReport">接收进度报告</param>
    /// <returns></returns>
//    protected OperateResult<FileBaseInfo> ReceiveFileFromSocket( Socket socket, Stream stream, Action<long, long> receiveReport )
//    {
//        // 先接收文件头信息
//        OperateResult<FileBaseInfo> fileResult = ReceiveFileHeadFromSocket( socket );
//        if (!fileResult.IsSuccess) return fileResult;
//
//        try
//        {
//            WriteStream( socket, stream, fileResult.Content.Size, receiveReport, true );
//            return fileResult;
//        }
//        catch (Exception ex)
//        {
//            LogNet?.WriteException( ToString( ), ex );
//            socket?.Close( );
//            return new OperateResult<FileBaseInfo>( )
//            {
//                Message = ex.Message
//            };
//        }
//    }
    /**
     * 删除文件的操作
     * @param filename 文件的名称
     * @return 是否删除成功
     */
    protected boolean DeleteFileByName( String filename )
    {
        try
        {
            File file = new File(filename);
            if (!file.exists()) return true;
            file.delete();
            return true;
        }
        catch (Exception ex)
        {
            if(LogNet!=null) LogNet.WriteException( toString( ), "delete file failed:" + filename, ex );
            return false;
        }
    }
    /**
     * 预处理文件夹的名称,除去文件夹名称最后一个'\',如果有的话
     * @param folder 文件夹名称
     * @return 结果数据
     */
    protected String PreprocessFolderName( String folder ) {
        if (folder.endsWith("\\")) {
            return folder.substring(0, folder.length() - 1);
        } else {
            return folder;
        }
    }
    /**
     * 从网络中接收Long数据
     * @param socket 套接字信息
     * @return 返回的结果
     */
    private OperateResultExOne<Long> ReceiveLong( Socket socket ) {
        OperateResultExOne<byte[]> read = Receive(socket, 8);
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult(read);
        return OperateResultExOne.CreateSuccessResult(Utilities.getLong(read.Content, 0));
    }
    /**
     * 将Long数据发送到套接字
     * @param socket 套接字
     * @param value 值
     * @return 返回的结果
     */
    private OperateResult SendLong( Socket socket, long value )
    {
        return Send( socket, Utilities.getBytes( value ) );
    }
    /**
     * 发送一个流的所有数据到网络套接字
     * @param socket 网络套接字
     * @param stream 输入流
     * @param receive 接收长度
     * @param report 进度报告
     * @param reportByPercent 是否按照百分比报告进度
     * @return 是否成功
     */
    protected OperateResult SendStream(Socket socket, InputStream stream, long receive, ActionOperateExTwo<Long, Long> report, boolean reportByPercent )
    {
        byte[] buffer = new byte[102400]; // 100K的数据缓存池
        long SendTotal = 0;
        long percent = 0;
        while (SendTotal < receive)
        {
            // 先从流中接收数据
            OperateResultExOne<Integer> read = ReadStream( stream, buffer );
            if (!read.IsSuccess)
            {
                OperateResult result = new OperateResult();
                result.Message = read.Message;
                return  result;
            }
            else
            {
                SendTotal += read.Content;
            }
            // 然后再异步写到socket中
            byte[] newBuffer = new byte[read.Content];
            System.arraycopy( buffer, 0, newBuffer, 0, newBuffer.length );
            OperateResult write = SendBytesAndCheckReceive( socket, read.Content, newBuffer );
            if (!write.IsSuccess)
            {
                OperateResult result = new OperateResult();
                result.Message = write.Message;
                return  result;
            }
            // 报告进度
            if (reportByPercent)
            {
                long percentCurrent = SendTotal * 100 / receive;
                if (percent != percentCurrent)
                {
                    percent = percentCurrent;
                    if(report!=null) report.Action( SendTotal, receive );
                }
            }
            else
            {
                // 报告进度
                if(report!=null) report.Action( SendTotal, receive );
            }
        }
        return OperateResult.CreateSuccessResult( );
    }
    /**
     * 从套接字中接收所有的数据然后写入到流当中去
     * @param socket 网络套接字
     * @param stream 输出流
     * @param totalLength 总长度
     * @param report 进度报告
     * @param reportByPercent 进度报告是否按照百分比
     * @return 结果类对象
     */
    protected OperateResult WriteStream(Socket socket, OutputStream stream, long totalLength, ActionOperateExTwo<Long, Long> report, boolean reportByPercent )
    {
        long count_receive = 0;
        long percent = 0;
        while (count_receive < totalLength)
        {
            // 先从流中异步接收数据
            OperateResultExTwo<Integer,byte[]> read = ReceiveBytesContentFromSocket( socket );
            if (!read.IsSuccess)
            {
                OperateResult result = new OperateResult();
                result.Message = read.Message;
                return  result;
            }
            count_receive += read.Content1;
            // 开始写入文件流
            OperateResult write = WriteStream( stream, read.Content2 );
            if (!write.IsSuccess)
            {
                OperateResult result = new OperateResult();
                result.Message = write.Message;
                return  result;
            }
            // 报告进度
            if (reportByPercent)
            {
                long percentCurrent = count_receive * 100 / totalLength;
                if (percent != percentCurrent)
                {
                    percent = percentCurrent;
                    if(report!=null) report.Action( count_receive, totalLength );
                }
            }
            else
            {
                if(report!=null) report.Action( count_receive, totalLength );
            }
        }
        return OperateResult.CreateSuccessResult( );
    }
    /**
     * 返回表示当前对象的字符串
     * @return
     */
    @Override
    public String toString()
    {
        return "NetworkXBase";
    }
}
src/main/java/com/zy/common/HslCommunication/Core/Net/StateOne/AlienSession.java
File was renamed from src/main/java/com/zy/gateway/core/net/session/AlienSession.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.net.session;
package com.zy.common.HslCommunication.Core.Net.StateOne;
import java.net.Socket;
src/main/java/com/zy/common/HslCommunication/Core/Net/StateOne/AppSession.java
File was renamed from src/main/java/com/zy/gateway/core/net/session/AppSession.java
@@ -1,7 +1,7 @@
package com.zy.gateway.core.net.session;
package com.zy.common.HslCommunication.Core.Net.StateOne;
import com.zy.gateway.core.base.SoftBasic;
import com.zy.gateway.core.net.HslProtocol;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.Net.HslProtocol;
import java.net.InetAddress;
import java.net.Socket;
src/main/java/com/zy/common/HslCommunication/Core/Security/HslSecurity.java
File was renamed from src/main/java/com/zy/gateway/core/base/HslSecurity.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.base;
package com.zy.common.HslCommunication.Core.Security;
public class HslSecurity {
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ByteTransformBase.java
File was renamed from src/main/java/com/zy/gateway/core/transfer/ByteTransformBase.java
@@ -1,6 +1,6 @@
package com.zy.gateway.core.transfer;
package com.zy.common.HslCommunication.Core.Transfer;
import com.zy.gateway.core.utils.Utilities;
import com.zy.common.HslCommunication.Utilities;
/**
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ByteTransformHelper.java
File was renamed from src/main/java/com/zy/gateway/core/transfer/ByteTransformHelper.java
@@ -1,8 +1,8 @@
package com.zy.gateway.core.transfer;
package com.zy.common.HslCommunication.Core.Transfer;
import com.zy.gateway.core.base.SoftBasic;
import com.zy.gateway.core.domain.FunctionOperateExOne;
import com.zy.gateway.core.domain.OperateResultExOne;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.Types.FunctionOperateExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
public class ByteTransformHelper {
@@ -13,7 +13,7 @@
     * @param <TResult> 结果类型
     * @return 最新的结果对象
     */
    public static <TResult> OperateResultExOne<TResult> GetResultFromBytes(OperateResultExOne<byte[]> result, FunctionOperateExOne<byte[], TResult> translator )
    public static <TResult> OperateResultExOne<TResult> GetResultFromBytes( OperateResultExOne<byte[]> result, FunctionOperateExOne<byte[], TResult> translator )
    {
        OperateResultExOne<TResult> tmp = new OperateResultExOne<TResult>( );
        try
src/main/java/com/zy/common/HslCommunication/Core/Transfer/DataFormat.java
File was renamed from src/main/java/com/zy/gateway/core/transfer/DataFormat.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.transfer;
package com.zy.common.HslCommunication.Core.Transfer;
/**
 * 应用于多字节数据的解析或是生成格式
src/main/java/com/zy/common/HslCommunication/Core/Transfer/IByteTransform.java
File was renamed from src/main/java/com/zy/gateway/core/transfer/IByteTransform.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.transfer;
package com.zy.common.HslCommunication.Core.Transfer;
public interface IByteTransform {
@@ -10,7 +10,7 @@
     * @param index 索引位置
     * @return boolean值
     */
    boolean TransBool(byte[] buffer, int index);
    boolean TransBool( byte[] buffer, int index );
    /**
     * 缓存中提取byte结果
@@ -18,7 +18,7 @@
     * @param index 索引位置
     * @return byte对象
     */
    byte TransByte(byte[] buffer, int index);
    byte TransByte( byte[] buffer, int index );
    /**
     * 从缓存中提取byte数组结果
@@ -27,7 +27,7 @@
     * @param length 读取的数组长度
     * @return
     */
    byte[] TransByte(byte[] buffer, int index, int length);
    byte[] TransByte( byte[] buffer, int index, int length );
    /**
     * 从缓存中提取short结果
@@ -35,7 +35,7 @@
     * @param index 索引位置
     * @return short对象
     */
    short TransInt16(byte[] buffer, int index);
    short TransInt16( byte[] buffer, int index );
    /**
     * 从缓存中提取short结果
@@ -44,7 +44,7 @@
     * @param length 读取的数组长度
     * @return short数组对象
     */
    short[] TransInt16(byte[] buffer, int index, int length);
    short[] TransInt16( byte[] buffer, int index, int length );
    /**
     * 从缓存中提取int结果
@@ -52,7 +52,7 @@
     * @param index 索引位置
     * @return int对象
     */
    int TransInt32(byte[] buffer, int index);
    int TransInt32( byte[] buffer, int index );
    /**
@@ -62,7 +62,7 @@
     * @param length 读取的数组长度
     * @return int数组对象
     */
    int[] TransInt32(byte[] buffer, int index, int length);
    int[] TransInt32( byte[] buffer, int index, int length );
    /**
@@ -71,7 +71,7 @@
     * @param index 索引位置
     * @return long对象
     */
    long TransInt64(byte[] buffer, int index);
    long TransInt64( byte[] buffer, int index );
    /**
@@ -81,7 +81,7 @@
     * @param length 读取的数组长度
     * @return long数组对象
     */
    long[] TransInt64(byte[] buffer, int index, int length);
    long[] TransInt64( byte[] buffer, int index, int length );
    /**
@@ -90,7 +90,7 @@
     * @param index 索引位置
     * @return float对象
     */
    float TransSingle(byte[] buffer, int index);
    float TransSingle( byte[] buffer, int index );
    /**
@@ -100,7 +100,7 @@
     * @param length 读取的数组长度
     * @return float数组对象
     */
    float[] TransSingle(byte[] buffer, int index, int length);
    float[] TransSingle( byte[] buffer, int index, int length );
    /**
@@ -109,7 +109,7 @@
     * @param index 索引位置
     * @return double对象
     */
    double TransDouble(byte[] buffer, int index);
    double TransDouble( byte[] buffer, int index );
    /**
@@ -119,7 +119,7 @@
     * @param length 读取的数组长度
     * @return double数组
     */
    double[] TransDouble(byte[] buffer, int index, int length);
    double[] TransDouble( byte[] buffer, int index, int length );
    /**
@@ -130,7 +130,7 @@
     * @param encoding 字符串的编码
     * @return string对象
     */
    String TransString(byte[] buffer, int index, int length, String encoding);
    String TransString( byte[] buffer, int index, int length, String encoding );
@@ -147,7 +147,7 @@
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(boolean value);
    byte[] TransByte( boolean value );
    /**
@@ -155,7 +155,7 @@
     * @param values 等待转化的数组
     * @return buffer数据
     */
    byte[] TransByte(boolean[] values);
    byte[] TransByte( boolean[] values );
    /**
@@ -163,21 +163,21 @@
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(byte value);
    byte[] TransByte( byte value );
    /**
     * short变量转化缓存数据
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(short value);
    byte[] TransByte( short value );
    /**
     * short数组变量转化缓存数据
     * @param values 等待转化的数组
     * @return buffer数据
     */
    byte[] TransByte(short[] values);
    byte[] TransByte( short[] values );
    /**
@@ -185,7 +185,7 @@
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(int value);
    byte[] TransByte( int value );
    /**
@@ -193,14 +193,14 @@
     * @param values 等待转化的数组
     * @return buffer数据
     */
    byte[] TransByte(int[] values);
    byte[] TransByte( int[] values );
    /**
     * long变量转化缓存数据
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(long value);
    byte[] TransByte( long value );
    /**
@@ -208,7 +208,7 @@
     * @param values 等待转化的数组
     * @return v
     */
    byte[] TransByte(long[] values);
    byte[] TransByte( long[] values );
    /**
@@ -216,7 +216,7 @@
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(float value);
    byte[] TransByte( float value );
    /**
@@ -224,7 +224,7 @@
     * @param values 等待转化的数组
     * @return buffer数据
     */
    byte[] TransByte(float[] values);
    byte[] TransByte( float[] values );
    /**
@@ -232,14 +232,14 @@
     * @param value 等待转化的数据
     * @return buffer数据
     */
    byte[] TransByte(double value);
    byte[] TransByte( double value );
    /**
     * double数组变量转化缓存数据
     * @param values 等待转化的数组
     * @return buffer数据
     */
    byte[] TransByte(double[] values);
    byte[] TransByte( double[] values );
    /**
     * 使用指定的编码字符串转化缓存数据
@@ -247,14 +247,14 @@
     * @param encoding 字符串的编码方式
     * @return buffer数据
     */
    byte[] TransByte(String value, String encoding);
    byte[] TransByte( String value, String encoding );
    /**
     * 设置数据解析的格式,ABCD,BADC,CDAB,DCBA格式
     * @param dataFormat
     */
    void setDataFormat(DataFormat dataFormat);
    void setDataFormat( DataFormat dataFormat );
    /**
     * 获取数据解析的格式,默认ABCD,可选BADC,CDAB,DCBA格式
src/main/java/com/zy/common/HslCommunication/Core/Transfer/RegularByteTransform.java
New file
@@ -0,0 +1,5 @@
package com.zy.common.HslCommunication.Core.Transfer;
public class RegularByteTransform extends ByteTransformBase
{
}
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ReverseBytesTransform.java
File was renamed from src/main/java/com/zy/gateway/core/transfer/ReverseBytesTransform.java
@@ -1,6 +1,6 @@
package com.zy.gateway.core.transfer;
package com.zy.common.HslCommunication.Core.Transfer;
import com.zy.gateway.core.utils.Utilities;
import com.zy.common.HslCommunication.Utilities;
/**
 * 反转的字节变换类
src/main/java/com/zy/common/HslCommunication/Core/Transfer/ReverseWordTransform.java
New file
@@ -0,0 +1,142 @@
package com.zy.common.HslCommunication.Core.Transfer;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Utilities;
/**
 * 以字节为单位的变换操作
 */
public class ReverseWordTransform extends ByteTransformBase
{
    /**
     * 实例化一个默认的对象
     */
    public  ReverseWordTransform(){
        this.setDataFormat(DataFormat.ABCD);
    }
    /**
     * 按照字节错位的方法
     * @param buffer 实际的字节数据
     * @param index 起始字节位置
     * @param length 数据长度
     * @return
     */
    private byte[] ReverseBytesByWord( byte[] buffer, int index, int length )
    {
        byte[] tmp = new byte[length];
        for (int i = 0; i < length; i++)
        {
            tmp[i] = buffer[index + i];
        }
        for (int i = 0; i < length / 2; i++)
        {
            byte b = tmp[i * 2 + 0];
            tmp[i * 2 + 0] = tmp[i * 2 + 1];
            tmp[i * 2 + 1] = b;
        }
        return tmp;
    }
    private byte[] ReverseBytesByWord( byte[] buffer )
    {
        return ReverseBytesByWord( buffer, 0, buffer.length );
    }
    /**
     * 字符串数据是否按照字来反转
     */
    public boolean IsStringReverse =false;
    /**
     * 从缓存中提取short结果
     * @param buffer 缓存数据
     * @param index 索引位置
     * @return short对象
     */
    @Override
    public short TransInt16( byte[] buffer, int index ) {
        return Utilities.getShort(ReverseBytesByWord(buffer, index, 2), 0);
    }
    /**
     * 从缓存中提取string结果,使用指定的编码
     * @param buffer 缓存对象
     * @param index 索引位置
     * @param length byte数组长度
     * @param encoding 字符串的编码
     * @return string对象
     */
    @Override
    public String TransString( byte[] buffer, int index, int length, String encoding ) {
        byte[] tmp = TransByte(buffer, index, length);
        if (IsStringReverse) {
            return Utilities.getString(ReverseBytesByWord(tmp), "ASCII");
        } else {
            return Utilities.getString(tmp, "ASCII");
        }
    }
    /**
     * bool数组变量转化缓存数据
     * @param values 等待转化的数组
     * @return buffer数据
     */
    @Override
    public byte[] TransByte( boolean[] values ) {
        return SoftBasic.BoolArrayToByte(values);
    }
    /**
     * short数组变量转化缓存数据
     * @param values 等待转化的数组
     * @return buffer数据
     */
    @Override
    public byte[] TransByte( short[] values ) {
        if (values == null) return null;
        byte[] buffer = new byte[values.length * 2];
        for (int i = 0; i < values.length; i++) {
            byte[] tmp = Utilities.getBytes(values[i]);
            System.arraycopy(tmp, 0, buffer, 2 * i, tmp.length);
        }
        return ReverseBytesByWord(buffer);
    }
    /**
     * 使用指定的编码字符串转化缓存数据
     * @param value 等待转化的数据
     * @param encoding 字符串的编码方式
     * @return buffer数据
     */
    @Override
    public byte[] TransByte( String value, String encoding ) {
        if (value == null) return null;
        byte[] buffer = Utilities.getBytes(value, encoding);
        buffer = SoftBasic.ArrayExpandToLengthEven(buffer);
        if (IsStringReverse) {
            return ReverseBytesByWord(buffer);
        } else {
            return buffer;
        }
    }
}
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperate.java
File was renamed from src/main/java/com/zy/gateway/core/domain/ActionOperate.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 空操作的类
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperateExOne.java
File was renamed from src/main/java/com/zy/gateway/core/domain/ActionOperateExOne.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 带一个参数对象的操作类
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperateExThree.java
File was renamed from src/main/java/com/zy/gateway/core/domain/ActionOperateExThree.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 带三个参数的类型对象
src/main/java/com/zy/common/HslCommunication/Core/Types/ActionOperateExTwo.java
File was renamed from src/main/java/com/zy/gateway/core/domain/ActionOperateExTwo.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 带二个参数对象的操作类
src/main/java/com/zy/common/HslCommunication/Core/Types/FunctionOperate.java
File was renamed from src/main/java/com/zy/gateway/core/domain/FunctionOperate.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
public class FunctionOperate<R>
{
src/main/java/com/zy/common/HslCommunication/Core/Types/FunctionOperateExOne.java
File was renamed from src/main/java/com/zy/gateway/core/domain/FunctionOperateExOne.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
public class FunctionOperateExOne<T,R>
{
src/main/java/com/zy/common/HslCommunication/Core/Types/HslTimeOut.java
File was renamed from src/main/java/com/zy/gateway/core/domain/HslTimeOut.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
import java.net.Socket;
import java.util.Date;
src/main/java/com/zy/common/HslCommunication/Core/Types/IDataTransfer.java
File was renamed from src/main/java/com/zy/gateway/core/domain/IDataTransfer.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 用于PLC通讯及Modbus自定义数据类型的读写操作
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResult.java
File was renamed from src/main/java/com/zy/gateway/core/domain/OperateResult.java
@@ -1,6 +1,6 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
import com.zy.gateway.core.StringResources;
import com.zy.common.HslCommunication.StringResources;
/**
 * 一个结果操作类的基类
@@ -28,7 +28,7 @@
     * @param err 错误码
     * @param msg 错误消息
     */
    public OperateResult(int err, String msg){
    public OperateResult(int err,String msg){
        this.ErrorCode = err;
        this.Message = msg;
    }
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExFour.java
File was renamed from src/main/java/com/zy/gateway/core/domain/OperateResultExFour.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 带三个参数的泛型类对象
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExOne.java
File was renamed from src/main/java/com/zy/gateway/core/domain/OperateResultExOne.java
@@ -1,10 +1,12 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 带一个参数的结果类对象
 * @param <T>
 */
public class OperateResultExOne<T> extends  OperateResult {
public class OperateResultExOne<T> extends  OperateResult
{
    /**
     * 默认的无参构造方法
@@ -26,7 +28,7 @@
     * @param err 错误码
     * @param msg 错误消息
     */
    public OperateResultExOne(int err, String msg){
    public OperateResultExOne(int err,String msg){
        super(err,msg);
    }
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExThree.java
File was renamed from src/main/java/com/zy/gateway/core/domain/OperateResultExThree.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
src/main/java/com/zy/common/HslCommunication/Core/Types/OperateResultExTwo.java
File was renamed from src/main/java/com/zy/gateway/core/domain/OperateResultExTwo.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain;
package com.zy.common.HslCommunication.Core.Types;
/**
 * 带2个参数的结果类
src/main/java/com/zy/common/HslCommunication/Enthernet/ComplexNet/NetComplexClient.java
New file
@@ -0,0 +1,472 @@
package com.zy.common.HslCommunication.Enthernet.ComplexNet;
import com.zy.common.HslCommunication.Core.Net.HslProtocol;
import com.zy.common.HslCommunication.Core.Net.NetHandle;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkXBase;
import com.zy.common.HslCommunication.Core.Net.StateOne.AppSession;
import com.zy.common.HslCommunication.Core.Types.*;
import com.zy.common.HslCommunication.Utilities;
import java.net.Socket;
import java.util.Date;
/**
 * 一个基于异步高性能的客户端网络类,支持主动接收服务器的消息
 */
public class NetComplexClient extends NetworkXBase {
    /**
     * 实例化一个对象
     */
    public NetComplexClient() {
        session = new AppSession();
        ServerTime = new Date();
    }
    private AppSession session;                  // 客户端的核心连接对象
    private int isConnecting = 0;                // 指示客户端是否处于连接服务器中,0代表未连接,1代表连接中
    private boolean IsQuie = false;              // 指示系统是否准备退出
    private Thread thread_heart_check = null;   // 心跳线程
    private String ipAddress = "";               // Ip地址
    private int port = 1000;                     // 端口号
    private boolean IsClientStart = false;         // 客户端是否启动
    private int ConnectFailedCount = 0;            // 失败重连次数
    private String ClientAlias = "";             // 客户端的别名
    private Date ServerTime = new Date();        // 服务器的时间,暂时不支持使用
    private int DelayTime = 0;                   // 获取延迟的时间
    /**
     * 获取IP地址
     *
     * @return Ip地址
     */
    public String getIpAddress() {
        return ipAddress;
    }
    /**
     * 设置Ip地址
     *
     * @param ipAddress Ip地址
     */
    public void setIpAddress(String ipAddress) {
        this.ipAddress = ipAddress;
    }
    /**
     * 获取端口号
     *
     * @return 端口号
     */
    public int getPort() {
        return port;
    }
    /**
     * 设置端口号
     *
     * @param port
     */
    public void setPort(int port) {
        this.port = port;
    }
    /**
     * 获取客户端是否启动
     *
     * @return boolean值
     */
    public boolean getIsClientStart() {
        return IsClientStart;
    }
    /**
     * 设置客户端是否启动
     *
     * @param clientStart 客户端是否启动
     */
    public void setClientStart(boolean clientStart) {
        IsClientStart = clientStart;
    }
    /**
     * 获取失败重连次数
     *
     * @return
     */
    public int getConnectFailedCount() {
        return ConnectFailedCount;
    }
    /**
     * 获取客户端的登录标识名
     *
     * @return 字符串信息
     */
    public String getClientAlias() {
        return ClientAlias;
    }
    /**
     * 设置客户端的登录标识名
     *
     * @param clientAlias
     */
    public void setClientAlias(String clientAlias) {
        ClientAlias = clientAlias;
    }
    /**
     * 获取服务器的时间
     * @return
     */
//    public Date getServerTime() {
//        return ServerTime;
//    }
    /**
     * 获取信息延迟的时间
     *
     * @return
     */
    public int getDelayTime() {
        return DelayTime;
    }
    /**
     * 客户端启动成功的事件,重连成功也将触发此事件,参数没有意义
     */
    public ActionOperate LoginSuccess;
    /**
     * 连接失败时触发的事件,参数为连接失败的次数
     */
    public ActionOperateExOne<Integer> LoginFailed;
    /**
     * 服务器的异常,启动,等等一般消息产生的时候,出发此事件
     */
    public ActionOperateExOne<String> MessageAlerts;
    /**
     * 在客户端断开后并在重连服务器之前触发,用于清理系统资源,参数无意义
     */
    public ActionOperate BeforReConnected;
    /**
     * 当接收到文本数据的时候,触发此事件
     */
    public ActionOperateExThree<NetComplexClient, NetHandle, String> AcceptString;
    /**
     * 当接收到字节数据的时候,触发此事件
     */
    public ActionOperateExThree<NetComplexClient, NetHandle, byte[]> AcceptByte;
    /**
     * 关闭该客户端引擎
     */
    public void ClientClose() {
        IsQuie = true;
        if (IsClientStart)
            SendBytes(session, HslProtocol.CommandBytes(HslProtocol.ProtocolClientQuit, 0, Token, null));
        IsClientStart = false;          // 关闭客户端
        thread_heart_check = null;
        LoginSuccess = null;            // 清空所有的事件
        LoginFailed = null;
        MessageAlerts = null;
        AcceptByte = null;
        AcceptString = null;
        try {
            session.getWorkSocket().close();
        } catch (Exception ex) {
        }
        if (LogNet != null) LogNet.WriteDebug(toString(), "Client Close.");
    }
    /**
     * 启动客户端引擎,连接服务器系统
     */
    public void ClientStart() {
        // 如果处于连接中就退出
        if (isConnecting != 0) return;
        isConnecting = 1;
        // 启动后台线程连接
        new Thread(){
            @Override
            public void run() {
                ThreadLogin();
            }
        }.start();
        // 启动心跳线程,在第一次Start的时候
        if (thread_heart_check == null) {
            thread_heart_check = new Thread(){
                @Override
                public void run() {
                    ThreadHeartCheck();
                }
            };
            thread_heart_check.start();
        }
    }
    /**
     * 连接服务器之前的消息提示,如果是重连的话,就提示10秒等待信息
     */
    private void AwaitToConnect() {
        if (ConnectFailedCount == 0) {
            // English Version : Connecting Server...
            if (MessageAlerts != null) MessageAlerts.Action("正在连接服务器...");
        } else {
            int count = 10;
            while (count > 0) {
                if (IsQuie) return;
                count--;
                // English Version : Disconnected, wait [count] second to restart
                if (MessageAlerts != null) MessageAlerts.Action("连接断开,等待" + count + "秒后重新连接");
                try {
                    Thread.sleep(1000);
                } catch (Exception ex) {
                }
            }
            if (MessageAlerts != null) MessageAlerts.Action("正在尝试第" + ConnectFailedCount + "次连接服务器...");
        }
    }
    private void ConnectFailed() {
        ConnectFailedCount++;
        isConnecting = 0;
        if (LoginFailed != null) LoginFailed.Action(ConnectFailedCount);
        if (LogNet != null) LogNet.WriteDebug(toString(), "Connected Failed, Times: " + ConnectFailedCount);
    }
    private OperateResultExOne<Socket> ConnectServer() {
        OperateResultExOne<Socket> connectResult = CreateSocketAndConnect(ipAddress, port, 10000);
        if (!connectResult.IsSuccess) {
            return connectResult;
        }
        // 连接成功,发送数据信息
        OperateResult sendResult = SendStringAndCheckReceive(connectResult.Content, 2, ClientAlias);
        if (!sendResult.IsSuccess) {
            return OperateResultExOne.<Socket>CreateFailedResult(sendResult);
        }
        if (MessageAlerts != null) MessageAlerts.Action("连接服务器成功!");
        return connectResult;
    }
    private void LoginSuccessMethod(Socket socket) {
        ConnectFailedCount = 0;
        try {
            session.setIpEndPoint(socket.getInetAddress());
            session.setLoginAlias(ClientAlias);
            session.setWorkSocket(socket);
            session.setHeartTime(new Date());
            IsClientStart = true;
            BeginReceiveBackground(session);
        } catch (Exception ex) {
            if (LogNet != null) LogNet.WriteException(toString(), ex);
        }
    }
    private void ThreadLogin() {
        // 连接的消息等待
        AwaitToConnect();
        OperateResultExOne<Socket> connectResult = ConnectServer();
        if (!connectResult.IsSuccess) {
            ConnectFailed();
            // 连接失败,重新连接服务器
            new Thread(){
                @Override
                public void run() {
                    ReconnectServer(null);
                }
            }.start();
            return;
        }
        // 登录成功
        LoginSuccessMethod(connectResult.Content);
        // 登录成功
        if (LoginSuccess != null) LoginSuccess.Action();
        isConnecting = 0;
        try {
            Thread.sleep(200);
        } catch (Exception ex) {
        }
    }
    private void ReconnectServer(Object obj) {
        // 是否连接服务器中,已经在连接的话,则不再连接
        if (isConnecting == 1) return;
        // 是否退出了系统,退出则不再重连
        if (IsQuie) return;
        // 触发连接失败,重连系统前错误
        if (BeforReConnected != null) BeforReConnected.Action();
        if (session != null) {
            CloseSocket(session.getWorkSocket());
        }
        // 重新启动客户端
        ClientStart();
    }
    /**
     * 通信出错后的处理
     *
     * @param receive 通信方法
     */
    @Override
    protected void SocketReceiveException(AppSession receive) {
        if (LogNet != null) LogNet.WriteDebug(toString(), "Socket Excepiton Occured.");
        // 异常掉线
        ReconnectServer(null);
    }
    /**
     * 服务器端用于数据发送文本的方法
     *
     * @param customer 用户自定义的命令头
     * @param str      发送的文本
     */
    public void Send(NetHandle customer, String str) {
        if (IsClientStart) {
            SendBytes(session, HslProtocol.CommandBytes(customer.get_CodeValue(), Token, str));
        }
    }
    /**
     * 服务器端用于发送字节的方法
     *
     * @param customer 用户自定义的命令头
     * @param bytes    实际发送的数据
     */
    public void Send(NetHandle customer, byte[] bytes) {
        if (IsClientStart) {
            SendBytes(session, HslProtocol.CommandBytes(customer.get_CodeValue(), Token, bytes));
        }
    }
    private void SendBytes(AppSession stateone, byte[] content) {
        super.Send(stateone.getWorkSocket(), content);
    }
    /**
     * 客户端的数据处理中心
     *
     * @param session  连接状态
     * @param protocol 协议头
     * @param customer 用户自定义
     * @param content  数据内容
     */
    @Override
    protected void DataProcessingCenter(AppSession session, int protocol, int customer, byte[] content) {
        if (protocol == HslProtocol.ProtocolCheckSecends) {
            Date dt = new Date(Utilities.getLong(content, 0));
            ServerTime = new Date(Utilities.getLong(content, 8));
            DelayTime = (int) (new Date().getTime() - dt.getTime());
            this.session.setHeartTime(new Date());
            // MessageAlerts?.Invoke("心跳时间:" + DateTime.Now.ToString());
        } else if (protocol == HslProtocol.ProtocolClientQuit) {
            // 申请了退出
        } else if (protocol == HslProtocol.ProtocolUserBytes) {
            // 接收到字节数据
            if (AcceptByte != null) AcceptByte.Action(this, new NetHandle(customer), content);
        } else if (protocol == HslProtocol.ProtocolUserString) {
            // 接收到文本数据
            String str = Utilities.byte2String(content);
            if (AcceptString != null) AcceptString.Action(this, new NetHandle(customer), str);
        }
    }
    /**
     * 心跳线程的方法
     */
    private void ThreadHeartCheck() {
        try {
            Thread.sleep(2000);
        } catch (Exception ex) {
        }
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (Exception ex) {
            }
            if (!IsQuie) {
                byte[] send = new byte[16];
                byte[] buffer = Utilities.getBytes(new Date().getTime());
                System.arraycopy(buffer, 0, send, 0, buffer.length);
                try {
                    SendBytes(session, HslProtocol.CommandBytes(HslProtocol.ProtocolCheckSecends, 0, Token, send));
                    double timeSpan = (new Date().getTime() - session.getHeartTime().getTime()) / 1000;
                    if (timeSpan > 1 * 8)//8次没有收到失去联系
                    {
                        if (isConnecting == 0) {
                            if (LogNet != null)
                                LogNet.WriteDebug(toString(), "Heart Check Failed int " + timeSpan + " Seconds.");
                            new Thread(){
                                @Override
                                public void run() {
                                    ReconnectServer(null);
                                }
                            }.start();
                        }
                        if (!IsQuie) {
                            try {
                                Thread.sleep(1000);
                            } catch (Exception ex) {
                            }
                        }
                    }
                } catch (Exception ex) {
                    System.out.println(ex.getStackTrace());
                }
            } else {
                break;
            }
        }
    }
    /**
     * 返回对象的字符串表示形式
     *
     * @return 字符串
     */
    @Override
    public String toString() {
        return "NetComplexClient";
    }
}
src/main/java/com/zy/common/HslCommunication/Enthernet/FileNet/FileBaseInfo.java
New file
@@ -0,0 +1,73 @@
package com.zy.common.HslCommunication.Enthernet.FileNet;
public class FileBaseInfo {
    /**
     * 获取文件的名称
     * @return
     */
    public String getName() {
        return Name;
    }
    /**
     * 设置文件的名称
     * @param name
     */
    public void setName(String name) {
        Name = name;
    }
    /**
     * 获取文件的大小
     * @return
     */
    public long getSize() {
        return Size;
    }
    /**
     * 设置文件的大小
     * @param size
     */
    public void setSize(long size) {
        Size = size;
    }
    /**
     * 获取文件的标识,注释
     * @return
     */
    public String getTag() {
        return Tag;
    }
    /**
     * 设置文件的标识,注释
     * @param tag
     */
    public void setTag(String tag) {
        Tag = tag;
    }
    /**
     * 获取文件的上传人
     * @return
     */
    public String getUpload() {
        return Upload;
    }
    /**
     * 设置文件的上传人
     * @param upload
     */
    public void setUpload(String upload) {
        Upload = upload;
    }
    private String Name ;     // 文件名称
    private long Size;        // 文件大小
    private String Tag;       // 文件的标识,注释
    private String Upload;    // 文件上传人
}
src/main/java/com/zy/common/HslCommunication/Enthernet/PushNet/NetPushClient.java
New file
@@ -0,0 +1,143 @@
package com.zy.common.HslCommunication.Enthernet.PushNet;
import com.zy.common.HslCommunication.Core.Net.HslProtocol;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkXBase;
import com.zy.common.HslCommunication.Core.Net.StateOne.AppSession;
import com.zy.common.HslCommunication.Core.Types.ActionOperateExTwo;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.Utilities;
import java.net.Socket;
public class NetPushClient extends NetworkXBase
{
    /**
     * 实例化一个发布订阅类的客户端,需要指定ip地址,端口,及订阅关键字
     * @param ipAddress 服务器的IP地址
     * @param port 服务器的端口号
     * @param key 订阅关键字
     */
    public NetPushClient( String ipAddress, int port, String key )
    {
        this.ipAddress = ipAddress;
        this.port = port;
        keyWord = key;
        if (key == null || key.isEmpty())
        {
            throw new RuntimeException( "key 不允许为空" );
        }
    }
    @Override
    protected void DataProcessingCenter(AppSession session, int protocol, int customer, byte[] content ) {
        if (protocol == HslProtocol.ProtocolUserString) {
            if (action != null) action.Action(this, Utilities.byte2String(content));
        }
    }
    @Override
    protected void SocketReceiveException( AppSession session) {
        // 发生异常的时候需要进行重新连接
        while (true) {
            System.out.print("10 秒钟后尝试重连服务器");
            try {
                Thread.sleep(10000);
            }catch (Exception ex){
            }
            if (CreatePush().IsSuccess) {
                System.out.print("重连服务器成功");
                break;
            }
        }
    }
    private OperateResult CreatePush( )
    {
        CloseSocket(CoreSocket);
        OperateResultExOne<Socket> connect = CreateSocketAndConnect( ipAddress,port, 5000 );
        if (!connect.IsSuccess) return connect;
        OperateResult send = SendStringAndCheckReceive( connect.Content, 0, keyWord );
        if (!send.IsSuccess) return send;
        OperateResultExTwo<Integer, String> receive = ReceiveStringContentFromSocket( connect.Content );
        if (!receive.IsSuccess) return receive;
        if (receive.Content1 != 0)
        {
            OperateResult result = new OperateResult();
            result.Message = receive.Content2;
            return result;
        }
        AppSession appSession = new AppSession( );
        CoreSocket = connect.Content;
        appSession.setWorkSocket(connect.Content);
        BeginReceiveBackground( appSession );
        return OperateResult.CreateSuccessResult( );
    }
    /**
     * 创建数据推送服务
     * @param pushCallBack 触发数据推送的委托
     * @return 是否成功
     */
    public OperateResult CreatePush( ActionOperateExTwo<NetPushClient,String> pushCallBack )
    {
        action = pushCallBack;
        return CreatePush( );
    }
    /**
     * 关闭消息推送的界面
     */
    public void ClosePush()
    {
        action = null;
        if (CoreSocket != null && CoreSocket.isConnected()){
            Send(CoreSocket,Utilities.getBytes( 100 ) );
        }
        CloseSocket(CoreSocket);
    }
    /**
     * 本客户端的关键字
     * @return
     */
    public String getKeyWord(){
        return keyWord;
    }
    private String ipAddress = "";                                 // IP地址
    private int port = 1000;                                       // 端口号
    private String keyWord = "";                                   // 缓存的订阅关键字
    private ActionOperateExTwo<NetPushClient,String> action;       // 服务器推送后的回调方法
    /**
     * 获取本对象的字符串表示形式
     * @return 字符串
     */
    @Override
    public String toString() {
        return "NetPushClient";
    }
}
src/main/java/com/zy/common/HslCommunication/Enthernet/SimplifyNet/NetSimplifyClient.java
New file
@@ -0,0 +1,130 @@
package com.zy.common.HslCommunication.Enthernet.SimplifyNet;
import com.zy.common.HslCommunication.Core.IMessage.HslMessage;
import com.zy.common.HslCommunication.Core.Net.HslProtocol;
import com.zy.common.HslCommunication.Core.Net.NetHandle;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDoubleBase;
import com.zy.common.HslCommunication.Core.Transfer.RegularByteTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Utilities;
import java.util.UUID;
/**
 * 同步访问的网络客户端
 */
public class NetSimplifyClient extends NetworkDoubleBase<HslMessage,RegularByteTransform>
{
    /**
     * 实例化一个客户端的对象,用于和服务器通信
     * @param ipAddress Ip地址
     * @param port 端口号
     */
    public NetSimplifyClient(String ipAddress, int port)
    {
        this.setIpAddress(ipAddress);
        this.setPort( port);
    }
    /**
     * 实例化一个客户端的对象,用于和服务器通信
     * @param ipAddress Ip地址
     * @param port 端口号
     * @param token 令牌
     */
    public NetSimplifyClient(String ipAddress, int port, UUID token)
    {
        this.setIpAddress(ipAddress);
        this.setPort( port);
        this.Token = token;
    }
    /**
     * 实例化一个客户端对象,需要手动指定Ip地址和端口
     */
    public NetSimplifyClient()
    {
    }
    /**
     * 客户端向服务器进行请求,请求字符串数据
     * @param customer 用户的指令头
     * @param send 发送数据
     * @return 带结果说明的对象
     */
    public OperateResultExOne<String> ReadFromServer(NetHandle customer, String send) {
        OperateResultExOne<String> result = new OperateResultExOne<String>();
        byte[] data = send.isEmpty() ? new byte[0] : Utilities.string2Byte(send);
        OperateResultExOne<byte[]> temp = ReadFromServerBase(HslProtocol.ProtocolUserString, customer.get_CodeValue(), data);
        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;
    }
    /**
     * 客户端向服务器进行请求,请求字节数据
     * @param customer 用户的指令头
     * @param send 发送的字节内容
     * @return 带结果说明的对象
     */
    public OperateResultExOne<byte[]> ReadFromServer(NetHandle customer, byte[] send) {
        return ReadFromServerBase(HslProtocol.ProtocolUserBytes, customer.get_CodeValue(), send);
    }
    /**
     * 需要发送的底层数据
     * @param headCode 数据的指令头
     * @param customer 需要发送的底层数据
     * @param send 需要发送的底层数据
     * @return 带结果说明的对象
     */
    private OperateResultExOne<byte[]> ReadFromServerBase(int headCode, int customer, byte[] send) {
        OperateResultExOne<byte[]> read = ReadFromCoreServer(HslProtocol.CommandBytes(headCode, customer, Token, send));
        if (!read.IsSuccess) {
            return read;
        }
        if(read.Content.length < HslProtocol.HeadByteLength){
            read.IsSuccess = false;
            read.Message = "length is not correct :" +read.Content.length;
            return read;
        }
        byte[] headBytes = new byte[HslProtocol.HeadByteLength];
        byte[] contentBytes = new byte[read.Content.length - HslProtocol.HeadByteLength];
        System.arraycopy(read.Content,0,headBytes,0,HslProtocol.HeadByteLength);
        if (contentBytes.length > 0) {
            System.arraycopy(read.Content, HslProtocol.HeadByteLength, contentBytes, 0, read.Content.length - HslProtocol.HeadByteLength);
        }
        contentBytes = HslProtocol.CommandAnalysis(headBytes, contentBytes);
        return OperateResultExOne.CreateSuccessResult(contentBytes);
    }
    /**
     * 获取本对象的字符串表示形式
     * @return 字符串信息
     */
    @Override
    public String toString() {
        return "NetSimplifyClient";
    }
}
src/main/java/com/zy/common/HslCommunication/Language/DefaultLanguage.java
File was renamed from src/main/java/com/zy/gateway/core/language/DefaultLanguage.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.language;
package com.zy.common.HslCommunication.Language;
/**
 * 系统的语言基类,默认也即是中文版本
src/main/java/com/zy/common/HslCommunication/Language/English.java
File was renamed from src/main/java/com/zy/gateway/core/language/English.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.language;
package com.zy.common.HslCommunication.Language;
/**
 * English Version Text
src/main/java/com/zy/common/HslCommunication/LogNet/Core/GenerateMode.java
New file
@@ -0,0 +1,32 @@
package com.zy.common.HslCommunication.LogNet.Core;
/**
 * 日志文件输出模式
 */
public enum GenerateMode {
    /**
     * 按每个小时生成日志文件
     */
    ByEveryHour,
    /**
     * 按每天生成日志文件
     */
    ByEveryDay,
    /**
     * 按每个周生成日志文件
     */
    ByEveryWeek,
    /**
     * 按每个月生成日志文件
     */
    ByEveryMonth,
    /**
     * 按每季度生成日志文件
     */
    ByEverySeason ,
    /**
     * 按每年生成日志文件
     */
    ByEveryYear,
}
src/main/java/com/zy/common/HslCommunication/LogNet/Core/HslMessageDegree.java
File was renamed from src/main/java/com/zy/gateway/core/log/HslMessageDegree.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.log;
package com.zy.common.HslCommunication.LogNet.Core;
/**
 * 日志的存储等级
src/main/java/com/zy/common/HslCommunication/LogNet/Core/HslMessageItem.java
New file
@@ -0,0 +1,147 @@
package com.zy.common.HslCommunication.LogNet.Core;
import com.zy.common.HslCommunication.Utilities;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * 单个日志的记录信息
 */
public class HslMessageItem {
    private AtomicInteger IdNumber = new AtomicInteger();
    private long id =0;
    private HslMessageDegree degree = HslMessageDegree.DEBUG;
    private int threadId = 0;
    private String text = "";
    private Date time = new Date();
    private String keyWord = "";
    /**
     * 默认的无参构造器
     */
    public HslMessageItem()
    {
        id = IdNumber.getAndIncrement();
    }
    /**
     * 单个记录信息的标识ID,程序重新运行时清空
     * @return long数据类型
     */
    public long getId() {
        return id;
    }
    /**
     * 获取消息的等级
     * @return 消息等级
     */
    public HslMessageDegree getDegree() {
        return degree;
    }
    /**
     * 设置消息的等级
     * @param degree 消息等级
     */
    public void setDegree(HslMessageDegree degree) {
        this.degree = degree;
    }
    /**
     * 获取线程的标识
     * @return 线程id
     */
    public int getThreadId() {
        return threadId;
    }
    /**
     * 设置线程的标识
     * @param threadId 线程id
     */
    public void setThreadId(int threadId) {
        this.threadId = threadId;
    }
    /**
     * 获取消息文本
     * @return string类型数据
     */
    public String getText() {
        return text;
    }
    /**
     * 设置消息文本
     * @param text 消息文本
     */
    public void setText(String text) {
        this.text = text;
    }
    /**
     * 获取当前的时间信息
     * @return 时间类型
     */
    public Date getTime() {
        return time;
    }
    /**
     * 设置当前的时间
     * @param time 时间
     */
    public void setTime(Date time) {
        this.time = time;
    }
    /**
     * 获取当前的关键字
     * @return string类型的关键字
     */
    public String getKeyWord() {
        return keyWord;
    }
    /**
     * 设置当前的关键字
     * @param keyWord 关键字
     */
    public void setKeyWord(String keyWord) {
        this.keyWord = keyWord;
    }
    /**
     * 返回表示当前对象的字符串
     * @return 字符串信息
     */
    @Override
    public String toString( )
    {
        if (keyWord == null || keyWord.length() == 0)
        {
            return "["+degree.toString()+"] "+ Utilities.getStringDateShort(time,"yyyy-MM-dd HH:mm:ss.fff") + " Thread["+String.format("D2",threadId)+"] "+text;
        }
        else
        {
            return "["+degree.toString()+"] "+ Utilities.getStringDateShort(time,"yyyy-MM-dd HH:mm:ss.fff") + " Thread["+String.format("D2",threadId)+"] " + keyWord +" : "+text;
        }
    }
    /**
     * 返回表示当前对象的字符串,剔除了关键字
     * @return 字符串数据
     */
    public String ToStringWithoutKeyword()
    {
        return "["+degree.toString()+"] "+ Utilities.getStringDateShort(time,"yyyy-MM-dd HH:mm:ss.fff") + " Thread["+String.format("D2",threadId)+"] "+text;
    }
}
src/main/java/com/zy/common/HslCommunication/LogNet/Core/ILogNet.java
File was renamed from src/main/java/com/zy/gateway/core/log/ILogNet.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.log;
package com.zy.common.HslCommunication.LogNet.Core;
/**
 * 日志的存储对象
@@ -135,7 +135,7 @@
     * 过滤掉指定的关键字的日志,该信息不存储,但仍然触发BeforeSaveToFile事件
     * @param keyword
     */
    void FiltrateKeyword(String keyword);
    void FiltrateKeyword( String keyword );
    /**
src/main/java/com/zy/common/HslCommunication/ModBus/ModbusAddress.java
New file
@@ -0,0 +1,277 @@
package com.zy.common.HslCommunication.ModBus;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.Address.DeviceAddressBase;
import com.zy.common.HslCommunication.Utilities;
/**
 * Modbus协议地址格式,可以携带站号,功能码,地址信息
 */
public class ModbusAddress extends DeviceAddressBase {
    /**
     * 实例化一个默认的对象
     */
    public ModbusAddress() {
        Station = -1;
        Function = ModbusInfo.ReadRegister;
        setAddress(0);
    }
    /**
     * 实例化一个默认的对象,使用默认的地址初始化
     * @param address
     */
    public ModbusAddress(String address) {
        Station = -1;
        Function = ModbusInfo.ReadRegister;
        setAddress(0);
        AnalysisAddress(address);
    }
    /**
     * 获取站号
     * @return
     */
    public int getStation() {
        return Station;
    }
    /**
     * 设置站号
     * @param station
     */
    public void setStation(int station) {
        Station = station;
    }
    /**
     * 获取功能码
     * @return
     */
    public byte getFunction() {
        return Function;
    }
    /**
     * 设置功能码
     * @param function
     */
    public void setFunction(byte function) {
        Function = function;
    }
    private int Station = -1;
    private byte Function = -1;
    /**
     * 解析Modbus的地址码
     * @param address 地址
     */
    @Override
    public void AnalysisAddress(String address) {
        if (address.indexOf(';') < 0) {
            // 正常地址,功能码03
            setAddress(Integer.parseInt(address));
        } else {
            // 带功能码的地址
            String[] list = address.split(";");
            for (int i = 0; i < list.length; i++) {
                if (list[i].charAt(0) == 's' || list[i].charAt(0) == 'S') {
                    // 站号信息
                    this.Station = Integer.parseInt(list[i].substring(2));
                } else if (list[i].charAt(0) == 'x' || list[i].charAt(0) == 'X') {
                    this.Function = (byte) Integer.parseInt(list[i].substring(2));
                } else {
                    setAddress(Integer.parseInt(list[i]));
                }
            }
        }
    }
    /**
     * 创建一个读取线圈的字节对象
     * @param station 读取的站号
     * @param length 读取数据的长度
     * @return 原始的modbus指令
     */
    public byte[] CreateReadCoils(byte station, int length) {
        byte[] buffer = new byte[6];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = ModbusInfo.ReadCoil;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = Utilities.getBytes(length)[1];
        buffer[5] = Utilities.getBytes(length)[0];
        return buffer;
    }
    /**
     * 创建一个读取离散输入的字节对象
     * @param station 读取的站号
     * @param length 读取数据的长度
     * @return 原始的modbus指令
     */
    public byte[] CreateReadDiscrete(byte station, int length) {
        byte[] buffer = new byte[6];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = ModbusInfo.ReadDiscrete;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = Utilities.getBytes(length)[1];
        buffer[5] = Utilities.getBytes(length)[0];
        return buffer;
    }
    /**
     * 创建一个读取寄存器的字节对象
     * @param station 读取的站号
     * @param length 读取数据的长度
     * @return 原始的modbus指令
     */
    public byte[] CreateReadRegister(byte station, int length) {
        byte[] buffer = new byte[6];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = Function;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = Utilities.getBytes(length)[1];
        buffer[5] = Utilities.getBytes(length)[0];
        return buffer;
    }
    /**
     * 创建一个写入单个线圈的指令
     * @param station 站号
     * @param value 值
     * @return 原始的modbus指令
     */
    public byte[] CreateWriteOneCoil(byte station, boolean value) {
        byte[] buffer = new byte[6];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = ModbusInfo.WriteOneCoil;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = (byte) (value ? 0xFF : 0x00);
        buffer[5] = 0x00;
        return buffer;
    }
    /**
     * 创建一个写入单个寄存器的指令
     * @param station 站号
     * @param data 值
     * @return 原始的modbus指令
     */
    public byte[] CreateWriteOneRegister(byte station, byte[] data) {
        byte[] buffer = new byte[6];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = ModbusInfo.WriteOneRegister;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = data[1];
        buffer[5] = data[0];
        return buffer;
    }
    /**
     * 创建一个写入批量线圈的指令
     * @param station 站号
     * @param values 值
     * @return 原始的modbus指令
     */
    public byte[] CreateWriteCoil(byte station, boolean[] values) {
        byte[] data = SoftBasic.BoolArrayToByte(values);
        byte[] buffer = new byte[7 + data.length];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = ModbusInfo.WriteCoil;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = (byte) (values.length / 256);
        buffer[5] = (byte) (values.length % 256);
        buffer[6] = (byte) (data.length);
        System.arraycopy(data, 0, buffer, 7, data.length);
        return buffer;
    }
    /**
     * 创建一个写入批量寄存器的指令
     * @param station 站号
     * @param values 值
     * @return 原始的modbus指令
     */
    public byte[] CreateWriteRegister(byte station, byte[] values) {
        byte[] buffer = new byte[7 + values.length];
        buffer[0] = this.Station < 0 ? station : (byte) this.Station;
        buffer[1] = ModbusInfo.WriteRegister;
        buffer[2] = Utilities.getBytes(this.getAddress())[1];
        buffer[3] = Utilities.getBytes(this.getAddress())[0];
        buffer[4] = (byte) (values.length / 2 / 256);
        buffer[5] = (byte) (values.length / 2 % 256);
        buffer[6] = (byte) (values.length);
        System.arraycopy(values, 0, buffer, 7, values.length);
        return buffer;
    }
    /**
     * 地址新增指定的数
     * @param value 地址值
     * @return 新增后的地址信息
     */
    public ModbusAddress AddressAdd(int value) {
        ModbusAddress address = new ModbusAddress();
        address.setAddress(getAddress() + value);
        address.setFunction(getFunction());
        address.setStation(getStation());
        return address;
    }
    /**
     * 地址新增1
     * @return 新增后的地址信息
     */
    public ModbusAddress AddressAdd() {
        return AddressAdd(1);
    }
    /**
     * 获取本对象的字符串表示形式
     * @return 字符串数据
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        if (Station >= 0) sb.append("s=" + Station + ";");
        if (Function >= 1) sb.append("x=" + Function + ";");
        sb.append(String.valueOf(getAddress()));
        return sb.toString();
    }
}
src/main/java/com/zy/common/HslCommunication/ModBus/ModbusInfo.java
New file
@@ -0,0 +1,150 @@
package com.zy.common.HslCommunication.ModBus;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
/**
 * Modbus协议相关的一些信息
 */
public class ModbusInfo {
    /**
     * 读取线圈
     */
    public static final byte ReadCoil = 0x01;
    /**
     * 读取离散量
     */
    public static final byte ReadDiscrete = 0x02;
    /**
     * 读取寄存器
     */
    public static final byte ReadRegister = 0x03;
    /**
     * 读取输入寄存器
     */
    public static final byte ReadInputRegister = 0x04;
    /**
     * 写单个线圈
     */
    public static final byte WriteOneCoil = 0x05;
    /**
     * 写单个寄存器
     */
    public static final byte WriteOneRegister = 0x06;
    /**
     * 写多个线圈
     */
    public static final byte WriteCoil = 0x0F;
    /**
     * 写多个寄存器
     */
    public static final byte WriteRegister = 0x10;
    /*****************************************************************************************
     *
     *    本服务器和客户端支持的异常返回
     *
     *******************************************************************************************/
    /**
     * 不支持该功能码
     */
    public static final byte FunctionCodeNotSupport = 0x01;
    /**
     * 该地址越界
     */
    public static final byte FunctionCodeOverBound = 0x02;
    /**
     * 读取长度超过最大值
     */
    public static final byte FunctionCodeQuantityOver = 0x03;
    /**
     * 读写异常
     */
    public static final byte FunctionCodeReadWriteException = 0x04;
    /**
     * 将modbus指令打包成Modbus-Tcp指令
     *
     * @param value Modbus指令
     * @param id    消息的序号
     * @return Modbus-Tcp指令
     */
    public static byte[] PackCommandToTcp(byte[] value, int id) {
        byte[] buffer = new byte[value.length + 6];
        buffer[0] = Utilities.getBytes(id)[1];
        buffer[1] = Utilities.getBytes(id)[0];
        buffer[4] = Utilities.getBytes(value.length)[1];
        buffer[5] = Utilities.getBytes(value.length)[0];
        System.arraycopy(value, 0, buffer, 6, value.length);
        return buffer;
    }
    /**
     * 分析Modbus协议的地址信息,该地址适应于tcp及rtu模式
     *
     * @param address         带格式的地址,比如"100","x=4;100","s=1;100","s=1;x=4;100"
     * @param isStartWithZero 起始地址是否从0开始
     * @return 转换后的地址信息
     */
    public static OperateResultExOne<ModbusAddress> AnalysisReadAddress(String address, boolean isStartWithZero) {
        try {
            ModbusAddress mAddress = new ModbusAddress(address);
            if (!isStartWithZero) {
                if (mAddress.getAddress() < 1) throw new Exception("地址值在起始地址为1的情况下,必须大于1");
                mAddress.setAddress(mAddress.getAddress() - 1);
            }
            return OperateResultExOne.CreateSuccessResult(mAddress);
        } catch (Exception ex) {
            OperateResultExOne<ModbusAddress> resultExOne = new OperateResultExOne<>();
            resultExOne.Message = ex.getMessage();
            return resultExOne;
        }
    }
    /**
     * 通过错误码来获取到对应的文本消息
     *
     * @param code 错误码
     * @return 错误的文本描述
     */
    public static String GetDescriptionByErrorCode(byte code) {
        switch (code) {
            case ModbusInfo.FunctionCodeNotSupport:
                return StringResources.Language.ModbusTcpFunctionCodeNotSupport();
            case ModbusInfo.FunctionCodeOverBound:
                return StringResources.Language.ModbusTcpFunctionCodeOverBound();
            case ModbusInfo.FunctionCodeQuantityOver:
                return StringResources.Language.ModbusTcpFunctionCodeQuantityOver();
            case ModbusInfo.FunctionCodeReadWriteException:
                return StringResources.Language.ModbusTcpFunctionCodeReadWriteException();
            default:
                return StringResources.Language.UnknownError();
        }
    }
}
src/main/java/com/zy/common/HslCommunication/ModBus/ModbusTcpNet.java
New file
@@ -0,0 +1,494 @@
package com.zy.common.HslCommunication.ModBus;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.BasicFramework.SoftIncrementCount;
import com.zy.common.HslCommunication.Core.IMessage.ModbusTcpMessage;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.DataFormat;
import com.zy.common.HslCommunication.Core.Transfer.ReverseWordTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
import java.io.ByteArrayOutputStream;
/**
 * Modbus-Tcp协议的客户端通讯类,方便的和服务器进行数据交互
 */
public class ModbusTcpNet extends NetworkDeviceBase<ModbusTcpMessage, ReverseWordTransform> {
    /**
     * 实例化一个MOdbus-Tcp协议的客户端对象
     */
    public ModbusTcpNet() {
        this.softIncrementCount = new SoftIncrementCount(65535, 0);
        this.WordLength = 1;
        this.station = 1;
    }
    /**
     * 指定服务器地址,端口号,客户端自己的站号来初始化
     *
     * @param ipAddress 服务器的Ip地址
     * @param port      服务器的端口号
     * @param station   客户端自身的站号,可以在读取的时候动态配置
     */
    public ModbusTcpNet(String ipAddress, int port, byte station) {
        this.softIncrementCount = new SoftIncrementCount(65535, 0);
        setIpAddress(ipAddress);
        setPort(port);
        this.WordLength = 1;
        this.station = station;
    }
    private byte station = 0x01;                                // 本客户端的站号
    private SoftIncrementCount softIncrementCount;              // 自增消息的对象
    private boolean isAddressStartWithZero = true;                 // 线圈值的地址值是否从零开始
    /**
     * 获取起始地址是否从0开始
     *
     * @return bool值
     */
    public boolean getAddressStartWithZero() {
        return isAddressStartWithZero;
    }
    /**
     * 设置起始地址是否从0开始
     *
     * @param addressStartWithZero true代表从0开始,false代表从1开始
     */
    public void setAddressStartWithZero(boolean addressStartWithZero) {
        this.isAddressStartWithZero = addressStartWithZero;
    }
    /**
     * 获取站号
     *
     * @return 站号
     */
    public byte getStation() {
        return station;
    }
    /**
     * 设置站号
     *
     * @param station 站号
     */
    public void setStation(byte station) {
        this.station = station;
    }
    /**
     * 设置多字节数据的反转类型,适用于int,float,double,long类型的数据
     *
     * @param dataFormat 数据类型
     */
    public void setDataFormat(DataFormat dataFormat) {
        getByteTransform().setDataFormat(dataFormat);
    }
    /**
     * 获取多字节数据的反转类型,适用于int,float,double,long类型的数据
     *
     * @return
     */
    public DataFormat getDataFormat() {
        return getByteTransform().getDataFormat();
    }
    /**
     * 字符串数据是否发生反转
     *
     * @return bool值
     */
    public boolean isStringReverse() {
        return getByteTransform().IsStringReverse;
    }
    /**
     * 设置字符串数据是否反转
     *
     * @param stringReverse bool值
     */
    public void setStringReverse(boolean stringReverse) {
        getByteTransform().IsStringReverse = stringReverse;
    }
    private OperateResultExOne<byte[]> BuildReadCoilCommand(String address, short count) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateReadCoils(station, count), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildReadDiscreteCommand(String address, short length) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateReadDiscrete(station, length), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildReadRegisterCommand(String address, short length) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateReadRegister(station, length), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildReadRegisterCommand(ModbusAddress address, short length) {
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(address.CreateReadRegister(station, length), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildWriteOneCoilCommand(String address, boolean value) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateWriteOneCoil(station, value), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildWriteOneRegisterCommand(String address, byte[] data) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateWriteOneRegister(station, data), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildWriteCoilCommand(String address, boolean[] values) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateWriteCoil(station, values), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    private OperateResultExOne<byte[]> BuildWriteRegisterCommand(String address, byte[] values) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        short messageId = (short) softIncrementCount.GetCurrentValue();
        // 生成最终tcp指令
        byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateWriteRegister(station, values), messageId);
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    /**
     * 检查当前的Modbus-Tcp响应是否是正确的
     *
     * @param send 发送的数据信息
     * @return 带是否成功的结果数据
     */
    private OperateResultExOne<byte[]> CheckModbusTcpResponse(byte[] send) {
        OperateResultExOne<byte[]> result = ReadFromCoreServer(send);
        if (result.IsSuccess) {
            if ((send[7] + 0x80) == result.Content[7]) {
                // 发生了错误
                result.IsSuccess = false;
                result.Message = ModbusInfo.GetDescriptionByErrorCode(result.Content[8]);
                result.ErrorCode = result.Content[8];
            }
        }
        return result;
    }
    /**
     * 读取服务器的数据,需要指定不同的功能码
     *
     * @param address 地址
     * @param length  长度
     * @return 结果数据
     */
    private OperateResultExOne<byte[]> ReadModBusBase(ModbusAddress address, short length) {
        OperateResultExOne<byte[]> command = BuildReadRegisterCommand(address, length);
        if (!command.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(command);
        OperateResultExOne<byte[]> resultBytes = CheckModbusTcpResponse(command.Content);
        if (resultBytes.IsSuccess) {
            // 二次数据处理
            if (resultBytes.Content.length >= 9) {
                byte[] buffer = new byte[resultBytes.Content.length - 9];
                System.arraycopy(resultBytes.Content, 9, buffer, 0, buffer.length);
                resultBytes.Content = buffer;
            }
        }
        return resultBytes;
    }
    /**
     * 读取服务器的数据,需要指定不同的功能码
     *
     * @param code    指令
     * @param address 地址
     * @param length  长度
     * @return 指令字节信息
     */
    private OperateResultExOne<byte[]> ReadModBusBase(byte code, String address, short length) {
        OperateResultExOne<byte[]> command = null;
        switch (code) {
            case ModbusInfo.ReadCoil: {
                command = BuildReadCoilCommand(address, length);
                break;
            }
            case ModbusInfo.ReadDiscrete: {
                command = BuildReadDiscreteCommand(address, length);
                break;
            }
            case ModbusInfo.ReadRegister: {
                command = BuildReadRegisterCommand(address, length);
                break;
            }
            default: {
                command = new OperateResultExOne<byte[]>();
                command.Message = StringResources.Language.ModbusTcpFunctionCodeNotSupport();
                break;
            }
        }
        if (!command.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(command);
        OperateResultExOne<byte[]> resultBytes = CheckModbusTcpResponse(command.Content);
        if (resultBytes.IsSuccess) {
            // 二次数据处理
            if (resultBytes.Content.length >= 9) {
                byte[] buffer = new byte[resultBytes.Content.length - 9];
                System.arraycopy(resultBytes, 9, buffer, 0, buffer.length);
                resultBytes.Content = buffer;
            }
        }
        return resultBytes;
    }
    /**
     * 读取线圈,需要指定起始地址
     *
     * @param address 起始地址,格式为"1234"
     * @return 带有成功标志的bool对象
     */
    public OperateResultExOne<Boolean> ReadCoil(String address) {
        OperateResultExOne<byte[]> read = ReadModBusBase(ModbusInfo.ReadCoil, address, (short) 1);
        if (!read.IsSuccess) return OperateResultExOne.<Boolean>CreateFailedResult(read);
        return GetBoolResultFromBytes(read);
    }
    /**
     * 批量的读取线圈,需要指定起始地址,读取长度
     *
     * @param address 起始地址,格式为"1234"
     * @param length  读取长度
     * @return 带有成功标志的bool数组对象
     */
    public OperateResultExOne<boolean[]> ReadCoil(String address, short length) {
        OperateResultExOne<byte[]> read = ReadModBusBase(ModbusInfo.ReadCoil, address, length);
        if (!read.IsSuccess) return OperateResultExOne.<boolean[]>CreateFailedResult(read);
        return OperateResultExOne.CreateSuccessResult(SoftBasic.ByteToBoolArray(read.Content, length));
    }
    /**
     * 读取输入线圈,需要指定起始地址
     *
     * @param address 起始地址,格式为"1234"
     * @return 带有成功标志的bool对象
     */
    public OperateResultExOne<Boolean> ReadDiscrete(String address) {
        OperateResultExOne<byte[]> read = ReadModBusBase(ModbusInfo.ReadDiscrete, address, (short) 1);
        if (!read.IsSuccess) return OperateResultExOne.<Boolean>CreateFailedResult(read);
        return GetBoolResultFromBytes(read);
    }
    /**
     * 批量的读取输入点,需要指定起始地址,读取长度
     *
     * @param address 起始地址,格式为"1234"
     * @param length  读取长度
     * @return 带有成功标志的bool数组对象
     */
    public OperateResultExOne<boolean[]> ReadDiscrete(String address, short length) {
        OperateResultExOne<byte[]> read = ReadModBusBase(ModbusInfo.ReadDiscrete, address, length);
        if (!read.IsSuccess) return OperateResultExOne.<boolean[]>CreateFailedResult(read);
        return OperateResultExOne.CreateSuccessResult(SoftBasic.ByteToBoolArray(read.Content, length));
    }
    /**
     * 从Modbus服务器批量读取寄存器的信息,需要指定起始地址,读取长度
     *
     * @param address 起始地址,格式为"1234",或者是带功能码格式03X1234
     * @param length  读取的数量
     * @return 带有成功标志的字节信息
     */
    @Override
    public OperateResultExOne<byte[]> Read(String address, short length) {
        OperateResultExOne<ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int alreadyFinished = 0;
        while (alreadyFinished < length) {
            short lengthTmp = (short) Math.min((length - alreadyFinished), 120);
            OperateResultExOne<byte[]> read = ReadModBusBase(analysis.Content.AddressAdd(alreadyFinished), lengthTmp);
            if (!read.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(read);
            try {
                outputStream.write(read.Content);
            } catch (Exception ex) {
            }
            alreadyFinished += lengthTmp;
        }
        byte[] data = outputStream.toByteArray();
        try {
            outputStream.close();
        } catch (Exception ex) {
        }
        return OperateResultExOne.CreateSuccessResult(data);
    }
    /**
     * 写一个寄存器数据
     *
     * @param address 起始地址
     * @param high    高位
     * @param low     地位
     * @return 返回写入结果
     */
    public OperateResult WriteOneRegister(String address, byte high, byte low) {
        OperateResultExOne<byte[]> command = BuildWriteOneRegisterCommand(address, new byte[]{high, low});
        if (!command.IsSuccess) {
            return command;
        }
        return CheckModbusTcpResponse(command.Content);
    }
    /**
     * 写一个寄存器数据
     *
     * @param address 起始地址
     * @param value   写入值
     * @return 返回写入结果
     */
    public OperateResult WriteOneRegister(String address, short value) {
        byte[] buffer = Utilities.getBytes(value);
        return WriteOneRegister(address, buffer[1], buffer[0]);
    }
    /**
     * 将数据写入到Modbus的寄存器上去,需要指定起始地址和数据内容
     *
     * @param address 起始地址,格式为"1234"
     * @param value   写入的数据,长度根据data的长度来指示
     * @return 返回写入结果
     */
    @Override
    public OperateResult Write(String address, byte[] value) {
        OperateResultExOne<byte[]> command = BuildWriteRegisterCommand(address, value);
        if (!command.IsSuccess) {
            return command;
        }
        return CheckModbusTcpResponse(command.Content);
    }
    /**
     * 写一个线圈信息,指定是否通断
     *
     * @param address 起始地址
     * @param value   写入值
     * @return 返回写入结果
     */
    public OperateResult WriteCoil(String address, boolean value) {
        OperateResultExOne<byte[]> command = BuildWriteOneCoilCommand(address, value);
        if (!command.IsSuccess) {
            return command;
        }
        return CheckModbusTcpResponse(command.Content);
    }
    /**
     * 写线圈数组,指定是否通断
     *
     * @param address 起始地址
     * @param values  写入值
     * @return 返回写入结果
     */
    public OperateResult WriteCoil(String address, boolean[] values) {
        OperateResultExOne<byte[]> command = BuildWriteCoilCommand(address, values);
        if (!command.IsSuccess) {
            return command;
        }
        return CheckModbusTcpResponse(command.Content);
    }
    /**
     * 向寄存器中写入bool数组,返回值说明,比如你写入M100,那么data[0]对应M100.0
     *
     * @param address 要写入的数据地址
     * @param values  要写入的实际数据,长度为8的倍数
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean[] values) {
        return Write(address, SoftBasic.BoolArrayToByte(values));
    }
    /**
     * 返回表示当前对象的字符串
     * @return 字符串信息
     */
    @Override
    public String toString() {
        return "ModbusTcpNet[" + getIpAddress() + ":"+getPort()+"]";
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecA1EDataType.java
New file
@@ -0,0 +1,89 @@
package com.zy.common.HslCommunication.Profinet.Melsec;
/**
 * 三菱PLC的数据类型,此处包含了几个常用的类型
 */
public class MelsecA1EDataType {
    /**
     * 如果您清楚类型代号,可以根据值进行扩展
     * @param code 数据类型的代号
     * @param type 0或1,默认为0
     * @param asciiCode ASCII格式的类型信息
     * @param fromBase >指示地址的多少进制的,10或是16
     */
    public MelsecA1EDataType( byte[] code, byte type, String asciiCode, int fromBase )
    {
        DataCode = code;
        AsciiCode = asciiCode;
        FromBase = fromBase;
        if (type < 2) DataType = type;
    }
    private byte[] DataCode = new byte[2];
    private byte DataType = 0x00;
    private String AsciiCode = "";
    private int FromBase = 0;
    /**
     * 类型的代号值(软元件代码,用于区分软元件类型,如:D,R)
     * @return
     */
    public byte[] getDataCode(){
        return DataCode;
    }
    /**
     * 数据的类型,0代表按字,1代表按位
     * @return
     */
    public byte getDataType(){
        return DataType;
    }
    /**
     * 当以ASCII格式通讯时的类型描述
     * @return
     */
    public String getAsciiCode(){
        return AsciiCode;
    }
    /**
     * 指示地址是10进制,还是16进制的
     * @return
     */
    public int getFromBase(){
        return FromBase;
    }
    /**
     * X输入寄存器
     */
    public final static MelsecA1EDataType X = new MelsecA1EDataType( new byte[] {0x58, 0x20}, (byte) 0x01, "X*", 8 );
    /**
     * Y输出寄存器
     */
    public final static MelsecA1EDataType Y = new MelsecA1EDataType( new byte[] {0x59,0x20}, (byte)0x01, "Y*", 8 );
    /**
     * M中间寄存器
     */
    public final static MelsecA1EDataType M = new MelsecA1EDataType( new byte[] {0x4D,0x20}, (byte)0x01, "M*", 10 );
    /**
     * S状态寄存器
     */
    public final static MelsecA1EDataType S = new MelsecA1EDataType( new byte[] {0x53,0x20}, (byte)0x01, "S*", 10 );
    /**
     * D数据寄存器
     */
    public final static MelsecA1EDataType D = new MelsecA1EDataType( new byte[] {0x44,0x20}, (byte)0x00, "D*", 10 );
    /**
     * R文件寄存器
     */
    public final static MelsecA1EDataType R = new MelsecA1EDataType( new byte[] { 0x52, 0x20 }, (byte)0x00, "R*", 10 );
}
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecA1ENet.java
New file
@@ -0,0 +1,336 @@
package com.zy.common.HslCommunication.Profinet.Melsec;
import com.zy.common.HslCommunication.Core.IMessage.MelsecA1EBinaryMessage;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.RegularByteTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.StringResources;
/**
 * 三菱PLC通讯协议,采用A兼容1E帧协议实现,使用二进制码通讯,请根据实际型号来进行选取
 */
public class MelsecA1ENet extends NetworkDeviceBase<MelsecA1EBinaryMessage,RegularByteTransform> {
    /**
     * 实例化三菱的A兼容1E帧协议的通讯对象
     */
    public MelsecA1ENet() {
        WordLength = 1;
    }
    /**
     * 实例化一个三菱的A兼容1E帧协议的通讯对象
     *
     * @param ipAddress PLCd的Ip地址
     * @param port      PLC的端口
     */
    public MelsecA1ENet(String ipAddress, int port) {
        WordLength = 1;
        super.setIpAddress(ipAddress);
        super.setPort(port);
    }
    private byte PLCNumber = (byte) (0xFF);                       // PLC编号
    /**
     * 获取PLC编号
     *
     * @return PLC编号
     */
    public byte getPLCNumber() {
        return PLCNumber;
    }
    /**
     * 设置PLC编号
     *
     * @param plcNumber PLC编号
     */
    public void setPLCNumber(byte plcNumber) {
        PLCNumber = plcNumber;
    }
    /**
     * 从三菱PLC中读取想要的数据,返回读取结果
     * @param address 读取地址,格式为"M100","D100","W1A0"
     * @param length 读取的数据长度,字最大值960,位最大值7168
     * @return 带成功标志的结果数据对象
     */
    @Override
    public OperateResultExOne<byte[]> Read(String address, short length) {
        // 获取指令
        OperateResultExOne<byte[]> command = BuildReadCommand( address, length, PLCNumber );
        if (!command.IsSuccess) return OperateResultExOne.CreateFailedResult( command );
        // 核心交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer( command.Content );
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult( read );
        // 错误代码验证
        if (read.Content[1] != 0) return new OperateResultExOne<>( read.Content[1], StringResources.Language.MelsecPleaseReferToManulDocument() );
        // 数据解析,需要传入是否使用位的参数
        return ExtractActualData( read.Content, command.Content[0] == 0x00 );
    }
    /**
     * 从三菱PLC中批量读取位软元件,返回读取结果
     * @param address 起始地址
     * @param length 读取的长度
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<boolean[]> ReadBool(String address, short length) {
        // 解析地址
        OperateResultExTwo<MelsecA1EDataType, Short> analysis = MelsecHelper.McA1EAnalysisAddress( address );
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult( analysis );
        // 位读取校验
        if (analysis.Content1.getDataType() == 0x00) return new OperateResultExOne<boolean[]>( 0, StringResources.Language.MelsecReadBitInfo() );
        // 核心交互
        OperateResultExOne<byte[]> read = Read( address, length );
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult( read );
        // 转化bool数组
        boolean[] result = new boolean[read.Content.length];
        for(int i=0;i<result.length;i++){
            if(read.Content[i] == 0x01) result[i] = true;
        }
        return OperateResultExOne.CreateSuccessResult( result );
    }
    /**
     * 从三菱PLC中批量读取位软元件,返回读取结果
     * @param address 起始地址
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<Boolean> ReadBool(String address) {
        OperateResultExOne<boolean[]> read = ReadBool(address, (short) 1);
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult(read);
        return OperateResultExOne.CreateSuccessResult(read.Content[0]);
    }
    /**
     * 向PLC写入数据,数据格式为原始的字节类型
     * @param address 起始地址
     * @param value 原始数据
     * @return 结果
     */
    @Override
    public OperateResult Write(String address, byte[] value) {
        // 解析指令
        OperateResultExOne<byte[]> command = BuildWriteCommand( address, value, PLCNumber );
        if (!command.IsSuccess) return command;
        // 核心交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer( command.Content );
        if (!read.IsSuccess) return read;
        // 错误码校验 (在A兼容1E协议中,结束代码后面紧跟的是异常信息的代码)
        if (read.Content[1] != 0) return new OperateResultExOne<byte[]>( read.Content[1], StringResources.Language.MelsecPleaseReferToManulDocument() );
        // 成功
        return OperateResult.CreateSuccessResult( );
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
     * @param address 要写入的数据地址
     * @param value 要写入的实际数据,长度为8的倍数
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean value) {
        return Write(address, new boolean[]{value});
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
     * @param address 要写入的数据地址
     * @param values 要写入的实际数据,可以指定任意的长度
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean[] values) {
        byte[] buffer = new byte[values.length];
        for (int i = 0; i < values.length; i++) {
            buffer[i] = values[i] ? (byte) 0x01 : (byte) 0x00;
        }
        return Write(address, buffer);
    }
    /**
     * 获取当前对象的字符串标识形式
     * @return 字符串信息
     */
    @Override
    public String toString() {
        return "MelsecA1ENet";
    }
    /**
     * 根据类型地址长度确认需要读取的指令头
     * @param address 起始地址
     * @param length 长度
     * @return 带有成功标志的指令数据
     */
    public static OperateResultExOne<byte[]> BuildReadCommand(String address, short length) {
        return BuildReadCommand(address,length,(byte)0xFF);
    }
    /**
     * 根据类型地址长度确认需要读取的指令头
     * @param address 起始地址
     * @param length 长度
     * @param plcNumber PLC号
     * @return 带有成功标志的指令数据
     */
    public static OperateResultExOne<byte[]> BuildReadCommand(String address, short length, byte plcNumber) {
        OperateResultExTwo<MelsecA1EDataType, Short> analysis = MelsecHelper.McA1EAnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis);
        byte subtitle = analysis.Content1.getDataType() == 0x01 ? (byte)0x00 : (byte)0x01;
        byte[] _PLCCommand = new byte[12];
        _PLCCommand[0] = subtitle;                              // 副标题
        _PLCCommand[1] = plcNumber;                             // PLC号
        _PLCCommand[2] = 0x0A;                                  // CPU监视定时器(L)这里设置为0x00,0x0A,等待CPU返回的时间为10*250ms=2.5秒
        _PLCCommand[3] = 0x00;                                  // CPU监视定时器(H)
        _PLCCommand[4] = (byte)(analysis.Content2 % 256);       // 起始软元件(开始读取的地址)
        _PLCCommand[5] = (byte)(analysis.Content2 / 256);
        _PLCCommand[6] = 0x00;
        _PLCCommand[7] = 0x00;
        _PLCCommand[8] = analysis.Content1.getDataCode()[1];    // 软元件代码(L)
        _PLCCommand[9] = analysis.Content1.getDataCode()[0];    // 软元件代码(H)
        _PLCCommand[10] = (byte)(length % 256);                 // 软元件点数
        _PLCCommand[11] = 0x00;
        return OperateResultExOne.CreateSuccessResult(_PLCCommand);
    }
    /**
     * 根据类型地址以及需要写入的数据来生成指令头
     * @param address 起始地址
     * @param value 值
     * @return 结果
     */
    public static OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] value) {
        return BuildWriteCommand(address,value,(byte)0xFF);
    }
    /**
     * 根据类型地址以及需要写入的数据来生成指令头
     * @param address 起始地址
     * @param value 值
     * @param plcNumber PLC号
     * @return 结果
     */
    public static OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] value, byte plcNumber) {
        OperateResultExTwo<MelsecA1EDataType, Short> analysis = MelsecHelper.McA1EAnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis);
        int length = -1;
        if (analysis.Content1.getDataType() == 1)
        {
            // 按照位写入的操作,数据需要重新计算
            length = value.length;
            value = MelsecHelper.TransBoolArrayToByteData( value );
        }
        byte subtitle = analysis.Content1.getDataType() == 0x01 ? (byte)0x02 : (byte)0x03;
        byte[] _PLCCommand = new byte[12 + value.length];
        _PLCCommand[0] = subtitle;                              // 副标题
        _PLCCommand[1] = plcNumber;                             // PLC号
        _PLCCommand[2] = 0x0A;                                  // CPU监视定时器(L)这里设置为0x00,0x0A,等待CPU返回的时间为10*250ms=2.5秒
        _PLCCommand[3] = 0x00;                                  // CPU监视定时器(H)
        _PLCCommand[4] = (byte)(analysis.Content2 % 256);       // 起始软元件(开始读取的地址)
        _PLCCommand[5] = (byte)(analysis.Content2 / 256);
        _PLCCommand[6] = 0x00;
        _PLCCommand[7] = 0x00;
        _PLCCommand[8] = analysis.Content1.getDataCode()[1];    // 软元件代码(L)
        _PLCCommand[9] = analysis.Content1.getDataCode()[0];    // 软元件代码(H)
        _PLCCommand[10] = (byte)(length % 256);                 // 软元件点数
        _PLCCommand[11] = 0x00;
        // 判断是否进行位操作
        if (analysis.Content1.getDataType() == 1) {
            if (length > 0) {
                _PLCCommand[10] = (byte)(length % 256);                       // 软元件点数
            }
            else {
                _PLCCommand[10] = (byte)(value.length * 2 % 256);             // 软元件点数
            }
        } else {
            _PLCCommand[10] = (byte)(value.length / 2 % 256);                 // 软元件点数
        }
        System.arraycopy(value, 0, _PLCCommand, 12, value.length);
        return OperateResultExOne.CreateSuccessResult(_PLCCommand);
    }
    /**
     * 从PLC反馈的数据中提取出实际的数据内容,需要传入反馈数据,是否位读取
     * @param response 反馈的数据内容
     * @param isBit 是否位读取
     * @return 解析后的结果对象
     */
    public static OperateResultExOne<byte[]> ExtractActualData( byte[] response, boolean isBit )
    {
        if (isBit)
        {
            // 位读取
            byte[] Content = new byte[(response.length - 2) * 2];
            for (int i = 2; i < response.length; i++)
            {
                if ((response[i] & 0x10) == 0x10)
                {
                    Content[(i - 2) * 2 + 0] = 0x01;
                }
                if ((response[i] & 0x01) == 0x01)
                {
                    Content[(i - 2) * 2 + 1] = 0x01;
                }
            }
            return OperateResultExOne.CreateSuccessResult( Content );
        }
        else
        {
            // 字读取
            byte[] Content = new byte[response.length - 2];
            System.arraycopy(response,2,Content,0,Content.length);
            return OperateResultExOne.CreateSuccessResult( Content );
        }
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecHelper.java
New file
@@ -0,0 +1,290 @@
package com.zy.common.HslCommunication.Profinet.Melsec;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.Utilities;
/**
 * 所有三菱通讯类的通用辅助工具类,包含了一些通用的静态方法,可以使用本类来获取一些原始的报文信息。详细的操作参见例子
 */
public class MelsecHelper {
    /**
     * 解析A1E协议数据地址
     * @param address 数据地址
     * @return 解析值
     */
    public static OperateResultExTwo<MelsecA1EDataType, Short> McA1EAnalysisAddress( String address )
    {
        OperateResultExTwo<MelsecA1EDataType, Short> result = new OperateResultExTwo<MelsecA1EDataType, Short>();
        try {
            switch (address.charAt(0)) {
                case 'X':
                case 'x': {
                    result.Content1 = MelsecA1EDataType.X;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecA1EDataType.X.getFromBase());
                    break;
                }
                case 'Y':
                case 'y': {
                    result.Content1 = MelsecA1EDataType.Y;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecA1EDataType.Y.getFromBase());
                    break;
                }
                case 'M':
                case 'm': {
                    result.Content1 = MelsecA1EDataType.M;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecA1EDataType.M.getFromBase());
                    break;
                }
                case 'S':
                case 's': {
                    result.Content1 = MelsecA1EDataType.S;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecA1EDataType.S.getFromBase());
                    break;
                }
                case 'D':
                case 'd': {
                    result.Content1 = MelsecA1EDataType.D;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecA1EDataType.D.getFromBase());
                    break;
                }
                case 'R':
                case 'r': {
                    result.Content1 = MelsecA1EDataType.R;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecA1EDataType.R.getFromBase());
                    break;
                }
                default:
                    throw new Exception("输入的类型不支持,请重新输入");
            }
        } catch (Exception ex) {
            result.Message = "地址格式填写错误:" + ex.getMessage();
            return result;
        }
        result.IsSuccess = true;
        return result;
    }
    /**
     * 解析数据地址
     * @param address 数据地址
     * @return 解析值
     */
    public static OperateResultExTwo<MelsecMcDataType, Short> McAnalysisAddress( String address )
    {
        OperateResultExTwo<MelsecMcDataType, Short> result = new OperateResultExTwo<MelsecMcDataType, Short>();
        try {
            switch (address.charAt(0)) {
                case 'M':
                case 'm': {
                    result.Content1 = MelsecMcDataType.M;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.M.getFromBase());
                    break;
                }
                case 'X':
                case 'x': {
                    result.Content1 = MelsecMcDataType.X;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.X.getFromBase());
                    break;
                }
                case 'Y':
                case 'y': {
                    result.Content1 = MelsecMcDataType.Y;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.Y.getFromBase());
                    break;
                }
                case 'D':
                case 'd': {
                    result.Content1 = MelsecMcDataType.D;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.D.getFromBase());
                    break;
                }
                case 'W':
                case 'w': {
                    result.Content1 = MelsecMcDataType.W;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.W.getFromBase());
                    break;
                }
                case 'L':
                case 'l': {
                    result.Content1 = MelsecMcDataType.L;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.L.getFromBase());
                    break;
                }
                case 'F':
                case 'f': {
                    result.Content1 = MelsecMcDataType.F;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.F.getFromBase());
                    break;
                }
                case 'V':
                case 'v': {
                    result.Content1 = MelsecMcDataType.V;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.V.getFromBase());
                    break;
                }
                case 'B':
                case 'b': {
                    result.Content1 = MelsecMcDataType.B;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.B.getFromBase());
                    break;
                }
                case 'R':
                case 'r': {
                    result.Content1 = MelsecMcDataType.R;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.R.getFromBase());
                    break;
                }
                case 'S':
                case 's': {
                    result.Content1 = MelsecMcDataType.S;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.S.getFromBase());
                    break;
                }
                case 'Z':
                case 'z': {
                    result.Content1 = MelsecMcDataType.Z;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.Z.getFromBase());
                    break;
                }
                case 'T':
                case 't': {
                    result.Content1 = MelsecMcDataType.T;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.T.getFromBase());
                    break;
                }
                case 'C':
                case 'c': {
                    result.Content1 = MelsecMcDataType.C;
                    result.Content2 = Short.parseShort(address.substring(1), MelsecMcDataType.C.getFromBase());
                    break;
                }
                default:
                    throw new Exception("输入的类型不支持,请重新输入");
            }
        } catch (Exception ex) {
            result.Message = "地址格式填写错误:" + ex.getMessage();
            return result;
        }
        result.IsSuccess = true;
        return result;
    }
    /**
     * 从字节构建一个ASCII格式的地址字节
     * @param value 字节信息
     * @return ASCII格式的地址
     */
    public static byte[] BuildBytesFromData(byte value )
    {
        return Utilities.getBytes(String.format("%02x",value),"ASCII");
    }
    /**
     * 从short数据构建一个ASCII格式地址字节
     * @param value short值
     * @return ASCII格式的地址
     */
    public static byte[] BuildBytesFromData( short value )
    {
        return Utilities.getBytes(String.format("%04x",value),"ASCII");
    }
    /**
     * 从int数据构建一个ASCII格式地址字节
     * @param value int值
     * @return ASCII格式的地址
     */
    public static byte[] BuildBytesFromData( int value )
    {
        return Utilities.getBytes(String.format("%04x",value),"ASCII");
    }
    /**
     * 从三菱的地址中构建MC协议的6字节的ASCII格式的地址
     * @param address 三菱地址
     * @param type 三菱的数据类型
     * @return 6字节的ASCII格式的地址
     */
    public static byte[] BuildBytesFromAddress( int address, MelsecMcDataType type )
    {
        return Utilities.getBytes(String.format(type.getFromBase() == 10 ? "%06d" : "%06x",address),"ASCII");
    }
    /**
     * 从字节数组构建一个ASCII格式的地址字节
     * @param value 字节信息
     * @return ASCII格式的地址
     */
    public static byte[] BuildBytesFromData( byte[] value )
    {
        byte[] buffer = new byte[value.length * 2];
        for (int i = 0; i < value.length; i++)
        {
            byte[] data = BuildBytesFromData( value[i] );
            buffer[2*i+0] = data[0];
            buffer[2*i+1] = data[1];
        }
        return buffer;
    }
    /**
     * 将0,1,0,1的字节数组压缩成三菱格式的字节数组来表示开关量的
     * @param value 原始的数据字节
     * @return 压缩过后的数据字节
     */
    public static byte[] TransBoolArrayToByteData( byte[] value )
    {
        int length = value.length % 2 == 0 ? value.length / 2 : (value.length / 2) + 1;
        byte[] buffer = new byte[length];
        for (int i = 0; i < length; i++)
        {
            if (value[i * 2 + 0] != 0x00) buffer[i] += 0x10;
            if ((i * 2 + 1) < value.length)
            {
                if (value[i * 2 + 1] != 0x00) buffer[i] += 0x01;
            }
        }
        return buffer;
    }
    /**
     * 计算Fx协议指令的和校验信息
     * @param data 字节数据
     * @return 校验之后的数据
     */
    public static byte[] FxCalculateCRC( byte[] data )
    {
        int sum = 0;
        for (int i = 1; i < data.length - 2; i++)
        {
            sum += data[i];
        }
        return BuildBytesFromData( (byte)sum );
    }
    /**
     * 检查指定的和校验是否是正确的
     * @param data 字节数据
     * @return 是否成功
     */
    public static boolean CheckCRC( byte[] data )
    {
        byte[] crc = FxCalculateCRC( data );
        if (crc[0] != data[data.length - 2]) return false;
        if (crc[1] != data[data.length - 1]) return false;
        return true;
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecMcAsciiNet.java
New file
@@ -0,0 +1,413 @@
package com.zy.common.HslCommunication.Profinet.Melsec;
import com.zy.common.HslCommunication.Core.IMessage.MelsecQnA3EAsciiMessage;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.RegularByteTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
/**
 * 三菱PLC通讯类,采用Qna兼容3E帧协议实现,需要在PLC侧先的以太网模块先进行配置,必须为ASCII通讯格式
 */
public class MelsecMcAsciiNet extends NetworkDeviceBase<MelsecQnA3EAsciiMessage, RegularByteTransform> {
    /**
     * 实例化三菱的Qna兼容3E帧协议的通讯对象
     */
    public MelsecMcAsciiNet() {
        WordLength = 1;
    }
    /**
     * 实例化一个三菱的Qna兼容3E帧协议的通讯对象
     * @param ipAddress PLC的Ip地址
     * @param port PLC的端口
     */
    public MelsecMcAsciiNet(String ipAddress, int port) {
        WordLength = 1;
        setIpAddress(ipAddress);
        setPort(port);
    }
    private byte NetworkNumber = 0x00;                       // 网络号
    private byte NetworkStationNumber = 0x00;                // 网络站号
    /**
     * 获取网络号
     *
     * @return
     */
    public byte getNetworkNumber() {
        return NetworkNumber;
    }
    /**
     * 设置网络号
     *
     * @param networkNumber
     */
    public void setNetworkNumber(byte networkNumber) {
        NetworkNumber = networkNumber;
    }
    /**
     * 获取网络站号
     *
     * @return
     */
    public byte getNetworkStationNumber() {
        return NetworkStationNumber;
    }
    /**
     * 设置网络站号
     *
     * @param networkStationNumber
     */
    public void setNetworkStationNumber(byte networkStationNumber) {
        NetworkStationNumber = networkStationNumber;
    }
    /**
     * 从三菱PLC中读取想要的数据,返回读取结果
     * @param address 读取地址,格式为"M100","D100","W1A0"
     * @param length 读取的数据长度,字最大值960,位最大值7168
     * @return 带成功标志的结果数据对象
     */
    @Override
    public OperateResultExOne<byte[]> Read(String address, short length) {
        //获取指令
        OperateResultExOne<byte[]> command = BuildReadCommand( address, length, NetworkNumber, NetworkStationNumber );
        if (!command.IsSuccess) return command;
        // 核心交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer( command.Content );
        if (!read.IsSuccess) return read;
        // 错误代码验证
        short errorCode = Short.parseShort(Utilities.getString(read.Content,18,4,"ASCII"), 16 );
        if (errorCode != 0) return new OperateResultExOne<>( errorCode, StringResources.Language.MelsecPleaseReferToManulDocument() );
        // 数据解析,需要传入是否使用位的参数
        return ExtractActualData( read.Content, command.Content[29] == 0x31 );
    }
    /**
     * 从三菱PLC中批量读取位软元件,返回读取结果
     * @param address 起始地址
     * @param length 读取的长度
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<boolean[]> ReadBool(String address, short length) {
        // 解析地址
        OperateResultExTwo<MelsecMcDataType, Short> analysis = MelsecHelper.McAnalysisAddress( address );
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult( analysis );
        // 位读取校验
        if (analysis.Content1.getDataType() == 0x00) return new OperateResultExOne<>( StringResources.Language.MelsecReadBitInfo() );
        // 核心交互
        OperateResultExOne<byte[]> read = Read( address, length );
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult( read );
        // 转化bool数组
        boolean[] content = new boolean[read.Content.length];
        for (int i = 0; i < read.Content.length; i++) {
            content[i] = read.Content[i] == 0x01;
        }
        return OperateResultExOne.CreateSuccessResult( content );
    }
    /**
     * 从三菱PLC中批量读取位软元件,返回读取结果
     * @param address 起始地址
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<Boolean> ReadBool(String address) {
        OperateResultExOne<boolean[]> read = ReadBool(address, (short) 1);
        if (!read.IsSuccess) return OperateResultExOne.<Boolean>CreateFailedResult(read);
        return OperateResultExOne.<Boolean>CreateSuccessResult(read.Content[0]);
    }
    /**
     * 向PLC写入数据,数据格式为原始的字节类型
     * @param address 起始地址
     * @param value 原始数据
     * @return 结果
     */
    @Override
    public OperateResult Write(String address, byte[] value) {
        // 解析指令
        OperateResultExOne<byte[]> command = BuildWriteCommand( address, value, NetworkNumber, NetworkStationNumber );
        if (!command.IsSuccess) return command;
        // 核心交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer( command.Content );
        if (!read.IsSuccess) return read;
        // 错误码验证
        short errorCode = Short.parseShort( Utilities.getString( read.Content, 18, 4 ,"ASCII"), 16 );
        if (errorCode != 0) return new OperateResultExOne<byte[]>( errorCode, StringResources.Language.MelsecPleaseReferToManulDocument() );
        // 写入成功
        return OperateResult.CreateSuccessResult( );
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
     * @param address 要写入的数据地址
     * @param value 要写入的实际数据,true 或者是 false
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean value) {
        return Write(address, new boolean[]{value});
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
     * @param address 要写入的数据地址
     * @param values 要写入的实际数据,可以指定任意的长度
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean[] values) {
        byte[] buffer = new byte[values.length];
        for (int i = 0; i < values.length; i++) {
            if (values[i]) buffer[i] = 0x01;
        }
        return Write(address, buffer);
    }
    /**
     * 返回表示当前对象的字符串
     * @return 字符串
     */
    @Override
    public String toString() {
        return "MelsecMcNet";
    }
    /**
     * 根据类型地址长度确认需要读取的指令头
     * @param address 起始地址
     * @param length 长度
     * @return 带有成功标志的指令数据
     */
    public static OperateResultExOne< byte[]> BuildReadCommand(String address, short length, byte networkNumber, byte networkStationNumber) {
        OperateResultExTwo<MelsecMcDataType, Short> analysis = MelsecHelper.McAnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis);
        // 默认信息----注意:高低字节交错
        try {
            byte[] _PLCCommand = new byte[42];
            _PLCCommand[0] = 0x35;                                      // 副标题
            _PLCCommand[1] = 0x30;
            _PLCCommand[2] = 0x30;
            _PLCCommand[3] = 0x30;
            _PLCCommand[4] = MelsecHelper.BuildBytesFromData(networkNumber)[0];                // 网络号
            _PLCCommand[5] = MelsecHelper.BuildBytesFromData(networkNumber)[1];
            _PLCCommand[6] = 0x46;                         // PLC编号
            _PLCCommand[7] = 0x46;
            _PLCCommand[8] = 0x30;                         // 目标模块IO编号
            _PLCCommand[9] = 0x33;
            _PLCCommand[10] = 0x46;
            _PLCCommand[11] = 0x46;
            _PLCCommand[12] = MelsecHelper.BuildBytesFromData(networkStationNumber)[0];         // 目标模块站号
            _PLCCommand[13] = MelsecHelper.BuildBytesFromData(networkStationNumber)[1];
            _PLCCommand[14] = 0x30;                         // 请求数据长度
            _PLCCommand[15] = 0x30;
            _PLCCommand[16] = 0x31;
            _PLCCommand[17] = 0x38;
            _PLCCommand[18] = 0x30;                         // CPU监视定时器
            _PLCCommand[19] = 0x30;
            _PLCCommand[20] = 0x31;
            _PLCCommand[21] = 0x30;
            _PLCCommand[22] = 0x30;                        // 批量读取数据命令
            _PLCCommand[23] = 0x34;
            _PLCCommand[24] = 0x30;
            _PLCCommand[25] = 0x31;
            _PLCCommand[26] = 0x30;                         // 以点为单位还是字为单位成批读取
            _PLCCommand[27] = 0x30;
            _PLCCommand[28] = 0x30;
            _PLCCommand[29] = analysis.Content1.getDataType() == 0 ? (byte) 0x30 : (byte) 0x31;
            _PLCCommand[30] = (analysis.Content1.getAsciiCode().getBytes("ASCII"))[0];            // 软元件类型
            _PLCCommand[31] = (analysis.Content1.getAsciiCode().getBytes("ASCII"))[1];
            _PLCCommand[32] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0];                   // 起始地址的地位
            _PLCCommand[33] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1];
            _PLCCommand[34] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2];
            _PLCCommand[35] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3];
            _PLCCommand[36] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4];
            _PLCCommand[37] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5];
            _PLCCommand[38] = MelsecHelper.BuildBytesFromData(length)[0];                                                      // 软元件点数
            _PLCCommand[39] = MelsecHelper.BuildBytesFromData(length)[1];
            _PLCCommand[40] = MelsecHelper.BuildBytesFromData(length)[2];
            _PLCCommand[41] = MelsecHelper.BuildBytesFromData(length)[3];
            return OperateResultExOne.CreateSuccessResult( _PLCCommand );
        }
        catch (Exception ex){
            return new OperateResultExOne<byte[]>(ex.getMessage());
        }
    }
    /**
     * 根据类型地址以及需要写入的数据来生成指令头
     * @param address 起始地址
     * @param value 实际的数据
     * @return 命令数据
     */
    public static OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] value, byte networkNumber, byte networkStationNumber) {
        OperateResultExTwo<MelsecMcDataType, Short> analysis = MelsecHelper.McAnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis);
        // 预处理指令
        if (analysis.Content1.getDataType() == 0x01)
        {
            // 位写入
            byte[] buffer = new byte[value.length];
            for(int i=0;i<buffer.length;i++){
                buffer[i] = value[i] == 0x00? (byte)0x30 : (byte)0x31;
            }
            value = buffer;
        }
        else
        {
            // 字写入
            byte[] buffer = new byte[value.length * 2];
            for (int i = 0; i < value.length / 2; i++)
            {
                byte[] tmp = MelsecHelper.BuildBytesFromData( Utilities.getShort( value, i * 2 ) );
                System.arraycopy(tmp,0,buffer,4*i,4);
            }
            value = buffer;
        }
        byte[] _PLCCommand = new byte[42 + value.length];
        try {
            _PLCCommand[0] = 0x35;                                      // 副标题
            _PLCCommand[1] = 0x30;
            _PLCCommand[2] = 0x30;
            _PLCCommand[3] = 0x30;
            _PLCCommand[4] = MelsecHelper.BuildBytesFromData(networkNumber)[0];                // 网络号
            _PLCCommand[5] = MelsecHelper.BuildBytesFromData(networkNumber)[1];
            _PLCCommand[6] = 0x46;                         // PLC编号
            _PLCCommand[7] = 0x46;
            _PLCCommand[8] = 0x30;                         // 目标模块IO编号
            _PLCCommand[9] = 0x33;
            _PLCCommand[10] = 0x46;
            _PLCCommand[11] = 0x46;
            _PLCCommand[12] = MelsecHelper.BuildBytesFromData(networkStationNumber)[0];         // 目标模块站号
            _PLCCommand[13] = MelsecHelper.BuildBytesFromData(networkStationNumber)[1];
            _PLCCommand[14] = MelsecHelper.BuildBytesFromData((_PLCCommand.length - 18))[0]; // 请求数据长度
            _PLCCommand[15] = MelsecHelper.BuildBytesFromData((_PLCCommand.length - 18))[1];
            _PLCCommand[16] = MelsecHelper.BuildBytesFromData((_PLCCommand.length - 18))[2];
            _PLCCommand[17] = MelsecHelper.BuildBytesFromData((_PLCCommand.length - 18))[3];
            _PLCCommand[18] = 0x30; // CPU监视定时器
            _PLCCommand[19] = 0x30;
            _PLCCommand[20] = 0x31;
            _PLCCommand[21] = 0x30;
            _PLCCommand[22] = 0x31; // 批量写入的命令
            _PLCCommand[23] = 0x34;
            _PLCCommand[24] = 0x30;
            _PLCCommand[25] = 0x31;
            _PLCCommand[26] = 0x30; // 子命令
            _PLCCommand[27] = 0x30;
            _PLCCommand[28] = 0x30;
            _PLCCommand[29] = analysis.Content1.getDataType() == 0 ? (byte) 0x30 : (byte) 0x31;
            _PLCCommand[30] = (analysis.Content1.getAsciiCode().getBytes("ASCII"))[0];                          // 软元件类型
            _PLCCommand[31] = (analysis.Content1.getAsciiCode().getBytes("ASCII"))[1];
            _PLCCommand[32] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0];                   // 起始地址的地位
            _PLCCommand[33] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1];
            _PLCCommand[34] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2];
            _PLCCommand[35] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3];
            _PLCCommand[36] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4];
            _PLCCommand[37] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5];
            // 判断是否进行位操作
            if (analysis.Content1.getDataType() == 1) {
                _PLCCommand[38] = MelsecHelper.BuildBytesFromData( value.length)[0];                                                      // 软元件点数
                _PLCCommand[39] = MelsecHelper.BuildBytesFromData( value.length)[1];
                _PLCCommand[40] = MelsecHelper.BuildBytesFromData( value.length)[2];
                _PLCCommand[41] = MelsecHelper.BuildBytesFromData( value.length)[3];
            } else {
                _PLCCommand[38] = MelsecHelper.BuildBytesFromData( (value.length / 4))[0];                                                      // 软元件点数
                _PLCCommand[39] = MelsecHelper.BuildBytesFromData( (value.length / 4))[1];
                _PLCCommand[40] = MelsecHelper.BuildBytesFromData( (value.length / 4))[2];
                _PLCCommand[41] = MelsecHelper.BuildBytesFromData( (value.length / 4))[3];
            }
            System.arraycopy(value,0,_PLCCommand,42,value.length);
            return OperateResultExOne.CreateSuccessResult(_PLCCommand);
        }
        catch (Exception ex){
            return new OperateResultExOne<>(ex.getMessage());
        }
    }
    /**
     * 从PLC反馈的数据中提取出实际的数据内容,需要传入反馈数据,是否位读取
     * @param response 反馈的数据内容
     * @param isBit 是否位读取
     * @return 解析后的结果对象
     */
    public static OperateResultExOne<byte[]> ExtractActualData( byte[] response, boolean isBit )
    {
        if (isBit)
        {
            // 位读取
            byte[] Content = new byte[response.length - 22];
            for (int i = 22; i < response.length; i++)
            {
                if (response[i] == 0x30)
                {
                    Content[i - 22] = 0x00;
                }
                else
                {
                    Content[i - 22] = 0x01;
                }
            }
            return OperateResultExOne.CreateSuccessResult( Content );
        }
        else
        {
            // 字读取
            byte[] Content = new byte[(response.length - 22) / 2];
            for (int i = 0; i < Content.length / 2; i++)
            {
                int tmp = Integer.parseInt( Utilities.getString( response, i * 4 + 22, 4 ,"ASCII"), 16 );
                byte[] buffer = Utilities.getBytes(tmp);
                Content[i*2+0] = buffer[0];
                Content[i*2+1] = buffer[1];
            }
            return OperateResultExOne.CreateSuccessResult( Content );
        }
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecMcDataType.java
New file
@@ -0,0 +1,122 @@
package com.zy.common.HslCommunication.Profinet.Melsec;
/**
 * 三菱的数据类型
 */
public class MelsecMcDataType {
    /**
     * 如果您清楚类型代号,可以根据值进行扩展
     * @param code 数据类型的代号
     * @param type 0或1,默认为0
     * @param asciiCode ASCII格式的类型信息
     * @param fromBase 指示地址的多少进制的,10或是16
     */
    public MelsecMcDataType( byte code, byte type, String asciiCode, int fromBase )
    {
        DataCode = code;
        AsciiCode = asciiCode;
        FromBase = fromBase;
        if (type < 2) DataType = type;
    }
    private byte DataCode = 0x00;                   // 类型代号
    private byte DataType = 0x00;                   // 数据类型
    private String AsciiCode = "";                  // ascii格式通信的字符
    private int FromBase = 0;                       // 类型
    /**
     * 数据的类型代号
     * @return
     */
    public byte getDataCode() {
        return DataCode;
    }
    /**
     * 字访问还是位访问,0表示字,1表示位
     * @return
     */
    public byte getDataType() {
        return DataType;
    }
    /**
     * 当以ASCII格式通讯时的类型描述
     * @return
     */
    public String getAsciiCode() {
        return AsciiCode;
    }
    /**
     * 指示地址是10进制,还是16进制的
     * @return
     */
    public int getFromBase() {
        return FromBase;
    }
    /**
     * X输入寄存器
     */
    public final static MelsecMcDataType X = new MelsecMcDataType( (byte) (0x9C), (byte) (0x01), "X*", 16 );
    /**
     * Y输出寄存器
     */
    public final static MelsecMcDataType Y = new MelsecMcDataType( (byte) (0x9D), (byte) (0x01), "Y*", 16 );
    /**
     * M中间寄存器
     */
    public final static MelsecMcDataType M = new MelsecMcDataType( (byte) (0x90), (byte) (0x01), "M*", 10 );
    /**
     * D数据寄存器
     */
    public final static MelsecMcDataType D = new MelsecMcDataType( (byte) (0xA8), (byte) (0x00), "D*", 10 );
    /**
     * W链接寄存器
     */
    public final static MelsecMcDataType W = new MelsecMcDataType( (byte) (0xB4), (byte) (0x00), "W*", 16 );
    /**
     * L锁存继电器
     */
    public final static MelsecMcDataType L = new MelsecMcDataType( (byte) (0x92), (byte) (0x01), "L*", 10 );
    /**
     * F报警器
     */
    public final static MelsecMcDataType F = new MelsecMcDataType( (byte) (0x93), (byte) (0x01), "F*", 10 );
    /**
     * V边沿继电器
     */
    public final static MelsecMcDataType V = new MelsecMcDataType( (byte) (0x94), (byte) (0x01), "V*", 10 );
    /**
     * B链接继电器
     */
    public final static MelsecMcDataType B = new MelsecMcDataType( (byte) (0xA0), (byte) (0x01), "B*", 16 );
    /**
     * R文件寄存器
     */
    public final static MelsecMcDataType R = new MelsecMcDataType( (byte) (0xAF), (byte) (0x00), "R*", 10 );
    /**
     * S步进继电器
     */
    public final static MelsecMcDataType S = new MelsecMcDataType( (byte) (0x98), (byte) (0x01), "S*", 10 );
    /**
     * 变址寄存器
     */
    public final static MelsecMcDataType Z = new MelsecMcDataType( (byte) (0xCC), (byte) (0x00), "Z*", 10 );
    /**
     * 定时器的值
     */
    public final static MelsecMcDataType T = new MelsecMcDataType( (byte) (0xC2), (byte) (0x00), "TN", 10 );
    /**
     * 计数器的值
     */
    public final static MelsecMcDataType C = new MelsecMcDataType( (byte) (0xC5), (byte) (0x00), "CN", 10 );
}
src/main/java/com/zy/common/HslCommunication/Profinet/Melsec/MelsecMcNet.java
New file
@@ -0,0 +1,378 @@
package com.zy.common.HslCommunication.Profinet.Melsec;
import com.zy.common.HslCommunication.Core.IMessage.MelsecQnA3EBinaryMessage;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.RegularByteTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
/**
 * 三菱的实际数据交互类
 */
public class MelsecMcNet extends NetworkDeviceBase<MelsecQnA3EBinaryMessage,RegularByteTransform> {
    /**
     * 实例化三菱的Qna兼容3E帧协议的通讯对象
     */
    public MelsecMcNet() {
        WordLength = 1;
    }
    /**
     * 实例化一个三菱的Qna兼容3E帧协议的通讯对象
     *
     * @param ipAddress PLCd的Ip地址
     * @param port      PLC的端口
     */
    public MelsecMcNet(String ipAddress, int port) {
        WordLength = 1;
        super.setIpAddress(ipAddress);
        super.setPort(port);
    }
    private byte NetworkNumber = 0x00;                       // 网络号
    private byte NetworkStationNumber = 0x00;                // 网络站号
    /**
     * 获取网络号
     *
     * @return 网络号
     */
    public byte getNetworkNumber() {
        return NetworkNumber;
    }
    /**
     * 设置网络号
     *
     * @param networkNumber 网络号
     */
    public void setNetworkNumber(byte networkNumber) {
        NetworkNumber = networkNumber;
    }
    /**
     * 获取网络站号
     *
     * @return 网络站号
     */
    public byte getNetworkStationNumber() {
        return NetworkStationNumber;
    }
    /**
     * 设置网络站号
     *
     * @param networkStationNumber 网络站号
     */
    public void setNetworkStationNumber(byte networkStationNumber) {
        NetworkStationNumber = networkStationNumber;
    }
    /**
     * 从三菱PLC中读取想要的数据,返回读取结果
     * @param address 读取地址,格式为"M100","D100","W1A0"
     * @param length 读取的数据长度,字最大值960,位最大值7168
     * @return 带成功标志的结果数据对象
     */
    @Override
    public OperateResultExOne<byte[]> Read(String address, short length) {
        // 获取指令
        OperateResultExOne<byte[]> command = BuildReadCommand( address, length, NetworkNumber, NetworkStationNumber );
        if (!command.IsSuccess) return OperateResultExOne.CreateFailedResult( command );
        // 核心交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer( command.Content );
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult( read );
        // 错误代码验证
        int errorCode = Utilities.getShort(read.Content, 9);
        if (errorCode != 0) return new OperateResultExOne<>( errorCode, StringResources.Language.MelsecPleaseReferToManulDocument() );
        // 数据解析,需要传入是否使用位的参数
        return ExtractActualData( read.Content, command.Content[13] == 1 );
    }
    /**
     * 从三菱PLC中批量读取位软元件,返回读取结果
     * @param address 起始地址
     * @param length 读取的长度
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<boolean[]> ReadBool(String address, short length) {
        // 解析地址
        OperateResultExTwo<MelsecMcDataType, Short> analysis = MelsecHelper.McAnalysisAddress( address );
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult( analysis );
        // 位读取校验
        if (analysis.Content1.getDataType() == 0x00) return new OperateResultExOne<boolean[]>( 0, StringResources.Language.MelsecReadBitInfo() );
        // 核心交互
        OperateResultExOne<byte[]> read = Read( address, length );
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult( read );
        // 转化bool数组
        boolean[] result = new boolean[read.Content.length];
        for(int i=0;i<result.length;i++){
            if(read.Content[i] == 0x01) result[i] = true;
        }
        return OperateResultExOne.CreateSuccessResult( result );
    }
    /**
     * 从三菱PLC中批量读取位软元件,返回读取结果
     * @param address 起始地址
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<Boolean> ReadBool(String address) {
        OperateResultExOne<boolean[]> read = ReadBool(address, (short) 1);
        if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult(read);
        return OperateResultExOne.CreateSuccessResult(read.Content[0]);
    }
    /**
     * 向PLC写入数据,数据格式为原始的字节类型
     * @param address 起始地址
     * @param value 原始数据
     * @return 结果
     */
    @Override
    public OperateResult Write(String address, byte[] value) {
        // 解析指令
        OperateResultExOne<byte[]> command = BuildWriteCommand( address, value, NetworkNumber, NetworkStationNumber );
        if (!command.IsSuccess) return command;
        // 核心交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer( command.Content );
        if (!read.IsSuccess) return read;
        // 错误码校验
        short ErrorCode = Utilities.getShort(read.Content, 9);
        if (ErrorCode != 0) return new OperateResultExOne<byte[]>( ErrorCode, StringResources.Language.MelsecPleaseReferToManulDocument() );
        // 成功
        return OperateResult.CreateSuccessResult( );
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
     * @param address 要写入的数据地址
     * @param value 要写入的实际数据,长度为8的倍数
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean value) {
        return Write(address, new boolean[]{value});
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入M100,values[0]对应M100
     * @param address 要写入的数据地址
     * @param values 要写入的实际数据,可以指定任意的长度
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean[] values) {
        byte[] buffer = new byte[values.length];
        for (int i = 0; i < values.length; i++) {
            buffer[i] = values[i] ? (byte) 0x01 : (byte) 0x00;
        }
        return Write(address, buffer);
    }
    /**
     * 获取当前对象的字符串标识形式
     * @return 字符串信息
     */
    @Override
    public String toString() {
        return "MelsecMcNet";
    }
    /**
     * 根据类型地址长度确认需要读取的指令头
     * @param address 起始地址
     * @param length 长度
     * @return 带有成功标志的指令数据
     */
    public static OperateResultExOne<byte[]> BuildReadCommand(String address, short length) {
        return BuildReadCommand(address,length,(byte) 0,(byte)0);
    }
    /**
     * 根据类型地址长度确认需要读取的指令头
     * @param address 起始地址
     * @param length 长度
     * @param networkNumber 网络号
     * @param networkStationNumber 网络站号
     * @return 带有成功标志的指令数据
     */
    public static OperateResultExOne<byte[]> BuildReadCommand(String address, short length, byte networkNumber, byte networkStationNumber) {
        OperateResultExTwo<MelsecMcDataType, Short> analysis = MelsecHelper.McAnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis);
        byte[] _PLCCommand = new byte[21];
        _PLCCommand[0] = 0x50;                         // 副标题
        _PLCCommand[1] = 0x00;
        _PLCCommand[2] = networkNumber;                // 网络号
        _PLCCommand[3] = (byte) (0xFF);                         // PLC编号
        _PLCCommand[4] = (byte) (0xFF);
        _PLCCommand[5] = 0x03;
        _PLCCommand[6] = networkStationNumber;         // 目标模块站号
        _PLCCommand[7] = 0x0C;                         // 请求数据长度
        _PLCCommand[8] = 0x00;
        _PLCCommand[9] = 0x0A;                         // CPU监视定时器
        _PLCCommand[10] = 0x00;
        _PLCCommand[11] = 0x01;                        // 批量读取数据命令
        _PLCCommand[12] = 0x04;
        _PLCCommand[13] = analysis.Content1.getDataType();               // 以点为单位还是字为单位成批读取
        _PLCCommand[14] = 0x00;
        _PLCCommand[15] = (byte) (analysis.Content2 % 256);       // 起始地址的地位
        _PLCCommand[16] = (byte) (analysis.Content2 / 256);
        _PLCCommand[17] = 0x00;
        _PLCCommand[18] = analysis.Content1.getDataCode();               // 指明读取的数据
        _PLCCommand[19] = (byte) (length % 256);        // 软元件长度的地位
        _PLCCommand[20] = (byte) (length / 256);
        return OperateResultExOne.CreateSuccessResult(_PLCCommand);
    }
    /**
     * 根据类型地址以及需要写入的数据来生成指令头
     * @param address 起始地址
     * @param value 值
     * @return 结果
     */
    public static OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] value) {
        return BuildWriteCommand(address,value,(byte)0,(byte)0);
    }
    /**
     * 根据类型地址以及需要写入的数据来生成指令头
     * @param address 起始地址
     * @param value 值
     * @param networkNumber 网络号
     * @param networkStationNumber 网络站号
     * @return 结果
     */
    public static OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] value, byte networkNumber, byte networkStationNumber) {
        OperateResultExTwo<MelsecMcDataType, Short> analysis = MelsecHelper.McAnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis);
        int length = -1;
        if (analysis.Content1.getDataType() == 1)
        {
            // 按照位写入的操作,数据需要重新计算
            length = value.length;
            value = MelsecHelper.TransBoolArrayToByteData( value );
        }
        byte[] _PLCCommand = new byte[21 + value.length];
        _PLCCommand[0] = 0x50;                                          // 副标题
        _PLCCommand[1] = 0x00;
        _PLCCommand[2] = networkNumber;                                 // 网络号
        _PLCCommand[3] = (byte) (0xFF);                                          // PLC编号
        _PLCCommand[4] = (byte) (0xFF);                                          // 目标模块IO编号
        _PLCCommand[5] = 0x03;
        _PLCCommand[6] = networkStationNumber;                          // 目标模块站号
        _PLCCommand[7] = (byte) ((_PLCCommand.length - 9) % 256);        // 请求数据长度
        _PLCCommand[8] = (byte) ((_PLCCommand.length - 9) / 256);
        ;
        _PLCCommand[9] = 0x0A;                                          // CPU监视定时器
        _PLCCommand[10] = 0x00;
        _PLCCommand[11] = 0x01;                                         // 批量读取数据命令
        _PLCCommand[12] = 0x14;
        _PLCCommand[13] = analysis.Content1.getDataType();                   // 以点为单位还是字为单位成批读取
        _PLCCommand[14] = 0x00;
        _PLCCommand[15] = (byte) (analysis.Content2 % 256);
        ;            // 起始地址的地位
        _PLCCommand[16] = (byte) (analysis.Content2 / 256);
        _PLCCommand[17] = 0x00;
        _PLCCommand[18] = analysis.Content1.getDataCode();                   // 指明写入的数据
        // 判断是否进行位操作
        if (analysis.Content1.getDataType() == 1) {
            if (length > 0) {
                _PLCCommand[19] = (byte) (length % 256);                 // 软元件长度的地位
                _PLCCommand[20] = (byte) (length / 256);
            } else {
                _PLCCommand[19] = (byte) (value.length * 2 % 256);        // 软元件长度的地位
                _PLCCommand[20] = (byte) (value.length * 2 / 256);
            }
        } else {
            _PLCCommand[19] = (byte) (value.length / 2 % 256);            // 软元件长度的地位
            _PLCCommand[20] = (byte) (value.length / 2 / 256);
        }
        System.arraycopy(value, 0, _PLCCommand, 21, value.length);
        return OperateResultExOne.CreateSuccessResult(_PLCCommand);
    }
    /**
     * 从PLC反馈的数据中提取出实际的数据内容,需要传入反馈数据,是否位读取
     * @param response 反馈的数据内容
     * @param isBit 是否位读取
     * @return 解析后的结果对象
     */
    public static OperateResultExOne<byte[]> ExtractActualData( byte[] response, boolean isBit )
    {
        if (isBit)
        {
            // 位读取
            byte[] Content = new byte[(response.length - 11) * 2];
            for (int i = 11; i < response.length; i++)
            {
                if ((response[i] & 0x10) == 0x10)
                {
                    Content[(i - 11) * 2 + 0] = 0x01;
                }
                if ((response[i] & 0x01) == 0x01)
                {
                    Content[(i - 11) * 2 + 1] = 0x01;
                }
            }
            return OperateResultExOne.CreateSuccessResult( Content );
        }
        else
        {
            // 字读取
            byte[] Content = new byte[response.length - 11];
            System.arraycopy(response,11,Content,0,Content.length);
            return OperateResultExOne.CreateSuccessResult( Content );
        }
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Omron/OmronFinsDataType.java
New file
@@ -0,0 +1,66 @@
package com.zy.common.HslCommunication.Profinet.Omron;
/**
 * 欧姆龙的Fins协议的数据类型
 */
public class OmronFinsDataType
{
    /**
     * 实例化一个Fins的数据类型
     * @param bitCode 位操作的指令
     * @param wordCode 字操作的指令
     */
    public OmronFinsDataType( byte bitCode, byte wordCode )
    {
        BitCode = bitCode;
        WordCode = wordCode;
    }
    /**
     * 获取进行位操作的指令
     * @return
     */
    public byte getBitCode() {
        return BitCode;
    }
    /**
     * 进行字操作的指令
     * @return
     */
    public byte getWordCode() {
        return WordCode;
    }
    private byte BitCode = 0;
    private byte WordCode = 0;
    /**
     * DM Area
     */
    public static final OmronFinsDataType DM = new OmronFinsDataType( (byte) 0x02, (byte) 0x82 );
    /**
     * CIO Area
     */
    public static final OmronFinsDataType CIO = new OmronFinsDataType(  (byte)0x30,  (byte)0xB0 );
    /**
     * Work Area
     */
    public static final OmronFinsDataType WR = new OmronFinsDataType(  (byte)0x31,  (byte)0xB1 );
    /**
     * Holding Bit Area
     */
    public static final OmronFinsDataType HR = new OmronFinsDataType(  (byte)0x32,  (byte)0xB2 );
    /**
     * Auxiliary Bit Area
     */
    public static final OmronFinsDataType AR = new OmronFinsDataType(  (byte)0x33,  (byte)0xB3 );
}
src/main/java/com/zy/common/HslCommunication/Profinet/Omron/OmronFinsNet.java
New file
@@ -0,0 +1,529 @@
package com.zy.common.HslCommunication.Profinet.Omron;
import com.zy.common.HslCommunication.Core.IMessage.FinsMessage;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.ReverseWordTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
import java.net.Socket;
/**
 * 欧姆龙Fins帧协议通讯类
 */
public class OmronFinsNet extends NetworkDeviceBase<FinsMessage,ReverseWordTransform> {
    /**
     * 实例化一个欧姆龙Fins帧协议的通讯对象
     */
    public OmronFinsNet() {
        WordLength = 1;
    }
    /**
     * 实例化一个欧姆龙Fins帧协议的通讯对象
     * @param ipAddress PLCd的Ip地址
     * @param port PLC的端口
     */
    public OmronFinsNet(String ipAddress, int port) {
        WordLength = 1;
        setIpAddress(ipAddress);
        setPort(port);
    }
    /**
     * 信息控制字段,默认0x80
     */
    public byte ICF = (byte) 0x80;
    /**
     * 系统使用的内部信息
     */
    public byte RSV = 0x00;
    /**
     * 网络层信息,默认0x02,如果有八层消息,就设置为0x07
     */
    public byte GCT = 0x02;
    /**
     * PLC的网络号地址,默认0x00
     */
    public byte DNA = 0x00;
    /**
     * PLC的节点地址,默认0x13
     */
    public byte DA1 = 0x13;
    /**
     * PLC的单元号地址
     */
    public byte DA2 = 0x00;
    /**
     * 上位机的网络号地址
     */
    public byte SNA = 0x00;
    private byte computerSA1 = 0x0B;
    /**
     * 上位机的节点地址,默认0x0B
     *
     * @return byte数据
     */
    public byte getSA1() {
        return computerSA1;
    }
    /**
     * 设置上位机的节点地址,默认0x0B
     *
     * @param computerSA1
     */
    public void setSA1(byte computerSA1) {
        this.computerSA1 = computerSA1;
        handSingle[19] = computerSA1;
    }
    /**
     * 上位机的单元号地址
     */
    public byte SA2 = 0x00;
    /**
     * 设备的标识号
     */
    public byte SID = 0x00;
    /**
     * 将普通的指令打包成完整的指令
     * @param cmd 指令
     * @return 字节
     */
    private byte[] PackCommand(byte[] cmd) {
        byte[] buffer = new byte[26 + cmd.length];
        System.arraycopy(handSingle, 0, buffer, 0, 4);
        byte[] tmp = Utilities.getBytes(buffer.length - 8);
        Utilities.bytesReverse(tmp);    // 翻转数组
        System.arraycopy(tmp, 0, buffer, 4, tmp.length);
        buffer[11] = 0x02;
        buffer[16] = ICF;
        buffer[17] = RSV;
        buffer[18] = GCT;
        buffer[19] = DNA;
        buffer[20] = DA1;
        buffer[21] = DA2;
        buffer[22] = SNA;
        buffer[23] = getSA1();
        buffer[24] = SA2;
        buffer[25] = SID;
        System.arraycopy(cmd, 0, buffer, 26, cmd.length);
        return buffer;
    }
    /**
     * 根据类型地址长度确认需要读取的指令头
     * @param address 起始地址
     * @param length 长度
     * @param isBit 是否是位读取
     * @return 带有成功标志的指令数据
     */
    private OperateResultExOne<byte[]> BuildReadCommand(String address, int length, boolean isBit) {
        OperateResultExTwo<OmronFinsDataType, byte[]> analysis = AnalysisAddress(address, isBit);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        byte[] _PLCCommand = new byte[8];
        _PLCCommand[0] = 0x01;
        _PLCCommand[1] = 0x01;
        if (isBit) {
            _PLCCommand[2] = analysis.Content1.getBitCode();
        } else {
            _PLCCommand[2] = analysis.Content1.getWordCode();
        }
        System.arraycopy(analysis.Content2, 0, _PLCCommand, 3, analysis.Content2.length);
        _PLCCommand[6] = (byte) (length / 256);
        _PLCCommand[7] = (byte) (length % 256);
        return OperateResultExOne.CreateSuccessResult( PackCommand( _PLCCommand ) );
    }
    /**
     *
     * @param address 根据类型地址以及需要写入的数据来生成指令头
     * @param value 起始地址
     * @param isBit 是否是位操作
     * @return 结果
     */
    private OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] value, boolean isBit) {
        OperateResultExTwo<OmronFinsDataType, byte[]> analysis = AnalysisAddress(address, isBit);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        byte[] _PLCCommand = new byte[8 + value.length];
        _PLCCommand[0] = 0x01;    // 读取存储区数据
        _PLCCommand[1] = 0x02;
        if (isBit) {
            _PLCCommand[2] = analysis.Content1.getBitCode();
        } else {
            _PLCCommand[2] = analysis.Content1.getWordCode();
        }
        System.arraycopy(analysis.Content2, 0, _PLCCommand, 3, analysis.Content2.length);
        if (isBit) {
            _PLCCommand[6] = (byte) (value.length / 256);
            _PLCCommand[7] = (byte) (value.length % 256);
        } else {
            _PLCCommand[6] = (byte) (value.length / 2 / 256);
            _PLCCommand[7] = (byte) (value.length / 2 % 256);
        }
        System.arraycopy(value, 0, _PLCCommand, 8, value.length);
        return OperateResultExOne.CreateSuccessResult( PackCommand( _PLCCommand ) );
    }
    /**
     * 在连接上欧姆龙PLC后,需要进行一步握手协议
     * @param socket 网络套接字
     * @return 结果对象
     */
    @Override
    protected OperateResult InitializationOnConnect(Socket socket) {
        // handSingle就是握手信号字节
        OperateResultExTwo<byte[], byte[]> read = ReadFromCoreServerBase(socket, handSingle);
        if (!read.IsSuccess) return read;
        // 检查返回的状态
        byte[] buffer = new byte[4];
        buffer[0] = read.Content2[7];
        buffer[1] = read.Content2[6];
        buffer[2] = read.Content2[5];
        buffer[3] = read.Content2[4];
        int status = Utilities.getInt(buffer, 0);
        if (status != 0) return new OperateResult( status, GetStatusDescription( status ) );
        // 提取PLC的节点地址
        if (read.Content2.length >= 16) DA1 = read.Content2[15];
        return OperateResult.CreateSuccessResult();
    }
    /**
     * 从欧姆龙PLC中读取想要的数据,返回读取结果,读取单位为字
     * @param address 读取地址,格式为"D100","C100","W100","H100","A100"
     * @param length 读取的数据长度,字最大值960,位最大值7168
     * @return 带成功标志的结果数据对象
     */
    @Override
    public OperateResultExOne<byte[]> Read(String address, short length) {
        //获取指令
        OperateResultExOne<byte[]> command = BuildReadCommand(address, length, false);
        if (!command.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(command);
        // 核心数据交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content);
        if (!read.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(read);
        // 数据有效性分析
        OperateResultExOne<byte[]> valid = ResponseValidAnalysis(read.Content, true);
        if (!valid.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(valid);
        // 读取到了正确的数据
        return OperateResultExOne.CreateSuccessResult(valid.Content);
    }
    /**
     * 从欧姆龙PLC中批量读取位软元件,返回读取结果
     * @param address 读取地址,格式为"D100","C100","W100","H100","A100"
     * @param length 读取的长度
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<boolean[]> ReadBool(String address, short length) {
        //获取指令
        OperateResultExOne<byte[]> command = BuildReadCommand(address, length, true);
        if (!command.IsSuccess) return OperateResultExOne.<boolean[]>CreateFailedResult(command);
        // 核心数据交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content);
        if (!read.IsSuccess) return OperateResultExOne.<boolean[]>CreateFailedResult(read);
        // 数据有效性分析
        OperateResultExOne<byte[]> valid = ResponseValidAnalysis(read.Content, true);
        if (!valid.IsSuccess) return OperateResultExOne.<boolean[]>CreateFailedResult(valid);
        // 返回正确的数据信息
        boolean[] buffer = new boolean[valid.Content.length];
        for (int i = 0; i < valid.Content.length; i++) {
            buffer[i] = valid.Content[i] != 0x00;
        }
        return OperateResultExOne.CreateSuccessResult(buffer);
    }
    /**
     * 从欧姆龙PLC中批量读取位软元件,返回读取结果
     * @param address 读取地址,格式为"D100.0","C100.15","W100.7","H100.4","A100.9"
     * @return 带成功标志的结果数据对象
     */
    public OperateResultExOne<Boolean> ReadBool(String address) {
        OperateResultExOne<boolean[]> read = ReadBool(address, (short) 1);
        if (read.IsSuccess) {
            return OperateResultExOne.CreateSuccessResult(read.Content[0]);
        } else {
            return OperateResultExOne.<Boolean>CreateFailedResult(read);
        }
    }
    /**
     * 向PLC写入数据,数据格式为原始的字节类型
     * @param address 起始地址
     * @param value 原始数据
     * @return 结果
     */
    @Override
    public OperateResult Write(String address, byte[] value) {
        //获取指令
        OperateResultExOne<byte[]> command = BuildWriteCommand(address, value, false);
        if (!command.IsSuccess) return command;
        // 核心数据交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content);
        if (!read.IsSuccess) return read;
        // 数据有效性分析
        OperateResultExOne<byte[]> valid = ResponseValidAnalysis(read.Content, false);
        if (!valid.IsSuccess) return valid;
        // 成功
        return OperateResult.CreateSuccessResult();
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入D100,values[0]对应D100.0
     * @param address 要写入的数据地址
     * @param value 要写入的实际数据,长度为8的倍数
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean value) {
        return Write(address, new boolean[]{value});
    }
    /**
     * 向PLC中位软元件写入bool数组,返回值说明,比如你写入D100,values[0]对应D100.0
     * @param address 要写入的数据地址
     * @param values 要写入的实际数据,可以指定任意的长度
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean[] values) {
        OperateResult result = new OperateResult();
        byte[] buffer = new byte[values.length];
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] = values[i] ? (byte) 0x01 : (byte) 0x00;
        }
        // 获取指令
        OperateResultExOne<byte[]> command = BuildWriteCommand(address, buffer, true);
        if (!command.IsSuccess) return command;
        // 核心数据交互
        OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content);
        if (!read.IsSuccess) return read;
        // 数据有效性分析
        OperateResultExOne<byte[]> valid = ResponseValidAnalysis(read.Content, false);
        if (!valid.IsSuccess) return valid;
        // 写入成功
        return OperateResult.CreateSuccessResult();
    }
    // 握手信号
    // 46494E530000000C0000000000000000000000D6
    private final byte[] handSingle = new byte[]
            {
                    0x46, 0x49, 0x4E, 0x53, // FINS
                    0x00, 0x00, 0x00, 0x0C, // 后面的命令长度
                    0x00, 0x00, 0x00, 0x00, // 命令码
                    0x00, 0x00, 0x00, 0x00, // 错误码
                    0x00, 0x00, 0x00, 0x01  // 节点号
            };
    /**
     * 返回表示当前对象的字符串
     *
     * @return 字符串
     */
    @Override
    public String toString() {
        return "OmronFinsNet";
    }
    /**
     * 解析数据地址,Omron手册第188页
     * @param address 数据地址
     * @param isBit 是否是位地址
     * @return 结果类对象
     */
    public static OperateResultExTwo<OmronFinsDataType, byte[]> AnalysisAddress(String address, boolean isBit) {
        OperateResultExTwo<OmronFinsDataType, byte[]> result = new OperateResultExTwo<OmronFinsDataType, byte[]>();
        try {
            switch (address.charAt(0)) {
                case 'D':
                case 'd': {
                    // DM区数据
                    result.Content1 = OmronFinsDataType.DM;
                    break;
                }
                case 'C':
                case 'c': {
                    // CIO区数据
                    result.Content1 = OmronFinsDataType.CIO;
                    break;
                }
                case 'W':
                case 'w': {
                    // WR区
                    result.Content1 = OmronFinsDataType.WR;
                    break;
                }
                case 'H':
                case 'h': {
                    // HR区
                    result.Content1 = OmronFinsDataType.HR;
                    break;
                }
                case 'A':
                case 'a': {
                    // AR区
                    result.Content1 = OmronFinsDataType.AR;
                    break;
                }
                default:
                    throw new Exception(StringResources.Language.NotSupportedDataType());
            }
            if (isBit) {
                // 位操作
                String[] splits = address.substring(1).split("\\.");
                int addr = Integer.parseInt(splits[0]);
                result.Content2 = new byte[3];
                result.Content2[0] = Utilities.getBytes(addr)[1];
                result.Content2[1] = Utilities.getBytes(addr)[0];
                if (splits.length > 1) {
                    result.Content2[2] = Byte.parseByte(splits[1]);
                    if (result.Content2[2] > 15) {
                        throw new Exception(StringResources.Language.OmronAddressMustBeZeroToFiveteen());
                    }
                }
            } else {
                // 字操作
                int addr = Integer.parseInt(address.substring(1));
                result.Content2 = new byte[3];
                result.Content2[0] = Utilities.getBytes(addr)[1];
                result.Content2[1] = Utilities.getBytes(addr)[0];
            }
        } catch (Exception ex) {
            result.Message = ex.getMessage();
            return result;
        }
        result.IsSuccess = true;
        return result;
    }
    /**
     * 对于PLC的反馈数据,进行验证
     * @param response PLC反馈数据
     * @param isRead 是否处于读取状态
     * @return 成功的数据结果
     */
    public static OperateResultExOne<byte[]> ResponseValidAnalysis(byte[] response, boolean isRead) {
        // 数据有效性分析
        if (response.length >= 16) {
            // 提取错误码
            byte[] buffer = new byte[4];
            buffer[0] = response[15];
            buffer[1] = response[14];
            buffer[2] = response[13];
            buffer[3] = response[12];
            int err = Utilities.getInt(buffer, 0);
            if (err > 0) return new OperateResultExOne<byte[]>(err, GetStatusDescription(err));
            if (response.length >= 30) {
                err = response[28] * 256 + response[29];
                if (err > 0)  return new OperateResultExOne<byte[]>(err,StringResources.Language.OmronReceiveDataError());
                if (!isRead) {
                    // 写入操作
                    return OperateResultExOne.CreateSuccessResult(new byte[0]);
                } else {
                    // 读取操作
                    byte[] content = new byte[response.length - 30];
                    if (content.length > 0) {
                        System.arraycopy(response, 30, content, 0, content.length);
                    }
                    return OperateResultExOne.CreateSuccessResult(content);
                }
            }
        }
        return new OperateResultExOne<byte[]>( StringResources.Language.OmronReceiveDataError() );
    }
    /**
     * 获取错误信息的字符串描述文本
     * @param err 错误码
     * @return 文本描述
     */
    public static String GetStatusDescription( int err )
    {
        switch (err)
        {
            case 0: return StringResources.Language.OmronStatus0();
            case 1: return StringResources.Language.OmronStatus1();
            case 2: return StringResources.Language.OmronStatus2();
            case 3: return StringResources.Language.OmronStatus3();
            case 20: return StringResources.Language.OmronStatus20();
            case 21: return StringResources.Language.OmronStatus21();
            case 22: return StringResources.Language.OmronStatus22();
            case 23: return StringResources.Language.OmronStatus23();
            case 24: return StringResources.Language.OmronStatus24();
            case 25: return StringResources.Language.OmronStatus25();
            default: return StringResources.Language.UnknownError();
        }
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Siemens/SiemensFetchWriteNet.java
New file
@@ -0,0 +1,330 @@
package com.zy.common.HslCommunication.Profinet.Siemens;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.IMessage.FetchWriteMessage;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.ReverseBytesTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExThree;
import com.zy.common.HslCommunication.StringResources;
/**
 * 使用了Fetch/Write协议来和西门子进行通讯,该种方法需要在PLC侧进行一些配置
 */
public class SiemensFetchWriteNet extends NetworkDeviceBase<FetchWriteMessage, ReverseBytesTransform> {
    /**
     * 实例化一个西门子的Fetch/Write协议的通讯对象
     */
    public SiemensFetchWriteNet() {
        WordLength = 2;
    }
    /**
     * 实例化一个西门子的Fetch/Write协议的通讯对象
     *
     * @param ipAddress PLC的Ip地址
     * @param port      PLC的端口
     */
    public SiemensFetchWriteNet(String ipAddress, int port) {
        WordLength = 2;
        setIpAddress(ipAddress);
        setPort(port);
    }
    /**
     * 从PLC读取数据,地址格式为I100,Q100,DB20.100,M100,T100,C100,以字节为单位
     *
     * @param address 起始地址,格式为I100,M100,Q100,DB20.100,T100,C100
     * @param length  读取的数量,以字节为单位
     * @return 带有成功标志的字节信息
     */
    @Override
    public OperateResultExOne<byte[]> Read(String address, short length) {
        OperateResultExOne<byte[]> result = new OperateResultExOne<byte[]>();
        OperateResultExOne<byte[]> command = BuildReadCommand(address, length);
        if (!command.IsSuccess) {
            result.CopyErrorFromOther(command);
            return result;
        }
        OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content);
        if (read.IsSuccess) {
            if (read.Content[8] == 0x00) {
                // 分析结果
                byte[] buffer = new byte[read.Content.length - 16];
                System.arraycopy(read.Content, 16, buffer, 0, buffer.length);
                result.Content = buffer;
                result.IsSuccess = true;
            } else {
                result.ErrorCode = read.Content[8];
                result.Message = "发生了异常,具体信息查找Fetch/Write协议文档";
            }
        } else {
            result.ErrorCode = read.ErrorCode;
            result.Message = read.Message;
        }
        return result;
    }
    /**
     * 读取指定地址的byte数据
     *
     * @param address 起始地址,格式为I100,M100,Q100,DB20.100
     * @return 返回写入结果
     */
    public OperateResultExOne<Byte> ReadByte(String address) {
        return GetByteResultFromBytes(Read(address, (short) 1));
    }
    /**
     * 将数据写入到PLC数据,地址格式为I100,Q100,DB20.100,M100,以字节为单位
     *
     * @param address 起始地址,格式为I100,M100,Q100,DB20.100
     * @param value   写入的数据,长度根据data的长度来指示
     * @return 返回写入结果
     */
    @Override
    public OperateResult Write(String address, byte[] value) {
        OperateResult result = new OperateResult();
        OperateResultExOne<byte[]> command = BuildWriteCommand(address, value);
        if (!command.IsSuccess) {
            result.CopyErrorFromOther(command);
            return result;
        }
        OperateResultExOne<byte[]> write = ReadFromCoreServer(command.Content);
        if (write.IsSuccess) {
            if (write.Content[8] != 0x00) {
                // 写入异常
                result.Message = "写入数据异常,代号为:" + String.valueOf(write.Content[8]);
            } else {
                result.IsSuccess = true;  // 写入成功
            }
        } else {
            result.ErrorCode = write.ErrorCode;
            result.Message = write.Message;
        }
        return result;
    }
    /**
     * 向PLC中写入bool数组,返回值说明,比如你写入M100,那么data[0]对应M100.0
     *
     * @param address 要写入的数据地址
     * @param values  要写入的实际数据,长度为8的倍数
     * @return 返回写入结果
     */
    public OperateResult Write(String address, boolean[] values) {
        return Write(address, SoftBasic.BoolArrayToByte(values));
    }
    /**
     * 向PLC中写入byte数据,返回值说明
     *
     * @param address 要写入的数据地址
     * @param value   要写入的实际数据
     * @return 返回写入结果
     */
    public OperateResult Write(String address, byte value) {
        return Write(address, new byte[]{value});
    }
    /**
     * 返回表示当前对象的字符串
     *
     * @return 字符串
     */
    @Override
    public String toString() {
        return "SiemensFetchWriteNet";
    }
    /**
     * 计算特殊的地址信息
     *
     * @param address 字符串信息
     * @return 实际值
     */
    public static int CalculateAddressStarted(String address) {
        if (address.indexOf('.') < 0) {
            return Integer.parseInt(address);
        } else {
            String[] temp = address.split("\\.");
            return Integer.parseInt(temp[0]);
        }
    }
    /**
     * 解析数据地址,解析出地址类型,起始地址,DB块的地址
     *
     * @param address 数据地址
     * @return 解析出地址类型,起始地址,DB块的地址
     */
    public static OperateResultExThree<Byte, Integer, Integer> AnalysisAddress(String address) {
        OperateResultExThree<Byte, Integer, Integer> result = new OperateResultExThree<Byte, Integer, Integer>();
        try {
            result.Content3 = 0;
            if (address.indexOf(0) == 'I') {
                result.Content1 = 0x03;
                result.Content2 = CalculateAddressStarted(address.substring(1));
            } else if (address.indexOf(0) == 'Q') {
                result.Content1 = 0x04;
                result.Content2 = CalculateAddressStarted(address.substring(1));
            } else if (address.indexOf(0) == 'M') {
                result.Content1 = 0x02;
                result.Content2 = CalculateAddressStarted(address.substring(1));
            } else if (address.indexOf(0) == 'D' || address.substring(0, 2).equals("DB")) {
                result.Content1 = 0x01;
                String[] adds = address.split("\\.");
                if (address.indexOf(1) == 'B') {
                    result.Content3 = Integer.parseInt(adds[0].substring(2));
                } else {
                    result.Content3 = Integer.parseInt(adds[0].substring(1));
                }
                if (result.Content3 > 255) {
                    result.Message = StringResources.Language.SiemensDBAddressNotAllowedLargerThan255();
                    return result;
                }
                result.Content2 = CalculateAddressStarted(address.substring(address.indexOf('.') + 1));
            } else if (address.indexOf(0) == 'T') {
                result.Content1 = 0x07;
                result.Content2 = CalculateAddressStarted(address.substring(1));
            } else if (address.indexOf(0) == 'C') {
                result.Content1 = 0x06;
                result.Content2 = CalculateAddressStarted(address.substring(1));
            } else {
                return new OperateResultExThree<Byte, Integer, Integer>(StringResources.Language.NotSupportedDataType());
            }
        } catch (Exception ex) {
            result.Message = ex.getMessage();
            return result;
        }
        result.IsSuccess = true;
        return result;
    }
    /**
     * 生成一个读取字数据指令头的通用方法
     *
     * @param address 地址
     * @param count   长度
     * @return 带结果标识的指令
     */
    public static OperateResultExOne<byte[]> BuildReadCommand(String address, int count) {
        OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress(address);
        if (!analysis.IsSuccess) return  OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        byte[] _PLCCommand = new byte[16];
        _PLCCommand[0] = 0x53;
        _PLCCommand[1] = 0x35;
        _PLCCommand[2] = 0x10;
        _PLCCommand[3] = 0x01;
        _PLCCommand[4] = 0x03;
        _PLCCommand[5] = 0x05;
        _PLCCommand[6] = 0x03;
        _PLCCommand[7] = 0x08;
        // 指定数据区
        _PLCCommand[8] = analysis.Content1;
        _PLCCommand[9] = analysis.Content3.byteValue();
        // 指定数据地址
        _PLCCommand[10] = (byte) (analysis.Content2 / 256);
        _PLCCommand[11] = (byte) (analysis.Content2 % 256);
        if (analysis.Content1 == 0x01 || analysis.Content1 == 0x06 || analysis.Content1 == 0x07) {
            if (count % 2 != 0) {
                return new OperateResultExOne<byte[]>(StringResources.Language.SiemensReadLengthMustBeEvenNumber());
            } else {
                // 指定数据长度
                _PLCCommand[12] = (byte) (count / 2 / 256);
                _PLCCommand[13] = (byte) (count / 2 % 256);
            }
        } else {
            // 指定数据长度
            _PLCCommand[12] = (byte) (count / 256);
            _PLCCommand[13] = (byte) (count % 256);
        }
        _PLCCommand[14] = (byte) 0xff;
        _PLCCommand[15] = 0x02;
        return OperateResultExOne.CreateSuccessResult(_PLCCommand);
    }
    /**
     * 生成一个写入字节数据的指令
     *
     * @param address 地址
     * @param data    数据
     * @return 带结果标识的指令
     */
    public static OperateResultExOne<byte[]> BuildWriteCommand(String address, byte[] data) {
        if (data == null) data = new byte[0];
        OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress(address);
        if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(analysis);
        byte[] _PLCCommand = new byte[16 + data.length];
        _PLCCommand[0] = 0x53;
        _PLCCommand[1] = 0x35;
        _PLCCommand[2] = 0x10;
        _PLCCommand[3] = 0x01;
        _PLCCommand[4] = 0x03;
        _PLCCommand[5] = 0x03;
        _PLCCommand[6] = 0x03;
        _PLCCommand[7] = 0x08;
        // 指定数据区
        _PLCCommand[8] = analysis.Content1;
        _PLCCommand[9] = analysis.Content3.byteValue();
        // 指定数据地址
        _PLCCommand[10] = (byte) (analysis.Content2 / 256);
        _PLCCommand[11] = (byte) (analysis.Content2 % 256);
        if (analysis.Content1 == 0x01 || analysis.Content1 == 0x06 || analysis.Content1 == 0x07) {
            if (data.length % 2 != 0) {
                return new OperateResultExOne<byte[]>(StringResources.Language.SiemensReadLengthMustBeEvenNumber());
            } else {
                // 指定数据长度
                _PLCCommand[12] = (byte) (data.length / 2 / 256);
                _PLCCommand[13] = (byte) (data.length / 2 % 256);
            }
        } else {
            // 指定数据长度
            _PLCCommand[12] = (byte) (data.length / 256);
            _PLCCommand[13] = (byte) (data.length % 256);
        }
        _PLCCommand[14] = (byte) 0xff;
        _PLCCommand[15] = 0x02;
        // 放置数据
        System.arraycopy(data, 0, _PLCCommand, 16, data.length);
        return OperateResultExOne.<byte[]>CreateSuccessResult(_PLCCommand);
    }
}
src/main/java/com/zy/common/HslCommunication/Profinet/Siemens/SiemensPLCS.java
File was renamed from src/main/java/com/zy/gateway/core/domain/siemens/SiemensPLCS.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.domain.siemens;
package com.zy.common.HslCommunication.Profinet.Siemens;
/**
 * 西门子的PLC类型,目前支持的访问类型
src/main/java/com/zy/common/HslCommunication/Profinet/Siemens/SiemensS7Net.java
File was renamed from src/main/java/com/zy/gateway/core/net/siemens/SiemensS7Net.java
@@ -1,16 +1,15 @@
package com.zy.gateway.core.net.siemens;
package com.zy.common.HslCommunication.Profinet.Siemens;
import com.zy.gateway.core.StringResources;
import com.zy.gateway.core.base.SoftBasic;
import com.zy.gateway.core.domain.OperateResult;
import com.zy.gateway.core.domain.OperateResultExOne;
import com.zy.gateway.core.domain.OperateResultExThree;
import com.zy.gateway.core.domain.OperateResultExTwo;
import com.zy.gateway.core.domain.siemens.S7Message;
import com.zy.gateway.core.domain.siemens.SiemensPLCS;
import com.zy.gateway.core.net.NetworkDeviceBase;
import com.zy.gateway.core.transfer.ReverseBytesTransform;
import com.zy.gateway.core.utils.Utilities;
import com.zy.common.HslCommunication.BasicFramework.SoftBasic;
import com.zy.common.HslCommunication.Core.IMessage.S7Message;
import com.zy.common.HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import com.zy.common.HslCommunication.Core.Transfer.ReverseBytesTransform;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Core.Types.OperateResultExThree;
import com.zy.common.HslCommunication.Core.Types.OperateResultExTwo;
import com.zy.common.HslCommunication.StringResources;
import com.zy.common.HslCommunication.Utilities;
import java.io.ByteArrayOutputStream;
import java.net.Socket;
@@ -195,7 +194,7 @@
            return OperateResultExOne.CreateSuccessResult(buffer);
        }
        else {
            return new OperateResultExOne<byte[]>(read.ErrorCode, StringResources.Language.SiemensDataLengthCheckFailed());
            return new OperateResultExOne<byte[]>(read.ErrorCode,StringResources.Language.SiemensDataLengthCheckFailed());
        }
    }
src/main/java/com/zy/common/HslCommunication/Utilities.java
File was renamed from src/main/java/com/zy/gateway/core/utils/Utilities.java
@@ -1,4 +1,4 @@
package com.zy.gateway.core.utils;
package com.zy.common.HslCommunication;
import java.io.ByteArrayOutputStream;
src/main/java/com/zy/common/Main.java
New file
@@ -0,0 +1,376 @@
package com.zy.common;
import com.zy.common.HslCommunication.Core.Net.NetHandle;
import com.zy.common.HslCommunication.Core.Transfer.DataFormat;
import com.zy.common.HslCommunication.Core.Types.ActionOperateExThree;
import com.zy.common.HslCommunication.Core.Types.ActionOperateExTwo;
import com.zy.common.HslCommunication.Core.Types.OperateResult;
import com.zy.common.HslCommunication.Core.Types.OperateResultExOne;
import com.zy.common.HslCommunication.Enthernet.ComplexNet.NetComplexClient;
import com.zy.common.HslCommunication.Enthernet.PushNet.NetPushClient;
import com.zy.common.HslCommunication.Enthernet.SimplifyNet.NetSimplifyClient;
import com.zy.common.HslCommunication.ModBus.ModbusTcpNet;
import com.zy.common.HslCommunication.Profinet.Melsec.MelsecA1ENet;
import com.zy.common.HslCommunication.Profinet.Melsec.MelsecMcAsciiNet;
import com.zy.common.HslCommunication.Profinet.Melsec.MelsecMcNet;
import com.zy.common.HslCommunication.Profinet.Siemens.SiemensPLCS;
import com.zy.common.HslCommunication.Profinet.Siemens.SiemensS7Net;
import java.util.Arrays;
public class Main {
    public static void main(String[] args) throws InterruptedException {
        SiemesTest();
        try {
            //Constructor[] aa = Integer.class.getDeclaredConstructors();
            //int i = (Integer) (aa[1].newInstance("1"));
            //System.out.println(Utilities.bytes2HexString( Utilities.getBytes(String.format("%04x",100),"ASCII")));
            //System.out.println(i);
            //System.out.println(Arrays.toString("123".split("\\." )));
            //ModbusTcpTets();
            //MelsecMcNet melsec_net = new MelsecMcNet("192.168.8.12", 6001);
            //System.out.println(melsec_net.ReadInt16("D100").Content);
            SiemensS7Net siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200,"192.168.8.12");
            OperateResult write = siemensS7Net.Write("M200",(short)200);
            if(!write.IsSuccess){
                System.out.println("Write failed:"+write.Message);
            }
            OperateResultExOne<Short> read = siemensS7Net.ReadInt16("M200");
            if(read.IsSuccess){
                System.out.println("Value:"+read.Content.toString());
            }
            else {
                System.out.println("Read failed:"+read.Message);
            }
        }
        catch (Exception ex){
            System.out.println(ex.getMessage());
        }
        Thread.sleep(1000);
    }
    /**
     * 简单网络客户端
     */
    public static void NetSimplifyClientTest() {
        NetSimplifyClient client = new NetSimplifyClient("127.0.0.1", 12345);
        OperateResultExOne<String> read = client.ReadFromServer(new NetHandle(2), "测试数据");
        if (read.IsSuccess) {
            System.out.println(read.Content);
        } else {
            System.out.println("读取失败:" + read.Message);
        }
    }
    /**
     * 三菱   A
     */
    private static void MelsecA1ETest() {
        MelsecA1ENet melsec_net = new MelsecA1ENet("192.168.0.100", 5000);
        melsec_net.SetPersistentConnection();
        boolean[] M100 = melsec_net.ReadBool("M100", (short) 1).Content;           // 读取M100是否通,十进制地址
        boolean[] X20 = melsec_net.ReadBool("X20", (short) 1).Content;             // 读取X20是否通,八进制地址
        boolean[] Y20 = melsec_net.ReadBool("Y20", (short) 1).Content;             // 读取Y20是否通,八进制地址
        short short_D1000 = melsec_net.ReadInt16("D1000").Content;                 // 读取D1000的short值
        int int_D1000 = melsec_net.ReadInt32("D1000").Content;                     // 读取D1000-D1001组成的int数据
        float float_D1000 = melsec_net.ReadFloat("D1000").Content;                 // 读取D1000-D1001组成的float数据
        long long_D1000 = melsec_net.ReadInt64("D1000").Content;                   // 读取D1000-D1003组成的long数据
        double double_D1000 = melsec_net.ReadDouble("D1000").Content;              // 读取D1000-D1003组成的double数据
        String str_D1000 = melsec_net.ReadString("D1000", (short) 10).Content;     // 读取D1000-D1009组成的条码数据
        melsec_net.Write("M100", new boolean[]{true});                            // 写入M100为通
        melsec_net.Write("Y20", new boolean[]{true});                             // 写入Y20为通
        melsec_net.Write("X20", new boolean[]{true});                             // 写入X20为通
        melsec_net.Write("D1000", (short) 1234);                                  // 写入D1000  short值  ,W3C0,R3C0 效果是一样的
        melsec_net.Write("D1000", 1234566);                                // 写入D1000  int值
        melsec_net.Write("D1000", 123.456f);                               // 写入D1000  float值
        melsec_net.Write("D1000", 123.456d);                               // 写入D1000  double值
        melsec_net.Write("D1000", 123456661235123534L);                    // 写入D1000  long值
        melsec_net.Write("D1000", "K123456789");                           // 写入D1000  string值
        OperateResultExOne<boolean[]> read = melsec_net.ReadBool("M100", (short) 10);
        if (read.IsSuccess) {
            boolean m100 = read.Content[0];
            boolean m101 = read.Content[1];
            boolean m102 = read.Content[2];
            boolean m103 = read.Content[3];
            boolean m104 = read.Content[4];
            boolean m105 = read.Content[5];
            boolean m106 = read.Content[6];
            boolean m107 = read.Content[7];
            boolean m108 = read.Content[8];
            boolean m109 = read.Content[9];
        } else {
            System.out.print("读取失败:" + read.Message);
        }
        OperateResultExOne<byte[]> read1 = melsec_net.Read("D100", (short) 5);
        if (read1.IsSuccess) {
            short D100 = melsec_net.getByteTransform().TransInt16(read1.Content, 0);
            short D101 = melsec_net.getByteTransform().TransInt16(read1.Content, 2);
            short D102 = melsec_net.getByteTransform().TransInt16(read1.Content, 4);
            short D103 = melsec_net.getByteTransform().TransInt16(read1.Content, 6);
            short D104 = melsec_net.getByteTransform().TransInt16(read1.Content, 8);
        } else {
            System.out.print("读取失败:" + read1.Message);
        }
        //解析复杂数据
        OperateResultExOne<byte[]> read3 = melsec_net.Read("D4000", (short) 10);
        if (read3.IsSuccess) {
            double 温度 = melsec_net.getByteTransform().TransInt16(read3.Content, 0) / 10d;//索引很重要
            double 压力 = melsec_net.getByteTransform().TransInt16(read3.Content, 2) / 100d;
            boolean IsRun = melsec_net.getByteTransform().TransInt16(read3.Content, 4) == 1;
            int 产量 = melsec_net.getByteTransform().TransInt32(read3.Content, 6);
            String 规格 = melsec_net.getByteTransform().TransString(read3.Content, 10, 10, "ascii");
        } else {
            System.out.print("读取失败:" + read3.Message);
        }
        // 写入测试,M100-M104 写入测试 此处写入后M100:通 M101:断 M102:断 M103:通 M104:通
        boolean[] values = new boolean[]{true, false, false, true, true};
        OperateResult write = melsec_net.Write("M100", values);
        if (write.IsSuccess) {
            System.out.print("写入成功");
        } else {
            System.out.print("写入失败:" + write.Message);
        }
        OperateResultExOne<Boolean> read2 = melsec_net.ReadBool("M100");
        if (read2.IsSuccess) {
            System.out.println(read2.Content);
        } else {
            System.out.println("读取失败:" + read.Message);
        }
    }
    /**
     * 三菱   Q
     */
    private static void MelsecTest() {
        MelsecMcNet melsec_net = new MelsecMcNet("192.168.1.192", 6001);
        boolean[] M100 = melsec_net.ReadBool("M100", (short) 1).Content;            // 读取M100是否通,十进制地址
        boolean[] X1A0 = melsec_net.ReadBool("X1A0", (short) 1).Content;            // 读取X1A0是否通,十六进制地址
        boolean[] Y1A0 = melsec_net.ReadBool("Y1A0", (short) 1).Content;            // 读取Y1A0是否通,十六进制地址
        boolean[] B1A0 = melsec_net.ReadBool("B1A0", (short) 1).Content;            // 读取B1A0是否通,十六进制地址
        short short_D1000 = melsec_net.ReadInt16("D1000").Content;                 // 读取D1000的short值  ,W3C0,R3C0 效果是一样的
        int int_D1000 = melsec_net.ReadInt32("D1000").Content;                     // 读取D1000-D1001组成的int数据
        float float_D1000 = melsec_net.ReadFloat("D1000").Content;                 // 读取D1000-D1001组成的float数据
        long long_D1000 = melsec_net.ReadInt64("D1000").Content;                   // 读取D1000-D1003组成的long数据
        double double_D1000 = melsec_net.ReadDouble("D1000").Content;              // 读取D1000-D1003组成的double数据
        String str_D1000 = melsec_net.ReadString("D1000", (short) 10).Content;     // 读取D1000-D1009组成的条码数据
        melsec_net.Write("M100", new boolean[]{true});                          // 写入M100为通
        melsec_net.Write("Y1A0", new boolean[]{true});                        // 写入Y1A0为通
        melsec_net.Write("X1A0", new boolean[]{true});                        // 写入X1A0为通
        melsec_net.Write("B1A0", new boolean[]{true});                        // 写入B1A0为通
        melsec_net.Write("D1000", (short) 1234);                                   // 写入D1000  short值  ,W3C0,R3C0 效果是一样的
        melsec_net.Write("D1000", 1234566);                                // 写入D1000  int值
        melsec_net.Write("D1000", 123.456f);                               // 写入D1000  float值
        melsec_net.Write("D1000", 123.456d);                               // 写入D1000  double值
        melsec_net.Write("D1000", 123456661235123534L);                    // 写入D1000  long值
        melsec_net.Write("D1000", "K123456789");                           // 写入D1000  string值
        OperateResultExOne<boolean[]> read = melsec_net.ReadBool("M100", (short) 10);
        if (read.IsSuccess) {
            boolean m100 = read.Content[0];
            boolean m101 = read.Content[1];
            boolean m102 = read.Content[2];
            boolean m103 = read.Content[3];
            boolean m104 = read.Content[4];
            boolean m105 = read.Content[5];
            boolean m106 = read.Content[6];
            boolean m107 = read.Content[7];
            boolean m108 = read.Content[8];
            boolean m109 = read.Content[9];
        } else {
            System.out.print("读取失败:" + read.Message);
        }
        OperateResultExOne<byte[]> read1 = melsec_net.Read("D100", (short) 5);
        if (read1.IsSuccess) {
            short D100 = melsec_net.getByteTransform().TransByte(read1.Content, 0);
            short D101 = melsec_net.getByteTransform().TransByte(read1.Content, 2);
            short D102 = melsec_net.getByteTransform().TransByte(read1.Content, 4);
            short D103 = melsec_net.getByteTransform().TransByte(read1.Content, 6);
            short D104 = melsec_net.getByteTransform().TransByte(read1.Content, 8);
        } else {
            System.out.print("读取失败:" + read1.Message);
        }
        //解析复杂数据
        OperateResultExOne<byte[]> read3 = melsec_net.Read("D4000", (short) 10);
        if (read3.IsSuccess) {
            double 温度 = melsec_net.getByteTransform().TransInt16(read3.Content, 0) / 10d;//索引很重要
            double 压力 = melsec_net.getByteTransform().TransInt16(read3.Content, 2) / 100d;
            boolean IsRun = melsec_net.getByteTransform().TransInt16(read3.Content, 4) == 1;
            int 产量 = melsec_net.getByteTransform().TransInt32(read3.Content, 6);
            String 规格 = melsec_net.getByteTransform().TransString(read3.Content, 10, 10, "ascii");
        } else {
            System.out.print("读取失败:" + read3.Message);
        }
        // 写入测试,M100-M104 写入测试 此处写入后M100:通 M101:断 M102:断 M103:通 M104:通
        boolean[] values = new boolean[]{true, false, false, true, true};
        OperateResult write = melsec_net.Write("M100", values);
        if (write.IsSuccess) {
            System.out.print("写入成功");
        } else {
            System.out.print("写入失败:" + write.Message);
        }
        OperateResultExOne<Boolean> read2 = melsec_net.ReadBool("M100");
        if (read2.IsSuccess) {
            System.out.println(read2.Content);
        } else {
            System.out.println("读取失败:" + read.Message);
        }
    }
    /**
     * 三菱   Q   ASCII通讯格式
     */
    private  static void MelsecAsciiTest(){
        MelsecMcAsciiNet melsec = new MelsecMcAsciiNet("192.168.1.192",6001);
        OperateResultExOne<short[]> read = melsec.ReadInt16("D100",(short) 2);
        if(read.IsSuccess)
        {
            System.out.println(Arrays.toString(read.Content));
        }
        else {
            System.out.println(read.ToMessageShowString());
        }
    }
    /**
     * 四门子
     */
    private static void SiemesTest(){
        SiemensS7Net siemens_net = new SiemensS7Net(SiemensPLCS.S1200,"192.168.1.195");
        OperateResult connect = siemens_net.ConnectServer();
        if(connect.IsSuccess){
            System.out.println("connect success!");
        }
        else {
            System.out.println("failed:"+connect.Message);
        }
        siemens_net.ConnectClose();
        // 上面是初始化
        System.out.println(siemens_net.ReadByte("M100").Content);
        byte m100_byte = siemens_net.ReadByte("M100").Content;
        short m100_short = siemens_net.ReadInt16("M100").Content;
        int m100_int = siemens_net.ReadInt32("M100").Content;
        long m100_long = siemens_net.ReadInt64("M100").Content;
        float m100_float = siemens_net.ReadFloat("M100").Content;
        double m100_double = siemens_net.ReadDouble("M100").Content;
        String m100_string = siemens_net.ReadString("M100",(short) 10).Content;
        siemens_net.Write("M100",(byte) 123);
        siemens_net.Write("M100",(short) 123);
        siemens_net.Write("M100",(int) 123);
        siemens_net.Write("M100",(long) 123);
        siemens_net.Write("M100", 123.456f);
        siemens_net.Write("M100", 123.456d);
        siemens_net.Write("M100","1234567890");
        OperateResultExOne<byte[]> read = siemens_net.Read( "M100", (short) 10 );
        {
            if(read.IsSuccess)
            {
                byte m100 = read.Content[0];
                byte m101 = read.Content[1];
                byte m102 = read.Content[2];
                byte m103 = read.Content[3];
                byte m104 = read.Content[4];
                byte m105 = read.Content[5];
                byte m106 = read.Content[6];
                byte m107 = read.Content[7];
                byte m108 = read.Content[8];
                byte m109 = read.Content[9];
            }
            else
            {
                // 发生了异常
            }
        }
    }
    private static void PushNetTest() {
        NetPushClient client = new NetPushClient("127.0.0.1", 23467, "A");
        OperateResult connect = client.CreatePush(new ActionOperateExTwo<NetPushClient,String>(){
            @Override
            public void Action(NetPushClient content1, String content2) {
                System.out.println(content2);
            }
        });
        if (connect.IsSuccess) {
            System.out.println("连接成功!");
        } else {
            System.out.println("连接失败!"+connect.Message);
        }
    }
    private static void ModbusTcpTets(){
        ModbusTcpNet modbusTcpNet = new ModbusTcpNet("127.0.0.1",502,(byte) 0x01);
        // 当你需要指定格式的数据解析时,就需要设置下面的这个信息
        modbusTcpNet.setDataFormat(DataFormat.BADC);
        OperateResultExOne<Double> read = modbusTcpNet.ReadDouble("s=2;x=4;200");
        if(read.IsSuccess){
            System.out.println(read.Content);
        }
        else {
            System.out.println(read.Message);
        }
        modbusTcpNet.Write("100",new int[]{12345,-12345});
    }
    private static void NetComplexClientTest(){
        System.out.println("Hello World!等待10s关闭");
        NetComplexClient client = new NetComplexClient();
        client.setIpAddress("127.0.0.1");
        client.setPort(12346);
        client.setClientAlias("测试1");
        client.AcceptString= new ActionOperateExThree<NetComplexClient,NetHandle,String>(){
            @Override
            public void Action(NetComplexClient content1, NetHandle content2, String content3) {
                System.out.println("Handle:"+content2.get_CodeValue()+"  Value:"+content3);
            }
        };
        client.ClientStart();
//        client.Send(new NetHandle(1),"asdasdi阿斯达阿斯达");
//        System.out.println(client.getDelayTime());
//        Thread.sleep(100000);
//        client.ClientClose();
    }
}
src/main/java/com/zy/common/web/AuthController.java
@@ -65,7 +65,7 @@
        if (user.getStatus()!=1){
            return R.parse(CodeRes.USER_10002);
        }
        if (!Cools.md5(user.getPassword()).equals(password)){
        if (!user.getPassword().equals(password)){
            return R.parse(CodeRes.USER_10003);
        }
        String token = Cools.enToken(System.currentTimeMillis() + mobile, user.getPassword());
src/main/java/com/zy/gateway/Test.java
File was deleted
src/main/java/com/zy/gateway/core/IReadWriteNet.java
File was deleted
src/main/java/com/zy/gateway/pipeline/Bootstrap.java
File was deleted
src/main/java/com/zy/gateway/pipeline/HandlerInitializer.java
File was deleted
src/main/java/com/zy/gateway/pipeline/PipelineBootstrap.java
File was deleted
src/main/java/com/zy/gateway/pipeline/PipelineProperties.java
File was deleted
src/main/resources/application.yml
@@ -13,7 +13,7 @@
#    password: xltys1995
    # sql-server
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=dlasrs
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=jsasrs
    username: sa
    password: sa@123
  mvc:
src/main/webapp/static/js/common.js
@@ -2,8 +2,7 @@
// var baseUrl = "/wcs";
// 测试
var baseUrl = "";
// 系统运行状态
var systemRunning = true;
// 赋值
function setVal(el, val) {
src/main/webapp/views/console.html
@@ -638,7 +638,7 @@
    // 系统运行开关
    function systemSwitch() {
        if (systemRunning){
        if (parent.systemRunning){
            layer.prompt({title: '请输入口令,并停止 WCS 系统', formType: 1,   shadeClose: true}, function(pass, idx){
                layer.close(idx);
                doSwitch(0, pass); // 停止wcs系统
@@ -669,11 +669,11 @@
                    if (res.data.status) {
                        $('#system-icon').attr("class", "system-icon-open");
                        $('#system-run-desc').html("系统运行中...");
                        systemRunning = true;
                        parent.systemRunning = true;
                    } else {
                        $('#system-icon').attr("class", "system-icon-close");
                        $('#system-run-desc').html("系统已停止!");
                        systemRunning = false;
                        parent.systemRunning = false;
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
@@ -696,11 +696,11 @@
                    if (res.data.status) {
                        $('#system-icon').attr("class", "system-icon-open");
                        $('#system-run-desc').html("系统运行中...");
                        systemRunning = true;
                        parent.systemRunning = true;
                    } else {
                        $('#system-icon').attr("class", "system-icon-close");
                        $('#system-run-desc').html("系统已停止!");
                        systemRunning = false;
                        parent.systemRunning = false;
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
src/main/webapp/views/crn.html
@@ -200,7 +200,7 @@
    // 判断手动操作模块是否可用
    function operatorBlockShow() {
        if (systemRunning) {
        if (parent.systemRunning) {
            $('.crn-operation').css("opacity", "0.5");
            $('.crn-operation-shade').show();
            $('.crn-operation-shade-span').show();
src/main/webapp/views/index.html
@@ -44,6 +44,9 @@
      localStorage.removeItem("token");
      window.location.href = baseUrl + "/login";
  }
  // 系统运行状态
  var systemRunning = true;
</script>
</html>