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

What would it take to include Sofar inverters? #395

Closed
onetoomany opened this issue Nov 30, 2023 · 33 comments
Closed

What would it take to include Sofar inverters? #395

onetoomany opened this issue Nov 30, 2023 · 33 comments

Comments

@onetoomany
Copy link

I've just upgraded my inverter to Sofar HYD, and keen to have BatPred running for it. What would it take to have BatPred run this inverter as well?

To control the inverter, the best way seems to be through RS485 via Sofar2MQTT.
This gives a number of MQTT topic subsets that cover SOC, grid power, inverter power, house load etc...., and MQTT publish topics to force charge or discharge the battery at variable rates. This is done through a mode called "Passive Mode" on the inverter, which isn't by time of day but is fully controlled by RS485 commands.

I saw the previous post about getting Solax inverters included, and the list of entities needed. Before I complete something similar, question is whether its more use to you in the MQTT topic format or not. Alternatively, as I can name the entities anything I want, would it would be simpler to have a specification that I can name my entities against and this become a more versatile solution?

For example:

Charging: (variable rate)

    service: mqtt.publish
    data:
      qos: "1"
      retain: true
      topic: Sofar2mqtt/set/charge
      payload: "3000"

Discharging, as above with Sofar2mqtt/set/discharge
Auto, again with Sofar2mqtt/set/auto and payload of "true"

SOC:

    - name: "sofar_inverter_battery_charge"
      state_topic: "Sofar2mqtt/state"
      unit_of_measurement: "W"
      device_class: power
      state_class: measurement
      value_template: > 
        {% if (value_json.battery_power < 32767) %}
        {{ (value_json.battery_power) * 10 }}
        {% else %}
        {{ 0 }}
        {% endif %} 
@springfall2008
Copy link
Owner

Hi,

The cleanest way to add support would be to control the inverter via Home Assistant entities as is being supported for other inverters. If you have the list of entities with their contents then it might not be too hard to map.

Basically you need information about the system, ideally can be read via HA but could be hard-wired:

  • Battery size
  • Max charge rate
  • Max discharge rate

Then you need to be able to read directly the following:

  • Battery state of charge
  • Ideally be able to read the current charge and discharge settings

Then you need a way to:

  • Start and stop charging and define what % to charge up to (or it could just stop when the % is reached)
  • Ideally you want a way to be able to force export for a time period, but this is optional

@onetoomany
Copy link
Author

Battery size - hard wired, as only the SOC is read
Max charge rate - hard wired, but typically 3kw for this inverter / 65A
Max discharge rate - hard wired, but typically 3kw for this inverter / 65A

The inverter has a certain level of battery control in it, with a max discharge of 15% and a max charge of 100%
For force charge or discharge, its a case of sending the MQTT command to start, then sending another command to return to Auto - I can't say charge for 30mins.

SOC: sensor.sofar_inverter_battery_SOC
Battery charge: sensor.sofar_inverter_battery_charge (W)
Battery discharge: sensor.sofar_inverter_battery_discharge (W)
Battery power (ie net of the above): sensor.sofar_inverter_battery_power (W)

Grid power: sensor.sofar_grid_power (W)
System power: sensor.sofar_inverter_system_power (W)
House load: sensor.sofar_house_consumption_power (W)
PV: sensor.sofar_solar_power (W)

Exported energy: sensor.sofar_energy_today_exported (kWh)
Imported energy: sensor.sofar_energy_today_purchase (kWh)
Consumed energy: sensor.sofar_energy_today_consumption (kWh)
PV Total energy: sensor.sofar_energy_today_generation (kWh)

Force charge: switch.sofar_charge_mode_3000 (or 1000, 1500, 2000, 2500 etc..)
Force discharge: switch.sofar_discharge_mode_3000
Force auto: switch.sofar_auto_mode
Force battery save: switch.sofar_auto_saver_mode (i.e. charge from PV but no discharge)
(not sure why these are down as switches not buttons)

@onetoomany
Copy link
Author

I've managed to get PredBat reading my data and creating a valid plan.
Next steps is to get it to control the inverter.

In the instructions, there are supposed binary_sensor.predbat_charging and binary_sensor.predbat_discharging that I thought I could create a trigger off to change the state of my inverter - however, these don't seem to exist in my sensors. How can I identify if my inverter should be changing between charging, discharging and auto?

Ideally, I'd use these sensors to start a charge until the sensor switches off again - i.e. if the plan says I need to add 0.5kwh to the battery, the sensor will switch off when I get there rather than at the end of the slot. Is this how they should work?

I'm also not sure what behaviour I'm meant to provide to my inverter for a FreezeChrg and HoldChrg period?
I assume both would map to Battery Save (i.e. don't discharge the battery, but charge with any excess solar if available).

@springfall2008
Copy link
Owner

Can you share your apps.yaml so far so it can be added?

I don't think you want to automate based on the sensors, we would want Predbat to trigger the charge or discharge itself. Can you maybe share an automation that starts/stops charging and discharging and then that can be used to add to Predbat code?

@onetoomany
Copy link
Author

There are four parts to this:

  1. A small ESP8266 and TTL>RS485 circuit as per https://github.com/cmcgerty/Sofar2mqtt, which communicates with HA via MQTT
  2. The inverter needs to be put into Passive mode
  3. yaml package for converting the MQTT messages to sensors - sofar_inverter.yaml.txt
  4. the app.yaml config for PredBat - apps.yaml.txt

Example commands to start / stop charging are:

  - alias: Set inverter to Charge at 3kW
    service: mqtt.publish
    data:
      qos: "1"
      retain: true
      topic: Sofar2mqtt/set/charge
      payload: "3000"

  - alias: Set inverter to Discharge at 2kW
    service: mqtt.publish
    data:
      qos: "1"
      retain: true
      topic: Sofar2mqtt/set/discharge
      payload: "2000"

  - alias: Set inverter to Auto
    service: mqtt.publish
    data:
      qos: "1"
      retain: true
      topic: Sofar2mqtt/set/auto
      payload: "true"

  - alias: Set inverter to Battery Save
    service: mqtt.publish
    data:
      qos: "1"
      retain: true
      topic: Sofar2mqtt/set/auto
      payload: "battery_save"

@springfall2008
Copy link
Owner

I'll try to have a go at supporting this soon, I don't think mqtt is hard to add

@springfall2008
Copy link
Owner

I've committed some changes to : https://github.com/springfall2008/batpred/tree/Sofar - The python updated and the template Predbat config file (https://github.com/springfall2008/batpred/blob/Sofar/templates/sofar.yaml) which you will need take my updates on.

Can you give it a try, I'll add in your other files once something is working?

@onetoomany
Copy link
Author

I've done a (very) manual install of branch - not sure if I've done it right, but I overwrote the predbat.py code and the apps.yaml.

I'm seeing this in the logs:
2023-12-13 10:21:27.253775 INFO pred_bat: Inverter 0 current charge rate is 3000.0 and new target is 2600
2023-12-13 10:21:27.254779 INFO pred_bat: ERROR: Exception raised argument of type 'int' is not iterable
As such, I'm not seeing any action on the inverter.

I'm also seeing a lot of warnings along the lines of:
2023-12-13 10:21:27.205542 WARNING pred_bat: pred_bat: Entity predbat.low_rate_end not found in namespace default
2023-12-13 10:21:27.205799 INFO AppDaemon: pred_bat: Entity predbat.low_rate_end created in namespace: default

@springfall2008
Copy link
Owner

For the first one I think 'battery_max_rate: 3000' needs adding to apps.yaml.

For the exception, can you go to 'settings, system, logs, appdaemon' and paste in the stack trace?

@springfall2008
Copy link
Owner

'm also seeing a lot of warnings along the lines of:
2023-12-13 10:21:27.205542 WARNING pred_bat: pred_bat: Entity predbat.low_rate_end not found in namespace default
2023-12-13 10:21:27.205799 INFO AppDaemon: pred_bat: Entity predbat.low_rate_end created in namespace: default

These are good, they happen when Predbat creates sensors for the first time

@onetoomany
Copy link
Author

TypeError: argument of type 'int' is not iterable

2023-12-13 10:21:27.261076 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 10:25:01.569609 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 10:25:01.570012 WARNING pred_bat: Unexpected error in worker for App pred_bat:
2023-12-13 10:25:01.570112 WARNING pred_bat: Worker Ags: {'id': '8d036e7bbad9476092a6330e419f5a46', 'name': 'pred_bat', 'objectid': 'a160f4009d1e4bd19236d6fb2fc78179', 'type': 'scheduler', 'function': <bound method PredBat.run_time_loop of <predbat.PredBat object at 0x7ff93eca89d0>>, 'pin_app': True, 'pin_thread': 0, 'kwargs': {'interval': 300, 'random_start': 0, 'random_end': 0, '__thread_id': 'thread-0'}}
2023-12-13 10:25:01.570180 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 10:25:01.571079 WARNING pred_bat: Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/appdaemon/threading.py", line 1022, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9701, in run_time_loop
    raise e
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9697, in run_time_loop
    self.update_pred(scheduled=True)
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9167, in update_pred
    status, status_extra = self.execute_plan()
                           ^^^^^^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 8162, in execute_plan
    inverter.adjust_charge_rate(inverter.battery_rate_max_charge * 60 * 1000)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1227, in adjust_charge_rate
    entity = self.base.get_entity(self.base.get_arg("charge_rate", indirect=False, index=self.id))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/appdaemon/adapi.py", line 3188, in get_entity
    self._check_entity(namespace, entity)
  File "/usr/lib/python3.11/site-packages/appdaemon/utils.py", line 231, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/appdaemon/utils.py", line 313, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/usr/lib/python3.11/site-packages/appdaemon/adapi.py", line 588, in _check_entity
    if "." not in entity:
       ^^^^^^^^^^^^^^^^^
TypeError: argument of type 'int' is not iterable

@springfall2008
Copy link
Owner

Thanks, I updated the YAML template and predbat.py on the branch, effectively it was trying to use the number as an entity which didn't work.

@onetoomany
Copy link
Author

2023-12-13 15:00:03.606184 INFO pred_bat: ERROR: Exception raised 'Inverter' object has no attribute 'call_service'

and from the appdaemon log:

AttributeError: 'Inverter' object has no attribute 'call_service'

2023-12-13 15:10:01.935502 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 15:15:01.569999 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 15:15:01.570388 WARNING pred_bat: Unexpected error in worker for App pred_bat:
2023-12-13 15:15:01.570521 WARNING pred_bat: Worker Ags: {'id': '18623fcedf254c8faab58b3c51441a5b', 'name': 'pred_bat', 'objectid': 'd7aa4f9da61445c7b0660cf33ae13a44', 'type': 'scheduler', 'function': <bound method PredBat.run_time_loop of <predbat.PredBat object at 0x7ff93f218c50>>, 'pin_app': True, 'pin_thread': 0, 'kwargs': {'interval': 300, 'random_start': 0, 'random_end': 0, '__thread_id': 'thread-0'}}
2023-12-13 15:15:01.570608 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 15:15:01.571914 WARNING pred_bat: Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/appdaemon/threading.py", line 1022, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9701, in run_time_loop
    raise e
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9697, in run_time_loop
    self.update_pred(scheduled=True)
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9167, in update_pred
    status, status_extra = self.execute_plan()
                           ^^^^^^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 8338, in execute_plan
    inverter.adjust_battery_target(self.charge_limit_percent_best[0])
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1339, in adjust_battery_target
    self.mimic_target_soc(soc)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1131, in mimic_target_soc
    self.alt_charge_discharge_enable("charge", True, grid=True, timed=False)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1740, in alt_charge_discharge_enable
    self.mqtt_message('set/charge', payload=self.battery_rate_max_charge)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1751, in mqtt_message
    self.call_service("mqtt/publish", qos=1, retain=True, topic=(self.inv_mqtt_topic + '/' + topic), payload=payload)
    ^^^^^^^^^^^^^^^^^
AttributeError: 'Inverter' object has no attribute 'call_service'

@springfall2008
Copy link
Owner

I've just pushed a fix for that, please update and re-try

@onetoomany
Copy link
Author

I've been running it this evening. A couple of issues still:
2023-12-13 21:25:01.596044 INFO pred_bat: Inverter 0 Current Target SOC is 38 already at target
2023-12-13 21:25:01.597545 INFO pred_bat: ERROR: Exception raised argument of type 'NoneType' is not iterable

The MQTT Sofar2mqtt/set/charge looks like at least an order of magnitude out - "0.05". The value needed is the charge rate in W, so 3000 = 3kW.

TypeError: argument of type 'NoneType' is not iterable

2023-12-13 21:20:01.554319 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 21:25:01.604998 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 21:25:01.605174 WARNING pred_bat: Unexpected error in worker for App pred_bat:
2023-12-13 21:25:01.605325 WARNING pred_bat: Worker Ags: {'id': '2796611130374988ac8979f660ae04ba', 'name': 'pred_bat', 'objectid': 'e7ed0dc28b3e41c0921015819db5efa5', 'type': 'scheduler', 'function': <bound method PredBat.run_time_loop of <predbat.PredBat object at 0x7ff93f2cf510>>, 'pin_app': True, 'pin_thread': 0, 'kwargs': {'interval': 300, 'random_start': 0, 'random_end': 0, '__thread_id': 'thread-0'}}
2023-12-13 21:25:01.605443 WARNING pred_bat: ------------------------------------------------------------
2023-12-13 21:25:01.606760 WARNING pred_bat: Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/appdaemon/threading.py", line 1022, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9701, in run_time_loop
    raise e
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9697, in run_time_loop
    self.update_pred(scheduled=True)
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9167, in update_pred
    status, status_extra = self.execute_plan()
                           ^^^^^^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 8338, in execute_plan
    inverter.adjust_battery_target(self.charge_limit_percent_best[0])
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1339, in adjust_battery_target
    self.mimic_target_soc(soc)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1132, in mimic_target_soc
    self.set_current_from_power("charge", self.battery_rate_max_charge)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1768, in set_current_from_power
    entity = self.base.get_entity(self.base.get_arg(f"timed_{direction}_current", indirect=False, index=self.id))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/appdaemon/adapi.py", line 3188, in get_entity
    self._check_entity(namespace, entity)
  File "/usr/lib/python3.11/site-packages/appdaemon/utils.py", line 231, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/appdaemon/utils.py", line 313, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/usr/lib/python3.11/site-packages/appdaemon/adapi.py", line 588, in _check_entity
    if "." not in entity:
       ^^^^^^^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable

@springfall2008
Copy link
Owner

Okay, I've pushed another fix to predbat.py

Sorry this is so slow, I can't test it myself.

@onetoomany
Copy link
Author

Only just been able to test this today, (and didn't want to disturb things during powerup and saver session)

  1. MQTT charge command still an order of magnitude out - saying 0.05 not 3000
    There are also a few MQTT commands that don't do anything - no harm, but no use either: e.g.
    set/target_soc
    set/reserve

  2. Some errors in the logs
    2023-12-14 19:59:04.546605 INFO pred_bat: ERROR: Exception raised 'PredBat' object has no attribute 'base'

2023-12-14 19:59:04.556722 WARNING pred_bat: Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/appdaemon/threading.py", line 1022, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9832, in update_time_loop
    raise e
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9827, in update_time_loop
    self.update_pred(scheduled=False)
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9183, in update_pred
    self.fetch_sensor_data()
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 8733, in fetch_sensor_data
    self.base.call_notify("Predbat: Joined Octopus saving event: start {}, end {}, price per kWh {}".format(start, end, saving_rate))
    ^^^^^^^^^
AttributeError: 'PredBat' object has no attribute 'base'

@gcoan
Copy link
Collaborator

gcoan commented Dec 14, 2023

The last of those error messages was when predbat sent a mobile notification that it was joining the saving session. Bug on my part, it's fixed in the latest release. Only occurs at the moment of joining the saving session, it joins ok but then crashes when sending the mobile alert.
Next 5 minute run of predbat as you've already joined the saving session it runs ok

springfall2008 added a commit that referenced this issue Dec 15, 2023
* Improvements

* Added load_scaling10 to allow the worst case scenario to include higher load - default 1.1
* Fix charge freeze to disable the charge window when holding using reserve
* Put some more options into expert mode
* Try to stop charge window from being disabled when it doesn't need to be
* Update customisation.md
* Update faq.md
* Second attempt to fix force discharge time to 0 
#462

* Sofar inverter fix - mqtt scale issue with charge rate
#395

* [pre-commit.ci lite] apply automatic fixes

---------

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
@springfall2008
Copy link
Owner

Can you try the latest from 'main' please, these things have been fixed

@onetoomany
Copy link
Author

This latest version seems to have regressed to an error that was fixed yesterday. Also, the MQTT message for set charge is still coming through as 0.05.

2023-12-15 12:35:01.520027 INFO pred_bat: ERROR: Exception raised argument of type 'NoneType' is not iterable

TypeError: argument of type 'NoneType' is not iterable

2023-12-15 12:30:05.520072 WARNING pred_bat: ------------------------------------------------------------
2023-12-15 12:35:01.526707 WARNING pred_bat: ------------------------------------------------------------
2023-12-15 12:35:01.527384 WARNING pred_bat: Unexpected error in worker for App pred_bat:
2023-12-15 12:35:01.527676 WARNING pred_bat: Worker Ags: {'id': '204daae70b4a4df9a51df251c685e547', 'name': 'pred_bat', 'objectid': '4d03feca25794dcfaabf8811c03279d7', 'type': 'scheduler', 'function': <bound method PredBat.run_time_loop of <predbat.PredBat object at 0x7fd68faf4e10>>, 'pin_app': True, 'pin_thread': 0, 'kwargs': {'interval': 300, 'random_start': 0, 'random_end': 0, '__thread_id': 'thread-0'}}
2023-12-15 12:35:01.527884 WARNING pred_bat: ------------------------------------------------------------
2023-12-15 12:35:01.529227 WARNING pred_bat: Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/appdaemon/threading.py", line 1022, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9899, in run_time_loop
    raise e
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9895, in run_time_loop
    self.update_pred(scheduled=True)
  File "/usr/lib/python3.11/site-packages/appdaemon/adbase.py", line 35, in f_app_lock
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 9235, in update_pred
    status, status_extra = self.execute_plan()
                           ^^^^^^^^^^^^^^^^^^^
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 8404, in execute_plan
    inverter.adjust_battery_target(self.charge_limit_percent_best[0])
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1342, in adjust_battery_target
    self.mimic_target_soc(soc)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1135, in mimic_target_soc
    self.set_current_from_power("charge", self.battery_rate_max_charge)
  File "/homeassistant/appdaemon/apps/batpred/predbat.py", line 1782, in set_current_from_power
    entity = self.base.get_entity(self.base.get_arg(f"timed_{direction}_current", indirect=False, index=self.id))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/appdaemon/adapi.py", line 3188, in get_entity
    self._check_entity(namespace, entity)
  File "/usr/lib/python3.11/site-packages/appdaemon/utils.py", line 231, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/appdaemon/utils.py", line 313, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/usr/lib/python3.11/site-packages/appdaemon/adapi.py", line 588, in _check_entity
    if "." not in entity:
       ^^^^^^^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable

@springfall2008
Copy link
Owner

What version is being reported in the log or in the version sensor?

I did just push another fix to main related to this crash so you might want to update

@onetoomany
Copy link
Author

THIS_VERSION = "v7.14.12"

@springfall2008
Copy link
Owner

v7.14.13 is on main right now, so maybe try that and see if it changes anything. I'll release it once its stable.

@onetoomany
Copy link
Author

I've not seen it charge yet, but seeing the following:

  1. Sofar2mqtt/set/auto payload should be lowercase "true" not "True". Not sure if this makes a difference looking at the ESP code though.
  2. the reserve value is being ignored - which is why I've not seen it charge. I've got a reserve set to 20% in the apps.yaml, yet the plan allows for my SOC to drop to 4%. The inverter kicks in on its own accord if the SOC drops below the reserve.

@springfall2008
Copy link
Owner

How can the reserve be set by Predbat, what's the MQTT command for that?

@onetoomany
Copy link
Author

I don't believe it can - we have to monitor it and set the inverter to standby ("Sofar2mqtt/set/standby") when we hit the lower reserve, or auto when hit the upper reserve.

@springfall2008
Copy link
Owner

I've added a fix on main for now which disables the set_reserve/set_reserve_hold if the inverter doesn't have a reserve. We could emulate as a next step.

@springfall2008
Copy link
Owner

@onetoomany
Copy link
Author

Thanks - I'm still seeing the following:

  1. Sofar2mqtt/set/auto still coming as "True" not "true"

  2. The SOC Predbat plan will drop below the "reserve" value set in apps.yaml. I'd have thought Predbat would treat the apps.yaml value as the lower limit for the plan. The behaviour I would expect would be:

  • The plan never drops below the "reserve" value
  • When the SOC hits that reserve value, a command is sent to the inverter to put it into either "battery save" or "standby" mode. Thinking about it, "battery save" mode could be better, as this means the battery will charge from any excess PV but not from the grid. The command for these are: Sofar2mqtt/set/auto with payload "battery_save" and Sofar2mqtt/set/standby
  1. Sofar2mqtt/set/target_soc - this has no effect on the inverter so is not needed

@springfall2008
Copy link
Owner

  1. I've fixed that on 'main' now
  2. I think you need to change the set_reserve_min in Home Assistant. The value in the apps.yaml is meant to point to a register that reads the current reserve value from the inverter, then Predbat will overwrite it with its own value. As Sofar is configured as not having a reserve then this register is ignored.
  3. The target_soc was mostly put there for other inverters in the future, if it's harmless we can ignore it.

@onetoomany
Copy link
Author

Great - this all seems to work!
What's needed to support the documentation for Sofar inverters, so others can use this too?

  • key elements are:
    1. sofar2mqtt EPS board (relatively easy to solder and flash, or can be bought pre-made)
    1. sofar.yaml package with the MQTT sensors. The one I've used is the default with a couple of additional inputs to support battery capacity.
    1. apps.yaml

@springfall2008
Copy link
Owner

Please review the documentation here and send me any updates:

https://github.com/springfall2008/batpred/blob/sofar/docs/other-inverters.md

@onetoomany
Copy link
Author

onetoomany commented Jan 3, 2024

Thanks - documentation looks like it covers it.

The only tweaks I'd make are:

  1. to explicitly state which entity you mean by
    "Note: You will need to change the min reserve in Home Assistant to match your minimum battery level." - namely 'input_number.predbat_set_reserve_min'
  2. state that the inverter needs to be put into "Passive Mode" for the sofar2mqtt to control the inverter.

Thanks again for your help in getting this to work!

gcoan added a commit to gcoan/batpred that referenced this issue Feb 3, 2024
springfall2008 added a commit that referenced this issue Feb 21, 2024
* load_inday_adjustment typo

* added min battery level sensor to Sofar inverters #395

* correct formatting issue on bullets

* Added battery_scaling advice for 80% DoD batteries and All in One

* Explain bold import/export rates on predbat plan

* New FAQ for inverter in calibration mode

* Detail of entities to uncomment out for battery discharge curve creation

* Add RobinC's tips from  #693

* rates_export_override example from #693

* Expanded freeze charging and freeze discharging #744

* Expanded manual_idle mode explanation (aka Eco mode) #729.
Added that changes to the selectors are async and Predbat still has to update the plan

* Car charging instructions and sample predbat-led charging automation per GE forum discussion

* Export rate overrides to shift when exporting is done #693

* Custom card install instructions

* best_soc_keep explanation #755

* Add manual card for Predbat plan card

* Adding custom card config

* Link to Apex Charts YT video

* Link to YT video and importance of creating charge curve for low power mode

* Corrected missing editor text

* Further highlight turning Enforce Basepath OFF

* Added links for useful HA introduction videos

* Added GivTCP self-run frequency recommendation & time inconsistency FAQ

* Expanded car_charging_hold explanation #766

* forecast_hours and forecast_plan_hours for #768

* [pre-commit.ci lite] apply automatic fixes

---------

Co-authored-by: Trefor Southwell <48591903+springfall2008@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
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

3 participants