2
votes

I've developed an azure function to handle decompression of messages as they enter the IoTHub.

The Function is connected to the IoTHub's built in Messaging Endpoint, so it can function like an EventHub.

What I would like to do it have the Function output the decompressed content back into the IoTHub so the Stream Analytics and other Jobs that I have running will not have to be connected to a different Endpoint to continue receiving telemetry.

There seems to be a fair amount of documentation surrounding the Azure Functions and hooking them up to IoTHubs, but some of it is from last year and I know things have changed quite a bit.

This is my current connection string to read and write to the same IoTHub:

Endpoint=sb://iothub-ns-34997-5db385cb1f.servicebus.windows.net/;SharedAccessKeyName=iothubowner;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=;EntityPath=IoTHub

Right now I've setup the Output to go to the IoTHub endpoint and I'm getting an error

Exception while executing function: Functions.DecompressionJS. Microsoft.Azure.WebJobs.Host: Error while handling parameter _binder after function returned:. Microsoft.ServiceBus: Unauthorized access. 'Send' claim(s) are required to perform this operation. Resource: 'sb://iothub-ns-34997-5db385cb1f.servicebus.windows.net/iothub'. TrackingId:e85de1ed565243bcb30bc622a2cab252_G4, SystemTracker:gateway6, Timestamp:6/22/2017 9:20:16 PM.

So I figured there was something wrong with the connection string and so I modified it to include the /iothub that the exception was telling me to use, since the rest of the endpoint matched the current connection string.

Once I updated the connection string and reran the function I got a different exception:

Exception while executing function: Functions.DecompressionJS. Microsoft.Azure.WebJobs.Host: Error while handling parameter _binder after function returned:. Microsoft.ServiceBus: Invalid EventHub address. It must be either of the following. Sender: <EventHubName>. Partition Sender: <EventHubName>/Partitions/<PartitionNumber>. Partition Receiver: <EventHubName>/ConsumerGroups/<ConsumerGroupName>/Partitions/<PartitionNumber>. TrackingId:ecb290822f494a86a61c21712656ea4c_G0, SystemTracker:gateway6, Timestamp:6/22/2017 8:44:14 PM.

So at this point I'm thinking that the IoTHub endpoint is only for reading messages and there is no way to get the decompressed content back into the IoTHub.

I'm hoping someone can prove me wrong and help me to configure my connection strings so I can have a closed loop and retrieve and send messages to and from the IoTHub without an intermediary.

1
You shouldn't post your access keys publicly... - Mikhail Shilkov
Thanks for the heads up. I had modified the access key already by omitting some content, but I've edited the shared access key so it's no longer the actual key. - Andrew Konken
Note that the old access key is still in the public revision history. - halfer
I had omitted pieces from the entity path and service bus address, so I think it should be okay. Since none of the information with the exception of the shared access key were complete. I appreciate the information, I had forgotten the revision history. - Andrew Konken
Have not tried this before but in your output binding, what is the value that you set for "path"? If you set it to "messages/events", it should work but may create an infinite loop. i.e. Would it not trigger your Function since the trigger and output binding share the same connection string and path? I am assuming that you have tried and it works if you are writing to a different IoTHub, e.g. IotHub2. and using the IoTHub2 connection string and "path":"messages/events" in the output binding inside the function.json. - Ling Toh

1 Answers

1
votes

The Azure IoT Hub is a bidirectional gateway between the devices and Azure cloud back end solutions. The communications with the Azure IoT Hub is done via its device-facing and service-facing endpoints. See more details here.

Your scenario requires to decompress a device event before its passing to the telemetry stream pipeline. Basically this telemetry pre-processing in the typical Azure stream pipeline can be done in the Azure Function (or worker role) and/or Azure Stream Analytics (ASA) job like is shown in the following picture: TelemetryPrepocessing

As you can see, the AF and/or ASA job are changing a real-time telemetry data in the stream pipeline and their state are stored in the next entity such as Event Hub. That's the common and recommended pattern of the real-time stream pipeline and push model.

Your scenario also requires to keep the same telemetry path (source) as you have it for uncompressed device events, so than there is a "non-standard" solution. The following screen snippet shows an example of this solution:

EmulateDevice

The concept of the above solution is based on the device emulator on the backend side. The Azure IoT Hub Routes will forward all events for their preprocessing to the custom endpoint such as Event Hub.

Behind that, the Azure Function will have a responsibility to decompress an ingested event and create new one for that device such as emulated device. Now, this emulated device can send a D2C message to the Azure IoT Hub like others real devices.

Note, that the emulated device is using a Https protocol (connection less) and Azure IoT Hub Authorization.

The events from the emulated devices in the Azure IoT Hub are routed to the Default Event Hub such as a default telemetry path.

Note, that the above solution allows to select an event preprocessing based on the Routes/Rules and its usage is depended from the business model.