public void DeactivateNVL(NodeVL vl) { Iec61850State iecs = vl.GetIecs(); if (iecs != null) { if (vl.urcb != null) { NodeData d = (NodeData)vl.urcb.Parent; List <NodeData> ndar = new List <NodeData>(); NodeBase b; if ((b = d.FindChildNode("RptEna")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = false; ndar.Add(n); } if ((b = d.FindChildNode("GI")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = false; ndar.Add(n); } iecs.Send(ndar.ToArray(), d.CommAddress, ActionRequested.Write); vl.Activated = false; vl.urcb = null; } } else { Logger.getLogger().LogError("Basic structure not found!"); } }
void OnDeleteNVLClick(object sender, EventArgs e) { NodeVL nvl = (NodeVL)(sender as ToolStripItem).Tag; Iec61850State iecs = nvl.GetIecs(); NodeBase[] ndarr = new NodeBase[1]; ndarr[0] = nvl; iecs.Send(ndarr, nvl.CommAddress, ActionRequested.DefineNVL); }
void OnReadDataClick(object sender, EventArgs e) { NodeBase data = (NodeBase)(sender as ToolStripItem).Tag; Iec61850State iecs = data.GetIecs(); NodeBase[] ndarr = new NodeBase[1]; ndarr[0] = data; iecs.Send(ndarr, data.CommAddress, ActionRequested.Read); }
void OnFileGetClick(object sender, EventArgs e) { NodeBase nfi = (NodeBase)(sender as ToolStripItem).Tag; Iec61850State iecs = nfi.GetIecs(); CommAddress ad = new CommAddress(); NodeBase[] ndarr = new NodeBase[1]; ndarr[0] = nfi; iecs.Send(ndarr, ad, ActionRequested.OpenFile); }
void OnDefineNVLClick(object sender, EventArgs e) { NodeVL nvl = (NodeVL)(sender as ToolStripItem).Tag; Iec61850State iecs = nvl.GetIecs(); List <NodeBase> ndar = new List <NodeBase>(); foreach (NodeBase n in nvl.GetChildNodes()) { ndar.Add(n); } iecs.Send(ndar.ToArray(), nvl.CommAddress, ActionRequested.DefineNVL); }
void OnWriteDataClick(object sender, EventArgs e) { NodeData data = (NodeData)(sender as ToolStripItem).Tag; Iec61850State iecs = data.GetIecs(); NodeData[] ndarr = new NodeData[1]; ndarr[0] = new NodeData(data.Name); ndarr[0].DataType = data.DataType; ndarr[0].DataValue = data.DataValue; ndarr[0].DataParam = data.DataParam; EditValue ev = new EditValue(ndarr[0]); DialogResult r = ev.ShowDialog(); if (r == DialogResult.OK) { iecs.Send(ndarr, data.Parent.CommAddress, ActionRequested.Write); Thread.Sleep(300); ndarr = new NodeData[1]; ndarr[0] = data; iecs.Send(ndarr, data.CommAddress, ActionRequested.Read); } }
void OnFileListClick(object sender, EventArgs e) { NodeBase nfi = (NodeBase)(sender as ToolStripItem).Tag; Iec61850State iecs = nfi.GetIecs(); CommAddress ad = new CommAddress(); NodeBase[] ndarr = new NodeBase[1]; ndarr[0] = nfi; if (!(nfi is NodeFile)) { NodeData nd = new NodeData("x"); nd.DataType = scsm_MMS_TypeEnum.visible_string; nd.DataValue = "/"; EditValue ev = new EditValue(nd); DialogResult r = ev.ShowDialog(); if (r == DialogResult.OK) { ad.Variable = nd.StringValue; } } iecs.Send(ndarr, ad, ActionRequested.GetDirectory); }
void OnDeactivateNVLClick(object sender, EventArgs e) { NodeVL vl = (NodeVL)(sender as ToolStripItem).Tag; Iec61850State iecs = vl.GetIecs(); if (iecs != null) { if (vl.urcb != null) { NodeData d = (NodeData)vl.urcb.Parent; List <NodeData> ndar = new List <NodeData>(); NodeBase b; if ((b = d.FindChildNode("RptEna")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = false; ndar.Add(n); } if ((b = d.FindChildNode("GI")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = false; ndar.Add(n); } iecs.Send(ndar.ToArray(), d.CommAddress, ActionRequested.Write); vl.Activated = false; vl.urcb = null; } } else { MessageBox.Show("Basic structure not found!"); } }
public void ActivateNVL(NodeVL vl) { //Logger.getLogger().LogError("Function not active, try to configure an RCB!"); //return; NodeBase ur = null; Iec61850State iecs = vl.GetIecs(); bool retry; if (iecs != null) { do { ur = (NodeData)iecs.DataModel.ied.FindNodeByValue(scsm_MMS_TypeEnum.visible_string, vl.IecAddress, ref ur); if (ur == null || ur.Parent == null) { Logger.getLogger().LogError("Suitable URCB not found, list cannot be activated!"); return; } retry = !ur.Parent.Name.ToLower().Contains("rcb"); vl.urcb = (NodeData)ur; NodeData d = (NodeData)vl.urcb.Parent; NodeData b; if ((b = (NodeData)d.FindChildNode("Resv")) != null) { // Resv is always a boolean // If true then the rcb is occupied and we need to find another one if ((bool)b.DataValue) { retry = true; } } } while (retry); if (vl.urcb != null) { NodeData d = (NodeData)vl.urcb.Parent; List <NodeData> ndar = new List <NodeData>(); NodeBase b; if ((b = d.FindChildNode("Resv")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = true; ndar.Add(n); } if ((b = d.FindChildNode("DatSet")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = ((NodeData)b).DataValue; ndar.Add(n); } if ((b = d.FindChildNode("OptFlds")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = new byte[] { 0x7c, 0x00 }; n.DataParam = 6; ndar.Add(n); } if ((b = d.FindChildNode("TrgOps")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = new byte[] { 0x74 }; n.DataParam = 2; ndar.Add(n); } if ((b = d.FindChildNode("RptEna")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = true; ndar.Add(n); } if ((b = d.FindChildNode("GI")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = true; ndar.Add(n); } iecs.Send(ndar.ToArray(), d.CommAddress, ActionRequested.Write); vl.Activated = true; } } else { Logger.getLogger().LogError("Basic structure not found!"); } }
public void DeleteNVL(NodeVL nvl) { NodeBase[] ndarr = new NodeBase[1]; ndarr[0] = nvl; iecs.Send(ndarr, nvl.CommAddress, ActionRequested.DeleteNVL); }
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 { } } }
void OnActivateNVLClick(object sender, EventArgs e) { NodeVL vl = (NodeVL)(sender as ToolStripItem).Tag; NodeBase ur = null; Iec61850State iecs = vl.GetIecs(); if (iecs != null) { do { ur = (NodeData)iecs.ied.FindNodeByValue(scsm_MMS_TypeEnum.visible_string, vl.Address, ref ur); if (ur == null) { MessageBox.Show("Suitable URCB not found, list cannot be activated!"); return; } } while (!ur.Parent.Name.ToLower().Contains("rcb")); vl.urcb = (NodeData)ur; if (vl.urcb != null) { NodeData d = (NodeData)vl.urcb.Parent; List <NodeData> ndar = new List <NodeData>(); NodeBase b; if ((b = d.FindChildNode("Resv")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = true; ndar.Add(n); } if ((b = d.FindChildNode("DatSet")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = ((NodeData)b).DataValue; ndar.Add(n); } if ((b = d.FindChildNode("OptFlds")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = new byte[] { 0x7c, 0x00 }; n.DataParam = 6; ndar.Add(n); } if ((b = d.FindChildNode("TrgOps")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = new byte[] { 0x74 }; n.DataParam = 2; ndar.Add(n); } if ((b = d.FindChildNode("RptEna")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = true; ndar.Add(n); } if ((b = d.FindChildNode("GI")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = true; ndar.Add(n); } iecs.Send(ndar.ToArray(), d.CommAddress, ActionRequested.Write); vl.Activated = true; } } else { MessageBox.Show("Basic structure not found!"); } }
private void SendCommand(NodeBase data, Iec61850State iecs, ActionRequested how) { if (data != null) { NodeData d = (NodeData)data.Parent; if (d != null) { NodeBase b, c; CommandParams cPar = new CommandParams(); cPar.CommType = CommandType.SingleCommand; if ((b = d.FindChildNode("ctlVal")) != null) { cPar.DataType = ((NodeData)b).DataType; cPar.Address = b.Address; cPar.ctlVal = ((NodeData)b).DataValue; } cPar.T = DateTime.MinValue; cPar.interlockCheck = true; cPar.synchroCheck = true; cPar.orCat = OrCat.STATION_CONTROL; cPar.orIdent = "IEDEXPLORER"; //cPar.orIdent = "ET03: 192.168.001.001 R001 K189 Origin:128"; cPar.CommandFlowFlag = CommandCtrlModel.Unknown; b = data; List <string> path = new List <string>(); do { b = b.Parent; path.Add(b.Name); } while (!(b is NodeFC)); path[0] = "ctlModel"; path[path.Count - 1] = "CF"; b = b.Parent; for (int i = path.Count - 1; i >= 0; i--) { if ((b = b.FindChildNode(path[i])) == null) { break; } } if (b != null) { if (b is NodeData) { cPar.CommandFlowFlag = (CommandCtrlModel)((long)((b as NodeData).DataValue)); } } CommandDialog dlg = new CommandDialog(cPar); DialogResult res = dlg.ShowDialog(this); if (res == DialogResult.Cancel) { return; } List <NodeData> ndar = new List <NodeData>(); //char *nameo[] = {"$Oper$ctlVal", "$Oper$origin$orCat", "$Oper$origin$orIdent", "$Oper$ctlNum", "$Oper$T", "$Oper$Test", "$Oper$Check"}; if ((b = d.FindChildNode("ctlVal")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = cPar.ctlVal; ndar.Add(n); } if ((b = d.FindChildNode("origin")) != null) { if (how == ActionRequested.WriteAsStructure) { NodeData n = new NodeData(b.Name); n.DataType = scsm_MMS_TypeEnum.structure; n.DataValue = 2; ndar.Add(n); if ((c = b.FindChildNode("orCat")) != null) { NodeData n2 = new NodeData(b.Name + "$" + c.Name); n2.DataType = ((NodeData)c).DataType; n2.DataValue = (long)cPar.orCat; n.AddChildNode(n2); } if ((c = b.FindChildNode("orIdent")) != null) { NodeData n2 = new NodeData(b.Name + "$" + c.Name); n2.DataType = ((NodeData)c).DataType; byte[] bytes = new byte[cPar.orIdent.Length]; int tmp1, tmp2; bool tmp3; Encoder ascii = (new ASCIIEncoding()).GetEncoder(); ascii.Convert(cPar.orIdent.ToCharArray(), 0, cPar.orIdent.Length, bytes, 0, cPar.orIdent.Length, true, out tmp1, out tmp2, out tmp3); n2.DataValue = bytes; n.AddChildNode(n2); } } else { if ((c = b.FindChildNode("orCat")) != null) { NodeData n = new NodeData(b.Name + "$" + c.Name); n.DataType = ((NodeData)c).DataType; n.DataValue = (long)cPar.orCat; ndar.Add(n); } if ((c = b.FindChildNode("orIdent")) != null) { NodeData n = new NodeData(b.Name + "$" + c.Name); n.DataType = ((NodeData)c).DataType; byte[] bytes = new byte[cPar.orIdent.Length]; int tmp1, tmp2; bool tmp3; Encoder ascii = (new ASCIIEncoding()).GetEncoder(); ascii.Convert(cPar.orIdent.ToCharArray(), 0, cPar.orIdent.Length, bytes, 0, cPar.orIdent.Length, true, out tmp1, out tmp2, out tmp3); n.DataValue = bytes; ndar.Add(n); } } } if ((b = d.FindChildNode("ctlNum")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = m_ctlNum++; ndar.Add(n); } if ((b = d.FindChildNode("T")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; byte[] btm = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; n.DataValue = btm; if (cPar.T != DateTime.MinValue) { int t = (int)Scsm_MMS.ConvertToUnixTimestamp(cPar.T); byte[] uib = BitConverter.GetBytes(t); btm[0] = uib[3]; btm[1] = uib[2]; btm[2] = uib[1]; btm[3] = uib[0]; } ndar.Add(n); } if ((b = d.FindChildNode("Test")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = false; ndar.Add(n); } if ((b = d.FindChildNode("Check")) != null) { NodeData n = new NodeData(b.Name); n.DataType = ((NodeData)b).DataType; n.DataValue = new byte[] { 0x40 }; n.DataParam = ((NodeData)b).DataParam; ndar.Add(n); } iecs.Send(ndar.ToArray(), d.CommAddress, how); } else { MessageBox.Show("Basic structure not found!"); } } }