CharlesGillanders / homeassistant-alphaESS

Monitor your energy generation, storage, and usage data using the official API from Alpha ESS.
MIT License
101 stars 22 forks source link

Service to change EV Charger Mode #70

Closed ckarrie closed 1 year ago

ckarrie commented 1 year ago

Hi, I would like to have a new service to change/set one of the four EV Charger Mode (SMILE-EVCT11):

Needed parameters (I guess):

see https://www.manualslib.de/manual/800017/Alpha-Ess-Smile-Evct11.html?page=11 for a german manual.

ckarrie commented 1 year ago

As far as I see, it's already implemented in vdwal's Java Implementation

Would love to see it in HomeAssistant/Python too :-)

roggepaul commented 1 year ago

Hi @ckarrie. It seems like you found a solution to change charging modes for the EV wallbox via HTTP request but I can not figure it out how to do it by looking at the java code. Do you have a simple example POST-request including the URL and the json body to update the charging mode? You would help me a lot.

ckarrie commented 1 year ago

Hi @roggepaul , I havn't tested it out yet. I'm not really familiar with Java, but if you u can read one code, you can read all codes :-)

Shouldn't be much magic, posting to cloud-settings URL with parameter chargingmode (integer), chargingpile_sn (serial number of wallbox) and token as auth. But not sure about the exact payload. Maybe someone else could figure it out, before I do.

vdwals commented 1 year ago

Hi all,

I can provide a more detailed JSON in the evening, but so far: The payload to set the charging mode is the same you receive when requesting the system settings inclusive the wallbox settings. Like Charge- and Discharge time. You just change the charging mode received and send the adjusted JSON back. @ckarrie has already listed the integer explanation of the different modes you need to set at the 'chargingmode' property.

roggepaul commented 1 year ago

Hi all,

Thank you for your responses. I tried out your suggestions and used a postman collection (https://github.com/CharlesGillanders/alphaess/blob/main/AlphaESS.postman_collection.json) I found online. I used the endpoint https://cloud.alphaess.com/api/Account/CustomUseESSSetting?system_id=xxx to receiver settings and pasted the whole data response into an post request to https://cloud.alphaess.com/api/Account/CustomUseESSSetting. I was able to successfully update the chargingpile_control_open to 0 or 1. I got a HTTP 200 and the "info":"Success" in the response body. The change was applied and visible in the app after a app refresh. But when I try to update the chargingmode value to 1,2,3 or 4 or any value inside the charging_pile_list array I still get a HTTP 200 and the "info":"Success" in the response body but the update doesnt get applied and is not visible in the app. Do you have any suggestions? Has anyone successfully updated the chargingmode or chargingpile settings via an api?

dvw-fyayc commented 1 year ago

Hi,

the chargingpilemode is not in the charging_pile_list.

{
    "code": 200,
    "info": "Success",
    "data": {
        "sys_sn": "AL701102XXXXX",
        "ems_version": "V0.10.62T",
        "charge_workdays": null,
        ...
        "chargingmode": 4,
        "charging_pile_list": [
            {
                "chargingpile_sn": "ALP20210402XXX",
                ...
            }
        ]
    }
}

If you adjust this charging mode entry, it should work.

BTW: What is chargingpile_control_open for?

roggepaul commented 1 year ago

@vdwals thank you for your response. I get the same structure like you when performing a GET on https://cloud.alphaess.com/api/Account/CustomUseESSSetting?system_id=xxx. I know that the chargingmode is not in the charging_pile_list array and I never had it there. I just tried to change different settings in the array. When I edit the chargingmode and POST it I still get a success message but no update inside the app. The same applies to changes in the charging_pile_list array (not regarding the charging_pile_list array). To my mind it should work and changing the chargingmode and values inside the charging_pile_list array returns a HTTP 200 but the update is not shown in the APP. Can you try it out and tell me if the values get updated and applied by Alphaess and is displayed in the app?

the chargingpile_control_open (turned on in my case) is the value for "Kontrollrecht offen" that is also changeable in the app inside the "EV-Charger Settings" menu.

Tupsi commented 1 year ago

Did anyone here get that working? I was wondering if it is possible to get a button in HA for start/stopping charging. From what I figured out in that java code it should be possible, have not found it implemented for HA yet though. From what I can see on his bitbucket @vdwals seems to be using it with HA, but I have not figured out yet, how to use that. Getting the container running is one thing, but how would I use it from within HA? So far I only pulled data from the MQTT broker, never sent anything back.

vdwals commented 1 year ago

Hi all,

sorry for the late reply. There was a bug in my eclipse and I was unable to debug it to give you the precise messages. So the request is a post request to https://cloud.alphaess.com/api/Account/CustomUseESSSetting and the body is

{
  "ac_tied": 0,
  "auto_soccalib_en": 0,
  "auto_startdg_en": 0,
  "backupbox": 0,
  "bakbox_ver": "V0.00",
  "basic_mode_jp": 0,
  "bat_high_cap": "100.0",
  "bat_highcap_we": 0,
  "bat_use_cap": "4.0",
  "bat_usecap_we": 0,
  "channel1": "0",
  "channel2": "0",
  "charge_mode1": 1,
  "charge_mode2": 1,
  "charge_soc1": null,
  "charge_soc2": "20",
  "charge_weekend": null,
  "charge_workdays": null,
  "charging_pile_list": [
    {
      "chargingpile_hard_ver": null,
      "chargingpile_id": "EV1",
      "chargingpile_phase": 3,
      "chargingpile_sn": "<replaced>",
      "chargingpile_soft_ver": null,
      "chargingpile_startpower": null,
      "chargingpile_switch": 1,
      "chargingpilename": null,
      "chargingpiletype": null,
      "max_current": 16.0,
      "priority": 1,
      "time_charge_1": 0,
      "time_charge_2": 0,
      "time_charge_e1": "15:00",
      "time_charge_e2": "16:00",
      "time_charge_s1": "13:00",
      "time_charge_s2": "07:00"
    }
  ],
  "chargingmode": 2,   <--- Normal
  "chargingpile": 1,
  "chargingpile_id": "EV1",
  "chargingpile_sn": "<replaced>",
  "chargingpile_switch": 1,
  "control_mode1": null,
  "control_mode2": "2",
  "ctr_dis": 0,
  "ctr_dis_we": 0,
  "currentsetting": "32",
  "date1": "0000000",
  "date2": "0000000",
  "delay1": 0,
  "delay2": 0,
  "delta": 1,
  "dg_cap": 0,
  "dg_frequency": 50,
  "duration1": 0,
  "duration2": 0,
  "ems_version": "V0.10.62T",
  "end_time1a": null,
  "end_time1b": null,
  "end_time2a": "00:00",
  "end_time2b": "00:00",
  "fill_e1a": "00:00",
  "fill_e2a": "00:00",
  "fill_s1a": "00:00",
  "fill_s2a": "00:00",
  "fillvalue": 0,
  "gc_charge_power": 0,
  "gc_output_mode": 0,
  "gc_rate_percent": 80,
  "gc_rated_power": 0,
  "gc_soc_end": 10,
  "gc_soc_start": 10,
  "gc_time_end": "0",
  "gc_time_start": "0",
  "generator": 0,
  "generator_mode": 0,
  "grid_charge": 0,
  "grid_Charge_we": 0,
  "l1_priority": 1,
  "l1_soc_limit": "0.00",
  "l2_priority": 2,
  "l2_soc_limit": "0.00",
  "l3_priority": 3,
  "l3_soc_limit": "0.00",
  "languageCode": "de-DE",
  "loadcut_soc": 10,
  "loadtied_soc": 11,
  "max_gridcharge": 10,
  "mbat": "SMILE5-BAT",
  "minv": "SMILE5-INV",
  "pause1": 0,
  "pause2": 0,
  "peace_mode_jp": 0,
  "peak_e1a": "00:00",
  "peak_e2a": "00:00",
  "peak_fill_en": 0,
  "peak_s1a": "00:00",
  "peak_s2a": "00:00",
  "peakvalue": 20,
  "pm_max": 0,
  "pm_offset": 0,
  "pm_offset_e1a": "00:00",
  "pm_offset_e2a": "00:00",
  "pm_offset_en": 0,
  "pm_offset_s1a": "00:00",
  "pm_offset_s2a": "00:00",
  "priority": 1,
  "soc_50_flag": 0,
  "start_time1a": null,
  "start_time1b": null,
  "start_time2a": "00:00",
  "start_time2b": "00:00",
  "stoinv_type": 1,
  "sts_en": 1,
  "switch_off1": 0,
  "switch_off2": 0,
  "switch_on1": 0,
  "switch_on2": 0,
  "sys_sn": "<replaced>",
  "system_id": "<replaced>",
  "time_cha_ewe1a": "00:00",
  "time_cha_ewe2a": "00:00",
  "time_cha_fwe1a": "00:00",
  "time_cha_fwe2a": "00:00",
  "time_chae1a": "00:00",
  "time_chae2a": "00:00",
  "time_chaf1a": "00:00",
  "time_chaf2a": "00:00",
  "time_charge_1": 0,
  "time_charge_2": 0,
  "time_charge_e1": "15:00",
  "time_charge_e2": "16:00",
  "time_charge_s1": "13:00",
  "time_charge_s2": "07:00",
  "time_dis_ewe1a": "00:00",
  "time_dis_ewe2a": "00:00",
  "time_dis_fwe1a": "00:00",
  "time_dis_fwe2a": "00:00",
  "time_dise1a": "00:00",
  "time_dise2a": "00:00",
  "time_disf1a": "00:00",
  "time_disf2a": "00:00",
  "ups1": "0",
  "ups2": "0",
  "upsReserve": 0,
  "vpp_mode_jp": 0
}

Which is exactly the response body from GET https://cloud.alphaess.com/api/Account/GetCustomUseESSSetting?system_id=, but with adjusted:

So it is like lifting the affected charger from the charger list into the main structure. I'm sorry for the previous confusion, I did hide the Response -> Request transformation well in a few steps by transforming one java DTO into another DTO which looked like using the same body. So this body is from my working debug session. Let me know if I can help you further. If you like to have a look, start at https://bitbucket.org/vdwals/alphaesscloud2mqtt/src/master/src/main/java/de/vdw/io/alpha2mqtt/services/alpha/ChargingService.java line 253. This triggers receiving the system settings, creating a setting dto to adjust charging mode and does the final request to the service as well as validates the result.

roggepaul commented 1 year ago

thanks @vdwals, I am now able to successfully update the chargingmode with your suggested json structure by copying some elements in the root of the json object. Is there any way to start/stop the EV-charging via an api like I do it in the app in the "EV-charger settings" tab (where a car and a wallbox is shown an there are two buttons at the bottom for starting and stopping the charging)?

ckarrie commented 1 year ago

I'm just to dump to make a successful GET/POST request. What I've done:

Python Code:


import requests

url = "https://cloud.alphaess.com/api/Account/GetCustomUseESSSetting?system_id=z1aSXXXXXXXXXXX"
token = "eyJhbXXXXX.XXXXXXXXXXXXX...XXX"

class BearerAuth(requests.auth.AuthBase):
    def __init__(self, token):
        self.token = token
    def __call__(self, r):
        r.headers["authorization"] = "Bearer " + self.token
        return r

resp = requests.get(url, auth=BearerAuth(token))

Get only a empty response with code 500.

vdwals commented 1 year ago

Hi, yes they improved their "scraping" protection a little bit. Each non-login request requires two additional headers:

In postman, I execute the following script to calculate both:

var timestamp = parseInt(new Date().getTime() / 1000);

var signature = "al8e4s" + CryptoJS.SHA512("LS885ZYDA95JVFQKUIUUUV7PQNODZRDZIS4ERREDS0EED8BCWSS" + timestamp).toString() + "ui893ed";

pm.collectionVariables.set("authsignature", signature);
pm.collectionVariables.set("authtimestamp", timestamp);

You need something similar in your code. They implemented it around octobre 22. Hope they don't improve it again, they obfuscated it well :-) To validate your script, you can compare your results with the headers you find in your browsers tools.

vdwals commented 1 year ago

thanks @vdwals, I am now able to successfully update the chargingmode with your suggested json structure by copying some elements in the root of the json object. Is there any way to start/stop the EV-charging via an api like I do it in the app in the "EV-charger settings" tab (where a car and a wallbox is shown an there are two buttons at the bottom for starting and stopping the charging)?

Hi, yes, Start and Stop are simple calls to the uris:

with the body:

{
    "sys_sn": "AL****",
    "chargingpile_sn": "ALP****"
}
ckarrie commented 1 year ago

Finally I got it to work.

Here is my python3 script: Usage (python3-requests needed):

  ## set max_current ("Ladestrom A/Phase"):
  python3 alpha.py -u <username> -p <password> -m 10

  ## stop charging:
  python3 alpha.py -u <username> -p <password> --stop 1

  ## start charging
  python3 alpha.py -u <username> -p <password> --start 1

alpha.py: https://gist.github.com/ckarrie/f8396907bb9b30a48284ce2e91954da6

Edit 1: removed code here for better reading experience Edit 2: it's a quick hack Edit 3: added a Class-based API https://github.com/ckarrie/alphaesscloud-api