Microsoft joined ABUS Security Tech Germany to develop an IoT solution that helps ABUS to securely connect their security devices to the Azure cloud in Germany and to envision a new generation of ABUS connected devices.

Key technologies

Core team

  • Tobias Feix – Product Manager, ABUS
  • Anja Kürschner – Portfolio Manager, ABUS
  • Pawel Brzakala – Architect, ABUS
  • Udo Schneider – Technical Manager, ABUS
  • Daniel Kreuzhofer – Technical Evangelist, Microsoft
  • Julia Jauss – Technical Evangelist, Microsoft

Customer profile

ABUS in their own words:

“Since 1924, ABUS provides the good feeling of security worldwide. As a German quality manufacturer, we ensure that our products are highly reliable and offer a long service life while being easy to operate. To meet the growing requirements of private and commercial users, ABUS provides a large product range of innovative security solutions in the areas of security at home, mobile security, and commercial security. The ABUS group comprises the companies ABUS August Bremicker Söhne KG, ABUS Security-Center GmbH & Co. KG, ABUS Pfaffenhain GmbH, and ABUS Seccor GmbH with around 3,500 employees worldwide.”

Problem statement

ABUS delivers approximately 50,000 IP-enabled security cameras per year and a few thousand IP-enabled alert systems. These devices are not natively cloud enabled because they require direct Internet connections done with port forwarding in the customer’s network firewall, which implies possible security issues. ABUS was looking for a cloud-based management and control solution that provides a central secure gateway for all IP-enabled devices in a customer’s network.

Proposed solution

To help ABUS enable their customers to use their devices in a more secure and controllable way, the Microsoft team engaged at an early stage of the project with the ABUS product-management team. We agreed on three major steps going forward to find the best possible solution and to help them transition their business model.

  • Envisioning workshop – To find out how ABUS makes products today and how they could work together using the intelligent cloud tomorrow
  • Architecture design session – To define a secure and scalable architecture for the ABUS IoT gateway solution
  • Proof of concept – To test and verify that Microsoft technology solves ABUS’s problems and helps their customers

Currently, a typical ABUS customer scenario looks like this:

ABUS traditional IP setup

A typical ABUS security customer has at least one ABUS alarm panel (in our example, the Secvest system) and one or more cameras. Additionally the Secvest alarm panel can communicate inside the building with other sensors and actors, such as the AC power switch and window sensors.

The connectivity from currently available mobile apps to the Secvest alarm panel or the cameras works only if a few requirements are met:

  • The internet router has a publicly visible IP address.
  • If the IP address of the router is dynamically assigned and changes every 24 hours, the router needs a DynDNS/No-IP setup.
  • The user needs to open a few ports to the Internet and map these to the internal ports of the devices, which is not easily understandable for everyone.

However, even if all these requirements are met, this is not a future-proof and secure scenario because Internet providers are constantly changing how (and whether) they assign public IPV4 addresses. This setup is currently not working for some providers, which only assign internal IPs or IPV6 IPs with NAT.

Additionally, it is generally not recommended to open ports to internal devices permanently. Doing so could be dangerous if the devices have security issues and outdated firmware.

All these considerations led to the decision that ABUS needs to change how their devices provide connectivity for mobile and stationary apps to make them more secure and reliable for the average user.

In the envisioning workshop and architecture-design session, ABUS and Microsoft representatives discussed and created a design for the future of the ABUS security device families.

The first design decision is based on the fact that for most of the legacy devices that currently exist in the market, the firmware cannot be updated to a level where the described problems can be solved inside the device software.

Therefore, ABUS and Microsoft created the “ABUS gateway,” a device running Windows 10 IoT Core and a custom Universal Windows Platform (UWP) application that provides connectivity from and to the Internet for the internal devices over secure protocols using Azure IoT Hub and Microsoft Azure Germany. The Windows 10 IoT Core device will have a custom Windows image including the gateway app, which will be automatically updated through the Windows Store, as well as the Windows 10 IoT Core operating system (OS) itself. This reduces management overhead and maintenance costs for ABUS significantly because they can use Microsoft field-proven technology for app and OS updates and upgrades.

IoT Hub setup

The ABUS gateway talks directly to the private IP addresses of the Secvest alarm panel and IP cameras to collect information and to trigger events and switches. These actions can be triggered through Azure IoT Hub using messages and methods. The UWP app on the gateway device connects to IoT Hub using the MQTT protocol.

All telemetry data that flows through IoT hub is split into several categories: device telemetry, gateway telemetry, control commands, and custom events.

Azure Functions takes care that telemetry data and custom event data gets filtered and is processed separately from the telemetry data. Azure Functions also enables live debugging of remote devices and the gateway. We found that, compared to Stream Analytics, which introduces a slight delay in message processing, Azure Functions is much faster for scenarios where messages need to be pulled from IoT Hub for immediate processing.

What has changed in this scenario is three major things:

  • No ports need to be open on the Internet router because the gateway actively connects to IoT Hub using MQTT and the connection is initiated from inside the local network. This connection then builds the tunnel for all communication from and to the internal devices using the gateway. Any IPV4/IPV6 translation and NAT issues are gone.
  • The Windows 10 IoT Core operating system and the UWP app on the gateway are updated automatically no matter whether or how frequently the firmware of the internal ABUS device is updated. This makes closing security bugs much easier and puts control back in the hands of ABUS.
  • The mobile apps use a single endpoint to talk to all known devices behind the gateway and do not need to know where these devices are.

Besides this general architecture, the plan for ABUS is also to incorporate IoT Hub connectivity in all newly created ABUS devices for the future to eliminate the need for a gateway device in most of the smaller cases. However, in larger installations the gateway device will still play the role of the central communication hub and a feature enabler, because releasing new versions of the UWP app through the Windows Store is much faster and convenient than the current update mechanisms of the security devices themselves.

Technical delivery

The project with ABUS started as a two-day workshop at the Microsoft facilities in Munich, where Microsoft and ABUS technical experts came together to code. The result was a prototype application that can communicate with the ABUS Secvest alarm panel and enable cloud-to-device communication through IoT Hub. We pulled information from the Secvest alarm panel (such as current status of alert loops) and stored it in Azure Table storage by using Stream Analytics.

In the following two weeks, the Microsoft team continued to work on the prototype to make it ready for an internal presentation at the ABUS and Microsoft management level.

During the development phase, we had to overcome a few technical challenges in combination with the Secvest alarm panel. We adapted our solution and decided to apply the “plugin” concept of the iot_homesecurity framework for easily adding future devices like cameras and other ABUS components.

Development setup

Devices used

  • ABUS hardware
    • ABUS Secvest alarm panel
    • ABUS IP dome cameras (1080p and 720p)
    • ABUS window sensors

      Photo of ABUS hardware board with Secvest alarm panel, two sizes of dome cameras, and five window sensors

    • ABUS AC power switch

      Photo of ABUS AC power switch in wall outlet

  • IoT device
    • Raspberry Pi 3 running Windows 10 IoT Core
    • UWP IoT app written in C#

Development environment

  • Visual Studio 2017 RC
  • Windows 10 Professional
  • Azure SDK for .NET
  • Visual Studio Team Services using Git as the source-code repository

Important frameworks

The final version of the prototype is available on GitHub: kreuzhofer/iot_homesecurity/tree/ABUS.

Solution deep dive

The solution consists of the following parts:

  • The UWP app W10Home.IoTCoreApp, which runs on the Windows 10 IoT Core gateway device.
  • Azure IoT Hub to receive and filter messages based on two main rules:
    • Log messages get forwarded to the log event hub queue for further processing by Azure Functions.
    • All other messages get forwarded to the main message queue.
  • An Azure function, which is supposed to be used to forward debugging and log information from the gateway device to a log viewer (currently logs are viewable only in the Azure Functions portal).
  • An Azure Stream Analytics query that stores device states per device in Azure Table storage and also stores all device state-change messages continously in another table. Also it forwards these messages to Power BI to be visualized in a dashboard.
  • The web app DevicePortal running in Azure App Service, which is used to manage device configuration and send messages to devices.

Solution overview

UWP app

Let’s look at the UWP app to understand the structure and how it manages connections to devices and IoT Hub.

UWP app structural overview

App startup

The Windows 10 IoT Core app starts as a background task, which starts automatically when the device boots. On startup, the CoreApp class is instantiated; it serves as the main entry point for the application.

public sealed class StartupTask : IBackgroundTask
{
    private BackgroundTaskDeferral _deferral;
    private CoreApp _coreApp;

    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        // This deferral should have an instance reference; if it doesn't, at some point
        // garbage collection will see that this method is not active and the local variable
        // should be removed, which results in the application being closed.
        _deferral = taskInstance.GetDeferral();

	_coreApp = new CoreApp();
	await _coreApp.Run();

	// The message-loop worker runs in the background and checks for specific messages
	// that tell CoreApp to either reboot the device or exit the app, which should
	// restart the app.
	MessageLoopWorker();

	// Don't release deferral; otherwise app will stop
    }

Initialization

CoreApp is a shared component, which can be used in the IoT app and also a desktop app to be able to debug it on the local developer machine.

It begins with the Run method, which tries to load a configuration file from the LocalFolder of the app. If it does not succeed, it will configure AzureIoTHubDevice, so it tries to load the latest config file from the cloud.

internal class CoreApp
{
    private Timer _everySecondTimer;
    private Timer _everyMinuteTimer;
    private HttpServer _httpServer;

    public async Task Run()
    {
        // Build configuration object to configure all devices
        RootConfiguration configurationObject = null;

        // first try to load the configuration file from the LocalFolder
        var localStorage = ApplicationData.Current.LocalFolder;
        var file = await localStorage.TryGetItemAsync("configuration.json");
        if (file != null) // file exists, continue to deserialize into actual configuration object
        {
            // local file content
            var configFileContent = await FileIO.ReadTextAsync((IStorageFile) file);
            configurationObject = JsonConvert.DeserializeObject<RootConfiguration>(configFileContent);
        }
        else // there is not yet a configuration file; tell AzureIoTHubDevice to load it from the cloud and then restart
        {
            configurationObject.DeviceConfigurations = new List<DeviceConfiguration>(new[]
                {
                    // by default, IoT Hub configuration now uses TPM chip
                    new DeviceConfiguration
                        {
                            Name = "iothub",
                            Type = "AzureIoTHubDevice",
                            Properties = new Dictionary<string, string>()
                                {
                                    { "TryLoadConfiguration", "true" }
                                  //{ "ConnectionString", "IOT_HUB_CONNECTION_STRING_ONLY_FOR_DEBUGGING" }
                                }
                        }
                });
            }
        }
    

Next step is to initialize the framework of available device types and hook up the IoC container that helps devices and other parts of the application to localize the needed components quickly.


// init device registry and add devices
var deviceRegistry = new DeviceRegistry();
deviceRegistry.RegisterDeviceType<AzureIoTHubDevice>();
deviceRegistry.RegisterDeviceType<SecVestDevice>();
deviceRegistry.RegisterDeviceType<ETATouchDevice>();
deviceRegistry.RegisterDeviceType<TwilioDevice>();

// add functions engine
var functionsEngine = new FunctionsEngine();

// init IoC
var container = new UnityContainer();
container.RegisterInstance<IMessageQueue>(new MessageQueue());
container.RegisterInstance<IDeviceRegistry>(deviceRegistry);
container.RegisterInstance(functionsEngine);

// register device instances
container.RegisterType<AzureIoTHubDevice>(new ContainerControlledLifetimeManager());
container.RegisterType<SecVestDevice>(new ContainerControlledLifetimeManager());
container.RegisterType<ETATouchDevice>(new ContainerControlledLifetimeManager());
container.RegisterType<TwilioDevice>(new ContainerControlledLifetimeManager());

// make Unity container available to ServiceLocator
var locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);

The purpose of the device registry is to hold instances of devices and initialize them as defined in the configuration file.


// configure devices
await deviceRegistry.InitializeDevicesAsync(configurationObject);

// start Lua engine
functionsEngine.Initialize(configurationObject);
			
// define cron timers
_everySecondTimer = new Timer(EverySecondTimerCallback, null, 1000, 1000);
_everyMinuteTimer = new Timer(EveryMinuteTimerCallbackAsync, null, 60 * 1000, 60 * 1000);

// start local webserver
var authProvider = new BasicAuthorizationProvider("Login", new FixedCredentialsValidator());
var restRouteHandler = new RestRouteHandler(authProvider);
restRouteHandler.RegisterController<QueueController>();
var configuration = new HttpServerConfiguration()
    .ListenOnPort(80)
    .RegisterRoute("api", restRouteHandler)
    .RegisterRoute(new StaticFileRouteHandler(@"Web", authProvider))
    .EnableCors(); // allow cors requests on all origins
//  .EnableCors(x => x.AddAllowedOrigin("http://specificserver:<listen-port>"));

var httpServer = new HttpServer(configuration);
_httpServer = httpServer;

await httpServer.StartServerAsync();

The functionsEngine function is another building block of the framework. It is configured to run Lua scripts either periodically or when triggered by the internal message loop.

Configuration files

Let’s have a look at a sample configuration file for the gateway device.

{
  "DeviceConfigurations": [
    {
      "Name": "iothub",
      "Type": "AzureIoTHubDevice",
      "Properties": {}
    },
    {
      "Name": "secvest",
      "Type": "SecvestDevice",
      "Properties": {
        "ConnectionString": "https://192.168.178.127:4433/",
        "Username": "1234",
        "Password": "1234"
      }
    }
  ],
  "Functions": [
    {
      "TriggerType": "RecurringIntervalTimer",
      "Name": "PollSecvestEveryMinute",
      "Code": "\r\n\t\t\t\t\tfunction run()\r\n\t\t\t\t\t\t-- get status from secvest every minute\r\n\t\t\t\t\t\tsecvest = registry.getDevice(\"secvest\");\r\n\t\t\t\t\t\tstatusChannel = secvest.getChannel(\"status\");\r\n\t\t\t\t\t\tstatusValue = statusChannel.read();\r\n\t\t\t\t\t\tif(statusValue != nil) then\r\n\t\t\t\t\t\t\t-- send status to iothub queue\r\n\t\t\t\t\t\t\tqueue.enqueue(\"iothub\", \"status@secvest\", statusValue, \"json\");\r\n\t\t\t\t\t\t\tend;\r\n\t\t\t\t\t\treturn 0;\r\n\t\t\t\t\tend;\r\n\t\t\t\t\t",
      "QueueName": null,
      "Interval": 60000
    },
    {
      "TriggerType": "MessageQueue",
      "Name": "WindSensorQueueHandler",
      "Code": "\r\n\t\t\t\t\tfunction run(message)\r\n\t\t\t\t\t\tif(message.Key == \"Wind\") then\r\n\t\t\t\t\t\t\tmessage.Key = \"windspeed@windsensor\";\r\n\t\t\t\t\t\t\tmessage.Tag = \"windspeed_kmh\"\r\n\t\t\t\t\t\tend;\r\n\t\t\t\t\t\tif(message.Key == \"Temperature\") then\r\n\t\t\t\t\t\t\tmessage.Key = \"temperature@windsensor\";\r\n\t\t\t\t\t\t\tmessage.Tag = \"temperature_celsius\"\r\n\t\t\t\t\t\tend;\r\n\r\n\t\t\t\t\t\tqueue.enqueue(\"iothub\", message); -- simply forward to iot hub message queue\r\n\t\t\t\t\t\treturn 0;\r\n\t\t\t\t\tend;\r\n\t\t\t\t\t",
      "QueueName": "windsensor",
      "Interval": 0
    }
  ]
}

The configuration file has two main sections:

  • DeviceConfigurations
    • Contains device-specific configuration properties like connections strings and passwords for communication with the device.
  • Functions
    • Contains functions that are triggered either by timer intervals in milliseconds or messages from an internal message queue.
    • Code of these functions can be written in Lua. (We are using the Moonsharp interpreter to execute them.)
    • Functions have access to global classes like the device registry, IoT Hub, and the message queue to be able to process messages and/or forward them to other queues, which could be also the iothub queue that forwards messages to IoT Hub.

Lua functions

Here’s one sample Lua script that polls the ABUS Secvest alarm panel every minute for the current status:

function run()
	-- get status from secvest every minute
	secvest = registry.getDevice(""secvest"");
	statusChannel = secvest.getChannel(""status"");
	statusValue = statusChannel.read();
	if(statusValue != nil) then
		-- send status to iothub queue
		queue.enqueue(""iothub"", ""status@secvest"", statusValue, ""json"");
		end;
	return 0;
end;

The script gets the Secvest device from the device registry and then gets the status channel and calls the read function. The status object then is forwarded into the internal iothub message queue.

Iot Hub connection

Looking at the AzureIoTHubDevice message loop, we can see that every message that is being sent to the iothub queue is being forwarded directly to IoT Hub. It also checks for incoming cloud-to-device (C2D) messages, which could be used to push messages back to the local devices.

private async void MessageReceiverLoop()
{
	do
	{
		try
		{
			// check internal message queue for IoT Hub messages to be forwarded
			var queue = ServiceLocator.Current.GetInstance<IMessageQueue>();
			if (queue.TryPeek("iothub", out QueueMessage queuemessage))
			{
				if (await SendChannelMessageToIoTHubAsync(queuemessage.Key, queuemessage.Value, queuemessage.Tag))
				{
					queue.TryDeque("iothub", out QueueMessage pop);
				};
			}
				// check IoT Hub incoming messages for processing
			var message = await _deviceClient.ReceiveAsync(TimeSpan.FromMilliseconds(250));
			if (message != null)
			{
				await _deviceClient.CompleteAsync(message);
				var reader = new StreamReader(message.BodyStream);
				var bodyString = await reader.ReadToEndAsync();
				Debug.WriteLine(bodyString);
				var messageObject = JsonConvert.DeserializeObject<QueueMessage>(bodyString);
				if (messageObject == null) // maybe an incompatible message object -> throw away and continue
				{
					continue;
				}
				if (messageObject.Key == "configure")
				{
					}
			}
		}
		catch (Exception ex)
		{
			Debug.WriteLine(ex.Message);
			//TODO Log
		}
	} while (true);
}

The messages sent to IoT Hub can be of two kinds:

  • Channel (device channel data)

    {
        "MessageType":"Channel",
        "DeviceId":"homecontroller",
        "DeviceType":"RaspberryPiGateway_v1",
        "ChannelType":"json",
        "ChannelKey":"status@secvest",
        "ChannelValue":"{\"Name\":\"Secvest\",\"Partitions\":[{\"id\":\"1\",\"state\":\"unset\",\"name\":\"Haus EG\",\"zones\":[\"101\",\"102\",\"201\",\"205\"]},{\"id\":\"2\",\"state\":\"unset\",\"name\":\"Haus DG\",\"zones\":[\"101\",\"102\",\"202\",\"205\"]},{\"id\":\"3\",\"state\":\"unset\",\"name\":\"Haus Keller\",\"zones\":[\"101\",\"102\",\"203\",\"205\"]},{\"id\":\"4\",\"state\":\"unset\",\"name\":\"Garage\",\"zones\":[\"101\",\"102\",\"204\",\"205\"]}]}","LocalTimestamp":"2017-04-12T17:05:20.4808507Z"
    }
    
  • Log (log data)

    {
        "MessageType":"Log",
        "DeviceId":"homecontroller",
        "DeviceType":"RaspberryPiGateway_v1",
        "LocalTimestamp":"2017-04-12T17:05:33.1527207Z",
        "Severity":"Debug",
        "Message":"EverySecondTimerCallback started"
    }
    

Azure IoT Hub

On the Azure side of things, let’s begin with IoT Hub, which takes in messages from the gateway devices and forwards them to Azure Stream Analytics or Azure Functions depending on the message type.

  • “Channel” messages are forwarded to the main message queue.
  • “Log” messages are filtered out and sent to another Event Hub queue, which gets processed by Azure functions.

To be able to send Log messages to a different queue, we defined a custom endpoint in IoT Hub.

Screen shot of IoT Hub custom endpoints

Then we created a special route that filters out Log messages and sends them to the Log endpoint.

Screen shot of IoT Hub routes

Azure Stream Analytics

Stream Analytics is used to direct device messages to different targets:

  • Azure Table storage for device status and device messages
  • Power BI for data visualization

The Stream Analytics query looks like this:

SELECT
    DeviceId,
    DeviceType,
    ChannelKey,
    ChannelValue,
    ChannelType,
    LocalTimestamp
INTO
    [PowerBI]
FROM
    [iothub]
TIMESTAMP BY LocalTimestamp

SELECT
    DeviceId,
    DeviceType,
    ChannelKey,
    ChannelValue,
    ChannelType,
    LocalTimestamp
INTO
    [DeviceState]
FROM
    [iothub]
TIMESTAMP BY LocalTimestamp

SELECT
    DeviceId,
    DeviceType,
    ChannelKey,
    ChannelValue,
    ChannelType,
    LocalTimestamp
INTO
    [DeviceMessages]
FROM
    [iothub]
TIMESTAMP BY LocalTimestamp

The queries that insert data into the DeviceState and DeviceMessages tables basically look the same, but they create different results:

  • The DeviceState output takes DeviceId and ChannelKey for the PartitionKey and RowKey values and so generates only one entry per ChannelKey.

    Screen shot of Azure Table insertion definition for DeviceState

  • The DeviceMessages output takes the DeviceId and LocalTimestamp value for the PartitionKey and RowKey and so generates an entry for every message sent to IoT Hub.

    Screen shot of Azure Table insertion definition for DeviceMessages

We then can have a first view of what’s in Azure Table by using Storage Explorer. For the DeviceState table, we can see that the current Secvest state is reflected by one row.

Screen shot of DeviceState table

In the DeviceMessages table we see all incoming messages.

Screen shot of DeviceMessages table

Azure Functions

In section Azure IoT Hub, we wrote about filtering the Log messages into a separate EventHub queue. This EventHub queue is monitored by an Azure function that processes the log messages. For debugging purposes, we log every message and apply another filter on critical errors, which might be important to forward to another queue.

The Azure function is written in C#. You can see from the screen shot that it processes and outputs log entries into the Logs pane of the Azure Functions window:

Screen shot of InputQueueFunction with Logs pane

The code itself is pretty straightforward. It takes an EventHub message, creates an object by using Newtonsoft JsonConvert, and checks whether it is a Log message and then additionally whether it is a critical error.

#r "Newtonsoft.Json"
using System;
using Newtonsoft.Json;

public static void Run(string myEventHubMessage, TraceWriter log)
{
    log.Info($"C# Event Hub trigger function processed a message: {myEventHubMessage}");

    dynamic messageObj = JsonConvert.DeserializeObject(myEventHubMessage);

    if(messageObj.MessageType == "Log") // this should be the case, we have set up a route for it
    {
        log.Error("Log message received.");
        if(messageObj.Severity == "Critial")
        {
            log.Info("Critial message! Forwarding to critial queue");
        }
    }
}

Azure App Service: Device portal web app

Device list

Finally, looking at the web app, we can see which devices are connected to the cloud.

Screen shot of Devices list in Device Portal

Device messages

We can send messages to the device, which get handled by MessageReceiverLoop in AzureIoTHubDevice.

Screen shot of device-message dialog box in Device Portal

Device remote configuration

In the Edit page for a device, one can specify a URL that points to a new configuration file for the device.

Screen shot of Edit page for DeviceData in Device Portal

As soon as this information is saved, the device twin gets updated with the new URL; on the device side, the new configuration gets loaded (by restarting the app).

AzureIoTHubDevice.cs


private async Task DesiredPropertyUpdateCallback(TwinCollection desiredProperties, object userContext)
{
	Debug.WriteLine(desiredProperties.ToString());
	if (desiredProperties.Contains("configurationUrl"))
	{
		await DownloadConfigAndRestart(desiredProperties);
	}
}

private async Task DownloadConfigAndRestart(TwinCollection desiredProperties)
{
	// download file
	var fileToDownload = desiredProperties["configurationUrl"].ToString();
	var httpClient = new HttpClient();
	var configFileContent = await httpClient.GetStringAsync(new Uri(fileToDownload));

	// save to disk
	var localStorage = ApplicationData.Current.LocalFolder;
	var file = await localStorage.CreateFileAsync("configuration.json", CreationCollisionOption.ReplaceExisting);
	await FileIO.WriteTextAsync(file, configFileContent);

	var queue = ServiceLocator.Current.GetInstance<IMessageQueue>();
	queue.Enqueue("management", "exit", null, null); // restart the app (StartupTask takes care of this)
}

Conclusion

In our engagement with ABUS, we successfully connected the Secvest alarm panel to Azure IoT Hub using Windows 10 IoT Core and a UWP app as the middleware to broker messages and get a secure and reliable messaging channel. At a very early stage of the project, ABUS decided to contract for Microsoft Azure Germany because of the unique security and legal model as well as the trusted Azure technology stack.

It looks like the solution is usable for taking it one step further: integrating more ABUS devices and creating a reusable solution for other clients. From our side, we will continue to develop the solution to be reusable and have the latest sources on GitHub for future engagements.

ABUS is currently evaluating the next stages of the project with proofs of concept, which cover several other aspects of the scenario like video streaming and video on demand. Another step is to find the right hardware for the gateway device, which will have requirements that exceed the Raspberry Pi 3. It will need to have an onboard TPM chip for extended security and onboard eMMC instead of the microSD card slot.

Additional resources