markwal / OctoPrint-PolarCloud

OctoPrint plugin that connects OctoPrint to the Polar3D cloud. You easily monitor your printer from outside your LAN without arcane setup of port forwarding, etc. Plus, take advantage of the rapidly evolving Polar Cloud capabilities and UI.
GNU Affero General Public License v3.0
15 stars 8 forks source link

Feature: Implement custom system commands #3

Closed howsTricks closed 7 years ago

howsTricks commented 7 years ago

I (like I assume alot of printers) use custom commands to turn on/off my printer. It's setup on a specific GPIO pin to trigger the power supply so I don't need to leave the machine running. Is there a way to get this implemented in PolarCloud so I don't need to leave my machine running?

This is the tutorial I followed: https://github.com/foosel/OctoPrint/wiki/Controlling-a-relay-board-from-your-RPi

Here's the API documentation on this http://docs.octoprint.org/en/master/api/system.html#list-all-registered-system-commands

dnewman-polar3d commented 7 years ago

If you were doing this with a gcode command such as M42, then I'd have a good answer for you. But it sounds like your not.

I'll wait for Mark to chime in. It should not be too hard for us to add to the cloud side an opaque management command for which you provide some sort of value, click SEND, and then Octoprint receives it and interprets that value to Do The Right Thing. By "management command", I mean a command which is there via the cloud's printer management page and thus not available to users you merely allow to queue & view prints. Or perhaps we could put it on the detail page and just not display it to non-owners/managers of the printer. (Me, I work on the backend, not the frontend -- the UI itself.)

markwal commented 7 years ago

OctoPrint has a pretty extensive model for allowing users and plugin authors to add functionality through various mechanisms. The one referenced here is via config.yaml which can add system commands to a menu. There are also config.yaml ways to add controls to the Control page that can have interesting behaviors and even custom javascript. There's no easy way to make that transparent in the cloud and also has security implications running in a multi-tenant cloud environment.

However, we could do the simplest case in the way you mention. Have a printer to cloud message that says please list these commands somewhere (dropdown button on the printer management page), but only to printer managers/owners. And when the user clicks one of them, send a message to the printer that says, "user clicked 'this' one of the commands you gave me".

howsTricks commented 7 years ago

Cool! Definitely very interested in this one!

dnewman-polar3d commented 7 years ago

Shouldn't be too hard. Probably won't be able to implement it until early July in the front end. I'll likely have it in the backend by tomorrow though. New command (printer -> cloud) to assert a list of strings. Printer server stores list in db. Backend web server provides list to frontend web SPA. It's a drop down list in web client. When one is selected an event makes it back to the printer (haven't thought of a good name yet). The event will have the printer's serial number (as always) and the specific choice.

I guess the list of strings from the printer to the cloud should be tuples: the string to present to the human reader, and the actual string to send back. That's largely icing but db space is CHEAP and might be easier that way for everyone.

Delay on seeing in the frontend would just be scheduling people's time. (Yeah, I primarily work on the backend, but I also schedule everyone's time.)

markwal commented 7 years ago

I agree. The tuple is a good idea. For names, how about: customCommandList and customCommand.

dnewman-polar3d commented 7 years ago

Works for me.... I guess it's an array of arrays

{
    serialNumber: 'whatever',
    commandList: [ ['display-name-1', 'whatever-1'], ['display-name-2', 'whatever-2'], ... ]
}

For the time being, server will barf on singletons and non-arrays. Maybe down the road we can be more permissive (i.e., 'naked-string' implies ['naked-string', 'naked-string'])

and then from the cloud to the printer

{
    serialNumber: 'whatever',
    command: 'whatever-1'
}
dnewman-polar3d commented 7 years ago

Implemented, document, and deployed on the development test server... backend at least. Not front end. I've tweaked it to

{
    "serialNumber": "printer-serial-number",          // string, required
    "customCommandList": [
        {
            "label": "menu-label-1",                  // string, required
            "command": "COMMAND-1",                   // string, required
            "helpText": "command-help-1",             // string, optional
            "confirmText": "confirmation-request-1",  // string, optional
        }, ...
    ]
}
  1. label may map to Octoprint's action?
  2. helpText may map to Octoprint's name?
  3. confirmText certainly maps to Octoprint's confirm.
  4. command is whatever you want to use to reference the actual command. I suppose you could even use the actual command. Can only be spoofed on the cloud side by someone with a valid JWT access token for an owner or manager of the printer. Presently, our JWT access tokens are only valid for 8 hours.