gdwaterworth / Home-Assistant---E-Linter-Logger---Sunsynk

31 stars 9 forks source link

Can't SET inverter, e.g. time1on #40

Closed peterthevicar closed 6 months ago

peterthevicar commented 6 months ago

Hi, first of all thank you so much for all the work you've done on this; it's been a steep learning curve for me and so helpful. I'm trying to write my own automation which is quite a bit simpler than yours as I don't have to worry about load shedding (being in the UK).

I have all the pieces except one: How to actually write settings back to the inverter! I changed the activeset for time1on to true and tried to use your flow but that didn't work for me.

Next I followed your node-red flow and used the same headers and payload. I even get a nice "Success" message back from SunSynk but the setting doesn't change. (See my python program below followed by its disappointing output)

Have you got this to work, and if so what is the secret?

Best wishes, Peter

def set_time1on(on_off):
    url = 'https://api.sunsynk.net/api/v1/common/setting/xxxxxxxx/set'
    #url = 'http://httpbin.org/post'
    payload = {'sn': "xxxxxxxx", 'time1on': on_off}
    headers = {'User-Agent': "Mozilla/5.0(Windows NT 10.0; Win64; x64; rv: 120.0) Gecko/20100101 Firefox/120.0",
           'Accept': "application/json",
           'Accept-Language': "en-US, en; q=0.5",
           'Accept-Encoding': "gzip, deflate, br",
           'Content-Type': "application/json;charset=UTF-8",
           'Authorization': "Bearer "+token,
           'Origin': "https://setting.inteless.com",
           'Connection': "keep-alive",
           'Referer': "https://setting.inteless.com/",
           'Sec-Fetch-Dest': "empty",
           'Sec-Fetch-Mode': "cors",
           'Sec-Fetch-Site': "same-site",
           'TE': "trailers"
           }
    r = requests.post(url, json=payload, headers=headers)
    print(r.json())

get_time1on() # get and print current state of time1on

set_time1on(False)

get_time1on()

time1on: True
{'code': 0, 'msg': 'Success', 'data': None, 'success': True}
time1on: True
peterthevicar commented 6 months ago

Sorry, should have said I'm using your V2 files, and I completely accept it's a work in progress so absolutely no complaints!

gdwaterworth commented 6 months ago

Time?on is not working that is why it is still false in the active set. None of the true/false ones are for some reason. Let me know if you specifically get those working. Also note that sometimes it takes time for the change to happen and show

peterthevicar commented 6 months ago

Thanks for taking the time to answer, I'll keep trying and let you know if I get anywhere.

peterthevicar commented 6 months ago

Success! This seems to work. There are two significant differences from how I was trying before:

  1. I've used the entire settings list rather than just the one I want to change
  2. There is an extra header 'Content-Length' which is set to the length of the payload string

Also, as you suggested there is a delay at the SunSynk end before the change registers. For me it is between 4 and 10 seconds but presumably depends on server load.

The python below splits the enormously long payload into lhs and rhs with the time1on setting in the middle. It sets the new value for time1on and then splices it all back together again. Obviously the right way to do it is to query the settings beforehand but at least this is a proof-of-concept.

Hope this helps,

Best wishes, Peter

def set_time1on(on_off):
    url = 'https://api.sunsynk.net/api/v1/common/setting/xxxxxxxx/set'
    #url = 'http://httpbin.org/post'

    lhs = '{"sn":"xxxxxxxx","safetyType":"0","battMode":"-1","solarSell":"0","pvMaxLimit":"3600","energyMode":"1","peakAndVallery":"1","sysWorkMode":"2","sellTime1":"00:00","sellTime2":"01:30","sellTime3":"02:00","sellTime4":"02:30","sellTime5":"22:30","sellTime6":"23:00","sellTime1Pac":"5000","sellTime2Pac":"5000","sellTime3Pac":"5000","sellTime4Pac":"5000","sellTime5Pac":"5000","sellTime6Pac":"5000","cap1":"20","cap2":"100","cap3":"20","cap4":"20","cap5":"100","cap6":"20","sellTime1Volt":"58","sellTime2Volt":"58","sellTime3Volt":"49","sellTime4Volt":"49","sellTime5Volt":"49","sellTime6Volt":"49","zeroExportPower":"20","solarMaxSellPower":"6500","mondayOn":true,"tuesdayOn":true,"wednesdayOn":true,"thursdayOn":true,"fridayOn":true,"saturdayOn":true,"sundayOn":true,'
    rhs= ',"time2on":false,"time3on":false,"time4on":false,"time5on":true,"time6on":false,"genTime1on":false,"genTime2on":false,"genTime3on":false,"genTime4on":false,"genTime5on":false,"genTime6on":false}'
    payload = lhs + '"time1on":' + ('true' if on_off else 'false') + rhs # Python would have initial capital
    print(payload)

    headers = {'User-Agent': "Mozilla/5.0(Windows NT 10.0; Win64; x64; rv: 120.0) Gecko/20100101 Firefox/120.0",
           'Accept': "application/json",
           'Accept-Language': "en-GB,en;q=0.5",
           'Accept-Encoding': "gzip, deflate, br",
           'Content-Type': "application/json;charset=UTF-8",
           'Authorization': "Bearer "+token,
           'Content-Length': str(len(payload)),
           'Origin': "https://setting.inteless.com",
           'Connection': "keep-alive",
           'Referer': "https://setting.inteless.com/",
           'Sec-Fetch-Dest': "empty",
           'Sec-Fetch-Mode': "cors",
           'Sec-Fetch-Site': "cross-site",
           'TE': "trailers"
           }
    r = requests.post(url, data=payload, headers=headers)
    print(r.json())
gdwaterworth commented 6 months ago

I have known about the “submit everything” and it works. Not my preferred way to deal with it tbh. Too much chance of changing settings inadvertantly I will have a look at the content length. Did see it , but never implemented

From: peterthevicar @.> Sent: Friday, December 29, 2023 10:49 PM To: gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk @.> Cc: gdwaterworth @.>; Comment @.> Subject: Re: [gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk] Can't SET inverter, e.g. time1on (Issue #40)

Success! This seems to work. There are two significant differences from how I was trying before:

  1. I've used the entire settings list rather than just the one I want to change
  2. There is an extra header 'Content-Length' which is set to the length of the payload string

Also, as you suggested there is a delay at the SunSynk end before the change registers. For me it is between 4 and 10 seconds but presumably depends on server load.

The python below splits the enormously long payload into lhs and rhs with the time1on setting in the middle. It sets the new value for time1on and then splices it all back together again. Obviously the right way to do it is to query the settings beforehand but at least this is a proof-of-concept.

Hope this helps,

Best wishes, Peter

def set_time1on(on_off):

url = 'https://api.sunsynk.net/api/v1/common/setting/xxxxxxxx/set'

#url = 'http://httpbin.org/post'

lhs = '{"sn":"xxxxxxxx","safetyType":"0","battMode":"-1","solarSell":"0","pvMaxLimit":"3600","energyMode":"1","peakAndVallery":"1","sysWorkMode":"2","sellTime1":"00:00","sellTime2":"01:30","sellTime3":"02:00","sellTime4":"02:30","sellTime5":"22:30","sellTime6":"23:00","sellTime1Pac":"5000","sellTime2Pac":"5000","sellTime3Pac":"5000","sellTime4Pac":"5000","sellTime5Pac":"5000","sellTime6Pac":"5000","cap1":"20","cap2":"100","cap3":"20","cap4":"20","cap5":"100","cap6":"20","sellTime1Volt":"58","sellTime2Volt":"58","sellTime3Volt":"49","sellTime4Volt":"49","sellTime5Volt":"49","sellTime6Volt":"49","zeroExportPower":"20","solarMaxSellPower":"6500","mondayOn":true,"tuesdayOn":true,"wednesdayOn":true,"thursdayOn":true,"fridayOn":true,"saturdayOn":true,"sundayOn":true,'

rhs= ',"time2on":false,"time3on":false,"time4on":false,"time5on":true,"time6on":false,"genTime1on":false,"genTime2on":false,"genTime3on":false,"genTime4on":false,"genTime5on":false,"genTime6on":false}'

payload = lhs + '"time1on":' + ('true' if on_off else 'false') + rhs # Python would have initial capital

print(payload)

headers = {'User-Agent': "Mozilla/5.0(Windows NT 10.0; Win64; x64; rv: 120.0) Gecko/20100101 Firefox/120.0",

       'Accept': "application/json",

       'Accept-Language': "en-GB,en;q=0.5",

       'Accept-Encoding': "gzip, deflate, br",

       'Content-Type': "application/json;charset=UTF-8",

       'Authorization': "Bearer "+token,

       'Content-Length': str(len(payload)),

       'Origin': "https://setting.inteless.com",

       'Connection': "keep-alive",

       'Referer': "https://setting.inteless.com/",

       'Sec-Fetch-Dest': "empty",

       'Sec-Fetch-Mode': "cors",

       'Sec-Fetch-Site': "cross-site",

       'TE': "trailers"

       }

r = requests.post(url, data=payload, headers=headers)

print(r.json())

— Reply to this email directly, view it on GitHubhttps://github.com/gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk/issues/40#issuecomment-1872330841, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AUYVNI55JZZLKYIJ2KCKGCTYL4UDBAVCNFSM6AAAAABBGXOYJSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZSGMZTAOBUGE. You are receiving this because you commented.Message ID: @.**@.>>

peterthevicar commented 6 months ago

OK I've narrowed it right down (code below works). Summary:

  1. You DON'T need the Content-Length
  2. You DON'T need most of the other settings, not even the serial number
  3. You DO need time1on and genTime1on
def set_time1on(on_off):
    url = 'https://api.sunsynk.net/api/v1/common/setting/2212052408/set'
    #url = 'http://httpbin.org/post'
    lhs = '{'
    rhs= ',"genTime1on":false}'
    payload = lhs + '"time1on":' + ('true' if on_off else 'false') + rhs # Python would have initial capital
    print(payload)

    headers = {'User-Agent': "Mozilla/5.0(Windows NT 10.0; Win64; x64; rv: 120.0) Gecko/20100101 Firefox/120.0",
           'Accept': "application/json",
           'Accept-Language': "en-GB,en;q=0.5",
           'Accept-Encoding': "gzip, deflate, br",
           'Content-Type': "application/json;charset=UTF-8",
           'Authorization': "Bearer "+token,
           'Origin': "https://setting.inteless.com",
           'Connection': "keep-alive",
           'Referer': "https://setting.inteless.com/",
           'Sec-Fetch-Dest': "empty",
           'Sec-Fetch-Mode': "cors",
           'Sec-Fetch-Site': "cross-site",
           'TE': "trailers"
           }
    r = requests.post(url, data=payload, headers=headers)
gdwaterworth commented 6 months ago

Be carefull about leaving the sn out Setups with dual inverters in the plant will be affected

Regards

From: peterthevicar @.> Sent: Saturday, December 30, 2023 3:20 PM To: gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk @.> Cc: gdwaterworth @.>; Comment @.> Subject: Re: [gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk] Can't SET inverter, e.g. time1on (Issue #40)

OK I've narrowed it right down (code below works). Summary:

  1. You DON'T need the Content-Length
  2. You DON'T need most of the other settings, not even the serial number
  3. You DO need time1on and genTime1on

def set_time1on(on_off):

url = 'https://api.sunsynk.net/api/v1/common/setting/2212052408/set'

#url = 'http://httpbin.org/post'

lhs = '{'

rhs= ',"genTime1on":false}'

payload = lhs + '"time1on":' + ('true' if on_off else 'false') + rhs # Python would have initial capital

print(payload)

headers = {'User-Agent': "Mozilla/5.0(Windows NT 10.0; Win64; x64; rv: 120.0) Gecko/20100101 Firefox/120.0",

       'Accept': "application/json",

       'Accept-Language': "en-GB,en;q=0.5",

       'Accept-Encoding': "gzip, deflate, br",

       'Content-Type': "application/json;charset=UTF-8",

       'Authorization': "Bearer "+token,

       'Origin': "https://setting.inteless.com",

       'Connection': "keep-alive",

       'Referer': "https://setting.inteless.com/",

       'Sec-Fetch-Dest': "empty",

       'Sec-Fetch-Mode': "cors",

       'Sec-Fetch-Site': "cross-site",

       'TE': "trailers"

       }

r = requests.post(url, data=payload, headers=headers)

— Reply to this email directly, view it on GitHubhttps://github.com/gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk/issues/40#issuecomment-1872527018, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AUYVNI24LOGWRRRMBXNZKMDYMAIJRAVCNFSM6AAAAABBGXOYJSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZSGUZDOMBRHA. You are receiving this because you commented.Message ID: @.**@.>>

peterthevicar commented 6 months ago

Thanks, that's helpful. I have a very simple setup so not aware of the issues with bigger ones.

peterthevicar commented 6 months ago

Around line 93 of the 'Create Inverter Update Request' node, I put in a kludge just to see if it works, which it does. I guess the next step is to do the pairing up of time?on with genTime?on via a mapping vector or a regexp substitution, and also read the current value to send back.

    } else if (BooleanEntities.includes(msg.payload.inverterid)) {
        if ((msg.payload.value === "on") || (msg.payload.value === "off")) 
        {
            if (msg.payload.value === "on") { outputmsg.payload[msg.payload.inverterid] = true;} else {outputmsg.payload[msg.payload.inverterid] = false ;}
            // PBCS: time1on change only accepted if genTime1on sent too
            if (msg.payload.inverterid == "time1on") {outputmsg.payload["genTime1on"] = false;}
gdwaterworth commented 6 months ago

I have a few idea's on how to do this. Will work on it

gdwaterworth commented 6 months ago

Code is in development branch for automation on gen and charge set automation

peterthevicar commented 6 months ago

Would it be helpful if I test it here, or are you still refining things?

gdwaterworth commented 6 months ago

Code is in the development branch. Few more checks and I will move it to the main branch tomorrow

Sent from Outlook for Androidhttps://aka.ms/AAb9ysg


From: peterthevicar @.> Sent: Sunday, December 31, 2023 9:42:28 PM To: gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk @.> Cc: gdwaterworth @.>; Comment @.> Subject: Re: [gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk] Can't SET inverter, e.g. time1on (Issue #40)

Would it be helpful if I test it here, or are you still refining things?

— Reply to this email directly, view it on GitHubhttps://github.com/gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk/issues/40#issuecomment-1873024273, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AUYVNI6DIEAEBWVLT4YEDUTYMG52JAVCNFSM6AAAAABBGXOYJSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZTGAZDIMRXGM. You are receiving this because you commented.Message ID: @.***>

gdwaterworth commented 6 months ago

Code to support updates in all gen and charge set fields has been merged into the stable environment

peterthevicar commented 6 months ago

Thanks for that, what an elegant solution! It works for me. Thanks again, Best wishes, Peter

On Mon, 1 Jan 2024 at 04:39, gdwaterworth @.***> wrote:

Code to support updates in all gen and charge set fields has been merged into the stable environment

— Reply to this email directly, view it on GitHub https://github.com/gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk/issues/40#issuecomment-1873150332, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC2X5XV3BJJHOZCQIF55IRLYMI4YTAVCNFSM6AAAAABBGXOYJSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZTGE2TAMZTGI . You are receiving this because you authored the thread.Message ID: <gdwaterworth/Home-Assistant---E-Linter-Logger---Sunsynk/issues/40/1873150332 @github.com>