Receiving terminal commands via websocket [Solved]


#1

Hi,

Trying to make my silly project on getting GCODE messages outputted to my terminal window without GUI in place, so doing this from the thin python client and command line.

I managed to get the REST API working with some status messages included such as bed temps etc, just to prove that it works.

Next got a websocket connected and just wanted to confirm it doesn't seem to have an authentication at all? Right now it keeps things simple, but in the future at least 2-way communication I guess needs to have authentication, if this was not meant to be more for plugin injector or similar.

I'm having hard time finding though where to place hooks to get the terminal messages visible? API docs talk very little about this and I would be happy to contribute if needed.

Thanks again in advance for all the help. This community is awesome here.


#2

I'm probably misunderstanding some part here, but if you only want to get the terminal messages via websocket, you don't need any hooks server-side. That information is already in the websocket messages.

So once you have established the websocket connection, you need to check for event that have a "current" property on the payload. There you'll find a logs property which contains the terminal messages since the last websocket event, as far as I understand.

This is an adapted version of my own function that extracts some information from the websocket:

private handleMessage(event: MessageEvent) {
    if (event.data.startsWith("a")) {
      var payload = JSON.parse(event.data.slice(1));

      if (payload.length === 1 && payload[0].current) {
        const data = payload[0].current;

        // terminal messages would be here:
        const messages = data.logs;
        console.log(messages);
      }
    }
  }

#3

Thanks Fabian. I am using Python websockets and upon connect I get one message, but nothing further. Not sure if I should automatically be subscribed to all GCODE messages as well:

{"connected": {"display_version": "1.3.10", "apikey": "xxx", "branch": "HEAD -> master", "plugin_hash": "18a34d83bd46f2dd17b8d8d2e6cb27ee", "config_hash": "yyy", "version": "1.3.10", "safe_mode": false, "debug": false}}

The code itself if it has any help:

import websocket

try:
    import thread
except ImportError:
    import _thread as thread
import time

HOST = "ws://octopi.local/sockjs/websocket"

def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("Closing Socket...")

if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp(HOST,
        on_message = on_message,
        on_error = on_error,
        on_close = on_close)
    ws.run_forever()

#4

I suspect that the missing authentication is the reason you only get one message (see http://docs.octoprint.org/en/master/api/push.html). I'm experimenting with an Octoprint instance without any authentication right now, so I haven't looked at that part in detail yet.


#5

Thanks! I was under the (apparently false or obsolete) understanding that websocket needed no authentication :slight_smile: I'll check if that will help.


#6

Thanks, Fabian - that was it!

I added one more method to my code:

def on_open(ws):
    print("Socket Open...")
    ws.send("{\"auth\": \"myusername:mypassword\"}")

And the messages started pouring in. Cheers :slight_smile: