FormBrowseServer.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  1. using Newtonsoft.Json.Linq;
  2. using Opc.Ua;
  3. using Opc.Ua.Client;
  4. using Opc.Ua.Export;
  5. using Org.BouncyCastle.Asn1.Ocsp;
  6. using Org.BouncyCastle.Asn1.X509;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.ComponentModel;
  10. using System.Data;
  11. using System.Drawing;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Threading.Tasks;
  15. using System.Windows.Forms;
  16. using static System.Windows.Forms.VisualStyles.VisualStyleElement;
  17. namespace OpcUaHelper.Forms
  18. {
  19. /// <summary>
  20. /// 一个浏览OPC服务器节点的窗口类
  21. /// </summary>
  22. public partial class FormBrowseServer : Form
  23. {
  24. #region Constructor
  25. /// <summary>
  26. /// 允许自己输入服务器地址的实例化
  27. /// </summary>
  28. public FormBrowseServer()
  29. {
  30. InitializeComponent();
  31. Icon = ClientUtils.GetAppIcon();
  32. m_typeImageMapping = new Dictionary<NodeId, string>( );
  33. }
  34. /// <summary>
  35. /// 固定地址且不允许更改的实例化
  36. /// </summary>
  37. public FormBrowseServer(string server)
  38. {
  39. InitializeComponent();
  40. Icon = ClientUtils.GetAppIcon();
  41. textBox1.Text = server;
  42. }
  43. #endregion
  44. #region Load Show Close
  45. private void FormBrowseServer_Load(object sender, EventArgs e)
  46. {
  47. BrowseNodesTV.Enabled = false;
  48. BrowseNodesTV.ImageList = new ImageList();
  49. BrowseNodesTV.ImageList.Images.Add("Class_489", Properties.Resources.Class_489);
  50. BrowseNodesTV.ImageList.Images.Add("ClassIcon", Properties.Resources.ClassIcon);
  51. BrowseNodesTV.ImageList.Images.Add("brackets", Properties.Resources.brackets_Square_16xMD);
  52. BrowseNodesTV.ImageList.Images.Add("VirtualMachine", Properties.Resources.VirtualMachine);
  53. BrowseNodesTV.ImageList.Images.Add("Enum_582", Properties.Resources.Enum_582);
  54. BrowseNodesTV.ImageList.Images.Add("Method_636", Properties.Resources.Method_636);
  55. BrowseNodesTV.ImageList.Images.Add("Module_648", Properties.Resources.Module_648);
  56. BrowseNodesTV.ImageList.Images.Add("Loading", Properties.Resources.loading);
  57. // 判断是否允许更改
  58. if (!string.IsNullOrEmpty(textBox1.Text)) textBox1.ReadOnly = true;
  59. // Opc Ua 服务的初始化
  60. OpcUaClientInitialization();
  61. }
  62. private string GetImageKeyFromDescription(ReferenceDescription target, NodeId sourceId)
  63. {
  64. if (target.NodeClass == NodeClass.Variable)
  65. {
  66. DataValue dataValue = m_OpcUaClient.ReadNode((NodeId)target.NodeId);
  67. if (dataValue.WrappedValue.TypeInfo != null)
  68. {
  69. if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.Scalar)
  70. {
  71. return "Enum_582";
  72. }
  73. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.OneDimension)
  74. {
  75. return "brackets";
  76. }
  77. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.TwoDimensions)
  78. {
  79. return "Module_648";
  80. }
  81. else
  82. {
  83. return "ClassIcon";
  84. }
  85. }
  86. else
  87. {
  88. return "ClassIcon";
  89. }
  90. }
  91. else if (target.NodeClass == NodeClass.Object)
  92. {
  93. if (sourceId == ObjectIds.ObjectsFolder)
  94. {
  95. return "VirtualMachine";
  96. }
  97. else
  98. {
  99. return "ClassIcon";
  100. }
  101. }
  102. else if (target.NodeClass == NodeClass.Method)
  103. {
  104. return "Method_636";
  105. }
  106. else
  107. {
  108. return "ClassIcon";
  109. }
  110. }
  111. private string GetImageIndex( DataValue dataValue )
  112. {
  113. if (dataValue == null) return "ClassIcon";
  114. if (dataValue.WrappedValue.TypeInfo != null)
  115. {
  116. if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.Scalar)
  117. {
  118. return "Enum_582";
  119. }
  120. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.OneDimension)
  121. {
  122. return "brackets";
  123. }
  124. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.TwoDimensions)
  125. {
  126. return "Module_648";
  127. }
  128. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.OneOrMoreDimensions)
  129. {
  130. return "Module_648";
  131. }
  132. else
  133. {
  134. return "ClassIcon";
  135. }
  136. }
  137. return "ClassIcon";
  138. }
  139. /// <summary>
  140. /// Returns an image index for the specified attribute.
  141. /// </summary>
  142. public string GetImageIndex( Session session, NodeClass nodeClass, ExpandedNodeId typeDefinitionId, bool selected, NodeId valueId = null )
  143. {
  144. if (nodeClass == NodeClass.Variable)
  145. {
  146. //if (session.NodeCache.IsTypeOf( typeDefinitionId, Opc.Ua.VariableTypeIds.PropertyType ))
  147. //{
  148. // return "ClassIcon";
  149. //}
  150. if (valueId != null) return GetImageIndex( m_OpcUaClient.ReadNode( valueId ) );
  151. return "ClassIcon";
  152. }
  153. if (nodeClass == NodeClass.Object)
  154. {
  155. if (typeDefinitionId == ObjectIds.ObjectsFolder)
  156. {
  157. return "VirtualMachine";
  158. }
  159. else if (session.NodeCache.IsTypeOf( typeDefinitionId, Opc.Ua.ObjectTypeIds.FolderType ))
  160. {
  161. if (selected)
  162. {
  163. return "ClassIcon";
  164. }
  165. else
  166. {
  167. return "ClassIcon";
  168. }
  169. }
  170. return "ClassIcon";
  171. }
  172. if (nodeClass == NodeClass.Method)
  173. {
  174. return "Method_636";
  175. }
  176. if (nodeClass == NodeClass.View)
  177. {
  178. return "Method_636";
  179. }
  180. return "ClassIcon";
  181. }
  182. private void FormBrowseServer_FormClosing(object sender, FormClosingEventArgs e)
  183. {
  184. m_OpcUaClient.Disconnect();
  185. }
  186. #endregion
  187. #region OPC UA client
  188. /// <summary>
  189. /// Opc客户端的核心类
  190. /// </summary>
  191. private OpcUaClient m_OpcUaClient = null;
  192. /// <summary>
  193. /// 初始化
  194. /// </summary>
  195. private void OpcUaClientInitialization()
  196. {
  197. m_OpcUaClient = new OpcUaClient();
  198. m_OpcUaClient.OpcStatusChange += M_OpcUaClient_OpcStatusChange1; ;
  199. m_OpcUaClient.ConnectComplete += M_OpcUaClient_ConnectComplete;
  200. }
  201. /// <summary>
  202. /// 连接服务器结束后马上浏览根节点
  203. /// </summary>
  204. /// <param name="sender"></param>
  205. /// <param name="e"></param>
  206. private void M_OpcUaClient_ConnectComplete(object sender, EventArgs e)
  207. {
  208. //try
  209. //{
  210. // OpcUaClient client = (OpcUaClient)sender;
  211. // if (client.Connected)
  212. // {
  213. // // populate the browse view.
  214. // PopulateBranch(ObjectIds.ObjectsFolder, BrowseNodesTV.Nodes);
  215. // BrowseNodesTV.Enabled = true;
  216. // }
  217. //}
  218. //catch (Exception exception)
  219. //{
  220. // ClientUtils.HandleException(Text, exception);
  221. //}
  222. try
  223. {
  224. m_session = m_OpcUaClient.Session as Opc.Ua.Client.Session;
  225. // set a suitable initial state.
  226. if (m_session != null)
  227. {
  228. BrowseDescription nodeToBrowse = new BrowseDescription( );
  229. nodeToBrowse.NodeId = Opc.Ua.ObjectIds.ViewsFolder;
  230. nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HierarchicalReferences;
  231. nodeToBrowse.IncludeSubtypes = true;
  232. nodeToBrowse.BrowseDirection = BrowseDirection.Forward;
  233. nodeToBrowse.NodeClassMask = 0;
  234. nodeToBrowse.ResultMask = (uint)BrowseResultMask.All;
  235. ReferenceDescriptionCollection references = ClientUtils.Browse( m_session, nodeToBrowse, false );
  236. }
  237. // browse the instances in the server.
  238. Initialize( m_session, ObjectIds.ObjectsFolder, ReferenceTypeIds.Organizes, ReferenceTypeIds.Aggregates );
  239. BrowseNodesTV.Enabled = true;
  240. }
  241. catch (Exception exception)
  242. {
  243. ClientUtils.HandleException( this.Text, exception );
  244. }
  245. }
  246. /// <summary>
  247. /// OPC 客户端的状态变化后的消息提醒
  248. /// </summary>
  249. /// <param name="sender"></param>
  250. /// <param name="e"></param>
  251. private void M_OpcUaClient_OpcStatusChange1(object sender, OpcUaStatusEventArgs e)
  252. {
  253. if (InvokeRequired)
  254. {
  255. BeginInvoke(new Action(() =>
  256. {
  257. M_OpcUaClient_OpcStatusChange1(sender, e);
  258. }));
  259. return;
  260. }
  261. if (e.Error)
  262. {
  263. toolStripStatusLabel1.BackColor = Color.Red;
  264. }
  265. else
  266. {
  267. toolStripStatusLabel1.BackColor = SystemColors.Control;
  268. }
  269. toolStripStatusLabel_opc.Text = e.ToString();
  270. }
  271. private ReferenceDescriptionCollection GetReferenceDescriptionCollection(NodeId sourceId)
  272. {
  273. TaskCompletionSource<ReferenceDescriptionCollection> task = new TaskCompletionSource<ReferenceDescriptionCollection>();
  274. // find all of the components of the node.
  275. BrowseDescription nodeToBrowse1 = new BrowseDescription();
  276. nodeToBrowse1.NodeId = sourceId;
  277. nodeToBrowse1.BrowseDirection = BrowseDirection.Forward;
  278. nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.Aggregates;
  279. nodeToBrowse1.IncludeSubtypes = true;
  280. nodeToBrowse1.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable | NodeClass.Method | NodeClass.ReferenceType | NodeClass.ObjectType | NodeClass.View | NodeClass.VariableType | NodeClass.DataType);
  281. nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All;
  282. // find all nodes organized by the node.
  283. BrowseDescription nodeToBrowse2 = new BrowseDescription();
  284. nodeToBrowse2.NodeId = sourceId;
  285. nodeToBrowse2.BrowseDirection = BrowseDirection.Forward;
  286. nodeToBrowse2.ReferenceTypeId = ReferenceTypeIds.Organizes;
  287. nodeToBrowse2.IncludeSubtypes = true;
  288. nodeToBrowse2.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable | NodeClass.Method | NodeClass.View | NodeClass.ReferenceType | NodeClass.ObjectType | NodeClass.VariableType | NodeClass.DataType);
  289. nodeToBrowse2.ResultMask = (uint)BrowseResultMask.All;
  290. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
  291. nodesToBrowse.Add(nodeToBrowse1);
  292. nodesToBrowse.Add(nodeToBrowse2);
  293. // fetch references from the server.
  294. ReferenceDescriptionCollection references = FormUtils.Browse(m_OpcUaClient.Session, nodesToBrowse, false);
  295. return references;
  296. }
  297. /// <summary>
  298. /// 0:NodeClass 1:Value 2:AccessLevel 3:DisplayName 4:Description
  299. /// </summary>
  300. /// <param name="nodeIds"></param>
  301. /// <returns></returns>
  302. private DataValue[] ReadOneNodeFiveAttributes(List<NodeId> nodeIds)
  303. {
  304. ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
  305. foreach (var nodeId in nodeIds)
  306. {
  307. NodeId sourceId = nodeId;
  308. nodesToRead.Add(new ReadValueId()
  309. {
  310. NodeId = sourceId,
  311. AttributeId = Attributes.NodeClass
  312. });
  313. nodesToRead.Add(new ReadValueId()
  314. {
  315. NodeId = sourceId,
  316. AttributeId = Attributes.Value
  317. });
  318. nodesToRead.Add(new ReadValueId()
  319. {
  320. NodeId = sourceId,
  321. AttributeId = Attributes.AccessLevel
  322. });
  323. nodesToRead.Add(new ReadValueId()
  324. {
  325. NodeId = sourceId,
  326. AttributeId = Attributes.DisplayName
  327. });
  328. nodesToRead.Add(new ReadValueId()
  329. {
  330. NodeId = sourceId,
  331. AttributeId = Attributes.Description
  332. });
  333. }
  334. // read all values.
  335. m_OpcUaClient.Session.Read(
  336. null,
  337. 0,
  338. TimestampsToReturn.Neither,
  339. nodesToRead,
  340. out DataValueCollection results,
  341. out DiagnosticInfoCollection diagnosticInfos);
  342. ClientBase.ValidateResponse(results, nodesToRead);
  343. ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
  344. return results.ToArray();
  345. }
  346. /// <summary>
  347. /// 读取一个节点的指定属性
  348. /// </summary>
  349. /// <param name="nodeId"></param>
  350. /// <param name="attribute"></param>
  351. /// <returns></returns>
  352. private DataValue ReadNoteDataValueAttributes(NodeId nodeId, uint attribute)
  353. {
  354. NodeId sourceId = nodeId;
  355. ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
  356. ReadValueId nodeToRead = new ReadValueId();
  357. nodeToRead.NodeId = sourceId;
  358. nodeToRead.AttributeId = attribute;
  359. nodesToRead.Add(nodeToRead);
  360. int startOfProperties = nodesToRead.Count;
  361. // find all of the pror of the node.
  362. BrowseDescription nodeToBrowse1 = new BrowseDescription();
  363. nodeToBrowse1.NodeId = sourceId;
  364. nodeToBrowse1.BrowseDirection = BrowseDirection.Forward;
  365. nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.HasProperty;
  366. nodeToBrowse1.IncludeSubtypes = true;
  367. nodeToBrowse1.NodeClassMask = 0;
  368. nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All;
  369. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
  370. nodesToBrowse.Add(nodeToBrowse1);
  371. // fetch property references from the server.
  372. ReferenceDescriptionCollection references = FormUtils.Browse(m_OpcUaClient.Session, nodesToBrowse, false);
  373. if (references == null)
  374. {
  375. return null;
  376. }
  377. for (int ii = 0; ii < references.Count; ii++)
  378. {
  379. // ignore external references.
  380. if (references[ii].NodeId.IsAbsolute)
  381. {
  382. continue;
  383. }
  384. ReadValueId nodeToRead2 = new ReadValueId();
  385. nodeToRead2.NodeId = (NodeId)references[ii].NodeId;
  386. nodeToRead2.AttributeId = Attributes.Value;
  387. nodesToRead.Add(nodeToRead2);
  388. }
  389. // read all values.
  390. DataValueCollection results = null;
  391. DiagnosticInfoCollection diagnosticInfos = null;
  392. m_OpcUaClient.Session.Read(
  393. null,
  394. 0,
  395. TimestampsToReturn.Neither,
  396. nodesToRead,
  397. out results,
  398. out diagnosticInfos);
  399. ClientBase.ValidateResponse(results, nodesToRead);
  400. ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
  401. return results[0];
  402. }
  403. #endregion
  404. #region Menu Click Event
  405. private void exitToolStripMenuItem_Click(object sender, EventArgs e)
  406. {
  407. // press exit menu button
  408. Close();
  409. }
  410. private void discoverToolStripMenuItem_Click(object sender, EventArgs e)
  411. {
  412. string endpointUrl = new DiscoverServerDlg().ShowDialog(m_OpcUaClient.AppConfig, null);
  413. if (endpointUrl != null)
  414. {
  415. textBox1.Text = endpointUrl;
  416. }
  417. }
  418. #endregion
  419. #region Press Connect Click Button
  420. private async void button1_Click( object sender, EventArgs e )
  421. {
  422. // connect to server
  423. using (FormConnectSelect formConnectSelect = new FormConnectSelect( m_OpcUaClient ))
  424. {
  425. if (formConnectSelect.ShowDialog( ) == DialogResult.OK)
  426. {
  427. try
  428. {
  429. await m_OpcUaClient.ConnectServer( textBox1.Text );
  430. button1.Enabled = false;
  431. button3.Enabled = true;
  432. }
  433. catch (Exception ex)
  434. {
  435. ClientUtils.HandleException( Text, ex );
  436. }
  437. }
  438. }
  439. }
  440. private void button3_Click( object sender, EventArgs e )
  441. {
  442. // 关闭连接
  443. try
  444. {
  445. m_OpcUaClient?.Disconnect( );
  446. button1.Enabled = true;
  447. button3.Enabled = false;
  448. }
  449. catch (Exception ex)
  450. {
  451. ClientUtils.HandleException( Text, ex );
  452. }
  453. }
  454. #endregion
  455. #region 填入分支
  456. /// <summary>
  457. /// Populates the branch in the tree view.
  458. /// </summary>
  459. /// <param name="sourceId">The NodeId of the Node to browse.</param>
  460. /// <param name="nodes">The node collect to populate.</param>
  461. private async void PopulateBranch(NodeId sourceId, TreeNodeCollection nodes)
  462. {
  463. nodes.Clear();
  464. nodes.Add(new TreeNode("Browsering...", 7, 7));
  465. // fetch references from the server.
  466. TreeNode[] listNode = await Task.Run(() =>
  467. {
  468. ReferenceDescriptionCollection references = GetReferenceDescriptionCollection(sourceId);
  469. List<TreeNode> list = new List<TreeNode>();
  470. if (references != null)
  471. {
  472. // process results.
  473. for (int ii = 0; ii < references.Count; ii++)
  474. {
  475. ReferenceDescription target = references[ii];
  476. TreeNode child = new TreeNode(Utils.Format("{0}", target));
  477. child.Tag = target;
  478. string key = GetImageKeyFromDescription(target, sourceId);
  479. child.ImageKey = key;
  480. child.SelectedImageKey = key;
  481. // if (target.NodeClass == NodeClass.Object || target.NodeClass == NodeClass.Unspecified || expanded)
  482. // {
  483. // child.Nodes.Add(new TreeNode());
  484. // }
  485. if (!checkBox1.Checked)
  486. {
  487. if (GetReferenceDescriptionCollection( (NodeId)target.NodeId ).Count > 0)
  488. {
  489. child.Nodes.Add( new TreeNode( ) );
  490. }
  491. }
  492. else
  493. {
  494. child.Nodes.Add( new TreeNode( ) );
  495. }
  496. list.Add(child);
  497. }
  498. }
  499. return list.ToArray();
  500. });
  501. // update the attributes display.
  502. // DisplayAttributes(sourceId);
  503. nodes.Clear();
  504. nodes.AddRange(listNode.ToArray());
  505. }
  506. #endregion
  507. #region 节点打开的时候操作
  508. private void BrowseNodesTV_MouseClick(object sender, MouseEventArgs e)
  509. {
  510. if (e.Button == MouseButtons.Right)
  511. {
  512. TreeNode tn = BrowseNodesTV.GetNodeAt(e.X, e.Y);
  513. if (tn != null)
  514. {
  515. BrowseNodesTV.SelectedNode = tn;
  516. }
  517. }
  518. }
  519. private async void BrowseNodesTV_BeforeExpand(object sender, TreeViewCancelEventArgs e)
  520. {
  521. //try
  522. //{
  523. // check if node has already been expanded once.
  524. if (e.Node.Nodes.Count != 1)
  525. {
  526. //return;
  527. }
  528. if (e.Node.Nodes.Count > 0)
  529. {
  530. if (e.Node.Nodes[0].Text != String.Empty)
  531. {
  532. return;
  533. }
  534. }
  535. // // populate children.
  536. // PopulateBranch((NodeId)reference.NodeId, e.Node.Nodes);
  537. //}
  538. //catch (Exception exception)
  539. //{
  540. // ClientUtils.HandleException(this.Text, exception);
  541. //}
  542. BrowseTV_BeforeExpand( sender, e );
  543. }
  544. private void BrowseNodesTV_AfterSelect(object sender, TreeViewEventArgs e)
  545. {
  546. try
  547. {
  548. RemoveAllSubscript( );
  549. // get the source for the node.
  550. ReferenceDescription reference = e.Node.Tag as ReferenceDescription;
  551. if (reference == null || reference.NodeId.IsAbsolute)
  552. {
  553. return;
  554. }
  555. // populate children.
  556. ShowMember((NodeId)reference.NodeId);
  557. }
  558. catch (Exception exception)
  559. {
  560. ClientUtils.HandleException(Text, exception);
  561. }
  562. }
  563. private void ClearDataGridViewRows(int index)
  564. {
  565. for (int i = dataGridView1.Rows.Count - 1; i >= index; i--)
  566. {
  567. if (i >= 0)
  568. {
  569. dataGridView1.Rows.RemoveAt(i);
  570. }
  571. }
  572. }
  573. #endregion
  574. #region 点击树节点后在数据表显示
  575. /// <summary>
  576. /// 点击了节点名称前的内容进行复制
  577. /// </summary>
  578. /// <param name="sender"></param>
  579. /// <param name="e"></param>
  580. private void label2_Click(object sender, EventArgs e)
  581. {
  582. if (!string.IsNullOrEmpty(textBox_nodeId.Text))
  583. {
  584. Clipboard.SetText(textBox_nodeId.Text);
  585. }
  586. }
  587. private async void ShowMember(NodeId sourceId)
  588. {
  589. textBox_nodeId.Text = sourceId.ToString();
  590. // dataGridView1.Rows.Clear();
  591. int index = 0;
  592. ReferenceDescriptionCollection references;
  593. try
  594. {
  595. references = await Task.Run(() =>
  596. {
  597. return GetReferenceDescriptionCollection(sourceId);
  598. });
  599. }
  600. catch(Exception exception)
  601. {
  602. ClientUtils.HandleException(Text, exception);
  603. return;
  604. }
  605. if (references?.Count > 0)
  606. {
  607. // 获取所有要读取的子节点
  608. List<NodeId> nodeIds = new List<NodeId>();
  609. for (int ii = 0; ii < references.Count; ii++)
  610. {
  611. ReferenceDescription target = references[ii];
  612. nodeIds.Add((NodeId)target.NodeId);
  613. }
  614. DateTime dateTimeStart = DateTime.Now;
  615. // 获取所有的值
  616. DataValue[] dataValues = await Task.Run(() =>
  617. {
  618. return ReadOneNodeFiveAttributes(nodeIds);
  619. });
  620. label_time_spend.Text = (int)(DateTime.Now - dateTimeStart).TotalMilliseconds + " ms";
  621. // 显示
  622. for (int jj = 0; jj < dataValues.Length; jj += 5)
  623. {
  624. AddDataGridViewNewRow(dataValues, jj, index++, nodeIds[jj / 5]);
  625. }
  626. }
  627. else
  628. {
  629. // 子节点没有数据的情况
  630. try
  631. {
  632. DateTime dateTimeStart = DateTime.Now;
  633. DataValue dataValue = m_OpcUaClient.ReadNode(sourceId);
  634. if (dataValue.WrappedValue.TypeInfo?.ValueRank == ValueRanks.OneDimension)
  635. {
  636. // 数组显示
  637. AddDataGridViewArrayRow(sourceId, out index);
  638. }
  639. else
  640. {
  641. // 显示单个数本身
  642. label_time_spend.Text = (int)(DateTime.Now - dateTimeStart).TotalMilliseconds + " ms";
  643. AddDataGridViewNewRow(ReadOneNodeFiveAttributes(new List<NodeId>() { sourceId }), 0, index++, sourceId);
  644. }
  645. }
  646. catch (Exception exception)
  647. {
  648. ClientUtils.HandleException(Text, exception);
  649. return;
  650. }
  651. }
  652. ClearDataGridViewRows(index);
  653. }
  654. private void AddDataGridViewNewRow(DataValue[] dataValues, int startIndex, int index, NodeId nodeId)
  655. {
  656. // int index = dataGridView1.Rows.Add();
  657. while (index >= dataGridView1.Rows.Count)
  658. {
  659. dataGridView1.Rows.Add();
  660. }
  661. DataGridViewRow dgvr = dataGridView1.Rows[index];
  662. dgvr.Tag = nodeId;
  663. if (dataValues[startIndex].WrappedValue.Value == null) return;
  664. NodeClass nodeclass = (NodeClass)dataValues[startIndex].WrappedValue.Value;
  665. dgvr.Cells[1].Value = dataValues[3 + startIndex].WrappedValue.Value;
  666. dgvr.Cells[5].Value = dataValues[4 + startIndex].WrappedValue.Value;
  667. dgvr.Cells[4].Value = GetDiscriptionFromAccessLevel(dataValues[2 + startIndex]);
  668. if (nodeclass == NodeClass.Object)
  669. {
  670. dgvr.Cells[0].Value = Properties.Resources.ClassIcon;
  671. dgvr.Cells[2].Value = "";
  672. dgvr.Cells[3].Value = nodeclass.ToString();
  673. }
  674. else if (nodeclass == NodeClass.Method)
  675. {
  676. dgvr.Cells[0].Value = Properties.Resources.Method_636;
  677. dgvr.Cells[2].Value = "";
  678. dgvr.Cells[3].Value = nodeclass.ToString();
  679. }
  680. else if (nodeclass == NodeClass.Variable)
  681. {
  682. DataValue dataValue = dataValues[1 + startIndex];
  683. if (dataValue.WrappedValue.TypeInfo != null)
  684. {
  685. dgvr.Cells[3].Value = dataValue.WrappedValue.TypeInfo.BuiltInType;
  686. dgvr.Cells[6].Value = dataValue.StatusCode.ToString();
  687. // dgvr.Cells[3].Value = dataValue.Value.GetType().ToString();
  688. if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.Scalar)
  689. {
  690. dgvr.Cells[2].Value = dataValue.WrappedValue.Value;
  691. dgvr.Cells[0].Value = Properties.Resources.Enum_582;
  692. }
  693. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.OneDimension)
  694. {
  695. dgvr.Cells[2].Value = dataValue.Value.GetType().ToString();
  696. dgvr.Cells[0].Value = Properties.Resources.brackets_Square_16xMD;
  697. }
  698. else if (dataValue.WrappedValue.TypeInfo.ValueRank == ValueRanks.TwoDimensions)
  699. {
  700. dgvr.Cells[2].Value = dataValue.Value.GetType().ToString();
  701. dgvr.Cells[0].Value = Properties.Resources.Module_648;
  702. }
  703. else
  704. {
  705. dgvr.Cells[2].Value = dataValue.Value.GetType().ToString();
  706. dgvr.Cells[0].Value = Properties.Resources.ClassIcon;
  707. }
  708. }
  709. else
  710. {
  711. dgvr.Cells[0].Value = Properties.Resources.ClassIcon;
  712. dgvr.Cells[2].Value = dataValue.Value;
  713. dgvr.Cells[3].Value = "null";
  714. }
  715. }
  716. else
  717. {
  718. dgvr.Cells[2].Value = "";
  719. dgvr.Cells[0].Value = Properties.Resources.ClassIcon;
  720. dgvr.Cells[3].Value = nodeclass.ToString();
  721. dgvr.Cells[6].Value = "";
  722. }
  723. }
  724. private void AddDataGridViewArrayRow(NodeId nodeId,out int index)
  725. {
  726. DateTime dateTimeStart = DateTime.Now;
  727. DataValue[] dataValues = ReadOneNodeFiveAttributes(new List<NodeId>() { nodeId });
  728. label_time_spend.Text = (int)(DateTime.Now - dateTimeStart).TotalMilliseconds + " ms";
  729. DataValue dataValue = dataValues[1];
  730. if (dataValue.WrappedValue.TypeInfo?.ValueRank == ValueRanks.OneDimension)
  731. {
  732. string access= GetDiscriptionFromAccessLevel(dataValues[2]);
  733. BuiltInType type = dataValue.WrappedValue.TypeInfo.BuiltInType;
  734. object des = dataValues[4].Value ?? "";
  735. object dis = dataValues[3].Value ?? type;
  736. Array array = dataValue.Value as Array;
  737. int i = 0;
  738. foreach(object obj in array)
  739. {
  740. while (i >= dataGridView1.Rows.Count)
  741. {
  742. dataGridView1.Rows.Add();
  743. }
  744. DataGridViewRow dgvr = dataGridView1.Rows[i];
  745. dgvr.Tag = null;
  746. dgvr.Cells[0].Value = Properties.Resources.Enum_582;
  747. dgvr.Cells[1].Value = $"{dis} [{i++}]";
  748. dgvr.Cells[2].Value = obj;
  749. dgvr.Cells[3].Value = type;
  750. dgvr.Cells[4].Value = access;
  751. dgvr.Cells[5].Value = des;
  752. }
  753. index = i;
  754. }
  755. else
  756. {
  757. index = 0;
  758. }
  759. }
  760. private string GetDiscriptionFromAccessLevel(DataValue value)
  761. {
  762. if (value.WrappedValue.Value != null)
  763. {
  764. switch ((byte)value.WrappedValue.Value)
  765. {
  766. case 0: return "None";
  767. case 1: return "CurrentRead";
  768. case 2: return "CurrentWrite";
  769. case 3: return "CurrentReadOrWrite";
  770. case 4: return "HistoryRead";
  771. case 8: return "HistoryWrite";
  772. case 12: return "HistoryReadOrWrite";
  773. case 16: return "SemanticChange";
  774. case 32: return "StatusWrite";
  775. case 64: return "TimestampWrite";
  776. default: return "None";
  777. }
  778. }
  779. else
  780. {
  781. return "null";
  782. }
  783. }
  784. #endregion
  785. #region 订阅刷新块
  786. private List<string> subNodeIds = new List<string>( );
  787. private bool isSingleValueSub = false;
  788. private void RemoveAllSubscript( )
  789. {
  790. m_OpcUaClient?.RemoveAllSubscription( );
  791. }
  792. private void SubCallBack( string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs eventArgs )
  793. {
  794. if (InvokeRequired)
  795. {
  796. Invoke( new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>( SubCallBack ), key, monitoredItem, eventArgs );
  797. return;
  798. }
  799. MonitoredItemNotification notification = eventArgs.NotificationValue as MonitoredItemNotification;
  800. string nodeId = monitoredItem.StartNodeId.ToString( );
  801. int index = subNodeIds.IndexOf( nodeId );
  802. if (index >= 0)
  803. {
  804. if (isSingleValueSub)
  805. {
  806. if (notification.Value.WrappedValue.TypeInfo?.ValueRank == ValueRanks.OneDimension)
  807. {
  808. Array array = notification.Value.WrappedValue.Value as Array;
  809. int i = 0;
  810. foreach (object obj in array)
  811. {
  812. DataGridViewRow dgvr = dataGridView1.Rows[i];
  813. dgvr.Cells[2].Value = obj;
  814. i++;
  815. }
  816. }
  817. else
  818. {
  819. dataGridView1.Rows[index].Cells[2].Value = notification.Value.WrappedValue.Value;
  820. }
  821. }
  822. else
  823. {
  824. dataGridView1.Rows[index].Cells[2].Value = notification.Value.WrappedValue.Value;
  825. }
  826. }
  827. }
  828. private async void button2_Click(object sender, EventArgs e)
  829. {
  830. if (m_OpcUaClient != null)
  831. {
  832. RemoveAllSubscript( );
  833. if (button2.BackColor != Color.LimeGreen)
  834. {
  835. button2.BackColor = Color.LimeGreen;
  836. // 判断当前的选择
  837. if (string.IsNullOrEmpty( textBox_nodeId.Text )) return;
  838. ReferenceDescriptionCollection references;
  839. try
  840. {
  841. references = await Task.Run( ( ) =>
  842. {
  843. return GetReferenceDescriptionCollection( new NodeId( textBox_nodeId.Text ) );
  844. } );
  845. }
  846. catch (Exception exception)
  847. {
  848. ClientUtils.HandleException( Text, exception );
  849. return;
  850. }
  851. subNodeIds = new List<string>( );
  852. if (references?.Count > 0)
  853. {
  854. isSingleValueSub = false;
  855. // 获取所有要订阅的子节点
  856. for (int ii = 0; ii < references.Count; ii++)
  857. {
  858. ReferenceDescription target = references[ii];
  859. subNodeIds.Add( ((NodeId)target.NodeId).ToString( ) );
  860. }
  861. }
  862. else
  863. {
  864. isSingleValueSub = true;
  865. // 子节点没有数据的情况
  866. subNodeIds.Add( textBox_nodeId.Text );
  867. }
  868. m_OpcUaClient.AddSubscription( "subTest", subNodeIds.ToArray( ), SubCallBack );
  869. }
  870. else
  871. {
  872. button2.BackColor = SystemColors.Control;
  873. }
  874. }
  875. }
  876. #endregion
  877. #region 点击了表格修改数据
  878. private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
  879. {
  880. if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex + 1].Value is BuiltInType builtInType)
  881. {
  882. dynamic value = null;
  883. if (dataGridView1.Rows[e.RowIndex].Tag is NodeId nodeId)
  884. {
  885. // 节点
  886. try
  887. {
  888. value = GetValueFromString(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), builtInType);
  889. }
  890. catch
  891. {
  892. MessageBox.Show("Invalid Input Value");
  893. return;
  894. }
  895. if (!m_OpcUaClient.WriteNode(nodeId.ToString(), value))
  896. {
  897. MessageBox.Show("Failed to write value");
  898. }
  899. }
  900. else
  901. {
  902. // 点击了数组修改
  903. IList<string> list = new List<string>();
  904. for (int jj = 0; jj < dataGridView1.RowCount; jj++)
  905. {
  906. list.Add(dataGridView1.Rows[jj].Cells[e.ColumnIndex].Value.ToString());
  907. }
  908. try
  909. {
  910. value = GetArrayValueFromString(list, builtInType);
  911. }
  912. catch(Exception ex)
  913. {
  914. MessageBox.Show("Invalid Input Value: " + ex.Message);
  915. return;
  916. }
  917. if (!m_OpcUaClient.WriteNode(textBox_nodeId.Text, value))
  918. {
  919. MessageBox.Show("Failed to write value");
  920. }
  921. }
  922. }
  923. else
  924. {
  925. MessageBox.Show("Invalid data type");
  926. }
  927. //MessageBox.Show(
  928. // "Type:" + dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.GetType().ToString() + Environment.NewLine +
  929. // "Value:" + dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
  930. }
  931. private dynamic GetValueFromString(string value, BuiltInType builtInType)
  932. {
  933. switch(builtInType)
  934. {
  935. case BuiltInType.Boolean:
  936. {
  937. return bool.Parse(value);
  938. }
  939. case BuiltInType.Byte:
  940. {
  941. return byte.Parse(value);
  942. }
  943. case BuiltInType.DateTime:
  944. {
  945. return DateTime.Parse(value);
  946. }
  947. case BuiltInType.Double:
  948. {
  949. return double.Parse(value);
  950. }
  951. case BuiltInType.Float:
  952. {
  953. return float.Parse(value);
  954. }
  955. case BuiltInType.Guid:
  956. {
  957. return Guid.Parse(value);
  958. }
  959. case BuiltInType.Int16:
  960. {
  961. return short.Parse(value);
  962. }
  963. case BuiltInType.Int32:
  964. {
  965. return int.Parse(value);
  966. }
  967. case BuiltInType.Int64:
  968. {
  969. return long.Parse(value);
  970. }
  971. case BuiltInType.Integer:
  972. {
  973. return int.Parse(value);
  974. }
  975. case BuiltInType.LocalizedText:
  976. {
  977. return value;
  978. }
  979. case BuiltInType.SByte:
  980. {
  981. return sbyte.Parse(value);
  982. }
  983. case BuiltInType.String:
  984. {
  985. return value;
  986. }
  987. case BuiltInType.UInt16:
  988. {
  989. return ushort.Parse(value);
  990. }
  991. case BuiltInType.UInt32:
  992. {
  993. return uint.Parse(value);
  994. }
  995. case BuiltInType.UInt64:
  996. {
  997. return ulong.Parse(value);
  998. }
  999. case BuiltInType.UInteger:
  1000. {
  1001. return uint.Parse(value);
  1002. }
  1003. default:throw new Exception("Not supported data type");
  1004. }
  1005. }
  1006. private dynamic GetArrayValueFromString(IList<string> values, BuiltInType builtInType)
  1007. {
  1008. switch (builtInType)
  1009. {
  1010. case BuiltInType.Boolean:
  1011. {
  1012. bool[] result = new bool[values.Count];
  1013. for (int i = 0; i < values.Count; i++)
  1014. {
  1015. result[i] = bool.Parse(values[i]);
  1016. }
  1017. return result;
  1018. }
  1019. case BuiltInType.Byte:
  1020. {
  1021. byte[] result = new byte[values.Count];
  1022. for (int i = 0; i < values.Count; i++)
  1023. {
  1024. result[i] = byte.Parse(values[i]);
  1025. }
  1026. return result;
  1027. }
  1028. case BuiltInType.DateTime:
  1029. {
  1030. DateTime[] result = new DateTime[values.Count];
  1031. for (int i = 0; i < values.Count; i++)
  1032. {
  1033. result[i] = DateTime.Parse(values[i]);
  1034. }
  1035. return result;
  1036. }
  1037. case BuiltInType.Double:
  1038. {
  1039. double[] result = new double[values.Count];
  1040. for (int i = 0; i < values.Count; i++)
  1041. {
  1042. result[i] = double.Parse(values[i]);
  1043. }
  1044. return result;
  1045. }
  1046. case BuiltInType.Float:
  1047. {
  1048. float[] result = new float[values.Count];
  1049. for (int i = 0; i < values.Count; i++)
  1050. {
  1051. result[i] = float.Parse(values[i]);
  1052. }
  1053. return result;
  1054. }
  1055. case BuiltInType.Guid:
  1056. {
  1057. Guid[] result = new Guid[values.Count];
  1058. for (int i = 0; i < values.Count; i++)
  1059. {
  1060. result[i] = Guid.Parse(values[i]);
  1061. }
  1062. return result;
  1063. }
  1064. case BuiltInType.Int16:
  1065. {
  1066. short[] result = new short[values.Count];
  1067. for (int i = 0; i < values.Count; i++)
  1068. {
  1069. result[i] = short.Parse(values[i]);
  1070. }
  1071. return result;
  1072. }
  1073. case BuiltInType.Int32:
  1074. {
  1075. int[] result = new int[values.Count];
  1076. for (int i = 0; i < values.Count; i++)
  1077. {
  1078. result[i] = int.Parse(values[i]);
  1079. }
  1080. return result;
  1081. }
  1082. case BuiltInType.Int64:
  1083. {
  1084. long[] result = new long[values.Count];
  1085. for (int i = 0; i < values.Count; i++)
  1086. {
  1087. result[i] = long.Parse(values[i]);
  1088. }
  1089. return result;
  1090. }
  1091. case BuiltInType.Integer:
  1092. {
  1093. int[] result = new int[values.Count];
  1094. for (int i = 0; i < values.Count; i++)
  1095. {
  1096. result[i] = int.Parse(values[i]);
  1097. }
  1098. return result;
  1099. }
  1100. case BuiltInType.LocalizedText:
  1101. {
  1102. return values.ToArray();
  1103. }
  1104. case BuiltInType.SByte:
  1105. {
  1106. sbyte[] result = new sbyte[values.Count];
  1107. for (int i = 0; i < values.Count; i++)
  1108. {
  1109. result[i] = sbyte.Parse(values[i]);
  1110. }
  1111. return result;
  1112. }
  1113. case BuiltInType.String:
  1114. {
  1115. return values.ToArray();
  1116. }
  1117. case BuiltInType.UInt16:
  1118. {
  1119. ushort[] result = new ushort[values.Count];
  1120. for (int i = 0; i < values.Count; i++)
  1121. {
  1122. result[i] = ushort.Parse(values[i]);
  1123. }
  1124. return result;
  1125. }
  1126. case BuiltInType.UInt32:
  1127. {
  1128. uint[] result = new uint[values.Count];
  1129. for (int i = 0; i < values.Count; i++)
  1130. {
  1131. result[i] = uint.Parse(values[i]);
  1132. }
  1133. return result;
  1134. }
  1135. case BuiltInType.UInt64:
  1136. {
  1137. ulong[] result = new ulong[values.Count];
  1138. for (int i = 0; i < values.Count; i++)
  1139. {
  1140. result[i] = ulong.Parse(values[i]);
  1141. }
  1142. return result;
  1143. }
  1144. case BuiltInType.UInteger:
  1145. {
  1146. uint[] result = new uint[values.Count];
  1147. for (int i = 0; i < values.Count; i++)
  1148. {
  1149. result[i] = uint.Parse(values[i]);
  1150. }
  1151. return result;
  1152. }
  1153. default: throw new Exception("Not supported data type");
  1154. }
  1155. }
  1156. private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
  1157. {
  1158. if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex + 1].Value is BuiltInType builtInType)
  1159. {
  1160. if (
  1161. builtInType == BuiltInType.Boolean ||
  1162. builtInType == BuiltInType.Byte ||
  1163. builtInType == BuiltInType.DateTime ||
  1164. builtInType == BuiltInType.Double ||
  1165. builtInType == BuiltInType.Float ||
  1166. builtInType == BuiltInType.Guid ||
  1167. builtInType == BuiltInType.Int16 ||
  1168. builtInType == BuiltInType.Int32 ||
  1169. builtInType == BuiltInType.Int64 ||
  1170. builtInType == BuiltInType.Integer ||
  1171. builtInType == BuiltInType.LocalizedText ||
  1172. builtInType == BuiltInType.SByte ||
  1173. builtInType == BuiltInType.String ||
  1174. builtInType == BuiltInType.UInt16 ||
  1175. builtInType == BuiltInType.UInt32 ||
  1176. builtInType == BuiltInType.UInt64 ||
  1177. builtInType == BuiltInType.UInteger
  1178. )
  1179. {
  1180. }
  1181. else
  1182. {
  1183. e.Cancel = true;
  1184. MessageBox.Show("Not support the Type of modify value!");
  1185. return;
  1186. }
  1187. }
  1188. else
  1189. {
  1190. e.Cancel = true;
  1191. MessageBox.Show("Not support the Type of modify value!");
  1192. return;
  1193. }
  1194. if (!dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex + 2].Value.ToString().Contains("Write"))
  1195. {
  1196. e.Cancel = true;
  1197. MessageBox.Show("Not support the access of modify value!");
  1198. }
  1199. }
  1200. #endregion
  1201. #region Browser New Method
  1202. private NodeId[] m_referenceTypeIds;
  1203. private NodeId m_rootId;
  1204. private Session m_session;
  1205. private Dictionary<NodeId, string> m_typeImageMapping;
  1206. private ViewDescription m_view;
  1207. /// <summary>
  1208. /// The view to use.
  1209. /// </summary>
  1210. public ViewDescription View
  1211. {
  1212. get
  1213. {
  1214. return m_view;
  1215. }
  1216. set
  1217. {
  1218. m_view = value;
  1219. }
  1220. }
  1221. /// <summary>
  1222. /// Initializes the control with a root and a set of hierarchial reference types to follow.
  1223. /// </summary>
  1224. /// <param name="session">The session.</param>
  1225. /// <param name="rootId">The root of the hierarchy to browse.</param>
  1226. /// <param name="referenceTypeIds">The reference types to follow.</param>
  1227. public void Initialize(
  1228. Session session,
  1229. NodeId rootId,
  1230. params NodeId[] referenceTypeIds )
  1231. {
  1232. // set default root.
  1233. if (NodeId.IsNull( rootId ))
  1234. {
  1235. rootId = Opc.Ua.ObjectIds.ObjectsFolder;
  1236. }
  1237. // set default reference type.
  1238. if (referenceTypeIds == null)
  1239. {
  1240. referenceTypeIds = new NodeId[] { Opc.Ua.ReferenceTypeIds.HierarchicalReferences };
  1241. }
  1242. m_rootId = rootId;
  1243. m_referenceTypeIds = referenceTypeIds;
  1244. // save session.
  1245. ChangeSession( session, true );
  1246. }
  1247. /// <summary>
  1248. /// Changes the session used by the control.
  1249. /// </summary>
  1250. private void ChangeSession( Session session, bool refresh )
  1251. {
  1252. m_session = session;
  1253. BrowseNodesTV.Nodes.Clear( );
  1254. if (m_session != null)
  1255. {
  1256. INode node = m_session.NodeCache.Find( m_rootId );
  1257. if (node != null)
  1258. {
  1259. TreeNode root = new TreeNode( node.ToString( ) );
  1260. root.ImageKey = GetImageIndex( m_session, node.NodeClass, node.TypeDefinitionId, false );
  1261. root.SelectedImageKey = GetImageIndex( m_session, node.NodeClass, node.TypeDefinitionId, true );
  1262. ReferenceDescription reference = new ReferenceDescription( );
  1263. reference.NodeId = node.NodeId;
  1264. reference.NodeClass = node.NodeClass;
  1265. reference.BrowseName = node.BrowseName;
  1266. reference.DisplayName = node.DisplayName;
  1267. reference.TypeDefinition = node.TypeDefinitionId;
  1268. root.Tag = reference;
  1269. root.Nodes.Add( new TreeNode( ) );
  1270. BrowseNodesTV.Nodes.Add( root );
  1271. root.Expand( );
  1272. BrowseNodesTV.SelectedNode = root;
  1273. }
  1274. }
  1275. }
  1276. /// <summary>
  1277. /// Handles the BeforeExpand event of the BrowseTV control.
  1278. /// </summary>
  1279. private async Task BrowseTV_BeforeExpand( object sender, TreeViewCancelEventArgs e )
  1280. {
  1281. try
  1282. {
  1283. e.Node.Nodes.Clear( );
  1284. e.Node.Nodes.Add( new TreeNode( "Browsering...", 7, 7 ) );
  1285. TreeNode[] listNode = await Task.Run( ( ) =>
  1286. {
  1287. Console.WriteLine( "BrowseTV_BeforeExpand, m_referenceTypeIds length: " + m_referenceTypeIds.Length );
  1288. ReferenceDescription reference = (ReferenceDescription)e.Node.Tag;
  1289. // build list of references to browse.
  1290. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection( );
  1291. for (int ii = 0; ii < m_referenceTypeIds.Length; ii++)
  1292. {
  1293. BrowseDescription nodeToBrowse = new BrowseDescription( );
  1294. nodeToBrowse.NodeId = m_rootId;
  1295. nodeToBrowse.BrowseDirection = BrowseDirection.Forward;
  1296. nodeToBrowse.ReferenceTypeId = m_referenceTypeIds[ii];
  1297. nodeToBrowse.IncludeSubtypes = true;
  1298. nodeToBrowse.NodeClassMask = 0;
  1299. nodeToBrowse.ResultMask = (uint)BrowseResultMask.All;
  1300. if (reference != null)
  1301. {
  1302. nodeToBrowse.NodeId = (NodeId)reference.NodeId;
  1303. }
  1304. nodesToBrowse.Add( nodeToBrowse );
  1305. }
  1306. // add the childen to the control.
  1307. SortedDictionary<ExpandedNodeId, TreeNode> dictionary = new SortedDictionary<ExpandedNodeId, TreeNode>( );
  1308. Console.WriteLine( " ClientUtils.Browse... " );
  1309. ReferenceDescriptionCollection references = ClientUtils.Browse( m_session, View, nodesToBrowse, false );
  1310. Console.WriteLine( " ClientUtils.Browse: " + (references == null ? "NULL" : "Count:" + references.Count) );
  1311. for (int ii = 0; references != null && ii < references.Count; ii++)
  1312. {
  1313. reference = references[ii];
  1314. // ignore out of server references.
  1315. if (reference.NodeId.IsAbsolute)
  1316. {
  1317. continue;
  1318. }
  1319. if (dictionary.ContainsKey( reference.NodeId ))
  1320. {
  1321. continue;
  1322. }
  1323. TreeNode child = new TreeNode( reference.ToString( ) );
  1324. if (!checkBox1.Checked)
  1325. {
  1326. if (GetReferenceDescriptionCollection( (NodeId)reference.NodeId ).Count > 0)
  1327. {
  1328. child.Nodes.Add( new TreeNode( ) );
  1329. }
  1330. }
  1331. else
  1332. {
  1333. child.Nodes.Add( new TreeNode( ) );
  1334. }
  1335. child.Tag = reference;
  1336. if (!reference.TypeDefinition.IsAbsolute)
  1337. {
  1338. try
  1339. {
  1340. if (!m_typeImageMapping.ContainsKey( (NodeId)reference.TypeDefinition ))
  1341. {
  1342. DataValue value = m_session.ReadValue( (NodeId)reference.NodeId );
  1343. m_typeImageMapping[(NodeId)reference.TypeDefinition] = GetImageIndex( value );
  1344. }
  1345. }
  1346. catch (Exception exception)
  1347. {
  1348. Utils.LogError( exception, "Error loading image." );
  1349. }
  1350. }
  1351. string index = "ClassIcon";
  1352. if (!m_typeImageMapping.TryGetValue( (NodeId)reference.TypeDefinition, out index ))
  1353. {
  1354. child.ImageKey = GetImageIndex( m_session, reference.NodeClass, reference.TypeDefinition, false );
  1355. child.SelectedImageKey = GetImageIndex( m_session, reference.NodeClass, reference.TypeDefinition, true );
  1356. }
  1357. else
  1358. {
  1359. child.ImageKey = index;
  1360. child.SelectedImageKey = index;
  1361. }
  1362. dictionary[reference.NodeId] = child;
  1363. }
  1364. // add nodes to tree.
  1365. List<TreeNode> list = new List<TreeNode>( );
  1366. foreach (TreeNode node in dictionary.Values)
  1367. {
  1368. list.Add( node );
  1369. }
  1370. return list.ToArray( );
  1371. } );
  1372. e.Node.Nodes.Clear( );
  1373. e.Node.Nodes.AddRange( listNode.ToArray( ) );
  1374. }
  1375. catch (Exception exception)
  1376. {
  1377. ClientUtils.HandleException( this.Text, exception );
  1378. }
  1379. if (checkBox2.Checked)
  1380. {
  1381. await Task.Run( ( ) =>
  1382. {
  1383. List<TreeNodeOpcValue> list = new List<TreeNodeOpcValue>( );
  1384. foreach (TreeNode node in e.Node.Nodes)
  1385. {
  1386. if (node.Tag is ReferenceDescription reference)
  1387. {
  1388. list.Add( new TreeNodeOpcValue( ) { Node = node, NodeId = (NodeId)reference.NodeId } );
  1389. }
  1390. }
  1391. try
  1392. {
  1393. m_session.ReadValues( list.Select( m => m.NodeId ).ToList( ), out DataValueCollection collections, out IList<ServiceResult> errors );
  1394. Invoke( new Action( ( ) =>
  1395. {
  1396. for (int i = 0; i < list.Count; i++)
  1397. {
  1398. if (Opc.Ua.StatusCode.IsGood( errors[i].StatusCode ))
  1399. {
  1400. list[i].Value = collections[i];
  1401. list[i].Node.ImageKey = GetImageIndex( collections[i] );
  1402. list[i].Node.SelectedImageKey = GetImageIndex( collections[i] );
  1403. }
  1404. }
  1405. } ) );
  1406. }
  1407. catch (Exception ex)
  1408. {
  1409. Utils.Trace( ex, "Error loading image." );
  1410. }
  1411. } );
  1412. }
  1413. }
  1414. #endregion
  1415. }
  1416. public class TreeNodeOpcValue
  1417. {
  1418. public TreeNode Node { get; set; }
  1419. public NodeId NodeId { get; set; }
  1420. public DataValue Value { get; set; }
  1421. }
  1422. }