System Commands in Home Assistant

I have integrated „Printer on“ and „... off“ commands in my system command menu.
I‘d like to add those commands to home assistant.

Is there a way to control it outside of the ui of OctoPrint? Maybe a single link that points to a command?

Hello fellow Home Assistant user! :wave:

Everything in the UI is using the REST API. System commands are documented here. Should be possible to trigger those via a RESTful command in HA. Take note of how to do authorization though.

I'm not sure where to start and the trial and error method will most probably not be successful with this.

Let's start with this

rest_command:
  octo_light_on:
    url: http://octopi.local
    method: POST
    headers: 
      authorization: 'myapikey?'
    payload: '{ "action": "lighton" }'

Is this the way it should look?

The API key should go into a HTTP header, not the authorization field.

I would guess like this:
headers: X-Api-Key:'yourapikey'

For the record, I used this guide to set up the system commands:

https://www.thingiverse.com/thing:1428478

Haven't tested this, but I'd try:

rest_command:
  octo_light_on:
    url: http://octopi.local/api/system/commands/custom/lighton
    method: POST
    headers:
      - "X-Api-Key: abcdefgh..."
    content_type:  "application/json; charset=utf-8"

or maybe

rest_command:
  octo_light_on:
    url: http://octopi.local/api/system/commands/custom/lighton
    method: POST
    headers:
      X-Api-Key: abcdefgh...
    content_type:  "application/json; charset=utf-8"

(the docs and example disagree on whether headers are a map or a list)

The first one ist not accepted by the config check.

The second example is accepted but does not work. I tried several different commands

  • lighton (friendly name)
  • lon (action)
  • light_on (name of the file)

as I'm not sure which one I have to chose, would guess "action".

lon would be correct. Anything in octoprint.log or HA's log when you try to run the command? My money would be on the api key header not being properly formatted yet and the request hence not being allowed to proceed.

I get this error in HA:

Error handling message: {'type': 'call_service', 'domain': 'rest_command', 'service': 'octo_light_on_1', 'service_data': {}, 'id': 14}
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/aiohttp/connector.py", line 843, in _create_direct_connection
traces=traces), loop=self._loop)
File "/usr/local/lib/python3.6/site-packages/aiohttp/connector.py", line 730, in _resolve_host
self._resolver.resolve(host, port, family=self._family)
File "/usr/local/lib/python3.6/site-packages/aiohttp/resolver.py", line 30, in resolve
host, port, type=socket.SOCK_STREAM, family=family)
File "uvloop/loop.pyx", line 1459, in getaddrinfo
socket.gaierror: [Errno -2] Name does not resolve

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/homeassistant/components/rest_command.py", line 103, in async_service_handler
headers=headers
File "/usr/local/lib/python3.6/site-packages/aiohttp/client.py", line 370, in _request
timeout=timeout
File "/usr/local/lib/python3.6/site-packages/aiohttp/connector.py", line 445, in connect
proto = await self._create_connection(req, traces, timeout)
File "/usr/local/lib/python3.6/site-packages/aiohttp/connector.py", line 757, in _create_connection
req, traces, timeout)
File "/usr/local/lib/python3.6/site-packages/aiohttp/connector.py", line 847, in _create_direct_connection
raise ClientConnectorError(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host octopi.local:80 ssl:None [Name does not resolve]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/homeassistant/components/websocket_api/decorators.py", line 16, in _handle_async_response
await func(hass, connection, msg)
File "/usr/local/lib/python3.6/site-packages/homeassistant/components/websocket_api/commands.py", line 148, in handle_call_service
connection.context(msg))
File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 1121, in async_call
self._execute_service(handler, service_call))
File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 1143, in _execute_service
await handler.func(service_call)
File "/usr/local/lib/python3.6/site-packages/homeassistant/components/rest_command.py", line 116, in async_service_handler
_LOGGER.error("Client error %s.", request.url)
UnboundLocalError: local variable 'request' referenced before assignment

code looks like this now:

  octo_light_on:
    url: http://octopi.local/api/system/commands/custom/lon
    method: POST
    headers:
      X-Api-Key: !secret octoprint_key
    content_type:  "application/json; charset=utf-8"

Changed octopi.local to the ip address of octoprint and now it works

EDIT:
Thank you and I also like to add that the content_type line is not necessary. So all it needs is

  octo_light_on:
    url: http://OCTOPRINT_IP/api/system/commands/custom/lon
    method: POST
    headers:
      X-Api-Key: !secret octoprint_key

But it seems like there will be another issues now.

I think there is no response. So if I turn on the light in the octoprint ui, the switch in homeassistant will still show a turned off light. Is there an easy way to make this show the right state?

In the text above I switch between light and printer on. I have 4 commands that I'd like to control by ha. (printer on, printer off, light on, light off).

I took the liberty and fixed your formatting.

My first hunch was a RESTful switch but that requires the same endpoint for on and off command which we don't have here. A Commandline Switch with some curl magic should work though. Something along the lines of (untested) curl -X POST -H "X-Api-Key: abcdef..." http://1.2.3.4/api/system/commands/custom/lon for command_on and curl -X POST -H "X-Api-Key: abcdef..." http://1.2.3.4/api/system/commands/custom/loff maybe.

But someone with more experience with Home Assistant than me might be more qualified to comment here.

Thanks!

The is is that this switch won't be updated if I change the light within the octoprint ui. In this case the state of the pin has to be monitored and than reportet to get the state in ha. Don't know how to do that and they way it works now is okay for me.

So now I put those four restful commands in scripts to use them in the lovelace-ui. It's not perfect, but good enough. Looks like in the picture below.

This is the code for the Buttons if someone is interessted.

  - type: glance
    show_state: false
    #show_name: false
    entities:
      - entity: script.printer_on
        name: An
        icon: mdi:printer-3d
        tap_action:
          action: toggle
      - entity: script.printer_off
        name: Aus
        icon: mdi:printer-3d
        tap_action:
          action: toggle
      - entity: script.printer_light_on
        name: An
        icon: mdi:lightbulb-on-outline
        tap_action:
          action: toggle    
      - entity: script.printer_light_off  
        name: Aus
        icon: mdi:lightbulb-outline
        tap_action:
          action: toggle

1 Like