CJNE / ha-myenergi

Home Assistant integration for MyEnergi devices
MIT License
147 stars 33 forks source link

Support libbi export to grid #442

Closed plord12 closed 1 month ago

plord12 commented 1 year ago

Is your feature request related to a problem? Please describe.

Since libbi 5.408 ( https://support.myenergi.com/hc/en-gb/articles/19276846239377-libbi-Firmware-Version-5-408 ) libbi supports export to grid. This is useful if you wanted to use your libbi to charge by cheap electricity (or solar) and export when export prices are high.

Describe the solution you'd like

HA entity to turn on and off export to grid.

Describe alternatives you've considered

none

Additional context

Also raised https://github.com/CJNE/pymyenergi/issues/18 for the underlying library

plord12 commented 4 months ago

I don't think the Libbi supports on-demand charging? Or at least not yet. It does some weird thing with Agile tariffs where at 4pm it gets the next day's cheapest periods and charges itself at those times, but there's no way to forcibly charge it.

You can automate with home assistant ... something like -

alias: Electricity Rule 1a - start charging battery from grid (offpeak + intelligent)
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.octopus_energy_a_xxxxxxxx_intelligent_dispatching
    from: "off"
    to: "on"
condition: []
action:
  - service: retry.call
    target:
      entity_id: select.myenergi_libbi_operating_mode
    data:
      service: select.select_option
      option: Normal
      on_error:
        - service: script.debug
          data:
            message: Rule 1a:Failed to set libbi to Normal
  - service: retry.call
    target:
      entity_id: switch.myenergi_libbi_charge_from_grid
    data:
      service: switch.turn_on
      on_error:
        - service: script.debug
          data:
            message: Rule 1a:Failed to set libbi to charge from grid
mode: single
MaximumFish commented 4 months ago

You can automate with home assistant ... something like -

I could be mistaken but I don't think that does what you think it does. I'm pretty sure it just toggles the preference to enable grid charging on a schedule based on your tariff. The same toggle that you find in the app under the Charging Preference drop-down.

Though now that I've typed that out perhaps it could be fudged by setting the entire day as off-peak and then toggling that preference on and off....? πŸ€”

githubjonny commented 4 months ago

You can automate with home assistant ... something like -

I could be mistaken but I don't think that does what you think it does. I'm pretty sure it just toggles the preference to enable grid charging on a schedule based on your tariff. The same toggle that you find in the app under the Charging Preference drop-down.

Though now that I've typed that out perhaps it could be fudged by setting the entire day as off-peak and then toggling that preference on and off....? πŸ€”

I literally just thought the same thing. However, if 'normal' was converted to charge using that method, what mode would you use to discharge to the house (not discharge as that goes to the grid and house until bat is depleted)

MalcolmSpencer commented 4 months ago

you can always force it to charge manually when in normal mode, just manually set the tariff at a low rate in the required slots, set the SOC to the desired level and enable charge from grid. I just need to be able to automate this in HA. I don't think PYMyenergi 0.2.0 supports setting the tariff so I will just leave it at a flat tariff for the whole day and then use the service calls to set the SOC and enable charge from grid.

plord12 commented 4 months ago

You can automate with home assistant ... something like -

I could be mistaken but I don't think that does what you think it does. I'm pretty sure it just toggles the preference to enable grid charging on a schedule based on your tariff. The same toggle that you find in the app under the Charging Preference drop-down.

Though now that I've typed that out perhaps it could be fudged by setting the entire day as off-peak and then toggling that preference on and off....? πŸ€”

Yes, you need to disable the tariff (I set every 1/2 hour to 7.5p). The above has been working for me with the "pre-release" plugin mentioned here.

You can also do things like export the battery before offpeak starts.

I did a talk recently to U3ACommunities on my setup - see https://plord.co.uk/talks/how-to-reduce-your-electricity-bill-to-zero/

MaximumFish commented 4 months ago

Ooo, I'll have a look at that! Thanks.

githubjonny commented 4 months ago

I did a talk recently to U3ACommunities on my setup - see https://plord.co.uk/talks/how-to-reduce-your-electricity-bill-to-zero/

Just been watching that for the last hour, looks like you have done virtually the same as me. One thing you may find helpful is a page I set up to work out what size battery would be best for me. I'll not go into it in detail on here since its nothing to do with this module but url is eoob.co.uk.

plord12 commented 4 months ago

One thing you may find helpful is a page I set up to work out what size battery would be best for me. I'll not go into it in detail on here since its nothing to do with this module but url is eoob.co.uk.

Many thanks for sharing.

MaximumFish commented 4 months ago

Yes, our setups are very similar but I'd not twigged that I could trick the Libbi into charging "out of hours" like that, so I'll make that change on my end for sure.

plord12 commented 4 months ago

Yes, our setups are very similar but I'd not twigged that I could trick the Libbi into charging "out of hours" like that, so I'll make that change on my end for sure.

Off topic, I know, but still useful.

One thing I eventually did was to have counters "minutes to xxx" and "minutes since xxx". Eg -

template:
  - sensor:
    - name: "Minutes to start of cheap rate"
      unique_id: minutes_to_start_of_cheap_rate
      unit_of_measurement: "min"
      state: >
        {% set diff=(strptime(states('input_datetime.octopus_start_of_offpeak'),"%H:%M:%S")|as_timestamp() - strptime(now().strftime("%H:%M:%S"),"%H:%M:%S")|as_timestamp())/60  %}
        {% if diff < 0 %}
        {{ (24*60)+diff }}
        {% else %}
        {{ diff }}
        {% endif %}
    - name: "Minutes to end of cheap rate"
      unique_id: minutes_to_end_of_cheap_rate
      unit_of_measurement: "min"
      state: >
        {% set diff=(strptime(states('input_datetime.octopus_end_of_offpeak'),"%H:%M:%S")|as_timestamp() - strptime(now().strftime("%H:%M:%S"),"%H:%M:%S")|as_timestamp())/60  %}
        {% if diff < 0 %}
        {{ (24*60)+diff }}
        {% else %}
        {{ diff }}
        {% endif %}
    - name: "Minutes since start of cheap rate"
      unique_id: minutes_since_start_of_cheap_rate
      unit_of_measurement: "min"
      state: >
        {% set diff=(strptime(now().strftime("%H:%M:%S"),"%H:%M:%S")|as_timestamp() - strptime(states('input_datetime.octopus_start_of_offpeak'),"%H:%M:%S")|as_timestamp())/60  %}
        {% if diff < 0 %}
        {{ (24*60)+diff }}
        {% else %}
        {{ diff }}
        {% endif %}

where input_datetime.octopus_start_of_offpeak is stored when the interation changes (sometimes binary_sensor.octopus_energy_electricity_xxxxx_off_peak is not known) -

alias: Octopus - store offpeak end
description: ""
trigger:
  - platform: state
    entity_id:
      - >-
        binary_sensor.octopus_energy_electricity_xxxxx_off_peak
    attribute: current_end
    not_to:
      - unknown
      - unavailable
action:
  - service: input_datetime.set_datetime
    metadata: {}
    data:
      datetime: >
        {{
        ((state_attr('binary_sensor.octopus_energy_electricity_xxxxxx_off_peak',
        'current_end')- timedelta(seconds=30))|as_local()) }}
    target:
      entity_id: input_datetime.octopus_end_of_offpeak
mode: single

You can then figure out when to start exporting your saved solar before offpeak starts (if SOC is high you can start exporting sooner) -

alias: Electricity Rule 3 - export battery before cheap rate
description: >-
  0.6 slightly too early (5% left), 0.7 about right (0% left).  Cant export
  whilst charging car, but possibly could if charging is completed.
trigger:
  - platform: template
    value_template: >-
      {% if states('sensor.myenergi_libbi_soc')|is_number and
        states('sensor.minutes_to_start_of_cheap_rate')|is_number
      %} {{ (states('sensor.myenergi_libbi_soc')|float)*0.68 >
      states('sensor.minutes_to_start_of_cheap_rate')|float }} {% endif %}
condition:
  - condition: state
    entity_id: select.myenergi_libbi_operating_mode
    state: Normal
  - condition: numeric_state
    entity_id: sensor.minutes_to_start_of_cheap_rate
    above: 1
  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.myenergi_zappi_xxxx_plug_status
        state: EV Connected
      - condition: state
        entity_id: sensor.myenergi_zappi_xxxxx_plug_status
        state: Charging
action:
  - service: script.debug
    metadata: {}
    data:
      message: >-
        Rule 3: Started export - minutes to start of cheap rate {{
        states('sensor.minutes_to_start_of_cheap_rate') }} soc {{
        states('sensor.myenergi_libbi_soc') }} %
  - service: retry.call
    target:
      entity_id: select.myenergi_libbi_operating_mode
    data:
      service: select.select_option
      option: Export
      on_error:
        - service: script.debug
          data:
            message: Rule 3:Failed to set libbi to Export
mode: single

I found you had to be careful not to import & export at the same time (eg discharge battery & charge car).

MaximumFish commented 4 months ago

Oh that's a cool way to do it. Currently I've blocked out certain times through the evening to export, so at 20:30 it exports down to 50%, at 21:30 take it down to 25%, and so on. My thinking being that people are largely still awake at those times and while it's not the point of highest demand, it's still going to be used energy.

I've worked around the car issue by having the export stop if the car's plugged in and "intelligent dispatch" turns on. And I've worked around it exporting into the car by setting the export margin on the Zappi to be really high. Previously I'd set it to switch the Zappi to stopped if either the car is already plugged in when the trigger fires, or if there's an active export and the car goes from unplugged to plugged in.

(I hope trizmark doesn't mind us discussing all of this in a bug report!)

MaximumFish commented 4 months ago

Yes, you need to disable the tariff (I set every 1/2 hour to 7.5p)

Wondering how you managed this... If I do the same it complains that I've only set one rate and won't let me save it, and if I set it to a single rate tariff it removes the option to grid charge completely.

Edit: Never mind, I was able to set it from the website rather than the app. Remove the empty row of peak slots and that did the trick.

ragg987 commented 4 months ago

Edit: Never mind, I was able to set it from the website rather than the app. Remove the empty row of peak slots and that did the trick.

Yes was just about to post that - there must be additional validation on the App compared to website. The rate on the single line does not matter, it can also be a high rate line. I wonder if this is a bug that permits a workaround, if so ME could well remove it at some point. I hope they enhance the API to permit a forced charge at some point.

On that bug where the App does not show the SoC updated elsewhere, I have already raised this with ME and they have been able to replicate and added to backlog. https://myenergi.info/viewtopic.php?p=126458#p126458

Patiently awaiting this release of the add-on to make it to HA. Thanks for sharing @plord12 , it never occured to me to export during the day and charging at bight. I also have to negotiate the splitting of FiT from SEG with Octopus - not got round to it yet. My back of a fag packet suggests I could be paid to use energy in the summer months, should partially off-set what I pay to heat (ASHP) in the winter period.

MaximumFish commented 4 months ago

Oh god I've just made the most complicated couple of automations to turn Grid charging on and off! So many conditions to test against! Might post it tomorrow if it actually works and there's interest.

githubjonny commented 4 months ago

Anyone know if there's a way to pull the temperature of the inverter from the libbi? Would be nice to kick a CPU fan into action when xyz temp is reached.

MalcolmSpencer commented 4 months ago

Temperature is available on the historic data API https://s18.myenergi.net/cgi-jday-Lxxxxx-yyyy-mm-dd but not the real-time API used by the HA integration. On the historic API there is

Inverter temp Battery temp Battery radiator temp Ambient temp Controller temp

videojedi commented 4 months ago

One thing I forgot to mention: setting the charge target does not seem to be reflected in the ME mobile app. I'm on Android, using 3.3.2 (rev. 41) version of the app and it does not reflect the changes I do via the API. The new charge target is taken into account (based on my testing), but the app will cache whatever value you set there. 🀷

This seems to be the same for the iOS app. Successful charge target change from home assistant but not reported in app.

githubjonny commented 4 months ago

In order to see that you need to use the currently unreleased version that's included further up here. I'm waiting for my PR to be accepted for pymyenergi and once that's done I can submit my PR for ha-myenergi, which would include this functionality in the official release.

Hi @trizmark any updates from pymyenergi? Thanks again for all your hard work πŸ‘

trizmark commented 3 months ago

It's been a long time coming, but finally it's here! https://github.com/CJNE/ha-myenergi/pull/553

Apologies for the delay (new job, family stuff)

githubjonny commented 3 months ago

@trizmark great job πŸ‘πŸΌ πŸ‘πŸΌ

I'm still getting 0.0.27 in HACS. Can't see if this has been pushed through. Anyway to jump to the latest build via HA?

MaximumFish commented 3 months ago

Also eagerly waiting for the new release, though I note that the page for #553 says that some checks have failed?

I'm wondering if this new version will have a way to actually check and confirm the state of the "charge from grid" toggle? My automation completely failed a couple of nights ago because the myenergi API was down at 23:30 when it tried to turn on grid charging, and the "until" loop that was supposed to safeguard against failed commands was just checking the state of this toggle. It was only when I woke up to an empty battery that I realised it's just a dumb toggle and not actually read back from anywhere!

I've fixed that now by instead checking the state of sensor.myenergi_libbi_xxxxxxxx_status to make sure it's switched to "Target Charge", but it doesn't work for turning grid charging off in the morning due to the state changing overnight to "Full" when it's full. Turning off grid charging doesn't change this state at all (I think it needs to drop below 95% first?) and there doesn't seem to be anything else to check against.

For now I'm just going to have to toggle it and hope that the API is up and running, but it would be great to have something reliable to check against.

trizmark commented 3 months ago

The failed checks are for linting and testing. The linting issue is a conflict between black8 and reorder-imports. The test failure is due to me making app_password and email optional, while the test expects them to be mandatory.

The charge_from_grid toggle is read and updated every minute. If you change it from the app, the state will be updated within a minute. If there's an issue with the ME API, the control will become unavailable and any turn_on or turn_off will fail. My solution for this was to check the availability of the control at the beginning of my automation. If the control is available, then just go ahead and change its state. If it's unavailable, start a 2 minute timer and execute the same automation once the timer expires. It's a very simple way of handling this kind of failure.

MaximumFish commented 3 months ago

Hmm, it didn't work like that for me. I noticed that the API was being screwy when I went to bed at 23:00. The SoC sensor hadn't updated for a while and the ME app was showing all yellow warning triangles on everything, but I assumed my automation would take care of things when it came back up.

As it is though, HA saw a brief blip of "unavailable" that morning, but when the automation fired it was happy enough. The "until" loop thought that it had turned on successfully and the state didn't change at any point throughout the night, even after the API had come back at around 1:00. Essentially, HA thought that it was on but the Libbi did not.

Of course the version I'm using is a few revisions behind the current one now, so maybe it'll work better in 0.0.28? πŸ€”

image Note: The name of the automation firing at 23:30 is misleading. It now starts the grid charging, but it's a repurposed automation that would stop the Libbi entirely during non-off-peak intelligent dispatch windows and the internal name didn't change along with the display name I guess.

plord12 commented 3 months ago

Hmm, it didn't work like that for me. I noticed that the API was being screwy when I went to bed at 23:00. The SoC sensor hadn't updated for a while and the ME app was showing all yellow warning triangles on everything, but I assumed my automation would take care of things when it came back up.

We need a local API.

I've raised support requests to myenergi to this effect. The more of us who do the same the better.

trizmark commented 3 months ago

@MaximumFish I'll do some more testing to see how the integration behaves during an API outage. @plord12 Fully agree with you, local API all the way! In fact, I implemented local monitoring by tapping into the Modbus interface. It doesn't give me control, but I can see everything real-time and have access to data that's not exposed via the API.

MaximumFish commented 3 months ago

That would be awesome, thank you.

It's not a huge issue right now as the only times I've ever had issues is overnight when switching grid charging on and I can check that's worked via the "Target Charge" state. In the mornings I'm currently just checking the app manually to make sure it's turned off properly. Though I wonder if I can do something funky with watching the grid draw to figure out if it's switched or not...

@plord12 if I were to raise the local API issue too, what would I be asking for exactly? I don't think I'd get away with just saying "Local API plz" :)

plord12 commented 3 months ago

@plord12 if I were to raise the local API issue too, what would I be asking for exactly? I don't think I'd get away with just saying "Local API plz" :)

I would say something like -

"There have been several times recently that I've been unable to control my myenergi devices .. a couple of cases where my internet connection was unreliable and a couple where the myenergi server didn't seem to respond. Regardless of the cause, its vital I can control the myenergi devices at all times. I've read that most manufacturers provide a "local API" to make this work.

I see companies like Octopus are giving out such devices for free.

Can you raise an enhacement request to provide a (documentend) local API and update the app to use it when possible.

Of course, once this exists, 3rdaprty tools such as home assistant can also make use of it"

trizmark commented 3 months ago

You can also highlight the fact that if integrations switch to local API, then they could save on AWS costs!

MaximumFish commented 3 months ago

Cool, I'll send something in to add to the pile!

githubjonny commented 2 months ago

Hi @CJNE, do we have an ETA for the update? Be fantastic to take advantage of the charge feature for the libbi (opens up some massive savings)

githubjonny commented 2 months ago

Can anyone give me a rough guide on upgrading before the latest version is officially released? Got caught out with a scheduled charge today (left over from yesterday's free electric 1-2pm grrr). So looking to update for charge/discharge full control

trizmark commented 2 months ago

@githubjonny Here's the version that has been merged yesterday. You simply extract it in the custom_components folder of your HA install. (I'd suggest removing the existing myenergi directory from there.) Once done, restart HA, find the integration on the config screen and select 'Configure' - this is where you can add the app email/password. Without that some of the libbi controls will be 'unavailable'. myenergi-0.0.28-pre.tgz

githubjonny commented 2 months ago

@trizmark Thank you. I just went to do this now and saw that the update was available in HA :) Ran the update and all went well. However, I can't seem to get the libbi to charge using the "on" toggle on switch.myenergi_libbi_XXXXXX_charge_from_grid (removed id). Clicking doesn't seem to do anything.

When I view logbook I see: 20 August 2024 became unknown 19:34:57 - 19 minutes ago became unavailable 19:34:55 - 19 minutes ago

I then re-read the release notes and saw :

"In order to access the new functionality, the integration requires the app email and password (to access the OAuth controlled API calls). This can simply be done by 'Reconfiguring' the integration. The app email and password is optional and only required if someone owns a libbi."

I think this may be an issue for me as I use a google login for my myenergi account. Any ideas? I can change the status of the libbi at the moment (export, normal, stopped) so there is some control there.

trizmark commented 2 months ago

@githubjonny We found a workaround for that! So, you need to create a new ME account with email and pass and invite this new account to manage your house. The component already caters for this (there's an invitation ID in the API that needs to be saved/passed on) and it works fine.

githubjonny commented 2 months ago

@trizmark thanks for your help with this. I'll do that 1st thing tomorrow. It's interesting I can control the libbi discharge without a standard login though. Wonder if there's a way to control charging with just the API etc.

ragg987 commented 2 months ago

You can also use your original email and user it to create an account with a password, no need to add another account/email. The ME portal recognises it as being the same. This method worked for my original Google login.

Looking forward to installing this upgrade, thank you.

On Tue, 20 Aug 2024, 21:10 Zoltan, @.***> wrote:

@githubjonny https://github.com/githubjonny We found a workaround for that! So, you need to create a new ME account with email and pass and invite this new account to manage your house. The component already caters for this (there's an invitation ID in the API that needs to be saved/passed on) and it works fine.

β€” Reply to this email directly, view it on GitHub https://github.com/CJNE/ha-myenergi/issues/442#issuecomment-2299574483, or unsubscribe https://github.com/notifications/unsubscribe-auth/A6PXPUDNBGRJQFFKIWILZU3ZSOID3AVCNFSM6AAAAAA6RDVDPCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEOJZGU3TINBYGM . You are receiving this because you are subscribed to this thread.Message ID: @.***>

githubjonny commented 2 months ago

see this is why I love open source software. Within a few minutes had two replies both offered solutions.

I just created a new account and can confirm what @ragg987 said works. As soon as I created the account and logged in it had all my details.

Thanks again everyone.

githubjonny commented 2 months ago

Just an update, @trizmark I now can control the charge from the grid toggle :) thanks for your hard work on that one πŸ‘πŸΌ

Just wondered what everyone's doing regarding half hour time slots? I'm assuming two tier pricing with all half hours on the cheap tariff?

Although, now I've said that 'out loud', I guess just one tariff is only needed (assuming ME allows charging on a single tariff).

Nope, 1 tariff = no ability to charge

trizmark commented 2 months ago

@githubjonny Yeah, two tier pricing and all the slots on the cheap tarriff. That way you can toggle the charge from grid on and off to control when the libbi charges.

Wonder if there's a way to control charging with just the API etc.

The ME API uses two different authentication methods. Most of the old sutff uses digest (based on API key/secret) and some of the new stuff uses OAuth (based on username/password). The ME engineers hinted on the forums that they're planning to move everything over to OAuth, but it looks like that'll take a long time. The mode selection API call is based on old auth (which worked without app email/pass), but charging from grid toggle and charge target setting API calls are based on new auth (which didn't work).

githubjonny commented 1 month ago

Temperature is available on the historic data API https://s18.myenergi.net/cgi-jday-Lxxxxx-yyyy-mm-dd but not the real-time API used by the HA integration. On the historic API there is

Inverter temp Battery temp Battery radiator temp Ambient temp Controller temp

@MalcolmSpencer , Any guides on how to achieve this anywhere online?

Future-Surfer commented 1 month ago

Now that we can change operating mode to 'export', do we think there is any scope for setting/limiting charge/discharge rates?

githubjonny commented 1 month ago

That would be handy if possible. Currently I export my battery before the cheap session starts at a low amp rate (to help battery life). However would prefer to dump battery much quicker during octopus saving session without having to alter settings manually

trizmark commented 1 month ago

Limiting charge/discharge rates is a no-go at the moment. While technically it would be possible, the feature is not implemented by the controller and it's not exposed via the API. I can clearly see the modbus messages from the libbi controller that instruct the inverter as to what rate to charge/discharge with, but that's not useful at the moment.

trizmark commented 1 month ago

Temperature is available on the historic data API https://s18.myenergi.net/cgi-jday-Lxxxxx-yyyy-mm-dd but not the real-time API used by the HA integration. On the historic API there is Inverter temp Battery temp Battery radiator temp Ambient temp Controller temp

@MalcolmSpencer , Any guides on how to achieve this anywhere online?

Are you hoping to have this data in HA or just in general? I could add this to pymyenergi, but I don't think there's a way to add historical data to HA (well, not without touching the DB directly).

Future-Surfer commented 1 month ago

While technically it would be possible, the feature is not implemented by the controller and it's not exposed via the API.

That makes sense. Would be able to tell whether this sort of thing (limiting charge/discharge) is within the realm of possibility for myenergi to expose via the API at some point? Just want to have an idea of where to set my expectations :)

trizmark commented 1 month ago

Possibly at some point, but I don't see that being in the next 12 months. I know they're reworking the libbi controller firmware. Not sure how big the controller FW is and how much space there is for extra features. After all, it's only an ESP32 doing an awful lot of things.

G6EJD commented 1 month ago

Why hasn’t this ’issue’ been closed? It’s become a rambling set of comments.