Ejemplo n.º 1
0
        public async Task <Dictionary <string, Qos> > SubscribeAsync(Dictionary <string, Qos> subscriptions, CancellationToken cancellationToken)
        {
            var builder = new MqttClientSubscribeOptionsBuilder();

            foreach (var entry in subscriptions)
            {
                builder.WithTopicFilter(entry.Key, MapQos(entry.Value));
            }

            try
            {
                var subscribeResult = await client.SubscribeAsync(builder.Build(), cancellationToken);

                var gainedQoses = new Dictionary <string, Qos>();
                foreach (var item in subscribeResult.Items)
                {
                    var gained = (int)item.ResultCode;
                    if (gained < 0 || gained > 2)
                    {
                        throw new MqttException(message: $"Subscribe [topiic={item.TopicFilter.Topic}, qos={item.TopicFilter.QualityOfServiceLevel} failed: [resultCode={item.ResultCode}].");
                    }

                    gainedQoses[item.TopicFilter.Topic] = (Qos)gained;
                }
                return(gainedQoses);
            }
            catch (Exception e)
            {
                throw new MqttException(cause: e);
            }
        }
Ejemplo n.º 2
0
        public MQTTClient()
        {
            var mqttClient = new MqttFactory().CreateMqttClient();

            var optionBuilder = new MqttClientOptionsBuilder();

            optionBuilder
            .WithClientId("c001")
            .WithTcpServer(opts =>
            {
                opts.Server = "127.0.0.1";
                opts.Port   = 108;
            })
            .WithCredentials("u001", "p001")
            .WithCleanSession(true);

            var options = optionBuilder.Build();

            mqttClient.ConnectAsync(options, CancellationToken.None).Wait();

            var recieveHander = new MsgRecieveHandler();

            mqttClient.ApplicationMessageReceivedHandler = recieveHander;


            var topicBuilder = new TopicFilterBuilder();

            topicBuilder.WithTopic("家/客厅/空调/#")
            .WithAtMostOnceQoS();
            var topicHome = topicBuilder.Build();

            var subscribOptionBuilder = new MqttClientSubscribeOptionsBuilder();

            subscribOptionBuilder.WithTopicFilter(topicHome);

            var subOpt = subscribOptionBuilder.Build();

            mqttClient.SubscribeAsync(subOpt, CancellationToken.None).Wait();

            var appMsg = new MqttApplicationMessage();

            appMsg.Topic   = "家/客厅/空调/开关";
            appMsg.Payload = Encoding.UTF8.GetBytes("我来了~");
            appMsg.QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
            appMsg.Retain = false;


            mqttClient.PublishAsync(appMsg, CancellationToken.None).Wait();
            //var appMsg = new MqttApplicationMessage("家/客厅/空调/开关",
            //    Encoding.UTF8.GetBytes("消息内容"),
            //    MqttQualityOfServiceLevel.AtMostOnce, false);
        }
Ejemplo n.º 3
0
        public RemoteMqttBroker(
            ILogger <RemoteMqttBroker> logger,
            IEventIdCreationSource eventIdCreationSource,
            IOptions <MqttNetworkOptions>?options = null)
        {
            _logger = logger;
            _eventIdCreationSource = eventIdCreationSource;

            EventId eventId = GetNextEventId();

            _logger.LogInformation(eventId, $"Creating Mqtt Client (Id: {ClientId}).");

            MqttNetworkOptions mqttNetworkOptions = options?.Value ?? MqttNetworkOptions.Default;

            mqttNetworkOptions.Host ??= MqttNetworkOptions.Default.Host !;

            if (mqttNetworkOptions.Port < 0x0000)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Port), mqttNetworkOptions.Port, "Port number too small.");
            }
            else if (mqttNetworkOptions.Port > 0xffff)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Port), mqttNetworkOptions.Port, "Port number too large.");
            }

            if (mqttNetworkOptions.Timeout < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Timeout), mqttNetworkOptions.Timeout, "Timeout timespan too small.");
            }
            else if (mqttNetworkOptions.Timeout > 99999)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Timeout), mqttNetworkOptions.Timeout, "Timeout timespan too large.");
            }

            _logger.LogInformation(eventId, $"MQTT Client Communication Timeout: {mqttNetworkOptions.Timeout} ms.");

            var clientOptionsBuilder = new MqttClientOptionsBuilder()
                                       .WithClientId(ClientId)
                                       .WithCommunicationTimeout(TimeSpan.FromSeconds(60))
                                       .WithTcpServer(mqttNetworkOptions.Host, mqttNetworkOptions.Port);

            _mqttClient = new MqttFactory().CreateMqttClient();
            _mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(eventArgs =>
            {
                _logger.LogDebug("Client Connected. Reason: " + (eventArgs.AuthenticateResult?.ReasonString ?? "null"));
            });

            _mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(eventArgs =>
            {
                _logger.LogDebug(eventArgs.Exception, "Client Disconnected. Reason: " + (eventArgs.AuthenticateResult?.ReasonString ?? "null"));
            });

            CancellationTokenSource?cancellationTokenSource = null;

            #region Connecting to remote Mqtt Broker

            try
            {
                _logger.LogInformation(eventId, $"Connecting to remote Mqtt-Broker (mqtt://{mqttNetworkOptions.Host}:{mqttNetworkOptions.Port}).");

                cancellationTokenSource = new CancellationTokenSource(TimeoutTimeSpan);
                var result = _mqttClient.ConnectAsync(clientOptionsBuilder.Build(), cancellationTokenSource.Token).GetAwaiter().GetResult();

                if (result.ResultCode != MqttClientConnectResultCode.Success)
                {
                    throw new Exception("Mqtt-Client ConnectResultCode Success expected. Actual: " + result.ResultCode);
                }
            }
            catch (OperationCanceledException)
            {
                string errorMessage = "Connect to remote Mqtt-Broker timed out.";
                _logger.LogCritical(eventId, errorMessage);
                throw new Exception(errorMessage);
            }
            catch (Exception exception)
            {
                string errorMessage = "Failed to connect to remote Mqtt-Broker.";
                _logger.LogCritical(eventId, exception, errorMessage);
                throw new Exception(errorMessage);
            }
            finally
            {
                cancellationTokenSource?.Dispose();
            }

            #endregion

            #region Subscribing to relevant Events

            try
            {
                _logger.LogInformation(eventId, $"Subscribing to relevant events.");

                MqttQualityOfServiceLevel     mqttQualityOfServiceLevel   = MqttQualityOfServiceLevel.AtLeastOnce;
                MqttClientSubscribeResultCode expectedSubscribeResultCode = MqttClientSubscribeResultCode.GrantedQoS1;

                MqttClientSubscribeOptionsBuilder subscribeOptionsBuilder = new MqttClientSubscribeOptionsBuilder()
                                                                            .WithTopicFilter(MqttTopics.TrackerHello, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.TrackerGoodbye, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientJoinAccepted, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientJoinDenied, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientRegistered, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientGoodbye, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FileInfoPublished, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionStarted, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionDelivered, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionEnded, mqttQualityOfServiceLevel);

                cancellationTokenSource = new CancellationTokenSource(TimeoutTimeSpan); //timeout
                MqttClientSubscribeResult result = _mqttClient.SubscribeAsync(subscribeOptionsBuilder.Build(), cancellationTokenSource.Token).GetAwaiter().GetResult();

                foreach (MqttClientSubscribeResultItem item in result.Items)
                {
                    if (item.ResultCode != expectedSubscribeResultCode)
                    {
                        throw new Exception($"Expected SubscribeResultCode {expectedSubscribeResultCode} for topic \"{item.TopicFilter.Topic}\". Actual: {item.ResultCode}");
                    }
                }
            }
            catch (Exception exception)
            {
                string errorMessage;

                if (exception is OperationCanceledException)
                {
                    errorMessage = "Subscribing to all relevant Events to remote Mqtt-Broker timed out.";
                    _logger.LogCritical(eventId, errorMessage);
                }
                else
                {
                    errorMessage = "Failed to subscribe to all relevant topics with expected SubscribeResultCode.";
                    _logger.LogCritical(eventId, exception, errorMessage);
                }

                try
                {
                    _logger.LogInformation("Disconnecting from remote Mqtt-Broker");
                    MqttClientDisconnectOptions disconnectOptions = new MqttClientDisconnectOptions()
                    {
                        ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                        ReasonString = errorMessage
                    };

                    cancellationTokenSource = new CancellationTokenSource(TimeoutTimeSpan);
                    _mqttClient.DisconnectAsync(disconnectOptions, cancellationTokenSource.Token).GetAwaiter().GetResult();
                }
                catch (OperationCanceledException)
                {
                    _logger.LogError(eventId, "Disconnecting from remote Mqtt-Broker timed out.");
                }
                catch (Exception disconnectException)
                {
                    _logger.LogError(eventId, disconnectException, "Disconnecting from remote Mqtt-Broker failed.");
                }
                finally
                {
                    cancellationTokenSource?.Dispose();
                }

                throw new Exception(errorMessage);
            }
            finally
            {
                cancellationTokenSource?.Dispose();
            }

            #endregion
        }