Help with registerCapabilityListener

Hi,

Is there a better example than the SDK offers for registering a listener for a capability change event? Within my app I want to act on certain changes in capabilities on some of my devices and in Homey 1.x it was simple by using the device.on method.

Now, when trying to implement the registerCapabilityListener on Homey 2.0 I can’t get it working; it’s trowing me errors like ‘device.registerCapabilityListener is not a function’, and the old device.on method just doesn’t seem to work anymore. Any hints/examples are much appreciated.

TIA, cheers,
/Cacti

It isn’t a better example, but it is a real world usage.


    /**
     * Initialises the capability listener.
     *
     * Basically : Registers every capability the group (MultipleCapabilityListener) has, so
     * when any of the group capabilities are changed, the function is called  which sets the
     * value of all of the devices to said value.
     *
     * As this is only listening for capabilities (which cant be changed in the settings), we never have to reload this.
     *
     * @returns {Promise<void>}
     */
    async initGroupListener() {

        /**
         * Register all of the capabilities at once with a (async) call back.
         *
         * values : An object with the changed capability values, e.g. { dim: 0.5 }
         * options : An object with optional properties, per capability, e.g. { dim: { duration: 300 } }
         *
         * Increase the time out - as large groups will require more time. Especially via 3rd Party server (alexa/google)
         */
        return this.registerMultipleCapabilityListener(this.capabilities, async (values, options) => {
            return this.updateDevicesCapabilities(values, options);
        }, 1000);
    }

Where :


 this.capabilities = await this.getCapabilities();

and

    /**
     * Updates the devices capabilities called from the groups capability listener.
     *
     * @param values
     * @returns {Promise<boolean>}
     */
    async updateDevicesCapabilities(values) {

        // Do stuff 

    } 

Thanks Jamie!

I’ll see if I can get that working.

Regards
/Cacti

Here is another example for listening in on a particular capability

This gets called from here while cycling through all devices.

1 Like

Thanks guys. All is well now!

Cheers,
/Cacti

1 Like

Hi,

Another question, how do I delete/remove/detach/destroy a listener? I use makeCapabilityInstance to attach a listener to specific capabilities, but what if I want to detach a listener? I can’t find any examples, and I’m unable to figure out how to implement the destroy method myself :slightly_smiling_face:

Looks like a capability instance has a destroy() method that you can call:

const instance = device.makeCapabilityInstance('onoff', handler);
…
instance.destroy();

Thanks, but I don’t see how I can use that (I’m not an experienced programmer)

I use this to attach a listener:

device.makeCapabilityInstance(params.capability,function(device, state) {
	this.stateChange(device,state,params.capability, 0)
}.bind(this, device));

I can do this:

const instance = device.makeCapabilityInstance(params.capability,function(device, state) {
	this.stateChange(device,state,params.capability, 0)
}.bind(this, device));

It also attached the listener, but instance.destroy() doesn’t detaches it.

Thanks for your input.

Edit: saw that it made no sense :slight_smile:

I can’t reproduce, using this code:

    const api     = await HomeyAPI.forCurrentHomey();
    const device  = await api.devices.getDevice({ id : DEVICE_ID });

    const listener = device.makeCapabilityInstance('meter_power', value => {
      console.log('listener update', value);
    });

    setTimeout(() => {
      console.log('destroying listener');
      listener.destroy();
    }, 5000);

It creates a capability listener for meter_power for a specific device. After 5 seconds, as expected, listener update messages stop from being logged.

Hi,

I have two functions one for attaching the eventlistener, and one for destroying it. I guess that is the reason this solution isn’t working for me; the instance created in the first function doesn’t seem to be available in the second function. And because I have many listeners I can’t make them global I think.

Thanks for testing though.

Solved it by creating a global array to store all these ‘instances’. Maybe it isn’t the best solution, but it works for me.

Thanks.

Assuming that you create these listeners inside a class instance, you could create an instance property (this.listeners for example) to store them in.

1 Like

Ik zie in deze regel code wel iets, maar ik zit nog vast.

hier heb ik deze regel ingeplaats:

this.registerCapabilityListener('my_enum_capability', async (value) => {
      this.log('Changes to :', value);

      if ( driver.data.id === 'sMode' ) {}
    });

maar er komt een rood lijntje onder driver

dit zou de oplossing zijn voor mijn probleem,
ik heb namelijk meerder apparaten in een device en ik kan niet uitlezen welke aan of uit gaat er gaat gewoon een aan of uit.

Met vriendelijke groeten,
Jens De Smet :grinning: .

I guess you’re in the device.js. If you’re using sdk3 you could try “this.driver…” etc.

image

Still a red line under data I want to be able to read the id.

Thanks for the effort anyway.

Did you declare the ‘data’ var in your driver class?
Like:
class MyDriver extends Homey.Driver {
data = {}

Yes I did that.

image

Especially the “data = {}” part within the class.

image

To access data you need to get it first:

let devData = this.getData();
if (devData.id === 'sMode'){}

The data setup during pairing is stored in the device instance.

Edit: Are you sure you want the id there though as that should be a unique identifier per device?