nazar-pc / solax-local-api-docs

Solax local API docs
38 stars 7 forks source link

Update re firmware 3.003.02 #1

Open jefft4 opened 1 year ago

jefft4 commented 1 year ago

Hi,

Great information :-) I'm trying to see if I can work out from the cloud portal and its API, what any of the other data items from my inverters are and add those to the lists. I can see some battery type and version info in solaxcloud, which I expect will be in the API response somewhere.

Meanwhile, one update for you: I've checked the 'Information' array from my inverters (X1 Hybrid G4 & X1 mini 2.0):

I guess that 'ver' will now need to be included in the logic to determine what data is in each position.

nazar-pc commented 1 year ago

The benefit of reverse-engineering official application is that these docs are supposed to be as accurate as the official Android application.

How recent is the firmware? It would help if you can provide sample response from your inverter here.

Latest Android app is 0.4.5, which is a bit newer than 0.4.3 I was looking at. It apparently now supports a few more devices and Pocket WiFi+LAN and Pocket WiFi+4G that didn't exist before.

So I might have to look and update things here again.

jefft4 commented 1 year ago

Mine were installed September 2022, both with v3 firmware out of the box as far as I know.

Here's the API response from the mini (with inverter IDs partly obscured): {"sn":"SVBH99XXXX","ver":"3.003.02","type":4,"Data":[2436,4,42,1463,0,3,0,52,0,5013,2,4633,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,1548,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"Information":[2.000,4,"XM3A20I2000000",8,2.22,0.00,1.38,0.00,0.00,1]}

and the information section from the Hybrid G4 for comparison: "Information":[5.000,15,"H4502AI5000000",8,1.28,0.00,1.25,1.04,0.00,1] Same positions for inverter serial number and software versions, plus the '8' in position [3] and '1' in [9].

npmdnl commented 1 year ago

Hi folks, well done. I'm working too on this evil inverter (type 15). By now I can 100% confirm Data[18] is battery current charge in %. For your information, I will publish gh repo with ansible playbook to get these numbers and put all the stuff in influxDB to be then ingested in Grafana dashboards (still working on this in spare time). At this moment I'm not using HomeAssistant.

nazar-pc commented 1 year ago

@jefft4 did you try official Android app with local WiFi connection and did it show correct data for you on X1 Mini 2.0?

Hi folks, well done. I'm working too on this evil inverter (type 15). By now I can 100% confirm Data[18] is battery current charge in %.

It is already documented as BatteryCapacity in Data2.txt, but thanks for confirming.

jefft4 commented 1 year ago

@jefft4 did you try official Android app with local WiFi connection and did it show correct data for you on X1 Mini 2.0?

I've never tried the SolaX Android app with local wi-fi; wasn't aware it could do that! The Android app in cloud mode shows me an aggregated view of my two inverters - as with the cloud app, sometimes it's a bit incorrect because the two inverters report to the cloud at different times. SolaX really could be smarter about that!

nazar-pc commented 1 year ago

On last page "Account" there is "Local" button, it allows you to connect to Inverter directly without Internet connection or anything like that. We use API that that feature is using. I suspect, official app will not work properly for you (I don't see how it would in their code), but I had an idea in https://github.com/squishykid/solax/issues/108#issuecomment-1596272398 on how to handle it.

On the other hand, if it does NOT work, you can report this to Solax (they were quite responsive over email) and once they fix the app, we can follow their footsteps.

jefft4 commented 1 year ago

Hi folks, well done. I'm working too on this evil inverter (type 15). By now I can 100% confirm Data[18] is battery current charge in %. For your information, I will publish gh repo with ansible playbook to get these numbers and put all the stuff in influxDB to be then ingested in Grafana dashboards (still working on this in spare time). At this moment I'm not using HomeAssistant.

This any help? This is the code from my NodeRed flow that extracts the key data elements for the Hybrid.

``` /* Data mappings for SolaX X1 Hybrid G4 (type = 15) Note that some fields are signed; Javascript can't cast to signed as its integers aren't fixed length, so we have to convert -ves here. Assumption is that they're 2's complement, so conversion for 16 bits is to subtract 2^16. */ var res = { payload: {} }; if (msg.payload.datagood) { res.payload.Timestamp = new Date(); res.payload.wifiSerial = msg.payload.sn; res.payload.wifiVersion = msg.payload.ver; res.payload.inverterType = msg.payload.type; res.payload.ACVoltage = msg.payload.Data[0] / 10; res.payload.ACCurrent = msg.payload.Data[1] / 10; res.payload.ACPower = msg.payload.Data[2]; if (res.payload.ACPower > 32768) { // have seen this -ve (e.g. 65534), though that should be impossible res.payload.ACPower = 0; } res.payload.ACFreqcy = msg.payload.Data[3] / 100; res.payload.VDC1 = msg.payload.Data[4] / 10; res.payload.VDC2 = msg.payload.Data[5] / 10; res.payload.IDC1 = msg.payload.Data[6] / 10; res.payload.IDC2 = msg.payload.Data[7] / 10; res.payload.powerDC1 = msg.payload.Data[8]; res.payload.powerDC2 = msg.payload.Data[9]; res.payload.runMode = msg.payload.Data[10]; // 11,12 are total yield * 10 in 32 bits res.payload.yieldToday = msg.payload.Data[13] / 10; res.payload.batteryVoltage = msg.payload.Data[14] / 100; // battery: values are 16 bits signed; -ve is discharging, +ve charging if (msg.payload.Data[15] > 2**15) { // -ve res.payload.batteryCurrent = (msg.payload.Data[15] - 2**16) / 100; } else { res.payload.batteryCurrent = msg.payload.Data[15] / 100; } if (msg.payload.Data[16] > 2**15) { res.payload.batteryPower = msg.payload.Data[16] - 2**16; } else { res.payload.batteryPower = msg.payload.Data[16]; } res.payload.batteryTemperature = msg.payload.Data[17]; res.payload.batteryCharge = msg.payload.Data[18]; // 28 EPS power, 29 EPS volts, 30 EPS current * 10 // feedInPower (grid): 32 bits signed; -ve is import, +ve is export res.payload.feedInPower = msg.payload.Data[33] * 2**16 + msg.payload.Data[32]; if (res.payload.feedInPower > 2**15) { // -ve value res.payload.feedInPower = res.payload.feedInPower - 2**32; } // these may be signed, but they're kWh generated/used which should never go -ve anyway so we don't try to handle it res.payload.feedInEnergy = (msg.payload.Data[35] * 2**16 + msg.payload.Data[34]) / 100; res.payload.consumeEnergy = (msg.payload.Data[37] * 2**16 + msg.payload.Data[36]) / 100; /* res.payload.inverterSerial = msg.Payload.Information[2]; res.payload.dspVersion = msg.Payload.Information[4]; res.payload.armVersion = msg.Payload.Information[6]; */ } ```
jefft4 commented 1 year ago

On last page "Account" there is "Local" button, it allows you to connect to Inverter directly without Internet connection or anything like that. We use API that that feature is using. I suspect, official app will not work properly for you (I don't see how it would in their code), but I had an idea in squishykid/solax#108 (comment) on how to handle it.

On the other hand, if it does NOT work, you can report this to Solax (they were quite responsive over email) and once they fix the app, we can follow their footsteps.

I have no problem getting data from the X1 mini; it's just the detection of the mini by this integration that wasn't working; that seemed to be caused by a change in the 'Information' array.

I guess that the app is using the same API that we can get on the local wi-fi access point @ IP 5.8.8.8. With the recent firmware versions, the same data is also presented at http:///optType=ReadRealTimeData&pwd=. This really helped me: https://github.com/kamilfb/home-assistant - I had set up reverse proxies, then thanks to this chap, tested the LAN URL and realised I didn't need them!

nazar-pc commented 1 year ago

This any help? This is the code from my NodeRed flow that extracts the key data elements for the Hybrid.

No, there is nothing in there that is not already in this repo. What I need to know is whether Android app can show the data from it or not.

I guess that the app is using the same API that we can get on the local wi-fi access point @ IP 5.8.8.8. With the recent firmware versions, the same data is also presented at http:///optType=ReadRealTimeData&pwd=.

ReadRealTimeData is also documented in this repo right in the readme, no need to run reverse proxies.

Repeating information that is already in this repo isn't that helpful, but checking Android app and reporting to Solax if it doesn't work would be VERY helpful.

jefft4 commented 1 year ago

This any help? This is the code from my NodeRed flow that extracts the key data elements for the Hybrid.

No, there is nothing in there that is not already in this repo. What I need to know is whether Android app can show the data from it or not.

I guess that the app is using the same API that we can get on the local wi-fi access point @ IP 5.8.8.8. With the recent firmware versions, the same data is also presented at http:///optType=ReadRealTimeData&pwd=.

ReadRealTimeData is also documented in this repo right in the readme, no need to run reverse proxies.

Repeating information that is already in this repo isn't that helpful, but checking Android app and reporting to Solax if it doesn't work would be VERY helpful.

It's just as well I'm not easily offended by people being snarky in posts online! My offer of the NR flow was to @npmdnl, not to you; your response to that was unnecessary and the tone was dismissive and somewhat rude. Being polite would have cost you 2 more seconds; saying nothing would have saved you 60. The smiley at the end doesn't change the tone.

Now to what you wanted: The local connection from the Android app to the X1 mini v2 appears to be fine; the two pieces of data that it reports, the PV power and AC power, are close enough to the values I get from the ReadRealTimeData endpoint that any variation is just timing. App reports version 4.2.6. I hope that helps you :-)

Also - I notice you mention in your main readme that you left out the battery serial number because yours reports garbage. For my Hybrid G4, it's a simple text string in information[2] and it's correct. Might be worth noting those inverters that we know do report it properly.

nazar-pc commented 1 year ago

Didn't mean to be rude, sorry if it came across that way, just wanted to keep conversation on topic here.

App reports version 4.2.6

I'm surprised, is this the version of Android app? Can you post link to Google Play? I'm using https://play.google.com/store/apps/details?id=com.solaxcloud.starter and it is only at 0.4.6 right now.

Also - I notice you mention in your main readme that you left out the battery serial number because yours reports garbage. For my Hybrid G4, it's a simple text string in information[2] and it's correct. Might be worth noting those inverters that we know do report it properly.

Information[2] is a serial number of the inverter, not battery. There is apparently serial number of battery too (which is distinct for every battery in case you have several) in Data, but decoding didn't match what I see as battery serial number in https://www.solaxcloud.com/ UI.

jefft4 commented 1 year ago

Didn't mean to be rude, sorry if it came across that way, just wanted to keep conversation on topic here.

App reports version 4.2.6

I'm surprised, is this the version of Android app? Can you post link to Google Play? I'm using https://play.google.com/store/apps/details?id=com.solaxcloud.starter and it is only at 0.4.6 right now.

That's what it says inside the app. I've just checked for updates and there is one available... that's dated 12 June; play store says it's 0.4.6, app now says 4.2.7. I guess SolaX is as good with version numbering as it is with documentation and consistent data design!! 😆

Also - I notice you mention in your main readme that you left out the battery serial number because yours reports garbage. For my Hybrid G4, it's a simple text string in information[2] and it's correct. Might be worth noting those inverters that we know do report it properly.

Information[2] is a serial number of the inverter, not battery. There is apparently serial number of battery too (which is distinct for every battery in case you have several) in Data, but decoding didn't match what I see as battery serial number in https://www.solaxcloud.com/ UI. Now that's interesting... the previous version of the app showed that value when I tapped the battery, but you're correct, it's actually the inverter serial number (H...) not the battery at all. This latest version gives more info than the previous app. It shows a completely different value for the battery serial, '6S5...'. The app layout now looks as if it can handle two batteries, each with a slave pack.

Where did you think the battery serial(s) might be stored in Data[], based on the app code? If I know where to start looking, I'll check if it's reliable for at least this inverter. Not that I care about serial numbers, but it's nice to be complete!

I've also got a new entity on the main flow diagram in the new app, 'Meter'. Looks like that's to handle the mysterious delta that they label 'other generation' in the cloud app. I think it's just what we'd call in Finance, a 'reconciling item' - i.e., a calculated number to plug a gap 😉 so I doubt it maps to a Data[] element but that value always bugged me so I'll briefly check again.

nazar-pc commented 1 year ago

The local connection from the Android app to the X1 mini v2 appears to be fine

Okay, so we are looking at the same version. Any chance you can look into what requests the app is making? There might be something the app is doing outside of JS that I can't see, though I doubt that. Knowing what endpoints they query in which order would be really helpful.

https://play.google.com/store/apps/details?id=com.emanuelef.remote_capture should work, especially because it is unencrypted HTTP.

Where did you think the battery serial(s) might be stored in Data[], based on the app code?

According to source code this is how (apparently just for Data2):

getSN([Data[157], Data[158], Data[159], Data[160], Data[161], Data[162], Data[163]])

With the function being this:

function getSN(e) {
    for (var t = "", r = "", a = "", l = 0; l < 7; l++) {
        r =
            0 == this.comm.bit8high(1, e[l])
                ? "0"
                : String.fromCharCode(bit8high(1, e[l])) + "";
        a = 0 == this.comm.bit8low(1, e[l])
            ? "0"
            : String.fromCharCode(bit8low(1, e[l])) + "";
        t += r + a;
    return t
}
function bit8low(e, t) {
    var a = t % 256;
    return 1 == e ? a : 0 == e ? a < 128 ? a : a - 256 : void 0
}
function bit8high(e, t) {
    var a = parseInt(t / 256);
    return 1 == e ? a : 0 == e ? a < 128 ? a : a - 256 : void 0
}

I didn't bother rewriting it in more readable form, but hopefully you get the idea.