이 가이드는 iOS에서 기기 및 기기 메타데이터 액세스에 이어 기기 제어 및 액세스의 추가 예를 소개합니다.
특정 기기 유형 또는 특성(예: 여기의 여러 예에서 사용된 Matter
OnOffTrait)을 사용하려면 가져와야 합니다.
import GoogleHomeSDK
import GoogleHomeTypes
특성이 명령어를 지원하는지 확인하기
특성 수준 supports 함수를 사용하여 특정 기기에서 명령어가 지원되는지 확인합니다.
예를 들어 기기가 On/Off 특성의 toggle 명령어를 지원하는지 확인하려면 다음을 실행합니다.
// Check if the OnOff trait supports the toggle command. if onOffTraitTest.supportsToggleCommand { print("onOffTrait supports toggle command") } else { print("onOffTrait does not support stateful toggle command") }
기기에 명령어 전송
명령어를 전송하는 것은 특성에서 상태 속성을 읽는 것과 유사합니다. 기기를 켜거나 끄려면 Google Home 생태계 데이터 모델에서 toggle()로 정의된 OnOffTrait 전환 명령어를 사용합니다. 이 메서드는 onOff가 true인 경우 false로 변경하고 false인 경우 true로 변경합니다.
// Calling a command on a trait. do { try await onOffTraitTest.toggle() } catch let _ as HomeError { // Code for handling the exception }
실행 흐름에서 문제가 감지되면 명령어가 예외를 반환할 수 있습니다. 개발자는 do-catch 블록을 사용하여 이러한 예외를 적절하게 처리하고 오류를 해결할 수 있는 경우 사용자에게 자세한 정보를 표시해야 합니다. 처리되지 않은 예외는 앱 런타임을 중지하고 앱에서 비정상 종료를 일으킬 수 있습니다.
또는 off() 또는 on() 명령어를 사용하여 상태를 명시적으로 설정합니다.
do { try await onOffTraitTest.off() try await onOffTraitTest.on() } catch let _ as HomeError { // Code for handling the exception }
상태를 변경하는 명령어를 전송한 후 완료되면 기기 상태 읽기에 설명된 대로 상태를 읽어 앱에서 처리할 수 있습니다.
매개변수가 있는 명령어 전송
일부 명령어는 OnOffTrait 또는 LevelControlTrait의 매개변수와 같은 매개변수를 사용할 수 있습니다.
offWithEffect
// Turn off the light using the DyingLight effect. do { try await onOffTraitTest.offWithEffect( effectIdentifier: Matter.OnOffTrait.EffectIdentifierEnum.dyingLight, effectVariant: 0 ) } catch let _ as HomeError { // Code for handling the exception }
moveToLevel
// Change the brightness of the light to 50% do { try await levelControlTraitTest.moveToLevel( level: UInt8(127), transitionTime: 0, optionsMask: Matter.LevelControlTrait.OptionsBitmap(), optionsOverride: Matter.LevelControlTrait.OptionsBitmap() ) } catch let _ as HomeError { // Code for handling the exception }
특성이 속성을 지원하는지 확인하기
일부 기기는 Matter 특성을 지원하지만 특정 속성은 지원하지 않을 수 있습니다. 예를 들어 Matter에 매핑된 Cloud-to-cloud 기기는 모든 Matter 속성을 지원하지 않을 수 있습니다. 이러한 케이스를 처리하려면 특성 수준 isSupported 속성을 사용하여 특정 기기에서 속성이 지원되는지 확인합니다.
예를 들어 기기가 On/Off 특성의 onOff 속성을 지원하는지 확인하려면 다음을 실행합니다.
// Check if the OnOff trait supports the onOff attribute. if onOffTrait.attributes.$onOff.isSupported { print("onOffTrait supports onOff state") } else { print("onOffTrait is for a command only device!") }
일부 속성은 Matter 사양 또는 Cloud-to-cloud smart home 스키마에서 null을 허용합니다. 이러한 속성의 경우 isSupported 외에 isNullable를 사용하여 속성에서 반환된 nil이 기기에서 해당 값을 보고하지 않았기 때문인지 또는 속성 값이 실제로 nil인지 확인할 수 있습니다.
// Check if a nullable attribute is set or is not supported. if let deviceType = await device.types.get(OnOffLightDeviceType.self) { if let onOffTrait = deviceType.traits[Matter.OnOffTrait.self] { if onOffTrait.attributes.startUpOnOff == nil { if onOffTrait.attributes.$startUpOnOff.isSupported { print( "onOffTrait supports startUpOnOff and it is nil. Check the spec for the contextual meaning." ) } else { print("onOffTrait does not support startUpOnOff!") } } else { print( "onOffTrait supports startUpOnOff and it is set to \(String(describing: onOffTrait.attributes.startUpOnOff))" ) } } }
특성 속성 업데이트
지정된 속성의 값을 변경하고 싶지만 특성의 명령어 중 어느 것도 이 작업을 수행하지 않는 경우 속성에서 값을 명시적으로 설정할 수 있습니다.
속성 값을 변경할 수 있는지 여부는 다음 두 가지 요소에 따라 달라집니다.
- 속성이 쓰기 가능한가요?
- 특성 명령어를 전송하는 부작용으로 속성 값이 변경될 수 있나요?
특성 및 속성에 관한 참고 문서에서 이 정보를 제공합니다.
따라서 속성 값이 변경되는 방식을 지정하는 속성 조합은 다음과 같습니다.
읽기 전용이며 다른 명령어의 영향을 받지 않습니다. 즉, 속성 값이 변경되지 않습니다. 예를 들어
SwitchTrait의currentPosition속성입니다.읽기 전용이며 다른 명령어의 영향을 받습니다. 즉, 속성 값을 변경하는 유일한 방법은 명령어를 전송하는 것입니다. 예를 들어
LevelControlTrait의currentLevel속성은 읽기 전용이지만moveToLevel와 같은 명령어로 값을 변경할 수 있습니다.쓰기 가능하며 다른 명령어의 영향을 받지 않습니다. 즉, 특성의
update함수를 사용하여 속성 값을 직접 변경할 수 있지만 속성 값에 영향을 미치는 명령어는 없습니다. 예를 들어DoorLockTrait의WrongCodeEntryLimit속성입니다.쓰기 가능하며 다른 명령어의 영향을 받습니다. 즉, 특성의
update함수를 사용하여 속성 값을 직접 변경할 수 있으며 명령어를 전송한 결과로 속성 값이 변경될 수 있습니다. 예를 들어ThermostatTrait의occupiedCoolingSetpoint속성은 작성할 수 있지만setpointRaiseLower명령어로 업데이트할 수도 있습니다.
update 함수를 사용하여 속성 값을 변경하는 예시
이 예시에서는 DoorLockTrait.wrongCodeEntryLimit 속성 값을 명시적으로 설정하는 방법을 보여줍니다.
속성 값을 설정하려면 특성의 update 함수를 호출하고 새 값을 설정하는 업데이트 함수를 전달합니다. 먼저 특성이 속성을 지원하는지 확인하는 것이 좋습니다.
예를 들면 다음과 같습니다.
if doorLockTraitTest.attributes.$wrongCodeEntryLimit.isSupported { let _ = try await doorLockTraitTest.update { $0.setWrongCodeEntryLimit(3) } }
기기 그룹 제어
구성원 기기를 반복하여 그룹의 모든 구성원을 세밀하게 제어하는 것 외에도 DeviceGroup를 단일 항목으로 제어할 수 있습니다. DeviceGroup는 HasParts 프로토콜을 준수하며 그룹의 기기에서 지원하는 DeviceType 부분을 노출합니다.
await group.part(_:)는 그룹에서 지원하는 경우 지정된DeviceType의 첫 번째 인스턴스를 반환하고, 그렇지 않으면nil를 반환합니다.try await group.parts(_:)는 지정된DeviceType와 일치하는 모든 최상위 부분의 배열을 반환합니다.
DeviceGroup의 기기 유형 부분에서 특성 명령어를 호출하면 SDK는 기본 연결 또는 전송 (예: Matter 또는 Cloud-to-cloud)에 관계없이 해당 기능을 지원하는 그룹의 모든 연결된 구성원 기기에 명령어를 전달합니다.
그룹 부분 특성 속성 및 오류 처리
그룹 부분을 타겟팅하면 그룹 전체에 멱등성 명령어 (예: 조명 켜기/끄기, 밝기 수준 설정)를 전송하려는 일반적인 사례가 간소화됩니다. DeviceGroup 부분에서 특성과 명령어를 사용할 때는 다음 동작에 유의하세요.
- 동적 상태 속성 (예:
OnOffTrait의onOff속성 또는LevelControlTrait의currentLevel속성)은 일반적으로 그룹 부분의 특성에 채워지지 않습니다. 그룹의 구성원 기기가 단일 값으로 결합할 수 없는 다른 상태에 있을 수 있기 때문입니다. 그러나 지원되는 명령어 (supports(_:)로 확인, 예: 조광 가능한 조명의.moveToLevelWithOnOff)와 일부 기능 속성 (예: 컬러 조명의ColorControlTrait에 있는colorTempPhysicalMinMireds및colorTempPhysicalMaxMireds)이 채워지므로 앱에서 UI 컨트롤을 적절하게 구성할 수 있습니다. - 그룹 구성원의 특성에 대한 일부 명령어는 그룹 부분에서 사용할 수 없습니다. 특히 값을 반환하는 명령어는 사용할 수 없습니다.
- 그룹 부분의 명령어는 각 기본 구성원 기기 명령어의 개별 결과를 반환하지 않습니다. 개별 명령어 결과를 검사하거나 값을 반환하는 명령어를 호출하려면 그룹의 구성원 기기를 직접 반복합니다.
DeviceGroup의 부분에 전송된 명령어는 구성원 기기 전체의 팬아웃이 완료되고 모든 기본 명령어 성공 또는 실패가 수집되면 완료됩니다. 명령어는 연결된 모든 구성원 기기에서 명령어가 실패하거나 모든 대상 기기를 사용할 수 없는 경우에만 실패하며 (HomeError발생), 단일 명령어 호출 문법과 일치하는 단일 명령어 실패로 표시됩니다. 하나 이상의 구성원 기기가 명령어를 실행하면 그룹 명령어가 오류를 발생시키지 않고 완료됩니다.
그룹 부분에 명령어 전송
기기 그룹의 모든 OnOffLightDeviceType 조명을 켜려면 다음 단계를 따르세요.
if let lightPart = await group.part(OnOffLightDeviceType.self),
let onOffTrait = lightPart.matterTraits.onOffTrait,
onOffTrait.supports(.on) {
try await onOffTrait.on()
}
여러 관련 기기 유형을 확인할 수도 있습니다 (예: OnOffTrait를 지원하는 그룹의 조명 기기 유형 사용 중지).
func onOffTrait(in group: DeviceGroup) async -> Matter.OnOffTrait? {
if let light = await group.part(OnOffLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
if let light = await group.part(DimmableLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
if let light = await group.part(ColorTemperatureLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
if let light = await group.part(ExtendedColorLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
return nil
}
if let trait = await onOffTrait(in: group) {
try await trait.off()
}
명령어를 전송하기 전에 그룹 부분에서 명령어 지원을 확인하거나 기능 경계를 읽을 수 있습니다 (예: 조광 가능 조명 부분에서 .moveToLevelWithOnOff 확인 또는 색상 온도 조명 부분에서 colorTempPhysicalMinMireds 및 colorTempPhysicalMaxMireds 읽기).
if let dimmableLight = await group.part(DimmableLightDeviceType.self),
let levelTrait = dimmableLight.matterTraits.levelControlTrait,
levelTrait.supports(.moveToLevelWithOnOff) {
try await levelTrait.moveToLevelWithOnOff(
level: 127,
transitionTime: nil,
optionsMask: [],
optionsOverride: []
)
}
if let colorLight = await group.part(ColorTemperatureLightDeviceType.self),
let colorTrait = colorLight.matterTraits.colorControlTrait,
let minMireds = colorTrait.attributes.colorTempPhysicalMinMireds,
let maxMireds = colorTrait.attributes.colorTempPhysicalMaxMireds {
let midMireds = UInt16((UInt32(minMireds) + UInt32(maxMireds)) / 2)
try await colorTrait.moveToColorTemperature(
colorTemperatureMireds: midMireds,
transitionTime: 0,
optionsMask: [],
optionsOverride: []
)
}