October 8, 20223 yr @frankie, would it be a big ask to explain to a non-IT person how to use the Sunsynk API to extract the current battery charge via POST? I can't figure out how to get the API token. (I want to see if I can use the battery SOC in a Hubotat-dashboard.) Thank you.
October 16, 20223 yr I created basic python code to use your sunsynk account credentials to query API in case you need to trigger other actions, like IoT devices from real-time data like generation or utility prices. https://github.com/AsTheSeaRises/SunSynk_API
October 24, 20223 yr @you1@RoganDawesdo your captures have a TCP packet every 5 minutes whose payload is 292 bytes and starts with a5 06? (total packet length is 346 bytes). If so then we probably have compatible dongles. I'm making a fair amount of progress in decoding it, and running a process on my router to extract the samples and put them into Influxdb. I'll share a repo once it's in a state where someone other than me has a hope of making it work.
October 25, 20223 yr On 2022/10/04 at 3:40 AM, Madek said: Got a surprise the other day. Previously sunsylk issued a magneto data logger with their inverters (looks like it) . We could not understand why we can not find the client on the sunsylk app. Then saw they gave us a magneto data logger that can only work on solarman. I also ordered an add data logger 6mnths ago. When we wanted to replace the magneto data logger that was issued 2yrs ago with the installation we found out they gave us again a magneto data logger. Still gotto contact the supplier. I want to know how could they sell a magneto data logger to us if the order stupilated a sunsylk dongle. Anyone else with the same problem? Yep, I ordered a 5K Sunsynk earlier this year and specifically requested the Sunsynk dongle, but it still came with Solarman dongle. The wholesaler refused to swop it out. I have managed to get another Sunsynk logger in the mean time, but I am still stuck with an unwanted Solarman dongle, which I advertised in the classifieds. It still leaves a bad taste in my mouth.
October 25, 20223 yr 16 hours ago, bmerry said: @you1@RoganDawesdo your captures have a TCP packet every 5 minutes whose payload is 292 bytes and starts with a5 06? (total packet length is 346 bytes). If so then we probably have compatible dongles. I'm making a fair amount of progress in decoding it, and running a process on my router to extract the samples and put them into Influxdb. I'll share a repo once it's in a state where someone other than me has a hope of making it work. Yeah, my packets also start like that, but the length is variable. First packet is 0x2B long, response is 0x13 long, then 0x0B, response 0x0B, 0xA4, 0x17, etc.
October 25, 20223 yr 9 minutes ago, RoganDawes said: Yeah, my packets also start like that, but the length is variable. First packet is 0x2B long, response is 0x13 long, then 0x0B, response 0x0B, 0xA4, 0x17, etc. I do also have short packets, although not such a variety of lengths. I don't know what they are, but the packets with the sensor data are much longer (as I say, in my case 292 bytes of payload), and have the inverter serial number (in ASCII) pretty close to the start.
November 4, 20223 yr Hi all, don't know if this thread is still alive but here is what I have deciphered so far, in the 292 bytes payload of the dongle. If anyone else can maybe confirm that this corresponds to their inverter data as well, I have the SUNSYNK-5K-SG01LP1
November 4, 20223 yr @PLCguyit's a bit tricky to read the offsets from that view since they don't start at zero, so at a glance I'm not able to say if it all lines up, but it seems promising! I've pushed my work-in-progress to Github, and you can see the fields I've decoded here. I'll take a look this weekend to see if they match yours and add any you have that I'm missing (I don't think I have any of the static fields like discharge limit). Note that some fields seem to be duplicated so for example I've noted battery temperature in a different place to you. Have you spotted anything that might be a time zone? The embedded timestamp is annoyingly in local time, which is not ideal for a time series database. I could just subtract a known time zone offset, which would be fine for South Africa, but in areas with daylight savings it gets more complicated and ambiguous. For now I'm just using the packet timestamps, but the dongle buffers data if the connection drops so the packet timestamps can be significantly later than the data they contain.
November 4, 20223 yr 2 hours ago, PLCguy said: Hi all, don't know if this thread is still alive but here is what I have deciphered so far, in the 292 bytes payload of the dongle. If anyone else can maybe confirm that this corresponds to their inverter data as well, I have the SUNSYNK-5K-SG01LP1 Neat! Nice work!
November 4, 20223 yr 3 hours ago, PLCguy said: I have the SUNSYNK-5K-SG01LP1 That's the same model I have. Is your dongle also the unbranded one with red and green LEDs in it, or the Sunsynk-branded one?
November 4, 20223 yr 32 minutes ago, bmerry said: That's the same model I have. Is your dongle also the unbranded one with red and green LEDs in it, or the Sunsynk-branded one? I guess it's the branded one as it has "Sunsynk" printed on it, but it also does have the red and green LED's. The same one posted earlier by @valienté with the picture. Below is the UI served from it. I have also checked and it's only port 80 open on the unit, the web server is mongoose6.7 but don't know if there are any exploits to try and get root on the unit. cgi-scripts that can be executed on the unit are, and there are others: http://<device-ip>/config?command=status http://<device-ip>/config?command=devinfo but the interesting one is this: just going to keep digging... Edited November 4, 20223 yr by PLCguy
November 4, 20223 yr 12 minutes ago, PLCguy said: I guess it's the branded one as it has "Sunsynk" printed on it, but it also does have the red and green LED's. Yeah, seems to be the same as mine (identical hardware revision); I guess they just decided to slap their logo on it. For what you identified as battery capacity: is that in Ah? That does seem to fit with my battery.
November 4, 20223 yr 44 minutes ago, PLCguy said: I have also checked and it's only port 80 open on the unit, the web server is mongoose6.7 but don't know if there are any exploits to try and get root on the unit. cgi-scripts that can be executed on the unit are, and there are others: The whole setup seems to be a typical IoT security disaster. I haven't yet seen a way to change the Wifi password used to access that interface, which means anyone in my area could connect and start uploading firmware (maybe it has to be signed but given the rest of the security I wouldn't count on it) or routing the telemetry through their connection. Some of my fields agree with yours, but there do seem to be differences. For example, where you've indicated INV AC output load, it looks like I have battery voltage (V-Bat in the data logger app). Your battery voltage is my V-BMS (similar to but not quite the same as V-Bat). Your INV power I can't seem to match up to any of the custom graphs shown by the data logger. I'm wondering if the logger sends any metadata when it first connects to indicate which field is which. At some point I want to try deliberately break its TCP connection while still running tcpdump on the router so that I can see what the initial exchange looks like.
November 4, 20223 yr 1 hour ago, PLCguy said: I have also checked and it's only port 80 open on the unit, the web server is mongoose6.7 but don't know if there are any exploits to try and get root on the unit. It’s an ESP32 running an RTOS, not Linux, so there’s no question of rooting it. I have pulled the firmware off mine using esptool, and there are a bunch of undocumented endpoints that may be worth poking at. Some are more complicated than a simple GET, though, and probably require specific parameters to be POSTed to them. One day I’ll get Ghidra going and take a look.
November 4, 20223 yr 2 minutes ago, bmerry said: I'm wondering if the logger sends any metadata when it first connects to indicate which field is which. At some point I want to try deliberately break its TCP connection while still running tcpdump on the router so that I can see what the initial exchange looks like. 🙂 I think I DOS'ed mine this morning when I ran gobuster against it, so I added delays of .2s between single queries, unfortunately no fruitful results. I'm still capturing packets atm and dont' want to stop the capture till at least after 00:00, I suspect some bytes will reset when it is the next day but want to confirm this with the current capture that has been running since this morning. With those "magic" bytes that start in the payload byte 7/8 (starting from 0) is an incremental counter that gets incremented by both the dongle and the server (hosted in China, and owned by Alibaba data center) each time one of them transmit a packet in the stream, since the capture this morning this counter is still going... the dongle represent the even values and responses from the server are odd values, but they are sequential. bytes 42/42 (from 0) is also some form of a counter that increments every 4 or 5 transmits, this is not consistent, but it keeps increasing (this may be a totalizing value), will confirm.
November 4, 20223 yr 2 minutes ago, RoganDawes said: It’s an ESP32 running an RTOS, not Linux, so there’s no question of rooting it. I have pulled the firmware off mine using esptool, and there are a bunch of undocumented endpoints that may be worth poking at. Some are more complicated than a simple GET, though, and probably require specific parameters to be POSTed to them. One day I’ll get Ghidra going and take a look. @RoganDawes ahh makes sense 🙈 saw the image earlier in the thread but didn't register 😄
November 6, 20223 yr I've written a bit of documentation for the capture tool, so while it's still pretty rough, I think it's ready for other people to try it out. See instructions at https://github.com/bmerry/sunsniff, and let me know if you run into difficulties, since that'll help me improve the instructions.
November 6, 20223 yr On 2022/11/04 at 10:00 PM, PLCguy said: bytes 42/42 (from 0) is also some form of a counter that increments every 4 or 5 transmits, this is not consistent, but it keeps increasing (this may be a totalizing value), will confirm. Bytes 41 and 42 are always in the range 0-59 so I'm fairly sure they're the minute and second of the timestamp.
November 6, 20223 yr 3 hours ago, bmerry said: Bytes 41 and 42 are always in the range 0-59 so I'm fairly sure they're the minute and second of the timestamp. Bytes 0 - 10 -> payload header Byte 2 = A1 when packet from server, = 01 when packet from wifi dongle Bytes 9-10 -> Actual data byte count from byte 11 Byte 11-20 -> Inverter ID Byte 37 -> Year Byte 38 -> Month Byte 39 -> Day Byte 40 -> Hour Byte 41 -> Minute Byte 66-67 -> Daily battery charge totalizer (resets to zero @ 00:00) | kWh = raw value / 10 Byte 68-69 -> Daily battery discharge totalizer (resets to zero @ 00:00) | kWh = raw value / 10 Byte 74-75 -> Total battery discharge since beginning of time | kWh = raw value / 10 Byte 82-83 -> Total grid import since beginning of time | kWh = raw value / 10 Byte 84-85 -> Grid instantaneous frequency | Hz = raw value / 100 Byte 96-97 -> Load usage totalizer since beginning of time | kWh = raw value / 10 Byte 140-141 -> Battery capacity (Battery setup screen parameter) | Ah = raw value Byte 182-183 -> V-grid-L1 | V = raw value / 10 Byte 186-187 -> Inverter AC output Byte 190-191 -> Unidentified voltage Byte 192-193 -> Unidentified voltage Byte 212-213 -> Grid power (Instantaneous) | watt = raw value Byte 216-217 -> Unidentified power Byte 218-219 -> Unidentified power Byte 220-221 -> Inverter power Byte 228-229 -> Inverter load output | watt = raw value / 10 Byte 242-243 -> Battery watts (instantaneous) Byte 244-245 -> Battery current (instantaneous) Byte 246-247 -> Unidentified frequency Byte 248-249 -> Unidentified frequency Byte 280-281 -> Battery capacity (0 when grid present, capacity value when grid off) Byte 282-283 -> Discharge limit Byte 285 -> SOC (State of charge) | % = raw value Byte 286-287 -> Battery voltage from BMS Byte 288-289 -> Battery current from BMS Byte 290-291 -> Real time battery temperature (range -99.9 degrees to +99.9 degrees scaled between 0x01 AND 0x7CF, where 0 degrees = 0x3E8
November 6, 20223 yr 7 minutes ago, PLCguy said: Bytes 0 - 10 -> payload header Byte 2 = A1 when packet from server, = 01 when packet from wifi dongle Bytes 9-10 -> Actual data byte count from byte 11 Byte 11-20 -> Inverter ID Byte 37 -> Year Byte 38 -> Month Byte 39 -> Day Byte 40 -> Hour Byte 41 -> Minute Byte 66-67 -> Daily battery charge totalizer (resets to zero @ 00:00) | kWh = raw value / 10 Byte 68-69 -> Daily battery discharge totalizer (resets to zero @ 00:00) | kWh = raw value / 10 Byte 74-75 -> Total battery discharge since beginning of time | kWh = raw value / 10 Byte 82-83 -> Total grid import since beginning of time | kWh = raw value / 10 Byte 84-85 -> Grid instantaneous frequency | Hz = raw value / 100 Byte 96-97 -> Load usage totalizer since beginning of time | kWh = raw value / 10 Byte 140-141 -> Battery capacity (Battery setup screen parameter) | Ah = raw value Byte 182-183 -> V-grid-L1 | V = raw value / 10 Byte 186-187 -> Inverter AC output Byte 190-191 -> Unidentified voltage Byte 192-193 -> Unidentified voltage Byte 212-213 -> Grid power (Instantaneous) | watt = raw value Byte 216-217 -> Unidentified power Byte 218-219 -> Unidentified power Byte 220-221 -> Inverter power Byte 228-229 -> Inverter load output | watt = raw value / 10 Byte 242-243 -> Battery watts (instantaneous) Byte 244-245 -> Battery current (instantaneous) Byte 246-247 -> Unidentified frequency Byte 248-249 -> Unidentified frequency Byte 280-281 -> Battery capacity (0 when grid present, capacity value when grid off) Byte 282-283 -> Discharge limit Byte 285 -> SOC (State of charge) | % = raw value Byte 286-287 -> Battery voltage from BMS Byte 288-289 -> Battery current from BMS Byte 290-291 -> Real time battery temperature (range -99.9 degrees to +99.9 degrees scaled between 0x01 AND 0x7CF, where 0 degrees = 0x3E8 That mostly agrees with what I've found, at least on the fields where we both have something (see here), but for me 248-249 is PV power, not a frequency, and bytes 212-213 are always zero. So perhaps they change the fields around depending on the firmware version? I did dump out the initial communication. I'd hoped to see something like a JSON document mapping offsets to identifiers, but all I could clearly identify were a bunch of version information, serial numbers, the connection key (in plaintext, yay) etc. Maybe I should see what I can get out of the cloud API. If I can download a full day of data it'll be easier to match to what I capture with tcpdump (currently I'm doing the matching by eyeball comparison to the phone app).
November 6, 20223 yr By the way, has anyone had their inverter long enough to charge/discharge/generate more than 6553.6 kWh? I assume the totals must actually be 32 bit, but until it ticks past that point it's going to be hard to say where the high bits are stored (assuming that they are stored, rather than reconstructed on the server side from history).
November 6, 20223 yr 10 minutes ago, bmerry said: (currently I'm doing the matching by eyeball comparison to the phone app). Yeah also doing eyeball matching but with the browser link
November 8, 20223 yr I've starting hacking together a Python script to scrape the API for data and get it into a Pandas dataframe. I'm planning to use it to automate matching fields to the raw TCP data, but it could probably also be used directly as a source of data e.g. to stash it in a local time-series database. See https://gist.github.com/bmerry/1f9317485830e736974c98cb1e5fd3b5. At the moment it just prints the dataframe, so to be useful you'll need to extend it to do something with the data.
November 9, 20223 yr Ok, I went a bit further with my script and found matches for all the graphs the web interface shows (in the Custom tab) that isn't just all zeros. In some cases there are multiple matches because several plots are identical. P-pv is a slightly odd case because it mostly matches to offset 248, but is sometimes off by 1. The values in each entry are offset:scale:bias, and where there are multiple entries there are multiple matching offsets. What will still be interesting is to check which offsets are NOT matched (and not all zeros). @PLCguyalready spotted one bit in one field that seems to be a boolean for grid connectivity, but I don't think we know what the other bits are. Grid P-grid ['214:1.0:0.0', '216:1.0:0.0', '220:1.0:0.0'] Grid F-grid ['84:0.01:0.0'] Grid I-grid-L1 ['196:0.01:0.0'] Grid V-grid-L1 ['176:0.1:0.0', '180:0.1:0.0'] Grid Import ['78:0.1:0.0'] Grid Total Import ['82:0.1:0.0'] Grid Total Export ['88:0.1:0.0', '112:0.1:0.0'] Grid P-L1 ['210:1.0:0.0'] Inv P-inv ['222:1.0:0.0', '226:1.0:0.0'] Inv P-pv [] Inv F-ac ['260:0.01:0.0', '262:0.01:0.0'] Inv V-ac-1 ['184:0.1:0.0', '188:0.1:0.0'] Inv I-ac-1 ['204:0.01:0.0'] Inv DC TEMP ['106:0.1:-100.0'] Inv AC TEMP ['108:0.1:-100.0'] String I-pv-1 ['146:0.1:0.0'] String I-pv-2 ['150:0.1:0.0'] String V-pv-1 ['144:0.1:0.0'] String V-pv-2 ['148:0.1:0.0'] String Daily Production ['142:0.1:0.0'] String Total Production ['118:0.1:0.0'] Battery SOC ['244:1.0:0.0'] Battery T-bat ['240:0.1:-100.0'] Battery V-bat ['242:0.01:0.0'] Battery I-bat ['258:0.01:0.0'] Battery P-bat ['256:1.0:0.0'] Battery Capacity ['140:1.0:0.0'] Battery Today Charging ['66:0.1:0.0'] Battery Today Discharging ['68:0.1:0.0'] Battery Total Discharging ['74:0.1:0.0'] Battery Total Charging ['70:0.1:0.0'] Battery T-BMS ['290:0.1:-100.0'] Battery V-BMS ['286:0.01:0.0'] Battery V-Charge-BMS ['276:0.01:0.0'] Battery I-BMS ['288:1.0:0.0'] Battery I-Charge-Limit-BMS ['280:1.0:0.0'] Battery I-Discharge-Limit-BMS ['282:1.0:0.0'] Load P-load ['228:1.0:0.0', '232:1.0:0.0'] Load P-Load-L1 ['228:1.0:0.0', '232:1.0:0.0'] Load Daily Consumption ['94:0.1:0.0'] Load Cumulative Consumption ['96:0.1:0.0'] Meter P-External-CT-L1 ['214:1.0:0.0', '216:1.0:0.0', '220:1.0:0.0'] Meter P-External-CT-Total ['214:1.0:0.0', '216:1.0:0.0', '220:1.0:0.0']
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.