/// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="value"></param>
        /// <param name="isBit">是否是位操作</param>
        /// <returns></returns>
        public OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, bool isBit)
        {
            var result   = new OperateResult <byte[]>( );
            var analysis = AnalysisAddress(address, isBit);

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

            byte[] _PLCCommand = new byte[8 + value.Length];
            _PLCCommand[0] = 0x01;    // 读取存储区数据
            _PLCCommand[1] = 0x02;
            if (isBit)
            {
                _PLCCommand[2] = analysis.Content1.BitCode;
            }
            else
            {
                _PLCCommand[2] = analysis.Content1.WordCode;
            }
            analysis.Content2.CopyTo(_PLCCommand, 3);

            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);
            }

            value.CopyTo(_PLCCommand, 8);


            try
            {
                result.Content   = PackCommand(_PLCCommand);
                result.IsSuccess = true;
            }
            catch (Exception ex)
            {
                LogNet?.WriteException(ToString( ), ex);
                result.Message = ex.Message;
            }
            return(result);
        }
Beispiel #2
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));
        }
Beispiel #3
0
        /// <summary>
        /// 写入自定义的数据到数据内存中去
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据值</param>
        /// <returns>是否写入成功的结果对象</returns>
        public override OperateResult Write(string address, byte[] value)
        {
            OperateResult<string> analysis = XGBFastEnet.AnalysisAddress(address, false);
            if (!analysis.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(analysis);

            int startIndex = CheckAddress(analysis.Content.Substring(3));
            switch (analysis.Content[1])
            {
                case 'P': pBuffer.SetBytes(value, startIndex); return OperateResult.CreateSuccessResult();
                case 'Q': qBuffer.SetBytes(value, startIndex); return OperateResult.CreateSuccessResult();
                case 'M': mBuffer.SetBool(value[0]==1 ? true:false, startIndex); return OperateResult.CreateSuccessResult();
                case 'D': dBuffer.SetBytes(value, startIndex == 0 ? startIndex : startIndex *= 2); return OperateResult.CreateSuccessResult();
                default: return new OperateResult<byte[]>(StringResources.Language.NotSupportedDataType);
            }
        }
Beispiel #4
0
        /// <summary>
        /// 读取自定义的寄存器的值
        /// </summary>
        /// <param name="address">起始地址,示例:"I100","M100"</param>
        /// <param name="length">数据长度</param>
        /// <exception cref="IndexOutOfRangeException"></exception>
        /// <returns>byte数组值</returns>
        public override OperateResult<byte[]> Read(string address, ushort length)
        {
            OperateResult<string> analysis = XGBFastEnet.AnalysisAddress(address, true);
            if (!analysis.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(analysis);

            int startIndex = CheckAddress(analysis.Content.Substring(3));
            switch (analysis.Content[1])
            {
                case 'P': return OperateResult.CreateSuccessResult(pBuffer.GetBytes(startIndex, length));
                case 'Q': return OperateResult.CreateSuccessResult(qBuffer.GetBytes(startIndex, length));
                case 'M': return OperateResult.CreateSuccessResult(SoftBasic.BoolArrayToByte(mBuffer.GetBool(startIndex , length *= 8)));
                case 'D': return OperateResult.CreateSuccessResult(dBuffer.GetBytes(startIndex==0 ? startIndex : startIndex*=2, length));
                default: return new OperateResult<byte[]>(StringResources.Language.NotSupportedDataType);
            }
        }
Beispiel #5
0
        public override OperateResult <string> ReadString(string address, ushort length, Encoding encoding)
        {
            OperateResult <byte[]> result = Read(address, length);

            if (!result.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <string>(result));
            }
            if (result.Content.Length >= 6)
            {
                int count = BitConverter.ToInt32(result.Content, 2);
                return(OperateResult.CreateSuccessResult <string>(encoding.GetString(result.Content, 6, count)));
            }
            return(OperateResult.CreateSuccessResult <string>(encoding.GetString(result.Content)));
        }
Beispiel #6
0
        /// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="value">数据值</param>
        /// <param name="plcNumber">PLC编号</param>
        /// <returns>带有成功标志的指令数据</returns>
        public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte plcNumber)
        {
            OperateResult <MelsecA1EDataType, ushort> operateResult = MelsecHelper.McA1EAnalysisAddress(address);

            if (!operateResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(operateResult));
            }
            int num = -1;

            if (operateResult.Content1.DataType == 1)
            {
                num   = value.Length;
                value = MelsecHelper.TransBoolArrayToByteData(value);
            }
            byte b = (byte)((operateResult.Content1.DataType == 1) ? 2 : 3);

            byte[] array = new byte[12 + value.Length];
            array[0]  = b;
            array[1]  = plcNumber;
            array[2]  = 10;
            array[3]  = 0;
            array[4]  = (byte)((int)operateResult.Content2 % 256);
            array[5]  = (byte)((int)operateResult.Content2 / 256);
            array[6]  = 0;
            array[7]  = 0;
            array[8]  = operateResult.Content1.DataCode[1];
            array[9]  = operateResult.Content1.DataCode[0];
            array[10] = (byte)(num % 256);
            array[11] = 0;
            if (operateResult.Content1.DataType == 1)
            {
                if (num > 0)
                {
                    array[10] = (byte)(num % 256);
                }
                else
                {
                    array[10] = (byte)(value.Length * 2 % 256);
                }
            }
            else
            {
                array[10] = (byte)(value.Length / 2 % 256);
            }
            Array.Copy(value, 0, array, 12, value.Length);
            return(OperateResult.CreateSuccessResult(array));
        }
        /// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="value"></param>
        /// <param name="length">指定长度</param>
        /// <returns></returns>
        private OperateResult <MelsecA1EDataType, byte[]> BuildWriteCommand(string address, byte[] value, int length = -1)
        {
            var analysis = AnalysisAddress(address);

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

            // 默认信息----注意:高低字节交错
            byte Subtitle = analysis.Content1.DataType == 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.DataCode[1];        // 软元件代码(L)
            _PLCCommand[9]  = analysis.Content1.DataCode[0];        // 软元件代码(H)
            _PLCCommand[10] = (byte)(length % 256);                 // 软元件点数
            _PLCCommand[11] = 0x00;

            // 判断是否进行位操作
            if (analysis.Content1.DataType == 0x01)
            {
                if (length > 0)
                {
                    _PLCCommand[10] = (byte)(length % 256);                       // 软元件点数
                }
                else
                {
                    _PLCCommand[10] = (byte)(value.Length * 2 % 256);             // 软元件点数
                }
            }
            else
            {
                _PLCCommand[10] = (byte)(value.Length / 2 % 256);                 // 软元件点数
            }

            Array.Copy(value, 0, _PLCCommand, 12, value.Length);                  // 将具体的要写入的数据附加到写入命令后面

            return(OperateResult.CreateSuccessResult(analysis.Content1, _PLCCommand));
        }
Beispiel #8
0
        /// <summary>
        /// 读取服务器的数据,需要指定不同的功能码
        /// </summary>
        /// <param name="code">指令</param>
        /// <param name="address">地址</param>
        /// <param name="length">长度</param>
        /// <returns></returns>
        private OperateResult <byte[]> ReadModBusBase(byte code, string address, ushort length)
        {
            OperateResult <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 OperateResult <byte[]>( )
            {
                    Message = StringResources.ModbusTcpFunctionCodeNotSupport
            }; break;
            }
            if (!command.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(command));
            }

            OperateResult <byte[]> resultBytes = CheckModbusTcpResponse(command.Content);

            if (resultBytes.IsSuccess)
            {
                // 二次数据处理
                if (resultBytes.Content?.Length >= 9)
                {
                    byte[] buffer = new byte[resultBytes.Content.Length - 9];
                    Array.Copy(resultBytes.Content, 9, buffer, 0, buffer.Length);
                    resultBytes.Content = buffer;
                }
            }
            return(resultBytes);
        }
        /***************************************************************************************
         *
         *    主要的数据交互分为4步
         *    1. 连接服务器,或是获取到旧的使用的网络信息
         *    2. 发送数据信息
         *    3. 接收反馈的数据信息
         *    4. 关闭网络连接,如果是短连接的话
         *
         **************************************************************************************/

        /// <summary>
        /// 获取本次操作的可用的网络套接字
        /// </summary>
        /// <returns>是否成功,如果成功,使用这个套接字</returns>
        private OperateResult <Socket> GetAvailableSocket( )
        {
            if (isPersistentConn)
            {
                // 如果是异形模式
                if (isUseSpecifiedSocket)
                {
                    if (IsSocketError)
                    {
                        return(new OperateResult <Socket>( )
                        {
                            Message = "连接不可用"
                        });
                    }
                    else
                    {
                        return(OperateResult.CreateSuccessResult(CoreSocket));
                    }
                }
                else
                {
                    // 长连接模式
                    if (IsSocketError || CoreSocket == null)
                    {
                        OperateResult connect = ConnectServer( );
                        if (!connect.IsSuccess)
                        {
                            IsSocketError = true;
                            return(OperateResult.CreateFailedResult <Socket>(connect));
                        }
                        else
                        {
                            IsSocketError = false;
                            return(OperateResult.CreateSuccessResult(CoreSocket));
                        }
                    }
                    else
                    {
                        return(OperateResult.CreateSuccessResult(CoreSocket));
                    }
                }
            }
            else
            {
                // 短连接模式
                return(CreateSocketAndInitialication( ));
            }
        }
        /// <summary>
        /// 返回读取的地址及长度信息,以及当前的偏置信息
        /// </summary><param name="address">读取的地址信息</param>
        /// <returns>带起始地址的结果对象</returns>
        private static OperateResult <ushort, ushort, ushort> FxCalculateBoolStartAddress(string address)
        {
            OperateResult <MelsecMcDataType, ushort> operateResult = FxAnalysisAddress(address);

            if (!operateResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <ushort, ushort, ushort>(operateResult));
            }
            ushort content = operateResult.Content2;

            if (operateResult.Content1 == MelsecMcDataType.M)
            {
                content = ((content < 8000) ? ((ushort)((int)content / 8 + 256)) : ((ushort)((content - 8000) / 8 + 480)));
            }
            else if (operateResult.Content1 == MelsecMcDataType.X)
            {
                content = (ushort)((int)content / 8 + 128);
            }
            else if (operateResult.Content1 == MelsecMcDataType.Y)
            {
                content = (ushort)((int)content / 8 + 160);
            }
            else if (operateResult.Content1 == MelsecMcDataType.S)
            {
                content = (ushort)((int)content / 8);
            }
            else if (operateResult.Content1 == MelsecMcDataType.CS)
            {
                content = (ushort)(content + (ushort)((int)content / 8 + 448));
            }
            else if (operateResult.Content1 == MelsecMcDataType.CC)
            {
                content = (ushort)(content + (ushort)((int)content / 8 + 960));
            }
            else if (operateResult.Content1 == MelsecMcDataType.TS)
            {
                content = (ushort)(content + (ushort)((int)content / 8 + 192));
            }
            else
            {
                if (operateResult.Content1 != MelsecMcDataType.TC)
                {
                    return(new OperateResult <ushort, ushort, ushort>(StringResources.Language.MelsecCurrentTypeNotSupportedBitOperate));
                }
                content = (ushort)(content + (ushort)((int)content / 8 + 704));
            }
            return(OperateResult.CreateSuccessResult(content, operateResult.Content2, (ushort)((int)operateResult.Content2 % 8)));
        }
Beispiel #11
0
        /// <summary>
        /// 读取PLC的型号信息
        /// </summary>
        /// <returns>返回型号的结果对象</returns>
        public OperateResult <string> ReadPlcType()
        {
            OperateResult <byte[]> operateResult = ReadFromCoreServer(PackMcCommand(Encoding.ASCII.GetBytes("01010000"), NetworkNumber, NetworkStationNumber));

            if (!operateResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <string>(operateResult));
            }
            ushort num = Convert.ToUInt16(Encoding.ASCII.GetString(operateResult.Content, 18, 4), 16);

            if (num != 0)
            {
                return(new OperateResult <string>(num, StringResources.Language.MelsecPleaseReferToManulDocument));
            }
            return(OperateResult.CreateSuccessResult(Encoding.ASCII.GetString(operateResult.Content, 22, 16).TrimEnd()));
        }
Beispiel #12
0
        /// <summary>
        /// 一次性从PLC获取所有的数据,按照先后顺序返回一个统一的Buffer,需要按照顺序处理,两个数组长度必须一致
        /// </summary>
        /// <param name="address">起始地址数组</param>
        /// <param name="length">数据长度数组</param>
        /// <returns>结果对象</returns>
        /// <exception cref="NullReferenceException"></exception>
        /// <remarks>
        /// <note type="warning">批量读取的长度有限制,最大为19个地址</note>
        /// </remarks>
        /// <example>
        /// 参照<see cref="Read(string, ushort)"/>
        /// </example>
        public OperateResult <byte[]> Read(string[] address, ushort[] length)
        {
            OperateResult <byte, int, ushort>[] addressResult = new OperateResult <byte, int, ushort> [address.Length];
            for (int i = 0; i < address.Length; i++)
            {
                OperateResult <byte, int, ushort> tmp = AnalysisAddress(address[i]);
                if (!tmp.IsSuccess)
                {
                    return(OperateResult.CreateFailedResult <byte[]>(addressResult[i]));
                }

                addressResult[i] = tmp;
            }

            return(Read(addressResult, length));
        }
        /// <summary>
        /// 生成一个写入字节数据的指令 -> Generate an instruction to write byte data
        /// </summary>
        /// <param name="address">起始地址,示例M100,I100,Q100,DB1.100 -> Start Address, example M100,I100,Q100,DB1.100</param>
        /// <param name="data">原始的字节数据 -> Raw byte data</param>
        /// <returns>包含结果对象的报文 -> Message containing the result object</returns>
        public static OperateResult <byte[]> BuildWriteByteCommand(string address, byte[] data)
        {
            if (data == null)
            {
                data = new byte[0];
            }

            OperateResult <byte, int, ushort> analysis = AnalysisAddress(address);

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

            return(BuildWriteByteCommand(analysis, data));
        }
Beispiel #14
0
        /// <summary>
        /// 读取指定地址的bool数据对象
        /// </summary>
        /// <param name="address">西门子的地址信息</param>
        /// <returns>带有成功标志的结果对象</returns>
        public OperateResult<bool> ReadBool(string address)
        {
            OperateResult<string> analysis = XGBFastEnet.AnalysisAddress(address, true);
            if (!analysis.IsSuccess) return OperateResult.CreateFailedResult<bool>(analysis);

            // to do, this is not right
            int startIndex = CheckAddress(analysis.Content.Substring(3));
            switch (analysis.Content[1])
            {
                case 'P': return OperateResult.CreateSuccessResult(pBuffer.GetBool(startIndex));
                case 'Q': return OperateResult.CreateSuccessResult(qBuffer.GetBool(startIndex));
                case 'M': return OperateResult.CreateSuccessResult(mBuffer.GetBool(startIndex));
                case 'D': return OperateResult.CreateSuccessResult(dBuffer.GetBool(startIndex));
                default: return new OperateResult<bool>(StringResources.Language.NotSupportedDataType);
            }
        }
        /// <summary>
        /// 返回读取的地址及长度信息
        /// </summary>
        /// <param name="address">读取的地址信息</param>
        /// <returns>带起始地址的结果对象</returns>
        private static OperateResult <ushort> FxCalculateWordStartAddress(string address)
        {
            // 初步解析,失败就返回
            var analysis = FxAnalysisAddress(address);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <ushort>(analysis));
            }


            // 二次解析
            ushort startAddress = analysis.Content2;

            if (analysis.Content1 == MelsecMcDataType.D)
            {
                if (startAddress >= 8000)
                {
                    startAddress = (ushort)((startAddress - 8000) * 2 + 0x0E00);
                }
                else
                {
                    startAddress = (ushort)(startAddress * 2 + 0x1000);
                }
            }
            else if (analysis.Content1 == MelsecMcDataType.CN)
            {
                if (startAddress >= 200)
                {
                    startAddress = (ushort)((startAddress - 200) * 4 + 0x0C00);
                }
                else
                {
                    startAddress = (ushort)(startAddress * 2 + 0x0A00);
                }
            }
            else if (analysis.Content1 == MelsecMcDataType.TN)
            {
                startAddress = (ushort)(startAddress * 2 + 0x0800);
            }
            else
            {
                return(new OperateResult <ushort>(StringResources.Language.MelsecCurrentTypeNotSupportedWordOperate));
            }

            return(OperateResult.CreateSuccessResult(startAddress));
        }
Beispiel #16
0
        /// <summary>
        /// 从PLC读取数据,地址格式为I100,Q100,DB20.100,M100,以位为单位
        /// </summary>
        /// <param name="address">起始地址,格式为I100,M100,Q100,DB20.100</param>
        /// <returns>结果对象</returns>
        private OperateResult <byte[]> ReadBitFromPLC(string address)
        {
            // 指令生成
            OperateResult <byte[]> command = BuildBitReadCommand(address);

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

            // 核心交互
            OperateResult <byte[]> read = ReadFromCoreServer(command.Content);

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


            // 分析结果
            int receiveCount = 1;

            if (read.Content.Length >= 21 && read.Content[20] == 1)
            {
                byte[] buffer = new byte[receiveCount];
                if (22 < read.Content.Length)
                {
                    if (read.Content[21] == 0xFF &&
                        read.Content[22] == 0x03)
                    {
                        // 有数据
                        buffer[0] = read.Content[25];
                    }
                }

                return(OperateResult.CreateSuccessResult(buffer));
            }
            else
            {
                return(new OperateResult <byte[]>( )
                {
                    ErrorCode = read.ErrorCode,
                    Message = "数据块长度校验失败",
                });
            }
        }
Beispiel #17
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));
        }
Beispiel #18
0
        private OperateResult <byte[]> ReadAddressData(McAddressData addressData)
        {
            byte[] mcCore = MelsecHelper.BuildAsciiReadMcCoreCommand(addressData, isBit: false);
            OperateResult <byte[]> operateResult = ReadFromCoreServer(PackMcCommand(mcCore, NetworkNumber, NetworkStationNumber));

            if (!operateResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(operateResult));
            }
            ushort num = Convert.ToUInt16(Encoding.ASCII.GetString(operateResult.Content, 18, 4), 16);

            if (num != 0)
            {
                return(new OperateResult <byte[]>(num, StringResources.Language.MelsecPleaseReferToManulDocument));
            }
            return(ExtractActualData(operateResult.Content, isBit: false));
        }
        /// <summary>
        /// 从欧姆龙PLC中读取想要的数据,返回读取结果,读取单位为字
        /// </summary>
        /// <param name="address">读取地址,格式为"D100","C100","W100","H100","A100"</param>
        /// <param name="length">读取的数据长度,字最大值960,位最大值7168</param>
        /// <returns>带成功标志的结果数据对象</returns>
        /// <remarks>
        /// 地址支持的列表如下:
        /// <list type="table">
        ///   <listheader>
        ///     <term>地址名称</term>
        ///     <term>示例</term>
        ///     <term>地址进制</term>
        ///   </listheader>
        ///   <item>
        ///     <term>DM Area</term>
        ///     <term>D100,D200</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>CIO Area</term>
        ///     <term>C100,C200</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>Work Area</term>
        ///     <term>W100,W200</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>Holding Bit Area</term>
        ///     <term>H100,H200</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>Auxiliary Bit Area</term>
        ///     <term>A100,A200</term>
        ///     <term>10</term>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <example>
        /// 假设起始地址为D100,D100存储了温度,100.6℃值为1006,D101存储了压力,1.23Mpa值为123,D102,D103存储了产量计数,读取如下:
        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\OmronFinsNet.cs" region="ReadExample2" title="Read示例" />
        /// 以下是读取不同类型数据的示例
        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\OmronFinsNet.cs" region="ReadExample1" title="Read示例" />
        /// </example>
        public override OperateResult<byte[]> Read( string address, ushort length )
        {
            //获取指令
            var command = BuildReadCommand( address, length, false );
            if (!command.IsSuccess) return OperateResult.CreateFailedResult<byte[]>( command );

            // 核心数据交互
            OperateResult<byte[]> read = ReadFromCoreServer( command.Content );
            if(!read.IsSuccess) return OperateResult.CreateFailedResult<byte[]>( read );

            // 数据有效性分析
            OperateResult<byte[]> valid = ResponseValidAnalysis( read.Content, true );
            if(!valid.IsSuccess) return OperateResult.CreateFailedResult<byte[]>( valid );

            // 读取到了正确的数据
            return OperateResult.CreateSuccessResult( valid.Content );
        }
        private OperateResult <byte[]> ReadAddressData(McAddressData addressData)
        {
            byte[] mcCore = MelsecHelper.BuildReadMcCoreCommand(addressData, isBit: false);
            OperateResult <byte[]> operateResult = ReadFromCoreServer(PackMcCommand(mcCore, NetworkNumber, NetworkStationNumber));

            if (!operateResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(operateResult));
            }
            ushort num = BitConverter.ToUInt16(operateResult.Content, 9);

            if (num != 0)
            {
                return(new OperateResult <byte[]>(num, StringResources.Language.MelsecPleaseReferToManulDocument));
            }
            return(ExtractActualData(SoftBasic.BytesArrayRemoveBegin(operateResult.Content, 11), isBit: false));
        }
        /// <summary>
        /// 从欧姆龙PLC中批量读取位软元件,返回读取结果
        /// </summary>
        /// <param name="address">读取地址,格式为"D100","C100","W100","H100","A100"</param>
        /// <param name="length">读取的长度</param>
        /// <returns>带成功标志的结果数据对象</returns>
        /// <remarks>
        /// 地址支持的列表如下:
        /// <list type="table">
        ///   <listheader>
        ///     <term>地址名称</term>
        ///     <term>示例</term>
        ///     <term>地址进制</term>
        ///   </listheader>
        ///   <item>
        ///     <term>DM Area</term>
        ///     <term>D100.0,D200.10</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>CIO Area</term>
        ///     <term>C100.0,C200.10</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>Work Area</term>
        ///     <term>W100.0,W200.10</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>Holding Bit Area</term>
        ///     <term>H100.0,H200.10</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>Auxiliary Bit Area</term>
        ///     <term>A100.0,A200.1</term>
        ///     <term>10</term>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <example>
        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\OmronFinsNet.cs" region="ReadBool" title="ReadBool示例" />
        /// </example>
        public OperateResult<bool[]> ReadBool( string address, ushort length )
        {
            //获取指令
            var command = BuildReadCommand( address, length, true );
            if (!command.IsSuccess) return OperateResult.CreateFailedResult<bool[]>( command );

            // 核心数据交互
            OperateResult<byte[]> read = ReadFromCoreServer( command.Content );
            if (!read.IsSuccess) return OperateResult.CreateFailedResult<bool[]>( read );

            // 数据有效性分析
            OperateResult<byte[]> valid = ResponseValidAnalysis( read.Content, true );
            if (!valid.IsSuccess) return OperateResult.CreateFailedResult<bool[]>( valid );

            // 返回正确的数据信息
            return OperateResult.CreateSuccessResult( valid.Content.Select( m => m != 0x00 ? true : false ).ToArray( ) );
        }
        /// <summary>
        /// 从PLC中读取想要的数据,返回读取结果
        /// </summary>
        public override OperateResult<byte[]> Read(string address, ushort length)
        {
            // 获取指令
            OperateResult<byte[]> command = BuildReadCommand(address, length);
            if (!command.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(command);

            // 核心交互
            OperateResult<byte[]> read = ReadBase(command.Content);
            if (!read.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(read);

            // 反馈检查
            OperateResult ackResult = CheckPlcReadResponse(read.Content);
            if (!ackResult.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(ackResult);

            // 数据提炼
            return ExtractActualData(read.Content);
        } 
        /// <summary>
        /// 从三菱PLC中读取想要的数据,返回读取结果
        /// </summary>
        /// <param name="address">读取地址,格式为"M100","D100","W1A0"</param>
        /// <param name="length">读取的数据长度,字最大值960,位最大值7168</param>
        /// <returns>带成功标志的结果数据对象</returns>
        /// <remarks>
        /// 地址支持的列表如下:
        /// <list type="table">
        ///   <listheader>
        ///     <term>地址名称</term>
        ///     <term>示例</term>
        ///     <term>地址进制</term>
        ///   </listheader>
        ///   <item>
        ///     <term>数据寄存器</term>
        ///     <term>D1000,D2000</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>定时器的值</term>
        ///     <term>T100,T200</term>
        ///     <term>10</term>
        ///   </item>
        ///   <item>
        ///     <term>计数器的值</term>
        ///     <term>C100,C200</term>
        ///     <term>10</term>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <example>
        /// 假设起始地址为D100,D100存储了温度,100.6℃值为1006,D101存储了压力,1.23Mpa值为123,D102,D103存储了产量计数,读取如下:
        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\MelsecAscii.cs" region="ReadExample2" title="Read示例" />
        /// 以下是读取不同类型数据的示例
        /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\MelsecAscii.cs" region="ReadExample1" title="Read示例" />
        /// </example>
        public override OperateResult <byte[]> Read(string address, ushort length)
        {
            var result = new OperateResult <byte[]>( );
            //获取指令
            var command = BuildReadWordCommand(address, length);

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

            var read = ReadBase(command.Content);

            if (read.IsSuccess)
            {
                OperateResult ackResult = CheckPlcReadResponse(read.Content);
                if (!ackResult.IsSuccess)
                {
                    return(OperateResult.CreateFailedResult <byte[]>(ackResult));
                }

                result.Content = new byte[(read.Content.Length - 4) / 2];
                for (int i = 0; i < result.Content.Length / 2; i++)
                {
                    byte[] buffer = new byte[4];
                    buffer[0] = read.Content[i * 4 + 1];
                    buffer[1] = read.Content[i * 4 + 2];
                    buffer[2] = read.Content[i * 4 + 3];
                    buffer[3] = read.Content[i * 4 + 4];

                    ushort tmp = Convert.ToUInt16(Encoding.ASCII.GetString(buffer), 16);
                    BitConverter.GetBytes(tmp).CopyTo(result.Content, i * 2);
                }

                result.IsSuccess = true;
            }
            else
            {
                result.ErrorCode = read.ErrorCode;
                result.Message   = read.Message;
            }

            return(result);
        }
Beispiel #24
0
        /// <summary>
        /// 以字为单位,创建ASCII数据写入的核心报文
        /// </summary>
        /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param>
        /// <param name="value">实际的原始数据信息</param>
        /// <param name="analysisAddress">对地址分析的委托方法</param>
        /// <returns>带有成功标识的报文对象</returns>
        public static OperateResult <byte[]> BuildAsciiWriteWordCoreCommand(string address, byte[] value, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress)
        {
            OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address);

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

            if (value == null)
            {
                value = new byte[0];
            }
            byte[] buffer = new byte[value.Length * 2];
            for (int i = 0; i < value.Length / 2; i++)
            {
                MelsecHelper.BuildBytesFromData(BitConverter.ToUInt16(value, i * 2)).CopyTo(buffer, 4 * i);
            }
            value = buffer;

            byte[] command = new byte[20 + value.Length];
            command[0]  = 0x31;                                                                              // 批量写入的命令
            command[1]  = 0x34;
            command[2]  = 0x30;
            command[3]  = 0x31;
            command[4]  = 0x30;                                                                              // 子命令
            command[5]  = 0x30;
            command[6]  = 0x30;
            command[7]  = 0x30;
            command[8]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0];                           // 软元件类型
            command[9]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1];
            command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0];       // 起始地址的地位
            command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1];
            command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2];
            command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3];
            command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4];
            command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5];
            command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[0];                // 软元件点数
            command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[1];
            command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[2];
            command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[3];
            value.CopyTo(command, 20);

            return(OperateResult.CreateSuccessResult(command));
        }
        /***************************************************************************************
         *
         *    主要的数据交互分为4步
         *    1. 连接服务器,或是获取到旧的使用的网络信息
         *    2. 发送数据信息
         *    3. 接收反馈的数据信息
         *    4. 关闭网络连接,如果是短连接的话
         *
         **************************************************************************************/

        /// <summary>
        /// 获取本次操作的可用的网络套接字
        /// </summary>
        /// <returns>是否成功,如果成功,使用这个套接字</returns>
        protected OperateResult <Socket> GetAvailableSocket( )
        {
            if (isPersistentConn)
            {
                // 如果是异形模式
                if (isUseSpecifiedSocket)
                {
                    if (IsSocketError)
                    {
                        return(new OperateResult <Socket>(StringResources.Language.ConnectionIsNotAvailable));
                    }
                    else
                    {
                        return(OperateResult.CreateSuccessResult(CoreSocket));
                    }
                }
                else
                {
                    // 长连接模式
                    if (IsSocketError || CoreSocket == null)
                    {
                        OperateResult connect = ConnectServer( );
                        if (!connect.IsSuccess)
                        {
                            IsSocketError = true;
                            return(OperateResult.CreateFailedResult <Socket>(connect));
                        }
                        else
                        {
                            IsSocketError = false;
                            return(OperateResult.CreateSuccessResult(CoreSocket));
                        }
                    }
                    else
                    {
                        return(OperateResult.CreateSuccessResult(CoreSocket));
                    }
                }
            }
            else
            {
                // 短连接模式
                return(CreateSocketAndInitialication( ));
            }
        }
Beispiel #26
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)));
        }
        /// <summary>
        /// 读取串口的数据
        /// </summary>
        /// <param name="send">发送的原始字节数据</param>
        /// <returns>带接收字节的结果对象</returns>
        public OperateResult <byte[]> ReadBase(byte[] send)
        {
            hybirdLock.Enter( );

            OperateResult sendResult = SPSend(SP_ReadData, send);

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

            OperateResult <byte[]> receiveResult = SPReceived(SP_ReadData, true);

            hybirdLock.Leave( );

            return(receiveResult);
        }
        /// <summary>
        /// 将信息 message 发送到指定的频道 channel
        /// </summary>
        /// <param name="channel">频道,和关键字不是一回事</param>
        /// <param name="message">消息</param>
        /// <returns>是否发送成功的结果对象</returns>
        public OperateResult <int> Publish(string channel, string message)
        {
            byte[] command = PackCommand(new string[] { "PUBLISH", channel, message });

            OperateResult <byte[]> read = ReadFromCoreServer(command);

            if (!read.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <int>(read));
            }

            if (read.Content[0] != ':')
            {
                return(new OperateResult <int>(Encoding.UTF8.GetString(read.Content)));
            }

            return(GetNumberFromCommandLine(read.Content));
        }
Beispiel #29
0
        /// <summary>
        /// 读取所有的温度数据,并转化成相关的信息
        /// </summary>
        /// <returns>结果数据对象</returns>
        public OperateResult <float[]> ReadAllTemperature( )
        {
            string address = "x=4;1";

            if (AddressStartWithZero)
            {
                address = "x=4;0";
            }

            OperateResult <short[]> read = ReadInt16(address, 128);

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

            return(OperateResult.CreateSuccessResult(read.Content.Select(m => TransformValue(m)).ToArray( )));
        }
Beispiel #30
0
        public OperateResult <byte[]> ReadCipFromServer(params byte[][] cips)
        {
            byte[] commandSpecificData = AllenBradleyHelper.PackCommandSpecificData(Slot, cips);
            byte[] send = AllenBradleyHelper.PackRequestHeader(0x6f, SessionHandle, commandSpecificData);
            OperateResult <byte[]> result = base.ReadFromCoreServer(send);

            if (!result.IsSuccess)
            {
                return(result);
            }
            OperateResult result2 = CheckResponse(result.Content);

            if (!result2.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(result2));
            }
            return(OperateResult.CreateSuccessResult <byte[]>(result.Content));
        }