public async Task StartAsyncSubscribesToTopics()
        {
            // Arrange
            var mockMqttConnection            = new Mock <IMqttConnection>();
            var mockTriggeredFunctionExecutor = new Mock <ITriggeredFunctionExecutor>();

            mockMqttConnection
            .Setup(x => x.SubscribeAsync(It.IsAny <MqttTopicFilter[]>()))
            .Returns(Task.CompletedTask);

            mockTriggeredFunctionExecutor
            .Setup(x => x.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()));

            var topicFilter = new MqttTopicFilter[] { new MqttTopicFilter()
                                                      {
                                                          Topic = "test/topic", QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce
                                                      } };
            var mqttListener = new MqttListener(mockMqttConnection.Object, topicFilter, mockTriggeredFunctionExecutor.Object, _mockLogger.Object);

            // Act
            await mqttListener.StartAsync(_cancellationToken).ConfigureAwait(false);

            await mqttListener.OnMessage(new MqttMessageReceivedEventArgs(DefaultMessage)); // Shouldnt we be able to raise the IMqttConnection.OnMessageEventHandler??

            // Assert
            mockMqttConnection.VerifyAll();
            mockTriggeredFunctionExecutor.VerifyAll();
        }
示例#2
0
        private async void Subscribe(object sender, RoutedEventArgs e)
        {
            try
            {
                var qos = MqttQualityOfServiceLevel.AtMostOnce;
                if (SubscribeQoS1.IsChecked == true)
                {
                    qos = MqttQualityOfServiceLevel.AtLeastOnce;
                }

                if (SubscribeQoS2.IsChecked == true)
                {
                    qos = MqttQualityOfServiceLevel.ExactlyOnce;
                }

                var topicFilter = new MqttTopicFilter {
                    Topic = SubscribeTopic.Text, QualityOfServiceLevel = qos
                };

                if (_mqttClient != null)
                {
                    await _mqttClient.SubscribeAsync(topicFilter);
                }

                if (_managedMqttClient != null)
                {
                    await _managedMqttClient.SubscribeAsync(topicFilter);
                }
            }
            catch (Exception exception)
            {
                Trace.Text += exception + Environment.NewLine;
            }
        }
        public async Task StopAsyncUnsubscribesToTopics()
        {
            // Arrange
            var mockMqttConnection            = new Mock <IMqttConnection>();
            var mockTriggeredFunctionExecutor = new Mock <ITriggeredFunctionExecutor>();

            mockMqttConnection
            .Setup(x => x.SubscribeAsync(It.IsAny <MqttTopicFilter[]>()))
            .Returns(Task.CompletedTask);

            mockMqttConnection
            .Setup(x => x.UnubscribeAsync(It.IsAny <string[]>()))
            .Returns(Task.CompletedTask);

            var topicFilter = new MqttTopicFilter[] { new MqttTopicFilter()
                                                      {
                                                          Topic = "test/topic", QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce
                                                      } };
            var mqttListener = new MqttListener(mockMqttConnection.Object, topicFilter, mockTriggeredFunctionExecutor.Object, _mockLogger.Object);

            // Act
            await mqttListener.StartAsync(_cancellationToken).ConfigureAwait(false);

            await mqttListener.StopAsync(_cancellationToken).ConfigureAwait(false);

            // Assert
            mockMqttConnection.VerifyAll();
        }
        async Task <InterceptingSubscriptionEventArgs> InterceptSubscribe(MqttTopicFilter topicFilter, CancellationToken cancellationToken)
        {
            var eventArgs = new InterceptingSubscriptionEventArgs
            {
                ClientId          = _session.Id,
                TopicFilter       = topicFilter,
                SessionItems      = _session.Items,
                Session           = new MqttSessionStatus(_session),
                CancellationToken = cancellationToken
            };

            if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
            {
                eventArgs.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS0;
            }
            else if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
            {
                eventArgs.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS1;
            }
            else if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
            {
                eventArgs.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS2;
            }

            if (topicFilter.Topic.StartsWith("$share/"))
            {
                eventArgs.Response.ReasonCode = MqttSubscribeReasonCode.SharedSubscriptionsNotSupported;
            }
            else
            {
                await _eventContainer.InterceptingSubscriptionEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
            }

            return(eventArgs);
        }
示例#5
0
        private MqttTopicFilter CreateTopicFilter(
            string topic,
            MqttQualityOfServiceLevel?qualityOfServiceLevel = null,
            bool?noLocal                      = null,
            bool?retainAsPublished            = null,
            MqttRetainHandling?retainHandling = null)
        {
            var result = new MqttTopicFilter
            {
                Topic = TopicFilterSanitizer.SanitizeTopic(topic)
            };

            if (qualityOfServiceLevel.HasValue)
            {
                result.QualityOfServiceLevel = qualityOfServiceLevel.Value;
            }

            if (noLocal.HasValue)
            {
                result.NoLocal = noLocal.Value;
            }

            if (retainAsPublished.HasValue)
            {
                result.RetainAsPublished = retainAsPublished.Value;
            }

            if (retainHandling.HasValue)
            {
                result.RetainHandling = retainHandling.Value;
            }

            return(result);
        }
        public async Task MessageForOtherTopicThanSubscribedToIsProcessed()
        {
            // Arrange
            var mockMqttConnection            = new Mock <IMqttConnection>();
            var mockTriggeredFunctionExecutor = new Mock <ITriggeredFunctionExecutor>();

            mockMqttConnection
            .Setup(x => x.SubscribeAsync(It.IsAny <MqttTopicFilter[]>()))
            .Returns(Task.CompletedTask);

            mockTriggeredFunctionExecutor
            .Setup(x => x.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()));

            var topicFilter = new MqttTopicFilter[] { new MqttTopicFilter()
                                                      {
                                                          Topic = "test/topic", QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce
                                                      } };
            var mqttListener = new MqttListener(mockMqttConnection.Object, topicFilter, mockTriggeredFunctionExecutor.Object, _mockLogger.Object);

            // Act
            await mqttListener.StartAsync(_cancellationToken).ConfigureAwait(false);

            var message = new MqttMessage("weird", new byte[] { }, MqttQualityOfServiceLevel.AtLeastOnce, true);
            await mqttListener.OnMessage(new MqttMessageReceivedEventArgs(message));

            // Assert
            mockMqttConnection.VerifyAll();
            mockTriggeredFunctionExecutor.VerifyAll();
        }
示例#7
0
        static async Task Main(string[] args)
        {
            var mqttFactory = new MqttFactory();

            var tlsOptions = new MqttClientTlsOptions
            {
                UseTls = false,
                IgnoreCertificateChainErrors      = true,
                IgnoreCertificateRevocationErrors = true,
                AllowUntrustedCertificates        = true
            };

            var options = new MqttClientOptions
            {
                ClientId        = "Note",
                ProtocolVersion = MqttProtocolVersion.V311,
                ChannelOptions  = new MqttClientTcpOptions
                {
                    Server     = "xx.xx.xx.xx",
                    Port       = 1883,
                    TlsOptions = tlsOptions
                }
            };

            if (options.ChannelOptions == null)
            {
                throw new InvalidOperationException();
            }

            options.Credentials = new MqttClientCredentials
            {
                Username = "******",
                Password = Encoding.UTF8.GetBytes("123456")
            };

            var topicFilter = new MqttTopicFilter {
                Topic = "esp32/dht/temperature"
            };


            options.CleanSession    = true;
            options.KeepAlivePeriod = TimeSpan.FromSeconds(5);

            managedMqttClientSubscriber = mqttFactory.CreateManagedMqttClient();
            managedMqttClientSubscriber.ConnectedHandler    = new MqttClientConnectedHandlerDelegate(OnSubscriberConnected);
            managedMqttClientSubscriber.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnSubscriberDisconnected);
            managedMqttClientSubscriber.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(OnSubscriberMessageReceived);

            await managedMqttClientSubscriber.SubscribeAsync(topicFilter);

            await managedMqttClientSubscriber.StartAsync(
                new ManagedMqttClientOptions
            {
                ClientOptions = options
            });

            while (true)
            {
            }
        }
示例#8
0
        Subscription CreateSubscription(MqttTopicFilter topicFilter, MqttSubscribePacket subscribePacket)
        {
            var subscription = new Subscription
            {
                Topic                 = topicFilter.Topic,
                NoLocal               = topicFilter.NoLocal,
                RetainHandling        = topicFilter.RetainHandling,
                RetainAsPublished     = topicFilter.RetainAsPublished,
                QualityOfServiceLevel = topicFilter.QualityOfServiceLevel,
                Identifier            = subscribePacket.Properties?.SubscriptionIdentifier ?? 0
            };

            _subscriptionsLock.EnterWriteLock();
            try
            {
                subscription.IsNewSubscription    = !_subscriptions.ContainsKey(topicFilter.Topic);
                _subscriptions[topicFilter.Topic] = subscription;
            }
            finally
            {
                _subscriptionsLock.ExitWriteLock();
            }

            return(subscription);
        }
        public MqttClientUnsubscribeOptionsBuilder WithTopicFilter(MqttTopicFilter topicFilter)
        {
            if (topicFilter is null)
            {
                throw new ArgumentNullException(nameof(topicFilter));
            }

            return(WithTopicFilter(topicFilter.Topic));
        }
示例#10
0
 public MyMqttClient(string clientId, string host, int port, string topic)
     : this(clientId, host, port)
 {
     if (!string.IsNullOrWhiteSpace(topic))
     {
         _topics = new MqttTopicFilterBuilder()
                   .WithTopic(topic)
                   .Build();
     }
 }
示例#11
0
    /// <summary>
    /// The method that handles the button click to subscribe to a certain topic.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The event args.</param>
    private async void ButtonSubscribeClick(object sender, EventArgs e)
    {
        var topicFilter = new MqttTopicFilter {
            Topic = this.TextBoxTopicSubscribed.Text.Trim()
        };

        await this.managedMqttClientSubscriber.SubscribeAsync(topicFilter);

        MessageBox.Show("Topic " + this.TextBoxTopicSubscribed.Text.Trim() + " is subscribed", "Notice", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
示例#12
0
        public async Task TestValidateSubscription()
        {
            // Add users to users dictionary to simulate that the connection was established successfully:
            var users = new Dictionary <string, User>
            {
                {
                    "Test",
                    new User
                    {
                        Id               = User1Id,
                        UserName         = "******",
                        ValidateClientId = false
                    }
                }
            };

            // Test user
            var mqttTopicFilter = new MqttTopicFilter
            {
                Topic = "d/e",
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce
            };

            var mqttConnectionValidatorContext = new MqttSubscriptionInterceptorContext("Test", mqttTopicFilter, new Dictionary <object, object>());

            var blacklist = await this.userRepository.GetBlacklistItemsForUser(User1Id, BlacklistWhitelistType.Subscribe);

            var whitelist = await this.userRepository.GetWhitelistItemsForUser(User1Id, BlacklistWhitelistType.Subscribe);

            var result = this.mqttValidator.ValidateSubscription(
                mqttConnectionValidatorContext,
                blacklist,
                whitelist,
                users["Test"],
                ClientIdPrefixes);

            Assert.IsTrue(result);

            mqttTopicFilter = new MqttTopicFilter
            {
                Topic = "e",
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce
            };

            mqttConnectionValidatorContext = new MqttSubscriptionInterceptorContext("Test", mqttTopicFilter, new Dictionary <object, object>());

            result = this.mqttValidator.ValidateSubscription(
                mqttConnectionValidatorContext,
                blacklist,
                whitelist,
                users["Test"],
                ClientIdPrefixes);

            Assert.IsTrue(result);
        }
        async Task <MqttSubscriptionInterceptorContext> InterceptSubscribeAsync(MqttTopicFilter topicFilter)
        {
            var context = new MqttSubscriptionInterceptorContext(_clientSession.ClientId, topicFilter, _clientSession.Items);

            if (_options.SubscriptionInterceptor != null)
            {
                await _options.SubscriptionInterceptor.InterceptSubscriptionAsync(context).ConfigureAwait(false);
            }

            return(context);
        }
示例#14
0
        private async void btn_subscribe_Click(object sender, EventArgs e)
        {
            string SubscribeTopic = txt_subscribe_topic.Text.Trim();
            int    level          = box_level_subscribe.SelectedIndex;
            var    topicFilter    = new MqttTopicFilter {
                Topic = SubscribeTopic, QualityOfServiceLevel = (MqttQualityOfServiceLevel)level
            };
            await client.SubscribeAsync(topicFilter);

            MessageBox.Show("主题:" + SubscribeTopic + " 订阅成功", title, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        public MqttClientService(IMqttClient mqttClient, IMqttClientOptions options, string[] topics)
        {
            _mqttClient = mqttClient;
            _options    = options;
            MqttTopicFilterBuilder topicFilterBuilder = new MqttTopicFilterBuilder();

            for (int i = 0; i < topics.Length; i++)
            {
                topicFilterBuilder.WithTopic(topics[i]);
            }
            _topicFilter = topicFilterBuilder.Build();
        }
示例#16
0
        public MainPage()
        {
            this.InitializeComponent();

            GetLamps();

            var factory = new MqttFactory();

            mqttClient = factory.CreateMqttClient();

            var options = new MqttClientOptionsBuilder()
                          .WithTcpServer(DomoticzUrl, 1883)
                          .Build();

            System.Threading.CancellationToken cancellationToken;
            mqttClient.ConnectAsync(options, cancellationToken);

            mqttClient.UseConnectedHandler(async e => {
                MqttTopicFilter topicFilter = new MqttTopicFilter();
                topicFilter.Topic           = "domoticz/out";
                await mqttClient.SubscribeAsync(topicFilter);
            });

            mqttClient.UseApplicationMessageReceivedHandler(async e => {
                dynamic json = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(e.ApplicationMessage.Payload));
                Lamp lamp    = LampCollection.FirstOrDefault(lc => lc.IDX == (uint)json.idx);
                if (lamp != null)
                {
                    Debug.WriteLine($"{lamp.Name} has updated! NValue: {json.nvalue}, SValue: {json.svalue1}");
                    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                                                                                                () => {
                        if (lamp.Dimmable)
                        {
                            if (lamp.ColorLamp)
                            {
                                lamp.SetStatus((uint)json.nvalue, (uint)json.svalue1, (byte)json.Color.r, (byte)json.Color.g, (byte)json.Color.b);
                            }
                            else
                            {
                                lamp.SetStatus((uint)json.nvalue, (uint)json.svalue1);
                            }
                        }
                        else
                        {
                            lamp.SetStatus((uint)json.nvalue);
                        }
                    });
                }
            });
        }
        public MqttClientSubscribeOptionsBuilder WithTopicFilter(MqttTopicFilter topicFilter)
        {
            if (topicFilter == null)
            {
                throw new ArgumentNullException(nameof(topicFilter));
            }

            if (_subscribeOptions.TopicFilters == null)
            {
                _subscribeOptions.TopicFilters = new List <MqttTopicFilter>();
            }

            _subscribeOptions.TopicFilters.Add(topicFilter);

            return(this);
        }
示例#18
0
        public void Test()
        {
            var sub = new string[] { "/test/#", "/test/+/test/test", "/test/+/#" };

            var pub = "/test/test/test/test";

            foreach (var item in sub)
            {
                Assert.True(MqttTopicFilter.Matches(pub, item));
            }
            var sub1 = new string[] { "test/#", "/test/sss/test/test", "/test//#" };

            foreach (var item in sub1)
            {
                Assert.False(MqttTopicFilter.Matches(pub, item));
            }
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            logger.LogInformation("executing task");

            if (mqttClient.IsConnected == false)
            {
                logger.LogWarning("publishing failed, trying to connect ...");
                await Connect();

                if (!mqttClient.IsConnected)
                {
                    logger.LogError("unable to connect to broker");
                    return;
                }
            }

            string[] strTopics = { "sensor/0/temperature", "sensor/0/humidity" };

            MqttClientSubscribeOptions objSubOptions = new MqttClientSubscribeOptions();

            List <MqttTopicFilter> objTopics = new List <MqttTopicFilter>();

            foreach (string strTopic in strTopics)
            {
                MqttTopicFilter objAdd = new MqttTopicFilter
                {
                    Topic = strTopic
                };
                objTopics.Add(objAdd);
            }

            objSubOptions.TopicFilters = objTopics;
            await mqttClient.SubscribeAsync(objSubOptions).ConfigureAwait(false); //!!!!subscribe goes here!!!!

            var message = new MqttApplicationMessageBuilder()
                          //here it does send the message
                          .WithTopic("hc")
                          .WithPayload("I'm ok")
                          .WithExactlyOnceQoS()
                          .WithRetainFlag()
                          .Build();

            await mqttClient.PublishAsync(message);

            return;
        }
示例#20
0
        static void Test1()
        {
            var sub = new string[] { "/test/#", "/test/+/test/test", "/test/+/#" };

            var pub = "/test/test/test/test";

            foreach (var item in sub)
            {
                XTrace.WriteLine(MqttTopicFilter.Matches(pub, item) + "");
            }
            var sub1 = new string[] { "test/#", "/test/sss/test/test", "/test//#" };

            foreach (var item in sub1)
            {
                XTrace.WriteLine(MqttTopicFilter.Matches(pub, item) + "");
            }
        }
示例#21
0
        public async Task SafeNotifyClientSubscribedTopicAsync(string clientId, MqttTopicFilter topicFilter)
        {
            try
            {
                var handler = ClientSubscribedTopicHandler;
                if (handler == null)
                {
                    return;
                }

                await handler.HandleClientSubscribedTopicAsync(new MqttServerClientSubscribedTopicEventArgs(clientId, topicFilter)).ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                _logger.Error(exception, "Error while handling custom 'ClientSubscribedTopic' event.");
            }
        }
示例#22
0
        async Task <MqttSubscriptionInterceptorContext> InterceptSubscribe(MqttTopicFilter topicFilter)
        {
            var interceptor = _options.SubscriptionInterceptor;

            if (interceptor == null)
            {
                return(null);
            }

            var context = new MqttSubscriptionInterceptorContext
            {
                ClientId     = _clientSession.ClientId,
                TopicFilter  = topicFilter,
                SessionItems = _clientSession.Items
            };

            await interceptor.InterceptSubscriptionAsync(context).ConfigureAwait(false);

            return(context);
        }
示例#23
0
        public async Task ConnectAsync()
        {
            var mqttClient = new MqttFactory().CreateMqttClient();

            mqttClient.UseApplicationMessageReceivedHandler(e => { HandleMessage(e.ApplicationMessage); });
            mqttClient.UseDisconnectedHandler(e => { HandleDisconnect(e.AuthenticateResult); });
            var topicFilter = new MqttTopicFilter
            {
                Topic = _mqttTopic
            };

            var options = new MqttClientOptionsBuilder()
                          .WithClientId(_clientId)
                          .WithTcpServer(_mqttServer, 1883)
                          .WithCredentials(_mqttUser, _mqttPassword)
                          .WithCleanSession()
                          .Build();

            mqttClient.ConnectAsync(options, CancellationToken.None).Wait();
            await mqttClient.SubscribeAsync(topicFilter);
        }
示例#24
0
        public async void Subscribe(string topic)
        {
            if (_mqttClient == null || !_mqttClient.IsConnected)
            {
                return;
            }
            if (!string.IsNullOrWhiteSpace(topic))
            {
                MqttTopicFilter builder = new MqttTopicFilter();

                builder.Topic = topic;
                builder.QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce;
                try
                {
                    await _mqttClient.SubscribeAsync(builder);
                }
                catch (Exception)
                {
                    throw new TimeoutException();
                }
            }
        }
示例#25
0
        static MqttBasePacket DecodeSubscribePacket(IMqttPacketBodyReader body)
        {
            ThrowIfBodyIsEmpty(body);

            var packet = new MqttSubscribePacket
            {
                PacketIdentifier = body.ReadTwoByteInteger()
            };

            while (!body.EndOfStream)
            {
                var topicFilter = new MqttTopicFilter
                {
                    Topic = body.ReadStringWithLengthPrefix(),
                    QualityOfServiceLevel = (MqttQualityOfServiceLevel)body.ReadByte()
                };

                packet.TopicFilters.Add(topicFilter);
            }

            return(packet);
        }
示例#26
0
        private static List <MqttTopicFilter> GetTopicsToSubscribe(string topicBase, int bucktesCount)
        {
            var res = new List <MqttTopicFilter>(bucktesCount + 1);

            var topicInfo = new MqttTopicFilter()
            {
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
                Topic = $"{topicBase}/info"
            };

            res.Add(topicInfo);

            for (int i = 1; i <= bucktesCount; ++i)
            {
                var topicBucket = new MqttTopicFilter()
                {
                    QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
                    Topic = $"{topicBase}/data{i - 1}"
                };
                res.Add(topicBucket);
            }

            return(res);
        }
示例#27
0
        MqttPacket DecodeSubscribePacket(ArraySegment <byte> body)
        {
            ThrowIfBodyIsEmpty(body);

            _bufferReader.SetBuffer(body.Array, body.Offset, body.Count);

            var packet = new MqttSubscribePacket
            {
                PacketIdentifier = _bufferReader.ReadTwoByteInteger()
            };

            while (!_bufferReader.EndOfStream)
            {
                var topicFilter = new MqttTopicFilter
                {
                    Topic = _bufferReader.ReadString(),
                    QualityOfServiceLevel = (MqttQualityOfServiceLevel)_bufferReader.ReadByte()
                };

                packet.TopicFilters.Add(topicFilter);
            }

            return(packet);
        }
        private static MqttClientSubscribeResultItem MapSubscribeResultItem(MqttTopicFilter topicFilter)
        {
            MqttClientSubscribeResultCode resultCode;

            switch (topicFilter.QualityOfServiceLevel)
            {
            case MqttQualityOfServiceLevel.AtMostOnce:
                resultCode = MqttClientSubscribeResultCode.GrantedQoS0;
                break;

            case MqttQualityOfServiceLevel.AtLeastOnce:
                resultCode = MqttClientSubscribeResultCode.GrantedQoS1;
                break;

            case MqttQualityOfServiceLevel.ExactlyOnce:
                resultCode = MqttClientSubscribeResultCode.GrantedQoS2;
                break;

            default:
                throw new InvalidOperationException("Invalid QualityOfServiceLevel.");
            }

            return(new MqttClientSubscribeResultItem(topicFilter, resultCode));
        }
 public MqttServerClientSubscribedTopicEventArgs(string clientId, MqttTopicFilter topicFilter)
 {
     ClientId    = clientId ?? throw new ArgumentNullException(nameof(clientId));
     TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
 }
 public MqttSubscriptionInterceptorContext(string clientId, MqttTopicFilter topicFilter, IDictionary <object, object> sessionItems)
 {
     ClientId     = clientId;
     TopicFilter  = topicFilter;
     SessionItems = sessionItems;
 }