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(); } } }
internal void AddNewRequest(ReadWriteRequest readWriteRequest, int reqPosition, bool splitFlag) { this.reqPosition = reqPosition; _getRequestBytesSize(readWriteRequest); if (_requestsSizeFitsPLCBuffer()) { _addToRequests(readWriteRequest, splitFlag); } else { _sizeExceedPLCBuffer(readWriteRequest, splitFlag); } }
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); }
/// <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); }
/// <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); }
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); }
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); } }
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); }
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); }
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; } }
/// <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()); } }
/// <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); } }
public void AddDataRequest(ReadWriteRequest dataRequest) { m_dataRequests.Add(dataRequest); }
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; } } }
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); } }