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(); } }
public void DataReported(MqttContent Content) { int Len = Content.Data.Length; if (Len == 0) { this.data = null; return; } this.dataCount += Len; try { if (this.data == null) { this.data = this.FindDataType(Content); } else { this.data.DataReported(Content); } this.SetOk(); } catch (Exception) { try { this.data = this.FindDataType(Content); } catch (Exception ex2) { this.Exception(ex2); return; } } if (this.broker.Client?.HasSniffers ?? false) { this.data.SnifferOutput(this.broker.Client); } if (Types.TryGetModuleParameter("Sensor", out object Obj) && Obj is SensorServer SensorServer) { try { InternalReadoutRequest Request = new InternalReadoutRequest(string.Empty, new ThingReference[] { this.node }, FieldType.All, null, DateTime.MinValue, DateTime.MaxValue, (sender, e) => { SensorServer.NewMomentaryValues(this.node, e.Fields); MqttTopic Current = this; MqttTopic Parent = this.parent; while (Parent != null) { foreach (Field F in e.Fields) { if (F.Name == "Value") { F.Name = Current.localTopic; } else { F.Name = Current.localTopic + ", " + F.Name; } SensorServer.NewMomentaryValues(Parent.node, F); } Current = Parent; Parent = Parent.parent; } return(Task.CompletedTask); }, (sender, e) => { return(Task.CompletedTask); }, null); this.StartReadout(Request); } catch (Exception ex) { this.Exception(ex); } } }