Jump to content

Inside the Ultimaker 3 - Day 3 - Remote access (part 2)


Daid

Recommended Posts

Posted (edited) · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

This is day 3 of "Inside the Ultimaker 3", Remote access part 2

 

-

 

 

Other days:

Day 1 - GCode

Day 2 - Remote access part 1

 

-

 

 

Welcome back. Yesterday we look at accessing data from the printer. Today we will look at changing data in the printer from remote access.

 

-

 

 

This is a whole lot more technical and complex then just accessing data. The reason for this is security and mistakes. First off, you might not want everyone on your network to start/abort/pause prints. And you might, by mistake, control a different printer then you wanted.

Think excidental use is uncommon? It happened at our office during development. And think how often you send something to a 2D printer to find it at a different printer then you expected.

 

Security!

First off, we had quite a few discussions about this at the office. As you need to have the proper trade-off between security and ease-of-use. Also, security is not an easy subject. Things that might look secure don't have to be. Things that are secure might be a pain to use.

 

-

 

 

So, we made the following decisions:

 

  • Reading of data is always possible. To make monitoring of printers easy, and while you can access camera feeds and print head positions. It's not possible to get the exact gcode file out of the printer. Thus the model is still quite secure.
  • Any "change" in the printer requires authentication. A change can be starting a print, aborting a print, or even changing the LED colors.
  • Authentication is done by a pairing mechanism. So your printer and Cura, a phone app, or any application you want need to "pair up". Most of this is invisible to the user.
  • Physical access is access. So if you can touch the printer you should also be able to pair up.
  • Multiple applications/devices can be paired with the printer at the same time.

 

The end result of this means that if you have an Ultimaker 3. And you connect with Cura for the first time, you need to say on the printer "I allow this Cura to use this printer".

20161021_110136.thumb.jpg.8ee96bc4affc8972c2741cb2333c0b36.jpg

 

-

 

 

On the technical side, this means any REST request to the printer that is not a HTTP GET request requires this pairing to be done correctly.

 

Pairing, under the hood.

The pairing process is actually a multi step process. These steps are:

 

  1. The application request a new ID/KEY combination from the printer. It does this with the name of the application and the name of the user that wants to access the printer.
  2. The printer returns this new ID/KEY combination to the application.
  3. The printer shows the dialog with DENY/ALLOW
  4. Until the user has selected ALLOW on the printer, this ID/KEY combination is not valid. The application keeps checking if the user selected allow or deny on the printer.
  5. Once ALLOW is selected, the ID/KEY combination can be used as username/password combination for HTTP Digest.

 

 

HTTP Digest...

The nice things about standards is, that you have so many to choose from. For security we looked for something that was quite easy to implement, but offered the security we needed.

While we did look at HTTPS, the problem there is that you need certificates, and which the openness of the devices this became complex really quick.

 

-

 

 

So, we looked at RFC 2617, known as HTTP Digest authentication. This standard on top of HTTP allows for easy username/password checking, while being protected against:

 

  • Man-in-the-middle attacks
  • Eavedrop attacks
  • Replay attacks

 

However, there is one problem with the standard. It says that you can always fall back to lesser secure modes. Which offer limited or no security at all.

So, we chose to implement one of the strongest forms of HTTP Digest, and REQUIRE it, instead of making all the security features optional.

 

-

 

 

This all sounds very complex. However, if you are a software engineer and you want to talk to the printer. You most likely have a library that will solve this for you.

However, as suggested in the other topic, postman is implements Digest auth as such a low level that it is impossible to get this to work consistantly.

The HTTP librart of QT has no problem with this. The "requests" library from python can also be used with almost no effort. I will provide an example in a bit.

 

The cop-out

If you are developing, and the security is in your way and you want to deal with it later. There is a cop-out. All this complex digest and pairing is disabled in the WiFi setup right now. As you are a local hotspot. This also made it easier to develop the WiFi setup.

So, for quick testing, you can start a WiFi setup, and connect to the local hotspot, and talk to the printer without any security.

 

The real thing

Finally, some actual things. There are 3 API parts that are important at first.

They are:

 

  • /api/v1/auth/verify: Used to check if your authentication id/key is still valid. This is the only API which requires authentication on a GET request. If you go here with your browser, you will get the username/password popup.
  • /api/v1/auth/request: This is used to setup a new pairing request. This needs to be done as a POST request, with 2 parameters "application" and "user". The API will return a JSON result with an "id" and a "key". This is your username and password for the HTTP Digest. However, this isn't valid till you pressed "ALLOW" at the printer. If you press "DENY", this combination of ID/KEY is discarded.
  • /api/v1/auth/check/{id}: This can be used to check the status of your new request. {id} should be filled with the result from the /api/v1/auth/request call. The result will be one of: "unauthorized", "authorized" or "unknown". "unauthorized" means that the user pressed "DENY" and you can discard the ID/KEY. "authorized" means "ALLOW" is pressed and you can now start using this ID/KEY. "unknown" means that the user hasn't done anything yet and you should try again.

 

Side effect: Currently, the printer only allows for 1 pairing request at the same time. If you send a 2nd request, the first one is denied automaticly.

 

-

 

 

So, in pseudo code:

 

if no (id, key) or "api/v1/auth/verify" == "unauthorized" then   id, key = post("api/v1/auth/request", application="Test", user="Daid")   while "api/v1/auth/check/" + id == "unknown" do       sleep 1 second   end   if "api/v1/auth/check/" + id == "unauthorized" then       abort: failed to pair up.   endend//We now have a valid id/key combination.

 

All that, just to pair up.

 

Doing actual things

Still following me? Good. If not, sorry, this is all very technical. I will provide example code at the end.

Now, we want to do thing. And there are quite a few things we can do with the API. I will cover a few things.

 

  • Changing the printer name. Why? It's the easiest API.
  • Changing the LED colors and heating up things.
  • Starting a print job. Why? It's the most important API.
  • Aborting a print job. After you started it, you might decide that you do not want it. (Or the print could be failing. But that is rare right?)

 

 

Change the name

Remember from day 1, the printer name was read at /api/v1/system/name. Now, we can set the printer name the same way, but instead of a HTTP GET, we need to use a HTTP PUT.

Now, all our APIs require JSON as input. This means a few things, the data in the PUT request needs to be valid JSON. And the Content-type header of the request needs to be set to "application/json".

If we want to set our printer name to MyUltimaker3, we get a request that looks like this:

 

PUT /api/v1/system/name HTTP/1.1Host: 10.180.1.209Connection: keep-aliveAccept: */*User-Agent: python-requests/2.11.1Accept-Encoding: gzip, deflateContent-type: application/jsonContent-Length: 14Authorization: Digest username="2af8417b8501e0422e191d5fbe64209e", realm="Jedi-API", nonce="76684432bdb9a1a386a877e41468a681", uri="/api/v1/system/name", response="50da68df53c0eeb9906212560b0077aa", qop="auth", nc=00000003, cnonce="b2316951bb03e010""MyUltimaker3"

 

This is an actual request that I logged. My auth ID is "2af8417b8501e0422e191d5fbe64209e" which you can see in the Authorization part, my auth KEY is "f9a43169c49bb9e81d670c946d6358dac428b820e0d9676e15b63bdcf57be45f", which you cannot see, and is used to generate the "response".

Placing this here to possibly assist in debugging if you are doing your own implementation of HTTP Digest.

The printer name is under some restrictions. So your printer might not always accept the new name.

 

Changing the LEDs and heating up.

Important note, in firmware versions 3.4.x these APIs are broken. They should be fixed as of firmware version 3.5.x

Changing the temperature. This is easy, we want to set the target temperature. The APIs for this are:

 

  • /api/v1/printer/heads/0/extruders/0/hotend/temperature/target
  • /api/v1/printer/heads/0/extruders/1/hotend/temperature/target
  • /api/v1/printer/bed/temperature/target

 

And, just like the name, you can just put a value into it to change the target. As this needs to be in JSON format, it needs to be a number without quotes, while the name was a string and thus needed quotes.

Setting the LED brightness and colors can be done in a single call. There are the APIs:

 

  • /api/v1/printer/led
  • /api/v1/printer/led/brightness
  • /api/v1/printer/led/saturation
  • /api/v1/printer/led/hue

 

The last 3 set each value seperately, but the first one can be used to set all 3 in one go. You do this by sending a single json dictionary containing the proper key/value combinations to /api/v1/printer/led. Once again, this needs to be a HTTP PUT request.

Example:

 

{"brightness": 50.0, "saturation": 20.0, "hue": 100.0}

 

Note, the current implementation of the API returns no status when you do this. So you do not know exactly if the request was accepted.

 

Starting a print

Starting a print is the most complex call there is, as you need to send a multi-part file upload. If you are not using a library for HTTP communication. Forget about it.

Else, it's easy, just do a HTTP POST request with a file upload to /api/v1/print_job, with the name of the file parameter to "file".

 

Abort/pausing a print job

You might want to abort or pause a print job remotely. This is all done trough the /api/v1/print_job/state API. Once again with PUT requests.

You need to PUT the new state you want into this state API, in the form {"target": "new state"}. There are 3 possible things you can PUT here.

 

  • abort, requests the print to be aborted.
  • pause, if the print isn't paused it will do so now.
  • print, if the print is paused, it will resume printing.

 

Note that this API in the current implementation always reports no content. So you need to poll the state to see if you request was actually honored.

 

Wrapping it up.

I'll just finish with my python3 code that can talk to the Ultimaker 3. You can use this as an example, or if you make an open-source product you can use it directly.

 

## This program is free software: you can redistribute it and/or modify# it under the terms of the GNU Affero General Public License as# published by the Free Software Foundation, either version 3 of the# License, or (at your option) any later version.# # This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU Affero General Public License for more details.# # You should have received a copy of the GNU Affero General Public License# along with this program.  If not, see .import requestsimport jsonimport osimport time## Ultimaker 3 API access class.#  Allows for access of the Ultimaker 3 API with authentication.#  Uses the python requests library to do the actual http requests, which does most of the work for us.class Ultimaker3:   # @param ip: IP address of the printer   # @param application: name of the application in string form, used during authentication requests and is shown on the printer.   def __init__(self, ip, application):       self.__ip = ip       self.__application = application       self.__session = requests.sessions.Session()       self.__setAuthData("", "")   # Set new authentication data, authentication data is send with each HTTP request to make sure we can PUT/POST data.   def __setAuthData(self, id, key):       self.__auth_id = id       self.__auth_key = key       self.__auth = requests.auth.HTTPDigestAuth(self.__auth_id, self.__auth_key)   # Load authentication data from a file. If this file does not exists, or the data in it is invalid, we request a new authentication set and store it in the file.   def loadAuth(self, filename):       try:           data = json.load(open(filename, "rt"))           self.__setAuthData(data["id"], data["key"])       except IOError:           self.__checkAuth()           self.saveAuth(filename)       if not self.__checkAuth():           self.saveAuth(filename)   # Save the authentication data to a file.   def saveAuth(self, filename):       json.dump({"id": self.__auth_id, "key": self.__auth_key}, open(filename, "wt"))   # Check if our authentication is valid, and if it is not request a new ID/KEY combination, this function can block till the user selected ALLOW/DENY on the printer.   def __checkAuth(self):       if self.__auth_id == "" or self.get("api/v1/auth/verify").status_code != 200:           print("Auth check failed, requesting new authentication")           response = self.post("api/v1/auth/request", data={"application": self.__application, "user": os.getlogin()})           if response.status_code != 200:               raise RuntimeError("Failed to request new API key")           data = response.json()           self.__setAuthData(data["id"], data["key"])           while True:               time.sleep(1)               response = self.get("api/v1/auth/check/%s" % (self.__auth_id))               data = response.json()               print(data["message"])               if data["message"] == "authorized":                   print("Authorized.")                   break               if data["message"] == "unauthorized":                   raise RuntimeError("Authorization denied")           return False       return True   # Do a new HTTP request to the printer. It formats data as JSON, and fills in the IP part of the URL.   def request(self, method, path, **kwargs):       if "data" in kwargs:           kwargs["data"] = json.dumps(kwargs["data"])           if "headers" not in kwargs:               kwargs["headers"] = {"Content-type": "application/json"}       return self.__session.request(method, "http://%s/%s" % (self.__ip, path), auth=self.__auth, **kwargs)   # Shorthand function to do a "GET" request.   def get(self, path, **kwargs):       return self.request("get", path, **kwargs)   # Shorthand function to do a "PUT" request.   def put(self, path, **kwargs):       return self.request("put", path, **kwargs)   # Shorthand function to do a "POST" request.   def post(self, path, **kwargs):       return self.request("post", path, **kwargs)

 

It's a very basic wrapper around the very new "requests" library for python. But it helps in setting up the authentication.

Example usage:

 

api = Ultimaker3("10.180.1.209", "Test script")api.loadAuth("auth.data")# Get all the system datasystem = api.get("api/v1/system").json()print(system["name"])# Change the system nameresult = api.put("api/v1/system/name", data="MyUltimaker3")print(result.json())# Set the target hotend temperature to 100C, and then back to 0.print(api.get("api/v1/printer/heads/0/extruders/0/hotend/temperature").json())result = api.put("api/v1/printer/heads/0/extruders/0/hotend/temperature/target", data=100.0).json()print(api.get("api/v1/printer/heads/0/extruders/0/hotend/temperature").json())result = api.put("api/v1/printer/heads/0/extruders/0/hotend/temperature/target", data=0.0).json()print(api.get("api/v1/printer/heads/0/extruders/0/hotend/temperature").json())# Change the LEDsapi.put("api/v1/printer/led", data={"brightness": 50.0, "saturation": 20.0, "hue": 100.0})# Start a print job.result = api.post("api/v1/print_job", files={"file": ("UM3_Box_20x20x10.gcode", open("UM3_Box_20x20x10.gcode", "rb"))})print(result.content)# Pause the printapi.put("api/v1/print_job/state", data={"target": "pause"})# Resume the printapi.put("api/v1/print_job/state", data={"target": "print"})# Abort the printapi.put("api/v1/print_job/state", data={"target": "abort"})

 

 

-

 

 

 

-

 

 

Disclaimer: Any information presented here could be wrong. I did my best to proof read everything, but it could confict with official statements and the actual behavior of the printer. This post is purely informative and does not necessary reflect the official view of Ultimaker.

20161021_110136.thumb.jpg.8ee96bc4affc8972c2741cb2333c0b36.jpg

Edited by Guest
  • Like 8
  • Thanks 1
Link to post
Share on other sites

Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

Thank you for the info @daid !! Cool stuff. 3dprint time lapses could be so cool with leds changing over time and custom scrips controlling a camera and leds.

Thanks!

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    I'm fairly happy with how the API turned out. I'm also quite curious as to what people will do with it.

     

    Well, now that I've been testing some odds and ends that we where not using yet, I've noticed a few things that we can improve and fix on. Especially status reporting on calls is a bit "random". For example, the result of setting a name is:

     

    {'message': " set", 'result': True, 'return_value': 1}

     

    or

     

    {'message': " set", 'result': True, 'return_value': 0}

     

    Depending on if it changed the name or not.

    While sending an abort/pause always comes back with an empty reply.

    Setting a single property of the led returns something that looks like setting the name, but setting them all at once returns an empty result like the abort/pause...

    I think our data querying part, and the data setting part are quite good, but the reporting back from certain calls is a bit messy.

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    I think our data querying part, and the data setting part are quite good, but the reporting back from certain calls is a bit messy.

     

    Yeah I agree. I focused more on getting the initial structure right and not so much on consistent reporting.

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Just made a small fix to the example script, authentication would not be saved if you needed new authenication because for example, you started to talk to a different Ultimaker3.

    • Like 1
    Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Hey, really nice work !

    Maybe you can help me with my problem.

    When i want to change the printer name the PUT request is working but i get from the printer: body: {"message": "Authorization required."}

    How can I send him the authentication id and key.

    I am trying to set up a nodeJS server.

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Hello,

    I'm using a Ultimaker3 with firmware : 3.7.7.20170627 (latest from stable).

    I have the following issue when calling GET /printer via a client generated from swagger tools : the Network object returns differs from the spec (returns an object : is an enum in spec), which throws a serialization exception.

    Is there an updated - correct - swagger doc somewhere ?

    A nuget package for a c# client ?

    If not, a github repo where we can contribute ?

    Thanks !

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    I'm trying to save a print by sending an API call to change the extruder temperature.  A bad pause caused the temperature to be set to 0, and it will not return back to the default printing temperature.  It tries to print at 0 C, which is cold extrusion, so I'm surprised it is letting me do that. 

     

    I'm trying to use the API documentation and digest authentication to accomplish this, but all I've been able to do is change the LED, and when I run the curl command through the API interface, it returns a 405 Method Not Allowed.  

     

    Is it even possible to modify extruder temperature during a print?  

     

    In other news, the forum has really garbled your python code posted here, removing a lot of the end of lines.  I'm trying to repair them, but since Python is an indent-based language, it is quickly becoming hectic and error-prone.  Do you have your class library and example in an easier format that retains the EOLs?

     

    api = Ultimaker3("10.180.1.209", "Test script")api.loadAuth("auth.data")
    # Get all the system data
    system = api.get("api/v1/system").json()print(system["name"])
    # Change the system name
    result = api.put("api/v1/system/name", data="MyUltimaker3")print(result.json())
    # Set the target hotend temperature to 100C, and then back to 0.
    print(api.get("api/v1/printer/heads/0/extruders/0/hotend/temperature").json())result = api.put("api/v1/printer/heads/0/extruders/0/hotend/temperature/target", data=100.0).json()print(api.get("api/v1/printer/heads/0/extruders/0/hotend/temperature").json())result = api.put("api/v1/printer/heads/0/extruders/0/hotend/temperature/target", data=0.0).json()print(api.get("api/v1/printer/heads/0/extruders/0/hotend/temperature").json())
    # Change the LEDs
    api.put("api/v1/printer/led", data={"brightness": 50.0, "saturation": 20.0, "hue": 100.0})
    # Start a print job.
    result = api.post("api/v1/print_job", files={"file": ("UM3_Box_20x20x10.gcode", open("UM3_Box_20x20x10.gcode", "rb"))})print(result.content)
    # Pause the print
    api.put("api/v1/print_job/state", data={"target": "pause"})
    # Resume the print
    api.put("api/v1/print_job/state", data={"target": "print"})
    # Abort the print
    api.put("api/v1/print_job/state", data={"target": "abort"})
    
    ## This program is free software: you can redistribute it and/or modify# it under the terms of the GNU Affero General Public License as# published by the Free Software Foundation, either version 3 of the# License, or (at your option) any later version.# # This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU Affero General Public License for more details.# # You should have received a copy of the GNU Affero General Public License# along with this program.  If not, see .
    import requests
    import json
    import os
    import time
    
    # Ultimaker 3 API access class.
    #  Allows for access of the Ultimaker 3 API with authentication.
    #  Uses the python requests library to do the actual http requests, which does most of the work for us.

    At the end there is where the EOLs become more difficult to repair. 

     

    Many thanks, 

    Sean 

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    There is discussion on how to set the temperature of either core here:

     

    Read particularly posts by robinmdh

     

    Note that your printer needs to be in developer mode and you need to ssh to the printer using username/password ultimaker/ultimaker.

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Thanks for the response.  Sadly, I did not put it in developer mode before printing, and so can't seem to connect via SSH.  Probably need to be like serially connected. 

     

     

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Oh.  That's a problem.  I put my printer into dev mode when it was just a few days old and it has been there since.  It's been a few years.

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Are there any other workarounds?  API Put method on the hotends doesn't seem to be allowed, which is immensely frustrating. 

     

    • Like 1
    Link to post
    Share on other sites

    Posted (edited) · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Can we submit the temperature API setting PUT "Method Not Allowed" as a bug?  This feature increases accessibility to the printer, and is awesome, but it fails to actually work when required.  Specifically, I'm trying to enact it during a pause, and I confirmed that the API Post method does not work when printing either. 

     

     

    Edited by SeanTapscott
  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Did some more testing, can move the head up and down and all kinds of positions, but cannot change the temperature. 

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    Finally figured it out. 

     

    Ok, figured this out. If you go back to his original API post, you'll find there's a typo in the Swagger API documentation. To set the temperature, you need to send a CURL -X PUT to http://192.168.1.15/.../extru.../1/hotend/temperature/target \
    -H 'Accept: application/json' \
    -H 'Authorization: Digest username="e7070a69184a88fa7155b53703c026de", realm="Jedi-API", nonce="ee9219554d47256f6fcda62f006908ea", uri="/api/v1/printer/heads/0/extruders/1/hotend/temperature/target", algorithm="MD5", qop=auth, nc=00000001, cnonce="iCCymccp", response="b1c26cba5c37a19c14731816024e269a"' \
    -H 'Content-Type: application/json' \
    -H 'Postman-Token: da5f6c8b-f68a-4fa8-94b6-9dd0eccc123c' \
    -H 'cache-control: no-cache' \
    -d 200

     

    Need to add /target to the end of the API call, and only pass in a number value, with no text. 

    • Like 1
    Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    I developed a web application by PHP. If I want to use POST print_job, do I need to generate new id and key every time? Because I found that a previous authorized id and key would be unauthorized next time. By the way, do I need to set api key? Thank you very much!

    • Like 1
    Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)

    That shouldn't happen, a id+key should remain valid unless the machine is factory reset. So you only need it once. (On HTTP Digest level things do expire, but I would expect PHP to handle this for you seamlessly)

    • Like 2
    Link to post
    Share on other sites

    Posted (edited) · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)
    On 5/18/2019 at 5:31 AM, Daid said:

    That shouldn't happen, a id+key should remain valid unless the machine is factory reset. So you only need it once. (On HTTP Digest level things do expire, but I would expect PHP to handle this for you seamlessly)

    Thank you very much! I solved this POST print_job problem. There are several syntax errors of PHP code.

    Edited by sxj1121
  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)
    On 5/28/2019 at 10:41 PM, sxj1121 said:

    Thank you very much! I solved this POST print_job problem. There are several syntax errors of PHP code.

    @sxj1121

    any chance you got your printing done with PHP, would you like to share some more on it then? I am working on the same thingy, actually I want to authorize the user to print GCODE files from my website to directly to their 3DPrinter say ( ultimaker S5). I also want to restrict the number of prints as well but that's second step. More interested into the process of printing a GCODE directly from my website to the 3D printer, have you any thoughts on it? Waiting on you and thanking you in advance!

  • Link to post
    Share on other sites

    Posted (edited) · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)
    3 hours ago, zaaf77 said:

    @sxj1121

    any chance you got your printing done with PHP, would you like to share some more on it then? I am working on the same thingy, actually I want to authorize the user to print GCODE files from my website to directly to their 3DPrinter say ( ultimaker S5). I also want to restrict the number of prints as well but that's second step. More interested into the process of printing a GCODE directly from my website to the 3D printer, have you any thoughts on it? Waiting on you and thanking you in advance!

    I am sorry that I can't directly share my code with you due to the restrictions of our lab. You could try to start from posting a gcode file on windows cmd by curl.

    In my PHP code, I also use curl to send gcode file. You could refer to my previous post. 

    For PHP7, it is:

            $data_array =  array(

              'jobname' => 'file',

              "file" => new \CURLFile($filedata)

            );

    If you want develop a perfect website. You need to develop a PHP file for using Get, Put, Post to call the API. Then develop another PHP file to receive the file which is uploaded from the front-end. Next save the file to local (You don't really need this step, but I don't know how to skip it). Then upload this file from local to API by Post.

     

    For restricting the number of prints, you could use AJAX to get the real-time print process. If it's not Not Found, then disable the upload function. But I think if 3D printer starts printing, then keep uploading files won't make any changes.

    Edited by sxj1121
    • Like 1
    Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)
    17 hours ago, sxj1121 said:

    I am sorry that I can't directly share my code with you due to the restrictions of our lab. You could try to start from posting a gcode file on windows cmd by curl.

    In my PHP code, I also use curl to send gcode file. You could refer to my previous post. 

    For PHP7, it is:

            $data_array =  array(

              'jobname' => 'file',

              "file" => new \CURLFile($filedata)

            );

    If you want develop a perfect website. You need to develop a PHP file for using Get, Put, Post to call the API. Then develop another PHP file to receive the file which is uploaded from the front-end. Next save the file to local (You don't really need this step, but I don't know how to skip it). Then upload this file from local to API by Post.

     

    For restricting the number of prints, you could use AJAX to get the real-time print process. If it's not Not Found, then disable the upload function. But I think if 3D printer starts printing, then keep uploading files won't make any changes.

    @sxj1121... .. Many thanks for your help and is much much appreciated! Thanks for the piece of code just above as well as a reference to your PHP7, Would you be kind enough to share the link to this.... I mean PHP7 you just mentioned above.... 

    Much appreciated once again and thankyou so very much...

    Have a nice day!

  • Link to post
    Share on other sites

    Posted · Inside the Ultimaker 3 - Day 3 - Remote access (part 2)
    11 hours ago, zaaf77 said:

    @sxj1121... .. Many thanks for your help and is much much appreciated! Thanks for the piece of code just above as well as a reference to your PHP7, Would you be kind enough to share the link to this.... I mean PHP7 you just mentioned above.... 

    Much appreciated once again and thankyou so very much...

    Have a nice day!

    you could download and install xampp, it would be easier for you to start programming. https://www.apachefriends.org/index.html

    • Thanks 1
    Link to post
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now
    • Our picks

      • UltiMaker Cura 5.7 stable released
        Cura 5.7 is here and it brings a handy new workflow improvement when using Thingiverse and Cura together, as well as additional capabilities for Method series printers, and a powerful way of sharing print settings using new printer-agnostic project files! Read on to find out about all of these improvements and more. 
         
        • 18 replies
      • S-Line Firmware 8.3.0 was released Nov. 20th on the "Latest" firmware branch.
        (Sorry, was out of office when this released)

        This update is for...
        All UltiMaker S series  
        New features
         
        Temperature status. During print preparation, the temperatures of the print cores and build plate will be shown on the display. This gives a better indication of the progress and remaining wait time. Save log files in paused state. It is now possible to save the printer's log files to USB if the currently active print job is paused. Previously, the Dump logs to USB option was only enabled if the printer was in idle state. Confirm print removal via Digital Factory. If the printer is connected to the Digital Factory, it is now possible to confirm the removal of a previous print job via the Digital Factory interface. This is useful in situations where the build plate is clear, but the operator forgot to select Confirm removal on the printer’s display. Visit this page for more information about this feature.
        • 0 replies
    ×
    ×
    • Create New...