Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Predbat not predicting any battery usage #1964

Open
TonyHoyle opened this issue Feb 4, 2025 · 27 comments
Open

Predbat not predicting any battery usage #1964

TonyHoyle opened this issue Feb 4, 2025 · 27 comments
Assignees

Comments

@TonyHoyle
Copy link

Describe the bug
Predbat consistently suggests I'll use at most 0.005w of battery which means it never predicts any battery usage. Other values seem reasonable and historical battery usage is plotted correctly.

Used the fox.yaml from https://raw.githubusercontent.com/springfall2008/batpred/main/templates/fox.yaml with some minor adjustments for Octopus and setting the soc_max to 10.36 to match my battery.

Expected behaviour
Some prediction of usage, even it it's not accurate yet due to shortage of data.

Predbat version

8.13.3

Environment details

  • Fox ESS H1 G2, 2xEP5 batteries
  • HAOS installer

Screenshots

Image

Image

Log file
Can you capture a log file from the time of the issue, debug mode is not normally required.

Predbat debug yaml file
predbat_debug.yaml.txt

Enable debug mode and let Predbat run for one cycle. Look in the 'debug' directory under the Predbat add-on and take the .yaml file for the time period in question.
Rename the predbat_debug_XX_XX_XX.yaml to predbat_debug_XX_XX_XX.yaml.txt and upload it to Github. This will allow your plan to be reproduced and also stores all your settings for review.

@gcoan
Copy link
Collaborator

gcoan commented Feb 4, 2025

have you got some of the fox sensors set to kW rather than Watts or vice versa?

If you look in the apps.yaml documentation it explains what each sensor needs to be set to

@TonyHoyle
Copy link
Author

I don't see how that could be changed.. the sensors are what they are.. it's up to predbat to be compatible with them. This is the example config from the documentation, which should work.

@WyndStryke
Copy link

WyndStryke commented Feb 5, 2025

When I look at the power chart, the battery line looks normal to me. So I'm not sure what the difference is between your config and mine.

There is always the possibility that you happen to have a Fox firmware version which writes the wrong information into the modbus registers. Does it look correct when you look at the modbus integration entities on the settings/integrations page?

Image

I don't see how that could be changed..

It's easy enough to do by adding a template sensor to multiply or divide by 1000. However I understand that some conversions already happen internally (but aren't necessarily visible on the config/charts), for example the sensor.pv_power which confused me for a while. So a figure might be off by 1000x in the chart and the config, but be might correct in the plan (which is the important bit). #1870

I do think the fox.yaml could do with a bit of TLC, for example to enable Fox's 'feed-in first' mode (which I think corresponds to 'freeze charge'). But it is really up to us Fox users to propose & test the changes to fox.yaml, because Trevor does not have a Fox system. There's also some discussion here: #1928

For comparison purposes, here is my apps.yaml:

Note that I am running in 'readonly' mode, so don't know if the control side of things is working. I have also never succeeded in getting the carbon intensity working, it reads in the forecasts but that's it.

pred_bat:
  module: predbat
  class: PredBat

# MM version for KH7+ECS4300-H4  20241222
# soc_max nominal battery capacity for ECS4300-H4 =16.59kWh   (original was 8.29, maybe for ECS4300-H2)
# battery_rate_max maximum charge/discharge rate, 50A*230V=11500W (note that recommended is 35A, this is handled later) (original was 4200)
# inverter_limit 7000 for KH7 (was 5000, maybe for H1 5000)
# export_limit 7000 (was 3600 commented out, optional in this case since same as inverter_limit)
# inverter_limit_charge/_discharge 8050 (for ECS4300-H4 recommended charge rate 35A * 230v = 8050)
# battery_charge_power_curve for ECS4800, presumably similar to ECS4300, based on 50A max, original was commented out
# rates_import / rates_export as E-on Next Drive + E-on Export
# metric_standing_charge 0.5784 (57.84p)
#
# ### nordpool wholesale prices
#
# carbon_intensity_uk - integration installed
# then input_number.predbat_carbon_metric and switch.predbat_carbon_enable to enable it
#
# Turn on low power mode - switch.predbat_set_charge_low_power
#
# predbat_inverter_loss - 0.02

  # Sets the prefix for all created entities in HA - only change if you want to run more than once instance
  prefix: predbat

  # Timezone to work in
  timezone: Europe/London

  # Currency, symbol for main currency second symbol for 1/100s e.g. $ c or £ p or e c
  currency_symbols:
    - '£'
    - 'p'

  # Days previous is the number of days back to find historical load data
  # Recommended is 7 to capture day of the week but 1 can also be used
  # if you have more history you could use 7 and 14 (in a list) but the standard data in HA only lasts 10 days
  # https://springfall2008.github.io/batpred/apps-yaml/#days_previous
  # Average load data over previous 3 weeks for any given week day.  Homeassistant/configuration.yaml sets history to 22 days.
  days_previous:
  - 7
  - 14
  - 21

  # Number of threads to use in plan calculation
  # Can be auto for automatic, 0 for off or values 1-N for a fixed number
  threads: auto

  # XXX: This is a configuration template, delete this line once you edit your configuration
#  template: True

  # Set to auto-match with a GivEnergy serial number, but you can override the serial or the sensor names
  # if it doesn't work or if you have more than one inverter you will need to list both
  #geserial: 're:sensor.givtcp_(.+)_soc_kwh'
  #geserial2: 're:sensor.givtcp2_(.+)_soc_kwh'

  # Sets the maximum period of zero load before the gap is filled, default 30 minutes
  # To disable set it to 1440
  load_filter_threshold: 30

  #
  # Sensors, more than one can be specified and they will be summed up automatically
  #
  # For two inverters the load today would normally be the master load sensor only (to cover the entire house)
  # If you have three phase and one inverter per phase then you would need three load sensors
  #
  # For pv_today if you have multiple solar inverter inputs then you should include one entry for each inverter
  #
  load_today:
    - sensor.load_energy_today
  import_today:
    - sensor.grid_consumption_energy_today
  export_today:
    - sensor.feed_in_energy_today
  pv_today:
    - sensor.solar_energy_today

  # Load forecast can be used to add to the historical load data (heat-pump)
  # To link to Predheat
  # Data must be in the format of 'last_updated' timestamp and 'energy' for incrementing kWh
  #load_forecast:
  #  - predheat.heat_energy$external
  #
  # If you enable ge_cloud_data then the load/import and export data will be fetches from the GE cloud instead of from GivTCP sensors
  # this is usually less efficient and of course prone to internet downtime, but could be useful if you lost your GivTCP data
  # Set the serial to the inverter serial to pull the data from and the key to your API key
  # When this is set load_today, import_today and export_today are not used
  #
  #ge_cloud_data: False
  #ge_cloud_serial: '{geserial}'
  #ge_cloud_key: 'xxxx'
  #
  # Controls/status - must by 1 per inverter
  #
  num_inverters: 1

  inverter_type: FoxESS
  inverter:
    name: "FoxESS"
    has_rest_api: False
    has_mqtt_api: False
    has_service_api: True
    output_charge_control: "power"
    has_charge_enable_time: False
    has_discharge_enable_time: False
    has_target_soc: False
    has_reserve_soc: False
    charge_time_format: "S"
    charge_time_entity_is_option: False
    soc_units: "%"
    num_load_entities: 1
    has_ge_inverter_mode: False
    time_button_press: False
    clock_time_format: "%Y-%m-%d %H:%M:%S"
    write_and_poll_sleep: 2
    has_time_window: False
    support_charge_freeze: False
    support_discharge_freeze: False

  # Services to control charging/discharging
  charge_start_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Force Charge"
  charge_stop_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Self Use"
  discharge_start_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Force Discharge"

  #
  # Run balance inverters every N seconds (0=disabled) - only for multi-inverter
  #balance_inverters_seconds: 60
  #
  # When set use the REST API rather than HA entity for control, should be more reliable/faster to control
  # Set one per inverter
  # If using Docker then change homeassistant.local to the Docker IP address
  #givtcp_rest:
  #  - 'http://homeassistant.local:6345'
  #  - 'http://homeassistant.local:6346'

  # When enabled automatic restart will restart the add-on if communication fails
  # Example below is auto-restart for GivTCP add-on itself
  #auto_restart:
  #  - shell: 'rm -rf /homeassistant/GivTCP/*.pkl'
  #  - service: hassio/addon_restart
  #    addon: a6a2857d_givtcp

  #  Example on how to restart the inverter via GivTCP
  #  - service: switch.turn_on
  #    entity_id: switch.givtcp_{geserial}_reboot_invertor

  # If not using REST then instead set the Control here (one for each inverter)
  # You should keep this section even when using REST as a fallback if it fails and for charge curve calculations
  # bms_charge_rate_estimated template sensor 35*240 (8400W) regardless of the actual result from the integration
  
  # bms_charge_rate available on KH inverters, may need to enable the sensor via settings/integrations/FoxESS/device
  charge_rate:
    - sensor.bms_charge_rate
  discharge_rate:
    - sensor.bms_discharge_rate
  battery_power:
    - sensor.invbatpower
  pv_power:
    - sensor.pv_power_w
  load_power:
    - sensor.load_power
  #soc_kw:
  #  - sensor.inverter_bms_kwh_remaining
  

  soc_percent:
     - sensor.battery_soc
  soc_max:
#    - 8.29   (original, probably ECS4300-H2, guessing this is nominal rather than after DoD%)
    - 16.59
  # battery_rate_max = watts, KH7 50 amps max (battery voltage variable, 85-480, 300 recommended, max DC power 10500, max AC power 14000)
  #                           ECS4300-H4 16.59 nominal capacity, voltage 230.4, recommended discharge 35A (max 50).  35x230.4=8050 but 50x230=11500
  #                           ECS4300-H6 would be 24.8 nominal capacity, voltage 345.6, recommended discharge 35A (max 50).  35x345.6=12096
  # Note that the recommended is 35A but max is 50A.  inverter_limit_charge/_discharge will limit to 35A.
  battery_rate_max:
#    - 4200   (original, probably ECS4300-H2, recommended 35A * 115v)
    - 11500
  #reserve:
  #  - number.givtcp_{geserial}_battery_power_reserve
  #inverter_mode:
  #  - select.givtcp_{geserial}_mode
  #inverter_time:
  #  - sensor.givtcp_{geserial}_invertor_time
  #charge_start_time:
  #  - select.givtcp_{geserial}_charge_start_time_slot_1
  #charge_end_time:
  #  - select.givtcp_{geserial}_charge_end_time_slot_1
  #charge_limit:
  #  - number.givtcp_{geserial}_target_soc
  #scheduled_charge_enable:
  #  - switch.givtcp_{geserial}_enable_charge_schedule
  #scheduled_discharge_enable:
  #  - switch.givtcp_{geserial}_enable_discharge_schedule
  #discharge_start_time:
  #  - select.givtcp_{geserial}_discharge_start_time_slot_1
  #discharge_end_time:
  #  - select.givtcp_{geserial}_discharge_end_time_slot_1

  # Inverter max AC limit (one per inverter). E.g for a 3.6kw inverter set to 3600
  # If you have a second inverter for PV only please add the two values together
  inverter_limit:
#    - 5000     (original, Probably H1 5000)
    - 7000

  # Export limit is a software limit set on your inverter that prevents exporting above a given level
  # When enabled Predbat will model this limit
  export_limit:
   - 7000
  # - 3600    (original, was commented out)

  # Some inverters don't turn off when the rate is set to 0, still charge or discharge at around 200w
  # The value can be set here in watts to model this (doesn't change operation)
  #inverter_battery_rate_min:
  #  - 200

# This models the difference between the max charge rate and recommended charge rate. Max=50A, and recommended = 35A on ECS4300-H4, 230v, = 8050.
# Might be beneficial to drop charge rate below the recommended 8050 to protect from battery degradation.
  inverter_limit_charge:
   - 8050

  inverter_limit_discharge:
   - 8050

  # Workaround to limit the maximum reserve setting, some inverters won't allow 100% to be set
  # Comment out if your inverter allows 100%
  #inverter_reserve_max : 98

  # Some batteries tail off their charge rate at high soc%
  # enter the charging curve here as a % of the max charge rate for each soc percentage.
  # the default is 1.0 (full power)
  # The example below is from GE 9.5kwh battery with latest firmware and gen1 inverter
  #battery_charge_power_curve:
  #  100 : 0.15
  #  99 : 0.15
  #  98 : 0.22
  #  97 : 0.31
  #  96 : 0.42
  #  95 : 0.48
  #  94 : 0.58
  #  93 : 0.68
  #  92 : 0.77
  #  91 : 0.85
  #  90 : 0.94
  #battery_discharge_power_curve:
  #  4: 1.0
### ECS4800 Charge curve with 50amps as 1.0 https://www.foxesscommunity.com/viewtopic.php?p=4554#p4554
### Linear from 80%-97% then drops abruptly.
  battery_charge_power_curve:
    100 : 0.05
    99 : 0.10
    98 : 0.20
    97 : 0.32
    96 : 0.36
    95 : 0.40
    94 : 0.44
    93 : 0.48
    92 : 0.52
    91 : 0.56
    90 : 0.60
    89 : 0.64
    88 : 0.68
    87 : 0.72
    86 : 0.76
    85 : 0.80
    84 : 0.84
    83 : 0.88
    82 : 0.92
    81 : 0.96

#  battery_temperature:
#   - sensor.bms_cell_temp_low  (KH register 37618, x10)
#
#  # Battery temperature charge adjustment curve
#  # Specific in C which is a multiple of the battery capacity
#  # e.g. 0.33 C is 33% of the battery capacity
#  # values unspecified will be assumed to be 1.0 hence rate is capped by max charge rate
# Battery temperature curve based on recent Fox ESS firmware with 50A as max charge rate.  
#     https://www.youtube.com/watch?v=nDAw0KAYvcE&list=WL&index=86&t=328s
#     <0c 0A, 0-4c 5A, 5-9c 10A, 10-14c 15A, 15-19c 25A, 20-44c 50A, 45-49c 25A, 50-53c 20A, 54,55c 3A, 55c+ 0A
#  battery_temperature_history: sensor.bms_cell_temp_low
#  battery_temperature_charge_curve:
#    19: 0.5
#    18: 0.5
#    17: 0.5
#    16: 0.5
#    15: 0.5
#    14: 0.30
#    13: 0.30
#    12: 0.30
#    11: 0.30
#    10: 0.30
#    9: 0.20
#    8: 0.20
#    7: 0.20
#    6: 0.20
#    5: 0.20
#    4: 0.10
#    3: 0.10
#    2: 0.10
#    1: 0.10
#    0: 0.00    

  # Inverter clock skew in minutes, e.g. 1 means it's 1 minute fast and -1 is 1 minute slow
  # Separate start and end options are applied to the start and end time windows, mostly as you want to start late (not early) and finish early (not late)
  # Separate discharge skew for discharge windows only
  inverter_clock_skew_start: 0
  inverter_clock_skew_end: 0
  inverter_clock_skew_discharge_start: 0
  inverter_clock_skew_discharge_end: 0

  # Clock skew adjusts the Appdaemon time
  # This is the time that Predbat takes actions like starting discharge/charging
  # Only use this for workarounds if your inverter time is correct but Predbat is somehow wrong (AppDaemon issue)
  # 1 means add 1 minute to AppDaemon time, -1 takes it away
  clock_skew: 0

  # Set these to match solcast sensor names
  # The regular expression (re:) makes the solcast bit optional
  # If these don't match find your own names in Home Assistant
  pv_forecast_today: sensor.solcast_pv_forecast_forecast_today
  pv_forecast_tomorrow: sensor.solcast_pv_forecast_forecast_tomorrow
  pv_forecast_d3: sensor.solcast_pv_forecast_forecast_day_3
  pv_forecast_d4: sensor.solcast_pv_forecast_forecast_day_4

  # car_charging_energy defines an incrementing sensor which measures the charge added to your car
  # is used for car_charging_hold feature to filter out car charging from the previous load data
  # Automatically set to detect Wallbox and Zappi, if it doesn't match manually enter your sensor name
  # Also adjust car_charging_energy_scale if it's not in kwH to fix the units
  car_charging_energy: 're:(sensor.myenergi_zappi_[0-9a-z]+_charge_added_session|sensor.wallbox_portal_added_energy)'

  # Defines the number of cars modelled by the system, set to 0 for no car
  num_cars: 0

  # If you have Octopus intelligent, enable the intelligent slot information to add to pricing
  # Will automatically disable if not found, or comment out to disable fully
  # When enabled it overrides the 'car_charging_planned' feature and predict the car charging based on the intelligent plan (unless octopus intelligent charging is False)
  # This matches either the intelligent slot from the Octopus Plugin or from the Intelligent plugin
  octopus_intelligent_slot: 're:(binary_sensor.octopus_intelligent_slot|re:binary_sensor.octopus_energy_intelligent_dispatching)'
  octopus_ready_time: 're:(time.octopus_energy_([0-9a-z_]+|)_intelligent_target_time)'
  octopus_charge_limit: 're:(number.octopus_energy([0-9a-z_]+|)_intelligent_charge_target)'

  # Example alternative configuration for Ohme integration release >=v0.6.1
  # octopus_intelligent_slot: 'binary_sensor.ohme_slot_active'
  # octopus_ready_time: 'time.ohme_target_time'
  # octopus_charge_limit: 'number.ohme_target_percent'

  # Octopus saving session points to the saving session Sensor in the Octopus plugin, when enabled saving sessions will be at the assumed
  # Rate is read automatically from the add-in and converted to pence using the conversion rate below (default is 8)
  octopus_saving_session: 're:(binary_sensor.octopus_energy([0-9a-z_]+|)_saving_session(s|))'
  octopus_saving_session_octopoints_per_penny: 8

  # Octopus free session points to the free session Sensor in the Octopus plugin
  # Note: You must enable this event sensor in the Octopus Integration in Home Assistant for it to work
  octopus_free_session: 're:(event.octopus_energy_([0-9a-z_]+|)_octoplus_free_electricity_session_events)'

  # Energy rates
  # Please set one of these three, if multiple are set then Octopus is used first, second rates_import/rates_export and latest basic metric

  # Set import and export entity to point to the Octopus Energy plugin import and export sensors
  # automatically matches your meter number assuming you have only one (no need to edit the below)
  # Will be ignored if you don't have the sensor but will error if you do have one and it's incorrect
  # NOTE: To get detailed energy rates you need to go in and manually enable the following events in HA
  #       event.octopus_energy_electricity_xxxxxxxx_previous_day_rates
  #       event.octopus_energy_electricity_xxxxxxxx_current_day_rates
  #       event.octopus_energy_electricity_xxxxxxxx_next_day_rates
  # and if you have export enable:
  #       event.octopus_energy_electricity_xxxxxxxx_export_previous_day_rates
  #       event.octopus_energy_electricity_xxxxxxxx_export_current_day_rates
  #       event.octopus_energy_electricity_xxxxxxxx_export_next_day_rates
  # Predbat will automatically find the event. entities from the link below to the sensors
  metric_octopus_import: 're:(sensor.(octopus_energy_|)electricity_[0-9a-z]+_[0-9a-z]+_current_rate)'
  metric_octopus_export: 're:(sensor.(octopus_energy_|)electricity_[0-9a-z]+_[0-9a-z]+_export_current_rate)'

  # Standing charge in pounds, can be set to a sensor or manually entered (e.g. 0.50 is 50p)
  # The default below will pick up the standing charge from the Octopus Plugin
  # The standing charge only impacts the cost graphs and doesn't change the way Predbat plans
  # If you don't want to show the standing charge then just delete this line or set to zero
  # metric_standing_charge: 're:(sensor.(octopus_energy_|)electricity_[0-9a-z]+_[0-9a-z]+_current_standing_charge)'
  metric_standing_charge: 0.5784

  # Or set your actual rates across time for import and export
  # If start/end is missing it's assumed to be a fixed rate
  # Gaps are filled with zero rate
  #rates_import:
  #  -  start: "00:30:00"
  #     end: "04:30:00"
  #     rate: 7.5
  #  -  start: "04:30:00"
  #     end: "00:30:00"
  #     rate: 40.0
  #
  #rates_export:
  #  -  rate: 4.2

  ### MM E-on Next Drive import (update as needed)
  ### Tariff name	Next Drive Fixed V5 Gas
  ### Starts from	12:00 AM, 31st Dec 2024
  ### Electricity
  ### Day rate	25.41p per kWh
  ### Night rate	6.70p per kWh
  ### Standing charge	57.84p per day
  ### Gas
  ### Unit rate	6.06p per kWh
  ### Standing charge	31.39p per day
  rates_import:
    -  start: "00:00:00"
       end: "07:00:00"
       rate: 6.7
    -  start: "07:00:00"
       end: "00:00:00"
       rate: 25.41
  
  rates_export:
    -  rate: 16.5
  
  ### MM Encourage export at peak time and before cheap rate period, discorage export during cheap period
  #rates_export_override:
#  - start: '00:00:00'
#    end: '07:00:00'
#    rate_increment: -2
#  - start: '16:00:00'
#    end: '19:00:00'
#    rate_increment: 2
#  - start: '22:30:00'
#    end: '23:45:00'
#    rate_increment: 4
  

  # Can be used instead of the plugin to get import rates directly online
  # Overrides metric_octopus_import and rates_import
  # rates_import_octopus_url : "https://api.octopus.energy/v1/products/FLUX-IMPORT-23-02-14/electricity-tariffs/E-1R-FLUX-IMPORT-23-02-14-A/standard-unit-rates"
  # rates_import_octopus_url : "https://api.octopus.energy/v1/products/AGILE-FLEX-BB-23-02-08/electricity-tariffs/E-1R-AGILE-FLEX-BB-23-02-08-A/standard-unit-rates"

  # Overrides metric_octopus_export and rates_export
  # rates_export_octopus_url: "https://api.octopus.energy/v1/products/FLUX-EXPORT-BB-23-02-14/electricity-tariffs/E-1R-FLUX-EXPORT-BB-23-02-14-A/standard-unit-rates"
  # rates_export_octopus_url: "https://api.octopus.energy/v1/products/AGILE-OUTGOING-BB-23-02-28/electricity-tariffs/E-1R-AGILE-OUTGOING-BB-23-02-28-A/standard-unit-rates/"
  # rates_export_octopus_url: "https://api.octopus.energy/v1/products/OUTGOING-FIX-12M-BB-23-02-09/electricity-tariffs/E-1R-OUTGOING-FIX-12M-BB-23-02-09-A/standard-unit-rates/"

  # Import rates can be overridden with rate_import_override
  # Export rates can be overridden with rate_export_override
  # Use the same format as above, but a date can be included if it just applies for a set day (e.g. Octopus power ups)
  # This will override even the Octopus plugin rates if enabled
  #
  #rates_import_override:
  # -  date: '2023-09-10'
  #    start: '14:00:00'
  #    end: '14:30:00'
  #    rate: 112
  #    load_scaling: 0.8

  # For pv estimate, leave blank for central estimate, or add 10 for 10% curve (worst case) or 90 or 90% curve (best case)
  # If you use 10 then disable pv_metric10_weight below
  # pv_estimate: 10

  # Days previous weight can be used to control the weighting of the previous load points, the values are multiplied by their
  # weights and then divided through by the total weight. E.g. if you used 1 and 0.5 then the first value would have 2/3rd of the weight and the second 1/3rd
  # Include one value for each days_previous value, each weighting on a separate line.
  # If any days_previous's that are not given a weighting they will assume a default weighting of 1.
  days_previous_weight:
    - 1

  # Number of hours forward to forecast, best left as-is unless you have specific reason
  forecast_hours: 48

  # Specify the devices that notifies are sent to, the default is 'notify' which goes to all
  #notify_devices:
  #  - mobile_app_treforsiphone12_2

  # Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
  # If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
  # One per inverter
  battery_scaling:
    - 0.9

  # Can be used to scale import and export data, used for workarounds
  import_export_scaling: 1.0

  # Export triggers:
  # For each trigger give a name, the minutes of export needed and the energy required in that time
  # Multiple triggers can be set at once so in total you could use too much energy if all run
  # Creates an entity called 'binary_sensor.predbat_export_trigger_<name>' which will be turned On when the condition is valid
  # connect this to your automation to start whatever you want to trigger
  export_triggers:
     - name: 'large'
       minutes: 60
       energy: 1.0
     - name: 'small'
       minutes: 15
       energy: 0.25

  # If you have a sensor that gives the energy consumed by your solar diverter then add it here
  # this will make the predictions more accurate. It should be an incrementing sensor, it can reset at midnight or not
  # It's assumed to be in Kwh but scaling can be applied if need be
  #iboost_energy_today: 'sensor.xxxxx'
  #iboost_energy_scaling: 1.0
  # Gas rates for comparison
  #metric_octopus_gas: 're:(sensor.(octopus_energy_|)gas_[0-9a-z]+_[0-9a-z]+_current_rate)'

  # Nordpool market energy rates
  #futurerate_url: 'https://dataportal-api.nordpoolgroup.com/api/DayAheadPrices?date=DATE&market=N2EX_DayAhead&deliveryArea=UK&currency=GBP'
  #futurerate_adjust_import: True
  #futurerate_adjust_export: False
  #futurerate_peak_start: "16:00:00"
  #futurerate_peak_end: "19:00:00"
  #futurerate_peak_premium_import: 14
  #futurerate_peak_premium_export: 6.5

  # Watch list, a list of sensors to watch for changes and then update the plan if they change
  # This is useful for things like the Octopus Intelligent Slot sensor so that the plan update as soon as you plugin in
  # Only uncomment the items you actually have set up above in apps.yaml, of course you can add your own as well
  # Note those using +[] are lists that are appended to this list, whereas {} items are single items only
  #watch_list:
  #  - '{octopus_intelligent_slot}'
  # - '{octopus_ready_time}'
  # - '{octopus_charge_limit}'
  #  - '{octopus_saving_session}'
  #  - '+[car_charging_planned]'
  #  - '+[car_charging_soc]'
  #  - '{car_charging_now}'
  
  # Carbon Intensity data from National grid
carbon_intensity: 're:(sensor.carbon_intensity_uk)'

@TonyHoyle
Copy link
Author

One thing I notice is charge_rate and discharge_rate are in amps not watts as the documentation says they should be, so either the documentation is wrong or they should be multiplied by sensor.batvolt..

But you're using the amps version and it appears to be working for you, so no idea..

@WyndStryke
Copy link

WyndStryke commented Feb 5, 2025

Well, firstly, I'm only using it for monitoring so if there are issues with control I wouldn't see them.

You could try hardwiring a template sensor to return an arbitrary figure in watts to see if that changes what you see, or even just comment out the sensors that you are concerned about. Perhaps if predbat doesn't like the units, it discards the sensor and just uses a default instead.

@zeclab
Copy link

zeclab commented Feb 5, 2025

Hi @TonyHoyle ,
I've just got my Fox setup last week and have been playing with Predbat. I see what you are saying about the BMS charge rate/discharge being in amps and can see the same as yourself on the chart.

Image

I was looking the entities and found sensor.battery_charge & sensor.battery_discharge in Kw and changed them to W.

Image

After updating the apps.yaml with these sensors and the chart is looking more along the lines of what I should be seeing?

Image

@TonyHoyle
Copy link
Author

TonyHoyle commented Feb 5, 2025

It isn't clear from the documentation what charge_rate is supposed to be - it just says 'Battery charge rate entity in watts'.
That could be interpreted the current charging current or the available charge rate.. based on its usage in the original yaml I assumed available charge rate & created a sensor for that.

That seems to clear up the graphs but of course may be wrong..

Edit: Turns out that was the wrong interpretation, so I removed them from this post.

@zeclab
Copy link

zeclab commented Feb 5, 2025

Cheers @TonyHoyle after adding those sensors, I'd say that my chart is looking more along the lines of what it should be.

Image

@gcoan
Copy link
Collaborator

gcoan commented Feb 5, 2025

It isn't clear from the documentation what charge_rate is supposed to be - it just says 'Battery charge rate entity in watts'.
That could be interpreted the current charging current or the available charge rate

The sensor that is configured in apps.yaml is expected to be an inverter sensor that (a) gives the current charge rate and (b) is something that Predbat can set to control the charge rate.

By using a template sensor for the entity, part b isn't going to work ....

Trefor has recently introduced the ability to control charge and discharge rate by % instead of watts value. Is this something the Fox inverter supports?

I can certainly expand the documentation to make this clearer, and if the Fox template needs changes, I can make those.

@WyndStryke
Copy link

WyndStryke commented Feb 5, 2025

These are all the sensors available, I think read-only

Sensors

Ambient Temp 30.0 °C
Battery Charge 0 kW
Battery Charge Today 16.0 kWh
Battery Charge Total 251.1 kWh
Battery Discharge 2.14 kW
Battery Discharge Today 15.0 kWh
Battery Discharge Total 267.3 kWh
Battery SoC 28%
Battery SoH Unavailable
Battery Temp 21.2 °C
BMS Cell mV High 32 mV   (obviously not correct)
BMS Cell mV Low 31 mV   (obviously not correct)
BMS Cell Temp High 17.8 °C
BMS Cell Temp Low 13.2 °C
BMS Charge Rate 20.0 A
BMS Discharge Rate 35.0 A
BMS kWh Remaining 16.58 kWh
Connection Status Connected
CT2 Meter 0.0 kW
Feed-in 1.65 kW
Feed-in Today 15.900 kWh
Feed-in Total 106.100 kWh
Grid Consumption 0 kW
Grid Consumption Today 17.4 kWh
Grid Consumption Total 292.0 kWh
Grid CT 1.65 kW
Grid Frequency 50.0 Hz
Grid Voltage 248 V
Input Energy Today 16.6 kWh
Input Energy Total 228.5 kWh
Inverter Battery Current 9 A
Inverter Battery Power 2.14 kW
Inverter Battery Voltage 230 V
Inverter Current 8 A
Inverter Fault Code None
Inverter Power 2.06 kW
Inverter State On Grid
Inverter Temp 23.5 °C
Load Energy Today 5.8 kWh
Load Energy Total 245.4 kWh
Load Power 0.42 kW
Max Charge Current 50.0 A
Max Discharge Current 50.0 A
Max SoC 100%
Min SoC 10%
Min SoC (On Grid) 10%
PV Power 0.0 kW
PV1 Current 0 A
PV1 Power 0.0 kW
PV1 Power Total 0.000 kWh
PV1 Voltage 0 V
PV2 Current 0 A
PV2 Power 0.0 kW
PV2 Power Total 58.288 kWh
PV2 Voltage 0 V
PV3 Current 0 A
PV3 Power 0.0 kW
PV3 Power Total 65.257 kWh
PV3 Voltage 8 V
PV4 Current 0 A
PV4 Power 0.0 kW
PV4 Power Total 0.012 kWh
PV4 Voltage 0 V
Solar Generation Today 9.0 kWh
Solar Generation Total 126.2 kWh
Version: Manager 1.37
Version: Master 1.41
Version: Slave 1.01
Yield Today 21.1 kWh
Yield Total 288.7 kWh

And there are also inputs

Force Charge Power 0.2kW
Force Discharge Power 2.0kW
Max SoC 100%
Min SoC 10%
Min SoC (On Grid) 10%
Work Mode Force Discharge

(a) gives the current charge rate and

What is meant by that exactly? The commanded charge rate, or the actual charge rate right at this instant?

For example, if you are in 'self-use' mode, charging the battery from PV, the actual charge rate (sensor.battery_charge) might be 200W or something like that, and changing from moment to moment. The max charge rate might be 20A (sensor.bms_charge_rate), but is not necessarily achievable, for example if the inverter limit is lower than that. The force charge rate (number.force_charge_power) might be 5kW (but it isn't in force charge mode, so that's irrelevant).

I don't think there is a single sensor which can be both written to and read, there's one for control & one for monitoring. OK yes you can read the control input, but it's not telling you anything other than what it was set to earlier.

To control the charge rates, the force charge power & force discharge power need to be written to (they take affect when in either force charge/discharge). However, if, for example, the battery is cold, the actual charge rate might be less than that (and this will be reflected in the sensor.bms_charge_rate being 5A or whatever instead of 20/25/50A), and also the instantaneous charge rate sensor.battery_charge being low too.

To monitor how much the battery is actually outputting in real time (rather than the max), you'd look at sensor.battery_charge (kW) and sensor.battery_discharge (kW), but I don't think you can write to them (or if you can, it'd be ignored).

Perhaps some sort of helper, which can accept inputs, writing them to number.force_charge_power, but reflects the sensor.battery_charge (if it is the instantaneous measurement which is needed) or sensor.bms_charge_rate * sensor.invbatvolt (if it is the maximum) when read?

Ultimately we could just hardwire either the input or the sensor to a constant. It's not critical to the core functionality as far as I understand it, although nice to have, particularly in winter when the battery might be cold, or if you want to throttle the charge rate to protect the battery via the low_charge functionality.

Trefor has recently introduced the ability to control charge and discharge rate by % instead of watts value. Is this something the Fox inverter supports?

Not as far as I know.

@TonyHoyle
Copy link
Author

Will predbat cope with the charge in watts and convert internally or is it necessary to create a battery_charge_w (and the same for discharge) in the same way as we create a pv_power_w?

@WyndStryke
Copy link

WyndStryke commented Feb 5, 2025

as we create a pv_power_w?

My understanding is that we don't actually need to create a pv_power_w, it'll convert internally for the key stuff (but the config page and the charts won't see the converted figure). So alternatively you can adjust the chart to also do the conversion.

Regarding on whether it can convert between kW and W for the charging rate, the chart is obviously off, but what does the plan show for the battery SoC (SoC%)? Does it go up and down as expected?

@WyndStryke
Copy link

WyndStryke commented Feb 6, 2025

Here are the various charge rate parameters charted over time. For work mode, pink is force-discharge, brown is force-charge, purple is feed-in first.

So the closest thing to an instantaneous battery charge sensor would be the inverter battery power sensor.invbatpower, which gives both positive and negative readings regardless of workmode (i.e., I think it is acting as if it was a CT clamp on the line feeding into the battery pack from the BMS).

Note that when there is no PV input, the sensor.battery_charge is always a bit below the commanded number.force_charge_power, presumably due to losses during AC/DC conversion. If there is PV, then obviously the sensor.battery_charge will be higher than the number.force_charge_power, since it is being charged simultaneously from both the AC side and the PV.

I'm sure that the number.force_charge_power is the one that we need to write to (likewise number.force_discharge_power). Note that number.force_charge_power is persistent across work modes, so you'd set it once and then could leave it henceforth, until you want to change it, and it can be queried too, giving the requested force charge power (which may or may not be achievable, depending on things like the battery temperature, which will affect the upper limit to charge speed, as reflected in the sensor.bms_charge_rate which is in amps, here it is flipping between 20A, 35A and 50A depending on sensor.bms_cell_temp_low. The sensor.battery_charge would also indirectly reflect that).

So if I understand things correctly (somewhat questionable!), we need an object to sit in the middle, if queried it should return sensor.battery_charge for the instantaneous battery charge rate (which could be changing from one moment to the next, if there is PV input, for example), and if written it should write to number.force_charge_power for the commanded force charge rate (in both case doing kW-W conversions if needed). Seems strange to me since it is conflating two different things, so I might be on the wrong track here.

Perhaps instead of sensor.battery_charge we should be looking at sensor.bms_charge_rate as an upper limit on the force charge rate, combined with the battery voltage. i.e., when queried we should return the lower of either number.force_charge_rate, or (sensor.bms_charge_rate*sensor.invbatvolt). This seems somewhat more logical to me since it is telling predbat what it is able to do, rather than whatever happens to be happening right now with PV and so forth.

Not entirely sure of the best way to do that, I'm still somewhat of a newbie. Perhaps a helper number + a couple of automations to write it's contents to number.force_charge_power if written to, and another to update it from sensor.bms_charge_rate whenever that changes?

Image

@gcoan
Copy link
Collaborator

gcoan commented Feb 6, 2025

So if I understand things correctly (somewhat questionable!), we need an object to sit in the middle, if queried it should return sensor.battery_charge for the instantaneous battery charge rate (which could be changing from one moment to the next, if there is PV input, for example), and if written it should write to number.force_charge_power for the commanded force charge rate (in both case doing kW-W conversions if needed). Seems strange to me since it is conflating two different things, so I might be on the wrong track here.

No, this isn't quite right.

Instantaneous current rate that the battery is charging or discharging at is defined as 'battery power' in apps.yaml https://springfall2008.github.io/batpred/apps-yaml/#battery-information

The charge rate https://springfall2008.github.io/batpred/apps-yaml/#chargedischarge-rate (either in watts or percentage value) is the rate that the inverter is set to force charge at. When you do a charge of the battery at full rate then predbat sets this to the maximum value for your inverter and then issues a 'start charge' command. To stop charging predbat will set this to zero as well as issuing a stop charge command.

from what you have said you just need to configure charge rate to number.force_charge_power in apps.yaml (and similar for discharge)

@WyndStryke
Copy link

from what you have said you just need to configure charge rate to number.force_charge_power in apps.yaml (and similar for discharge)

Great stuff, that sounds way easier :-)

Thank you.

@TonyHoyle
Copy link
Author

TonyHoyle commented Feb 6, 2025

It looks like that isn't enough.

Service call number/set_value data {'value': 5800, 'entity_id': 'number.force_charge_power'} failed with response None

predbat seems to be expecting this (write only) value to return something. It also seems to be writing watts not kw as required.

@WyndStryke
Copy link

WyndStryke commented Feb 6, 2025

If you look in the entities list for the FoxESS modbus device, can you see it's contents?

In the predbat/config page, I see:

charge_rate | - number.force_charge_power = 0.2 | - number.force_charge_power = 0.2-- | -- | --- number.force_charge_power = 0.2
discharge_rate | - number.force_discharge_power = 0.2 | - number.force_discharge_power = 0.2 - number.force_discharge_power = 0.2

and in development tools, I see:

number.force_charge_power
Force Charge Power | 0.2 | min: 0 max: 7 step: 0.001 mode: box unit_of_measurement: kW device_class: power friendly_name: Force Charge Power
-- | -- | --
Force Charge Power 0.2	
min: 0
max: 7
step: 0.001
mode: box
unit_of_measurement: kW
device_class: power
friendly_name: Force Charge Power

If you set a 'friendly name' when configuring the integration, the name might have a prefix (for example, number.foxess_force_charge_power)

@TonyHoyle
Copy link
Author

Min 0 and Max 7 would be a problem when predbat is trying to set it to 5800 :)

@WyndStryke
Copy link

WyndStryke commented Feb 6, 2025

Yeah I haven't tried to address the kW to W thing yet, not sure whether it will handle it or not. I'm running in read-only mode so my installation probably won't ever try to write to it.

As far as the plan and the charts are concerned, it all looks good, so it's just the control side of things? I'm using a manually configured charge curve (battery_charge_power_curve in the apps.yaml above) so that's one additional factor which is simpler on my side. If yours is trying to estimate a charge curve then that might also be affected by the kW/W thing.

@TonyHoyle
Copy link
Author

A W to KW translator seems to work, as in it sets what seem to be sane values.
'I've never got the charge curve stuff to work but I don't think it matters as it'll presumably default to 100%.

predbatt.yaml.txt

@WyndStryke
Copy link

WyndStryke commented Feb 6, 2025

'I've never got the charge curve stuff to work but I don't think it matters as it'll presumably default to 100%.

If a charge curve isn't supplied, I think it'll try to figure it out from your historical charge data (IIRC, it doesn't simply default to 100%). What I was wondering was if the automatic charge curve might have been the cause of your battery line being flat in your chart.

If it is trying to generate it from kW figures without converting, it might have decided that your charge curve was basically 0.001 all the way through the SoC range, hence a flat line.

Just a theory, don't know if it holds water or not, but might explain why mine was looking OK and yours wasn't.

@WyndStryke
Copy link

WyndStryke commented Feb 6, 2025

Since I think we understand this aspect of the configuration now, how about the other things in the fox.yaml? For example, I think it would be good to get Feed-in First etc working. Not entirely sure I understand which Fox work mode maps onto which predbat work mode, but this is my first guess:

  • Self-use Use PV for load first, then charge battery, then export if battery full, just the normal state I guess
  • Feed-in First Use PV for load first, then export, hold battery level steady as long as PV available (it will drop if PV unavailable). I think Freeze charge and/or freeze discharge is the most similar to this?
  • Force charge / force discharge - I think the same as in predbat
# Services to control charging/discharging
# charge_start_service - Should be set to a service that is called when charging starts
  charge_start_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Force Charge"
#charge_freeze_service - If your inverter supports charge freeze set to a service that starts this mode
  charge_freeze_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Feed-in First"
#charge_stop_service - Should be set to a service that is called when charging/charge freeze stops
  charge_stop_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Self Use"
#discharge_start_service - Should be set to a service that is called when force export (discharge) starts
  discharge_start_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Force Discharge"
#discharge_stop_service - Should be set to a service that is called when export/export freeze stops
  discharge_stop_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Self Use"
#discharge_freeze_service - If your inverter supports export freeze set to a service that starts this mode
  discharge_freeze_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Feed-in First"

@gcoan
Copy link
Collaborator

gcoan commented Feb 6, 2025

If a charge curve isn't supplied, I think it'll try to figure it out from your historical charge data (IIRC, it doesn't simply default to 100%).

The charge curve is optional

Predbat does default the charge curve to 100% all the way if you don't specify anything in apps.yaml, or if you set the charge curve to 'auto' it will try to work it out from historical data - but this auto-determination is clearly logged as such in the logfile.

https://springfall2008.github.io/batpred/apps-yaml/#battery-chargedischarge-curves

@WyndStryke
Copy link

or if you set the charge curve to 'auto' it will try to work it out from historical data

Ah that must be it, thank you

@gcoan
Copy link
Collaborator

gcoan commented Feb 6, 2025

Self-use Use PV for load first, then charge battery, then export if battery full, just the normal state I guess
Feed-in First Use PV for load first, then export, hold battery level steady as long as PV available (it will drop if PV unavailable). I think Freeze charge and/or freeze discharge is the most similar to this?
Force charge / force discharge - I think the same as in predbat

The mappings you have presented sound logical, except I see you have mapped Feed-in First to both Freeze charge and Freeze Discharge services.

[The Predbat terminology changed recently so what was previously called Discharge is now called Export. The service names look to have not changed though]

In Predbat the behaviour of these is different:

  • in freeze charge the battery level is held but if there is more solar than house load the battery will charge
  • in freeze export the battery level is held, any solar will be used by the house or exported

https://springfall2008.github.io/batpred/what-does-predbat-do/#predbat-modes

It sounds from your description that Feed-in First more closely matches Freeze Export. If there isn't an equivalent of Freeze Charge then you can set support_discharge_freeze to False

https://springfall2008.github.io/batpred/inverter-setup/#i-want-to-add-an-unsupported-inverter-to-predbat

@TonyHoyle
Copy link
Author

TonyHoyle commented Feb 7, 2025

I had a go at creating charge_rate_kw and discharge_rate_kw but although it appeared to work I wasn't happy with the amount I had to change (I've never worked on a homeassistant plugin before, and I'm not going to submit anything that would break stuff).

Ideally it'd just understand which it was supposed to be using and translate automatically, but where the reading seems to go through a routine that does that, writing all goes direct and it's probably a big change to make that happen..

I've stuck my automations etc. on github in the hope that it helps others:
https://github.com/TonyHoyle/foxess_predbat

The only thing left I had to override is the minimum battery % (predbat_set_reserve_min) which seems to be set only by the UI and defaults to 4% whereas fox won't let you set a minimum below 10%, otherwise the predictor kept trying to predict it'd run lower.

@WyndStryke
Copy link

WyndStryke commented Feb 11, 2025

@springfall2008 @gcoan I think Tony's workaround has pinpointed what the ideal fix would be.

Firstly if predbat were able to adapt to a kW entity for these two settings when it needs to command the inverter's charge rate, it would be the simplest solution.

Secondly, if the fox.yaml could be updated to refer to number.force_charge_rate and number.force_discharge_rate instead of sensor.bms_charge_rate and sensor.bms_discharge_rate if/when a kW entity is supported, then that would be great. The two sensors are purely read-only so can't be used to command the charge or discharge rates.

It has been confirmed that sensor.bms_(dis)charge_rate isn't correct. https://foxesscommunity.com/viewtopic.php?p=7004#p7004

In the short term, perhaps update the comments or documentation with Tony's suggested workaround above (if it looks good to you)?

Also, would it be possible to add these into the fox.yaml?

    support_charge_freeze: false
    support_discharge_freeze: true

# Services to control charging/discharging
# charge_start_service - Should be set to a service that is called when charging starts
  charge_start_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Force Charge"
#charge_freeze_service - If your inverter supports charge freeze set to a service that starts this mode
#  charge_freeze_service:  N/A
#charge_stop_service - Should be set to a service that is called when charging/charge freeze stops
  charge_stop_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Self Use"
#discharge_start_service - Should be set to a service that is called when force export (discharge) starts
  discharge_start_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Force Discharge"
#discharge_stop_service - Should be set to a service that is called when export/export freeze stops
  discharge_stop_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Self Use"
#discharge_freeze_service - If your inverter supports export freeze set to a service that starts this mode
  discharge_freeze_service:
    service: select.select_option
    entity_id: select.work_mode
    option: "Feed-in First"

Now that the 'freeze export blocked by metric minimum improvement export' issue has been identified, the freeze export is actually behaving correctly in my plan so I think the above is good-to-go.

I've discovered that some of the fox inverters also have two more work-modes: 'backup', and 'peak shaving', mine has neither of these, so I don't know what they do, or if they are at all relevant to predbat.

There are also two more charge/discharge rate controls, but I don't think they would be suitable. They change everything, including PV charging and supporting the house load, not just the force charge and force discharge modes (they're in amps too). So I feel that these should be ignored unless that's something that predbat wants to control.

number.max_charge_current 
number.max_discharge_current 
force_charge_power is setting the inverters active power register and that is the maximum ac output it will throttle at.
max_charge rate is setting the dc input current used to charge to the batteries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants