Photo by Thomas Kolnowski on Unsplash

HomeKit is around for a while now. I use it daily to control my lights or remotely close my front door. The only downside is that its feature set is quite limited. For my app Sensory, I’m trying to design an alarm system based on Hue Motion Sensors purely in Apple’s new SwiftUI.

After a coding session, I discovered that it was possible to access/control these accessories from within my app. With the extensions that Homebridge can give you, I would be able to control* my nest thermostat again!

*Do you want to know how to create a temperature dial in SwiftUI? Read more about it here.

In this article, I’m going to explain how to interact with accessories found in HomeKit and display them in SwiftUI. The main focus is on making my motion sensor working again without the Hue API.

Before you start, make sure you have added the correct capabilities to your project and added a valid entry in the Info.plist. (Privacy — HomeKit Usage Description).

Let’s create a class that can leverage the SDK querying accessories for us.

The above ViewModel makes querying devices a lot easier for us!

The gist utilizes the Resource enum that I used in “Networking in SwiftUI.” If you have not read that before, I suggest you give that a read here.

In short, we initialize the ViewModel, set the delegate, and wait until HomeKit signals us that we have accessories loaded. We load the accessories based on a model identifier*. When we have fetched a resource, we transform it into what we expect.

*Getting the correct identifiers can take some debugging

The above code does nothing without a model; we still need a way to query for the accessory’s properties, let’s work on that. Introducing a protocol named HomeKitAccessory

This protocol helps us to read/write values quickly.

Now we have a “standardized” way to query our accessories for information. We are still missing a model, one that holds our motion sensor data.

There are a lot of more identifiers available than the one listed here.

This model is still barebones since I’m still working on getting all the values I need for my project. This model is a bit special; we are setting the accessory delegate to ourselves.

This delegate has a method that fires when a value changes and updates the model automatically whenever a value changes since we conform to ObservableObject. Just make sure that the variable in our View has the annotation “@ObservedObject.”

We are ready to display it in a SwiftUI view. You can use a basic ForEach or List to display all the sensors instead of the GridStack. The gists below show a grid view with multiple sensor views assuming you have more than one.

The resource enum makes it pleasant to display views based on their current state!

AssetColor is an extension to fetch named colors safely.

Bonus: I have attached the view modifier EitherBackground so you can attach two different kinds of backgrounds (ex: Color vs. Gradient) on a view based on a condition.

That’s a wrap; as usual, I’ll leave the basic setup as an implementation to the reader. I’m happy that I can continue to work on my alarm system this time based on HomeKit SDK.

See you in the next article.

Here at Pinch, we continue experimenting with SwiftUI to make our apps even better. Do you have any questions or remarks? Let us know in the comments.