Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Device: Energy Monitoring Support #486

Open
shivanathd opened this issue Oct 8, 2024 · 0 comments
Open

New Device: Energy Monitoring Support #486

shivanathd opened this issue Oct 8, 2024 · 0 comments
Labels
newDevice Add support for a new device.

Comments

@shivanathd
Copy link

shivanathd commented Oct 8, 2024

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)

I wish if someone can look at the code, and if we can implement the Power Metering to all the devices it would be great to pull this into EVE app..

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.dpCurrent = config.dpCurrent || '18';
    this.dpVoltage = config.dpVoltage || '20';
    this.dpPower = config.dpPower || '19';
    this.tuyaDevice = this.initializeTuyaDevice();

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

    // 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.currentConsumptionCharacteristic = this.service.addCharacteristic(Characteristic.CurrentConsumption);
    this.totalConsumptionCharacteristic = this.service.addCharacteristic(Characteristic.TotalConsumption);
    this.voltageCharacteristic = this.service.addCharacteristic(Characteristic.Voltage);
    this.electricCurrentCharacteristic = this.service.addCharacteristic(Characteristic.ElectricCurrent);

    this.currentConsumptionCharacteristic.on('get', this.getCurrentConsumption.bind(this));
    this.voltageCharacteristic.on('get', this.getVoltage.bind(this));
    this.electricCurrentCharacteristic.on('get', this.getElectricCurrent.bind(this));

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

  // Initialize Tuya Device
  initializeTuyaDevice() {
    return new TuyaDevice({ id: this.deviceId, key: this.accessToken });
  }

  // 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: Math.round(new Date().valueOf() / 1000), power: power });
          // Update HomeKit characteristics with the latest power data
          this.currentConsumptionCharacteristic.updateValue(power);
          this.voltageCharacteristic.updateValue(voltage);
          this.electricCurrentCharacteristic.updateValue(current);
        }
      } catch (error) {
        this.log.error('Error fetching power data:', error);
      }
    }, 600000); // Refresh every 10 minutes
  }

  // 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[this.dpCurrent] || 0,
          voltage: response.dps[this.dpVoltage] || 0,
          power: response.dps[this.dpPower] || 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);
};


@shivanathd shivanathd added the newDevice Add support for a new device. label Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
newDevice Add support for a new device.
Projects
None yet
Development

No branches or pull requests

1 participant