refreshCapabilities()/refreshCapability)
These methods may be called when you detect a change in the Reactor configuration or mapping implementations. It is up to your Controller class to determine how to do that. When a change is detected (more on that at the end of this post), calling refreshCapabilities()
will re-apply the capabilities already extended to the target Entity and sync the attribute dictionary. Entities maintain local copies of capability definitions because an entity can tweak a capability to reflect it's actual abilities/data.
Let's say for example that I add an attribute called ramp_rate
to the system dimming
capability. None of the entities that have this capability already assigned would automatically inherit ramp_rate
when you upgrade Reactor. To get it, you'd have to use one of the refresh...()
methods.
Action Responses
Returning a response from an action implementation is as straightforward as resolve()
-ing the Promise that an action implementation is required to return with an argument containing the data for the response. If you are defining the action for a capability of yours, you add response: true
to the action definition for the capability, so that the UI presents the field to allow the user to specify where the response should be stored.
Detecting Changes -- When to Call refresh...()
Many of the built-in Controller classes use extensive implementation maps to convert data from the related hub/source into attributes, and to provide implementations for actions. These Controllers have large and complex xxx_capabilities
and xxx_devices
files containing this data. When the Controller class is loaded, these data files are read, and later the individual Controller instances then use the loaded data.
From time to time, device support will change for one of these Controllers, so the map files change to reflect that. This is usually accompanied by a change in the version
and revision
values in the file headers. Reactor's system-wide capabilities are defined in a similar way, and have similar version
and revision
values.
The built-in Controllers look at these version and revision numbers and compare them to stored data in an entity instance. If they are not identical, the Controller will call refreshCapabilities()
on the entity.
In some cases, like MQTTController, where configuration/implementation of an entity is derived from multiple templates in user configuration rather than system files, handling/requiring a version
and revision
for each template would add complexity for the user and be really tedious to deal with, so a slightly different approach is used. After all the include
s are processed by the referenced templates and a full template has been assembled for the entity, it is hashed using util.hash()
. The first time an entity is configured (detected by a hash value not being present on the entity), the hash value is stored on the entity. Thereafter, the new hash derived at Controller startup is compared to the hash stored on the entity, and if they differ, the entity is refreshed and the new hash stored on the entity. In this way, the hash on the entity always reflects the latest configuration/templates, and if they change, that is quickly detected and the changes applied.