Example #1
0
            /// <summary>
            /// Получить подходящий порядок байт по умолчанию
            /// </summary>
            public int[] GetDefByteOrder(int elemCnt)
            {
                switch (elemCnt)
                {
                case 1:
                    if (defByteOrder2 == null)
                    {
                        defByteOrder2 = ModbusUtils.ParseByteOrder(DefByteOrder2);
                    }
                    return(defByteOrder2);

                case 2:
                    if (defByteOrder4 == null)
                    {
                        defByteOrder4 = ModbusUtils.ParseByteOrder(DefByteOrder4);
                    }
                    return(defByteOrder4);

                case 4:
                    if (defByteOrder8 == null)
                    {
                        defByteOrder8 = ModbusUtils.ParseByteOrder(DefByteOrder8);
                    }
                    return(defByteOrder8);

                default:
                    return(null);
                }
            }
Example #2
0
        /// <summary>
        /// Loads the group from the XML node.
        /// </summary>
        public virtual void LoadFromXml(XmlElement groupElem)
        {
            if (groupElem == null)
            {
                throw new ArgumentNullException("groupElem");
            }

            Name    = groupElem.GetAttribute("name");
            Address = (ushort)groupElem.GetAttrAsInt("address");
            Active  = groupElem.GetAttrAsBool("active", true);

            XmlNodeList elemNodes   = groupElem.SelectNodes("Elem");
            int         maxElemCnt  = MaxElemCnt;
            ElemType    defElemType = DefElemType;

            foreach (XmlElement elemElem in elemNodes)
            {
                if (Elems.Count >= maxElemCnt)
                {
                    break;
                }

                Elem elem = CreateElem();
                elem.Name     = elemElem.GetAttribute("name");
                elem.ElemType = elemElem.GetAttrAsEnum("type", defElemType);

                if (ByteOrderEnabled)
                {
                    elem.ByteOrderStr = elemElem.GetAttribute("byteOrder");
                    elem.ByteOrder    = ModbusUtils.ParseByteOrder(elem.ByteOrderStr);
                }

                Elems.Add(elem);
            }
        }
Example #3
0
        /// <summary>
        /// Расшифровать PDU ответа
        /// </summary>
        public virtual bool DecodeRespPDU(byte[] buffer, int offset, int length, out string errMsg)
        {
            errMsg = "";
            bool result       = false;
            byte respFuncCode = buffer[offset];

            if (respFuncCode == FuncCode)
            {
                if (length == RespPduLen)
                {
                    result = true;
                }
                else
                {
                    errMsg = ModbusPhrases.IncorrectPduLength;
                }
            }
            else if (respFuncCode == ExcFuncCode)
            {
                errMsg = length == 2 ?
                         ModbusPhrases.DeviceError + ": " + ModbusUtils.GetExcDescr(buffer[offset + 1]) :
                         ModbusPhrases.IncorrectPduLength;
            }
            else
            {
                errMsg = ModbusPhrases.IncorrectPduFuncCode;
            }

            return(result);
        }
Example #4
0
        /// <summary>
        /// Инициализировать PDU запроса, рассчитать длину ответа
        /// </summary>
        public override void InitReqPDU()
        {
            if (Multiple)
            {
                // формирование PDU для команды WriteMultipleCoils или WriteMultipleRegisters
                int dataLength = TableType == TableType.Coils ?
                                 ((ElemCnt % 8 == 0) ? ElemCnt / 8 : ElemCnt / 8 + 1) :
                                 ElemCnt *ModbusUtils.GetDataLength(ElemType);

                ReqPDU    = new byte[6 + dataLength];
                ReqPDU[0] = FuncCode;
                ReqPDU[1] = (byte)(Address / 256);
                ReqPDU[2] = (byte)(Address % 256);
                ReqPDU[3] = (byte)(ElemCnt / 256);
                ReqPDU[4] = (byte)(ElemCnt % 256);
                ReqPDU[5] = (byte)dataLength;

                ModbusUtils.ApplyByteOrder(Data, 0, ReqPDU, 6, dataLength, ByteOrder, false);

                // установка длины ответа
                RespPduLen = 5;
            }
            else
            {
                // формирование PDU для команды WriteSingleCoil или WriteSingleRegister
                int dataLength = TableType == TableType.Coils ? 2 : ModbusUtils.GetDataLength(ElemType);
                ReqPDU    = new byte[3 + dataLength];
                ReqPDU[0] = FuncCode;
                ReqPDU[1] = (byte)(Address / 256);
                ReqPDU[2] = (byte)(Address % 256);

                if (TableType == TableType.Coils)
                {
                    ReqPDU[3] = Value > 0 ? (byte)0xFF : (byte)0x00;
                    ReqPDU[4] = 0x00;
                }
                else
                {
                    byte[] data = dataLength == 2 ?
                                  new byte[] // standard Modbus
                    {
                        (byte)(Value / 256),
                        (byte)(Value % 256)
                    } :
                    Data;

                    ModbusUtils.ApplyByteOrder(data, 0, ReqPDU, 3, dataLength, ByteOrder, false);
                }

                // установка длины ответа
                RespPduLen = ReqPDU.Length; // echo
            }
        }
Example #5
0
        /// <summary>
        /// Получить значение элемента в соответствии с его типом, преобразованное в double
        /// </summary>
        public double GetElemVal(int elemInd)
        {
            Elem elem = Elems[elemInd];

            byte[] elemVal = ElemVals[elemInd];
            byte[] buf;

            // перестановка байт в случае необходимости
            if (elem.ByteOrder == null)
            {
                buf = elemVal;
            }
            else
            {
                buf = new byte[elemVal.Length];
                ModbusUtils.ApplyByteOrder(elemVal, buf, elem.ByteOrder);
            }

            // расчёт значения
            switch (elem.ElemType)
            {
            case ElemType.UShort:
                return(BitConverter.ToUInt16(buf, 0));

            case ElemType.Short:
                return(BitConverter.ToInt16(buf, 0));

            case ElemType.UInt:
                return(BitConverter.ToUInt32(buf, 0));

            case ElemType.Int:
                return(BitConverter.ToInt32(buf, 0));

            case ElemType.ULong:
                return(BitConverter.ToUInt64(buf, 0));

            case ElemType.Long:
                return(BitConverter.ToInt64(buf, 0));

            case ElemType.Float:
                return(BitConverter.ToSingle(buf, 0));

            case ElemType.Double:
                return(BitConverter.ToDouble(buf, 0));

            case ElemType.Bool:
                return(buf[0] > 0 ? 1.0 : 0.0);

            default:
                return(0.0);
            }
        }
Example #6
0
        /// <summary>
        /// Get the value of the element according to its type, converted to double
        /// </summary>
        public double GetElemVal(int elemInd)
        {
            var elem = Elems[elemInd];

            byte[] elemVal = ElemVals[elemInd];
            byte[] buf;

            // swapping bytes if necessary
            if (elem.ByteOrder == null)
            {
                buf = elemVal;
            }
            else
            {
                buf = new byte[elemVal.Length];
                ModbusUtils.ApplyByteOrder(elemVal, buf, elem.ByteOrder);
            }

            // calculation of value
            switch (elem.ElemType)
            {
            case ElemType.UShort:
                return(BitConverter.ToUInt16(buf, 0));

            case ElemType.Short:
                return(BitConverter.ToInt16(buf, 0));

            case ElemType.UInt:
                return(BitConverter.ToUInt32(buf, 0));

            case ElemType.Int:
                return(BitConverter.ToInt32(buf, 0));

            case ElemType.ULong:
                return(BitConverter.ToUInt64(buf, 0));

            case ElemType.Long:
                return(BitConverter.ToInt64(buf, 0));

            case ElemType.Float:
                return(BitConverter.ToSingle(buf, 0));

            case ElemType.Double:
                return(BitConverter.ToDouble(buf, 0));

            case ElemType.Bool:
                return(buf[0] > 0 ? 1.0 : 0.0);

            default:
                return(0.0);
            }
        }
Example #7
0
        /// <summary>
        /// Инициализировать ADU запроса и рассчитать длину ответа
        /// </summary>
        public virtual void InitReqADU(byte devAddr, TransModes transMode)
        {
            if (ReqPDU != null)
            {
                int pduLen = ReqPDU.Length;

                switch (transMode)
                {
                case TransModes.RTU:
                    ReqADU    = new byte[pduLen + 3];
                    ReqADU[0] = devAddr;
                    ReqPDU.CopyTo(ReqADU, 1);
                    ushort crc = ModbusUtils.CalcCRC16(ReqADU, 0, pduLen + 1);
                    ReqADU[pduLen + 1] = (byte)(crc % 256);
                    ReqADU[pduLen + 2] = (byte)(crc / 256);
                    RespAduLen         = RespPduLen + 3;
                    break;

                case TransModes.ASCII:
                    byte[] aduBuf = new byte[pduLen + 2];
                    aduBuf[0] = devAddr;
                    ReqPDU.CopyTo(aduBuf, 1);
                    aduBuf[pduLen + 1] = ModbusUtils.CalcLRC(aduBuf, 0, pduLen + 1);

                    StringBuilder sbADU = new StringBuilder();
                    foreach (byte b in aduBuf)
                    {
                        sbADU.Append(b.ToString("X2"));
                    }

                    ReqADU     = Encoding.Default.GetBytes(sbADU.ToString());
                    ReqStr     = ModbusUtils.Colon + sbADU;
                    RespAduLen = RespPduLen + 2;
                    break;

                default:     // TransModes.TCP
                    ReqADU    = new byte[pduLen + 7];
                    ReqADU[0] = 0;
                    ReqADU[1] = 0;
                    ReqADU[2] = 0;
                    ReqADU[3] = 0;
                    ReqADU[4] = (byte)((pduLen + 1) / 256);
                    ReqADU[5] = (byte)((pduLen + 1) % 256);
                    ReqADU[6] = devAddr;
                    ReqPDU.CopyTo(ReqADU, 7);
                    RespAduLen = RespPduLen + 7;
                    break;
                }
            }
        }
Example #8
0
            /// <summary>
            /// Загрузить настройки шаблона из XML-узла
            /// </summary>
            public void LoadFromXml(XmlElement settingsElem)
            {
                if (settingsElem == null)
                {
                    throw new ArgumentNullException("settingsElem");
                }

                ZeroAddr      = settingsElem.GetChildAsBool("ZeroAddr", false);
                DecAddr       = settingsElem.GetChildAsBool("DecAddr", true);
                DefByteOrder2 = settingsElem.GetChildAsString("DefByteOrder2");
                DefByteOrder4 = settingsElem.GetChildAsString("DefByteOrder4");
                DefByteOrder8 = settingsElem.GetChildAsString("DefByteOrder8");

                defByteOrder2 = ModbusUtils.ParseByteOrder(DefByteOrder2);
                defByteOrder4 = ModbusUtils.ParseByteOrder(DefByteOrder4);
                defByteOrder8 = ModbusUtils.ParseByteOrder(DefByteOrder8);
            }
Example #9
0
        /// <summary>
        /// Инициализировать PDU запроса, рассчитать длину ответа
        /// </summary>
        public override void InitReqPDU()
        {
            if (Multiple)
            {
                // формирование PDU для команды WriteMultipleCoils или WriteMultipleRegisters
                int byteCnt = TableType == TableType.Coils ?
                              ((ElemCnt % 8 == 0) ? ElemCnt / 8 : ElemCnt / 8 + 1) :
                              ElemCnt * 2;

                ReqPDU    = new byte[6 + byteCnt];
                ReqPDU[0] = FuncCode;
                ReqPDU[1] = (byte)(Address / 256);
                ReqPDU[2] = (byte)(Address % 256);
                ReqPDU[3] = (byte)(ElemCnt / 256);
                ReqPDU[4] = (byte)(ElemCnt % 256);
                ReqPDU[5] = (byte)byteCnt;

                ModbusUtils.ApplyByteOrder(Data, 0, ReqPDU, 6, byteCnt, ByteOrder, false);
            }
            else
            {
                // формирование PDU для команды WriteSingleCoil или WriteSingleRegister
                ReqPDU    = new byte[5];
                ReqPDU[0] = FuncCode;
                ReqPDU[1] = (byte)(Address / 256);
                ReqPDU[2] = (byte)(Address % 256);

                if (TableType == TableType.Coils)
                {
                    ReqPDU[3] = Value > 0 ? (byte)0xFF : (byte)0x00;
                    ReqPDU[4] = 0x00;
                }
                else
                {
                    byte[] data = new byte[]
                    {
                        (byte)(Value / 256),
                        (byte)(Value % 256)
                    };
                    ModbusUtils.ApplyByteOrder(data, 0, ReqPDU, 3, 2, ByteOrder, false);
                }
            }

            // установка длины ответа
            RespPduLen = 5;
        }
Example #10
0
        /// <summary>
        /// Loads the command from the XML node.
        /// </summary>
        public virtual void LoadFromXml(XmlElement cmdElem)
        {
            if (cmdElem == null)
            {
                throw new ArgumentNullException("cmdElem");
            }

            Address  = (ushort)cmdElem.GetAttrAsInt("address");
            ElemType = cmdElem.GetAttrAsEnum("elemType", DefElemType);
            ElemCnt  = cmdElem.GetAttrAsInt("elemCnt", 1);
            Name     = cmdElem.GetAttribute("name");
            CmdNum   = cmdElem.GetAttrAsInt("cmdNum");

            if (ByteOrderEnabled)
            {
                ByteOrderStr = cmdElem.GetAttribute("byteOrder");
                ByteOrder    = ModbusUtils.ParseByteOrder(ByteOrderStr);
            }
        }
Example #11
0
        /// <inheritdoc />
        /// <summary>
        /// Initialize the request PDU, calculate the answer length
        /// </summary>
        public override void InitReqPDU()
        {
            if (Multiple)
            {
                // PDU generation for WriteMultipleCoils or WriteMultipleRegisters command
                int byteCnt = TableType == TableType.Coils
                    ? ((ElemCnt % 8 == 0) ? ElemCnt / 8 : ElemCnt / 8 + 1)
                    : ElemCnt * 2;

                ReqPDU    = new byte[6 + byteCnt];
                ReqPDU[0] = FuncCode;
                ReqPDU[1] = (byte)(Address / 256);
                ReqPDU[2] = (byte)(Address % 256);
                ReqPDU[3] = (byte)(ElemCnt / 256);
                ReqPDU[4] = (byte)(ElemCnt % 256);
                ReqPDU[5] = (byte)byteCnt;

                ModbusUtils.ApplyByteOrder(Data, ReqPDU, 6, byteCnt, ByteOrder);
            }
            else
            {
                // PDU generation for WriteSingleCoil or WriteSingleRegister
                ReqPDU    = new byte[5];
                ReqPDU[0] = FuncCode;
                ReqPDU[1] = (byte)(Address / 256);
                ReqPDU[2] = (byte)(Address % 256);

                if (TableType == TableType.Coils)
                {
                    ReqPDU[3] = Value > 0 ? (byte)0xFF : (byte)0x00;
                    ReqPDU[4] = 0x00;
                }
                else
                {
                    var data = new byte[] { (byte)(Value / 256), (byte)(Value % 256) };
                    ModbusUtils.ApplyByteOrder(data, ReqPDU, 3, 2, ByteOrder);
                }
            }

            // setting the length of the response
            RespPduLen = 5;
        }
Example #12
0
        /// <summary>
        /// Загрузить шаблон устройства
        /// </summary>
        public bool Load(string fileName, out string errMsg)
        {
            SetToDefault();

            try
            {
                // загрузка шаблона устройства
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(fileName);

                // загрузка настроек шаблона
                XmlNode settingsNode = xmlDoc.DocumentElement.SelectSingleNode("Settings");
                if (settingsNode != null)
                {
                    Sett.LoadFromXml((XmlElement)settingsNode);
                }

                // загрузка групп элементов
                XmlNode elemGroupsNode = xmlDoc.DocumentElement.SelectSingleNode("ElemGroups");
                if (elemGroupsNode != null)
                {
                    int kpTagInd = 0;

                    foreach (XmlElement elemGroupElem in elemGroupsNode.ChildNodes)
                    {
                        TableTypes tableType = elemGroupElem.GetAttrAsEnum <TableTypes>("tableType");
                        ElemGroup  elemGroup = new ElemGroup(tableType);
                        elemGroup.Name          = elemGroupElem.GetAttribute("name");
                        elemGroup.Address       = (ushort)elemGroupElem.GetAttrAsInt("address");
                        elemGroup.Active        = elemGroupElem.GetAttrAsBool("active", true);
                        elemGroup.StartKPTagInd = kpTagInd;
                        elemGroup.StartSignal   = kpTagInd + 1;

                        XmlNodeList elemNodes   = elemGroupElem.SelectNodes("Elem");
                        ElemTypes   defElemType = elemGroup.DefElemType;

                        foreach (XmlElement elemElem in elemNodes)
                        {
                            Elem elem = new Elem();
                            elem.Name     = elemElem.GetAttribute("name");
                            elem.ElemType = elemElem.GetAttrAsEnum("type", defElemType);

                            if (elemGroup.ByteOrderEnabled)
                            {
                                elem.ByteOrderStr = elemElem.GetAttribute("byteOrder");
                                elem.ByteOrder    = ModbusUtils.ParseByteOrder(elem.ByteOrderStr);
                                if (elem.ByteOrder == null)
                                {
                                    elem.ByteOrder = Sett.GetDefByteOrder(elem.Length);
                                }
                            }

                            elemGroup.Elems.Add(elem);
                        }

                        if (0 < elemGroup.Elems.Count && elemGroup.Elems.Count <= DataUnit.GetMaxElemCnt(tableType))
                        {
                            ElemGroups.Add(elemGroup);
                            kpTagInd += elemGroup.Elems.Count;
                        }
                    }
                }

                // загрузка команд
                XmlNode cmdsNode = xmlDoc.DocumentElement.SelectSingleNode("Cmds");
                if (cmdsNode != null)
                {
                    foreach (XmlElement cmdElem in cmdsNode.ChildNodes)
                    {
                        ModbusCmd cmd = new ModbusCmd(
                            cmdElem.GetAttrAsEnum <TableTypes>("tableType"),
                            cmdElem.GetAttrAsBool("multiple"),
                            cmdElem.GetAttrAsInt("elemCnt", 1));
                        cmd.ElemType = cmdElem.GetAttrAsEnum("elemType", cmd.DefElemType);
                        cmd.Address  = (ushort)cmdElem.GetAttrAsInt("address");
                        cmd.Name     = cmdElem.GetAttribute("name");
                        cmd.CmdNum   = cmdElem.GetAttrAsInt("cmdNum");

                        if (cmd.ByteOrderEnabled)
                        {
                            cmd.ByteOrderStr = cmdElem.GetAttribute("byteOrder");
                            cmd.ByteOrder    = ModbusUtils.ParseByteOrder(cmd.ByteOrderStr);
                            if (cmd.ByteOrder == null)
                            {
                                cmd.ByteOrder = Sett.GetDefByteOrder(cmd.ElemCnt);
                            }
                        }

                        if (0 < cmd.CmdNum && cmd.CmdNum <= ushort.MaxValue)
                        {
                            Cmds.Add(cmd);
                        }
                    }
                }

                errMsg = "";
                return(true);
            }
            catch (Exception ex)
            {
                errMsg = ModbusPhrases.LoadTemplateError + ":" + Environment.NewLine + ex.Message;
                return(false);
            }
        }
Example #13
0
        /// <summary>
        /// Выполнить запрос в режиме ASCII
        /// </summary>
        public bool AsciiRequest(DataUnit dataUnit)
        {
            if (!CheckConnection())
            {
                return(false);
            }

            bool result = false;

            // отправка запроса
            ExecWriteToLog(dataUnit.ReqDescr);
            Connection.WriteLine(dataUnit.ReqStr, out string logText);
            ExecWriteToLog(logText);

            // приём ответа
            string line = Connection.ReadLine(Timeout, out logText);

            ExecWriteToLog(logText);
            int lineLen = line == null ? 0 : line.Length;

            if (lineLen >= 3)
            {
                int aduLen = (lineLen - 1) / 2;

                if (aduLen == dataUnit.RespAduLen && lineLen % 2 == 1)
                {
                    // получение ADU ответа
                    byte[] aduBuf  = new byte[aduLen];
                    bool   parseOK = true;

                    for (int i = 0, j = 1; i < aduLen && parseOK; i++, j += 2)
                    {
                        try
                        {
                            aduBuf[i] = byte.Parse(line.Substring(j, 2), NumberStyles.HexNumber);
                        }
                        catch
                        {
                            ExecWriteToLog(ModbusPhrases.IncorrectSymbol);
                            parseOK = false;
                        }
                    }

                    if (parseOK)
                    {
                        if (aduBuf[aduLen - 1] == ModbusUtils.CalcLRC(aduBuf, 0, aduLen - 1))
                        {
                            // расшифровка ответа
                            string errMsg;

                            if (dataUnit.DecodeRespPDU(aduBuf, 1, aduLen - 2, out errMsg))
                            {
                                ExecWriteToLog(ModbusPhrases.OK);
                                result = true;
                            }
                            else
                            {
                                ExecWriteToLog(errMsg + "!");
                            }
                        }
                        else
                        {
                            ExecWriteToLog(ModbusPhrases.LrcError);
                        }
                    }
                }
                else
                {
                    ExecWriteToLog(ModbusPhrases.IncorrectAduLength);
                }
            }
            else
            {
                ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation);
            }

            return(result);
        }
Example #14
0
        /// <summary>
        /// Выполнить запрос в режиме RTU
        /// </summary>
        public bool RtuRequest(DataUnit dataUnit)
        {
            if (!CheckConnection())
            {
                return(false);
            }

            bool result = false;

            // отправка запроса
            ExecWriteToLog(dataUnit.ReqDescr);
            Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length,
                             CommUtils.ProtocolLogFormats.Hex, out string logText);
            ExecWriteToLog(logText);

            // приём ответа
            // считывание начала ответа для определения длины PDU
            int readCnt = Connection.Read(InBuf, 0, 5, Timeout, CommUtils.ProtocolLogFormats.Hex, out logText);

            ExecWriteToLog(logText);

            if (readCnt == 5)
            {
                int pduLen;
                int count;

                if (InBuf[0] != dataUnit.ReqADU[0]) // проверка адреса устройства в ответе
                {
                    ExecWriteToLog(ModbusPhrases.IncorrectDevAddr);
                }
                else if (!(InBuf[1] == dataUnit.FuncCode || InBuf[1] == dataUnit.ExcFuncCode))
                {
                    ExecWriteToLog(ModbusPhrases.IncorrectPduFuncCode);
                }
                else
                {
                    if (InBuf[1] == dataUnit.FuncCode)
                    {
                        // считывание окончания ответа
                        pduLen = dataUnit.RespPduLen;
                        count  = dataUnit.RespAduLen - 5;

                        readCnt = Connection.Read(InBuf, 5, count, Timeout,
                                                  CommUtils.ProtocolLogFormats.Hex, out logText);
                        ExecWriteToLog(logText);
                    }
                    else // устройство вернуло исключение
                    {
                        pduLen  = 2;
                        count   = 0;
                        readCnt = 0;
                    }

                    if (readCnt == count)
                    {
                        if (InBuf[pduLen + 1] + InBuf[pduLen + 2] * 256 == ModbusUtils.CalcCRC16(InBuf, 0, pduLen + 1))
                        {
                            // расшифровка ответа
                            string errMsg;

                            if (dataUnit.DecodeRespPDU(InBuf, 1, pduLen, out errMsg))
                            {
                                ExecWriteToLog(ModbusPhrases.OK);
                                result = true;
                            }
                            else
                            {
                                ExecWriteToLog(errMsg + "!");
                            }
                        }
                        else
                        {
                            ExecWriteToLog(ModbusPhrases.CrcError);
                        }
                    }
                    else
                    {
                        ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation);
                    }
                }
            }
            else
            {
                ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation);
            }

            return(result);
        }
Example #15
0
        /// <summary>
        /// Run ASCII query
        /// </summary>
        public bool AsciiRequest(DataUnit dataUnit)
        {
            if (!CheckConnection())
            {
                return(false);
            }

            var result = false;

            // sending request
            ExecWriteToLog(dataUnit.ReqDescr);
            Connection.WriteLine(dataUnit.ReqStr, out string logText);
            ExecWriteToLog(logText);

            // reception of the answer
            string line = Connection.ReadLine(Timeout, out logText);

            ExecWriteToLog(logText);
            int lineLen = line == null ? 0 : line.Length;

            if (lineLen >= 3)
            {
                int aduLen = (lineLen - 1) / 2;

                if (aduLen == dataUnit.RespAduLen && lineLen % 2 == 1)
                {
                    // getting ADU response
                    var aduBuf  = new byte[aduLen];
                    var parseOK = true;

                    for (int i = 0,
                         j = 1;
                         i < aduLen && parseOK;
                         i++, j += 2)
                    {
                        try {
                            aduBuf[i] = byte.Parse(line.Substring(j, 2), NumberStyles.HexNumber);
                        } catch {
                            ExecWriteToLog(ModbusPhrases.IncorrectSymbol);
                            parseOK = false;
                        }
                    }

                    if (parseOK)
                    {
                        if (aduBuf[aduLen - 1] == ModbusUtils.CalcLRC(aduBuf, 0, aduLen - 1))
                        {
                            // answer decryption
                            string errMsg;

                            if (dataUnit.DecodeRespPDU(aduBuf, 1, aduLen - 2, out errMsg))
                            {
                                ExecWriteToLog(ModbusPhrases.OK);
                                result = true;
                            }
                            else
                            {
                                ExecWriteToLog(errMsg + "!");
                            }
                        }
                        else
                        {
                            ExecWriteToLog(ModbusPhrases.LrcError);
                        }
                    }
                }
                else
                {
                    ExecWriteToLog(ModbusPhrases.IncorrectAduLength);
                }
            }
            else
            {
                ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation);
            }

            return(result);
        }
Example #16
0
        /// <summary>
        /// Run RTU query
        /// </summary>
        public bool RtuRequest(DataUnit dataUnit)
        {
            if (!CheckConnection())
            {
                return(false);
            }

            var result = false;

            // sending request
            ExecWriteToLog(dataUnit.ReqDescr);
            Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length,
                             CommUtils.ProtocolLogFormats.Hex, out string logText);
            ExecWriteToLog(logText);

            // reception of the answer
            // reading the start of the response to determine the length of the PDU
            int readCnt = Connection.Read(InBuf, 0, 5, Timeout, CommUtils.ProtocolLogFormats.Hex, out logText);

            ExecWriteToLog(logText);

            if (readCnt == 5)
            {
                int pduLen;
                int count;

                if (InBuf[0] != dataUnit.ReqADU[0]) // checking device address in response
                {
                    ExecWriteToLog(ModbusPhrases.IncorrectDevAddr);
                }
                else if (!(InBuf[1] == dataUnit.FuncCode || InBuf[1] == dataUnit.ExcFuncCode))
                {
                    ExecWriteToLog(ModbusPhrases.IncorrectPduFuncCode);
                }
                else
                {
                    if (InBuf[1] == dataUnit.FuncCode)
                    {
                        // read end of response
                        pduLen = dataUnit.RespPduLen;
                        count  = dataUnit.RespAduLen - 5;

                        readCnt = Connection.Read(InBuf, 5, count, Timeout,
                                                  CommUtils.ProtocolLogFormats.Hex, out logText);
                        ExecWriteToLog(logText);
                    }
                    else   // device returned exception
                    {
                        pduLen  = 2;
                        count   = 0;
                        readCnt = 0;
                    }

                    if (readCnt == count)
                    {
                        if (InBuf[pduLen + 1] + InBuf[pduLen + 2] * 256 ==
                            ModbusUtils.CalcCRC16(InBuf, 0, pduLen + 1))
                        {
                            // answer decryption
                            string errMsg;

                            if (dataUnit.DecodeRespPDU(InBuf, 1, pduLen, out errMsg))
                            {
                                ExecWriteToLog(ModbusPhrases.OK);
                                result = true;
                            }
                            else
                            {
                                ExecWriteToLog(errMsg + "!");
                            }
                        }
                        else
                        {
                            ExecWriteToLog(ModbusPhrases.CrcError);
                        }
                    }
                    else
                    {
                        ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation);
                    }
                }
            }
            else
            {
                ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation);
            }

            return(result);
        }
Example #17
0
 /// <summary>
 /// Gets the default number of command elements depending on the element type.
 /// </summary>
 public virtual int GetDefElemCnt(ElemType elemType)
 {
     return(ModbusUtils.GetQuantity(elemType));
 }