Need help accessing the API from outside OctoPrint


#1

What is the problem?
I am making a page that would allow me to monitor my printer. While I have the video stream working, I would like to add basic info such as print time, estimated time left, layers printed/total, temps of hotbed, tools, and pi... Basic things like that. I do not plan on using it to send any commands since I can (securely) remote in and control the prints. The page is running on the same device as OctoPrint.

The problem I am having is figuring out how to access the API. I cant find any documentation of how to actually connect to it. I have searched the docs and found the doc on push updates which I think is what I am looking for for automatic refreshing updates like in octoprint. It's just no where that I can see is how to actually connect and grab the data. I have also spent a couple of hours trying to google how to do it or see if there was an open source project that has the same effect.

So my question is: does anyone have a project like this where they don't mind me looking at their source and try to figure this out or be willing to guide me through the process? Even some reading material that would guide me in the right direction would help. I am proficient in HTML and CSS but only have a basic understanding of how other languages work like JS and PHP.

Additional information about your setup
OctoPrint 1.3.9 & OctoPi 0.15.1


#2

I have some code in this area.

Robo phone app (PhoneGap via JavaScript)
octo-client NodeJS module
octo-conky Conky script to gather printer logistics (uses octo-client as a dependency)
octo-pause Node service endpoint to pause the printer (uses octo-client as a dependency)


#3

You want the REST API documentation. Theoretically push updates are better but at a lower coding level just call the API every 10 or 60 seconds.


#4

I think you can't get around javascript.
I am actually coding something similar.

My next step is connecting my server to the frontend with socket io.
octo-client by @OutsourcedGuru works really great. i have modified it so i can set and overwrite the configuration for each printer in loops.
This was for me one reason to implement it with a client server model.

With socket io i also can securely stream the webcam streams/pictures with authentication to a specific browser.
So you expose the server to the internet and doesn't expose octoprint and the webcam streams to the web.
So no data will be sent if you have not the password.


#5

Yeah, I am just having a really hard time trying to hack this together. I have worked on it for 4 hours today and am getting very frustrated because the thing I have managed to accomplish is to figure out how to visibly look at the json through the url in the browser looking through OutsourcedGuru's code.

This image is all I am trying to achieve: https://imgur.com/a/RFAMtmB
Nothing fancy, just show information. Eventually have it refresh every so often. I don't need to send any commands to the server at all since if something went wrong, I have another method to connect to octoprint that keeps it within my network.

Thank you guys for the help so far. I have actually learned a couple of things going through the code but just have not been able to put 2 and 2 together. Taking a break for tonight before I become rabbit holed.


#6

I'm guessing that you meant to say "the thing I haven't managed..." to cause your frustration...?

Remember to install octo-client per the instructions. You'll need to dive into the './node_modules/octo-client/config.js' file and edit this directly with your printer's information.

Your code then should be as simple as this:

var OctoPrint = require('octo-client');

OctoPrint.printerState(function(response){
  console.log(response);
  console.log('Operational: ' + response.state.flags.operational);
});

#7

It was actually supposed to be "the only thing I have managed to accomplish" (which is still true).

I am trying a different approach with jquery and Knockout to try and pull the data from the JSON itself. So far, I have managed to pull the array from the server but have unable to map it to the HTML where I would like it to go. Here is a JS Fiddle of what I have so far. Just trying to take it one step at a time before I try and work on getting the rest of the API urls inserted. I have a feeling I am overlooking something simple but I have tried many different examples and scoured stack overflow to no avail. This is the closest I have gotten.

I don't have NPM on the server because I am running this off the same pi that octoprint is running on. I feel like I would have a very hard time getting everything mapped and working how I would like it to work. For me, the simpler, the better. Especially now because I feel like I am so close but so far and I am just about ready to live with just the video feed.


#8

You ought to be able to then say console.log(data.job.file.name), for example, and get the selected filename.


#9

After doing what I should have done in the first place and take my time and getting a few examples up and comparing them, I was finally able to achieve getting and displaying the info from the multiple api pages using Knockout (KO) and jQuery. JS Fiddle of the working script. The next step is to get live updating implemented and then to stylize everything to be pretty.

The steps that I took for the people who are interested:

I noticed that most of the scripts were using something to the tune of self.records = ko.observableArray([]); to just grab the data and put it in an automatic array that is readable by KO. After that, I noticed that the corresponding HTML always had a data-bind="foreach: (insertJsonTagHere)" loop in the HTML in which had to be surrounding the data that you were trying to display. That would have made me do something like <li class="list-group-item"><span data-bind="foreach: (insertContainerName)"><strong>Status:</strong> <span data-bind="text: (insertJsonTagHere)">unknown</span></span></li> for each list item. I thought that this was very unproductive.

I finally was able to dig around enough and find a couple of examples where I saw people using things that would bind a tag to be called directly without the need for a container. By using self.state = ko.observable();, it would simplify things and I could also use it multiple times on the same page if needed. So I tried it and it wouldn't show up... It wasn't until about 30 minutes later that I needed to give it something for the variable to point to within the JSON. Adding self.state(data.state); within the $.getJSON() fixed that and things showed up!

Now, to tackle multi-dimensional arrays... Doing the normal thing of self.state(data.state[1][0]); wasnt bringing anything back. After a bit more Googling, I was finally able to find an article that stated the the problem was simple. Instead of brackets, use a . and just keep typing names. So to get the actual temperature of the hotend, for example, all you need to do is self.toolTempActual(pData.temperature.tool0.actual);. Worked like a charm.

And this is the point I am at. I can now access all the data and work with it.
Things I would still like to do:
-Automatic updating of the data (my F5 key has been used so many times over the 5+ years I've had this keyboard)
-Make things pretty.

I will share my code when I am happy with it for anyone that would also like something like this. (Even though I am sure there are many iterations of the same thing already but I like to make my own things)


#10

In a case like this, I think I would try to look at the OctoPrint code itself in the area of anything that automatically updates in the same way. The expression here is called "going to school on it". I'd suggest going to school on the side panel widget which displays the job progress to find out if anything is necessary in the world of KO to make that happen.

Lately, I'm familiar with React programming and the idea that if a component's state changes then it will be auto-rendered again to display that new state. I would guess that KO might be similar.