iRayanKhan / homebridge-tuya

A Homebridge plugin to control Tuya devices locally.
MIT License
394 stars 164 forks source link

Current Power Consumption of Outlet #25

Closed DSchumacher2104 closed 4 years ago

DSchumacher2104 commented 5 years ago

Hello, fist of all, thank you for creating this wunderful plugin. I'm using it with 2 tuya outlets. The plugin would be perfect, if it would be possible to add the power consumption feature of the outlets and let HomeKit read the current power consumption. This would be great for creating automations e. g. for a washing machine. So it would be possible to determine the end of the washing process. You even can use fakegato (https://github.com/simont77/fakegato-history) to create a statistic of the power consumption.

Can the tuya-API Support this Feature?

codetheweb commented 5 years ago

It's definitely possible, you'd just have to modify the generic accessory type for this use case. I don't have any plans to add this feature currently, although I'm happy to accept a PR for it.

DSchumacher2104 commented 5 years ago

Sorry, but sadly i'm not able to code such things. I even can't see, which Tuya-API commands can be used to read the power consumption data.

Redlah commented 5 years ago

Hey,

I would also be very interested in this feature. It would be so great if you could add this. I'm new to Homebridge and all the smart things stuff. Is there any tutorial about programming of such APIs or how to extend the existing one for own tests (modify which file etc.) for beginners? I am also a programmer but from a completely different field.

Thx in advance!

codetheweb commented 5 years ago

@Redlah unfortunately, the lack of documentation on creating Homebridge plugins is somewhat frustrating.

But take a look at lib/generic.js in this repo and see if you can add a characteristic like this plugin does.

I don't think the HomeKit app can display power consumption, so you'd have to use a third-party app like Eve.

Redlah commented 5 years ago

Thanks for your fast response! Yes, I haven't found any useful information on the internet yet. So it would be a good idea and the next step, for a professional like you, to create a tutorial to enlarge the community. :-p The best example would be an extension of the Homebride-Tuya plugin. :-)

I had a look to both, generic.js and the index.js of the plugin you suggested. But I think at the moment I'm still far away from writing my own code. :-( Just because I have only needed javascript once before and because I'm not familiar with the terms yet. Although it can't be much code, because it's not really much code yet in these plugins.

The stupid thing is, I bought the Raspberry and the outlets only for this function. Yes, I found an app "Controller für Homekit" with that I was able to solve my use case (drop of the power consumption as event) . But the Koogeek outlet (hk ready) I used, is only designed for 2500 watts, which was not enough for my washing machine, so I bought the Gosund outlets. With which I now try to achieve the same functionality again.

So if you have any further hint, I would be very thankful and happy.

Redlah commented 5 years ago

Hey,

I'm still trying to understand how the Homebridge framework and the code of the plugin, you have linked, works.

But take a look at lib/generic.js in this repo and see if you can add a characteristic like this plugin does.

I think for the first step, this is the important part.? Has the "Characteristic" object all information /attributes of the device included? And the only thing is to get the correct attributes out of it, with this UUID and create also a characteristic with additional properties like unit.. etc.? If yes, how do I get the UUID of the power consumption?

image

codetheweb commented 5 years ago

@Redlah I'm sorry, but I haven't worked with custom characteristics before.

I'll revisit this Thursday and see how hard it would be for me to add support.

Redlah commented 5 years ago

@codetheweb all right, thank you very much.

DSchumacher2104 commented 5 years ago

I used homebridge-tuya-lan plugin to get the signature of my smart plugs. I think this is similar to the "dps" Parameter used by this plugin. The results are:

[2019-2-19 16:09:20] [TuyaLan] Ready to handle OxaOxe 2-fach 16A 1 with signature {"1":true,"2":true,"7":95,"8":48,"9":2267} [2019-2-19 16:09:20] [TuyaLan] Ready to handle gosund 16A 1 with signature {"1":true,"2":0,"4":19,"5":8,"6":2280} [2019-2-19 16:09:21] [TuyaLan] Ready to handle vodool 10A 1 with signature {"1":true,"2":0,"4":40,"5":45,"6":2280} [2019-2-19 18:01:24] [TuyaLan] Ready to handle RGB-Steckdose 16A 2 with signature {"1":false,"2":"colour","3":180,"4":255,"5":"00b7ff00c5ffff","6":"00ff0000000000","7":"ffff500100ff00","8":"ffff8003ff000000ff000000ff000000000000000000","9":"ffff5001ff0000","10":"ffff0505ff000000ff00ffff00ff00ff0000ff000000","101":true,"104":0,"105":0,"106":2273} [2019-2-19 16:09:21] [TuyaLan] Ready to handle AOFO 4-fach mit USB 1 with signature {"1":true,"2":true,"3":true,"4":false,"7":false,"101":0,"102":0,"103":0,"104":0,"105":0}

The frist device in a Smart Double-Outlet Plug, "1" and "2" are outlet states, "7" is current in mA (=95 mA), "8" is Power in W 10 (=4.8 W) and 9 in Voltage in V 10 (=226.7 V).

The second und third devices are Smart (Single-Outlet) Plug from different vendors, "1" is outlet state, "2" unknown, "4" is current in mA (=19 mA/40 mA), "5" is Power in W 10 (=0.8 W/4.5 W) and 6 in Voltage in V 10 (=228.0 V/228.0 V).

The fourth device is "WiFi Smart Socket with LED Indicator 16A", a smart plug with a RGB-Lightring around. The settings/states of the LED light are independent from outlet power state. "1" is power state of the RGB Indicator, "2-"10" are additional light parameters (e. g. brightness, Colour, hue …), i think. "101" is outlet power state, "104" is current in mA (=0 mA), "105" is Power in W 10 (=0.0 W) and "106" in Voltage in V 10 (=227.3 V).

The last device is a Smart Power Strip with USB, 1-4 are outlets und 7 is USB-Port. Is has no additional functions.

I hope this information can help!

xatrix78 commented 5 years ago

Hello, I have a RGB lamp and several sockets with power indicator. If I can help somehow, let me know. I have tested every tuya plugin now. No one works as well as this one. If this plugin were now extended, that would be perfect!

codetheweb commented 5 years ago

@xatrix78 please test this PR and give any feedback you have in that thread.

xatrix78 commented 5 years ago

How can I use this PR?

xatrix78 commented 5 years ago

@codetheweb

I added this code { "name": "Küchenlampe", "id": "xx", "key": "xx", "type": "lightbulb", "features": "dimmable colortemp rgb", "options": { "dpsOn": 1, "dpsBright": 3, "dpsOpMode": 2, "dpsColortemp": 4, "dpsColor": 5, "brighnessMin": 25, "brighnessMax": 255, "colorTempMin": 0, "colorTempMax": 255, "saturationMin": 0, "saturationMax": 255, "lightnessMin": 0, "lightnessMax": 255 } },

But I always get a plug. Are there some files that I have to change?

Then I use the lightbulb type I get this error: [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 3 255 [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 4 252 [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 5 FF000000006464 [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 6 3855b40168ffff [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 7 ffff500100ff00 [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 8 ffff8006ff000000ff000000ffff0000ff0000ff0000 [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 9 ffff5001ff0000 [2019-2-21 15:27:18] [TuyaPlatform] Unmapped dps data 10 ffff0506ff000000ff00ffff00ff00ff0000ffff0000 [2019-2-21 15:27:35] [TuyaPlatform] Error: Timeout waiting for response at Timeout._sendTimeout.setTimeout [as _onTimeout] (/usr/local/lib/node_modules/homebridge-tuya/node_modules/tuyapi/index.js:423:25) at ontimeout (timers.js:475:11) at tryOnTimeout (timers.js:310:5) at Timer.listOnTimeout (timers.js:270:5) [2019-2-21 15:27:56] [TuyaPlatform] Error: Error communicating with device. Make sure nothing else is trying to control it or connected to it. at Socket.client.setTimeout (/usr/local/lib/node_modules/homebridge-tuya/node_modules/tuyapi/index.js:478:35) at Object.onceWrapper (events.js:313:30) at emitNone (events.js:106:13) at Socket.emit (events.js:208:7) at Socket._onTimeout (net.js:407:8) at ontimeout (timers.js:475:11) at tryOnTimeout (timers.js:310:5) at Timer.listOnTimeout (timers.js:270:5)

xatrix78 commented 5 years ago

Any news aboot Power Consumption?

DSchumacher2104 commented 5 years ago

What is the npm command to install the PR?

codetheweb commented 5 years ago

@Redlah spent about 2 hours on this tonight, quite a bit harder than I thought it would be.

I'll continue working on it but please don't expect it to be added within the next week.

To be honest, this plugin is a bit of a mess right now and needs to be cleaned up and updated.

@xatrix78 @DSchumacher2104 install the PR with npm git://github.com/zysoft/homebridge-tuya.git#lightbulb-rc1 -g. Please direct any further questions/feedback about the lightbulb component to this thread.

Redlah commented 5 years ago

@codetheweb thank you for your efforts.

I am curious about the changes/innovations to the existing code. Maybe it will help me to understand how it works. :-)

DSchumacher2104 commented 5 years ago

The author of the homebridge-tuya-lan plugin began to integrate the power consuption feature in his plugin and it works. Look here

pitleh commented 5 years ago

I switched my plugs to the "homebridge-tuya-lan" plugin, but cannot see the power consumption data? is there a another version I need to install?

DSchumacher2104 commented 5 years ago

I think we should not discuss this here. Read the linked issue.

xatrix78 commented 5 years ago

@DSchumacher2104 I have problems with the homebridge-tuya-lan plugin. This Plugin is much better for me! So it would be nice that power consuption works.

DSchumacher2104 commented 5 years ago

Yes, this would be nice. However, i'm not able to programm this feature. I hope @codetheweb and @Redlah can do it for us.

codetheweb commented 5 years ago

(I'm copy/pasting this into every open issue and PR.)

This plugin is now deprecated, as I don't have enough time to maintain it along with other TuyAPI related projects. Please use AMoo-Miki's homebridge-tuya-lan plugin instead. (Or, you can continue to use this plugin, but I will not be giving support or adding any new devices.)

I'm sorry about this, but this plugin is taking a disproportionate amount of my time that I believe is better spent making TuyAPI more stable and adding more tools to the ecosystem.

xatrix78 commented 5 years ago

Ok Thanks for your work

Redlah commented 5 years ago

@codetheweb ok, unfortunately the other plugin doesn't work for me yet. The outlets are displayed in Homekit, but don't react. I even reinstalled my Raspberry Pi but without success.

But I think it is something with my setup. Because even your plugin doesn't work anymore... :-/

xatrix78 commented 5 years ago

@Redlah I have the same problem. this plugin is much better and stable.

iRayanKhan commented 4 years ago

Closing; inactive thread. If you need support please re-open this issue.

lzMeMod commented 4 years ago

@iRayanKhan I enjoy using your plugin. Do you have any plans to implement this feature in near future? Would be really nice.

duchu commented 3 years ago

@iRayanKhan yeah i think it would be good to enable this feature in next update. Do you have any plans with that? Need any help?

iRayanKhan commented 3 years ago

@iRayanKhan yeah i think it would be good to enable this feature in next update. Do you have any plans with that? Need any help?

@duchu if you'd like to make a PR to add this in, I'd merge it. I haven't explored energy consumption, but would be cool to have.

shivanathd commented 2 weeks ago

Hi Everyone, I dont know how to code this but i used CHAT-GPT canvas and tried creating the code , Assuming we're planning to use Fakegato - History Library ([](https://github.com/simont77/fakegato-history))

hope someone can test it and implement it

cc: @iRayanKhan


// Code from GPT
const TuyaDevice = require('tuya-device');
const fakegatoHistory = require('fakegato-history');
const { Service, Characteristic } = require('homebridge');

class TuyaPowerAccessory {
  constructor(log, config, api) {
    this.log = log;
    this.config = config;
    this.api = api;

    this.name = config.name;
    this.deviceId = config.deviceId;
    this.accessToken = config.accessToken;
    this.tuyaDevice = new TuyaDevice({ id: this.deviceId, key: this.accessToken });

    // Setup Fakegato History Service to track energy data
    this.historyService = new fakegatoHistory('energy', this, {
      storage: 'fs',
      path: this.api.user.persistPath(),
    });

    // Register Service and Characteristics for Power
    this.service = new Service.Outlet(this.name);
    this.service
      .getCharacteristic(Characteristic.On)
      .on('set', this.setOn.bind(this))
      .on('get', this.getOn.bind(this));

    this.service
      .getCharacteristic(Characteristic.OutletInUse)
      .on('get', this.getOutletInUse.bind(this));

    // Adding characteristics to track power consumption
    this.service.addCharacteristic(Characteristic.CurrentConsumption);
    this.service.addCharacteristic(Characteristic.TotalConsumption);
    this.service.addCharacteristic(Characteristic.Voltage);
    this.service.addCharacteristic(Characteristic.ElectricCurrent);

    this.service
      .getCharacteristic(Characteristic.CurrentConsumption)
      .on('get', this.getCurrentConsumption.bind(this));

    this.service
      .getCharacteristic(Characteristic.Voltage)
      .on('get', this.getVoltage.bind(this));

    this.service
      .getCharacteristic(Characteristic.ElectricCurrent)
      .on('get', this.getElectricCurrent.bind(this));

    // Periodically fetch power consumption data
    this.refreshPowerConsumption();
  }

  // Method to periodically refresh power data
  refreshPowerConsumption() {
    setInterval(async () => {
      try {
        const powerData = await this.fetchPowerData();
        if (powerData) {
          const { current, voltage, power } = powerData;
          // Add entry to the Fakegato history service
          this.historyService.addEntry({ time: new Date().getTime() / 1000, power: power });
          // Update HomeKit characteristics with the latest power data
          this.service.updateCharacteristic(Characteristic.CurrentConsumption, power);
          this.service.updateCharacteristic(Characteristic.Voltage, voltage);
          this.service.updateCharacteristic(Characteristic.ElectricCurrent, current);
        }
      } catch (error) {
        this.log.error('Error fetching power data:', error);
      }
    }, 60000); // Refresh every 60 seconds
  }

  // Fetch power consumption data from Tuya device
  async fetchPowerData() {
    try {
      const response = await this.tuyaDevice.get({ schema: true });
      if (response && response.dps) {
        // Extract power data points from the response
        const powerData = {
          current: response.dps['18'] || 0,
          voltage: response.dps['20'] || 0,
          power: response.dps['19'] || 0,
        };
        return powerData;
      }
    } catch (error) {
      this.log.error('Error fetching power data from Tuya API:', error);
    }
    return null;
  }

  // Get the current power consumption
  getCurrentConsumption(callback) {
    this.fetchPowerData()
      .then((data) => {
        if (data) {
          callback(null, data.power);
        } else {
          callback(new Error('Could not fetch current consumption'));
        }
      })
      .catch((error) => callback(error));
  }

  // Get the current voltage
  getVoltage(callback) {
    this.fetchPowerData()
      .then((data) => {
        if (data) {
          callback(null, data.voltage);
        } else {
          callback(new Error('Could not fetch voltage'));
        }
      })
      .catch((error) => callback(error));
  }

  // Get the current electric current
  getElectricCurrent(callback) {
    this.fetchPowerData()
      .then((data) => {
        if (data) {
          callback(null, data.current);
        } else {
          callback(new Error('Could not fetch electric current'));
        }
      })
      .catch((error) => callback(error));
  }

  // Set the power state of the device
  async setOn(value, callback) {
    try {
      await this.tuyaDevice.set({ dps: 1, set: value });
      callback(null);
    } catch (error) {
      this.log.error('Error setting power state:', error);
      callback(error);
    }
  }

  // Get the current power state of the device
  async getOn(callback) {
    try {
      const response = await this.tuyaDevice.get({ dps: 1 });
      if (response && typeof response === 'boolean') {
        callback(null, response);
      } else {
        callback(new Error('Could not fetch power state'));
      }
    } catch (error) {
      this.log.error('Error getting power state:', error);
      callback(error);
    }
  }

  // Determine if the outlet is currently in use
  getOutletInUse(callback) {
    this.fetchPowerData()
      .then((data) => {
        if (data) {
          callback(null, data.power > 0);
        } else {
          callback(new Error('Could not determine outlet usage'));
        }
      })
      .catch((error) => callback(error));
  }

  // Return all services provided by this accessory
  getServices() {
    return [this.service, this.historyService];
  }
}

module.exports = (homebridge) => {
  fakegatoHistory(homebridge);
  homebridge.registerAccessory('homebridge-tuya-power', 'TuyaPowerAccessory', TuyaPowerAccessory);
};