Ejemplo n.º 1
0
        /// <summary>
        /// 检查当前的Modbus-Rtu响应是否是正确的
        /// </summary>
        /// <param name="send">发送的数据信息</param>
        /// <returns>带是否成功的结果数据</returns>
        protected virtual OperateResult <byte[]> CheckModbusTcpResponse(byte[] send)
        {
            // 核心交互
            OperateResult <byte[]> result = ReadBase(send);

            if (!result.IsSuccess)
            {
                return(result);
            }

            // 长度校验
            if (result.Content.Length < 5)
            {
                return(new OperateResult <byte[]>(StringResources.Language.ReceiveDataLengthTooShort + "5"));
            }

            // 检查crc
            if (!SoftCRC16.CheckCRC16(result.Content))
            {
                return(new OperateResult <byte[]>(StringResources.Language.ModbusCRCCheckFailed));
            }

            // 发生了错误
            if ((send[1] + 0x80) == result.Content[1])
            {
                return(new OperateResult <byte[]>(result.Content[2], ModbusInfo.GetDescriptionByErrorCode(result.Content[2])));
            }

            // 移除CRC校验
            byte[] buffer = new byte[result.Content.Length - 2];
            Array.Copy(result.Content, 0, buffer, 0, buffer.Length);
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 检查当前的Modbus-Ascii响应是否是正确的
        /// </summary>
        /// <param name="send">发送的数据信息</param>
        /// <returns>带是否成功的结果数据</returns>
        protected override OperateResult <byte[]> CheckModbusTcpResponse(byte[] send)
        {
            // 转ascii
            byte[] modbus_ascii = ModbusInfo.TransRtuToAsciiPackCommand(send);

            // 核心交互
            OperateResult <byte[]> result = ReadBase(modbus_ascii);

            if (!result.IsSuccess)
            {
                return(result);
            }

            // 还原modbus报文
            OperateResult <byte[]> modbus_core = ModbusInfo.TransAsciiPackCommandToRtu(result.Content);

            if (!modbus_core.IsSuccess)
            {
                return(modbus_core);
            }

            // 发生了错误
            if ((send[1] + 0x80) == modbus_core.Content[1])
            {
                return new OperateResult <byte[]>( )
                       {
                           ErrorCode = modbus_core.Content[2], Message = ModbusInfo.GetDescriptionByErrorCode(modbus_core.Content[2])
                       }
            }
            ;

            // 成功的消息
            return(OperateResult.CreateSuccessResult(modbus_core.Content));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 从Modbus服务器批量读取寄存器的信息,需要指定起始地址,读取长度
        /// </summary>
        /// <param name="address">起始地址,格式为"1234",或者是带功能码格式x=3;1234</param>
        /// <param name="length">读取的数量</param>
        /// <returns>带有成功标志的字节信息</returns>
        /// <remarks>
        /// 富地址格式,支持携带站号信息,功能码信息,具体参照类的示例代码
        /// </remarks>
        /// <example>
        /// 此处演示批量读取的示例
        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Modbus\Modbus.cs" region="ReadExample1" title="Read示例" />
        /// </example>
        public override OperateResult <byte[]> Read(string address, ushort length)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisAddress(address, isAddressStartWithZero, ModbusInfo.ReadRegister);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            List <byte> lists           = new List <byte>( );
            ushort      alreadyFinished = 0;

            while (alreadyFinished < length)
            {
                ushort lengthTmp            = (ushort)Math.Min((length - alreadyFinished), 120);
                OperateResult <byte[]> read = ReadModBusBase(analysis.Content.AddressAdd(alreadyFinished), lengthTmp);
                if (!read.IsSuccess)
                {
                    return(OperateResult.CreateFailedResult <byte[]>(read));
                }

                lists.AddRange(read.Content);
                alreadyFinished += lengthTmp;
            }
            return(OperateResult.CreateSuccessResult(lists.ToArray( )));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 生成一个读取寄存器的指令头
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="length">长度</param>
        /// <returns>携带有命令字节</returns>
        private OperateResult <byte[]> BuildReadRegisterCommand(ModbusAddress address, ushort length)
        {
            ushort messageId = (ushort)softIncrementCount.GetCurrentValue( );

            // 生成最终tcp指令
            byte[] buffer = ModbusInfo.PackCommandToTcp(address.CreateReadRegister(station, length), messageId);
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// 生成一个读取线圈的指令头
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="count">长度</param>
        /// <returns>携带有命令字节</returns>
        private OperateResult <byte[]> BuildReadCoilCommand(string address, ushort count)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            // 生成最终tcp指令
            byte[] buffer = ModbusInfo.PackCommandToRtu(analysis.Content.CreateReadCoils(station, count));
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 6
0
        private OperateResult <byte[]> BuildWriteRegisterCommand(string address, byte[] values)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            // 生成最终tcp指令
            byte[] buffer = ModbusInfo.PackCommandToRtu(analysis.Content.CreateWriteRegister(station, values));
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 生成一个读取寄存器的指令头
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="length">长度</param>
        /// <returns>携带有命令字节</returns>
        public OperateResult <byte[]> BuildReadRegisterCommand(string address, ushort length)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            // 生成最终rtu指令
            byte[] buffer = ModbusInfo.PackCommandToRtu(analysis.Content.CreateReadRegister(station, length));
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// 生成批量写入单个线圈的报文信息
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="values">实际数据值</param>
        /// <returns>包含结果对象的报文</returns>
        public OperateResult <byte[]> BuildWriteCoilCommand(string address, bool[] values)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisAddress(address, isAddressStartWithZero, ModbusInfo.WriteCoil);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            // 生成最终rtu指令
            byte[] buffer = ModbusInfo.PackCommandToRtu(analysis.Content.CreateWriteCoil(station, values));
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 9
0
        private OperateResult <byte[]> BuildWriteRegisterCommand(string address, byte[] values)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, isAddressStartWithZero);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            ushort messageId = (ushort)softIncrementCount.GetCurrentValue( );

            // 生成最终tcp指令
            byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateWriteRegister(station, values), messageId);
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// 检查当前的Modbus-Tcp响应是否是正确的
        /// </summary>
        /// <param name="send">发送的数据信息</param>
        /// <returns>带是否成功的结果数据</returns>
        private OperateResult <byte[]> CheckModbusTcpResponse(byte[] send)
        {
            OperateResult <byte[]> resultBytes = ReadFromCoreServer(send);

            if (resultBytes.IsSuccess)
            {
                if ((send[7] + 0x80) == resultBytes.Content[7])
                {
                    // 发生了错误
                    resultBytes.IsSuccess = false;
                    resultBytes.Message   = ModbusInfo.GetDescriptionByErrorCode(resultBytes.Content[8]);
                    resultBytes.ErrorCode = resultBytes.Content[8];
                }
            }
            return(resultBytes);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// 生成批量写入单个线圈的报文信息
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="values">实际数据值</param>
        /// <returns>包含结果对象的报文</returns>
        public OperateResult <byte[]> BuildWriteCoilCommand(string address, bool[] values)
        {
            // 解析富地址
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisAddress(address, isAddressStartWithZero, ModbusInfo.WriteCoil);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            // 获取消息号
            ushort messageId = (ushort)softIncrementCount.GetCurrentValue( );

            // 生成最终tcp指令
            byte[] buffer = ModbusInfo.PackCommandToTcp(analysis.Content.CreateWriteCoil(station, values), messageId);
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// 检查当前的Modbus-Tcp响应是否是正确的
        /// </summary>
        /// <param name="send">发送的数据信息</param>
        /// <returns>带是否成功的结果数据</returns>
        private OperateResult <byte[]> CheckModbusTcpResponse(byte[] send)
        {
            OperateResult <byte[]> result = ReadBase(send);

            if (!result.IsSuccess)
            {
                return(result);
            }

            if (result.Content.Length < 5)
            {
                return(new OperateResult <byte[]>( )
                {
                    IsSuccess = false,
                    Message = "接收数据长度不能小于5",
                });
            }

            if (!SoftCRC16.CheckCRC16(result.Content))
            {
                return(new OperateResult <byte[]>( )
                {
                    IsSuccess = false,
                    Message = "CRC校验失败",
                });
            }

            if ((send[1] + 0x80) == result.Content[1])
            {
                // 发生了错误
                return(new OperateResult <byte[]>( )
                {
                    IsSuccess = false,
                    Message = ModbusInfo.GetDescriptionByErrorCode(result.Content[2]),
                    ErrorCode = result.Content[2],
                });
            }
            else
            {
                // 移除CRC校验
                byte[] buffer = new byte[result.Content.Length - 2];
                Array.Copy(result.Content, 0, buffer, 0, buffer.Length);
                return(OperateResult.CreateSuccessResult(buffer));
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// 检查当前的Modbus-Rtu响应是否是正确的
        /// </summary>
        /// <param name="send">发送的数据信息</param>
        /// <returns>带是否成功的结果数据</returns>
        protected virtual OperateResult <byte[]> CheckModbusTcpResponse(byte[] send)
        {
            // 核心交互
            OperateResult <byte[]> result = ReadBase(send);

            if (!result.IsSuccess)
            {
                return(result);
            }

            // 长度校验
            if (result.Content.Length < 5)
            {
                return new OperateResult <byte[]>( )
                       {
                           IsSuccess = false, Message = "接收数据长度不能小于5"
                       }
            }
            ;

            // 检查crc
            if (!SoftCRC16.CheckCRC16(result.Content))
            {
                return new OperateResult <byte[]>( )
                       {
                           Message = "CRC校验失败"
                       }
            }
            ;

            // 发生了错误
            if ((send[1] + 0x80) == result.Content[1])
            {
                return new OperateResult <byte[]>( )
                       {
                           ErrorCode = result.Content[2], Message = ModbusInfo.GetDescriptionByErrorCode(result.Content[2])
                       }
            }
            ;

            // 移除CRC校验
            byte[] buffer = new byte[result.Content.Length - 2];
            Array.Copy(result.Content, 0, buffer, 0, buffer.Length);
            return(OperateResult.CreateSuccessResult(buffer));
        }
Ejemplo n.º 14
0
        /// <summary>
        /// 批量读取线圈或是离散的数据信息,需要指定地址和长度,具体的结果取决于实现
        /// </summary>
        /// <param name="address">数据地址</param>
        /// <param name="length">数据长度</param>
        /// <returns>带有成功标识的bool[]数组</returns>
        public override OperateResult <bool[]> ReadBool(string address, ushort length)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisAddress(address, isAddressStartWithZero, ModbusInfo.ReadCoil);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <bool[]>(analysis));
            }

            var read = ReadModBusBase((byte)analysis.Content.Function, address, length);

            if (!read.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <bool[]>(read));
            }

            return(OperateResult.CreateSuccessResult(SoftBasic.ByteToBoolArray(read.Content, length)));
        }
Ejemplo n.º 15
0
        private void SocketAsyncCallBack(IAsyncResult ar)
        {
            if (ar.AsyncState is AppSession session)
            {
                try
                {
                    int receiveCount = session.WorkSocket.EndReceive(ar);

                    ModbusTcpMessage       mdMessage = new ModbusTcpMessage( );
                    OperateResult <byte[]> read1     = ReceiveByMessage(session.WorkSocket, 5000, mdMessage);
                    if (!read1.IsSuccess)
                    {
                        LogNet?.WriteDebug(ToString( ), string.Format(StringResources.Language.ClientOfflineInfo, session.IpEndPoint));
                        RemoveClient(session);
                        return;
                    }
                    ;

                    ushort id   = (ushort)(read1.Content[0] * 256 + read1.Content[1]);
                    byte[] back = ModbusInfo.PackCommandToTcp(ReadFromModbusCore(SoftBasic.BytesArrayRemoveBegin(read1.Content, 6)), id);
                    if (back != null)
                    {
                        session.WorkSocket.Send(back);
                    }
                    else
                    {
                        session.WorkSocket.Close( );
                        RemoveClient(session);
                        return;
                    }

                    RaiseDataReceived(read1.Content);
                    session.WorkSocket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, new AsyncCallback(SocketAsyncCallBack), session);
                }
                catch
                {
                    // 关闭连接,记录日志
                    session.WorkSocket?.Close( );
                    LogNet?.WriteDebug(ToString( ), string.Format(StringResources.Language.ClientOfflineInfo, session.IpEndPoint));
                    RemoveClient(session);
                    return;
                }
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// 读取自定义的寄存器的值。按照字为单位
        /// </summary>
        /// <param name="address">起始地址,示例:"100","x=4;100"</param>
        /// <param name="length">数据长度</param>
        /// <exception cref="IndexOutOfRangeException"></exception>
        /// <returns>byte数组值</returns>
        public override OperateResult <byte[]> Read(string address, ushort length)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisAddress(address, true, ModbusInfo.ReadRegister);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            if (analysis.Content.Function == ModbusInfo.ReadRegister)
            {
                return(OperateResult.CreateSuccessResult(registerBuffer.GetBytes(analysis.Content.Address * 2, length * 2)));
            }
            else if (analysis.Content.Function == ModbusInfo.ReadInputRegister)
            {
                return(OperateResult.CreateSuccessResult(inputRegisterBuffer.GetBytes(analysis.Content.Address * 2, length * 2)));
            }
            else
            {
                return(new OperateResult <byte[]>(StringResources.Language.NotSupportedDataType));
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// 写入自定义的数据到数据内存中去
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据值</param>
        /// <returns>是否写入成功的结果对象</returns>
        public override OperateResult Write(string address, byte[] value)
        {
            OperateResult <ModbusAddress> analysis = ModbusInfo.AnalysisReadAddress(address, true);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            if (analysis.Content.Function == ModbusInfo.ReadRegister)
            {
                registerBuffer.SetBytes(value, analysis.Content.Address * 2);
                return(OperateResult.CreateSuccessResult( ));
            }
            else if (analysis.Content.Function == ModbusInfo.ReadInputRegister)
            {
                inputRegisterBuffer.SetBytes(value, analysis.Content.Address * 2);
                return(OperateResult.CreateSuccessResult( ));
            }
            else
            {
                return(new OperateResult <byte[]>(StringResources.Language.NotSupportedDataType));
            }
        }
Ejemplo n.º 18
0
 /// <summary>
 /// 生成一个读取寄存器的指令头
 /// </summary>
 /// <param name="address">地址</param>
 /// <param name="length">长度</param>
 /// <returns>携带有命令字节</returns>
 private OperateResult <byte[]> BuildReadRegisterCommand(ModbusAddress address, ushort length)
 {
     // 生成最终tcp指令
     byte[] buffer = ModbusInfo.PackCommandToRtu(address.CreateReadRegister(station, length));
     return(OperateResult.CreateSuccessResult(buffer));
 }
Ejemplo n.º 19
0
        /// <summary>
        /// 接收到串口数据的时候触发
        /// </summary>
        /// <param name="sender">串口对象</param>
        /// <param name="e">消息</param>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int rCount = 0;

            byte[] buffer  = new byte[1024];
            byte[] receive = null;

            while (true)
            {
                System.Threading.Thread.Sleep(20);              // 此处做个微小的延时,等待数据接收完成
                int count = serialPort.Read(buffer, rCount, serialPort.BytesToRead);
                rCount += count;
                if (count == 0)
                {
                    break;
                }

                receive = new byte[rCount];
                Array.Copy(buffer, 0, receive, 0, count);
            }

            if (receive == null)
            {
                return;
            }

            if (receive.Length < 3)
            {
                LogNet?.WriteError(ToString( ), $"Uknown Data:" + SoftBasic.ByteToHexString(receive, ' '));
                return;
            }

            if (Serial.SoftCRC16.CheckCRC16(receive))
            {
                byte[] modbusCore = SoftBasic.BytesArrayRemoveLast(receive, 2);

                if (!CheckModbusMessageLegal(modbusCore))
                {
                    // 指令长度验证错误,关闭网络连接
                    LogNet?.WriteError(ToString( ), $"Receive Nosense Modbus-rtu : " + SoftBasic.ByteToHexString(receive, ' '));
                    return;
                }

                // 验证站号是否一致
                if (station >= 0 && station != modbusCore[0])
                {
                    LogNet?.WriteError(ToString( ), $"Station not match Modbus-rtu : " + SoftBasic.ByteToHexString(receive, ' '));
                    return;
                }

                // LogNet?.WriteError( ToString( ), $"Success:" + BasicFramework.SoftBasic.ByteToHexString( receive, ' ' ) );
                // 需要回发消息
                byte[] copy = ModbusInfo.PackCommandToRtu(ReadFromModbusCore(modbusCore));

                serialPort.Write(copy, 0, copy.Length);

                if (IsStarted)
                {
                    RaiseDataReceived(receive);
                }
            }
            else
            {
                LogNet?.WriteWarn("CRC Check Failed : " + SoftBasic.ByteToHexString(receive, ' '));
            }
        }