public static void Main(string[] args) { try { Console.ForegroundColor = ConsoleColor.White; Console.Out.WriteLine("Welcome to the PC Sensor application."); Console.Out.WriteLine(new string('-', 79)); Console.Out.WriteLine("This application will publish performace couters as sensor values."); Console.Out.WriteLine("Values will be published over XMPP using the interface defined in the IEEE XMPP IoT extensions."); Log.Register(new ConsoleEventSink()); Log.RegisterExceptionToUnnest(typeof(System.Runtime.InteropServices.ExternalException)); Log.RegisterExceptionToUnnest(typeof(System.Security.Authentication.AuthenticationException)); xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config", Environment.MachineName, // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(Program).Assembly); using (XmppClient Client = xmppConfiguration.GetClient("en", typeof(Program).Assembly, false)) { Client.AllowRegistration(FormSignatureKey, FormSignatureSecret); if (xmppConfiguration.Sniffer) { Client.Add(new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces)); } if (!string.IsNullOrEmpty(xmppConfiguration.Events)) { Log.Register(new XmppEventSink("XMPP Event Sink", Client, xmppConfiguration.Events, false)); } if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(Client, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += (sender, e) => { ownerJid = e.JID; Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic)); }; thingRegistryClient.Disowned += (sender, e) => { Log.Informational("Thing has been disowned.", ownerJid); ownerJid = string.Empty; Register(); }; thingRegistryClient.Removed += (sender, e) => { Log.Informational("Thing has been removed from the public registry.", ownerJid); }; } ProvisioningClient ProvisioningClient = null; if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) { ProvisioningClient = new ProvisioningClient(Client, xmppConfiguration.Provisioning); } Timer ConnectionTimer = new Timer((P) => { if (Client.State == XmppState.Offline || Client.State == XmppState.Error || Client.State == XmppState.Authenticating) { try { Client.Reconnect(); } catch (Exception ex) { Log.Critical(ex); } } }, null, 60000, 60000); bool Connected = false; bool ImmediateReconnect; Client.OnStateChanged += (sender, NewState) => { switch (NewState) { case XmppState.Connected: Connected = true; if (!registered && thingRegistryClient != null) { Register(); } break; case XmppState.Offline: ImmediateReconnect = Connected; Connected = false; if (ImmediateReconnect) { Client.Reconnect(); } break; } }; Client.OnPresenceSubscribe += (sender, e) => { e.Accept(); // TODO: Provisioning RosterItem Item = Client.GetRosterItem(e.FromBareJID); if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From) { Client.RequestPresenceSubscription(e.FromBareJID); } Client.SetPresence(Availability.Chat); }; Client.OnPresenceUnsubscribe += (sender, e) => { e.Accept(); }; Client.OnRosterItemUpdated += (sender, e) => { if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe) { Client.RemoveRosterItem(e.BareJid); } }; SortedDictionary <string, string[]> CategoryIncluded = new SortedDictionary <string, string[]>(); List <string> Instances = new List <string>(); XmlDocument Doc = new XmlDocument(); Doc.Load("categories.xml"); XSL.Validate("categories.xml", Doc, "Categories", "http://waher.se/Schema/PerformanceCounterCategories.xsd", XSL.LoadSchema("Waher.Service.PcSensor.Schema.PerformanceCounterCategories.xsd")); foreach (XmlNode N in Doc.DocumentElement.ChildNodes) { if (N.LocalName == "Category") { XmlElement E = (XmlElement)N; string Name = XML.Attribute(E, "name"); bool Include = XML.Attribute(E, "include", false); if (Include) { Instances.Clear(); foreach (XmlNode N2 in N.ChildNodes) { if (N2.LocalName == "Instance") { E = (XmlElement)N2; Instances.Add(XML.Attribute(E, "name")); } } CategoryIncluded[Name] = Instances.ToArray(); } else { CategoryIncluded[Name] = null; } } } SensorServer SensorServer = new SensorServer(Client, ProvisioningClient, false); SensorServer.OnExecuteReadoutRequest += (Sender, Request) => { Log.Informational("Readout requested", string.Empty, Request.Actor); List <Field> Fields = new List <Field>(); DateTime Now = DateTime.Now; Fields.Add(new StringField(ThingReference.Empty, Now, "Machine Name", Environment.MachineName, FieldType.Identity, FieldQoS.AutomaticReadout)); Fields.Add(new StringField(ThingReference.Empty, Now, "OS Platform", Environment.OSVersion.Platform.ToString(), FieldType.Identity, FieldQoS.AutomaticReadout)); Fields.Add(new StringField(ThingReference.Empty, Now, "OS Service Pack", Environment.OSVersion.ServicePack, FieldType.Identity, FieldQoS.AutomaticReadout)); Fields.Add(new StringField(ThingReference.Empty, Now, "OS Version", Environment.OSVersion.VersionString, FieldType.Identity, FieldQoS.AutomaticReadout)); Fields.Add(new Int32Field(ThingReference.Empty, Now, "Processor Count", Environment.ProcessorCount, FieldType.Status, FieldQoS.AutomaticReadout)); string[] InstanceNames; string FieldName; string Unit; double Value; byte NrDec; bool Updated = false; foreach (PerformanceCounterCategory Category in PerformanceCounterCategory.GetCategories()) { FieldName = Category.CategoryName; lock (CategoryIncluded) { if (CategoryIncluded.TryGetValue(FieldName, out InstanceNames)) { if (InstanceNames == null) { continue; } } else { CategoryIncluded[FieldName] = null; Updated = true; continue; } } if (Category.CategoryType == PerformanceCounterCategoryType.MultiInstance) { foreach (string InstanceName in Category.GetInstanceNames()) { if (InstanceNames.Length > 0 && Array.IndexOf <string>(InstanceNames, InstanceName) < 0) { continue; } foreach (PerformanceCounter Counter in Category.GetCounters(InstanceName)) { FieldName = Category.CategoryName + ", " + InstanceName + ", " + Counter.CounterName; Value = Counter.NextValue(); GetUnitPrecision(ref FieldName, Value, out NrDec, out Unit); if (Fields.Count >= 100) { Request.ReportFields(false, Fields); Fields.Clear(); } Fields.Add(new QuantityField(ThingReference.Empty, Now, FieldName, Value, NrDec, Unit, FieldType.Momentary, FieldQoS.AutomaticReadout)); } } } else { foreach (PerformanceCounter Counter in Category.GetCounters()) { FieldName = Category.CategoryName + ", " + Counter.CounterName; Value = Counter.NextValue(); GetUnitPrecision(ref FieldName, Value, out NrDec, out Unit); if (Fields.Count >= 100) { Request.ReportFields(false, Fields); Fields.Clear(); } Fields.Add(new QuantityField(ThingReference.Empty, Now, FieldName, Value, NrDec, Unit, FieldType.Momentary, FieldQoS.AutomaticReadout)); } } } Request.ReportFields(true, Fields); if (Updated) { using (StreamWriter s = File.CreateText("categories.xml")) { using (XmlWriter w = XmlWriter.Create(s, XML.WriterSettings(true, false))) { w.WriteStartElement("Categories", "http://waher.se/Schema/PerformanceCounterCategories.xsd"); lock (CategoryIncluded) { foreach (KeyValuePair <string, string[]> P in CategoryIncluded) { w.WriteStartElement("Category"); w.WriteAttributeString("name", P.Key); w.WriteAttributeString("include", CommonTypes.Encode(P.Value != null)); if (P.Value != null) { foreach (string InstanceName in P.Value) { w.WriteStartElement("Instance"); w.WriteAttributeString("name", P.Key); w.WriteEndElement(); } } w.WriteEndElement(); } } w.WriteEndElement(); w.Flush(); } } } }; BobClient BobClient = new BobClient(Client, Path.Combine(Path.GetTempPath(), "BitsOfBinary")); ChatServer ChatServer = new ChatServer(Client, BobClient, SensorServer); Client.Connect(); while (true) { Thread.Sleep(1000); } } } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.Out.WriteLine(ex.Message); } finally { Log.Terminate(); } }
public static void Main(string[] args) { try { Console.ForegroundColor = ConsoleColor.White; Console.Out.WriteLine("Welcome to the Mock Temperature sensor application."); Console.Out.WriteLine(new string('-', 79)); Console.Out.WriteLine("This application will simulate an outside temperature sensor."); Console.Out.WriteLine("Values will be published over XMPP using the interface defined in the IEEE XMPP IoT extensions."); Console.Out.WriteLine("You can also chat with the sensor."); Log.Register(new ConsoleEventSink()); Log.RegisterExceptionToUnnest(typeof(System.Runtime.InteropServices.ExternalException)); Log.RegisterExceptionToUnnest(typeof(System.Security.Authentication.AuthenticationException)); xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config", Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(Program).Assembly); using (XmppClient Client = xmppConfiguration.GetClient("en", typeof(Program).Assembly, false)) { Client.AllowRegistration(FormSignatureKey, FormSignatureSecret); if (xmppConfiguration.Sniffer) { Client.Add(new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces)); } if (!string.IsNullOrEmpty(xmppConfiguration.Events)) { Log.Register(new XmppEventSink("XMPP Event Sink", Client, xmppConfiguration.Events, false)); } if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(Client, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += (sender, e) => { ownerJid = e.JID; Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic)); }; thingRegistryClient.Disowned += (sender, e) => { Log.Informational("Thing has been disowned.", ownerJid); ownerJid = string.Empty; Register(); }; thingRegistryClient.Removed += (sender, e) => { Log.Informational("Thing has been removed from the public registry.", ownerJid); }; } ProvisioningClient ProvisioningClient = null; if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) { ProvisioningClient = new ProvisioningClient(Client, xmppConfiguration.Provisioning); } Timer ConnectionTimer = new Timer((P) => { if (Client.State == XmppState.Offline || Client.State == XmppState.Error || Client.State == XmppState.Authenticating) { try { Client.Reconnect(); } catch (Exception ex) { Log.Critical(ex); } } }, null, 60000, 60000); bool Connected = false; bool ImmediateReconnect; Client.OnStateChanged += (sender, NewState) => { switch (NewState) { case XmppState.Connected: Connected = true; if (!registered && thingRegistryClient != null) { Register(); } break; case XmppState.Offline: ImmediateReconnect = Connected; Connected = false; if (ImmediateReconnect) { Client.Reconnect(); } break; } }; Client.OnPresenceSubscribe += (sender, e) => { e.Accept(); // TODO: Provisioning RosterItem Item = Client.GetRosterItem(e.FromBareJID); if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From) { Client.RequestPresenceSubscription(e.FromBareJID); } Client.SetPresence(Availability.Chat); }; Client.OnPresenceUnsubscribe += (sender, e) => { e.Accept(); }; Client.OnRosterItemUpdated += (sender, e) => { if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe) { Client.RemoveRosterItem(e.BareJid); } }; LinkedList <DayHistoryRecord> DayHistoricalValues = new LinkedList <DayHistoryRecord>(); LinkedList <MinuteHistoryRecord> MinuteHistoricalValues = new LinkedList <MinuteHistoryRecord>(); DateTime SampleTime = DateTime.Now; DateTime PeriodStart = SampleTime.Date; DateTime Now; DateTime MinTime = SampleTime; DateTime MaxTime = SampleTime; double CurrentTemperature = ReadTemp(); double MinTemp = CurrentTemperature; double MaxTemp = CurrentTemperature; double SumTemp = CurrentTemperature; int NrTemp = 1; int NrDayRecords = 0; int NrMinuteRecords = 0; object SampleSynch = new object(); SensorServer SensorServer = new SensorServer(Client, ProvisioningClient, true); SensorServer.OnExecuteReadoutRequest += (Sender, Request) => { Log.Informational("Readout requested", string.Empty, Request.Actor); List <Field> Fields = new List <Field>(); bool IncludeTemp = Request.IsIncluded("Temperature"); bool IncludeTempMin = Request.IsIncluded("Temperature, Min"); bool IncludeTempMax = Request.IsIncluded("Temperature, Max"); bool IncludeTempAvg = Request.IsIncluded("Temperature, Average"); bool IncludePeak = Request.IsIncluded(FieldType.Peak); bool IncludeComputed = Request.IsIncluded(FieldType.Computed); lock (SampleSynch) { if (IncludeTemp && Request.IsIncluded(FieldType.Momentary)) { Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature", CurrentTemperature, 1, "°C", FieldType.Momentary, FieldQoS.AutomaticReadout)); } if (IncludePeak) { if (IncludeTempMin) { Fields.Add(new QuantityField(ThingReference.Empty, MinTime, "Temperature, Min", MinTemp, 1, "°C", FieldType.Peak, FieldQoS.AutomaticReadout)); } if (IncludeTempMax) { Fields.Add(new QuantityField(ThingReference.Empty, MaxTime, "Temperature, Max", MaxTemp, 1, "°C", FieldType.Peak, FieldQoS.AutomaticReadout)); } } if (IncludeTempAvg && IncludeComputed) { Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature, Average", SumTemp / NrTemp, 2, "°C", FieldType.Computed, FieldQoS.AutomaticReadout)); } if (Request.IsIncluded(FieldType.Historical)) { foreach (DayHistoryRecord Rec in DayHistoricalValues) { if (!Request.IsIncluded(Rec.PeriodStart)) { continue; } if (Fields.Count >= 100) { Request.ReportFields(false, Fields); Fields.Clear(); } if (IncludePeak) { if (IncludeTempMin) { Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Min", Rec.MinTemperature, 1, "°C", FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout)); } if (IncludeTempMax) { Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Max", Rec.MaxTemperature, 1, "°C", FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout)); } } if (IncludeTempAvg && IncludeComputed) { Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Average", Rec.AverageTemperature, 1, "°C", FieldType.Computed | FieldType.Historical, FieldQoS.AutomaticReadout)); } } foreach (MinuteHistoryRecord Rec in MinuteHistoricalValues) { if (!Request.IsIncluded(Rec.Timestamp)) { continue; } if (IncludeTemp) { if (Fields.Count >= 100) { Request.ReportFields(false, Fields); Fields.Clear(); } Fields.Add(new QuantityField(ThingReference.Empty, Rec.Timestamp, "Temperature", Rec.Temperature, 1, "°C", FieldType.Historical, FieldQoS.AutomaticReadout)); } } } } Request.ReportFields(true, Fields); }; Timer SampleTimer = new Timer((P) => { lock (SampleSynch) { Now = DateTime.Now; if (Now.Date != PeriodStart.Date) { DayHistoryRecord Rec = new DayHistoryRecord(PeriodStart.Date, PeriodStart.Date.AddDays(1).AddMilliseconds(-1), MinTemp, MaxTemp, SumTemp / NrTemp); DayHistoricalValues.AddFirst(Rec); if (NrDayRecords < MaxRecordsPerPeriod) { NrDayRecords++; } else { DayHistoricalValues.RemoveLast(); } // TODO: Persistence PeriodStart = Now.Date; SumTemp = 0; NrTemp = 0; } CurrentTemperature = ReadTemp(); if (Now.Minute != SampleTime.Minute) { MinuteHistoryRecord Rec = new MinuteHistoryRecord(Now, CurrentTemperature); MinuteHistoricalValues.AddFirst(Rec); if (NrMinuteRecords < MaxRecordsPerPeriod) { NrMinuteRecords++; } else { MinuteHistoricalValues.RemoveLast(); } // TODO: Persistence } SampleTime = Now; if (CurrentTemperature < MinTemp) { MinTemp = CurrentTemperature; MinTime = SampleTime; } if (CurrentTemperature > MaxTemp) { MaxTemp = CurrentTemperature; MaxTime = SampleTime; } SumTemp += CurrentTemperature; NrTemp++; } if (SensorServer.HasSubscriptions(ThingReference.Empty)) { SensorServer.NewMomentaryValues(new QuantityField(ThingReference.Empty, SampleTime, "Temperature", CurrentTemperature, 1, "°C", FieldType.Momentary, FieldQoS.AutomaticReadout)); } }, null, 1000 - PeriodStart.Millisecond, 1000); BobClient BobClient = new BobClient(Client, Path.Combine(Path.GetTempPath(), "BitsOfBinary")); ChatServer ChatServer = new ChatServer(Client, BobClient, SensorServer); InteroperabilityServer InteroperabilityServer = new InteroperabilityServer(Client); InteroperabilityServer.OnGetInterfaces += (sender, e) => { e.Add("XMPP.IoT.Sensor.Temperature", "XMPP.IoT.Sensor.Temperature.History", "XMPP.IoT.Sensor.Temperature.Average", "XMPP.IoT.Sensor.Temperature.Average.History", "XMPP.IoT.Sensor.Temperature.Min", "XMPP.IoT.Sensor.Temperature.Min.History", "XMPP.IoT.Sensor.Temperature.Max", "XMPP.IoT.Sensor.Temperature.Max.History"); }; Client.Connect(); while (true) { Thread.Sleep(1000); } } } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.Out.WriteLine(ex.Message); } finally { Log.Terminate(); } }
private async void StartActuator() { try { Log.Informational("Starting application."); SimpleXmppConfiguration xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config", Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(App).GetTypeInfo().Assembly); Log.Informational("Connecting to XMPP server."); xmppClient = xmppConfiguration.GetClient("en", typeof(App).GetTypeInfo().Assembly, false); xmppClient.AllowRegistration(FormSignatureKey, FormSignatureSecret); if (xmppConfiguration.Sniffer && MainPage.Sniffer != null) { xmppClient.Add(MainPage.Sniffer); } if (!string.IsNullOrEmpty(xmppConfiguration.Events)) { Log.Register(new XmppEventSink("XMPP Event Sink", xmppClient, xmppConfiguration.Events, false)); } if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(xmppClient, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += (sender, e) => { ownerJid = e.JID; Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic)); this.RaiseOwnershipChanged(); }; thingRegistryClient.Disowned += (sender, e) => { Log.Informational("Thing has been disowned.", ownerJid); ownerJid = string.Empty; this.Register(); // Will call this.OwnershipChanged() after successful registration. }; thingRegistryClient.Removed += (sender, e) => { Log.Informational("Thing has been removed from the public registry.", ownerJid); }; } if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) { provisioningClient = new ProvisioningClient(xmppClient, xmppConfiguration.Provisioning); } Timer ConnectionTimer = new Timer((P) => { if (xmppClient.State == XmppState.Offline || xmppClient.State == XmppState.Error || xmppClient.State == XmppState.Authenticating) { try { Log.Informational("Reconnecting."); xmppClient.Reconnect(); } catch (Exception ex) { Log.Critical(ex); } } }, null, 60000, 60000); xmppClient.OnStateChanged += (sender, NewState) => { Log.Informational(NewState.ToString()); switch (NewState) { case XmppState.Connected: connected = true; if (!registered && thingRegistryClient != null) { Register(); } break; case XmppState.Offline: immediateReconnect = connected; connected = false; if (immediateReconnect) { xmppClient.Reconnect(); } break; } }; xmppClient.OnPresenceSubscribe += (sender, e) => { Log.Informational("Subscription request received from " + e.From + "."); e.Accept(); // TODO: Provisioning RosterItem Item = xmppClient.GetRosterItem(e.FromBareJID); if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From) { xmppClient.RequestPresenceSubscription(e.FromBareJID); } xmppClient.SetPresence(Availability.Chat); }; xmppClient.OnPresenceUnsubscribe += (sender, e) => { Log.Informational("Unsubscription request received from " + e.From + "."); e.Accept(); }; xmppClient.OnRosterItemUpdated += (sender, e) => { if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe) { xmppClient.RemoveRosterItem(e.BareJid); } }; bool SwitchOn = false; sensorServer = new SensorServer(xmppClient, provisioningClient, false); sensorServer.OnExecuteReadoutRequest += (Sender, Request) => { DateTime Now = DateTime.Now; Log.Informational("Readout requested", string.Empty, Request.Actor); Request.ReportFields(true, new BooleanField(ThingReference.Empty, Now, "Lamp", SwitchOn, FieldType.Momentary, FieldQoS.AutomaticReadout)); }; controlServer = new ControlServer(xmppClient, new BooleanControlParameter("Lamp", "Control", "Lamp switch on.", "If checked, lamp is turned on.", (Node) => SwitchOn, (Node, Value) => { SwitchOn = Value; Log.Informational("Lamp turned " + (SwitchOn ? "ON" : "OFF")); UpdateMainWindow(SwitchOn); })); this.bobClient = new BobClient(this.xmppClient, Path.Combine(Path.GetTempPath(), "BitsOfBinary")); this.chatServer = new ChatServer(xmppClient, this.bobClient, this.sensorServer, this.controlServer); interoperabilityServer = new InteroperabilityServer(xmppClient); interoperabilityServer.OnGetInterfaces += (sender, e) => { e.Add("XMPP.IoT.Actuator.Lamp"); }; xmppClient.Connect(); } catch (Exception ex) { Log.Emergency(ex); MessageDialog Dialog = new MessageDialog(ex.Message, "Error"); await Dialog.ShowAsync(); } }
/// <summary> /// Starts the gateway. /// </summary> /// <param name="ConsoleOutput">If console output is permitted.</param> public static bool Start(bool ConsoleOutput) { gatewayRunning = new Semaphore(1, 1, "Waher.IoTGateway.Running"); if (!gatewayRunning.WaitOne(1000)) { return(false); // Is running in another process. } Semaphore StartingServer = new Semaphore(1, 1, "Waher.IoTGateway.Starting"); if (!StartingServer.WaitOne(1000)) { gatewayRunning.Release(); gatewayRunning.Dispose(); gatewayRunning = null; StartingServer.Dispose(); return(false); // Being started in another process. } try { Initialize(); appDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); if (!appDataFolder.EndsWith(new string(Path.DirectorySeparatorChar, 1))) { appDataFolder += Path.DirectorySeparatorChar; } appDataFolder += "IoT Gateway" + Path.DirectorySeparatorChar; Log.Register(new XmlFileEventSink("XML File Event Sink", appDataFolder + "Events" + Path.DirectorySeparatorChar + "Event Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appDataFolder + "Transforms" + Path.DirectorySeparatorChar + "EventXmlToHtml.xslt", 7)); Log.Informational("Server starting up."); beforeUninstallCommandNr = Gateway.RegisterServiceCommand(BeforeUninstall); rootFolder = appDataFolder + "Root" + Path.DirectorySeparatorChar; if (!Directory.Exists(rootFolder)) { appDataFolder = string.Empty; rootFolder = "Root" + Path.DirectorySeparatorChar; } Types.SetModuleParameter("AppData", appDataFolder); Types.SetModuleParameter("Root", rootFolder); scheduler = new Scheduler(); rnd = RandomNumberGenerator.Create(); Task.Run(() => CodeContent.GraphViz.Init()); XmlDocument Config = new XmlDocument(); string GatewayConfigFileName = appDataFolder + "Gateway.config"; if (!File.Exists(GatewayConfigFileName)) { GatewayConfigFileName = "Gateway.config"; } Config.Load(GatewayConfigFileName); XSL.Validate("Gateway.config", Config, "GatewayConfiguration", "http://waher.se/Schema/GatewayConfiguration.xsd", XSL.LoadSchema(typeof(Gateway).Namespace + ".Schema.GatewayConfiguration.xsd", typeof(Gateway).Assembly)); domain = Config.DocumentElement["Domain"].InnerText; XmlElement DatabaseConfig = Config.DocumentElement["Database"]; if (!CommonTypes.TryParse(DatabaseConfig.Attributes["encrypted"].Value, out bool Encrypted)) { Encrypted = true; } databaseProvider = new FilesProvider(appDataFolder + DatabaseConfig.Attributes["folder"].Value, DatabaseConfig.Attributes["defaultCollectionName"].Value, int.Parse(DatabaseConfig.Attributes["blockSize"].Value), int.Parse(DatabaseConfig.Attributes["blocksInCache"].Value), int.Parse(DatabaseConfig.Attributes["blobBlockSize"].Value), Encoding.UTF8, int.Parse(DatabaseConfig.Attributes["timeoutMs"].Value), Encrypted, false); Database.Register(databaseProvider); PersistedEventLog PersistedEventLog = new PersistedEventLog(7, new TimeSpan(4, 15, 0)); Log.Register(PersistedEventLog); PersistedEventLog.Queue(new Event(EventType.Informational, "Server starting up.", string.Empty, string.Empty, string.Empty, EventLevel.Minor, string.Empty, string.Empty, string.Empty)); xmppConfigFileName = Config.DocumentElement["XmppClient"].Attributes["configFileName"].Value; if (!File.Exists(xmppConfigFileName)) { xmppConfigFileName = appDataFolder + xmppConfigFileName; } if (ConsoleOutput) { xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog(xmppConfigFileName, Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(Gateway).Assembly); } else if (File.Exists(xmppConfigFileName)) { xmppConfiguration = new SimpleXmppConfiguration(xmppConfigFileName); RuntimeSettings.Set("XMPP.CONFIG", xmppConfiguration.ExportSimpleXmppConfiguration()); } else { string XmppConfig = RuntimeSettings.Get("XMPP.CONFIG", string.Empty); XmlDocument Doc = new XmlDocument(); Doc.LoadXml(XmppConfig); xmppConfiguration = new SimpleXmppConfiguration(Doc); } xmppClient = xmppConfiguration.GetClient("en", typeof(Gateway).Assembly, false); xmppClient.AllowRegistration(FormSignatureKey, FormSignatureSecret); xmppClient.OnValidateSender += XmppClient_OnValidateSender; Types.SetModuleParameter("XMPP", xmppClient); if (xmppConfiguration.Sniffer) { ISniffer Sniffer; if (ConsoleOutput) { Sniffer = new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces); xmppClient.Add(Sniffer); } Sniffer = new XmlFileSniffer(appDataFolder + "XMPP" + Path.DirectorySeparatorChar + "XMPP Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appDataFolder + "Transforms" + Path.DirectorySeparatorChar + "SnifferXmlToHtml.xslt", 7, BinaryPresentationMethod.ByteCount); xmppClient.Add(Sniffer); } if (!string.IsNullOrEmpty(xmppConfiguration.Events)) { Log.Register(new XmppEventSink("XMPP Event Sink", xmppClient, xmppConfiguration.Events, false)); } if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(xmppClient, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += ThingRegistryClient_Claimed; thingRegistryClient.Disowned += ThingRegistryClient_Disowned; thingRegistryClient.Removed += ThingRegistryClient_Removed; } if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) { provisioningClient = new ProvisioningClient(xmppClient, xmppConfiguration.Provisioning); } DateTime Now = DateTime.Now; int MsToNext = 60000 - (Now.Second * 1000 + Now.Millisecond); connectionTimer = new Timer(CheckConnection, null, MsToNext, 60000); xmppClient.OnStateChanged += XmppClient_OnStateChanged; xmppClient.OnPresenceSubscribe += XmppClient_OnPresenceSubscribe; xmppClient.OnPresenceUnsubscribe += XmppClient_OnPresenceUnsubscribe; xmppClient.OnRosterItemUpdated += XmppClient_OnRosterItemUpdated; ibbClient = new Networking.XMPP.InBandBytestreams.IbbClient(xmppClient, MaxChunkSize); Types.SetModuleParameter("IBB", ibbClient); socksProxy = new Networking.XMPP.P2P.SOCKS5.Socks5Proxy(xmppClient); Types.SetModuleParameter("SOCKS5", socksProxy); string CertificateLocalFileName = Config.DocumentElement["Certificate"].Attributes["configFileName"].Value; string CertificateFileName; string CertificateXml; string CertificatePassword; byte[] CertificateRaw; try { CertificateRaw = Convert.FromBase64String(RuntimeSettings.Get("CERTIFICATE.BASE64", string.Empty)); CertificatePassword = RuntimeSettings.Get("CERTIFICATE.PWD", string.Empty); certificate = new X509Certificate2(CertificateRaw, CertificatePassword); } catch (Exception) { certificate = null; } if (File.Exists(CertificateFileName = appDataFolder + CertificateLocalFileName)) { CertificateXml = File.ReadAllText(CertificateFileName); } else if (File.Exists(CertificateFileName = CertificateLocalFileName) && certificate == null) { CertificateXml = File.ReadAllText(CertificateFileName); } else { CertificateFileName = null; CertificateXml = null; } if (CertificateXml != null) { XmlDocument CertificateConfig = new XmlDocument(); CertificateConfig.LoadXml(CertificateXml); XSL.Validate(CertificateLocalFileName, CertificateConfig, "CertificateConfiguration", "http://waher.se/Schema/CertificateConfiguration.xsd", XSL.LoadSchema(typeof(Gateway).Namespace + ".Schema.CertificateConfiguration.xsd", typeof(Gateway).Assembly)); CertificateLocalFileName = CertificateConfig.DocumentElement["FileName"].InnerText; if (File.Exists(appDataFolder + CertificateLocalFileName)) { CertificateLocalFileName = appDataFolder + CertificateLocalFileName; } CertificateRaw = File.ReadAllBytes(CertificateLocalFileName); CertificatePassword = CertificateConfig.DocumentElement["Password"].InnerText; certificate = new X509Certificate2(CertificateRaw, CertificatePassword); RuntimeSettings.Set("CERTIFICATE.BASE64", Convert.ToBase64String(CertificateRaw)); RuntimeSettings.Set("CERTIFICATE.PWD", CertificatePassword); if (CertificateLocalFileName != "certificate.pfx" || CertificatePassword != "testexamplecom") { try { File.Delete(CertificateLocalFileName); } catch (Exception) { Log.Warning("Unable to delete " + CertificateLocalFileName + " after importing it into the encrypted database."); } try { File.Delete(CertificateFileName); } catch (Exception) { Log.Warning("Unable to delete " + CertificateFileName + " after importing it into the encrypted database."); } } } foreach (XmlNode N in Config.DocumentElement["Ports"].ChildNodes) { if (N.LocalName == "Port") { XmlElement E = (XmlElement)N; string Protocol = XML.Attribute(E, "protocol"); if (!string.IsNullOrEmpty(Protocol) && int.TryParse(E.InnerText, out int Port)) { ports.AddLast(new KeyValuePair <string, int>(Protocol, Port)); } } } webServer = new HttpServer(GetConfigPorts("HTTP"), GetConfigPorts("HTTPS"), certificate); Types.SetModuleParameter("HTTP", webServer); StringBuilder sb = new StringBuilder(); foreach (int Port in webServer.OpenPorts) { sb.AppendLine(Port.ToString()); } try { File.WriteAllText(appDataFolder + "Ports.txt", sb.ToString()); } catch (Exception ex) { Log.Critical(ex); } HttpFolderResource HttpFolderResource; HttpxProxy HttpxProxy; webServer.Register(new HttpFolderResource("/Graphics", "Graphics", false, false, true, false)); // TODO: Add authentication mechanisms for PUT & DELETE. webServer.Register(new HttpFolderResource("/highlight", "Highlight", false, false, true, false)); // Syntax highlighting library, provided by http://highlightjs.org webServer.Register(HttpFolderResource = new HttpFolderResource(string.Empty, rootFolder, false, false, true, true)); // TODO: Add authentication mechanisms for PUT & DELETE. webServer.Register(HttpxProxy = new HttpxProxy("/HttpxProxy", xmppClient, MaxChunkSize)); webServer.Register("/", (req, resp) => { throw new TemporaryRedirectException(Config.DocumentElement["DefaultPage"].InnerText); }); webServer.Register(clientEvents = new ClientEvents()); HttpFolderResource.AllowTypeConversion(); MarkdownToHtmlConverter.EmojiSource = Emoji1_24x24; XmlElement FileFolders = Config.DocumentElement["FileFolders"]; if (FileFolders != null) { foreach (XmlNode N in FileFolders.ChildNodes) { if (N is XmlElement E && E.LocalName == "FileFolder") { string WebFolder = XML.Attribute(E, "webFolder"); string FolderPath = XML.Attribute(E, "folderPath"); webServer.Register(new HttpFolderResource(WebFolder, FolderPath, false, false, true, true)); } } } httpxServer = new HttpxServer(xmppClient, webServer, MaxChunkSize); Types.SetModuleParameter("HTTPX", HttpxProxy); Types.SetModuleParameter("HTTPXS", httpxServer); HttpxProxy.IbbClient = ibbClient; httpxServer.IbbClient = ibbClient; HttpxProxy.Socks5Proxy = socksProxy; httpxServer.Socks5Proxy = socksProxy; if (xmppConfiguration.Sniffer) { ISniffer Sniffer; Sniffer = new XmlFileSniffer(appDataFolder + "HTTP" + Path.DirectorySeparatorChar + "HTTP Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appDataFolder + "Transforms" + Path.DirectorySeparatorChar + "SnifferXmlToHtml.xslt", 7, BinaryPresentationMethod.ByteCount); webServer.Add(Sniffer); } coapEndpoint = new CoapEndpoint(); Types.SetModuleParameter("CoAP", coapEndpoint); concentratorServer = new ConcentratorServer(xmppClient, provisioningClient, new MeteringTopology()); Types.SetModuleParameter("Concentrator", concentratorServer); Types.SetModuleParameter("Sensor", concentratorServer.SensorServer); Types.SetModuleParameter("Control", concentratorServer.ControlServer); } catch (Exception ex) { Log.Critical(ex); gatewayRunning.Release(); gatewayRunning.Dispose(); gatewayRunning = null; StartingServer.Release(); StartingServer.Dispose(); ExceptionDispatchInfo.Capture(ex).Throw(); } Task.Run(async() => { try { try { string BinaryFolder = AppDomain.CurrentDomain.BaseDirectory; string[] LanguageFiles = Directory.GetFiles(BinaryFolder, "*.lng", SearchOption.AllDirectories); string FileName; if (LanguageFiles.Length > 0) { XmlSchema Schema = XSL.LoadSchema(Translator.SchemaResource, typeof(Translator).Assembly); foreach (string LanguageFile in LanguageFiles) { try { FileName = LanguageFile; if (FileName.StartsWith(BinaryFolder)) { FileName = FileName.Substring(BinaryFolder.Length); } DateTime LastWriteTime = File.GetLastWriteTime(LanguageFile); DateTime LastImportedTime = await RuntimeSettings.GetAsync(FileName, DateTime.MinValue); if (LastWriteTime > LastImportedTime) { Log.Informational("Importing language file.", FileName); string Xml = File.ReadAllText(LanguageFile); XmlDocument Doc = new XmlDocument(); Doc.LoadXml(Xml); XSL.Validate(FileName, Doc, Translator.SchemaRoot, Translator.SchemaNamespace, Schema); using (XmlReader r = new XmlNodeReader(Doc)) { await Translator.ImportAsync(r); } RuntimeSettings.Set(FileName, LastWriteTime); } } catch (Exception ex) { Log.Critical(ex, LanguageFile); } } } Types.StartAllModules(int.MaxValue); } finally { StartingServer.Release(); StartingServer.Dispose(); } } catch (Exception ex) { Log.Critical(ex); } finally { xmppClient.Connect(); } }); return(true); }
private async void StartActuator() { try { Log.Informational("Starting application."); SimpleXmppConfiguration xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config", Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(App).GetTypeInfo().Assembly); Log.Informational("Connecting to XMPP server."); xmppClient = xmppConfiguration.GetClient("en", typeof(App).GetTypeInfo().Assembly, false); xmppClient.AllowRegistration(FormSignatureKey, FormSignatureSecret); if (xmppConfiguration.Sniffer && MainPage.Sniffer != null) xmppClient.Add(MainPage.Sniffer); if (!string.IsNullOrEmpty(xmppConfiguration.Events)) Log.Register(new XmppEventSink("XMPP Event Sink", xmppClient, xmppConfiguration.Events, false)); if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(xmppClient, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += (sender, e) => { ownerJid = e.JID; Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair<string, object>("Public", e.IsPublic)); this.RaiseOwnershipChanged(); }; thingRegistryClient.Disowned += (sender, e) => { Log.Informational("Thing has been disowned.", ownerJid); ownerJid = string.Empty; this.Register(); // Will call this.OwnershipChanged() after successful registration. }; thingRegistryClient.Removed += (sender, e) => { Log.Informational("Thing has been removed from the public registry.", ownerJid); }; } if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) provisioningClient = new ProvisioningClient(xmppClient, xmppConfiguration.Provisioning); Timer ConnectionTimer = new Timer((P) => { if (xmppClient.State == XmppState.Offline || xmppClient.State == XmppState.Error || xmppClient.State == XmppState.Authenticating) { try { Log.Informational("Reconnecting."); xmppClient.Reconnect(); } catch (Exception ex) { Log.Critical(ex); } } }, null, 60000, 60000); xmppClient.OnStateChanged += (sender, NewState) => { Log.Informational(NewState.ToString()); switch (NewState) { case XmppState.Connected: connected = true; if (!registered && this.thingRegistryClient != null) this.Register(); break; case XmppState.Offline: immediateReconnect = connected; connected = false; if (immediateReconnect) xmppClient.Reconnect(); break; } }; xmppClient.OnPresenceSubscribe += (sender, e) => { Log.Informational("Subscription request received from " + e.From + "."); e.Accept(); // TODO: Provisioning RosterItem Item = xmppClient.GetRosterItem(e.FromBareJID); if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From) xmppClient.RequestPresenceSubscription(e.FromBareJID); xmppClient.SetPresence(Availability.Chat); }; xmppClient.OnPresenceUnsubscribe += (sender, e) => { Log.Informational("Unsubscription request received from " + e.From + "."); e.Accept(); }; xmppClient.OnRosterItemUpdated += (sender, e) => { if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe) xmppClient.RemoveRosterItem(e.BareJid); }; gpio = GpioController.GetDefault(); if (gpio != null) { int c = gpio.PinCount; int i; for (i = 0; i < c; i++) { if (gpio.TryOpenPin(i, GpioSharingMode.Exclusive, out GpioPin Pin, out GpioOpenStatus Status) && Status == GpioOpenStatus.PinOpened) { gpioPins[i] = new KeyValuePair<GpioPin, KeyValuePair<TextBlock, TextBlock>>(Pin, MainPage.Instance.AddPin("GPIO" + i.ToString(), Pin.GetDriveMode(), Pin.Read().ToString())); Pin.ValueChanged += async (sender, e) => { if (!this.gpioPins.TryGetValue(sender.PinNumber, out KeyValuePair<GpioPin, KeyValuePair<TextBlock, TextBlock>> P)) return; PinState Value = e.Edge == GpioPinEdge.FallingEdge ? PinState.LOW : PinState.HIGH; if (this.sensorServer.HasSubscriptions(ThingReference.Empty)) { DateTime TP = DateTime.Now; string s = "GPIO" + sender.PinNumber.ToString(); this.sensorServer.NewMomentaryValues( new EnumField(ThingReference.Empty, TP, s, Value, FieldType.Momentary, FieldQoS.AutomaticReadout)); } await P.Value.Value.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => P.Value.Value.Text = Value.ToString()); }; } } } DeviceInformationCollection Devices = await Microsoft.Maker.Serial.UsbSerial.listAvailableDevicesAsync(); foreach (DeviceInformation DeviceInfo in Devices) { if (DeviceInfo.IsEnabled && DeviceInfo.Name.StartsWith("Arduino")) { Log.Informational("Connecting to " + DeviceInfo.Name); arduinoUsb = new UsbSerial(DeviceInfo); arduinoUsb.ConnectionEstablished += () => { Log.Informational("USB connection established."); }; arduino = new RemoteDevice(arduinoUsb); arduino.DeviceReady += async () => { Log.Informational("Device ready."); Dictionary<int, bool> DisabledPins = new Dictionary<int, bool>(); Dictionary<string, KeyValuePair<Enum, string>> Values = new Dictionary<string, KeyValuePair<Enum, string>>(); PinMode Mode; PinState State; string s; ushort Value; foreach (byte PinNr in arduino.DeviceHardwareProfile.DisabledPins) DisabledPins[PinNr] = true; foreach (byte PinNr in arduino.DeviceHardwareProfile.AnalogPins) { if (DisabledPins.ContainsKey(PinNr)) continue; s = "A" + (PinNr - arduino.DeviceHardwareProfile.AnalogOffset).ToString(); if (arduino.DeviceHardwareProfile.isAnalogSupported(PinNr)) arduino.pinMode(s, PinMode.ANALOG); Mode = arduino.getPinMode(s); Value = arduino.analogRead(s); Values[s] = new KeyValuePair<Enum, string>(Mode, Value.ToString()); } foreach (byte PinNr in arduino.DeviceHardwareProfile.DigitalPins) { if (DisabledPins.ContainsKey(PinNr) || (PinNr > 6 && PinNr != 13)) // Not sure why this limitation is necessary. Without it, my Arduino board (or the Microsoft Firmata library) stops providing me with pin update events. continue; if (PinNr == 13) { arduino.pinMode(13, PinMode.OUTPUT); // Onboard LED. arduino.digitalWrite(13, PinState.HIGH); } else { if (arduino.DeviceHardwareProfile.isDigitalInputSupported(PinNr)) arduino.pinMode(PinNr, PinMode.INPUT); } s = "D" + PinNr.ToString(); Mode = arduino.getPinMode(PinNr); State = arduino.digitalRead(PinNr); Values[s] = new KeyValuePair<Enum, string>(Mode, State.ToString()); } await MainPage.Instance.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { lock (arduinoPins) { foreach (KeyValuePair<string, KeyValuePair<Enum, string>> P in Values) arduinoPins[P.Key] = MainPage.Instance.AddPin(P.Key, P.Value.Key, P.Value.Value); } }); this.SetupControlServer(); }; arduino.AnalogPinUpdated += async (pin, value) => { KeyValuePair<TextBlock, TextBlock> P; DateTime TP = DateTime.Now; lock (this.arduinoPins) { if (!this.arduinoPins.TryGetValue(pin, out P)) return; } if (this.sensorServer.HasSubscriptions(ThingReference.Empty)) { this.sensorServer.NewMomentaryValues( new Int32Field(ThingReference.Empty, TP, pin + ", Raw", value, FieldType.Momentary, FieldQoS.AutomaticReadout), new QuantityField(ThingReference.Empty, TP, pin, value / 10.24, 2, "%", FieldType.Momentary, FieldQoS.AutomaticReadout)); } await P.Value.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => P.Value.Text = value.ToString()); }; arduino.DigitalPinUpdated += async (pin, value) => { KeyValuePair<TextBlock, TextBlock> P; DateTime TP = DateTime.Now; string s = "D" + pin.ToString(); lock (this.arduinoPins) { if (!this.arduinoPins.TryGetValue("D" + pin.ToString(), out P)) return; } if (this.sensorServer.HasSubscriptions(ThingReference.Empty)) { this.sensorServer.NewMomentaryValues( new EnumField(ThingReference.Empty, TP, s, value, FieldType.Momentary, FieldQoS.AutomaticReadout)); } await P.Value.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => P.Value.Text = value.ToString()); }; arduinoUsb.ConnectionFailed += message => { Log.Error("USB connection failed: " + message); }; arduinoUsb.ConnectionLost += message => { Log.Error("USB connection lost: " + message); }; arduinoUsb.begin(57600, SerialConfig.SERIAL_8N1); break; } } sensorServer = new SensorServer(xmppClient, provisioningClient, true); sensorServer.OnExecuteReadoutRequest += (Sender, Request) => { DateTime Now = DateTime.Now; LinkedList<Field> Fields = new LinkedList<Field>(); DateTime TP = DateTime.Now; string s; bool ReadMomentary = Request.IsIncluded(FieldType.Momentary); bool ReadStatus = Request.IsIncluded(FieldType.Status); Log.Informational("Readout requested", string.Empty, Request.Actor); foreach (KeyValuePair<GpioPin, KeyValuePair<TextBlock, TextBlock>> Pin in gpioPins.Values) { if (ReadMomentary && Request.IsIncluded(s = "GPIO" + Pin.Key.PinNumber.ToString())) { Fields.AddLast(new EnumField(ThingReference.Empty, TP, s, Pin.Key.Read(), FieldType.Momentary, FieldQoS.AutomaticReadout)); } if (ReadStatus && Request.IsIncluded(s = "GPIO" + Pin.Key.PinNumber.ToString() + ", Mode")) { Fields.AddLast(new EnumField(ThingReference.Empty, TP, s, Pin.Key.GetDriveMode(), FieldType.Status, FieldQoS.AutomaticReadout)); } } if (arduinoPins != null) { foreach (KeyValuePair<string, KeyValuePair<TextBlock, TextBlock>> Pin in arduinoPins) { byte i; if (ReadMomentary && Request.IsIncluded(s = Pin.Key)) { if (s.StartsWith("D") && byte.TryParse(s.Substring(1), out i)) { Fields.AddLast(new EnumField(ThingReference.Empty, TP, s, arduino.digitalRead(i), FieldType.Momentary, FieldQoS.AutomaticReadout)); } else { ushort Raw = arduino.analogRead(s); double Percent = Raw / 10.24; Fields.AddLast(new Int32Field(ThingReference.Empty, TP, s + ", Raw", Raw, FieldType.Momentary, FieldQoS.AutomaticReadout)); Fields.AddLast(new QuantityField(ThingReference.Empty, TP, s, Percent, 2, "%", FieldType.Momentary, FieldQoS.AutomaticReadout)); } } if (ReadStatus && Request.IsIncluded(s = Pin.Key + ", Mode")) { if (s.StartsWith("D") && byte.TryParse(s.Substring(1), out i)) { Fields.AddLast(new EnumField(ThingReference.Empty, TP, s, arduino.getPinMode(i), FieldType.Status, FieldQoS.AutomaticReadout)); } else { Fields.AddLast(new EnumField(ThingReference.Empty, TP, s, arduino.getPinMode(s), FieldType.Status, FieldQoS.AutomaticReadout)); } } } } Request.ReportFields(true, Fields); }; if (arduino == null) this.SetupControlServer(); xmppClient.Connect(); } catch (Exception ex) { Log.Emergency(ex); MessageDialog Dialog = new MessageDialog(ex.Message, "Error"); await Dialog.ShowAsync(); } }
private async void StartSensor() { try { Log.Informational("Starting application."); SimpleXmppConfiguration xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config", Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(App).GetTypeInfo().Assembly); Log.Informational("Connecting to XMPP server."); xmppClient = xmppConfiguration.GetClient("en", typeof(App).GetTypeInfo().Assembly, false); xmppClient.AllowRegistration(FormSignatureKey, FormSignatureSecret); if (xmppConfiguration.Sniffer && MainPage.Sniffer != null) { xmppClient.Add(MainPage.Sniffer); } if (!string.IsNullOrEmpty(xmppConfiguration.Events)) { Log.Register(new XmppEventSink("XMPP Event Sink", xmppClient, xmppConfiguration.Events, false)); } if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(xmppClient, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += (sender, e) => { ownerJid = e.JID; Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic)); this.RaiseOwnershipChanged(); }; thingRegistryClient.Disowned += (sender, e) => { Log.Informational("Thing has been disowned.", ownerJid); ownerJid = string.Empty; this.Register(); // Will call this.OwnershipChanged() after successful registration. }; thingRegistryClient.Removed += (sender, e) => { Log.Informational("Thing has been removed from the public registry.", ownerJid); }; } if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) { provisioningClient = new ProvisioningClient(xmppClient, xmppConfiguration.Provisioning); } Timer ConnectionTimer = new Timer((P) => { if (xmppClient.State == XmppState.Offline || xmppClient.State == XmppState.Error || xmppClient.State == XmppState.Authenticating) { try { Log.Informational("Reconnecting."); xmppClient.Reconnect(); } catch (Exception ex) { Log.Critical(ex); } } }, null, 60000, 60000); xmppClient.OnStateChanged += (sender, NewState) => { Log.Informational(NewState.ToString()); switch (NewState) { case XmppState.Connected: connected = true; if (!registered && thingRegistryClient != null) { this.Register(); } break; case XmppState.Offline: immediateReconnect = connected; connected = false; if (immediateReconnect) { xmppClient.Reconnect(); } break; } }; xmppClient.OnPresenceSubscribe += (sender, e) => { Log.Informational("Subscription request received from " + e.From + "."); e.Accept(); // TODO: Provisioning RosterItem Item = xmppClient.GetRosterItem(e.FromBareJID); if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From) { xmppClient.RequestPresenceSubscription(e.FromBareJID); } xmppClient.SetPresence(Availability.Chat); }; xmppClient.OnPresenceUnsubscribe += (sender, e) => { Log.Informational("Unsubscription request received from " + e.From + "."); e.Accept(); }; xmppClient.OnRosterItemUpdated += (sender, e) => { if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe) { xmppClient.RemoveRosterItem(e.BareJid); } }; LinkedList <DayHistoryRecord> DayHistoricalValues = new LinkedList <DayHistoryRecord>(); LinkedList <MinuteHistoryRecord> MinuteHistoricalValues = new LinkedList <MinuteHistoryRecord>(); DateTime SampleTime = DateTime.Now; DateTime PeriodStart = SampleTime.Date; DateTime Now; DateTime MinTime = SampleTime; DateTime MaxTime = SampleTime; double CurrentTemperature = this.ReadTemp(); double MinTemp = CurrentTemperature; double MaxTemp = CurrentTemperature; double SumTemp = CurrentTemperature; int NrTemp = 1; int NrDayRecords = 0; int NrMinuteRecords = 0; object SampleSynch = new object(); this.sampleTimer = new Timer((P) => { lock (SampleSynch) { Now = DateTime.Now; if (Now.Date != PeriodStart.Date) { DayHistoryRecord Rec = new DayHistoryRecord(PeriodStart.Date, PeriodStart.Date.AddDays(1).AddMilliseconds(-1), MinTemp, MaxTemp, SumTemp / NrTemp); DayHistoricalValues.AddFirst(Rec); if (NrDayRecords < MaxRecordsPerPeriod) { NrDayRecords++; } else { DayHistoricalValues.RemoveLast(); } // TODO: Persistence PeriodStart = Now.Date; SumTemp = 0; NrTemp = 0; } CurrentTemperature = this.ReadTemp(); if (Now.Minute != SampleTime.Minute) { MinuteHistoryRecord Rec = new MinuteHistoryRecord(Now, CurrentTemperature); MinuteHistoricalValues.AddFirst(Rec); if (NrMinuteRecords < MaxRecordsPerPeriod) { NrMinuteRecords++; } else { MinuteHistoricalValues.RemoveLast(); } // TODO: Persistence } SampleTime = Now; if (CurrentTemperature < MinTemp) { MinTemp = CurrentTemperature; MinTime = SampleTime; } if (CurrentTemperature > MaxTemp) { MaxTemp = CurrentTemperature; MaxTime = SampleTime; } SumTemp += CurrentTemperature; NrTemp++; } if (this.sensorServer.HasSubscriptions(ThingReference.Empty)) { this.sensorServer.NewMomentaryValues(new QuantityField(ThingReference.Empty, SampleTime, "Temperature", CurrentTemperature, 1, "°C", FieldType.Momentary, FieldQoS.AutomaticReadout)); } this.UpdateMainWindow(CurrentTemperature, MinTemp, MaxTemp, SumTemp / NrTemp); }, null, 1000 - PeriodStart.Millisecond, 1000); this.sensorServer = new SensorServer(xmppClient, provisioningClient, true); this.sensorServer.OnExecuteReadoutRequest += (Sender, Request) => { Log.Informational("Readout requested by " + Request.From, string.Empty, Request.Actor); List <Field> Fields = new List <Field>(); bool IncludeTemp = Request.IsIncluded("Temperature"); bool IncludeTempMin = Request.IsIncluded("Temperature, Min"); bool IncludeTempMax = Request.IsIncluded("Temperature, Max"); bool IncludeTempAvg = Request.IsIncluded("Temperature, Average"); bool IncludePeak = Request.IsIncluded(FieldType.Peak); bool IncludeComputed = Request.IsIncluded(FieldType.Computed); lock (SampleSynch) { if (IncludeTemp && Request.IsIncluded(FieldType.Momentary)) { Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature", CurrentTemperature, 1, "°C", FieldType.Momentary, FieldQoS.AutomaticReadout)); } if (IncludePeak) { if (IncludeTempMin) { Fields.Add(new QuantityField(ThingReference.Empty, MinTime, "Temperature, Min", MinTemp, 1, "°C", FieldType.Peak, FieldQoS.AutomaticReadout)); } if (IncludeTempMax) { Fields.Add(new QuantityField(ThingReference.Empty, MaxTime, "Temperature, Max", MaxTemp, 1, "°C", FieldType.Peak, FieldQoS.AutomaticReadout)); } } if (IncludeTempAvg && IncludeComputed) { Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature, Average", SumTemp / NrTemp, 2, "°C", FieldType.Computed, FieldQoS.AutomaticReadout)); } if (Request.IsIncluded(FieldType.Historical)) { foreach (DayHistoryRecord Rec in DayHistoricalValues) { if (!Request.IsIncluded(Rec.PeriodStart)) { continue; } if (Fields.Count >= 100) { Request.ReportFields(false, Fields); Fields.Clear(); } if (IncludePeak) { if (IncludeTempMin) { Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Min", Rec.MinTemperature, 1, "°C", FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout)); } if (IncludeTempMax) { Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Max", Rec.MaxTemperature, 1, "°C", FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout)); } } if (IncludeTempAvg && IncludeComputed) { Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Average", Rec.AverageTemperature, 1, "°C", FieldType.Computed | FieldType.Historical, FieldQoS.AutomaticReadout)); } } foreach (MinuteHistoryRecord Rec in MinuteHistoricalValues) { if (!Request.IsIncluded(Rec.Timestamp)) { continue; } if (IncludeTemp) { if (Fields.Count >= 100) { Request.ReportFields(false, Fields); Fields.Clear(); } Fields.Add(new QuantityField(ThingReference.Empty, Rec.Timestamp, "Temperature", Rec.Temperature, 1, "°C", FieldType.Historical, FieldQoS.AutomaticReadout)); } } } } Request.ReportFields(true, Fields); }; this.bobClient = new BobClient(this.xmppClient, Path.Combine(Path.GetTempPath(), "BitsOfBinary")); this.chatServer = new ChatServer(this.xmppClient, this.bobClient, this.sensorServer); this.interoperabilityServer = new InteroperabilityServer(xmppClient); this.interoperabilityServer.OnGetInterfaces += (sender, e) => { e.Add("XMPP.IoT.Sensor.Temperature", "XMPP.IoT.Sensor.Temperature.History", "XMPP.IoT.Sensor.Temperature.Average", "XMPP.IoT.Sensor.Temperature.Average.History", "XMPP.IoT.Sensor.Temperature.Min", "XMPP.IoT.Sensor.Temperature.Min.History", "XMPP.IoT.Sensor.Temperature.Max", "XMPP.IoT.Sensor.Temperature.Max.History"); }; xmppClient.Connect(); } catch (Exception ex) { Log.Emergency(ex); MessageDialog Dialog = new MessageDialog(ex.Message, "Error"); await Dialog.ShowAsync(); } }
static void Main(string[] args) { try { Console.ForegroundColor = ConsoleColor.White; Console.Out.WriteLine("Welcome to the Mock Temperature sensor application."); Console.Out.WriteLine(new string('-', 79)); Console.Out.WriteLine("This application will simulate an outside temperature sensor."); Console.Out.WriteLine("Values will be published over XMPP using the interface defined in the IEEE XMPP IoT extensions."); Console.Out.WriteLine("You can also chat with the sensor."); Log.Register(new ConsoleEventSink()); Log.RegisterExceptionToUnnest(typeof(System.Runtime.InteropServices.ExternalException)); Log.RegisterExceptionToUnnest(typeof(System.Security.Authentication.AuthenticationException)); xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config", Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name. Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password. FormSignatureKey, FormSignatureSecret, typeof(Program).Assembly); using (XmppClient Client = xmppConfiguration.GetClient("en", typeof(Program).Assembly, false)) { Client.AllowRegistration(FormSignatureKey, FormSignatureSecret); if (xmppConfiguration.Sniffer) { Client.Add(new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces)); } if (!string.IsNullOrEmpty(xmppConfiguration.Events)) { Log.Register(new XmppEventSink("XMPP Event Sink", Client, xmppConfiguration.Events, false)); } if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry)) { thingRegistryClient = new ThingRegistryClient(Client, xmppConfiguration.ThingRegistry); thingRegistryClient.Claimed += (sender, e) => { ownerJid = e.JID; Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic)); }; thingRegistryClient.Disowned += (sender, e) => { Log.Informational("Thing has been disowned.", ownerJid); ownerJid = string.Empty; Register(); }; thingRegistryClient.Removed += (sender, e) => { Log.Informational("Thing has been removed from the public registry.", ownerJid); }; } ProvisioningClient ProvisioningClient = null; if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning)) { ProvisioningClient = new ProvisioningClient(Client, xmppConfiguration.Provisioning); } Timer ConnectionTimer = new Timer((P) => { if (Client.State == XmppState.Offline || Client.State == XmppState.Error || Client.State == XmppState.Authenticating) { try { Client.Reconnect(); } catch (Exception ex) { Log.Critical(ex); } } }, null, 60000, 60000); bool Connected = false; bool ImmediateReconnect; Client.OnStateChanged += (sender, NewState) => { switch (NewState) { case XmppState.Connected: Connected = true; if (!registered && thingRegistryClient != null) { Register(); } break; case XmppState.Offline: ImmediateReconnect = Connected; Connected = false; if (ImmediateReconnect) { Client.Reconnect(); } break; } }; Client.OnPresenceSubscribe += (sender, e) => { e.Accept(); // TODO: Provisioning RosterItem Item = Client.GetRosterItem(e.FromBareJID); if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From) { Client.RequestPresenceSubscription(e.FromBareJID); } Client.SetPresence(Availability.Chat); }; Client.OnPresenceUnsubscribe += (sender, e) => { e.Accept(); }; Client.OnRosterItemUpdated += (sender, e) => { if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe) { Client.RemoveRosterItem(e.BareJid); } }; bool SwitchOn = false; SensorServer SensorServer = new SensorServer(Client, ProvisioningClient, false); SensorServer.OnExecuteReadoutRequest += (Sender, Request) => { DateTime Now = DateTime.Now; Log.Informational("Readout requested", string.Empty, Request.Actor); Request.ReportFields(true, new BooleanField(ThingReference.Empty, Now, "Lamp", SwitchOn, FieldType.Momentary, FieldQoS.AutomaticReadout)); }; ControlServer ControlServer = new ControlServer(Client, new BooleanControlParameter("Lamp", "Control", "Lamp switch on.", "If checked, lamp is turned on.", (Node) => SwitchOn, (Node, Value) => { SwitchOn = Value; Log.Informational(Environment.NewLine + Environment.NewLine + "Lamp turned " + (SwitchOn ? "ON" : "OFF") + Environment.NewLine + Environment.NewLine); })); BobClient BobClient = new BobClient(Client, Path.Combine(Path.GetTempPath(), "BitsOfBinary")); ChatServer ChatServer = new ChatServer(Client, BobClient, SensorServer, ControlServer); InteroperabilityServer InteroperabilityServer = new InteroperabilityServer(Client); InteroperabilityServer.OnGetInterfaces += (sender, e) => { e.Add("XMPP.IoT.Actuator.Lamp"); }; Client.Connect(); while (true) { Thread.Sleep(1000); } } } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.Out.WriteLine(ex.Message); } finally { Log.Terminate(); } }