python-e3dc icon indicating copy to clipboard operation
python-e3dc copied to clipboard

Wallbox interaction

Open mdhom opened this issue 3 years ago • 29 comments

This PR will enable the library to interact with the wallbox as known from the wallbox page on the web portal.

  • [X ] Decide on the start/stop/toggle behavior

This PR is still in progress

mdhom avatar Mar 06 '22 15:03 mdhom

def set_wb_charge_toggle(self, enable, keepAlive=False):
            """Setting the Wallbox charge function via rscp protocol locally.

            Args:
                enable (bool): True/False
                keepAlive (Optional[bool]): True to keep connection alive

            Returns:
                0 if success
                -1 if error
            """
            
            #barry_off = bytearray([0,0,0,1,0,0])
            barry_on = bytearray([0,0,0,0,1,0])

          
            if enable:
                pprint(barry_on)
                res = self.sendRequest(
                    (
                        "WB_REQ_DATA",
                        "Container",
                        [
                            ("WB_INDEX", "UChar8", 0),
                            ("WB_REQ_SET_EXTERN", "Container",
                            [
                                ("WB_EXTERN_DATA", "ByteArray", barry_on), 
                                ("WB_EXTERN_DATA_LEN", "UChar8", 6),
                            ])
                        ],
                    ),
                    keepAlive=keepAlive,
                )
                pprint(res)
            else:
                res = self.sendRequest(
                    (
                        "WB_REQ_DATA",
                        "Container",
                        [
                            ("WB_INDEX", "UChar8", 0),
                            ("WB_REQ_SET_EXTERN", "Container",
                            [
                                ("WB_EXTERN_DATA", "ByteArray", barry_off), 
                                ("WB_EXTERN_DATA_LEN", "UChar8", 6),
                            ])
                        ],
                    ),
                    keepAlive=keepAlive,
                )

            # validate return code for EMS_RES_WEATHER_REGULATED_CHARGE_ENABLED is 0
            if res[2][0][2] == 0:
                print("Ok...")
                return 0
                
            else:
                print("NOk...")
                return -1

With this function i can start/stop the wallbox ;-)

othorg avatar Mar 06 '22 16:03 othorg

With this function i can start/stop the wallbox ;-)

I still believe that this isn't an actual start / stop behavior. When I run your code trying to start charging, the only thing that happens is that the "chargingCanceled" flag toggles, but no current is flowing... I think there still are some puzzle pieces missing in understanding what is happening under the hood...

mdhom avatar Mar 06 '22 16:03 mdhom

As i wrote before... Sun Mode has to be off. For me it works actually. We should figure out what in which modus your wallbox is (Sunmode or Mixed mode)

What do you think... One function called like "wallbox_controller" or something like that, and we should figure out what byte-Sequences are valid?

othorg avatar Mar 06 '22 16:03 othorg

my wallbox is in mixed mode and still no charging. I just saw that my phases where changed from 3 to 1 calling your start method. image That is how it looks like currently in the web portal

mdhom avatar Mar 06 '22 16:03 mdhom

ok. Did you ever seen the Button "Ladevorgang starten"? Than we should compare the wallbox settings on S10 itself... Bildschirmfoto 2022-03-06 um 17 35 31

othorg avatar Mar 06 '22 16:03 othorg

Ok, I made some tests. First it seems that my car wasn't accepting current, I now started charging via the cars app, now the wallbox is actually charging.

But still, the barry_on = bytearray([0, 0, 0, 0, 1, 0]) payload seems to be a toggle command. With repeatedly sending this payload, I can toggle the chargingCanceled flag (and the Ladevorgang starten button (dis-)appears accordingly). The chargingActive flag goes True as soon as current is actually flowing. In combination with knowing the chargingCanceled you can actually implement a start/stop behaviour with the toggle, outside of this library...

Whenever I send your barry_off = bytearray([0,0,0,1,0,0]) payload, charging isn't changed but my phases are set from 3 to 1. Which actually would make sense, because you are setting a different index of the array and I`m pretty sure that is modifying the phases, and not the "charging" state.

mdhom avatar Mar 06 '22 16:03 mdhom

Oh my fault... you are right. I had used following code

def set_wb_charge_toggle(self, enable, keepAlive=False):
            """Setting the Wallbox charge function via rscp protocol locally.

            Args:
                enable (bool): True/False
                keepAlive (Optional[bool]): True to keep connection alive

            Returns:
                0 if success
                -1 if error
            """
            
            #barry_off = bytearray([0,0,0,0,1,0])
            barry = bytearray([0,0,0,0,1,0])

          
            if enable:
                pprint(barry)
                res = self.sendRequest(
                    (
                        "WB_REQ_DATA",
                        "Container",
                        [
                            ("WB_INDEX", "UChar8", 0),
                            ("WB_REQ_SET_EXTERN", "Container",
                            [
                                ("WB_EXTERN_DATA", "ByteArray", barry), 
                                ("WB_EXTERN_DATA_LEN", "UChar8", 6),
                            ])
                        ],
                    ),
                    keepAlive=keepAlive,
                )
                pprint(res)

And in my mind i was a step ahead... So i think one function maybe "wallbox_controller" with different sets of byteArrays should work... What do you think?

othorg avatar Mar 06 '22 16:03 othorg

not sure what you mean with the controller method. I would not want to have a user of the library need to handle bytearrays just for toggle switches in the wallbox, I would always wrap that special setting into a separate method. Internally I could introduce such a controller method for reusing the same code of sending the request. Is that what you meant?

mdhom avatar Mar 06 '22 16:03 mdhom

not sure what you mean with the controller method. I would not want to have a user of the library need to handle bytearrays just for toggle switches in the wallbox, I would always wrap that special setting into a separate method. Internally I could introduce such a controller method for reusing the same code of sending the request. Is that what you meant?

Yes, exactly... :-)

othorg avatar Mar 06 '22 17:03 othorg

@vchrisb in this PR another 4-5 methods will be added to the e3dc client. Is there any plan on e.g. splitting some functionalities into subclasses, so that maintenance of code will be easier in the future? The _e3dc.py has already over 2k lines, I could think of some subclassing could help? E.g. something like that:

e3dc =E3DC(...)
wallbox = e3dc.get_wallbox(0)
wallbox.get_data()
wallbox.set_sun_mode()

Is that something that is planned, should I implement the new wallbox-feature like that or would you prefer just adding the new code to the _e3dc.py?

mdhom avatar Mar 06 '22 17:03 mdhom

For now I would suggest implementing it like the other methods in _e3dc.py for consistency. Creating subclasses is probably a larger refactoring effort to be addressed separately.

vchrisb avatar Mar 06 '22 20:03 vchrisb

@othorg I think the PR is ready for reviewing. Can you please test it again with your system?

mdhom avatar Mar 06 '22 20:03 mdhom

@mdhom i checked/tested your code. Everything works as expected. Thank you very much for your work! For me, it's a great enhancement!

Two suggestions only: Description in function toggle_wallbox_charging should (could) be: Toggles charging of the wallbox via rscp protocol locally if sunModeOn = False

And you wrote before: This PR will enable the library to interact with the wallbox as known from the wallbox page on the web portal.

In my opinion it would be great to have another function to set the max current like in the webinterface? What do you think? Then you have created a complete library for the wallbox....

othorg avatar Mar 07 '22 04:03 othorg

Two suggestions only: Description in function toggle_wallbox_charging should (could) be: Toggles charging of the wallbox via rscp protocol locally if sunModeOn = False

Is that really the case? I think it toggles the chargingCanceled flag even if sunMode is on. It behaves kind of a switch that can actively prohibit charging if chargingCanceled is set to true, otherwise the wallbox decides on its own, when it charges and when not. What do you think?

In my opinion it would be great to have another function to set the max current like in the webinterface? What do you think? Then you have created a complete library for the wallbox....

Yes you're right, I forgot that and also setting the number of phases. I added both functionalities right now, please test once again.

mdhom avatar Mar 07 '22 07:03 mdhom

Yes you're right, I forgot that and also setting the number of phases. I added both functionalities right now, please test once again.

I remember that the new wallboxes (smart connect) can't set the phases. This setting in my opinion tells the wallbox only to detect the amount of phases for starting the charging process. I think this function is an older relict of the old wallbox. The old one could switch the phases inside the wallbox.

Attached ist the modbus documentation. Maybe it helps to understand my thoughts... Bildschirmfoto 2022-03-07 um 08 54 52

othorg avatar Mar 07 '22 07:03 othorg

Is that really the case? I think it toggles the chargingCanceled flag even if sunMode is on. It behaves kind of a switch that can actively prohibit charging if chargingCanceled is set to true, otherwise the wallbox decides on its own, when it charges and when not. What do you think?

ok. Than we should explain it a bit more in this function. But my first expectation is to toggle immediately the charging process. And this happens only if the sunMode is switched off. This is my perception at the moment. In the webportal it's not possible to charge (button is not visible) if the sun mode is on. If i toggle the sun mode to off (Webportal) than it's possible to start the charging process. Maybe it depends on the settings in the S10 itself? IMG_0982

othorg avatar Mar 07 '22 08:03 othorg

@mdhom regarding #59 set_wallbox_max_charge_current... Do you think it's useful to build an exception, if the parameter value (int) is higher as the possible/permitted value in the S10 (I think 16A/32A)?

othorg avatar Mar 07 '22 08:03 othorg

@mdhom regarding #59 set_wallbox_max_charge_current... Do you think it's useful to build an exception, if the parameter value (int) is higher as the possible/permitted value in the S10 (I think 16A/32A)?

have you tested what happens / is returned if you set an invalid current? Maybe we actually get an error in return...

mdhom avatar Mar 07 '22 10:03 mdhom

@mdhom regarding #59 set_wallbox_max_charge_current... Do you think it's useful to build an exception, if the parameter value (int) is higher as the possible/permitted value in the S10 (I think 16A/32A)?

have you tested what happens / is returned if you set an invalid current? Maybe we actually get an error in return...

My E3DC system clips the requested max_charge_current to the configured limits Min. Ladestrom and Absicherung (right of Max. Ladestrom / in the Wallbox Settings of the E3DC display).

mstv avatar Apr 15 '22 13:04 mstv

@mdhom regarding #59 set_wallbox_max_charge_current... Do you think it's useful to build an exception, if the parameter value (int) is higher as the possible/permitted value in the S10 (I think 16A/32A)?

have you tested what happens / is returned if you set an invalid current? Maybe we actually get an error in return...

My E3DC system clips the requested max_charge_current to the configured limits Min. Ladestrom and Absicherung (right of Max. Ladestrom / in the Wallbox Settings of the E3DC display).

Thanks for testing, that is what I expected here. Once we have cleared your suggestions, I think this PR would be ready for completing.

mdhom avatar May 01 '22 06:05 mdhom

My wallbox has a key switch either for locking or for restriction to sun mode (depending on the wallbox configuration in the E3DC settings). The keystate can be requested with ("WB_REQ_KEY_STATE", "None", None).


Whether the wallbox may discharge the battery can be controlled with ('EMS_REQ_SET_BATTERY_TO_CAR_MODE', "UChar8", 1 if enabled else 0) and be read with ("EMS_REQ_BATTERY_TO_CAR_MODE", None, None).

mstv avatar May 01 '22 12:05 mstv

awesome, where did you find those infos / how were you able to reverse-engineer those values? I'll add the Keystate and discharge priority to this PR?

Edit: reading key state works (although I haven't physically toggled the keyswitch on my wallbox yet), but I fail to request the "Battery to car mode". Do you have some "example code" how to request that mode?

mdhom avatar May 02 '22 11:05 mdhom

awesome, where did you find those infos / how were you able to reverse-engineer those values? I'll add the Keystate and discharge priority to this PR?

I have watched the data and compared it with the detailed charge info at the E-Mobility page.

The "energy*" values have automatically been reset multiple times in April, sometimes when my script lost the connection and perhaps at 100 kWh. I.e. the documentation "consumed energy this month in watthours" might not be exact.

reading key state works (although I haven't physically toggled the keyswitch on my wallbox yet), but I fail to request the "Battery to car mode". Do you have some "example code" how to request that mode?

Sorry, it is ("EMS_REQ_BATTERY_TO_CAR_MODE", "None", None).

mstv avatar May 03 '22 21:05 mstv

Hi, As i see there are only very few changes do be done prior to merging this PR. @mdhom Could you complete this PR? I'd like to use the WB features as well. Thanks a lot!

bullitt186 avatar Aug 23 '23 05:08 bullitt186

All, I really would like to include the WB features implemented by @mdhom into python-e3dc. I forked his branch and verified that it still works with 0.8.1 with a MultiConnect II ('get_wallbox_data()', 'toggle_wallbox_charging()', 'set_wallbox_max_charge_current()', 'set_wallbox_sunmode()'). I could not test 'set_wallbox_schuko()' as the Multiconnect II does not have a schuko outlet.

@vchrisb - what's open/pending in the PR? I'd be happy to finish mdhom's work in a new PR from my fork, as it seems that @mdhom seems to have abandoned his fork?

bullitt186 avatar Oct 21 '23 05:10 bullitt186

There is an open discussion between @mdhom and @mstv on a few topics I think. I can't test this PR, as I don't have a wallbox. A few wallbox users should test the PR and confirm it does work as expected.

vchrisb avatar Oct 21 '23 09:10 vchrisb

If you want to see how I get the S10 & WB data using the unmodified release 0.7.3, you could look at https://github.com/mstv/e3dc_control/blob/main/control/e3dc_direct.py.

mstv avatar Oct 21 '23 20:10 mstv

Thank you @mstv, your code works fine for me, so I could integrate it in hacs-e3dc based on the current version of python-e3dc. However i think the "clean" way would be to get the features rightaway in this library.

I did yesterday some more testing throughout the day with this PR and my Wallbox and did not find any issues. So I'd actually recommend to integrate the PR. By that we can integrate it in hacs-e3dc. I guess by that we will also get more users using the WB features; if this reveals any bugs/issues, i am happy to follow up on these.

bullitt186 avatar Oct 22 '23 06:10 bullitt186

However i think the "clean" way would be to get the features rightaway in this library.

Of course. I just provided it in order to make my above comments clearer.

It would be good to

  • add the field described in https://github.com/fsantini/python-e3dc/pull/59#discussion_r862464933
  • add the field described in https://github.com/fsantini/python-e3dc/pull/59#discussion_r862464941
  • add requests and field get: ("EMS_REQ_BATTERY_TO_CAR_MODE", "None", None) set: ('EMS_REQ_SET_BATTERY_TO_CAR_MODE', "UChar8", 1 if enabled else 0)

either in this or in a follow-up PR.

mstv avatar Oct 22 '23 10:10 mstv