diff --git a/.github/workflows/codeLintGlobal.yml b/.github/workflows/codeLintGlobal.yml
deleted file mode 100644
index d10bd11..0000000
--- a/.github/workflows/codeLintGlobal.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-on:
- # Trigger the workflow on push or pull request,
- # but only for the main branch
- push:
- branches:
- - beta
- pull_request:
- branches:
- - beta
- - master
-
-name : 'Code Lint Global'
-
-jobs:
- run-linters:
- name: Test Linters
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out Git repository
- uses: actions/checkout@v3
-
- - name: Set up PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: "7.4"
- coverage: none
- tools: phpcs
-
- - name: Set up Python
- uses: actions/setup-python@v1
- with:
- python-version: 3.8
-
- - name: Set up Node.js
- uses: actions/setup-node@v1
- with:
- node-version: 14
-
- # ESLint and Prettier must be in `package.json`
- - name: Install Node.js dependencies
- run: npm i prettier
-
- - name: Install Python dependencies
- run: pip install flake8 black
-
- - name: Run linters
- uses: wearerequired/lint-action@v2
- with:
- php_codesniffer: false
- # Optional: Ignore warnings
- php_codesniffer_args: "-n --ignore-annotations ./core ./desktop ./plugin_info"
- flake8: true
- prettier: true
- prettier_extensions: css,html,js,json,jsx,md,sass,scss,ts,tsx,vue,yaml
- auto_fix: true
- prettier_auto_fix: true
- git_email: commit@jeedom.com
- git_name: 'JeedomBot lint Pretty'
- commit: false
- black: true
- black_auto_fix: true
diff --git a/.github/workflows/lint_Php73.yml b/.github/workflows/lint_Php73.yml
deleted file mode 100644
index e9f65cf..0000000
--- a/.github/workflows/lint_Php73.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name : 'Php 7.3'
-
-on:
- push:
- branches:
- - beta
- paths:
- - "**.php"
- pull_request:
- branches:
- - beta
- - master
- paths:
- - "**.php"
-
-jobs:
- run-linters:
- name: Run linters
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out Git repository
- uses: actions/checkout@v3
-
- - name: PHP syntax checker 7.3
- uses: prestashop/github-action-php-lint/7.3@v1
- with:
- folder-to-exclude: "! -path \"./3rdparty/*\""
diff --git a/.github/workflows/lint_Php74.yml b/.github/workflows/lint_Php74.yml
deleted file mode 100644
index e87f508..0000000
--- a/.github/workflows/lint_Php74.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name : 'Php 7.4'
-
-on:
- push:
- branches:
- - beta
- paths:
- - "**.php"
- pull_request:
- branches:
- - beta
- - master
- paths:
- - "**.php"
-
-jobs:
- run-linters:
- name: Run linters
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out Git repository
- uses: actions/checkout@v3
-
- - name: PHP syntax checker 7.4
- uses: prestashop/github-action-php-lint/7.4@v1
- with:
- folder-to-exclude: "! -path \"./3rdparty/*\""
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
deleted file mode 100644
index b6669dc..0000000
--- a/.github/workflows/php.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: "PHP"
-
-on:
- push:
- branches:
- - beta
- paths:
- - "**.php"
- pull_request:
- branches:
- - beta
- - master
- paths:
- - "**.php"
-
-jobs:
- phpcs:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: michaelw90/PHP-Lint@master
-
-
diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml
index 26d8687..08026e2 100644
--- a/.github/workflows/prettier.yml
+++ b/.github/workflows/prettier.yml
@@ -1,6 +1,5 @@
on:
- # Trigger the workflow on push or pull request,
- # but only for the main branch
+ # Create branch > prettier / this workflows create commit on branch prettier.
push:
branches:
- prettier
@@ -8,49 +7,8 @@ on:
branches:
- prettier
-name : 'Prettier'
+name : 'Prettier Plugin Jeedom'
jobs:
- run-linters:
- name: Test Linters
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out Git repository
- uses: actions/checkout@v3
-
- - name: Set up PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: "7.4"
- coverage: none
- tools: phpcs
-
- - name: Set up Python
- uses: actions/setup-python@v1
- with:
- python-version: 3.8
-
- - name: Set up Node.js
- uses: actions/setup-node@v1
- with:
- node-version: 14
-
- # ESLint and Prettier must be in `package.json`
- - name: Install Node.js dependencies
- run: npm i prettier
-
- - name: Install Python dependencies
- run: pip install black
-
- - name: Run linters
- uses: wearerequired/lint-action@v2
- with:
- prettier: true
- prettier_extensions: css,html,js,json,jsx,md,sass,scss,ts,tsx,vue,yaml
- auto_fix: true
- prettier_auto_fix: true
- git_email: commit@jeedom.com
- git_name: 'JeedomBot lint Pretty'
- black: true
- black_auto_fix: true
+ prettier:
+ uses: jeedom/workflows/.github/workflows/prettier.yml@main
diff --git a/.github/workflows/work.yml b/.github/workflows/work.yml
new file mode 100644
index 0000000..345021e
--- /dev/null
+++ b/.github/workflows/work.yml
@@ -0,0 +1,15 @@
+on:
+ # Workflows check plugin Jeedom
+ push:
+ branches:
+ - beta
+ pull_request:
+ branches:
+ - beta
+ - master
+
+name : 'Full Workflows Plugin Jeedom'
+
+jobs:
+ plugin:
+ uses: jeedom/workflows/.github/workflows/plugin.yml@main
diff --git a/3rdparty/rtsp-to-hls-copy.sh b/3rdparty/rtsp-to-hls-copy.sh
new file mode 100644
index 0000000..0a20aea
--- /dev/null
+++ b/3rdparty/rtsp-to-hls-copy.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+#[ $# -eq 0 ] && { echo "Usage: $0 rtsp://... <name>"; exit 1; }
+
+BASEDIR=$(dirname "$0")
+SOURCE="$1"
+DEST="$2"
+NAME=${2:-cctv}
+#ARCHIVE=${ARCHIVE:-archive}
+
+HLS_TIME=${HLS_TIME:-5}
+HLS_LIST_SIZE=${HLS_LIST_SIZE:-5}
+
+ffmpeg -rtsp_transport tcp -i "$SOURCE" \
+-f hls \
+-vsync 0 -copyts -vcodec copy -acodec copy \
+-tune zerolatency \
+-movflags frag_keyframe+empty_moov \
+-hls_flags delete_segments+append_list \
+-hls_init_time 1 \
+-hls_time $HLS_TIME \
+-hls_list_size $HLS_LIST_SIZE \
+-hls_base_url "segments/" \
+-hls_segment_filename ${BASEDIR}"/../data/segments/$NAME-%d.ts" \
+${BASEDIR}"/../data/$NAME.m3u8"
\ No newline at end of file
diff --git a/3rdparty/rtsp-to-hls-x264.sh b/3rdparty/rtsp-to-hls-x264.sh
new file mode 100644
index 0000000..c930606
--- /dev/null
+++ b/3rdparty/rtsp-to-hls-x264.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+#[ $# -eq 0 ] && { echo "Usage: $0 rtsp://... <name>"; exit 1; }
+
+BASEDIR=$(dirname "$0")
+SOURCE="$1"
+DEST="$2"
+NAME=${2:-cctv}
+#ARCHIVE=${ARCHIVE:-archive}
+
+HLS_TIME=${HLS_TIME:-5}
+HLS_LIST_SIZE=${HLS_LIST_SIZE:-5}
+
+ffmpeg -rtsp_transport tcp -i "$SOURCE" \
+-f hls \
+-vsync 0 -copyts -c:v libx264 -preset ultrafast -tune zerolatency -profile:v main \
+-c:a copy \
+-movflags frag_keyframe+empty_moov \
+-hls_flags delete_segments+append_list \
+-hls_init_time 1 \
+-hls_time $HLS_TIME \
+-hls_list_size $HLS_LIST_SIZE \
+-hls_base_url "segments/" \
+-hls_segment_filename ${BASEDIR}"/../data/segments/$NAME-%d.ts" \
+${BASEDIR}"/../data/$NAME.m3u8"
\ No newline at end of file
diff --git a/core/ajax/camera.ajax.php b/core/ajax/camera.ajax.php
index 5310519..dd995ca 100644
--- a/core/ajax/camera.ajax.php
+++ b/core/ajax/camera.ajax.php
@@ -31,7 +31,8 @@
if(!is_object($camera)){
throw new \Exception(__('Impossible de trouver la camera : ',__FILE__).init('id'));
}
- if(count(system::ps('rtsp-to-hls.sh.*'.$camera->getConfiguration('localApiKey'))) == 0){
+ $rtspScript = dirname(__FILE__) . '/../../3rdparty/rtsp-to-hls-' . ($camera->getConfiguration('encodeX264RTSP', 0) == 1 ? 'x264' : 'copy') . '.sh ';
+ if(count(system::ps('rtsp-to-hls-*.sh.*'.$camera->getConfiguration('localApiKey'))) == 0){
shell_exec('(ps ax || ps w) | grep ffmpeg.*'.$camera->getConfiguration('localApiKey').' | awk \'{print $2}\' | xargs sudo kill -9');
$replace = array(
'#username#' => urlencode($camera->getConfiguration('username')),
@@ -43,8 +44,8 @@
if (!file_exists(dirname(__FILE__) . '/../../data/segments')) {
mkdir(dirname(__FILE__) . '/../../data/segments', 0777, true);
}
- log::add('camera', 'debug', 'nohup '.dirname(__FILE__) . '/../../3rdparty/rtsp-to-hls.sh ' . trim(str_replace(array_keys($replace), $replace, $camera->getConfiguration('cameraStreamAccessUrl'))).' "' . $camera->getConfiguration('localApiKey') . '" > /dev/null 2>&1 &');
- exec('nohup ' .dirname(__FILE__) . '/../../3rdparty/rtsp-to-hls.sh ' . trim(str_replace(array_keys($replace), $replace, $camera->getConfiguration('cameraStreamAccessUrl'))).' "' . $camera->getConfiguration('localApiKey') . '" > /dev/null 2>&1 &');
+ log::add('camera', 'debug', 'nohup ' . $rtspScript . trim(str_replace(array_keys($replace), $replace, $camera->getConfiguration('cameraStreamAccessUrl'))).' "' . $camera->getConfiguration('localApiKey') . '" > /dev/null 2>&1 &');
+ exec('nohup ' . $rtspScript . trim(str_replace(array_keys($replace), $replace, $camera->getConfiguration('cameraStreamAccessUrl'))).' "' . $camera->getConfiguration('localApiKey') . '" > /dev/null 2>&1 &');
$i=0;
while(!file_exists(__DIR__.'/../../data/'.$camera->getConfiguration('localApiKey').'.m3u8')){
sleep(1);
@@ -56,72 +57,70 @@
}
$camera->setCache('lastStreamCall',strtotime('now'));
shell_exec(system::getCmdSudo().' find '.__DIR__.'/../../data/segments/'.$camera->getConfiguration('localApiKey').'-*.ts -mmin +5 -type f -exec rm -f {} \; 2>&1 > /dev/null');
- ajax::success();
- }
-
- if (!isConnect('admin')) {
- throw new Exception(__('401 - Accès non autorisé', __FILE__));
- }
-
-
-
- if (init('action') == 'addDiscoverCam') {
- camera::addDiscoverCam(json_decode(init('config'), true));
- ajax::success();
- }
-
- if (init('action') == 'removeRecord') {
- $file = init('file');
- $file = str_replace('..', '', $file);
- $record_dir = calculPath(config::byKey('recordDir', 'camera'));
- shell_exec('rm -rf ' . $record_dir . '/' . $file);
- ajax::success();
+ ajax::success();
+ }
+
+ if (init('action') == 'getCamera') {
+ if (init('object_id') == '') {
+ $object = jeeObject::byId($_SESSION['user']->getOptions('defaultDashboardObject'));
+ } else {
+ $object = jeeObject::byId(init('object_id'));
}
-
- if (init('action') == 'removeAllSnapshot') {
- $camera = camera::byId(init('id'));
- if (!is_object($camera)) {
- throw new Exception(__('Impossible de trouver la caméra : ' . init('id'), __FILE__));
- }
- $camera->removeAllSnapshot();
- ajax::success();
+ if (!is_object($object)) {
+ $object = jeeObject::rootObject();
}
-
- if (init('action') == 'getCamera') {
- if (init('object_id') == '') {
- $object = jeeObject::byId($_SESSION['user']->getOptions('defaultDashboardObject'));
- } else {
- $object = jeeObject::byId(init('object_id'));
- }
- if (!is_object($object)) {
- $object = jeeObject::rootObject();
- }
- $return = array();
- $return['eqLogics'] = array();
- if (init('object_id') == '') {
- foreach (jeeObject::all() as $object) {
- foreach ($object->getEqLogic(true, false, 'camera') as $camera) {
- $return['eqLogics'][] = $camera->toHtml(init('version'));
- }
- }
- } else {
+ $return = array();
+ $return['eqLogics'] = array();
+ if (init('object_id') == '') {
+ foreach (jeeObject::all() as $object) {
foreach ($object->getEqLogic(true, false, 'camera') as $camera) {
$return['eqLogics'][] = $camera->toHtml(init('version'));
}
- foreach (jeeObject::buildTree($object) as $child) {
- $cameras = $child->getEqLogic(true, false, 'camera');
- if (count($cameras) > 0) {
- foreach ($cameras as $camera) {
- $return['eqLogics'][] = $camera->toHtml(init('version'));
- }
+ }
+ } else {
+ foreach ($object->getEqLogic(true, false, 'camera') as $camera) {
+ $return['eqLogics'][] = $camera->toHtml(init('version'));
+ }
+ foreach (jeeObject::buildTree($object) as $child) {
+ $cameras = $child->getEqLogic(true, false, 'camera');
+ if (count($cameras) > 0) {
+ foreach ($cameras as $camera) {
+ $return['eqLogics'][] = $camera->toHtml(init('version'));
}
}
}
- ajax::success($return);
}
-
- throw new Exception(__('Aucune methode correspondante à : ', __FILE__) . init('action'));
- /* * *********Catch exeption*************** */
- } catch (Exception $e) {
- ajax::error(displayException($e), $e->getCode());
+ ajax::success($return);
+ }
+
+ if (!isConnect('admin')) {
+ throw new Exception(__('401 - Accès non autorisé', __FILE__));
}
+
+ if (init('action') == 'addDiscoverCam') {
+ camera::addDiscoverCam(json_decode(init('config'), true));
+ ajax::success();
+ }
+
+ if (init('action') == 'removeRecord') {
+ $file = init('file');
+ $file = str_replace('..', '', $file);
+ $record_dir = calculPath(config::byKey('recordDir', 'camera'));
+ shell_exec('rm -rf ' . $record_dir . '/' . $file);
+ ajax::success();
+ }
+
+ if (init('action') == 'removeAllSnapshot') {
+ $camera = camera::byId(init('id'));
+ if (!is_object($camera)) {
+ throw new Exception(__('Impossible de trouver la caméra : ' . init('id'), __FILE__));
+ }
+ $camera->removeAllSnapshot();
+ ajax::success();
+ }
+
+ throw new Exception(__('Aucune methode correspondante à : ', __FILE__) . init('action'));
+ /* * *********Catch exeption*************** */
+} catch (Exception $e) {
+ ajax::error(displayException($e), $e->getCode());
+}
diff --git a/core/class/camera.class.php b/core/class/camera.class.php
index c5654cd..85bdc6e 100644
--- a/core/class/camera.class.php
+++ b/core/class/camera.class.php
@@ -229,7 +229,7 @@ public static function cronHourly() {
}
}
- public static function cronDayly() {
+ public static function cronDaily() {
foreach (camera::byType('camera') as $camera) {
try {
shell_exec('(ps ax || ps w) | grep ffmpeg.*' . $camera->getConfiguration('localApiKey') . ' | awk \'{print $2}\' | xargs sudo kill -9');
@@ -338,7 +338,7 @@ public static function addDiscoverCam($_config) {
/* * *********************Methode d'instance************************* */
public function configOnvif() {
- try{
+ try {
$onvif = new Ponvif();
$onvif->setUsername($this->getConfiguration('username'));
$onvif->setPassword($this->getConfiguration('password'));
@@ -349,7 +349,7 @@ public function configOnvif() {
$this->setConfiguration('cameraStreamProfileToken', $sources[0][0]['profiletoken']); //save profiletoken for sending onvif ptz cmd
$this->setConfiguration('cameraStreamAccessUrl', $mediaUri);
} catch (Exception $e) {
- log::add('camera','error','[ONVIF] '.$e->getMessage());
+ log::add('camera', 'error', '[ONVIF] ' . $e->getMessage());
}
}
@@ -583,17 +583,22 @@ public function toHtml($_version = 'dashboard', $_fluxOnly = false) {
'#name#' => ($cmd->getDisplay('icon') != '') ? $cmd->getDisplay('icon') : $cmd->getName(),
);
$action .= template_replace($replaceCmd, getTemplate('core', $version, 'camera_action', 'camera')) . ' ';
+ if ($cmd->getDisplay('forceReturnLineAfter', 0) == 1) {
+ $action .= '
';
+ }
} else {
if ($cmd->getType() == 'info') {
$info .= $cmd->toHtml($_version);
+ if ($cmd->getDisplay('forceReturnLineAfter', 0) == 1) {
+ $info .= '';
+ }
} else {
$action .= $cmd->toHtml($_version);
+ if ($cmd->getDisplay('forceReturnLineAfter', 0) == 1) {
+ $action .= '';
+ }
}
}
-
- if ($cmd->getDisplay('forceReturnLineAfter', 0) == 1) {
- $action .= '
';
- }
}
}
}
@@ -608,12 +613,12 @@ public function toHtml($_version = 'dashboard', $_fluxOnly = false) {
);
$on = $this->getCmd(null, 'on');
$off = $this->getCmd(null, 'off');
- if (is_object($on)) {
+ if (is_object($on) && $on->getIsVisible() == 1) {
$replace['#cmd_on_id#'] = $on->getId();
} else {
$replace['#cmd_on_id#'] = '""';
}
- if (is_object($off)) {
+ if (is_object($off) && $off->getIsVisible() == 1) {
$replace['#cmd_off_id#'] = $off->getId();
} else {
$replace['#cmd_off_id#'] = '""';
@@ -957,12 +962,22 @@ public function export($_withCmd = true) {
}
public function getImage() {
+ if (method_exists($this, 'getCustomImage')) {
+ $customImage = $this->getCustomImage();
+ if ($customImage !== null) {
+ return $customImage;
+ }
+ }
if (file_exists(__DIR__ . '/../config/devices/' . self::getImgFilePath($this->getConfiguration('device')) . '.png')) {
return 'plugins/camera/core/config/devices/' . self::getImgFilePath($this->getConfiguration('device')) . '.png';
}
return 'plugins/camera/core/config/devices/' . self::getImgFilePath($this->getConfiguration('device')) . '.jpg';
}
+ public static function backupExclude() {
+ // retourne le répertoire des datas à ne pas enregistrer dans le backup Jeedom
+ return ['data'];
+ }
/* * **********************Getteur Setteur*************************** */
}
@@ -1005,19 +1020,20 @@ public function execute($_options = null) {
break;
}
$eqLogic = $this->getEqLogic();
- if ($this->getLogicalId() == 'recordCmd') {
+ $logicalId = $this->getLogicalId();
+ if ($logicalId === 'recordCmd') {
$eqLogic->recordCam($_options['slider']);
return true;
}
- if ($this->getLogicalId() == 'stopRecordCmd') {
+ if ($logicalId === 'stopRecordCmd') {
$eqLogic->stopRecord();
return true;
}
- if ($this->getLogicalId() == 'takeSnapshot') {
+ if ($logicalId === 'takeSnapshot') {
$eqLogic->takeSnapshot();
return true;
}
- if ($this->getLogicalId() == 'on') {
+ if ($logicalId === 'on') {
$cmd = cmd::byId(str_replace('#', '', $eqLogic->getConfiguration('commandOn')));
if (is_object(!$cmd)) {
throw new Exception(__('Impossible de trouver la commande ON', __FILE__));
@@ -1025,7 +1041,7 @@ public function execute($_options = null) {
$cmd->execCmd();
return true;
}
- if ($this->getLogicalId() == 'off') {
+ if ($logicalId === 'off') {
if ($eqLogic->getCmd(null, 'recordState')->execCmd() == 1) {
$eqLogic->stopCam();
return true;
@@ -1038,7 +1054,7 @@ public function execute($_options = null) {
$cmd->execCmd();
return true;
}
- if ($this->getLogicalId() == 'sendSnapshot') {
+ if ($logicalId === 'sendSnapshot') {
if (!isset($_options['title'])) {
$_options['title'] = '';
}
@@ -1048,70 +1064,70 @@ public function execute($_options = null) {
$eqLogic->recordCam($_options['title'], $_options['message']);
return true;
}
- if ($eqLogic->getConfiguration('device') == 'onvif') {
- $profileToken = $eqLogic->getConfiguration('cameraStreamProfileToken');
- $speedX = $eqLogic->getConfiguration('speed_x', 1);
- $speedY = $eqLogic->getConfiguration('speed_y', 1);
- $speedZ = $eqLogic->getConfiguration('speed_z', 1);
- $sleep = $eqLogic->getConfiguration('delay_stop', 0) * 1000;
-
- $onvif = new Ponvif();
- $onvif->setUsername($eqLogic->getConfiguration('username'));
- $onvif->setPassword($eqLogic->getConfiguration('password'));
- $onvif->setIPAddress($eqLogic->getConfiguration('ip') . ':' . $eqLogic->getConfiguration('onvif_port', 80));
- $onvif->initialize();
-
- $action = false;
-
- try {
- switch ($this->getLogicalId()) {
- case 'ptzleft':
- $onvif->ptz_ContinuousMove($profileToken, -$speedX, 0);
- $action = true;
- break;
- case 'ptzright':
- $onvif->ptz_ContinuousMove($profileToken, $speedX, 0);
- $action = true;
- break;
- case 'ptzup':
- $onvif->ptz_ContinuousMove($profileToken, 0, $speedY);
- $action = true;
- break;
- case 'ptzdown':
- $onvif->ptz_ContinuousMove($profileToken, 0, -$speedY);
- $action = true;
- break;
- case 'ptzzoomin':
- case 'ptzzoomout':
- $onvif->ptz_ContinuousMoveZoom($profileToken, ($logicalId === 'ptzzoomout') ? -$speedZ : $speedZ);
- $action = true;
- break;
- case 'ptzmovestop':
- $onvif->ptz_ContinuousMove($profileToken, 0, 0);
- break;
- case 'ptzstop':
- $onvif->ptz_Stop($profileToken, 'true', 'true');
- break;
- case 'ptzreboot':
- $onvif->core_SystemReboot();
- break;
- case 'gotohome':
- $onvif->ptz_GotoHomePosition($profileToken, 0, 0);
- break;
- }
-
- if ($action && strpos($request = $this->getConfiguration('stopCmdUrl'), '#') === 0) {
- usleep($sleep);
- $cmd = cmd::byId(str_replace('#', '', $request));
- if (is_object($cmd)) {
- $cmd->execCmd();
- }
- return true;
- }
- } catch (Exception $e) {
- log::add('camera', 'debug', 'onvif error reason for ' . $this->getLogicalId() . ' : ' . json_encode($onvif->getLastResponse()));
- }
- }
+ if ($eqLogic->getConfiguration('device') == 'onvif') {
+ $profileToken = $eqLogic->getConfiguration('cameraStreamProfileToken');
+ $speedX = $eqLogic->getConfiguration('speed_x', 1);
+ $speedY = $eqLogic->getConfiguration('speed_y', 1);
+ $speedZ = $eqLogic->getConfiguration('speed_z', 1);
+ $sleep = $eqLogic->getConfiguration('delay_stop', 0) * 1000;
+
+ $onvif = new Ponvif();
+ $onvif->setUsername($eqLogic->getConfiguration('username'));
+ $onvif->setPassword($eqLogic->getConfiguration('password'));
+ $onvif->setIPAddress($eqLogic->getConfiguration('ip') . ':' . $eqLogic->getConfiguration('onvif_port', 80));
+ $onvif->initialize();
+
+ $action = false;
+
+ try {
+ switch ($logicalId) {
+ case 'ptzleft':
+ $onvif->ptz_ContinuousMove($profileToken, -$speedX, 0);
+ $action = true;
+ break;
+ case 'ptzright':
+ $onvif->ptz_ContinuousMove($profileToken, $speedX, 0);
+ $action = true;
+ break;
+ case 'ptzup':
+ $onvif->ptz_ContinuousMove($profileToken, 0, $speedY);
+ $action = true;
+ break;
+ case 'ptzdown':
+ $onvif->ptz_ContinuousMove($profileToken, 0, -$speedY);
+ $action = true;
+ break;
+ case 'ptzzoomin':
+ case 'ptzzoomout':
+ $onvif->ptz_ContinuousMoveZoom($profileToken, ($logicalId === 'ptzzoomout') ? -$speedZ : $speedZ);
+ $action = true;
+ break;
+ case 'ptzmovestop':
+ $onvif->ptz_ContinuousMove($profileToken, 0, 0);
+ break;
+ case 'ptzstop':
+ $onvif->ptz_Stop($profileToken, 'true', 'true');
+ break;
+ case 'ptzreboot':
+ $onvif->core_SystemReboot();
+ break;
+ case 'gotohome':
+ $onvif->ptz_GotoHomePosition($profileToken, 0, 0);
+ break;
+ }
+
+ if ($action && strpos($request = $this->getConfiguration('stopCmdUrl'), '#') === 0) {
+ usleep($sleep);
+ $cmd = cmd::byId(str_replace('#', '', $request));
+ if (is_object($cmd)) {
+ $cmd->execCmd();
+ }
+ return true;
+ }
+ } catch (Exception $e) {
+ log::add('camera', 'debug', 'onvif error reason for ' . $logicalId . ' : ' . json_encode($onvif->getLastResponse()));
+ }
+ }
if (strpos($request, '#') === 0) {
$cmd = cmd::byId(str_replace('#', '', $request));
if (is_object($cmd)) {
diff --git a/core/config/devices/freebox/rocketcam.json b/core/config/devices/freebox/rocketcam.json
index 87f3a1d..520b648 100644
--- a/core/config/devices/freebox/rocketcam.json
+++ b/core/config/devices/freebox/rocketcam.json
@@ -2,8 +2,9 @@
"name" : "RocketCam",
"manufacturer" : "Freebox",
"configuration": {
+ "username" : "freeboxcam",
"urlStream": "\/img\/snapshot.cgi?size=4&quality=1",
- "cameraStreamAccessUrl" : "rtsp:\/\/#username#:#password#@#ip#\/img\/live",
+ "cameraStreamAccessUrl" : "http:\/\/#username#:#password#@#ip#\/img\/stream.m3u8",
"protocole": "http"
},
"commands": []
diff --git a/core/config/devices/reolink/reolink.trackMix.json b/core/config/devices/reolink/reolink.trackMix.json
new file mode 100644
index 0000000..4a9b585
--- /dev/null
+++ b/core/config/devices/reolink/reolink.trackMix.json
@@ -0,0 +1,108 @@
+{
+ "name" : "Reolink TrackMix",
+ "manufacturer" : "Reolink",
+ "buylink" : "https://reolink.com/fr/product/reolink-trackmix-poe/",
+ "configuration": {
+ "port": "",
+ "urlStream": "\/cgi-bin\/api.cgi?cmd=Snap&channel=0&user=#username#&password=#password#",
+ "cameraStreamAccessUrl" : "rtsp:\/\/#username#:#password#@#ip#\/h264Preview_01_sub",
+ "protocole": "https"
+ },
+ "commands": [
+ {
+ "eqType": "camera",
+ "name": "Motion alarme",
+ "type": "info",
+ "subType": "binary",
+ "isHistorized": "1",
+ "isVisible": "1",
+ "logicalId" : "motionDetectAlarm",
+ "display" : {
+ "invertBinary" : "1"
+ },
+ "template" : {
+ "dashboard" : "timePresence",
+ "mobile" : "timePresence"
+ },
+ "configuration": {
+ "repeatEventManagement": "never"
+ }
+ },
+ {
+ "eqType": "camera",
+ "name": "Motion Pet alarme",
+ "type": "info",
+ "subType": "binary",
+ "isHistorized": "0",
+ "isVisible": "1",
+ "logicalId" : "motionDogcatAlarm",
+ "display" : {
+ "invertBinary" : "1"
+ },
+ "template" : {
+ "dashboard" : "timePresence",
+ "mobile" : "timePresence"
+ },
+ "configuration": {
+ "repeatEventManagement": "never"
+ }
+ },
+ {
+ "eqType": "camera",
+ "name": "Motion People alarme",
+ "type": "info",
+ "subType": "binary",
+ "isHistorized": "0",
+ "isVisible": "1",
+ "logicalId" : "motionPeopleAlarm",
+ "display" : {
+ "invertBinary" : "1"
+ },
+ "template" : {
+ "dashboard" : "timePresence",
+ "mobile" : "timePresence"
+ },
+ "configuration": {
+ "repeatEventManagement": "never"
+ }
+ },
+ {
+ "eqType": "camera",
+ "name": "Motion Vehicle alarme",
+ "type": "info",
+ "subType": "binary",
+ "isHistorized": "0",
+ "isVisible": "1",
+ "logicalId" : "motionVehicleAlarm",
+ "display" : {
+ "invertBinary" : "1"
+ },
+ "template" : {
+ "dashboard" : "timePresence",
+ "mobile" : "timePresence"
+ },
+ "configuration": {
+ "repeatEventManagement": "never"
+ }
+ },
+ {
+ "eqType": "camera",
+ "name": "Motion Face alarme",
+ "type": "info",
+ "subType": "binary",
+ "isHistorized": "0",
+ "isVisible": "1",
+ "logicalId" : "motionFaceAlarm",
+ "display" : {
+ "invertBinary" : "1"
+ },
+ "template" : {
+ "dashboard" : "timePresence",
+ "mobile" : "timePresence"
+ },
+ "configuration": {
+ "repeatEventManagement": "never"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/core/config/devices/reolink/reolink.trackMix.php b/core/config/devices/reolink/reolink.trackMix.php
new file mode 100644
index 0000000..7ff46d6
--- /dev/null
+++ b/core/config/devices/reolink/reolink.trackMix.php
@@ -0,0 +1,46 @@
+getConfiguration('ip') . ':' . $_eqLogic->getConfiguration('port',80);
+ $url .= '/cgi-bin/api.cgi?cmd=GetMdState&user=' . $_eqLogic->getConfiguration('username') . '&password=' . $_eqLogic->getConfiguration('password');
+ $request_http = new com_http($url);
+ try {
+ $result = $request_http->exec();
+ $data = json_decode($result, true);
+ $cmd = $_eqLogic->getCmd('info', 'motionDetectAlarm');
+ if (is_object($cmd)){
+ if (isset($data[0])) {
+ if(array_key_exists("value", $data[0])) {
+ if(array_key_exists("state", $data[0]['value'])) {
+ $_eqLogic->checkAndUpdateCmd($cmd, $data[0]['value']['state']);
+ }
+ }
+ }
+ }
+ } catch (Exception $e) {
+ log::add('camera', 'debug', 'Erreur com_http ! (GetMdState)');
+ }
+
+ $url = $_eqLogic->getConfiguration('ip') . ':' . $_eqLogic->getConfiguration('port',80);
+ $url .= '/cgi-bin/api.cgi?cmd=GetAiState&user=' . $_eqLogic->getConfiguration('username') . '&password=' . $_eqLogic->getConfiguration('password');
+ $request_http = new com_http($url);
+ try {
+ $result = $request_http->exec();
+ $data = json_decode($result, true);
+ if (isset($data[0])) {
+ if(array_key_exists("value", $data[0])) {
+ foreach ($data[0]['value'] as $key => $value) {
+ if(is_array($value) && array_key_exists("support", $value) && $value['support'] == 1) { // return support or not
+ $cmd = $_eqLogic->getCmd('info', 'motion' . ucfirst(str_replace('_', '', $key)) . 'Alarm');
+ if (is_object($cmd) && array_key_exists("alarm_state", $value)) {
+ $_eqLogic->checkAndUpdateCmd($cmd, $value['alarm_state']);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception $e) {
+ log::add('camera', 'debug', 'Erreur com_http ! (GetAiState)');
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/core/config/devices/reolink/reolink.trackMix.png b/core/config/devices/reolink/reolink.trackMix.png
new file mode 100644
index 0000000..328a6ed
Binary files /dev/null and b/core/config/devices/reolink/reolink.trackMix.png differ
diff --git a/core/config/devices/ubiquiti/ubiquiti.UVC G5 Turret Ultra.json b/core/config/devices/ubiquiti/ubiquiti.UVC G5 Turret Ultra.json
new file mode 100644
index 0000000..e6dd62c
--- /dev/null
+++ b/core/config/devices/ubiquiti/ubiquiti.UVC G5 Turret Ultra.json
@@ -0,0 +1,9 @@
+{
+ "name": "Ubiquiti G5 Turret Ultra",
+ "manufacturer": "Ubiquiti",
+ "configuration": {
+ "urlStream": "\/snap.jpeg",
+ "protocole": "http"
+ },
+ "commands": []
+}
\ No newline at end of file
diff --git a/core/config/devices/ubiquiti/ubiquiti.UVC G5 Turret Ultra.png b/core/config/devices/ubiquiti/ubiquiti.UVC G5 Turret Ultra.png
new file mode 100644
index 0000000..c8e9935
Binary files /dev/null and b/core/config/devices/ubiquiti/ubiquiti.UVC G5 Turret Ultra.png differ
diff --git a/core/i18n/de_DE.json b/core/i18n/de_DE.json
index bd981b4..df2185b 100644
--- a/core/i18n/de_DE.json
+++ b/core/i18n/de_DE.json
@@ -119,8 +119,9 @@
"URL du flux": "Feed-URL",
"URL du flux, RTSP": "Stream-URL, RTSP",
"Stream du flux RTSP": "Stream des RTSP-Streams",
- "Option flux video": "Video-Stream-Option",
- "Previsualiser": "Vorschau",
+ "Convertir en x264 le flux RTSP": "Konvertieren Sie den RTSP-Stream in x264",
+ "Option flux vidéo": "Video-Stream-Option",
+ "Prévisualiser": "Vorschau",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "Vergessen Sie nicht, vor der Vorschau zu speichern, um Ihre Änderungen anzuzeigen",
"Position sur le panel": "Position auf dem Panel",
"Informations": "Information",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Video",
"Durée maximum d'un enregistrement (s)": "Maximale Dauer einer Aufnahme (n)",
- "Toujours faire une video": "Mach immer ein Video",
+ "Toujours faire une vidéo": "Mach immer ein Video",
"Nombre d'images par seconde de la vidéo": "Anzahl der Bilder pro Sekunde des Videos",
"Supprimer toutes les captures de la caméra": "Löschen Sie alle Kameraaufnahmen",
"Commande ON": "EIN-Befehl",
diff --git a/core/i18n/en_US.json b/core/i18n/en_US.json
index 75a7d4c..96cc2f1 100644
--- a/core/i18n/en_US.json
+++ b/core/i18n/en_US.json
@@ -119,8 +119,9 @@
"URL du flux": "Feed URL",
"URL du flux, RTSP": "URL of RTSP stream",
"Stream du flux RTSP": "Stream of RTSP stream",
- "Option flux video": "Video stream option",
- "Previsualiser": "Preview",
+ "Convertir en x264 le flux RTSP": "Convert RTSP stream to x264",
+ "Option flux vidéo": "Video stream option",
+ "Prévisualiser": "Preview",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "Don't forget to save to see your changes before previewing",
"Position sur le panel": "Positon on the panel",
"Informations": "Information",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Video",
"Durée maximum d'un enregistrement (s)": "Maximum duration of a recording (s)",
- "Toujours faire une video": "Always make a video",
+ "Toujours faire une vidéo": "Always make a video",
"Nombre d'images par seconde de la vidéo": "Number of frames per second of the video",
"Supprimer toutes les captures de la caméra": "Delete all camera captures",
"Commande ON": "ON command",
diff --git a/core/i18n/es_ES.json b/core/i18n/es_ES.json
index f2ec0ff..a5c75e2 100644
--- a/core/i18n/es_ES.json
+++ b/core/i18n/es_ES.json
@@ -119,8 +119,9 @@
"URL du flux": "URL del feed",
"URL du flux, RTSP": "URL de transmisión, RTSP",
"Stream du flux RTSP": "Flujo de flujo RTSP",
- "Option flux video": "Opción de transmisión de video",
- "Previsualiser": "Avance",
+ "Convertir en x264 le flux RTSP": "Convertir transmisión RTSP a x264",
+ "Option flux vidéo": "Opción de transmisión de video",
+ "Prévisualiser": "Avance",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "No olvide guardar para ver los cambios antes de obtener una vista previa",
"Position sur le panel": "Posición en el panel",
"Informations": "Información",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Vídeo",
"Durée maximum d'un enregistrement (s)": "Duración máxima de una grabación (s)",
- "Toujours faire une video": "Siempre haz un video",
+ "Toujours faire une vidéo": "Siempre haz un video",
"Nombre d'images par seconde de la vidéo": "Número de fotogramas por segundo del video",
"Supprimer toutes les captures de la caméra": "Eliminar todas las capturas de cámara",
"Commande ON": "Comando ON",
diff --git a/core/i18n/fr_FR.json b/core/i18n/fr_FR.json
index 7969041..58d7929 100644
--- a/core/i18n/fr_FR.json
+++ b/core/i18n/fr_FR.json
@@ -119,8 +119,9 @@
"URL du flux": "URL du flux",
"URL du flux, RTSP": "URL du flux, RTSP",
"Stream du flux RTSP": "Stream du flux RTSP",
- "Option flux video": "Option flux video",
- "Previsualiser": "Previsualiser",
+ "Convertir en x264 le flux RTSP": "Convertir en x264 le flux RTSP",
+ "Option flux vidéo": "Option flux vidéo",
+ "Prévisualiser": "Prévisualiser",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation",
"Position sur le panel": "Position sur le panel",
"Informations": "Informations",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Vidéo",
"Durée maximum d'un enregistrement (s)": "Durée maximum d'un enregistrement (s)",
- "Toujours faire une video": "Toujours faire une video",
+ "Toujours faire une vidéo": "Toujours faire une vidéo",
"Nombre d'images par seconde de la vidéo": "Nombre d'images par seconde de la vidéo",
"Supprimer toutes les captures de la caméra": "Supprimer toutes les captures de la caméra",
"Commande ON": "Commande ON",
diff --git a/core/i18n/id_ID.json b/core/i18n/id_ID.json
index 6843544..39fb2da 100644
--- a/core/i18n/id_ID.json
+++ b/core/i18n/id_ID.json
@@ -119,8 +119,9 @@
"URL du flux": "URL du flux",
"URL du flux, RTSP": "URL du flux, RTSP",
"Stream du flux RTSP": "Stream du flux RTSP",
- "Option flux video": "Option flux video",
- "Previsualiser": "Previsualiser",
+ "Convertir en x264 le flux RTSP": "Convertir en x264 le flux RTSP",
+ "Option flux vidéo": "Option flux video",
+ "Prévisualiser": "Previsualiser",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation",
"Position sur le panel": "Position sur le panel",
"Informations": "Informasi",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Vidéo",
"Durée maximum d'un enregistrement (s)": "Durée maximum d'un enregistrement (s)",
- "Toujours faire une video": "Toujours faire une video",
+ "Toujours faire une vidéo": "Toujours faire une video",
"Nombre d'images par seconde de la vidéo": "Nombre d'images par seconde de la vidéo",
"Supprimer toutes les captures de la caméra": "Supprimer toutes les captures de la caméra",
"Commande ON": "Commande ON",
diff --git a/core/i18n/it_IT.json b/core/i18n/it_IT.json
index 41abb4c..6634f04 100644
--- a/core/i18n/it_IT.json
+++ b/core/i18n/it_IT.json
@@ -119,8 +119,9 @@
"URL du flux": "URL du flux",
"URL du flux, RTSP": "URL du flux, RTSP",
"Stream du flux RTSP": "Stream du flux RTSP",
- "Option flux video": "Option flux video",
- "Previsualiser": "Previsualiser",
+ "Convertir en x264 le flux RTSP": "Convertir en x264 le flux RTSP",
+ "Option flux vidéo": "Option flux video",
+ "Prévisualiser": "Previsualiser",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation",
"Position sur le panel": "Position sur le panel",
"Informations": "Informazioni",
@@ -138,7 +139,7 @@
"Normal": "Normale",
"Vidéo": "Vidéo",
"Durée maximum d'un enregistrement (s)": "Durée maximum d'un enregistrement (s)",
- "Toujours faire une video": "Toujours faire une video",
+ "Toujours faire une vidéo": "Toujours faire une video",
"Nombre d'images par seconde de la vidéo": "Nombre d'images par seconde de la vidéo",
"Supprimer toutes les captures de la caméra": "Supprimer toutes les captures de la caméra",
"Commande ON": "Commande ON",
diff --git a/core/i18n/ja_JP.json b/core/i18n/ja_JP.json
index cd3b15c..58ffff6 100644
--- a/core/i18n/ja_JP.json
+++ b/core/i18n/ja_JP.json
@@ -119,8 +119,9 @@
"URL du flux": "URL du flux",
"URL du flux, RTSP": "URL du flux, RTSP",
"Stream du flux RTSP": "Stream du flux RTSP",
- "Option flux video": "Option flux video",
- "Previsualiser": "Previsualiser",
+ "Convertir en x264 le flux RTSP": "Convertir en x264 le flux RTSP",
+ "Option flux vidéo": "Option flux video",
+ "Prévisualiser": "Previsualiser",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation",
"Position sur le panel": "Position sur le panel",
"Informations": "情報",
@@ -138,7 +139,7 @@
"Normal": "ノーマル",
"Vidéo": "ビデオ",
"Durée maximum d'un enregistrement (s)": "Durée maximum d'un enregistrement (s)",
- "Toujours faire une video": "Toujours faire une video",
+ "Toujours faire une vidéo": "Toujours faire une video",
"Nombre d'images par seconde de la vidéo": "Nombre d'images par seconde de la vidéo",
"Supprimer toutes les captures de la caméra": "Supprimer toutes les captures de la caméra",
"Commande ON": "Commande ON",
diff --git a/core/i18n/pt_PT.json b/core/i18n/pt_PT.json
index 1abbf7f..314b32d 100644
--- a/core/i18n/pt_PT.json
+++ b/core/i18n/pt_PT.json
@@ -119,8 +119,9 @@
"URL du flux": "URL do feed",
"URL du flux, RTSP": "URL de fluxo, RTSP",
"Stream du flux RTSP": "Fluxo de fluxo RTSP",
- "Option flux video": "Opção de transmissão de vídeo",
- "Previsualiser": "Antevisão",
+ "Convertir en x264 le flux RTSP": "Converter fluxo RTSP para x264",
+ "Option flux vidéo": "Opção de transmissão de vídeo",
+ "Prévisualiser": "Antevisão",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "Não se esqueça de salvar para ver suas alterações antes de visualizar",
"Position sur le panel": "Posição no painel",
"Informations": "Informação",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Vídeo",
"Durée maximum d'un enregistrement (s)": "Duração máxima de uma gravação",
- "Toujours faire une video": "Sempre faça um vídeo",
+ "Toujours faire une vidéo": "Sempre faça um vídeo",
"Nombre d'images par seconde de la vidéo": "Número de quadros por segundo do vídeo",
"Supprimer toutes les captures de la caméra": "Excluir todas as capturas de câmera",
"Commande ON": "Comando ON",
diff --git a/core/i18n/ru_RU.json b/core/i18n/ru_RU.json
index a2f851d..c9b9858 100644
--- a/core/i18n/ru_RU.json
+++ b/core/i18n/ru_RU.json
@@ -119,8 +119,9 @@
"URL du flux": "URL du flux",
"URL du flux, RTSP": "URL du flux, RTSP",
"Stream du flux RTSP": "Stream du flux RTSP",
- "Option flux video": "Option flux video",
- "Previsualiser": "Previsualiser",
+ "Convertir en x264 le flux RTSP": "Convertir en x264 le flux RTSP",
+ "Option flux vidéo": "Option flux video",
+ "Prévisualiser": "Previsualiser",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation",
"Position sur le panel": "Position sur le panel",
"Informations": "Информация",
@@ -138,7 +139,7 @@
"Normal": "нормальный",
"Vidéo": "Vidéo",
"Durée maximum d'un enregistrement (s)": "Durée maximum d'un enregistrement (s)",
- "Toujours faire une video": "Toujours faire une video",
+ "Toujours faire une vidéo": "Toujours faire une video",
"Nombre d'images par seconde de la vidéo": "Nombre d'images par seconde de la vidéo",
"Supprimer toutes les captures de la caméra": "Supprimer toutes les captures de la caméra",
"Commande ON": "Commande ON",
diff --git a/core/i18n/tr.json b/core/i18n/tr.json
index 9ea6eef..7a692fb 100644
--- a/core/i18n/tr.json
+++ b/core/i18n/tr.json
@@ -119,8 +119,9 @@
"URL du flux": "URL du flux",
"URL du flux, RTSP": "URL du flux, RTSP",
"Stream du flux RTSP": "Stream du flux RTSP",
- "Option flux video": "Option flux video",
- "Previsualiser": "Previsualiser",
+ "Convertir en x264 le flux RTSP": "Convertir en x264 le flux RTSP",
+ "Option flux vidéo": "Option flux video",
+ "Prévisualiser": "Previsualiser",
"N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation": "N'oubliez pas de sauvegarder pour voir vos modifications avant la prévisualisation",
"Position sur le panel": "Position sur le panel",
"Informations": "Bilgiler",
@@ -138,7 +139,7 @@
"Normal": "Normal",
"Vidéo": "Vidéo",
"Durée maximum d'un enregistrement (s)": "Durée maximum d'un enregistrement (s)",
- "Toujours faire une video": "Toujours faire une video",
+ "Toujours faire une vidéo": "Toujours faire une video",
"Nombre d'images par seconde de la vidéo": "Nombre d'images par seconde de la vidéo",
"Supprimer toutes les captures de la caméra": "Supprimer toutes les captures de la caméra",
"Commande ON": "Commande ON",
diff --git a/core/template/dashboard/camera.html b/core/template/dashboard/camera.html
index 785f273..6210cfd 100644
--- a/core/template/dashboard/camera.html
+++ b/core/template/dashboard/camera.html
@@ -54,10 +54,12 @@
maxWidth:eqLogic_#id#.width() + 'px'
});
setTimeout(function(){
- Object.assign(document.querySelector('.eqLogic[data-eqLogic_id="#id#"] .directDisplay img').style, {
- maxHeight:(eqLogic_#id#.height() - 60) + 'px',
- maxWidth:eqLogic_#id#.width() + 'px'
- });
+ if (document.querySelector('.eqLogic[data-eqLogic_id="#id#"] .directDisplay img')) {
+ Object.assign(document.querySelector('.eqLogic[data-eqLogic_id="#id#"] .directDisplay img').style, {
+ maxHeight:(eqLogic_#id#.height() - 60) + 'px',
+ maxWidth:eqLogic_#id#.width() + 'px'
+ });
+ }
}, 1000);
eqLogic_#id#.off('resize').on('resize',function(){
diff --git a/core/template/dashboard/camera_stream.html b/core/template/dashboard/camera_stream.html
index a4054a9..c4df77f 100644
--- a/core/template/dashboard/camera_stream.html
+++ b/core/template/dashboard/camera_stream.html
@@ -68,6 +68,10 @@
video#id#.play();
});
});
+ hls#id#.on(Hls.Events.ERROR, function (event, data) {
+
+ console.log('error', event, data)
+ });
}else if (video#id#.canPlayType('application/vnd.apple.mpegurl')) {
video#id#.src = '#url#';
video#id#.addEventListener('loadedmetadata',function() {
@@ -80,4 +84,4 @@
}
});
-
+
\ No newline at end of file
diff --git a/core/template/dashboard/camera_stream_only.html b/core/template/dashboard/camera_stream_only.html
index 31a572d..70a26c0 100644
--- a/core/template/dashboard/camera_stream_only.html
+++ b/core/template/dashboard/camera_stream_only.html
@@ -47,4 +47,4 @@
}
});
-
+
\ No newline at end of file
diff --git a/desktop/modal/camera.displayImage.php b/desktop/modal/camera.displayImage.php
index 1b5b3ac..c4a63e2 100644
--- a/desktop/modal/camera.displayImage.php
+++ b/desktop/modal/camera.displayImage.php
@@ -8,4 +8,4 @@
if (strpos(init('src'), 'camera') === false) {
throw new Exception('{{401 - Accès non autorisé}}');
}
-echo '
';
+echo '
';
diff --git a/desktop/modal/camera.displayVideo.php b/desktop/modal/camera.displayVideo.php
index 9379d45..e43ba9a 100644
--- a/desktop/modal/camera.displayVideo.php
+++ b/desktop/modal/camera.displayVideo.php
@@ -2,13 +2,13 @@
if (!isConnect()) {
throw new Exception('{{401 - Accès non autorisé}}');
}
-if (!substr_compare(init('src'), '.mp4', -strlen('.mp4')) !== 0) {
+if (substr_compare(init('src'), '.mp4', -strlen('.mp4')) !== 0) {
throw new Exception('{{401 - Accès non autorisé}}');
}
if (strpos(init('src'), 'camera') === false) {
throw new Exception('{{401 - Accès non autorisé}}');
}
echo '';
diff --git a/desktop/modal/camera.history.php b/desktop/modal/camera.history.php
index 3719990..33e1ae7 100644
--- a/desktop/modal/camera.history.php
+++ b/desktop/modal/camera.history.php
@@ -50,20 +50,25 @@
echo '';
krsort($file);
foreach ($file as $time => $filename) {
- $fontType = 'fas-camera';
+ $fontType = 'fa-camera';
if (strpos($filename, '.mp4')) {
- $fontType = 'fas-video-camera';
+ $fontType = 'fa-video';
$i++;
}
- echo '
';
- echo '
' . str_replace('-', ':', $time) . '';
+ echo '
';
+ echo '
' . str_replace('-', ':', $time) . '';
if (strpos($filename, '.mp4')) {
- echo '
';
+ echo '
';
} else {
- echo '
 . ')
';
+ echo '
 . ')
';
}
- echo '
';
- echo ' ';
+ echo '
';
+ echo '';
+ echo ' ';
+ if (strpos($filename, '.mp4')) {
+ echo ' ';
+ }
+ echo '';
echo '
';
}
echo '
';
@@ -78,7 +83,7 @@
$('#md_modal2').dialog({
title: "Image"
});
- $('#md_modal2').load('index.php?v=d&plugin=camera&modal=camera.displayImage&src=' + $(this).attr('src')).dialog('open');
+ $('#md_modal2').load('index.php?v=d&plugin=camera&modal=camera.displayImage&src=' + $(this).attr('data-src')).dialog('open');
});
$('.displayVideo').on('click', function() {
$('#md_modal2').dialog({
diff --git a/desktop/modal/health.php b/desktop/modal/health.php
index 93e1b6d..114c7a5 100644
--- a/desktop/modal/health.php
+++ b/desktop/modal/health.php
@@ -44,8 +44,8 @@
getIsEnable()) ? '' : 'disableCard';
- if (file_exists(dirname(__FILE__) . '/../../core/config/devices/' . $eqLogic->getConfiguration('device') . '.jpg')) {
- $img = '
 . '.jpg)
';
+ if ($eqLogic->getConfiguration('device') != "" && camera::getImgFilePath($eqLogic->getConfiguration('device')) !== false) {
+ $img = '
) . ')
';
} else {
$img = '
 . ')
';
}
@@ -75,12 +75,12 @@
} else {
echo '
' . $framerate . '/s | ';
}
-
- echo '
' . $eqLogic->getConfiguration('refreshDelaySlow',1) . '/s | ';
- echo '
' . $eqLogic->getConfiguration('refreshDelayFast',1) . '/s | ';
+
+ echo '
' . $eqLogic->getConfiguration('refreshDelaySlow', 1) . '/s | ';
+ echo '
' . $eqLogic->getConfiguration('refreshDelayFast', 1) . '/s | ';
echo '
' . $eqLogic->getConfiguration('maxReccordTime') . 's | ';
echo '
' . $eqLogic->getConfiguration('createtime') . ' | ';
}
?>
-
+
\ No newline at end of file
diff --git a/desktop/php/camera.php b/desktop/php/camera.php
index 14d74ba..676618c 100644
--- a/desktop/php/camera.php
+++ b/desktop/php/camera.php
@@ -48,18 +48,17 @@
echo '
';
foreach ($eqLogics as $eqLogic) {
$opacity = ($eqLogic->getIsEnable()) ? '' : 'disableCard';
- echo '
';
+ echo '
';
if ($eqLogic->getConfiguration('device') != "" && camera::getImgFilePath($eqLogic->getConfiguration('device')) !== false) {
- echo '
) . ')
';
- }
- else {
+ echo '
) . ')
';
+ } else {
echo '
 . ')
';
}
echo '
';
echo '
' . $eqLogic->getHumanName(true, true) . '';
echo '
';
if ($eqLogic->getConfiguration('ip', '') != '') {
- echo ''.$eqLogic->getConfiguration('ip').'';
+ echo '' . $eqLogic->getConfiguration('ip') . '';
}
echo ($eqLogic->getIsVisible() == 1) ? '' : '';
echo '';
@@ -214,13 +213,19 @@
+
+
-
-
-
-
{{Si votre caméra n'est pas dans la liste vous pouvez trouver}}
{{ici}} {{les informations de configuration pour pas mal de camera}}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-