ESP32 controller over WIFI
-
Update:
Thanks for the support from this community, the controller is now working. Here are some pictures.
It is quite basic but if you want to take a look into the code here it is https://github.com/cjccjj/Duet-ESP32-WIFI-Controller
Hi, I have a ESP32 board that integrated with a small OLED display and a few buttons. I want to make it a simple wifi controller for my Duet Printer which doesn't have a screen. It will only do simple tasks like start / stop / pause / resume / load upload filament / and maybe a few Gcode macro. After some research I am thinking to make use of the Telnet communication, to send Gcode to Duet board, which seems to be the easiest way. Is Telnet the best way for this? Please if anyone has any suggestion. Thank you!
-
A quick look at the specs suggests that it has a http client capability. Given that, maybe all you need is to use the http interface.
-
@stuartofmt Thank you for the reply, yes, it has http client. My question is more about the coding difficulties for my use. The Json response like rr_status looks clear but is depreciated or soon will be. The more powerful Object Model Framework looks very complicated to me, and I didn't find examples that can be direct reference. So, as I just want it to be a simple interface that shows minimal status and send a few Gcode, I wonder if I there is simpler way to write code for this.
-
@cjccjj How much RAM will be available? In my mind, you'd have to get the file list from Duets SD card, display it on the OLED and then select the file you want to "start". Same for macros...
You might be able to split the file list into small chunks? -
@cjccjj the object model response needs a JSON parser, then it is easy to use. You could look for an off-the-shelf JSON parser library, or use the one in PanelDueFirmware at https://github.com/Duet3D/PanelDueFirmware/blob/master/src/Hardware/SerialIo.cpp.
-
@cjccjj said in ESP32 controller over WIFI:
@stuartofmt The more powerful Object Model Framework looks very complicated to me, and I didn't find examples that can be direct reference.
The object model is no more complicated than rr_status, just a different structure. If you go the http route I, and many others,can assist. You'd be basically looking at at loop every "n' seconds for status that you are interested in and either a http get of post for sending commands (again depending on what you want).
As @dc42 pointed out - most of the work would be done by the json parser and, of course, any code relating to the ESP32 interfaces.
-
@o_lampe ESP32 has 520KB of ram, I think it is more then enough to show file list. I will still use PC but it is located in another room than the printer. So the controller is only for quick easy operations that have to be done in front of the printer.
-
@dc42 Thank you, I will definitely look into it. I have been using ArduinoJson library for some simple project, I think it will work.
-
@stuartofmt Thank you for the help and yes interfaces and network would be fine as I have done similar I think what I need is to understand the structure, and a little encouragement. I am just learning these in spare time and found it fun to play with both hardware and software.
-
I use python but the main thing to remember with SBC is that you need to include a header in the http calls.
Below is some skeletal code to give you the idea
def urlCall(url, post): if post is False: r = requests.get(url, timeout=timelimit, headers=urlHeaders) else: r = requests.post(url, data=post, headers=urlHeaders) return r
I get the header with some code like this:
global urlHeaders urlHeaders = {} URL = ('http://' + duet + '/machine/connect?password=' + password) # Connect with password r = urlCall(URL, False) code = r.status_code if code == 200: j = json.loads(r.text) sessionKey = j['sessionKey'] urlHeaders = {'X-Session-Key': sessionKey}
thereafter calls can be made like this
def getLayer() URL = ('http://' + duet + '/machine/status') r = urlCall(URL, False) if r.ok: try: j = json.loads(r.text) layer = j['job']['layer'] if layer is None: layer = -1 return layer except Exception as e: print('Could not get Layer Info') print(e)
-
@stuartofmt Thank you for the reminder and the examples. I think I now have a basic idea how to code the controller, that I send request as follows, parse the responses, add some logic and organize the information on the screen ( I am using a standalone board, /machine/status doesn't work)
url = "printer/rr_connect" #Connect url = "printer/rr_filelist?dir=0:/gcodes/" #List job files url = "printer/rr_gcode?gcode=" #Run Gcode url = "printer/rr_model?key=state&flags=v" #Get object at the key of "state"
One thing I am not sure about is how to constantly get the most common status. The "state" key of the object model is not a replacement of "rr_status". It seems to me it will require several http requests to collect status information across the model at different keys (one request per key). It is not very efficient and perhaps will slow down the update routine and performance.
-
@cjccjj said in ESP32 controller over WIFI:
@stuartofmt
One thing I am not sure about is how to constantly get the most common status.Ah - a read one of your earlier posts as if you were using SBC.
A couple of comments / suggestions as it relates to standalone and the rr_ calls
-
you do not need a session header nor do you need to use rr_connect first (unless you use password).
-
Take a look at what you want to do and only implement (in the interest of space) those calls you need.
-
rr_model?key=state returns a variety of information that you can parse down into. Note that some of the fields can return null so you do need to test to see if they are populated. What status do you think you want? Given the screen realestate - I'm guessing not a lot.
-
In general, you don't need to poll too often and any commands (like pause / resume etc) can just be sent when needed,
If you take a look at DuetLapse3.py, I implement both models. Search for ?key= and you will see some useful options
https://github.com/stuartofmt/DuetLapse3A skeletal example that may help:
URL = ('http://' + duet + '/rr_model?key=state') r = urlCall(URL, False) if r.ok: j = json.loads(r.text) status = j['result']['status'] message = '' if j['result'].get('messageBox') != None: if j['result']['messageBox'].get('message') != None: message = j['result']['messageBox']['message'] seq = j['result']['messageBox']['seq']
-
-
@cjccjj said:
One thing I am not sure about is how to constantly get the most common status. The "state" key of the object model is not a replacement of "rr_status". It seems to me it will require several http requests to collect status information across the model at different keys (one request per key).
Request the root key with the 'f' flag set. That will return all the frequently-changing status in a single operation.
-
@dc42 This saved me a lot of time. I looked into DWC and copied the flag set in it. Thank you.
-
@stuartofmt Thank you, the comments and suggestions are very helpful.
I was able to get it running over the weekend. It now shows basic printing job information and status, and can also run any Gcode stored on the board SD (thanks to the M98 command).
The coding is pretty sloppy and not very useful to others as I didn't handle the Json response very well it only works on my specific setup, but I uploaded it to https://github.com/cjccjj/Duet-ESP32-WIFI-Controller for my own record and just in case anyone want to take a look.
-
Congratulations. I have not used the flags. I could not find any description of their behavior.
If you found something - please let me know.
-
@stuartofmt the root key with flags? I just opened DWC with Chrome developer tool, and looked how it updates. It communicates using rr_model?flags=d99fn which is actually explained here https://docs.duet3d.com/User_manual/Reference/Gcodes#m409-query-object-model
-
@cjccjj said in ESP32 controller over WIFI:
@stuartofmt
... which is actually explained here https://docs.duet3d.com/User_manual/Reference/Gcodes#m409-query-object-modelAh - I never used M409, just http calls and never made the association. Thx.
In any case - I've recently moved to SBC , so cannot test further on standalone. Those flags don't exist according the the OpenAPI reference
https://github.com/Duet3D/DuetSoftwareFramework/blob/v3.4-dev/OpenAPI.yaml
which makes sense in that there is a "big" processor involvedYou should post some images when you can. Others will likely be interested.