Writing an Event Processor for IoT Hub with C#
Start course

Once your data is in IoT Hub, you need to be able to access it; ideally with different processors. Using different processors allows you to break out the responsibilities of each.

Azure provides a few options for processing events and sending feedback to devices. In this course we'll introduce you to Stream Analytics, Azure Functions and raw processing with C#.

If you want to follow along, or just try this out for yourself, you can find the code here.

Processing Azure IoT Hub Events and Data: What You'll Learn

Lecture What you'll learn
Course Intro What to expect from this course
Understanding Streaming Data Processing for IoT Hub  
Writing an Event Processor for IoT Hub with C#  
Handling Device-To-Cloud data with Azure Functions  
Processing IoT Hub data streams with Azure Stream Analytics  
Sending feedback to devices with Azure Functions Reviewing the code for the device
Final Thoughts Wrapping up the course



Welcome back!

In this I’ll show you how to create an event processor using C#. Writing your own event processor is like having your Lego bricks which allow you to create any model, architecture, or algorithm you want.

This gives you the most flexibility, however, it also has the most amount of addition effort.

We’re here in our Azure portal. And I’ve already created an IoT Hub and an Azure storage account.

Let’s head into IoT Hub. Looking at the device can see that we have one device named "dev1" which we’ll use for our simulated device.

Under shared access policies, I’ve created a policy for our event processor, and it has service permissions; which allow us to retrieve a message from the message endpoint.

On the endpoint I’ve configured a consumer group named processor. It's a good practice to create a consumer group for each processor.

Let's switch over to our Visual Studio project.

We have "IoTHubDeviceClient" and "IoTHubEventProcessor". Let's look at the IoTHubDeviceClient. This is a basic device simulator written in C#.

Then there is only a command implemented, which is for telemetry.

In the telemetry implementation there is a loop that generates one event per second.

The event itself is simple, it has a DeviceId; Index that is a sequence number; and the Data is our simulated telemetry . Then Date is when that event is generated.

The value for data is adjustable by using the up and down arrows on the keyboard. This allows me to adjust the data up and down by increments of 1. This will let me simulate different data patterns.

Okay, then there is the event processor which is a class that implements the IEventProcessor interface from the EventHubs namespace.

It contains four methods. Open, Close, ProcessError, and Process Events. And ProcessEvents is the interesting method.

Let's see how it is implemented.

In this example the open, close and process error, only write to the console.

The ProcessEvents method has arguments for the context as well as an IEnumerable of EventData.

Here I’m looping over the messages and passing them into another method that grabs the event data and hands it off to an event delegate.

So, let's see how the event processor works. If you look at the Processor class, there’s a Main method.

In order to instantiate a new EventProcessorHost you need a few settings.

The ConnectionString represents the connection to the IoT Hub namespace.

The Path represents the specific EventHub-compatible endpoint for IoT Hub.

Then there is the ConsumerGroupName. Again, specify a consumer group for each process you run.

Then there is the storage and a container. Since we have multiple partitions processed by the event processor, each event processor has a state that will be persisted in this storage, inside the specified container.

I have implemented commands for a couple of scenarios: logging and average.

First, let’s look at logging.

The first thing to do is call "RegisterEventProcessorAsync". We don't control how the processor is created here. You only stop and wait for a key to finish, while eventProcessorHost does the work for you.

This loop is just a sort of clock to gauge time.

So, if we go to the command line, I have one here. Let’s start another command line instance.

On the first one I’ll run a batch files that runs the simulated device.

On the second I’ll run a logging batch file that runs the eventProcessorHost process.

Notice that there are the events that are sent by the device. Here, you see that the processor is starting.

The processing is quite simple, it’s just writing to the console, you can see the messages being processed by the logging processor.

If I increase the data value by clicking the up key on the keyboard, here we see that we have a 22.

If I click the down arrow, the data value going down and the processor is receiving the events. Great. So, let’s stop the device, and processor. So that’s a simple example of using an event processor to just log events. Now, logging them to the console isn’t very useful, however persisting the records to DocumentDB, SQL, or anywhere else is easy from here.

Alright, let's do something more interesting. What is far more interesting than logging is control. That means looking at the data, finding a pattern, and then sending feedback to the device based on what we find.

Here in the Processor class I have another command for "average". I’m calculating the average of the value in the Data property for a 10 second window. Pretend that the data is something meaningful, maybe something like temperature.

If the average value hits above 24 and there are at least 8 messages, we send a “SWITCH-ON” command. You can imagine that in this case there’s a device listening with a fan that will listen for the “SWITCH-ON” command.

Let’s run this to see it in action. I’ll start by running the dev1 batch file.

Okay, then I’ll run on a second command prompt, an "average" batch file that launches the same processor with some other arguments.

So far it looks like the previous demo. Let’s increase the Data property. Notice it going up 23, 26. Okay. Now that we have some events, I’ll decrease the value. Notice here that we have some feedback. This command here to “SWITCH-ON” was triggered because our command condition was met. Obviously, this is a demo, so we’re not actually controlling anything, though you can imagine using this with an actual device.

Keep in mind that when it comes to controlling devices in production you’ll need to consider how many commands you send, and or make sure that they’re executed idempotently on the device

Alright, that’s going to wrap up this lesson, so let’s recap.

The advantage of implementing your own Event Processor is that you have full control over the processing. You can implement any processing model you want.

You can write a stateless processor. You can implement a stateful processor; you can do whatever you want in code and use any supporting library you need.

However the drawbacks are that you’ll need to manage the infrastructure; you’ll also need to write a lot of code that isn’t specific to your business logic.

So raw event processing requires a lot more development effort!

In the next lesson, we’ll consider how to handle messages with Azure Functions.

About the Author

Marco Parenzan is a Research Lead for Microsoft Azure in Cloud Academy. He has been awarded three times as a Microsoft MVP on Microsoft Azure. He is a speaker in major community events in Italy about Azure and .NET development and he is a community lead for 1nn0va, an official Microsoft community in Pordenone, Italy. He has written a book on Azure in 2016. He loves IoT and retrogaming.