예제 #1
0
        /// <summary>
        /// Performs a request in the ASCII mode.
        /// </summary>
        protected bool AsciiRequest(DataUnit dataUnit)
        {
            bool result = false;

            // send request
            log.WriteLine(dataUnit.ReqDescr);
            Connection.WriteLine(dataUnit.ReqStr, out string logText);
            log.WriteLine(logText);

            // receive response
            string line = Connection.ReadLine(Timeout, out logText);

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

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

                if (aduLen == dataUnit.RespAduLen && lineLen % 2 == 1)
                {
                    // receive response 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
                        {
                            log.WriteLine(ModbusPhrases.IncorrectSymbol);
                            parseOK = false;
                        }
                    }

                    if (parseOK)
                    {
                        if (aduBuf[aduLen - 1] == ModbusUtils.LRC(aduBuf, 0, aduLen - 1))
                        {
                            // decode response
                            if (dataUnit.DecodeRespPDU(aduBuf, 1, aduLen - 2, out string errMsg))
                            {
                                log.WriteLine(ModbusPhrases.OK);
                                result = true;
                            }
                            else
                            {
                                log.WriteLine(errMsg + "!");
                            }
                        }
                        else
                        {
                            log.WriteLine(ModbusPhrases.LrcError);
                        }
                    }
                }
                else
                {
                    log.WriteLine(ModbusPhrases.IncorrectAduLength);
                }
            }
            else
            {
                log.WriteLine(ModbusPhrases.CommErrorWithExclamation);
            }

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Performs a request in the TCP mode.
        /// </summary>
        protected bool TcpRequest(DataUnit dataUnit)
        {
            bool result = false;

            // specify transaction ID
            if (++TransactionID == 0)
            {
                TransactionID = 1;
            }

            dataUnit.ReqADU[0] = (byte)(TransactionID / 256);
            dataUnit.ReqADU[1] = (byte)(TransactionID % 256);

            // send request
            log.WriteLine(dataUnit.ReqDescr);
            Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length, ProtocolFormat.Hex, out string logText);
            log.WriteLine(logText);

            // receive response
            // read MBAP header
            int readCnt = Connection.Read(InBuf, 0, 7, Timeout, ProtocolFormat.Hex, out logText);

            log.WriteLine(logText);

            if (readCnt == 7)
            {
                int pduLen = InBuf[4] * 256 + InBuf[5] - 1;

                if (InBuf[0] == dataUnit.ReqADU[0] && InBuf[1] == dataUnit.ReqADU[1] && // transaction ID
                    InBuf[2] == 0 && InBuf[3] == 0 && pduLen > 0 &&                     // protocol ID
                    InBuf[6] == dataUnit.ReqADU[6])                                     // unit ID
                {
                    // read PDU
                    readCnt = Connection.Read(InBuf, 7, pduLen, Timeout, ProtocolFormat.Hex, out logText);
                    log.WriteLine(logText);

                    if (readCnt == pduLen)
                    {
                        // decode response
                        if (dataUnit.DecodeRespPDU(InBuf, 7, pduLen, out string errMsg))
                        {
                            log.WriteLine(ModbusPhrases.OK);
                            result = true;
                        }
                        else
                        {
                            log.WriteLine(errMsg + "!");
                        }
                    }
                    else
                    {
                        log.WriteLine(ModbusPhrases.CommErrorWithExclamation);
                    }
                }
                else
                {
                    log.WriteLine(ModbusPhrases.IncorrectMbap);
                }
            }
            else
            {
                log.WriteLine(ModbusPhrases.CommErrorWithExclamation);
            }

            return(result);
        }
예제 #3
0
        /// <summary>
        /// Performs a request in the PDU mode.
        /// </summary>
        protected bool RtuRequest(DataUnit dataUnit)
        {
            bool result = false;

            // send request
            log.WriteLine(dataUnit.ReqDescr);
            Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length, ProtocolFormat.Hex, out string logText);
            log.WriteLine(logText);

            // receive response
            // partial read to calculate PDU length
            const int FirstCount = 2;
            int       readCnt    = Connection.Read(InBuf, 0, FirstCount, Timeout, ProtocolFormat.Hex, out logText);

            log.WriteLine(logText);

            if (readCnt != FirstCount)
            {
                log.WriteLine(ModbusPhrases.CommErrorWithExclamation);
            }
            else if (InBuf[0] != dataUnit.ReqADU[0]) // validate device address
            {
                log.WriteLine(ModbusPhrases.IncorrectDevAddr);
            }
            else if (!(InBuf[1] == dataUnit.FuncCode || InBuf[1] == dataUnit.ExcFuncCode)) // validate function code
            {
                log.WriteLine(ModbusPhrases.IncorrectPduFuncCode);
            }
            else
            {
                int pduLen;
                int count;

                if (InBuf[1] == dataUnit.FuncCode)
                {
                    pduLen = dataUnit.RespPduLen;
                    count  = dataUnit.RespAduLen - FirstCount;
                }
                else // exception received
                {
                    pduLen = 2;
                    count  = 3;
                }

                // read rest of response
                readCnt = Connection.Read(InBuf, FirstCount, count, Timeout, ProtocolFormat.Hex, out logText);
                log.WriteLine(logText);

                if (readCnt != count)
                {
                    log.WriteLine(ModbusPhrases.CommErrorWithExclamation);
                }
                else if (InBuf[pduLen + 1] + InBuf[pduLen + 2] * 256 != ModbusUtils.CRC16(InBuf, 0, pduLen + 1))
                {
                    log.WriteLine(ModbusPhrases.CrcError);
                }
                else if (dataUnit.DecodeRespPDU(InBuf, 1, pduLen, out string errMsg))
                {
                    log.WriteLine(ModbusPhrases.OK);
                    result = true;
                }
                else
                {
                    log.WriteLine(errMsg + "!");
                }
            }

            return(result);
        }