/// <summary> /// Event arguments for <see cref="ProvisioningServer.CanRead"/> callbacks. /// </summary> /// <param name="Jid">Jid of request</param> /// <param name="Result">If readout is allowed or not or not.</param> /// <param name="Request">Allowed readout request parameters, possibly reduced compared to the original readout.</param> /// <param name="State">State object passed to the request.</param> public CanReadEventArgs(string Jid, bool Result, ReadoutRequest Request, object State) : base(Jid) { this.result = Result; this.request = Request; this.state = State; }
private void GetForm(XmppClient Client, XmlElement Element, IqType IqType, string From, string To, string Id) { string LanguageCode = XmlUtilities.GetAttribute(Element, "xml:lang", string.Empty); if (this.provisioning == null) { this.RequestRejected(From, Id, "Control rejected. No provisioning server found.", "cancel", "forbidden", "urn:ietf:params:xml:ns:xmpp-stanzas", string.Empty); } else { string ServiceToken = XmlUtilities.GetAttribute(Element, "serviceToken", string.Empty); string DeviceToken = XmlUtilities.GetAttribute(Element, "deviceToken", string.Empty); string UserToken = XmlUtilities.GetAttribute(Element, "userToken", string.Empty); List <NodeReference> Nodes; List <string> Parameters; ReadoutRequest.ParseNodesAndFieldNames(Element, out Nodes, out Parameters); Parameters = new List <string> (); Parameters.AddRange(this.parameterByName.Keys); this.provisioning.CanControl(From, this.CanControlGetFormResponse, new object[] { LanguageCode, From, Id }, ServiceToken, DeviceToken, UserToken, Parameters.ToArray(), Nodes == null ? (NodeReference[])null : Nodes.ToArray()); } }
public Job(ReadoutRequest Request, int SeqNr, DateTime When, string From, XmppSensorServer Sensor) { this.Request = Request; this.SeqNr = SeqNr; this.When = When; this.From = From; this.Sensor = Sensor; }
private void SendFields(int SeqNr, string From, ReadoutRequest Request) { try { StringBuilder sb = new StringBuilder(); SensorDataXmlExport Export = new SensorDataXmlExport(sb, false, true); string Xml100; PartitionedExport Partitioner = new PartitionedExport(sb, Export, 5000, (Partition, State) => { Xml100 = Partition.Substring(0, System.Math.Min(100, Partition.Length)); if (Xml100.Contains("<fields xmlns=\"urn:xmpp:iot:sensordata\"")) { Partition = Xml100.Replace("<fields xmlns=\"urn:xmpp:iot:sensordata\"", "<fields xmlns=\"urn:xmpp:iot:sensordata\" seqnr=\"" + SeqNr.ToString() + "\"") + Partition.Substring(Xml100.Length); } this.client.SendMessage(From, string.Empty, MessageType.Normal, Partition); }, null); this.DoReadout(Request, Partitioner); string Xml = sb.ToString(); Xml100 = Xml.Substring(0, System.Math.Min(100, Xml.Length)); if (Xml100.Contains("<fields xmlns=\"urn:xmpp:iot:sensordata\"")) { Xml = Xml100.Replace("<fields xmlns=\"urn:xmpp:iot:sensordata\"", "<fields xmlns=\"urn:xmpp:iot:sensordata\" done=\"true\" seqnr=\"" + SeqNr.ToString() + "\"") + Xml.Substring(Xml100.Length); this.client.SendMessage(From, string.Empty, MessageType.Normal, Xml); } else { this.client.SendMessage(From, string.Empty, MessageType.Normal, Xml); this.Done(SeqNr, From); } } catch (Exception ex2) { StringBuilder sb = new StringBuilder(); XmlWriter w = XmlWriter.Create(sb, XmlUtilities.GetXmlWriterSettings(false, true, true)); w.WriteStartElement("failure", "urn:xmpp:iot:sensordata"); w.WriteAttributeString("seqnr", SeqNr.ToString()); w.WriteAttributeString("done", "true"); w.WriteStartElement("error"); w.WriteValue(ex2.Message); w.WriteEndElement(); w.WriteEndElement(); w.Flush(); string Xml = sb.ToString(); this.client.SendMessage(From, string.Empty, MessageType.Normal, Xml); } }
/// <summary> /// Performs a readout. /// </summary> /// <param name="Request">Readout request object, specifying what to read.</param> /// <param name="Response">Sensor data will be output to this interface.</param> public void DoReadout(ReadoutRequest Request, ISensorDataExport Response) { ReadoutEventHandler h = this.OnReadout; if (h != null) { h(Request, Response); } else { Response.Start(); Response.End(); } }
private void Set(XmppClient Client, XmlElement Element, string From, string To) { string LanguageCode = XmlUtilities.GetAttribute(Element, "xml:lang", string.Empty); if (this.provisioning != null) { string ServiceToken = XmlUtilities.GetAttribute(Element, "serviceToken", string.Empty); string DeviceToken = XmlUtilities.GetAttribute(Element, "deviceToken", string.Empty); string UserToken = XmlUtilities.GetAttribute(Element, "userToken", string.Empty); List <NodeReference> Nodes; List <string> Parameters; ReadoutRequest.ParseNodesAndFieldNames(Element, out Nodes, out Parameters); this.provisioning.CanControl(From, this.CanControlResponse, new object[] { LanguageCode, From, null, Element }, ServiceToken, DeviceToken, UserToken, Parameters == null ? (string[])null : Parameters.ToArray(), Nodes == null ? (NodeReference[])null : Nodes.ToArray()); } }
private static void ExportSensorData(ISensorDataExport Output, ReadoutRequest Request) { Output.Start(); lock (synchObject) { Output.StartNode("Sensor"); Export(Output, new Record[] { new Record(DateTime.Now, temperatureC, lightPercent, motionDetected) }, ReadoutType.MomentaryValues, Request); Export(Output, perSecond, ReadoutType.HistoricalValuesSecond, Request); Export(Output, perMinute, ReadoutType.HistoricalValuesMinute, Request); Export(Output, perHour, ReadoutType.HistoricalValuesHour, Request); Export(Output, perDay, ReadoutType.HistoricalValuesDay, Request); Export(Output, perMonth, ReadoutType.HistoricalValuesMonth, Request); Output.EndNode(); } Output.End(); }
private void Req(XmppClient Client, XmlElement Element, IqType IqType, string From, string To, string Id) { ReadoutRequest Request = new ReadoutRequest(Element); int seqnr = XmlUtilities.GetAttribute(Element, "seqnr", 0); DateTime When = XmlUtilities.GetAttribute(Element, "when", DateTime.MinValue); string LanguageCode = XmlUtilities.GetAttribute(Element, "xml:lang", string.Empty); if (this.provisioning == null) { this.RequestRejected(seqnr, From, Id, "Readout rejected. No provisioning server found.", "cancel", "forbidden", "urn:ietf:params:xml:ns:xmpp-stanzas"); } else { this.provisioning.CanRead(Request, From, this.ReqCanReadResponse, new object[] { seqnr, When, LanguageCode, From, Id }); } }
private static void ExportSensorData(ISensorDataExport Output, ReadoutRequest Request) { DateTime Now = DateTime.Now; string s; int i; Output.Start(); Output.StartNode("Actuator"); Output.StartTimestamp(Now); if ((Request.Types & ReadoutType.MomentaryValues) != 0 && Request.ReportTimestamp(Now)) { if (Request.ReportField("Digital Output Count")) { Output.ExportField("Digital Output Count", 8, ReadoutType.StatusValues); } for (i = 0; i < 8; i++) { s = "Digital Output " + (i + 1).ToString(); if (Request.ReportField(s)) { Output.ExportField(s, digitalOutputs [i].Value); } } if (Request.ReportField("State")) { Output.ExportField("State", alarmThread != null); } } Output.EndTimestamp(); Output.EndNode(); Output.End(); }
private void SubscribeCanReadResponse(CanReadEventArgs e) { object[] P = (object[])e.State; int seqnr = (int)P [0]; Duration MaxAge = (Duration)P [1]; Duration MinInterval = (Duration)P [2]; Duration MaxInterval = (Duration)P [3]; ReadoutRequest Request = (ReadoutRequest)P [4]; List <Condition> Conditions = (List <Condition>)P [5]; bool Req = (bool)P [6]; string LanguageCode = (string)P [7]; string From = (string)P [8]; string Id = (string)P [9]; bool Respond = (bool)P [10]; bool Trigger = false; double Current; if (e.Result) { if (Respond) { this.Accepted(seqnr, From, Id); } List <Condition> Conditions2 = new List <Condition> (); if (Req) { Trigger = true; } lock (this.synchObj) { foreach (Condition Condition in Conditions) { if (e.Request.ReportField(Condition.FieldName)) { Conditions2.Add(Condition); if (this.currentValues.TryGetValue(Condition.FieldName, out Current) && Condition.Trigger(Condition.FieldName, Current, false)) { Trigger = true; } } } } Subscription Subscription = new Subscription(); Subscription.Key = XmppClient.StripResource(From).ToLower(); Subscription.SeqNr = seqnr; Subscription.MaxAge = MaxAge; Subscription.MinInterval = MinInterval; Subscription.MaxInterval = MaxInterval; Subscription.OrgRequest = Request; Subscription.Request = e.Request; Subscription.OrgConditions = Conditions; Subscription.Conditions = Conditions2.ToArray(); Subscription.LanguageCode = LanguageCode; Subscription.From = From; Subscription.Id = Id; this.AddSubscription(Subscription); } else { if (Respond) { this.RequestRejected(seqnr, From, Id, "Event subscription rejected by provisioning server.", "cancel", "forbidden", "urn:ietf:params:xml:ns:xmpp-stanzas"); } else { Unregister(XmppClient.StripResource(From).ToLower(), seqnr); } } if (Trigger) { DateTime Now = DateTime.Now; Job Job = new Job(e.Request, seqnr, Now, From, this); this.Register(From, seqnr, Job); Job.Start(); } this.ReevaluateNext(); }
private void Subscribe(XmppClient Client, XmlElement Element, IqType IqType, string From, string To, string Id) { ReadoutRequest Request = new ReadoutRequest(Element); int seqnr = XmlUtilities.GetAttribute(Element, "seqnr", 0); Duration MaxAge = XmlUtilities.GetAttribute(Element, "maxAge", Duration.Zero); Duration MinInterval = XmlUtilities.GetAttribute(Element, "minInterval", Duration.Zero); Duration MaxInterval = XmlUtilities.GetAttribute(Element, "maxInterval", Duration.Zero); bool Req = XmlUtilities.GetAttribute(Element, "req", false); string LanguageCode = XmlUtilities.GetAttribute(Element, "xml:lang", string.Empty); List <Condition> Conditions = null; Condition Condition; XmlElement E; double d; foreach (XmlNode N in Element.ChildNodes) { if (N.LocalName == "field" && (E = N as XmlElement) != null) { if (E.HasAttribute("changedBy")) { Condition = new Condition(); Condition.ChangedUp = XmlUtilities.GetAttribute(E, "changedBy", 0.0); Condition.ChangedDown = Condition.ChangedUp; } else if (E.HasAttribute("changedUp")) { Condition = new Condition(); Condition.ChangedUp = XmlUtilities.GetAttribute(E, "changedUp", 0.0); if (E.HasAttribute("changedDown")) { Condition.ChangedDown = XmlUtilities.GetAttribute(E, "changedDown", 0.0); } } else if (E.HasAttribute("changedDown")) { Condition = new Condition(); Condition.ChangedDown = XmlUtilities.GetAttribute(E, "changedDown", 0.0); } else { continue; } Condition.FieldName = XmlUtilities.GetAttribute(E, "name", string.Empty); if (E.HasAttribute("currentValue")) { Condition.CurrentValue = XmlUtilities.GetAttribute(E, "currentValue", 0.0); } else { lock (this.synchObj) { if (this.currentValues.TryGetValue(Condition.FieldName, out d)) { Condition.CurrentValue = d; } } } if (Conditions == null) { Conditions = new List <Condition> (); } Conditions.Add(Condition); } } if (this.provisioning == null) { this.RequestRejected(seqnr, From, Id, "Event subscription rejected. No provisioning server found.", "cancel", "forbidden", "urn:ietf:params:xml:ns:xmpp-stanzas"); } else { this.provisioning.CanRead(Request, From, this.SubscribeCanReadResponse, new object[] { seqnr, MaxAge, MinInterval, MaxInterval, Request, Conditions, Req, LanguageCode, From, Id, true }); } }
private static void HttpGetSensorData(HttpServerResponse resp, string ContentType, ISensorDataExport Output, ReadoutRequest Request) { resp.ContentType = ContentType; resp.Encoding = System.Text.Encoding.UTF8; resp.Expires = DateTime.Now; resp.ReturnCode = HttpStatusCode.Successful_OK; ExportSensorData(Output, Request); }
/// <summary> /// Determines whether a readout can be performed, partially performed or be rejected. /// </summary> /// <param name="Request">Readout request.</param> /// <param name="From">JID from which the request was made.</param> /// <param name="Callback">Callback method to call, when the response is available.</param> /// <param name="State">State object to pass on to the response callback.</param> public void CanRead(ReadoutRequest Request, string From, CanReadCallback Callback, object State) { string BareJid = XmppClient.StripResource(From); if (BareJid == this.address) { if (Callback != null) { CanReadEventArgs e = new CanReadEventArgs(BareJid, true, Request, State); try { Callback(e); } catch (Exception ex) { Log.Exception(ex); } } } else { StringBuilder sb = new StringBuilder(); XmlWriter w = XmlWriter.Create(sb, XmlUtilities.GetXmlWriterSettings(false, true, true)); w.WriteStartElement("canRead", "urn:xmpp:iot:provisioning"); w.WriteAttributeString("jid", BareJid); if (!string.IsNullOrEmpty(Request.ServiceToken)) { w.WriteAttributeString("serviceToken", Request.ServiceToken); this.UpdateTokenSource(Request.ServiceToken, From); } if (!string.IsNullOrEmpty(Request.DeviceToken)) { w.WriteAttributeString("deviceToken", Request.DeviceToken); this.UpdateTokenSource(Request.DeviceToken, From); } if (!string.IsNullOrEmpty(Request.UserToken)) { w.WriteAttributeString("userToken", Request.UserToken); this.UpdateTokenSource(Request.UserToken, From); } WriteReadoutTypes(w, Request.Types); WriteNodes(w, Request.Nodes); WriteFields(w, Request.GetFields()); w.WriteEndElement(); w.Flush(); string Xml = sb.ToString(); string Hash = this.CalcHash(Xml); StanzaError Error = null; XmlNodeList Response; if ((Response = this.GetCachedResponse(Hash)) != null) { this.CanReadResponse(this.client, string.Empty, Response, ref Error, new object[] { Callback, State, null, Request }); } else { this.client.IqGet(Xml, this.address, this.CanReadResponse, new object[] { Callback, State, Hash, Request }, "Can Read?"); } } }
private void OnMessage(XmppClient Client, XmppMessage Message) { if (Message.MessageType != MessageType.Chat) { return; } string s = Message.Body.Trim(); if (string.IsNullOrEmpty(s)) { return; } DateTime Now = DateTime.Now; DateTime Timeout = Now.AddMinutes(-15); LinkedList <Session> ToRemove = null; Session Session; string s2; int i; lock (this.sessionByJid) { foreach (KeyValuePair <DateTime, Session> P in this.sessionByLastAccess) { if (P.Key <= Timeout) { if (ToRemove == null) { ToRemove = new LinkedList <Session> (); } ToRemove.AddLast(P.Value); } else { break; } } if (ToRemove != null) { foreach (Session S in ToRemove) { this.sessionByJid.Remove(S.From); this.sessionByLastAccess.Remove(S.LastAccess); } } if (this.sessionByJid.TryGetValue(Message.From, out Session)) { this.sessionByLastAccess.Remove(Session.LastAccess); } else { Session = new Session(); Session.From = Message.From; this.sessionByJid [Session.From] = Session; } while (this.sessionByLastAccess.ContainsKey(Now)) { Now = Now.AddTicks(gen.Next(1, 10)); } Session.LastAccess = Now; this.sessionByLastAccess [Now] = Session; } switch (s) { case "#": this.SendMenu(Client, Message.From, true, string.Empty, Session); break; case "##": this.SendMenu(Client, Message.From, false, string.Empty, Session); break; case "?": if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.MomentaryValues, DateTime.MinValue, DateTime.MaxValue); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } break; case "??": if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.All, DateTime.MinValue, DateTime.MaxValue); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } break; case "html+": Session.Html = true; Client.SendMessage(Message.From, "HTML mode turned on.", MessageType.Chat); break; case "html-": Session.Html = false; Client.SendMessage(Message.From, "HTML mode turned off.", MessageType.Chat); break; case "=?": case "!?": if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so control through the chat interface is not allowed.", Session); } else if (this.control == null) { this.SendErrorMessage(Message.From, "No control interface provided.", Session); } else { this.provisioning.CanControl(Message.From, this.CanControlListParametersResponse, new object[] { Message.From, Session }, null, null, null, this.control.Parameters, null); } break; default: if (s.EndsWith("??")) { if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.All, DateTime.MinValue, DateTime.MaxValue, null, new string[] { s.Substring(0, s.Length - 2) }); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } } else if (s.EndsWith("?")) { if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so readout through the chat interface is not allowed.", Session); } else if (this.sensor == null) { this.SendErrorMessage(Message.From, "No sensor interface provided.", Session); } else { ReadoutRequest Request = new ReadoutRequest(ReadoutType.MomentaryValues, DateTime.MinValue, DateTime.MaxValue, null, new string[] { s.Substring(0, s.Length - 1) }); this.provisioning.CanRead(Request, Message.From, this.CanReadResponse, new object[] { Message.From, Session }); } } else if ((i = s.IndexOfAny(controlDelimiters)) > 0) { IControlParameter Parameter; if (this.provisioning == null) { this.SendErrorMessage(Message.From, "No provisioning server has been found, so control operations through the chat interface is not allowed.", Session); } else if (this.control == null) { this.SendErrorMessage(Message.From, "No control interface provided.", Session); } else if ((Parameter = this.control [s2 = s.Substring(0, i).Trim()]) == null) { this.SendErrorMessage(Message.From, "No control parameter named '" + s2 + "' found.", Session); } else { this.provisioning.CanControl(Message.From, this.CanControlParameterResponse, new object[] { Message.From, Session, Parameter, s2, s.Substring(i + 1).Trim() }, null, null, null, new string[] { s2 }, null); } } else { this.SendMenu(Client, Message.From, true, "Hello. Following is a list of commands you can use when chatting with me.\r\n\r\n", Session); } break; } }
private void CanControlResponse(XmppClient Client, string Type, XmlNodeList Response, ref StanzaError Error, object State) { object[] P = (object[])State; CanControlCallback Callback = (CanControlCallback)P [0]; object State2 = (object)P [1]; string Hash = (string)P [2]; string[] Parameters = (string[])P [3]; NodeReference[] NodeReferences = (NodeReference[])P [4]; bool CanControl = false; string Jid = string.Empty; XmlElement E; if (Error != null) { Error = null; } else if (Response != null) { if (Hash != null) { this.AddToCache(Hash, Response); } foreach (XmlNode N in Response) { if (N.LocalName == "canControlResponse" && (E = N as XmlElement) != null) { CanControl = XmlUtilities.GetAttribute(E, "result", false); List <NodeReference> Nodes; List <string> ParameterNames; ReadoutRequest.ParseNodesAndFieldNames(E, out Nodes, out ParameterNames); if (Nodes == null) { NodeReferences = null; } else { NodeReferences = Nodes.ToArray(); } if (ParameterNames == null) { Parameters = null; } else { Parameters = ParameterNames.ToArray(); } break; } } } CanControlEventArgs e = new CanControlEventArgs(Jid, CanControl, Parameters, NodeReferences, State2); if (Callback != null) { try { Callback(e); } catch (Exception ex) { Log.Exception(ex); } } }
private static void HttpGetSensorData(HttpServerResponse resp, HttpServerRequest req, string ContentType, ISensorDataExport ExportModule) { ReadoutRequest Request = new ReadoutRequest(req); HttpGetSensorData(resp, ContentType, ExportModule, Request); }
private static void HttpGetSensorData(HttpServerResponse resp, string ContentType, ISensorDataExport ExportModule, ReadoutRequest Request) { networkLed.High(); try { resp.ContentType = ContentType; resp.Encoding = System.Text.Encoding.UTF8; resp.Expires = DateTime.Now; resp.ReturnCode = HttpStatusCode.Successful_OK; ExportSensorData(ExportModule, Request); } finally { networkLed.Low(); } }
private static void HttpGetSensorData(HttpServerResponse resp, string ContentType, ISensorDataExport Output, ReadoutRequest Request) { DateTime Now = DateTime.Now; string s; int i; resp.ContentType = ContentType; resp.Encoding = System.Text.Encoding.UTF8; resp.Expires = DateTime.Now; resp.ReturnCode = HttpStatusCode.Successful_OK; Output.Start(); Output.StartNode("Actuator"); Output.StartTimestamp(Now); if ((Request.Types & ReadoutType.MomentaryValues) != 0 && Request.ReportTimestamp(Now)) { if (Request.ReportField("Digital Output Count")) { Output.ExportField("Digital Output Count", 8, ReadoutType.StatusValues); } for (i = 0; i < 8; i++) { s = "Digital Output " + (i + 1).ToString(); if (Request.ReportField(s)) { Output.ExportField(s, digitalOutputs [i].Value); } } if (Request.ReportField("State")) { Output.ExportField("State", alarmThread != null); } } Output.EndTimestamp(); Output.EndNode(); Output.End(); }
private static void Export(ISensorDataExport Output, IEnumerable <Record> History, ReadoutType Type, ReadoutRequest Request) { if ((Request.Types & Type) != 0) { foreach (Record Rec in History) { if (!Request.ReportTimestamp(Rec.Timestamp)) { continue; } Output.StartTimestamp(Rec.Timestamp); if (Request.ReportField("Temperature")) { Output.ExportField("Temperature", Rec.TemperatureC, 1, "C", Type); } if (Request.ReportField("Light")) { Output.ExportField("Light", Rec.LightPercent, 1, "%", Type); } if (Request.ReportField("Motion")) { Output.ExportField("Motion", Rec.Motion, Type); } Output.EndTimestamp(); } } }