예제 #1
0
        /// <summary>
        /// Reconnects a client after an error or if it's offline. Reconnecting, instead of creating a completely new connection,
        /// saves time.
        /// </summary>
        public async Task Reconnect()
        {
            try
            {
                this.secondTimer?.Dispose();
                this.secondTimer = null;

                if (this.state == MqttState.Connected)
                {
                    await this.DISCONNECT();
                }

                this.DisposeClient();
            }
            catch (Exception)
            {
                // Ignore
            }
            finally
            {
                this.secondTimer = null;
                this.client      = null;
            }

            this.state = MqttState.Offline;

            await this.BeginConnect();
        }
예제 #2
0
        /// <summary>
        /// Reconnects a client after an error or if it's offline. Reconnecting, instead of creating a completely new connection,
        /// saves time.
        /// </summary>
        public void Reconnect()
        {
            try
            {
                if (this.secondTimer != null)
                {
                    this.secondTimer.Dispose();
                }

                if (this.state == MqttState.Connected)
                {
                    this.DISCONNECT();
                }

                this.DisposeClient();
            }
            catch (Exception)
            {
                // Ignore
            }
            finally
            {
                this.secondTimer = null;
                this.client      = null;
            }

            this.state = MqttState.Offline;

            Task.Run(this.BeginConnect);
        }
예제 #3
0
        private async void MqttClient_OnStateChanged(object Sender, MqttState NewState)
        {
            try
            {
                switch (NewState)
                {
                case MqttState.Connected:
                    this.connectionOk = true;
                    await this.node.RemoveErrorAsync("Offline");

                    await this.node.RemoveErrorAsync("Error");

                    this.mqttClient.SUBSCRIBE("#", MqttQualityOfService.AtLeastOnce);
                    break;

                case MqttState.Error:
                    await this.node.LogErrorAsync("Error", "Connection to broker failed.");

                    this.Reconnect();
                    break;

                case MqttState.Offline:
                    await this.node.LogErrorAsync("Offline", "Connection is closed.");

                    this.Reconnect();
                    break;
                }
            }
            catch (Exception ex)
            {
                Log.Critical(ex);
            }
        }
예제 #4
0
        private Task Client_OnStateChanged(object Sender, MqttState NewState)
        {
            switch (NewState)
            {
            case MqttState.Connected:
                this.isOnline = true;

                if (string.IsNullOrEmpty(this.credentials.ObjectId))
                {
                    Database.Insert(this.credentials);
                }

                this.client.SUBSCRIBE(this.subscriptions);

                this.connected?.TrySetResult(true);
                break;

            case MqttState.Error:
            case MqttState.Offline:
                this.isOnline = false;
                this.connected?.TrySetResult(false);
                break;
            }

            this.Model.ExternalEvent(this, "OnStateChanged",
                                     new KeyValuePair <string, object>("NewState", NewState),
                                     new KeyValuePair <string, object>("Client", this.client));

            return(Task.CompletedTask);
        }
예제 #5
0
        /// <summary>
        /// Manages an MQTT connection. Implements MQTT v3.1.1, as defined in
        /// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
        /// </summary>
        /// <param name="Host">Host name or IP address of MQTT server.</param>
        /// <param name="Port">Port to connect to.</param>
        /// <param name="Tls">If TLS is used to encrypt communication.</param>
        /// <param name="UserName">User Name</param>
        /// <param name="Password">Password</param>
        /// <param name="WillTopic">Topic to publish the last will and testament, in case the connection drops unexpectedly.</param>
        /// <param name="WillQoS">Quality of Service of last will and testament, in case the connection drops unexpectedly.</param>
        /// <param name="WillRetain">If last will and testament should be retained, in case the connection drops unexpectedly.</param>
        /// <param name="WillData">Data of last will and testament, in case the connection drops unexpectedly.</param>
        /// <param name="Sniffers">Sniffers to use.</param>
        public MqttClient(string Host, int Port, bool Tls, string UserName, string Password, string WillTopic,
                          MqttQualityOfService WillQoS, bool WillRetain, byte[] WillData, params ISniffer[] Sniffers)
            : base(Sniffers)
        {
            this.host     = Host;
            this.port     = Port;
            this.tls      = Tls;
            this.userName = UserName;
            this.password = Password;
#if !WINDOWS_UWP
            this.clientCertificate = null;
#endif
            this.state      = MqttState.Offline;
            this.will       = !string.IsNullOrEmpty(WillTopic) && WillData != null;
            this.willTopic  = WillTopic;
            this.willQoS    = WillQoS;
            this.willRetain = WillRetain;
            this.willData   = WillData;

            if (this.will && this.willData.Length > 65535)
            {
                throw new ArgumentException("Will data too large.", nameof(WillData));
            }

            Task.Run(() => this.BeginConnect());
        }
예제 #6
0
        private void Mqtt_OnStateChanged(object Sender, MqttState NewState)
        {
            this.Dispatcher.Invoke(new Action(() => this.ConnectionState.Content = NewState.ToString()));

            if (NewState == MqttState.Connected)
            {
                this.Dispatcher.Invoke(new Action(() => this.mqtt.SUBSCRIBE(this.Topic.Text)));
            }
        }
예제 #7
0
 /// <summary>
 /// Manages an MQTT connection. Implements MQTT v3.1.1, as defined in
 /// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
 /// </summary>
 /// <param name="Host">Host name or IP address of MQTT server.</param>
 /// <param name="Port">Port to connect to.</param>
 /// <param name="Tls">If TLS is used to encrypt communication.</param>
 /// <param name="UserName">User Name</param>
 /// <param name="Password">Password</param>
 public MqttConnection(string Host, int Port, bool Tls, string UserName, string Password)
 {
     this.host     = Host;
     this.port     = Port;
     this.tls      = Tls;
     this.userName = UserName;
     this.password = Password;
     this.state    = MqttState.Connecting;
     this.client   = new TcpClient();
     this.client.BeginConnect(Host, Port, this.ConnectCallback, null);
 }
예제 #8
0
        /// <summary>
        /// Manages an MQTT connection. Implements MQTT v3.1.1, as defined in
        /// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
        /// </summary>
        /// <param name="Host">Host name or IP address of MQTT server.</param>
        /// <param name="Port">Port to connect to.</param>
        /// <param name="Tls">If TLS is used to encrypt communication.</param>
        /// <param name="UserName">User Name</param>
        /// <param name="Password">Password</param>
        /// <param name="Sniffers">Sniffers to use.</param>
        public MqttClient(string Host, int Port, bool Tls, string UserName, string Password, params ISniffer[] Sniffers)
            : base(Sniffers)
        {
            this.host              = Host;
            this.port              = Port;
            this.tls               = Tls;
            this.userName          = UserName;
            this.password          = Password;
            this.clientCertificate = null;
            this.state             = MqttState.Offline;

            Task.Run(() => this.BeginConnect());
        }
예제 #9
0
        public MqttClient(string Host, int Port, X509Certificate ClientCertificate, params ISniffer[] Sniffers)
#endif
            : base(Sniffers)
        {
            this.host              = Host;
            this.port              = Port;
            this.tls               = true;
            this.userName          = string.Empty;
            this.password          = string.Empty;
            this.clientCertificate = ClientCertificate;
            this.state             = MqttState.Offline;

            Task.Run(() => this.BeginConnect());
        }
예제 #10
0
        private async void RaiseOnStateChanged(MqttState State)
        {
            StateChangedEventHandler h = this.OnStateChanged;

            if (h != null)
            {
                try
                {
                    await h(this, State);
                }
                catch (Exception ex)
                {
                    this.Exception(ex);
                }
            }
        }
예제 #11
0
 private void CheckOnline(object _)
 {
     if (this.mqttClient != null)
     {
         try
         {
             MqttState State = this.mqttClient.State;
             if (State == MqttState.Offline || State == MqttState.Error)
             {
                 this.mqttClient.Reconnect();
             }
         }
         finally
         {
             this.nextCheck = Scheduler.Add(DateTime.Now.AddMinutes(1), this.CheckOnline, null);
         }
     }
 }
예제 #12
0
        private async Task DISCONNECT()
        {
            BinaryOutput Packet = new BinaryOutput();

            Packet.WriteByte((byte)MqttControlPacketType.DISCONNECT << 4);
            Packet.WriteUInt(2);

            byte[] PacketData = Packet.GetPacket();

            TaskCompletionSource <bool> Done = new TaskCompletionSource <bool>();

            await this.Write(PacketData, 0, (sender, e) =>
            {
                this.State = MqttState.Offline;
                Done.TrySetResult(true);
            });

            await Task.WhenAny(Done.Task, Task.Delay(1000));
        }
예제 #13
0
        private void DISCONNECT()
        {
            BinaryOutput Packet = new BinaryOutput();

            Packet.WriteByte((byte)MqttControlPacketType.DISCONNECT << 4);
            Packet.WriteUInt(2);

            byte[] PacketData = Packet.GetPacket();

            ManualResetEvent Done = new ManualResetEvent(false);

            this.BeginWrite(PacketData, 0, (sender, e) =>
            {
                this.State = MqttState.Offline;
                Done.Set();
            });

            Done.WaitOne(1000);
        }
예제 #14
0
        private void MqttConnection_OnStateChanged(object Sender, MqttState NewState)
        {
            if (NewState == MqttState.Connected)
            {
                this.mqttConnection.SUBSCRIBE(this.mqttNegotiationTopic);

                BinaryOutput Output = new BinaryOutput();
                Output.WriteByte(0);
                Output.WriteString(this.applicationName);

                this.localPlayer.SetEndpoints(this.p2pNetwork.ExternalEndpoint, this.p2pNetwork.LocalEndpoint);
                this.Serialize(this.localPlayer, Output);

                this.mqttConnection.PUBLISH(this.mqttNegotiationTopic, MqttQualityOfService.AtLeastOnce, false, Output);

#if LineListener
                Console.Out.WriteLine("Tx: HELLO(" + this.localPlayer.ToString() + ")");
#endif
            }
        }
예제 #15
0
        private void EndDisconnect(IAsyncResult ar)
        {
            ManualResetEvent Done = (ManualResetEvent)ar.AsyncState;

            try
            {
                if (!(this.stream is null))
                {
                    this.stream.EndWrite(ar);
                }

                this.State = MqttState.Offline;
            }
            catch (Exception ex)
            {
                this.ConnectionError(ex);
            }
            finally
            {
                Done.Set();
            }
        }
예제 #16
0
 private async void CheckOnline(object _)
 {
     try
     {
         if (this.mqttClient != null)
         {
             MqttState State = this.mqttClient.State;
             if (State == MqttState.Offline || State == MqttState.Error)
             {
                 await this.mqttClient.Reconnect();
             }
         }
     }
     catch (Exception ex)
     {
         Log.Critical(ex);
     }
     finally
     {
         this.nextCheck = Scheduler.Add(DateTime.Now.AddMinutes(1), this.CheckOnline, null);
     }
 }
예제 #17
0
        private void Client_OnStateChanged(object Sender, MqttState NewState)
        {
            switch (NewState)
            {
            case MqttState.Connected:
                uint i;

                lock (this.synchObj)
                {
                    i = this.eventsLost;
                    this.eventsLost = 0;

                    this.connected = true;
                }

                if (i > 0)
                {
                    Log.Notice(i.ToString() + " events lost while MQTT connection was down.",
                               this.ObjectID, string.Empty, "EventsLost", new KeyValuePair <string, object>("Nr", i));
                }
                break;

            case MqttState.Offline:
                bool ImmediateReconnect;
                lock (this.synchObj)
                {
                    ImmediateReconnect = this.connected;
                    this.connected     = false;
                }

                if (ImmediateReconnect && this.timer != null)
                {
                    this.client.Reconnect();
                }
                break;
            }
        }
예제 #18
0
		private void EndDisconnect(IAsyncResult ar)
		{
			ManualResetEvent Done = (ManualResetEvent)ar.AsyncState;
			try
			{
				if (this.stream != null)
					this.stream.EndWrite(ar);

				this.State = MqttState.Offline;
			}
			catch (Exception ex)
			{
				this.ConnectionError(ex);
			}
			finally
			{
				Done.Set();
			}
		}
		private void mqttConnection_OnStateChanged(MqttConnection Sender, MqttState NewState)
		{
			if (NewState == MqttState.Connected)
			{
				this.mqttConnection.SUBSCRIBE(this.mqttNegotiationTopic);

				BinaryOutput Output = new BinaryOutput();
				Output.WriteByte(0);
				Output.WriteString(this.applicationName);

				this.localPlayer.SetEndpoints(this.p2pNetwork.ExternalEndpoint, this.p2pNetwork.LocalEndpoint);
				this.Serialize(this.localPlayer, Output);

				this.mqttConnection.PUBLISH(this.mqttNegotiationTopic, MqttQualityOfService.AtLeastOne, false, Output);

#if LineListener
				Console.Out.WriteLine("Tx: HELLO(" + this.localPlayer.ToString() + ")");
#endif
			}
		}
예제 #20
0
		/// <summary>
		/// Manages an MQTT connection. Implements MQTT v3.1.1, as defined in
		/// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
		/// </summary>
		/// <param name="Host">Host name or IP address of MQTT server.</param>
		/// <param name="Port">Port to connect to.</param>
		/// <param name="Tls">If TLS is used to encrypt communication.</param>
		/// <param name="UserName">User Name</param>
		/// <param name="Password">Password</param>
		public MqttConnection(string Host, int Port, bool Tls, string UserName, string Password)
		{
			this.host = Host;
			this.port = Port;
			this.tls = Tls;
			this.userName = UserName;
			this.password = Password;
			this.state = MqttState.Connecting;
			this.client = new TcpClient();
			this.client.BeginConnect(Host, Port, this.ConnectCallback, null);
		}