服务(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 识别:
使用 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识别:
比如,对于一个车库开门器来说,目标状态就是打开或者关闭。对于一个锁来说,目标状态又是上锁和未上锁。
在你获得了一个 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 文档,获悉你应该实现哪些方法以观察这些变化。