Reading onboard data from Grant Aerona HP290 HomeAssistant

The Grant Aerona HP290 heat pump uses a Plum ecoMAX360i touch screen controller. It’s a good controller and works well.

Grant use TP-Link hardware running custom firmware to post data to EcoNet. EcoNet service allows every setting to be adjusted remotely and lots metrics from onboard sensors to be monitored with basic graphing. The TP-link hardware has a local HTTP API which can be used to read data locally. Local control is also possible.

Currently, I’m aware of three Home Assistant integrations / methods which are able to do this, once the data is in Home Assistant it’s easy to use Emoncms History Integration to get the data into Emoncms for more advanced graphing:

1. EcoNET-300 HACS

Easy to setup, install via HACS. Supports many different Plum controllers. Only a limited number of metrics are supported on the Grant HP290

2. Econet MQTT Publisher

by @MrW

Run using a docker container, doesn’t require Home Assistant. Publishes data to MQTT. Supports most more metrics from Grant HP290

Forum thread:

3. Home Assistant REST

by @GSV3MiaC

REST API calls from HomeAssistant, requires manual setup. Most complete set of metrics, this is what I’m currently using. See forum post.

# For Econet Grant Heatpump

- authentication: basic
  username: "admin"
  password: "admin"
  scan_interval: 30
  resource: http://192.168.86.31/econet/editParams
  sensor:
    - name: "Heat pump SCOP"
      unique_id: 'f541d4d5-b12a-4c2b-9566-d284d75d5c7e'
      value_template: "{{ value_json['informationParams']['222'][1][0]
      [0] }}"
      state_class: measurement

    - name: "Circuit 1 thermostat day setting"
      unique_id: '38edd4cd-32d9-45c3-bc97-af814b29fbc5'
      value_template: "{{ value_json['data']['238']['value'] }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

    - name: "Circuit 1 thermostat night setting"
      unique_id: 'da60f424-fc3c-49d4-9320-3eb5076c2b81'
      value_template: "{{ value_json['data']['239']['value'] }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

    - name: "Circuit 1 hysteresis"
      unique_id: 'circuit1 hysteresis'
      value_template: "{{ value_json['data']['240']['value'] }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

    - name: "Circuit 1 weather comp curve"
      unique_id: 'c1 weather curve'
      value_template: "{{ value_json['data']['273']['value'] }}"
      state_class: measurement

    - name: "Circuit 1 curve shift"
      unique_id: 'circuit1 curve shift'
      value_template: "{{ value_json['data']['275']['value'] }}"
      state_class: measurement

    - name: "DHW thermostat setting"
      unique_id: '458520e1-7dd6-42a6-83d0-40aa736ffc60'
      value_template: "{{ value_json['data']['103']['value'] }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

    - name: "DHW thermostat hysteresis"
      unique_id: 'dhw hysteresis'
      value_template: "{{ value_json['data']['104']['value'] }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

#- authentication: basic
#  username: "admin"
#  password: "admin"
#  scan_interval: 30
#  resource: http:/192.168.86.31/econet/editParams
#  sensor:
    - name: "Heat pump fan speed"
      unique_id: '1828f0ea-5f4e-4d3e-8d24-50a7670bda97'
      value_template: "{{ value_json['informationParams']['22'][1][0]
      [0] }}"
      unit_of_measurement: "rpm"
      state_class: measurement

    - name: "Heat pump electrical power"
      unique_id: '3f91960f-84bd-4c24-979e-baa3cb323e8a'
      value_template: "{{ value_json['informationParams']['211'][1][0]
      [0] }}"
      unit_of_measurement: "kW"
      device_class: power
      state_class: measurement

    - name: "Heat pump thermal power"
      unique_id: '1e66d359-d68f-4288-b461-5edaa227e682'
      value_template: "{{ value_json['informationParams']['212'][1][0]
      [0] }}"
      unit_of_measurement: "kW"
      device_class: power
      state_class: measurement

    - name: "Heat pump COP"
      unique_id: '98e05155-0dd7-476c-bd62-37370a429f37'
      value_template: "{{ value_json['informationParams']['221'][1][0]
      [0] }}"
      state_class: measurement

#    - name: "Heat pump flow rate"
#      unique_id: '43071e0d-09db-4e90-ae85-acf83c125b5a'
#      value_template: "{{ value_json['informationParams']['231'][1][0]
#      [0] }}"
#      unit_of_measurement: "l/s"
#      device_class: volume_flow_rate
#      state_class: measurement

# Water flow rate in cuM/hr * 10

    - name: "Heatpump Flow Rate"
      unique_id: 'flowrate'
      value_template: "{{ value_json['data']['1211']['value'] }}"
      state_class: measurement

    - name: "Register65"
      unique_id: 'register65'
      value_template: "{{ value_json['data']['1212']['value'] }}"
      state_class: measurement

#    - name: "Register68"
#      unique_id: 'register68'
#      value_template: "{{ value_json['data']['1215']['value'] }}"
#      state_class: measurement

 #   - name: "Fan Speed2"
 #     unique_id: 'Fanspeed2'
 #     value_template: "{{ value_json['data']['1219']['value'] }}"
 #     unit_of_measurement: "rpm"
 #     state_class: measurement

    - name: "Target Flow Temp"
      unique_id: 'targetflowtemp'
      value_template: "{{ value_json['informationParams']['12'][1][0][0]}}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

# Circuit 1 calculated flow temp

    - name: "C1 Desired Heating LWT"
      unique_id: 'c1flow'
      value_template: "{{ value_json['informationParams']['93'][1][0][0]}}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

# Water pump is info 11

    - name: "Water Pump running"
      unique_id: 'pump_running'
      value_template: "{% set s = value_json['informationParams']['11'][1][0][0] %} {% if s == '2' %} {{'No'}} {% elif s=='0' %} {{'Yes'}} {% else %} {{s}} {% endif %}"
 
# Heating demanded?

    - name: "Heat Demanded"
      unique_id: 'heatdemanded'
      value_template: "{%set s= value_json['informationParams']['26'][1][0][0] %} {% if s == '1' %} {{'No'}} {% elif s == '0' %} {{'Yes'}} {% else %} {{s}} {% endif %}"

    - name: "Information26"
      unique_id: 'information26'
      value_template: "{%set s= value_json['informationParams']['26'][1][0][0] %} {% if s == '1' %} {{'No'}} {% elif s == '0' %} {{'Yes'}} {% else %} {{s}} {% endif %}"
#      value_template: "{{ value_json['informationParams']['26'][1][0][0]}}"

# duplicate of 094 - CH valve state?

    - name: "CH or DHW"
      unique_id: 'chordhw'
      value_template: "{%set s= value_json['informationParams']['13'][1][0][0] %} {% if s == '1' %} {{'CH'}} {% elif s== '0' %} {{'HW'}} {% else %} {{s}} {% endif %}"

    - name: "Information13"
      unique_id: 'information13'
      value_template: "{%set s= value_json['informationParams']['13'][1][0][0] %} {% if s == '1' %} {{'CH'}} {% elif s== '0' %} {{'HW'}} {% else %} {{s}} {% endif %}"

# the following is also apparently under parameter 24,72 and 81 !!

    - name: "Actual Flow Temp"
      unique_id: 'actualflowtemp'
      value_template: "{{ value_json['informationParams']['14'][1][0][0]}}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

# the following is also apparently under parameter 25, and 91 !!

    - name: "Actual Return Temp"
      unique_id: 'actualreturntemp'
      value_template: "{{ value_json['informationParams']['15'][1][0][0]}}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

#      water pump runtime hrs, since last power cycle
#    - name: "Information201202"
#      unique_id: 'information201202'
#      value_template: "{{ value_json['informationParams']['201'][1][0][0]}}"

#    - name: "Information2032042"
#      unique_id: 'information203204'
#      value_template: "{{ value_json['informationParams']['203'][1][0][0]}}"

#    - name: "Heating Energy"
#      unique_id: 'information203'
#      value_template: "{{ value_json['informationParams']['203'][1][0][0] | float / 1000}}"
#      unit_of_measurement: "kWh"
#      device_class: energy
#      state_class: measurement

#    - name: "DHW Heating Energy"
#      unique_id: 'information204'
#      value_template: "{{ value_json['informationParams']['204'][1][0][0] | float / 1000}}"
#      unit_of_measurement: "kWh"
#      device_class: energy
#      state_class: measurement

# compressor Hz?

    - name: "Compressor Freq"
      unique_id: 'compressor freq'
      value_template: "{{ value_json['informationParams']['21'][1][0][0]}}"
      unit_of_measurement: "Hz"
      device_class: frequency
      state_class: measurement

    - name: "Information21"
      unique_id: 'information21'
      value_template: "{{ value_json['informationParams']['21'][1][0][0]}}"
      unit_of_measurement: "Hz"
      device_class: frequency
      state_class: measurement

    - name: "Actual DHW Temp"
      unique_id: 'actualdhwtemp'
      value_template: "{{ value_json['informationParams']['61'][1][0][0]}}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

# CH Valve State?

    - name: "Information94"
      unique_id: 'information94'
      value_template: "{{ value_json['informationParams']['94'][1][0][0]}}"

    - name: "Information95"
      unique_id: 'information95'
      value_template: "{{ value_json['informationParams']['95'][1][0][0]}}"

    - name: "HP reported Ambient"
      unique_id: 'hpambienttemp'
      value_template: "{{ value_json['informationParams']['23'][1][0][0]}}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

    - name: "DHW Load time"
      unique_id: 'dhw load time'
      value_template: "{{ value_json['data']['113']['value'] }}"
      state_class: measurement

    - name: "DHW start 1 loading"
      unique_id: 'dhw start load'
      value_template: "{{ value_json['data']['115']['value'] }}"

    - name: "DHW work mode"
      unique_id: 'dhw work mode'
      value_template: "{% set s= value_json['data']['119']['value'] %} {% if s==2 %} {{'Scheduled'}} {% elif s==1 %}  {{'On'}} {% elif s==0 %} {{'Off'}} {% else %} {{s}} {% endif %}"

    - name: "Circuit1 work mode"
      unique_id: 'c1 work mode'
      value_template: "{% set s= value_json['data']['236']['value'] %}  {% if s==3 %} {{'Scheduled'}} {% elif s==1 %} {{'Day'}} {% elif s==2 %} {{'Night'}} {% elif s==0 %} {{'Off'}} {% else %} {{s}} {% endif %}" 

- authentication: basic
  username: "admin"
  password: "admin"
  scan_interval: 30
  resource: http://192.168.86.31/econet/regParams
  sensor:
 #   - name: "Hot water cylinder"
 #     unique_id: 'b9c0657f-e4cb-460d-b10f-f39092f5be62'
 #     value_template: "{{ value_json.curr.TempCWU }}"
 #     unit_of_measurement: "°C"
 #     device_class: temperature
 #     state_class: measurement

    - name: "Exterior weather sensor"
      unique_id: '230ae67e-169a-4a26-98b1-851d9f39492c'
      value_template: "{{ value_json.curr.TempWthr }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

# 1 if (water circulation) pump is on
#    - name: "AxenUpperPump"
#      unique_id: 'axenupperpump'
#      value_template: "{{ value_json.curr.AxenUpperPump }}"
#      unit_of_measurement: "rpm"
#      state_class: measurement

#    - name: "Target flow temperature"
#      unique_id: 'a41f64ea-f29c-46b3-a29c-eb575f5b623f'
#      value_template: "{{ value_json.curr.HeatSourceCalcPresetTemp }}"
#      unit_of_measurement: "°C"
#      device_class: temperature
#      state_class: measurement

#    - name: "Heat pump inlet temperature"
#      unique_id: '5755ad9c-5707-4754-9920-74e6fc499616'
#      value_template: "{{ value_json.curr.AxenReturnTemp }}"
#      unit_of_measurement: "°C"
#      device_class: temperature
#      state_class: measurement

#    - name: "Heat pump outlet temperature"
#      unique_id: '2d68ee3a-6345-4d1e-949d-7952ad61f866'
#      value_template: "{{ value_json.curr.AxenOutgoingTemp }}"
#      unit_of_measurement: "°C"
#      device_class: temperature
#      state_class: measurement

#    - name: "Heat pump compressor frequency"
#      unique_id: '7786493f-70bd-4b87-9ad8-848a340aed23'
#      value_template: "{{ value_json.curr.AxenCompressorFreq }}"
#      unit_of_measurement: "Hz"
#      device_class: frequency
#      state_class: measurement

    - name: "Panel thermostat Temperature"
      unique_id: '4d98cf06-6b87-4193-9d0e-7ccf9c355386'
      value_template: "{{ value_json.curr.Circuit1thermostat }}"
      unit_of_measurement: "°C"
      device_class: temperature
      state_class: measurement

    - name: "Heat pump valve state"
      unique_id: 'c1659951-b9b7-4bad-bdf8-ea5bc9dc30f4'
      value_template: "{{ value_json.curr.flapValveStates}}"
      device_class: enum

    - name: "Heat pump work state"
      unique_id: '3d61585c-47f7-42c8-9ca1-81dab1103680'
      value_template: "{% set s= value_json.curr.AxenWorkState %} {% if s==2 %} {{'Scheduled'}} {% elif s==1 %}  {{'On'}} {% elif s==0 %} {{'Off'}} {% else %} {{s}} {% endif %}"

    - name: "Grant Heat pump system pressure"
      unique_id: '550e8400-e29b-41d4-a716-446655440000'
      # Translates jq '.tilesParams[76][0][0][0]' to Jinja2
      value_template: "{{ value_json.tilesParams[76][0][0][0] }}"
      unit_of_measurement: "BAR"

While onboard metrics are very intersting the sensors are not very accurate. COP figures should be ignored.

1 Like

HA REST is working really well for me. Any speculation on Register65 and the information ones? some like 13 and 21 look like duplicates of CH or DHW and Compressor Freq.

Register 65 is always 0 for me.
Information 13 is either CH or DHW
Information 21 is duplicate of compressor freq
Information 26 is always Yes for me.
Information 94 is “On” during CH and “Off” during DHW
Information 95 is always 1 for me.

Thanks to all for sharing their work on this. Has anyone figured out which data in the REST output is the circulation pump PWM %?

P.S. Very quick and dirty emonhub interfacer for the Econet local http api at emonhub/src/interfacers/EmonHubEconet300Interfacer.py at local-production · dconlon/emonhub · GitHub. It seems like most folk are using HA these days but I’m happy to tune it up and submit a PR if it gets used.

Mmm I’m not sure, maybe @GSV3MiaC would know? I’m also interested to know if system water pressure metric is available.

That would be awesome! :folded_hands:

HA is great, but Emoncms is much better for data logging and detailed multigraphing with statistics etc. Although maybe I am biased :slight_smile:

1 Like

System pressure would be very useful. There’s a bunch of pressures/temps in the engineer (1234) menu for the refrigerant side which I can’t think of a use case for now but I’d still graph them if I could! I expect they are all in the JSON but it’ll take a bit of time to figure out what is what.

Okay it’ll be a couple of weeks but I’ll find some time to make a decent job of it and send it through. I’m an emonhub fan, it’s a nice lightweight bridge between varied data sources and Emoncms/MQTT so thanks for your efforts :

1 Like

There are a whole bunch of sensors in the 1234 engineer menu but they are not exposed in any of the econet endpoints I know about. In particular I can’t find pressure or pump PWM data (both directions, the ‘pwm feedback %’ is documented elsewhere as advising the status of the pump).

In the meantime, to keep HA users amused, these are the RESTful commands I have found a use for (this needs inserting in config.yaml, and then the IP address needs changed to whatever your econet is at). Use at own risk! You call them from HA using the YAML syntax in a script:

action: rest_command.set_ch1_night_temp
data:
value: “{{new_target}}”
response_variable: rest_response

What you do with the response variable is up to you (you may not even want one).

hopefully the rather critical indentation survives the pasting ..

rest_command:
  set_dhw_temp:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=103&newParamValue={{value}}&_=UID"

  set_dhw_hysteresis:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=104&newParamValue={{value}}&_=UID"

# 0 =off, 1=day, 2=night, 3=scheduled
  set_ch1_work_state:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=236&newParamValue={{value}}&_=UID"

# 0 =off, 1=on, 2=scheduled
  set_dhw_work_state:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=119&newParamValue={{value}}&_=UID"

  set_ch1_day_temp:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=238&newParamValue={{value}}&_=UID"

  set_ch1_night_temp:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=239&newParamValue={{value}}&_=UID"

  set_ch1_hysteresis:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=240&newParamValue={{value}}&_=UID"

  set_ch1_curve:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=273&newParamValue={{value}}&_=UID"

  set_ch1_curve_shift:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=275&newParamValue={{value}}&_=UID"

  boost_dhw:
    username: "admin"
    password: "admin"
    method: put
    url: "http://192.168.1.25/econet/newParam?newParamName=115&newParamValue=1&_=UID"

This lets me turn on/off CH (off before switch to DHW avoids some valve noise), and potentially vary the WC curve and offset based on a LOT of parameters, other than just what the thermostat thinks is happening in one room. OK, I admit this is buying a dog and barking yourself. :grinning_face:

1 Like

I’ve been working on integrating some sensors, numbers and selects for ecomax360i controller to the econet300 hacs integration: https://github.com/LeeNuss/ecoNET-300-Home-Assistant-Integration/tree/feature/sensors-inputs-ecomax360i
Controls are still bit clunky and needs thorougher testing, but the basics work. Happy to extend the available entities if anyone wants to use the integration

Ah cool, nice work. What’s the easiest way to test this via HACS?

you should be able to install it via hacs by adding https://github.com/LeeNuss/ecoNET-300-Home-Assistant-Integration as custom repo, make sure to remove jontofront’s original integration. Then download tag 1.2.0-a-ecomax360-1 (click “Need a different version”), restart & add device as usual with econet300 integration. hope that works, I currently can’t verify installing it via the hacs

Ok great, are you going to try and get jontofront’ to merge these changes into his main repo?

yeah that’s definitely the plan, but it might take a while to get that merged. The different api endpoint and his recent changes means there’s a decent amount of refactoring to do. I’ll keep working on supporting more functionality of the controller so it’s at least usable from my fork until merged.

1 Like

Firstly, my HP was installed just over a week ago and this integration has helped me loads!
I tried to install via HACS and it wouldn’t work. I don’t know if it’s because I previously had the jontofront original installed.

I manually installed from your dev branch and it’s working well. Now I’ll need to have a dig around to see if I can contribute in any way.

Thanks!

1 Like

I’ve finally gotten a bit of time to improve my emonhub interfacer. I’m working through some of the presently unidentified values in the REST endpoint and have identified a couple more.

1307 from the “data” data structure looks potentially interesting, for my install it ranges between 50 and 680, is roughly proportional to OAT and so roughly indirectly proportional to flow temp. Just wondered if anyone had any idea what it could be?

Hey, sorry I hadn’t posted here in a while. I extracted the filesystem of the econet300, so I got access to the complete application/webserver on it. With that I created a list of all the parameters exposed to the econet24 cloud service. It’s split into two tables for editable and read only parameters. As it’s too many parameters to do manually, I just splurged it through an LLM, so not sure it’s 100% accurate.
I marked all parameters if they are exposed to a local api endpoint (many of them are only readable via the cloud api endpoints).
However afaik from my testing all of the editable parameters can be modified via the local api even if they cannot be read.

parameter list:

Readonly parameter list (hard to find start of it in the document):

2 Likes

the 1307 parameter is labelled as AXEN_REGISTER_1238, so unfortunately not particularly revealing what this represents

Ah this is incredible, thank you! How did you extract this by the way?

Have you tried monitoring the service parameters read only values to try and marry it up to something in the interface? potentially could help

Amazing work! Is the system pressure parameter available via local REST?

Yes I have, there doesn’t seem to be anything that matches it. Equally there are lots of things in the service parameters that would be nice to get into EmonCMS that don’t seem to be in the REST.

There’s nothing that sounds like it in @LeeNuss’s extract. No value in /econet/regParams nor /econet/editParams changes when I change my system pressure. It has to be passing through the bridge as it gets to the cloud service but I don’t think its available in any of the known REST endpoints.

@LeeNuss did you find any REST endpoints other than /econet/[reg|edit|sys]Params in your filesystem extraction?