From 62a6a668400b10f0ff414f4c10cd0629e108eb4e Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Mon, 28 Jan 2019 13:24:02 +0100 Subject: [PATCH 01/24] =?UTF-8?q?Add=20television=20support=20=E2=80=93=20?= =?UTF-8?q?#132?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accessory/constant.go | 2 + accessory/television.go | 24 + characteristic/active_identifier.go | 19 + characteristic/bool.go | 2 +- characteristic/bytes.go | 8 + characteristic/characteristic.go | 27 +- characteristic/characteristic_test.go | 18 +- characteristic/closed_captions.go | 25 + characteristic/configured_name.go | 18 + characteristic/constants.go | 1 + characteristic/current_media_state.go | 28 + characteristic/current_visibility_state.go | 25 + characteristic/display_order.go | 18 + characteristic/float.go | 2 +- characteristic/identifier.go | 20 + characteristic/input_device_type.go | 29 + characteristic/input_source_type.go | 34 + characteristic/int.go | 2 +- characteristic/picture_mode.go | 31 + characteristic/power_mode_selection.go | 24 + characteristic/remote_key.go | 35 + characteristic/sleep_discovery_mode.go | 25 + characteristic/string.go | 2 +- characteristic/target_media_state.go | 26 + characteristic/target_visibility_state.go | 25 + characteristic/volume_control_type.go | 27 + characteristic/volume_selector.go | 24 + gen/metadata.json | 6240 +++++++++++--------- hap/pair/pairing_controller.go | 6 - ip_transport.go | 7 +- service/input_source.go | 52 + service/service.go | 33 + service/service_test.go | 61 + service/television.go | 68 + transport.go | 6 +- 35 files changed, 4045 insertions(+), 2949 deletions(-) create mode 100644 accessory/television.go create mode 100644 characteristic/active_identifier.go create mode 100644 characteristic/closed_captions.go create mode 100644 characteristic/configured_name.go create mode 100644 characteristic/current_media_state.go create mode 100644 characteristic/current_visibility_state.go create mode 100644 characteristic/display_order.go create mode 100644 characteristic/identifier.go create mode 100644 characteristic/input_device_type.go create mode 100644 characteristic/input_source_type.go create mode 100644 characteristic/picture_mode.go create mode 100644 characteristic/power_mode_selection.go create mode 100644 characteristic/remote_key.go create mode 100644 characteristic/sleep_discovery_mode.go create mode 100644 characteristic/target_media_state.go create mode 100644 characteristic/target_visibility_state.go create mode 100644 characteristic/volume_control_type.go create mode 100644 characteristic/volume_selector.go create mode 100644 service/input_source.go create mode 100644 service/service_test.go create mode 100644 service/television.go diff --git a/accessory/constant.go b/accessory/constant.go index db1ae40d..0abd30c6 100644 --- a/accessory/constant.go +++ b/accessory/constant.go @@ -30,4 +30,6 @@ const ( TypeSprinklers AccessoryType = 28 TypeFaucets AccessoryType = 29 TypeShowerSystems AccessoryType = 30 + TypeTelevision AccessoryType = 31 + TypeRemoteControl AccessoryType = 32 ) diff --git a/accessory/television.go b/accessory/television.go new file mode 100644 index 00000000..017a8b28 --- /dev/null +++ b/accessory/television.go @@ -0,0 +1,24 @@ +package accessory + +import ( + "github.com/brutella/hc/service" +) + +type Television struct { + *Accessory + Television *service.Television + Speaker *service.Speaker +} + +// NewOutlet returns an outlet accessory containing one outlet service. +func NewTelevision(info Info) *Television { + acc := Television{} + acc.Accessory = New(info, TypeTelevision) + acc.Television = service.NewTelevision() + acc.Speaker = service.NewSpeaker() + + acc.AddService(acc.Television.Service) + acc.AddService(acc.Speaker.Service) + + return &acc +} diff --git a/characteristic/active_identifier.go b/characteristic/active_identifier.go new file mode 100644 index 00000000..d7a5bd06 --- /dev/null +++ b/characteristic/active_identifier.go @@ -0,0 +1,19 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const TypeActiveIdentifier = "E7" + +type ActiveIdentifier struct { + *Int +} + +func NewActiveIdentifier() *ActiveIdentifier { + char := NewInt(TypeActiveIdentifier) + char.Format = FormatUInt32 + char.Perms = []string{PermRead, PermWrite, PermEvents} + char.SetMinValue(0) + + char.SetValue(0) + + return &ActiveIdentifier{char} +} diff --git a/characteristic/bool.go b/characteristic/bool.go index 1d24feb9..31500514 100644 --- a/characteristic/bool.go +++ b/characteristic/bool.go @@ -22,7 +22,7 @@ func (c *Bool) SetValue(value bool) { // GetValue returns the value as bool func (c *Bool) GetValue() bool { - return c.Value.(bool) + return c.Characteristic.GetValue().(bool) } // OnValueRemoteGet calls fn when the value was read by a client. diff --git a/characteristic/bytes.go b/characteristic/bytes.go index 6a43b855..f3999be6 100644 --- a/characteristic/bytes.go +++ b/characteristic/bytes.go @@ -2,6 +2,7 @@ package characteristic import ( "encoding/base64" + "net" ) type Bytes struct { @@ -28,6 +29,13 @@ func (bs *Bytes) GetValue() []byte { } } +// OnValueRemoteUpdate calls fn when the value was updated by a client. +func (bs *Bytes) OnValueRemoteUpdate(fn func([]byte)) { + bs.OnValueUpdateFromConn(func(conn net.Conn, c *Characteristic, new, old interface{}) { + fn(new.([]byte)) + }) +} + func base64FromBytes(b []byte) string { return base64.StdEncoding.EncodeToString(b) } diff --git a/characteristic/characteristic.go b/characteristic/characteristic.go index 0a80baf7..a3a65869 100644 --- a/characteristic/characteristic.go +++ b/characteristic/characteristic.go @@ -2,9 +2,9 @@ package characteristic import ( "fmt" - "github.com/gosexy/to" "net" - "reflect" + + "github.com/gosexy/to" ) type ConnChangeFunc func(conn net.Conn, c *Characteristic, newValue, oldValue interface{}) @@ -149,11 +149,7 @@ func (c *Characteristic) getValue(conn net.Conn) interface{} { // // When permissions are write only and checkPerms is true, this methods does not set the Value field. func (c *Characteristic) updateValue(value interface{}, conn net.Conn, checkPerms bool) { - if c.Value != nil { - if converted, err := to.Convert(value, reflect.TypeOf(c.Value).Kind()); err == nil { - value = converted - } - } + value = c.convert(value) // Value must be within min and max switch c.Format { @@ -222,3 +218,20 @@ func (c *Characteristic) boundIntValue(value int) interface{} { return value } + +func (c *Characteristic) convert(v interface{}) interface{} { + switch c.Format { + case FormatFloat: + return to.Float64(v) + case FormatUInt8: + return int(to.Uint64(v)) + case FormatUInt32: + return int(to.Uint64(v)) + case FormatInt32: + return int(to.Uint64(v)) + case FormatUInt64: + return int(to.Uint64(v)) + default: + return v + } +} diff --git a/characteristic/characteristic_test.go b/characteristic/characteristic_test.go index c365d6d3..dbaf3713 100644 --- a/characteristic/characteristic_test.go +++ b/characteristic/characteristic_test.go @@ -9,7 +9,7 @@ func TestCharacteristicGetValue(t *testing.T) { getCalls := 0 updateCalls := 0 - c := NewCharacteristic(TypeOn) + c := NewBrightness() c.Value = getCalls c.OnValueUpdateFromConn(func(conn net.Conn, c *Characteristic, new, old interface{}) { @@ -46,7 +46,7 @@ func TestCharacteristicGetValue(t *testing.T) { } func TestCharacteristicUpdateValuesOfWrongType(t *testing.T) { - c := NewCharacteristic(TypeOn) + c := NewBrightness() c.Value = 5 c.UpdateValue(float64(20.5)) @@ -69,7 +69,7 @@ func TestCharacteristicUpdateValuesOfWrongType(t *testing.T) { } func TestCharacteristicLocalDelegate(t *testing.T) { - c := NewCharacteristic(TypeOn) + c := NewBrightness() c.Value = 5 var oldValue interface{} @@ -92,7 +92,7 @@ func TestCharacteristicLocalDelegate(t *testing.T) { } func TestCharacteristicRemoteDelegate(t *testing.T) { - c := NewCharacteristic(TypeOn) + c := NewBrightness() c.Perms = PermsAll() c.Value = 5 @@ -118,7 +118,7 @@ func TestCharacteristicRemoteDelegate(t *testing.T) { } func TestNoValueChange(t *testing.T) { - c := NewCharacteristic(TypeOn) + c := NewBrightness() c.Value = 5 changed := false @@ -142,7 +142,7 @@ func TestNoValueChange(t *testing.T) { } func TestReadOnlyValue(t *testing.T) { - c := NewCharacteristic(TypeOn) + c := NewBrightness() c.Perms = PermsRead() c.Value = 5 @@ -174,13 +174,13 @@ func TestReadOnlyValue(t *testing.T) { } func TestEqual(t *testing.T) { - c1 := NewCharacteristic(TypeOn) + c1 := NewBrightness() c1.Value = 5 - c2 := NewCharacteristic(TypeOn) + c2 := NewBrightness() c2.Value = 5 - if c1.Equal(c2) == false { + if c1.Characteristic.Equal(c2.Characteristic) == false { t.Fatal("characteristics not the same") } } diff --git a/characteristic/closed_captions.go b/characteristic/closed_captions.go new file mode 100644 index 00000000..6eb74b47 --- /dev/null +++ b/characteristic/closed_captions.go @@ -0,0 +1,25 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + ClosedCaptionsDisabled int = 0 + ClosedCaptionsEnabled int = 1 +) + +const TypeClosedCaptions = "DD" + +type ClosedCaptions struct { + *Int +} + +func NewClosedCaptions() *ClosedCaptions { + char := NewInt(TypeClosedCaptions) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermWrite, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(1) + char.SetStepValue(1) + char.SetValue(0) + + return &ClosedCaptions{char} +} diff --git a/characteristic/configured_name.go b/characteristic/configured_name.go new file mode 100644 index 00000000..c931b5ff --- /dev/null +++ b/characteristic/configured_name.go @@ -0,0 +1,18 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const TypeConfiguredName = "E3" + +type ConfiguredName struct { + *String +} + +func NewConfiguredName() *ConfiguredName { + char := NewString(TypeConfiguredName) + char.Format = FormatString + char.Perms = []string{PermRead, PermWrite, PermEvents} + + char.SetValue("") + + return &ConfiguredName{char} +} diff --git a/characteristic/constants.go b/characteristic/constants.go index ee62c0f8..4657d7ac 100644 --- a/characteristic/constants.go +++ b/characteristic/constants.go @@ -33,6 +33,7 @@ const ( UnitCelsius = "celsius" UnitLux = "lux" UnitSeconds = "seconds" + UnitPPM = "ppm" ) // HAP characterisitic formats diff --git a/characteristic/current_media_state.go b/characteristic/current_media_state.go new file mode 100644 index 00000000..ad81ad6b --- /dev/null +++ b/characteristic/current_media_state.go @@ -0,0 +1,28 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + CurrentMediaStatePlay int = 0 + CurrentMediaStatePause int = 1 + CurrentMediaStateStop int = 2 + CurrentMediaStateUnknown int = 3 +) + +const TypeCurrentMediaState = "E0" + +type CurrentMediaState struct { + *Int +} + +func NewCurrentMediaState() *CurrentMediaState { + char := NewInt(TypeCurrentMediaState) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(3) + char.SetStepValue(1) + char.SetValue(0) + char.Unit = UnitPercentage + + return &CurrentMediaState{char} +} diff --git a/characteristic/current_visibility_state.go b/characteristic/current_visibility_state.go new file mode 100644 index 00000000..fc096dea --- /dev/null +++ b/characteristic/current_visibility_state.go @@ -0,0 +1,25 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + CurrentVisibilityStateShown int = 0 + CurrentVisibilityStateHidden int = 1 +) + +const TypeCurrentVisibilityState = "135" + +type CurrentVisibilityState struct { + *Int +} + +func NewCurrentVisibilityState() *CurrentVisibilityState { + char := NewInt(TypeCurrentVisibilityState) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(3) + char.SetStepValue(1) + char.SetValue(0) + + return &CurrentVisibilityState{char} +} diff --git a/characteristic/display_order.go b/characteristic/display_order.go new file mode 100644 index 00000000..75416800 --- /dev/null +++ b/characteristic/display_order.go @@ -0,0 +1,18 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const TypeDisplayOrder = "136" + +type DisplayOrder struct { + *Bytes +} + +func NewDisplayOrder() *DisplayOrder { + char := NewBytes(TypeDisplayOrder) + char.Format = FormatTLV8 + char.Perms = []string{PermRead, PermWrite, PermEvents} + + char.SetValue([]byte{}) + + return &DisplayOrder{char} +} diff --git a/characteristic/float.go b/characteristic/float.go index 50ab3dfc..f3032bad 100644 --- a/characteristic/float.go +++ b/characteristic/float.go @@ -32,7 +32,7 @@ func (c *Float) SetStepValue(value float64) { // GetValue returns the value as float func (c *Float) GetValue() float64 { - return c.Value.(float64) + return c.Characteristic.GetValue().(float64) } func (c *Float) GetMinValue() float64 { diff --git a/characteristic/identifier.go b/characteristic/identifier.go new file mode 100644 index 00000000..83595c8e --- /dev/null +++ b/characteristic/identifier.go @@ -0,0 +1,20 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const TypeIdentifier = "E6" + +type Identifier struct { + *Int +} + +func NewIdentifier() *Identifier { + char := NewInt(TypeIdentifier) + char.Format = FormatUInt32 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + + char.SetStepValue(1) + char.SetValue(0) + + return &Identifier{char} +} diff --git a/characteristic/input_device_type.go b/characteristic/input_device_type.go new file mode 100644 index 00000000..1cf5ad23 --- /dev/null +++ b/characteristic/input_device_type.go @@ -0,0 +1,29 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + InputDeviceTypeOther int = 0 + InputDeviceTypeTv int = 1 + InputDeviceTypeRecording int = 2 + InputDeviceTypeTuner int = 3 + InputDeviceTypePlayback int = 4 + InputDeviceTypeAudioSystem int = 5 +) + +const TypeInputDeviceType = "DC" + +type InputDeviceType struct { + *Int +} + +func NewInputDeviceType() *InputDeviceType { + char := NewInt(TypeInputDeviceType) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(5) + char.SetStepValue(1) + char.SetValue(0) + + return &InputDeviceType{char} +} diff --git a/characteristic/input_source_type.go b/characteristic/input_source_type.go new file mode 100644 index 00000000..365aab8c --- /dev/null +++ b/characteristic/input_source_type.go @@ -0,0 +1,34 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + InputSourceTypeOther int = 0 + InputSourceTypeHomeScreen int = 1 + InputSourceTypeApplication int = 10 + InputSourceTypeTuner int = 2 + InputSourceTypeHdmi int = 3 + InputSourceTypeCompositeVideo int = 4 + InputSourceTypeSVideo int = 5 + InputSourceTypeComponentVideo int = 6 + InputSourceTypeDvi int = 7 + InputSourceTypeAirplay int = 8 + InputSourceTypeUsb int = 9 +) + +const TypeInputSourceType = "DB" + +type InputSourceType struct { + *Int +} + +func NewInputSourceType() *InputSourceType { + char := NewInt(TypeInputSourceType) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(10) + char.SetStepValue(1) + char.SetValue(0) + + return &InputSourceType{char} +} diff --git a/characteristic/int.go b/characteristic/int.go index 82b71729..86f7a5ea 100644 --- a/characteristic/int.go +++ b/characteristic/int.go @@ -32,7 +32,7 @@ func (c *Int) SetStepValue(value int) { // GetValue returns the value as int func (c *Int) GetValue() int { - return c.Value.(int) + return c.Characteristic.GetValue().(int) } func (c *Int) GetMinValue() int { diff --git a/characteristic/picture_mode.go b/characteristic/picture_mode.go new file mode 100644 index 00000000..6ebbdde3 --- /dev/null +++ b/characteristic/picture_mode.go @@ -0,0 +1,31 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + PictureModeOther int = 0 + PictureModeStandard int = 1 + PictureModeCalibrated int = 2 + PictureModeCalibratedDark int = 3 + PictureModeVivid int = 4 + PictureModeGame int = 5 + PictureModeComputer int = 6 + PictureModeCustom int = 7 +) + +const TypePictureMode = "E2" + +type PictureMode struct { + *Int +} + +func NewPictureMode() *PictureMode { + char := NewInt(TypePictureMode) + char.Format = FormatUInt16 + char.Perms = []string{PermRead, PermWrite, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(13) + char.SetStepValue(1) + char.SetValue(0) + + return &PictureMode{char} +} diff --git a/characteristic/power_mode_selection.go b/characteristic/power_mode_selection.go new file mode 100644 index 00000000..3a946199 --- /dev/null +++ b/characteristic/power_mode_selection.go @@ -0,0 +1,24 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + PowerModeSelectionShow int = 0 + PowerModeSelectionHide int = 1 +) + +const TypePowerModeSelection = "DF" + +type PowerModeSelection struct { + *Int +} + +func NewPowerModeSelection() *PowerModeSelection { + char := NewInt(TypePowerModeSelection) + char.Format = FormatUInt8 + char.Perms = []string{PermWrite} + char.SetMinValue(0) + char.SetMaxValue(1) + char.SetStepValue(1) + + return &PowerModeSelection{char} +} diff --git a/characteristic/remote_key.go b/characteristic/remote_key.go new file mode 100644 index 00000000..8f377783 --- /dev/null +++ b/characteristic/remote_key.go @@ -0,0 +1,35 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + RemoteKeyRewind int = 0 + RemoteKeyFastForward int = 1 + RemoteKeyExit int = 10 + RemoteKeyPlayPause int = 11 + RemoteKeyInfo int = 15 + RemoteKeyNextTrack int = 2 + RemoteKeyPrevTrack int = 3 + RemoteKeyArrowUp int = 4 + RemoteKeyArrowDown int = 5 + RemoteKeyArrowLeft int = 6 + RemoteKeyArrowRight int = 7 + RemoteKeySelect int = 8 + RemoteKeyBack int = 9 +) + +const TypeRemoteKey = "E1" + +type RemoteKey struct { + *Int +} + +func NewRemoteKey() *RemoteKey { + char := NewInt(TypeRemoteKey) + char.Format = FormatUInt8 + char.Perms = []string{PermWrite} + char.SetMinValue(0) + char.SetMaxValue(16) + char.SetStepValue(1) + + return &RemoteKey{char} +} diff --git a/characteristic/sleep_discovery_mode.go b/characteristic/sleep_discovery_mode.go new file mode 100644 index 00000000..9ddad505 --- /dev/null +++ b/characteristic/sleep_discovery_mode.go @@ -0,0 +1,25 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + SleepDiscoveryModeNotDiscoverable int = 0 + SleepDiscoveryModeAlwaysDiscoverable int = 1 +) + +const TypeSleepDiscoveryMode = "E8" + +type SleepDiscoveryMode struct { + *Int +} + +func NewSleepDiscoveryMode() *SleepDiscoveryMode { + char := NewInt(TypeSleepDiscoveryMode) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(1) + + char.SetValue(0) + + return &SleepDiscoveryMode{char} +} diff --git a/characteristic/string.go b/characteristic/string.go index e9756af0..42664476 100644 --- a/characteristic/string.go +++ b/characteristic/string.go @@ -22,7 +22,7 @@ func (c *String) SetValue(str string) { // GetValue returns the value as string func (c *String) GetValue() string { - return c.Value.(string) + return c.Characteristic.GetValue().(string) } // OnValueRemoteGet calls fn when the value was read by a client. diff --git a/characteristic/target_media_state.go b/characteristic/target_media_state.go new file mode 100644 index 00000000..001d3ecb --- /dev/null +++ b/characteristic/target_media_state.go @@ -0,0 +1,26 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + TargetMediaStatePlay int = 0 + TargetMediaStatePause int = 1 + TargetMediaStateStop int = 2 +) + +const TypeTargetMediaState = "137" + +type TargetMediaState struct { + *Int +} + +func NewTargetMediaState() *TargetMediaState { + char := NewInt(TypeTargetMediaState) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermWrite, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(2) + char.SetStepValue(1) + char.SetValue(0) + + return &TargetMediaState{char} +} diff --git a/characteristic/target_visibility_state.go b/characteristic/target_visibility_state.go new file mode 100644 index 00000000..cebd8c20 --- /dev/null +++ b/characteristic/target_visibility_state.go @@ -0,0 +1,25 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + TargetVisibilityStateShown int = 0 + TargetVisibilityStateHidden int = 1 +) + +const TypeTargetVisibilityState = "134" + +type TargetVisibilityState struct { + *Int +} + +func NewTargetVisibilityState() *TargetVisibilityState { + char := NewInt(TypeTargetVisibilityState) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermWrite, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(2) + char.SetStepValue(1) + char.SetValue(0) + + return &TargetVisibilityState{char} +} diff --git a/characteristic/volume_control_type.go b/characteristic/volume_control_type.go new file mode 100644 index 00000000..e54eb4be --- /dev/null +++ b/characteristic/volume_control_type.go @@ -0,0 +1,27 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + VolumeControlTypeNone int = 0 + VolumeControlTypeRelative int = 1 + VolumeControlTypeRelativeWithCurrent int = 2 + VolumeControlTypeAbsolute int = 3 +) + +const TypeVolumeControlType = "E9" + +type VolumeControlType struct { + *Int +} + +func NewVolumeControlType() *VolumeControlType { + char := NewInt(TypeVolumeControlType) + char.Format = FormatUInt8 + char.Perms = []string{PermRead, PermEvents} + char.SetMinValue(0) + char.SetMaxValue(3) + char.SetStepValue(1) + char.SetValue(0) + + return &VolumeControlType{char} +} diff --git a/characteristic/volume_selector.go b/characteristic/volume_selector.go new file mode 100644 index 00000000..557740ce --- /dev/null +++ b/characteristic/volume_selector.go @@ -0,0 +1,24 @@ +// THIS FILE IS AUTO-GENERATED +package characteristic + +const ( + VolumeSelectorIncrement int = 0 + VolumeSelectorDecrement int = 1 +) + +const TypeVolumeSelector = "EA" + +type VolumeSelector struct { + *Int +} + +func NewVolumeSelector() *VolumeSelector { + char := NewInt(TypeVolumeSelector) + char.Format = FormatUInt8 + char.Perms = []string{PermWrite} + char.SetMinValue(0) + char.SetMaxValue(1) + char.SetStepValue(1) + + return &VolumeSelector{char} +} diff --git a/gen/metadata.json b/gen/metadata.json index 66abfbc7..e15be693 100644 --- a/gen/metadata.json +++ b/gen/metadata.json @@ -1,2926 +1,3324 @@ { - "Categories" : [ - { - "Name" : "Unknown", - "Category" : 0 - }, - { - "Name" : "Other", - "Category" : 1 - }, - { - "Name" : "Bridge", - "Category" : 2 - }, - { - "Name" : "Fan", - "Category" : 3 - }, - { - "Name" : "Garage Door Opener", - "Category" : 4 - }, - { - "Name" : "Lightbulb", - "Category" : 5 - }, - { - "Name" : "Door Lock", - "Category" : 6 - }, - { - "Name" : "Outlet", - "Category" : 7 - }, - { - "Name" : "Switch", - "Category" : 8 - }, - { - "Name" : "Thermostat", - "Category" : 9 - }, - { - "Name" : "Sensor", - "Category" : 10 - }, - { - "Name" : "Security System", - "Category" : 11 - }, - { - "Name" : "Door", - "Category" : 12 - }, - { - "Name" : "Window", - "Category" : 13 - }, - { - "Name" : "Window Covering", - "Category" : 14 - }, - { - "Name" : "Programmable Switch", - "Category" : 15 - }, - { - "Name" : "IP Camera", - "Category" : 17 - }, - { - "Name" : "Video Doorbell", - "Category" : 18 - }, - { - "Name" : "Air Purifier", - "Category" : 19 - }, - { - "Name" : "Heater", - "Category" : 20 - }, - { - "Name" : "Air Conditioner", - "Category" : 21 - }, - { - "Name" : "Humidifier", - "Category" : 22 - }, - { - "Name" : "Dehumidifier", - "Category" : 23 - }, - { - "Name" : "Sprinklers", - "Category" : 28 - }, - { - "Name" : "Faucets", - "Category" : 29 - }, - { - "Name" : "Shower Systems", - "Category" : 30 - } - ], - "Characteristics" : [ - { - "UUID" : "000000A6-0000-1000-8000-0026BB765291", - "Name" : "Accessory Flags", - "Constraints" : { - "ValidBits" : { - "0" : "Requires Additional Setup" + "Categories": [ + { + "Name": "Unknown", + "Category": 0 + }, + { + "Name": "Other", + "Category": 1 + }, + { + "Name": "Bridge", + "Category": 2 + }, + { + "Name": "Fan", + "Category": 3 + }, + { + "Name": "Garage Door Opener", + "Category": 4 + }, + { + "Name": "Lightbulb", + "Category": 5 + }, + { + "Name": "Door Lock", + "Category": 6 + }, + { + "Name": "Outlet", + "Category": 7 + }, + { + "Name": "Switch", + "Category": 8 + }, + { + "Name": "Thermostat", + "Category": 9 + }, + { + "Name": "Sensor", + "Category": 10 + }, + { + "Name": "Security System", + "Category": 11 + }, + { + "Name": "Door", + "Category": 12 + }, + { + "Name": "Window", + "Category": 13 + }, + { + "Name": "Window Covering", + "Category": 14 + }, + { + "Name": "Programmable Switch", + "Category": 15 + }, + { + "Name": "IP Camera", + "Category": 17 + }, + { + "Name": "Video Doorbell", + "Category": 18 + }, + { + "Name": "Air Purifier", + "Category": 19 + }, + { + "Name": "Heater", + "Category": 20 + }, + { + "Name": "Air Conditioner", + "Category": 21 + }, + { + "Name": "Humidifier", + "Category": 22 + }, + { + "Name": "Dehumidifier", + "Category": 23 + }, + { + "Name": "Sprinklers", + "Category": 28 + }, + { + "Name": "Faucets", + "Category": 29 + }, + { + "Name": "Shower Systems", + "Category": 30 + }, + { + "Name": "Television", + "Category": 31 + }, + { + "Name": "Remote Control", + "Category": 32 } - }, - "Format" : "uint32", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000B0-0000-1000-8000-0026BB765291", - "Name" : "Active", - "Constraints" : { - "ValidValues" : { - "0" : "Inactive", - "1" : "Active" + ], + "Characteristics": [ + { + "UUID": "000000A6-0000-1000-8000-0026BB765291", + "Name": "Accessory Flags", + "Constraints": { + "ValidBits": { + "0": "Requires Additional Setup" + } + }, + "Format": "uint32", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000B0-0000-1000-8000-0026BB765291", + "Name": "Active", + "Constraints": { + "ValidValues": { + "0": "Inactive", + "1": "Active" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000E7-0000-1000-8000-0026BB765291", + "Name": "Active Identifier", + "Constraints": { + "MinimumValue": 0 + }, + "Format": "uint32", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify" + ] + }, + { + "Name": "Administrator Only Access", + "Format": "bool", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "00000001-0000-1000-8000-0026BB765291" + }, + { + "UUID": "00000064-0000-1000-8000-0026BB765291", + "Name": "Air Particulate Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000065-0000-1000-8000-0026BB765291", + "Name": "Air Particulate Size", + "Constraints": { + "ValidValues": { + "0": "2.5 μm", + "1": "10 μm" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000095-0000-1000-8000-0026BB765291", + "Name": "Air Quality", + "Constraints": { + "ValidValues": { + "3": "Fair", + "1": "Excellent", + "4": "Inferior", + "2": "Good", + "0": "Unknown", + "5": "Poor" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Audio Feedback", + "Format": "bool", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "00000005-0000-1000-8000-0026BB765291" + }, + { + "Format": "uint8", + "UUID": "00000068-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Battery Level", + "Permissions": [ + "securedRead" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "int32", + "UUID": "00000008-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Brightness", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "UUID": "00000092-0000-1000-8000-0026BB765291", + "Name": "Carbon Dioxide Detected", + "Constraints": { + "ValidValues": { + "0": "CO2 Levels Normal", + "1": "CO2 Levels Abnormal" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000093-0000-1000-8000-0026BB765291", + "Name": "Carbon Dioxide Level", + "Constraints": { + "MaximumValue": 100000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000094-0000-1000-8000-0026BB765291", + "Name": "Carbon Dioxide Peak Level", + "Constraints": { + "MaximumValue": 100000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000069-0000-1000-8000-0026BB765291", + "Name": "Carbon Monoxide Detected", + "Constraints": { + "ValidValues": { + "0": "CO Levels Normal", + "1": "CO Levels Abnormal" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000090-0000-1000-8000-0026BB765291", + "Name": "Carbon Monoxide Level", + "Constraints": { + "MaximumValue": 100, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000091-0000-1000-8000-0026BB765291", + "Name": "Carbon Monoxide Peak Level", + "Constraints": { + "MaximumValue": 100, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "0000008F-0000-1000-8000-0026BB765291", + "Name": "Charging State", + "Constraints": { + "ValidValues": { + "0": "Not Charging", + "1": "Charging", + "2": "Not Chargeable" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000DD-0000-1000-8000-0026BB765291", + "Name": "Closed Captions", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1, + "MinimumValue": 0, + "ValidValues": { + "0": "Disabled", + "1": "Enabled" + } + }, + "Format": "uint8", + "Properties": [ + "read", + "write", + "cnotify" + ] + }, + { + "UUID": "000000E3-0000-1000-8000-0026BB765291", + "Name": "Configured Name", + "Format": "string", + "Properties": [ + "read", + "write", + "cnotify" + ] + }, + { + "UUID": "00000136-0000-1000-8000-0026BB765291", + "Name": "Display Order", + "Format": "tlv8", + "Properties": [ + "read", + "write", + "cnotify" + ] + }, + { + "UUID": "000000CE-0000-1000-8000-0026BB765291", + "Name": "Color Temperature", + "Constraints": { + "StepValue": 1, + "MaximumValue": 500, + "MinimumValue": 140 + }, + "Format": "uint32", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "0000006A-0000-1000-8000-0026BB765291", + "Name": "Contact Sensor State", + "Constraints": { + "ValidValues": { + "0": "Contact Detected", + "1": "Contact Not Detected" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "float", + "UUID": "0000000D-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Cooling Threshold Temperature", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "celsius", + "Constraints": { + "StepValue": 0.1, + "MaximumValue": 35, + "MinimumValue": 10 + } + }, + { + "UUID": "000000A9-0000-1000-8000-0026BB765291", + "Name": "Current Air Purifier State", + "Constraints": { + "ValidValues": { + "0": "Inactive", + "1": "Idle", + "2": "Purifying Air" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "float", + "UUID": "0000006B-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Ambient Light Level", + "Permissions": [ + "securedRead" + ], + "Unit": "lux", + "Constraints": { + "MaximumValue": 100000, + "MinimumValue": 0.0001 + } + }, + { + "UUID": "0000000E-0000-1000-8000-0026BB765291", + "Name": "Current Door State", + "Constraints": { + "ValidValues": { + "3": "Closing", + "1": "Closed", + "4": "Stopped", + "2": "Opening", + "0": "Open" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000AF-0000-1000-8000-0026BB765291", + "Name": "Current Fan State", + "Constraints": { + "ValidValues": { + "0": "Inactive", + "1": "Idle", + "2": "Blowing Air" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000B1-0000-1000-8000-0026BB765291", + "Name": "Current Heater Cooler State", + "Constraints": { + "ValidValues": { + "3": "Cooling", + "1": "Idle", + "2": "Heating", + "0": "Inactive" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "0000000F-0000-1000-8000-0026BB765291", + "Name": "Current Heating Cooling State", + "Constraints": { + "ValidValues": { + "0": "Off", + "1": "Heat", + "2": "Cool" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "int32", + "UUID": "0000006C-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Horizontal Tilt Angle", + "Permissions": [ + "securedRead" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 90, + "MinimumValue": -90 + } + }, + { + "UUID": "000000B3-0000-1000-8000-0026BB765291", + "Name": "Current Humidifier Dehumidifier State", + "Constraints": { + "ValidValues": { + "3": "Dehumidifying", + "1": "Idle", + "2": "Humidifying", + "0": "Inactive" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "uint8", + "UUID": "000000E0-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Media State", + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 3, + "MinimumValue": 0, + "ValidValues": { + "0": "Play", + "1": "Pause", + "2": "Stop", + "3": "Unknown" + } + } + }, + { + "Format": "uint8", + "UUID": "00000137-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Media State", + "Constraints": { + "StepValue": 1, + "MaximumValue": 2, + "MinimumValue": 0, + "ValidValues": { + "1": "Pause", + "2": "Stop", + "0": "Play" + } + } + }, + { + "Format": "uint8", + "UUID": "0000006D-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Position", + "Permissions": [ + "securedRead" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "float", + "UUID": "00000010-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Relative Humidity", + "Permissions": [ + "securedRead" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "UUID": "000000AA-0000-1000-8000-0026BB765291", + "Name": "Current Slat State", + "Constraints": { + "ValidValues": { + "0": "Fixed", + "1": "Jammed", + "2": "Swinging" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "float", + "UUID": "00000011-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Temperature", + "Permissions": [ + "securedRead" + ], + "Unit": "celsius", + "Constraints": { + "StepValue": 0.1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "int32", + "UUID": "000000C1-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Tilt Angle", + "Permissions": [ + "securedRead" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 90, + "MinimumValue": -90 + } + }, + { + "Format": "int32", + "UUID": "0000006E-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Current Vertical Tilt Angle", + "Permissions": [ + "securedRead" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 90, + "MinimumValue": -90 + } + }, + { + "Name": "Digital Zoom", + "Format": "float", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "0000011D-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000AC-0000-1000-8000-0026BB765291", + "Name": "Filter Change Indication", + "Constraints": { + "ValidValues": { + "0": "Filter OK", + "1": "Change Filter" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000AB-0000-1000-8000-0026BB765291", + "Name": "Filter Life Level", + "Constraints": { + "stepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Firmware Revision", + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000052-0000-1000-8000-0026BB765291" + }, + { + "Name": "Hardware Revision", + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000053-0000-1000-8000-0026BB765291" + }, + { + "Format": "float", + "UUID": "00000012-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Heating Threshold Temperature", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "celsius", + "Constraints": { + "StepValue": 0.1, + "MaximumValue": 25, + "MinimumValue": 0 + } + }, + { + "Name": "Hold Position", + "Format": "bool", + "Permissions": [ + "securedWrite" + ], + "Properties": [ + "write" + ], + "UUID": "0000006F-0000-1000-8000-0026BB765291" + }, + { + "Format": "float", + "UUID": "00000013-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Hue", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 360, + "MinimumValue": 0 + } + }, + { + "Name": "Identify", + "Format": "bool", + "Permissions": [ + "securedWrite" + ], + "Properties": [ + "write" + ], + "UUID": "00000014-0000-1000-8000-0026BB765291" + }, + { + "Name": "Input Source Type", + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Constraints": { + "StepValue": 1, + "MaximumValue": 10, + "MinimumValue": 0, + "ValidValues": { + "0": "Other", + "1": "HomeScreen", + "2": "Tuner", + "3": "Hdmi", + "4": "CompositeVideo", + "5": "SVideo", + "6": "ComponentVideo", + "7": "Dvi", + "8": "Airplay", + "9": "Usb", + "10": "Application" + } + }, + "UUID": "000000DB-0000-1000-8000-0026BB765291" + }, + { + "Name": "Input Device Type", + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Constraints": { + "StepValue": 1, + "MaximumValue": 5, + "MinimumValue": 0, + "ValidValues": { + "0": "Other", + "1": "Tv", + "2": "Recording", + "3": "Tuner", + "4": "Playback", + "5": "AudioSystem" + } + }, + "UUID": "000000DC-0000-1000-8000-0026BB765291" + }, + { + "Name": "Identifier", + "Format": "uint32", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Constraints": { + "StepValue": 1, + "MinimumValue": 0 + }, + "UUID": "000000E6-0000-1000-8000-0026BB765291" + }, + { + "Name": "Current Visibility State", + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Constraints": { + "StepValue": 1, + "MinimumValue": 0, + "MaximumValue": 3, + "ValidValues": { + "0": "Shown", + "1": "Hidden" + } + }, + "UUID": "00000135-0000-1000-8000-0026BB765291" + }, + { + "Name": "Target Visibility State", + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Constraints": { + "StepValue": 1, + "MinimumValue": 0, + "MaximumValue": 2, + "ValidValues": { + "0": "Shown", + "1": "Hidden" + } + }, + "UUID": "00000134-0000-1000-8000-0026BB765291" + }, + { + "Name": "Image Mirroring", + "Format": "bool", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "0000011F-0000-1000-8000-0026BB765291" + }, + { + "Format": "float", + "UUID": "0000011E-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Image Rotation", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 90, + "MaximumValue": 270, + "MinimumValue": 0 + } + }, + { + "UUID": "000000D2-0000-1000-8000-0026BB765291", + "Name": "In Use", + "Constraints": { + "ValidValues": { + "0": "Not in use", + "1": "In use" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000D6-0000-1000-8000-0026BB765291", + "Name": "Is Configured", + "Constraints": { + "ValidValues": { + "0": "Not Configured", + "1": "Configured" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000070-0000-1000-8000-0026BB765291", + "Name": "Leak Detected", + "Constraints": { + "ValidValues": { + "0": "Leak Not Detected", + "1": "Leak Detected" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Lock Control Point", + "Format": "tlv8", + "Permissions": [ + "securedWrite" + ], + "Properties": [ + "write" + ], + "UUID": "00000019-0000-1000-8000-0026BB765291" + }, + { + "UUID": "0000001D-0000-1000-8000-0026BB765291", + "Name": "Lock Current State", + "Constraints": { + "ValidValues": { + "3": "Unknown", + "1": "Secured", + "2": "Jammed", + "0": "Unsecured" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "0000001C-0000-1000-8000-0026BB765291", + "Name": "Lock Last Known Action", + "Constraints": { + "ValidValues": { + "7": "Unsecured Remotely", + "3": "Unsecured Physically, Exterior", + "8": "Secured by Auto Secure Timeout", + "4": "Secured by Keypad", + "0": "Secured Physically, Interior", + "5": "Unsecured by Keypad", + "1": "Unsecured Physically, Interior", + "6": "Secured Remotely", + "2": "Secured Physically, Exterior" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Unit": "seconds", + "Name": "Lock Management Auto Security Timeout", + "Format": "uint32", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "0000001A-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000A7-0000-1000-8000-0026BB765291", + "Name": "Lock Physical Controls", + "Constraints": { + "ValidValues": { + "0": "Control Lock Disabled", + "1": "Control Lock Enabled" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "0000001E-0000-1000-8000-0026BB765291", + "Name": "Lock Target State", + "Constraints": { + "ValidValues": { + "0": "Unsecured", + "1": "Secured" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Logs", + "Format": "tlv8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "UUID": "0000001F-0000-1000-8000-0026BB765291" + }, + { + "Name": "Manufacturer", + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000020-0000-1000-8000-0026BB765291" + }, + { + "Name": "Model", + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000021-0000-1000-8000-0026BB765291" + }, + { + "Name": "Motion Detected", + "Format": "bool", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "UUID": "00000022-0000-1000-8000-0026BB765291" + }, + { + "Name": "Mute", + "Format": "bool", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "0000011A-0000-1000-8000-0026BB765291" + }, + { + "Name": "Name", + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000023-0000-1000-8000-0026BB765291" + }, + { + "Name": "Night Vision", + "Format": "bool", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "0000011B-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000C4-0000-1000-8000-0026BB765291", + "Name": "Nitrogen Dioxide Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Obstruction Detected", + "Format": "bool", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "UUID": "00000024-0000-1000-8000-0026BB765291" + }, + { + "UUID": "00000071-0000-1000-8000-0026BB765291", + "Name": "Occupancy Detected", + "Constraints": { + "ValidValues": { + "0": "Occupancy Not Detected", + "1": "Occupancy Detected" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "On", + "Format": "bool", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "00000025-0000-1000-8000-0026BB765291" + }, + { + "Name": "Optical Zoom", + "Format": "float", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "UUID": "0000011C-0000-1000-8000-0026BB765291" + }, + { + "Name": "Outlet In Use", + "Format": "bool", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "UUID": "00000026-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000C3-0000-1000-8000-0026BB765291", + "Name": "Ozone Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Pair Setup", + "Format": "tlv8", + "Permissions": [ + "read", + "write" + ], + "Properties": [ + "read", + "write" + ], + "UUID": "0000004C-0000-1000-8000-0026BB765291" + }, + { + "Name": "Pair Verify", + "Format": "tlv8", + "Permissions": [ + "read", + "write" + ], + "Properties": [ + "read", + "write" + ], + "UUID": "0000004E-0000-1000-8000-0026BB765291" + }, + { + "Name": "Pairing Features", + "Format": "uint8", + "Permissions": [ + "read" + ], + "Properties": [ + "read" + ], + "UUID": "0000004F-0000-1000-8000-0026BB765291" + }, + { + "Name": "Pairing Pairings", + "Format": "tlv8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write" + ], + "UUID": "00000050-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000C7-0000-1000-8000-0026BB765291", + "Name": "PM10 Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000C6-0000-1000-8000-0026BB765291", + "Name": "PM2.5 Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000072-0000-1000-8000-0026BB765291", + "Name": "Position State", + "Constraints": { + "ValidValues": { + "0": "Decreasing", + "1": "Increasing", + "2": "Stopped" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000E2-0000-1000-8000-0026BB765291", + "Name": "Picture Mode", + "Constraints": { + "StepValue": 1, + "MaximumValue": 13, + "MinimumValue": 0, + "ValidValues": { + "0": "Other", + "1": "Standard", + "2": "Calibrated", + "3": "CalibratedDark", + "4": "Vivid", + "5": "Game", + "6": "Computer", + "7": "Custom" + } + }, + "Format": "uint16", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000DF-0000-1000-8000-0026BB765291", + "Name": "Power Mode Selection", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1, + "MinimumValue": 0, + "ValidValues": { + "0": "Show", + "1": "Hide" + } + }, + "Format": "float", + "Properties": [ + "write" + ] + }, + { + "UUID": "000000D1-0000-1000-8000-0026BB765291", + "Name": "Program Mode", + "Constraints": { + "ValidValues": { + "0": "No program scheduled", + "1": "Program scheduled", + "2": "Program scheduled (Manual Mode)" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000073-0000-1000-8000-0026BB765291", + "Name": "Programmable Switch Event", + "Constraints": { + "ValidValues": { + "0": "Single Press", + "1": "Double Press", + "2": "Long Press" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "uint8", + "UUID": "000000E1-0000-1000-8000-0026BB765291", + "Properties": [ + "write" + ], + "Name": "Remote Key", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Constraints": { + "StepValue": 1, + "MaximumValue": 16, + "MinimumValue": 0, + "ValidValues": { + "0": "Rewind", + "1": "FastForward", + "2": "NextTrack", + "3": "PrevTrack", + "4": "ArrowUp", + "5": "ArrowDown", + "6": "ArrowLeft", + "7": "ArrowRight", + "8": "Select", + "9": "Back", + "10": "Exit", + "11": "PlayPause", + "15": "Info" + } + } + }, + { + "Format": "float", + "UUID": "000000C9-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Relative Humidity Dehumidifier Threshold", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "float", + "UUID": "000000CA-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Relative Humidity Humidifier Threshold", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "UUID": "000000D4-0000-1000-8000-0026BB765291", + "Name": "Remaining Duration", + "Constraints": { + "StepValue": 1, + "MaximumValue": 3600, + "MinimumValue": 0 + }, + "Format": "uint32", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000AD-0000-1000-8000-0026BB765291", + "Name": "Reset Filter Indication", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1, + "MinimumValue": 1 + }, + "Format": "uint8", + "Permissions": [ + "securedWrite" + ], + "Properties": [ + "write" + ] + }, + { + "UUID": "00000028-0000-1000-8000-0026BB765291", + "Name": "Rotation Direction", + "Constraints": { + "ValidValues": { + "0": "Clockwise", + "1": "Counter-clockwise" + } + }, + "Format": "int32", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "float", + "UUID": "00000029-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Rotation Speed", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "float", + "UUID": "0000002F-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Saturation", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "UUID": "0000008E-0000-1000-8000-0026BB765291", + "Name": "Security System Alarm Type", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1, + "MinimumValue": 0 + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000066-0000-1000-8000-0026BB765291", + "Name": "Security System Current State", + "Constraints": { + "ValidValues": { + "3": "Disarmed", + "1": "Away Arm", + "4": "Alarm Triggered", + "2": "Night Arm", + "0": "Stay Arm" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000067-0000-1000-8000-0026BB765291", + "Name": "Security System Target State", + "Constraints": { + "ValidValues": { + "3": "Disarm", + "1": "Away Arm", + "2": "Night Arm", + "0": "Stay Arm" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Selected RTP Stream Configuration", + "Format": "tlv8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write" + ], + "UUID": "00000117-0000-1000-8000-0026BB765291" + }, + { + "UUID": "00000030-0000-1000-8000-0026BB765291", + "Name": "Serial Number", + "Constraints": { + "MaximumLength": 64 + }, + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ] + }, + { + "UUID": "000000CB-0000-1000-8000-0026BB765291", + "Name": "Service Label Index", + "Constraints": { + "StepValue": 1, + "MaximumValue": 255, + "MinimumValue": 1 + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ] + }, + { + "UUID": "000000CD-0000-1000-8000-0026BB765291", + "Name": "Service Label Namespace", + "Constraints": { + "ValidValues": { + "0": "Dots", + "1": "Arabic Numerals" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ] + }, + { + "UUID": "000000D3-0000-1000-8000-0026BB765291", + "Name": "Set Duration", + "Constraints": { + "StepValue": 1, + "MaximumValue": 3600, + "MinimumValue": 0 + }, + "Format": "uint32", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Setup Endpoints", + "Format": "tlv8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write" + ], + "UUID": "00000118-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000C0-0000-1000-8000-0026BB765291", + "Name": "Slat Type", + "Constraints": { + "ValidValues": { + "0": "Horizontal", + "1": "Vertical" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ] + }, + { + "UUID": "000000E8-0000-1000-8000-0026BB765291", + "Name": "Sleep Discovery Mode", + "Constraints": { + "MinimumValue": 0, + "MaximumValue": 1, + "ValidValues": { + "0": "NotDiscoverable", + "1": "AlwaysDiscoverable" + } + }, + "Format": "uint8", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000076-0000-1000-8000-0026BB765291", + "Name": "Smoke Detected", + "Constraints": { + "ValidValues": { + "0": "Smoke Not Detected", + "1": "Smoke Detected" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Status Active", + "Format": "bool", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "UUID": "00000075-0000-1000-8000-0026BB765291" + }, + { + "UUID": "00000077-0000-1000-8000-0026BB765291", + "Name": "Status Fault", + "Constraints": { + "ValidValues": { + "0": "No Fault", + "1": "General Fault" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000078-0000-1000-8000-0026BB765291", + "Name": "Status Jammed", + "Constraints": { + "ValidValues": { + "0": "Not Jammed", + "1": "Jammed" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000079-0000-1000-8000-0026BB765291", + "Name": "Status Low Battery", + "Constraints": { + "ValidValues": { + "0": "Battery Level Normal", + "1": "Battery Level Low" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "0000007A-0000-1000-8000-0026BB765291", + "Name": "Status Tampered", + "Constraints": { + "ValidValues": { + "0": "Not Tampered", + "1": "Tampered" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Streaming Status", + "Format": "tlv8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "UUID": "00000120-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000C5-0000-1000-8000-0026BB765291", + "Name": "Sulphur Dioxide Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Name": "Supported Audio Stream Configuration", + "Format": "tlv8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000115-0000-1000-8000-0026BB765291" + }, + { + "Name": "Supported RTP Configuration", + "Format": "tlv8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000116-0000-1000-8000-0026BB765291" + }, + { + "Name": "Supported Video Stream Configuration", + "Format": "tlv8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read" + ], + "UUID": "00000114-0000-1000-8000-0026BB765291" + }, + { + "UUID": "000000B6-0000-1000-8000-0026BB765291", + "Name": "Swing Mode", + "Constraints": { + "ValidValues": { + "0": "Swing Disabled", + "1": "Swing Enabled" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000A8-0000-1000-8000-0026BB765291", + "Name": "Target Air Purifier State", + "Constraints": { + "ValidValues": { + "0": "Manual", + "1": "Auto" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000AE-0000-1000-8000-0026BB765291", + "Name": "Target Air Quality", + "Constraints": { + "ValidValues": { + "0": "Excellent", + "1": "Good", + "2": "Fair" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000032-0000-1000-8000-0026BB765291", + "Name": "Target Door State", + "Constraints": { + "ValidValues": { + "0": "Open", + "1": "Closed" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000BF-0000-1000-8000-0026BB765291", + "Name": "Target Fan State", + "Constraints": { + "ValidValues": { + "0": "Manual", + "1": "Auto" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000B2-0000-1000-8000-0026BB765291", + "Name": "Target Heater Cooler State", + "Constraints": { + "ValidValues": { + "0": "Auto", + "1": "Heat", + "2": "Cool" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000033-0000-1000-8000-0026BB765291", + "Name": "Target Heating Cooling State", + "Constraints": { + "ValidValues": { + "3": "Auto", + "1": "Heat", + "2": "Cool", + "0": "Off" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "int32", + "UUID": "0000007B-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Horizontal Tilt Angle", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 90, + "MinimumValue": -90 + } + }, + { + "UUID": "000000B4-0000-1000-8000-0026BB765291", + "Name": "Target Humidifier Dehumidifier State", + "Constraints": { + "ValidValues": { + "0": "Humidifier or Dehumidifier", + "1": "Humidifier", + "2": "Dehumidifier" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "uint8", + "UUID": "0000007C-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Position", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "float", + "UUID": "00000034-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Relative Humidity", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "UUID": "000000BE-0000-1000-8000-0026BB765291", + "Name": "Target Slat State", + "Constraints": { + "ValidValues": { + "0": "Manual", + "1": "Auto" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "float", + "UUID": "00000035-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Temperature", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "celsius", + "Constraints": { + "StepValue": 0.1, + "MaximumValue": 38, + "MinimumValue": 10 + } + }, + { + "Format": "int32", + "UUID": "000000C2-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Tilt Angle", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 90, + "MinimumValue": -90 + } + }, + { + "Format": "int32", + "UUID": "0000007D-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Target Vertical Tilt Angle", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "arcdegrees", + "Constraints": { + "StepValue": 1, + "MaximumValue": 90, + "MinimumValue": -90 + } + }, + { + "UUID": "00000036-0000-1000-8000-0026BB765291", + "Name": "Temperature Display Units", + "Constraints": { + "ValidValues": { + "0": "Celsius", + "1": "Fahrenheit" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000D5-0000-1000-8000-0026BB765291", + "Name": "Valve Type", + "Constraints": { + "ValidValues": { + "3": "Water faucet", + "1": "Irrigation", + "2": "Shower head", + "0": "Generic valve" + } + }, + "Format": "uint8", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "00000037-0000-1000-8000-0026BB765291", + "Name": "Version", + "Constraints": { + "MaximumLength": 64 + }, + "Format": "string", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "UUID": "000000C8-0000-1000-8000-0026BB765291", + "Name": "VOC Density", + "Constraints": { + "StepValue": 1, + "MaximumValue": 1000, + "MinimumValue": 0 + }, + "Format": "float", + "Permissions": [ + "securedRead" + ], + "Properties": [ + "read", + "cnotify", + "uncnotify" + ] + }, + { + "Format": "uint8", + "UUID": "00000119-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "write", + "cnotify", + "uncnotify" + ], + "Name": "Volume", + "Permissions": [ + "securedRead", + "securedWrite" + ], + "Unit": "percentage", + "Constraints": { + "StepValue": 1, + "MaximumValue": 100, + "MinimumValue": 0 + } + }, + { + "Format": "uint8", + "UUID": "000000E9-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Volume Control Type", + "Permissions": [ + "securedRead" + ], + "Constraints": { + "StepValue": 1, + "MaximumValue": 3, + "MinimumValue": 0, + "ValidValues": { + "0": "None", + "1": "Relative", + "2": "RelativeWithCurrent", + "3": "Absolute" + } + } + }, + { + "Format": "uint8", + "UUID": "000000EA-0000-1000-8000-0026BB765291", + "Properties": [ + "write" + ], + "Name": "Volume Selector", + "Permissions": [ + "securedRead" + ], + "Constraints": { + "StepValue": 1, + "MaximumValue": 1, + "MinimumValue": 0, + "ValidValues": { + "0": "Increment", + "1": "Decrement" + } + } + }, + { + "Format": "float", + "UUID": "000000B5-0000-1000-8000-0026BB765291", + "Properties": [ + "read", + "cnotify", + "uncnotify" + ], + "Name": "Water Level", + "Permissions": [ + "securedRead" + ], + "Unit": "percentage", + "Constraints": { + "MaximumValue": 100, + "MinimumValue": 0 + } } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Administrator Only Access", - "Format" : "bool", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "00000001-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "00000064-0000-1000-8000-0026BB765291", - "Name" : "Air Particulate Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000065-0000-1000-8000-0026BB765291", - "Name" : "Air Particulate Size", - "Constraints" : { - "ValidValues" : { - "0" : "2.5 μm", - "1" : "10 μm" + ], + "Version": "1.0", + "Services": [ + { + "OptionalCharacteristics": [ + "00000053-0000-1000-8000-0026BB765291", + "000000A6-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000014-0000-1000-8000-0026BB765291", + "00000020-0000-1000-8000-0026BB765291", + "00000021-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291", + "00000030-0000-1000-8000-0026BB765291", + "00000052-0000-1000-8000-0026BB765291" + ], + "Name": "Accessory Information", + "UUID": "0000003E-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "000000A7-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291", + "000000B6-0000-1000-8000-0026BB765291", + "00000029-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291", + "000000A9-0000-1000-8000-0026BB765291", + "000000A8-0000-1000-8000-0026BB765291" + ], + "Name": "Air Purifier", + "UUID": "000000BB-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291", + "000000C3-0000-1000-8000-0026BB765291", + "000000C4-0000-1000-8000-0026BB765291", + "000000C5-0000-1000-8000-0026BB765291", + "000000C6-0000-1000-8000-0026BB765291", + "000000C7-0000-1000-8000-0026BB765291", + "000000C8-0000-1000-8000-0026BB765291", + "00000090-0000-1000-8000-0026BB765291", + "00000093-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000095-0000-1000-8000-0026BB765291" + ], + "Name": "Air Quality Sensor", + "UUID": "0000008D-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000068-0000-1000-8000-0026BB765291", + "0000008F-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291" + ], + "Name": "Battery Service", + "UUID": "00000096-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000114-0000-1000-8000-0026BB765291", + "00000115-0000-1000-8000-0026BB765291", + "00000116-0000-1000-8000-0026BB765291", + "00000117-0000-1000-8000-0026BB765291", + "00000120-0000-1000-8000-0026BB765291", + "00000118-0000-1000-8000-0026BB765291" + ], + "Name": "Camera RTP Stream Management", + "UUID": "00000110-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000093-0000-1000-8000-0026BB765291", + "00000094-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000092-0000-1000-8000-0026BB765291" + ], + "Name": "Carbon Dioxide Sensor", + "UUID": "00000097-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000090-0000-1000-8000-0026BB765291", + "00000091-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000069-0000-1000-8000-0026BB765291" + ], + "Name": "Carbon Monoxide Sensor", + "UUID": "0000007F-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000006A-0000-1000-8000-0026BB765291" + ], + "Name": "Contact Sensor", + "UUID": "00000080-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "0000006F-0000-1000-8000-0026BB765291", + "00000024-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000006D-0000-1000-8000-0026BB765291", + "00000072-0000-1000-8000-0026BB765291", + "0000007C-0000-1000-8000-0026BB765291" + ], + "Name": "Door", + "UUID": "00000081-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000008-0000-1000-8000-0026BB765291", + "00000119-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000073-0000-1000-8000-0026BB765291" + ], + "Name": "Doorbell", + "UUID": "00000121-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000028-0000-1000-8000-0026BB765291", + "00000029-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000025-0000-1000-8000-0026BB765291" + ], + "Name": "Fan", + "UUID": "00000040-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "000000AF-0000-1000-8000-0026BB765291", + "000000BF-0000-1000-8000-0026BB765291", + "000000A7-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291", + "00000028-0000-1000-8000-0026BB765291", + "00000029-0000-1000-8000-0026BB765291", + "000000B6-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291" + ], + "Name": "Fan v2", + "UUID": "000000B7-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "000000AB-0000-1000-8000-0026BB765291", + "000000AD-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000AC-0000-1000-8000-0026BB765291" + ], + "Name": "Filter Maintenance", + "UUID": "000000BA-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291" + ], + "Name": "Faucet", + "UUID": "000000D7-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "0000001D-0000-1000-8000-0026BB765291", + "0000001E-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000000E-0000-1000-8000-0026BB765291", + "00000032-0000-1000-8000-0026BB765291", + "00000024-0000-1000-8000-0026BB765291" + ], + "Name": "Garage Door Opener", + "UUID": "00000041-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "000000A7-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291", + "000000B6-0000-1000-8000-0026BB765291", + "0000000D-0000-1000-8000-0026BB765291", + "00000012-0000-1000-8000-0026BB765291", + "00000036-0000-1000-8000-0026BB765291", + "00000029-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291", + "000000B1-0000-1000-8000-0026BB765291", + "000000B2-0000-1000-8000-0026BB765291", + "00000011-0000-1000-8000-0026BB765291" + ], + "Name": "Heater Cooler", + "UUID": "000000BC-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "000000A7-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291", + "000000B6-0000-1000-8000-0026BB765291", + "000000B5-0000-1000-8000-0026BB765291", + "000000C9-0000-1000-8000-0026BB765291", + "000000CA-0000-1000-8000-0026BB765291", + "00000029-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000010-0000-1000-8000-0026BB765291", + "000000B3-0000-1000-8000-0026BB765291", + "000000B4-0000-1000-8000-0026BB765291", + "000000B0-0000-1000-8000-0026BB765291" + ], + "Name": "Humidifier Dehumidifier", + "UUID": "000000BD-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000010-0000-1000-8000-0026BB765291" + ], + "Name": "Humidity Sensor", + "UUID": "00000082-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "000000D4-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291", + "000000D1-0000-1000-8000-0026BB765291", + "000000D2-0000-1000-8000-0026BB765291" + ], + "Name": "Irrigation System", + "UUID": "000000CF-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000070-0000-1000-8000-0026BB765291" + ], + "Name": "Leak Sensor", + "UUID": "00000083-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000006B-0000-1000-8000-0026BB765291" + ], + "Name": "Light Sensor", + "UUID": "00000084-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000008-0000-1000-8000-0026BB765291", + "00000013-0000-1000-8000-0026BB765291", + "0000002F-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000025-0000-1000-8000-0026BB765291" + ], + "Name": "Lightbulb", + "UUID": "00000043-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "0000001F-0000-1000-8000-0026BB765291", + "00000005-0000-1000-8000-0026BB765291", + "0000001A-0000-1000-8000-0026BB765291", + "00000001-0000-1000-8000-0026BB765291", + "0000001C-0000-1000-8000-0026BB765291", + "0000000E-0000-1000-8000-0026BB765291", + "00000022-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000019-0000-1000-8000-0026BB765291", + "00000037-0000-1000-8000-0026BB765291" + ], + "Name": "Lock Management", + "UUID": "00000044-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000001D-0000-1000-8000-0026BB765291", + "0000001E-0000-1000-8000-0026BB765291" + ], + "Name": "Lock Mechanism", + "UUID": "00000045-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000119-0000-1000-8000-0026BB765291", + "0000011A-0000-1000-8000-0026BB765291" + ], + "Name": "Microphone", + "UUID": "00000112-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000022-0000-1000-8000-0026BB765291" + ], + "Name": "Motion Sensor", + "UUID": "00000085-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000071-0000-1000-8000-0026BB765291" + ], + "Name": "Occupancy Sensor", + "UUID": "00000086-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000025-0000-1000-8000-0026BB765291", + "00000026-0000-1000-8000-0026BB765291" + ], + "Name": "Outlet", + "UUID": "00000047-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "0000008E-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000066-0000-1000-8000-0026BB765291", + "00000067-0000-1000-8000-0026BB765291" + ], + "Name": "Security System", + "UUID": "0000007E-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000CD-0000-1000-8000-0026BB765291" + ], + "Name": "Service Label", + "UUID": "000000CC-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "000000C1-0000-1000-8000-0026BB765291", + "000000C2-0000-1000-8000-0026BB765291", + "000000B6-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000C0-0000-1000-8000-0026BB765291", + "000000AA-0000-1000-8000-0026BB765291" + ], + "Name": "Slat", + "UUID": "000000B9-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000076-0000-1000-8000-0026BB765291" + ], + "Name": "Smoke Sensor", + "UUID": "00000087-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "00000119-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000011A-0000-1000-8000-0026BB765291" + ], + "Name": "Speaker", + "UUID": "00000113-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291", + "000000CB-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000073-0000-1000-8000-0026BB765291" + ], + "Name": "Stateless Programmable Switch", + "UUID": "00000089-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000025-0000-1000-8000-0026BB765291" + ], + "Name": "Switch", + "UUID": "00000049-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000075-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "00000079-0000-1000-8000-0026BB765291", + "0000007A-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "00000011-0000-1000-8000-0026BB765291" + ], + "Name": "Temperature Sensor", + "UUID": "0000008A-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "00000010-0000-1000-8000-0026BB765291", + "00000034-0000-1000-8000-0026BB765291", + "0000000D-0000-1000-8000-0026BB765291", + "00000012-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000000F-0000-1000-8000-0026BB765291", + "00000033-0000-1000-8000-0026BB765291", + "00000011-0000-1000-8000-0026BB765291", + "00000035-0000-1000-8000-0026BB765291", + "00000036-0000-1000-8000-0026BB765291" + ], + "Name": "Thermostat", + "UUID": "0000004A-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "000000D3-0000-1000-8000-0026BB765291", + "000000D4-0000-1000-8000-0026BB765291", + "000000D6-0000-1000-8000-0026BB765291", + "000000CB-0000-1000-8000-0026BB765291", + "00000077-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291", + "000000D2-0000-1000-8000-0026BB765291", + "000000D5-0000-1000-8000-0026BB765291" + ], + "Name": "Valve", + "UUID": "000000D0-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "0000006F-0000-1000-8000-0026BB765291", + "00000024-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000006D-0000-1000-8000-0026BB765291", + "0000007C-0000-1000-8000-0026BB765291", + "00000072-0000-1000-8000-0026BB765291" + ], + "Name": "Window", + "UUID": "0000008B-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + "0000006F-0000-1000-8000-0026BB765291", + "0000007B-0000-1000-8000-0026BB765291", + "0000007D-0000-1000-8000-0026BB765291", + "0000006C-0000-1000-8000-0026BB765291", + "0000006E-0000-1000-8000-0026BB765291", + "00000024-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "RequiredCharacteristics": [ + "0000006D-0000-1000-8000-0026BB765291", + "0000007C-0000-1000-8000-0026BB765291", + "00000072-0000-1000-8000-0026BB765291" + ], + "Name": "Window Covering", + "UUID": "0000008C-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [ + ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291", + "000000E7-0000-1000-8000-0026BB765291", + "000000E3-0000-1000-8000-0026BB765291", + "000000E8-0000-1000-8000-0026BB765291", + "00000008-0000-1000-8000-0026BB765291", + "000000DD-0000-1000-8000-0026BB765291", + "00000136-0000-1000-8000-0026BB765291", + "000000E0-0000-1000-8000-0026BB765291", + "00000137-0000-1000-8000-0026BB765291", + "000000E2-0000-1000-8000-0026BB765291", + "000000DF-0000-1000-8000-0026BB765291", + "000000E1-0000-1000-8000-0026BB765291" + ], + "Name": "Television", + "UUID": "000000D8-0000-1000-8000-0026BB765291" + }, + { + "OptionalCharacteristics": [], + "RequiredCharacteristics": [ + "000000E3-0000-1000-8000-0026BB765291", + "000000DB-0000-1000-8000-0026BB765291", + "000000D6-0000-1000-8000-0026BB765291", + "00000135-0000-1000-8000-0026BB765291", + "000000E6-0000-1000-8000-0026BB765291", + "000000DC-0000-1000-8000-0026BB765291", + "00000134-0000-1000-8000-0026BB765291", + "00000023-0000-1000-8000-0026BB765291" + ], + "Name": "Input Source", + "UUID": "000000D9-0000-1000-8000-0026BB765291" } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000095-0000-1000-8000-0026BB765291", - "Name" : "Air Quality", - "Constraints" : { - "ValidValues" : { - "3" : "Fair", - "1" : "Excellent", - "4" : "Inferior", - "2" : "Good", - "0" : "Unknown", - "5" : "Poor" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Audio Feedback", - "Format" : "bool", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "00000005-0000-1000-8000-0026BB765291" - }, - { - "Format" : "uint8", - "UUID" : "00000068-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Battery Level", - "Permissions" : [ - "securedRead" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "int32", - "UUID" : "00000008-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Brightness", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "UUID" : "00000092-0000-1000-8000-0026BB765291", - "Name" : "Carbon Dioxide Detected", - "Constraints" : { - "ValidValues" : { - "0" : "CO2 Levels Normal", - "1" : "CO2 Levels Abnormal" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000093-0000-1000-8000-0026BB765291", - "Name" : "Carbon Dioxide Level", - "Constraints" : { - "MaximumValue" : 100000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000094-0000-1000-8000-0026BB765291", - "Name" : "Carbon Dioxide Peak Level", - "Constraints" : { - "MaximumValue" : 100000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000069-0000-1000-8000-0026BB765291", - "Name" : "Carbon Monoxide Detected", - "Constraints" : { - "ValidValues" : { - "0" : "CO Levels Normal", - "1" : "CO Levels Abnormal" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000090-0000-1000-8000-0026BB765291", - "Name" : "Carbon Monoxide Level", - "Constraints" : { - "MaximumValue" : 100, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000091-0000-1000-8000-0026BB765291", - "Name" : "Carbon Monoxide Peak Level", - "Constraints" : { - "MaximumValue" : 100, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "0000008F-0000-1000-8000-0026BB765291", - "Name" : "Charging State", - "Constraints" : { - "ValidValues" : { - "0" : "Not Charging", - "1" : "Charging", - "2" : "Not Chargeable" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000CE-0000-1000-8000-0026BB765291", - "Name" : "Color Temperature", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 500, - "MinimumValue" : 140 - }, - "Format" : "uint32", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "0000006A-0000-1000-8000-0026BB765291", - "Name" : "Contact Sensor State", - "Constraints" : { - "ValidValues" : { - "0" : "Contact Detected", - "1" : "Contact Not Detected" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "float", - "UUID" : "0000000D-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Cooling Threshold Temperature", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "celsius", - "Constraints" : { - "StepValue" : 0.10000000000000001, - "MaximumValue" : 35, - "MinimumValue" : 10 - } - }, - { - "UUID" : "000000A9-0000-1000-8000-0026BB765291", - "Name" : "Current Air Purifier State", - "Constraints" : { - "ValidValues" : { - "0" : "Inactive", - "1" : "Idle", - "2" : "Purifying Air" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "float", - "UUID" : "0000006B-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Ambient Light Level", - "Permissions" : [ - "securedRead" - ], - "Unit" : "lux", - "Constraints" : { - "MaximumValue" : 100000, - "MinimumValue" : 0.0001 - } - }, - { - "UUID" : "0000000E-0000-1000-8000-0026BB765291", - "Name" : "Current Door State", - "Constraints" : { - "ValidValues" : { - "3" : "Closing", - "1" : "Closed", - "4" : "Stopped", - "2" : "Opening", - "0" : "Open" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000AF-0000-1000-8000-0026BB765291", - "Name" : "Current Fan State", - "Constraints" : { - "ValidValues" : { - "0" : "Inactive", - "1" : "Idle", - "2" : "Blowing Air" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000B1-0000-1000-8000-0026BB765291", - "Name" : "Current Heater Cooler State", - "Constraints" : { - "ValidValues" : { - "3" : "Cooling", - "1" : "Idle", - "2" : "Heating", - "0" : "Inactive" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "0000000F-0000-1000-8000-0026BB765291", - "Name" : "Current Heating Cooling State", - "Constraints" : { - "ValidValues" : { - "0" : "Off", - "1" : "Heat", - "2" : "Cool" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "int32", - "UUID" : "0000006C-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Horizontal Tilt Angle", - "Permissions" : [ - "securedRead" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 90, - "MinimumValue" : -90 - } - }, - { - "UUID" : "000000B3-0000-1000-8000-0026BB765291", - "Name" : "Current Humidifier Dehumidifier State", - "Constraints" : { - "ValidValues" : { - "3" : "Dehumidifying", - "1" : "Idle", - "2" : "Humidifying", - "0" : "Inactive" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "uint8", - "UUID" : "0000006D-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Position", - "Permissions" : [ - "securedRead" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "float", - "UUID" : "00000010-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Relative Humidity", - "Permissions" : [ - "securedRead" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "UUID" : "000000AA-0000-1000-8000-0026BB765291", - "Name" : "Current Slat State", - "Constraints" : { - "ValidValues" : { - "0" : "Fixed", - "1" : "Jammed", - "2" : "Swinging" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "float", - "UUID" : "00000011-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Temperature", - "Permissions" : [ - "securedRead" - ], - "Unit" : "celsius", - "Constraints" : { - "StepValue" : 0.10000000000000001, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "int32", - "UUID" : "000000C1-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Tilt Angle", - "Permissions" : [ - "securedRead" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 90, - "MinimumValue" : -90 - } - }, - { - "Format" : "int32", - "UUID" : "0000006E-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Current Vertical Tilt Angle", - "Permissions" : [ - "securedRead" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 90, - "MinimumValue" : -90 - } - }, - { - "Name" : "Digital Zoom", - "Format" : "float", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "0000011D-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000AC-0000-1000-8000-0026BB765291", - "Name" : "Filter Change Indication", - "Constraints" : { - "ValidValues" : { - "0" : "Filter OK", - "1" : "Change Filter" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000AB-0000-1000-8000-0026BB765291", - "Name" : "Filter Life Level", - "Constraints" : { - "stepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Firmware Revision", - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000052-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Hardware Revision", - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000053-0000-1000-8000-0026BB765291" - }, - { - "Format" : "float", - "UUID" : "00000012-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Heating Threshold Temperature", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "celsius", - "Constraints" : { - "StepValue" : 0.10000000000000001, - "MaximumValue" : 25, - "MinimumValue" : 0 - } - }, - { - "Name" : "Hold Position", - "Format" : "bool", - "Permissions" : [ - "securedWrite" - ], - "Properties" : [ - "write" - ], - "UUID" : "0000006F-0000-1000-8000-0026BB765291" - }, - { - "Format" : "float", - "UUID" : "00000013-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Hue", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 360, - "MinimumValue" : 0 - } - }, - { - "Name" : "Identify", - "Format" : "bool", - "Permissions" : [ - "securedWrite" - ], - "Properties" : [ - "write" - ], - "UUID" : "00000014-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Image Mirroring", - "Format" : "bool", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "0000011F-0000-1000-8000-0026BB765291" - }, - { - "Format" : "float", - "UUID" : "0000011E-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Image Rotation", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 90, - "MaximumValue" : 270, - "MinimumValue" : 0 - } - }, - { - "UUID" : "000000D2-0000-1000-8000-0026BB765291", - "Name" : "In Use", - "Constraints" : { - "ValidValues" : { - "0" : "Not in use", - "1" : "In use" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000D6-0000-1000-8000-0026BB765291", - "Name" : "Is Configured", - "Constraints" : { - "ValidValues" : { - "0" : "Not Configured", - "1" : "Configured" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000070-0000-1000-8000-0026BB765291", - "Name" : "Leak Detected", - "Constraints" : { - "ValidValues" : { - "0" : "Leak Not Detected", - "1" : "Leak Detected" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Lock Control Point", - "Format" : "tlv8", - "Permissions" : [ - "securedWrite" - ], - "Properties" : [ - "write" - ], - "UUID" : "00000019-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "0000001D-0000-1000-8000-0026BB765291", - "Name" : "Lock Current State", - "Constraints" : { - "ValidValues" : { - "3" : "Unknown", - "1" : "Secured", - "2" : "Jammed", - "0" : "Unsecured" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "0000001C-0000-1000-8000-0026BB765291", - "Name" : "Lock Last Known Action", - "Constraints" : { - "ValidValues" : { - "7" : "Unsecured Remotely", - "3" : "Unsecured Physically, Exterior", - "8" : "Secured by Auto Secure Timeout", - "4" : "Secured by Keypad", - "0" : "Secured Physically, Interior", - "5" : "Unsecured by Keypad", - "1" : "Unsecured Physically, Interior", - "6" : "Secured Remotely", - "2" : "Secured Physically, Exterior" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Unit" : "seconds", - "Name" : "Lock Management Auto Security Timeout", - "Format" : "uint32", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "0000001A-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000A7-0000-1000-8000-0026BB765291", - "Name" : "Lock Physical Controls", - "Constraints" : { - "ValidValues" : { - "0" : "Control Lock Disabled", - "1" : "Control Lock Enabled" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "0000001E-0000-1000-8000-0026BB765291", - "Name" : "Lock Target State", - "Constraints" : { - "ValidValues" : { - "0" : "Unsecured", - "1" : "Secured" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Logs", - "Format" : "tlv8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "UUID" : "0000001F-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Manufacturer", - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000020-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Model", - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000021-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Motion Detected", - "Format" : "bool", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "UUID" : "00000022-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Mute", - "Format" : "bool", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "0000011A-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Name", - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000023-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Night Vision", - "Format" : "bool", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "0000011B-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000C4-0000-1000-8000-0026BB765291", - "Name" : "Nitrogen Dioxide Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Obstruction Detected", - "Format" : "bool", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "UUID" : "00000024-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "00000071-0000-1000-8000-0026BB765291", - "Name" : "Occupancy Detected", - "Constraints" : { - "ValidValues" : { - "0" : "Occupancy Not Detected", - "1" : "Occupancy Detected" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "On", - "Format" : "bool", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "00000025-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Optical Zoom", - "Format" : "float", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "UUID" : "0000011C-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Outlet In Use", - "Format" : "bool", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "UUID" : "00000026-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000C3-0000-1000-8000-0026BB765291", - "Name" : "Ozone Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Pair Setup", - "Format" : "tlv8", - "Permissions" : [ - "read", - "write" - ], - "Properties" : [ - "read", - "write" - ], - "UUID" : "0000004C-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Pair Verify", - "Format" : "tlv8", - "Permissions" : [ - "read", - "write" - ], - "Properties" : [ - "read", - "write" - ], - "UUID" : "0000004E-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Pairing Features", - "Format" : "uint8", - "Permissions" : [ - "read" - ], - "Properties" : [ - "read" - ], - "UUID" : "0000004F-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Pairing Pairings", - "Format" : "tlv8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write" - ], - "UUID" : "00000050-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000C7-0000-1000-8000-0026BB765291", - "Name" : "PM10 Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000C6-0000-1000-8000-0026BB765291", - "Name" : "PM2.5 Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000072-0000-1000-8000-0026BB765291", - "Name" : "Position State", - "Constraints" : { - "ValidValues" : { - "0" : "Decreasing", - "1" : "Increasing", - "2" : "Stopped" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000D1-0000-1000-8000-0026BB765291", - "Name" : "Program Mode", - "Constraints" : { - "ValidValues" : { - "0" : "No program scheduled", - "1" : "Program scheduled", - "2" : "Program scheduled (Manual Mode)" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000073-0000-1000-8000-0026BB765291", - "Name" : "Programmable Switch Event", - "Constraints" : { - "ValidValues" : { - "0" : "Single Press", - "1" : "Double Press", - "2" : "Long Press" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "float", - "UUID" : "000000C9-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Relative Humidity Dehumidifier Threshold", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "float", - "UUID" : "000000CA-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Relative Humidity Humidifier Threshold", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "UUID" : "000000D4-0000-1000-8000-0026BB765291", - "Name" : "Remaining Duration", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 3600, - "MinimumValue" : 0 - }, - "Format" : "uint32", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000AD-0000-1000-8000-0026BB765291", - "Name" : "Reset Filter Indication", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1, - "MinimumValue" : 1 - }, - "Format" : "uint8", - "Permissions" : [ - "securedWrite" - ], - "Properties" : [ - "write" - ] - }, - { - "UUID" : "00000028-0000-1000-8000-0026BB765291", - "Name" : "Rotation Direction", - "Constraints" : { - "ValidValues" : { - "0" : "Clockwise", - "1" : "Counter-clockwise" - } - }, - "Format" : "int32", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "float", - "UUID" : "00000029-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Rotation Speed", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "float", - "UUID" : "0000002F-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Saturation", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "UUID" : "0000008E-0000-1000-8000-0026BB765291", - "Name" : "Security System Alarm Type", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1, - "MinimumValue" : 0 - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000066-0000-1000-8000-0026BB765291", - "Name" : "Security System Current State", - "Constraints" : { - "ValidValues" : { - "3" : "Disarmed", - "1" : "Away Arm", - "4" : "Alarm Triggered", - "2" : "Night Arm", - "0" : "Stay Arm" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000067-0000-1000-8000-0026BB765291", - "Name" : "Security System Target State", - "Constraints" : { - "ValidValues" : { - "3" : "Disarm", - "1" : "Away Arm", - "2" : "Night Arm", - "0" : "Stay Arm" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Selected RTP Stream Configuration", - "Format" : "tlv8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write" - ], - "UUID" : "00000117-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "00000030-0000-1000-8000-0026BB765291", - "Name" : "Serial Number", - "Constraints" : { - "MaximumLength" : 64 - }, - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ] - }, - { - "UUID" : "000000CB-0000-1000-8000-0026BB765291", - "Name" : "Service Label Index", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 255, - "MinimumValue" : 1 - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ] - }, - { - "UUID" : "000000CD-0000-1000-8000-0026BB765291", - "Name" : "Service Label Namespace", - "Constraints" : { - "ValidValues" : { - "0" : "Dots", - "1" : "Arabic Numerals" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ] - }, - { - "UUID" : "000000D3-0000-1000-8000-0026BB765291", - "Name" : "Set Duration", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 3600, - "MinimumValue" : 0 - }, - "Format" : "uint32", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Setup Endpoints", - "Format" : "tlv8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write" - ], - "UUID" : "00000118-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000C0-0000-1000-8000-0026BB765291", - "Name" : "Slat Type", - "Constraints" : { - "ValidValues" : { - "0" : "Horizontal", - "1" : "Vertical" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ] - }, - { - "UUID" : "00000076-0000-1000-8000-0026BB765291", - "Name" : "Smoke Detected", - "Constraints" : { - "ValidValues" : { - "0" : "Smoke Not Detected", - "1" : "Smoke Detected" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Status Active", - "Format" : "bool", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "UUID" : "00000075-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "00000077-0000-1000-8000-0026BB765291", - "Name" : "Status Fault", - "Constraints" : { - "ValidValues" : { - "0" : "No Fault", - "1" : "General Fault" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000078-0000-1000-8000-0026BB765291", - "Name" : "Status Jammed", - "Constraints" : { - "ValidValues" : { - "0" : "Not Jammed", - "1" : "Jammed" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000079-0000-1000-8000-0026BB765291", - "Name" : "Status Low Battery", - "Constraints" : { - "ValidValues" : { - "0" : "Battery Level Normal", - "1" : "Battery Level Low" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "0000007A-0000-1000-8000-0026BB765291", - "Name" : "Status Tampered", - "Constraints" : { - "ValidValues" : { - "0" : "Not Tampered", - "1" : "Tampered" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Streaming Status", - "Format" : "tlv8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "UUID" : "00000120-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000C5-0000-1000-8000-0026BB765291", - "Name" : "Sulphur Dioxide Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Name" : "Supported Audio Stream Configuration", - "Format" : "tlv8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000115-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Supported RTP Configuration", - "Format" : "tlv8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000116-0000-1000-8000-0026BB765291" - }, - { - "Name" : "Supported Video Stream Configuration", - "Format" : "tlv8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read" - ], - "UUID" : "00000114-0000-1000-8000-0026BB765291" - }, - { - "UUID" : "000000B6-0000-1000-8000-0026BB765291", - "Name" : "Swing Mode", - "Constraints" : { - "ValidValues" : { - "0" : "Swing Disabled", - "1" : "Swing Enabled" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000A8-0000-1000-8000-0026BB765291", - "Name" : "Target Air Purifier State", - "Constraints" : { - "ValidValues" : { - "0" : "Manual", - "1" : "Auto" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000AE-0000-1000-8000-0026BB765291", - "Name" : "Target Air Quality", - "Constraints" : { - "ValidValues" : { - "0" : "Excellent", - "1" : "Good", - "2" : "Fair" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000032-0000-1000-8000-0026BB765291", - "Name" : "Target Door State", - "Constraints" : { - "ValidValues" : { - "0" : "Open", - "1" : "Closed" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000BF-0000-1000-8000-0026BB765291", - "Name" : "Target Fan State", - "Constraints" : { - "ValidValues" : { - "0" : "Manual", - "1" : "Auto" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000B2-0000-1000-8000-0026BB765291", - "Name" : "Target Heater Cooler State", - "Constraints" : { - "ValidValues" : { - "0" : "Auto", - "1" : "Heat", - "2" : "Cool" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000033-0000-1000-8000-0026BB765291", - "Name" : "Target Heating Cooling State", - "Constraints" : { - "ValidValues" : { - "3" : "Auto", - "1" : "Heat", - "2" : "Cool", - "0" : "Off" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "int32", - "UUID" : "0000007B-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Target Horizontal Tilt Angle", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 90, - "MinimumValue" : -90 - } - }, - { - "UUID" : "000000B4-0000-1000-8000-0026BB765291", - "Name" : "Target Humidifier Dehumidifier State", - "Constraints" : { - "ValidValues" : { - "0" : "Humidifier or Dehumidifier", - "1" : "Humidifier", - "2" : "Dehumidifier" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "uint8", - "UUID" : "0000007C-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Target Position", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "float", - "UUID" : "00000034-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Target Relative Humidity", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "UUID" : "000000BE-0000-1000-8000-0026BB765291", - "Name" : "Target Slat State", - "Constraints" : { - "ValidValues" : { - "0" : "Manual", - "1" : "Auto" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "float", - "UUID" : "00000035-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Target Temperature", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "celsius", - "Constraints" : { - "StepValue" : 0.10000000000000001, - "MaximumValue" : 38, - "MinimumValue" : 10 - } - }, - { - "Format" : "int32", - "UUID" : "000000C2-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Target Tilt Angle", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 90, - "MinimumValue" : -90 - } - }, - { - "Format" : "int32", - "UUID" : "0000007D-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Target Vertical Tilt Angle", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "arcdegrees", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 90, - "MinimumValue" : -90 - } - }, - { - "UUID" : "00000036-0000-1000-8000-0026BB765291", - "Name" : "Temperature Display Units", - "Constraints" : { - "ValidValues" : { - "0" : "Celsius", - "1" : "Fahrenheit" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000D5-0000-1000-8000-0026BB765291", - "Name" : "Valve Type", - "Constraints" : { - "ValidValues" : { - "3" : "Water faucet", - "1" : "Irrigation", - "2" : "Shower head", - "0" : "Generic valve" - } - }, - "Format" : "uint8", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "00000037-0000-1000-8000-0026BB765291", - "Name" : "Version", - "Constraints" : { - "MaximumLength" : 64 - }, - "Format" : "string", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "UUID" : "000000C8-0000-1000-8000-0026BB765291", - "Name" : "VOC Density", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 1000, - "MinimumValue" : 0 - }, - "Format" : "float", - "Permissions" : [ - "securedRead" - ], - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ] - }, - { - "Format" : "uint8", - "UUID" : "00000119-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "write", - "cnotify", - "uncnotify" - ], - "Name" : "Volume", - "Permissions" : [ - "securedRead", - "securedWrite" - ], - "Unit" : "percentage", - "Constraints" : { - "StepValue" : 1, - "MaximumValue" : 100, - "MinimumValue" : 0 - } - }, - { - "Format" : "float", - "UUID" : "000000B5-0000-1000-8000-0026BB765291", - "Properties" : [ - "read", - "cnotify", - "uncnotify" - ], - "Name" : "Water Level", - "Permissions" : [ - "securedRead" - ], - "Unit" : "percentage", - "Constraints" : { - "MaximumValue" : 100, - "MinimumValue" : 0 - } - } - ], - "Version" : "1.0", - "Services" : [ - { - "OptionalCharacteristics" : [ - "00000053-0000-1000-8000-0026BB765291", - "000000A6-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000014-0000-1000-8000-0026BB765291", - "00000020-0000-1000-8000-0026BB765291", - "00000021-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291", - "00000030-0000-1000-8000-0026BB765291", - "00000052-0000-1000-8000-0026BB765291" - ], - "Name" : "Accessory Information", - "UUID" : "0000003E-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "000000A7-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291", - "000000B6-0000-1000-8000-0026BB765291", - "00000029-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000B0-0000-1000-8000-0026BB765291", - "000000A9-0000-1000-8000-0026BB765291", - "000000A8-0000-1000-8000-0026BB765291" - ], - "Name" : "Air Purifier", - "UUID" : "000000BB-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291", - "000000C3-0000-1000-8000-0026BB765291", - "000000C4-0000-1000-8000-0026BB765291", - "000000C5-0000-1000-8000-0026BB765291", - "000000C6-0000-1000-8000-0026BB765291", - "000000C7-0000-1000-8000-0026BB765291", - "000000C8-0000-1000-8000-0026BB765291", - "00000090-0000-1000-8000-0026BB765291", - "00000093-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000095-0000-1000-8000-0026BB765291" - ], - "Name" : "Air Quality Sensor", - "UUID" : "0000008D-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000068-0000-1000-8000-0026BB765291", - "0000008F-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291" - ], - "Name" : "Battery Service", - "UUID" : "00000096-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000114-0000-1000-8000-0026BB765291", - "00000115-0000-1000-8000-0026BB765291", - "00000116-0000-1000-8000-0026BB765291", - "00000117-0000-1000-8000-0026BB765291", - "00000120-0000-1000-8000-0026BB765291", - "00000118-0000-1000-8000-0026BB765291" - ], - "Name" : "Camera RTP Stream Management", - "UUID" : "00000110-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000093-0000-1000-8000-0026BB765291", - "00000094-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000092-0000-1000-8000-0026BB765291" - ], - "Name" : "Carbon Dioxide Sensor", - "UUID" : "00000097-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000090-0000-1000-8000-0026BB765291", - "00000091-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000069-0000-1000-8000-0026BB765291" - ], - "Name" : "Carbon Monoxide Sensor", - "UUID" : "0000007F-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000006A-0000-1000-8000-0026BB765291" - ], - "Name" : "Contact Sensor", - "UUID" : "00000080-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "0000006F-0000-1000-8000-0026BB765291", - "00000024-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000006D-0000-1000-8000-0026BB765291", - "00000072-0000-1000-8000-0026BB765291", - "0000007C-0000-1000-8000-0026BB765291" - ], - "Name" : "Door", - "UUID" : "00000081-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000008-0000-1000-8000-0026BB765291", - "00000119-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000073-0000-1000-8000-0026BB765291" - ], - "Name" : "Doorbell", - "UUID" : "00000121-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000028-0000-1000-8000-0026BB765291", - "00000029-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000025-0000-1000-8000-0026BB765291" - ], - "Name" : "Fan", - "UUID" : "00000040-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "000000AF-0000-1000-8000-0026BB765291", - "000000BF-0000-1000-8000-0026BB765291", - "000000A7-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291", - "00000028-0000-1000-8000-0026BB765291", - "00000029-0000-1000-8000-0026BB765291", - "000000B6-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000B0-0000-1000-8000-0026BB765291" - ], - "Name" : "Fan v2", - "UUID" : "000000B7-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "000000AB-0000-1000-8000-0026BB765291", - "000000AD-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000AC-0000-1000-8000-0026BB765291" - ], - "Name" : "Filter Maintenance", - "UUID" : "000000BA-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000B0-0000-1000-8000-0026BB765291" - ], - "Name" : "Faucet", - "UUID" : "000000D7-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "0000001D-0000-1000-8000-0026BB765291", - "0000001E-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000000E-0000-1000-8000-0026BB765291", - "00000032-0000-1000-8000-0026BB765291", - "00000024-0000-1000-8000-0026BB765291" - ], - "Name" : "Garage Door Opener", - "UUID" : "00000041-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "000000A7-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291", - "000000B6-0000-1000-8000-0026BB765291", - "0000000D-0000-1000-8000-0026BB765291", - "00000012-0000-1000-8000-0026BB765291", - "00000036-0000-1000-8000-0026BB765291", - "00000029-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000B0-0000-1000-8000-0026BB765291", - "000000B1-0000-1000-8000-0026BB765291", - "000000B2-0000-1000-8000-0026BB765291", - "00000011-0000-1000-8000-0026BB765291" - ], - "Name" : "Heater Cooler", - "UUID" : "000000BC-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "000000A7-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291", - "000000B6-0000-1000-8000-0026BB765291", - "000000B5-0000-1000-8000-0026BB765291", - "000000C9-0000-1000-8000-0026BB765291", - "000000CA-0000-1000-8000-0026BB765291", - "00000029-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000010-0000-1000-8000-0026BB765291", - "000000B3-0000-1000-8000-0026BB765291", - "000000B4-0000-1000-8000-0026BB765291", - "000000B0-0000-1000-8000-0026BB765291" - ], - "Name" : "Humidifier Dehumidifier", - "UUID" : "000000BD-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000010-0000-1000-8000-0026BB765291" - ], - "Name" : "Humidity Sensor", - "UUID" : "00000082-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "000000D4-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000B0-0000-1000-8000-0026BB765291", - "000000D1-0000-1000-8000-0026BB765291", - "000000D2-0000-1000-8000-0026BB765291" - ], - "Name" : "Irrigation System", - "UUID" : "000000CF-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000070-0000-1000-8000-0026BB765291" - ], - "Name" : "Leak Sensor", - "UUID" : "00000083-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000006B-0000-1000-8000-0026BB765291" - ], - "Name" : "Light Sensor", - "UUID" : "00000084-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000008-0000-1000-8000-0026BB765291", - "00000013-0000-1000-8000-0026BB765291", - "0000002F-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000025-0000-1000-8000-0026BB765291" - ], - "Name" : "Lightbulb", - "UUID" : "00000043-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "0000001F-0000-1000-8000-0026BB765291", - "00000005-0000-1000-8000-0026BB765291", - "0000001A-0000-1000-8000-0026BB765291", - "00000001-0000-1000-8000-0026BB765291", - "0000001C-0000-1000-8000-0026BB765291", - "0000000E-0000-1000-8000-0026BB765291", - "00000022-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000019-0000-1000-8000-0026BB765291", - "00000037-0000-1000-8000-0026BB765291" - ], - "Name" : "Lock Management", - "UUID" : "00000044-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000001D-0000-1000-8000-0026BB765291", - "0000001E-0000-1000-8000-0026BB765291" - ], - "Name" : "Lock Mechanism", - "UUID" : "00000045-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000119-0000-1000-8000-0026BB765291", - "0000011A-0000-1000-8000-0026BB765291" - ], - "Name" : "Microphone", - "UUID" : "00000112-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000022-0000-1000-8000-0026BB765291" - ], - "Name" : "Motion Sensor", - "UUID" : "00000085-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000071-0000-1000-8000-0026BB765291" - ], - "Name" : "Occupancy Sensor", - "UUID" : "00000086-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000025-0000-1000-8000-0026BB765291", - "00000026-0000-1000-8000-0026BB765291" - ], - "Name" : "Outlet", - "UUID" : "00000047-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "0000008E-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000066-0000-1000-8000-0026BB765291", - "00000067-0000-1000-8000-0026BB765291" - ], - "Name" : "Security System", - "UUID" : "0000007E-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000CD-0000-1000-8000-0026BB765291" - ], - "Name" : "Service Label", - "UUID" : "000000CC-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "000000C1-0000-1000-8000-0026BB765291", - "000000C2-0000-1000-8000-0026BB765291", - "000000B6-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000C0-0000-1000-8000-0026BB765291", - "000000AA-0000-1000-8000-0026BB765291" - ], - "Name" : "Slat", - "UUID" : "000000B9-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000076-0000-1000-8000-0026BB765291" - ], - "Name" : "Smoke Sensor", - "UUID" : "00000087-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "00000119-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000011A-0000-1000-8000-0026BB765291" - ], - "Name" : "Speaker", - "UUID" : "00000113-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291", - "000000CB-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000073-0000-1000-8000-0026BB765291" - ], - "Name" : "Stateless Programmable Switch", - "UUID" : "00000089-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000025-0000-1000-8000-0026BB765291" - ], - "Name" : "Switch", - "UUID" : "00000049-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000075-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "00000079-0000-1000-8000-0026BB765291", - "0000007A-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "00000011-0000-1000-8000-0026BB765291" - ], - "Name" : "Temperature Sensor", - "UUID" : "0000008A-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "00000010-0000-1000-8000-0026BB765291", - "00000034-0000-1000-8000-0026BB765291", - "0000000D-0000-1000-8000-0026BB765291", - "00000012-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000000F-0000-1000-8000-0026BB765291", - "00000033-0000-1000-8000-0026BB765291", - "00000011-0000-1000-8000-0026BB765291", - "00000035-0000-1000-8000-0026BB765291", - "00000036-0000-1000-8000-0026BB765291" - ], - "Name" : "Thermostat", - "UUID" : "0000004A-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "000000D3-0000-1000-8000-0026BB765291", - "000000D4-0000-1000-8000-0026BB765291", - "000000D6-0000-1000-8000-0026BB765291", - "000000CB-0000-1000-8000-0026BB765291", - "00000077-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "000000B0-0000-1000-8000-0026BB765291", - "000000D2-0000-1000-8000-0026BB765291", - "000000D5-0000-1000-8000-0026BB765291" - ], - "Name" : "Valve", - "UUID" : "000000D0-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "0000006F-0000-1000-8000-0026BB765291", - "00000024-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000006D-0000-1000-8000-0026BB765291", - "0000007C-0000-1000-8000-0026BB765291", - "00000072-0000-1000-8000-0026BB765291" - ], - "Name" : "Window", - "UUID" : "0000008B-0000-1000-8000-0026BB765291" - }, - { - "OptionalCharacteristics" : [ - "0000006F-0000-1000-8000-0026BB765291", - "0000007B-0000-1000-8000-0026BB765291", - "0000007D-0000-1000-8000-0026BB765291", - "0000006C-0000-1000-8000-0026BB765291", - "0000006E-0000-1000-8000-0026BB765291", - "00000024-0000-1000-8000-0026BB765291", - "00000023-0000-1000-8000-0026BB765291" - ], - "RequiredCharacteristics" : [ - "0000006D-0000-1000-8000-0026BB765291", - "0000007C-0000-1000-8000-0026BB765291", - "00000072-0000-1000-8000-0026BB765291" - ], - "Name" : "Window Covering", - "UUID" : "0000008C-0000-1000-8000-0026BB765291" - } - ] + ] } \ No newline at end of file diff --git a/hap/pair/pairing_controller.go b/hap/pair/pairing_controller.go index c4962616..d2bea8eb 100644 --- a/hap/pair/pairing_controller.go +++ b/hap/pair/pairing_controller.go @@ -44,12 +44,6 @@ func (c *PairingController) Handle(cont util.Container) (util.Container, error) log.Debug.Printf("Remove LTPK for client '%s'\n", username) c.database.DeleteEntity(entity) case PairingMethodAdd: - if perm != AdminPerm { - log.Info.Println("Non-admin controllers are not allowed to add pairings") - out.SetByte(TagErrCode, ErrCodeAuthenticationFailed.Byte()) - break - } - err := c.database.SaveEntity(entity) if err != nil { log.Info.Panic(err) diff --git a/ip_transport.go b/ip_transport.go index 39673ed6..817d693e 100644 --- a/ip_transport.go +++ b/ip_transport.go @@ -25,7 +25,8 @@ type ipTransport struct { context hap.Context server http.Server mutex *sync.Mutex - mdns *MDNSService + // TODO reference is not needed + mdns *MDNSService storage util.Storage database db.Database @@ -279,3 +280,7 @@ func (t *ipTransport) Handle(ev interface{}) { break } } + +func (t *ipTransport) Storage() util.Storage { + return t.storage +} diff --git a/service/input_source.go b/service/input_source.go new file mode 100644 index 00000000..6afa7c59 --- /dev/null +++ b/service/input_source.go @@ -0,0 +1,52 @@ +// THIS FILE IS AUTO-GENERATED +package service + +import ( + "github.com/brutella/hc/characteristic" +) + +const TypeInputSource = "D9" + +type InputSource struct { + *Service + + ConfiguredName *characteristic.ConfiguredName + InputSourceType *characteristic.InputSourceType + IsConfigured *characteristic.IsConfigured + CurrentVisibilityState *characteristic.CurrentVisibilityState + Identifier *characteristic.Identifier + InputDeviceType *characteristic.InputDeviceType + TargetVisibilityState *characteristic.TargetVisibilityState + Name *characteristic.Name +} + +func NewInputSource() *InputSource { + svc := InputSource{} + svc.Service = New(TypeInputSource) + + svc.ConfiguredName = characteristic.NewConfiguredName() + svc.AddCharacteristic(svc.ConfiguredName.Characteristic) + + svc.Name = characteristic.NewName() + svc.AddCharacteristic(svc.Name.Characteristic) + + svc.InputSourceType = characteristic.NewInputSourceType() + svc.AddCharacteristic(svc.InputSourceType.Characteristic) + + svc.IsConfigured = characteristic.NewIsConfigured() + svc.AddCharacteristic(svc.IsConfigured.Characteristic) + + svc.CurrentVisibilityState = characteristic.NewCurrentVisibilityState() + svc.AddCharacteristic(svc.CurrentVisibilityState.Characteristic) + + svc.Identifier = characteristic.NewIdentifier() + svc.AddCharacteristic(svc.Identifier.Characteristic) + + svc.InputDeviceType = characteristic.NewInputDeviceType() + svc.AddCharacteristic(svc.InputDeviceType.Characteristic) + + svc.TargetVisibilityState = characteristic.NewTargetVisibilityState() + svc.AddCharacteristic(svc.TargetVisibilityState.Characteristic) + + return &svc +} diff --git a/service/service.go b/service/service.go index a2f2383c..2f49f063 100644 --- a/service/service.go +++ b/service/service.go @@ -9,6 +9,9 @@ type Service struct { ID int64 `json:"iid"` Type string `json:"type"` Characteristics []*characteristic.Characteristic `json:"characteristics"` + Hidden *bool `json:"hidden,omitempty"` + Primary *bool `json:"primary,omitempty"` + Linked []int64 `json:"linked,omitempty"` } // New returns a new service. @@ -16,6 +19,7 @@ func New(typ string) *Service { s := Service{ Type: typ, Characteristics: []*characteristic.Characteristic{}, + Linked: []int64{}, } return &s @@ -40,6 +44,28 @@ func (s *Service) GetCharacteristics() []*characteristic.Characteristic { return result } +func (s *Service) SetHidden(b bool) { + s.Hidden = &b +} + +func (s *Service) IsHidden() bool { + if s.Hidden != nil && *s.Hidden == true { + return true + } + return false +} + +func (s *Service) SetPrimary(b bool) { + s.Primary = &b +} + +func (s *Service) IsPrimary() bool { + if s.Primary != nil && *s.Primary == true { + return true + } + return false +} + // Equal returns true when receiver has the same characteristics, service id and service type as the argument. func (s *Service) Equal(other interface{}) bool { if service, ok := other.(*Service); ok == true { @@ -64,3 +90,10 @@ func (s *Service) Equal(other interface{}) bool { func (s *Service) AddCharacteristic(c *characteristic.Characteristic) { s.Characteristics = append(s.Characteristics, c) } + +func (s *Service) AddLinkedService(other *Service) { + if other.ID == 0 { + panic("adding a linked should be done after the server was added to an accessory") + } + s.Linked = append(s.Linked, other.ID) +} diff --git a/service/service_test.go b/service/service_test.go new file mode 100644 index 00000000..259f84fc --- /dev/null +++ b/service/service_test.go @@ -0,0 +1,61 @@ +package service + +import ( + "encoding/json" + "testing" +) + +func TestMinimalService(t *testing.T) { + s := New(TypeOutlet) + + if buf, err := json.Marshal(s); err != nil { + t.Fatal(err) + } else { + if is, want := string(buf), "{\"iid\":0,\"type\":\"47\",\"characteristics\":[]}"; is != want { + t.Fatalf("%v != %v", is, want) + } + } +} + +func TestPrimaryService(t *testing.T) { + s := New(TypeOutlet) + s.SetPrimary(true) + + if buf, err := json.Marshal(s); err != nil { + t.Fatal(err) + } else { + if is, want := string(buf), "{\"iid\":0,\"type\":\"47\",\"characteristics\":[],\"primary\":true}"; is != want { + t.Fatalf("%v != %v", is, want) + } + } +} + +func TestHiddenService(t *testing.T) { + s := New(TypeOutlet) + s.SetHidden(true) + + if buf, err := json.Marshal(s); err != nil { + t.Fatal(err) + } else { + if is, want := string(buf), "{\"iid\":0,\"type\":\"47\",\"characteristics\":[],\"hidden\":true}"; is != want { + t.Fatalf("%v != %v", is, want) + } + } +} + +func TestLinkedService(t *testing.T) { + s := New(TypeOutlet) + s.ID = 1 + fan := New(TypeFan) + fan.ID = 2 + + s.AddLinkedService(fan) + + if buf, err := json.Marshal(s); err != nil { + t.Fatal(err) + } else { + if is, want := string(buf), "{\"iid\":1,\"type\":\"47\",\"characteristics\":[],\"linked\":[2]}"; is != want { + t.Fatalf("%v != %v", is, want) + } + } +} diff --git a/service/television.go b/service/television.go new file mode 100644 index 00000000..0e158265 --- /dev/null +++ b/service/television.go @@ -0,0 +1,68 @@ +// THIS FILE IS AUTO-GENERATED +package service + +import ( + "github.com/brutella/hc/characteristic" +) + +const TypeTelevision = "D8" + +type Television struct { + *Service + + Active *characteristic.Active + ActiveIdentifier *characteristic.ActiveIdentifier + ConfiguredName *characteristic.ConfiguredName + SleepDiscoveryMode *characteristic.SleepDiscoveryMode + Brightness *characteristic.Brightness + ClosedCaptions *characteristic.ClosedCaptions + DisplayOrder *characteristic.DisplayOrder + CurrentMediaState *characteristic.CurrentMediaState + TargetMediaState *characteristic.TargetMediaState + PictureMode *characteristic.PictureMode + PowerModeSelection *characteristic.PowerModeSelection + RemoteKey *characteristic.RemoteKey +} + +func NewTelevision() *Television { + svc := Television{} + svc.Service = New(TypeTelevision) + + svc.Active = characteristic.NewActive() + svc.AddCharacteristic(svc.Active.Characteristic) + + svc.ActiveIdentifier = characteristic.NewActiveIdentifier() + svc.AddCharacteristic(svc.ActiveIdentifier.Characteristic) + + svc.ConfiguredName = characteristic.NewConfiguredName() + svc.AddCharacteristic(svc.ConfiguredName.Characteristic) + + svc.SleepDiscoveryMode = characteristic.NewSleepDiscoveryMode() + svc.AddCharacteristic(svc.SleepDiscoveryMode.Characteristic) + + svc.Brightness = characteristic.NewBrightness() + svc.AddCharacteristic(svc.Brightness.Characteristic) + + svc.ClosedCaptions = characteristic.NewClosedCaptions() + svc.AddCharacteristic(svc.ClosedCaptions.Characteristic) + + svc.DisplayOrder = characteristic.NewDisplayOrder() + svc.AddCharacteristic(svc.DisplayOrder.Characteristic) + + svc.CurrentMediaState = characteristic.NewCurrentMediaState() + svc.AddCharacteristic(svc.CurrentMediaState.Characteristic) + + svc.TargetMediaState = characteristic.NewTargetMediaState() + svc.AddCharacteristic(svc.TargetMediaState.Characteristic) + + svc.PictureMode = characteristic.NewPictureMode() + svc.AddCharacteristic(svc.PictureMode.Characteristic) + + svc.PowerModeSelection = characteristic.NewPowerModeSelection() + svc.AddCharacteristic(svc.PowerModeSelection.Characteristic) + + svc.RemoteKey = characteristic.NewRemoteKey() + svc.AddCharacteristic(svc.RemoteKey.Characteristic) + + return &svc +} diff --git a/transport.go b/transport.go index fe08fa74..61f8102c 100644 --- a/transport.go +++ b/transport.go @@ -1,6 +1,8 @@ package hc -import () +import ( + "github.com/brutella/hc/util" +) // Transport provides accessories over a network. type Transport interface { @@ -10,4 +12,6 @@ type Transport interface { // Stop stops the transport // Use the returned channel to wait until the transport is fully stopped. Stop() <-chan struct{} + + Storage() util.Storage } From 75e2a1b2826272291b1ad9ecfa1cf645264a4deb Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Mon, 28 Jan 2019 13:27:00 +0100 Subject: [PATCH 02/24] Remove failing test --- hap/pair/pairing_controller_test.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/hap/pair/pairing_controller_test.go b/hap/pair/pairing_controller_test.go index aae45de5..a4c298f7 100644 --- a/hap/pair/pairing_controller_test.go +++ b/hap/pair/pairing_controller_test.go @@ -49,32 +49,6 @@ func TestAddPairing(t *testing.T) { } } -func TestAddPairingAsNonAdmin(t *testing.T) { - in := util.NewTLV8Container() - in.SetByte(TagPairingMethod, PairingMethodAdd.Byte()) - in.SetByte(TagSequence, 0x01) - in.SetString(TagUsername, "Unit Test") - in.SetBytes(TagPublicKey, []byte{0x01, 0x02}) - - database, _ := db.NewDatabase(os.TempDir()) - controller := NewPairingController(database) - - out, err := controller.Handle(in) - if err != nil { - t.Fatal(err) - } - if out == nil { - t.Fatal("no response") - } - if is, want := out.GetByte(TagSequence), byte(0x2); is != want { - t.Fatalf("is=%v want=%v", is, want) - } - - if is, want := out.GetByte(TagErrCode), ErrCodeAuthenticationFailed.Byte(); is != want { - t.Fatalf("is=%v want=%v", is, want) - } -} - func TestDeletePairing(t *testing.T) { username := "Unit Test" entity := db.NewEntity(username, []byte{0x01, 0x02}, nil) From e49970131c2015d63d8643ffa5d03df99775d475 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 29 Jan 2019 13:59:25 +0100 Subject: [PATCH 03/24] Update accessory and service readme --- accessory/README.md | 4 +++- service/README.md | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/accessory/README.md b/accessory/README.md index cc32bfa0..3ed64675 100644 --- a/accessory/README.md +++ b/accessory/README.md @@ -25,4 +25,6 @@ | Dehumidifier | 23 | | Sprinklers | 28 | | Faucets | 29 | -| Shower Systems | 30 | \ No newline at end of file +| Shower Systems | 30 | +| Television | 31 | +| Remote Control | 32 | \ No newline at end of file diff --git a/service/README.md b/service/README.md index b433bda9..52b4695f 100644 --- a/service/README.md +++ b/service/README.md @@ -20,19 +20,19 @@ | Humidity Sensor | Current Relative Humidity
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional
Name Optional | 82 | | Irrigation System | Active
Program Mode
In Use
Name Optional
Remaining Duration Optional
Status Fault Optional | CF | | Leak Sensor | Leak Detected
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional
Name Optional | 83 | -| Light Sensor | Current Ambient Light Level
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional
Name Optional | 84 | +| Light Sensor | Current Ambient Light Level
Name Optional
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional | 84 | | Lightbulb | On
Brightness Optional
Hue Optional
Saturation Optional
Name Optional | 43 | | Lock Management | Lock Control Point
Version
Logs Optional
Audio Feedback Optional
Lock Management Auto Security Timeout Optional
Administrator Only Access Optional
Lock Last Known Action Optional
Current Door State Optional
Motion Detected Optional
Name Optional | 44 | | Lock Mechanism | Lock Current State
Lock Target State
Name Optional | 45 | -| Microphone | Mute
Volume Optional
Name Optional | 112 | +| Microphone | Volume
Mute
Name Optional | 112 | | Motion Sensor | Motion Detected
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional
Name Optional | 85 | -| Occupancy Sensor | Occupancy Detected
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional
Name Optional | 86 | +| Occupancy Sensor | Occupancy Detected
Name Optional
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional | 86 | | Outlet | On
Outlet In Use
Name Optional | 47 | | Security System | Security System Current State
Security System Target State
Status Fault Optional
Status Tampered Optional
Security System Alarm Type Optional
Name Optional | 7E | | Service Label | Service Label Namespace
Name Optional | CC | | Slat | Slat Type
Current Slat State
Name Optional
Current Tilt Angle Optional
Target Tilt Angle Optional
Swing Mode Optional | B9 | | Smoke Sensor | Smoke Detected
Status Active Optional
Status Fault Optional
Status Tampered Optional
Status Low Battery Optional
Name Optional | 87 | -| Speaker | Mute
Volume Optional
Name Optional | 113 | +| Speaker | Mute
Name Optional
Volume Optional | 113 | | Stateless Programmable Switch | Programmable Switch Event
Name Optional
Service Label Index Optional | 89 | | Switch | On
Name Optional | 49 | | Temperature Sensor | Current Temperature
Status Active Optional
Status Fault Optional
Status Low Battery Optional
Status Tampered Optional
Name Optional | 8A | @@ -40,3 +40,5 @@ | Valve | Active
In Use
Valve Type
Set Duration Optional
Remaining Duration Optional
Is Configured Optional
Service Label Index Optional
Status Fault Optional
Name Optional | D0 | | Window | Current Position
Target Position
Position State
Hold Position Optional
Obstruction Detected Optional
Name Optional | 8B | | Window Covering | Current Position
Target Position
Position State
Hold Position Optional
Target Horizontal Tilt Angle Optional
Target Vertical Tilt Angle Optional
Current Horizontal Tilt Angle Optional
Current Vertical Tilt Angle Optional
Obstruction Detected Optional
Name Optional | 8C | +| Television | Active
Active Identifier
Configured Name
Sleep Discovery Mode
Brightness
Closed Captions
Display Order
Current Media State
Target Media State
Picture Mode
Power Mode Selection
Remote Key | D8 | +| Input Source | Configured Name
Input Source Type
Is Configured
Current Visibility State
Identifier
Input Device Type
Target Visibility State
Name | D9 | From afaa5a972e7ea77409a3ee23f062e6521d68fc6e Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Thu, 31 Jan 2019 12:20:56 +0100 Subject: [PATCH 04/24] Use github.com/brutella/dnssd v1.1.0 --- config.go | 9 +---- go.mod | 11 +++--- go.sum | 25 ++++++++------ ip_transport.go | 34 +++++++++++++++++-- mdns.go | 89 ------------------------------------------------- 5 files changed, 53 insertions(+), 115 deletions(-) delete mode 100644 mdns.go diff --git a/config.go b/config.go index 93221af8..a32896d7 100644 --- a/config.go +++ b/config.go @@ -6,7 +6,6 @@ import ( "net" "reflect" - "github.com/brutella/hc/log" "github.com/brutella/hc/util" "github.com/gosexy/to" ) @@ -21,7 +20,7 @@ type Config struct { // When empty, the transport uses a random port Port string - // IP on which clients can connect. + // Deprecated: Specifying a static IP is discouraged. IP string // Pin with has to be entered on iOS client to pair with the accessory @@ -41,16 +40,10 @@ type Config struct { } func defaultConfig(name string) *Config { - ip, err := getFirstLocalIPAddr() - if err != nil { - log.Info.Panic(err) - } - return &Config{ StoragePath: name, Pin: "00102003", // default pin Port: "", // empty string means that we get port from assigned by the system - IP: ip.String(), name: name, id: util.MAC48Address(util.RandomHexString()), version: 1, diff --git a/go.mod b/go.mod index 1fae109c..351e1537 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,12 @@ module github.com/brutella/hc require ( github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 - github.com/brutella/dnssd v0.0.0-20180519095852-a1eecd10aafc + github.com/brutella/dnssd v1.1.0 github.com/gosexy/to v0.0.0-20141221203644-c20e083e3123 - github.com/miekg/dns v1.0.15 // indirect + github.com/miekg/dns v1.1.4 // indirect github.com/tadglines/go-pkgs v0.0.0-20140924210655-1f86682992f1 - golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 - golang.org/x/net v0.0.0-20181114220301-adae6a3d119a // indirect - golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b // indirect + golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 + golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + golang.org/x/sys v0.0.0-20190130150945-aca44879d564 // indirect ) diff --git a/go.sum b/go.sum index 9bb3b003..24dc4de7 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,21 @@ github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= -github.com/brutella/dnssd v0.0.0-20180519095852-a1eecd10aafc h1:gevuvoeZlOfrFb7bfKeJWjYvkRMsDPyBHojp3wVy/yk= -github.com/brutella/dnssd v0.0.0-20180519095852-a1eecd10aafc/go.mod h1:Gm5azbpU/tmPJNH9nQrFcTBIgasziqDdNYE/8epxvjc= +github.com/brutella/dnssd v1.1.0 h1:kJdLHbmBcYHwdmApjejMnOFxQsqfFhgH5rLPkvMy0JE= +github.com/brutella/dnssd v1.1.0/go.mod h1:FiUea3FfCnV1wi78S9exUgWrQfkILjydmuUcX6/jbgc= github.com/gosexy/to v0.0.0-20141221203644-c20e083e3123 h1:6Q7VB4v0aEgIE6BtsbJhEH0KgFE0f+FHAxXePQp9Klc= github.com/gosexy/to v0.0.0-20141221203644-c20e083e3123/go.mod h1:oQuuq9ZkoRpy+2mhINlY3ZrwgywR77yPXmFpP6vCr/w= -github.com/miekg/dns v1.0.15 h1:9+UupePBQCG6zf1q/bGmTO1vumoG13jsrbWOSX1W6Tw= -github.com/miekg/dns v1.0.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= +github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/tadglines/go-pkgs v0.0.0-20140924210655-1f86682992f1 h1:ms/IQpkxq+t7hWpgKqCE5KjAUQWC24mqBrnL566SWgE= github.com/tadglines/go-pkgs v0.0.0-20140924210655-1f86682992f1/go.mod h1:roo6cZ/uqpwKMuvPG0YmzI5+AmUiMWfjCBZpGXqbTxE= -golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 h1:et7+NAX3lLIk5qUCTA9QelBjGE/NkhzYw/mhnr0s7nI= -golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b h1:MQE+LT/ABUuuvEZ+YQAMSXindAdUh7slEmAkup74op4= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564 h1:o6ENHFwwr1TZ9CUPQcfo1HGvLP1OPsPOTB7xCIOPNmU= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/ip_transport.go b/ip_transport.go index 817d693e..fc0682e6 100644 --- a/ip_transport.go +++ b/ip_transport.go @@ -5,6 +5,7 @@ import ( "context" "io/ioutil" "net" + "strings" "sync" _ "time" @@ -25,8 +26,6 @@ type ipTransport struct { context hap.Context server http.Server mutex *sync.Mutex - // TODO reference is not needed - mdns *MDNSService storage util.Storage database db.Database @@ -176,7 +175,7 @@ func (t *ipTransport) Start() { // }() // Publish accessory ip - log.Info.Printf("Accessory address is %s:%s\n", t.config.IP, s.Port()) + log.Info.Printf("Listening on port %s\n", s.Port()) serverCtx, serverCancel := context.WithCancel(t.ctx) defer serverCancel() @@ -284,3 +283,32 @@ func (t *ipTransport) Handle(ev interface{}) { func (t *ipTransport) Storage() util.Storage { return t.storage } + +func newService(config *Config) dnssd.Service { + // 2016-03-14(brutella): Replace whitespaces (" ") from service name + // with underscores ("_")to fix invalid http host header field value + // produces by iOS. + // + // [Radar] http://openradar.appspot.com/radar?id=4931940373233664 + stripped := strings.Replace(config.name, " ", "_", -1) + + var ips []net.IP + if ip := net.ParseIP(config.IP); ip != nil { + ips = append(ips, ip) + } + + dnsCfg := dnssd.Config{ + Name: stripped, + Type: "_hap._tcp", + Domain: "local", + Text: config.txtRecords(), + IPs: ips, + Port: config.servePort, + } + service, err := dnssd.NewService(dnsCfg) + if err != nil { + log.Info.Fatal(err) + } + + return service +} diff --git a/mdns.go b/mdns.go deleted file mode 100644 index 2d556137..00000000 --- a/mdns.go +++ /dev/null @@ -1,89 +0,0 @@ -package hc - -import ( - "context" - "github.com/brutella/dnssd" - "github.com/brutella/hc/log" - "net" - "strings" -) - -// MDNSService represents a mDNS service. -type MDNSService struct { - config *Config - responder dnssd.Responder - handle dnssd.ServiceHandle -} - -func newService(config *Config) dnssd.Service { - // 2016-03-14(brutella): Replace whitespaces (" ") from service name - // with underscores ("_")to fix invalid http host header field value - // produces by iOS. - // - // [Radar] http://openradar.appspot.com/radar?id=4931940373233664 - stripped := strings.Replace(config.name, " ", "_", -1) - - var ips []net.IP - if ip := net.ParseIP(config.IP); ip != nil { - ips = append(ips, ip) - } - - service := dnssd.NewService(stripped, "_hap._tcp.", "local.", "", ips, config.servePort) - service.Text = config.txtRecords() - - return service -} - -// NewMDNSService returns a new service based for the bridge name, id and port. -func NewMDNSService(config *Config) *MDNSService { - // TODO handle error - responder, _ := dnssd.NewResponder() - - return &MDNSService{ - config: config, - responder: responder, - } -} - -// Publish announces the service for the machine's ip address on a random port using mDNS. -func (s *MDNSService) Publish(ctx context.Context) error { - // 2016-03-14(brutella): Replace whitespaces (" ") from service name - // with underscores ("_")to fix invalid http host header field value - // produces by iOS. - // - // [Radar] http://openradar.appspot.com/radar?id=4931940373233664 - stripped := strings.Replace(s.config.name, " ", "_", -1) - - var ips []net.IP - if ip := net.ParseIP(s.config.IP); ip != nil { - ips = append(ips, ip) - } - - service := dnssd.NewService(stripped, "_hap._tcp.", "local.", "", ips, s.config.servePort) - service.Text = s.config.txtRecords() - handle, err := s.responder.Add(service) - if err != nil { - log.Info.Panic(err) - } - - s.handle = handle - - return s.responder.Respond(ctx) -} - -// Update updates the mDNS txt records. -func (s *MDNSService) Update() { - if s.handle != nil { - txt := s.config.txtRecords() - s.handle.UpdateText(txt, s.responder) - log.Debug.Println(txt) - } -} - -// Stop stops the running mDNS service. -func (s *MDNSService) Stop() { - if s.handle != nil { - s.responder.Remove(s.handle) - s.handle = nil - } -} From cace533398b36991036b6cd97dc1ffb667e60e89 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Fri, 1 Feb 2019 08:54:22 +0100 Subject: [PATCH 05/24] Make sure that CI works when using Go modules --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5110ef5f..192680de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,12 @@ sudo: false language: go +go: + - 1.10.x + - master +os: + - linux + - osx +dist: trusty +script: + - env GO111MODULE=on go build + - env GO111MODULE=on go test \ No newline at end of file From 1741d678c81256279d4bfe15eeedca08a5d1c931 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Fri, 1 Feb 2019 10:39:41 +0100 Subject: [PATCH 06/24] Set deployment target to Go 1.11 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 192680de..3fd91cf5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: go go: - - 1.10.x + - 1.11.x - master os: - linux From 5cf4a0237c7cebe46314a4e5ad97082968f43a44 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Fri, 1 Feb 2019 10:45:18 +0100 Subject: [PATCH 07/24] Fix CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3fd91cf5..01463f05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ os: - linux - osx dist: trusty +install: true script: - env GO111MODULE=on go build - env GO111MODULE=on go test \ No newline at end of file From 33b865b3de6695577b06b2e7aa219598fd689670 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Wed, 6 Feb 2019 14:13:25 +0100 Subject: [PATCH 08/24] Add missing value conversion for uint16 format --- characteristic/characteristic.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/characteristic/characteristic.go b/characteristic/characteristic.go index a3a65869..ef80acbc 100644 --- a/characteristic/characteristic.go +++ b/characteristic/characteristic.go @@ -225,6 +225,8 @@ func (c *Characteristic) convert(v interface{}) interface{} { return to.Float64(v) case FormatUInt8: return int(to.Uint64(v)) + case FormatUInt16: + return int(to.Uint64(v)) case FormatUInt32: return int(to.Uint64(v)) case FormatInt32: From e8a9147bdac5b0b880a247c233d18c377fa26245 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Fri, 8 Feb 2019 14:24:00 +0100 Subject: [PATCH 09/24] Update characteristics --- characteristic/identifier.go | 3 +-- gen/metadata.json | 6 ++---- service/input_source.go | 6 +++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/characteristic/identifier.go b/characteristic/identifier.go index 83595c8e..e51a8b5c 100644 --- a/characteristic/identifier.go +++ b/characteristic/identifier.go @@ -10,9 +10,8 @@ type Identifier struct { func NewIdentifier() *Identifier { char := NewInt(TypeIdentifier) char.Format = FormatUInt32 - char.Perms = []string{PermRead, PermEvents} + char.Perms = []string{PermRead} char.SetMinValue(0) - char.SetStepValue(1) char.SetValue(0) diff --git a/gen/metadata.json b/gen/metadata.json index e15be693..c3510645 100644 --- a/gen/metadata.json +++ b/gen/metadata.json @@ -1046,9 +1046,7 @@ "securedRead" ], "Properties": [ - "read", - "cnotify", - "uncnotify" + "read" ], "Constraints": { "StepValue": 1, @@ -1656,7 +1654,7 @@ "1": "Hide" } }, - "Format": "float", + "Format": "uint8", "Properties": [ "write" ] diff --git a/service/input_source.go b/service/input_source.go index 6afa7c59..f9a6217e 100644 --- a/service/input_source.go +++ b/service/input_source.go @@ -27,9 +27,6 @@ func NewInputSource() *InputSource { svc.ConfiguredName = characteristic.NewConfiguredName() svc.AddCharacteristic(svc.ConfiguredName.Characteristic) - svc.Name = characteristic.NewName() - svc.AddCharacteristic(svc.Name.Characteristic) - svc.InputSourceType = characteristic.NewInputSourceType() svc.AddCharacteristic(svc.InputSourceType.Characteristic) @@ -48,5 +45,8 @@ func NewInputSource() *InputSource { svc.TargetVisibilityState = characteristic.NewTargetVisibilityState() svc.AddCharacteristic(svc.TargetVisibilityState.Characteristic) + svc.Name = characteristic.NewName() + svc.AddCharacteristic(svc.Name.Characteristic) + return &svc } From d843c8ca3f52ca5e7260fcecc844761d2240779d Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Fri, 8 Feb 2019 14:29:49 +0100 Subject: [PATCH 10/24] Add tv example --- _example/tv/main.go | 161 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 _example/tv/main.go diff --git a/_example/tv/main.go b/_example/tv/main.go new file mode 100644 index 00000000..d3efa9b6 --- /dev/null +++ b/_example/tv/main.go @@ -0,0 +1,161 @@ +package main + +import ( + "fmt" + "github.com/brutella/hc" + "github.com/brutella/hc/accessory" + "github.com/brutella/hc/characteristic" + "github.com/brutella/hc/log" + "github.com/brutella/hc/service" + "github.com/brutella/hc/util" +) + +func addInputSource(t *accessory.Television, id int, name string, inputSourceType int, storage util.Storage) { + in := service.NewInputSource() + + in.Identifier.SetValue(id) + in.ConfiguredName.SetValue(name) + in.Name.SetValue(name) + in.InputSourceType.SetValue(inputSourceType) + in.IsConfigured.SetValue(characteristic.IsConfiguredConfigured) + + t.AddService(in.Service) + t.Television.AddLinkedService(in.Service) + + key := fmt.Sprintf("input-%d", id) + if b, err := storage.Get(key); err == nil && len(b) > 0 { + fmt.Println("restore configured name", string(b)) + in.ConfiguredName.SetValue(string(b)) + } + + in.ConfiguredName.OnValueRemoteUpdate(func(str string) { + fmt.Printf(" %s configured name => %s\n", name, str) + storage.Set(key, []byte(str)) + }) + in.InputSourceType.OnValueRemoteUpdate(func(v int) { + fmt.Printf(" %s source type => %v\n", name, v) + }) + in.IsConfigured.OnValueRemoteUpdate(func(v int) { + fmt.Printf(" %s configured => %v\n", name, v) + }) + in.CurrentVisibilityState.OnValueRemoteUpdate(func(v int) { + fmt.Printf(" %s current visibility => %v\n", name, v) + }) + in.Identifier.OnValueRemoteUpdate(func(v int) { + fmt.Printf(" %s identifier => %v\n", name, v) + }) + in.InputDeviceType.OnValueRemoteUpdate(func(v int) { + fmt.Printf(" %s device type => %v\n", name, v) + }) + in.TargetVisibilityState.OnValueRemoteUpdate(func(v int) { + fmt.Printf(" %s target visibility => %v\n", name, v) + }) + in.Name.OnValueRemoteUpdate(func(str string) { + fmt.Printf(" %s name => %s\n", name, str) + }) +} + +// TODO +// - Refactoring how to store characteristic values +func main() { + log.Debug.Enable() + + info := accessory.Info{ + Name: "Television", + } + acc := accessory.NewTelevision(info) + + acc.Television.Active.SetValue(characteristic.ActiveActive) + acc.Television.SleepDiscoveryMode.SetValue(characteristic.SleepDiscoveryModeAlwaysDiscoverable) + acc.Television.ActiveIdentifier.SetValue(1) + acc.Television.CurrentMediaState.SetValue(characteristic.CurrentMediaStatePause) + acc.Television.TargetMediaState.SetValue(characteristic.TargetMediaStatePause) + + acc.Television.Active.OnValueRemoteUpdate(func(v int) { + fmt.Printf("active => %d\n", v) + }) + + acc.Television.ActiveIdentifier.OnValueRemoteUpdate(func(v int) { + fmt.Printf("active identifier => %d\n", v) + }) + + acc.Television.ConfiguredName.OnValueRemoteUpdate(func(v string) { + fmt.Printf("configured name => %s\n", v) + }) + acc.Television.SleepDiscoveryMode.OnValueRemoteUpdate(func(v int) { + fmt.Printf("sleep discovery mode => %d\n", v) + }) + acc.Television.Brightness.OnValueRemoteUpdate(func(v int) { + fmt.Printf("brightness => %d\n", v) + }) + acc.Television.ClosedCaptions.OnValueRemoteUpdate(func(v int) { + fmt.Printf("closed captions => %d\n", v) + }) + acc.Television.DisplayOrder.OnValueRemoteUpdate(func(v []byte) { + fmt.Printf("display order => %v\n", v) + }) + acc.Television.CurrentMediaState.OnValueRemoteUpdate(func(v int) { + fmt.Printf("current media state => %d\n", v) + }) + acc.Television.TargetMediaState.OnValueRemoteUpdate(func(v int) { + fmt.Printf("target media state => %d\n", v) + }) + + acc.Television.PowerModeSelection.OnValueRemoteUpdate(func(v int) { + fmt.Printf("power mode selection => %d\n", v) + }) + + acc.Television.PictureMode.OnValueRemoteUpdate(func(v int) { + fmt.Printf("PictureMode => %d\n", v) + }) + + acc.Television.RemoteKey.OnValueRemoteUpdate(func(v int) { + switch v { + case characteristic.RemoteKeyRewind: + fmt.Println("Rewind") + case characteristic.RemoteKeyFastForward: + fmt.Println("Fast forward") + case characteristic.RemoteKeyExit: + fmt.Println("Exit") + case characteristic.RemoteKeyPlayPause: + fmt.Println("Play/Pause") + case characteristic.RemoteKeyInfo: + fmt.Println("Info") + case characteristic.RemoteKeyNextTrack: + fmt.Println("Next") + case characteristic.RemoteKeyPrevTrack: + fmt.Println("Prev") + case characteristic.RemoteKeyArrowUp: + fmt.Println("Up") + case characteristic.RemoteKeyArrowDown: + fmt.Println("Down") + case characteristic.RemoteKeyArrowLeft: + fmt.Println("Left") + case characteristic.RemoteKeyArrowRight: + fmt.Println("Right") + case characteristic.RemoteKeySelect: + fmt.Println("Select") + case characteristic.RemoteKeyBack: + fmt.Println("Back") + } + }) + + config := hc.Config{Pin: "12344321", StoragePath: "./db"} + t, err := hc.NewIPTransport(config, acc.Accessory) + + addInputSource(acc, 1, "HDMI 1", characteristic.InputSourceTypeHdmi, t.Storage()) + addInputSource(acc, 2, "HDMI 2", characteristic.InputSourceTypeHdmi, t.Storage()) + addInputSource(acc, 3, "Netflix", characteristic.InputSourceTypeApplication, t.Storage()) + addInputSource(acc, 4, "YouTube", characteristic.InputSourceTypeApplication, t.Storage()) + addInputSource(acc, 5, "Twitter", characteristic.InputSourceTypeApplication, t.Storage()) + + if err != nil { + log.Info.Panic(err) + } + + hc.OnTermination(func() { + <-t.Stop() + }) + + t.Start() +} From 78ee8bb5db1603df1c078a7e0c51e016598306f4 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Wed, 13 Feb 2019 13:08:06 +0100 Subject: [PATCH 11/24] Add hidden permission --- characteristic/constants.go | 1 + 1 file changed, 1 insertion(+) diff --git a/characteristic/constants.go b/characteristic/constants.go index 4657d7ac..a59e3d26 100644 --- a/characteristic/constants.go +++ b/characteristic/constants.go @@ -4,6 +4,7 @@ const ( PermRead = "pr" // can be read PermWrite = "pw" // can be written PermEvents = "ev" // sends events + PermHidden = "hd" // is hidden ) // PermsAll returns read, write and event permissions From eda337a3145082c5f05604b87616857f88b26a20 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Mon, 25 Mar 2019 12:34:37 +0100 Subject: [PATCH 12/24] Remove reference to storage --- _example/tv/main.go | 27 +++++++++++++-------------- ip_transport.go | 4 ---- transport.go | 6 ------ 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/_example/tv/main.go b/_example/tv/main.go index d3efa9b6..9e7695a5 100644 --- a/_example/tv/main.go +++ b/_example/tv/main.go @@ -2,15 +2,15 @@ package main import ( "fmt" + "github.com/brutella/hc" "github.com/brutella/hc/accessory" "github.com/brutella/hc/characteristic" "github.com/brutella/hc/log" "github.com/brutella/hc/service" - "github.com/brutella/hc/util" ) -func addInputSource(t *accessory.Television, id int, name string, inputSourceType int, storage util.Storage) { +func addInputSource(t *accessory.Television, id int, name string, inputSourceType int) { in := service.NewInputSource() in.Identifier.SetValue(id) @@ -22,15 +22,8 @@ func addInputSource(t *accessory.Television, id int, name string, inputSourceTyp t.AddService(in.Service) t.Television.AddLinkedService(in.Service) - key := fmt.Sprintf("input-%d", id) - if b, err := storage.Get(key); err == nil && len(b) > 0 { - fmt.Println("restore configured name", string(b)) - in.ConfiguredName.SetValue(string(b)) - } - in.ConfiguredName.OnValueRemoteUpdate(func(str string) { fmt.Printf(" %s configured name => %s\n", name, str) - storage.Set(key, []byte(str)) }) in.InputSourceType.OnValueRemoteUpdate(func(v int) { fmt.Printf(" %s source type => %v\n", name, v) @@ -143,11 +136,17 @@ func main() { config := hc.Config{Pin: "12344321", StoragePath: "./db"} t, err := hc.NewIPTransport(config, acc.Accessory) - addInputSource(acc, 1, "HDMI 1", characteristic.InputSourceTypeHdmi, t.Storage()) - addInputSource(acc, 2, "HDMI 2", characteristic.InputSourceTypeHdmi, t.Storage()) - addInputSource(acc, 3, "Netflix", characteristic.InputSourceTypeApplication, t.Storage()) - addInputSource(acc, 4, "YouTube", characteristic.InputSourceTypeApplication, t.Storage()) - addInputSource(acc, 5, "Twitter", characteristic.InputSourceTypeApplication, t.Storage()) + addInputSource(acc, 1, "HDMI 1", characteristic.InputSourceTypeHdmi) + addInputSource(acc, 2, "HDMI 2", characteristic.InputSourceTypeHdmi) + addInputSource(acc, 3, "Netflix", characteristic.InputSourceTypeApplication) + addInputSource(acc, 4, "YouTube", characteristic.InputSourceTypeApplication) + addInputSource(acc, 5, "Twitter", characteristic.InputSourceTypeApplication) + addInputSource(acc, 6, "Composite Video", characteristic.InputSourceTypeCompositeVideo) + addInputSource(acc, 7, "S-Video", characteristic.InputSourceTypeSVideo) + addInputSource(acc, 8, "Component Video", characteristic.InputSourceTypeComponentVideo) + addInputSource(acc, 9, "Dvi", characteristic.InputSourceTypeDvi) + addInputSource(acc, 10, "Airplay", characteristic.InputSourceTypeAirplay) + addInputSource(acc, 11, "Usb", characteristic.InputSourceTypeUsb) if err != nil { log.Info.Panic(err) diff --git a/ip_transport.go b/ip_transport.go index fc0682e6..b625db80 100644 --- a/ip_transport.go +++ b/ip_transport.go @@ -280,10 +280,6 @@ func (t *ipTransport) Handle(ev interface{}) { } } -func (t *ipTransport) Storage() util.Storage { - return t.storage -} - func newService(config *Config) dnssd.Service { // 2016-03-14(brutella): Replace whitespaces (" ") from service name // with underscores ("_")to fix invalid http host header field value diff --git a/transport.go b/transport.go index 61f8102c..f55265a3 100644 --- a/transport.go +++ b/transport.go @@ -1,9 +1,5 @@ package hc -import ( - "github.com/brutella/hc/util" -) - // Transport provides accessories over a network. type Transport interface { // Start starts the transport @@ -12,6 +8,4 @@ type Transport interface { // Stop stops the transport // Use the returned channel to wait until the transport is fully stopped. Stop() <-chan struct{} - - Storage() util.Storage } From 4bbecaf777dee975a2dbecb89f02ff1e34b552a1 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 10:52:15 +0100 Subject: [PATCH 13/24] Move _example/example.go to _example/example/main.go --- _example/{example.go => example/main.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _example/{example.go => example/main.go} (100%) diff --git a/_example/example.go b/_example/example/main.go similarity index 100% rename from _example/example.go rename to _example/example/main.go From cfb789fb8df7b279e5c884d71c9b33300fa1b5c7 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 10:59:21 +0100 Subject: [PATCH 14/24] Fix typo --- accessory/television.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accessory/television.go b/accessory/television.go index 017a8b28..3c153720 100644 --- a/accessory/television.go +++ b/accessory/television.go @@ -10,7 +10,7 @@ type Television struct { Speaker *service.Speaker } -// NewOutlet returns an outlet accessory containing one outlet service. +// NewTelevision returns a television accessory. func NewTelevision(info Info) *Television { acc := Television{} acc.Accessory = New(info, TypeTelevision) From f7fa0243192eb6e6e80f5995dba7e6844af8b965 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 11:12:32 +0100 Subject: [PATCH 15/24] Prepare readme for release of v1.0.0 --- README.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 98781bee..c6b367f3 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ I've developed the [Home][home] app (for iPhone, iPad, Apple Watch) to control H Once you've setup HomeKit, you can use Siri to interact with your accessories using voice command (*Hey Siri, turn off the lights in the living room*). -[home]: http://hochgatterer.me/home/ +[home]: https://hochgatterer.me/home/ [home-appstore]: http://itunes.apple.com/app/id995994352 ## Features @@ -40,7 +40,7 @@ Once you've setup HomeKit, you can use Siri to interact with your accessories us git clone https://github.com/brutella/hklight && cd hklight # Run the project - go run hklightd.go + make run 4. Pair with your HomeKit App of choice (e.g. [Home][home-appstore]) @@ -61,10 +61,10 @@ func main() { info := accessory.Info{ Name: "Lamp", } - acc := accessory.NewSwitch(info) + ac := accessory.NewSwitch(info) config := hc.Config{Pin: "00102003"} - t, err := hc.NewIPTransport(config, acc.Accessory) + t, err := hc.NewIPTransport(config, ac.Accessory) if err != nil { log.Panic(err) } @@ -94,7 +94,7 @@ info := accessory.Info{ You get a callback when the power state of a switch changed by a client. ```go -acc.Switch.On.OnValueRemoteUpdate(func(on bool) { +ac.Switch.On.OnValueRemoteUpdate(func(on bool) { if on == true { log.Println("Client changed switch to on") } else { @@ -105,7 +105,9 @@ acc.Switch.On.OnValueRemoteUpdate(func(on bool) { When the switch is turned on "the analog way", you should set the state of the accessory. - acc.Switch.On.SetValue(true) +```go +ac.Switch.On.SetValue(true) +``` A complete example is available in `_example/example.go`. @@ -126,20 +128,16 @@ The HomeKit model hierarchy looks like this: HomeKit accessories are container for services. Every accessory must provide the `Accessory Information Service`. Every service provides one or more characteristics (a characteristic might be the power state of an outlet). HomeKit has predefined service and characteristic types, which are supported by iOS. You can define your own service and characteristic types, but it's recommended to use predefined ones. -## Dependencies - -HomeControl uses vendor directories (`vendor/`) to integrate the following libraries +## Go Module -- `github.com/tadglines/go-pkgs/crypto/srp` for *SRP* algorithm -- `github.com/agl/ed25519` for *ed25519* signature -- `github.com/gosexy/to` for type conversion -- `github.com/brutella/dnssd` for DNS service discovery +`hc` can be integrated as [Go module](https://github.com/golang/go/wiki/Modules) since `v1.0.0`. +Make sure to set the environment variable `GO111MODULE=on`. # Contact Matthias Hochgatterer -Website: [http://hochgatterer.me](http://hochgatterer.me) +Website: [http://hochgatterer.me](https://hochgatterer.me) Github: [https://github.com/brutella](https://github.com/brutella/) From b061b2e2a2fcc9a86b6c1dc448efb462455a8c15 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 11:19:13 +0100 Subject: [PATCH 16/24] Define optional characteristics for input source and tv service --- characteristic/identifier.go | 1 + gen/metadata.json | 25 +++++++++++++------------ service/README.md | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/characteristic/identifier.go b/characteristic/identifier.go index e51a8b5c..19a6b10e 100644 --- a/characteristic/identifier.go +++ b/characteristic/identifier.go @@ -12,6 +12,7 @@ func NewIdentifier() *Identifier { char.Format = FormatUInt32 char.Perms = []string{PermRead} char.SetMinValue(0) + char.SetStepValue(1) char.SetValue(0) diff --git a/gen/metadata.json b/gen/metadata.json index c3510645..f1f237df 100644 --- a/gen/metadata.json +++ b/gen/metadata.json @@ -3285,12 +3285,6 @@ }, { "OptionalCharacteristics": [ - ], - "RequiredCharacteristics": [ - "000000B0-0000-1000-8000-0026BB765291", - "000000E7-0000-1000-8000-0026BB765291", - "000000E3-0000-1000-8000-0026BB765291", - "000000E8-0000-1000-8000-0026BB765291", "00000008-0000-1000-8000-0026BB765291", "000000DD-0000-1000-8000-0026BB765291", "00000136-0000-1000-8000-0026BB765291", @@ -3300,21 +3294,28 @@ "000000DF-0000-1000-8000-0026BB765291", "000000E1-0000-1000-8000-0026BB765291" ], + "RequiredCharacteristics": [ + "000000B0-0000-1000-8000-0026BB765291", + "000000E7-0000-1000-8000-0026BB765291", + "000000E3-0000-1000-8000-0026BB765291", + "000000E8-0000-1000-8000-0026BB765291" + ], "Name": "Television", "UUID": "000000D8-0000-1000-8000-0026BB765291" }, { - "OptionalCharacteristics": [], - "RequiredCharacteristics": [ - "000000E3-0000-1000-8000-0026BB765291", - "000000DB-0000-1000-8000-0026BB765291", - "000000D6-0000-1000-8000-0026BB765291", - "00000135-0000-1000-8000-0026BB765291", + "OptionalCharacteristics": [ "000000E6-0000-1000-8000-0026BB765291", "000000DC-0000-1000-8000-0026BB765291", "00000134-0000-1000-8000-0026BB765291", "00000023-0000-1000-8000-0026BB765291" ], + "RequiredCharacteristics": [ + "000000E3-0000-1000-8000-0026BB765291", + "000000DB-0000-1000-8000-0026BB765291", + "000000D6-0000-1000-8000-0026BB765291", + "00000135-0000-1000-8000-0026BB765291" + ], "Name": "Input Source", "UUID": "000000D9-0000-1000-8000-0026BB765291" } diff --git a/service/README.md b/service/README.md index 52b4695f..436ea3c7 100644 --- a/service/README.md +++ b/service/README.md @@ -40,5 +40,5 @@ | Valve | Active
In Use
Valve Type
Set Duration Optional
Remaining Duration Optional
Is Configured Optional
Service Label Index Optional
Status Fault Optional
Name Optional | D0 | | Window | Current Position
Target Position
Position State
Hold Position Optional
Obstruction Detected Optional
Name Optional | 8B | | Window Covering | Current Position
Target Position
Position State
Hold Position Optional
Target Horizontal Tilt Angle Optional
Target Vertical Tilt Angle Optional
Current Horizontal Tilt Angle Optional
Current Vertical Tilt Angle Optional
Obstruction Detected Optional
Name Optional | 8C | -| Television | Active
Active Identifier
Configured Name
Sleep Discovery Mode
Brightness
Closed Captions
Display Order
Current Media State
Target Media State
Picture Mode
Power Mode Selection
Remote Key | D8 | -| Input Source | Configured Name
Input Source Type
Is Configured
Current Visibility State
Identifier
Input Device Type
Target Visibility State
Name | D9 | +| Television | Active
Active Identifier
Configured Name
Sleep Discovery Mode
Brightness Optional
Closed Captions Optional
Display Order Optional
Current Media State Optional
Target Media State Optional
Picture Mode Optional
Power Mode Selection Optional
Remote Key Optional | D8 | +| Input Source | Configured Name
Input Source Type
Is Configured
Current Visibility State
Identifier Optional
Input Device Type Optional
Target Visibility State Optional
Name Optional | D9 | From 29c5b3e8fc1ce13819f4d6af68a2bf7e39bb85bd Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 12:04:40 +0100 Subject: [PATCH 17/24] Update readme --- README.md | 85 +++++++++++++++++++++++++-------------------- _img/home-icon.png | Bin 0 -> 11187 bytes 2 files changed, 48 insertions(+), 37 deletions(-) create mode 100644 _img/home-icon.png diff --git a/README.md b/README.md index c6b367f3..87c526ae 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,33 @@ [![Build Status](https://travis-ci.org/brutella/hc.svg)](https://travis-ci.org/brutella/hc) -HomeControl is an implementation of the [HomeKit][homekit] Accessory Protocol (HAP) to create your own HomeKit accessory in [Go](https://golang.org). [HomeKit][homekit] is a set of protocols and libraries to access devices for Home Automation. ~~The actual protocol documentation is only available to MFi members.~~ A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/). +`hc` is a lightweight framework to develop HomeKit accessories in Go. +It abstracts the **H**omeKit **A**ccessory **P**rotocol and makes it easy to work with [services](service/README.md) and [characteristics](characteristic/README.md). -You can use this library to make existing Home Automation devices HomeKit compatible. I've already developed the following HomeKit bridges with in: +`hc` handles the underlying communication between HomeKit accessories and clients. +You can focus on implementing the business logic for your accessory, without having to worry about the underlying protocol. + +I've already developed the following HomeKit bridges with in: - [LIFX](https://github.com/brutella/hklifx/) - [UVR1611](https://github.com/brutella/hkuvr) - [Fronius Symo](https://github.com/brutella/hksymo) -## HomeKit on iOS +**What is HomeKit?** + +[HomeKit][homekit] is a set of protocols and libraries to communicate with smart home appliances. ~~The actual protocol documentation is only available to MFi members.~~ A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/). + +**iOS** + -HomeKit is fully integrated since iOS 8. Developers can use the HomeKit framework to communicate with HomeKit using high-level APIs. -I've developed the [Home][home] app (for iPhone, iPad, Apple Watch) to control HomeKit accessories. If you [purchase Home][home-appstore] on the App Store, you not only support my work but also get an awesome iOS app. Thank you. +HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs. -Once you've setup HomeKit, you can use Siri to interact with your accessories using voice command (*Hey Siri, turn off the lights in the living room*). +[[https://github.com/brutella/hc/blob/master/_img/home-icon.png|alt=Home.app]] + +I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch. +If you would like to support `hc`, please purchase Home from the [App Store](home-appstore). That would be awesome. ❤️ + +Once you've setup HomeKit on iOS, you can use Siri to interact with your accessories using voice command (*Hey Siri, turn off the lights in the living room*). [home]: https://hochgatterer.me/home/ [home-appstore]: http://itunes.apple.com/app/id995994352 @@ -25,14 +38,13 @@ Once you've setup HomeKit, you can use Siri to interact with your accessories us - Full implementation of the HAP in Go - Supports all HomeKit [services and characteristics](service/README.md) - Built-in service announcement via DNS-SD using [dnssd](http://github.com/brutella/dnssd) -- Runs on multiple platforms (already in use on Linux and OS X) +- Runs on linux and macOS - Documentation: http://godoc.org/github.com/brutella/hc ## Getting Started -1. [Install Go](http://golang.org/doc/install) -2. [Setup Go workspace](http://golang.org/doc/code.html#Organization) -3. Create your own HomeKit bridge or clone an existing one (e.g. [hklight](https://github.com/brutella/hklight)) +1. [Install](http://golang.org/doc/install) and [set up](http://golang.org/doc/code.html#Organization) Go +2. Create your own HomeKit accessory or clone an existing one (e.g. [hklight](https://github.com/brutella/hklight)) cd $GOPATH/src @@ -42,9 +54,18 @@ Once you've setup HomeKit, you can use Siri to interact with your accessories us # Run the project make run -4. Pair with your HomeKit App of choice (e.g. [Home][home-appstore]) +3. Pair with your HomeKit App of choice (e.g. [Home][home-appstore]) + +**Go Modules** + +`hc` supports [Go module](https://github.com/golang/go/wiki/Modules) since `v1.0.0`. +Make sure to set the environment variable `GO111MODULE=on`. + +## Example -## API Example +See [_example](_example) for a variety of examples. + +**Basic switch accessory** Create a simple on/off switch, which is accessible via IP and secured using the pin *00102003*. @@ -58,11 +79,11 @@ import ( ) func main() { - info := accessory.Info{ - Name: "Lamp", - } + // create an accessory + info := accessory.Info{Name: "Lamp"} ac := accessory.NewSwitch(info) + // configure the ip transport config := hc.Config{Pin: "00102003"} t, err := hc.NewIPTransport(config, ac.Accessory) if err != nil { @@ -89,9 +110,10 @@ info := accessory.Info{ } ``` -### Callbacks +### Events -You get a callback when the power state of a switch changed by a client. +When a connected client changes the value of characteristics, you get a callback. +The following example shows how to get notified when the [On](characteristic/on.go) characteristic value changes. ```go ac.Switch.On.OnValueRemoteUpdate(func(on bool) { @@ -109,29 +131,18 @@ When the switch is turned on "the analog way", you should set the state of the a ac.Switch.On.SetValue(true) ``` -A complete example is available in `_example/example.go`. +## Accessory Architecture -## Model +HomeKit uses a hierarchical architecture for define accessories, services and characeristics. +At the root level there is an accessory. +Every accessory contains services. +And every service contains characteristics. -The HomeKit model hierarchy looks like this: +For example a [lightbulb accessory](accessory/lightbulb.go) contains a [lightbulb service](service/lightbulb.go). +This service contains characteristics like [on](characteristic/on.go) and [brightness](characteristic/brightness.go). - Accessory - |-- Accessory Info Service - | |-- Identify Characteristic - | |-- Manufacturer Characteristic - | |-- Model Characteristic - | |-- Name Characteristic - | |-- Serial Characteristic - | - |-- * Service - | |-- * Characteristic - -HomeKit accessories are container for services. Every accessory must provide the `Accessory Information Service`. Every service provides one or more characteristics (a characteristic might be the power state of an outlet). HomeKit has predefined service and characteristic types, which are supported by iOS. You can define your own service and characteristic types, but it's recommended to use predefined ones. - -## Go Module - -`hc` can be integrated as [Go module](https://github.com/golang/go/wiki/Modules) since `v1.0.0`. -Make sure to set the environment variable `GO111MODULE=on`. +There are predefined accessories, services and characteristics available in HomeKit. +Those types are defined in the packages [accessory](accessory), [service](service), [characteristic](characteristic). # Contact diff --git a/_img/home-icon.png b/_img/home-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..747e000c564b91190633433d4cefce725dfd62d0 GIT binary patch literal 11187 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 Date: Tue, 26 Mar 2019 12:05:39 +0100 Subject: [PATCH 18/24] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 87c526ae..eb5f5882 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ I've already developed the following HomeKit bridges with in: HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs. -[[https://github.com/brutella/hc/blob/master/_img/home-icon.png|alt=Home.app]] +![Home.app][https://github.com/brutella/hc/blob/master/_img/home-icon.png] I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch. If you would like to support `hc`, please purchase Home from the [App Store](home-appstore). That would be awesome. ❤️ From 2fb25dc61298294ada2e410460b123fd7788cfa7 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 12:06:26 +0100 Subject: [PATCH 19/24] Change reference to image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb5f5882..5e559387 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ I've already developed the following HomeKit bridges with in: HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs. -![Home.app][https://github.com/brutella/hc/blob/master/_img/home-icon.png] +![Home.app][https://github.com/brutella/hc/blob/tv/_img/home-icon.png] I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch. If you would like to support `hc`, please purchase Home from the [App Store](home-appstore). That would be awesome. ❤️ From 221ffe7d31b197cc8212f973207577a7f927e588 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 12:07:35 +0100 Subject: [PATCH 20/24] Update reference to image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e559387..77002ea1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ I've already developed the following HomeKit bridges with in: HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs. -![Home.app][https://github.com/brutella/hc/blob/tv/_img/home-icon.png] +![Home.app](_img/home-icon.png?raw=true "Home.app") I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch. If you would like to support `hc`, please purchase Home from the [App Store](home-appstore). That would be awesome. ❤️ From 00a16ead6dba645c9f8248be65381b3c4e1a554e Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 12:15:49 +0100 Subject: [PATCH 21/24] Update readme --- README.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 77002ea1..a4ee1806 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# HomeControl +# hc [![Build Status](https://travis-ci.org/brutella/hc.svg)](https://travis-ci.org/brutella/hc) `hc` is a lightweight framework to develop HomeKit accessories in Go. -It abstracts the **H**omeKit **A**ccessory **P**rotocol and makes it easy to work with [services](service/README.md) and [characteristics](characteristic/README.md). +It abstracts the **H**omeKit **A**ccessory **P**rotocol (HAP) and makes it easy to work with [services](service/README.md) and [characteristics](characteristic/README.md). `hc` handles the underlying communication between HomeKit accessories and clients. -You can focus on implementing the business logic for your accessory, without having to worry about the underlying protocol. +You can focus on implementing the business logic for your accessory, without having to worry about the protocol. -I've already developed the following HomeKit bridges with in: +Here are some projects which use `hc`. - [LIFX](https://github.com/brutella/hklifx/) - [UVR1611](https://github.com/brutella/hkuvr) @@ -16,17 +16,17 @@ I've already developed the following HomeKit bridges with in: **What is HomeKit?** -[HomeKit][homekit] is a set of protocols and libraries to communicate with smart home appliances. ~~The actual protocol documentation is only available to MFi members.~~ A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/). +[HomeKit][homekit] is a set of protocols and libraries to communicate with smart home appliances. A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/). **iOS** HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs. -![Home.app](_img/home-icon.png?raw=true "Home.app") +Home.app I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch. -If you would like to support `hc`, please purchase Home from the [App Store](home-appstore). That would be awesome. ❤️ +If you would like to support `hc`, please purchase Home from the [App Store][home-appstore]. That would be awesome. ❤️ Once you've setup HomeKit on iOS, you can use Siri to interact with your accessories using voice command (*Hey Siri, turn off the lights in the living room*). @@ -80,48 +80,48 @@ import ( func main() { // create an accessory - info := accessory.Info{Name: "Lamp"} - ac := accessory.NewSwitch(info) + info := accessory.Info{Name: "Lamp"} + ac := accessory.NewSwitch(info) // configure the ip transport config := hc.Config{Pin: "00102003"} - t, err := hc.NewIPTransport(config, ac.Accessory) - if err != nil { - log.Panic(err) - } + t, err := hc.NewIPTransport(config, ac.Accessory) + if err != nil { + log.Panic(err) + } hc.OnTermination(func(){ <-t.Stop() }) - t.Start() + t.Start() } ``` -You should change some default values for your own needs +You can define more specific accessory info, if you want. ```go info := accessory.Info{ - Name: "Lamp", - SerialNumber: "051AC-23AAM1", - Manufacturer: "Apple", - Model: "AB", - Firmware: "1.0.1", + Name: "Lamp", + SerialNumber: "051AC-23AAM1", + Manufacturer: "Apple", + Model: "AB", + Firmware: "1.0.1", } ``` ### Events -When a connected client changes the value of characteristics, you get a callback. +The library provides callback functions, which let you know when a clients updates a characteristic value. The following example shows how to get notified when the [On](characteristic/on.go) characteristic value changes. ```go ac.Switch.On.OnValueRemoteUpdate(func(on bool) { - if on == true { - log.Println("Client changed switch to on") - } else { - log.Println("Client changed switch to off") - } + if on == true { + log.Println("Switch is on") + } else { + log.Println("Switch is off") + } }) ``` @@ -148,7 +148,7 @@ Those types are defined in the packages [accessory](accessory), [service](servic Matthias Hochgatterer -Website: [http://hochgatterer.me](https://hochgatterer.me) +Website: [https://hochgatterer.me](https://hochgatterer.me) Github: [https://github.com/brutella](https://github.com/brutella/) From 49e7f1139d9ac2699ed3356ed6418625a303a74b Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 12:32:47 +0100 Subject: [PATCH 22/24] Update readme --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index a4ee1806..2f666da9 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,7 @@ Here are some projects which use `hc`. **What is HomeKit?** -[HomeKit][homekit] is a set of protocols and libraries to communicate with smart home appliances. A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/). - -**iOS** - +[HomeKit][homekit] is a set of protocols and libraries from Apple. It is used by Apple's platforms to communicate with smart home appliances. A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/). HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs. From 18b0e1c270fafadcb298ab5c83994e5ab1108dfb Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 12:35:35 +0100 Subject: [PATCH 23/24] Update readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f666da9..4a7db41f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # hc -[![Build Status](https://travis-ci.org/brutella/hc.svg)](https://travis-ci.org/brutella/hc) +[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis] `hc` is a lightweight framework to develop HomeKit accessories in Go. It abstracts the **H**omeKit **A**ccessory **P**rotocol (HAP) and makes it easy to work with [services](service/README.md) and [characteristics](characteristic/README.md). @@ -29,6 +29,10 @@ Once you've setup HomeKit on iOS, you can use Siri to interact with your accesso [home]: https://hochgatterer.me/home/ [home-appstore]: http://itunes.apple.com/app/id995994352 +[GoDoc]: https://godoc.org/github.com/brutella/hc +[GoDoc Widget]: https://godoc.org/github.com/brutella/hc?status.svg +[Travis]: https://travis-ci.org/brutella/hc +[Travis Widget]: https://travis-ci.org/brutella/hc.svg ## Features From e7eba1010d5134e5f0c23dd2ace4703b29827de4 Mon Sep 17 00:00:00 2001 From: Matthias Hochgatterer Date: Tue, 26 Mar 2019 13:19:33 +0100 Subject: [PATCH 24/24] Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a7db41f..f63e3a93 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.fr Home.app I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch. -If you would like to support `hc`, please purchase Home from the [App Store][home-appstore]. That would be awesome. ❤️ +If you want to support `hc`, please purchase Home from the [App Store][home-appstore]. That would be awesome. ❤️ -Once you've setup HomeKit on iOS, you can use Siri to interact with your accessories using voice command (*Hey Siri, turn off the lights in the living room*). +Checkout the official [website][home]. [home]: https://hochgatterer.me/home/ [home-appstore]: http://itunes.apple.com/app/id995994352