返回首页 HomeKit 开发指南

访问服务和特性

服务(HMService)代表了一个配件(accessory)的某个功能和一些具有可读写的特性(HMCharacteristic)。一个配件可以拥有多项服务,一个服务也可以有很多特性。比如一个车库开门器可能拥有一个照明和开关的服务。照明服务可能拥有打开/关闭和调节亮度的特性。用户不能制造智能家电配件和它们的服务-配件制造商会制造配件和它们的服务-但是用户可以改变服务的特性。一些拥有可读写属性的特性代表着某种物理状态,比如,一个恒温器中的当前温度就是一个只可读的值,但是目标温度又是可读写的。苹果预先定义了一些服务和特性的名称,以便让 Siri 能够识别它们。

获得配件的服务和属性

在依照 Getting the Accessroties in a Room 中描述,你创建了一个配件对象之后,你可以获得配件的服务和特性。当然你也可以直接从 home 中按照类型获得不同的服务。

重要:不要暴露匿名服务-比如固件升级服务-给用户

通过 HMAccessory 类对象的 services 属性,我们可以获得一个配件的服务。

NSArray *services = accessroy.services;

要获得一个 home 当中配件提供的特定服务,使用 HMHome 类对象的 servicesWithTypes:方法。

// Get all lights and thermostats in a home
NSArray *lightServices = [home servicesWithTypes:[HMServicesTypeLightbulb]];
NSArray *thermostatServices = [home servicesWithTypes:[HMServicesTypeThermostat]];

使用 HMServices 类对象的 name 属性来获得服务的名称

NSString *name = services.name;

要获得一个服务的特性,请使用 characteristics 属性。

NSArray *characteristics = service.characteristics

使用 servicesType 属性来获得服务的类型

NSString *serviceType = service.serviceType;

苹果定义了一些服务类型,并能被 Siri 识别:

  • 门锁(Door locks)
  • 车库开门器(Garage door openers)
  • 灯光(Lights)
  • 插座(Outlets)
  • 恒温器(Thermostats)

改变服务名称

使用 updateName:completionHandler:异步方法来改变服务名称。传入此方法的服务名称参数必须在一个 home 当中是唯一的,并且服务名可被 Siri 识别。

[service updateName:@"Garage 1 Opener" completionHandler:^(NSError *error) {
    if (error) {
        // Failed to change the name
    } else {
        // Successfully changed the name
    }
}];

访问特性的值

特性代表了一个服务的一个参数,它要么是只读、可读写或者只写。它提供了这个参数可能的值的信息,比如,一个布尔或者一个范围值。恒温器中的温度就是只读的,而目标温度又是可读写的。一个执行某个任务的命令且不要求任何返回-比如播放一段声音或者闪烁一下灯光来确认某个配件-可能就是只写的。

苹果定义了一些特性的类型,并能被Siri识别:

  • 亮度(Brightness)
  • 最近温度(Current temperature)
  • 锁的状态(Lock state)
  • 电源的状态(Power state)
  • 目标状态(Target state)
  • 目标温度(Target temperature)

比如,对于一个车库开门器来说,目标状态就是打开或者关闭。对于一个锁来说,目标状态又是上锁和未上锁。

在你获得了一个 HMService 对象之后,如 Getting Services and Their Properties 所描述的,你可以获得每个服务的特性的值。因为这些值是从配件中获得的,这些读写的方法都是异步的,并可以传入一个完成回调的 block。

使用 readValueWithCompletionHandler:异步方法来读取一个特性的值。

[characteristic readValueWithCompletionHandler:^(NSError *error) {
    if (error == nil) {
       // Successfully read the value
       id value = characteristic.value;
    }
    else {
       // Unable to read the value
} }];

在 if 语句块中,加入你的代码以更新 App 的视图。

使用 writeValue:completionHandler:异步方法来向一个特性写入值。

[self.characteristic writeValue:@42 withCompletionHandler:^(NSError *error) {
    if (error == nil) {
       // Successfully wrote the value
    }
    else {
       // Unable to write the value
} }];

不要以为函数调用完成就意味着写入成功,实际上只有在当完成回调执行并没有错误产生时才表示写入成功。比如,直到一个开关的特性改变之前都不要改变这个开关的状态。在 if 语句块中,加入你的代码,以更新 App 的视图。

另外,在别的app更新了特性的值时也需要更新视图,在Observing Changes to Accessories中有描述。

创建服务组

一个服务组(HMServiceGroup)提供了控制不同配件的任意数量服务的快捷方式-比如,当用户离开家之后控制家中的某些灯。

在你创建了一个 HMHome 对象之后,如 Getting the Primary Home and Collection of Homes 中描述,你也就在这个家中创建一个服务组。

为了创建一个服务组,我们使用 HMHome 类对象的 addServiceGroupWithName:completionHandler:方法。方法中参数服务组的名称必须在此家中唯一,并可以被 Siri 识别。

[self.home addServiceGroupWithName:@"Away Lights" completionHandler:^(HMServiceGroup *serviceGroup, NSError *error) {
    if (error == nil) {
       // Successfully created the service group
} else {
       // Unable to create the service group
    }];

我们使用 HMServiceGroup 类对象的 addService:completionHandler:方法来向服务组中添加一个服务。服务可以在一个或多个服务组中。

[serviceGroup addService:service completionHandler:^(NSError *error) {
    if (error == nil) {
       // Successfully added service to service group
    }
       // Unable to add the service to the service group
    }];

通过 HMHome 类对象的 serviceGroups 属性,来获得这个家的所有服务组。

NSArray *serviceGroups = self.home.serviceGroups;

通过 HMServiceGroup 类对象的 accessory 属性,我们获得服务所对应的智能电器。

HMAccessory *accessory = service.accessory;

和配件类似,代理方法在别的 App 改变服务组时也会被调用。如果你的app使用了服务组,请阅读 HMHomeDelegate Protocol Reference 文档,获悉你应该实现哪些方法以观察这些变化。