private static string getROWORequestsPropertiesString(ReadWriteRequest readWriteRequest)
        {
            string result = String.Empty;

            // The string results format is:
            // RequestType:OperandType-StartAddress-NumberOfOperands.  where
            // ':' - is the delimitator for the requestType
            // '-' - is the delimitator between request properties.
            // '.' - used to mark the end of the request properties.
            // Example: RO:MI-1-10. means Read 10 MI from address 1.

            if (readWriteRequest is ReadOperands)
            {
                ReadOperands ro = readWriteRequest as ReadOperands;

                result += "RO:" + ro.OperandType.ToString() +
                          "-" + ro.StartAddress.ToString() +
                          "-" + ro.NumberOfOperands.ToString() +
                          ".";
            }
            else
            {
                WriteOperands wo = readWriteRequest as WriteOperands;
                result += "WO" + wo.OperandType.ToString() +
                          "-" + wo.StartAddress.ToString() +
                          "-" + wo.NumberOfOperands.ToString() +
                          ".";
            }

            return(result);
        }
        private bool ReadDataTableFitsThePlcBuffer(ReadWriteRequest readWriteRequest)
        {
            ReadDataTables rdt         = readWriteRequest as ReadDataTables;
            int            requestSize = rdt.NumberOfRowsToRead * rdt.NumberOfBytesToReadInRow;

            return(requestSize <= PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_HEADER_AND_FOOTER);
        }
        private bool WriteDataTableFitsThePlcBuffer(ReadWriteRequest readWriteRequest)
        {
            WriteDataTables wdt            = readWriteRequest as WriteDataTables;
            int             wdtRequestSize = Utils.Lengths.LENGTH_HEADER_AND_FOOTER +
                                             Utils.Lengths.LENGTH_WRITE_DATA_TABLE_DETAILS +
                                             wdt.NumberOfBytesToWriteInRow * wdt.NumberOfRowsToWrite;

            return(wdtRequestSize <= PLCVersion.PlcBuffer);
        }
        private bool receiveMessageSizeFitsThePLCBuffer(ReadWriteRequest operand)
        {
            ReadOperands readOperands       = operand as ReadOperands;
            int          operandSize        = Utils.GetOperandSizeByCommandCode(readOperands.OperandType.ToString());
            int          receiveDataSize    = readOperands.NumberOfOperands * operandSize;
            int          receiveMessageSize = Utils.Lengths.LENGTH_ASCII_RECEIVE_MESSAGE + receiveDataSize;

            return(receiveMessageSize <= PLCVersion.PlcBuffer && readOperands.NumberOfOperands <= 255);
        }
        private void ReadWriteWriteOperand(ReadWriteRequest operand, string parentID, bool suppressEthernetHeader)
        {
            WriteOperands writeOperands = operand as WriteOperands;
            GuidClass     guid          = new GuidClass();

            pcomA.BuildAsciiCommand(UnitId,
                                    Utils.ASCIIOperandTypes[Enum.GetName(typeof(OperandTypes), writeOperands.OperandType)]
                                    .CommandCodeForWrite,
                                    (operand as WriteOperands).StartAddress, writeOperands.NumberOfOperands, writeOperands.Values,
                                    (operand as WriteOperands).TimerValueFormat);

            string readMessage = pcomA.MessageToPLC as string;

            if (this.BreakFlag)
            {
                throw new ComDriveExceptions("Request aborted by user",
                                             ComDriveExceptions.ComDriveException.AbortedByUser);
            }

            lock (guid)
            {
                Channel.Send(readMessage, ReceiveString, guid, parentID, "ASCII Protocol - Write Operands", PlcGuid,
                             suppressEthernetHeader);
                Monitor.Wait(guid);
            }

            if (this.BreakFlag)
            {
                throw new ComDriveExceptions("Request aborted by user",
                                             ComDriveExceptions.ComDriveException.AbortedByUser);
            }

            PlcResponseMessage plcResponseMessage;

            lock (_lockObj)
            {
                plcResponseMessage = m_responseMessageQueue[guid];
                m_responseMessageQueue.Remove(guid);
            }

            if (plcResponseMessage.comException == CommunicationException.Timeout)
            {
                throw new ComDriveExceptions("Cannot communicate with the PLC with the specified UnitID!",
                                             ComDriveExceptions.ComDriveException.CommunicationTimeout);
            }

            pcomA.DisAssembleAsciiResult(plcResponseMessage.response, UnitId,
                                         Utils.ASCIIOperandTypes[Enum.GetName(typeof(OperandTypes), writeOperands.OperandType)]
                                         .CommandCodeForWrite,
                                         (operand as WriteOperands).StartAddress, writeOperands.NumberOfOperands, null,
                                         writeOperands.TimerValueFormat);
            if (pcomA.MessageFromPLC != null)
            {
                operand.ResponseValues = (pcomA.MessageFromPLC as AbstractASCIIMessage).Values;
            }
        }
        private bool sentMessageSizeFitsThePLCBuffer(ReadWriteRequest operand)
        {
            WriteOperands writeOperands   = operand as WriteOperands;
            int           operandSize     = Utils.GetOperandSizeByCommandCode(writeOperands.OperandType.ToString());
            int           sentDataSize    = writeOperands.NumberOfOperands * operandSize;
            int           sentMessageSize = 0;

            sentMessageSize = Utils.Lengths.LENGTH_ASCII_SEND_MESSAGE + sentDataSize + Utils.Lengths.LENGTH_LENGTH +
                              Utils.Lengths.LENGTH_ADDRESS;
            return(sentMessageSize <= PLCVersion.PlcBuffer && writeOperands.NumberOfOperands <= 255);
        }
 private byte GetOperandSize(ReadWriteRequest dr)
 {
     if (dr is ReadOperands)
     {
         return((dr as ReadOperands).OperandType.ToString().GetOperandIdByName().GetOperandSizeByValue());
     }
     else
     {
         return((dr as WriteOperands).OperandType.ToString().GetOperandIdByName().GetOperandSizeByValue());
     }
 }
        private void _receiveSizeExceedPLCBUffer(ReadWriteRequest readWriteRequest)
        {
            ReadOperands ro = readWriteRequest as ReadOperands;
            ushort       availableReceiveSize  = (ushort)(plcBuffer - bytesNoToReceive - (Utils.Lengths.LENGTH_WR_DETAILS));
            ushort       availableNoOfOperands = (ushort)(availableReceiveSize / operandSize);

            if (availableNoOfOperands > 255)
            {
                availableReceiveSize -=
                    (ushort)((availableNoOfOperands / 255) * (Utils.Lengths.LENGTH_WR_DETAILS + 1));
                availableReceiveSize -= 1;
                availableReceiveSize -= (ushort)((availableNoOfOperands % 255) % 2);
                availableNoOfOperands = (ushort)(availableReceiveSize / operandSize);
            }

            ushort noOfOperands = 0;
            ushort startAddress = ro.StartAddress;
            int    requestNo    = 0;

            ReadOperands remainingRo = new ReadOperands
            {
                NumberOfOperands = (ushort)(ro.NumberOfOperands - availableNoOfOperands),
                OperandType      = ro.OperandType,
                StartAddress     = (ushort)(ro.StartAddress + availableNoOfOperands),
                TimerValueFormat = ro.TimerValueFormat
            };


            while (availableNoOfOperands > 0)
            {
                if (availableNoOfOperands > 255)
                {
                    noOfOperands           = 255;
                    availableNoOfOperands -= noOfOperands;
                }
                else
                {
                    noOfOperands          = availableNoOfOperands;
                    availableNoOfOperands = 0;
                }

                requestNo++;
                ReadOperands tmpRO = new ReadOperands(noOfOperands, ro.OperandType, startAddress, ro.TimerValueFormat);
                requestsList.Add(tmpRO);
                startAddress += noOfOperands;
                _updateSplitDetailsList();
            }

            ReadWriteRequest[] tmpReq = requestsList.ToArray();
            allRequestsList.Add(tmpReq.ToList());

            _resetRequestsList();
            AddNewRequest(remainingRo, reqPosition, true);
        }
        private void _addRequestsWhenNoOfOperandsExceed255(ReadWriteRequest readWriteRequest)
        {
            ushort startAddress;
            ushort noOfOperands;
            ushort remainingNoOfOperands;

            if (readWriteRequest is ReadOperands)
            {
                ReadOperands ro = readWriteRequest as ReadOperands;
                remainingNoOfOperands = ro.NumberOfOperands;
                startAddress          = ro.StartAddress;
                noOfOperands          = 255;

                while (remainingNoOfOperands > 0)
                {
                    requestsList.Add(new ReadOperands(noOfOperands, ro.OperandType, startAddress, ro.TimerValueFormat));
                    startAddress          += noOfOperands;
                    remainingNoOfOperands -= noOfOperands;

                    if (remainingNoOfOperands <= 255)
                    {
                        noOfOperands = remainingNoOfOperands;
                    }

                    _updateSplitDetailsList();
                }
            }
            else
            {
                WriteOperands wo = readWriteRequest as WriteOperands;
                remainingNoOfOperands = wo.NumberOfOperands;
                startAddress          = wo.StartAddress;
                noOfOperands          = 255;

                while (remainingNoOfOperands > 0)
                {
                    object[] values = new object[noOfOperands];
                    Array.Copy(wo.Values, startAddress - wo.StartAddress, values, 0, noOfOperands);

                    requestsList.Add(new WriteOperands(noOfOperands, wo.OperandType, startAddress, values,
                                                       wo.TimerValueFormat));
                    startAddress          += noOfOperands;
                    remainingNoOfOperands -= noOfOperands;

                    if (remainingNoOfOperands <= 255)
                    {
                        noOfOperands = remainingNoOfOperands;
                    }

                    _updateSplitDetailsList();
                }
            }
        }
示例#10
0
        internal void AddNewRequest(ReadWriteRequest readWriteRequest, int reqPosition, bool splitFlag)
        {
            this.reqPosition = reqPosition;
            _getRequestBytesSize(readWriteRequest);

            if (_requestsSizeFitsPLCBuffer())
            {
                _addToRequests(readWriteRequest, splitFlag);
            }
            else
            {
                _sizeExceedPLCBuffer(readWriteRequest, splitFlag);
            }
        }
示例#11
0
        private List <WriteOperands> GetSplitedWriteOperands(ReadWriteRequest operand)
        {
            WriteOperands writeOperands = operand as WriteOperands;

            List <WriteOperands> results = new List <WriteOperands>();
            int    operandSize           = Utils.GetOperandSizeByCommandCode(writeOperands.OperandType.ToString());
            ushort startAddress          = writeOperands.StartAddress;
            ushort remainingNoOfOperands = writeOperands.NumberOfOperands;
            int    splitMaxDataSize      = PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_ASCII_SEND_MESSAGE -
                                           Utils.Lengths.LENGTH_ADDRESS;
            ushort splitMaxNoOfOperands = (ushort)(splitMaxDataSize / operandSize);

            object[] valuesToWrite    = (operand as WriteOperands).Values;
            int      sourceIndex      = 0;
            int      destinationIndex = 0;

            if (splitMaxNoOfOperands > 255)
            {
                splitMaxNoOfOperands = 255;
            }

            bool bDone = false;

            while (!bDone)
            {
                if (remainingNoOfOperands <= splitMaxNoOfOperands)
                {
                    object[] splitValues = new object[remainingNoOfOperands];
                    Array.Copy(valuesToWrite, sourceIndex, splitValues, destinationIndex, remainingNoOfOperands);
                    results.Add(new WriteOperands(remainingNoOfOperands, writeOperands.OperandType, startAddress,
                                                  splitValues, writeOperands.TimerValueFormat));
                    bDone = true;
                }
                else
                {
                    object[] splitValues = new object[splitMaxNoOfOperands];
                    Array.Copy(valuesToWrite, sourceIndex, splitValues, destinationIndex, splitMaxNoOfOperands);
                    results.Add(new WriteOperands(splitMaxNoOfOperands, writeOperands.OperandType, startAddress,
                                                  splitValues.ToArray(), writeOperands.TimerValueFormat));
                    startAddress          += splitMaxNoOfOperands;
                    remainingNoOfOperands -= splitMaxNoOfOperands;
                    sourceIndex           += splitMaxNoOfOperands;
                }
            }

            return(results);
        }
示例#12
0
        /// <summary>
        /// Processes a batch of read requests.
        /// </summary>
        private ServiceResult ProcessReadRequests(List <ReadWriteRequest> requests)
        {
            for (int ii = 0; ii < requests.Count; ii++)
            {
                ReadWriteRequest request = requests[ii];

                double value = 0;

                if (!m_externalValues.TryGetValue(request.Handle.NodeId, out value))
                {
                    m_externalValues[request.Handle.NodeId] = 0;
                }

                request.Value = new Variant(value);
            }

            return(ServiceResult.Good);
        }
示例#13
0
        /// <summary>
        /// Processes a batch of write requests.
        /// </summary>
        private ServiceResult ProcessWriteRequests(List <ReadWriteRequest> requests)
        {
            for (int ii = 0; ii < requests.Count; ii++)
            {
                ReadWriteRequest request = requests[ii];

                #region Task #D4 - Add Support for Access Control
                if (!HasAccess(request.UserIdentity, request.Handle.NodeId))
                {
                    request.Result = StatusCodes.BadUserAccessDenied;
                    continue;
                }
                #endregion

                m_externalValues[request.Handle.NodeId] = (double)request.Value.Value;
            }

            return(ServiceResult.Good);
        }
示例#14
0
        private int GetReadOperandReceiveSize(ReadWriteRequest readWriteRequest)
        {
            ReadOperands readOperands = readWriteRequest as ReadOperands;
            int          operandSize  = readOperands.OperandType.GetOperandSizeByOperandTypeForFullBinarry();
            int          result       = 0;

            if (operandSize == 1)
            {
                result = (readOperands.NumberOfOperands / 8);
                if (readOperands.NumberOfOperands % 8 != 0)
                {
                    result++;
                }
            }
            else
            {
                result = operandSize * readOperands.NumberOfOperands;
            }

            return(result);
        }
示例#15
0
        private void _sizeExceedPLCBuffer(ReadWriteRequest readWriteRequest, bool splitFlag)
        {
            if (_canWriteAtLeast1Operand() && _canReadAtLeast1Operand())
            {
                if (readWriteRequest is ReadOperands)
                {
                    _receiveSizeExceedPLCBUffer(readWriteRequest);
                }
                else
                {
                    _sendSizeExceedPLCBuffer(readWriteRequest);
                }
            }
            else
            {
                ReadWriteRequest[] tmpReq = requestsList.ToArray();
                allRequestsList.Add(tmpReq.ToList());

                _resetRequestsList();
                AddNewRequest(readWriteRequest, reqPosition, splitFlag);
            }
        }
示例#16
0
        private void _addToRequests(ReadWriteRequest readWriteRequest, bool splitFlag)
        {
            ushort noOfOperands = (readWriteRequest is ReadOperands)
                ? (readWriteRequest as ReadOperands).NumberOfOperands
                : (readWriteRequest as WriteOperands).NumberOfOperands;

            if (noOfOperands > 255)
            {
                _addRequestsWhenNoOfOperandsExceed255(readWriteRequest);
            }
            else
            {
                requestsList.Add(readWriteRequest);

                if (splitFlag)
                {
                    _updateSplitDetailsList();
                }
            }

            _updateRequestsListSize();
        }
        private static string getRDTorWDTRequestsPropertiesString(ReadWriteRequest readWriteRequest)
        {
            string result = String.Empty;

            // The string results format is:
            // RequestType:StartAddress-NumberOfRowsToRead/Write-RowSizeInBytes-NumberOfBytesToRead/WriteInRow.
            // ':' - is the delimitator for the requestType
            // '-' - is the delimitator between request properties.
            // '.' - used to mark the end of the request properties.
            // Example: RDT:1-10-20-10.

            if (readWriteRequest is ReadDataTables)
            {
                ReadDataTables rdt = readWriteRequest as ReadDataTables;

                result += "RDT:" + rdt.StartAddress.ToString() +
                          "-" + rdt.NumberOfRowsToRead.ToString() +
                          "-" + rdt.RowSizeInBytes.ToString() +
                          "-" + rdt.NumberOfBytesToReadInRow.ToString() +
                          "-" + rdt.PartOfProject.ToString() +
                          "-" + rdt.SubCommand.ToString() +
                          ".";
            }
            else
            {
                WriteDataTables wdt = readWriteRequest as WriteDataTables;
                result += "WDT" + wdt.StartAddress.ToString() +
                          "-" + wdt.NumberOfRowsToWrite.ToString() +
                          "-" + wdt.RowSizeInBytes.ToString() +
                          "-" + wdt.NumberOfBytesToWriteInRow.ToString() +
                          "-" + wdt.SubCommand.ToString() +
                          ".";
            }

            return(result);
        }
示例#18
0
        private List <ReadOperands> GetSplitedReadOperands(ReadWriteRequest operand)
        {
            ReadOperands        readOpearnd = operand as ReadOperands;
            List <ReadOperands> results     = new List <ReadOperands>();
            int    operandSize           = Utils.GetOperandSizeByCommandCode(readOpearnd.OperandType.ToString());
            ushort startAddress          = readOpearnd.StartAddress;
            ushort remainingNoOfOperands = readOpearnd.NumberOfOperands;
            int    splitMaxDataSize      = PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_ASCII_RECEIVE_MESSAGE;
            ushort splitMaxNoOfOperands  = (ushort)(splitMaxDataSize / operandSize);

            if (splitMaxNoOfOperands > 255)
            {
                splitMaxNoOfOperands = 255;
            }

            bool bDone = false;

            while (!bDone)
            {
                if (remainingNoOfOperands <= splitMaxNoOfOperands)
                {
                    results.Add(new ReadOperands(remainingNoOfOperands, readOpearnd.OperandType, startAddress,
                                                 readOpearnd.TimerValueFormat));
                    bDone = true;
                }
                else
                {
                    results.Add(new ReadOperands(splitMaxNoOfOperands, readOpearnd.OperandType, startAddress,
                                                 readOpearnd.TimerValueFormat));
                    startAddress          += splitMaxNoOfOperands;
                    remainingNoOfOperands -= splitMaxNoOfOperands;
                }
            }

            return(results);
        }
示例#19
0
        private void SplitAndSendBinaryData(ReadWriteRequest binaryRequest, string parentID)
        {
            BinaryRequest binRequest = binaryRequest as BinaryRequest;

            PComB pComB = new PComB();

            int       offsetInBuffer                = 0;
            int       chunkSize                     = 0;
            int       outgoingBufferSize            = 0;
            int       currentAddress                = binRequest.Address;
            int       messageKey                    = binRequest.MessageKey;
            const int MIN_TIME_BETWEEN_CHUNKS_WRITE = 20;

            GuidClass          guid;
            PlcResponseMessage plcResponseMessage;

            byte[] outgoingChunk;

            if (binRequest.OutgoingBuffer != null)
            {
                outgoingBufferSize = binRequest.OutgoingBuffer.Length;
            }

            switch (binRequest.CommandCode)
            {
            case 0x1:
            case 0x41:
            case 75:
            case 5:

                if ((binRequest.OutgoingBuffer == null) || (outgoingBufferSize == 0))
                {
                    binRequest.RaiseProgressEvent(0, binRequest.ElementsCount,
                                                  RequestProgress.en_NotificationType.SetMinMax, 0, "");
                    binRequest.RaiseProgressEvent(0, binRequest.ElementsCount,
                                                  RequestProgress.en_NotificationType.ProgressChanged, 0, "");

                    if (this.BreakFlag)
                    {
                        throw new ComDriveExceptions("Request aborted by user",
                                                     ComDriveExceptions.ComDriveException.AbortedByUser);
                    }

                    if (binRequest.WaitForIdle)
                    {
                        WaitForFlashIdle((byte)UnitId, parentID);
                    }


                    byte[] arrivedData = new byte[binRequest.ElementsCount];
                    while (offsetInBuffer < binRequest.ElementsCount)
                    {
                        int sizeOfDataToCopy;

                        if (this.BreakFlag)
                        {
                            throw new ComDriveExceptions("Request aborted by user",
                                                         ComDriveExceptions.ComDriveException.AbortedByUser);
                        }
                        chunkSize        = binRequest.ElementsCount - offsetInBuffer;
                        sizeOfDataToCopy = chunkSize;

                        if (chunkSize > PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_HEADER_AND_FOOTER)
                        {
                            chunkSize = PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_HEADER_AND_FOOTER;
                        }

                        if (binRequest.ChunkSizeAlignment != 0)
                        {
                            // Chop the end of the chunk to fit into aligment
                            chunkSize -= (chunkSize % binRequest.ChunkSizeAlignment);
                        }

                        if (binRequest.FlashBankSize != 0)
                        {
                            // Chop the end of the chunk so the burned data will not be written on 2 different flash banks
                            if (((currentAddress + chunkSize) / binRequest.FlashBankSize) !=
                                (currentAddress / binRequest.FlashBankSize))
                            {
                                chunkSize -= ((currentAddress + chunkSize) % binRequest.FlashBankSize);
                            }
                        }

                        if (chunkSize == 0)
                        {
                            chunkSize = binRequest.ChunkSizeAlignment;
                        }
                        else
                        {
                            sizeOfDataToCopy = chunkSize;
                        }


                        pComB.BuildBinaryCommand((byte)UnitId, messageKey, binRequest.CommandCode,
                                                 binRequest.SubCommand, currentAddress, chunkSize, 0, new byte[0]);

                        guid = new GuidClass();

                        lock (guid)
                        {
                            Channel.Send(pComB.MessageToPLC as byte[], ReceiveBytes, guid, parentID,
                                         "Binary Protocol - Binary Request (" + binRequest.CommandCode.ToString() + ")",
                                         PlcGuid);
                            Monitor.Wait(guid);
                        }

                        if (this.BreakFlag)
                        {
                            throw new ComDriveExceptions("Request aborted by user",
                                                         ComDriveExceptions.ComDriveException.AbortedByUser);
                        }

                        lock (_lockObj)
                        {
                            plcResponseMessage = m_responseMessageQueue[guid];
                            m_responseMessageQueue.Remove(guid);
                        }

                        if (plcResponseMessage.comException == CommunicationException.Timeout)
                        {
                            throw new ComDriveExceptions(
                                      "Cannot communicate with the PLC with the specified UnitID!",
                                      ComDriveExceptions.ComDriveException.CommunicationTimeout);
                        }

                        binRequest.IncomingBuffer =
                            new byte[plcResponseMessage.responseBytesMessage.Length -
                                     Utils.Lengths.LENGTH_HEADER_AND_FOOTER];

                        if (binRequest.IncomingBuffer.Length > 0)
                        {
                            Array.Copy(plcResponseMessage.responseBytesMessage, Utils.Lengths.LENGTH_HEADER,
                                       binRequest.IncomingBuffer, 0, binRequest.IncomingBuffer.Length);
                        }

                        Array.Copy(binRequest.IncomingBuffer, 0, arrivedData, offsetInBuffer, sizeOfDataToCopy);
                        if (plcResponseMessage.responseBytesMessage[12] == 0xFF)
                        {
                            binRequest.PlcReceiveResult =
                                (BinaryRequest.ePlcReceiveResult)plcResponseMessage.responseBytesMessage[13];
                        }
                        else if (plcResponseMessage.responseBytesMessage[12] == binRequest.CommandCode + 0x80)
                        {
                            binRequest.PlcReceiveResult = BinaryRequest.ePlcReceiveResult.Sucsess;
                        }
                        else
                        {
                            binRequest.PlcReceiveResult = BinaryRequest.ePlcReceiveResult.Unknown;
                        }

                        offsetInBuffer += sizeOfDataToCopy;
                        currentAddress += sizeOfDataToCopy;
                        messageKey++;     // Message Key is % 256. The BuildBinaryCommand takes care of that
                        binRequest.MessageKey = messageKey;
                        binRequest.MessageKey = binRequest.MessageKey % 256;

                        if (binRequest.MessageKey == 0)
                        {
                            messageKey            = binRequest.CycledMessageKey;
                            binRequest.MessageKey = messageKey;
                        }

                        if (binRequest.WaitForIdle)
                        {
                            WaitForFlashIdle((byte)UnitId, parentID);
                        }

                        binRequest.RaiseProgressEvent(0, binRequest.ElementsCount,
                                                      RequestProgress.en_NotificationType.ProgressChanged, offsetInBuffer, "");
                    }

                    binRequest.IncomingBuffer = arrivedData;
                    binRequest.RaiseProgressEvent(0, binRequest.ElementsCount,
                                                  RequestProgress.en_NotificationType.Completed, binRequest.ElementsCount, "");
                }
                else
                {
                    if (this.BreakFlag)
                    {
                        throw new ComDriveExceptions("Request aborted by user",
                                                     ComDriveExceptions.ComDriveException.AbortedByUser);
                    }

                    if (binRequest.WaitForIdle)
                    {
                        WaitForFlashIdle((byte)UnitId, parentID);
                    }

                    binRequest.RaiseProgressEvent(0, outgoingBufferSize,
                                                  RequestProgress.en_NotificationType.SetMinMax, 0, "");
                    binRequest.RaiseProgressEvent(0, outgoingBufferSize,
                                                  RequestProgress.en_NotificationType.ProgressChanged, 0, "");

                    //if (binRequest.SubCommand == (int)MemoryType.InternalFlash && binRequest.CommandCode == 0x41)
                    //{
                    //    if ((binRequest.OutgoingBuffer.Length % 8) != 0)
                    //    {
                    //        byte[] binDataToBurn = new byte[binRequest.OutgoingBuffer.Length + 8 - binRequest.OutgoingBuffer.Length % 8];
                    //        for (int i = binRequest.OutgoingBuffer.Length; i < binDataToBurn.Length; i++)
                    //        {
                    //            binDataToBurn[i] = 0xFF;
                    //        }

                    //        Array.Copy(binRequest.OutgoingBuffer, 0, binDataToBurn, 0, binRequest.OutgoingBuffer.Length);
                    //        binRequest.OutgoingBuffer = binDataToBurn;
                    //        outgoingBufferSize = binRequest.OutgoingBuffer.Length;
                    //    }
                    //}

                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    long lastTime = 0;
                    while (offsetInBuffer < outgoingBufferSize)
                    {
                        if (this.BreakFlag)
                        {
                            throw new ComDriveExceptions("Request aborted by user",
                                                         ComDriveExceptions.ComDriveException.AbortedByUser);
                        }

                        chunkSize = outgoingBufferSize - offsetInBuffer;
                        if (chunkSize > PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_HEADER_AND_FOOTER)
                        {
                            chunkSize = PLCVersion.PlcBuffer - Utils.Lengths.LENGTH_HEADER_AND_FOOTER;
                        }

                        if (binRequest.ChunkSizeAlignment != 0)
                        {
                            // Chop the end of the chunk to fit into aligment
                            chunkSize -= (chunkSize % binRequest.ChunkSizeAlignment);
                        }

                        if (binRequest.FlashBankSize != 0)
                        {
                            // Chop the end of the chunk so the burned data will not be written on 2 different flash banks
                            if (((currentAddress + chunkSize) / binRequest.FlashBankSize) !=
                                (currentAddress / binRequest.FlashBankSize))
                            {
                                chunkSize -= ((currentAddress + chunkSize) % binRequest.FlashBankSize);
                            }
                        }

                        //if (binRequest.SubCommand == (int)MemoryType.InternalFlash && binRequest.CommandCode == 0x41)
                        //{
                        //    if ((chunkSize % 8) != 0)
                        //        chunkSize -= chunkSize % 8;
                        //}

                        outgoingChunk = new byte[chunkSize];
                        Array.Copy(binRequest.OutgoingBuffer, offsetInBuffer, outgoingChunk, 0, chunkSize);

                        // Programming command (0x41)
                        // We want to put it on PLC even if the chunk is full with 0xff (Because it is not a flash memory)
                        if ((binRequest.CommandCode == 0x41 && binRequest.SubCommand == (int)MemoryType.SRAM) ||
                            IsValidChunkBufferData(outgoingChunk, binRequest.DecodeValue))
                        {
                            if (sw.ElapsedMilliseconds - lastTime < MIN_TIME_BETWEEN_CHUNKS_WRITE)
                            {
                                Thread.Sleep((int)(MIN_TIME_BETWEEN_CHUNKS_WRITE -
                                                   (sw.ElapsedMilliseconds - lastTime)));
                            }

                            pComB.BuildBinaryCommand((byte)UnitId, messageKey, binRequest.CommandCode,
                                                     binRequest.SubCommand, currentAddress, chunkSize, (ushort)chunkSize,
                                                     outgoingChunk);

                            lastTime = sw.ElapsedMilliseconds;
                            messageKey++;     // Message Key is % 256. The BuildBinaryCommand takes care of that
                            binRequest.MessageKey = messageKey;
                            binRequest.MessageKey = binRequest.MessageKey % 256;

                            if (binRequest.MessageKey == 0)
                            {
                                messageKey            = binRequest.CycledMessageKey;
                                binRequest.MessageKey = messageKey;
                            }

                            guid = new GuidClass();

                            lock (guid)
                            {
                                Channel.Send(pComB.MessageToPLC as byte[], ReceiveBytes, guid, parentID,
                                             "Binary Protocol - Binary Request (" + binRequest.CommandCode.ToString() + ")",
                                             PlcGuid);
                                Monitor.Wait(guid);
                            }

                            if (this.BreakFlag)
                            {
                                throw new ComDriveExceptions("Request aborted by user",
                                                             ComDriveExceptions.ComDriveException.AbortedByUser);
                            }

                            lock (_lockObj)
                            {
                                plcResponseMessage = m_responseMessageQueue[guid];
                                m_responseMessageQueue.Remove(guid);
                            }

                            if (plcResponseMessage.comException == CommunicationException.Timeout)
                            {
                                throw new ComDriveExceptions(
                                          "Cannot communicate with the PLC with the specified UnitID!",
                                          ComDriveExceptions.ComDriveException.CommunicationTimeout);
                            }

                            binRequest.IncomingBuffer =
                                new byte[plcResponseMessage.responseBytesMessage.Length -
                                         Utils.Lengths.LENGTH_HEADER_AND_FOOTER];
                            if (binRequest.IncomingBuffer.Length > 0)
                            {
                                Array.Copy(plcResponseMessage.responseBytesMessage, Utils.Lengths.LENGTH_HEADER,
                                           binRequest.IncomingBuffer, 0, binRequest.IncomingBuffer.Length);
                            }

                            if (plcResponseMessage.responseBytesMessage[12] == 0xFF)
                            {
                                binRequest.PlcReceiveResult =
                                    (BinaryRequest.ePlcReceiveResult)plcResponseMessage.responseBytesMessage[13];
                            }
                            else if (plcResponseMessage.responseBytesMessage[12] == binRequest.CommandCode + 0x80)
                            {
                                binRequest.PlcReceiveResult = BinaryRequest.ePlcReceiveResult.Sucsess;
                            }
                            else
                            {
                                binRequest.PlcReceiveResult = BinaryRequest.ePlcReceiveResult.Unknown;
                            }

                            if (binRequest.PlcReceiveResult != BinaryRequest.ePlcReceiveResult.Sucsess)
                            {
                                return;
                            }

                            if (binRequest.WaitForIdle)
                            {
                                WaitForFlashIdle((byte)UnitId, parentID);
                            }
                            else
                            {
                                if (binRequest.CommandCode == 0x41)
                                {
                                    Thread.Sleep(25);
                                }
                            }
                        }
                        else
                        {
                            Debug.Print("Not Valid");
                        }

                        offsetInBuffer += chunkSize;
                        currentAddress += chunkSize;

                        binRequest.RaiseProgressEvent(0, outgoingBufferSize,
                                                      RequestProgress.en_NotificationType.ProgressChanged, offsetInBuffer, "");
                    }

                    binRequest.RaiseProgressEvent(0, outgoingBufferSize,
                                                  RequestProgress.en_NotificationType.Completed, outgoingBufferSize, "");
                }

                break;

            default:

                binRequest.RaiseProgressEvent(0, 100, RequestProgress.en_NotificationType.SetMinMax, 0, "");
                binRequest.RaiseProgressEvent(0, 100, RequestProgress.en_NotificationType.ProgressChanged, 0, "");

                pComB.BuildBinaryCommand((byte)UnitId, messageKey, binRequest.CommandCode,
                                         binRequest.SubCommand, currentAddress, binRequest.ElementsCount, (ushort)outgoingBufferSize,
                                         binRequest.OutgoingBuffer);

                if (this.BreakFlag)
                {
                    throw new ComDriveExceptions("Request aborted by user",
                                                 ComDriveExceptions.ComDriveException.AbortedByUser);
                }

                if (binRequest.WaitForIdle)
                {
                    WaitForFlashIdle((byte)UnitId, parentID);
                }

                guid = new GuidClass();

                lock (guid)
                {
                    Channel.Send(pComB.MessageToPLC as byte[], ReceiveBytes, guid, parentID,
                                 "Binary Protocol - Binary Request (" + binRequest.CommandCode.ToString() + ")", PlcGuid);
                    Monitor.Wait(guid);
                }

                if (this.BreakFlag)
                {
                    throw new ComDriveExceptions("Request aborted by user",
                                                 ComDriveExceptions.ComDriveException.AbortedByUser);
                }

                lock (_lockObj)
                {
                    plcResponseMessage = m_responseMessageQueue[guid];
                    m_responseMessageQueue.Remove(guid);
                }

                if (plcResponseMessage.comException == CommunicationException.Timeout)
                {
                    throw new ComDriveExceptions("Cannot communicate with the PLC with the specified UnitID!",
                                                 ComDriveExceptions.ComDriveException.CommunicationTimeout);
                }

                binRequest.IncomingBuffer = new byte[plcResponseMessage.responseBytesMessage.Length -
                                                     Utils.Lengths.LENGTH_HEADER_AND_FOOTER];
                if (binRequest.IncomingBuffer.Length > 0)
                {
                    Array.Copy(plcResponseMessage.responseBytesMessage, Utils.Lengths.LENGTH_HEADER,
                               binRequest.IncomingBuffer, 0, binRequest.IncomingBuffer.Length);
                }

                if (plcResponseMessage.responseBytesMessage[12] == 0xFF)
                {
                    binRequest.PlcReceiveResult =
                        (BinaryRequest.ePlcReceiveResult)plcResponseMessage.responseBytesMessage[13];
                }
                else if (plcResponseMessage.responseBytesMessage[12] == binRequest.CommandCode + 0x80)
                {
                    binRequest.PlcReceiveResult = BinaryRequest.ePlcReceiveResult.Sucsess;
                }
                else
                {
                    binRequest.PlcReceiveResult = BinaryRequest.ePlcReceiveResult.Unknown;
                }

                if (binRequest.WaitForIdle)
                {
                    WaitForFlashIdle((byte)UnitId, parentID);
                }

                binRequest.RaiseProgressEvent(0, 100, RequestProgress.en_NotificationType.Completed, 100, "");

                break;
            }
        }
示例#20
0
        /// <summary>
        /// Handles a write operation.
        /// </summary>
        protected override void Write(
            ServerSystemContext context,
            IList <WriteValue> nodesToWrite,
            IList <ServiceResult> errors,
            List <NodeHandle> nodesToValidate,
            IDictionary <NodeId, NodeState> cache)
        {
            List <ReadWriteRequest> requests = new List <ReadWriteRequest>();

            // validates the nodes and constructs requests for external nodes.
            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                WriteValue nodeToWrite = nodesToWrite[ii];
                NodeHandle handle      = nodesToValidate[ii];

                lock (Lock)
                {
                    // validate node.
                    NodeState source = ValidateNode(context, handle, cache);

                    if (source == null)
                    {
                        continue;
                    }

                    // determine if an external source is required.
                    if (IsExternalSource(handle, nodeToWrite.AttributeId))
                    {
                        errors[handle.Index] = AddWriteRequest(context, handle, nodeToWrite, requests);
                        continue;
                    }

                    // write the attribute value.
                    errors[handle.Index] = source.WriteAttribute(
                        context,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    source.ClearChangeMasks(context, false);
                }
            }

            // send request to external system.
            try
            {
                ProcessWriteRequests(requests);
            }
            catch (Exception e)
            {
                // handle unexpected communication error.
                ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system.");

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    requests[ii].Result = error;
                }
            }

            // set results.
            for (int ii = 0; ii < requests.Count; ii++)
            {
                ReadWriteRequest request = requests[ii];
                errors[request.Handle.Index] = request.Result;
            }
        }
        internal void ReadWrite(ref ReadWriteRequest[] values, bool suppressEthernetHeader)
        {
            lock (objectLocker)
            {
                m_BreakFlagCount++;
            }

            System.Diagnostics.Debug.Print("Entering Read Write. Count: " + m_BreakFlagCount.ToString());
            Guid parentID = Guid.NewGuid();

            List <ReadWriteRequest> requestsList = new List <ReadWriteRequest>();

            try
            {
                ComDriverLogger.LogReadWriteRequest(DateTime.Now, m_channel.GetLoggerChannelText(), values,
                                                    MessageDirection.Sent, parentID.ToString());

                CheckReadWriteRequests(values);

                for (int i = 0; i < values.Length; i++)
                {
                    ReadWriteRequest rw = values[i];

                    if ((rw is ReadOperands) || (rw is WriteOperands))
                    {
                        requestsList.Add(rw);

                        if (i == values.Length - 1)
                        {
                            if (requestsList.Count > 0)
                            {
                                ReadWriteRequest[] requestsArray = requestsList.ToArray();
                                if (OperandsExecuter != null)
                                {
                                    OperandsExecuter.PerformReadWrite(ref requestsArray, parentID.ToString(),
                                                                      suppressEthernetHeader);
                                }
                                else
                                {
                                    throw new ComDriveExceptions(
                                              "The PLC or the state the PLC is in does not support Read/Write Operands",
                                              ComDriveExceptions.ComDriveException.UnsupportedCommand);
                                }

                                requestsList.Clear();
                            }
                        }
                    }

                    else if ((rw is ReadDataTables) || (rw is WriteDataTables))
                    {
                        ReadWriteRequest[] requestsArray;

                        if (requestsList.Count > 0)
                        {
                            requestsArray = requestsList.ToArray();
                            if (OperandsExecuter != null)
                            {
                                OperandsExecuter.PerformReadWrite(ref requestsArray, parentID.ToString(),
                                                                  suppressEthernetHeader);
                            }
                            else
                            {
                                throw new ComDriveExceptions(
                                          "The PLC or the state the PLC is in does not support Read/Write Operands",
                                          ComDriveExceptions.ComDriveException.UnsupportedCommand);
                            }

                            requestsList.Clear();
                        }

                        requestsArray = new ReadWriteRequest[] { rw };

                        if (DataTablesExecuter != null)
                        {
                            DataTablesExecuter.PerformReadWrite(ref requestsArray, parentID.ToString(),
                                                                suppressEthernetHeader);
                        }
                        else
                        {
                            throw new ComDriveExceptions(
                                      "The PLC or the state the PLC is in does not support Read/Write Data Tables",
                                      ComDriveExceptions.ComDriveException.UnsupportedCommand);
                        }
                    }

                    else if (rw is BinaryRequest)
                    {
                        ReadWriteRequest[] requestsArray;
                        if (requestsList.Count > 0)
                        {
                            requestsArray = requestsList.ToArray();
                            if (OperandsExecuter != null)
                            {
                                OperandsExecuter.PerformReadWrite(ref requestsArray, parentID.ToString(),
                                                                  suppressEthernetHeader);
                            }
                            else
                            {
                                throw new ComDriveExceptions(
                                          "The PLC or the state the PLC is in does not support Read/Write Operands",
                                          ComDriveExceptions.ComDriveException.UnsupportedCommand);
                            }

                            requestsList.Clear();
                        }

                        requestsArray = new ReadWriteRequest[] { rw };

                        BinaryRequest br = rw as BinaryRequest;

                        switch (br.CommandCode)
                        {
                        case 0x1:    //Read Ram/Flash
                        case 0x41:   //Write Ram/Flash
                        case 62:     //Set Password
                        case 0x2:    //verify password
                        case 0x9:    //Download Start
                        case 0x45:   //Download End
                        case 0xA:    //Erase Flash
                        case 0x7:    //Wait for flash idle
                        case 0xB:    //Blind mode
                        case 0x13:   //UnBlind mode
                        case 0xF:    //Put PLC in state (Preebot, boot, OS Stop, OS Run)
                        case 0xC:    //Get PLC Name

                            if (BasicBinaryExecuter != null)
                            {
                                BasicBinaryExecuter.PerformReadWrite(ref requestsArray, parentID.ToString(),
                                                                     suppressEthernetHeader);
                            }
                            else
                            {
                                throw new ComDriveExceptions(
                                          "The PLC or the state the PLC is in does not support Basic Binary commands",
                                          ComDriveExceptions.ComDriveException.UnsupportedCommand);
                            }

                            break;

                        default:

                            if (BinaryExecuter != null)
                            {
                                BinaryExecuter.PerformReadWrite(ref requestsArray, parentID.ToString(),
                                                                suppressEthernetHeader);
                            }
                            else
                            {
                                throw new ComDriveExceptions(
                                          "The PLC or the state the PLC is in does not support Binary Commands",
                                          ComDriveExceptions.ComDriveException.UnsupportedCommand);
                            }

                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ComDriveExceptions comDriveException = ex as ComDriveExceptions;
                if (comDriveException != null)
                {
                    if ((comDriveException.ErrorCode == ComDriveExceptions.ComDriveException.AbortedByUser) ||
                        m_BreakFlag)
                    {
                        throw;
                    }
                    else if (m_BreakFlag)
                    {
                        throw new ComDriveExceptions("Request aborted by user",
                                                     ComDriveExceptions.ComDriveException.AbortedByUser);
                    }
                    else
                    {
                        throw;
                    }
                }
                else if (m_BreakFlag)
                {
                    throw new ComDriveExceptions("Request aborted by user",
                                                 ComDriveExceptions.ComDriveException.AbortedByUser);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                lock (objectLocker)
                {
                    m_BreakFlagCount--;
                }

                System.Diagnostics.Debug.Print("Exiting Read Write. Count: " + m_BreakFlagCount.ToString());
                ComDriverLogger.LogReadWriteRequest(DateTime.Now, m_channel.GetLoggerChannelText(), values,
                                                    MessageDirection.Received, parentID.ToString());
            }
        }
示例#22
0
        /// <summary>
        /// Handles a read operations that fetch data from an external source.
        /// </summary>
        protected override void Read(
            ServerSystemContext context,
            IList <ReadValueId> nodesToRead,
            IList <DataValue> values,
            IList <ServiceResult> errors,
            List <NodeHandle> nodesToValidate,
            IDictionary <NodeId, NodeState> cache)
        {
            List <ReadWriteRequest> requests = new List <ReadWriteRequest>();

            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                NodeHandle  handle     = nodesToValidate[ii];
                ReadValueId nodeToRead = nodesToRead[ii];
                DataValue   value      = values[ii];

                lock (Lock)
                {
                    // validate node.
                    NodeState source = ValidateNode(context, handle, cache);

                    if (source == null)
                    {
                        continue;
                    }

                    // determine if an external source is required.
                    if (IsExternalSource(handle, nodeToRead.AttributeId))
                    {
                        errors[handle.Index] = AddReadRequest(context, handle, nodeToRead, requests);
                        continue;
                    }

                    // read built-in metadata.
                    errors[handle.Index] = source.ReadAttribute(
                        context,
                        nodeToRead.AttributeId,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        value);
                }
            }

            // send request to external system.
            try
            {
                ProcessReadRequests(requests);
            }
            catch (Exception e)
            {
                // handle unexpected communication error.
                ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system.");

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    requests[ii].Result = error;
                }
            }

            // set results.
            for (int ii = 0; ii < requests.Count; ii++)
            {
                ReadWriteRequest request = requests[ii];

                if (ServiceResult.IsBad(request.Result))
                {
                    errors[request.Handle.Index] = request.Result;
                    continue;
                }

                values[request.Handle.Index] = new DataValue(request.Value);
            }
        }
示例#23
0
 public void AddDataRequest(ReadWriteRequest dataRequest)
 {
     m_dataRequests.Add(dataRequest);
 }
示例#24
0
        private void _getRequestBytesSize(ReadWriteRequest readWriteRequest)
        {
            ushort noOfOperands;
            int    noOf255Splits, noOfSplits;

            if (readWriteRequest is WriteOperands)
            {
                WriteOperands wo = readWriteRequest as WriteOperands;
                noOfOperands = wo.NumberOfOperands;
                operandSize  = wo.OperandType.GetOperandSizeByOperandTypeForFullBinarry();

                noOf255Splits = noOfOperands / 255;
                noOfSplits    = noOfOperands % 255;

                if (noOfOperands > 255)
                {
                    requestBytesNoToSend =
                        (ushort)(noOf255Splits * Utils.Lengths.LENGTH_WR_DETAILS + noOf255Splits * 255 * operandSize);
                    requestBytesNoToSend += (ushort)((operandSize % 2) * (noOf255Splits + noOfSplits % 2));

                    if (noOfSplits > 0)
                    {
                        requestBytesNoToSend += (ushort)(Utils.Lengths.LENGTH_WR_DETAILS + noOfSplits * operandSize);
                    }
                }
                else
                {
                    requestBytesNoToSend  = (ushort)(operandSize * noOfOperands + Utils.Lengths.LENGTH_WR_DETAILS);
                    requestBytesNoToSend += (ushort)(requestBytesNoToSend % 2);
                }

                requestBytesNoToReceive = 0;
            }
            else
            {
                ReadOperands ro = readWriteRequest as ReadOperands;
                noOfOperands = ro.NumberOfOperands;
                operandSize  = ro.OperandType.GetOperandSizeByOperandTypeForFullBinarry();

                if (noOfOperands > 255)
                {
                    noOf255Splits = (noOfOperands / 255);
                    noOfSplits    = (noOfOperands % 255);

                    requestBytesNoToSend    = (ushort)(noOf255Splits * Utils.Lengths.LENGTH_WR_DETAILS);
                    requestBytesNoToReceive =
                        (ushort)(noOf255Splits * Utils.Lengths.LENGTH_WR_DETAILS + noOf255Splits * 255 * operandSize);
                    requestBytesNoToReceive += (ushort)((operandSize % 2) * (noOf255Splits + noOfSplits % 2));

                    if (noOfSplits != 0)
                    {
                        requestBytesNoToSend    += Utils.Lengths.LENGTH_WR_DETAILS;
                        requestBytesNoToReceive +=
                            (ushort)(Utils.Lengths.LENGTH_WR_DETAILS + noOfSplits * operandSize);
                    }
                }
                else
                {
                    requestBytesNoToReceive  = (ushort)(operandSize * noOfOperands + Utils.Lengths.LENGTH_WR_DETAILS);
                    requestBytesNoToReceive += (ushort)(requestBytesNoToReceive % 2);
                    requestBytesNoToSend     = Utils.Lengths.LENGTH_WR_DETAILS;
                }
            }
        }
示例#25
0
        private void _sendSizeExceedPLCBuffer(ReadWriteRequest readWriteRequest)
        {
            WriteOperands wo = readWriteRequest as WriteOperands;
            ushort        availableSendSize     = (ushort)(plcBuffer - bytesNoToSend - Utils.Lengths.LENGTH_WR_DETAILS);
            ushort        availableNoOfOperands = (ushort)(availableSendSize / operandSize);

            if (availableNoOfOperands > 255)
            {
                availableSendSize    -= (ushort)((availableNoOfOperands / 255) * (Utils.Lengths.LENGTH_WR_DETAILS + 1));
                availableSendSize    -= 1;
                availableSendSize    -= (ushort)((availableNoOfOperands % 255) % 2);
                availableNoOfOperands = (ushort)(availableSendSize / operandSize);
            }

            ushort noOfOperands = 0;
            ushort startAddress = wo.StartAddress;
            int    requestNo    = 0;

            WriteOperands remainingWo = new WriteOperands
            {
                NumberOfOperands = (ushort)(wo.NumberOfOperands - availableNoOfOperands),
                OperandType      = wo.OperandType,
                StartAddress     = (ushort)(wo.StartAddress + availableNoOfOperands),
                TimerValueFormat = wo.TimerValueFormat
            };

            object[] remainingValues = new object[remainingWo.NumberOfOperands];
            Array.Copy(wo.Values, availableNoOfOperands, remainingValues, 0, remainingWo.NumberOfOperands);
            remainingWo.Values = remainingValues;

            if (_canWriteAtLeast1Operand())
            {
                object[] values = null;

                while (availableNoOfOperands > 0)
                {
                    requestNo++;

                    if (availableNoOfOperands > 255)
                    {
                        noOfOperands           = 255;
                        availableNoOfOperands -= noOfOperands;
                        values = new object[noOfOperands];
                    }
                    else
                    {
                        noOfOperands          = availableNoOfOperands;
                        availableNoOfOperands = 0;
                        values = new object[noOfOperands];
                    }

                    Array.Copy(wo.Values, (requestNo - 1) * 255, values, 0, noOfOperands);
                    WriteOperands tmpWO = new WriteOperands(noOfOperands, wo.OperandType, startAddress, values,
                                                            wo.TimerValueFormat);
                    requestsList.Add(tmpWO);
                    startAddress += noOfOperands;
                    _updateSplitDetailsList();
                }

                ReadWriteRequest[] tmpReq = requestsList.ToArray();
                allRequestsList.Add(tmpReq.ToList());

                _resetRequestsList();
                AddNewRequest(remainingWo, reqPosition, true);
            }
        }