Connect MQTTnet with Azure IoT Hub - .net-4.5

I have created a device that delivers messages. Now I want to send them to an Azure IoT Hub by using MQTTnet Version 2.4.0 because the .NET target Framework is on Version 4.5 and it is not my decision to change it.
My Question:
Is there any other or better method to do this
What MqttClientOption do I take best
What Parameters to set to which value to connect to the Hub
I have tried almost every combination of values for the ClientId/UserName/Password as described here: https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support#using-the-mqtt-protocol-directly-as-a-device
but none of them worked for me
I have tried outside the Project and build a similar device on the current framework and it worked perfectly with the newer version of MQTTnet.
Sadly I don't get any kind of error message only a MqttCommunicationTimedOutException after about 10 seconds.
Thanks for your help I have been stuck at this problem for almost a week.

The following code snippet is a working example of the simulated device1 using the MQTT protocol directly to the Azure IoT Hub via the MQTTnet Version 2.4.0 library:
using MQTTnet;
using MQTTnet.Core;
using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
using System;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var options = new MqttClientTcpOptions()
{
Server = "myIoTHub.azure-devices.net",
Port = 8883,
ClientId = "device1",
UserName = "myIoTHub.azure-devices.net/device1/api-version=2018-06-30",
Password = "SharedAccessSignature sr=myIoTHub.azure-devices.net%2Fdevices%2Fdevice1&sig=****&se=1592830262",
ProtocolVersion = MQTTnet.Core.Serializer.MqttProtocolVersion.V311,
TlsOptions = new MqttClientTlsOptions() { UseTls = true },
CleanSession = true
};
var factory = new MqttClientFactory();
var mqttClient = factory.CreateMqttClient();
// handlers
mqttClient.Connected += delegate (object sender, EventArgs e)
{
Console.WriteLine("Connected");
};
mqttClient.Disconnected += delegate (object sender, EventArgs e)
{
Console.WriteLine("Disconnected");
};
mqttClient.ApplicationMessageReceived += delegate (object sender, MqttApplicationMessageReceivedEventArgs e)
{
Console.WriteLine(Encoding.ASCII.GetString(e.ApplicationMessage.Payload));
};
mqttClient.ConnectAsync(options).Wait();
// subscribe on the topics
var topicFilters = new[] {
new TopicFilter("devices/device1/messages/devicebound/#", MqttQualityOfServiceLevel.AtLeastOnce),
new TopicFilter("$iothub/twin/PATCH/properties/desired/#", MqttQualityOfServiceLevel.AtLeastOnce),
new TopicFilter("$iothub/methods/POST/#", MqttQualityOfServiceLevel.AtLeastOnce)
};
mqttClient.SubscribeAsync(topicFilters).Wait();
// publish message
var topic = $"devices/device1/messages/events/$.ct=application%2Fjson&$.ce=utf-8";
var payload = Encoding.ASCII.GetBytes("Hello IoT Hub");
var message = new MqttApplicationMessage(topic, payload, MqttQualityOfServiceLevel.AtLeastOnce, false);
mqttClient.PublishAsync(message);
Console.Read();
}
}
}
and the following screen snippet shows an example of the output for updating a desired twin property color and receiving a C2D message:

Related

Connecting Unity client to XMPP server

I'm trying to make a client for chat using unity.
I have found this library https://github.com/bilelmnasser/Unity-3D-Xmpp-Protocol-
so I've imported to my project and being testing the code but I can't seem to get it to work.
using UnityEngine;
using Xmpp;
using Xmpp.protocol.client;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
var xmppClient = new XmppClientConnection("localhost");
//xmppClient.ConnectServer = "ipServer";
xmppClient.Server = "localhost";
xmppClient.Port = 5222;
xmppClient.Username = "admin#localhost";
xmppClient.Password = "password";
xmppClient.Open();
xmppClient.OnLogin += delegate(object o) { xmppClient.Send(new Message("user#localhost", MessageType.chat, "Hello, how are you?")); };
}
Here is my code. I have a ejabberd server running using docker.
I've created two users and tested on node server as client and it worked fine, but can't get to work on unity...
any help would be great!

Connection not working from Android to UWP on desktop - ZeroMq (NetMq)

I tried some examples of ZMQ on C++,C# and Python. I am trying to have Request-Reply pattern to connect Android device to PC running UWP with Xamarin forms.
Below is the Requestor code:
public void HelloWorld()
{
var timer = new Timer(60000);
timer.Start();
timer.Elapsed += (sender, args) =>
{
this.Cancel = true;
timer.Stop();
};
// Create
const string endpoint = "tcp://PC_ip:3245";
using (var request = new RequestSocket())
{
request.Bind(endpoint);
Thread.Sleep(2000);
while (!Cancel)
{
request.SendFrame("Requester says hello");
var reply = request.ReceiveFrameString();
Debug.WriteLine("Gets reply {0}",reply);
}
}
}
Reply socket code:
public void HelloWorld()
{
var timer = new Timer(60000);
const string endpoint = "tcp://PC_ip:3245";
timer.Start();
timer.Elapsed += (sender, args) =>
{
timer.Stop();
Cancel = true;
};
using (var replierSocket = new ResponseSocket())
{
replierSocket.Connect(endpoint);
Thread.Sleep(2000);
while (!Cancel)
{
var replyFromRequester = replierSocket.ReceiveFrameString();
Debug.WriteLine("Got reply {0}", replyFromRequester);
replierSocket.SendFrame("Response socket say hello");
}
}
}
Cancel is boolean
I went through some questions posted on this and added delay and these connection code blocks only trigger after button clicks on app.
While debugging , request.ReceiveFrameString() replierSocket.ReceiveFrameString(); are not even hit.
I am new to network programming , I understand that for REQ/REP pattern the code has to be in particular order which I traced and fixed I believe and turned off firewall on my PC so that firewall wont block my incoming connections from Android device.
PC_ip stands for IPv4 address I got from ipconfig /all for my wifi. I also tried external ip of my machine from sites like whatsmyip.org at ResponseSocket but I still dont get response between devices.
Please let me know what am I doing wrong.
Issue replication repository : GitHub/me/XamZeroMq

SignalR Core with Redis Pub\Sub and console application

I am having Asp.Net Core 2.1 with SignalR Core 1.0.1.
I have created chat application that is described here:
https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-2.1&tabs=visual-studio
Also have configured SignalR to use Redis using
services.AddSignalR().AddRedis(Configuration["ConnectionStrings:Redis"]);
Having running Redis server up with redis-cli monitor I can see the following commands coming:
1530086417.413730 [0 127.0.0.1:57436] "SUBSCRIBE" "SignalRCore.Hubs.ChatHub:connection:VAIbFqtNyPVaod18jmm_Aw"
1530086428.181854 [0 127.0.0.1:57435] "PUBLISH" "SignalRCore.Hubs.ChatHub:all" "\x92\x90\x81\xa4json\xc4W{\"type\":1,\"target\":\"ReceiveMessage\",\"arguments\":[{\"user\":\"user\",\"message\":\"message\"}]}\x1e"
Everything works fine till the time when I would like to push some message from another console application.
In that application I am using ServiceStack.Redis and the code is the following:
var redisManager = new RedisManagerPool(configuration["ConnectionStrings:Redis"]);
using (var client = redisManager.GetClient())
{
client.PublishMessage("SignalRCore.Hubs.ChatHub:all", "{\"type\":1,\"target\":\"ReceiveMessage\",\"arguments\":[{\"user\":\"FromConsole\",\"message\":\"Message\"}]");
}
The messages are not handled by browser. I assume the case is in this additional information that is used for SignalR:
"\x92\x90\x81\xa4json\xc4W{...}\x1e"
Related monitor record:
1530087843.512083 [0 127.0.0.1:49480] "PUBLISH" "SignalRCore.Hubs.ChatHub:all" "{\"type\":1,\"target\":\"ReceiveMessage\",\"arguments\":[{\"user\":\"FromConsole\",\"message\":\"Message\"}]"
Any ideas how can I specify this additional data for publish?
Probably I should use something more suitable for my case instead of ServiceStack.Redis
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.AspNetCore.SignalR.Redis.Internal;
using StackExchange.Redis;
using System.Collections.Generic;
static void Main(string[] args)
{
using (var redis = ConnectionMultiplexer.Connect("127.0.0.1:6379"))
{
var sub = redis.GetSubscriber();
var protocol = new JsonHubProtocol();
var redisProtocol = new RedisProtocol(new List<JsonHubProtocol>() { protocol});
var bytes = redisProtocol.WriteInvocation("ReceiveMessage", new[] { "60344", "60344" });
sub.Publish("SignalRChat.Hubs.ChatHub:all", bytes);
}
}
How to find it?
in signalr source code search ".Publish", you can find the https://github.com/aspnet/SignalR/blob/c852bdcc332ffb998ec6a5b226e35d5e74d24009/src/Microsoft.AspNetCore.SignalR.StackExchangeRedis/RedisHubLifetimeManager.cs
it uses the RedisProtocol and messagepack to .WriteBytes. header footer name count...

does kafka support dotnet core?

I'm trying to make a Kafka producer and consumer, but my project is in dotnet Core 2.0 and it doesn't seem to work well with kafka. This is the proof-of-concept I've tried coming up with. I'm using Visual Studio 2017 with the kafka-net nuget package:
using
using KafkaNet;
using KafkaNet.Model;
using KafkaNet.Protocol;
producer
static void Main(string[] args)
{
string payload = "Welcome to Kafka!";
string topic = "IDGTestTopic";
Message msg = new Message(payload);
Uri uri = new Uri("localhost:9092");
var options = new KafkaOptions(uri);
var router = new BrokerRouter(options);
var client = new Producer(router);
client.SendMessageAsync(topic, new List<Message> { msg }).Wait();
Console.ReadLine();
}
consumer
static void Main(string[] args)
{
string topic = "IDGTestTopic";
Uri uri = new Uri("http://localhost:9092");
var options = new KafkaOptions(uri);
var router = new BrokerRouter(options);
var consumer = new Consumer(new ConsumerOptions(topic, router));
foreach (var message in consumer.Consume())
{
Console.WriteLine(Encoding.UTF8.GetString(message.Value));
}
Console.ReadLine();
}
When I try to run the producer first, I get an error message on the BrokerRouter:
$exception {System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: port
at System.Net.IPEndPoint..ctor(IPAddress address, Int32 port)
at KafkaNet.DefaultKafkaConnectionFactory.Resolve(Uri kafkaAddress, IKafkaLog log)
at KafkaNet.Model.KafkaOptions.<get_KafkaServerEndpoints>d__0.MoveNext()
at KafkaNet.BrokerRouter..ctor(KafkaOptions kafkaOptions)
at SampleKafkaProducer.Program.Main(String[] args) in C:\v4target\SampleKafka\SampleKafkaProducer\SampleKafkaProducer\Program.cs:line 18} System.ArgumentOutOfRangeException
How is a port of 9092 out of range? My Visual Studio projects are running on ports in the 55000's. Multiple sources I've researched use 9092 as a kafka port.
Does anyone understand the error message? Is part of the main problem because I'm using a version of Kafka not compatible with dotnet core?
The problem is with the uri.
Uri uri = new Uri("localhost:9092");
If you print out the uri.Port, it's -1. Hence the ArgumentOutOfRangeException.
Try this instead:
Uri uri = new Uri("http://localhost:9092");
From the KafkaNet Repository. This is how they setup the URI:
var options = new KafkaOptions(new Uri("http://CSDKAFKA01:9092"), new Uri("http://CSDKAFKA02:9092"))
{
Log = new ConsoleLog()
};

MassTransit 3 How to send a message explicitly to the error queue

I'm using MassTransit with Reactive Extensions to stream messages from the queue in batches. Since the behaviour isn't the same as a normal consumer I need to be able to send a message to the error queue if it fails an x number of times.
I've looked through the MassTransit source code and posted on the google groups and can't find an anwser.
Is this available on the ConsumeContext interface? Or is this even possible?
Here is my code. I've removed some of it to make it simpler.
_busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.UseInMemoryScheduler();
cfg.ReceiveEndpoint(host, "customer_update_queue", e =>
{
var _observer = new ObservableObserver<ConsumeContext<Customer>>();
_observer.Buffer(TimeSpan.FromMilliseconds(1000)).Subscribe(OnNext);
e.Observer(_observer);
});
});
private void OnNext(IList<ConsumeContext<Customer>> messages)
{
foreach (var consumeContext in messages)
{
Console.WriteLine("Content: " + consumeContext.Message.Content);
if (consumeContext.Message.RetryCount > 3)
{
// I want to be able to send to the error queue
consumeContext.SendToErrorQueue()
}
}
}
I've found a work around by using the RabbitMQ client mixed with MassTransit. Since I can't throw an exception when using an Observable and therefore no error queue is created. I create it manually using the RabbitMQ client like below.
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";
factory.UserName = "guest";
factory.Password = "guest";
using (IConnection connection = factory.CreateConnection())
{
using (IModel model = connection.CreateModel())
{
string exchangeName = "customer_update_queue_error";
string queueName = "customer_update_queue_error";
string routingKey = "";
model.ExchangeDeclare(exchangeName, ExchangeType.Fanout);
model.QueueDeclare(queueName, false, false, false, null);
model.QueueBind(queueName, exchangeName, routingKey);
}
}
The send part is to send it directly to the message queue if it fails an x amount of times like so.
consumeContext.Send(new Uri("rabbitmq://localhost/customer_update_queue_error"), consumeContext.Message);
Hopefully the batch feature will be implemented soon and I can use that instead.
https://github.com/MassTransit/MassTransit/issues/800