mirror of
https://github.com/nikdoof/hapz2m.git
synced 2026-01-30 11:38:22 +00:00
Introduce SetCharacteristicValueFunc to the Mapping
This function allows either replacing or modifying the usual Exposed->Characteristic value propagation. It also adds a CurrentValue to the mapping to monitor for changes/updates, regardless of whether the value was updated into the Characteristic. This will be the source of truth.
This commit is contained in:
31
bridge.go
31
bridge.go
@@ -697,9 +697,34 @@ func (br *Bridge) UpdateAccessoryState(devName string, payload []byte) {
|
|||||||
if BRIDGE_DEVMODE {
|
if BRIDGE_DEVMODE {
|
||||||
log.Printf("updating %q to %+v", prop, newVal)
|
log.Printf("updating %q to %+v", prop, newVal)
|
||||||
}
|
}
|
||||||
_, errCode := mapping.SetCharacteristicValue(newVal)
|
|
||||||
if errCode != 0 {
|
// convert to Characteristic value to determine if it has changed
|
||||||
log.Printf("unable to update characteristic value for %q: %d", prop, errCode)
|
// since we don't know what the Exposed -> Characteristic mapping would be
|
||||||
|
newCv, err := mapping.ToCharacteristicValue(newVal)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("unable to convert characteristic value for %q: %v", prop, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
oldCv := mapping.SetCurrentValue(newCv)
|
||||||
|
changed := oldCv != newCv
|
||||||
|
|
||||||
|
// call the Set func if defined
|
||||||
|
doDefault := true
|
||||||
|
setFunc := mapping.SetCharacteristicValueFunc
|
||||||
|
if setFunc != nil {
|
||||||
|
doDefault, err = setFunc(mapping, newCv, changed)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("SetCharacteristicValueFunc for %s error: %+v", mapping, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if doDefault {
|
||||||
|
_, errCode := mapping.Characteristic.SetValueRequest(newCv, nil)
|
||||||
|
if errCode != 0 {
|
||||||
|
log.Printf("unable to update characteristic value for %q: %d", prop, errCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
z2m.go
42
z2m.go
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -228,6 +229,9 @@ func uniq[T comparable](items []T) []T {
|
|||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
|
// sentinel nil value for atomic.Value
|
||||||
|
var nilValue = &struct{}{}
|
||||||
|
|
||||||
// Maps a zigbee2mqtt device property into a HAP characteristic.
|
// Maps a zigbee2mqtt device property into a HAP characteristic.
|
||||||
// Contains convenience methods to translate values between the two systems.
|
// Contains convenience methods to translate values between the two systems.
|
||||||
// z2m "binary" types are inherently translated to bool using the ValueOn/Off properties defined,
|
// z2m "binary" types are inherently translated to bool using the ValueOn/Off properties defined,
|
||||||
@@ -240,6 +244,15 @@ type ExposeMapping struct {
|
|||||||
Characteristic *characteristic.C
|
Characteristic *characteristic.C
|
||||||
|
|
||||||
Translator MappingTranslator
|
Translator MappingTranslator
|
||||||
|
|
||||||
|
// Hook function for setting Characteristic value.
|
||||||
|
// It returns a bool to allow/prevent the normal setting of Characteristic value.
|
||||||
|
// If an error is returned, the handler stops any further processing for this mapping.
|
||||||
|
SetCharacteristicValueFunc func(m *ExposeMapping, newVal any, changed bool) (doDefault bool, err error)
|
||||||
|
|
||||||
|
// keeps track of current value, regardless of whether it's been
|
||||||
|
// transferred to Characteristic or not
|
||||||
|
currentVal atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new ExposeMapping
|
// Creates a new ExposeMapping
|
||||||
@@ -262,6 +275,11 @@ func (m *ExposeMapping) ToExposedValue(v any) (any, error) {
|
|||||||
return m.Translator.ToExposedValue(v)
|
return m.Translator.ToExposedValue(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts an Exposed value to a Characteristic value
|
||||||
|
func (m *ExposeMapping) ToCharacteristicValue(v any) (any, error) {
|
||||||
|
return m.Translator.ToCharacteristicValue(v)
|
||||||
|
}
|
||||||
|
|
||||||
// Calls c.SetValueRequest() with the translated exposed value
|
// Calls c.SetValueRequest() with the translated exposed value
|
||||||
// if the error code is -1, there was a translation error.
|
// if the error code is -1, there was a translation error.
|
||||||
// Otherwise it's a HAP error code
|
// Otherwise it's a HAP error code
|
||||||
@@ -274,6 +292,30 @@ func (m *ExposeMapping) SetCharacteristicValue(v any) (any, int) {
|
|||||||
return m.Characteristic.SetValueRequest(cv, nil)
|
return m.Characteristic.SetValueRequest(cv, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the current value
|
||||||
|
func (m *ExposeMapping) CurrentValue() any {
|
||||||
|
v := m.currentVal.Load()
|
||||||
|
if v == nilValue {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the current value for this mapping.
|
||||||
|
// This value is persisted and used for detecting changes, regardless of
|
||||||
|
// whether it is propagated to the Characteristic
|
||||||
|
func (m *ExposeMapping) SetCurrentValue(v any) any {
|
||||||
|
if v == nil {
|
||||||
|
v = nilValue
|
||||||
|
}
|
||||||
|
|
||||||
|
old := m.currentVal.Swap(v)
|
||||||
|
if old == nilValue {
|
||||||
|
old = nil
|
||||||
|
}
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
// Function that creates services from a z2m Device, invoked by createAccessory()
|
// Function that creates services from a z2m Device, invoked by createAccessory()
|
||||||
|
|||||||
Reference in New Issue
Block a user