Introducing HomeKit 

Session 213 WWDC 2014

iOS 8 introduces HomeKit, a high-level device connectivity framework enabling apps to interact with physical accessories in the world around us. Learn the objects that define these devices, see how to control them, and discover how to create a full device control experience for the home.

Hello, everybody.

[ Applause ]

Thank you very much.

So my name is Kevin McLaughlin.

And I am here this afternoon to tell you about HomeKit.

I know it has been a day packed full of all kinds of new information, but I hope you are very excited to be here as I am excited to see everybody here.

So you’ve heard a little bit about HomeKit already, I assume.

Let’s talk about it just as we’re getting started here.

So HomeKit is a new feature for iOS that is bringing, as Craig said very well, some rationality to home automation.

It provides a great opportunity for us, you as developers and us to work together to provide a much more consistent experience for our users as they start to get into home automation.

And we want to bring this to a much wider audience than home automation has really been accessible to in the past.

So let’s get started.

So today I will tell you a little bit about the features of HomeKit, and we’ll go through the core concepts, how to use the APIs, how to get started, and then a few advanced topics that are either interesting to me and hopefully to you, or I know are interesting to you.

So let’s get on with it.

So the first feature I want to tell you about is something that is really important and is core to delivering a consistency that I talked about.

So we have a Common Database that is stored in iOS, and it contains all of the home information, all of the accessory information that has been configured and is available to all of your apps.

Every time a user uses one of your apps to configure a new accessory, to set up their home, to set up some other operation, those things are stored through HomeKit, through the framework, in this Common Database.

And then when the user uses another application for some other purpose and they see some of their home information in this other application, they’re going to see the same information that they saw or that they set up in their other applications.

And this means to our users, to your users, everything is going to look a lot more connected, and it’s going to make a lot more sense.

This is starting to provide that consistent experience that we want to deliver.

Now building on that, as we mentioned yesterday, we have a great interface for users, which is Siri.

So users can use Siri to interact with their HomeKit accessories in a very natural way by just speaking commands that make sense.

I’ll talk a little bit about how that’s enabled as we go through the presentation today.

Now in creating HomeKit, we have put in a lot of effort to define a common language for us to use to talk to accessories, but we can’t define every kind of accessory that all of our clever accessory manufacturers are going to invent.

I’ve already heard about dozens of interesting things that are well beyond what we’re starting with.

So you can see here, garage door, light bulb, door lock-these are things that are common accessories that we have defined in HomeKit, and I’ll talk some more about that as well, but anything else is possible.

We don’t want HomeKit to be restricted and contained.

We want HomeKit to create innovation and creativity.

And so anything that an accessory manufacturer can imagine and can create, they can define and make available through HomeKit to your applications.

And all of that is exciting, but you want to be able to use these accessories.

And so HomeKit also provides access to your HomeKit accessories when you are not at home.

This is enabled through iOS device connectivity.

And there’s no special requirement for your application or for the accessories to take advantage of this great feature of HomeKit.

But with all of that connectivity comes something very important.

It’s actually a pair of things that are very closely coupled.

That’s security and privacy.

We take security and privacy very seriously.

And we have spent a lot of time and effort, attention, reviews after reviews, making sure that we have a great solution here.

So we have end-to-end encryption between iOS devices and accessories.

And this enables us to have security so that accessories can’t be misused.

It also enables us to ensure user privacy is maintained.

We don’t think that it’s good enough to be sort of private, your data stored somewhere else.

We think it’s important to take privacy very seriously and do the best that is possible.

In keeping with this paradigm of ensuring privacy and security and making sure that our users have really good, reliable, understandable experiences when they start using your HomeKit applications, HomeKit APIs can only be used when your application is in the foreground.

This ensures that users know exactly what’s going on.

There’s nothing for them to be afraid of when they take that first step or second step into using home automation.

OK. So that’s enough about the high-level stuff.

Let’s get into some of the details.

So, to get started with HomeKit, your entry point is the Home Manager.

The Home Manager provides your pointers to the common database, accessed through the homes.

The Home Manager allows your application to manage the homes: which one is primary, adding or removing homes as necessary, and will notify you of changes.

Now, for example, somebody might have, for whatever reason, multiple homes set up.

Those might change.

This is where you would get notified about that.

So you can start updating your application to match what the user knows they have.

So the Home Manager is represented by the HMHomeManager class.

You simply create an instance of it, and then you set a delegate to be your application.

To use the Home Manager, the most important thing, the first thing you want to do is you want to implement this delegate callback homeManagerDidUpdateHomes.

When you get this callback, that means that the Home Manager has finished loading or preparing the home data.

And you can now save a pointer to the array of homes.

And you can also save what is currently set as the primary home.

Now if there aren’t any homes, then you’ll need to create a home for the user.

So you add a home with name.

And that completes with a completionHandler.

It would only fail likely if the home had the same name as another home because homes need to be uniquely named.

So homes contain all of the data for a home.

So you have your rooms, you have your accessories, and so on.

It notifies you of changes to that home.

And the names of homes are recognized by Siri so that users can refer to them when they are giving commands.

On a home we have the name, we have an array of all the rooms, and an array of all the accessories that are in that home.

To fill out the concept or the image or the map of a home, whatever you want to call it, you’ll need to create rooms.

So on the home you can create a room or add a room with name, provide a name for the room, and, again, that would only fail typically if there was a room that already had the same name.

So, moving on to rooms.

Rooms contain accessories.

A room, again, will notify you of changes.

And rooms must be uniquely named within a home.

So a home creates its own namespace.

Everything within a home must have a unique name.

Names of rooms are recognized by Siri.

So users can also interact with them to make some nice natural interactions with their accessories.

Rooms are represented by the HMRoom class.

And they have an array of the accessories that are in that room.

Let’s move on to accessories.

So an accessory corresponds to a physical device.

Accessories are assigned to a room, and that can change.

You can assign an accessory to a different room.

Accessory objects allow you to access the device state.

Can I talk to this accessory right now, for example.

It will notify you of changes to that accessory.

Again, they have to be uniquely named within a home.

And names of accessories also are recognized by Siri.

An accessory is the whole object that the user is referring to.

And I’ll talk about how the details of that accessory are exposed and made available after this.

So an accessory has a pointer back to the room that it’s in, and it has a pointer to the array of services that represent the functionality of that accessory.

An important delegate callback for you to implement on accessory is the DidUpdateReachability callback.

So an accessory at any point in time may be reachable.

You may be able to communicate with it from your application, or you may not.

It may be off.

You may be far away from it, in a situation where you don’t have access.

In this case, this callback will be given to your application to let you know when that reachability changes.

So you might start out with an accessory that is not reachable, and then if for some reason it becomes reachable you’ll be notified, and then you can update the UI in your application to reflect that so the user knows what’s going on.

So to describe a little bit more about how accessories look, let’s talk about services.

So services represent functionality of accessories.

They contain characteristics.

So you could describe a service as a grouping of characteristics where characteristics are specific parameters you could interact with, and I’ll talk about those next.

So, services are interesting in that they may have a name.

And what that means is there are some services that really aren’t intended for the user to directly interact with them.

They’re sort of more of an operational type of functionality.

So here, for example, we have a light bulb.

A service that has a light bulb would typically have a name because the user is going to want to name it.

And if that light has a name, I refer to it.

But a service to update firmware on an accessory is something that a user typically would not need to name and refer to in many different ways.

It’s something that your application would take care of for them, present that in a more user friendly way than saying “Oh, here’s your firmware update service, and here’s the data that goes into it.”

So in your UI, generally you will not expose unnamed services.

So this is a way that some of the messiness, if you will, or the, you could look at it in a different way and some of the great functionality of the protocol and of HomeKit framework don’t need to be exposed to users who just want to interact with these accessories that they’ve bought.

Names of services must be unique within a home, and they are recognized by Siri.

And importantly for services, we not only recognize names of services, but also we have Apple-defined service types.

And Siri understands those types, which means that users can refer to service types using natural language, and synonyms and other things like that, that may not be exactly the name provided to the service.

Services are represented in HMService.

We have a name, an array of characteristics, the service type of the service, and a pointer back to the accessory.

The services are a collection of characteristics.

A good example, just as it shows here is, for a light bulb service, your main characteristic is the power state of that light bulb service, and so the power state is a characteristic that you can directly interact with.

Characteristics provide some information, some metadata about the characteristics.

So they are self-describing.

So you might get a range, you might get units, step values, and so on.

So you can display appropriate controls to a user when you get a characteristic.

You get the results through a completion handler because it may not be immediate.

And characteristics are recognized by Siri although they are not named by the user.

So we’ve defined a number of characteristic types, and Siri can understand what those mean, so you just can interact with those giving commands through Siri.

The characteristics can be of a few varieties.

With these main ones, so some characteristics, you only read the values from them.

So you might say, “What is the current temperature outside or inside?”

You have a thermostat.

It tells you the current temperature.

You don’t need to write to the current temperature.

You can’t directly, immediately change that with a digital command, but you read from it.

When you want to change the temperature, you need to tell your thermostat that you have a new target temperature.

So your target temperature is something that you do write to, and you may also read from that because you might say, “Why is it so hot in here?

What is the current target temperature of this thermostat?”

So you read that, and then maybe you write it and change it.

And there are some few characteristics that you only write to.

A write-only characteristic is something, think about it a little bit, but where you tell the accessory to do something, and it’s going to do it, and it doesn’t matter what it may have to say back to you.

There’s no feedback.

It just, the accessory does it independently on its own.

So an example here, and an important one, is the identify characteristic, which is a special characteristic that all accessories must support, and it provides an interface where from your application, you can let a user say, “Hey, I’d like you to help me find out which one of my accessories this is.”

So you send an identify characteristic right to that accessory.

And then it will do something that identifies itself to the user.

So a light bulb might flash.

A thermostat might blink an LED.

A garage door opener or an IP camera might beep, maybe also flash a light.

Whatever it is, this is accessory specific.

And the purpose is to help the user know which thing they are about to interact with.

It’s especially useful when a user, for example, say, connects several lights.

And they say, “OK.

Now I need to set up my lights.

Which one is this?”

All right.

They all have the same default information.

I’m not going to go look them up by serial number.

That’s boring.

So just identify that for me.

And you send the identify characteristic right to that accessory, it blinks, the user knows which one it is, they can proceed.

So characteristics are an HMCharacteristic.

You can readValueWithCompletionHandler to get the value of a characteristic and also writeValueWithCompletionHandler.

So now we’ve talked about these objects, these things.

They correspond to physical things in the real world.

We need to be able to find and set up these accessories.

We do that with the Accessory Browser.

So this tool lets you and your application find out if there are any new accessories available and then help a user add those to a home.

So you create an instance of the Accessory Browser, set the delegate, and then, when appropriate, you start searching for new accessories.

You’ll find some.

You’ll remove some.

I’ll talk about that next.

And then later when you’re done, you stop searching for new accessories.

So it’s responsible for power management, to stop searching for new accessories when it’s no longer necessary to do that.

You’ve left the view.

You’re leaving the application.

You’ve decided that enough time has passed and so on.

So while you’re searching for new accessories, you will get this callback didFindNewAccessory.

And it will come with a pointer to the accessory that was found.

And you can now, for example, add this to a list of accessories in the UI that the user can select from for which ones they want to configure.

If, when you start searching there are already some accessories that have been found, you can get the list from the Accessory Browser of the already found new accessories.

And then you’ll get this callback every time a new one is added to that list.

When you have found the new accessories and the user would like to set one of them up, you need to add that accessory to a home.

And it’s important to note that this method is on HMHome.

It’s not on the Accessory Browser.

So we add the accessory to a home.

When the accessory is successfully added to a home, it’s time to name the accessory and assign it to a room.

Also while you’re searching for new accessories, you will sometimes get this callback.

Especially, you will get this callback when you add an accessory to a home.

This is didRemoveNewAccessory.

This allows you in your UI when you have a list of accessories that you are showing to the user which new accessories would you like to configure, and they do select one and they do add it to a home, you’ll get this callback to tell you it’s removed from the list of new accessories.

In this case, because it was added to a home, so you can update your UI to take that one off the list.

So that’s a quick introduction to how to get started, basic functionality.

And maybe, like I have been recently, you’d like to get right into it and write something.

And you wonder, how are we going to do that?

We don’t have any of these HomeKit accessories yet.

So we thought about that.

We came up with something.

We have a great solution, which is the HomeKit Accessory Simulator.

And this is available for you in Xcode at this location.

And it’s a great tool, and I’m going to show you how that works.


So here is our HomeKit Accessory Simulator.

Now you can see that in this case, there are a number of accessories that have already been created in the simulator, but I’ll walk you through it.

I’m just kind of making sure it’s big enough for everybody to see in the back.

Come forward if you can’t see it.

So here on the left we have the list of accessories that are created and Bridges, which I’ll talk about briefly at the end.

Then on the right there’s information about the accessories.

So what I’m going to do is I am going to go down to this Add Accessory button here on the bottom left and choose to Add a New Accessory.

So I’m going to call this Garage Door Demo 213.

I’m going to add this accessory.

So you’ll see now that I’ve added a new accessory to the accessory simulator.

And let me show you what that looks like in this very, very simple sample app that we wrote.

So this is just a tab view.

You can see there are new accessories on one tab and configured accessories on the other.

These other accessories are already configured.

We see here that we have the Garage Door Demo accessory that I’ve just created has shown up here on the New Accessories tab.

But it’s not very interesting yet.

It just has an accessory information service.

This is created by default because all accessories must have an accessory information service.

So I can go up here to add another service.

So this is a garage door.

So let’s add a garage door opener service.

We can see that’s added with all of these characteristics.

And now since garage door openers typically also have a light, let’s add a light.

Now you see we’ve created our garage door opener accessory, and it has the accessory information service.

It has the garage door opener service, which corresponds to the motor that actually opens and closes the garage door.

And we have a light bulb service correspond to the light that’s on that garage door.

So let’s go ahead and configure this accessory.

So when we go to add an accessory to a home, the user must enter a setup code.

This comes from the accessory.

Maybe on the packaging or on a label or on a screen or LCD on the accessory.

In the simulator, it’s here right under the name.

I see Setup Code, which looks like it’s 9143.

So let me enter that.

I’ll go ahead and set that up.

And you can see now that disappears from the list of new accessories because it was successfully added to the home.

Now if I jump over here to the Configured Accessories tab, I think I saw that I have a-I’m revealing my practicing-but here we have the garage door accessory that I’ve just added.

And you can see that it has two services and a Details tab.

The Details tab shows the accessory information.

This is not something that we need to interact with, but it’s there for reference.

We can also go in and see all of the characteristics for the garage door and all of the characteristics for the light.

And just to show that these are connected, we can see if I click on the power characteristic of the light, the power in the light bulb service of the garage door goes on and off along with that.

It’s sort of in the middle up there.

OK. So that shows you the basic use of the HomeKit Accessory Simulator and also showing sort of the Accessory Browser in action and adding an accessory and then showing the services and characteristics.

But let’s come back to Bridges for a moment.

So Bridges are a special type of accessory where you have one accessory that supports HomeKit Accessory Protocol that connects with iOS.

And then you have some other end-point accessories that are connected to the Bridge because they can’t communicate directly with iOS for some reason.

So a typical example may be a hub that has some lights behind it that are using some other protocol.

So in this case the hub is the first accessory that HomeKit connects to.

So I can come down here, and I can Add a New Bridge.

So let’s call this Demo Bridge 214.

So I’ve created a Bridge.

Now when a Bridge is created, you’ll see that it is actually an accessory that’s available.

So if I go over to New Accessories, that has shown up.

I could connect to it right now, but it’s really very uninteresting.

We need to add some accessories behind this Bridge.

So I click on Add Accessories.

So let’s add a light behind the Bridge.

Now we see we’ve added a light accessory connected to this Bridge.

While we’re here, let’s go ahead and add another light behind that Bridge.

So now we have two lights.

And you’ll see, on the right we show the accessories that are connected to the Bridge on the left.

Below the Bridge we have the actual light accessories listed here that would show the services of those.

Now here, these are created only with accessory information to start.

Let’s go ahead and add lights to them.

Now if I go back and look at the Bridge, you’ll see that we have a nice view to show you of the accessories that are connected behind the Bridge.

And of course we can pair with the Bridge just the same way we did before, and set this up.

8107. So that appears over here.

We can go down to our Connected Accessories.

And now you’re going to see something interesting.

The Demo Bridges there, and we can click on that and see that it just has details, which show the accessory information of the Bridge.

But the lights are also here.

So lights that are behind a Bridge are presented to you through HomeKit like separate accessories.

And you can interact directly with those lights even though there’s something in the middle and there’s always protocol translation and other things going on.

You don’t have to worry about that.

You get the accessory, which is what the user really cares about.

And so you can then interact directly with these accessories.

They can be turned on and off similarly.

OK. So that is the demo.

So let’s get back to our slides.

Perfect. So the HomeKit Accessory Simulator is available in Xcode 6.

It acts just like real accessories, so when you develop your application using the simulator, using the HomeKit Accessory Simulator, you’re doing the real thing.

When you eventually get real accessories to connect to, they’re going to work the same way.

They’re going to be exposed to you the same way through HomeKit.

So this is a great way for you to get started and a great way for you to develop and test your HomeKit applications.

So during this presentation so far, we’ve talked about all the steps at various points along the way for how to get the initial setup of a home and getting accessories added.

We’ve talked about this.

And I want to run through it for you just as a summary.

So first we need to create a home.

The user provides a name for the home.

Then we need to add rooms to the home.

The user provides names for those rooms.

Again, all these names will have to be unique.

And then we add accessories.

So we use the Accessory Browser.

We add the accessories to the home.

The user provides a name for the accessory.

The user chooses which room to put that accessory in for the home.

And after that then the user can actually go and continue using their accessory and can interact with it through your applications, through other applications, through Siri.

So now let’s move on to some more advanced topics.

So I’ve talked a lot about services and characteristics.

And I’ve talked about something defined by Apple and then custom ones.

So here on the left you can see a list of services that are some of the services we’ve defined.

And we can see these services correspond to, kind of broadly, accessory types or functional groupings of characteristics.

Then you see on the right a sampling of some of the characteristics that we’ve defined, and there are many more of these.

And then, as I said earlier, to encourage innovation, invention, creativity, we allow definition of any custom service, any custom characteristic an accessory manufacturer wants to use.

Those are all available to you through HomeKit.

And all of these services and characteristics that are defined by Apple are recognized by Siri and understood by Siri so that users can interact with them in very natural ways.

Turn something on.

Switch something on.

There’s some other ways that users, all of us I guess, refer to things in our homes.

So groupings of rooms like upstairs or downstairs or maybe the bedrooms.

So rooms can be collected into zones.

It’s represented in HMZone and is an arbitrary grouping of rooms.

And this is just an association.

It’s not an ownership relationship.

So a room can be in any number of zones.

Zones also are uniquely named, and zones are recognized by Siri.

We have another type of grouping, which is to help group and refer to functionality that is provided by accessories.

We might want to do something across multiple accessories where you don’t necessarily need to control everything on the accessory.

So these are called Service Groups in HMServiceGroup.

So you can imagine you might have nightlights in your home where some of the nightlights are their own accessory, but some nightlights are-it’s a light on a coffee machine, it’s a light on a microwave, it’s a light on the refrigerator.

It’s a light on whatever it is.

And so you can grab all of these light services that are actually nightlights, you can group them together into a Service Group, and you can easily display that to the user.

You can easily perform operations on all of those nightlights.

Services can be in any number of groups.

This is just an association.

Service Groups are also named uniquely of course within a home.

And names of Service Groups are also recognized by Siri.

And now getting into a couple more things that are quite interesting.

So first are Action Sets.

So this is the HomeKit implementation behind collecting accessories into scenes.

So how this works is we take a bunch of actions or actions or something you’re going to do to an accessory.

And we group those together into an Action Set.

So, for example, night.

So we might have a Night Action Set or a night scene.

And so this Night Action Set might turn off all your lights, lock your door, close your garage, turn the thermostat down.

That could be grouped together to be easily referred to for the user and easily execute all at once.

And when I say all at once, I really mean all at once.

The order of execution is undefined.

So you can’t expect that something is always going to happen before something else in an Action Set.

Everything will just be done at the same time.

It’s all going to get done, best effort to do everything.

Action Sets, again, uniquely named and recognized by Siri.

So what are these actions?

So actions are HMCharacteristicWriteAction.

This is a very literal name because what you’re doing in an action is you’re writing to a characteristic.

So, for example, you may have an action that is Close the Garage.

It’s a single write to a single characteristic on the garage, the garage door opener service.

And so that’s a single action.

So you would create that action, add it to the Action Set.

So Action Sets are interesting.

They’re starting to allow you to do something more complex.

We also have Triggers.

So Triggers are HMTimerTrigger.

So a Timer Trigger is set up to fire at a specific date and time.

They can repeat.

They are uniquely named within a home, but they are not interacted with through spoken commands.

But they have something very special about them, which is they are actually executed by iOS in the background at the time when that Trigger is supposed to be executed, when it fires.

So a Trigger is set to run an Action Set.

And that Action Set can, the executing of the Action Set can happen even when no apps are running or whatever because the Trigger is managed by iOS.

So you can imagine that even with just being able to specify dates and times, collections of actions to happen, repeating Triggers, you can start to get some pretty interesting functionality.

So I’d like to give you a quick demo of how Action Sets and Triggers work.

So we have here our HomeKit Accessory Simulator still running.

And I have another very simple sample app to show you.

Nice and large this time.

So here we have in this home that’s in the background, we have some Action Sets and some Triggers already defined.

So if we look at these Action Sets, we have the Night Action Set, that example I gave earlier, and we also have a Lights On and Lights Off Action Set.

So if you look at the Night Action Set, what we’ve displayed here are all of the characteristic rights that are part of this Action Set.

And if we go and look at, for example, some things here so the, thermostat’s target temperature, let’s say that was set at 70.

We can go here and unlock the door, for example, and then we can go here in this Action Set, and you can see that the door lock is going to have the lock characteristic set to Locked.

The thermostat is going to have the target temperature set to 68.

So I can execute this Action Set, and we can see that the lock has indeed changed to Locked.

Thermostat target temperature has changed back to 68.

And these lights are off.

So simple way, once it’s all set up, very simple way to go and control many accessories at the same time.

So now let’s look at these other two.

So Lights On.

It simply turns on all the lights.

And Lights Off obviously, right, it just turns off the lights.

So these two Action Sets just give me the opportunity to show you a very simple demo of how Triggers work.

So we have here two Triggers that are created.

One runs the Action Set Lights On, and one runs the Action Set Lights Off.

And we can see that when I’ve turned these Triggers on, I’ve enabled them, that these lights just start blinking.

Probably not a commonly used use case in the real world, but a great example for a demo.

So let’s stop that.

That’s Triggers and Action Sets.

Let’s go back to the slides.

So using Action Sets and Triggers together, you’ll be able to script or allow the user to script some fairly complex and interesting interactions and enable you and your users to control many accessories very easily and very quickly.

So one more thing I want to tell you about HomeKit, as you’re looking through our documentation, you’re going to see there are a lot of delegate methods.

And you might ask, “Do I need all of these delegate methods?

Do I have to implement every single one?”

And well, yes.

They’re there for a reason.

They’re there because, if you remember back at the beginning of the presentation, we talked about the shared database.

And because of the shared database, we get this great consistency across the user experience, different applications that have different specialized purposes.

The user is going to see that all these apps are aware of their home.

They have their home set up.

They have their living room.

They have their kitchen.

They have their ceiling lights.

They’re going to see that in every app.

All right.

It’s going to feel great to a user who is using this.

But you don’t want your app to get out of sync with what the user knows they have set up for their home.

And because of this shared database, it can be updated in many different ways.

Many of those ways are not through your app.

Through some other app.

Through some other event.

Accessories are changing.

And so all of these delegate methods are how we tell you what’s changing.

Someone changed the name of that room.

That accessory state has changed.

Someone has added a-I should be so lucky-added a lake house to their collection of homes.

And so when these things happen, you want to be able to update your app so that the user sees that your app is connected, your app knows what’s going on.

Everything is being communicated.

So these delegate methods are how you do that.

So that brings us just about to the end of my presentation.

And if this timer is right, I’ve gone quite a bit faster than I expected.

But that’s okay, right?

It’s at the end of the day.

I want you to remember this.

So HomeKit is providing you the opportunity to deliver a much more consistent experience for home automation through your applications.

The framework has been designed to be easy to use.

It’s simple to create a home.

It’s simple to add an accessory.

It’s simple to interact with it.

You can easily get the lists of accessories that are available and display them to users.

We’ve also enabled you to get an early start and also to be able to very effectively and easily debug and test your applications using the HomeKit Accessory Simulator.

And there’s information available for you if you’re curious about how to get started, either with HomeKit or with making a HomeKit accessory at

For more information, we have our great Evangelism Team who is there for you to reach out to.

And we have documentation available at all the regular places, including the MFi Program for accessory manufacturers.

So that finishes for me today.

I want to say thank you very much.

[ Applause ]

I definitely appreciate the opportunity to talk to you.

Enjoy the rest of the show.

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US