Ejemplo n.º 1
0
        public override List <Field> ProcessReadoutRequest(ReadoutType Types, DateTime From, DateTime To)
        {
            String           Path   = this.resource;
            EditableTreeNode Node   = this.Parent;
            CoapServer       Server = null;
            CoapFolder       Folder;

            while (Node != null)
            {
                if ((Folder = Node as CoapFolder) != null)
                {
                    Path = Folder.Folder + "/" + Path;
                }
                else if ((Server = Node as CoapServer) != null)
                {
                    break;
                }

                Node = Node.Parent;
            }

            if (Server == null)
            {
                throw new Exception("No CoAP Server node found.");
            }

            CoapEndpoint Endpoint = Server.Endpoint;
            CoapResponse Response = Endpoint.GET(true, Server.Host, Server.Port, Path, this.query, 20000);

            return(this.ParseContent(Response.Response, Types, From, To));
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Represents a registration on an observable resource.
 /// </summary>
 /// <param name="Client">UDP Client on which the request was received.</param>
 /// <param name="Endpoint">CoAP Endpoint managing the resource.</param>
 /// <param name="Request">Request message.</param>
 internal ObservationRegistration(ClientBase Client, CoapEndpoint Endpoint,
                                  CoapMessage Request)
 {
     this.client   = Client;
     this.endpoint = Endpoint;
     this.request  = Request;
 }
Ejemplo n.º 3
0
        /// <summary>
        /// <see cref="IDisposable.Dispose"/>
        /// </summary>
        public void Dispose()
        {
            if (this.coapEndpoint != null)
            {
                if (this.state == Lwm2mState.Operation)
                {
                    this.Deregister();
                }

                foreach (Lwm2mObject Object in this.objects.Values)
                {
                    this.coapEndpoint.Unregister(Object);

                    foreach (Lwm2mObjectInstance Instance in Object.Instances)
                    {
                        this.coapEndpoint.Unregister(Instance);

                        foreach (Lwm2mResource Resource in Instance.Resources)
                        {
                            this.coapEndpoint.Unregister(Resource);
                        }
                    }
                }

                this.coapEndpoint.Unregister(this);
                this.coapEndpoint.Unregister(this.bsResource);
                this.coapEndpoint = null;

                this.objects.Clear();
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Class implementing an LWM2M client, as defined in:
        /// http://www.openmobilealliance.org/release/LightweightM2M/V1_0-20170208-A/OMA-TS-LightweightM2M-V1_0-20170208-A.pdf
        /// </summary>
        /// <param name="ClientName">Client name.</param>
        /// <param name="CoapEndpoint">CoAP endpoint to use for LWM2M communication.</param>
        /// <param name="Objects">Objects</param>
        public Lwm2mClient(string ClientName, CoapEndpoint CoapEndpoint,
                           params Lwm2mObject[] Objects)
            : base("/")
        {
            this.coapEndpoint     = CoapEndpoint;
            this.serverReferences = ServerReferences;
            this.clientName       = ClientName;
            this.state            = Lwm2mState.Bootstrap;
            this.bsResource       = new BootstreapResource(this);

            this.coapEndpoint.Register(this);
            this.coapEndpoint.Register(this.bsResource);

            foreach (Lwm2mObject Object in Objects)
            {
                if (Object.Id < 0)
                {
                    throw new ArgumentException("Invalid object ID.", nameof(Object));
                }

                if (this.objects.ContainsKey(Object.Id))
                {
                    throw new ArgumentException("An object with ID " + Object.Id + " is already registered.", nameof(Object));
                }

                this.objects[Object.Id] = Object;
                Object.Client           = this;

                this.coapEndpoint.Register(Object);
                Object.AfterRegister();
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Event arguments for CoAP response callbacks.
 /// </summary>
 /// <param name="Client">UDP Client.</param>
 /// <param name="Endpoint">CoAP Endpoint.</param>
 /// <param name="Message">CoAP message.</param>
 /// <param name="Resource">CoAP resource if relevant.</param>
 internal CoapMessageEventArgs(ClientBase Client, CoapEndpoint Endpoint, CoapMessage Message,
                               CoapResource Resource)
 {
     this.client   = Client;
     this.endpoint = Endpoint;
     this.message  = Message;
     this.resource = Resource;
 }
        /// <summary>
        /// <see cref="Clayster.Library.Internet.LineListeners.ILineListenable.LineListenerError"/>
        /// </summary>
        public void LineListenerError(string s)
        {
            CoapEndpoint Endpoint = this.Endpoint;

            if (Endpoint != null)
            {
                Endpoint.LineListenerError(s);
            }
        }
        /// <summary>
        /// <see cref="Clayster.Library.Internet.LineListeners.ILineListenable.LineListenerDataRead"/>
        /// </summary>
        public void LineListenerDataRead(string Id, byte[] Data)
        {
            CoapEndpoint Endpoint = this.Endpoint;

            if (Endpoint != null)
            {
                Endpoint.LineListenerDataRead(Id, Data);
            }
        }
        /// <summary>
        /// <see cref="Clayster.Library.Internet.LineListeners.ILineListenable.LineListenerRowRead"/>
        /// </summary>
        public void LineListenerRowRead(string Id, string Row)
        {
            CoapEndpoint Endpoint = this.Endpoint;

            if (Endpoint != null)
            {
                Endpoint.LineListenerRowRead(Id, Row);
            }
        }
        /// <summary>
        /// <see cref="Clayster.Library.Internet.LineListeners.ILineListenable.UnregisterLineListener"/>
        /// </summary>
        public void UnregisterLineListener(ILineListener Listener)
        {
            CoapEndpoint Endpoint = this.Endpoint;

            if (Endpoint != null)
            {
                Endpoint.UnregisterLineListener(Listener);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns a response to the caller.
        /// </summary>
        /// <param name="Code">CoAP message code.</param>
        /// <param name="Payload">Optional payload.</param>
        /// <param name="Block2Nr">Block index to transmit.</param>
        /// <param name="BlockSize">Block size, in case the <paramref name="Payload"/> needs to be divided into blocks.</param>
        /// <param name="Options">Optional options.</param>
        internal void Respond(CoapCode Code, byte[] Payload, int Block2Nr, int BlockSize,
                              params CoapOption[] Options)
        {
            this.endpoint.Transmit(this.client, this.remoteEndpoint, this.client.IsEncrypted,
                                   this.responded ? (ushort?)null : this.request.MessageId,
                                   this.ResponseType, Code, this.request.Token, false, Payload, Block2Nr, BlockSize,
                                   this.resource, null, null, null, null, CoapEndpoint.Merge(Options, this.additionalResponseOptions));

            this.responded = true;
        }
Ejemplo n.º 11
0
 /// <summary>
 /// CoAP response to return to a received request.
 /// </summary>
 /// <param name="Client">Client receiving the response.</param>
 /// <param name="Endpoint">CoAP Endpoint.</param>
 /// <param name="RemoteEndpoint">Remote endpoint.</param>
 /// <param name="Request">Request.</param>
 /// <param name="Notifications">How notifications are sent, if at all.</param>
 /// <param name="Resource">CoAP resource.</param>
 /// <param name="AdditionalResponseOptions">Additional response options.</param>
 internal CoapResponse(ClientBase Client, CoapEndpoint Endpoint, IPEndPoint RemoteEndpoint,
                       CoapMessage Request, Notifications Notifications, CoapResource Resource, params CoapOption[] AdditionalResponseOptions)
 {
     this.client                    = Client;
     this.endpoint                  = Endpoint;
     this.remoteEndpoint            = RemoteEndpoint;
     this.request                   = Request;
     this.notifications             = Notifications;
     this.resource                  = Resource;
     this.additionalResponseOptions = AdditionalResponseOptions;
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Returns a response to the caller.
        /// </summary>
        /// <param name="Code">CoAP message code.</param>
        /// <param name="Payload">Optional payload to be encoded.</param>
        /// <param name="BlockSize">Block size, in case the <paramref name="Payload"/> needs to be divided into blocks.</param>
        /// <param name="Options">Optional options.</param>
        public void Respond(CoapCode Code, object Payload, int BlockSize, params CoapOption[] Options)
        {
            byte[] Data = CoapEndpoint.Encode(Payload, out int ContentFormat);

            if (!CoapEndpoint.HasOption(Options, 12))
            {
                Options = CoapEndpoint.Merge(Options, new CoapOptionContentFormat((ulong)ContentFormat));
            }

            this.Respond(Code, Data, BlockSize, Options);
        }
Ejemplo n.º 13
0
        public void TestCleanup()
        {
            if (this.client != null)
            {
                ulong[]  Tokens     = this.client.GetActiveTokens();
                ushort[] MessageIDs = this.client.GetActiveMessageIDs();

                this.client.Dispose();
                this.client = null;

                Assert.AreEqual(0, Tokens.Length, "There are tokens that have not been unregistered properly.");
                Assert.AreEqual(0, MessageIDs.Length, "There are message IDs that have not been unregistered properly.");
            }
        }
Ejemplo n.º 14
0
        private void Cleanup(ref CoapEndpoint Client)
        {
            if (Client != null)
            {
                ulong[]  Tokens     = Client.GetActiveTokens();
                ushort[] MessageIDs = Client.GetActiveMessageIDs();

                Client.Dispose();
                Client = null;

                Assert.AreEqual(0, Tokens.Length, "There are tokens that have not been unregistered properly.");
                Assert.AreEqual(0, MessageIDs.Length, "There are message IDs that have not been unregistered properly.");
            }
        }
Ejemplo n.º 15
0
        public async Task TestInitialize()
        {
            this.coapClient = new CoapEndpoint(new int[] { 5783 }, new int[] { 5784 }, null, null,
                                               false, false, new TextWriterSniffer(Console.Out, BinaryPresentationMethod.Hexadecimal));

            this.lwm2mClient = new Lwm2mClient("Lwm2mTestClient", this.coapClient,
                                               new Lwm2mSecurityObject(),
                                               new Lwm2mServerObject(),
                                               new Lwm2mAccessControlObject(),
                                               new Lwm2mDeviceObject("Waher Data AB", "Unit Test", Environment.MachineName,
                                                                     Environment.OSVersion.VersionString, "PC", Environment.OSVersion.Platform.ToString(),
                                                                     Environment.Version.ToString()));

            await this.lwm2mClient.LoadBootstrapInfo();
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Decodes the payload of the message.
 /// </summary>
 /// <returns>Decoded payload.</returns>
 public object Decode()
 {
     if (this.payload == null)
     {
         return(null);
     }
     else if (!this.contentFormat.HasValue)
     {
         return(this.payload);
     }
     else
     {
         return(CoapEndpoint.Decode((int)this.contentFormat.Value, this.payload, this.baseUri));
     }
 }
Ejemplo n.º 17
0
        internal ObservationRegistration RegisterSubscription(ClientBase Client,
                                                              CoapEndpoint Endpoint, CoapMessage Message)
        {
            ObservationRegistration Result;
            string Key = Message.From.ToString() + " " + Message.Token.ToString();

            Result = new ObservationRegistration(Client, Endpoint, Message);

            lock (this.registrations)
            {
                this.registrations[Key] = Result;
                this.registeredMessages = null;
            }

            return(Result);
        }
        public CoapEndpoint GetEndpoint(string MulticastAddress)
        {
            lock (this.synchObject)
            {
                ILineListener[] LineListeners = null;

                if (this.recycle)
                {
                    this.recycle = false;
                    if (this.endpoint != null)
                    {
                        LineListeners = this.endpoint.LineListeners;
                        this.endpoint.Dispose();
                        this.endpoint = null;
                    }
                }

                if (this.endpoint == null)
                {
                    if (string.IsNullOrEmpty(MulticastAddress))
                    {
                        this.endpoint = new CoapEndpoint(this.port, this.ttl);
                    }
                    else
                    {
                        this.endpoint = new CoapEndpoint(this.port, this.ttl, MulticastAddress);
                    }

                    User User = this.User;
                    if (User != null)
                    {
                        this.endpoint.RegisterResource(new CoapTopologyBridge(User));
                    }

                    if (LineListeners != null)
                    {
                        foreach (ILineListener LL in LineListeners)
                        {
                            this.endpoint.RegisterLineListener(LL);
                        }
                    }
                }

                return(this.endpoint);
            }
        }
Ejemplo n.º 19
0
        public void TestCleanup()
        {
            if (this.lwm2mClient != null)
            {
                this.lwm2mClient.Dispose();
                this.lwm2mClient = null;
            }

            if (this.coapClient != null)
            {
                CoapResource[] Resources = this.coapClient.GetRegisteredResources();

                this.coapClient.Dispose();
                this.coapClient = null;

                Assert.AreEqual(1, Resources.Length, "There are resources still registered on the CoAP client.");
            }
        }
Ejemplo n.º 20
0
        public async Task TestSendMulticastMessagToExplicitMulticastEndpoint()
        {
            // Arrange
            var mockClientEndpoint = new Mock <MockEndpoint> {
                CallBase = true
            };

            mockClientEndpoint
            .Setup(e => e.SendAsync(It.IsAny <CoapPacket>(), It.IsAny <CancellationToken>()))
            .CallBase()
            .Verifiable("Message was not sent via multicast endpoint");

            var destEndpoint = new CoapEndpoint {
                IsMulticast = true
            };

            var message = new CoapMessage
            {
                IsMulticast = true,
                Type        = CoapMessageType.NonConfirmable,
                Code        = CoapMessageCode.Get,
                Options     = new System.Collections.Generic.List <CoapOption>
                {
                    new Options.ContentFormat(Options.ContentFormatType.ApplicationLinkFormat)
                },
                Payload = Encoding.UTF8.GetBytes("</.well-known/core>")
            };


            // Ack
            using (var client = new CoapClient(mockClientEndpoint.Object))
            {
                var ct = new CancellationTokenSource(MaxTaskTimeout);

                await client.SendAsync(message, destEndpoint, ct.Token);
            }

            // Assert
            Mock.Verify(mockClientEndpoint);
        }
Ejemplo n.º 21
0
        internal string GetUri()
        {
            string Host = null;
            int?   Port = null;
            string Path = null;

            if (!(this.options is null))
            {
                foreach (CoapOption Option in this.options)
                {
                    switch (Option.OptionNumber)
                    {
                    case 3:
                        Host = ((CoapOptionUriHost)Option).Value;
                        break;

                    case 7:
                        Port = (int)((CoapOptionUriPort)Option).Value;
                        break;

                    case 11:
                        if (Path is null)
                        {
                            Path = "/";
                        }
                        else
                        {
                            Path += "/";
                        }

                        Path += ((CoapOptionUriPath)Option).Value;
                        break;
                    }
                }
            }

            return(CoapEndpoint.GetUri(Host, Port, Path, null));
        }
Ejemplo n.º 22
0
        public void TestSendMulticastMessagtoNonMulticastEndpointThrowsCoapClientException()
        {
            // Arrange
            var mockClientEndpoint = new Mock <MockEndpoint> {
                CallBase = true
            };

            var destEndpoint = new CoapEndpoint {
                IsMulticast = false
            };

            var message = new CoapMessage
            {
                IsMulticast = true,
                Type        = CoapMessageType.NonConfirmable,
                Code        = CoapMessageCode.Get,
                Options     = new System.Collections.Generic.List <CoapOption>
                {
                    new Options.ContentFormat(Options.ContentFormatType.ApplicationLinkFormat)
                },
                Payload = Encoding.UTF8.GetBytes("</.well-known/core>")
            };

            // Ack
            AsyncTestDelegate action = async() => {
                using (var client = new CoapClient(mockClientEndpoint.Object))
                {
                    var ct = new CancellationTokenSource(MaxTaskTimeout);

                    await client.SendAsync(message, destEndpoint, ct.Token);
                }
            };

            // Assert
            Assert.ThrowsAsync <CoapClientException>(action);
        }
Ejemplo n.º 23
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=sensor.db;Version=3;";
			DB.BackupProviderName = "Clayster.Library.Data.Providers.SQLiteServer.SQLiteServerProvider";
			db = DB.GetDatabaseProxy ("TheSensor");

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

			// Initializing hardware and retrieving current sensor values

			try
			{
				tmp102.Configure (false, TexasInstrumentsTMP102.FaultQueue.ConsecutiveFaults_6, TexasInstrumentsTMP102.AlertPolarity.AlertActiveLow,
					TexasInstrumentsTMP102.ThermostatMode.ComparatorMode, false, TexasInstrumentsTMP102.ConversionRate.Hz_1, false);

				temp = (short)tmp102.ReadTemperatureRegister ();
				temperatureC = temp / 256.0;

				for (int i = 0; i < 10; i++)
					tempAvgWindow [i] = temp;

				sumTemp = temp * 10;
			} catch (Exception ex)
			{
				Log.Exception (ex);

				sumTemp = 0;
				temperatureC = 0;
				errorLed.High ();
			}

			try
			{
				adc.Configure (true, false, false, false, false, false);

				light = adc.ReadRegistersBinary () [0];
				lightPercent = (100.0 * light) / 0x0fff;

				for (int i = 0; i < 10; i++)
					lightAvgWindow [i] = light;

				sumLight = light * 10;
			} catch (Exception ex)
			{
				Log.Exception (ex);

				sumLight = 0;
				lightPercent = 0;
				errorLed.High ();
			}

			// Loading historical Sensor Values

			Log.Information ("Loading Minute Values.");
			perMinute.AddRange (Record.LoadRecords (Rank.Minute));

			Log.Information ("Loading Hour Values.");
			perHour.AddRange (Record.LoadRecords (Rank.Hour));

			Log.Information ("Loading Day Values.");
			perDay.AddRange (Record.LoadRecords (Rank.Day));

			Log.Information ("Loading Month Values.");
			perMonth.AddRange (Record.LoadRecords (Rank.Month));

			// Resuming average calculations

			int Pos = perSecond.Count;
			DateTime CurrentTime = DateTime.Now;
			DateTime Timestamp;

			while (Pos-- > 0)
			{
				Record Rec = perSecond [Pos];
				Timestamp = Rec.Timestamp;
				if (Timestamp.Minute == CurrentTime.Minute && Timestamp.Hour == CurrentTime.Hour && Timestamp.Date == CurrentTime.Date)
				{
					sumSeconds += Rec;
					nrSeconds++;
				} else
					break;
			}

			Pos = perMinute.Count;
			while (Pos-- > 0)
			{
				Record Rec = perMinute [Pos];
				Timestamp = Rec.Timestamp;
				if (Timestamp.Hour == CurrentTime.Hour && Timestamp.Date == CurrentTime.Date)
				{
					sumMinutes += Rec;
					nrMinutes++;
				} else
					break;
			}

			Pos = perHour.Count;
			while (Pos-- > 0)
			{
				Record Rec = perHour [Pos];
				Timestamp = Rec.Timestamp;
				if (Timestamp.Date == CurrentTime.Date)
				{
					sumHours += Rec;
					nrHours++;
				} else
					break;
			}

			Pos = perDay.Count;
			while (Pos-- > 0)
			{
				Record Rec = perDay [Pos];
				Timestamp = Rec.Timestamp;
				if (Timestamp.Month == CurrentTime.Month && Timestamp.Year == CurrentTime.Year)
				{
					sumDays += Rec;
					nrDays++;
				} else
					break;
			}

			// Sampling of new Sensor Values

			Timer Timer = new Timer (SampleSensorValues, null, 1000 - DateTime.Now.Millisecond, 1000);	// Every second.

			// HTTP Interface

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

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

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

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

			HttpServer.Register ("/", HttpGetRoot, HttpPostRoot, false);							// Synchronous, no authentication
			HttpServer.Register ("/html", HttpGetHtml, false);										// Synchronous, no authentication
			HttpServer.Register ("/historygraph", HttpGetHistoryGraph, false);						// Synchronous, no authentication
			HttpServer.Register ("/credentials", HttpGetCredentials, HttpPostCredentials, false);	// Synchronous, no 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 ("/event/xml", HttpGetEventXml, true, false);						// Asynchronous, http authentication
			HttpServer.Register ("/event/json", HttpGetEventJson, true, false);						// Asynchronous, http authentication
			HttpServer.Register ("/event/turtle", HttpGetEventTurtle, true, false);					// Asynchronous, http authentication
			HttpServer.Register ("/event/rdf", HttpGetEventRdf, true, false);						// Asynchronous, http authentication

			// 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 Sensor Realm", GetDigestUserPasswordHash));
			// HttpsServer.RegisterAuthenticationMethod (new SessionAuthentication ());
			// 
			// 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));
				
			CoapEndpoint.RegisterResource ("temp/txt", "Current Temperature, as text.", CoapBlockSize.BlockLimit_64Bytes, false, 30, true, (Request, Payload) =>
				{
					return FieldNumeric.Format (temperatureC, "C", 1);
				});

			motionTxt = CoapEndpoint.RegisterResource ("motion/txt", "Motion detection, as text.", CoapBlockSize.BlockLimit_64Bytes, false, 10, true, (Request, Payload) =>
				{
					return motionDetected ? "1" : "0";
				});

			CoapEndpoint.RegisterResource ("light/txt", "Current Light Density, as text.", CoapBlockSize.BlockLimit_64Bytes, false, 2, true, (Request, Payload) =>
				{
					return FieldNumeric.Format (lightPercent, "%", 1);
				});

			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

			mqttThread = new Thread (MqttThread);
			mqttThread.Name = "MQTT";
			mqttThread.Priority = ThreadPriority.BelowNormal;
			mqttThread.Start ();

			// Main loop

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

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

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

				CoapEndpoint.Dispose ();

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

				executionLed.Dispose ();
				measurementLed.Dispose ();
				errorLed.Dispose ();
				networkLed.Dispose ();
				motion.Dispose ();
				i2cBus.Dispose ();
			}

			return 0;
		}
Ejemplo n.º 24
0
		private static void MonitorCoap ()
		{
			CoapEndpoint Endpoint = new CoapEndpoint ();
			//Endpoint.RegisterLineListener (new ConsoleOutLineListenerSink (BinaryFormat.Hexadecimal));

			CoapObserver LightObserver = new CoapObserver (Endpoint, true, "192.168.0.15", CoapEndpoint.DefaultCoapPort, "light/txt", string.Empty, 2 * 5);
			CoapObserver MotionObserver = new CoapObserver (Endpoint, true, "192.168.0.15", CoapEndpoint.DefaultCoapPort, "motion/txt", string.Empty, 10 * 5);
			bool HasLightValue = false;
			bool HasMotionValue = false;

			LightObserver.OnDataReceived += (o, e) =>
			{
				string s = e.Response as string;
				double d;

				if (!string.IsNullOrEmpty (s) && s.EndsWith (" %") && XmlUtilities.TryParseDouble (s.Substring (0, s.Length - 2), out d))
				{
					lightPercent = d;
					
					if (!HasLightValue)
					{
						HasLightValue = true;
						if (HasMotionValue)
							hasValues = true;
					}

					CheckControlRules ();
				}
			};

			MotionObserver.OnDataReceived += (o, e) =>
			{
				string s = e.Response as string;
				bool b;

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

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

					CheckControlRules ();
				}
			};

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

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

								lock (synchObject)
								{
									i = lastLedMask;
								}

								Endpoint.StartPOST (true, "192.168.0.23", CoapEndpoint.DefaultCoapPort, "do/txt", string.Empty, i.ToString (), CoapBlockSize.BlockLimit_64Bytes, null, null);
								break;

							case 1:	// Update Alarm
								bool b;

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

								Endpoint.StartPOST (true, "192.168.0.23", CoapEndpoint.DefaultCoapPort, "alarm/txt", string.Empty, b ? "1" : "0", CoapBlockSize.BlockLimit_64Bytes, null, null);

								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);
					}
				}
			} finally
			{
				LightObserver.Dispose ();
				MotionObserver.Dispose ();
				Endpoint.Dispose ();
			}
		}
Ejemplo n.º 25
0
 protected virtual void SetupClientServer()
 {
     this.server            = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort }, null, null, null, false, true, new TextWriterSniffer(Console.Out, BinaryPresentationMethod.Hexadecimal));
     this.client            = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort + 2 }, null, null, null, true, false);
     this.clientCredentials = null;
 }
Ejemplo n.º 26
0
 public void TestInitialize()
 {
     this.client = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                                    new int[] { CoapEndpoint.DefaultCoapsPort }, null, null, false, false,
                                    new TextWriterSniffer(Console.Out, BinaryPresentationMethod.Hexadecimal));
 }
Ejemplo n.º 27
0
 /// <summary>
 /// Event arguments for CoAP response callbacks.
 /// </summary>
 /// <param name="Client">UDP Client.</param>
 /// <param name="Endpoint">CoAP Endpoint.</param>
 /// <param name="Ok">If the request was successful or not.</param>
 /// <param name="State">State object passed to the original request.</param>
 /// <param name="Message">Response message.</param>
 /// <param name="Resource">Resource</param>
 internal CoapResponseEventArgs(ClientBase Client, CoapEndpoint Endpoint, bool Ok, object State, CoapMessage Message, CoapResource Resource)
     : base(Client, Endpoint, Message, Resource)
 {
     this.ok    = Ok;
     this.state = State;
 }
Ejemplo n.º 28
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;
		}
Ejemplo n.º 29
0
        /// <summary>
        /// Stops the gateway.
        /// </summary>
        public static void Stop()
        {
            IDisposable Disposable;

            Log.Informational("Server shutting down.");

            /*
             * if (databaseProvider != null)
             *      File.WriteAllText(appDataFolder + "Stop.xml", databaseProvider.ExportXml(true).Result);
             */

            if (gatewayRunning != null)
            {
                gatewayRunning.Release();
                gatewayRunning.Dispose();
                gatewayRunning = null;
            }

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

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

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

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

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

            if (xmppClient != null)
            {
                using (ManualResetEvent OfflineSent = new ManualResetEvent(false))
                {
                    xmppClient.SetPresence(Availability.Offline, string.Empty, (sender, e) => OfflineSent.Set());
                    OfflineSent.WaitOne(1000);
                }

                foreach (ISniffer Sniffer in xmppClient.Sniffers)
                {
                    XmppClient.Remove(Sniffer);

                    Disposable = Sniffer as IDisposable;
                    if (Disposable != null)
                    {
                        Disposable.Dispose();
                    }
                }

                xmppClient.Dispose();
                xmppClient = null;
            }

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

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

            if (webServer != null)
            {
                foreach (ISniffer Sniffer in webServer.Sniffers)
                {
                    webServer.Remove(Sniffer);

                    Disposable = Sniffer as IDisposable;
                    if (Disposable != null)
                    {
                        Disposable.Dispose();
                    }
                }

                webServer.Dispose();
                webServer = null;
            }

            clientEvents = null;
        }
Ejemplo n.º 30
0
        /// <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);
        }
Ejemplo n.º 31
0
        private async void Init()
        {
            try
            {
                Log.Informational("Starting application.");

                Types.Initialize(
                    typeof(FilesProvider).GetTypeInfo().Assembly,
                    typeof(RuntimeSettings).GetTypeInfo().Assembly,
                    typeof(IContentEncoder).GetTypeInfo().Assembly,
                    typeof(ICoapContentFormat).GetTypeInfo().Assembly,
                    typeof(IDtlsCredentials).GetTypeInfo().Assembly,
                    typeof(App).GetTypeInfo().Assembly);

                db = new FilesProvider(Windows.Storage.ApplicationData.Current.LocalFolder.Path +
                                       Path.DirectorySeparatorChar + "Data", "Default", 8192, 1000, 8192, Encoding.UTF8, 10000);
                Database.Register(db);
                await db.RepairIfInproperShutdown(null);

                await db.Start();

                DeviceInformationCollection Devices = await UsbSerial.listAvailableDevicesAsync();

                DeviceInformation DeviceInfo = this.FindDevice(Devices, "Arduino", "USB Serial Device");
                if (DeviceInfo is null)
                {
                    Log.Error("Unable to find Arduino device.");
                }
                else
                {
                    Log.Informational("Connecting to " + DeviceInfo.Name);

                    this.arduinoUsb = new UsbSerial(DeviceInfo);
                    this.arduinoUsb.ConnectionEstablished += () =>
                                                             Log.Informational("USB connection established.");

                    this.arduino              = new RemoteDevice(this.arduinoUsb);
                    this.arduino.DeviceReady += () =>
                    {
                        Log.Informational("Device ready.");

                        this.arduino.pinMode(13, PinMode.OUTPUT);                            // Onboard LED.
                        this.arduino.digitalWrite(13, PinState.HIGH);

                        this.arduino.pinMode(8, PinMode.INPUT);                              // PIR sensor (motion detection).
                        PinState Pin8 = this.arduino.digitalRead(8);
                        this.lastMotion = Pin8 == PinState.HIGH;
                        MainPage.Instance.DigitalPinUpdated(8, Pin8);

                        this.arduino.pinMode(9, PinMode.OUTPUT);                             // Relay.
                        this.arduino.digitalWrite(9, 0);                                     // Relay set to 0

                        this.arduino.pinMode("A0", PinMode.ANALOG);                          // Light sensor.
                        MainPage.Instance.AnalogPinUpdated("A0", this.arduino.analogRead("A0"));

                        this.sampleTimer = new Timer(this.SampleValues, null, 1000 - DateTime.Now.Millisecond, 1000);
                    };

                    this.arduino.AnalogPinUpdated += (pin, value) =>
                    {
                        MainPage.Instance.AnalogPinUpdated(pin, value);
                    };

                    this.arduino.DigitalPinUpdated += (pin, value) =>
                    {
                        MainPage.Instance.DigitalPinUpdated(pin, value);

                        if (pin == 8)
                        {
                            this.lastMotion = (value == PinState.HIGH);
                            this.motionResource?.TriggerAll();
                            this.momentaryResource?.TriggerAll();
                        }
                    };

                    this.arduinoUsb.ConnectionFailed += message =>
                    {
                        Log.Error("USB connection failed: " + message);
                    };

                    this.arduinoUsb.ConnectionLost += message =>
                    {
                        Log.Error("USB connection lost: " + message);
                    };

                    this.arduinoUsb.begin(57600, SerialConfig.SERIAL_8N1);
                }

                this.deviceId = await RuntimeSettings.GetAsync("DeviceId", string.Empty);

                if (string.IsNullOrEmpty(this.deviceId))
                {
                    this.deviceId = Guid.NewGuid().ToString().Replace("-", string.Empty);
                    await RuntimeSettings.SetAsync("DeviceId", this.deviceId);
                }

                Log.Informational("Device ID: " + this.deviceId);

                /************************************************************************************
                * To create an unencrypted CoAP Endpoint on the default CoAP port:
                *
                *    this.coapEndpoint = new CoapEndpoint();
                *
                * To create an unencrypted CoAP Endpoint on the default CoAP port,
                * with a sniffer that outputs communication to the window:
                *
                *    this.coapEndpoint = new CoapEndpoint(new LogSniffer());
                *
                * To create a DTLS encrypted CoAP endpoint, on the default CoAPS port, using
                * the users defined in the IUserSource users:
                *
                *    this.coapEndpoint = new CoapEndpoint(CoapEndpoint.DefaultCoapsPort, this.users);
                *
                * To create a CoAP endpoint, that listens to both the default CoAP port, for
                * unencrypted communication, and the default CoAPS port, for encrypted,
                * authenticated and authorized communication, using
                * the users defined in the IUserSource users. Only users having the given
                * privilege (if not empty) will be authorized to access resources on the endpoint:
                *
                *    this.coapEndpoint = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                *       new int[] { CoapEndpoint.DefaultCoapsPort }, this.users, "PRIVILEGE", false, false);
                *
                ************************************************************************************/

                this.coapEndpoint = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                                                     new int[] { CoapEndpoint.DefaultCoapsPort }, this.users, string.Empty, false, false);

                this.lightResource = this.coapEndpoint.Register("/Light", (req, resp) =>
                {
                    string s;

                    if (this.lastLight.HasValue)
                    {
                        s = ToString(this.lastLight.Value, 2) + " %";
                    }
                    else
                    {
                        s = "-";
                    }

                    resp.Respond(CoapCode.Content, s, 64);
                }, Notifications.Unacknowledged, "Light, in %.", null, null,
                                                                new int[] { PlainText.ContentFormatCode });

                this.lightResource?.TriggerAll(new TimeSpan(0, 0, 5));

                this.motionResource = this.coapEndpoint.Register("/Motion", (req, resp) =>
                {
                    string s;

                    if (this.lastMotion.HasValue)
                    {
                        s = this.lastMotion.Value ? "true" : "false";
                    }
                    else
                    {
                        s = "-";
                    }

                    resp.Respond(CoapCode.Content, s, 64);
                }, Notifications.Acknowledged, "Motion detector.", null, null,
                                                                 new int[] { PlainText.ContentFormatCode });

                this.motionResource?.TriggerAll(new TimeSpan(0, 1, 0));

                this.momentaryResource = this.coapEndpoint.Register("/Momentary", (req, resp) =>
                {
                    if (req.IsAcceptable(Xml.ContentFormatCode))
                    {
                        this.ReturnMomentaryAsXml(req, resp);
                    }
                    else if (req.IsAcceptable(Json.ContentFormatCode))
                    {
                        this.ReturnMomentaryAsJson(req, resp);
                    }
                    else if (req.IsAcceptable(PlainText.ContentFormatCode))
                    {
                        this.ReturnMomentaryAsPlainText(req, resp);
                    }
                    else if (req.Accept.HasValue)
                    {
                        throw new CoapException(CoapCode.NotAcceptable);
                    }
                    else
                    {
                        this.ReturnMomentaryAsPlainText(req, resp);
                    }
                }, Notifications.Acknowledged, "Momentary values.", null, null,
                                                                    new int[] { Xml.ContentFormatCode, Json.ContentFormatCode, PlainText.ContentFormatCode });

                this.momentaryResource?.TriggerAll(new TimeSpan(0, 0, 5));
            }
            catch (Exception ex)
            {
                Log.Emergency(ex);

                MessageDialog Dialog = new MessageDialog(ex.Message, "Error");
                await MainPage.Instance.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                                            async() => await Dialog.ShowAsync());
            }
        }
Ejemplo n.º 32
0
        private async void Init()
        {
            try
            {
                Log.Informational("Starting application.");

                Types.Initialize(
                    typeof(FilesProvider).GetTypeInfo().Assembly,
                    typeof(RuntimeSettings).GetTypeInfo().Assembly,
                    typeof(IContentEncoder).GetTypeInfo().Assembly,
                    typeof(ICoapContentFormat).GetTypeInfo().Assembly,
                    typeof(IDtlsCredentials).GetTypeInfo().Assembly,
                    typeof(Lwm2mClient).GetTypeInfo().Assembly,
                    typeof(App).GetTypeInfo().Assembly);

                db = new FilesProvider(Windows.Storage.ApplicationData.Current.LocalFolder.Path +
                                       Path.DirectorySeparatorChar + "Data", "Default", 8192, 1000, 8192, Encoding.UTF8, 10000);
                Database.Register(db);
                await db.RepairIfInproperShutdown(null);

                await db.Start();

#if GPIO
                gpio = GpioController.GetDefault();
                if (gpio != null)
                {
                    if (gpio.TryOpenPin(gpioOutputPin, GpioSharingMode.Exclusive, out this.gpioPin, out GpioOpenStatus Status) &&
                        Status == GpioOpenStatus.PinOpened)
                    {
                        if (this.gpioPin.IsDriveModeSupported(GpioPinDriveMode.Output))
                        {
                            this.gpioPin.SetDriveMode(GpioPinDriveMode.Output);

                            this.output = await RuntimeSettings.GetAsync("Actuator.Output", false);

                            this.gpioPin.Write(this.output.Value ? GpioPinValue.High : GpioPinValue.Low);

                            this.digitalOutput0?.Set(this.output.Value);
                            this.actuation0?.Set(this.output.Value);
                            await MainPage.Instance.OutputSet(this.output.Value);

                            Log.Informational("Setting Control Parameter.", string.Empty, "Startup",
                                              new KeyValuePair <string, object>("Output", this.output.Value));
                        }
                        else
                        {
                            Log.Error("Output mode not supported for GPIO pin " + gpioOutputPin.ToString());
                        }
                    }
                    else
                    {
                        Log.Error("Unable to get access to GPIO pin " + gpioOutputPin.ToString());
                    }
                }
#else
                DeviceInformationCollection Devices = await UsbSerial.listAvailableDevicesAsync();

                DeviceInformation DeviceInfo = this.FindDevice(Devices, "Arduino", "USB Serial Device");
                if (DeviceInfo is null)
                {
                    Log.Error("Unable to find Arduino device.");
                }
                else
                {
                    Log.Informational("Connecting to " + DeviceInfo.Name);

                    this.arduinoUsb = new UsbSerial(DeviceInfo);
                    this.arduinoUsb.ConnectionEstablished += () =>
                                                             Log.Informational("USB connection established.");

                    this.arduino              = new RemoteDevice(this.arduinoUsb);
                    this.arduino.DeviceReady += async() =>
                    {
                        try
                        {
                            Log.Informational("Device ready.");

                            this.arduino.pinMode(13, PinMode.OUTPUT);                                // Onboard LED.
                            this.arduino.digitalWrite(13, PinState.HIGH);

                            this.arduino.pinMode(8, PinMode.INPUT);                                  // PIR sensor (motion detection).

                            this.arduino.pinMode(9, PinMode.OUTPUT);                                 // Relay.

                            this.output = await RuntimeSettings.GetAsync("Actuator.Output", false);

                            this.arduino.digitalWrite(9, this.output.Value ? PinState.HIGH : PinState.LOW);

                            this.digitalOutput0?.Set(this.output.Value);
                            this.actuation0?.Set(this.output.Value);
                            await MainPage.Instance.OutputSet(this.output.Value);

                            Log.Informational("Setting Control Parameter.", string.Empty, "Startup",
                                              new KeyValuePair <string, object>("Output", this.output.Value));

                            this.arduino.pinMode("A0", PinMode.ANALOG);                             // Light sensor.
                        }
                        catch (Exception ex)
                        {
                            Log.Critical(ex);
                        }
                    };

                    this.arduinoUsb.ConnectionFailed += message =>
                    {
                        Log.Error("USB connection failed: " + message);
                    };

                    this.arduinoUsb.ConnectionLost += message =>
                    {
                        Log.Error("USB connection lost: " + message);
                    };

                    this.arduinoUsb.begin(57600, SerialConfig.SERIAL_8N1);
                }
#endif
                this.deviceId = await RuntimeSettings.GetAsync("DeviceId", string.Empty);

                if (string.IsNullOrEmpty(this.deviceId))
                {
                    this.deviceId = Guid.NewGuid().ToString().Replace("-", string.Empty);
                    await RuntimeSettings.SetAsync("DeviceId", this.deviceId);
                }

                Log.Informational("Device ID: " + this.deviceId);

                /************************************************************************************
                * To create an unencrypted CoAP Endpoint on the default CoAP port:
                *
                *    this.coapEndpoint = new CoapEndpoint();
                *
                * To create an unencrypted CoAP Endpoint on the default CoAP port,
                * with a sniffer that outputs communication to the window:
                *
                *    this.coapEndpoint = new CoapEndpoint(new LogSniffer());
                *
                * To create a DTLS encrypted CoAP endpoint, on the default CoAPS port, using
                * the users defined in the IUserSource users:
                *
                *    this.coapEndpoint = new CoapEndpoint(CoapEndpoint.DefaultCoapsPort, this.users);
                *
                * To create a CoAP endpoint, that listens to both the default CoAP port, for
                * unencrypted communication, and the default CoAPS port, for encrypted,
                * authenticated and authorized communication, using
                * the users defined in the IUserSource users. Only users having the given
                * privilege (if not empty) will be authorized to access resources on the endpoint:
                *
                *    this.coapEndpoint = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                *       new int[] { CoapEndpoint.DefaultCoapsPort }, this.users, "PRIVILEGE", false, false);
                *
                ************************************************************************************/

                this.coapEndpoint = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                                                     new int[] { CoapEndpoint.DefaultCoapsPort }, this.users, string.Empty, false, false);

                this.outputResource = this.coapEndpoint.Register("/Output", (req, resp) =>
                {
                    string s;

                    if (this.output.HasValue)
                    {
                        s = this.output.Value ? "true" : "false";
                    }
                    else
                    {
                        s = "-";
                    }

                    resp.Respond(CoapCode.Content, s, 64);
                }, async(req, resp) =>
                {
                    try
                    {
                        string s = req.Decode() as string;
                        if (s is null && req.Payload != null)
                        {
                            s = Encoding.UTF8.GetString(req.Payload);
                        }

                        if (s is null || !CommonTypes.TryParse(s, out bool Output))
                        {
                            resp.RST(CoapCode.BadRequest);
                        }
                        else
                        {
                            resp.Respond(CoapCode.Changed);
                            await this.SetOutput(Output, req.From.ToString());
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Critical(ex);
                    }
                }, Notifications.Acknowledged, "Digital Output.", null, null,
Ejemplo n.º 33
0
        private async void Init()
        {
            try
            {
                Log.Informational("Starting application.");

                Types.Initialize(
                    typeof(FilesProvider).GetTypeInfo().Assembly,
                    typeof(RuntimeSettings).GetTypeInfo().Assembly,
                    typeof(IContentEncoder).GetTypeInfo().Assembly,
                    typeof(ICoapContentFormat).GetTypeInfo().Assembly,
                    typeof(IDtlsCredentials).GetTypeInfo().Assembly,
                    typeof(Lwm2mClient).GetTypeInfo().Assembly,
                    typeof(App).GetTypeInfo().Assembly);

                Database.Register(new FilesProvider(Windows.Storage.ApplicationData.Current.LocalFolder.Path +
                                                    Path.DirectorySeparatorChar + "Data", "Default", 8192, 1000, 8192, Encoding.UTF8, 10000));

#if GPIO
                gpio = GpioController.GetDefault();
                if (gpio != null)
                {
                    if (gpio.TryOpenPin(gpioOutputPin, GpioSharingMode.Exclusive, out this.gpioPin, out GpioOpenStatus Status) &&
                        Status == GpioOpenStatus.PinOpened)
                    {
                        if (this.gpioPin.IsDriveModeSupported(GpioPinDriveMode.Output))
                        {
                            this.gpioPin.SetDriveMode(GpioPinDriveMode.Output);

                            this.output = await RuntimeSettings.GetAsync("Actuator.Output", false);

                            this.gpioPin.Write(this.output.Value ? GpioPinValue.High : GpioPinValue.Low);

                            this.digitalOutput0?.Set(this.output.Value);
                            this.actuation0?.Set(this.output.Value);
                            await MainPage.Instance.OutputSet(this.output.Value);

                            Log.Informational("Setting Control Parameter.", string.Empty, "Startup",
                                              new KeyValuePair <string, object>("Output", this.output.Value));
                        }
                        else
                        {
                            Log.Error("Output mode not supported for GPIO pin " + gpioOutputPin.ToString());
                        }
                    }
                    else
                    {
                        Log.Error("Unable to get access to GPIO pin " + gpioOutputPin.ToString());
                    }
                }
#else
                DeviceInformationCollection Devices = await UsbSerial.listAvailableDevicesAsync();

                foreach (DeviceInformation DeviceInfo in Devices)
                {
                    if (DeviceInfo.IsEnabled && DeviceInfo.Name.StartsWith("Arduino"))
                    {
                        Log.Informational("Connecting to " + DeviceInfo.Name);

                        this.arduinoUsb = new UsbSerial(DeviceInfo);
                        this.arduinoUsb.ConnectionEstablished += () =>
                                                                 Log.Informational("USB connection established.");

                        this.arduino              = new RemoteDevice(this.arduinoUsb);
                        this.arduino.DeviceReady += async() =>
                        {
                            try
                            {
                                Log.Informational("Device ready.");

                                this.arduino.pinMode(13, PinMode.OUTPUT);                                    // Onboard LED.
                                this.arduino.digitalWrite(13, PinState.HIGH);

                                this.arduino.pinMode(8, PinMode.INPUT);                                      // PIR sensor (motion detection).

                                this.arduino.pinMode(9, PinMode.OUTPUT);                                     // Relay.

                                this.output = await RuntimeSettings.GetAsync("Actuator.Output", false);

                                this.arduino.digitalWrite(9, this.output.Value ? PinState.HIGH : PinState.LOW);

                                this.digitalOutput0?.Set(this.output.Value);
                                this.actuation0?.Set(this.output.Value);
                                await MainPage.Instance.OutputSet(this.output.Value);

                                Log.Informational("Setting Control Parameter.", string.Empty, "Startup",
                                                  new KeyValuePair <string, object>("Output", this.output.Value));

                                this.arduino.pinMode("A0", PinMode.ANALOG);                                 // Light sensor.
                            }
                            catch (Exception ex)
                            {
                                Log.Critical(ex);
                            }
                        };

                        this.arduinoUsb.ConnectionFailed += message =>
                        {
                            Log.Error("USB connection failed: " + message);
                        };

                        this.arduinoUsb.ConnectionLost += message =>
                        {
                            Log.Error("USB connection lost: " + message);
                        };

                        this.arduinoUsb.begin(57600, SerialConfig.SERIAL_8N1);
                        break;
                    }
                }
#endif
                this.deviceId = await RuntimeSettings.GetAsync("DeviceId", string.Empty);

                if (string.IsNullOrEmpty(this.deviceId))
                {
                    this.deviceId = Guid.NewGuid().ToString().Replace("-", string.Empty);
                    await RuntimeSettings.SetAsync("DeviceId", this.deviceId);
                }

                Log.Informational("Device ID: " + this.deviceId);

                /************************************************************************************
                * To create an unencrypted CoAP Endpoint on the default CoAP port:
                *
                *    this.coapEndpoint = new CoapEndpoint();
                *
                * To create an unencrypted CoAP Endpoint on the default CoAP port,
                * with a sniffer that outputs communication to the window:
                *
                *    this.coapEndpoint = new CoapEndpoint(new LogSniffer());
                *
                * To create a DTLS encrypted CoAP endpoint, on the default CoAPS port, using
                * the users defined in the IUserSource users:
                *
                *    this.coapEndpoint = new CoapEndpoint(CoapEndpoint.DefaultCoapsPort, this.users);
                *
                * To create a CoAP endpoint, that listens to both the default CoAP port, for
                * unencrypted communication, and the default CoAPS port, for encrypted,
                * authenticated and authorized communication, using
                * the users defined in the IUserSource users. Only users having the given
                * privilege (if not empty) will be authorized to access resources on the endpoint:
                *
                *    this.coapEndpoint = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                *       new int[] { CoapEndpoint.DefaultCoapsPort }, this.users, "PRIVILEGE", false, false);
                *
                ************************************************************************************/

                this.coapEndpoint = new CoapEndpoint(new int[] { CoapEndpoint.DefaultCoapPort },
                                                     new int[] { CoapEndpoint.DefaultCoapsPort }, this.users, string.Empty, false, false);

                this.outputResource = this.coapEndpoint.Register("/Output", (req, resp) =>
                {
                    string s;

                    if (this.output.HasValue)
                    {
                        s = this.output.Value ? "true" : "false";
                    }
                    else
                    {
                        s = "-";
                    }

                    resp.Respond(CoapCode.Content, s, 64);
                }, async(req, resp) =>
                {
                    try
                    {
                        string s = req.Decode() as string;
                        if (s == null && req.Payload != null)
                        {
                            s = Encoding.UTF8.GetString(req.Payload);
                        }

                        if (s == null || !CommonTypes.TryParse(s, out bool Output))
                        {
                            resp.RST(CoapCode.BadRequest);
                        }
                        else
                        {
                            resp.Respond(CoapCode.Changed);
                            await this.SetOutput(Output, req.From.ToString());
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Critical(ex);
                    }
                }, Notifications.Acknowledged, "Digital Output.", null, null,
                                                                 new int[] { PlainText.ContentFormatCode });

                this.outputResource?.TriggerAll(new TimeSpan(0, 1, 0));

                this.lwm2mClient = new Lwm2mClient("MIoT:Actuator:" + this.deviceId, this.coapEndpoint,
                                                   new Lwm2mSecurityObject(),
                                                   new Lwm2mServerObject(),
                                                   new Lwm2mAccessControlObject(),
                                                   new Lwm2mDeviceObject("Waher Data AB", "ActuatorLwm2m", this.deviceId, "1.0", "Actuator", "1.0", "1.0"),
                                                   new DigitalOutput(this.digitalOutput0 = new DigitalOutputInstance(0, this.output.HasValue && this.output.Value, "Relay")),
                                                   new Actuation(this.actuation0         = new ActuationInstance(0, this.output.HasValue && this.output.Value, "Relay")));

                this.digitalOutput0.OnRemoteUpdate += async(Sender, e) =>
                {
                    try
                    {
                        await this.SetOutput(((DigitalOutputInstance)Sender).Value, e.Request.From.ToString());
                    }
                    catch (Exception ex)
                    {
                        Log.Critical(ex);
                    }
                };

                this.actuation0.OnRemoteUpdate += async(Sender, e) =>
                {
                    try
                    {
                        await this.SetOutput(((ActuationInstance)Sender).Value, e.Request.From.ToString());
                    }
                    catch (Exception ex)
                    {
                        Log.Critical(ex);
                    }
                };

                await this.lwm2mClient.LoadBootstrapInfo();

                this.lwm2mClient.OnStateChanged += (sender, e) =>
                {
                    Log.Informational("LWM2M state changed to " + this.lwm2mClient.State.ToString() + ".");
                };

                this.lwm2mClient.OnBootstrapCompleted += (sender, e) =>
                {
                    Log.Informational("Bootstrap procedure completed.");
                };

                this.lwm2mClient.OnBootstrapFailed += (sender, e) =>
                {
                    Log.Error("Bootstrap procedure failed.");

                    this.coapEndpoint.ScheduleEvent(async(P) =>
                    {
                        try
                        {
                            await this.RequestBootstrap();
                        }
                        catch (Exception ex)
                        {
                            Log.Critical(ex);
                        }
                    }, DateTime.Now.AddMinutes(15), null);
                };

                this.lwm2mClient.OnRegistrationSuccessful += (sender, e) =>
                {
                    Log.Informational("Server registration completed.");
                };

                this.lwm2mClient.OnRegistrationFailed += (sender, e) =>
                {
                    Log.Error("Server registration failed.");
                };

                this.lwm2mClient.OnDeregistrationSuccessful += (sender, e) =>
                {
                    Log.Informational("Server deregistration completed.");
                };

                this.lwm2mClient.OnDeregistrationFailed += (sender, e) =>
                {
                    Log.Error("Server deregistration failed.");
                };

                this.lwm2mClient.OnRebootRequest += async(sender, e) =>
                {
                    Log.Warning("Reboot is requested.");

                    try
                    {
                        await this.RequestBootstrap();
                    }
                    catch (Exception ex)
                    {
                        Log.Critical(ex);
                    }
                };

                await this.RequestBootstrap();
            }
            catch (Exception ex)
            {
                Log.Emergency(ex);

                MessageDialog Dialog = new MessageDialog(ex.Message, "Error");
                await MainPage.Instance.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                                            async() => await Dialog.ShowAsync());
            }
        }