I am trying to subscribe MQTT messages in Azure IoT Hub. I am able to publish message using MQTTNet library but when I create subscriber to receive message from IoT hub then connection gets disconnected once message is published to the IoT hub.
I have tried to publish message from separate application and VS code extension, in both cases subscriber gets disconnected on message published.
I am using following code for subscriber
Console.WriteLine("Starting Subscriber.....");
//create subscriber client
var mqttFactory = new MqttFactory();
var mqttClient = mqttFactory.CreateMqttClient();
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithClientId("<Device-Id>")
.WithTcpServer("<IoTHub>.azure-devices.net", 8883)
.WithCredentials("<IoTHub>.azure-devices.net/<Device-Id>/api-version=2018-06-30", "SharedAccessSignature")
.WithTls(new MqttClientOptionsBuilderTlsParameters() { UseTls = true })
.WithCleanSession()
.Build();
mqttClient.ConnectedAsync += async (MqttClientConnectedEventArgs arg) =>
{
Console.WriteLine("Connected");
};
mqttClient.DisconnectedAsync += async (MqttClientDisconnectedEventArgs arg) =>
{
Console.WriteLine("Disconnected");
};
mqttClient.ApplicationMessageReceivedAsync += async (MqttApplicationMessageReceivedEventArgs arg) =>
{
Console.WriteLine("Message received");
};
var result = mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None).GetAwaiter().GetResult();
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic("devices/<Device-Id>/messages/events/");
})
.Build();
var r = mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None).GetAwaiter().GetResult();
Console.WriteLine("MQTT client subscribed to topic.");
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
When I run this code and publish message then I get following output
Instead of receiver event, mqtt disconnect event fires. I am using 4.1.4.563 version of MQTTnet library. Any help would be gratefully appreciated, thanks!
You are subscribing to a custom topic. See here similar question.
Device can subscribe to devices/{device_id}/messages/devicebound/#
Related
I newbe to Signal R Core here. i am try to connect to a Signal R client to A Serverless hub. In my example for now i just want to create multiple instances of en get a connection every time a new one is connected.
static async Task Main(string[] args)
{
var client = new HttpClient();
var response = await client.GetAsync("http://localhost:7071/api/negotiate?userid=1");
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
var d = JsonConvert.DeserializeObject<dynamic>(responseBody);
string urlString = Convert.ToString(d.Url);
var connection = new HubConnectionBuilder()
.ConfigureLogging(logging =>
{
// Set the log level of signalr stuffs
logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
})
.WithUrl(urlString, options => options.AccessTokenProvider = () => Task.FromResult(Convert.ToString(d.AccessToken)))
.Build();
connection.On<NewConnection>("newConnection", c => OnReceiveMessage(c));
await connection.StartAsync();
// while (connection.State == HubConnectionState.Connected)
// {
// }
Console.Read();
}
private static void OnReceiveMessage(NewConnection connection)
{
Console.WriteLine($"user {connection.UserId} with connctionid {connection.ConnectionId} has been connected");
}
On my Javascript client this is working but on my Net client it keeps disconnecting everytime right after connection:
[2022-10-02T11:03:27.542Z] Executing 'Functions.OnConnected' (Reason='(null)', Id=3878244a-50cd-47a6-b8c6-98ed1c0dd5c6)
[2022-10-02T11:03:27.544Z] KimOo3chMz6M9zxEPAlpzQ has connected
[2022-10-02T11:03:27.549Z] Executed 'Functions.OnConnected' (Succeeded, Id=3878244a-50cd-47a6-b8c6-98ed1c0dd5c6, Duration=7ms)
[2022-10-02T11:03:27.571Z] Executing 'Functions.OnDisconnected' (Reason='(null)', Id=693bec34-3ed3-434c-93fb-e366c1113e4a)
[2022-10-02T11:03:27.572Z] KimOo3chMz6M9zxEPAlpzQ has disconnected
Not sure what i am missing at the moment.
Found the answer. This behavior was cause by the fact that websockets are not supported by default in Net-Core console app. by changing this to longpolling this as solved.
I am using the MQTTNet library for the MQTT connection in my application. I am using Mosquitto Broker as a MQTT broker. My app is in .Net core 3.1.
I am having requirement to send the MQTT message to device when the app is connected, normal disconnected and unexpected disconnected.
For the connected scenario, I am using the UseConnectedHandler extension method of the IMQTTClient.
mqttClient.UseConnectedHandler((MqttClientConnectedEventArgs e) =>
{
// Console.WriteLine("MqttClient - Connected");
// Publish the Connect Message
});
For the unexpected disconnect scenario I am using the WithWillMessage feature.
var mqttOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithWillMessage(_options.LastWillMessage)
.WithCleanSession()
.WithClientId(_options.DevcommMqttClientId)
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithCommunicationTimeout(TimeSpan.FromSeconds(30))
.WithCredentials(_options.DevcommMqttUsername ?? string.Empty, _options.DevcommMqttPassword ?? string.Empty)
.WithTcpServer(_options.DevcommMqttHost, _options.DevcommMqttPort)
.WithTls(o =>
{
o.UseTls = _options.DevcommUseTls;
o.AllowUntrustedCertificates = _options.DevcommTlsAllowUntrustedCertificates;
o.IgnoreCertificateChainErrors = _options.DevcommTlsIgnoreCertificateChainErrors;
o.IgnoreCertificateRevocationErrors = _options.DevcommTlsIgnoreCertificateRevocationErrors;
o.SslProtocol = ParseSslProtocols(_options.DevcommTlsProtocols);
o.Certificates = _options.DevcommTlsClientCertificates.AsEnumerable();
o.CertificateValidationHandler = CertificateValidationHandler;
})
.Build())
.Build();
I am now stuck at graceful disconnect scenario. The UseDisconnectedHandler extension method is being called after the disconnect and not before disconnect.
Mosquitto broker is providing the feature of close message, which is similar of before disconnect event.
Is there anyway that using MQTTNet I can send the before disconnect message?
I need an help, I can't connect with the broker.
I'm using MQTTNet library into my api project .net core
this is my code:
// GET: api/<SendCommandController>
[HttpGet]
public void Get()
{
var options = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com", 1883)
.Build();
var factory = new MqttFactory();
var mqttClient = factory.CreateMqttClient();
mqttClient.ConnectAsync(options, CancellationToken.None);
var message = new MqttApplicationMessageBuilder()
.WithTopic("Test/Mqtt")
.WithPayload("Hello World")
.WithExactlyOnceQoS()
.WithRetainFlag()
.Build();
mqttClient.PublishAsync(message, CancellationToken.None);
}
so I follow the tutorial but can't connect to broker hivemq and I can't connect to my personal broker.
So, I tested hivemq broker with mqtt.fx and works.
Only in the code the return is connected = false.
Any ideas? the error is "the client is not connected"
C# is not a language I've done much with, but I assume you are missing an await before mqttClient.ConnectAsync(options, CancellationToken.None); so the rest of the code waits for the connection to complete before trying to send the message
I'm trying to notify the user when a message is not received after some time, using MassTransit and RabbitMQ.
From what I read, the timeout is set using the TimeToLive property when the message is published. When that specified time runs out, the message should be automatically added to a Dead Letter queue, named with a "_skipped" at the end.
How do I retrieve messages from Dead Letter queues? In my attempt below, the message is added to the both queues right away, and it never times out.
I think I could do this using sagas, but it seems like a over complicated solution for such a simple problem, so I would like to avoid using it if at all possible.
static void Main(string[] args)
{
var bus = CreateBus("rabbitmq://localhost/", "guest", "guest", true);
var msg = new TestMessage("First Message");
LogMessageSent(msg);
bus.Publish(msg, c => c.TimeToLive = TimeSpan.FromSeconds(15));
Console.ReadKey();
bus.Stop();
bus = CreateBus("rabbitmq://localhost/", "guest", "guest", false);
msg = new TestMessage("SecondMessage");
LogMessageSent(msg);
bus.Publish(msg, c => c.TimeToLive = TimeSpan.FromSeconds(15));
Console.ReadKey();
bus.Stop();
}
private static IBusControl CreateBus(string rabbitUrl, string username, string password, bool enableEndpoint)
{
var bus = Bus.Factory.CreateUsingRabbitMq(c =>
{
var host = c.Host(new Uri(rabbitUrl), h =>
{
h.Username(username);
h.Password(password);
});
if (enableEndpoint)
{
c.ReceiveEndpoint(host, "TestQueue", x =>
{
x.Handler<TestMessage>(e => LogMessageReceived(e.Message, "TestQueue"));
});
}
c.ReceiveEndpoint(host, "TestQueue_skipped", x =>
{
x.Handler<TestMessage>(e => LogMessageReceived(e.Message, "TestQueue_skipped"));
});
});
bus.Start();
return bus;
}
private static void LogMessageSent(TestMessage msg)
{
Console.WriteLine(string.Format("{0} - Message \"{1}\" sent.", DateTime.Now.ToString("HH:mm:ss"), msg.Content));
}
private static Task LogMessageReceived(TestMessage msg, string queueName)
{
Console.WriteLine(string.Format("{0} - Message \"{1}\" received on queue \"{2}\".", DateTime.Now.ToString("HH:mm:ss"), msg.Content, queueName));
return Task.CompletedTask;
}
public class TestMessage
{
public string Content { get; }
public TestMessage(string content)
{
Content = content;
}
}
Because you are calling Publish, the message is sent to every subscriber. Since each receive endpoint is adding the consumer, that creates a subscription (and subsequent exchange binding in RabbitMQ) for that message type. You can disable this by specifying BindMessageExchanges = false on that skipped receive endpoint. You will need to manually remove the exchange binding on the broker.
As to your TimeToLive question, that isn't how it works. TimeToLive is passed to the broker, and if the message expires, it is moved to a broker-specified dead-letter queue, if so configured. It is not moved to the skipped queue which has a different meaning in MassTransit. In MassTransit, the skipped queue is for messages that are delivered to a receive endpoint but there wasn't a consumer configured on that endpoint to consume the message.
For RabbitMQ, you can configure the dead-letter queue in MassTransit by using:
endpoint.BindDeadLetterQueue("dead-letter-queue-name");
This will configure the broker so that messages which reach their TTL are moved to the specified exchange/queue. Then your consumer on that receive endpoint will be able to consume them (again, be sure to set BindMessageExchanges = false on the dead-letter receive endpoint.
For example:
c.ReceiveEndpoint(host, "TestQueue_expired", x =>
{
x.BindMessageExchanges = false;
x.Handler<TestMessage>(e => LogMessageReceived(e.Message, "TestQueue_expired"));
});
And then your original receive endpoint:
c.ReceiveEndpoint(host, "TestQueue", x =>
{
x.BindDeadLetterQueue("TestQueue_expired");
x.Handler<TestMessage>(e => LogMessageReceived(e.Message, "TestQueue"));
});
I'm monitoring the topic and subs and messages are getting in, however my masstransit consumer is not receiving anything.
Here's how it's been setup:
var bus = Bus.Factory.CreateUsingAzureServiceBus(
cfg =>
{
var azSbHost = cfg.Host(new Uri(CloudConfigurationManager.GetSetting("ServiceBus.Url"))
, host =>
{
host.TokenProvider = TokenProvider
.CreateSharedAccessSignatureTokenProvider
(CloudConfigurationManager.GetSetting("ServiceBus.SharedAccessKeyName"),
CloudConfigurationManager.GetSetting("ServiceBus.AccessKey"),
TokenScope.Namespace);
});
cfg.ReceiveEndpoint(azSbHost,
e =>
{
e.Consumer<PingConsumer>();
});
//azSbHost.
});
The Ping Consumer:
public class PingConsumer : IConsumer<Ping>
{
public async Task Consume(ConsumeContext<Ping> pingContext)
{
pingContext.Respond(new Pong
{
Message = "Pong: " + pingContext.Message.Message
});
}
}
And the sender:
var pong = await _bus.CreatePublishRequestClient<Ping, Pong>(TimeSpan.FromSeconds(10),null ).Request(
new Ping {Message = "Ping: " + message});
In Azure, I'm seeing my message count climbing up and not going down. So messages are getting to the queue, but consumer is not consuming the message.
I was missing a VERY important key call to make it all work on both client and server side.
Bus.Start