mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
change MQTT to toggle recordings instead of clips
This commit is contained in:
parent
181a504a14
commit
c527b1ca5d
@ -88,13 +88,13 @@ Topic to turn detection for a camera on and off. Expected values are `ON` and `O
|
|||||||
|
|
||||||
Topic with current state of detection for a camera. Published values are `ON` and `OFF`.
|
Topic with current state of detection for a camera. Published values are `ON` and `OFF`.
|
||||||
|
|
||||||
### `frigate/<camera_name>/clips/set`
|
### `frigate/<camera_name>/recordings/set`
|
||||||
|
|
||||||
Topic to turn clips for a camera on and off. Expected values are `ON` and `OFF`.
|
Topic to turn recordings for a camera on and off. Expected values are `ON` and `OFF`.
|
||||||
|
|
||||||
### `frigate/<camera_name>/clips/state`
|
### `frigate/<camera_name>/recordings/state`
|
||||||
|
|
||||||
Topic with current state of clips for a camera. Published values are `ON` and `OFF`.
|
Topic with current state of recordings for a camera. Published values are `ON` and `OFF`.
|
||||||
|
|
||||||
### `frigate/<camera_name>/snapshots/set`
|
### `frigate/<camera_name>/snapshots/set`
|
||||||
|
|
||||||
|
@ -21,22 +21,22 @@ logger = logging.getLogger(__name__)
|
|||||||
def create_mqtt_client(config: FrigateConfig, camera_metrics):
|
def create_mqtt_client(config: FrigateConfig, camera_metrics):
|
||||||
mqtt_config = config.mqtt
|
mqtt_config = config.mqtt
|
||||||
|
|
||||||
def on_clips_command(client, userdata, message):
|
def on_recordings_command(client, userdata, message):
|
||||||
payload = message.payload.decode()
|
payload = message.payload.decode()
|
||||||
logger.debug(f"on_clips_toggle: {message.topic} {payload}")
|
logger.debug(f"on_recordings_toggle: {message.topic} {payload}")
|
||||||
|
|
||||||
camera_name = message.topic.split("/")[-3]
|
camera_name = message.topic.split("/")[-3]
|
||||||
|
|
||||||
clips_settings = config.cameras[camera_name].clips
|
record_settings = config.cameras[camera_name].record
|
||||||
|
|
||||||
if payload == "ON":
|
if payload == "ON":
|
||||||
if not clips_settings.enabled:
|
if not record_settings.enabled:
|
||||||
logger.info(f"Turning on clips for {camera_name} via mqtt")
|
logger.info(f"Turning on recordings for {camera_name} via mqtt")
|
||||||
clips_settings.enabled = True
|
record_settings.enabled = True
|
||||||
elif payload == "OFF":
|
elif payload == "OFF":
|
||||||
if clips_settings.enabled:
|
if record_settings.enabled:
|
||||||
logger.info(f"Turning off clips for {camera_name} via mqtt")
|
logger.info(f"Turning off recordings for {camera_name} via mqtt")
|
||||||
clips_settings.enabled = False
|
record_settings.enabled = False
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Received unsupported value at {message.topic}: {payload}")
|
logger.warning(f"Received unsupported value at {message.topic}: {payload}")
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics):
|
|||||||
# register callbacks
|
# register callbacks
|
||||||
for name in config.cameras.keys():
|
for name in config.cameras.keys():
|
||||||
client.message_callback_add(
|
client.message_callback_add(
|
||||||
f"{mqtt_config.topic_prefix}/{name}/clips/set", on_clips_command
|
f"{mqtt_config.topic_prefix}/{name}/recordings/set", on_recordings_command
|
||||||
)
|
)
|
||||||
client.message_callback_add(
|
client.message_callback_add(
|
||||||
f"{mqtt_config.topic_prefix}/{name}/snapshots/set", on_snapshots_command
|
f"{mqtt_config.topic_prefix}/{name}/snapshots/set", on_snapshots_command
|
||||||
@ -159,8 +159,8 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics):
|
|||||||
|
|
||||||
for name in config.cameras.keys():
|
for name in config.cameras.keys():
|
||||||
client.publish(
|
client.publish(
|
||||||
f"{mqtt_config.topic_prefix}/{name}/clips/state",
|
f"{mqtt_config.topic_prefix}/{name}/recordings/state",
|
||||||
"ON" if config.cameras[name].clips.enabled else "OFF",
|
"ON" if config.cameras[name].record.enabled else "OFF",
|
||||||
retain=True,
|
retain=True,
|
||||||
)
|
)
|
||||||
client.publish(
|
client.publish(
|
||||||
|
@ -107,12 +107,12 @@ describe('MqttProvider', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('prefills the clips/detect/snapshots state from config', async () => {
|
test('prefills the recordings/detect/snapshots state from config', async () => {
|
||||||
jest.spyOn(Date, 'now').mockReturnValue(123456);
|
jest.spyOn(Date, 'now').mockReturnValue(123456);
|
||||||
const config = {
|
const config = {
|
||||||
cameras: {
|
cameras: {
|
||||||
front: { name: 'front', detect: { enabled: true }, clips: { enabled: false }, snapshots: { enabled: true } },
|
front: { name: 'front', detect: { enabled: true }, record: { enabled: false }, snapshots: { enabled: true } },
|
||||||
side: { name: 'side', detect: { enabled: false }, clips: { enabled: false }, snapshots: { enabled: false } },
|
side: { name: 'side', detect: { enabled: false }, record: { enabled: false }, snapshots: { enabled: false } },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
render(
|
render(
|
||||||
@ -122,10 +122,10 @@ describe('MqttProvider', () => {
|
|||||||
);
|
);
|
||||||
await screen.findByTestId('data');
|
await screen.findByTestId('data');
|
||||||
expect(screen.getByTestId('front/detect/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"ON"}');
|
expect(screen.getByTestId('front/detect/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"ON"}');
|
||||||
expect(screen.getByTestId('front/clips/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
expect(screen.getByTestId('front/recordings/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
||||||
expect(screen.getByTestId('front/snapshots/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"ON"}');
|
expect(screen.getByTestId('front/snapshots/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"ON"}');
|
||||||
expect(screen.getByTestId('side/detect/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
expect(screen.getByTestId('side/detect/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
||||||
expect(screen.getByTestId('side/clips/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
expect(screen.getByTestId('side/recordings/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
||||||
expect(screen.getByTestId('side/snapshots/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
expect(screen.getByTestId('side/snapshots/state')).toHaveTextContent('{"lastUpdate":123456,"payload":"OFF"}');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -41,8 +41,8 @@ export function MqttProvider({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Object.keys(config.cameras).forEach((camera) => {
|
Object.keys(config.cameras).forEach((camera) => {
|
||||||
const { name, clips, detect, snapshots } = config.cameras[camera];
|
const { name, record, detect, snapshots } = config.cameras[camera];
|
||||||
dispatch({ topic: `${name}/clips/state`, payload: clips.enabled ? 'ON' : 'OFF' });
|
dispatch({ topic: `${name}/recordings/state`, payload: record.enabled ? 'ON' : 'OFF' });
|
||||||
dispatch({ topic: `${name}/detect/state`, payload: detect.enabled ? 'ON' : 'OFF' });
|
dispatch({ topic: `${name}/detect/state`, payload: detect.enabled ? 'ON' : 'OFF' });
|
||||||
dispatch({ topic: `${name}/snapshots/state`, payload: snapshots.enabled ? 'ON' : 'OFF' });
|
dispatch({ topic: `${name}/snapshots/state`, payload: snapshots.enabled ? 'ON' : 'OFF' });
|
||||||
});
|
});
|
||||||
@ -101,12 +101,12 @@ export function useDetectState(camera) {
|
|||||||
return { payload, send, connected };
|
return { payload, send, connected };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useClipsState(camera) {
|
export function useRecordingsState(camera) {
|
||||||
const {
|
const {
|
||||||
value: { payload },
|
value: { payload },
|
||||||
send,
|
send,
|
||||||
connected,
|
connected,
|
||||||
} = useMqtt(`${camera}/clips/state`, `${camera}/clips/set`);
|
} = useMqtt(`${camera}/recordings/state`, `${camera}/recordings/set`);
|
||||||
return { payload, send, connected };
|
return { payload, send, connected };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import CameraImage from '../components/CameraImage';
|
|||||||
import ClipIcon from '../icons/Clip';
|
import ClipIcon from '../icons/Clip';
|
||||||
import MotionIcon from '../icons/Motion';
|
import MotionIcon from '../icons/Motion';
|
||||||
import SnapshotIcon from '../icons/Snapshot';
|
import SnapshotIcon from '../icons/Snapshot';
|
||||||
import { useDetectState, useClipsState, useSnapshotsState } from '../api/mqtt';
|
import { useDetectState, useRecordingsState, useSnapshotsState } from '../api/mqtt';
|
||||||
import { useConfig, FetchStatus } from '../api';
|
import { useConfig, FetchStatus } from '../api';
|
||||||
import { useMemo } from 'preact/hooks';
|
import { useMemo } from 'preact/hooks';
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ export default function Cameras() {
|
|||||||
|
|
||||||
function Camera({ name, conf }) {
|
function Camera({ name, conf }) {
|
||||||
const { payload: detectValue, send: sendDetect } = useDetectState(name);
|
const { payload: detectValue, send: sendDetect } = useDetectState(name);
|
||||||
const { payload: clipValue, send: sendClips } = useClipsState(name);
|
const { payload: recordValue, send: sendRecordings } = useRecordingsState(name);
|
||||||
const { payload: snapshotValue, send: sendSnapshots } = useSnapshotsState(name);
|
const { payload: snapshotValue, send: sendSnapshots } = useSnapshotsState(name);
|
||||||
const href = `/cameras/${name}`;
|
const href = `/cameras/${name}`;
|
||||||
const buttons = useMemo(() => {
|
const buttons = useMemo(() => {
|
||||||
@ -46,11 +46,11 @@ function Camera({ name, conf }) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `Toggle clips ${clipValue === 'ON' ? 'off' : 'on'}`,
|
name: `Toggle recordings ${recordValue === 'ON' ? 'off' : 'on'}`,
|
||||||
icon: ClipIcon,
|
icon: ClipIcon,
|
||||||
color: clipValue === 'ON' ? 'blue' : 'gray',
|
color: recordValue === 'ON' ? 'blue' : 'gray',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
sendClips(clipValue === 'ON' ? 'OFF' : 'ON');
|
sendRecordings(recordValue === 'ON' ? 'OFF' : 'ON');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ function Camera({ name, conf }) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[detectValue, sendDetect, clipValue, sendClips, snapshotValue, sendSnapshots]
|
[detectValue, sendDetect, recordValue, sendRecordings, snapshotValue, sendSnapshots]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -51,13 +51,13 @@ describe('Cameras Route', () => {
|
|||||||
|
|
||||||
test('buttons toggle detect, clips, and snapshots', async () => {
|
test('buttons toggle detect, clips, and snapshots', async () => {
|
||||||
const sendDetect = jest.fn();
|
const sendDetect = jest.fn();
|
||||||
const sendClips = jest.fn();
|
const sendRecordings = jest.fn();
|
||||||
const sendSnapshots = jest.fn();
|
const sendSnapshots = jest.fn();
|
||||||
jest.spyOn(Mqtt, 'useDetectState').mockImplementation(() => {
|
jest.spyOn(Mqtt, 'useDetectState').mockImplementation(() => {
|
||||||
return { payload: 'ON', send: sendDetect };
|
return { payload: 'ON', send: sendDetect };
|
||||||
});
|
});
|
||||||
jest.spyOn(Mqtt, 'useClipsState').mockImplementation(() => {
|
jest.spyOn(Mqtt, 'useRecordingsState').mockImplementation(() => {
|
||||||
return { payload: 'OFF', send: sendClips };
|
return { payload: 'OFF', send: sendRecordings };
|
||||||
});
|
});
|
||||||
jest.spyOn(Mqtt, 'useSnapshotsState').mockImplementation(() => {
|
jest.spyOn(Mqtt, 'useSnapshotsState').mockImplementation(() => {
|
||||||
return { payload: 'ON', send: sendSnapshots };
|
return { payload: 'ON', send: sendSnapshots };
|
||||||
@ -72,11 +72,11 @@ describe('Cameras Route', () => {
|
|||||||
fireEvent.click(screen.getAllByLabelText('Toggle snapshots off')[0]);
|
fireEvent.click(screen.getAllByLabelText('Toggle snapshots off')[0]);
|
||||||
expect(sendSnapshots).toHaveBeenCalledWith('OFF');
|
expect(sendSnapshots).toHaveBeenCalledWith('OFF');
|
||||||
|
|
||||||
fireEvent.click(screen.getAllByLabelText('Toggle clips on')[0]);
|
fireEvent.click(screen.getAllByLabelText('Toggle recordings on')[0]);
|
||||||
expect(sendClips).toHaveBeenCalledWith('ON');
|
expect(sendRecordings).toHaveBeenCalledWith('ON');
|
||||||
|
|
||||||
expect(sendDetect).toHaveBeenCalledTimes(1);
|
expect(sendDetect).toHaveBeenCalledTimes(1);
|
||||||
expect(sendSnapshots).toHaveBeenCalledTimes(1);
|
expect(sendSnapshots).toHaveBeenCalledTimes(1);
|
||||||
expect(sendClips).toHaveBeenCalledTimes(1);
|
expect(sendRecordings).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user