2using System.Collections.Generic;
4using System.Threading.Tasks;
5using System.Windows.Controls;
6using System.Windows.Media;
7using System.Windows.Input;
45 this.nodeInfo = NodeInfo;
48 this.parameters =
null;
54 this.children =
new SortedDictionary<string, TreeNode>()
56 {
string.Empty,
new Loading(
this) }
101 get => this.nodeInfo;
102 internal set => this.nodeInfo = value;
112 if (!(this.parameters is
null))
114 string s = this.parameters[
"Type"];
115 if (!
string.IsNullOrEmpty(s))
146 public override void Write(XmlWriter Output)
160 while (!(Loop is
null))
181 while (!(Loop is
null))
193 private bool loadingChildren =
false;
203 if (Concentrator is
null)
207 if (AccountNode is
null)
210 return AccountNode.ConcentratorClient;
219 if (!this.loadingChildren && !this.IsLoaded)
224 if (!(ConcentratorClient is
null) && !
string.IsNullOrEmpty(FullJid))
228 Mouse.OverrideCursor = Cursors.Wait;
230 this.loadingChildren =
true;
233 this.loadingChildren =
false;
238 SortedDictionary<string, TreeNode> Children = new SortedDictionary<string, TreeNode>();
240 foreach (NodeInformation Ref in e.NodesInformation)
241 Children[Ref.NodeId] = new Node(this, Ref);
243 this.children = Children;
246 this.DataSource?.NodesAdded(Children.Values, this);
249 MainWindow.ErrorBox(
string.IsNullOrEmpty(e.ErrorText) ?
"Unable to get child nodes." : e.ErrorText);
251 return Task.CompletedTask;
257 if (!(this.children is
null))
258 this.
DataSource?.NodesRemoved(this.children.Values,
this);
260 this.children =
null;
275 base.UnloadChildren();
279 if (!(this.children is
null))
280 this.
DataSource?.NodesRemoved(this.children.Values,
this);
282 this.children =
new SortedDictionary<string, TreeNode>()
284 {
string.Empty,
new Loading(
this) }
313 new ThingReference[] { new ThingReference(this.nodeInfo.NodeId, this.nodeInfo.SourceId, this.nodeInfo.Partition) },
FieldType.Momentary);
331 new ThingReference[] { new ThingReference(this.nodeInfo.NodeId, this.nodeInfo.SourceId, this.nodeInfo.Partition) },
FieldType.All);
334 throw new NotSupportedException();
351 new ThingReference(this.nodeInfo.NodeId, this.nodeInfo.SourceId, this.nodeInfo.Partition)
381 throw new NotSupportedException();
392 if (Concentrator is
null)
422 public override void Add()
427 if (!(ConcentratorClient is
null) && !
string.IsNullOrEmpty(FullJid))
429 Mouse.OverrideCursor = Cursors.Wait;
437 switch (e.Result.Length)
440 MainWindow.ErrorBox(
"No nodes can be added to this type of node.");
444 MainWindow.UpdateGui(() =>
446 this.Add(e.Result[0].Unlocalized);
447 return Task.CompletedTask;
452 MainWindow.UpdateGui(() =>
454 SelectItemDialog Form = new SelectItemDialog(
"Add node",
"Select type of node to add:",
455 "Add node of selected type.",
"Type",
"Class", e.Result)
457 Owner = MainWindow.currentInstance
460 bool? Result = Form.ShowDialog();
462 if (Result.HasValue && Result.Value)
464 LocalizedString? Item = Form.SelectedItem;
466 this.Add(Item.Value.Unlocalized);
469 return Task.CompletedTask;
475 MainWindow.ErrorBox(
string.IsNullOrEmpty(e.ErrorText) ?
"Unable to add nodes." : e.ErrorText);
477 return Task.CompletedTask;
483 private void Add(
string Type)
485 string FullJid = this.Concentrator?.FullJid;
490 Mouse.OverrideCursor = Cursors.Wait;
498 MainWindow.UpdateGui(async () =>
500 ParameterDialog Dialog = await ParameterDialog.CreateAsync(e.Form);
507 return Task.CompletedTask;
512 this.Add(
new Node(
this, e.NodeInformation));
513 else if (!
string.IsNullOrEmpty(e.From))
514 MainWindow.ErrorBox(
string.IsNullOrEmpty(e.ErrorText) ?
"Unable to set parameters." : e.ErrorText);
516 return Task.CompletedTask;
522 internal void Add(Node Node)
524 if (!this.loadingChildren && this.IsLoaded)
526 SortedDictionary<string, TreeNode> Children =
new SortedDictionary<string, TreeNode>();
528 if (!(this.children is
null))
530 foreach (KeyValuePair<string, TreeNode> P
in this.children)
531 Children[P.Key] = P.Value;
534 Children[Node.NodeId] = Node;
535 this.children = Children;
538 this.DataSource?.NodesAdded(Children.Values,
this);
549 string FullJid = this.Concentrator?.FullJid;
554 Mouse.OverrideCursor = Cursors.Wait;
564 base.Delete(Parent, OnDeleted);
572 MainWindow.ErrorBox(
string.IsNullOrEmpty(e.ErrorText) ?
"Unable to destroy node." : e.ErrorText);
574 return Task.CompletedTask;
585 string FullJid = this.Concentrator?.FullJid;
587 string OldKey = this.Key;
591 Mouse.OverrideCursor = Cursors.Wait;
599 MainWindow.UpdateGui(async () =>
601 ParameterDialog Dialog = await ParameterDialog.CreateAsync(e.Form);
608 return Task.CompletedTask;
614 this.nodeInfo = e.NodeInformation;
617 string NewKey = this.Key;
620 if (NewKey != OldKey && !(Parent is
null))
621 Parent.RenameChild(OldKey, NewKey,
this);
623 else if (!
string.IsNullOrEmpty(e.From))
624 MainWindow.ErrorBox(
string.IsNullOrEmpty(e.ErrorText) ?
"Unable to set properties." : e.ErrorText);
626 return Task.CompletedTask;
635 public override bool IsSniffable => this.nodeInfo.Sniffable && this.IsOnline;
643 string FullJid = this.Concentrator?.FullJid;
648 Mouse.OverrideCursor = Cursors.Wait;
650 this.ConcentratorClient.
RegisterSniffer(FullJid, this.nodeInfo, DateTime.Now.AddHours(1), Sniffer,
651 string.Empty,
string.Empty,
string.Empty, (Sender, e) =>
653 MainWindow.MouseDefault();
657 if (Sniffer is TabSniffer TabSniffer)
658 TabSniffer.SnifferId = e.SnifferId;
663 return Task.CompletedTask;
676 string FullJid = this.Concentrator?.FullJid;
684 Mouse.OverrideCursor = Cursors.Wait;
687 string.Empty,
string.Empty,
string.Empty, (Sender, e) =>
689 MainWindow.MouseDefault();
690 return Task.CompletedTask;
702 base.SelectionChanged();
704 if (!(this.nodeInfo is
null) && this.nodeInfo.HasCommands &&
this.commands is
null)
706 string FullJid = this.Concentrator?.FullJid;
713 this.ConcentratorClient.
GetNodeCommands(FullJid, this.nodeInfo,
string.Empty,
string.Empty,
string.Empty, (Sender, e) =>
716 this.commands = e.Result;
718 MainWindow.ErrorBox(
string.IsNullOrEmpty(e.ErrorText) ?
"Unable to get commands." : e.ErrorText);
720 return Task.CompletedTask;
734 if (
Node ==
this && !(this.commands is
null))
740 if (Command.Command ==
"Search")
743 this.GroupSeparator(ref CurrentGroup, Command.SortCategory, Menu);
745 Menu.Items.Add(Item =
new MenuItem()
747 Header = Command.Name,
752 Item.Click += this.NodeCommandClick;
757 private void NodeCommandClick(
object Sender, System.Windows.RoutedEventArgs e)
759 string FullJid = this.Concentrator?.FullJid;
764 MenuItem Item = (MenuItem)Sender;
767 if (!
string.IsNullOrEmpty(Command.ConfirmationString))
769 if (System.Windows.MessageBox.Show(
MainWindow.currentInstance, Command.ConfirmationString,
"Confirm",
770 System.Windows.MessageBoxButton.YesNoCancel, System.Windows.MessageBoxImage.Question) != System.Windows.MessageBoxResult.Yes)
776 switch (Command.Type)
779 Mouse.OverrideCursor = Cursors.Wait;
786 this.ShowCommandResult(e2, Command);
788 return Task.CompletedTask;
794 Mouse.OverrideCursor = Cursors.Wait;
812 return Task.CompletedTask;
816 this.ShowCommandResult(e2, Command);
817 return Task.CompletedTask;
822 Mouse.OverrideCursor = Cursors.Wait;
836 await e2.Form.Submit();
844 return Task.CompletedTask;
853 MainWindow.currentInstance.Tabs.Items.Add(TabItem);
856 TabItem.Content = ResultView;
862 this.ShowCommandResult(e2, Command);
864 return Task.CompletedTask;
874 if (!(this.commands is
null))
876 this.commands =
null;
877 this.SelectionChanged();
882 if (!
string.IsNullOrEmpty(
Command.SuccessString))
883 MainWindow.MessageBox(
Command.SuccessString,
"Success", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
885 else if (!
string.IsNullOrEmpty(e.
From))
887 if (!
string.IsNullOrEmpty(
Command.FailureString))
888 MainWindow.MessageBox(
Command.FailureString,
"Failure", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
897 public override bool CanSearch
901 if (!(this.commands is
null))
905 if (Command.Command ==
"Search")
919 if (!(this.commands is
null))
923 if (Command.Command ==
"Search")
925 MenuItem Item =
new MenuItem()
927 Header = Command.Name,
932 this.NodeCommandClick(Item,
new System.Windows.RoutedEventArgs());
944 public override bool CanCopy => this.IsOnline;
949 public override async
void Copy()
951 string FullJid = this.Concentrator?.FullJid;
956 Mouse.OverrideCursor = Cursors.Wait;
961 StringBuilder sb =
new StringBuilder();
963 System.Windows.Clipboard.SetText(
XML.
PrettyXml(sb.ToString()));
974 MainWindow.ShowStatus(
"Copy placed in clipboard.");
982 TaskCompletionSource<DataForm> Request =
new TaskCompletionSource<DataForm>();
990 Request.TrySetResult(e.
Form);
993 Request.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get node information."));
999 ParametersResult,
null,
null);
1001 DataForm Form = await Request.Task;
1003 sb.Append(
"<createNewNode xmlns='");
1005 sb.Append(
"' type='");
1008 if (!(Parent is
null))
1010 sb.Append(
"' id='");
1013 if (!
string.IsNullOrEmpty(Parent.
SourceId))
1015 sb.Append(
"' src='");
1019 if (!
string.IsNullOrEmpty(Parent.
Partition))
1021 sb.Append(
"' pt='");
1030 TaskCompletionSource<NodeInformation[]> NodesInformation =
new TaskCompletionSource<NodeInformation[]>();
1035 NodesInformation.TrySetResult(e.NodesInformation);
1037 NodesInformation.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get information about children."));
1039 return Task.CompletedTask;
1045 if (!(Children is
null))
1052 sb.Append(
"</createNewNode>");
1058 public override bool CanPaste
1062 string FullJid = this.Concentrator?.FullJid;
1063 if (
string.IsNullOrEmpty(FullJid))
1073 if (!System.Windows.Clipboard.ContainsText())
1076 string s = System.Windows.Clipboard.GetText();
1082 XmlDocument Doc =
new XmlDocument();
1086 !(Doc.DocumentElement is
null) &&
1087 Doc.DocumentElement.LocalName ==
"createNewNode" &&
1106 string FullJid = this.Concentrator?.FullJid;
1107 if (
string.IsNullOrEmpty(FullJid))
1117 if (!System.Windows.Clipboard.ContainsText())
1120 string s = System.Windows.Clipboard.GetText();
1121 if (
string.IsNullOrEmpty(s))
1124 XmlDocument Doc =
new XmlDocument();
1127 Mouse.OverrideCursor = Cursors.Wait;
1131 catch (XmlException ex)
1137 catch (Exception ex)
1147 MainWindow.ShowStatus(
"Contents of clipboard pasted to node.");
1152 Node Parent, XmlElement Xml)
1155 Xml.LocalName !=
"createNewNode" ||
1158 throw new Exception(
"Clipboard does not contain node information.");
1162 if (
string.IsNullOrEmpty(NodeType))
1163 throw new Exception(
"Node type missing.");
1166 LinkedList<XmlElement> ChildElements =
null;
1168 foreach (XmlNode N
in Xml.ChildNodes)
1170 if (!(N is XmlElement E))
1173 switch (E.LocalName)
1176 if (ImportForm is
null)
1179 throw new Exception(
"Multiple form elements in XML.");
1182 case "createNewNode":
1183 if (ChildElements is
null)
1184 ChildElements =
new LinkedList<XmlElement>();
1186 ChildElements.AddLast(E);
1190 throw new Exception(
"Unrecognized XML element: " + E.LocalName);
1194 if (ImportForm is
null)
1195 throw new Exception(
"Parameter form element missing from XML.");
1197 MainWindow.ShowStatus(
"Adding " + NodeType +
" to " + Parent.
NodeId +
"...");
1199 TaskCompletionSource<Node> Request =
new TaskCompletionSource<Node>();
1209 Dictionary<string, bool> VariablesProcessed = new Dictionary<string, bool>();
1211 foreach (Networking.XMPP.DataForms.Field Field in e.Form.Fields)
1213 VariablesProcessed[Field.Var] = true;
1215 Networking.XMPP.DataForms.Field InputField = ImportForm[Field.Var];
1219 if (InputField is null)
1221 Request.TrySetException(new Exception(
"Unable to add node of type " +
1222 NodeType +
" to node " + Parent.NodeId +
". Required field " + Field.Var +
1223 " did not have a value in the node being pasted from the clipboard. " +
1224 "Error reported: " + Field.Error));
1227 else if (Field.Var ==
"NodeId")
1229 if (IdCounter++ == 0)
1230 await Field.SetValue(InputField.ValueString);
1232 await Field.SetValue(InputField.ValueString +
" (" + IdCounter.ToString() +
")");
1234 else if (IdCounter > 1)
1236 Request.TrySetException(new Exception(
"Unable to add node of type " +
1237 NodeType +
" to node " + Parent.NodeId +
". Value in clipboard for field " +
1238 Field.Var +
" was not acceptable. Error reported: " + Field.Error));
1242 await Field.SetValue(InputField.ValueStrings);
1244 else if (!(InputField is null))
1245 await Field.SetValue(InputField.ValueStrings);
1248 List<Networking.XMPP.DataForms.Field> ExtendedFields =
null;
1250 foreach (Networking.XMPP.DataForms.Field
Field in ImportForm.
Fields)
1252 if (VariablesProcessed.ContainsKey(Field.Var))
1255 VariablesProcessed[Field.Var] = true;
1257 if (ExtendedFields is null)
1259 ExtendedFields = new List<Networking.XMPP.DataForms.Field>();
1260 ExtendedFields.AddRange(e.Form.Fields);
1263 ExtendedFields.Add(
Field);
1266 if (!(ExtendedFields is
null))
1273 Request.TrySetException(e.
StanzaError ??
new Exception(
"Unable to add a node of type " +
1274 NodeType +
" to node " + Parent.
NodeId +
"."));
1277 catch (Exception ex)
1279 Request.TrySetException(ex);
1286 Node NewNode =
new Node(Parent, e.NodeInformation);
1287 Parent.
Add(NewNode);
1288 Request.TrySetResult(NewNode);
1290 else if (!
string.IsNullOrEmpty(e.
From))
1293 return Task.CompletedTask;
1296 Node CreatedNode = await Request.Task;
1298 if (!(ChildElements is
null))
1300 foreach (XmlElement Child
in ChildElements)
Interaction logic for QueryResultView.xaml
Interaction logic for ParameterDialog.xaml
bool Empty
If the dialog is empty.
static async Task< ParameterDialog > CreateAsync(DataForm Form)
Interaction logic for ParameterDialog.xaml
Interaction logic for xaml
Represents a data source in a concentrator.
Represents a node in a concentrator.
bool IsOnline
If the concentrator hosting the node is online.
override string Header
Tree Node header text.
override bool CanDelete
If the node can be deleted.
override bool CanAddChildren
If children can be added to the node.
override bool CanReadSensorData
If it's possible to read sensor data from the node.
override ImageSource ImageResource
Image resource for the node.
XmppConcentrator Concentrator
Reference to the concentrator node.
override bool CanEdit
If the node can be edited.
override void Add()
Is called when the user wants to add a node to the current node.
override bool CanSubscribeToSensorData
If it's possible to subscribe to sensor data from the node.
void AddContexMenuItems(TreeNode Node, ref string CurrentGroup, ContextMenu Menu)
Adds context sensitive menu items to a context menu.
override async void Copy()
Is called when the user wants to copy the node to the clipboard.
override void AddSniffer(ISniffer Sniffer)
Adds a sniffer to the node.
override string TypeName
Node Type Name.
override async Task GetConfigurationForm(EventHandlerAsync< DataFormEventArgs > Callback, object State)
Gets the configuration form for the node.
override void LoadChildren()
Method is called to make sure children are loaded.
DataSource DataSource
Reference to the data source node.
override async Task< SensorDataClientRequest > StartSensorDataMomentaryReadout()
Starts readout of momentary sensor data values.
override async Task< SensorDataSubscriptionRequest > SubscribeSensorDataMomentaryReadout(FieldSubscriptionRule[] Rules)
Starts subscription of momentary sensor data values.
override void Write(XmlWriter Output)
Saves the object to a file.
override void Edit()
Is called when the user wants to edit a node.
override void Search()
Performs a search on the node.
override Task< SensorDataClientRequest > StartSensorDataFullReadout()
Starts readout of all sensor data values.
override void UnloadChildren()
Method is called to notify children can be unloaded.
override void SelectionChanged()
Method called when selection has been changed.
override async void Paste()
Is called when the user wants to paste data from the clipboard to the node.
Node(TreeNode Parent, NodeInformation NodeInfo)
Represents a node in a concentrator.
string Partition
Partition ID
ConcentratorClient ConcentratorClient
Reference to the concentrator client
override string Key
Key in parent child collection.
override bool CanRecycle
If the node can be recycled.
override string ToolTip
Tool Tip for node.
override async Task Delete(TreeNode Parent, EventHandler OnDeleted)
Method called when a node is to be deleted.
override async Task< bool > RemoveSniffer(ISniffer Sniffer)
Removes a sniffer from the node.
override bool CanConfigure
If it's possible to configure control parameters on the node.
Represents an XMPP concentrator.
Represents a data source in a concentrator.
Abstract base class for tree nodes in the connection view.
virtual DisplayableParameters DisplayableParameters
Gets available displayable parameters.
TreeNode Parent
Parent node. May be null if a root node.
virtual void OnUpdated()
Raises the Updated event.
bool IsExpanded
If the node is expanded.
Class representing a normal XMPP account.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string Encode(string s)
Encodes a string for use in XML.
static XmlException AnnotateException(XmlException ex)
Creates a new XML Exception object, with reference to the source XML file, for information.
static bool IsValidXml(string Xml)
Checks if a string is valid XML
static string PrettyXml(string Xml)
Reformats XML to make it easier to read.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Implements an XMPP concentrator client interface.
Task GetNodeParametersForEdit(string To, IThingReference Node, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< DataFormEventArgs > FormCallback, EventHandlerAsync< NodeInformationEventArgs > NodeCallback, object State)
Gets the set of parameters for the purpose of editing a node.
Task GetChildNodes(string To, IThingReference Node, bool Parameters, bool Messages, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< NodesInformationEventArgs > Callback, object State)
Gets information about all child nodes of a node in a data source.
Task GetAddableNodeTypes(string To, IThingReference Node, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< LocalizedStringsResponseEventArgs > Callback, object State)
Gets a list of what type of nodes can be added to a given node.
Task< bool > UnregisterSniffer(string To, IThingReference Node, string SnifferId, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Registers a new sniffer on a node.
Task DestroyNode(string To, IThingReference Node, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Destroys a node.
Task GetQueryParameters(string To, IThingReference Node, string Command, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< DataFormEventArgs > FormCallback, EventHandlerAsync< NodeQueryResponseEventArgs > QueryCallback, object State)
Gets the set of parameters for a parametrized query.
Task RegisterSniffer(string To, IThingReference Node, DateTime Expires, ISniffer Sniffer, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< SnifferRegistrationEventArgs > Callback, object State)
Registers a new sniffer on a node.
Task GetNodeCommands(string To, IThingReference Node, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< CommandsEventArgs > Callback, object State)
Gets available commands for a node.
Task GetCommandParameters(string To, IThingReference Node, string Command, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< DataFormEventArgs > FormCallback, EventHandlerAsync< NodeCommandResponseEventArgs > CommandCallback, object State)
Gets the set of parameters for a parametrized command.
Task ExecuteCommand(string To, IThingReference Node, string Command, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< NodeCommandResponseEventArgs > Callback, object State)
Executes a node command.
Task GetParametersForNewNode(string To, IThingReference Node, string NodeType, string Language, string ServiceToken, string DeviceToken, string UserToken, EventHandlerAsync< DataFormEventArgs > FormCallback, EventHandlerAsync< NodeInformationEventArgs > NodeCallback, object State)
Gets a set of parameters for the creation of a new node.
Implements an XMPP concentrator server interface.
const string NamespaceConcentratorCurrent
Neuro-Foundation v1 namespace
Information about a command on a node.
Implements an XMPP control client interface.
Task GetForm(string To, string Language, params ThingReference[] Nodes)
Gets a control form.
Event arguments for responses to IQ queries.
string From
From address attribute
bool Ok
If the response is an OK result response (true), or an error response (false).
XmppException StanzaError
Any stanza error returned.
string ErrorText
Any error specific text.
string LastPresenceFullJid
Full JID of last resource sending online presence.
Maintains the status of a field subscription rule.
Implements an XMPP sensor client interface.
Task< SensorDataClientRequest > RequestReadout(string Destination, FieldType Types)
Requests a sensor data readout.
Task< SensorDataSubscriptionRequest > Subscribe(string Destination, FieldType Types, FieldSubscriptionRule[] Fields, bool ImmediateReadout)
Subscribes to sensor data readout.
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
XmppState State
Current state of connection.
string Language
Language of the client in the XMPP network.
XmppClient Client
XMPP Client.
Contains a reference to a thing
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
XmppState
State of XMPP connection.
FieldType
Field Type flags
Represents a duration value, as defined by the xsd:duration data type: http://www....
static Duration FromMinutes(int Minutes)
Creates a Duration object from a given number of minutes.
static Duration FromSeconds(int Seconds)
Creates a Duration object from a given number of seconds.