Add OctoEverywhere webhook to Notify.Events automation
LAN-mode OctoEverywhere webhooks post fixed JSON that Notify.Events can't parse. This local-only webhook automation translates important events into titled Notify.Events alerts, passing the OctoEverywhere channel token per message (the notify_events platform ignores per-platform api_key). Requires notify_event_octoeverywhere_token in secrets.yaml on the host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9eee3374b2
commit
7831b35af2
@@ -0,0 +1,100 @@
|
||||
### OctoEverywhere -> Notify.Events ###
|
||||
# OctoEverywhere (LAN mode) POSTs fixed JSON to this webhook. Notify.Events can't
|
||||
# parse that JSON itself, so this automation turns it into a readable alert.
|
||||
#
|
||||
# Token: the notify_events platform ignores per-platform api_key and always uses
|
||||
# the global notify_events token (Cats). Passing `token` inside `data` overrides
|
||||
# it per message, same pattern as script.notify_events_alerts.
|
||||
# Requires `notify_event_octoeverywhere_token` in secrets.yaml (the Home Assistant
|
||||
# source token from the Notify.Events "OctoEverywhere" channel).
|
||||
#
|
||||
# Event types: https://docs.octoeverywhere.com/webhook-notifications/event-types/
|
||||
# Forwarded ("important only"): 1-5, 7-12, 16. Skipped: 6 Progress, 13, 14, 15.
|
||||
|
||||
- id: '1793812953197'
|
||||
alias: OctoEverywhere to Notify.Events
|
||||
description: Turns OctoEverywhere webhook JSON into readable Notify.Events alerts
|
||||
mode: queued
|
||||
max: 10
|
||||
triggers:
|
||||
- trigger: webhook
|
||||
webhook_id: octoeverywhere-7301a739d954078c5a5c5fb3
|
||||
allowed_methods:
|
||||
- POST
|
||||
local_only: true
|
||||
actions:
|
||||
# HA only fills trigger.json when the request's Content-Type contains "json".
|
||||
# Otherwise the body is dropped and p is empty, which the safety net catches.
|
||||
- variables:
|
||||
p: "{{ trigger.json | default({}, true) }}"
|
||||
ev: "{{ p.EventType | default(0) | int(0) }}"
|
||||
wanted: [1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 16]
|
||||
names:
|
||||
"1": Print started
|
||||
"2": Print complete
|
||||
"3": Print failed
|
||||
"4": Print paused
|
||||
"5": Print resumed
|
||||
"6": Print progress
|
||||
"7": Gadget possible failure
|
||||
"8": Gadget paused the print
|
||||
"9": Printer error
|
||||
"10": First layer complete
|
||||
"11": Filament change required
|
||||
"12": Needs your attention
|
||||
"13": OctoEverywhere daily notification limit reached
|
||||
"14": Third layer complete
|
||||
"15": Bed cool down complete
|
||||
"16": Test notification
|
||||
|
||||
# Safety net: body wasn't readable JSON, so say so instead of failing silently
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ not p }}"
|
||||
then:
|
||||
- action: notify.notify_events_alerts
|
||||
data:
|
||||
message: OctoEverywhere sent a webhook that Home Assistant could not read as JSON. Check this automation's trace.
|
||||
data:
|
||||
token: !secret notify_event_octoeverywhere_token
|
||||
title: OctoEverywhere webhook problem
|
||||
level: warning
|
||||
- stop: Body was not JSON
|
||||
|
||||
# Drop events we don't want
|
||||
- condition: template
|
||||
value_template: "{{ ev in wanted }}"
|
||||
|
||||
# Build the message
|
||||
- variables:
|
||||
printer: "{{ p.PrinterName | default('Printer', true) }}"
|
||||
event_name: "{{ names[ev | string] | default('Event ' ~ ev, true) }}"
|
||||
level: "{{ 'error' if ev in [3, 8, 9] else 'warning' if ev in [4, 7, 11, 12] else 'success' if ev == 2 else 'info' }}"
|
||||
priority: "{{ 'high' if ev in [3, 4, 7, 8, 9, 11, 12] else 'normal' }}"
|
||||
images: "{{ [{'url': p.SnapshotUrl, 'name': 'snapshot.jpg'}] if p.SnapshotUrl else [] }}"
|
||||
body: >-
|
||||
{%- set parts = [] -%}
|
||||
{%- if p.FileName %}{% set parts = parts + ['<b>File:</b> ' ~ p.FileName] %}{% endif -%}
|
||||
{%- if p.Progress is defined and ev not in [1, 2] %}{% set parts = parts + ['<b>Progress:</b> ' ~ p.Progress ~ '%'] %}{% endif -%}
|
||||
{%- if p.TimeRemainingSec is defined and (p.TimeRemainingSec | int(0)) > 0 and ev not in [2, 3] -%}
|
||||
{%- set s = p.TimeRemainingSec | int(0) -%}
|
||||
{%- set parts = parts + ['<b>Time left:</b> ' ~ (s // 3600) ~ 'h ' ~ ((s % 3600) // 60) ~ 'm'] -%}
|
||||
{%- endif -%}
|
||||
{%- if p.DurationSec is defined and ev in [2, 3] -%}
|
||||
{%- set d = p.DurationSec | int(0) -%}
|
||||
{%- set parts = parts + ['<b>Ran for:</b> ' ~ (d // 3600) ~ 'h ' ~ ((d % 3600) // 60) ~ 'm'] -%}
|
||||
{%- endif -%}
|
||||
{%- if p.Error %}{% set parts = parts + ['<b>Error:</b> ' ~ p.Error] %}{% endif -%}
|
||||
{%- if p.QuickViewUrl %}{% set parts = parts + ['<a href="' ~ p.QuickViewUrl ~ '">Open printer</a>'] %}{% endif -%}
|
||||
{{ parts | join('<br>') }}
|
||||
|
||||
# Send it. If a snapshot ever breaks delivery, remove the images line.
|
||||
- action: notify.notify_events_alerts
|
||||
data:
|
||||
message: "{{ body if body else event_name }}"
|
||||
data:
|
||||
token: !secret notify_event_octoeverywhere_token
|
||||
title: "{{ printer }}: {{ event_name }}"
|
||||
level: "{{ level }}"
|
||||
priority: "{{ priority }}"
|
||||
images: "{{ images }}"
|
||||
Reference in New Issue
Block a user