Franklin84
Franklin84

Reputation: 573

Azure IoT Hub - Receive Events from different Devices with multiple EventHubReceiver


I try to receive messages from Devices with the "EventHubReceiver" (Device2Cloud). Each device should have it's own, single receiver.

It isn't a problem to create one single EventHubReceiver (per Partition) for all devices:

string iotHubconnectionString = CloudConfigurationManager.GetSetting("Microsoft.IotHub.ConnectionStringPayed");
string iotHubD2cEndpoint = "messages/events";
EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(iotHubconnectionString, iotHubD2cEndpoint);
EventHubRuntimeInformation runtimeInformation = eventHubClient.GetRuntimeInformation();

If I then want to receive messages from the clients I do the following steps:

EventHubReceiver eventHubReceiver = eventHubClient2.GetDefaultConsumerGroup().CreateReceiver(partition);  //Get the partitions via the runtimeInformation: string[] partitions = runtimeInformation.PartitionIds;
var incommingMessage = eventHubReceiver.ReceiveAsync();    //Wait here for incomming messages

That works all right, but all messages from all "Devices" arrive then at this one "EventHubReceiver". I would like to have multiple receiver, that only receive messages from a single device.
I tried to change the following codeline:

string iotHubD2cEndpoint = "messages/events";

to

string iotHubD2cEndpoint = "devices/{deviceID}/messages/events";

but that doesn't work all right. I get the following error:

The link address 'devices/secondDevice/messages/events/$management' did not match any of the expected formats. Supported formats: '/$cbs', '/devices/{deviceid}/messages/events', '/devices/{deviceid}/messages/deviceBound', '/messages/deviceBound', '/messages/serviceBound/feedback', '/messages/events/*'.

So the problem is that I get 'devices/secondDevice/messages/events/$management'
insted of 'devices/secondDevice/messages/events/'
I don't know, whether it is just not possible to create a single EventHubReceiver for each Device or I've got a error in the code or thinking.

Upvotes: 1

Views: 3168

Answers (2)

Franklin84
Franklin84

Reputation: 573

I forgot to mention, that I've already got a solution. But it is not very nice:

  • All deviceThreads (one for each partition and device) wait ("WaitOne") at one point (locked with AutoResetEvent)
  • I receive all messages with a single receiver
  • I put the message into a own queue for each device (Dictionary that contains as key a object of the device(id and partition) and as value a List
  • I set a single thread set free with the "set" command.
  • The thread looks in its queue and:
    • if there is a message in the queue it continues and returns the result with a "yield return" -> waits again for a new message
    • else it sets a different thread fee and returns to the freeze state

All threads loop in a while(true) to wait for messages. The solution is working, but it doesn't look very performant (with many threads) and a bit complicated.

Upvotes: 0

ppatierno
ppatierno

Reputation: 10065

When a device send telemetry data to IoT Hub, the events are made available to the related D2C endpoint in the cloud that is "event hub compatible". It has an "event hub like" behaviour and for this reason we are able to get message using an EventHubReceiver. However, event hubs works in partitions and the incoming message can be assigned to partitions in a round robin fashion or hashing a partition key. In the IoT Hub architecture I don't know if it use round robin but it's possibile that it use to hash the device id (as partition key) so all messages from a device go into a partition. It doesn't mean that the partition contains messages only for that device ! It's impossible to have a partition for each device :-) So ... a partition containes messages mixed from different device (but message from a specific device go always in the same partition). An Event Hub receiver can read from partition so it gets all messages from more device. You need to distinguish them based on device id.

Upvotes: 2

Related Questions