For completeness, here’s the Home Assistant OpenEVSE sensor component. Let me know how you get on if you mange to test this:
I tried to implement that in my configuration.yaml file but it probably belongs in sensors.yaml because nothing showed up. I ran out of time to test, and now I’m in Munich waiting for my connecting flight.
Jake
I’m pretty sure you can added it to either file. The yaml syntax can be quite picky. See my openenergymonitor example where I added sensor info to confuguration,yaml
. Probably not best practice but works for simple setups:
Hi Glyn,
I managed to get one of my OpenEVSE units working with the new firmware, I have Hassio loaded in docker, I installed emoncms with docker, and I have the OpenEVSE posting to emoncms. Not going to lie, I feel pretty accomplished right now.
However, what I really want to do is ‘see’ if the car is connected to the OpenEVSE as a condition for presence detection if I can. I can get empty icons by using your configuration example above, but I don’t have those parameters set up in my emoncms, and I’m not even sure if ‘status’ exists.
Any pointers?
I have managed to get values in the icons now. I’ve been trying to convert the temperature to F, which I can see in emoncms, but not in hassio. Also, my car finished charging just about the same time I made the tweaks for the current reading, so I’m not sure if it’s correct or not.
Nice work @jakekooser, that sounds really great
It would be cool if you could share your .yaml setup and some screenshots to show off your setup.
I’ve finally got round to testing the OpenEVSE Home Assistant integration myself, however I’ve not been able to get it to work. I’ve entered the following into my config.yaml file, after a restart the metrics do not display and there are no errors in the logfile, any ideas?
- platform: openevse
host: 192.168.XX.XX
monitored_variables:
- status
- usage_session
- charge_time
Hi Glyn,
I am not sure if I ever got it working the way I wanted to with the IP address. I do know I enabled MQTT and just ended up connecting that to my MQTT server and it’s working fine.
This is what I have in my sensors.yaml file - I separated it out from the main configuration.yaml to save space.
### Smart car charging amps
- platform: mqtt
name: OpenEVSE amps
state_topic: "car/charging_amps"
unit_of_measurement: 'amps'
### Smart car connection status
- platform: mqtt
name: OpenEVSE status
state_topic: "car/status"
### OpenEVSE total KWh
- platform: mqtt
name: OpenEVSE KWh
state_topic: "openevse/kwh"
I use node-red to process the reading I get from the OpenEVSE like so:
I use a state-machine node to process the connection status from the EVSE to tell me on my phone (VIA MQTT message) if the car is charging, connected, or disconnected like so:
And that allows me to see a graph on a Lovelace history-graph card, and display the charging status and current as entities
Here’s what the graph looks like, I just came back from a dinner party and plugged the car in.
For me, it was easiest just to jump in with MQTT, since I really didn’t have much understanding of the Open Energy Monitor stuff. I still don’t really have a perfect grasp of MQTT, but it allowed me to get the information I wanted to see easily enough.
Hope this helps!
Jake
Thanks, I agree MQTT is the best way to do this. I’ve just seen an open issue on HA github discussion the openevse component:
https://github.com/home-assistant/home-assistant/issues/12954
User TonyApuzzo has developed a MQTT based solution which looks very good:
That looks pretty nice as well. I haven’t really needed any more information than my setup gathers. I really need to sort out a node-red automation to remind me if the car is not plugged in.
The core Home Assistant OpenEVSE integration is now working again and compatible with all OpenEVSE WiFi since about 2017 V2.x, V3.x and V4.x
A few tweets are still needed e.g truncate energy readings! But the basic data is updating as sensors in HA
To enable it just add the following to your HA configuration.yaml
and change the IP address to match your unit.
- platform: openevse
host: 192.168.86.242
monitored_variables:
- status
- charge_time
- rtc_temp
- ir_temp
- ambient_temp
- usage_session
- usage_total
Sensors will then appear in HA and can be put into UI cards in the usual way.
The integration is basic at the moment, but overtime more functions will be added e.g control.
If anyone wants to help with this effort here are some dev threads:
An alternative which could be used in conjunction is to embed the OpenEVSE UI inside a HA card e.g
Not working for me, keep getting authentication error, how do you add the username/password when creating the integration? FW 4.1.0 and latest HA
Ooh this exactly what I need, where I can find this?
Try clicking that link - in blue. (I haven’t checked, but it might go to somewhere helpful.)
Yup I eventually found the config file hidden in his github, messing with it now
Looks like that code is ancient in terms of Home Assistant, rest_cmd no longer exists and I have replaced it with rest_command like so:
rest_command:
openevse_rapi:
method: post
authentication: digest
username: !secret OPENEVSE_USERNAME
password: !secret OPENEVSE_PASSWORD
url: "{{ url | default('http://' ~ host ~ '/r?json=1&rapi=' ~ rapi, true) }}"
But authentication: digest
is not recognized so I have removed it.
Basically just errors:
2021-09-08 20:38:27 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'value_json' is undefined when rendering '{{- value_json.ret -}}'
2021-09-08 20:38:38 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'host' is undefined when rendering '{{ url | default('http://' ~ host ~ '/r?json=1&rapi=' ~ rapi, true) }}'
2021-09-08 20:38:38 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'rapi' is undefined when rendering '{{ url | default('http://' ~ host ~ '/r?json=1&rapi=' ~ rapi, true) }}'
2021-09-08 20:38:54 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data
I assume this worked ages ago but not since HA is updated so frequently.
I’m working on getting this to work too since the native integration is so limited.
Also the integration needs to be updated to the new rules on energy meters so it can easily be added to the Energy Dashboard. And ca we get the ability to turn on and off the schedule so we can charge on demand?
Yes there are many changes, I am going through them one by one but it’s hit and miss due to the intermittent wifi connection of the evse
Would be nice if someone else can confirm if it works ok, here is the updated code:
# ---
# #
# # Control an OpenEVSE Electric Car Charging Station.
# #
# # There are unfortunately quite a few pre-requisites needed to work with
# # OpenEVSE.
# #
# ## REQUIREMENTS ##
# #
# # Version 2.9.1 of OpenEVSE WiFi module, both MQTT and REST APIs are
# # used because each provides different capabilities.
# #
# # You must have MQTT setup in Home Assistant.
# #
# # Required custom components:
# # input_number (allows dynamic adjustment of min/max values)
# # input_select (allows label/value to be separately set)
# # rest_command (supports HTTP basic authentication required by OpenEVSE)
# #
# # Required secrets
# # See '../secrets-example.yaml' for required secrets
# #
# # You must configure the OpenEVSE wifi control panel Services Tab:
# # - Enable MQTT: Checked
# # - Host: Your hassio IP address where the MQTT broker is running
# # - Port: MQTT broker port (1883)
# # - Username: MQTT username for OpenEVSE (e.g. "openevse")
# # - Password: MQTT password for OpenEVSE
# # - Base-topic: openevse (or edit secrets)
# # - Voltage-topic: Unused
# #
# # Optional Solar PV divert (this is poorly tested as I don't have a PV setup)
# # - Enable Solar PV divert: checked
# # - Feed: openevse_solar
# #
# # For RAPI Details, see:
# # https://github.com/OpenEVSE/open_evse/blob/stable/firmware/open_evse/rapi_proc.h
# #
# # RAPI Service
# # When calling this, set service data for either the full URL in `url`
# # or set both `host` and `rapi` variables. `url` has precedence
# # This requires a rest_cmd that supports http basic auth
rest_command:
openevse_rapi:
method: post
username: !secret OPENEVSE_USERNAME
password: !secret OPENEVSE_PASSWORD
url: "{{ url | default('http://' ~ host ~ '/r?json=1&rapi=' ~ rapi, true) }}"
# # Sensors
sensor:
#Get OpenEVSE min/max current via REST
- platform: rest
name: "OpenEVSE RAPI $GC"
resource: !secret OPENEVSE_REST_GET_CURRENT_CAPACITY_RANGE
force_update: no
authentication: basic
username: !secret OPENEVSE_USERNAME
password: !secret OPENEVSE_PASSWORD
headers:
User-Agent: Home Assistant
Content-Type: application/json
json_attributes: [ 'cmd', 'ret' ]
value_template: >-
{{ value_json.ret }}
# Get OpenEVSE Current Settings via REST
- platform: rest
name: "OpenEVSE RAPI $GE"
resource: !secret OPENEVSE_R_GE
force_update: no
authentication: basic
username: !secret OPENEVSE_USERNAME
password: !secret OPENEVSE_PASSWORD
headers:
User-Agent: Home Assistant
Content-Type: application/json
json_attributes: [ 'cmd', 'ret' ]
value_template: >-
{{ value_json.ret }}
- platform: rest
name: "OpenEVSE RAPI $GG"
resource: !secret OPENEVSE_REST_GET_CHARGING_CURRENT_AND_VOLTAGE
force_update: yes
authentication: basic
username: !secret OPENEVSE_USERNAME
password: !secret OPENEVSE_PASSWORD
headers:
User-Agent: Home Assistant
Content-Type: application/json
json_attributes: [ 'cmd', 'ret' ]
value_template: >-
{{ value_json.ret }}
- platform: rest
name: "OpenEVSE Status"
resource: !secret OPENEVSE_R_STATUS
force_update: no
authentication: basic
username: !secret OPENEVSE_USERNAME
password: !secret OPENEVSE_PASSWORD
headers:
User-Agent: Home Assistant
Content-Type: application/json
json_attributes:
- "mode"
- "wifi_client_connected"
- "srssi"
- "ipaddress"
- "emoncms_connected"
- "packets_sent"
- "packets_success"
- "mqtt_connected"
- "ohm_hour"
- "free_heap"
- "comm_sent"
- "comm_success"
- "amp"
- "pilot"
- "temp1"
- "temp2"
- "temp3"
- "state"
- "elapsed"
- "wattsec"
- "watthour"
- "gfcicount"
- "nogndcount"
- "stuckcount"
- "divertmode"
- "solar"
- "grid_ie"
- "charge_rate"
- "divert_update"
value_template: >-
{{- value_json.state -}}
# The RAPI REST Sensor is very unreliable, so filter it
- platform: filter
name: "OpenEVSE Session Energy"
entity_id: sensor.openevse_session_energy_raw
filters:
- filter: outlier
window_size: 6
radius: 0.5
# Template Sensors
- platform: template
sensors:
openevse_session_energy_raw:
friendly_name: "OpenEVSE Session Energy (unfiltered)"
icon_template: mdi:gauge
device_class: energy
unit_of_measurement: 'kWh'
value_template: >-
{% set wattsec = state_attr('sensor.openevse_status', 'wattsec') | float(-1) %}
{% if wattsec >= 0 %}
{{ (wattsec / 3600000)|round(2) }}
{% else %}
unknown
{% endif %}
# Charging current from REST API
openevse_current_now_rest:
unique_id: openevse_current_now_rest
friendly_name: "OpenEVSE Current Now (REST)"
icon_template: mdi:current-ac
device_class: current
unit_of_measurement: 'A'
value_template: >-
{{- states('sensor.openevse_rapi_gg') |
regex_replace('^\$OK ([0-9]+) (-?[0-9]+).*', '\\1') | float(0) / 1000 -}}
# Combine both MQTT and REST sensors since neither ends up being super reliable
openevse_current_now:
unique_id: openevse_current_now
friendly_name: "OpenEVSE Current Now"
icon_template: mdi:current-ac
device_class: current
unit_of_measurement: 'A'
value_template: >-
{{-
([
state_attr('sensor.openevse_status','charge_rate') | float(0),
states('sensor.openevse_current_now_mqtt') | float(0)
] | max)
-}}
# Combine both MQTT and REST sensors since neither ends up being super reliable
openevse_pilot:
unique_id: openevse_pilot
friendly_name: "OpenEVSE Pilot"
icon_template: mdi:current-ac
device_class: current
unit_of_measurement: 'A'
value_template: >-
{{-
([
state_attr('sensor.openevse_status','pilot') | float(0),
states('sensor.openevse_pilot_mqtt') | float(0)
] | max)
-}}
openevse_pilot_rest:
friendly_name: "OpenEVSE Pilot (REST)"
icon_template: mdi:current-ac
device_class: current
unit_of_measurement: 'A'
value_template: "{{ state_attr('sensor.openevse_status', 'pilot') | float(-1) }}"
openevse_state:
friendly_name: "OpenEVSE State"
icon_template: >-
{%- if state_attr('sensor.openevse_status', 'state') | regex_match('^[01]$') -%}
mdi:power-plug-off
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^2$') -%}
mdi:car-electric
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^3$') -%}
mdi:battery-charging
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^([456789]|10)$') -%}
mdi:battery-alert
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^254$') -%}
mdi:sleep
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^255$') -%}
mdi:power-off
{%- else -%}
mdi:battery-unknown
{%- endif -%}
value_template: >-
{%- if state_attr('sensor.openevse_status', 'state') | regex_match('^[01]$') -%}
Not Connected
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^2$') -%}
Connected
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^3$') -%}
Charging
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^([456789]|10)$') -%}
Error ({{- state_attr('sensor.openevse_status', 'state') -}})
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^254$') -%}
Sleeping
{%- elif state_attr('sensor.openevse_status', 'state') | regex_match('^255$') -%}
Disabled
{%- else -%}
Unknown ({{- state_attr('sensor.openevse_status', 'state') -}})
{%- endif -%}
- platform: mqtt
name: "OpenEVSE Temp 2"
state_topic: !secret OPENEVSE_T_TEMP2
unit_of_measurement: '°F'
device_class: temperature
value_template: >-
{%- macro C2F(temperature) -%}
{% set tmp = (((temperature *9) /50.0) + 32) %}
{{- "%0.2f" % tmp -}}
{%- endmacro -%}
{{- C2F(value|float)|float -}}
- platform: mqtt
name: "OpenEVSE Current Now (MQTT)"
icon: mdi:current-ac
state_topic: !secret OPENEVSE_T_AMP
device_class: current
unit_of_measurement: "A"
value_template: >-
{{- (value|float / 1000.0) | round(1) -}}
- platform: mqtt
name: "OpenEVSE Pilot (MQTT)"
icon: mdi:current-ac
state_topic: !secret OPENEVSE_T_PILOT
device_class: current
unit_of_measurement: "A"
value_template: >-
{{- value|int -}}
- platform: mqtt
name: "OpenEVSE Total Energy"
unique_id: openevse_total_energy_01
icon: mdi:gauge-full
state_topic: !secret OPENEVSE_T_WH
state_class: total_increasing
device_class: energy
unit_of_measurement: kWh
value_template: >-
{{- value|float / 1000 | round(2) -}}
# Switches
switch:
- platform: template
switches:
openevse_enable:
friendly_name: "OpenEVSE Enable"
turn_off:
- service: rest_command.openevse_rapi
data:
url: !secret OPENEVSE_REST_DISABLE
turn_on:
- service: rest_command.openevse_rapi
data:
url: !secret OPENEVSE_REST_ENABLE
icon_template: >-
{%- if state_attr('sensor.openevse_status', 'state') | regex_match('^[0123]$') -%}
mdi:power-on
{%- else -%}
mdi:power-off
{%- endif -%}
value_template: >-
{{- state_attr('sensor.openevse_status', 'state') | regex_match('^[0123]$') -}}
openevse_divertmode:
friendly_name: "OpenEVSE Eco Divert"
turn_off:
- service: mqtt.publish
data:
topic: !secret OPENEVSE_T_DIVERT
retain: true
payload: 1
turn_on:
- service: mqtt.publish
data:
topic: !secret OPENEVSE_T_DIVERT
retain: true
payload: 2
icon_template: >-
{%- if state_attr('sensor.openevse_status', 'divertmode') | regex_match('^2$') -%}
mdi:solar-power
{%- else -%}
mdi:power-off
{%- endif -%}
value_template: >-
{{- state_attr('sensor.openevse_status', 'divertmode') | regex_match('^2$') -}}
input_boolean:
# When true causes pilot current changes to be persisted into the OpenEVSE
# firmware (otherwise saving pilot current is temporary) when this is OFF
# then the volatile parameter is sent when changing the current
openevse_save_current:
name: "OpenEVSE Persist Current"
initial: on
icon: mdi:sync
input_number:
openevse_pilot:
name: "OpenEVSE Current"
unit_of_measurement: "A"
min: 10
max: 32
initial: 16
step: 1
# Requires use of custom input_select component
input_select:
openevse_service_level:
name: OpenEVSE Service Level
options:
- "A"
- "1"
- "2"
icon: mdi:target
script:
set_openevse_max_current:
icon: mdi:content-save
alias: OpenEVSE Set Pilot
sequence:
- service: rest_command.openevse_rapi
data:
host: !secret OPENEVSE_HOST
rapi: "{{ '$SC ' ~ (states('input_number.openevse_pilot')|int) ~ (' V' if not is_state('input_boolean.openevse_save_current', 'on')) }}"
automation openevse:
- alias: Update OpenEVSE Min/Max Current
id: update_openevse_min_max_current
trigger:
platform: state
entity_id: sensor.openevse_rapi_gc
condition:
condition: template
value_template: >-
{{ state_attr('sensor.openevse_rapi_gc', 'ret') | regex_match('^\$OK [0-9]+ +[0-9]+') }}
action:
- service: input_number.set_value
data_template:
entity_id: input_number.openevse_pilot
# Restrict the min to 6A - 10A
min: >-
{%- set ret = state_attr('sensor.openevse_rapi_gc', 'ret') -%}
{%- set rgx = '(?<=^\$OK) +([0-9]+) +([0-9]+)' -%}
{%- set v = ret | regex_findall_index(rgx) -%}
{{- [10, [6, v[0]|int]|max] | min -}}
# Restrict the max to 32A even if L2 returns >32A
max: >-
{%- set ret = state_attr('sensor.openevse_rapi_gc', 'ret') -%}
{%- set rgx = '(?<=^\$OK )([0-9]+) +([0-9]+)' -%}
{%- set v = ret | regex_findall_index(rgx) -%}
{{- [32, v[1]|int]|min -}}
- id: update_input_number_openevse_pilot
alias: Update input_number OpenEVSE Current
description: >-
Reflect changes made to pilot current on OpenEVSE back to the input_number
slider position.
trigger:
platform: state
entity_id: sensor.openevse_pilot
condition:
condition: template
value_template: >-
{{
(states('sensor.openevse_pilot')|int >= state_attr('input_number.openevse_pilot', 'min')|int)
and
(states('sensor.openevse_pilot')|int <= state_attr('input_number.openevse_pilot', 'max')|int)
}}
action:
- service: input_number.set_value
data:
entity_id: input_number.openevse_pilot
value: "{{ states('sensor.openevse_pilot')|int }}"
- alias: Update OpenEVSE Service Level
id: update_openevse_service_level
description: >-
Reflect changes made to service level on the OpenEVSE back to Home Assistant.
trigger:
platform: mqtt
topic: !secret OPENEVSE_T_ISL
action:
service: input_select.select_option
data_template:
entity_id: input_select.openevse_service_level
option: >-
{%- for option in state_attr("input_select.openevse_service_level", "options") -%}
{%- if trigger.payload == option -%}
{{- state_attr("input_select.openevse_service_level", 'options')[loop.index - 1] -}}
{%- endif -%}
{%- endfor -%}
- alias: Set OpenEVSE Service Level
id: set_openevse_service_level
trigger:
platform: state
entity_id: input_select.openevse_service_level
action:
service: rest_command.openevse_rapi
data_template:
host: !secret OPENEVSE_HOST
rapi: >-
{%- for option in state_attr("input_select.openevse_service_level", "options") -%}
{%- if is_state("input_select.openevse_service_level", option) -%}
{{- '$SL+' ~ state_attr("input_select.openevse_service_level", 'options')[loop.index - 1] -}}
{%- endif -%}
{%- endfor -%}
FYI I would strongly advise against using RAPI as it is deprecated in the v4 firmware.
If you are missing anything thing from the WiFi API raise a ticket in the repo and it can probably be added.
You also should make use of the WebSocket as you will get much faster feedback and don’t have to poll the WiFi module all the time.
Also, also you can auto discover OpenEVSE units via mDNS or MQTT. Although this may need more of a ‘proper’ integration, I haven’t looked in to the details of Home Assistant yet.
I have started doing some documentation of the v4 API which might help you, there are also some examples of the API calls, but in short:
- status can be retrieved from the
/status
endpoint as you are doing, and as I mentioned could be updated via/ws
websocket -
OpenEVSE Enable
should be implemented using the/override
endpoint -
OpenEVSE Eco divert
should use set thecharge_mode
config -
OpenEVSE Current
should use the/claims
endpoint, although there is a bug in the current release that I have fixed on thejeremypoulter/issue9
branch