misc/soliscloud-inverter-control#2: On/Off Triggering Mechanism



Issue Information

Issue Type: issue
Status: closed
Reported By: btasker
Assigned To: btasker

Milestone: PoC
Created: 31-Dec-24 19:06



Description

setChargeDischargeTimings() simply sets a charge schedule based on what's passed into it - there's no logic to decide when would be best to charge/discharge.

My ultimate aim is to be able to control this from HomeAssistant - using the Octopus integration's target rate sensor to target the cheapest time of day.

Realistically, I'm unlikely to build a HA addon from this script - it's more likely that I'll use flask to stand up a small API and the target rate sensors simply turn on and off, so we need a way to toggle on and off rather than providing times.



Toggle State Changes

Activity


assigned to @btasker

I think what I want to do is create functions like startCharging()/stopCharging().

These would then dynamically generate times to feed into the API

Start()

The start time would be the beginning of the current hour, effectively triggering immediately.

The end time just needs to be some time in the future, because at some point, stopCharging() will get called.

However, there are a couple of caveats here

  • We should assume that the call to stopCharging() might fail, so the stop time should be a fixed amount of time (3 hours maybe?). The function should take an argument which defines how long away the stop time should be
  • The inverter uses a 24h clock with no understanding of dates, so if the stop time rolls into the next day we'll need to reduce it to 23:59

Stop()

To stop charging, we need to invalidate the setting - setting it to 00:00-00:00


Catches

There are likely to be a few issues with this approach

The first that comes to mind is that fixed timings can no longer be set via the Soliscloud app/web interface.

We'll likely only use 1 time slot and there are 3, so on the face of it, they could coexist. The problem is, timeslots aren't allowed to overlap so we'd have to implement complicated logic to amend slots and account for that.

The second is that we'll be quite reliant on the Soliscloud API behaving. That's not always a given: although the API remains reachable, sometimes they fail to communicate with the inverter.

We should almost certainly implement retries to reduce the impact of this

The following function calculates the time range to use:

def calculateDynamicTimeRange(end_hours = 3):
    ''' Calculate a time range to pass into the API
    '''

    now = datetime.now()

    hour_begin = now.replace(minute=0)
    hour_end = hour_begin + timedelta(hours=end_hours)

    if int(hour_begin.strftime("%H")) > int(hour_end.strftime("%H")):
        # Time wrapped
        hour_end = hour_end.replace(hour=0)

    # Turn into a textual range
    b = hour_begin.strftime("%H:%M")
    e = hour_end.strftime("%H:%M")

    return f"{b}-{e}"

The minute will always be 00 - the end time is only intended as a safety net.

verified

mentioned in commit b0e368d7d187aaa2f7bf1448c7a3ca78c5c458d3

Commit: b0e368d7d187aaa2f7bf1448c7a3ca78c5c458d3 
Author: B Tasker                            
                            
Date: 2024-12-31T19:27:47.000+00:00 

Message

feat: add function to dynamically calculate a timerange (misc/soliscloud-inverter-control#2)

This generates a timerange which would cause the inverter to turn on now and then turn back off in n hours time

+21 -0 (21 lines changed)
verified

mentioned in commit d0872c067e9a268da91b0eabcc08e494011483e7

Commit: d0872c067e9a268da91b0eabcc08e494011483e7 
Author: B Tasker                            
                            
Date: 2024-12-31T19:45:26.000+00:00 

Message

feat: add functions to immediately start/stop a charge (misc/soliscloud-inverter-control#2)

+84 -5 (89 lines changed)

The commit above adds two functions

    soliscloud.startCharge(config, 3)
    soliscloud.stopCharge(config)

These can be used to start and stop charging. Need to add equivalents for discharge (probably tomorrow).

Surprisingly, we'll probably then be ready to look at wrapping it in a Flask app so that HomeAssistant can be told to make calls to it.

verified

mentioned in commit f94ec7bfd65e36cb1a1d111068f5fd6f34a0725a

Commit: f94ec7bfd65e36cb1a1d111068f5fd6f34a0725a 
Author: B Tasker                            
                            
Date: 2025-01-01T11:43:44.000+00:00 

Message

feat: allow discharge to be started and stopped (misc/soliscloud-inverter-control#2)

+87 -55 (142 lines changed)

There are now 4 functions which can be called:

soliscloud.startCharge(config, 3)
soliscloud.startDischarge(config, 3)

soliscloud.stopCharge(config)
soliscloud.stopDischarge(config)

It doesn't make sense to have to keep passing config about though, so I'm going to remove that from the method signatures

verified

mentioned in commit 416e8f7cb99b93e7a948d940b4e14a2edf00c951

Commit: 416e8f7cb99b93e7a948d940b4e14a2edf00c951 
Author: B Tasker                            
                            
Date: 2025-01-01T11:48:29.000+00:00 

Message

fix: config already exists within the class, stop passing it around (misc/soliscloud-inverter-control#2)

+18 -18 (36 lines changed)

Invocation is now:

soliscloud.startCharge(3)
soliscloud.startDischarge(3)

soliscloud.stopCharge()
soliscloud.stopDischarge()

The stop functions are only really separate for convenience - calling either will stop both charge and discharge.