Miles Nash
Published © CC BY-NC

3D Printer Monitoring with Alexa and Arduino

This gadget allows users to monitor many aspects of their 3D printer and current 3D print through a NeoPixel ring and a custom Alexa skill.

IntermediateFull instructions provided8 hours8,281

Things used in this project

Story

Read more

Custom parts and enclosures

Enclosure

Print and Assemble

Schematics

Circuit Diagram

Correct wiring for Printer Host

Code

Amazon Sample Utterances

ColdFusion
Paste into amazon sample utterances box.
Introduction to introduce itself
Introduction introduce yourself
Introduction introduction
Introduction what can you do
Introduction what are you capable of
Introduction what it is capable of
Introduction what is can do
Introduction what it's functions are
Introduction about its functionality
Introduction what is is that you can do
Introduction what exactly can you do
Introduction what is your prpose
Introduction who are you
Introduction what is the purpose of you
Introduction what is printerhost
Introduction what do it does with my printer
Introduction what it does with my three dee printer
Introduction how and what ist is capable of doing with my three dee printer
Introduction what were you designed to do
Introduction what problem do you solve
Overview overview
Overview give me an overview
Overview to overview
Overview please overview
Overview to please give me an overview
Overview to summarise my print
Overview to get me an overview of my print
Overview to give a summary of my print
Overview to tell me how my print is doing
Overview to tell me a summary of my print
Overview how is my print
Overview how is my print going
Overview what is happening with my print
Overview what is going on with my print
Overview how is myy three dee print
Overview how's my three dee print doing
Overview to check on my print
Overview to check on my three dee print
Overview to give me a summary of my print
Overview to give me a summary of my three dee print
TimeLeft how much time is left on my print
TimeLeft how much time is left on my three dee print
TimeLeft how much longer will it be until my print is done
TimeLeft how much longer will it be until my three dee print is done
TimeLeft how much more time is left on my print
TimeLeft how much more time is left on the print
TimeLeft how much more time is left on my three dee print
TimeLeft how much more time is left on the three dee print
TimeLeft how much longer does my printer have to go
TimeLeft how much longer does my printer have left
TimeLeft how much time until completion
TimeLeft when will my print be done
TimeLeft when will my print complete
TimeLeft when will my print be finished
TimeLeft when will the print be finished
TimeLeft time left
TimeLeft how much more time
TimeLeft time remaining
TimeLeft to tell me how much time is left
TimeLeft to tell my how much time is left opn my print
TimePrinted how long has my printer been printing for
TimePrinted how long has my three dee printer been printing for
TimePrinted how much time has my three dee printer been prining for
TimePrinted how many hours have been printed
TimePrinted time printed
TimePrinted how long has my print been going for
TimePrinted how long has my print been printing
TimePrinted how long has my three dee print been three dee printing
TimePrinted to tell me how long my printer has been printing
TimePrinted to tell me how much time my three dee print has been printing for
TimePrinted how long my printer has been running
TimePrinted how long my print has been three dee printing
TimePrinted for how much time my printer has printed
TimePrinted for how long my printer has been printing
TimePrinted for how long my printer has been printing for
TimePrinted for the time that I have been printing
TimePrinted for the time that my print has been printing for
TimePrinted for the amount of time that my printer has already priunted
TimePrinted the amount of time for which my three dee printer has been three dee printing
TimePrinted the time my printer has spent printing
PercentComplete what percent of my print is completed
PercentComplete percent completed
PercentComplete what percent of my print has been printed
PercentComplete to what extent has my print finished
PercentComplete what percent is my print done
PercentComplete how much of my print has been printed
PercentComplete what percent is my print completed
PercentComplete to tell me what ercent of my print is finished
PercentComplete to tell me what percentage my print is completed
PercentComplete what percent of my print is done
PercentComplete how far my print is in percentage
PercentComplete for the percentage my print has completed
PercentComplete for the percentage of which my print has printed
PercentComplete the percentage of my print which has been printed
PercentComplete the amount that my print is finished in percent
PercentComplete how much percent my printer is done
PercentComplete the percent completion of my print
PercentComplete the percent which my printer has completed
PercentComplete how much print is done in percent
PercentComplete the percentage of three dee print completion
PercentComplete the percentage my three dee print has printed
PercentComplete how many percents my printer has printed
EstimatedTime how long is my print expected to take
EstimatedTime how long should this print take
EstimatedTime how long should it take my printer to print this model
EstimatedTime how much time will it take for my printer to print this
EstimatedTime what is the estimated print time of my print
EstimatedTime what's the expected print time of my print
EstimatedTime what amount of time is necessary for my print to fully complete
EstimatedTime how much time will my print take
EstimatedTime how much time will ti take my print to fully print
EstimatedTime how long my print is expected to last
EstimatedTime how much time my print is estimated to last
EstimatedTime the amount of time my three dee print will take
EstimatedTime how long it will take my three dee print to print from start to finish
EstimatedTime estimated time
EstimatedTime total estimated print time
EstimatedTime expected print time
EstimatedTime for the expected print time
EstimatedTime for the ammount of time my print should take
EstimatedTime for the time my print will take
EstimatedTime for the time my three dee printer will take to complete
FileName file name
FileName what file do I have selected
FileName which file I have selected
FileName which file I am printing
FileName what file I am printing
FileName for the name of the file I have selected
FileName for the name of the file I have chosen
FileName for the name of the file that is printing
FileName what is printing
FileName what my three dee printer is printing
FileName what file my three dee printer is three dee printing
FileName the file name
FileName to tell me the name of the file I have selected
FileName to tell me which file I am printing
FileName to tell my what file I my printer is currecntly printing
FileName what file is qued
FileName for the file name
FileName to tell me te file name
FileName what S T L my printer is printing
FileName which g code is my printer printing
FileName what is my printer printing currently
PrinterData printer data
PrinterData how is my printer
PrinterData how is my printer doing
PrinterData what is going on with my printer
PrinterData how well is my printer doing
PrinterData status
PrinterData operation
PrinterData is my printer printing
PrinterData is my printer paused
PrinterData is my printer connected
PrinterData printer
PrinterData if my printer is broken
PrinterData if my three dee printer is functioning
PrinterData if my printer is functining
PrinterData to tell me the status of my printer
PrinterData about my printer
PrinterData about my three dee printer
PrinterData if my printer is running smoothly
PrinterData to tell me how my printer is doing
PrinterData how is my printer
PrinterData how's my printer

Interaction Model

JSON
Paste into JSON box of the Amazon Skill service
{
    "interactionModel": {
        "languageModel": {
            "invocationName": "printer host",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "EstimatedTime",
                    "slots": [],
                    "samples": [
                        "how long is my print expected to take",
                        "how long should this print take",
                        "how long should it take my printer to print this model",
                        "how much time will it take for my printer to print this",
                        "what is the estimated print time of my print",
                        "what's the expected print time of my print",
                        "what amount of time is necessary for my print to fully complete",
                        "how much time will my print take",
                        "how much time will ti take my print to fully print",
                        "how long my print is expected to last",
                        "how much time my print is estimated to last",
                        "the amount of time my three dee print will take",
                        "how long it will take my three dee print to print from start to finish",
                        "estimated time",
                        "total estimated print time",
                        "expected print time",
                        "for the expected print time",
                        "for the ammount of time my print should take",
                        "for the time my print will take",
                        "for the time my three dee printer will take to complete"
                    ]
                },
                {
                    "name": "FileName",
                    "slots": [],
                    "samples": [
                        "file name",
                        "what file do I have selected",
                        "which file I have selected",
                        "which file I am printing",
                        "what file I am printing",
                        "for the name of the file I have selected",
                        "for the name of the file I have chosen",
                        "for the name of the file that is printing",
                        "what is printing",
                        "what my three dee printer is printing",
                        "what file my three dee printer is three dee printing",
                        "the file name",
                        "to tell me the name of the file I have selected",
                        "to tell me which file I am printing",
                        "to tell my what file I my printer is currecntly printing",
                        "what file is qued",
                        "for the file name",
                        "to tell me te file name",
                        "what S T L my printer is printing",
                        "which g code is my printer printing",
                        "what is my printer printing currently"
                    ]
                },
                {
                    "name": "Overview",
                    "slots": [],
                    "samples": [
                        "overview",
                        "give me an overview",
                        "to overview",
                        "please overview",
                        "to please give me an overview",
                        "to summarise my print",
                        "to get me an overview of my print",
                        "to give a summary of my print",
                        "to tell me how my print is doing",
                        "to tell me a summary of my print",
                        "how is my print",
                        "how is my print going",
                        "what is happening with my print",
                        "what is going on with my print",
                        "how is myy three dee print",
                        "how's my three dee print doing",
                        "to check on my print",
                        "to check on my three dee print",
                        "to give me a summary of my print",
                        "to give me a summary of my three dee print"
                    ]
                },
                {
                    "name": "PercentComplete",
                    "slots": [],
                    "samples": [
                        "what percent of my print is completed",
                        "percent completed",
                        "what percent of my print has been printed",
                        "to what extent has my print finished",
                        "what percent is my print done",
                        "how much of my print has been printed",
                        "what percent is my print completed",
                        "to tell me what ercent of my print is finished",
                        "to tell me what percentage my print is completed",
                        "what percent of my print is done",
                        "how far my print is in percentage",
                        "for the percentage my print has completed",
                        "for the percentage of which my print has printed",
                        "the percentage of my print which has been printed",
                        "the amount that my print is finished in percent",
                        "how much percent my printer is done",
                        "the percent completion of my print",
                        "the percent which my printer has completed",
                        "how much print is done in percent",
                        "the percentage of three dee print completion",
                        "the percentage my three dee print has printed",
                        "how many percents my printer has printed"
                    ]
                },
                {
                    "name": "PrinterData",
                    "slots": [],
                    "samples": [
                        "printer data",
                        "how is my printer",
                        "how is my printer doing",
                        "what is going on with my printer",
                        "how well is my printer doing",
                        "status",
                        "operation",
                        "is my printer printing",
                        "is my printer paused",
                        "is my printer connected",
                        "printer",
                        "if my printer is broken",
                        "if my three dee printer is functioning",
                        "if my printer is functining",
                        "to tell me the status of my printer",
                        "about my printer",
                        "about my three dee printer",
                        "if my printer is running smoothly",
                        "to tell me how my printer is doing",
                        "how's my printer"
                    ]
                },
                {
                    "name": "StartPOST",
                    "slots": [],
                    "samples": [
                        "start my print",
                        "start a print of the current selected file",
                        "commence printing",
                        "begin a print",
                        "begin my print",
                        "start print",
                        "start printing",
                        "start the print",
                        "start printing selected file",
                        "start printing the file i selected",
                        "start printing the currently selected file"
                    ]
                },
                {
                    "name": "TimeLeft",
                    "slots": [],
                    "samples": [
                        "how much time is left on my print",
                        "how much time is left on my three dee print",
                        "how much longer will it be until my print is done",
                        "how much longer will it be until my three dee print is done",
                        "how much more time is left on my print",
                        "how much more time is left on the print",
                        "how much more time is left on my three dee print",
                        "how much more time is left on the three dee print",
                        "how much longer does my printer have to go",
                        "how much longer does my printer have left",
                        "how much time until completion",
                        "when will my print be done",
                        "when will my print complete",
                        "when will my print be finished",
                        "when will the print be finished",
                        "time left",
                        "how much more time",
                        "time remaining",
                        "to tell me how much time is left",
                        "to tell my how much time is left opn my print"
                    ]
                },
                {
                    "name": "TimePrinted",
                    "slots": [],
                    "samples": [
                        "how long has my printer been printing for",
                        "how long has my three dee printer been printing for",
                        "how much time has my three dee printer been prining for",
                        "how many hours have been printed",
                        "time printed",
                        "how long has my print been going for",
                        "how long has my print been printing",
                        "how long has my three dee print been three dee printing",
                        "to tell me how long my printer has been printing",
                        "to tell me how much time my three dee print has been printing for",
                        "how long my printer has been running",
                        "how long my print has been three dee printing",
                        "for how much time my printer has printed",
                        "for how long my printer has been printing",
                        "for how long my printer has been printing for",
                        "for the time that I have been printing",
                        "for the time that my print has been printing for",
                        "for the amount of time that my printer has already priunted",
                        "the amount of time for which my three dee printer has been three dee printing",
                        "the time my printer has spent printing"
                    ]
                },
                {
                    "name": "CancelPOST",
                    "slots": [],
                    "samples": [
                        "end the current print",
                        "cancel the file currently printing",
                        "cancel the file i am printing",
                        "cancel the print that is printing",
                        "cancel the print that is being printed",
                        "cancel my current print",
                        "end my print",
                        "cancel",
                        "cancel my print"
                    ]
                },
                {
                    "name": "RestartPOST",
                    "slots": [],
                    "samples": [
                        "restart the file printing",
                        "restart my three dee print",
                        "restart the three dee print",
                        "restart the print that is currently printing",
                        "restart",
                        "restart the file my three dee printer is printing",
                        "restart my current three dee print",
                        "restart the current print",
                        "restart my print"
                    ]
                },
                {
                    "name": "PausePOST",
                    "slots": [],
                    "samples": [
                        "pause the three dee print",
                        "resume the three dee print",
                        "resume the file being printed",
                        "unpause the print my pinter is printing",
                        "pause the print",
                        "pause the current file",
                        "resume the current model",
                        "unpause my print",
                        "unpause",
                        "resume print",
                        "resume printing",
                        "resume",
                        "pause",
                        "pause my print"
                    ]
                },
                {
                    "name": "ConfirmPause",
                    "slots": [],
                    "samples": [
                        "confirm the resume",
                        "confirm resume",
                        "please pause",
                        "yes pause",
                        "confirm pause"
                    ]
                },
                {
                    "name": "ConfirmStart",
                    "slots": [],
                    "samples": [
                        "start confirm",
                        "yes start",
                        "confirm the start",
                        "confirm start"
                    ]
                },
                {
                    "name": "ConfirmRestart",
                    "slots": [],
                    "samples": [
                        "confirm the restart",
                        "restart confirm",
                        "restart confirmed",
                        "confirm restart"
                    ]
                },
                {
                    "name": "ConfirmCancel",
                    "slots": [],
                    "samples": [
                        "confirmed cancel",
                        "cancel confirmed",
                        "confirm the cancel",
                        "confirm cancel"
                    ]
                },
                {
                    "name": "CommandPOST",
                    "slots": [],
                    "samples": [
                        "have the printer do a command",
                        "send a custom command",
                        "excecute a custom command"
                    ]
                },
                {
                    "name": "ConfirmCommand",
                    "slots": [],
                    "samples": [
                        "command confirmed",
                        "confirm command"
                    ]
                }
            ],
            "types": []
        }
    }
}

Arduino Code

C/C++
Paste into a new Arduino Sketch
/*
Printer Host 1.0.0
This sketch will receive data from octoprint, write it to thingspeak channels, and display the data on a neopixel ring.
 */
#include <ThingSpeak.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <String.h>
#include <OctoPrintAPI.h>
#include <Adafruit_NeoPixel.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>

unsigned long api_mtbs = 60000; //mean time between api requests
unsigned long api_lasttime = 0;   //last time api request has been done
unsigned long api2_mtbs = 60000; //mean time between api requests
unsigned long api2_lasttime = 0;   //last time api request has been done
#define ringLength 16
#define PIN 12
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
uint32_t off = strip.Color(0,0,0);
WiFiClient client; 
//------------------------------------------
//              User Data
//------------------------------------------

const char* ssid     = "----------";                  //your SSID(name) of WIFI
const char* password = "----------";                  // password of Wifi

String OctoPrintAPIKey = "----------------";          //API key from OctoPrint
unsigned long printerID = ------;                     //channel id of thingspeak printer channel
const char * printerWriteApiKey = "----------------"; //write api key for thingspeak printer channel
unsigned long jobID = ------;                         //channel id of thingspeak job channel
const char * jobWriteApiKey = "----------------";     //write api key for thingspeak job channel
String POSTWriteApiKey = "----------------";          //write api key for thingspeak POST channel
String POSTReadApiKey = "----------------";           //read api key for thingspeak POST channel
String POSTid = "------";                             //channel id for thingspeak POST channel

IPAddress ip(--, -, -, ---);               // IP adress of Raspberry Pi. 11.1.1.111 = (11, 1, 1, 111)
const int octoprint_httpPort = 80;         //If you are connecting through a router this will work, but you need a random port forwarded to the OctoPrint server from your router. Enter that port here if you are external

//------------------------------------------
//           Color Setttings
//------------------------------------------
int background = 1;                                          //Would you like yout Printer Host to show a color even when not printing? 1 = yes 0 = no
int brightness = 150;                                        //How bright would you like your Neopixel Display? 1-255
uint32_t standby = strip.Color(0, 0, 255);                   //What color would you like to show as the background (disregard if you do not want a background)
uint32_t error = strip.Color(255, 0, 0);                     //What color would you like to indicate that the printer is disconnected or experiencing an error
uint32_t paused = strip.Color(255, 255, 0);                  //What color would you like to indicate that the printer is paused
uint32_t printing = strip.Color(0, 255, 0);                  //What color would you like to indicate that the printer is printing
//All Colors Are In RGB Format
//------------------------------------------
//------------------------------------------
String postStart;
String postCancel;
String postRestart;
String postPause;
bool debug = true;
String TSPostString;
int bedTemp;
int toolTemp;
String operational;    
String status; 
String fileName;
String percentComplete;
int percent;
int timePrinted;
int timePrintedRemaining;
String timePrintedHours;
String timePrintedMinutes;
int timeLeft;
int timeLeftRemaining;
String timeLeftHours;
String timeLeftMinutes;
int estimatedTime;
int estimatedTimeRemainder;
String estimatedTimeHours;
String estimatedTimeMinutes;
const char* ESP_HOST_NAME = "esp-" + ESP.getFlashChipId();
const char* host = "api.thingspeak.com";
//WiFiClient client; 
OctoprintApi api(client, ip, octoprint_httpPort, OctoPrintAPIKey);

void wifiConnect(){
  WiFi.begin(ssid, password);
  Serial.print("ssid");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected!");
  Serial.println(WiFi.localIP());
  Serial.println();
}

void setup() {
  
  Serial.begin(115200);
  delay(10);
  
  strip.begin();
  strip.show(); // Initialize all pixels to 'off' 
  strip.setBrightness(brightness);
  
  // start by connecting to WiFi 
  
  wifiConnect();
  ThingSpeak.begin(client);

    //Reset POST commands
    client.print(String("GET ")  + "/update?api_key="+POSTWriteApiKey+"&field1=0&field2=0&field3=0&field4=0 HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" + 
                "Connection: close\r\n\r\n");
}
void loop() {

  delay(100);

 //-----------------------------------------------------------------------------
 //                  Fetch data from Octoprint
 //-----------------------------------------------------------------------------


  if (millis() - api_lasttime > api_mtbs || api_lasttime==0) { //only do this after a certain period of time has passed
  
    if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status     
      if(api.getOctoprintVersion()){
        Serial.println("---------Version---------");
        Serial.print("Octoprint API: ");
        Serial.println(api.octoprintVer.octoprintApi);
        Serial.print("Octoprint Server: ");
        Serial.println(api.octoprintVer.octoprintServer);
        Serial.println("------------------------");
      }
      Serial.println();
      if(api.getPrinterStatistics()){
        Serial.println("---------Stats---------");
        Serial.print("Printer Current State: ");
        Serial.println(api.printerStats.printerState);
        Serial.print("Printer State - closedOrError:  ");
        Serial.println(api.printerStats.printerStateclosedOrError);
        Serial.print("Printer State - error:  ");
        Serial.println(api.printerStats.printerStateerror);
        Serial.print("Printer State - operational:  ");
        Serial.println(api.printerStats.printerStateoperational);
        Serial.print("Printer State - paused:  ");
        Serial.println(api.printerStats.printerStatepaused);
        Serial.print("Printer State - printing:  ");
        Serial.println(api.printerStats.printerStatePrinting);
        Serial.print("Printer State - ready:  ");
        Serial.println(api.printerStats.printerStateready);
        Serial.print("Printer State - sdReady:  ");
        Serial.println(api.printerStats.printerStatesdReady);
        Serial.println();
        Serial.println("------Termperatures-----");
        Serial.print("Printer Temp - Tool (°C):  ");
        Serial.println(api.printerStats.printerTool0TempActual);
        Serial.print("Printer State - Bed (°C):  ");
        Serial.println(api.printerStats.printerBedTempActual);
        Serial.println("------------------------");           
      }
      Serial.println();
      if(api.getPrintJob()){  //Get the print job API endpoint
        Serial.println("---------------------------");
        Serial.print("Printer current state string:\t");
        Serial.println(api.printJob.printerState);

        Serial.println();
        Serial.println("----------Job (File information)--------");
        Serial.print("jobFileDate (Epoch) long:\t");
        Serial.println(api.printJob.jobFileDate);
        Serial.print("jobFileName String:\t\t");
        Serial.println(api.printJob.jobFileName);
        Serial.print("jobFileOrigin String:\t\t");
        Serial.println(api.printJob.jobFileOrigin);
        Serial.print("jobFileSize (bytes) long:\t");
        Serial.println(api.printJob.jobFileSize);
        Serial.print("estimatedPrintTime (sec) long:\t");
        Serial.println(api.printJob.estimatedPrintTime);
        Serial.println("----------------------------------------");  
        Serial.println();
        Serial.println("-------Job (Progress information)-------");
        Serial.print("progressCompletion (%) float:\t\t");
        Serial.println(api.printJob.progressCompletion);
        Serial.print("progressFilepos (bytes) long:\t\t");
        Serial.println(api.printJob.progressFilepos);
        Serial.print("progressPrintTime (sec) long:\t\t");
        Serial.println(api.printJob.progressPrintTime);
        Serial.print("progressPrintTimeLeft (sec) long:\t");
        Serial.println(api.printJob.progressPrintTimeLeft);
        Serial.println("----------------------------------------");
        Serial.println();  
      }
      //Map Values to Variables
      operational = api.printerStats.printerStateoperational;
        
        
      if(api.printerStats.printerStatePrinting == 1){
        status = "1"; //if printing, set status to printing
      }else if(api.printerStats.printerStatepaused == 1){
        status = "2";
      }else if(api.printerStats.printerStateready == 1){
        status = "3";
      }else{
        status = "4";
      }
      //map all received data to variables and convert times to hh:mm format
      toolTemp = (api.printerStats.printerTool0TempActual);
      bedTemp = (api.printerStats.printerBedTempActual);
      fileName = api.printJob.jobFileName;
      estimatedTime = api.printJob.estimatedPrintTime;
      percentComplete = api.printJob.progressCompletion;
      percent = percentComplete.toFloat();
      timePrinted = api.printJob.progressPrintTime;
      timeLeft = api.printJob.progressPrintTimeLeft;
      timePrintedHours =  timePrinted / 3600;
      timePrintedRemaining = timePrinted % 3600;
      timePrintedMinutes = timePrintedRemaining /60;
      timeLeftHours =  timeLeft / 3600;
      timeLeftRemaining = timeLeft % 3600;
      timeLeftMinutes = timeLeftRemaining /60;
      estimatedTimeHours =  estimatedTime / 3600;
      estimatedTimeRemainder = estimatedTime % 3600;
      estimatedTimeMinutes = estimatedTimeRemainder /60;
    }
    api_lasttime = millis();
  }


 //-----------------------------------------------------------------------------
 //                  Update thingspeak with new data from octoprint
 //-----------------------------------------------------------------------------


  //connect to thingspeak
  if (millis() - api2_lasttime > api2_mtbs || api2_lasttime==0) {
    // Serial.print("connecting to ");
    //Serial.println(host);
    
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
      return;
    }


    //check for POST commands
    //code adapted from zoomkat arduino forum post: http://forum.arduino.cc/index.php?topic=44646.0
    client.print(String("GET ")  + "/channels/"+POSTid+"/feeds/last.json?api_key="+POSTReadApiKey+"&results=1 HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" + 
                "Connection: close\r\n\r\n");                                                         //updates values in printer thingspeak channel   

                
     while(client.connected() && !client.available()) delay(1); //waits for data
     while (client.connected() || client.available()) { //connected or data available
      char c = client.read(); //gets byte from ethernet buffer
      TSPostString += c; //places captured byte in TSPostString
     }
    TSPostString.remove(0,TSPostString.indexOf("{")); //isolate the json data
    TSPostString.remove(TSPostString.indexOf("}")+1); //isolate the json data
    Serial.println(TSPostString);
    String fixedString = TSPostString;
    TSPostString=""; //clear TSPostString variable
    
    //parsing
    //code adapted from
    const size_t bufferSize = JSON_OBJECT_SIZE(6);
    DynamicJsonBuffer jsonBuffer(bufferSize);
    char b[104];
    TSPostString.toCharArray(b,104);
    JsonObject& root = jsonBuffer.parseObject(fixedString);
    //json parameters
    const char* field1 = root["field1"]; // "1"
    const char* field2 = root["field2"]; // "0"
    const char* field3 = root["field3"]; // "0"
    const char* field4 = root["field4"]; // "0"
    Serial.println("debug");
    Serial.println(field1); 
    Serial.println(field2); 
    Serial.println(field3); 
    Serial.println(field4); 
    postStart = String(field1);
    postCancel = String(field2);
    postRestart = String(field3);
    postPause = String(field4);
    if(postStart == "1"){
      api.octoPrintJobStart();
      Serial.print("Print started");
    }
    if(postCancel == "1"){
      api.octoPrintJobCancel();
      Serial.print("Print cancelled");
    }
    if(postRestart == "1"){
      api.octoPrintJobRestart();
      Serial.print("Print restarted");
    }
    if(postPause == "1"){
      api.octoPrintJobPauseResume();
      Serial.print("Print resumed/paused");
    }
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //TO DO: Clean Up, Parse, Connect to OctoPrint commands.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                
    //update data
    
    //updates values in printer thingspeak channel
    ThingSpeak.setField(1, operational);
    ThingSpeak.setField(2, status);
    ThingSpeak.setField(3, toolTemp);
    ThingSpeak.setField(4, bedTemp);
    ThingSpeak.writeFields(printerID, printerWriteApiKey);
    Serial.print("TS printer channel updated");

    //updates values in job thingspeak channel
    ThingSpeak.setField(1, fileName);
    ThingSpeak.setField(2, estimatedTimeHours);
    ThingSpeak.setField(3, estimatedTimeMinutes);
    ThingSpeak.setField(4, percentComplete);
    ThingSpeak.setField(5, timePrintedHours);
    ThingSpeak.setField(6, timePrintedMinutes);
    ThingSpeak.setField(7, timeLeftHours);
    ThingSpeak.setField(8, timeLeftMinutes);
    ThingSpeak.writeFields(jobID, jobWriteApiKey);
    
    delay(100);
    //Reset POST commands
    client.print(String("GET ")  + "/update?api_key="+POSTWriteApiKey+"&field1=0&field2=0&field3=0&field4=0 HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" + 
                "Connection: close\r\n\r\n");
  
    if (debug == true){
      //serial print data: for debugging
      Serial.println("Thingspeak Updated");
      
      Serial.println("operational = " + operational);   
      
      Serial.println("status = " + status);   
      
      Serial.println("tool temp = " + toolTemp);
     
      Serial.println("bed temp = " + bedTemp);
      
      Serial.println("file name = " + fileName);   
      
      Serial.println("estimated print time = " + estimatedTimeMinutes);   
      
      Serial.println("percent complete = " + percentComplete);   
      
      Serial.println("hours printed = " + timePrintedHours);   
     
      Serial.println("minutes printed = " + timePrintedMinutes);   
     
      Serial.println("Hours remaining = " + timeLeftHours); 
      
      Serial.println("mnutes remaining = " + timeLeftMinutes); 
    }
    api2_lasttime = millis();
  }

  //-----------------------------------------------------------------------------
  //                  Check for Post commands
  //-----------------------------------------------------------------------------


  //-----------------------------------------------------------------------------
  //                  Display data using neopixels
  //-----------------------------------------------------------------------------
  if (operational == "0"){
    for(int i = 0; i<= ringLength; i++){  //display error color if experiencing an error
      strip.setPixelColor(i, error);
    }
  }else{
    if(status == "1"){  
      drawRing(printing, percent);  //display printing color on number of pixels representing print completion percentage
    }else if(status == "2"){
      drawRing(paused, percent);  //display paused color on number of pixels representing print completion percentage
    }else{
      if(background = 1){
        for(int i = 0; i<= ringLength; i++){
          strip.setPixelColor(i, standby); //display background color if a backround is wanted
        }
      }else{
        for(int i = 0; i<= ringLength; i++){
          strip.setPixelColor(i, off);  //turn all pixels off if no background is wanted
        }
      }
    }
  }
  strip.show();//show the pixels in their written state
}

void drawRing(uint32_t color, float percent){
  int pixelPercent = 100/ringLength; // the percentage needed to fill one pixel
  int fullPixels = percent/(pixelPercent); //the number of pixels that should be lit up 
  int i = 0;
  while (i < fullPixels){ //color all pixels up to fullPixels
    strip.setPixelColor(i, color);
    i++;
  }
}

Lambda Index Code

JavaScript
Paste into the index.js document of the function code in Lambda.
'use strict';
var SPEECH_OUTPUT = 'Hello World!';
var AlexaSkill = require('./AlexaSkill');
var https = require('https');
//User Input////////////////////////////////////////
var APP_ID = '--------------------';          //The application id of the alexa skill 
var jobChannelId = ------;                    //ThingSpeak Job Channel ID
var jobSpeakKey = '----------------';         //ThingSpeak Job Channel Read Key
var jobWriteKey = '----------------';         //ThingSpeak Job Channel Write Key
var printerChannelId = ------;                //ThingSpeak Printer Channel ID
var printerSpeakKey = '----------------';     //ThingSpeak Printer Read Key
var printerWriteKey = '----------------';     //ThingSpeak Printer Write Key
////////////////////////////////////////////////////
var fileName,estimatedHours,estimatedMinutes,percentComplete,timePrintedHours,timePrintedMinutes,timeLeftHours,timeLeftMinutes;
var operational,status,operationalString,statusString,toolTemp,bedTemp;

// Create JobUrl to retrieve data about current print job in JSON format
var JobUrl = 'https://api.thingspeak.com/channels/' + jobChannelId + '/feed/last.json?api_key=' + jobSpeakKey;
var PrinterUrl = 'https://api.thingspeak.com/channels/'+ printerChannelId + '/feed/last.json?api_key=' + printerSpeakKey;

var PrinterHost = function () {
    AlexaSkill.call(this, APP_ID);
};
// Extend AlexaSkill
PrinterHost.prototype = Object.create(AlexaSkill.prototype);
PrinterHost.prototype.constructor = PrinterHost;
PrinterHost.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    //console.log("onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};
PrinterHost.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    //console.log("onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    handlePrinterHostRequest(response);
};
/**
 * Overridden to show that a subclass can override this function to teardown session state.
 */
PrinterHost.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    //console.log("onSessionEnded requestId: " + sessionEndedRequest.requestId + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};
PrinterHost.prototype.intentHandlers = {
  
    "Overview": function (intent, session, response) {
        var speechOutput = "Your print is " + percentComplete +
                " percent complete and has " + timeLeftHours + " hours and " +
                timeLeftMinutes + " minutes remaining on a " + estimatedHours +
                " hours and " + estimatedMinutes + " minute print of " + fileName;
                
        response.tell(speechOutput);
    },
    "TimeLeft": function (intent, session, response) {
        var speechOutput = "Your print has " + timeLeftHours +
        " hours and " + timeLeftMinutes + " minutes remaining";
        response.tell(speechOutput);
    },
    "TimePrinted": function (intent, session, response) {
        var speechOutput = "Your print has been printing for " +
                timePrintedHours + " hours and " + timePrintedMinutes + " minutes";
        response.tell(speechOutput);
    },
    "PercentComplete": function (intent, session, response) {
        var speechOutput = "Your print is " + percentComplete + 
        " percent complete";
        response.tell(speechOutput);
    },
    "EstimatedTime": function (intent, session, response) {
        var speechOutput = "Your print is estimated to last a total of " + 
                estimatedHours + " hours and " + estimatedMinutes + " minutes";
        response.tell(speechOutput);
    },
    "FileName": function (intent, session, response) {
        var speechOutput = "Your printer is printing " + fileName;
        response.tell(speechOutput);
    },
    "PrinterData": function (intent, session, response){
        
        var speechOutput = 'your printer is ' + operationalString + ' and is currently ' + statusString +
        '. The hotend is ' +toolTemp+ ' degrees celcius and the print bed is ' + bedTemp+ ' degrees ';
        response.tell(speechOutput);
    },
    "StartPOST": function (intent, session, response){
        var speechOutput = 'please say ,confirm start, to confirm';
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=1&field2=0&field3=0&field4=0";
        https.get(URL, function(res) {});
        response.ask(speechOutput);
    },
    "ConfirmStart": function(intent, session, response){
        var speechOutput = 'okay, I have started the print of '+ fileName ;
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=0&field3=0&field4=1";
        https.get(URL, function(res) {});
        response.tell(speechOutput);
    },
    "CancelPOST": function (intent, session, response){
        var speechOutput = 'please say, confirm cancel, to confirm';
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=1&field3=0&field4=0";
        https.get(URL, function(res) {});
        response.ask(speechOutput);
    },
    "ConfirmCancel": function(intent, session, response){
        var speechOutput = 'okay, I have canceled the print of '+ fileName;
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=1&field3=0&field4=0";
        https.get(URL, function(res) {});
        response.tell(speechOutput);
    },
    "RestartPOST": function(intent, session, response){
        var speechOutput = 'please say, confirm restart, to confirm';
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=0&field3=1&field4=0";
        https.get(URL, function(res) {});
        response.ask(speechOutput);
    },
    "ConfirmRestart": function(intent, session, response){
        var speechOutput = 'okay, I have restarted the print of '+ fileName ;
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=0&field3=0&field4=1";
        https.get(URL, function(res) {});
        response.tell(speechOutput);
    },
    "PausePOST": function(intent, session, response){
        var speechOutput = 'please say, confirm pause, or ,confirm resume, to confirm';
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=0&field3=0&field4=1";
        https.get(URL, function(res) {});
        response.ask(speechOutput);
    },
    "ConfirmPause": function(intent, session, response){
        var speechOutput = 'okay, I have paused or resumed the print of '+ fileName ;
        var URL = "https://api.thingspeak.com/update?api_key="+postWriteKey+"&field1=0&field2=0&field3=0&field4=1";
        https.get(URL, function(res) {});
        response.tell(speechOutput);
    },
    "AMAZON.HelpIntent": function (intent, session, response) {
        response.ask("Start by asking 'Alexa, ask printer host for an overview' to get an overview of your printer. You can also ask about specific attributes of your printer, or tell your printer to do something, What can I do for you?");
    },
    "AMAZON.StopIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    },
    "AMAZON.CancelIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    }
};
/* -------------------------------------------------------------
 * Get all thingspeak data and map to variables
 * -------------------------------------------------------------
 */
function handlePrinterHostRequest(response) {
    // Create speech output
    var speechOutput = "Hey! I am printerhost, your 3d printer monitoring system. I can monitor your 3d printer by updating you on information such as printer state, percent job completion, and estimated time left on a print.";
    var cardTitle = "Initial Request";
    response.tellWithCard(speechOutput, cardTitle, speechOutput);
}
// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    https.get(JobUrl, function(res) {
        // Get latest sensor data from home IoT SoC
        res.on('data', function(d) {
            fileName = JSON.parse(d).field1;
            estimatedHours = JSON.parse(d).field2;
            estimatedMinutes = JSON.parse(d).field3;
            percentComplete = JSON.parse(d).field4;
            timePrintedHours = JSON.parse(d).field5;
            timePrintedMinutes = JSON.parse(d).field6;
            timeLeftHours = JSON.parse(d).field7;
            timeLeftMinutes = JSON.parse(d).field8;
           
            fileName = fileName.replace('.gcode', ' ');
            fileName = fileName.replace('_', ' ')
           
            
            
            
            
            // Create an instance of the SpaceGeek skill.
            var PrinterHost_skill = new PrinterHost();
            PrinterHost_skill.execute(event, context);
        });
        res.on('end', function() {
        });
        res.on('error', function(e) {
            context.fail("Got error: " + e.message);
        });
    });
    https.get(PrinterUrl, function(res) {
        // Get latest sensor data from home IoT SoC
        res.on('data', function(d) {
            operational = JSON.parse(d).field1;
            status = JSON.parse(d).field2;
            toolTemp = JSON.parse(d).field3;
            bedTemp = JSON.parse(d).field4;
           
          
           
            if (operational == ("1")){
              operationalString = 'operational';
          }else{
             operationalString =  'not operational';
          }
          
          if (status == "1"){
              statusString = 'printing';
          }else if(status == "2"){
              statusString = 'paused';
          }else if(status == "3"){
              statusString = 'standing by'
          }else{
              statusString = 'disconnected or experiencing an error';
          }
            
            
            
            // Create an instance of the SpaceGeek skill.
            var PrinterHost_skill = new PrinterHost();
            PrinterHost_skill.execute(event, context);
        });
        res.on('end', function() {
        });
        res.on('error', function(e) {
            context.fail("Got error: " + e.message);
        });
    });
};

Alexa Skill Lambda Code

JavaScript
Paste into the Alexa Skill document in the function code of lambda
/**
    Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
    Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
        http://aws.amazon.com/apache2.0/
    or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

'use strict';

function AlexaSkill(appId) {
  this._appId = appId;
}

AlexaSkill.speechOutputType = {
  PLAIN_TEXT: 'PlainText',
  SSML: 'SSML'
};

AlexaSkill.prototype.requestHandlers = {
  LaunchRequest: function(event, context, response) {
    this.eventHandlers.onLaunch.call(this, event.request, event.session, response);
  },

  IntentRequest: function(event, context, response) {
    this.eventHandlers.onIntent.call(this, event.request, event.session, response);
  },

  SessionEndedRequest: function(event, context) {
    this.eventHandlers.onSessionEnded(event.request, event.session);
    context.succeed();
  }
};

/**
 * Override any of the eventHandlers as needed
 */
AlexaSkill.prototype.eventHandlers = {
  /**
   * Called when the session starts.
   * Subclasses could have overriden this function to open any necessary resources.
   */
  onSessionStarted: function(sessionStartedRequest, session) {},

  /**
   * Called when the user invokes the skill without specifying what they want.
   * The subclass must override this function and provide feedback to the user.
   */
  onLaunch: function(launchRequest, session, response) {
    throw 'onLaunch should be overriden by subclass';
  },

  /**
   * Called when the user specifies an intent.
   */
  onIntent: function(intentRequest, session, response) {
    var intent = intentRequest.intent,
      intentName = intentRequest.intent.name,
      intentHandler = this.intentHandlers[intentName];
    if (intentHandler) {
      console.log('dispatch intent = ' + intentName);
      intentHandler.call(this, intent, session, response);
    } else {
      throw 'Unsupported intent = ' + intentName;
    }
  },

  /**
   * Called when the user ends the session.
   * Subclasses could have overriden this function to close any open resources.
   */
  onSessionEnded: function(sessionEndedRequest, session) {}
};

/**
 * Subclasses should override the intentHandlers with the functions to handle specific intents.
 */
AlexaSkill.prototype.intentHandlers = {};

AlexaSkill.prototype.execute = function(event, context) {
  try {
    console.log('session applicationId: ' + event.session.application.applicationId);

    // Validate that this request originated from authorized source.
    if (this._appId && event.session.application.applicationId !== this._appId) {
      console.log('The applicationIds don\'t match : ' + event.session.application.applicationId + ' and '
        + this._appId);
      throw 'Invalid applicationId';
    }

    if (!event.session.attributes) {
      event.session.attributes = {};
    }

    if (event.session.new) {
      this.eventHandlers.onSessionStarted(event.request, event.session);
    }

    // Route the request to the proper handler which may have been overriden.
    var requestHandler = this.requestHandlers[event.request.type];
    requestHandler.call(this, event, context, new Response(context, event.session));
  } catch (e) {
    console.log('Unexpected exception ' + e);
    context.fail(e);
  }
};
var Response = function(context, session) {
  this._context = context;
  this._session = session;
};

function createSpeechObject(optionsParam) {
  if (optionsParam && optionsParam.type === 'SSML') {
    return {
      type: optionsParam.type,
      ssml: optionsParam.speech
    };
  } else {
    return {
      type: optionsParam.type || 'PlainText',
      text: optionsParam.speech || optionsParam
    };
  }
}

Response.prototype = (function() {
  var buildSpeechletResponse = function(options) {
    var alexaResponse = {
      outputSpeech: createSpeechObject(options.output),
      shouldEndSession: options.shouldEndSession
    };
    if (options.reprompt) {
      alexaResponse.reprompt = {
        outputSpeech: createSpeechObject(options.reprompt)
      };
    }
    if (options.cardTitle && options.cardContent) {
      alexaResponse.card = {
        type: 'Simple',
        title: options.cardTitle,
        content: options.cardContent
      };
    }
    var returnResult = {
      version: '1.0',
      response: alexaResponse
    };
    if (options.session && options.session.attributes) {
      returnResult.sessionAttributes = options.session.attributes;
    }
    return returnResult;
  };

  return {
    tell : function(speechOutput) {
      this._context.succeed(buildSpeechletResponse({
        session: this._session,
        output: speechOutput,
        shouldEndSession: true
      }));
    },
    tellWithCard: function(speechOutput, cardTitle, cardContent) {
      this._context.succeed(buildSpeechletResponse({
        session: this._session,
        output: speechOutput,
        cardTitle: cardTitle,
        cardContent: cardContent,
        shouldEndSession: true
      }));
    },
    ask: function(speechOutput, repromptSpeech) {
      this._context.succeed(buildSpeechletResponse({
        session: this._session,
        output: speechOutput,
        reprompt: repromptSpeech,
        shouldEndSession: false
      }));
    },
    askWithCard: function(speechOutput, repromptSpeech, cardTitle, cardContent) {
      this._context.succeed(buildSpeechletResponse({
        session: this._session,
        output: speechOutput,
        reprompt: repromptSpeech,
        cardTitle: cardTitle,
        cardContent: cardContent,
        shouldEndSession: false
      }));
    }
  };
})();

module.exports = AlexaSkill;

Thing Speak Configuration

Credits

Miles Nash

Miles Nash

7 projects • 28 followers
I'm a UC Berkeley EECS student with a passion for innovation and creating new things.

Comments