Close

Talking with the 3D printer

A project log for ESP Swiss Knife

This battery powered device is a all-in-one toolbox : WiFi AP, 3D printer remote, clock, serial console, sensors hub, and many more...

arcadia-labsArcadia Labs 05/26/2016 at 21:570 Comments

This is the last improvement to the device : showing the state of my 3D printer.

I already connected a Raspberry Pi, a TFT and a relay to the printer, installed Octoprint and writed a custom pygame interface (I love pygame + RPi). It allows me to control it from everywhere.

I also wanted to check the printer status, without a computer.

Octoprint software exposes an API, so it was almost just a matter of connecting the ESP to it, and parsing the exposed json.

Here is the code :

// OCTOPRINT
#define octoprint_host "1.2.3.4"
const int octoprint_httpPort = 5000;
String octoprint_apikey = "YOUR_OCTOPRINT_API_KEY";

String printerOperational;
String printerPaused;
String printerPrinting;
String printerReady;
String printerText;
String printerHotend;
String printerTarget;

// Function to get and parse the octoprint data
void getOctoPrint() {
  http.begin("http://" + String(octoprint_host) + ":" + String(octoprint_httpPort) + "/api/printer?apikey=" + String(octoprint_apikey) ); //HTTP

  // start connection and send HTTP header
  int httpCode = http.GET();
  // httpCode will be negative on error
  if(httpCode > 0) {
      // HTTP header has been send and Server response header has been handled
      // Serial.println("[OctoPrint] GET... code: " + String(httpCode) );

      if(httpCode == 409) {
        payload = http.getString();
        if (String(payload) == "Printer is not operational") {
          printerText = "Printer is not operational";
        }
      }

      else if(httpCode == 200) {
        payload = http.getString();

        StaticJsonBuffer<1024> jsonBuffer;
        JsonObject& root = jsonBuffer.parseObject(payload.c_str());
        // Test if parsing succeeds.
        if (!root.success()) {
          Serial.println("parseObject() failed");
          return;
        }
        else {
          const char* text;
          text = root["state"]["text"];
          printerText = String(text);
          text = root["state"]["flags"]["operational"];
          printerOperational = String(text);
          text = root["state"]["flags"]["paused"];
          printerPaused = String(text);
          text = root["state"]["flags"]["printing"];
          printerPrinting = String(text);
          text = root["state"]["flags"]["ready"];
          printerReady = String(text);
          text = root["temperature"]["tool0"]["actual"];
          printerHotend = String(text);
          text = root["temperature"]["tool0"]["target"];
          printerTarget = String(text);

          return;
        }
      }
      else {
        payload = http.getString();
        Serial.println( "[OctoPrint] HTTP_CODE_" + String(httpCode) + " : " + String(payload) );
      }
  } else {
      Serial.println("[OctoPrint] GET... failed, error: " + String(http.errorToString(httpCode).c_str()) );
  }
  http.end();
}

// Function to show octoprint state to the display
void octoprint1(SSD1306 *display, SSD1306UiState* state, int16_t x, int16_t y) {
  page = 41;
  ui.disableIndicator();
  if (printerText == "Printer is not operational") {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_16);
    display->drawString(displayWidth / 2 + x , 14 + y, "OFF" );
  }
  else {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_16);
    display->drawString(displayWidth / 2 + x , 14 + y, printerText);
    display->setFont(ArialMT_Plain_24);
    display->drawString(displayWidth / 2 + x , 40 + y, printerHotend + "°");
  }
  
}
Of course, you will have to check the octoprint status on timed intervals (I set it to 5 seconds).

It is also a very basic script, using the "state" json only. An improved script, checking the other exposed json, could tell remaining printing time, % completed, file being printed, etc... (example : http://docs.octoprint.org/en/master/api/job.html)

In all honesty : this is very cool and I love this feature !

Discussions