Esempio n. 1
0
        static EdgeMessage ConvertToInternalMessage(MqttPublishInfo publishInfo, string deviceId, Option <string> moduleId, string bag)
        {
            var allProperties = new Dictionary <string, string>();

            if (!string.Equals(bag, string.Empty))
            {
                UrlEncodedDictionarySerializer.Deserialize(bag, 0, allProperties);
            }

            var systemProperties = new Dictionary <string, string>();
            var properties       = new Dictionary <string, string>();

            systemProperties[SystemProperties.ConnectionDeviceId] = deviceId;
            moduleId.ForEach(id => systemProperties[SystemProperties.ConnectionModuleId] = id);

            foreach (KeyValuePair <string, string> property in allProperties)
            {
                if (SystemProperties.IncomingSystemPropertiesMap.TryGetValue(property.Key, out string systemPropertyName))
                {
                    systemProperties.Add(systemPropertyName, property.Value);
                }
                else
                {
                    properties.Add(property.Key, property.Value);
                }
            }

            var hubMessage = new EdgeMessage.Builder(publishInfo.Payload)
                             .SetProperties(properties)
                             .SetSystemProperties(systemProperties)
                             .Build();

            return(hubMessage);
        }
Esempio n. 2
0
        static string PopulateMessagePropertiesFromMessage(string topicName, Message message)
        {
            var systemProperties = new Dictionary <string, string>();

            foreach (KeyValuePair <string, object> property in message.SystemProperties)
            {
                string propertyName;
                if (FromSystemPropertiesMap.TryGetValue(property.Key, out propertyName))
                {
                    systemProperties[propertyName] = ConvertFromSystemProperties(property.Value);
                }
            }
            string properties = UrlEncodedDictionarySerializer.Serialize(new ReadOnlyMergeDictionary <string, string>(systemProperties, message.Properties));

            string msg;

            if (properties != string.Empty)
            {
                msg = topicName.EndsWith(SegmentSeparator, StringComparison.Ordinal) ? topicName + properties + SegmentSeparator : topicName + SegmentSeparator + properties;
            }
            else
            {
                msg = topicName;
            }

            return(msg);
        }
Esempio n. 3
0
        /// <summary>
        /// This method examines the <see cref="ProtocolGateway.Messaging.IMessage.Address"/> property
        /// of the <paramref name="message"/> argument - which here is an MQTT topic name - and
        /// extracts features from it that it then uses to populate the <see cref="ProtocolGateway.Messaging.IMessage.Properties"/>
        /// property.
        /// </summary>
        public bool TryParseProtocolMessagePropsFromAddress(IProtocolGatewayMessage message)
        {
            var uri = new Uri(message.Address, UriKind.Relative);
            IList <IList <KeyValuePair <string, string> > > matches = this.inboundTable
                                                                      .Select(template => template.Match(uri))
                                                                      .Where(match => match.Count > 0)
                                                                      .ToList();

            if (matches.Count > 1)
            {
                this.logger.LogWarning($"Topic name {message.Address} matches more than one route. Picking first matching route.");
            }
            else if (matches.Count == 1)
            {
                foreach (KeyValuePair <string, string> match in matches[0])
                {
                    // If the template has a key called "params" then it contains all the properties set by the user on
                    // the sent message in query string format. So get the value and parse it.
                    if (match.Key == "params")
                    {
                        UrlEncodedDictionarySerializer.Deserialize(match.Value, 0, message.Properties);
                    }
                    else
                    {
                        message.Properties.Add(match.Key, match.Value);
                    }
                }
            }

            return(matches.Count > 0);
        }
Esempio n. 4
0
        public static void PopulateMessagePropertiesFromPacket(Message message, PublishPacket publish)
        {
            message.LockToken = publish.QualityOfService == QualityOfService.AtLeastOnce ? publish.PacketId.ToString() : null;

            // Device bound messages could be in 2 formats, depending on whether it is going to the device, or to a module endpoint
            // Format 1 - going to the device - devices/{deviceId}/messages/devicebound/{properties}/
            // Format 2 - going to module endpoint - devices/{deviceId}/modules/{moduleId/endpoints/{endpointId}/{properties}/
            // So choose the right format to deserialize properties.
            string[] topicSegments     = publish.TopicName.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            string   propertiesSegment = topicSegments.Length > 6 ? topicSegments[6] : topicSegments[4];

            Dictionary <string, string> properties = UrlEncodedDictionarySerializer.Deserialize(propertiesSegment, 0);

            foreach (KeyValuePair <string, string> property in properties)
            {
                string propertyName;
                if (ToSystemPropertiesMap.TryGetValue(property.Key, out propertyName))
                {
                    message.SystemProperties[propertyName] = ConvertToSystemProperty(property);
                }
                else
                {
                    message.Properties[property.Key] = property.Value;
                }
            }
        }
        static string GetPropertyBag(IMessage message)
        {
            var properties = new Dictionary <string, string>(message.Properties);

            foreach (KeyValuePair <string, string> systemProperty in message.SystemProperties)
            {
                if (SystemProperties.OutgoingSystemPropertiesMap.TryGetValue(systemProperty.Key, out string onWirePropertyName))
                {
                    properties[onWirePropertyName] = systemProperty.Value;
                }
            }

            return(UrlEncodedDictionarySerializer.Serialize(properties));
        }
Esempio n. 6
0
        public static void PopulateMessagePropertiesFromPacket(Message message, PublishPacket publish)
        {
            message.LockToken = publish.QualityOfService == QualityOfService.AtLeastOnce ? publish.PacketId.ToString() : null;
            Dictionary <string, string> properties = UrlEncodedDictionarySerializer.Deserialize(publish.TopicName, publish.TopicName.NthIndexOf('/', 0, 4) + 1);

            foreach (KeyValuePair <string, string> property in properties)
            {
                string propertyName;
                if (ToSystemPropertiesMap.TryGetValue(property.Key, out propertyName))
                {
                    message.SystemProperties[propertyName] = ConvertToSystemProperty(property);
                }
                else
                {
                    message.Properties[property.Key] = property.Value;
                }
            }
        }
Esempio n. 7
0
        public async Task SendUpstreamMessage(string payload, IDictionary <string, string> propertyBag, CancellationToken stopToken)
        {
            var propertyUrlString = "";

            if (propertyBag != null)
            {
                propertyUrlString = UrlEncodedDictionarySerializer.Serialize(propertyBag);
            }
            var topic = $"devices/{upstreamClientCredentials.DeviceId}/messages/events/{propertyUrlString}";

            logger.LogInformation($"SendMessage: Topic {topic} with Payload {payload}");
            var msg = new MqttApplicationMessageBuilder()
                      .WithTopic(topic)
                      .WithPayload(payload)
                      .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) // qos = 1
                      .Build();

            await upstreamClient.PublishAsync(msg, stopToken);
        }
Esempio n. 8
0
        public async Task PublishLeafDeviceMessage(LocalDeviceMqttPublicationCategory category, string topicName, string payload, IDictionary <string, string> propertyBag, CancellationToken stopToken)
        {
            var propertyUrlString = "";

            if (propertyBag != null)
            {
                propertyUrlString = UrlEncodedDictionarySerializer.Serialize(propertyBag);
            }


            if (category == LocalDeviceMqttPublicationCategory.Twin)
            {
                // if topic name is null send to all topics
                foreach (var t in device.LocalDeviceMqttPublications.Twin)
                {
                    var t1 = t.Topic.Trim('/') + "/" + propertyUrlString;  // Ensure topic ends with a forward slash /

                    if (topicName == null)
                    {
                        // send to all topics
                        logger.LogInformation($"SendMessage: Topic {t1} with Payload {payload}");
                        var msg = new MqttApplicationMessageBuilder()
                                  .WithTopic(t1)
                                  .WithPayload(payload)
                                  .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) // qos = 1
                                  .Build();

                        await downstreamClient.PublishAsync(msg, stopToken);
                    }
                    else if (topicName == t.Name)
                    {
                        logger.LogInformation($"SendMessage: Topic {t1} with Payload {payload}");
                        var msg = new MqttApplicationMessageBuilder()
                                  .WithTopic(t1)
                                  .WithPayload(payload)
                                  .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) // qos = 1
                                  .Build();

                        await downstreamClient.PublishAsync(msg, stopToken);
                    }
                }
            }
        }
        public override async Task Run(MessageContext context, CancellationToken stopToken)
        {
            logger.LogInformation("To Do: Translate IoT Edge messages into controller calls");
            var e = context.MqttMessage;

            var topic = e.ApplicationMessage.Topic;

            logger.LogInformation($"Matching topic: {topic}");

            // Separate twin messages from

            // determine the message type based on the responded to topic
            var c2dMatch          = this.c2dTopicRegex.Match(topic);
            var twinResponseMatch = twinResponseTopicRegex.Match(topic);

            if (c2dMatch.Success)
            {
                var d  = c2dMatch.Groups[1].Value;
                var pb = c2dMatch.Groups[2].Value;


                logger.LogInformation($"Found c2d");

                var properties = UrlEncodedDictionarySerializer.Deserialize(pb, 0);

                var result = controller.CloudToDeviceMessage(e.ApplicationMessage, properties);
                context.Result = result;
            }
            else if (twinResponseMatch.Success)
            {
                var responseCode = twinResponseMatch.Groups[1].Value;
                var ridProperty  = twinResponseMatch.Groups[2].Value;

                var rid = ridProperty.Split('=')[1].TrimEnd('/');
                logger.LogInformation($"Twin response received with status {responseCode} and rid property {ridProperty}");

                var result = controller.DeviceTwin(e.ApplicationMessage, responseCode, rid, context.Client.TwinStateLifecycle.LastRequestId);
                context.Result = result;
            }

            await Task.CompletedTask;
        }
Esempio n. 10
0
        public async Task PublishMessage(IMqttClient client, string topic, string payload, IDictionary <string, string> propertyBag, CancellationToken stopToken)
        {
            var t = $"{topic.TrimEnd('/')}/";

            if (propertyBag != null)
            {
                var propertyUrlString = UrlEncodedDictionarySerializer.Serialize(propertyBag);

                t = $"{topic.TrimEnd('/')}/{propertyUrlString}";
            }

            logger.LogInformation($"SendMessage: Topic {topic} with Payload {payload}");
            var msg = new MqttApplicationMessageBuilder()
                      .WithTopic(topic)
                      .WithPayload(payload)
                      .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) // qos = 1
                      .Build();

            await client.PublishAsync(msg, stopToken);
        }
        public override async Task Run(MessageContext context, CancellationToken stopToken)
        {
            logger.LogInformation("To Do: Translate IoT Edge messages into controller calls");
            var e = context.MqttMessage;

            var topic = e.ApplicationMessage.Topic;

            logger.LogInformation($"Matching topic: {topic}");

            if (context.Client.GetLocalDeviceSubscriptionCategoryForTopic(topic) == Connection.LocalDeviceSubscriptionCategory.TwinRequestTopics)
            {
                logger.LogInformation($"Topic {topic} matches category {Connection.LocalDeviceSubscriptionCategory.TwinRequestTopics}");

                // Ask controller to handle twin request
                var result = controller.TwinRequest(context.Client.TwinStateLifecycle, e.ApplicationMessage);

                context.Result = result;
            }
            else
            {
                logger.LogInformation($"Topic {topic} not matched to any category");
                var result = controller.DeviceToCloudMessage(e.ApplicationMessage);

                context.Result = result;
            }

            // determine the message type based on the responded to topic
            var match = this.c2dTopicRegex.Match(topic);

            if (match.Success)
            {
                var d  = match.Groups[1].Value;
                var pb = match.Groups[2].Value;

                logger.LogInformation($"Found c2d");

                var properties = UrlEncodedDictionarySerializer.Deserialize(pb, 0);
            }

            await Task.CompletedTask;
        }
Esempio n. 12
0
        /// <summary>
        /// This method takes an endpoint reference (<paramref name="endPointUri"/>) and an
        /// Edge Hub <see cref="IMessage"/> object (<paramref name="message"/>) and builds
        /// an MQTT topic name. The <paramref name="endPointUri"/> refers to a template endpoint
        /// name. A cloud-to-device (C2D) endpoint for example might look like this -
        /// <c>devices/{deviceId}/messages/devicebound</c> where <c>{deviceId}</c> is a place
        /// holder for the identifier of the device that is receiving the C2D message.
        /// </summary>
        public bool TryBuildProtocolAddressFromEdgeHubMessage(string endPointUri, IMessage message, IDictionary <string, string> messagePropertiesToSend, out string address)
        {
            address = null;
            if (this.outboundTemplateMap.TryGetValue(endPointUri, out UriPathTemplate template))
            {
                try
                {
                    address = template.Bind(message.SystemProperties);
                    if (!string.IsNullOrWhiteSpace(address) && messagePropertiesToSend != null && messagePropertiesToSend.Count > 0)
                    {
                        address = Invariant($"{address.TrimEnd('/')}/{UrlEncodedDictionarySerializer.Serialize(messagePropertiesToSend)}");
                    }
                }
                catch (InvalidOperationException ex)
                {
                    // An InvalidOperationException exception means that one of the required
                    // template fields was not supplied in the "properties" dictionary. We
                    // handle that by simply returning false.
                    this.logger.LogWarning($"Applying properties ${message.SystemProperties.ToLogString()} on endpoint URI {endPointUri} failed with error {ex}.");
                }
            }

            return(!string.IsNullOrEmpty(address));
        }