Getting push notifications solely from a local web browser hooked up to a local OctoPrint instance

What is the problem?

I would like to know if it is possible to receive push notifications from a printer to a local browser (ex. 111.111.1. to my computer running a localhost site and specifically without having to build out a plugin. (Everything is living in the same Network).

As some background, I have been building an application for it for the last couple of months, everything is running off of only the OctoPrint REST API and I'm able to pretty much do anything other being able to get push notifications.

What did you already try to solve it?

I've looked at the documentation intensively, both for Plugin Development (but I'm trying hard not to jump into building out a plugin yet) and the REST API. The push updates section doesn't seem to be an actual API point as there isn't really anything that would concretely define so other than running a GET request to /api/login (which seems to only work for POST requests aka it doesn't respond to GET requests). When I do retrieve the data (using POST) I have no idea where to send that data with the auth field as it doesn't really say what to do or where to go. I've tried running SockJS-client on my end and connecting to it but my socket knowledge is limiting and I don't think that sockets work like that.

Any guidance would be of great help!

you use that information to create a websocket connection back to octoprint, and then you get all the same data that gets pushed to the OctoPrint interface, including those that plugins inject. This is similar to how OctoDash, OctoFarm, and OctoScreen all work now.

1 Like

For anyone curios, I looked through OctoDash and found that you need to connect your websocket to OctoPrint's Socket: ws://<your printer's address>/sockjs/websocket.

In order to connect to the socket you need a session ID and a username that you get AFTER logging in. The entire snippet that will get you hooked up looks like this:

import axios from "axios";
import { webSocket } from "rxjs/webSocket";
const res = await axios.post(
        "http://localhost:9000/api/login?passive=true&apikey=SOME_API_KEY_STORED_IN_YOUR_OCTOPRINT'S_SETTINGS"
      );
const auth = res.data.name + ":" + res.data.session;
const socket = webSocket("ws://localhost:9000/sockjs/websocket");
socket.next({ auth: auth });
socket.subscribe(
      (msg) => console.log("message received: ", msg),
      (err) => console.error(err),
      () => console.log("complete")
);

And localhost:9000 can be changed to wherever your OctoPrint's instance is located.

Does using rxjs/webSocket work better for you than the SockJS Client? The only possible downside I can think of is maybe it won't work on such ancient browsers - sockjs will fall back to a polling method if it can't use the socket, but I don't think that should be an issue for most modern projects.

For reference, this is my socket client implementation in a React app:

You can install the UI that it is powering as a plugin, but I wouldn't recommend it... This is my learning project so it won't work for most things!

2 Likes

I simply used rxjs instead because it's what was used inside of OctoDash. I personally don't care for ancient browsers but since SockJS accounts for it, it would probably be much better to use it.

I'm not familiar with sockets at all however, but I'd like to ask if you'd know if this can be done on a Node.js / backend environment?

If I were able to get updates from OctoPrint and send it to the backend, it would be an absolute life saver.

I haven't done it from nodejs personally, but I imagine one of these websocket clients should work on the backend too. It would connect the same way the browser does to OctoPrint.

A quick google found sockjs/sockjs-client-node: SockJS client for Node (github.com), which is deprecated with a note that says that the original sockjs-client now supports running in node as well, so I guess you should be able to use that.

sockjs/sockjs-client: WebSocket emulation - Javascript client (github.com)

1 Like