Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard: Camera image should expires #1880

Merged
merged 5 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions front/src/components/boxs/camera/Camera.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Hls from 'hls.js';
import config from '../../../config';
import { WEBSOCKET_MESSAGE_TYPES } from '../../../../../server/utils/constants';
import get from 'get-value';
import style from './style.css';

const SEGMENT_DURATIONS_PER_LATENCY = {
'ultra-low': 1,
Expand Down Expand Up @@ -270,8 +271,7 @@ class CameraBoxComponent extends Component {
{image && <img class="card-img-top" src={`data:${image}`} alt={props.roomName} />}
{error && (
<div>
<p class="alert alert-danger">
<i class="fe fe-bell" />
<p class={style.noImageToShowError}>
<span class="pl-2">
<Text id="dashboard.boxes.camera.noImageToShow" />
</span>
Expand Down
12 changes: 12 additions & 0 deletions front/src/components/boxs/camera/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.noImageToShowError {
background-color: #34495e;
color: white;
height: 244px;
padding: 12px;
padding-bottom: 0px;
margin-bottom: 0px;
display: table-cell;
vertical-align: middle;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
2 changes: 1 addition & 1 deletion front/src/config/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
},
"camera": {
"editCameraLabel": "Select the camera you want to display here.",
"noImageToShow": "No image to show",
"noImageToShow": "No image to show. Are you sure you camera is connected and accessible to Gladys?",
"editBoxNameLabel": "Enter the name you want to give to the box:",
"editBoxNamePlaceholder": "Name of the box",
"latencyBoxName": "Latency",
Expand Down
2 changes: 1 addition & 1 deletion front/src/config/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
},
"camera": {
"editCameraLabel": "Sélectionnez la caméra que vous souhaitez afficher ici.",
"noImageToShow": "Aucune image à afficher",
"noImageToShow": "Aucune image à afficher. Êtes-vous sûr que votre caméra est connectée et accessible par Gladys ?",
"editBoxNameLabel": "Entrez le nom que vous souhaitez donner à la box :",
"editBoxNamePlaceholder": "Nom de la box",
"latencyBoxName": "Latence",
Expand Down
12 changes: 12 additions & 0 deletions server/lib/device/camera/camera.getImage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const { NotFoundError } = require('../../../utils/coreErrors');
const { DEVICE_FEATURE_CATEGORIES, DEVICE_FEATURE_TYPES } = require('../../../utils/constants');
const { isNumeric } = require('../../../utils/device');

const CAMERA_IMAGE_EXPIRATION_TIME_IN_HOURS = 1;

/**
* @description Get image of a camera.
Expand All @@ -19,6 +22,15 @@ async function getImage(selector) {
if (!deviceFeature) {
throw new NotFoundError('Camera image feature not found');
}
let lastValueInTimestamp = new Date(deviceFeature.last_value_changed).getTime();
if (!isNumeric(lastValueInTimestamp)) {
lastValueInTimestamp = 0;
}
const tooOldTimestamp = Date.now() - CAMERA_IMAGE_EXPIRATION_TIME_IN_HOURS * 60 * 60 * 1000;
const lastValueIsToOld = lastValueInTimestamp < tooOldTimestamp;
if (lastValueIsToOld) {
throw new NotFoundError('Camera image is too old');
}
return Promise.resolve(deviceFeature.last_value_string);
}

Expand Down
55 changes: 55 additions & 0 deletions server/test/lib/device/camera/camera.getImage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('Camera.getImage', () => {
selector: 'test-camera',
category: 'camera',
type: 'image',
last_value_changed: new Date().toISOString(),
last_value_string: RANDOM_IMAGE,
},
],
Expand All @@ -45,6 +46,60 @@ describe('Camera.getImage', () => {
const promise = deviceManager.camera.getImage('camera-not-found');
return assert.isRejected(promise, 'Camera not found');
});
it('should return camera image is too old (old date)', async () => {
const stateManager = new StateManager(event);
const deviceManager = new Device(event, {}, stateManager, {}, {}, {}, job);
stateManager.setState('device', 'test-camera', {
features: [
{
id: '565d05fc-1736-4b76-99ca-581232901d96',
selector: 'test-camera',
category: 'camera',
type: 'image',
last_value_changed: new Date(Date.now() - 5 * 60 * 60 * 1000).toISOString(),
last_value_string: RANDOM_IMAGE,
},
],
});
const promise = deviceManager.camera.getImage('test-camera');
return assert.isRejected(promise, 'Camera image is too old');
});
it('should return camera image is too old (null date)', async () => {
const stateManager = new StateManager(event);
const deviceManager = new Device(event, {}, stateManager, {}, {}, {}, job);
stateManager.setState('device', 'test-camera', {
features: [
{
id: '565d05fc-1736-4b76-99ca-581232901d96',
selector: 'test-camera',
category: 'camera',
type: 'image',
last_value_changed: null,
last_value_string: null,
},
],
});
const promise = deviceManager.camera.getImage('test-camera');
return assert.isRejected(promise, 'Camera image is too old');
});
it('should return camera image is too old (wrong date)', async () => {
const stateManager = new StateManager(event);
const deviceManager = new Device(event, {}, stateManager, {}, {}, {}, job);
stateManager.setState('device', 'test-camera', {
features: [
{
id: '565d05fc-1736-4b76-99ca-581232901d96',
selector: 'test-camera',
category: 'camera',
type: 'image',
last_value_changed: 'lalala',
last_value_string: null,
},
],
});
const promise = deviceManager.camera.getImage('test-camera');
return assert.isRejected(promise, 'Camera image is too old');
});
it('should return camera not found', async () => {
const stateManager = new StateManager(event);
const deviceManager = new Device(event, {}, stateManager, {}, {}, {}, job);
Expand Down
Loading