November 11, 20223 yr I have been putting together some flows in Home Assistant NodeRed to query the SunSynk API on the website directly. Been working on endpoints. Looks like I have access to all readings and Inverter settings now. I have only pulled out some of them into sensors so I can use them in HA. Still need to make/find some nice cards. Busy looking at how to set some settings. Basic process is there, just need to make sure it all works Edited November 13, 20223 yr by Gary Waterworth
November 12, 20223 yr On 2022/11/11 at 9:42 AM, Gary Waterworth said: I have been putting together some flows in Home Assistant NodeRed to query the SunSynk API on the website directly. Been working on endpoints. Looks like I have access to all readings and Inverter settings now. I have only pulled out some of them into sensors so I can use them in HA. Still need to make/find some nice cards. Busy looking at how to set some settings. Basic process is there, just need to make sure it all works Useful Endpoints and Information. My flows are being changed daily atm with error checking and optimisation. When I have things more stable I will post an export. I must admit I love NodeRed integration in Home Assistant. Makes things like this easy to do with minimal outside components required. General Function Code I use to pass into the web request : I save the access token and inverter serial number into 2 sensors beforehand so they can be reused var states = global.get('homeassistant.homeAssistant.states'); var bearer = states["sensor.sunsynk_access_token"]; var sn = states["sensor.sunsynk_serial_number"]; msg.headers = { Authorization: "Bearer " + bearer.state, "Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", "Connection": "keep-alive", "Accept": "*/*", "Cache-Control": "no-cache", "Origin": "https://sunsynk.net", "Referrer": "https://sunsynk.net" } msg.url = "http://pv.inteless.com/api/v1/inverter/battery/" + sn.state + "/realtime?sn=" + sn.state + "&lan"; msg.payload=""; return msg; Example of Function Code to extract what is needed. ( This was for Invertor Temperature ) var origpayload = msg.payload; if (origpayload.msg == "Success") { msg.payload = msg.payload.data.temp; node.status(msg.payload); return msg } else { msg.payload = ""; node.status("Error") return null; } Various URLS; There is obv a lot more data being returned returned that can be used as seen above. I am only extracting detail into sensors that I am actually using atm. It is fairly straightforward to get the urls needed. Just needs some technical skill. If anyone is interested I will help privately. And no its not Wireshark. There is ssl decoding required. I am still working on getting settings back into Inverter. Having to b a lot more carefull with my testing. The requests below can be done http or https. Just using http for now while i test Get Bearer Token : POST : http://pv.inteless.com/oauth/token ( Format as per prev post above ) Get List of Invertors : GET : "http://pv.inteless.com/api/v1/inverters?page=1&limit=10&total=0&status=-1&sn=&plantId=&type=-2&softVer=&hmiVer=&agentCompanyId=-1&gsn=" Get Battery Info : GET : "http://pv.inteless.com/api/v1/inverter/battery/" + sn.state + "/realtime?sn=" + sn.state + "&lan" Get Grid Info : Get : "http://pv.inteless.com/api/v1/inverter/grid/" + sn.state + "/realtime?sn=" + sn.state Get Load Info : Get : "http://pv.inteless.com/api/v1/inverter/load/" + sn.state + "/realtime?sn=" + sn.state Get Input Info ( PV Etc ) : Get : "http://pv.inteless.com/api/v1/inverter/" + sn.state + "/realtime/input" Get Invertor Settings : Get : "http://pv.inteless.com/api/v1/common/setting/" + sn.state + "/read" Edited November 12, 20223 yr by Gary Waterworth
November 13, 20223 yr Just a sample view I am working on in the HA dashboard Current Solar Generation ( Tesla Power Card ) Summary Solar Generation ( HA Energy Management ) Solar Gen Graphs and Predication Stacked Graph of Summary ( Apexcharts ) Was during loadshedding and rain/cloudy ( grid V was 3.8v lol ) . So Numbers are all over the place Need to just look at the numbers in defferent scenarios for the tesla card and make sure the calculation logic is correct Edited November 13, 20223 yr by Gary Waterworth
November 13, 20223 yr Have a look at the card I created for HA. I'm sure you can pull all the necessary sensor data through the API. This is what my dashboard currently looks like
November 13, 20223 yr Thanks Will definatly have a look at it tomorrow. I have access to all the data for those sensors. Just need to pull some ones I dont have into sensors. Still have a lot of work to figure out updating the settings. Got a framework sorted out on paper. Just need to make sure it works. Ideally want to possibly change battery % settings based on load shedding level/time/anticipated weather. Edited November 13, 20223 yr by Gary Waterworth
November 29, 20223 yr Done some more work on this I have a situation where I like to cycle the batteries down to 20% to 30% of soc every night to save on importing eskom. But then I sometimes have a situation where if I have loadshedding early and it is cloudy etc then I have to skimp. Theory is that if I can calculate when load shedding is coming up ( using Eskom SE ) I can then turn off the "use timer" and basically leave it on ups until I am at a certain soc, based on a few other params as well . I have managed to figure out how to set this with the sunsynk website api. Going to be testing this logic for a while and then may need to tweak a bit // run every 15 min // -------------------------- // 1. If time left till LOS < 180 Mins // 2. If SOC < 60% // 3. If PV being generated < 4000 // 4. If Use Timer = 1 <- Enabled // Set Use Timer = 0 <- Disabled // Otherwise // If Use Time = 0 <- Disabled // Set Use Timer = 1 <- Enable // Otherwise stop message flow And the flow for the Eskom SE Calendar Calcs Edited November 29, 20223 yr by Gary Waterworth
December 6, 20223 yr Hi Does anybody know how to hack the Sunsynk 8kva hybrid inverter? I have a pesky rental company that switches me off before the 7th of each month even if I paid on the 5th it still takes 24-48h to reflect on their end….. then it takes a week of fighting back and forth before my system works again! I just want to teach these oaks a lesson. I won’t name them but if one of you gifted gents can help me much appreciated. you can contact me here we can exchange details to maybe forward a phone call. I have dongle plugged into my system….. don’t know if remote hacking would be possible?? Regards ”No-Solar”
December 6, 20223 yr Rented solar system ? Normal banking in RSA takes 2 to 3 days to clear between banks. Edited December 6, 20223 yr by Gary Waterworth
December 6, 20223 yr 3 hours ago, No Solar said: Hi Does anybody know how to hack the Sunsynk 8kva hybrid inverter? I have a pesky rental company that switches me off before the 7th of each month even if I paid on the 5th it still takes 24-48h to reflect on their end….. then it takes a week of fighting back and forth before my system works again! I just want to teach these oaks a lesson. I won’t name them but if one of you gifted gents can help me much appreciated. you can contact me here we can exchange details to maybe forward a phone call. I have dongle plugged into my system….. don’t know if remote hacking would be possible?? Regards ”No-Solar” Unplug the dongle? Or just pay them earlier ... Edited December 6, 20223 yr by RoganDawes
December 6, 20223 yr API Document I got somewhere else E-linter CSP Platform Open API Manual_V211004_sunsynk.pdf
December 29, 20223 yr On 2022/12/06 at 2:49 PM, Gary Waterworth said: API Document I got somewhere else E-linter CSP Platform Open API Manual_V211004_sunsynk.pdfUnavailable Hi Gary, Did you get anywhere writing settings to the inverter? I've managed to recreate what you have done in Node-Red and can read all of the values. I would like to control state of charge added overnight based on an estimate of solar generation. However, I can't see anything in the API documentation suggesting this can be set? Thanks.
December 30, 20223 yr Hey Ian Yes, I have actually been testing something for that, but I went with a different approach I basically enable and disable the "Use Timer" on whether I want to force charge batteries up to a certain value when load shedding is coming up. The duration of time before and soc levels I want are based on the duration of load shedding expected. None of this is in the documentation. I have been emulating what the app does, which is also different to the api docs on the reading of values. AT some stage I need to figure out the signing requirements for the openapi and move most of mine to the openapi instead of what I am doing now. You can set any values that are available in the app. If you want I will extract the raw list of variable names for you. Currently the way I set my system up is : var soclow = 50; var sochigh = 60; var pt = 60; if (lls > 180) { pt = 120; soclow = 60; sochigh = 80 } if (lls > 240) { pt = 180; soclow = 80; sochigh = 95 } if (lls > 300) { pt = 240; soclow = 95; sochigh = 98 } So if expected Load Shedding Length is <= 180mins , then start charging 60 mins in advance starting at 50% and stop charging at 60% 180.01 mins > 240mins , then start charging 120 mins in advance starting at 60% and stop charging at 80% 240.01 mins > 300mins , then start charging 180 mins in advance starting at 80% and stop charging at 95% 300.01 mins > infin , then start charging 240 mins in advance starting at 95% and stop charging at 98% I am busy testnig and refining these, but they will be individual based on your size and usage of your system Function Code for the actual check, outputs a 1 or 0 that is used to enable/disable the User Timer. I know the code is still a bit klunky and also has a number of checks because I am paranoid There is also functionality for a override switch to force the USE TIMER mode as well a switch to enable/disable use of the logic. var origpayload = msg.payload; var current = ""; var states = global.get('homeassistant.homeAssistant.states'); var timeruse = states["sensor.sunsynk_use_timer"]; var soc = states["sensor.nodered_2c7a9474e7859ee9"]; var timeleft = states["sensor.minutes_to_load_shedding"]; var pv1 = states["sensor.pv1_power"]; var pv2 = states["sensor.pv2_power"]; var gridv = states["sensor.grid_voltage"]; var override = states["switch.ups_mode_manual_override"]; var lengthls = states["sensor.length_load_shedding"]; // Error Checking if (lengthls.state != undefined) { } else { node.status("Undef lengthls"); return null } if (override.state != undefined) { } else { node.status("Undef override"); return null } if (timeruse.state != undefined) { } else { node.status("Undef timer");return null } if (soc.state != undefined) { } else { node.status("Undef soc");return null } if (pv1.state != undefined) { } else { node.status("Undef pv1");return null } if (pv2.state != undefined) { } else { node.status("Undef pv2");return null } if (timeleft.state != undefined) { } else { node.status("Undef timeleft");return null } if (gridv.state != undefined) { } else { node.status("Undef GridV"); return null } var pv = parseInt(pv1.state) + parseInt(pv2.state); var soclow = 50; var sochigh = 60; var pt = 60; var pvtest = 1500; var lls = parseInt(lengthls.state); if (lls > 180) { pt = 120; soclow = 60; sochigh = 80 } if (lls > 240) { pt = 180; soclow = 80; sochigh = 95 } if (lls > 300) { pt = 240; soclow = 95; sochigh = 98 } if (parseInt(timeleft.state) <= pt) { current = current + " TL " } if (parseInt(soc.state) <= soclow) { current = current + " SOC " } if (pv <= pvtest) { current = current + " PV "} if (timeruse.state === "1") { current = current + " TIMER "} if (override.state === "on") { msg.payload = "0" ; current = current + " OVERRIDE" ; node.status("Current: " + current + " pv:" + pvtest + " pt:" + pt + " low:" + soclow + " high:" + sochigh + " s:" + soc.state + " t:" + timeruse.state + " p:" + pv + " t:" + timeleft.state + " p:" + msg.payload); return msg ; } msg.payload = "1"; if ((parseInt(timeleft.state) <= pt ) && (parseInt(soc.state) <= soclow) && (pv <= pvtest)) { msg.payload = "0" } else { if ( timeruse.state === "0" ) { if ((parseInt(soc.state) >= soclow) && (parseInt(soc.state) <= sochigh) && (pv <= pvtest)) { current = current + " Delay Reactivate "; msg.payload = "0"; } else { current = current + " Reactivate "; msg.payload = "1"; } } else { current = current + " No Action "; msg.payload = "1"; } } if (parseInt(gridv.state) <= 200) { current = current + " NoGrid "; node.status("No Grid"); msg.payload = "1" } node.status("Current: " + current + " pv:" + pvtest + " pt:" + pt + " low:" + soclow + " high:" + sochigh + " s:" + soc.state + " t:" + timeruse.state + " p:" + pv + " t:" + timeleft.state + " p:" + msg.payload); return msg; Code for creating the request to enable/disable the USE TIMER notes : bearer is the bearer access code sn is the unit serial number peakAndVallery is the variable sent to sunsynk to enable disable the USE TIMER function var states = global.get('homeassistant.homeAssistant.states'); var bearer = states["sensor.sunsynk_access_token"]; var sn = states["sensor.sunsynk_serial_number"]; var timeruse = states["sensor.sunsynk_use_timer"]; if (timeruse.state != undefined) { } else { node.status("Undef");return null } if (bearer.state != undefined) { } else { node.status("Undef");return null } if (sn.state != undefined) { } else { node.status("Undef");return null } if (parseInt(timeruse.state) === parseInt(msg.payload)) { node.status("No Action") ; return null } else {} msg.headers = { Authorization: "Bearer " + bearer.state, "Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", "Connection": "keep-alive", "Accept": "*/*", "Cache-Control": "no-cache", "Origin": "https://sunsynk.net", "Referrer": "https://sunsynk.net" } msg.url = "https://pv.inteless.com/api/v1/common/setting/" + sn.state + "/set"; //msg.payload = "{sn:xxxx,"safetyType":"2","battMode":"-1","solarSell":"0","pvMaxLimit":"8000","energyMode":"1","peakAndVallery":"0","sysWorkMode":"1","sellTime1":"00:00","sellTime2":"04:00","sellTime3":"09:00","sellTime4":"15:00","sellTime5":"22:00","sellTime6":"23:00","sellTime1Pac":"8000","sellTime2Pac":"8000","sellTime3Pac":"8000","sellTime4Pac":"8000","sellTime5Pac":"8000","sellTime6Pac":"8000","cap1":"50","cap2":"40","cap3":"30","cap4":"90","cap5":"70","cap6":"60","sellTime1Volt":"49","sellTime2Volt":"49","sellTime3Volt":"49","sellTime4Volt":"49","sellTime5Volt":"49","sellTime6Volt":"49","zeroExportPower":"20","solarMaxSellPower":"9000","mondayOn":true,"tuesdayOn":true,"wednesdayOn":true,"thursdayOn":true,"fridayOn":true,"saturdayOn":true,"sundayOn":true,"time1on":true,"time2on":true,"time3on":true,"time4on":true,"time5on":true,"time6on":true,"genTime1on":true,"genTime2on":true,"genTime3on":true,"genTime4on":true,"genTime5on":true,"genTime6on":true}" msg.payload = { "sn": sn.state , "peakAndVallery": msg.payload } node.status("Action Sent"); return msg; I Use the Eskom SE Push integration to calculate the next load shedding time and length of it MINS TO NEXT LOADSHEDDING var origmsg = msg.payload; if (origmsg.start_time != undefined) { var startdate = new Date(origmsg.start_time); var start = startdate.getTime(); var currentdate = new Date(); var current = currentdate.getTime(); var diff = start - current; msg.payload = parseInt((diff / 1000 / 60).toFixed(1)); node.status(startdate.toLocaleString()); if ( msg.payload <= 0 ) { msg.payload = 99999 } else { } if ( origmsg.state === "on" ) { msg.payload = 99998 } else { } } else { msg.payload = 99997; node.status("No Events"); } return msg; // Error States // 99997 - No new event // 99998 - Current Event Running // 99999 - Start time has passed LENGTH OF LOADSHEDDING IN MINS var origmsg = msg.payload; msg.payload = 0; if ((origmsg.start_time != undefined) && (origmsg.end_time != undefined)) { var startdate = new Date(origmsg.start_time); var start = startdate.getTime(); var enddate = new Date(origmsg.end_time); var end = enddate.getTime(); var diff = end - start; if ( diff <= 0 ) { diff = 1 } msg.payload = parseInt((diff / 1000 / 60).toFixed(1)); // add 60 min due to se being 2 hours instead of 3 hours msg.payload = msg.payload + 60; node.status(startdate.toLocaleString()); } else { return null; } return msg; Edited December 30, 20223 yr by Gary Waterworth
December 30, 20223 yr Thanks Gary - that's fantastic. I'm actually in the UK but stumbled across this thread. I'll take a look through this - I'm mainly interested in setting the 'cap1' property as my electricity tariff allows me to charge four 4 hours overnight at a cheap rate. It looks like I can happily send that property via the API. I'm intending to vary this based on the projected solar energy production the next day - this will mean I try and avoid spilling any surplus solar back to the grid. It's winter time here and my panels are only giving around 1kWh some days so I'm not in a massive rush!
December 30, 20223 yr Back to the original topic of hacking the dongle itself, I have interposed a pair of rs232 dongles back to back, and used “socat -x /dev/ttyUSB0,b9600,rawer,nonblock /dev/ttyUSB1,b9600,rawer,nonblock” to dump the traffic in either direction. I did also have to inject 12V on the RI pin feeding the dongle, in order to provide sufficient power to actually run it. Quite clever actually, as any RS232 interface would have to be 12V tolerant on all pins. The data transferred certainly does look like simple modbus traffic as suggested in an earlier post, so flashing it with esphome and using either the streamserver integration or the modbus integration is definitely an option. And yes, I understand that altering the firmware of the dongle will prevent it from updating the firmware of the inverter itself. One could either keep a copy of the original firmware handy to flash back onto the dongle if needed, or look into reimplementing the protocol between the website and the dongle. Not too sure how worthwhile (or future proof) that would be. It also looks like connecting to this port could be a really easy alternative to the rs485 adapters that many folks are using (but sometimes struggle to get working). I’ll test in a bit whether the kellerza Sunsynk integration “just works” if I point mbusd to the rs232 adapter instead of the rs485 one, or if it needs some additional configuration and tweaking. That could also be a solution for folks that have multiple inverters in parallel, but that all want to be masters on the RS485 bus. I guess I also probably want to get the dev container running, and a fake mqtt server or similar to avoid polluting my hass installation with extra entities!
December 31, 20223 yr This post was recognized by Energy-Jason! RoganDawes was awarded the badge 'Great Support' and 50 points. Yup, confirmed that you can simply use mbusd and query the exact same registers via RS232 that you can via RS485. /usr/bin/mbusd -d -L - -P 503 -v 2 -C 32 -T 0 -p /dev/ttyUSB1 -s 9600 -m 8n1 -N 3 -W 500 Then: ➜ modbus-cli bin/modbus -s 1 192.168.201.1:502 178 Parsed 0 registers definitions from 1 files 178: 195 0xc3 ➜ modbus-cli bin/modbus -s 1 192.168.201.1:503 178 Parsed 0 registers definitions from 1 files 178: 197 0xc5 Where TCP:502 is the RS485 version of the above mbusd instance (identical command line, except for the device and the tcp port), and both work exactly the same. It's interesting to see that the dongle is attempting to detect devices on a number of different addresses, even over RS232, though. Some sorting through the logs later: Count Modbus Command String v-- Address v-- Command (03 == Read holding register) 5177 01 03 00 3b 00 42 b4 36 4776 01 03 00 96 00 32 24 33 4235 01 03 01 38 00 08 c4 3d 1395 01 03 00 00 00 13 04 07 1347 01 03 00 0f 00 01 b4 09 674 04 03 00 00 00 1e c5 97 674 03 03 00 00 00 1e c4 20 674 02 03 00 00 00 1e c5 f1 673 1d 03 00 00 00 1e c7 9e 673 1c 03 00 00 00 1e c6 4f 673 1b 03 00 00 00 1e c7 f8 673 1a 03 00 00 00 1e c6 29 673 19 03 00 00 00 1e c6 1a 673 18 03 00 00 00 1e c7 cb 673 17 03 00 00 00 1e c7 34 673 16 03 00 00 00 1e c6 e5 673 15 03 00 00 00 1e c6 d6 673 14 03 00 00 00 1e c7 07 673 13 03 00 00 00 1e c6 b0 673 12 03 00 00 00 1e c7 61 673 11 03 00 00 00 1e c7 52 673 10 03 00 00 00 1e c6 83 673 0f 03 00 00 00 1e c4 ec 673 0e 03 00 00 00 1e c5 3d 673 0d 03 00 00 00 1e c5 0e 673 0c 03 00 00 00 1e c4 df 673 0b 03 00 00 00 1e c5 68 673 0a 03 00 00 00 1e c4 b9 673 09 03 00 00 00 1e c4 8a 673 08 03 00 00 00 1e c5 5b 673 07 03 00 00 00 1e c5 a4 673 06 03 00 00 00 1e c4 75 673 05 03 00 00 00 1e c4 46 672 20 03 00 00 00 1e c3 73 672 1f 03 00 00 00 1e c6 7c 672 1e 03 00 00 00 1e c7 ad So, obviously, polling a large batch of registers on address 1 is the primary command, but it polls other registers on address 1 less frequently, and periodically checks to see if any other addresses between 01-20 (hex) will also respond. 5 01 03 01 b1 00 37 55 c7 5 01 03 01 40 00 64 44 09 5 01 03 01 2c 00 10 84 33 5 01 03 00 c8 00 64 c5 df 5 01 03 00 19 00 22 14 14 5 01 03 00 14 00 02 84 0f 2 01 03 00 00 00 1e c5 c2 And then a few other much less frequently polled registers. Edited December 31, 20223 yr by RoganDawes Added less frequently polled registers.
December 31, 20223 yr 13 hours ago, RoganDawes said: One could either keep a copy of the original firmware handy to flash back onto the dongle if needed, or look into reimplementing the protocol between the website and the dongle. Not too sure how worthwhile (or future proof) that would be. Just realised that it might be possible to run the firmware in the Wokwi ESP32 emulator (or other RISC-V ESP32 emulator, I guess), pointing it to mbusd which can multiplex/share access between multiple clients.
December 31, 20223 yr This sounds pretty cool @RoganDawes. I've been thinking about going the RS485 route, but didn't really want to spend money on hardware for it when my current solution is working well enough. If reprogramming the original dongle will work that would be awesome. I'm a software guy so I have no idea how one would go about flashing the dongle. What tools would one need?
December 31, 20223 yr 45 minutes ago, RoganDawes said: Just realised that it might be possible to run the firmware in the Wokwi ESP32 emulator (or other RISC-V ESP32 emulator, I guess), pointing it to mbusd which can multiplex/share access between multiple clients. But to make that work, there would need to be a layer that wraps MODBUS RTU with MODBUS TCP framing. Not quite as simple as I had thought it might be. Tested by doing "socat /dev/ttyUSB1,b9600,nonblock,rawer TCP:mbusd:502", and watching it disconnect.
December 31, 20223 yr 25 minutes ago, RoganDawes said: But to make that work, there would need to be a layer that wraps MODBUS RTU with MODBUS TCP framing. Not quite as simple as I had thought it might be. Tested by doing "socat /dev/ttyUSB1,b9600,nonblock,rawer TCP:mbusd:502", and watching it disconnect. That wont be too difficult, back in the day i created a mb tcp to rtu gateway on esp32 for plc. I do recall the rtu crc not used on the tcp side, as the tcp has inherent crc. If you add the crc, the tcp side will see framing error. Also i think the slave address falls away as the ip address is used binding. Not too sure about the slave address though. So unfortunately you will have to decode received frames from both side, and re assemble / encode for transmission. Edited December 31, 20223 yr by BritishRacingGreen
December 31, 20223 yr @RoganDawes if i am correct i saw Rust code on one of your github instances . Is that on ESP32 or on Openwrt?
December 31, 20223 yr 7 minutes ago, BritishRacingGreen said: @RoganDawes if i am correct i saw Rust code on one of your github instances . Is that on ESP32 or on Openwrt? This Wokwi simulator is intriguing, does it actually entertain a Hardware Abstraction Layer, where, eg, a hardware timer is emulated?
December 31, 20223 yr 1 hour ago, bmerry said: This sounds pretty cool @RoganDawes. I've been thinking about going the RS485 route, but didn't really want to spend money on hardware for it when my current solution is working well enough. If reprogramming the original dongle will work that would be awesome. I'm a software guy so I have no idea how one would go about flashing the dongle. What tools would one need? You just need a USB-UART dongle, just make sure that it is 3.3v, not 5V. And a few jumper wires, probably, just to do the hook up from the dongle to the UART. Basically, the ESP32 has a serial boot loader that you can invoke and interact with by pulling a pin low at power on. Usually, that is done automatically by the USB-UART if all the lines are connected for you, but the bare minimum is GND, RX, TX to the UART, voltage supplied to the ESP32 *somehow*, and some way to ground GPIO0. That can be as simple as pressing a jumper wire against a pin while applying power, doesn't have to be sophisticated.
December 31, 20223 yr 45 minutes ago, BritishRacingGreen said: That wont be too difficult, back in the day i created a mb tcp to rtu gateway on esp32 for plc. I do recall the rtu crc not used on the tcp side, as the tcp has inherent crc. If you add the crc, the tcp side will see framing error. Also i think the slave address falls away as the ip address is used binding. Not too sure about the slave address though. So unfortunately you will have to decode received frames from both side, and re assemble / encode for transmission. Oh sure, it's not difficult, just a simple matter of programming, right? 😉
December 31, 20223 yr 41 minutes ago, BritishRacingGreen said: @RoganDawes if i am correct i saw Rust code on one of your github instances . Is that on ESP32 or on Openwrt? If you did, it's not mine. I don't grok Rust yet, I'm afraid.
December 31, 20223 yr 33 minutes ago, BritishRacingGreen said: This Wokwi simulator is intriguing, does it actually entertain a Hardware Abstraction Layer, where, eg, a hardware timer is emulated? Wokwi is a cycle accurate hardware level emulator, with almost(?) all the peripherals implemented, as well as a number of external components that you might want to connect to your device.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.