Puck.js PowerMeter to HomeAssistant

Posted on
  • Hello
    Here is my project. Not sure if I should be posting a code here or in pastebin. Let me know so that I will do it next time =)
    Anyway. I have this working by using Puck.js that counts pulses on my smart power meter and transmits them for ESPHome running ESP32 board to pickup and process into HomeAssistant.
    At the moment have an issue with with the code (which is reused example code plus few extras) - it is set to keep track of pulses (hourly, daily etc), but it does not reset when the hour is changed over. Which causes incorrect values - it increments what was already there from the previous day =(
    Can someone skim through the code and suggest any optimizations and help me with counter resets for daily pulses?

    function Counter() {
      this.clear();
    }
    /// Clear the counters back to zero
    Counter.prototype.clear = function() {
      this.totals = {
        count : 0,                // Overall count
        year : new Uint32Array(12), // each month of the year (0..11)
        week : new Uint32Array(7), // each day of the week (0..6)
        month : new Uint32Array(31), // each day of the month (0..31)
        day : new Uint32Array(24), // each hour (0..23)
      };
      this.historyPeriod = 60*60*1000; // 1 hour in milliseconds
      this.history = new Uint32Array(96); // last 96 hours
      this.historyTime = 0;
      this.lastUpdate = new Date.now();
    };
    
    Counter.prototype.inc = function(n) {
      if (n===undefined) n=1;
      
      var t = this.totals;
      var d = new Date();
      // Totals by time period
      t.count+=n;  
      t.year[d.getMonth()]+=n;
      t.week[d.getDay()]+=n;
      t.month[d.getDate()-1]+=n;
      t.day[d.getHours()]+=n;
      print("Day:"+t.day);
      print("Month:"+t.month);
    
      pulseHour=t.day[d.getHours()];
      pulseDay=t.month[d.getDate()-1];
      
      // Rolling history
      this.historyTime += d.getTime()-this.lastUpdate;
      this.lastUpdate = d.getTime();
     
      var steps = Math.floor(this.historyTime / this.historyPeriod);
      
      if (steps>=0) {
        this.historyTime -= steps*this.historyPeriod;
        var h = this.history;
    
        h.set(new Uint32Array(h.buffer, 4*steps), 0);
        h.fill(0, h.length-steps);
        h[h.length-1]+=n;
      }
    };
    
    
    var c = new Counter();
    var pulseTotal = 0;
    var power = 0;
    var cTime = Date.now();
    var pulseHour = 0;
    var pulseDay = 0;
    E.setTimeZone(8);
    var LEDStatus = 0;  // 0 = LED Status off    1 = LED Status on
    var txpower = 0;  //-20, -16, -12, -8, -4, 0, and 4
    
    NRF.setSecurity({display : 1, mitm : 1, bond : 1, passkey : '123456'});
    NRF.setTxPower(txpower); //-20, -16, -12, -8, -4, 0, and 4
    
    // Update BLE advertising
    function update() {
      var a = new ArrayBuffer(4);
      var dataV = new DataView(a);
      var mydate = new Date();
      var temp = E.getTemperature();
      var batt = E.getBattery();
      var dataJSON = {b:batt,t:temp,c:1};
      var timeDiff = (Date.now() - cTime);
      //Number of pulses per wh - found or set on the meter.
      var ppwh = 1; //1000 pulses/kwh = 1 pulse per wh
      //Calculate power
      
      var totalkWh = pulseTotal/1000;
      if (pulseHour>0) {
        power = Math.floor(((60*60*1000) / timeDiff)/ppwh);
      }
      cTime=Date.now();
    
      //dataV.setUint32(0, c.totals.day, false/*big endian*/);
      //print(c.totals.day[mydate.getHours()])­;
      print(mydate.toString());
      
      print("Temperature:"+temp);
      print("Battery:"+batt);
      print("Current power use:"+power);
      print("Total power use:"+totalkWh);
      print("Pulses this hour:"+pulseHour);
      print("Pulses this day:"+pulseDay);
      
      NRF.setTxPower(txpower);    //-20, -16, -12, -8, -4, 0, and 4
      NRF.setAdvertising([{
        0x2a03 : [String(power)], 
        0x2a04 : [String(pulseHour)],
        0x2a05 : [String(pulseDay)]}],
        {interval: 600,
        showName:false
        }
     //   name: "PM \xE2\x9A\xA1"} // default is 375 - save a bit of power
      );
      power = 0;
    }
    
    function onInit() {
      var sDate = new Date();
      clearWatch();
      D1.write(0);
      pinMode(D2,"input_pullup");
      setWatch(function(e) {
        c.inc(1);
        pulseTotal++;
        update();
        if (LEDStatus==1){
          digitalPulse(LED1,1,1); // show activity
        }
      }, D2, { repeat:true, edge:"falling" });
      update();
      setInterval(function() {
        power = 0;
        if (sDate.getMinutes()==0) {
          update();
        }
        NRF.setAdvertising({
          0x1809 : [E.getTemperature()],
          0x180f : [Puck.getBatteryPercentage()],
          0x2a03 : [String(power)]
        });
        print("Battery and temp data sent");
      }, 30000);
      
    }
    
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Puck.js PowerMeter to HomeAssistant

Posted by Avatar for user130485 @user130485

Actions