Powerpal smart energy monitor

Thanks @muneeb1990 got your code up and running today on an M5 Atom Lite.
From what I can see in HA everything looks good, however the data being pushed to Powerpal by the automation\Rest is way off! See screenshot attached showing 15.4kW!! It should be like 700watts.
Is it possible it’s not reflecting the pulse_per_kwh ? Mine is set to 3200 as per my meter and configured in the yaml file of the ESP device.

Any help would be greatly appreciated!!!

I’m having this experience too with a 3200/pulse per kw meter too.
The watt hours seem to be super far off compared to everyone else.

I’m testing this code now, so far it seems to work but I haven’t got much data to compare yet.

int mywatt_hrs = (uint32_t)roundf((pulses_within_interval / this->pulses_per_kwh_) * kw_to_w_conversion);

Have you set 3200 in Powerpal app as well? I don’t see anywhere in the code where this value is hard-coded to 1000 so not sure what’s going on.

Yeah, 3200 in the Powerpal app as well. I couldn’t see anywhere in the code where it was hard set. I’m getting some discrepancy between HA and Powerpal, so will compare with what the United energy platform says my meter is doing.

Powerpal cloud is now significantly lower than United energy and HA. Will hopefully get a bit of time this week to dig into it a bit more and roll my testing change back.



image

I think there might be an issue with update frequency associated with using timestamp as the trigger. Can you try changing the configuration.yaml to the following:

rest_command:
  my_request:
    url: https://readings.powerpal.net/api/v1/meter_reading/<device-id>
    method: POST
    headers:
      authorization: "authorization key"
      accept: ""
    payload: >-
       [ {"cost":{{ states.sensor.powerpal_cost_json.state }},"is_peak": false, "pulses":{{ states.sensor.powerpal_pulses_json.state }}, "timestamp": {{ as_timestamp(now(),0) | int(0) }} , "watt_hours": {{ states.sensor.powerpal_watt_hours_json.state}} } ]
    content_type: 'application/json'
    verify_ssl: true

And automation.yaml:

alias: Powerpal Cloud Upload
description: ""
trigger:
  - platform: time_pattern
    minutes: /1
condition: []
action:
  - service: rest_command.my_request
    data: {}
mode: single
1 Like

Went to try this today and discovered my Powerpal stopped sending data some time yesterday. Will do some digging into why and hopefully I can get it running again.

Just tried but unfortunately results appear to be the same in Powerpal app.
The timestamp is different between the two but the rest remains the same.

Example output pasting the payload line into templates:
Old:
[ {“cost”:0.00549223134,“is_peak”: false, “pulses”:93, “timestamp”: 1674627660, “watt_hours”: 298 } ]

New:
[ {“cost”:0.00549223134,“is_peak”: false, “pulses”:93, “timestamp”: 1674627840 , “watt_hours”: 298 } ]

Yeah that fix was for reduced usage being reflected in the app. Have you set your app to 3200 as well?

Confirming I do have it set to 3200 in the PowerPal app and readings had been accurate with direct Bluetooth connection. That said I think I’ve got it pretty close now!

With the readings being far to high I first tried dividing the watt hours being sent to PowerPal by 3.2 thinking that would account for the flashes per second and that possibly by disconnecting the PowerPal from the app that it may default back to 1000 even though it was set to 3200.
That theory went out the window as results were still to high but I’ve got it pretty close by dividing by 5. I can’t say I understand why it’s by 5 but it does seem to get me within +/-0.1 kWh from what I see in HA (which is 100% accurate confirmed with power distributors web portal) so I’m happy enough with that.

Final config below for anyone else who may have similar issues.

configuration.yaml

rest_command:
  my_request:
    url: https://readings.powerpal.net/api/v1/meter_reading/<device-id>
    method: POST
    headers:
      authorization: "authorization key"
      accept: ""
    payload: >-
       [ {"cost":{{ states.sensor.powerpal_cost_json.state }},"is_peak": false, "pulses":{{ states.sensor.powerpal_pulses_json.state }}, "timestamp": {{ (int(states.sensor.powerpal_timestamp_json.state)//60) * 60 }}, "watt_hours": {{ int(states.sensor.powerpal_watt_hours_json.state)/5}} } ]
    content_type: 'application/json'
    verify_ssl: true

Automation you suggested:

alias: Powerpal Cloud Upload
description: ""
trigger:
  - platform: time_pattern
    minutes: /1
condition: []
action:
  - service: rest_command.my_request
    data: {}
mode: single
1 Like

That seems to have done the trick, it’s tracking much more accurately now with the time change and the change to how the watt hours are calculated.

I’ve been tracking for about 8 hours now and it’s spot on! Thank you!

Awesome, glad to know it’s working.

Just to help others on the same journey - got my ESP32 working to pull data from my Powerpal over the weekend and have a few learnings:

  • I had compile issues too so followed @starryalley version of powerpal_ble. I also removed ble_client from the components declaration towards the top of the YAML. Once I’d done that then it all compiled smoothly

  • Next, I had heaps of trouble finding the Mac address of my powerpal. I tried running the esp32_ble_tracker and the iphone apps etc. I even let ble_tracker run with logging level set at VERY_VERBOSE and pulled those logs into a spreadsheet to make a list of every bluetooth device in range. I had 31 unique Mac addresses to go through. At up to 5 minute compile time, that equals a huge time suck. What makes this difficult is that I didn’t know whether the Powerpal was broadcasting a name, and I had a heap of devices reporting an empty name field - so I had to just go through the list (in order of RSSI) and try each once. In the end, I turned off as many bluetooth devices as I could find and ran the scanner - and I can confirm that Powerpal IS reporting a name. So here’s the scan result that I got - after that everything was super-easy.

[11:28:41][VV][esp32_ble_tracker:648]: Parse Result:
[11:28:41][VV][esp32_ble_tracker:665]:   Address: DD:A3:C1:7F:DA:0B (RANDOM)
[11:28:41][VV][esp32_ble_tracker:667]:   RSSI: -60
[11:28:41][VV][esp32_ble_tracker:668]:   Name: 'Powerpal 0001e9f0'
[11:28:41][VV][esp32_ble_tracker:676]:   Ad Flag: 5
[11:28:41][VV][esp32_ble_tracker:679]:   Service UUID: 0xFCD7
[11:28:41][VV][esp32_ble_tracker:698]: Adv data: 02.01.05.03.03.D7.FC.12.09.50.6F.77.65.72.70.61.6C.20.30.30.30.31.65.39.66.30 (26)

I was interested that the RSSI was so low! But also that the Mac address is Random (meaning it may change at some point in the future and I need to watch for data drop outs).

  • Lastly, I had to change the sensor definition in the yaml to include a unit of measurement, this means you can use the data in the Home Assistant Energy Dashboard. My cost sensor now looks like this
cost:
       name: "Powerpal Cost_json"
       unit_of_measurement: "$/kWh"
1 Like

Hello everyone - I’ve recently made some changes to enable Daily Energy values to persist through reboots. Copy the powerpal_ble folder from here into my_components folder under config>esphome.

Updated yaml:

esphome:
  name: "esp32-powerpal"
  on_boot:
    then:
      - lambda: |-
           powerpal_ble_powerpal->daily_pulses_ = id(powerpal_daily_pulses_backup) ;

esp32:
  board: esp32dev

external_components:
  - source:
      type: local
      path: my_components
    components: [powerpal_ble]
# Enable logging
logger:
 level: VERY_VERBOSE
 logs:
  esp32_ble_tracker: WARN
# Enable Home Assistant API
api:

ota:

#esp32_ble_tracker:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

# optional requirement used with daily energy sensor
time:
  - platform: homeassistant
    id: homeassistant_time

esp32_ble_tracker:

ble_client:
  - mac_address: XX:XX:XX:XX:XX:XX
    id: powerpal

#http_request:
 #id: powerpal_cloud_uploader

switch:
  - platform: restart
    name: "Powerpal Monitor Reboot"

globals:
  - id: powerpal_daily_pulses_backup
    type: int
    restore_value: true

sensor:
  - platform: powerpal_ble
    ble_client_id: powerpal
    power:
      name: "Powerpal Power"
    daily_energy:
      name: "Powerpal Daily Energy"
    daily_pulses:
      name: "Powerpal Daily Pulses"
    energy:
      name: "Powerpal Total Energy"
    battery_level:
      name: "Powerpal Battery"
    watt_hours:
       name: "Powerpal Watt Hours_json"
    cost:
       name: "Powerpal Cost_json"
    timestamp:
       name: "Powerpal Timestamp_json"
    pulses:
       name: "Powerpal Pulses_json"
    pairing_code: 123456
    notification_interval: 1
    pulses_per_kwh: 1000
    #http_request_id: powerpal_cloud_uploader
    time_id: homeassistant_time # daily energy still works without a time_id, but recommended to include one to properly handle daylight savings, etc.
    cost_per_kwh: x.xxx #dollars per kWh

  - platform: homeassistant
    id: ha_daily_pulses
    entity_id: sensor.powerpal_daily_pulses
    on_value:
     then:
       - globals.set:
          id: powerpal_daily_pulses_backup
          value: !lambda 'return int(x);'
3 Likes

Thanks everyone for the pointers and @muneeb1990 for the code - got mine running nicely.

I ended up purchasing a pack of the M5Stack Atom Lites, and now have spares sitting here in NSW, Australia if anyone’s interested - currently listed on ebay. Feel free to DM me if you want one (selling for ~ $20 per unit plus postage), just covering costs getting them to Australia :slight_smile:

Rob

I am about 99% of the way there, except that I don’t think the upload to the Powerpal cloud is working correctly. I checked the logs and this error appears:

I have no idea what that error message means, so I would really appeciate some advice on what it means and what I need to do to fix it.

I believe that I am running the latest versions of @muneeb1990 's code and .yaml scripts (powerpal.yaml, configuration.yaml & automations.yaml).

Thanks in anticipation …

Further to my post yesterday, here is a more detailed error report from the log file today:

2023-03-27 13:21:00.264 ERROR (MainThread) [homeassistant.components.rest_command] Client error. Url: https://readings.powerpal.net/api/v1/meter_reading/000222e2. Error: Cannot connect to host readings.powerpal.net:443 ssl:default [Name does not resolve]

2023-03-27 13:22:00.242 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: ‘None’ has no attribute ‘state’ when rendering ‘[ {“cost”:{{ states.sensor.powerpal_cost_json.state }},“is_peak”: false, “pulses”:{{ states.sensor.powerpal_pulses_json.state }}, “timestamp”: {{ as_timestamp(now(),0) | int(0) }} , “watt_hours”: {{ states.sensor.powerpal_watt_hours_json.state}} } ]’

I would love to know what those messages mean and how to fix them … :grinning:

Looks like HA is unable to reach the URL. Have you tried pinging it from the system running HA? Maybe do a ping test to see if it’s reachable.

Here’s the ping result from HA:

and here’s the same ping from my Windows 10 PC:

Does this mean that Powerpal have changed the host details? I don’t understand why I cannot ping that URL … :worried: