Skip to content

Implementing a Capability

Peter Wood edited this page Sep 28, 2020 · 3 revisions

General

Capabilities are the basis of the Shimmering Bee ecosystem, they abstract the complexity of individual home automation protocols with a standardised interface. This means that the controller could have a mix of Zigbee, MQTT, Modbus, etc with no additional work.

Capabilities are defined in shimmeringbee/da, if you wish to implement a capability that is not present you are free to use capability IDs 0xfe00 to 0xfeff. These are considered local to your implementation, if you distribute them, you may wish to make this number configurable.

Capability implementations are welcome as pull requests, though may require work to standardise them into any common approaches inside ZDA.

Data

Capabilities must maintain their own data stores, that is, any state or calculated settings must be stored inside the capability. There is no ZDA wide storage system, there was at one point, but it has since been removed. Providing that an implemented Capbility subscribes to the RemovedDevice callback, it is safe to use a devices Identifier (IEEEAddressWithSubidentifier) for indexing any data store.

Locking vs Go-routine Message Loop / Actors

Handling state in Go can be a little tricky, there are multiple ways of managing it.

  • Assume that concurrent access to data will happen, and use sync.Mutex or sync.RWMutex to protect the data.
  • Use a go routine to manage the data, and communicate changes and fetches via messages - or start a go routine per device and handle messages.

Both have advantages and disadvantages. Commit 9dff422dcaf61b2595e296cab14e52e2a4b05acc shows an implementation using message based management of data, and while it is Go idiomatic, it is larger that it needs to be with mutexes. ZDA will tend to use mutexes over go routines.

Callbacks

Callbacks are used to inform the capability of changes or standard requests with regards to devices, ZDA assumes that the callback function will block until all actions required are completed, the capability must not return until all work is completed.

Unorganised Notes

  • Capabilities that will be merged into ZDA, should be implemented in a package under zda/capability/impl/ with the name of the capability in snake case.
  • Capabilities must support the CapabiltiyBasic interface defined in zda/capability.
  • Capabilities essentially must support InitableCapability interface defined in zda/capability, otherwise they will have no access to base ZDA features from the Supervisor interface.
  • Capabilities with data retrieved or cached from the zigbee network must implement PersistableCapability interface defined in zda/capability.
  • Capabilities that operate with an event loop (rather than relying on locking), should implement the ProcessingCapability interface to be informed of start and stop events.
  • Capabilities are likely to take a da.Device from a consumer of the capability, however internally they must rely on capability.Device.
  • Capabilities that need to know of adding and removing of events should register their interest via the EventSubscription interface.