- Electron main process subscribes to Frigate's MQTT topics (frigate/<camera>/person and frigate/events) directly via mqtt.js, bypassing the broken HA MQTT integration - Watched cameras: Front_Porch, FPE, Porch_Downstairs, Driveway_door - On person detection, exits photo-frame idle and shows full-screen camera feed for 30 seconds - Removed HA entity-based person detection code (entityToCameraName, personDetectionEntities config dependency) - Deleted unused useFrigateDetection HTTP polling hook (superseded)
91 lines
3.1 KiB
TypeScript
91 lines
3.1 KiB
TypeScript
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
|
|
|
|
export interface ElectronAPI {
|
|
screen: {
|
|
wake: () => Promise<boolean>;
|
|
sleep: () => Promise<boolean>;
|
|
setIdleTimeout: (timeout: number) => Promise<boolean>;
|
|
activity: () => Promise<boolean>;
|
|
};
|
|
presence: {
|
|
start: () => Promise<boolean>;
|
|
stop: () => Promise<boolean>;
|
|
onDetected: (callback: () => void) => () => void;
|
|
onCleared: (callback: () => void) => () => void;
|
|
};
|
|
frigate: {
|
|
startStream: (rtspUrl: string) => Promise<boolean>;
|
|
stopStream: () => Promise<boolean>;
|
|
onPersonDetected: (callback: (camera: string) => void) => () => void;
|
|
};
|
|
app: {
|
|
quit: () => void;
|
|
toggleFullscreen: () => void;
|
|
toggleDevTools: () => void;
|
|
};
|
|
config: {
|
|
getStoredToken: () => Promise<string | null>;
|
|
getJellyfinApiKey: () => Promise<string | null>;
|
|
};
|
|
photos: {
|
|
list: () => Promise<string[]>;
|
|
getDir: () => Promise<string>;
|
|
getUrl: (relative: string) => Promise<string | null>;
|
|
};
|
|
}
|
|
|
|
const electronAPI: ElectronAPI = {
|
|
screen: {
|
|
wake: () => ipcRenderer.invoke('screen:wake'),
|
|
sleep: () => ipcRenderer.invoke('screen:sleep'),
|
|
setIdleTimeout: (timeout: number) => ipcRenderer.invoke('screen:setIdleTimeout', timeout),
|
|
activity: () => ipcRenderer.invoke('screen:activity'),
|
|
},
|
|
presence: {
|
|
start: () => ipcRenderer.invoke('presence:start'),
|
|
stop: () => ipcRenderer.invoke('presence:stop'),
|
|
onDetected: (callback: () => void) => {
|
|
const handler = (_event: IpcRendererEvent) => callback();
|
|
ipcRenderer.on('presence:detected', handler);
|
|
return () => ipcRenderer.removeListener('presence:detected', handler);
|
|
},
|
|
onCleared: (callback: () => void) => {
|
|
const handler = (_event: IpcRendererEvent) => callback();
|
|
ipcRenderer.on('presence:cleared', handler);
|
|
return () => ipcRenderer.removeListener('presence:cleared', handler);
|
|
},
|
|
},
|
|
frigate: {
|
|
startStream: (rtspUrl: string) => ipcRenderer.invoke('frigate:startStream', rtspUrl),
|
|
stopStream: () => ipcRenderer.invoke('frigate:stopStream'),
|
|
onPersonDetected: (callback: (camera: string) => void) => {
|
|
const handler = (_event: IpcRendererEvent, camera: string) => callback(camera);
|
|
ipcRenderer.on('frigate:personDetected', handler);
|
|
return () => ipcRenderer.removeListener('frigate:personDetected', handler);
|
|
},
|
|
},
|
|
app: {
|
|
quit: () => ipcRenderer.invoke('app:quit'),
|
|
toggleFullscreen: () => ipcRenderer.invoke('app:toggleFullscreen'),
|
|
toggleDevTools: () => ipcRenderer.invoke('app:toggleDevTools'),
|
|
},
|
|
config: {
|
|
getStoredToken: () => ipcRenderer.invoke('config:getStoredToken'),
|
|
getJellyfinApiKey: () => ipcRenderer.invoke('config:getJellyfinApiKey'),
|
|
},
|
|
photos: {
|
|
list: () => ipcRenderer.invoke('photos:list'),
|
|
getDir: () => ipcRenderer.invoke('photos:getDir'),
|
|
getUrl: (relative: string) => ipcRenderer.invoke('photos:getUrl', relative),
|
|
},
|
|
};
|
|
|
|
contextBridge.exposeInMainWorld('electronAPI', electronAPI);
|
|
|
|
// Type declaration for renderer
|
|
declare global {
|
|
interface Window {
|
|
electronAPI: ElectronAPI;
|
|
}
|
|
}
|