Beispiel #1
0
		private static void MonitorMqtt ()
		{
			UTF8Encoding Encoder = new UTF8Encoding (false);
			bool HasLightValue = false;
			bool HasMotionValue = false;
			MqttClient Client = null;

			try
			{
				WaitHandle[] Handles = new WaitHandle[]{ updateLeds, updateAlarm };

				while (executing)
				{
					try
					{
						if (Client == null)
						{
							Client = new MqttClient ("iot.eclipse.org", MqttClient.DefaultPort, "LearningIoTController", string.Empty, false);
							//Client.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal));

							Client.Open ();
							Client.CONNECT (20, true);

							Client.OnDataPublished += (Sender, e) =>
							{
								string Topic = e.Topic;
								if (!Topic.StartsWith ("Clayster/LearningIoT/Sensor/"))
									return;

								string s = System.Text.Encoding.UTF8.GetString (e.Data);
								PhysicalMagnitude Magnitude;
								bool b;

								Topic = Topic.Substring (28);
								switch (Topic)
								{
									case "Light":
										if (PhysicalMagnitude.TryParse (s, out Magnitude) && Magnitude.Unit == "%" && Magnitude.Value >= 0 && Magnitude.Value <= 100)
										{
											lightPercent = Magnitude.Value;
											if (!HasLightValue)
											{
												HasLightValue = true;
												if (HasMotionValue)
													hasValues = true;
											}

											CheckControlRules ();
										}
										break;

									case "Motion":
										if (!string.IsNullOrEmpty (s) && XmlUtilities.TryParseBoolean (s, out b))
										{
											motion = b;

											if (!HasMotionValue)
											{
												HasMotionValue = true;
												if (HasLightValue)
													hasValues = true;
											}

											CheckControlRules ();
										}
										break;
								}
							};

							Client.SUBSCRIBE (new KeyValuePair<string, MqttQoS> ("Clayster/LearningIoT/Sensor/#", MqttQoS.QoS1_Acknowledged));
							Log.Information ("Listening on MQTT topic Clayster/LearningIoT/Sensor @ ", EventLevel.Minor, Client.Host + ":" + Client.PortNumber.ToString ());
						}

						switch (WaitHandle.WaitAny (Handles, 1000))
						{
							case 0:	// Update LEDS
								int i;

								lock (synchObject)
								{
									i = lastLedMask;
								}

								Client.PUBLISH ("Clayster/LearningIoT/Actuator/do", Encoder.GetBytes (i.ToString ()), MqttQoS.QoS1_Acknowledged, true);

								// Just to synchronize with the other topics.
								for (int j = 1; j <= 8; j++)
								{
									Client.PUBLISH ("Clayster/LearningIoT/Actuator/do" + j.ToString (), Encoder.GetBytes ((i & 1).ToString ()), MqttQoS.QoS1_Acknowledged, true);
									i >>= 1;
								}
								break;

							case 1:	// Update Alarm
								bool b;

								lock (synchObject)
								{
									b = lastAlarm.Value;
								}

								Client.PUBLISH ("Clayster/LearningIoT/Actuator/ao", Encoder.GetBytes (b ? "1" : "0"), MqttQoS.QoS1_Acknowledged, true);

								if (b)
								{
									Thread T = new Thread (SendAlarmMail);
									T.Priority = ThreadPriority.BelowNormal;
									T.Name = "SendAlarmMail";
									T.Start ();
								}
								break;

							default:	// Timeout
								CheckSubscriptions (30);
								break;
						}
					} catch (ThreadAbortException)
					{
						// Don't log. Exception will be automatically re-raised.
					} catch (Exception ex)
					{
						Log.Exception (ex);

						if (Client != null)
						{
							Client.Dispose ();
							Client = null;
						}

						Thread.Sleep(5000);
					}
				}
			} finally
			{
				Client.Dispose ();
			}
		}
Beispiel #2
0
		public static int Main (string[] args)
		{
			Log.Register (new ConsoleOutEventLog (80));
			Log.Information ("Initializing application...");

			HttpSocketClient.RegisterHttpProxyUse (false, false);	// Don't look for proxies.

			DB.BackupConnectionString = "Data Source=actuator.db;Version=3;";
			DB.BackupProviderName = "Clayster.Library.Data.Providers.SQLiteServer.SQLiteServerProvider";
			db = DB.GetDatabaseProxy ("TheActuator");

			Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
			{
				e.Cancel = true;
				executionLed.Low ();
			};

			// HTTP Interface

			HttpServer HttpServer = new HttpServer (80, 10, true, true, 1);
			int i;

			Log.Information ("HTTP Server receiving requests on port " + HttpServer.Port.ToString ());

			HttpServer.RegisterAuthenticationMethod (new DigestAuthentication ("The Actuator Realm", GetDigestUserPasswordHash));
			HttpServer.RegisterAuthenticationMethod (new SessionAuthentication ());

			credentials = LoginCredentials.LoadCredentials ();
			if (credentials == null)
			{
				credentials = new LoginCredentials ();
				credentials.UserName = "******";
				credentials.PasswordHash = CalcHash ("Admin", "Password");
				credentials.SaveNew ();
			}

			state = State.LoadState ();
			if (state == null)
			{
				state = new State ();
				state.SaveNew ();
			} else
			{
				for (i = 0; i < 8; i++)
					digitalOutputs [i].Value = state.GetDO (i + 1);

				if (state.Alarm)
					AlarmOn ();
				else
					AlarmOff ();
			}

			WebServiceAPI wsApi;

			HttpServer.Register ("/", HttpGetRoot, HttpPostRoot, false);							// Synchronous, no authentication
			HttpServer.Register ("/credentials", HttpGetCredentials, HttpPostCredentials, false);	// Synchronous, no authentication
			HttpServer.Register ("/set", HttpGetSet, HttpPostSet, true);							// Synchronous, http authentication
			HttpServer.Register ("/xml", HttpGetXml, true);											// Synchronous, http authentication
			HttpServer.Register ("/json", HttpGetJson, true);										// Synchronous, http authentication
			HttpServer.Register ("/turtle", HttpGetTurtle, true);									// Synchronous, http authentication
			HttpServer.Register ("/rdf", HttpGetRdf, true);											// Synchronous, http authentication
			HttpServer.Register (wsApi = new WebServiceAPI (), true);

			// HTTPS interface

			// Certificate must be a valid P12 (PFX) certificate file containing a private key.
			// X509Certificate2 Certificate = new X509Certificate2 ("Certificate.pfx", "PASSWORD");
			// HttpServer HttpsServer = new HttpServer (443, 10, true, true, 1, true, false, Certificate);
			//
			// HttpsServer.RegisterAuthenticationMethod (new DigestAuthentication ("The Actuator Realm", GetDigestUserPasswordHash));
			// 
			// foreach (IHttpServerResource Resource in HttpServer.GetResources())
			//    HttpsServer.Register (Resource);
			// 
			// Log.Information ("HTTPS Server receiving requests on port " + HttpsServer.Port.ToString ());

			// CoAP Interface

			CoapEndpoint CoapEndpoint = new CoapEndpoint ();
			Log.Information ("CoAP endpoint receiving requests on port " + CoapEndpoint.Port.ToString ());

			//CoapEndpoint.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal, true));

			for (i = 1; i <= 8; i++)
			{
				CoapEndpoint.RegisterResource ("do" + i.ToString () + "/txt", "Digital Output " + i.ToString () + ", as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, false, 
					CoapGetDigitalOutputTxt, CoapSetDigitalOutputTxt);
			}
				
			CoapEndpoint.RegisterResource ("do/txt", "Digital Outputs, as a number 0-255 as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, false, 
				CoapGetDigitalOutputsTxt, CoapSetDigitalOutputsTxt);

			CoapEndpoint.RegisterResource ("alarm/txt", "Alarm Output " + i.ToString () + ", as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, false, 
				CoapGetAlarmOutputTxt, CoapSetAlarmOutputTxt);

			foreach (CoapBlockSize BlockSize in Enum.GetValues(typeof(CoapBlockSize)))
			{
				if (BlockSize == CoapBlockSize.BlockLimit_Datagram)
					continue;

				string Bytes = (1 << (4 + (int)BlockSize)).ToString ();

				CoapEndpoint.RegisterResource ("xml/" + Bytes, "Complete sensor readout, in XML. Control content using query parmeters. Block size=" + Bytes + " bytes.", 
					BlockSize, false, 30, false, CoapGetXml);

				CoapEndpoint.RegisterResource ("json/" + Bytes, "Complete sensor readout, in JSON. Control content using query parmeters. Block size=" + Bytes + " bytes.", 
					BlockSize, false, 30, false, CoapGetJson);

				CoapEndpoint.RegisterResource ("turtle/" + Bytes, "Complete sensor readout, in TURTLE. Control content using query parmeters. Block size=" + Bytes + " bytes.", 
					BlockSize, false, 30, false, CoapGetTurtle);

				CoapEndpoint.RegisterResource ("rdf/" + Bytes, "Complete sensor readout, in RDF. Control content using query parmeters. Block size=" + Bytes + " bytes.", 
					BlockSize, false, 30, false, CoapGetRdf);
			}

			// MQTT

			MqttClient MqttClient = new MqttClient ("iot.eclipse.org", MqttClient.DefaultPort, "LearningIoTActuator", string.Empty, false);
			//MqttClient.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal));

			MqttClient.Open ();
			MqttClient.CONNECT (20, true);

			MqttClient.PUBLISH ("Clayster/LearningIoT/Actuator/ao", state.Alarm ? "1" : "0", MqttQoS.QoS1_Acknowledged, true);
			MqttClient.PUBLISH ("Clayster/LearningIoT/Actuator/do", wsApi.GetDigitalOutputs ().ToString (), MqttQoS.QoS1_Acknowledged, true);

			for (i = 1; i <= 8; i++)
				MqttClient.PUBLISH ("Clayster/LearningIoT/Actuator/do" + i.ToString (), wsApi.GetDigitalOutput (i) ? "1" : "0", MqttQoS.QoS1_Acknowledged, true);

			MqttClient.SUBSCRIBE (new KeyValuePair<string, MqttQoS> ("Clayster/LearningIoT/Actuator/#", MqttQoS.QoS1_Acknowledged));
			MqttClient.OnDataPublished += OnMqttDataPublished;

			Log.Information ("Receiving commands via MQTT from Clayster/LearningIoT/Actuator @ ", EventLevel.Minor, MqttClient.Host + ":" + MqttClient.PortNumber.ToString ());

			// Main loop

			Log.Information ("Initialization complete. Application started...");

			try
			{
				while (executionLed.Value)
				{		
					System.Threading.Thread.Sleep (1000);
					RemoveOldSessions ();
				}

			} catch (Exception ex)
			{
				Log.Exception (ex);
				executionLed.Low ();
			} finally
			{
				Log.Information ("Terminating application.");
				Log.Flush ();
				Log.Terminate ();

				HttpServer.Dispose ();
				//HttpsServer.Dispose ();

				if (MqttClient != null)
					MqttClient.Dispose ();

				executionLed.Dispose ();

				foreach (DigitalOutput Output in digitalOutputs)
					Output.Dispose ();

				if (alarmThread != null)
				{
					alarmThread.Abort ();
					alarmThread = null;
				}
			}

			return 0;
		}
Beispiel #3
0
		private static void MqttThread ()
		{
			WaitHandle[] Events = new WaitHandle[]{ mqttNewTemp, mqttNewLight, mqttNewMotion };
			MqttClient Client = null;

			try
			{
				while (true)
				{
					try
					{
						if (Client == null)
						{
							Client = new MqttClient ("iot.eclipse.org", MqttClient.DefaultPort, "LearningIoTSensor", string.Empty, false);
							//Client.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal));

							Client.Open ();
							Client.CONNECT (20, true);

							Log.Information ("Publishing via MQTT to Clayster/LearningIoT/Sensor @ ", EventLevel.Minor, Client.Host + ":" + Client.PortNumber.ToString ());
						}

						switch (WaitHandle.WaitAny (Events, 1000))
						{
							case 0:	// New temperature
								Client.PUBLISH ("Clayster/LearningIoT/Sensor/Temperature", FieldNumeric.Format (temperatureC, "C", 1), MqttQoS.QoS1_Acknowledged, true);
								break;

							case 1:	// New light
								Client.PUBLISH ("Clayster/LearningIoT/Sensor/Light", FieldNumeric.Format (lightPercent, "%", 1), MqttQoS.QoS1_Acknowledged, true);
								break;

							case 2:	// New motion
								Client.PUBLISH ("Clayster/LearningIoT/Sensor/Motion", motionDetected ? "1" : "0", MqttQoS.QoS1_Acknowledged, true);
								break;
						}
					} catch (Exception ex)
					{
						Log.Exception (ex);

						if (Client != null)
						{
							Client.Dispose ();
							Client = null;
						}

						mqttNewTemp.Set ();
						mqttNewLight.Set ();
						mqttNewMotion.Set ();

						Thread.Sleep(5000);
					}
				}

			} catch (ThreadAbortException)
			{
				Thread.ResetAbort ();
			} catch (Exception ex)
			{
				Log.Exception (ex);
			} finally
			{
				if (Client != null)
					Client.Dispose ();
			}
		}
Beispiel #4
0
        private static void MonitorMqtt()
        {
            UTF8Encoding Encoder        = new UTF8Encoding(false);
            bool         HasLightValue  = false;
            bool         HasMotionValue = false;
            MqttClient   Client         = null;

            try
            {
                WaitHandle[] Handles = new WaitHandle[] { updateLeds, updateAlarm };

                while (executing)
                {
                    try
                    {
                        if (Client == null)
                        {
                            Client = new MqttClient("iot.eclipse.org", MqttClient.DefaultPort, "LearningIoTController", string.Empty, false);
                            //Client.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal));

                            Client.Open();
                            Client.CONNECT(20, true);

                            Client.OnDataPublished += (Sender, e) =>
                            {
                                string Topic = e.Topic;
                                if (!Topic.StartsWith("Clayster/LearningIoT/Sensor/"))
                                {
                                    return;
                                }

                                string            s = System.Text.Encoding.UTF8.GetString(e.Data);
                                PhysicalMagnitude Magnitude;
                                bool b;

                                Topic = Topic.Substring(28);
                                switch (Topic)
                                {
                                case "Light":
                                    if (PhysicalMagnitude.TryParse(s, out Magnitude) && Magnitude.Unit == "%" && Magnitude.Value >= 0 && Magnitude.Value <= 100)
                                    {
                                        lightPercent = Magnitude.Value;
                                        if (!HasLightValue)
                                        {
                                            HasLightValue = true;
                                            if (HasMotionValue)
                                            {
                                                hasValues = true;
                                            }
                                        }

                                        CheckControlRules();
                                    }
                                    break;

                                case "Motion":
                                    if (!string.IsNullOrEmpty(s) && XmlUtilities.TryParseBoolean(s, out b))
                                    {
                                        motion = b;

                                        if (!HasMotionValue)
                                        {
                                            HasMotionValue = true;
                                            if (HasLightValue)
                                            {
                                                hasValues = true;
                                            }
                                        }

                                        CheckControlRules();
                                    }
                                    break;
                                }
                            };

                            Client.SUBSCRIBE(new KeyValuePair <string, MqttQoS> ("Clayster/LearningIoT/Sensor/#", MqttQoS.QoS1_Acknowledged));
                            Log.Information("Listening on MQTT topic Clayster/LearningIoT/Sensor @ ", EventLevel.Minor, Client.Host + ":" + Client.PortNumber.ToString());
                        }

                        switch (WaitHandle.WaitAny(Handles, 1000))
                        {
                        case 0:                                 // Update LEDS
                            int i;

                            lock (synchObject)
                            {
                                i = lastLedMask;
                            }

                            Client.PUBLISH("Clayster/LearningIoT/Actuator/do", Encoder.GetBytes(i.ToString()), MqttQoS.QoS1_Acknowledged, true);

                            // Just to synchronize with the other topics.
                            for (int j = 1; j <= 8; j++)
                            {
                                Client.PUBLISH("Clayster/LearningIoT/Actuator/do" + j.ToString(), Encoder.GetBytes((i & 1).ToString()), MqttQoS.QoS1_Acknowledged, true);
                                i >>= 1;
                            }
                            break;

                        case 1:                                 // Update Alarm
                            bool b;

                            lock (synchObject)
                            {
                                b = lastAlarm.Value;
                            }

                            Client.PUBLISH("Clayster/LearningIoT/Actuator/ao", Encoder.GetBytes(b ? "1" : "0"), MqttQoS.QoS1_Acknowledged, true);

                            if (b)
                            {
                                Thread T = new Thread(SendAlarmMail);
                                T.Priority = ThreadPriority.BelowNormal;
                                T.Name     = "SendAlarmMail";
                                T.Start();
                            }
                            break;

                        default:                                        // Timeout
                            CheckSubscriptions(30);
                            break;
                        }
                    } catch (ThreadAbortException)
                    {
                        // Don't log. Exception will be automatically re-raised.
                    } catch (Exception ex)
                    {
                        Log.Exception(ex);

                        if (Client != null)
                        {
                            Client.Dispose();
                            Client = null;
                        }

                        Thread.Sleep(5000);
                    }
                }
            } finally
            {
                Client.Dispose();
            }
        }
        public static int Main(string[] args)
        {
            Log.Register(new ConsoleOutEventLog(80));
            Log.Information("Initializing application...");

            HttpSocketClient.RegisterHttpProxyUse(false, false);                // Don't look for proxies.

            DB.BackupConnectionString = "Data Source=actuator.db;Version=3;";
            DB.BackupProviderName     = "Clayster.Library.Data.Providers.SQLiteServer.SQLiteServerProvider";
            db = DB.GetDatabaseProxy("TheActuator");

            Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
            {
                e.Cancel = true;
                executionLed.Low();
            };

            // HTTP Interface

            HttpServer HttpServer = new HttpServer(80, 10, true, true, 1);
            int        i;

            Log.Information("HTTP Server receiving requests on port " + HttpServer.Port.ToString());

            HttpServer.RegisterAuthenticationMethod(new DigestAuthentication("The Actuator Realm", GetDigestUserPasswordHash));
            HttpServer.RegisterAuthenticationMethod(new SessionAuthentication());

            credentials = LoginCredentials.LoadCredentials();
            if (credentials == null)
            {
                credentials              = new LoginCredentials();
                credentials.UserName     = "******";
                credentials.PasswordHash = CalcHash("Admin", "Password");
                credentials.SaveNew();
            }

            state = State.LoadState();
            if (state == null)
            {
                state = new State();
                state.SaveNew();
            }
            else
            {
                for (i = 0; i < 8; i++)
                {
                    digitalOutputs [i].Value = state.GetDO(i + 1);
                }

                if (state.Alarm)
                {
                    AlarmOn();
                }
                else
                {
                    AlarmOff();
                }
            }

            WebServiceAPI wsApi;

            HttpServer.Register("/", HttpGetRoot, HttpPostRoot, false);                                         // Synchronous, no authentication
            HttpServer.Register("/credentials", HttpGetCredentials, HttpPostCredentials, false);                // Synchronous, no authentication
            HttpServer.Register("/set", HttpGetSet, HttpPostSet, true);                                         // Synchronous, http authentication
            HttpServer.Register("/xml", HttpGetXml, true);                                                      // Synchronous, http authentication
            HttpServer.Register("/json", HttpGetJson, true);                                                    // Synchronous, http authentication
            HttpServer.Register("/turtle", HttpGetTurtle, true);                                                // Synchronous, http authentication
            HttpServer.Register("/rdf", HttpGetRdf, true);                                                      // Synchronous, http authentication
            HttpServer.Register(wsApi = new WebServiceAPI(), true);

            // HTTPS interface

            // Certificate must be a valid P12 (PFX) certificate file containing a private key.
            // X509Certificate2 Certificate = new X509Certificate2 ("Certificate.pfx", "PASSWORD");
            // HttpServer HttpsServer = new HttpServer (443, 10, true, true, 1, true, false, Certificate);
            //
            // HttpsServer.RegisterAuthenticationMethod (new DigestAuthentication ("The Actuator Realm", GetDigestUserPasswordHash));
            //
            // foreach (IHttpServerResource Resource in HttpServer.GetResources())
            //    HttpsServer.Register (Resource);
            //
            // Log.Information ("HTTPS Server receiving requests on port " + HttpsServer.Port.ToString ());

            // CoAP Interface

            CoapEndpoint CoapEndpoint = new CoapEndpoint();

            Log.Information("CoAP endpoint receiving requests on port " + CoapEndpoint.Port.ToString());

            //CoapEndpoint.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal, true));

            for (i = 1; i <= 8; i++)
            {
                CoapEndpoint.RegisterResource("do" + i.ToString() + "/txt", "Digital Output " + i.ToString() + ", as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, false,
                                              CoapGetDigitalOutputTxt, CoapSetDigitalOutputTxt);
            }

            CoapEndpoint.RegisterResource("do/txt", "Digital Outputs, as a number 0-255 as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, false,
                                          CoapGetDigitalOutputsTxt, CoapSetDigitalOutputsTxt);

            CoapEndpoint.RegisterResource("alarm/txt", "Alarm Output " + i.ToString() + ", as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, false,
                                          CoapGetAlarmOutputTxt, CoapSetAlarmOutputTxt);

            foreach (CoapBlockSize BlockSize in Enum.GetValues(typeof(CoapBlockSize)))
            {
                if (BlockSize == CoapBlockSize.BlockLimit_Datagram)
                {
                    continue;
                }

                string Bytes = (1 << (4 + (int)BlockSize)).ToString();

                CoapEndpoint.RegisterResource("xml/" + Bytes, "Complete sensor readout, in XML. Control content using query parmeters. Block size=" + Bytes + " bytes.",
                                              BlockSize, false, 30, false, CoapGetXml);

                CoapEndpoint.RegisterResource("json/" + Bytes, "Complete sensor readout, in JSON. Control content using query parmeters. Block size=" + Bytes + " bytes.",
                                              BlockSize, false, 30, false, CoapGetJson);

                CoapEndpoint.RegisterResource("turtle/" + Bytes, "Complete sensor readout, in TURTLE. Control content using query parmeters. Block size=" + Bytes + " bytes.",
                                              BlockSize, false, 30, false, CoapGetTurtle);

                CoapEndpoint.RegisterResource("rdf/" + Bytes, "Complete sensor readout, in RDF. Control content using query parmeters. Block size=" + Bytes + " bytes.",
                                              BlockSize, false, 30, false, CoapGetRdf);
            }

            // MQTT

            MqttClient MqttClient = new MqttClient("iot.eclipse.org", MqttClient.DefaultPort, "LearningIoTActuator", string.Empty, false);

            //MqttClient.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal));

            MqttClient.Open();
            MqttClient.CONNECT(20, true);

            MqttClient.PUBLISH("Clayster/LearningIoT/Actuator/ao", state.Alarm ? "1" : "0", MqttQoS.QoS1_Acknowledged, true);
            MqttClient.PUBLISH("Clayster/LearningIoT/Actuator/do", wsApi.GetDigitalOutputs().ToString(), MqttQoS.QoS1_Acknowledged, true);

            for (i = 1; i <= 8; i++)
            {
                MqttClient.PUBLISH("Clayster/LearningIoT/Actuator/do" + i.ToString(), wsApi.GetDigitalOutput(i) ? "1" : "0", MqttQoS.QoS1_Acknowledged, true);
            }

            MqttClient.SUBSCRIBE(new KeyValuePair <string, MqttQoS> ("Clayster/LearningIoT/Actuator/#", MqttQoS.QoS1_Acknowledged));
            MqttClient.OnDataPublished += OnMqttDataPublished;

            Log.Information("Receiving commands via MQTT from Clayster/LearningIoT/Actuator @ ", EventLevel.Minor, MqttClient.Host + ":" + MqttClient.PortNumber.ToString());

            // Main loop

            Log.Information("Initialization complete. Application started...");

            try
            {
                while (executionLed.Value)
                {
                    System.Threading.Thread.Sleep(1000);
                    RemoveOldSessions();
                }
            } catch (Exception ex)
            {
                Log.Exception(ex);
                executionLed.Low();
            } finally
            {
                Log.Information("Terminating application.");
                Log.Flush();
                Log.Terminate();

                HttpServer.Dispose();
                //HttpsServer.Dispose ();

                if (MqttClient != null)
                {
                    MqttClient.Dispose();
                }

                executionLed.Dispose();

                foreach (DigitalOutput Output in digitalOutputs)
                {
                    Output.Dispose();
                }

                if (alarmThread != null)
                {
                    alarmThread.Abort();
                    alarmThread = null;
                }
            }

            return(0);
        }