mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-09 15:35:39 +02:00
feat(obico): AI print-failure detection via self-hosted Obico ML API (#172)
Adds a Failure Detection tab under Settings that wires Bambuddy to a
self-hosted Obico ml_api container — no cloud, no account, no WebSocket.
While a print is running, the detection service periodically hands the
printer's camera snapshot URL to the ML API and smooths scores over
time (30-frame warmup + EWM, alpha=2/13, short/long rolling means) so
one noisy frame can't trigger an action. When the smoothed score
crosses HIGH, the configured action fires exactly once per print:
notify, pause, or pause-and-cut-power (via linked smart plugs).
- Backend: new obico_detection + obico_smoothing + obico_actions
services, /obico/status and /obico/test-connection routes
(SETTINGS_READ / SETTINGS_UPDATE), six obico_* AppSettings fields
with validators for sensitivity/action/enabled_printers.
- Frontend: FailureDetectionSettings component (enable, ML URL + test,
sensitivity, action, poll interval, per-printer monitor list, live
status + detection history), new sidebar tab with service-active
bullet, toast on save.
- Tests: 17 detection unit tests + 15 smoothing unit tests + 4
frontend component tests.
- Docs: README bullet, CHANGELOG entry, wiki page under Analytics,
website features.html entry.
This commit is contained in:
@@ -925,6 +925,12 @@ export interface AppSettings {
|
||||
ldap_group_mapping: string;
|
||||
ldap_auto_provision: boolean;
|
||||
ldap_default_group: string;
|
||||
obico_enabled: boolean;
|
||||
obico_ml_url: string;
|
||||
obico_sensitivity: 'low' | 'medium' | 'high';
|
||||
obico_action: 'notify' | 'pause' | 'pause_and_off';
|
||||
obico_poll_interval: number;
|
||||
obico_enabled_printers: string;
|
||||
}
|
||||
|
||||
export type AppSettingsUpdate = Partial<AppSettings>;
|
||||
@@ -1832,6 +1838,37 @@ export interface LocalBackupFile {
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface ObicoDetectionEvent {
|
||||
printer_id: number;
|
||||
task_name: string;
|
||||
timestamp: string;
|
||||
current_p: number;
|
||||
score: number;
|
||||
class: 'safe' | 'warning' | 'failure';
|
||||
detections: number;
|
||||
}
|
||||
|
||||
export interface ObicoStatus {
|
||||
is_running: boolean;
|
||||
last_error: string | null;
|
||||
per_printer: Record<string, { class: string; frame_count: number; score: number }>;
|
||||
thresholds: { low: number; high: number };
|
||||
history: ObicoDetectionEvent[];
|
||||
enabled: boolean;
|
||||
ml_url: string;
|
||||
sensitivity: 'low' | 'medium' | 'high';
|
||||
action: 'notify' | 'pause' | 'pause_and_off';
|
||||
poll_interval: number;
|
||||
external_url_configured: boolean;
|
||||
}
|
||||
|
||||
export interface ObicoTestConnection {
|
||||
ok: boolean;
|
||||
status_code: number | null;
|
||||
body: string | null;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export interface GitHubTestConnectionResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
@@ -4518,6 +4555,16 @@ export const api = {
|
||||
deleteLocalBackup: (filename: string) =>
|
||||
request<{ success: boolean; message: string }>(`/local-backup/backups/${encodeURIComponent(filename)}`, { method: 'DELETE' }),
|
||||
|
||||
// Obico AI failure detection
|
||||
getObicoStatus: () =>
|
||||
request<ObicoStatus>('/obico/status'),
|
||||
|
||||
testObicoConnection: (url: string) =>
|
||||
request<ObicoTestConnection>('/obico/test-connection', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ url }),
|
||||
}),
|
||||
|
||||
// Local Presets (OrcaSlicer imports)
|
||||
getLocalPresets: () =>
|
||||
request<LocalPresetsResponse>('/local-presets/'),
|
||||
|
||||
Reference in New Issue
Block a user