athombv / homey-web-api-issues

This issue tracker is for Homey Developers using the Web API.
4 stars 1 forks source link

Expose ManagerDevices updateCapabilityValue to update Homey without triggering setCapabilityValue listeners #47

Open torarnv opened 1 year ago

torarnv commented 1 year ago

Some devices do not have the ability to report their state, for example the Nexa series of "dumb" 433 sockets/dimmers. To reflect the device's state in Homey, we rely on the remote control signal, which is used both to listen for changes, as well as control the device.

A common practice in this case is that the remote control and device are directly paired, outside of Homey, so that if Homey is down, or has issues receiving 433 signal, the lights still work. This would potentially result in the device receiving duplicate state changes, e.g.:

  1. Remote turns on light
  2. Light receives signal from remote, turns on device
  3. Homey receives signal from remote, turns on device
  4. Homey sees that device is turned on, sends signal to turn on
  5. Light receives signal to turn on again, when it's already on, potentially triggering a "choose dim level mode", or similar

Luckily, a Device implemented using the App SDK doesn't have this problem of recursing back to its capability listener when calling setCapabilityValue:

class Device extends Homey.Device {
  async onInit() {
    this.registerCapabilityListener("onoff", async (value) => {
      await DeviceApi.setMyDeviceState({ on: value });
    });

    DeviceApi.on('state-changed', (isOn) => {
      this.setCapabilityValue('onoff', isOn).catch(this.error);
    });
  }
}

Because it only results in updating locale state, and emitting updateCapabilityValue so that Homey can react to the state change. All good so far 😃

Now, consider a scenario where a device is controlled by two remotes, both directly paired to the device outside of Homey. In that case, the Homey device is only set up to "mirror" one of the remote controls. The other remote control is paired to Homey as a plain remote control, without being tied to anything. To tie the remote control to the light, we need to use Flows/HomeyScript. But unlike the case above with the App SDK, the Web SDK setCapabilityValue function recurses back into the light device's capability listener, resulting in duplicated "turn on" signals, as in point 5 above.

This is where a updateCapabilityValue in the Web SDK would be useful, so it can be used in HomeyScript automations. Hope this can be added! 🤞🏻

torarnv commented 11 months ago

One possible implementation would be the following two commits:

The functionality builds on the existing machinery inside home-core for updating capability values, which takes care of updating the UI, running flows, etc. – i.e. all the things you want to happen in reaction to a device changing its state in the eyes of Homey. Except, importantly, when hitting the app device's _onUpdateCapabilityValue in the homey-apps-sdk-v3, the app only updates its local state, and doesn't trigger capability listeners like _onSetCapabilityValue would have.

The latter would have resulted in the app trying to set the state of the external device to match the new capability value, but the whole reason we've updated the capability value is because we know it has already changed externally. And letting the app change the state of the external device (again) would be treated by the device as "go into dim level setting".

In my case I use this new API to update the Homey state when I detect that a secondary controller button has changed the state of the external device directly, and then reflect that in Homey:

image

With the HomeyScript just posting to the Web API's '/device/:deviceId/capability/:capabilityId/update' endpoint.

The plumbing all the way to the Homey Web API JS SDK porcelain has been left out for now.

JacobArrow commented 8 months ago

Bump! I have the exact same issue as mentioned above, and I would really benefit from this implementation :)

jancihr commented 7 months ago

the same here with many KAKU wall switches directly linked to KAKU relays for light control. It would be even easier for users (me) if KAKU end devices would support setting its on/off state without triggering it in the flows interface directly :)