private async Task ReceiveHubMessagesAsync() { using (Message receivedMessage = await DeviceClient.ReceiveAsync(TimeSpan.FromSeconds(30)).ConfigureAwait(false)) { if (receivedMessage == null) { Console.WriteLine("\t{0}> Timed out", DateTime.Now.ToLocalTime()); return; } var message = new MqttApplicationMessageBuilder() .WithPayload(receivedMessage.GetBytes()); string payload = Encoding.ASCII.GetString(receivedMessage.GetBytes()); Console.WriteLine("\t{0}> Received message: {1}", DateTime.Now.ToLocalTime(), payload); if (receivedMessage.Properties.ContainsKey("topic")) { message.WithTopic(receivedMessage.Properties["topic"]); } var keyExclude = new string[] { "topic", "clientId" }; foreach (var prop in receivedMessage.Properties.Where(k => !keyExclude.Contains(k.Key))) { message.WithUserProperty(prop.Key, prop.Value); } await LocalClient.PublishAsync(message.Build(), CancellationToken.None); await DeviceClient.CompleteAsync(receivedMessage).ConfigureAwait(false); } }
public async Task PublishAsync(string topic, byte[] payload, Dictionary <string, string> properties, Qos qos, CancellationToken cancellationToken) { var mqttMessageBuilder = new MqttApplicationMessageBuilder() .WithTopic(topic) .WithPayload(payload) .WithQualityOfServiceLevel(MapQos(qos)); if (properties != null) { foreach (var entry in properties) { mqttMessageBuilder.WithUserProperty(entry.Key, entry.Value); } } MqttClientPublishResult publishResult; try { publishResult = await client.PublishAsync(mqttMessageBuilder.Build(), cancellationToken); } catch (Exception e) { throw new MqttException(cause: e); } ValidatePublishResult(publishResult); }
private async Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs) { if (!eventArgs.ApplicationMessage.Topic.Contains(GetRequestTopic(null, null))) { return; } var message = eventArgs.ApplicationMessage; var methodName = message.GetUserProperty("Method"); var id = message.GetUserProperty("Id"); var timeout = message.GetUserProperty <int?>("Timeout"); var broadcast = message.GetUserProperty <bool?>("Broadcast") ?? false; var noResponse = message.GetUserProperty <bool?>("NoResponse") ?? false; var clientId = GetSource(message.Topic); using var serviceScope = _serviceProvider.CreateScope(); using var cts = timeout.HasValue ? new CancellationTokenSource(timeout.Value * 1000) : new CancellationTokenSource(); var responseBuilder = new MqttApplicationMessageBuilder() .WithContentType(DefaultSerializer.ContentType) .WithTopic(GetResponseTopic(GetSource(message.Topic))) .WithAtLeastOnceQoS(); if (broadcast) { responseBuilder.WithUserProperty("Broadcast", true.ToString()); } if (timeout > 0) { responseBuilder.WithMessageExpiryInterval((uint)timeout.Value); } try { if (!RpcMethodResolver.Methods.TryGetValue(methodName, out var method)) { if (string.IsNullOrEmpty(id) || noResponse) { return; } throw new EntryPointNotFoundException($"Method '{methodName}' not found."); } var parameters = method.GetParameters(); object[] args; switch (parameters.Length) { case 0: args = null; break; case 1: var parameterInfo = parameters.First(); args = parameterInfo.ParameterType == typeof(byte[]) ? new[] { (object)message.Payload } : new[] { DefaultSerializer.Deserialize(message.Payload, parameterInfo.ParameterType) }; break; default: _logger.Error(new NotImplementedException(), "Multiple parameters resolving has not been supported yet, please use a key-value object."); return; } var rpcService = (IRpcService)serviceScope.ServiceProvider.GetService(method.DeclaringType); rpcService.CurrentContext = new RpcContext { Topic = message.Topic, RemoteClientId = clientId }; var task = Task.Run(async() => { var returnValue = method.Invoke(rpcService, args); if (returnValue is Task t) { await t.ConfigureAwait(false); if (t.GetType().IsGenericType) { var resultProperty = t.GetType().GetProperty("Result"); Debug.Assert(resultProperty != null); returnValue = resultProperty.GetValue(t); } } return(returnValue); }, cts.Token); if (!string.IsNullOrEmpty(id)) { if (!_waitingCalls.TryAdd(id, new CancellableTask(task, cts))) { throw new InvalidOperationException(); } } else { _noIdCalls.TryAdd(cts, task); } var result = await task.ConfigureAwait(false); responseBuilder.WithUserProperty("Success", true.ToString()); if (!noResponse) { responseBuilder.WithUserProperty("Id", id) .WithPayload(DefaultSerializer.Serialize(result)); } } catch (Exception ex) { responseBuilder.WithUserProperty("Success", false.ToString()) .WithUserProperty("ErrorCode", ex.HResult.ToString()) .WithUserProperty("ErrorMessage", ex.Message); } finally { if (!string.IsNullOrEmpty(id)) { _waitingCalls.TryRemove(id, out _); } else { _noIdCalls.TryRemove(cts, out _); } if (!noResponse) { await _mqttClient.PublishAsync(responseBuilder.Build()).ConfigureAwait(false); } } }