Energy tracking with Puck.js and Passive BLE

TL:DR: Puck.js, LDR, modified Passive BLE Monitor component and code for Puck.js here.

Just a little project that got me scratching my head over the last few weeks!

I have a ‘smart’ electricity meter I wanted to integrate with HA but because it’s a SMETS1 and I’m no longer with my electric company it’s now as useful as nipples on a fish.

My meter is outside my house, so I wanted something inexpensive, battery-powered (sorry HA Glow), long-lasting, and without having to interfere with any of the high-amp wiring coming into the house. I also wanted accuracy without fiddly linear calibration - CT clamps have issues here.

I based this project on Gordon Williams’ Puck.js board - it’s a £30 CR2032-powered board with 6-12 months battery life, a button, LEDs, magnetometer, compass, themometer, IR, and more. Gordon has already made a smart meter project with this using a light dependent resistor soldered to D1 and D2 to measure the LED flashes on a standard 1000 Imp/kWh electricity meter.

I have modified this project so that it also calculates the active electricity usage in the house in watts. Data is broadcast as a byte array over BLE advertising to minimise power consumption. To read the data I have made a custom version of the Passive BLE Monitor component, which can be found here. The required code for the Puck.js is included in the repository (puckjs_energymeter.js).

Alternatively you can buy an iNode for a similar price - this is already integrated into the BLE Passive Monitor component, however it only updates once per minute, battery reporting is less accurate, and I had issues trying to get hold of one. Plus the Puck.js allows for a lot more customisation if you know what you’re doing!

Also, if you’re like me and you’re finding your HA is just a bit too far from the meter to get reliable readings, here’s a template for an ESP32 flashed with ESPHome which can act as a hub for the meter and forward the data on to HA. You can also use this if you don’t want to use the Passive BLE Monitor integration:

esphome:
  name: electricity-meter
  platform: ESP32
  board: esp32dev

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: "[otapassword]"

wifi:
  ssid: "[ssid]"
  password: "[password]"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Electricity-Meter"
    password: "[password]"

captive_portal:

sensor:
  - platform: template
    name: "energy"
    id: energy
    state_class: "total_increasing"
    unit_of_measurement: "kWh"
    device_class: "energy"

  - platform: template
    name: "power"
    id: power
    unit_of_measurement: "W"
    device_class: "power"

  - platform: template
    name: "battery"
    id: battery
    unit_of_measurement: "%"
    device_class: "battery"

  - platform: template
    name: "batteryVoltage"
    id: batteryVoltage
    unit_of_measurement: "V"
    device_class: "voltage"

esp32_ble_tracker:
  scan_parameters:
    active: false
  on_ble_manufacturer_data_advertise:
    - mac_address: [mac]
      manufacturer_id: 83a0
      then:
        - lambda: |-
            float value1 = ((x[0]) + (x[1] << 8) + (x[2] << 16) + (x[3] << 24));
            id(energy).publish_state(value1 / 1000);
            float value2 = (x[4]) + (x[5] << 8);
            id(power).publish_state(value2);
            float value3 = (x[6]);
            id(battery).publish_state(value3);
            float value4 = (x[7]);
            id(batteryVoltage).publish_state(value4 / 10);

Hey! Spent months on puck.js =) and your code is so small…
How do I get the total energy use for a day? I get instant, but no total.
Also, in my puck.js code I had to modify so that it sends Zero for instant power in between cycles, as during the day it will just stay on its last value, as most energy is coming from solar