Skip to content
View in the app

A better way to browse. Learn more.

Power Forum - Renewable Energy Discussion

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

SunSynk WiFi Dongle Hacking.

Featured Replies

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 :)

 

image.thumb.png.ff083c4839fe9e6e78c67c44deaf2bf9.png

 

Edited by Gary Waterworth

  • Replies 152
  • Views 48.9k
  • Created
  • Last Reply

Top Posters In This Topic

Most Popular Posts

  • 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

  • Is an ESP32 MCU, would be cool to reflash with ESPhome and pull all the data from the inverter that way.   

  • To confirm do you want to pull the firmware from the nodemcu, or just utilise their API?   It might be easier to just write some HA integration which directly talks to the SunSynk cloud APIs

Posted Images

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 :)

 

image.thumb.png.d89e6b4830f47996cfc37c4e1a23ddfa.png

 

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 by Gary Waterworth

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

 

image.thumb.png.fc158793a935dc5c8f8cc177679f3701.png

Edited by Gary Waterworth

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 by Gary Waterworth

  • 3 weeks later...

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
image.thumb.png.7bca2b51d38cb78f4fe2d8ce82432168.png
 

And the flow for the Eskom SE Calendar Calcs

image.png.9e2f2ca3b027a8be8842fe368adf77e4.png

Edited by Gary Waterworth

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”

 

 

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 by RoganDawes

  • 4 weeks later...
On 2022/12/06 at 2:49 PM, Gary Waterworth said:

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. 

Hey Ian

 

Yes, I have actually been testing something for that, but I went with a different approach

image.png.34a56fb6609ceac76ff1b73e4d512074.png

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

image.thumb.png.27a8a4a9aa55739ca3d4069c972ef4de.png

 

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
 
image.thumb.png.79d5a9ee33aa62039755074e4282fc5e.png
 
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;

 

 
 
 
 
 
 

 

 

 

image.png

Edited by Gary Waterworth

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!

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!

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 by RoganDawes
Added less frequently polled registers.

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.

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?

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.

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 by BritishRacingGreen

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. 

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? 😉 

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.

Guest
Reply to this topic...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.