Octoprint setup, UI, scripts and automations

Hey guys,
After combining some ideas found in the community, i thought i should share my end result, in case it helps somebody.
Happy to provide any help (if i can :slight_smile:)

Here is my final ui:

Hardware:

  • Ender 3p
  • Rpi3b
  • D-link Smart plug W215
  • Xiaomi Temp/Humidity sensor (with its gateway)

Setup:
I have a 3way socket on my d-link plug, which powers the printer, a desk lamp and the pi through a 5v usb charger (could have gone with buck converter and power it through the ender’s PSU but i didnt bother)

Configuration:
(whole UI and Package file at the end)

Octoprint Component:

octoprint:
  host: !secret octoprint_host
  api_key: !secret octoprint_api_key
  bed: true
  number_of_tools: 2

Shutdown scripts:

script:
  3dprint_off:
    alias: ¨Turn off 3d printer after 10 minutes¨
    sequence:
    - delay:
        minutes: 10 #release
        # seconds: 10 #production
    - condition: state
      entity_id: sensor.octoprint_current_state
      state: 'Operational'
    - service: rest_command.shutdown_octoprint
    - service: notify.mobile_app_sm_g975f
      data:
        message: "Octopi is Down, Printer is next" 
    - delay:
        seconds: 30
    - service: switch.turn_off
      data:
        entity_id: switch.d_link_smart_plug

  octopi_off:
    alias: "Soft Shutdown Octopi"
    sequence:
    - delay:
        seconds: 30 #added to avoid accidental clics 
    - service: rest_command.shutdown_octoprint

#shutdown octopi RPI
rest_command:
  shutdown_octoprint:
    url: http://octopi.local/api/system/commands/core/shutdown #use numeric IP alternatively
    method: POST
    headers: 
      X-Api-Key: !secret octoprint_api_key

I added a 30sec delay to the octopi soft-off because, yes i managed to ruin a print by accidentally clicking it.
This delay also turns the ui from “execute” into a toggle and allows me to add a lock to it.


Custom sensors rewriting time to be readable as octoprint component reads them in seconds (stolen from these forums / dont remember the user to quote, sorry):

sensor: #fix time display
  - platform: template
    sensors:
      octoprint_time_elapsed_format:
        friendly_name: 'Printing Time Elapsed'
        value_template: >-
          {% set etime = states.sensor.octoprint_time_elapsed.state | int %}
          {% set seconds = etime % 60 %}
          {% set minutes = ((etime % 3600) / 60) | int %}
          {% set hours = ((etime % 86400) / 3600) | int %}
          {% set days = (etime / 86400) | int %}
          {%- if days > 0 -%}
            {%- if days == 1 -%}
              1 day
            {%- else -%}
              {{ days }} days
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if hours > 0 -%}
            {%- if hours == 1 -%}
              1 hour
            {%- else -%}
              {{ hours }} hours
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if minutes > 0 -%}
            {%- if minutes == 1 -%}
              1 minute
            {%- else -%}
              {{ minutes }} minutes
            {%- endif -%}
          {%- endif -%}
      octoprint_time_remaining_format:
        friendly_name: 'Printing Time Remaining'
        value_template: >-
          {% set rtime = states.sensor.octoprint_time_remaining.state | int %}
          {% set seconds = rtime % 60 %}
          {% set minutes = ((rtime % 3600) / 60) | int %}
          {% set hours = ((rtime % 86400) / 3600) | int %}
          {% set days = (rtime / 86400) | int %}
          {%- if days > 0 -%}
            {%- if days == 1 -%}
              1 day
            {%- else -%}
              {{ days }} days
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if hours > 0 -%}
            {%- if hours == 1 -%}
              1 hour
            {%- else -%}
              {{ hours }} hours
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if minutes > 0 -%}
            {%- if minutes == 1 -%}
              1 minute
            {%- else -%}
              {{ minutes }} minutes
            {%- endif -%}
          {%- endif -%}

Automations to handle print start / progress / end and printer idle, along with android actionable notifications for canceling shutdown:

automation: 
 #print start
  - alias: 3DP Send me a notification when the print starts
    trigger:
      platform: state
      entity_id: sensor.octoprint_current_state
      from: 'Operational'
      to: 'Printing'
    action:
     - service: notify.mobile_app_sm_g975f
       data:
        message: "Printing Started"

#print 50%
  - alias: 3DP Send me a notification when the print is above 50%
    trigger:
      platform: numeric_state
      entity_id: sensor.octoprint_job_percentage
      above: 50
    action:
     service: notify.mobile_app_sm_g975f
     data:
        message: "Print is at {{states.sensor.octoprint_job_percentage.state}}%" 

#print finish
  - alias: 3DP Send me a notification when the print is finished AND TURN OFF PRINTER
    trigger:
      platform: state
      entity_id: sensor.octoprint_current_state
      from: 'Printing'
      to: 'Operational'
    action:
    - service: notify.mobile_app_sm_g975f
      data:
        message: "Print finished, Shutting down in 10"
        data:
          actions:
          - action: kill_script_3dprint_off
            title: Cancel Shutdown
    - service: homeassistant.turn_on
      entity_id: script.3dprint_off

#print Idle
  - alias: 3DP Send me a notification when the printer is idle AND TURN OFF PRINTER
    trigger:
      platform: state
      entity_id: sensor.octoprint_current_state
      to: 'Operational'
      for: 01:20:00
    action:
    - service: notify.mobile_app_sm_g975f
      data:
        message: "Printer Idle, Shutting down in 10"
        data:
          actions:
          - action: kill_script_3dprint_off
            title: Cancel Shutdown
    - service: homeassistant.turn_on
      entity_id: script.3dprint_off

#handle actionable notification replies
  - alias: 3DP Action from Notify - Cancel 3DP shutdown
    id: kill_scrip_3dprint_off_after_actionable_notification
    trigger:
      platform: event
      event_type: mobile_app_notification_action
      event_data:
        action: kill_script_3dprint_off
    action:
    - service: script.turn_off
      entity_id: script.3dprint_off

#Cancel shutdown if the printer has changed status since last print finished
  - id: 'kill_script_if_im_playing'
    alias: Cancel printer shutdown if im playing
    trigger:
    - entity_id: sensor.octoprint_current_state
      from: Operational
      platform: state
    condition:
    - condition: state
      entity_id: script.3dprint_off
      state: 'on'
    action:
    - entity_id: script.3dprint_off
      service: script.turn_off


Lovelace UI:

  1. auto-entities card (HACS) that shows up only if there’s some error. (i actually use this on my main ui page to display alerts like doors open or devices low bat, it’s pretty useful)
  2. Main switches locked with toggle-lock-entity-row (HACS) to avoid banging my head on the desk after turning stuff off mid-print
  3. A link to open octoprint in a new tab
  4. Camera stream from octoprint
  5. Several info from the octoprint plug in - job percentage, time remaining etc.
  6. Printer sensors displayed nicely with mini-graph-card(HACS) with nice colors and stuff ^^
  7. Filament box, filled with silica to preserve filaments. Its sensors also displayed with mini-graph-card
  8. Power consumption data from the smart plug (which also reports temperature but it’s internal, so no practical data there, besides safety i guess?)

Here is my whole tab, copied from the raw config section:

  - badges: []
    cards:
      - card:
          title: Octoprint ERROR
          type: entities
        filter:
          include:
            - entity_id: binary_sensor.octopr*error*
              state: 'on'
        show_empty: false
        show_header_toggle: false
        type: 'custom:auto-entities'
      - entities:
          - entity: switch.d_link_smart_plug
            type: 'custom:toggle-lock-entity-row'
          - entity: script.octopi_off
            type: 'custom:toggle-lock-entity-row'
          - entity: script.3dprint_off
            name: Shutdown Octopi then Printer (10m)
            type: 'custom:toggle-lock-entity-row'
          - icon: 'mdi:printer-3d'
            name: OctoPrint
            type: weblink
            url: 'http://octopi.local'
        show_header_toggle: false
        type: entities
      - aspect_ratio: 50%
        camera_image: camera.octoprint
        entity: camera.octoprint
        image: 'http://octopi.local/webcam/?action=snapshot'
        show_name: false
        show_state: false
        type: picture-entity
      - entities:
          - entity: sensor.octoprint_job_percentage
          - entity: sensor.octoprint_time_remaining_format
          - entity: sensor.octoprint_time_elapsed_format
        title: Job
        type: entities
      - entities:
          - entity: sensor.octoprint_current_state
          - entity: binary_sensor.octoprint_printing
          - entity: binary_sensor.octoprint_printing_error
          - entity: sensor.d_link_plug_temperature
        title: Status
        type: entities
      - entities:
          - entity: sensor.d_link_plug_current_power_w
            name: Current Power
          - entity: sensor.d_link_plug_total_consumption
            name: Total Power
            color: gray
            y_axis: secondary
        hours_to_show: 24
        color_thresholds:
          - value: 50
            color: green
          - value: 100
            color: orange
          - value: 150
            color: red
        line_width: 3
        show:
          labels: true
          legend: false
          labels_secondary: true
        icon: 'mdi:printer-3d'
        name: Power Consumption
        type: 'custom:mini-graph-card'
      - entities:
          - entity: sensor.humidity_158d00046546d8
            name: Box Humidity
          - entity: sensor.temperature_158d00046546d8
            name: Box Temp
            color: gray
            y_axis: secondary
        hours_to_show: 24
        line_width: 3
        color_thresholds:
          - value: 18
            color: green
          - value: 22
            color: orange
          - value: 100
            color: red
        show:
          labels: true
          legend: false
          name_adaptive_color: false
          labels_secondary: true
        icon: 'mdi:water-percent'
        name: Filament Box Humidity / Temp
        type: 'custom:mini-graph-card'
      - entities:
          - entity: sensor.octoprint_actual_bed_temp
            name: Current Temp
            color: orange
          - entity: sensor.octoprint_target_bed_temp
            color: skyblue
            name: Target Temp
        hours_to_show: 24
        line_width: 3
        color_thresholds:
          - value: 35
            color: white
          - value: 40
            color: green
          - value: 49
            color: orange
          - value: 70
            color: red
        show:
          labels: hover
          legend: false
          name_adaptive_color: false
        icon: 'mdi:temperature-celsius'
        name: Bed Temp
        type: 'custom:mini-graph-card'
      - entities:
          - entity: sensor.octoprint_actual_tool0_temp
            name: Current Temp
            color: orange
          - entity: sensor.octoprint_target_tool0_temp
            color: darkred
            name: Target Temp
        hours_to_show: 24
        line_width: 3
        color_thresholds:
          - value: 35
            color: white
          - value: 179
            color: green
          - value: 220
            color: orange
          - value: 300
            color: red
        show:
          labels: hover
          legend: false
          name_adaptive_color: false
        icon: 'mdi:temperature-celsius'
        name: Hotend Temp
        type: 'custom:mini-graph-card'
    icon: 'mdi:printer-3d'
    path: 3dp
    title: 3DP

The whole file octoprint.yaml is in my packages folder:

octoprint:
  host: !secret octoprint_host
  api_key: !secret octoprint_api_key
  bed: true
  number_of_tools: 2


#shutdown octopi RPI
rest_command:
  shutdown_octoprint:
    url: http://octopi.local/api/system/commands/core/shutdown
    method: POST
    headers: 
      X-Api-Key: !secret octoprint_api_key

#notifications and commands regarding printer
automation:
  - alias: 3DP Send me a notification when the print starts
    trigger:
      platform: state
      entity_id: sensor.octoprint_current_state
      from: 'Operational'
      to: 'Printing'
    action:
     - service: notify.mobile_app_sm_g975f
       data:
        message: "Printing Started"
  - alias: 3DP Send me a notification when the print is above 50%
    trigger:
      platform: numeric_state
      entity_id: sensor.octoprint_job_percentage
      above: 50
    action:
     service: notify.mobile_app_sm_g975f
     data:
        message: "Print is at {{states.sensor.octoprint_job_percentage.state}}%" 
  - alias: 3DP Send me a notification when the print is finished AND TURN OFF PRINTER
    trigger:
      platform: state
      entity_id: sensor.octoprint_current_state
      from: 'Printing'
      to: 'Operational'
    action:
    - service: notify.mobile_app_sm_g975f
      data:
        message: "Print finished, Shutting down in 10"
        data:
          actions:
          - action: kill_script_3dprint_off
            title: Cancel Shutdown
    - service: homeassistant.turn_on
      entity_id: script.3dprint_off


  - alias: 3DP Send me a notification when the printer is idle AND TURN OFF PRINTER
    trigger:
      platform: state
      entity_id: sensor.octoprint_current_state
      to: 'Operational'
      for: 01:20:00
    action:
    - service: notify.mobile_app_sm_g975f
      data:
        message: "Printer Idle, Shutting down in 10"
        data:
          actions:
          - action: kill_script_3dprint_off
            title: Cancel Shutdown
    - service: homeassistant.turn_on
      entity_id: script.3dprint_off

  - alias: 3DP Action from Notify - Cancel 3DP shutdown
    id: kill_scrip_3dprint_off_after_actionable_notification
    trigger:
      platform: event
      event_type: mobile_app_notification_action
      event_data:
        action: kill_script_3dprint_off
    action:
    - service: script.turn_off
      entity_id: script.3dprint_off

  - id: 'kill_script_if_im_playing'
    alias: Cancel printer shutdown if im playing
    trigger:
    - entity_id: sensor.octoprint_current_state
      from: Operational
      platform: state
    condition:
    - condition: state
      entity_id: script.3dprint_off
      state: 'on'
    action:
    - entity_id: script.3dprint_off
      service: script.turn_off


script:
  3dprint_off:
    alias: ¨Turn off 3d printer after 10 minutes¨
    sequence:
    - delay:
        minutes: 10 #release
        # seconds: 10 #production
    - condition: state
      entity_id: sensor.octoprint_current_state
      state: 'Operational'
    - service: rest_command.shutdown_octoprint
    - service: notify.mobile_app_sm_g975f
      data:
        message: "Octopi is Down, Printer is next" 
    - delay:
        seconds: 30
    - service: switch.turn_off
      data:
        entity_id: switch.d_link_smart_plug

  octopi_off:
    alias: "Soft Shutdown Octopi"
    sequence:
    - delay:
        seconds: 30
    - service: rest_command.shutdown_octoprint


sensor: #fix time display
  - platform: template
    sensors:
      octoprint_time_elapsed_format:
        friendly_name: 'Printing Time Elapsed'
        value_template: >-
          {% set etime = states.sensor.octoprint_time_elapsed.state | int %}
          {% set seconds = etime % 60 %}
          {% set minutes = ((etime % 3600) / 60) | int %}
          {% set hours = ((etime % 86400) / 3600) | int %}
          {% set days = (etime / 86400) | int %}
          {%- if days > 0 -%}
            {%- if days == 1 -%}
              1 day
            {%- else -%}
              {{ days }} days
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if hours > 0 -%}
            {%- if hours == 1 -%}
              1 hour
            {%- else -%}
              {{ hours }} hours
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if minutes > 0 -%}
            {%- if minutes == 1 -%}
              1 minute
            {%- else -%}
              {{ minutes }} minutes
            {%- endif -%}
          {%- endif -%}
      octoprint_time_remaining_format:
        friendly_name: 'Printing Time Remaining'
        value_template: >-
          {% set rtime = states.sensor.octoprint_time_remaining.state | int %}
          {% set seconds = rtime % 60 %}
          {% set minutes = ((rtime % 3600) / 60) | int %}
          {% set hours = ((rtime % 86400) / 3600) | int %}
          {% set days = (rtime / 86400) | int %}
          {%- if days > 0 -%}
            {%- if days == 1 -%}
              1 day
            {%- else -%}
              {{ days }} days
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if hours > 0 -%}
            {%- if hours == 1 -%}
              1 hour
            {%- else -%}
              {{ hours }} hours
            {%- endif -%}
            {{ ', ' }}
          {%- endif -%}
          {%- if minutes > 0 -%}
            {%- if minutes == 1 -%}
              1 minute
            {%- else -%}
              {{ minutes }} minutes
            {%- endif -%}
          {%- endif -%}
37 Likes

Thanks for idea.

1 Like

That looks awesome!

I’m trying something somewhat similar (without the fancy UI for now :wink: )

I would like to be notified when the printer actually starts printing (when all initial heating is done), but am getting errors, and probably do have some troubles getting to understand the coding here:

- id: '1588942782353'
  alias: Notify 3D Print desired temps reached (Ender 3)
  description: ''
  trigger:
  - entity_id: sensor.creality_ender_3_current_state
    for: "00:05:00"
    from: Operational
    platform: state
    to: Printing
  condition:
  - condition: template
    value_template: "{{ (sensor.creality_ender_3_actual_tool0_temp) >= ( (sensor.creality_ender_3_target_tool0_temp) ) }}"
  - condition: template
    value_template: "{{ (sensor.creality_ender_3_actual_bed_temp) >= ( (sensor.creality_ender_3_target_bed_temp) ) }}"
  - condition: numeric_state
    entity_id: sensor.creality_ender_3_job_percentage
    state: <0.2
  action:
  - data:
      message: The Ender3 3D Printer has reached its desired temperatures and is starting the actual print!
    service: notify.mycroft

Im in no way expert :slight_smile: but try adding | int after every value in your logical tests.
(sensor.creality_ender_3_target_bed_temp) | int
Also i dont know if extra parentheses are required but add em anyway, you already got an extra set in the second part of your tests.
Remember you can check those tests instantly in the Templating tab, inside Developers tools

Thank you. This is excellent work. One stop guide for what every 3D printing user needs. :slight_smile:

1 Like

This is brilliant. Thank you for sharing. I’m new to Home Assistant and OctoPrint, and this was a fun way to learn more about both platforms.

1 Like

I am thinking of adding Octoprint to my 3D printer setup but one question for you @krash, in your HA page you have the video feed displayed as a card.
Is that a separate webcam (outside of Octoprint?) The reason I ask is that it would be nice if I could use the pi camera attached to a pi4 that will be running the opctoprint server but according to https://www.home-assistant.io/integrations/octoprint/ there are just binary sensors/sensors available, nothing about a camera.
Any ideas if that is possible?

Yes, it is possible.

The pi running octoprint broadcasts it’s Webcam as a stream.

You then add this stream as a Webcam to HA using the link that octoprint provides.

You can use either the pi camera or (in my case) an old laptop Webcam that I soldered onto a USB cable, plugged in to the pi. (if you go the USB way make sure the specific Webcam is supported by octoprint.

1 Like

Good to know :slight_smile:
I wonder if the pi camera can see anything in low light

That I don’t know, but I have a desk lamp in the same plug as the printer that always goes when the printer and the rpi turn on.

wonder if someone can tell me the mdi icon who is default with the time remaining and elapse sensor.
when i use the template sensor i get an"eye"
well dont know if i am clear :slight_smile:

found them :slight_smile:
clock-start and clock-end

2 Likes

Here is my setup to shutdown when extruder temperature has hit a certain point (vs. just timed):

- id: '1597548579610'
  alias: Turn Off 3D Printer After Complete
  trigger:
  - entity_id: binary_sensor.octoprint_printing
    from: 'on'
    platform: state
    to: 'off'
  condition: []
  action:
  - wait_template: '{{ states(''sensor.octoprint_actual_tool0_temp_c'')|int < 40 }}'
  - data: {}
    entity_id: switch.sonoff_a
    service: switch.turn_off
  - data: {}
    entity_id: switch.sonoff_b
    service: switch.turn_off
  mode: single
1 Like

Hi, Great Work.

I was just wondering, is there a way to wake up the raspberry pi running octoprint from within HASSIO??

Home assistant has a wake-on-lan switch that wakes up compatible devices by sending packets.

I don’t know if octoprint supports it tho.
You ll also have to use the Lan port, I don’t think WoL works with wifi.
Looks like rpis don’t support WoL at all. You ll have to go the smart outlet way.

1 Like

Hey Harry,

I would like to integrate the Xiaomi Temp/Humidity sensor (with its gateway) as well but cannot find the gateway V1 anymore, I read that the API key for V2 or 3 tot can be subtracted. Which gateway do you have?

Hey Andre,
I had some trouble trying to find a compatible gateway.
I bought a current one (1y ago?) and it didn’t work, so I gave it to a friend.
I was lucky and found two old China market pieces in a shop in my city (Athens, Greece) that actually worked.

I don’t remember the exact product code and I’m not home right now but I’m certain I’ve posted about it here.

I’ll look it up and let you know.

Edit:
Here’s my post on that issue.

DGNWG05LM was the EU version that didn’t work.
DGNWG02LM are the two CN versions that I still use.

By the way, all that was back in January. I don’t know what the current situation is :slight_smile:

That’s great I am looking forward to it (
Ζεστή στέγη)

Is there a Greek pun there? :smile:
I’m afraid I don’t get it :frowning:

As for our subject, I gave you the model codes above :slight_smile:

I know, I searched already at Ali but can’t find the V1 version anymore :pensive: bummer