Skip to content

Commit

Permalink
v1.1.7
Browse files Browse the repository at this point in the history
  • Loading branch information
seydx committed Apr 15, 2022
1 parent d4943e4 commit 04d753f
Show file tree
Hide file tree
Showing 29 changed files with 415 additions and 191 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,5 @@ parseFFmpeg.js
parseUrl.js
systeminformation.js
parseRegions.js
src2
src2
lang.js
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,4 @@ parseUrl.js
systeminformation.js
parseRegions.js
src2
lang.js
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
# Changelog
All notable changes to this project will be documented in this file.

# NEXT
# v1.1.7 - 2022-04-15

## Other Changes
- i18n: Thai (th) language added by [@tomzt](https://github.com/tomzt)
- i18n: French (fr) language added by [@NebzHB](https://github.com/NebzHB)
- i18n: Spanish (es) language added by [@mastefordev](https://github.com/masterfordev)
- Added a new config.json tab to `Interface > Settings > System`
- Improved videoanalysis
- Minor UI improvements
- Bump dependencies

## Bugfixes
- Fixed an issue where pinging camera sources with `non-break spaces` failed
- Fixed an issue where Doorbell Topic and Message were not displayed in the interface
- Fixed an issue where changing `recordOnMovement` in the ui settings was resetted after restart
- Fixed an issue where notifications were saved to the database even if the notifications were disabled in the settings
- Fixed an issue where Telegram sometimes could not send videos
- Fixed tests
- Minor bugfixes

# v1.1.6 - 2022-01-25

## Bugfixes
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "camera.ui",
"version": "1.1.6",
"version": "1.1.7",
"description": "NVR like user interface for RTSP capable cameras.",
"author": "SeydX (https://github.com/SeydX/camera.ui)",
"scripts": {
Expand Down
43 changes: 43 additions & 0 deletions src/api/components/config/config.controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
/* eslint-disable unicorn/prevent-abbreviations */
'use-strict';

import fs from 'fs-extra';

import * as ConfigModel from './config.model.js';

import LoggerService from '../../../services/logger/logger.service.js';
import ConfigService from '../../../services/config/config.service.js';

const { log } = LoggerService;

export const downloadConfig = async (req, res, next) => {
try {
const configPath = ConfigService.configPath;

res.header('Content-Type', 'application/json');
res.sendFile(configPath, (err) => {
if (err) {
if (err?.status === 404 || err?.statusCode === 404) {
log.debug(err.message);
}

next();
}
});
} catch (error) {
res.status(500).send({
statusCode: 500,
message: error.message,
});
}
};

export const lastModifiedConfig = async (req, res) => {
try {
const configPath = ConfigService.configPath;
const configFileInfo = await fs.stat(configPath);

res.status(200).send(configFileInfo);
} catch (error) {
res.status(500).send({
statusCode: 500,
message: error.message,
});
}
};

export const show = async (req, res) => {
try {
const result = await ConfigModel.show(req.jwt, req.query.target);
Expand Down
45 changes: 45 additions & 0 deletions src/api/components/config/config.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,51 @@ export const routesConfig = (app) => {
*/

app.get('/api/config', [ValidationMiddleware.validJWTOptional, ConfigController.show]);

/**
* @swagger
* /api/system/config/download:
* get:
* tags: [System]
* security:
* - bearerAuth: []
* summary: Get config.json
* responses:
* 200:
* description: Successfull
* 401:
* description: Unauthorized
* 500:
* description: Internal server error
*/
app.get('/api/config/download', [
ValidationMiddleware.validJWTNeeded,
PermissionMiddleware.onlyMasterCanDoThisAction,
ConfigController.downloadConfig,
]);

/**
* @swagger
* /api/config/stat:
* get:
* tags: [Config]
* security:
* - bearerAuth: []
* summary: Get Config file info
* responses:
* 200:
* description: Successfull
* 401:
* description: Unauthorized
* 500:
* description: Internal server error
*/
app.get('/api/config/stat', [
ValidationMiddleware.validJWTNeeded,
PermissionMiddleware.onlyMasterCanDoThisAction,
ConfigController.lastModifiedConfig,
]);

/**
* @swagger
* /api/config/{target}:
Expand Down
44 changes: 26 additions & 18 deletions src/api/components/notifications/notifications.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,6 @@ export const createNotification = async (data) => {
throw new Error('Can not assign notification to camera!');
}

//Check notification size, if we exceed more than {100} notifications, remove the latest
const notificationList = await Database.interfaceDB.chain.get('notifications').cloneDeep().value();

if (notificationList.length > notificationsLimit) {
const diff = notificationList.length - notificationsLimit;
const diffNotifiations = notificationList.slice(-diff);

for (const notification of diffNotifiations) {
Cleartimer.removeNotificationTimer(notification.id);
}

await Database.interfaceDB.chain.get('notifications').dropRight(notificationList, diff).value();
}

const cameraSetting = camerasSettings.find((cameraSetting) => cameraSetting && cameraSetting.name === camera.name);

const id = data.id || (await nanoid());
Expand Down Expand Up @@ -152,10 +138,6 @@ export const createNotification = async (data) => {
label: label,
};

await Database.interfaceDB.chain.get('notifications').push(notification).value();

Cleartimer.setNotification(id, timestamp);

const notify = {
...notification,
title: cameraName,
Expand All @@ -171,6 +153,32 @@ export const createNotification = async (data) => {
isNotification: true,
};

const notificationSettings = await Database.interfaceDB.chain
.get('settings')
.get('notifications')
.cloneDeep()
.value();

if (notificationSettings.active) {
//Check notification size, if we exceed more than {100} notifications, remove the latest
const notificationList = await Database.interfaceDB.chain.get('notifications').cloneDeep().value();

if (notificationList.length > notificationsLimit) {
const diff = notificationList.length - notificationsLimit;
const diffNotifiations = notificationList.slice(-diff);

for (const notification of diffNotifiations) {
Cleartimer.removeNotificationTimer(notification.id);
}

await Database.interfaceDB.chain.get('notifications').dropRight(notificationList, diff).value();
}

await Database.interfaceDB.chain.get('notifications').push(notification).value();

Cleartimer.setNotification(id, timestamp);
}

return {
notification: notification,
notify: notify,
Expand Down
2 changes: 1 addition & 1 deletion src/api/components/system/system.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const routesConfig = (app) => {

/**
* @swagger
* /api/system/log/download:
* /api/system/db/download:
* get:
* tags: [System]
* security:
Expand Down
10 changes: 7 additions & 3 deletions src/common/cleartimer.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,20 @@ export default class Cleartimer {
if (timeValue) {
const endTime = moment.unix(timestamp).add(timeValue, timeTyp);

//log.debug(`SET cleartimer for ${isRecording ? 'Recording' : 'Notification'} (${id}) - Endtime: ${endTime}`);
/*log.debug(
`SET cleartimer for ${
isRecording ? 'Recording' : 'Notification'
} (${id}) - Removing after ${timeValue} ${timeTyp} - Endtime: ${endTime}`
);*/

const interval = isRecording ? 24 * 60 * 60 * 1000 : 60 * 60 * 1000;
const interval = isRecording ? 6 * 60 * 60 * 1000 : 30 * 60 * 1000;

const timer = setInterval(async () => {
const now = moment();

if (now > endTime) {
clearInterval(timer);
await (isRecording ? Cleartimer.#clearRecording(id) : Cleartimer.#clearNotification(id));
clearInterval(timer);
}
}, interval);

Expand Down
3 changes: 2 additions & 1 deletion src/common/ping.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export default class Ping {
static async status(camera, timeout = 1) {
const { log } = LoggerService;

let cameraSource = camera.videoConfig.source.split('-i ')[1];
//fix for non-break-spaces
let cameraSource = camera.videoConfig.source.replace(/\u00A0/g, ' ').split('-i ')[1];

if (!cameraSource) {
log.warn(`Can not ping camera source, no source found (${camera.videoConfig.source})`, camera.name);
Expand Down
3 changes: 2 additions & 1 deletion src/common/telegram.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ export default class Telegram {
if (content.video) {
try {
log.debug('Telegram: Sending Video');
await Telegram.bot.sendVideo(chatID, content.video, {}, { filename: content.fileName });
const stream = fs.createReadStream(content.video);
await Telegram.bot.sendVideo(chatID, stream, {}, { filename: content.fileName });
} catch (error) {
log.info('An error occured during sending video!', 'Telegram', 'notifications');
log.error(error?.message || error, 'Telegram', 'notifications');
Expand Down
7 changes: 2 additions & 5 deletions src/controller/camera/services/media.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ export default class MediaService {
async probe() {
// eslint-disable-next-line no-unused-vars
return new Promise((resolve, reject) => {
log.debug(
`Probe stream: ${ConfigService.ui.options.videoProcessor} ${this.#camera.videoConfig.subSource}`,
this.cameraName
);

const arguments_ = [
'-hide_banner',
'-loglevel',
Expand All @@ -57,6 +52,8 @@ export default class MediaService {
...this.#camera.videoConfig.source.split(/\s+/),
];

log.debug(`Probe stream: ${ConfigService.ui.options.videoProcessor} ${arguments_.join(' ')}`, this.cameraName);

let cp = spawn(ConfigService.ui.options.videoProcessor, arguments_, {
env: process.env,
});
Expand Down
2 changes: 1 addition & 1 deletion src/controller/camera/services/prebuffer.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ export default class PrebufferService {
};

this.events.on(eventName, safeWriteData);
this.prebufferSession.events.once('killed', cleanup);
this.prebufferSession?.events.once('killed', cleanup);

const parser = this.parsers[container];
const availablePrebuffers = parser.findSyncFrame(
Expand Down
Loading

0 comments on commit 04d753f

Please sign in to comment.