第六部分:访问服务和特性
服务(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文档,获悉你应该实现哪些方法以观察这些变化。
更多建议: