bewee / tuya-adapter

GNU General Public License v3.0
8 stars 8 forks source link

Toggle action for devices with logical on/off #16

Closed sjorn3 closed 4 years ago

sjorn3 commented 4 years ago

Firstly thanks for this - it's super cool :)

I have a simple project I'm working on where I need to be able to update device properties via HTTP requests. Currently if I want to toggle the lights on and off I need to send one request to get the current state and then another to update to the opposite state. Caching a local state leads to turning it on when it's already on sometimes and vis versa (with my setup, multiple switches e.t.c, this would happen a lot). Therefore having access to a toggle action would half the execution time.

This may already be possible and I'm just missing something - let me know if that's the case.

Otherwise I've had a go here. I believe the tuya-api has support for toggling directly - but there's probably an easier way using the state cached in the raspberry pi. I've had a go at forking and implementing and having a go but I'm quite stuck and I don't have the best setup. Started by making an action to turn off which I've attached if you're curious. If you have pointers on how to continue that would be appreciated or if it's a feature you think you could add I'd be happy with that too.

For extra context I'm using this avatar controls E14 colour light: https://www.amazon.co.uk/gp/product/B07W6Z6KPG/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=1 which I got working (relatively) easily so you could add it to your list. I had to configure it with: "minbrightness":25,"maxbrightness":255,"minlighttemperature":0,"maxlighttemperature":255"

Sean.

colourlight-device.js:

...
class ColourLightDevice extends TuyaDevice {
  constructor(adapter, cnf, cid) {
    super(adapter, cnf, cid);

    this.name = cnf.name&&cnf.name!='' ? cnf.name : 'Colour Light';
    this['@type'] = ['Light', 'OnOffSwitch'];

    // Altered this so I can access power property below
    this.powerProperty = new PowerProperty(this, {dps: this.ownconf.dps.on, default_dps: 1});                                   
    this.addProperty(powerProperty);

    const modecb = ((mode) => {
      switch (mode) {
        case 'white':
          this.setVisibility(['on', 'mode', 'brightness', 'lighttemperature']);
          break;
        case 'colour':
          this.setVisibility(['on', 'mode', 'colour', 'hue', 'saturation', 'lightness']);
          break;
      }
      this.adapter.handleDeviceUpdated(this);
    }).bind(this);
    this.addProperty(new ModeProperty(this, {dps: this.ownconf.dps.mode, default_dps: 2, modes: ['white', 'colour'], modestxt: ['White', 'Colour'], setcb: modecb, updatecb: modecb}));

    this.addProperty(new BrightnessProperty(this, {dps: this.ownconf.dps.brightness, default_dps: 3}));
    this.addProperty(new LighttemperatureProperty(this, {dps: this.ownconf.dps.lighttemperature, default_dps: 4}));
    this.addProperty(new ColourProperty(this, {dps: this.ownconf.dps.colour, default_dps: 5}));
    this.addProperty(new HueProperty(this));
    this.addProperty(new SaturationProperty(this));
    this.addProperty(new LightnessProperty(this));
    this.addAction('toggle', {label: 'Toggle'}); // This line creates a toggle action in the UI, this works.
  }

  // Added this function to perform action (just turns off for now) - seems to prevent connection - probably missing something.
  performAction(action) {
    this.powerProperty.update(false);
  }
}
bewee commented 4 years ago

Hi,

thanks for contacting me. 069d28c6feea87e626b645a754c0884287441a98 adds your light bulb to the list.

this.powerProperty.update(false);

The update function is called (internally) whenever the device tells the gateway that this propertie's value changed. In this case, only the UI is updated (so nothing is sent to the device) and you correctly experience no reaction of the device. You have to use setValue instead which is meant for exactly this purpose. Does this solve the problem?

However, I think this feature is really very very specific. It makes the device overview more complex for all users although almost nobody needs this action. Therefore I currently think that I wouldn't merge this feature into this repository's master.

But by advertising my own stuff again I want to point to another solution: I'm currently working on an add-on which would allow to create macros (kinda more complex rules). If you want to, have a look at it here (unfortunately the UI isn't working yet, but the backend runs quite well already. If you're interested, just tell me and I can explain to you how to create a macro there, which you could then trigger through your HTTP request).

sjorn3 commented 4 years ago

Thanks - yes unfortunate that it would appear on the UI for all. I would imagine it could be possible to disable it in the config or something like that but actually a macro could be a better solution since there are a lot of other niggly things I'd like to do & have the same problem for some smart plugs from a different manufacturer. Would definitely be interested as long as it doesn't take too much of your time.

bewee commented 4 years ago

I have closed the issue for now.

Just follow these steps:

  1. Download and install the add-on
  2. Go to settings > developer > create local authorization. Make sure that all devices are checked and "monitor and control" is selected. Then click allow and copy the token from the first text field.
  3. Go to settings > add-ons > macrozilla > configure and paste your token in the access token field, then save
  4. Open your gateway's website and open the developer console (usually F12, but depending on your browser)
  5. Paste the following script and press enter
    (async () => {
    console.log('Create macro');
    const response = await window.API.postJson('/extensions/macrozilla/api/create-macro',  {path_id: 1, name: 'Toggle power property of my tuya device'});
    console.log(response);
    const macro_id = response.id;
    console.log('Fill macro');
    macro_content = [{id: macro_id, type: 'thing', function: 'next', thing: 'tuya-xxxx', property: 'on'}];
    console.log(await window.API.postJson('/extensions/macrozilla/api/update-macro',  {id: macro_id, description: macro_content}));
    })();

    The output of it should look like this

    Create macro
    {id: 1, success: true}
    Fill macro
    {success: true}

    Now you can execute this macro by POSTing {"id":1} to https://[your-gateway]/extensions/macrozilla/api/exec-macro. In order to test this, just execute the following script in the developer console:

    (async () => {
    console.log(await window.API.postJson('/extensions/macrozilla/api/exec-macro',  {id: 1}))
    })();

    If anything does not work out as expected (and that's quite likely to be honest^^) just report back :)

bewee commented 4 years ago

@sjorn3 The described add-on is now available via the add-on list. You can install it from there, build your macro using the graphical editor (no more manual JSON editing required) and then trigger your macro by URL just as described above.