Сповіщення¶
Дев'ять каналів доставки, один редактор, одна конфігурація маршрутизації. Підпиши кожен провайдер на потрібні події, постав тихі години й щоденний digest на провайдер, кастомізуй шаблони на мову. І десятий адресат, який нікуди не йде з ферми: центр сповіщень за дзвоником у sidebar-і — він наповнюється для кожного, хто заходить, незалежно від того, чи налаштований бодай один провайдер.
Підтримувані провайдери¶
| Провайдер | Складність | Можливості |
|---|---|---|
| Telegram | Середньо | Через бота BamDude з actionable inline-кнопками (clear plate, mark maintenance done, pause/stop). Розсилається в кожен авторизований чат, який підписаний на подію. |
| Discord | Легко | URL webhook каналу, форматування embed, прикріплення картинок. |
| Email (SMTP) | Середньо | STARTTLS / SSL / plain. Per-provider to_email — різні юзери бачать різні тіла. |
| Pushover | Легко | Рівні пріоритету, прикріплення картинок до 2.5 МБ. |
| ntfy | Легко | Topic-based, опційний bearer-токен, прикріплення картинок. |
| Bark | Легко | Тільки iOS, без акаунта. Рівні переривання — Critical доставляє крізь Silent mode і Focus. Публічний релей або власний bark-server. |
| CallMeBot | Легко | Bridge до WhatsApp / Signal — телефон + API-ключ, URL-encoded повідомлення. |
| Signal CLI API | Середньо | Власний signal-cli-rest-api — номери отримувачів або одна група, прикріплення картинок. |
| Home Assistant | Легко | persistent_notification.create або будь-який notify.* сервіс. Глобальний URL/token Home Assistant з Settings (або HA_URL / HA_TOKEN env). |
| Webhook | Гнучко | Generic JSON або Slack-format POST, кастомні імена полів, base64 картинка, опційний bearer. |
Додавання провайдера¶
- Перейдіть до Settings > Notifications
- Натисніть Add Provider
- Виберіть тип провайдера та введіть конфігурацію
- Натисніть Send Test для перевірки
- Налаштуйте тригери подій
- Натисніть Add
Кожен провайдер підписується на події окремо, і форма пропонує їх усі, згрупованими так само, як у центрі сповіщень: друк, принтери, філамент, AMS, черга, склад, сенсори. Що ти бачиш увімкненим під час додавання — з тим провайдер і збережеться.
Налаштування на провайдер¶
ntfy¶
Topic-based, безкоштовно, без облікового запису. Найпростіший канал, щоб підняти.
| Поле | Значення |
|---|---|
| Server | https://ntfy.sh (default) або URL власної self-hosted інстанції |
| Topic | Унікальний рядок — будь-хто, хто його знає, може писати, тож роби невідгадуваним |
| Bearer token | Опційно; потрібно для self-hosted topic-ів за ACL |
Підпишись на телефоні через ntfy Android чи iOS. ntfy підтримує 5 рівнів priority, які BamDude мапить на подію:
| Priority | ntfy value | Типове використання |
|---|---|---|
| Min | 1 | Diagnostics-style ping-и — без звуку, без бейджа |
| Low | 2 | Інформаційне, не-термінове (напр. "first layer complete") |
| Default | 3 | Стандартне сповіщення |
| High | 4 | Audible / urgent (напр. "filament low") |
| Urgent | 5 | Будить пристрій, ігнорує Do-Not-Disturb (напр. "print failed") |
WhatsApp / Signal (CallMeBot)¶
Безкоштовний міст до WhatsApp / Signal — без власної бот-інфраструктури.
- Додай CallMeBot у контакти: +34 644 51 95 23
- Надішли
I allow callmebot to send me messagesчерез WhatsApp - CallMeBot відповість твоїм API-ключем
| Поле | Значення |
|---|---|
| Phone number | Твій номер у форматі E.164 (напр. +1234567890) |
| API key | Ключ, який повернув CallMeBot |
Discord¶
URL webhook каналу — найпростіший спосіб закинути rich embed-повідомлення з мініатюрами в Discord-сервер.
- У Discord відкрий settings цільового каналу → Integrations → Webhooks
- Натисни New Webhook, кастомізуй ім'я/аватар, Copy Webhook URL
- Встав URL у форму провайдера BamDude
BamDude постить як embed-и зі snapshot-картинкою inline, коли вона є.
Pushover¶
Per-user push-сервіс з нативними iOS/Android-додатками і on-device priority-ескалацією.
- Створи акаунт на pushover.net і встанови додаток
- Створи Application у дашборді
| Поле | Значення |
|---|---|
| User key | Зі сторінки твого акаунту Pushover |
| API token | З Application, який ти щойно створив |
Pushover priority мапиться на numeric levels -2…+2 на подію в BamDude — ідея та сама, що й у ntfy, але зі шкалою Pushover.
Priority 2 (Emergency) вимагає двох додаткових полів
Pushover обов'язково вимагає інтервал повтору й термін дії для Emergency-сповіщень: вони повторюються, доки їх не підтвердять, тож сервіс відхиляє будь-яке повідомлення з priority 2, де не вказано як часто і як довго. Виставте Priority у 2 — і з'являться два поля:
| Поле | Значення | За замовчуванням |
|---|---|---|
| Повтор екстреного сигналу (с) | Як часто Pushover повторює | 60 с (мін. 30 с) |
| Термін дії екстреного сигналу (с) | Коли припинити | 3600 с (макс. 10800 с) |
Надсилаються лише при priority 2 — на решті рівнів Pushover їх ігнорує. До 0.4.7b4 BamDude не надсилав їх узагалі, тож провайдер із Emergency-пріоритетом валив кожне сповіщення.
Bark (iOS)¶
Bark — безкоштовний iOS-застосунок для push, узагалі без акаунта: встанови, скопіюй device key, який він показує, встав сюди. Більше нічого не обов'язково.
| Поле | Значення |
|---|---|
| Device Key | Ключ, який Bark показує на першому екрані — обов'язковий |
| Server | https://api.day.app (типово) або власний bark-server |
| Group | Опційно — складе сповіщення BamDude в окрему групу в застосунку |
| Sound | Опційно — одна зі звукових назв зі списку Bark |
| Interruption Level | Default / Active / Time Sensitive / Critical |
Critical — саме те, заради чого Bark поруч із ntfy і Pushover
| Рівень | Що робить iOS |
|---|---|
| Critical | Доставляє крізь Silent mode і крізь Focus — друк, що став о 03:00, таки достукається |
| Time Sensitive | Пробиває заплановані зведення, не заходячи так далеко |
| Active | Звичайне сповіщення |
| Passive | Приходить без звуку — записане, але не оголошене |
Заведи print failed і filament runout на Critical-провайдер Bark, а решту лиши на Default-провайдері, замість будити себе кожною подією.
Самохостний bark-server підпадає під ті самі правила адрес, що й самохостний ntfy: у власній мережі — можна, усе, що не є справжнім HTTP-сервісом, — відхиляється. Якщо він за Cloudflare-челенджем, BamDude так і скаже, замість вивалити сторінку челенджа.
«OK», який не OK
bark-server подекуди повідомляє про помилку всередині тіла з HTTP 200. BamDude читає тіло, а не довіряє статусу, — тож хибний device key у Send Test буде помилкою, а не «надіслано», яке нікуди не дійшло.
SMTP / Gmail¶
Звичайний SMTP — працює з будь-яким провайдером, що дає username + password auth.
| Поле | Приклад |
|---|---|
| SMTP host | smtp.gmail.com |
| Port | 587 (STARTTLS) або 465 (SSL) |
| Security | STARTTLS / SSL / plain |
| Username | Повна email-адреса |
| Password | App password (не пароль акаунту — Gmail відхилить останній) |
| From address | Адреса відправника, яку бачать отримувачі |
| To address | Per-provider; дозволяє різним членам команди отримувати різні тіла |
Для Gmail: увімкни 2FA, потім згенеруй App Password і використай його тут.
Home Assistant¶
Zero-config, коли HA вже підключений у Settings → Network → Home Assistant (або через HA_URL / HA_TOKEN env vars). Якщо лишити поля порожніми, події стають викликами persistent_notification.create в дашборді HA.
| Поле | Значення |
|---|---|
| Service | Опційно — будь-який сервіс HA, напр. notify.mobile_app_myphone. Приймається як notify.x, notify/x або api/services/notify/x. Порожнє = persistent_notification.create |
| Data (JSON) | Опційно — JSON-об'єкт, який іде у вкладене data HA, тобто саме туди, куди його кладе автоматизація |
Поле Data — це те, від чого залежить поведінка Android-push. Опції mobile-app інтеграції HA живуть там, а не в заголовку й тексті:
priority: high + ttl: 0 — саме те, від чого сповіщення приходить негайно, а не коли телефон наступного разу прокинеться; channel дає алертам принтерів власний звук, замість ховати їх серед усього іншого, що надсилає HA.
Чому JSON, а не рядки key=value
Щоб ttl: 0 лишався числом, якого чекає HA, і щоб вкладені опції взагалі були можливі. Поле перевіряється при збереженні і ще раз при надсиланні — некоректне відхиляється перед тобою, а не перетворюється на сповіщення, яке тихо ніколи не приходить.
Лиши порожнім — і нічого не зміниться: воно надсилається, лише коли заповнене, бо persistent_notification.create відхиляє зайві ключі.
Форвард HA-сповіщень в інші канали
Використовуй HA-автоматизації, щоб дзеркалити persistent-сповіщення на HA Companion app, Telegram, ntfy тощо — отримаєш єдиний audit log в HA плюс звичний мобільний push.
Signal CLI API¶
Повідомлення в Signal через власну інстанцію signal-cli-rest-api. Провайдер названо за тим, з чим він говорить: офіційного API в Signal немає, і BamDude не вдає, що це воно. Спершу зареєструй номер у signal-cli (README того проєкту веде за руку); далі BamDude шле з цього номера.
| Поле | Значення |
|---|---|
| Signal API URL | Базовий URL твого signal-cli-rest-api, напр. http://192.168.1.50:8080. Вставлений повний endpoint /v2/send із його документації не ламає нічого — BamDude зрізає його до бази. |
| Sender Number | Номер, зареєстрований у signal-cli, у форматі E.164 (+380501234567) |
| Recipient Type | Phone Numbers — один або кілька отримувачів, рядок за рядком, — або Group ID — одна група Signal. signal-cli-rest-api не вміє змішати обидва в одному запиті, тож провайдер — або те, або те; хочеш обидва — додай другий провайдер. |
| Group ID | ID групи, як його показує signal-cli; голий id отримає префікс group. сам |
| Authorization | Опційно — значення заголовка Authorization, якщо API стоїть за reverse proxy з автентифікацією (Bearer … або просто токен) |
Фото завершеного друку прикріплюється до повідомлення. URL підпадає під ті самі правила адрес, що й самохостний ntfy чи bark-server: у власній мережі — можна, усе, що не є справжнім HTTP-сервісом, — відхиляється.
BamDude у Docker, а signal-cli-rest-api ще немає? Штатний docker-compose.signal.yml піднімає його поруч із BamDude, і docker-install.sh це пропонує — див. Docker → Сайдкар для сповіщень Signal.
Generic Webhook¶
Для всього іншого — n8n, Node-RED, кастомні HTTP-ендпоінти, Slack-format інтеграції.
| Поле | Значення |
|---|---|
| URL | Твій ендпоінт (HTTPS рекомендовано) |
| Headers | Опційно — для Authorization: Bearer … тощо |
| Format | generic (структурований BamDude JSON) або slack (тільки {"text": "..."}) |
Дивись Webhook Payload Schema нижче для форми структурованого JSON.
Webhook Payload Schema¶
Generic-format webhooks шлють стандартизований JSON-конверт: title, message, timestamp, source, event (рядок типу події), плюс усі event-specific поля піднімаються на top-level ключі, тож automation-tools можуть branch-итися на event без парсингу message-тексту.
print_complete:
{
"title": "Print Complete",
"message": "Workshop X1C: benchy.3mf completed in 2h 15m",
"timestamp": "2026-04-02T14:30:00.123456",
"source": "BamDude",
"event": "print_complete",
"printer": "Workshop X1C",
"filename": "benchy.3mf",
"duration": "2h 15m",
"filament_grams": "15.2",
"filament_details": "AMS-A T1 PLA: 15.2g"
}
print_failed (і print_stopped) несуть додаткові поля progress + reason:
{
"title": "Print Failed",
"message": "Workshop X1C: benchy.3mf failed at 50%",
"timestamp": "2026-04-02T15:15:00.123456",
"source": "BamDude",
"event": "print_failed",
"printer": "Workshop X1C",
"filename": "benchy.3mf",
"duration": "0h 45m",
"filament_grams": "7.6",
"filament_details": "PLA: 7.6g",
"progress": "50",
"reason": "Filament runout"
}
printer_offline — мінімальний payload, тільки те, що релевантне:
{
"title": "Printer Offline",
"message": "Workshop X1C is offline",
"timestamp": "2026-04-02T14:30:00.123456",
"source": "BamDude",
"event": "printer_offline",
"printer": "Workshop X1C"
}
first_layer_complete — включає base64-encoded JPEG-snapshot у полі image:
{
"title": "First Layer Complete",
"message": "Workshop X1C: benchy.3mf — Layer 1/200 done",
"timestamp": "2026-04-02T14:30:00.123456",
"source": "BamDude",
"event": "first_layer_complete",
"printer": "Workshop X1C",
"filename": "benchy.3mf",
"total_layers": "200",
"image": "/9j/4AAQSkZJRg..."
}
Декодування картинки
Поле image — стандартний base64-encoded JPEG. Home Assistant: передай у notify.mobile_app_* як image data через template. Node-RED: Buffer.from(msg.payload.image, 'base64'). Поле присутнє лише, коли snapshot реально був захоплений — не всі події його містять.
Slack / Mattermost format compatibility
З format = slack шлеться тільки {"text": "..."} — структуровані поля події відкидаються. Юзай generic-формат для будь-якої automation, що читає структуровані дані; slack — лише для людино-читабельних channel-постів.
Тригери подій¶
Кожен провайдер підписується незалежно. Вимкнення події на одному провайдері не зупиняє її на інших.
Друк:
| Подія | Спрацьовує коли |
|---|---|
print_start |
Друк запустився на принтері |
first_layer_complete |
Завершився перший шар (швидко ловить first-layer фейли) |
print_progress |
На 25% / 50% / 75% прогресу. Поріг мінімальної тривалості глушить їх для друків, коротших за N хвилин — і значення належить кожному отримувачу: кожен чат Telegram має власне (біля чекбокса «Проміжний прогрес» у налаштуваннях чату), кожен інший провайдер — своє (на його картці, біля того ж тогла). Порожньо або 0 = слати завжди; спільного глобального значення немає. Тривалість оцінюється із власного remaining-time принтера на кожному milestone, а невідома оцінка шле, а не вгадує. |
print_paused |
Принтер перейшов RUNNING→PAUSE — у тілі нормалізована {reason} (двері відкриті / філамент скінчився / presence-check / G-code pause / AI defect / об'єкти на платі / paused by user / HMS-other) плюс {hms_code} для forensics. За замовчуванням ON для нових провайдерів + входить у дефолтний event-набір Telegram-чату. |
print_resumed |
Принтер перейшов PAUSE→RUNNING — у тілі {paused_for} (mm:ss) обчислений по delta між edge'ами. За замовчуванням ON для нових провайдерів; opt-in для Telegram-чатів. |
Стан паузи також візуалізується на сторінці Принтерів у реальному часі — на картці paused-принтера поряд зі статусом з'являється маленький <PauseChip> із класифікованою причиною і живим mm:ss-лічильником, плюс жовта попереджувальна піпка в кутку. Чіп зникає у мить resume; resume-нотифікація несе те саме значення {paused_for}, що і chip відраховував.
| print_complete | Друк завершився успішно |
| print_failed | HMS-помилка / hardware-фейл зупинили друк |
| print_stopped | Користувач зупинив друк |
| bed_cooled | Стіл охолов до порогу (сигнал готовності зняти деталь) |
AMS / філамент:
| Подія | Спрацьовує коли |
|---|---|
print_missing_spool_assignment |
Друк стартував без повного мапінгу spool→AMS |
filament_low |
Залишок котушки нижче low_stock_threshold (або власного порога котушки). Котушка з інвентарю перевіряється, коли лягає витрата друку, — раз на пробіг; неприв'язана котушка Bambu (лічильник принтера) і слот, прив'язаний до Spoolman, — на кожній зміні AMS, раз на котушку в слоті. |
ams_humidity_high / ams_temperature_high |
AMS перевищив свій поріг |
sensor_above_max / sensor_below_min |
Показ датчика вийшов за задані для нього межі |
sensor_back_in_range |
…і повернувся |
sensor_silent / sensor_speaking_again |
Датчик перестав звітувати — і почав знову |
Принтер:
| Подія | Спрацьовує коли |
|---|---|
printer_offline |
MQTT-розрив |
printer_error |
Спрацював HMS-код (BamDude додає переклад людською) |
ai_failure_detection |
AI-детекція збою (Obico) позначила ймовірний провал друку — opt-in, вимкнено за замовчуванням. Виділено з printer_error, тож можна отримувати AI-алерти без кожного HMS-коду. Має власний шаблон, власний per-provider тоглер і власний per-chat Telegram-пункт; тіло несе принтер, назву роботи, оцінку впевненості та дію, яку виконав BamDude (notify / pause / pause + power off). |
plate_not_empty |
Bed-occupancy gate зловив старт наступного друку (auto-pause) |
maintenance_due |
Інтервал обслуговування досягнуто |
Черга:
| Подія | Спрацьовує коли |
|---|---|
queue_job_added / queue_job_started / queue_job_waiting / queue_job_skipped / queue_job_failed |
Lifecycle черги. Тільки ті події, на які ти підписався. |
queue_completed |
Спорожніли черги всієї інсталяції — спрацьовує лише раз, коли кожен принтер idle і нічого не лишилось у черзі. |
printer_queue_completed |
Спорожніла власна черга окремого принтера — спрацьовує у мить, коли цей принтер завершив свою останню задачу, незалежно від того, що роблять інші принтери. |
Глобальне vs. per-printer завершення черги
На setup-і з одним принтером ці дві події еквівалентні. На багатопринтерній фермі вони різняться: queue_completed чекає, поки idle стане кожен принтер, тож довга задача на одному принтері придушує подію для всіх інших. printer_queue_completed спрацьовує per-printer у мить, коли власна черга принтера спорожніла — обери цю, якщо хочеш ping "ця машина вільна, став наступну плату" на кожен принтер. printer_queue_completed ON за замовчуванням для нових провайдерів; queue_completed — off за замовчуванням.
Користувач / система:
| Подія | Спрацьовує коли |
|---|---|
user_created, password_reset |
Account-management емейли (HTML + plain). |
user_print_start / user_print_complete / user_print_failed / user_print_stopped |
Per-user email коли користувач — власник друку. |
test |
Тест-надсилання з редактора провайдера. |
Інтерактивні сповіщення Telegram¶
При використанні Telegram як провайдера сповіщень BamDude надсилає інтерактивні сповіщення з вбудованими кнопками:
| Подія | Дії |
|---|---|
| Print Complete | Кнопка очищення пластини |
| Maintenance Due | Кнопка підтвердження виконання |
| Print Progress | Кнопки паузи / зупинки |
Докладніше у розділі Налаштування Telegram-бота.
Маршрутизація подій по чатах
Telegram-сповіщення не йдуть в один захардкоджений чат -- вони розсилаються в кожен авторизований чат, у якого telegram_chats.notification_events містить активну подію. Тож один чат може підписатися лише на "Print Complete" + "HMS Error", а інший -- забирати все. Підписки кожного чату налаштовуються в Settings > Notifications > Telegram Chats.
Локалізовані шаблони на користувача
Тіла сповіщень рендеряться з notification_templates_{en,uk}.json. Мова шаблону вибирається на отримувача -- Telegram бере settings.language користувача-власника чату, email бере мову користувача-отримувача тощо. Додавання нового ключа шаблону означає оновлення обох JSON-файлів en та uk (BamDude постачається лише з en + uk).
Пріоритет на подію (ntfy і Pushover)¶
І ntfy, і Pushover підтримують priority-рівні — default / high / urgent для ntfy, -2…+2 для Pushover. BamDude дає обрати priority на тип події на кожному провайдері, тож завершений друк не пушитиме на lock-screen, а провал друку — пушитиме:
| Тип події | Рекомендований ntfy-priority | Чому |
|---|---|---|
print_complete, bed_cooled |
default |
Інформаційне — прочитається коли зручно. |
print_failed, printer_error, plate_not_empty |
high чи urgent |
Потребує дії. |
filament_low, maintenance_due |
default |
Plan-ahead, не interrupt-now. |
ams_humidity_high |
high |
Стосується пластика, який ось-ось у роботу. |
Налаштовується в edit-формі провайдера: dropdown priority поряд з тоглером підписки на подію. Defaults мапять кожну подію на default-priority — opt-in escalation тільки де треба. Той самий контроль у Pushover приймає numeric levels.
Це незалежне від нижче daily-digest / quiet-hours pipeline'у — quiet-hour-suppressed подія не відсилається жодним priority; активна подія все одно поважає вибраний per-event priority.
Тихі години і щоденний digest¶
Форма конфіга залежить від типу провайдера — Telegram-бот окремий випадок.
Не-telegram провайдери (email / ntfy / pushover / discord / webhook / homeassistant / callmebot / signal) тримають обидва налаштування на самому provider-row:
| Налаштування | Де | Ефект |
|---|---|---|
quiet_hours_enabled + quiet_hours_start / quiet_hours_end |
Конфіг провайдера | Події всередині вікна викидаються (не чекають — quiet hours це "мовчати", не "відкласти"). |
daily_digest_enabled + daily_digest_time |
Конфіг провайдера | Події протягом дня зберігаються в notification_digest_queue; коли годинник переходить daily_digest_time, BamDude вислає чергу одним digest-повідомленням. |
Telegram (m045) структурований інакше: бот/provider-row тримає тільки розклад (daily_digest_enabled + daily_digest_time), а per-event opt-in, тихий час і per-chat digest opt-in живуть на кожному рядку TelegramChat. Один чат може бути в quiet-годинах, а інший залишатися гучним — обидва живляться одним ботом. Деталі per-chat-полів див. Налаштування Telegram-бота.
Редактор шаблонів¶
Кожна подія має дефолтний шаблон у data/notification_templates_{en,uk}.json. Вкладка Templates під Settings → Notifications дозволяє перевизначити будь-який — тітул + тіло — з MarkdownV2 toolbar і live-прев'ю.
Вкладка Templates групує дефолтні шаблони за призначенням, щоб одним поглядом було видно, який dispatch-шлях кожен з них живить:
| Група | К-ть | Для чого |
|---|---|---|
| Print events | 9 | print_start/complete/failed/stopped/progress, plate_not_empty, bed_cooled, first_layer_complete, print_missing_spool_assignment |
| Printer status | 4 | printer_offline, printer_error, filament_low, maintenance_due |
| AMS environmental | 2 | ams_humidity_high, ams_temperature_high (також reuse-яться у runtime для AMS-HT-подій) |
| Print queue | 7 | queue_job_added/started/waiting/skipped/failed, queue_completed, printer_queue_completed |
| Job owner emails | 4 | user_print_start/complete/failed/stopped — SMTP-only, шлеться власнику задачі друку |
| System emails | 2 | user_created (welcome), password_reset |
| Test | 1 | test — для кнопок "Send test" |
Кожна картка несе маленький UPPERCASE-бейдж каналу:
- Зелений
ALL— фан-аут до всіх типів провайдерів (TG / email / ntfy / pushover / discord / webhook / homeassistant / callmebot / signal). Записи у перших 4 групах. - Синій
EMAIL— SMTP-only флоу. 4×user_print_*job-owner emails плюсuser_created/password_reset. - Амбер
TEST— внутрішній test-button helper.
Маппінг — це метадані про те, який dispatch-шлях кожен шаблон живить; не зберігаються на рядку, рендеряться зі статичної таблиці у frontend-і.
Підстановка змінних — простий {plate_holder} синтаксис ({printer_name}, {filament_grams}, {eta} і т.д.); схема залочена на подію, тож редактор сам попереджає, коли placeholder не резолвиться.
Шаблон вибирається за мовою отримувача: Telegram-чат, прив'язаний до оператора з settings.language=uk, отримає українське тіло; email до іншого юзера з settings.language=en — англійське. Нові ключі додавайте в обидва JSON-файли — BamDude постачається лише з en + uk.
Приклад Daily Digest¶
Коли провайдер має daily_digest_enabled + daily_digest_time встановлене, кожна подія, яка спрацювала за день, кладеться в чергу і об'єднується в одне summary-повідомлення на digest-час:
Daily Print Summary (Apr 14)
3 prints completed
1 print failed
Total time: 8h 45m
Filament used: 245g
Details:
- Benchy (2h 15m) - completed
- Phone Stand (45m) - completed
- Cable Clip (15m) - completed
- Prototype v3 (3h 30m) - failed
Digest-повідомлення поважає той самий вибір мови шаблону, що й immediate-сповіщення — Telegram-чати, прив'язані до операторів з uk-мовою, отримують українське summary, а англомовний email-отримувач — англійське.
Змінні шаблонів¶
Шаблони підставляють {variable}-плейсхолдери. Схема залочена на подію, тож редактор попереджає, коли використано невідомий плейсхолдер. Змінні згруповані за категорією події:
Print events (print_start, print_complete, print_failed, print_stopped, print_progress):
| Змінна | Значення |
|---|---|
{printer_name} (alias {printer}) |
Display-ім'я принтера |
{print_name} (alias {filename}) |
Файл, який зараз друкується |
{progress} |
% завершення (тільки failed/stopped) |
{eta_minutes} / {eta} |
Wall-clock час завершення |
{estimated_time} |
Прогнозована тривалість друку (напр. 1h 23m) |
{duration} |
Реальний elapsed-час друку |
{filament_used_g} (alias {filament_grams}) |
Загальні грами (scaled by progress для фейлів) |
{filament_details} |
Per-spool breakdown (напр. AMS-A T1 PLA: 15.2g) |
{material} |
Aggregate material name |
{reason} |
Причина фейлу (тільки failed/stopped) |
{finish_photo_url} |
URL camera-snapshot (див. нижче) |
Printer events (printer_offline, printer_error):
| Змінна | Значення |
|---|---|
{printer_name} |
Display-ім'я принтера |
{error_code} (alias {error_type}) |
HMS error code |
{error_message} (alias {error_detail}) |
Людино-читабельний опис (BamDude перекладає каталог 853 кодів) |
AMS events (ams_humidity_high, ams_temperature_high, filament_low, print_missing_spool_assignment):
| Змінна | Значення |
|---|---|
{ams_id} |
AMS-юніт (AMS-A, AMS-B, …) |
{slot} |
Tray index (T1–T4) |
{material} |
Матеріал, призначений на слот |
{remaining_percent} |
Залишок філаменту (filament_low) |
{humidity} |
% вологості (humidity events) |
{missing_slots} |
Comma-separated лейбли слотів (A1, A3) для print_missing_spool_assignment |
{missing_slot_details} |
Per-slot breakdown з очікуваним профілем (- A1: PLA Basic) |
Common для будь-якої події: {timestamp}, {app_name} (завжди "BamDude").
Натисни Reset to default у редакторі, щоб відновити оригінальний шаблон з notification_templates_{en,uk}.json.
Finish Photo URL¶
Плейсхолдер {finish_photo_url} кладе camera-snapshot готової плити в сповіщення про завершення / провал. Потребує доступної external URL:
- Settings → System → External URL — постав адресу, до якої отримувачі мають доступ (напр.
https://bamdude.example.comчиhttp://192.168.1.100:8000) - Налаштування auto-detect-иться з браузера, коли вперше відкриваєш System settings
- Відредагуй шаблон і додай
{finish_photo_url}куди хочеш фото
Email вшиває фото inline, не лише посилання
Для email-провайдерів, коли підставлений {finish_photo_url} присутній у тілі і finish-фото справді зроблено, BamDude шле лист як multipart/related зі вбудованим inline JPEG (через Content-ID, на який посилається HTML-частина) — фото видно прямо в тілі листа, а не як голе посилання. Plain-text альтернатива й далі несе клікабельний URL для text-only клієнтів. Коли шаблон не містить {finish_photo_url} (або фото немає), використовується звичайний single-part text-лист — без несподіваного attachment-а. Не-email канали (WhatsApp / webhook / …) й далі отримують посилання — тому External URL нижче має бути досяжним.
External URL — обов'язкова умова
Без сконфігурованого External URL плейсхолдер рендериться порожнім. Camera-snapshot-и також ходять через stream-token camera flow — URL вшиває short-lived токен, тож отримувач забирає JPEG без Authorization-хедера.
Quick Disable¶
Глобальний mute-toggle живе у sidebar-і — клік по іконці дзвоника гасить усі вихідні сповіщення на усіх провайдерах, поки не клікнеш ще раз. Корисно під maintenance-вікно, demo-прогон чи галасливу міграцію, коли не хочеться флудити team-чат.
Toggle не видаляє digest-и-в-роботі — події, що впали в digest-чергу до mute, все одно вийдуть на наступний daily_digest_time. Щоб затримати digest, відключи daily-digest на самому провайдері.
Per-Printer фільтрація¶
Кожен не-telegram провайдер має скоуп принтерів — Всі (default), один або будь-яка підмножина, відмічена чекбоксами на формі провайдера. Події з принтерів поза вибраною множиною ніколи не доходять до цього провайдера, незалежно від event-toggle-ів. Для Telegram скоуп живе на кожному чаті (див. Telegram Bot → Скоуп принтерів) — і там він обмежує й самого бота: списки, камери, чергу та керування. Корисні патерни:
- Один Discord-webhook на майстерню — кожен прив'язаний до її принтерів
- "VIP printer" Telegram-чат, прив'язаний до однієї production-одиниці, що генерує дохід
- Maintenance-only ntfy провайдер, прив'язаний до принтерів, у яких підходять заміни фільтрів / ременів
Центр сповіщень¶
Раніше кожне сповіщення йшло назовні — Telegram, email, ntfy, Discord, що там було налаштовано. Інсталяції, де не сконфігуровано жодного провайдера, просто не було куди покласти алерт про власне залізо: подія спрацювала, не збіглася ні з ким і зникла. Тепер дзвоник у sidebar-і відкриває персональний центр сповіщень із трьома вкладками, і вхідні наповнюються незалежно від того, чи налаштований хоч один провайдер. У цьому й суть: провайдери — це те, як сповіщення доходить до твого телефона, а вхідні — як воно доходить до того, хто зайшов в інтерфейс.
Прочитане і непрочитане — у кожного своє. Один оператор, що відкрив алерт, не гасить його для решти. Це і є різниця між вхідними і спільним логом: з подією розбирається кожен, хто на неї підписаний.
Вхідні¶
Події, на які ти підписаний, найновіші згори. Непрочитані рядки помічені; клік по рядку позначає його прочитаним і розгортає повний текст. Кожен рядок несе:
| У рядку | Що показує |
|---|---|
| Рівень | info, warning або error |
| Принтер | з якого принтера прийшла подія |
| Давність | скільки часу тому це сталося |
Список звужують чотири фільтри — рівень, принтер, лише непрочитані і період: останні 24 години, 7 днів, 30 днів або весь час. Довга історія вантажиться сторінками через кнопку Show more, а не вся одразу.
Mark all read і Clear діють на фільтр, а не на всі вхідні
Обидві кнопки застосовуються рівно до того, що зараз вибрано фільтрами. З error + один принтер + останні 7 днів Clear видалить саме ці рядки й не зачепить решту — а без жодного фільтра видалить усе. Clear саме видаляє, тому спершу питає підтвердження. Рядки також можна видаляти по одному просто з рядка.
Підписки¶
Чекбокс на кожну подію, згруповані за областями — друки, принтери, філамент, AMS, черга, інвентар, сенсори, — і поряд із кожною вказано її рівень, тож видно ціну підписки ще до того, як ти поставиш галочку.
За замовчуванням людина отримує лише warning-и й error-и. Вхідні мовчать, доки справді щось не потребує уваги, а кнопка Reset to defaults повертає рівно цей стан після будь-яких експериментів. Кожна зміна зберігається одразу — Save-кнопки, яку можна забути натиснути, тут немає.
Підписки належать людині, а не фермі: два оператори на одній інсталяції можуть стежити за зовсім різним, і вибір одного ніяк не змінює вхідні іншого.
Email¶
Ті самі чотири per-user email-перемикачі, які раніше були всім вмістом цієї сторінки, з незміненою поведінкою — що і коли вони шлють, див. Per-User Email сповіщення нижче.
Вкладка з'являється, тільки якщо увімкнено Advanced Authentication, увімкнено майстер-перемикач User Notifications і в тебе є право notifications:user_email — ті самі три умови, що й раніше.
Лічильник непрочитаного¶
Дзвоник у sidebar-і несе живий лічильник непрочитаного. Він оновлюється по тому самому WebSocket-з'єднанню, яким уже користується решта інтерфейсу, тож нова подія з'являється на дзвонику без перезавантаження сторінки і без полінгу. На вузьких екранах компактний хедер несе той самий дзвоник і той самий лічильник.
Дозвіл¶
Центр сповіщень вимагає права notifications:inbox.
Нотатка до оновлення — кастомна група його сама не отримає
Administrators, Operators і Viewers отримують notifications:inbox під час оновлення. Група, яку ти зробив руками, — ні: оновлення не дописує права у групи, зібрані вручну. Доки адміністратор не видасть право, учасники такої групи втрачають сторінку цілком, разом із per-user email-перемикачами, які в них були раніше. Пройдись по своїх кастомних групах одразу після оновлення.
Зберігання¶
Settings → Data Management містить Inbox notifications (days).
| Налаштування | Типово | Діапазон |
|---|---|---|
| Inbox notifications | 30 днів | 1–365 днів |
Щоденне прибирання видаляє все, старше за вікно, незалежно від того, прочитане воно чи ні — вхідні, які ніхто не відкриває, не ростуть вічно. Видалення користувача забирає його вхідні разом із ним.
Per-User Email сповіщення¶
Окремо від системи провайдерів вище — BamDude вміє писати email власнику друку напряму, коли той завершиться / провалиться / зупиниться — корисно у shared / multi-tenant deployment-ах, де кожен юзер хоче пошту своїх друків в особисту скриньку.
Вимоги¶
- Authentication увімкнена (вона завжди увімкнена з 0.4.0+)
- SMTP сконфігурований у Settings → System → Email
- Settings → Notifications → User Notifications перемкнуто on
- У користувача є email на акаунті
- Користувач має право
notifications:user_email(за замовчуванням у Administrators + Operators — див. Authentication) - Користувач має право
notifications:inbox— перемикачі є вкладкою центру сповіщень, і без цього права сторінку взагалі не відкрити
Підтримувані події¶
| Подія | Спрацьовує на |
|---|---|
user_print_start |
Друк користувача стартує |
user_print_complete |
Його друк завершився успішно |
user_print_failed |
Його друк збився |
user_print_stopped |
Він сам скасував свій друк |
Кожен користувач вмикає й вимикає ці чотири події окремо на вкладці Email свого центру сповіщень — того самого дзвоника в sidebar-і, який раніше відкривав лише цей список перемикачів. Майстер-перемикач User Notifications — у operator-а / admin-а під Settings → Notifications.
Як пропустити подію, що вимагає дії, крізь ніч¶
Деякі події зупиняють ферму, доки хтось не втрутиться:
plate_not_empty— перед стартом queue-job-а зловили непорожній стіл, і диспетч тепер на паузі. Проспати — означає, що черга стоятиме до пробудження.bed_cooled— стіл упав нижче налаштованого порога (типово 35 °C) після друку, тобто деталь можна знімати.- Порогові алерти сенсорів — у кімнаті надто холодно чи надто волого для філаменту, який зараз друкується.
Тихі години — на провайдер, а не на подію
Обходу на рівні події немає. Провайдер усередині свого тихого вікна відкидає все, зокрема й три пункти вище, — тож провайдер, тихий із 22:00, не скаже тобі, що черга стала о 01:00.
Замість цього маршрутизуй: заведи для подій, що вимагають дії, окремий провайдер із вимкненими тихими годинами, а балакучі (прогрес, старт друку) лиши на тому, який спить. На iOS найсильніший варіант цього — провайдер Bark на рівні Critical: він проходить ще й крізь Silent mode і Focus.
Щоденний digest — окремий opt-in канал, і він нічого не затримує: кожне сповіщення надсилається тоді, коли сталося, а digest — це додаткове зведення зверху.
Тестування¶
Кожен провайдер має кнопку Send Test поряд із save-action. Клік запускає синтетичну подію через повний pipeline (template render, quiet-hour gate, priority mapping, transport-specific wrap), тож результуюче повідомлення — точне прев'ю того, як виглядатимуть реальні події, не stripped-down "hello world".
Re-test після редагування шаблонів, зміни priority чи transport-level полів типу SMTP credentials. Тест обходить digest-чергу (завжди шлеться одразу), тож не треба чекати digest-час, щоб побачити результат.
Поради¶
Почніть з ntfy
ntfy -- найпростіший провайдер для налаштування: не потрібен обліковий запис, просто оберіть назву теми та підпишіться на телефоні.
Кілька провайдерів
Ви можете налаштувати кілька провайдерів для одночасного отримання сповіщень через різні канали.
Базується на документації Bambuddy.