diff --git a/enumerate_device.go b/enumerate_device.go index b046191..43a78d5 100644 --- a/enumerate_device.go +++ b/enumerate_device.go @@ -319,7 +319,7 @@ func (e enumerateDevice) updateCapabilitiesOnDevice(ctx context.Context, d *devi if found && c.ImplName() != capImplName { found = false - if err := c.Detach(ctx); err != nil { + if err := c.Detach(ctx, implcaps.NoLongerEnumerated); err != nil { errs[cF].Errors = append(errs[cF].Errors, fmt.Errorf("failed to detach conflicting capabiltiy: %w", err)) } @@ -339,7 +339,7 @@ func (e enumerateDevice) updateCapabilitiesOnDevice(ctx context.Context, d *devi } if !attached { - if err := c.Detach(ctx); err != nil { + if err := c.Detach(ctx, implcaps.NoLongerEnumerated); err != nil { errs[cF].Errors = append(errs[cF].Errors, fmt.Errorf("failed to detach failed attach on capabiltiy: %s: %w", capImplName, err)) } delete(d.capabilities, cF) @@ -357,7 +357,7 @@ func (e enumerateDevice) updateCapabilitiesOnDevice(ctx context.Context, d *devi if !slices.Contains(activeCapabilities, k) { errs[k] = &capabilities.EnumerationCapability{Attached: false} - if err := v.Detach(ctx); err != nil { + if err := v.Detach(ctx, implcaps.NoLongerEnumerated); err != nil { errs[k].Errors = append(errs[k].Errors, fmt.Errorf("failed to detach redundant capabiltiy: %w", err)) } delete(d.capabilities, k) diff --git a/gateway.go b/gateway.go index 5e0d690..4ae4d3c 100644 --- a/gateway.go +++ b/gateway.go @@ -21,6 +21,10 @@ func New(baseCtx context.Context, p zigbee.Provider, r ruleExecutor) da.Gateway gw := &gateway{ provider: p, + selfDevice: gatewayDevice{ + dd: &deviceDiscovery{}, + }, + ctx: ctx, ctxCancel: cancel, diff --git a/implcaps/generic/product_information.go b/implcaps/generic/product_information.go index 89c791d..5c2c645 100644 --- a/implcaps/generic/product_information.go +++ b/implcaps/generic/product_information.go @@ -58,7 +58,7 @@ func (g *ProductInformation) Attach(_ context.Context, _ da.Device, _ implcaps.A return true, nil } -func (g *ProductInformation) Detach(_ context.Context) error { +func (g *ProductInformation) Detach(_ context.Context, _ implcaps.DetachType) error { return nil } diff --git a/implcaps/interface.go b/implcaps/interface.go index e57c7ea..fe52ca0 100644 --- a/implcaps/interface.go +++ b/implcaps/interface.go @@ -22,6 +22,20 @@ const ( Load ) +type DetachType int + +const ( + // Shutdown is used to Detach a capability during the shutdown phase of the ZDA, the network and device should + // be assumed to still existing their established state. + Shutdown DetachType = iota + // DeviceRemoved is used when a device has been removed from the Zigbee network, this has already occurred and it + // should be assumed that no communication is possible. + DeviceRemoved + // NoLongerEnumerated is used when the enumeration of the node no longer results in this capability existing, or + // it's being replaced by a different implementation. Tidy up via the network may be possible. + NoLongerEnumerated +) + type ZDACapability interface { // BasicCapability functions should also be present. da.BasicCapability @@ -33,7 +47,7 @@ type ZDACapability interface { Attach(context.Context, da.Device, AttachType, map[string]interface{}) (bool, error) // Detach is called when a capability is removed from a device. This will be called after an Attach that returned // false, even if it was a new enumeration. - Detach(context.Context) error + Detach(context.Context, DetachType) error // State returns a data structure that should be passed to Attach with AttachType.LOAD to reload the capability // from a persistent store. State() map[string]interface{}