Iâm started to collect my Homevolt battery sensors from the local webserver in a package to access all data in Home-Assistant.
Please use if want, and post comments or improvements.
Invite: https://invite.tibber.com/zg5s6hew
- Enable local webserver on Homevolt
- Enabled at start or 3s press on left button under the hood
- Navigate to Homevolt local webserver by http://ip-address
- Force local webserver to enabled in Params
- Turn on password, if desired
- Turn on secure http, if desired
- Store Params to flash
Guide in swedish
Wi-Fi-guide
Om ditt batteri har dÄlig LTE-anslutning som orsakar lÄngsamma eller misslyckade uppdateringar, kan du manuellt stÀlla in Wi-Fi via batteriets portal:
Aktivera servicelÀge
- HÄll in knappen pÄ vÀnstra sidan av vÀxelriktaren i 3 sekunder.
- Anslut till batteriets Wi-Fi
- Ăppna Wi-Fi-instĂ€llningarna pĂ„ din telefon.
- Anslut till nÀtverket som heter HVSM-<QR-kod pÄ batteriet>.
- Konfigurera Wi-Fi via portalen
- NÀr du Àr ansluten bör en portal öppnas automatiskt.
- Klicka âKonfigurera Wi-Fiâ.
- VÀlj och anslut till kundens Wi-Fi-nÀtverk.
Om portalen inte öppnas automatiskt:
- Ăppna en webblĂ€sare och navigera till: http://10.133.70.1/ eller http://homevolt-.local
- Hitta serienumret pÄ vÀxelriktarens förpackning:
- Det börjar med 68b och ser ut som 68b6b34dcbac
Using custom components in package to calculate income:
to include packages folder to config.
homeassistant:
packages: !include_dir_named packages
Secrets file
- Change to http without s if not using local cert
- Change ip-address in the file.
homevolt_status: "https://192.168.1.100/status.json"
homevolt_ems: "https://192.168.1.100/ems.json"
homevolt_error: "https://192.168.1.100/error_report.json"
homevolt_schedule: "https://192.168.1.100/schedule.json"
homevolt_params: "https://192.168.1.100/params.json"
homevolt_logs: "https://192.168.1.100/logs.json"
homevolt_pass: "password_in_local_webserver"
packages\homevolt.yaml
### Homevolt package
# updated 2025-03-17
# Custom changes
# Uses nordpool integration for the sensor:
# sensor.nordpool_kwh_se3_sek_3_095
# ip and password in command_line curl
# price for battery and purchased day
# ------------------------------------------------ #
# REST integration
rest:
- resource: !secret homevolt_status
username: "admin"
password: !secret homevolt_pass
verify_ssl: false
scan_interval: 300
timeout: 30
sensor:
- name: "Homevolt status"
value_template: "{{ value_json.uptime if 'uptime' in value_json }}"
icon: "mdi:battery-clock"
json_attributes:
- uptime
- wifi_status
- lte_status
- mqtt_status
- w868_status
- ems_status
- name: "Homevolt LTE cellid"
value_template: >-
{{ ((value_json.lte_status.cell_id) | replace('"','')) if value_json is defined }}
icon: "mdi:sim"
- resource: !secret homevolt_ems
username: "admin"
password: !secret homevolt_pass
verify_ssl: false
scan_interval: 30
timeout: 30
sensor:
- name: "Homevolt EMS"
value_template: "{{ value_json.ems[0].ems_data.state_str }}"
icon: >-
mdi:battery-{{ int((float(value_json.ems[0].ems_data.soc_avg)/100) | round(-1), 0)
if not float(value_json.ems[0].ems_data.soc_avg) < 5 else 'outline' }}
json_attributes:
- ems
- aggregated
- sensors
- name: "Homevolt EMS error"
value_template: "{{ (value_json.ems[0].error_str)[:255] }}"
icon: "mdi:battery-unknown"
json_attributes_path: "$.ems[0]"
json_attributes:
- error_str
- name: "Homevolt EMS varning"
value_template: "{{ (value_json.ems[0].ems_data.warning_str | join(', ') | replace('_', ' ') | replace('ems', 'EMS'))[:255] }}"
icon: "mdi:battery-unknown"
json_attributes_path: "$.ems[0].ems_data"
json_attributes:
- warning_str
- name: "Homevolt EMS info"
value_template: "{{ (value_json.ems[0].ems_data.info_str | join(', ') | replace('_', ' ') | replace('ems', 'EMS'))[:255] }}"
icon: "mdi:battery-unknown"
json_attributes_path: "$.ems[0].ems_data"
json_attributes:
- info_str
- name: "Homevolt temperatur"
value_template: "{{ float(value_json.ems[0].ems_data.sys_temp,0)/10 }}"
icon: "mdi:battery-heart-variant"
unit_of_measurement: '°C'
device_class: temperature
- name: "Homevolt spÀnning L1"
value_template: "{{ value_json.ems[0].ems_voltage.l1 /10 }}"
unit_of_measurement: 'V'
icon: "mdi:meter-electric-outline"
device_class: voltage
- name: "Homevolt frekvens"
value_template: "{{ value_json.ems[0].ems_data.frequency /1000 }}"
unit_of_measurement: 'Hz'
icon: "mdi:meter-electric-outline"
device_class: frequency
- name: "Homevolt effekt"
value_template: "{{ value_json.ems[0].ems_data.power }}"
unit_of_measurement: 'W'
icon: "mdi:battery-sync-outline"
device_class: power
- name: "Homevolt energi producerat"
value_template: "{{ value_json.ems[0].ems_data.energy_produced /1000 }}"
unit_of_measurement: 'kW'
icon: "mdi:battery-positive"
device_class: power
- name: "Homevolt energi konsumerat"
value_template: "{{ value_json.ems[0].ems_data.energy_consumed /1000 }}"
unit_of_measurement: 'kW'
icon: "mdi:battery-negative"
device_class: power
- name: "Homevolt effekt tillgÀnglig"
value_template: >-
{{
float(value_json.ems[0].ems_prediction.avail_ch_pwr,0) -
float(value_json.ems[0].ems_prediction.avail_di_pwr,0)
}}
unit_of_measurement: 'kW'
icon: "mdi:battery-negative"
device_class: power
json_attributes_path: "$.ems[0].ems_prediction"
json_attributes:
- avail_ch_pwr
- avail_di_pwr
- name: "Homevolt konsumerat"
value_template: "{{ value_json.ems[0].ems_aggregate.exported_kwh }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-positive"
device_class: energy
state_class: total
- name: "Homevolt producerat"
value_template: "{{ value_json.ems[0].ems_aggregate.imported_kwh }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-negative"
device_class: energy
state_class: total
- name: "Homevolt bat0"
value_template: "{{ float(value_json.ems[0].bms_data[0].soc)/100 }}"
unit_of_measurement: '%'
icon: "mdi:battery-{{ float(value_json.ems[0].bms_data[1].soc)/100 | round(-1) }}"
- name: "Homevolt bat1"
value_template: "{{ float(value_json.ems[0].bms_data[1].soc)/100 }}"
unit_of_measurement: '%'
icon: "mdi:battery-{{ float(value_json.ems[0].bms_data[1].soc)/100 | round(-1) }}"
- name: "Homevolt bat0 laddningar"
value_template: "{{ value_json.ems[0].bms_data[0].cycle_count }}"
icon: "mdi:battery"
# Pulse CT
- name: "Homevolt nÀteffekt"
value_template: "{{ value_json.sensors[0].total_power }}"
unit_of_measurement: 'W'
icon: "mdi:battery-negative"
device_class: power
state_class: measurement
json_attributes_path: "$.sensors[0]"
json_attributes:
- phase
- name: "Homevolt nÀt konsumerat"
value_template: "{{ value_json.sensors[0].energy_imported }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-negative"
device_class: energy
state_class: total
- name: "Homevolt nÀt producerat"
value_template: "{{ value_json.sensors[0].energy_exported }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-positive"
device_class: energy
state_class: total
- name: "Homevolt solcell effekt"
value_template: "{{ value_json.sensors[1].total_power }}"
unit_of_measurement: 'W'
icon: "mdi:battery-positive"
device_class: power
state_class: measurement
json_attributes_path: "$.sensors[1]"
json_attributes:
- phase
- name: "Homevolt solcell konsumerat"
value_template: "{{ value_json.sensors[1].energy_imported }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-negative"
device_class: energy
state_class: total
- name: "Homevolt solcell producerat"
value_template: "{{ value_json.sensors[1].energy_exported }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-positive"
device_class: energy
state_class: total
- name: "Homevolt hushÄlleffekt"
value_template: "{{ value_json.sensors[2].total_power }}"
unit_of_measurement: 'W'
icon: "mdi:battery-negative"
device_class: power
state_class: measurement
json_attributes_path: "$.sensors.[2]"
json_attributes:
- phase
- name: "Homevolt batteri konsumerat"
value_template: "{{ value_json.sensors[2].energy_imported }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-negative"
device_class: energy
state_class: total
- name: "Homevolt batteri producerat"
value_template: "{{ value_json.sensors[2].energy_exported }}"
unit_of_measurement: 'kWh'
icon: "mdi:battery-positive"
device_class: energy
state_class: total
- resource: !secret homevolt_schedule
username: "admin"
password: !secret homevolt_pass
verify_ssl: false
scan_interval: 1800
sensor:
- name: "Homevolt schema"
value_template: >-
{{ (value_json.schedule | rejectattr('from', '>', (now().timestamp())) | rejectattr('to', '<', (now().timestamp())) | map(attribute='type') |
first |
replace('1', 'Ladda, uttag:') | replace('3', 'VĂ€nta') | replace('4', 'NĂ€t urladdning, ') | replace('2', 'Urladdning, ')) if 'schedule' in value_json
}} {{ (value_json.schedule | rejectattr('from', '>', (now().timestamp())) | rejectattr('to', '<', (now().timestamp())) | map(attribute='params.setpoint') | first) ~'W' if 'schedule' in value_json and
(value_json.schedule | rejectattr('from', '>', (now().timestamp())) | rejectattr('to', '<', (now().timestamp())) | map(attribute='params.setpoint') | first) > 0
}}
icon: >-
{% set type = (value_json.schedule | rejectattr('from', '>', (now().timestamp())) | rejectattr('to', '<', (now().timestamp())) | map(attribute='type') | first) %}
{{ 'mdi:battery-positive' if type == 1 }}
{{ 'mdi:battery-negative' if type == 2 or type == 4 }}
{{ 'mdi:battery-clock-outline' if type == 3 }}
json_attributes:
- local_mode
- schedule
- schedule_id
- name: "Homevolt schema nÀsta"
value_template: >-
{{ (time_until(as_datetime(float(value_json.schedule[1].from,0)),1)) if 'schedule' in value_json
}}
{{ (value_json.schedule[1].type |
replace('1', 'Ladda, uttag:') | replace('3', 'VĂ€nta') | replace('4', 'NĂ€t urladdning, ') | replace('2', 'Urladdning, ')) if 'schedule' in value_json
}}{{ (value_json.schedule[1].params.setpoint ) ~'W' if 'schedule' in value_json and 'setpoint' in value_json.schedule[1].params
}}
icon: "mdi:calendar-clock-outline"
# ------------------------------------------------ #
# Command line integration
# used to fetch json array
command_line:
- sensor:
name: "Homevolt logs"
scan_interval: 600
icon: "mdi:text"
command: >
echo "{\"logs\":" $(curl -sk -u 'admin:password' https://192.168.1.100/logs.json) "}"
value_template: >-
Error: {{ value_json.logs | selectattr('level','eq', 'error') | list | count }},
Warning: {{ value_json.logs | selectattr('level','eq', 'warning') | list | count }},
Info: {{ value_json.logs| selectattr('level','eq', 'info') | list | count }},
Total: {{ value_json.logs | length if value_json is defined }}
json_attributes:
- logs
# password in curl
- sensor:
name: "Homevolt parametrar"
scan_interval: 7200
icon: "mdi:console-line"
command: >
echo "{\"params\":" $(curl -sk -u 'admin:password' https://192.168.1.100/params.json) "}"
value_template: >-
{{ value_json.params | length if value_json is defined }}
json_attributes:
- params
# password in curl
- sensor:
name: "Homevolt errors"
scan_interval: 600
icon: "mdi:battery-alert-variant-outline"
command: >
echo "{\"errors\":" $(curl -sk -u 'admin:password' https://192.168.1.100/error_report.json) "}"
value_template: >-
{{ (value_json.errors |
rejectattr('message','in',
['','Throttled','idle','up2date','Rev:1 (435 mV)','Protocol version: 5']) |
rejectattr('message','contains', 'OK') |
rejectattr('message','contains', 'online') |
rejectattr('message','contains', 'No ') |
rejectattr('message','contains', ' 100.00%') |
rejectattr('message','contains', 'RSSI ') |
rejectattr('message','contains', ' valid') |
rejectattr('message','contains', ' available') |
map(attribute='message') | list | join(', '))[:255]
if value_json is defined }}
json_attributes:
- errors
- sensor:
name: "Homevolt console"
scan_interval: 2592000
icon: "mdi:console"
command: >-
echo "{\"result\": \"$( curl -sk -u admin:password -X POST --form cmd='{{
states('input_text.homevolt_cmd') if
states('input_text.homevolt_cmd') in ['time uptime','help'] or
states('input_text.homevolt_cmd').startswith('echo')
else
'echo command not accepted to send by HA'
}}' https://192.168.1.100/console.json | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g' )\"}"
value_template: >-
{{ value_json.result[:255] }}
json_attributes:
- result
# password in curl
# ------------------------------------------------ #
# Template integration
template:
- sensor:
name: "Homevolt intÀkt momentant"
unit_of_measurement: "SEK"
state: >-
{{ float(states('sensor.nordpool_kwh_se3_sek_3_095'), 0) * (float(states('sensor.homevolt_effekt'), 0)/1000) | round(2) }}
device_class: monetary
icon: "mdi:cash"
- sensor:
name: "Homevolt nÀt L1"
unit_of_measurement: "A"
state: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[0].amp, 0) }}"
device_class: current
state_class: measurement
icon: "mdi:current-ac"
attributes:
power: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[0].power,0) }}"
volt: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[0].voltage,0) }}"
- sensor:
name: "Homevolt nÀt L2"
unit_of_measurement: "A"
state: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[1].amp, 0) }}"
device_class: current
state_class: measurement
icon: "mdi:current-ac"
attributes:
power: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[1].power,0) }}"
volt: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[1].voltage,0) }}"
- sensor:
name: "Homevolt nÀt L3"
unit_of_measurement: "A"
state: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[2].amp, 0) }}"
device_class: current
state_class: measurement
icon: "mdi:current-ac"
attributes:
power: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[2].power,0) }}"
volt: "{{ float(state_attr('sensor.homevolt_nateffekt', 'phase')[2].voltage,0) }}"
- trigger:
- platform: time_pattern
hours: "/1"
sensor:
name: "Homevolt Ă„terbetalning"
unit_of_measurement: "SEK"
state: >-
{{ float(states('sensor.homevolt_intakt'),0) + float(this.attributes.gridrewards_per_dygn | default(0),0)* int((as_timestamp(now()) - as_timestamp(this.attributes.montage_datum | default('2025-01-01')))/60/60/24, 0) }}
device_class: monetary
icon: "mdi:cash"
attributes:
kostnad_batteri: "70000"
montage_datum: "2025-02-10"
gridrewards_per_dygn: "18.5"
sparat_nyttjande: "{{ float(states('sensor.homevolt_intakt'),0) }}"
gridrewards_total: "{{ float(this.attributes.gridrewards_per_dygn,0)* int((as_timestamp(now()) - as_timestamp(this.attributes.montage_datum | default('2025-01-01')))/60/60/24,0) }}"
beraknad_ater_days: >-
{% set per_day = ((this.state | default(0)) / int((as_timestamp(now()) - as_timestamp(this.attributes.montage_datum | default('2025-01-01')))/60/60/24, 0)) %}
{{ int((int(this.attributes.kostnad_batteri,0) - (float(this.state,0))) / per_day, 0) }}
beraknad_ater: "{{ (int(this.attributes.beraknad_ater_days,0) * (24*60*60) + as_timestamp(now())) | timestamp_custom('%Y-%m-%d', True) }}"
# ------------------------------------------------ #
# Sensor integration
sensor:
- platform: integration
source: sensor.homevolt_intakt_momentant
name: Homevolt intÀkt
#unit_time: h
method: left
round: 2
utility_meter:
yearly_earning:
source: sensor.homevolt_intakt
name: Homevolt intÀkt Är
cycle: yearly
net_consumption: true
monthly_earning:
source: sensor.homevolt_intakt
name: Homevolt intÀkt mÄnad
cycle: monthly
net_consumption: true
# Input for cmd
input_text:
homevolt_cmd:
name: Homevolt cmd input
initial: time uptime
# ------------------------------------------------ #
# Automation integration
automation:
- alias: Homevolt uppdatera schema varje timme
id: "homevolt_update"
description: "Uppdaterar schema sensor varje timme för att fÄ senaste schema | homevolt.yaml"
trigger:
- platform: time_pattern
minutes: 1
action:
- action: homeassistant.update_entity
data:
entity_id:
- sensor.homevolt_schema
- alias: Homevolt uppdatera console
id: "homevolt_update_console"
description: "Uppdaterar console-frÄga | homevolt.yaml"
trigger:
- platform: state
entity_id: input_text.homevolt_cmd
for: "00:00:06"
action:
- action: homeassistant.update_entity
data:
entity_id:
- sensor.homevolt_console