biemond / solaredge.modbus

Homey Solaredge modbus app
GNU General Public License v3.0
8 stars 9 forks source link

Value of "Storage Charge/Discharge Mode" #47

Open CaptainVoni opened 1 year ago

CaptainVoni commented 1 year ago

The value of "Storage Charge/Discharge Mode" is defined as text, so I assumed it will return the label of the respective mode. But instead it returns a number, e.g. in case of Maximize self-consumption it will contain "7" as value.

Is this intentionally? If so, how can we verify if a specific mode is set, i.e. is there somewhere a documented mapping between the label and the number?

Shouldnt it be possible to set the mode to a specific value and when verifying the mode, that same value is returned?

biemond commented 1 year ago

pushed a new version

CaptainVoni commented 1 year ago

Translations seem perfect now. I noticed two things:

Am I right that you removed the (non-working) minimum discharge power?

biemond commented 1 year ago

thanks , yep can you find out what minimal discharge works for you , from the inverter menu.

CaptainVoni commented 1 year ago

thanks , yep can you find out what minimal discharge works for you , from the inverter menu.

What do you mean by "inverter menu"? I just checked everything I can find in SetApp and also on the monitoring website, but I can't find anything about the discharge power of the battery.

biemond commented 1 year ago

ok will do some checks

CaptainVoni commented 1 year ago

I guess I should report this to the Homey support, right?

image

I'm under the impression that the Homey built-in flow cards for capabilities are buggy. I guess I should wait with the bug report until this version of the App is released, otherwise they might just blame the "untested app".

biemond commented 1 year ago

oh let me verify this. thanks for reporting.

biemond commented 1 year ago

indeed I see the same, always true

biemond commented 1 year ago

So greater than works for me, but you cannot test them from advanced flow. there is for me , no true or false output. and then the value is not tested

Screen Shot 2023-09-23 at 18 32 18
biemond commented 1 year ago

so discharge 0 ,10,50 and 100 is working for me

<img width="498" alt="Screen Shot 2023-09-23 at 20 00 56" src="https://github.com/biemond/solaredge.modbus/assets/1085004/529c0816-5f60-478b-b155-e17c67ad16

Screen Shot 2023-09-23 at 19 50 32 Screen Shot 2023-09-23 at 19 50 38 Screen Shot 2023-09-23 at 19 56 20 Screen Shot 2023-09-23 at 19 58 53 Screen Shot 2023-09-23 at 20 00 49

0c">

CaptainVoni commented 1 year ago

so discharge 0 ,10,50 and 100 is working for me

Tested all of them right now: all are working for me except zero. But 10 W is also perfectly fine for me. Many thanks for your efforts! When do you think will you release this version?

CaptainVoni commented 1 year ago

Are you planning on adding such trigger?

* A trigger for a change of the storage control mode and the storage charge/discharge mode is missing. If you want to add them you can use "Speicherkontrollmodus hat sich geändert" (storage control mode) and "Speicher-Lade/Entlade-Modus hat sich geändert" (storage charge/discharge mode) as translation.

I'm asking because my battery turns itself off every day between 21:00 and 22:00 and I want to react on that.

biemond commented 1 year ago

no problem. also I think the default of remote action = 6 hours , than you need to do something else it will go to the default again.

let me ask to publish it to release

CaptainVoni commented 1 year ago

no problem. also I think the default of remote action = 6 hours , than you need to do something else it will go to the default again.

Oh, that's interesting! Will check that. Thanks for the hint!

biemond commented 1 year ago

I think it is an hour but I set it to 6 hours

  if (type == 'storagedefaultmode') {
        const storagedefaultmodeRes = await client.writeSingleRegister(0xe004, Number(4));
        console.log('controlmodewrite', storagedefaultmodeRes)

        // set timeout to 6 hours, done in seconds
        const remoteTimeout = await client.writeMultipleRegisters(0xe00b, [ Number(21600), 0 ]);
        console.log('remote_control_command_timeout', remoteTimeout);
        // 0 – Off
        // 1 – Charge excess PV power only.
        // Only PV excess power not going to AC is used for charging the battery. Inverter NominalActivePowerLimit (or the inverter rated power whichever is lower) sets how much power the inverter is producing to the AC. In this mode, the battery cannot be discharged. If the PV power is lower than NominalActivePowerLimit the AC production will be equal to the PV power.
        // 2 – Charge from PV first, before producing power to the AC.
        // The Battery charge has higher priority than AC production. First charge the battery then produce AC.
        // If StorageRemoteCtrl_ChargeLimit is lower than PV excess power goes to AC according to NominalActivePowerLimit. If NominalActivePowerLimit is reached and battery StorageRemoteCtrl_ChargeLimit is reached, PV power is curtailed.
        // 3 – Charge from PV+AC according to the max battery power.
        // Charge from both PV and AC with priority on PV power.
        // If PV production is lower than StorageRemoteCtrl_ChargeLimit, the battery will be charged from AC up to NominalActivePow-erLimit. In this case AC power = StorageRemoteCtrl_ChargeLimit- PVpower.
        // If PV power is larger than StorageRemoteCtrl_ChargeLimit the excess PV power will be directed to the AC up to the Nominal-ActivePowerLimit beyond which the PV is curtailed.
        // 4 – Maximize export – discharge battery to meet max inverter AC limit.
        // AC power is maintained to NominalActivePowerLimit, using PV power and/or battery power. If the PV power is not sufficient, battery power is used to complement AC power up to StorageRemoteCtrl_DishargeLimit. In this mode, charging excess power will occur if there is more PV than the AC limit.
        // 5 – Discharge to meet loads consumption. Discharging to the grid is not allowed. 
        // 7 – Maximize self-consumption
        const remotecontrolwrite = await client.writeSingleRegister(0xe00d, Number(value));
        console.log('remotecontrolwrite', remotecontrolwrite);
      }
CaptainVoni commented 1 year ago

It really might be that timeout. But I do set the mode at least once an hour, but the value to which I set it to might stay the same for some hours.

As I write this, the mode reset itself to off. I checked and I had it set to "Discharge to meet loads consumption" before 18:00 and set it to "Maximize self-consumption" at 18:00. So that's just three hours.

And it resets itself pretty much every day at around the same time. That's really strange...

CaptainVoni commented 1 year ago
    // 5 – Discharge to meet loads consumption. Discharging to the grid is not allowed. 
    // 7 – Maximize self-consumption

Ok... I need to know... what's mode 6? :-D

biemond commented 11 months ago

can you try this , the new change mode triggers https://homey.app/a/solaredge.modbus/test/

CaptainVoni commented 11 months ago

Thanks! I just installed it and will keep it testing over the next days. I'll report back.

CaptainVoni commented 10 months ago

Just for your info: I'm still testing. Something seems to be fishy, it clearly missed a few state changes yesterday, however my inverter needed a restart yesterday, so I don't want to point fingers in any direction yet.

CaptainVoni commented 10 months ago

Correction to my last message: it gets all state changes, but it triggers before the state is updated in the app, i.e. if you read the state directly after the trigger fired, you will get the state BEFORE the state change, not the current one. Verifying this right now and checking how long it takes until the state is updated after the trigger fired.

biemond commented 10 months ago

interesting, had to do 2 part , 1 is from the device menu which set and triggers , other is from set Cap and comparing previous value , then fire and set new value .

maybe I need to fire after the set change is done.

can you add a 1 sec delay, like to know if 1 sec is enough or set change can take many seconds.

if (this.validResultRecord(result['storage_control_mode'])) { 
                    this.addCapability('storagecontrolmode');
                    var storagecontrolmode = result['storage_control_mode'].value;
                    console.log('changedStoragecontrolmode old ' + this.getCapabilityValue('storagecontrolmode') );
                    console.log('changedStoragecontrolmode new ' + storagecontrolmode );
                    if (this.getCapabilityValue('storagecontrolmode') != storagecontrolmode) {
                        let tokens = {
                            "mode": Number(storagecontrolmode)
                        };
                        let state = {};
                        console.log('trigger changedStoragecontrolmode ' + storagecontrolmode );
                        this.homey.flow.getDeviceTriggerCard('changedStoragecontrolmode').trigger(this, tokens, state);
                    }                    
                    this.setCapabilityValue('storagecontrolmode', storagecontrolmode);
                }

                if (this.validResultRecord(result['remote_control_command_mode'])) { 
                    this.addCapability('storagedefaultmode');
                    var storagedefaultmode = result['remote_control_command_mode'].value;
                    if (this.getCapabilityValue('storagedefaultmode') != storagedefaultmode) {
                        let tokens = {
                            "mode": Number(storagedefaultmode)
                        };
                        let state = {};
                        console.log('trigger changedStoragedefaultmode ' + storagedefaultmode );
                        this.homey.flow.getDeviceTriggerCard('changedStoragedefaultmode').trigger(this, tokens, state);
                    } 
                    this.setCapabilityValue('storagedefaultmode', storagedefaultmode);
                }
CaptainVoni commented 10 months ago

Just a delay of one second is sufficient to reliable get the correct value.

Looking at your code I wonder if the "this.setCapabilityValue(...)" shouldn't be inside the if-clause, just right above the "this.homey.flow.getDeviceTriggerCard(...)...".

biemond commented 10 months ago

yes you are correct, let me fix that. if you do from menu it works

CaptainVoni commented 10 months ago

I have the test-version of the app on auto update and have a flow logging all mode-changes to the timeline, so I should see if that really fixes it. I will let you know.

biemond commented 10 months ago

yep will push in a hour or so. was working on growatt tl device.

CaptainVoni commented 10 months ago

You're pretty busy :smile: I really appreciate the work you put into this - thanks!

biemond commented 10 months ago

yeah, at some point it will be modbus inverter homey app with main focus solaredge . it seems growatt cloud side is buggy or cost them too much money , plus it seems this modbus adapter is cheap and works well on most inverters. always a drama with registers. at least solaredge has it as a default plus good docs. and not like enphase with local device you can still do max 5 min or pay 250 dollar a month for near realtime data.

biemond commented 10 months ago

done https://homey.app/a/solaredge.modbus/test/

CaptainVoni commented 10 months ago

Looks like it’s unchanged. It seems that setCapabilityValue is an async function, so you might need to add „await“ there.

biemond commented 10 months ago

that explains , on code itself it is probably done in ms

CaptainVoni commented 10 months ago

Just let me know when you added await; I will test again. I'm pretty sure this will solve it.

biemond commented 10 months ago

it was not async func so I used a sleep and it works for me https://homey.app/a/solaredge.modbus/test/

CaptainVoni commented 10 months ago

I can confirm, it works now reliable. Thanks!

I'm just curious: when you tried to use await, did the function simply fail or was the capability not updated before the trigger?

biemond commented 10 months ago

with await, the compiler fails because function itself was not async. so this was the quick solution.