public void Send(NodeBase[] Data, CommAddress Address, ActionRequested Action) { WriteQueueElement el = new WriteQueueElement(Data, Address, Action); SendQueue.Enqueue(el); sendQueueWritten.Set(); }
private void WorkerThreadProc(object obj) { Scsm_MMS_Worker self = (Scsm_MMS_Worker)obj; iecs = new Iec61850State(); iecs.hostname = self.isoParameters.hostname; // due to tcps inheritance iecs.port = self.isoParameters.port; // due to tcps inheritance iecs.cp = self.isoParameters; iecs.logger = Logger.getLogger(); _env.winMgr.BindToCapture(iecs); _waitHandles[0] = iecs.connectDone; _waitHandles[1] = iecs.receiveDone; _waitHandles[2] = iecs.sendDone; _waitHandles[3] = new ManualResetEvent(false); // end thread _waitHandles[4] = iecs.sendQueueWritten; //DateTime tout = null; CommAddress ad = new CommAddress(); DateTime IdentifyTimeoutBase = new DateTime(); TimeSpan IdentifyTimeout = new TimeSpan(0, 0, 5); // 5 sec while (self._run) { switch (iecs.tstate) { case TcpProtocolState.TCP_STATE_START: iecs.logger.LogInfo("[TCP_STATE_START]"); iecs.kstate = IsoTpktState.TPKT_RECEIVE_START; iecs.ostate = IsoProtocolState.OSI_STATE_START; iecs.istate = Iec61850lStateEnum.IEC61850_STATE_START; TcpRw.StartClient(iecs); break; case TcpProtocolState.TCP_STATE_SHUTDOWN: iecs.logger.LogInfo("[TCP_STATE_SHUTDOWN]"); Stop(); Thread.Sleep(10000); iecs.tstate = TcpProtocolState.TCP_STATE_START; break; case TcpProtocolState.TCP_CONNECTED: switch (iecs.ostate) { case IsoProtocolState.OSI_CONNECT_COTP: iecs.logger.LogInfo("[OSI_CONNECT_COTP]"); iecs.ostate = IsoProtocolState.OSI_CONNECT_COTP_WAIT; iecs.iso.SendCOTPSessionInit(iecs); break; case IsoProtocolState.OSI_CONNECT_PRES: iecs.logger.LogInfo("[OSI_CONNECT_PRES]"); // This cannot be before Send, but is issued inside Send chain before TCP send // iecs.ostate = IsoProtocolState.OSI_CONNECT_PRES_WAIT; iecs.mms.SendInitiate(iecs); break; case IsoProtocolState.OSI_CONNECTED: switch (iecs.istate) { case Iec61850lStateEnum.IEC61850_STATE_START: if (iecs.DataModel.ied.Identify) { iecs.logger.LogInfo("[IEC61850_STATE_START] (Send IdentifyRequest)"); iecs.istate = Iec61850lStateEnum.IEC61850_CONNECT_MMS_WAIT; iecs.mms.SendIdentify(iecs); IdentifyTimeoutBase = DateTime.UtcNow; } else { iecs.istate = Iec61850lStateEnum.IEC61850_READ_NAMELIST_DOMAIN; } break; case Iec61850lStateEnum.IEC61850_CONNECT_MMS_WAIT: // If we wait for Identify response too long, continue without it if (DateTime.UtcNow.Subtract(IdentifyTimeout).CompareTo(IdentifyTimeoutBase) > 0) { // Timeout expired iecs.istate = Iec61850lStateEnum.IEC61850_READ_NAMELIST_DOMAIN; iecs.logger.LogWarning("MMS Identify message not supported by server, although declared in ServicesSupportedCalled bitstring"); } break; case Iec61850lStateEnum.IEC61850_READ_NAMELIST_DOMAIN: iecs.logger.LogDebug("[IEC61850_READ_NAMELIST_DOMAIN]"); iecs.istate = Iec61850lStateEnum.IEC61850_READ_NAMELIST_DOMAIN_WAIT; iecs.mms.SendGetNameListDomain(iecs); break; case Iec61850lStateEnum.IEC61850_READ_NAMELIST_VAR: iecs.logger.LogDebug("[IEC61850_READ_NAMELIST_VAR]"); iecs.istate = Iec61850lStateEnum.IEC61850_READ_NAMELIST_VAR_WAIT; iecs.mms.SendGetNameListVariables(iecs); break; case Iec61850lStateEnum.IEC61850_READ_ACCESSAT_VAR: iecs.logger.LogDebug("[IEC61850_READ_ACCESSAT_VAR]"); iecs.istate = Iec61850lStateEnum.IEC61850_READ_ACCESSAT_VAR_WAIT; iecs.mms.SendGetVariableAccessAttributes(iecs); break; case Iec61850lStateEnum.IEC61850_READ_MODEL_DATA: if (_env.dataReadOnStartup) { iecs.logger.LogDebug("[IEC61850_READ_MODEL_DATA]"); CommAddress adr = new CommAddress(); adr.Domain = null; adr.Variable = null; adr.owner = null; NodeBase[] data = new NodeBase[1]; // Issue reads by FC level data[0] = iecs.DataModel.ied.GetActualChildNode().GetActualChildNode().GetActualChildNode(); WriteQueueElement wqel = new WriteQueueElement(data, adr, ActionRequested.Read); iecs.istate = Iec61850lStateEnum.IEC61850_READ_MODEL_DATA_WAIT; iecs.mms.SendRead(iecs, wqel); } else { iecs.logger.LogDebug("[IEC61850_READ_MODEL_DATA] - Skipped due to a presetting"); iecs.istate = Iec61850lStateEnum.IEC61850_READ_NAMELIST_NAMED_VARIABLE_LIST; } break; case Iec61850lStateEnum.IEC61850_READ_NAMELIST_NAMED_VARIABLE_LIST: iecs.logger.LogDebug("[IEC61850_READ_NAMELIST_NAMED_VARIABLE_LIST]"); iecs.istate = Iec61850lStateEnum.IEC61850_READ_NAMELIST_NAMED_VARIABLE_LIST_WAIT; iecs.mms.SendGetNameListNamedVariableList(iecs); break; case Iec61850lStateEnum.IEC61850_READ_ACCESSAT_NAMED_VARIABLE_LIST: iecs.logger.LogDebug("[IEC61850_READ_ACCESSAT_NAMED_VARIABLE_LIST]"); iecs.istate = Iec61850lStateEnum.IEC61850_READ_ACCESSAT_NAMED_VARIABLE_LIST_WAIT; if (iecs.mms.SendGetNamedVariableListAttributes(iecs) != 0) { // No VarLists iecs.logger.LogInfo("Init end: [IEC61850_FREILAUF]"); iecs.istate = Iec61850lStateEnum.IEC61850_MAKEGUI; } break; case Iec61850lStateEnum.IEC61850_MAKEGUI: iecs.logger.LogDebug("[IEC61850_MAKEGUI]"); iecs.DataModel.BuildIECModelFromMMSModel(); self._env.winMgr.MakeIedTree(iecs); self._env.winMgr.MakeIecTree(iecs); self._env.winMgr.mainWindow.Set_iecf(iecs); iecs.istate = Iec61850lStateEnum.IEC61850_FREILAUF; break; case Iec61850lStateEnum.IEC61850_FREILAUF: // File service handling switch (iecs.fstate) { case FileTransferState.FILE_DIRECTORY: if (iecs.lastFileOperationData[0] is NodeIed) { self._env.winMgr.MakeFileTree(iecs); } iecs.fstate = FileTransferState.FILE_NO_ACTION; break; case FileTransferState.FILE_OPENED: case FileTransferState.FILE_READ: // issue a read iecs.Send(iecs.lastFileOperationData, ad, ActionRequested.ReadFile); iecs.fstate = FileTransferState.FILE_NO_ACTION; break; case FileTransferState.FILE_COMPLETE: // issue a close // file can be saved from context menu iecs.Send(iecs.lastFileOperationData, ad, ActionRequested.CloseFile); iecs.fstate = FileTransferState.FILE_NO_ACTION; break; } break; } break; case IsoProtocolState.OSI_STATE_SHUTDOWN: TcpRw.StopClient(iecs); break; } break; default: break; } int waitres = WaitHandle.WaitAny(_waitHandles, 500); switch (waitres) { case 0: // connect if (iecs.ostate == IsoProtocolState.OSI_STATE_START) { iecs.ostate = IsoProtocolState.OSI_CONNECT_COTP; } iecs.connectDone.Reset(); TcpRw.Receive(iecs); // issue a Receive call break; case 1: // receive iecs.receiveDone.Reset(); TcpRw.Receive(iecs); // issue a new Receive call break; case 2: // send iecs.sendDone.Reset(); break; case 3: // endthread self._run = false; break; case 4: // send data iecs.sendQueueWritten.Reset(); Logger.getLogger().LogDebug("SendQueue Waiting for lock in Worker!"); WriteQueueElement el; while (iecs.SendQueue.TryDequeue(out el)) { switch (el.Action) { case ActionRequested.Write: iecs.mms.SendWrite(iecs, el); break; case ActionRequested.WriteAsStructure: iecs.mms.SendWriteAsStructure(iecs, el); break; case ActionRequested.Read: if (el.Data[0] is NodeVL) { iecs.mms.SendReadVL(iecs, el); } else { iecs.mms.SendRead(iecs, el); } break; case ActionRequested.DefineNVL: iecs.mms.SendDefineNVL(iecs, el); break; case ActionRequested.DeleteNVL: iecs.mms.SendDeleteNVL(iecs, el); break; case ActionRequested.GetDirectory: iecs.mms.SendFileDirectory(iecs, el); break; case ActionRequested.OpenFile: iecs.mms.SendFileOpen(iecs, el); break; case ActionRequested.ReadFile: iecs.mms.SendFileRead(iecs, el); break; case ActionRequested.CloseFile: iecs.mms.SendFileClose(iecs, el); break; case ActionRequested.FileDelete: iecs.mms.SendFileDelete(iecs, el); break; } } break; case WaitHandle.WaitTimeout: break; } } TcpRw.StopClient(iecs); _env.winMgr.UnBindFromCapture(iecs); if (restart_allowed) { restart_allowed = false; try { _env.winMgr.mainWindow.BeginInvoke((Action) delegate { _env.winMgr.mainWindow.Restart(); }); } catch { } } }