Merge branch 'dev' into 'master'
Tabantha Frontier See merge request Shinobi-Systems/Shinobi!49merge-requests/55/head^2
commit
8bccd65fa1
|
@ -27,7 +27,7 @@ if [ ! -e "./super.json" ]; then
|
|||
fi
|
||||
echo "Shinobi - Run yum update"
|
||||
sudo yum update -y
|
||||
sudo yum install make -y
|
||||
sudo yum install make zip -y
|
||||
echo "============="
|
||||
echo "Shinobi - Do you want to Install FFMPEG?"
|
||||
echo "(y)es or (N)o"
|
||||
|
@ -143,21 +143,14 @@ if [ "$mysqlDefaultData" = "y" ] || [ "$mysqlDefaultData" = "Y" ]; then
|
|||
echo "====================================="
|
||||
echo "====================================="
|
||||
fi
|
||||
if [ ! "$sqliteormariadb" = "M" ] && [ ! "$sqliteormariadb" = "m" ]; then
|
||||
echo "====================================="
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "====================================="
|
||||
echo "|| Login with the Superuser and create a new user!!"
|
||||
echo "||==================================="
|
||||
echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser."
|
||||
echo "||==================================="
|
||||
echo "|| Default Superuser : admin@shinobi.video"
|
||||
echo "|| Default Password : admin"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
else
|
||||
echo "+=================================+"
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "|| Access the main Shinobi panel at http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080 in your web browser."
|
||||
echo "+=================================+"
|
||||
fi
|
||||
echo "====================================="
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "====================================="
|
||||
echo "|| Login with the Superuser and create a new user!!"
|
||||
echo "||==================================="
|
||||
echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser."
|
||||
echo "||==================================="
|
||||
echo "|| Default Superuser : admin@shinobi.video"
|
||||
echo "|| Default Password : admin"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Install prerequisites
|
||||
DIR=`dirname $0`
|
||||
INSTALLERS_DIR="$DIR"
|
||||
echo "-----------------------------------"
|
||||
if ! [ -x "$(command -v opencv_version)" ]; then
|
||||
echo "Installing OpenCV"
|
||||
dos2unix $INSTALLERS_DIR/opencv-cuda.sh
|
||||
sh $INSTALLERS_DIR/opencv-cuda.sh
|
||||
else
|
||||
echo "OpenCV found... : $(opencv_version)"
|
||||
fi
|
||||
# this includes all the ones missing from OpenALPR's guide.
|
||||
sudo apt install libtesseract-dev git cmake build-essential libleptonica-dev -y
|
||||
sudo apt install liblog4cplus-dev libcurl3-dev -y
|
||||
sudo apt install libleptonica-dev -y
|
||||
sudo apt install libcurl4-openssl-dev -y
|
||||
sudo apt install liblog4cplus-dev -y
|
||||
sudo apt install beanstalkd -y
|
||||
sudo apt install openjdk-8-jdk -y
|
||||
|
||||
# Clone the latest code from GitHub
|
||||
git clone https://github.com/openalpr/openalpr.git
|
||||
|
||||
# Setup the build directory
|
||||
cd openalpr/src
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# setup the compile environment
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_INSTALL_SYSCONFDIR:PATH=/etc ..
|
||||
|
||||
# compile the library
|
||||
make
|
||||
|
||||
# Install the binaries/libraries to your local system (prefix is /usr)
|
||||
sudo make install
|
||||
|
||||
# Test the library
|
||||
wget http://plates.openalpr.com/h786poj.jpg -O lp.jpg
|
||||
alpr lp.jpg
|
||||
rm lp.jpg
|
|
@ -1,4 +1,14 @@
|
|||
# Install prerequisites
|
||||
DIR=`dirname $0`
|
||||
INSTALLERS_DIR="$DIR"
|
||||
echo "-----------------------------------"
|
||||
if ! [ -x "$(command -v opencv_version)" ]; then
|
||||
echo "Installing OpenCV"
|
||||
dos2unix $INSTALLERS_DIR/opencv-cuda.sh
|
||||
sh $INSTALLERS_DIR/opencv-cuda.sh
|
||||
else
|
||||
echo "OpenCV found... : $(opencv_version)"
|
||||
fi
|
||||
# this includes all the ones missing from OpenALPR's guide.
|
||||
sudo apt install libtesseract-dev git cmake build-essential libleptonica-dev -y
|
||||
sudo apt install liblog4cplus-dev libcurl3-dev -y
|
||||
|
@ -28,4 +38,4 @@ sudo make install
|
|||
# Test the library
|
||||
wget http://plates.openalpr.com/h786poj.jpg -O lp.jpg
|
||||
alpr lp.jpg
|
||||
rm lp.jpg
|
||||
rm lp.jpg
|
||||
|
|
|
@ -115,15 +115,6 @@ sudo chmod -R 755 .
|
|||
touch INSTALL/installed.txt
|
||||
dos2unix /home/Shinobi/INSTALL/shinobi
|
||||
ln -s /home/Shinobi/INSTALL/shinobi /usr/bin/shinobi
|
||||
if [ "$mysqlDefaultData" = "y" ] || [ "$mysqlDefaultData" = "Y" ]; then
|
||||
echo "=====================================" > INSTALL/installed.txt
|
||||
echo "======= Login Credentials =======" >> INSTALL/installed.txt
|
||||
echo "|| Username : $userEmail" >> INSTALL/installed.txt
|
||||
echo "|| Password : $userPasswordPlain" >> INSTALL/installed.txt
|
||||
echo "|| API Key : $apiKey" >> INSTALL/installed.txt
|
||||
echo "=====================================" >> INSTALL/installed.txt
|
||||
echo "=====================================" >> INSTALL/installed.txt
|
||||
fi
|
||||
echo "Shinobi - Start Shinobi and set to start on boot?"
|
||||
echo "(y)es or (N)o"
|
||||
read startShinobi
|
||||
|
@ -134,31 +125,14 @@ if [ "$startShinobi" = "y" ] || [ "$startShinobi" = "Y" ]; then
|
|||
sudo pm2 save
|
||||
sudo pm2 list
|
||||
fi
|
||||
if [ "$mysqlDefaultData" = "y" ] || [ "$mysqlDefaultData" = "Y" ]; then
|
||||
echo "details written to INSTALL/installed.txt"
|
||||
echo "====================================="
|
||||
echo "======= Login Credentials ======="
|
||||
echo "|| Username : $userEmail"
|
||||
echo "|| Password : $userPasswordPlain"
|
||||
echo "|| API Key : $apiKey"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
fi
|
||||
if [ ! "$sqliteormariadb" = "M" ] && [ ! "$sqliteormariadb" = "m" ]; then
|
||||
echo "====================================="
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "====================================="
|
||||
echo "|| Login with the Superuser and create a new user!!"
|
||||
echo "||==================================="
|
||||
echo "|| Open http://$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1):8080/super in your web browser."
|
||||
echo "||==================================="
|
||||
echo "|| Default Superuser : admin@shinobi.video"
|
||||
echo "|| Default Password : admin"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
else
|
||||
echo "+=================================+"
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "|| Access the main Shinobi panel at http://$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1):8080 in your web browser."
|
||||
echo "+=================================+"
|
||||
fi
|
||||
echo "====================================="
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "====================================="
|
||||
echo "|| Login with the Superuser and create a new user!!"
|
||||
echo "||==================================="
|
||||
echo "|| Open http://$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1):8080/super in your web browser."
|
||||
echo "||==================================="
|
||||
echo "|| Default Superuser : admin@shinobi.video"
|
||||
echo "|| Default Password : admin"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
|
|
114
INSTALL/shinobi
114
INSTALL/shinobi
|
@ -1,30 +1,68 @@
|
|||
#!/bin/bash
|
||||
installationDirectory="/home/Shinobi"
|
||||
if [ ! "$1" ]; then
|
||||
if [ ! -e "/etc/shinobisystems/path.txt" ]; then
|
||||
installationDirectory="/home/Shinobi"
|
||||
else
|
||||
installationDirectory=$(cat /etc/shinobisystems/cctv.txt)
|
||||
fi
|
||||
cd $installationDirectory
|
||||
currentBuild=$(git show --oneline -s)
|
||||
gitOrigin=$(git remote show origin)
|
||||
splitBuildString=($currentBuild)
|
||||
currentCommitNumber=${splitBuildString[0]}
|
||||
if [[ $gitOrigin == *'ShinobiCE'* ]]; then
|
||||
repo="CE"
|
||||
else
|
||||
repo="Pro"
|
||||
fi
|
||||
if [[ $@ == *'help'* ]] || [ ! "$1" ]; then
|
||||
echo "========================================================="
|
||||
echo "==!! Shinobi : The Open Source CCTV and NVR Solution !!=="
|
||||
echo "========================================================="
|
||||
echo "You are missing function parameters."
|
||||
echo "Example : shinobi [command] .."
|
||||
echo "Example : shinobi flush restart logs"
|
||||
if [ ! "$1" ]; then
|
||||
echo "You are missing function parameters."
|
||||
echo "Example : shinobi [command] .."
|
||||
echo "Example : shinobi flush restart logs"
|
||||
else
|
||||
echo "Hello there! if you need support come on over"
|
||||
echo "to the Shinobi Community Chat! :)"
|
||||
echo "https://discordapp.com/invite/mdhmvuH/"
|
||||
fi
|
||||
echo "========================================================="
|
||||
echo "Your available options for COMMAND are as follows"
|
||||
echo "========================================================="
|
||||
echo "| start or s :"
|
||||
echo "| start :"
|
||||
echo "|--> Start camera.js and cron.js under PM2 (Process Manager)"
|
||||
echo "-"
|
||||
echo "| restart or r :"
|
||||
echo "| restart :"
|
||||
echo "|--> Restart all processes running under the PM2 daemon."
|
||||
echo "-"
|
||||
echo "| stop, exit, or e :"
|
||||
echo "| stop, exit :"
|
||||
echo "|--> Stop all processes running under the PM2 daemon."
|
||||
echo "-"
|
||||
echo "| version :"
|
||||
echo "|--> get version of your current build by git."
|
||||
echo "-"
|
||||
echo "| logs :"
|
||||
echo "|--> Get PM2 log stream with last 100 lines."
|
||||
echo "-"
|
||||
echo "| clear, flush, or f :"
|
||||
echo "| update :"
|
||||
echo "|--> Update via Git."
|
||||
echo "-"
|
||||
echo "| getMaster :"
|
||||
echo "|--> Switch to the Master Branch (For Pro Repo only)."
|
||||
echo "-"
|
||||
echo "| getDev :"
|
||||
echo "|--> Switch to the Development Branch (For Pro Repo only)."
|
||||
echo "-"
|
||||
echo "| clear, flush :"
|
||||
echo "|--> Clear all PM2 logs."
|
||||
echo "-"
|
||||
echo "| bootupEnable :"
|
||||
echo "|--> Start Shinobi on OS reboot."
|
||||
echo "-"
|
||||
echo "| bootupDisable :"
|
||||
echo "|--> Disable starting Shinobi on OS reboot."
|
||||
echo "-"
|
||||
echo "| kill :"
|
||||
echo "|--> Stop the entire PM2 daemon."
|
||||
fi
|
||||
|
@ -34,7 +72,8 @@ fi
|
|||
if [[ $@ == *'restart'* ]]; then
|
||||
proccessAlive=$(pm2 list | grep camera)
|
||||
if [ "$proccessAlive" ]; then
|
||||
pm2 restart all
|
||||
pm2 restart $installationDirectory/camera.js
|
||||
pm2 restart $installationDirectory/cron.js
|
||||
else
|
||||
echo "Shinobi process is not running."
|
||||
fi
|
||||
|
@ -58,11 +97,64 @@ fi
|
|||
if [[ $@ == *'stop'* ]] || [[ $@ == *'exit'* ]]; then
|
||||
proccessAlive=$(pm2 list | grep camera)
|
||||
if [ "$proccessAlive" ]; then
|
||||
pm2 kill
|
||||
pm2 stop $installationDirectory/camera.js
|
||||
pm2 stop $installationDirectory/cron.js
|
||||
else
|
||||
echo "Shinobi process is not running."
|
||||
fi
|
||||
fi
|
||||
if [[ $@ == *'version'* ]]; then
|
||||
echo "Build ID : $currentCommitNumber"
|
||||
if [[ $repo == "Pro" ]]; then
|
||||
echo "Repository : Shinobi Pro"
|
||||
else
|
||||
echo "Repository : Shinobi CE"
|
||||
fi
|
||||
echo $currentBuild
|
||||
fi
|
||||
if [[ $@ == *'bootupEnable'* ]] || [[ $@ == *'bootupenable'* ]]; then
|
||||
pm2 startup
|
||||
pm2 save
|
||||
fi
|
||||
if [[ $@ == *'bootupDisable'* ]] || [[ $@ == *'bootupdisable'* ]]; then
|
||||
pm2 unstartup
|
||||
pm2 save
|
||||
fi
|
||||
if [[ $@ == *'getDev'* ]] || [[ $@ == *'getdev'* ]]; then
|
||||
if [[ $repo == "Pro" ]]; then
|
||||
git checkout dev
|
||||
echo "Shinobi - Restart Shinobi to make the changes take affect."
|
||||
else
|
||||
echo "Shinobi - Cannot use \"getDev\" with Shinobi CE"
|
||||
fi
|
||||
fi
|
||||
if [[ $@ == *'getMaster'* ]] || [[ $@ == *'getmaster'* ]]; then
|
||||
if [[ $repo == "Pro" ]]; then
|
||||
git checkout master
|
||||
echo "Shinobi - Restart Shinobi to make the changes take affect."
|
||||
else
|
||||
echo "Shinobi - Cannot use \"getMaster\" with Shinobi CE"
|
||||
fi
|
||||
fi
|
||||
if [[ $@ == *'update'* ]]; then
|
||||
echo "============="
|
||||
echo "Shinobi - Are you sure you want to update? This will restart Shinobi."
|
||||
echo "(y)es or (N)o"
|
||||
read updateshinobi
|
||||
if [ "$updateshinobi" = "y" ] || [ "$updateshinobi" = "Y" ]; then
|
||||
echo "Beginning Update Process..."
|
||||
pm2 stop $installationDirectory/camera.js
|
||||
pm2 stop $installationDirectory/cron.js
|
||||
npm install --unsafe-perm
|
||||
npm audit fix --force
|
||||
git reset --hard
|
||||
git pull
|
||||
pm2 start $installationDirectory/camera.js
|
||||
pm2 start $installationDirectory/cron.js
|
||||
else
|
||||
echo "Cancelled Update Process."
|
||||
fi
|
||||
fi
|
||||
if [[ $@ == *'kill'* ]]; then
|
||||
pm2 kill
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
var fs = require('fs');
|
||||
var moment = require('moment');
|
||||
var exec = require('child_process').exec;
|
||||
var execSync = require('child_process').execSync;
|
||||
s = {
|
||||
isWin: (process.platform === 'win32' || process.platform === 'win64'),
|
||||
mainDirectory: __dirname.split('/INSTALL')[0]
|
||||
}
|
||||
var createTerminalCommands = function(callback){
|
||||
var next = function(){
|
||||
if(callback)callback()
|
||||
}
|
||||
if(!s.isWin){
|
||||
var etcPath = '/etc/shinobisystems/'
|
||||
console.log('Creating "' + etcPath + '"...')
|
||||
var createPathFile = function(){
|
||||
var pathTxt = etcPath + 'cctv.txt'
|
||||
console.log('Creating "' + pathTxt + '"...')
|
||||
fs.writeFile(pathTxt,s.mainDirectory,function(err){
|
||||
if(err)console.log(err)
|
||||
fs.chmod(pathTxt,0o777,function(err){
|
||||
if(err)console.log(err)
|
||||
console.log('Linking "' + s.mainDirectory + '/INSTALL/shinobi" to "/usr/bin/shinobi"...')
|
||||
fs.symlink(s.mainDirectory + '/INSTALL/shinobi', '/usr/bin/shinobi', next)
|
||||
console.log('You can now use `shinobi` in terminal.')
|
||||
})
|
||||
})
|
||||
}
|
||||
fs.stat(etcPath,function(err,stat){
|
||||
if(!err && stat){
|
||||
createPathFile()
|
||||
}else{
|
||||
fs.mkdir(etcPath,createPathFile)
|
||||
}
|
||||
})
|
||||
}else{
|
||||
//no commands for windows yet
|
||||
next()
|
||||
}
|
||||
}
|
||||
createTerminalCommands()
|
|
@ -30,12 +30,17 @@ if [ ! -e "./super.json" ]; then
|
|||
echo "* You can edit these settings in \"super.json\" located in the Shinobi directory."
|
||||
sudo cp super.sample.json super.json
|
||||
fi
|
||||
if ! [ -x "$(command -v ifconfig)" ]; then
|
||||
echo "============="
|
||||
echo "Shinobi - Installing Net-Tools"
|
||||
sudo apt install net-tools -y
|
||||
fi
|
||||
if ! [ -x "$(command -v node)" ]; then
|
||||
echo "============="
|
||||
echo "Shinobi - Installing Node.js"
|
||||
wget https://deb.nodesource.com/setup_9.x
|
||||
chmod +x setup_9.x
|
||||
./setup_9.x
|
||||
wget https://deb.nodesource.com/setup_8.x
|
||||
chmod +x setup_8.x
|
||||
./setup_8.x
|
||||
sudo apt install nodejs -y
|
||||
else
|
||||
echo "Node.js Found..."
|
||||
|
@ -44,7 +49,7 @@ fi
|
|||
if ! [ -x "$(command -v npm)" ]; then
|
||||
sudo apt install npm -y
|
||||
fi
|
||||
sudo apt install make -y
|
||||
sudo apt install make zip -y
|
||||
if ! [ -x "$(command -v ffmpeg)" ]; then
|
||||
if [ "$getubuntuversion" = "16" ] || [ "$getubuntuversion" < "16" ]; then
|
||||
echo "============="
|
||||
|
@ -132,21 +137,14 @@ if [ "$startShinobi" = "y" ] || [ "$startShinobi" = "y" ]; then
|
|||
sudo pm2 save
|
||||
sudo pm2 list
|
||||
fi
|
||||
if [ ! "$sqliteormariadb" = "M" ] && [ ! "$sqliteormariadb" = "m" ]; then
|
||||
echo "====================================="
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "====================================="
|
||||
echo "|| Login with the Superuser and create a new user!!"
|
||||
echo "||==================================="
|
||||
echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser."
|
||||
echo "||==================================="
|
||||
echo "|| Default Superuser : admin@shinobi.video"
|
||||
echo "|| Default Password : admin"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
else
|
||||
echo "+=================================+"
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "|| Access the main Shinobi panel at http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080 in your web browser."
|
||||
echo "+=================================+"
|
||||
fi
|
||||
echo "====================================="
|
||||
echo "||===== Install Completed =====||"
|
||||
echo "====================================="
|
||||
echo "|| Login with the Superuser and create a new user!!"
|
||||
echo "||==================================="
|
||||
echo "|| Open http://$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'):8080/super in your web browser."
|
||||
echo "||==================================="
|
||||
echo "|| Default Superuser : admin@shinobi.video"
|
||||
echo "|| Default Password : admin"
|
||||
echo "====================================="
|
||||
echo "====================================="
|
||||
|
|
|
@ -26,7 +26,9 @@ loadLib('codeTester')(s,config,lang,io)
|
|||
//basic functions
|
||||
loadLib('basic')(s,config)
|
||||
//video processing engine
|
||||
loadLib('ffmpeg')(s,config,function(){
|
||||
loadLib('ffmpeg')(s,config,function(ffmpeg){
|
||||
//ffmpeg coProcessor
|
||||
loadLib('ffmpegCoProcessor')(s,config,lang,ffmpeg)
|
||||
//database connection : mysql, sqlite3..
|
||||
loadLib('sql')(s,config)
|
||||
//working directories : videos, streams, fileBin..
|
||||
|
@ -67,6 +69,8 @@ loadLib('ffmpeg')(s,config,function(){
|
|||
loadLib('notification')(s,config,lang)
|
||||
//custom module loader
|
||||
loadLib('customAutoLoad')(s,config,lang,app,io)
|
||||
//scheduling engine
|
||||
loadLib('scheduler')(s,config,lang,app,io)
|
||||
//on-start actions, daemon(s) starter
|
||||
loadLib('startup')(s,config,lang)
|
||||
})
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
"API": "API",
|
||||
"ONVIF": "ONVIF",
|
||||
"FFprobe": "Probe",
|
||||
"Monitor States": "Monitor States",
|
||||
"Schedule": "Schedule",
|
||||
"Schedules": "Schedules",
|
||||
"Monitor States and Schedules": "Monitor States and Schedules",
|
||||
"Filters": "Filters",
|
||||
"Full URL Path": "Full URL Path",
|
||||
"Logs": "Logs",
|
||||
|
@ -116,6 +120,8 @@
|
|||
"Can View Videos and Events": "Can View Videos and Events",
|
||||
"Can Delete Videos and Events": "Can Delete Videos and Events",
|
||||
"Saved Filters": "Saved Filters",
|
||||
"Saved Presets": "Saved Presets",
|
||||
"Saved Schedules": "Saved Schedules",
|
||||
"Filter Name": "Filter Name",
|
||||
"Find Where": "Find Where",
|
||||
"Reason": "Reason",
|
||||
|
@ -288,9 +294,15 @@
|
|||
"DeleteMonitorText": "Do you want to delete this monitor? You cannot recover it. You can choose for the files to remain in the filesystem. If you choose to recreate a monitor with the same ID the videos and events will become visible in the dashboard.",
|
||||
"DeleteMonitorsText": "Do you want to delete these monitors? You cannot recover them. You can choose to keep the files for these IDs in the filesystem. If you choose to recreate a monitor with one of the IDs the videos and events will become visible in the dashboard.",
|
||||
"Invalid JSON": "Invalid JSON",
|
||||
"Invalid Data": "Invalid Data",
|
||||
"Name cannot be empty.": "Name cannot be empty.",
|
||||
"Start Time cannot be empty.": "Start Time cannot be empty.",
|
||||
"Must be atleast one row": "Must be atleast one row",
|
||||
"InvalidJSONText": "Please ensure this is a valid JSON string for Shinobi monitor configuration.",
|
||||
"Passwords don't match": "Passwords don't match",
|
||||
"Email address is in use.": "Email address is in use.",
|
||||
"Group Key is in use.": "Group Key is in use.",
|
||||
"Create Sub-Accounts at /admin": "Create Sub-Accounts at /admin",
|
||||
"No Events found for this video": "No Events found for this video",
|
||||
"Video and Time Span (Minutes)": "Video and Time Span (Minutes)",
|
||||
"Video Length (minutes) and Motion Count per video": "Video Length (minutes) and Motion Count per video",
|
||||
|
@ -329,6 +341,10 @@
|
|||
"Filter for Objects only": "Filter for Objects only",
|
||||
"Custom": "Custom",
|
||||
"Detector": "Detector",
|
||||
"Audio Detector": "Audio Detector",
|
||||
"Audio Detection": "Audio Detection",
|
||||
"Minimum dB": "Minimum dB",
|
||||
"Maximum dB": "Maximum dB",
|
||||
"Connected": "Connected",
|
||||
"Not Saved": "Not Saved",
|
||||
"Not Connected": "Not Connected",
|
||||
|
@ -400,7 +416,17 @@
|
|||
"Image Height": "Image Height",
|
||||
"Record File Type": "Record File Type",
|
||||
"Video Codec": "Video Codec",
|
||||
"Delete Monitor States Preset": "Delete Monitor States Preset",
|
||||
"Delete Monitor State?": "Delete Monitor State",
|
||||
"deleteMonitorStateText1": "Do you want to delete this Monitor States Preset?",
|
||||
"deleteMonitorStateText2": "Do you want to delete this Monitor's Preset?",
|
||||
"Search Images": "Search Images",
|
||||
"Launch in New Window": "Launch in New Window",
|
||||
"Preset": "Preset",
|
||||
"Presets": "Presets",
|
||||
"possibleInternalError": "Possible Internal Error",
|
||||
"sizePurgeLockedText": "The Size Purge Lock (deleteOverMax) appears to have failed to unlock. Unlocking now...",
|
||||
"Use coProcessor": "Use coProcessor",
|
||||
"Audio Codec": "Audio Codec",
|
||||
"Video Record Rate": "Video Record Rate <small>(FPS)</small>",
|
||||
"Record Width": "Record Width",
|
||||
|
@ -415,6 +441,7 @@
|
|||
"Stream to YouTube": "Stream to YouTube",
|
||||
"Stream to YouTube Flags": "Stream to YouTube Flags",
|
||||
"Recording Flags": "Recording Flags",
|
||||
"Traditional Recording Flags": "Traditional Recording Flags",
|
||||
"Output Method": "Output Method",
|
||||
"Webhook": "Webhook",
|
||||
"Event Webhook Error": "Event Webhook Error",
|
||||
|
@ -426,6 +453,8 @@
|
|||
"Save Events to SQL": "Save Events to SQL",
|
||||
"Email on Trigger": "Email on Trigger <small>Emails go to the main account holder's login address.</small>",
|
||||
"Attach Video Clip": "Attach Video Clip",
|
||||
"Error While Decoding": "Error While Decoding",
|
||||
"ErrorWhileDecodingText": "Your hardware may have an unstable connection to the network. Check your network connections.",
|
||||
"Discord": "Discord",
|
||||
"Discord Alert on Trigger": "Discord Alert on Trigger",
|
||||
"Allow Next Email": "Allow Next Email <small>in Minutes</small>",
|
||||
|
@ -642,6 +671,7 @@
|
|||
"Monitor mode is already": "Monitor mode is already",
|
||||
"Monitor or Key does not exist.": "Monitor or Key does not exist.",
|
||||
"No Group with this key exists": "No Group with this key exists",
|
||||
"Success": "Success",
|
||||
"Trigger Successful": "Trigger Successful",
|
||||
"No such file": "No such file",
|
||||
"h265BrowserText1": "If you are trying to play an H.265 file, you may need to download it and open it in another application like VLC.",
|
||||
|
@ -666,6 +696,10 @@
|
|||
"Inserted State Configuration": "Inserted State Configuration",
|
||||
"Edited State Configuration": "Edited State Configuration",
|
||||
"Deleted State Configuration": "Deleted State Configuration",
|
||||
"Schedule Configuration Not Found": "Schedule Configuration Not Found",
|
||||
"Inserted Schedule Configuration": "Inserted Schedule Configuration",
|
||||
"Edited Schedule Configuration": "Edited Schedule Configuration",
|
||||
"Deleted Schedule Configuration": "Deleted Schedule Configuration",
|
||||
"Dashboard Language": "Dashboard Language",
|
||||
"Form Data Not Found": "Form Data Not Found",
|
||||
"File Not Found": "File Not Found",
|
||||
|
@ -777,6 +811,11 @@
|
|||
"RTMP Stream":"RTMP Stream",
|
||||
"Stream Channel":"Stream Channel",
|
||||
"Confidence":"Confidence",
|
||||
"Trainer Engine":"Trainer Engine",
|
||||
"Train":"Train",
|
||||
"TrainConfirm":"Are you sure you want to begin training? This can take more than 12 hours with over 500 images. This will consume a large amount of resources, like RAM or CPU.",
|
||||
"Batch":"Batch",
|
||||
"Subdivision":"Subdivision",
|
||||
"Map":"Map",
|
||||
"Add Map":"Add Map",
|
||||
"Add Input Feed":"Add Input Feed",
|
||||
|
@ -792,6 +831,7 @@
|
|||
"TV Channel ID":"TV Channel ID",
|
||||
"TV Channel Group":"TV Channel Group",
|
||||
"Emotion Average":"Emotion Average",
|
||||
"Require Object to be in Region":"Require Object to be in Region",
|
||||
"Show Regions of Interest":"Show Regions of Interest",
|
||||
"Confidence of Detection":"Confidence of Detection",
|
||||
"Edit Selected":"Edit Selected",
|
||||
|
|
|
@ -12,7 +12,7 @@ module.exports = function(s,config){
|
|||
if(s.isWin===true){
|
||||
cmd = "Taskkill /IM ffmpeg.exe /F"
|
||||
}else{
|
||||
cmd = "ps aux | grep -ie ffmpeg | awk '{print $2}' | xargs kill -9"
|
||||
cmd = "pkill -9 ffmpeg"
|
||||
}
|
||||
exec(cmd,{detached: true})
|
||||
};
|
||||
|
@ -33,7 +33,7 @@ module.exports = function(s,config){
|
|||
s.parseJSON = function(string){
|
||||
var parsed
|
||||
try{
|
||||
string = JSON.parse(string)
|
||||
parsed = JSON.parse(string)
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
|
@ -226,4 +226,19 @@ module.exports = function(s,config){
|
|||
break;
|
||||
}
|
||||
}
|
||||
s.createTimeout = function(timeoutVar,timeoutLength,defaultLength,multiplier,callback){
|
||||
var theTimeout
|
||||
if(!multiplier)multiplier = 1000 * 60
|
||||
if(!timeoutLength || timeoutLength === ''){
|
||||
theTimeout = defaultLength
|
||||
}else{
|
||||
theTimeout = parseFloat(timeoutLength) * multiplier
|
||||
}
|
||||
clearTimeout(timeoutVar)
|
||||
timeoutVar = setTimeout(function(){
|
||||
clearTimeout(timeoutVar)
|
||||
delete(timeoutVar)
|
||||
if(callback)callback()
|
||||
},theTimeout)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,134 @@
|
|||
var fs = require('fs')
|
||||
var express = require('express')
|
||||
module.exports = function(s,config,lang,app,io){
|
||||
var checkFolder = function(folderName){
|
||||
var folderPath = __dirname + '/' + folderName
|
||||
fs.readdir(folderPath,function(err,folderContents){
|
||||
if(!err && folderContents){
|
||||
folderContents.forEach(function(filename){
|
||||
if(filename.indexOf('.js') > -1){
|
||||
var customModulePath = folderPath + '/' + filename
|
||||
s.customAutoLoadModules = {}
|
||||
s.customAutoLoadTree = {
|
||||
pages: [],
|
||||
PageBlocks: [],
|
||||
LibsJs: [],
|
||||
LibsCss: [],
|
||||
adminPageBlocks: [],
|
||||
adminLibsJs: [],
|
||||
adminLibsCss: [],
|
||||
superPageBlocks: [],
|
||||
superLibsJs: [],
|
||||
superLibsCss: []
|
||||
}
|
||||
var folderPath = __dirname + '/customAutoLoad'
|
||||
var search = function(searchFor,searchIn){return searchIn.indexOf(searchFor) > -1}
|
||||
fs.readdir(folderPath,function(err,folderContents){
|
||||
if(!err && folderContents){
|
||||
folderContents.forEach(function(filename){
|
||||
s.customAutoLoadModules[filename] = {}
|
||||
var customModulePath = folderPath + '/' + filename
|
||||
if(filename.indexOf('.js') > -1){
|
||||
s.customAutoLoadModules[filename].type = 'file'
|
||||
try{
|
||||
require(customModulePath)(s,config,lang,app,io)
|
||||
}catch(err){
|
||||
console.log('Failed to Load Module : ' + filename)
|
||||
console.log(err)
|
||||
}
|
||||
}else{
|
||||
if(fs.lstatSync(customModulePath).isDirectory()){
|
||||
s.customAutoLoadModules[filename].type = 'folder'
|
||||
try{
|
||||
require(customModulePath)(s,config,lang,app,io)
|
||||
fs.readdir(customModulePath,function(err,folderContents){
|
||||
folderContents.forEach(function(name){
|
||||
switch(name){
|
||||
case'web':
|
||||
var webFolder = s.checkCorrectPathEnding(customModulePath) + 'web/'
|
||||
fs.readdir(webFolder,function(err,webFolderContents){
|
||||
webFolderContents.forEach(function(name){
|
||||
switch(name){
|
||||
case'libs':
|
||||
case'pages':
|
||||
if(name === 'libs'){
|
||||
if(config.webPaths.home !== '/'){
|
||||
app.use('/libs',express.static(webFolder + '/libs'))
|
||||
}
|
||||
app.use(s.checkCorrectPathEnding(config.webPaths.home)+'libs',express.static(webFolder + '/libs'))
|
||||
app.use(s.checkCorrectPathEnding(config.webPaths.admin)+'libs',express.static(webFolder + '/libs'))
|
||||
app.use(s.checkCorrectPathEnding(config.webPaths.super)+'libs',express.static(webFolder + '/libs'))
|
||||
}
|
||||
var libFolder = webFolder + name + '/'
|
||||
fs.readdir(libFolder,function(err,webFolderContents){
|
||||
webFolderContents.forEach(function(libName){
|
||||
var thirdLevelName = libFolder + libName
|
||||
switch(libName){
|
||||
case'js':
|
||||
case'css':
|
||||
case'blocks':
|
||||
fs.readdir(thirdLevelName,function(err,webFolderContents){
|
||||
webFolderContents.forEach(function(filename){
|
||||
var fullPath = thirdLevelName + '/' + filename
|
||||
var blockPrefix = ''
|
||||
switch(true){
|
||||
case search('super.',filename):
|
||||
blockPrefix = 'super'
|
||||
break;
|
||||
case search('admin.',filename):
|
||||
blockPrefix = 'admin'
|
||||
break;
|
||||
}
|
||||
switch(libName){
|
||||
case'js':
|
||||
s.customAutoLoadTree[blockPrefix + 'LibsJs'].push(filename)
|
||||
break;
|
||||
case'css':
|
||||
s.customAutoLoadTree[blockPrefix + 'LibsCss'].push(filename)
|
||||
break;
|
||||
case'blocks':
|
||||
s.customAutoLoadTree[blockPrefix + 'PageBlocks'].push(fullPath)
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
break;
|
||||
default:
|
||||
if(libName.indexOf('.ejs') > -1){
|
||||
s.customAutoLoadTree.pages.push(thirdLevelName)
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
break;
|
||||
case'languages':
|
||||
var languagesFolder = s.checkCorrectPathEnding(customModulePath) + 'languages/'
|
||||
fs.readdir(languagesFolder,function(err,files){
|
||||
if(err)return console.log(err);
|
||||
files.forEach(function(filename){
|
||||
var fileData = require(languagesFolder + filename)
|
||||
var rule = filename.replace('.json','')
|
||||
if(config.language === rule){
|
||||
lang = Object.assign(lang,fileData)
|
||||
}
|
||||
if(s.loadedLanguages[rule]){
|
||||
s.loadedLanguages[rule] = Object.assign(s.loadedLanguages[rule],fileData)
|
||||
}else{
|
||||
s.loadedLanguages[rule] = Object.assign(s.copySystemDefaultLanguage(),fileData)
|
||||
}
|
||||
})
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
}catch(err){
|
||||
console.log('Failed to Load Module : ' + filename)
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
fs.mkdirSync(folderPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
checkFolder('customAutoLoad')
|
||||
}
|
||||
})
|
||||
}else{
|
||||
fs.mkdirSync(folderPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
var P2P = require('pipe2pam');
|
||||
// Matrix In Region Libs >
|
||||
var SAT = require('sat')
|
||||
var V = SAT.Vector;
|
||||
var P = SAT.Polygon;
|
||||
// Matrix In Region Libs />
|
||||
var P2P = require('pipe2pam')
|
||||
// pamDiff is based on https://www.npmjs.com/package/pam-diff
|
||||
var PamDiff = require('./detectorPamDiff.js');
|
||||
var PamDiff = require('pam-diff')
|
||||
module.exports = function(s,config){
|
||||
s.createPamDiffEngine = function(e){
|
||||
var width,
|
||||
|
@ -46,7 +51,7 @@ module.exports = function(s,config){
|
|||
[width,height],
|
||||
[width,0]
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
e.triggerTimer = {}
|
||||
|
@ -58,7 +63,7 @@ module.exports = function(s,config){
|
|||
regions : regions.forPam,
|
||||
drawMatrix : e.details.detector_show_matrix
|
||||
});
|
||||
s.group[e.ke].mon[e.id].p2p = new P2P();
|
||||
s.group[e.ke].mon[e.id].p2p = new P2P()
|
||||
var regionArray = Object.values(regionJson)
|
||||
if(config.detectorMergePamRegionTriggers === true){
|
||||
// merge pam triggers for performance boost
|
||||
|
@ -317,4 +322,39 @@ module.exports = function(s,config){
|
|||
}
|
||||
return trigger
|
||||
}
|
||||
s.isAtleastOneMatrixInRegion = function(regions,matrices,callback){
|
||||
var regionPolys = []
|
||||
var matrixPoints = []
|
||||
regions.forEach(function(region,n){
|
||||
var polyPoints = []
|
||||
region.points.forEach(function(point){
|
||||
polyPoints.push(new V(parseInt(point[0]),parseInt(point[1])))
|
||||
})
|
||||
regionPolys[n] = new P(new V(0,0), polyPoints)
|
||||
})
|
||||
var collisions = []
|
||||
var foundInRegion = false
|
||||
matrices.forEach(function(matrix){
|
||||
var matrixPoints = [
|
||||
new V(matrix.x,matrix.y),
|
||||
new V(matrix.width,matrix.y),
|
||||
new V(matrix.width,matrix.height),
|
||||
new V(matrix.x,matrix.height)
|
||||
]
|
||||
var matrixPoly = new P(new V(0,0), matrixPoints)
|
||||
regionPolys.forEach(function(region,n){
|
||||
var response = new SAT.Response()
|
||||
var collided = SAT.testPolygonPolygon(matrixPoly, region, response)
|
||||
if(collided === true){
|
||||
collisions.push({
|
||||
matrix: matrix,
|
||||
region: regions[n]
|
||||
})
|
||||
foundInRegion = true
|
||||
}
|
||||
})
|
||||
})
|
||||
if(callback)callback(foundInRegion,collisions)
|
||||
return foundInRegion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,25 @@ var exec = require('child_process').exec;
|
|||
var spawn = require('child_process').spawn;
|
||||
var request = require('request');
|
||||
module.exports = function(s,config,lang){
|
||||
var addEventDetailsToString = function(eventData,string,addOps){
|
||||
//d = event data
|
||||
if(!addOps)addOps = {}
|
||||
var newString = string + ''
|
||||
var d = Object.assign(eventData,addOps)
|
||||
var detailString = s.stringJSON(d.details)
|
||||
newString
|
||||
.replace(/{{TIME}}/g,d.currentTimestamp)
|
||||
.replace(/{{REGION_NAME}}/g,d.details.name)
|
||||
.replace(/{{SNAP_PATH}}/g,s.dir.streams+'/'+d.ke+'/'+d.id+'/s.jpg')
|
||||
.replace(/{{MONITOR_ID}}/g,d.id)
|
||||
.replace(/{{GROUP_KEY}}/g,d.ke)
|
||||
.replace(/{{DETAILS}}/g,detailString)
|
||||
if(d.details.confidence){
|
||||
newString = newString
|
||||
.replace(/{{CONFIDENCE}}/g,d.details.confidence)
|
||||
}
|
||||
return newString
|
||||
}
|
||||
s.filterEvents = function(x,d){
|
||||
switch(x){
|
||||
case'archive':
|
||||
|
@ -45,6 +64,7 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
d.mon=s.group[d.ke].mon_conf[d.id];
|
||||
var currentConfig = s.group[d.ke].mon[d.id].details
|
||||
var hasMatrices = (d.details.matrices && d.details.matrices.length > 0)
|
||||
//read filters
|
||||
if(
|
||||
currentConfig.use_detector_filters === '1' &&
|
||||
|
@ -160,7 +180,7 @@ module.exports = function(s,config,lang){
|
|||
})
|
||||
if(d.details.matrices && d.details.matrices.length === 0 || filter.halt === true){
|
||||
return
|
||||
}else if(d.details.matrices && d.details.matrices.length > 0){
|
||||
}else if(hasMatrices){
|
||||
var reviewedMatrix = []
|
||||
d.details.matrices.forEach(function(matrix){
|
||||
if(matrix)reviewedMatrix.push(matrix)
|
||||
|
@ -193,6 +213,16 @@ module.exports = function(s,config,lang){
|
|||
return
|
||||
}
|
||||
}
|
||||
// check if object should be in region
|
||||
if(hasMatrices && currentConfig.detector_obj_region === '1'){
|
||||
var regions = s.group[d.ke].mon[d.id].parsedObjects.cords
|
||||
var isMatrixInRegions = s.isAtleastOneMatrixInRegion(regions,d.details.matrices)
|
||||
if(isMatrixInRegions){
|
||||
s.debugLog('Matrix in region!')
|
||||
}else{
|
||||
return
|
||||
}
|
||||
}
|
||||
// check modified indifference
|
||||
if(filter.indifference !== false && d.details.confidence < parseFloat(filter.indifference)){
|
||||
// fails indifference check for modified indifference
|
||||
|
@ -210,12 +240,12 @@ module.exports = function(s,config,lang){
|
|||
})
|
||||
}else{
|
||||
//save this detection result in SQL, only coords. not image.
|
||||
if(filter.save && currentConfig.detector_save==='1'){
|
||||
if(filter.save && currentConfig.detector_save === '1'){
|
||||
s.sqlQuery('INSERT INTO Events (ke,mid,details) VALUES (?,?,?)',[d.ke,d.id,detailString])
|
||||
}
|
||||
if(currentConfig.detector_notrigger === '1'){
|
||||
var detector_notrigger_timeout
|
||||
if(!currentConfig.detector_notrigger_timeout||currentConfig.detector_notrigger_timeout===''){
|
||||
if(!currentConfig.detector_notrigger_timeout||currentConfig.detector_notrigger_timeout === ''){
|
||||
detector_notrigger_timeout = 10
|
||||
}
|
||||
detector_notrigger_timeout = parseFloat(currentConfig.detector_notrigger_timeout)*1000*60;
|
||||
|
@ -270,17 +300,7 @@ module.exports = function(s,config,lang){
|
|||
})
|
||||
|
||||
if(filter.webhook && currentConfig.detector_webhook === '1'){
|
||||
var detector_webhook_url = currentConfig.detector_webhook_url
|
||||
.replace(/{{TIME}}/g,d.currentTimestamp)
|
||||
.replace(/{{REGION_NAME}}/g,d.details.name)
|
||||
.replace(/{{SNAP_PATH}}/g,s.dir.streams+'/'+d.ke+'/'+d.id+'/s.jpg')
|
||||
.replace(/{{MONITOR_ID}}/g,d.id)
|
||||
.replace(/{{GROUP_KEY}}/g,d.ke)
|
||||
.replace(/{{DETAILS}}/g,detailString)
|
||||
if(d.details.confidence){
|
||||
detector_webhook_url = detector_webhook_url
|
||||
.replace(/{{CONFIDENCE}}/g,d.details.confidence)
|
||||
}
|
||||
var detector_webhook_url = addEventDetailsToString(d,currentConfig.detector_webhook_url)
|
||||
request({url:detector_webhook_url,method:'GET',encoding:null},function(err,data){
|
||||
if(err){
|
||||
s.userLog(d,{type:lang["Event Webhook Error"],msg:{error:err,data:data}})
|
||||
|
@ -289,28 +309,8 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
|
||||
if(filter.command && currentConfig.detector_command_enable === '1' && !s.group[d.ke].mon[d.id].detector_command){
|
||||
var detector_command_timeout
|
||||
if(!currentConfig.detector_command_timeout||currentConfig.detector_command_timeout===''){
|
||||
detector_command_timeout = 1000*60*10;
|
||||
}else{
|
||||
detector_command_timeout = parseFloat(currentConfig.detector_command_timeout)*1000*60;
|
||||
}
|
||||
s.group[d.ke].mon[d.id].detector_command=setTimeout(function(){
|
||||
clearTimeout(s.group[d.ke].mon[d.id].detector_command);
|
||||
delete(s.group[d.ke].mon[d.id].detector_command);
|
||||
|
||||
},detector_command_timeout);
|
||||
var detector_command = currentConfig.detector_command
|
||||
.replace(/{{TIME}}/g,d.currentTimestamp)
|
||||
.replace(/{{REGION_NAME}}/g,d.details.name)
|
||||
.replace(/{{SNAP_PATH}}/g,s.dir.streams+'/'+d.ke+'/'+d.id+'/s.jpg')
|
||||
.replace(/{{MONITOR_ID}}/g,d.id)
|
||||
.replace(/{{GROUP_KEY}}/g,d.ke)
|
||||
.replace(/{{DETAILS}}/g,detailString)
|
||||
if(d.details.confidence){
|
||||
detector_command = detector_command
|
||||
.replace(/{{CONFIDENCE}}/g,d.details.confidence)
|
||||
}
|
||||
s.createTimeout(s.group[d.ke].mon[d.id].detector_command,currentConfig.detector_command_timeout,10)
|
||||
var detector_command = addEventDetailsToString(d,currentConfig.detector_command)
|
||||
exec(detector_command,{detached: true})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -382,7 +382,16 @@ module.exports = function(s,config,onFinish){
|
|||
//x = temporary values
|
||||
//check if CUDA is enabled
|
||||
e.isStreamer = (e.type === 'dashcam'|| e.type === 'socket')
|
||||
if(e.details.accelerator === '1' && e.details.hwaccel === 'cuvid' && e.details.hwaccel_vcodec === ('h264_cuvid' || 'hevc_cuvid' || 'mjpeg_cuvid' || 'mpeg4_cuvid')){
|
||||
e.coProcessor = false
|
||||
if(
|
||||
e.details.use_coprocessor === '1' &&
|
||||
e.details.accelerator === '1' &&
|
||||
e.isStreamer === false &&
|
||||
(!e.details.input_maps || e.details.input_maps.length === 0) &&
|
||||
(e.details.snap === '1' || e.details.stream_type === 'mjpeg' || e.details.stream_type === 'b64' || e.details.detector === '1')
|
||||
){
|
||||
e.coProcessor = true
|
||||
}else if(e.details.accelerator === '1' && e.details.hwaccel === 'cuvid' && e.details.hwaccel_vcodec === ('h264_cuvid' || 'hevc_cuvid' || 'mjpeg_cuvid' || 'mpeg4_cuvid')){
|
||||
e.cudaEnabled = true
|
||||
}
|
||||
//
|
||||
|
@ -563,9 +572,11 @@ module.exports = function(s,config,onFinish){
|
|||
x.pipe+=x.preset_stream+x.stream_acodec+x.stream_vcodec+' -f hls'+x.cust_stream+' -hls_time '+x.hls_time+' -hls_list_size '+x.hls_list_size+' -start_number 0 -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'s.m3u8"';
|
||||
break;
|
||||
case'mjpeg':
|
||||
if(e.coProcessor === false){
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality;
|
||||
if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions}
|
||||
x.pipe+=' -an -c:v mjpeg -f mpjpeg -boundary_tag shinobi'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
}
|
||||
break;
|
||||
case'h265':
|
||||
x.cust_stream+=' -movflags +frag_keyframe+empty_moov+default_base_moof -metadata title="Shinobi H.265 Stream" -reset_timestamps 1'
|
||||
|
@ -578,9 +589,11 @@ module.exports = function(s,config,onFinish){
|
|||
x.pipe+=' -f hevc'+x.stream_acodec+x.stream_vcodec+x.cust_stream+' pipe:1';
|
||||
break;
|
||||
case'b64':case'':case undefined:case null://base64
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality;
|
||||
if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions}
|
||||
x.pipe+=' -an -c:v mjpeg -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
if(e.coProcessor === false){
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality;
|
||||
if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions}
|
||||
x.pipe+=' -an -c:v mjpeg -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
x.pipe=''
|
||||
|
@ -588,11 +601,12 @@ module.exports = function(s,config,onFinish){
|
|||
}
|
||||
if(e.details.stream_channels){
|
||||
e.details.stream_channels.forEach(function(v,n){
|
||||
// if(v.stream_type === 'mjpeg')e.coProcessor = true;
|
||||
x.pipe += s.createStreamChannel(e,n+config.pipeAddition,v)
|
||||
})
|
||||
}
|
||||
//api - snapshot bin/ cgi.bin (JPEG Mode)
|
||||
if(e.details.snap === '1'){
|
||||
if(e.details.snap === '1' && e.coProcessor === false){
|
||||
if(e.details.input_map_choices&&e.details.input_map_choices.snap){
|
||||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.snap)
|
||||
|
@ -735,12 +749,23 @@ module.exports = function(s,config,onFinish){
|
|||
x.record_string+=x.vcodec+x.record_fps+x.record_video_filters+x.record_dimensions+x.segment;
|
||||
}
|
||||
}
|
||||
ffmpeg.buildAudioDetector = function(e,x){
|
||||
if(e.details.detector_audio === '1'){
|
||||
if(e.details.input_map_choices&&e.details.input_map_choices.detector_audio){
|
||||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector_audio)
|
||||
}else{
|
||||
x.pipe += ' -map 0:a'
|
||||
}
|
||||
x.pipe += ' -acodec pcm_s16le -f s16le -ac 1 -ar 16000 pipe:6'
|
||||
}
|
||||
}
|
||||
ffmpeg.buildMainDetector = function(e,x){
|
||||
//e = monitor object
|
||||
//x = temporary values
|
||||
x.cust_detect = ' '
|
||||
//detector - plugins, motion
|
||||
if(e.details.detector === '1' && e.details.detector_send_frames === '1'){
|
||||
if(e.details.detector === '1' && e.details.detector_send_frames === '1' && e.coProcessor === false){
|
||||
if(e.details.input_map_choices&&e.details.input_map_choices.detector){
|
||||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
|
@ -761,14 +786,15 @@ module.exports = function(s,config,onFinish){
|
|||
if(e.details.detector_use_detect_object === '1'){
|
||||
//for object detection
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
x.pipe += ' -f singlejpeg '+x.detector_vf+x.cust_detect+x.dratio+' pipe:4';
|
||||
x.pipe += ' -an -f singlejpeg '+x.detector_vf+x.cust_detect+x.dratio+' pipe:4';
|
||||
}
|
||||
}else{
|
||||
x.pipe+=' -f image2pipe '+x.detector_vf+x.cust_detect+x.dratio+' pipe:3';
|
||||
x.pipe+=' -an -f image2pipe '+x.detector_vf+x.cust_detect+x.dratio+' pipe:3';
|
||||
}
|
||||
}
|
||||
//Traditional Recording Buffer
|
||||
if(e.details.detector=='1'&&e.details.detector_trigger=='1'&&e.details.detector_record_method==='sip'){
|
||||
if(e.details.cust_sip_record && e.details.cust_sip_record !== ''){x.pipe += ' ' + e.details.cust_sip_record}
|
||||
if(e.details.input_map_choices&&e.details.input_map_choices.detector_sip_buffer){
|
||||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector_sip_buffer)
|
||||
|
@ -836,6 +862,12 @@ module.exports = function(s,config,onFinish){
|
|||
x.pipe+=x.detector_buffer_fps+x.detector_buffer_acodec+' -c:v '+e.details.detector_buffer_vcodec+' -f hls -tune '+e.details.detector_buffer_tune+' -g '+e.details.detector_buffer_g+' -hls_time '+e.details.detector_buffer_hls_time+' -hls_list_size '+e.details.detector_buffer_hls_list_size+' -start_number '+e.details.detector_buffer_start_number+' -live_start_index '+e.details.detector_buffer_live_start_index+' -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'detectorStream.m3u8"'
|
||||
}
|
||||
}
|
||||
ffmpeg.buildCoProcessorFeed = function(e,x){
|
||||
if(e.coProcessor === true){
|
||||
// the coProcessor ffmpeg consumes this HLS stream (no audio, frames only)
|
||||
x.pipe += ' -q:v 1 -an -c:v copy -f hls -tune zerolatency -g 1 -hls_time 2 -hls_list_size 3 -start_number 0 -live_start_index 3 -hls_allow_cache 0 -hls_flags +delete_segments+omit_endlist "'+e.sdir+'coProcessor.m3u8"'
|
||||
}
|
||||
}
|
||||
ffmpeg.assembleMainPieces = function(e,x){
|
||||
//create executeable FFMPEG command
|
||||
x.ffmpegCommandString = x.loglevel+x.input_fps;
|
||||
|
@ -852,6 +884,9 @@ module.exports = function(s,config,onFinish){
|
|||
case'mjpeg':
|
||||
x.ffmpegCommandString += ' -reconnect 1 -f mjpeg'+x.cust_input+x.hwaccel+' -i "'+e.url+'"';
|
||||
break;
|
||||
// case'rtmp':
|
||||
// x.ffmpegCommandString += x.cust_input+x.hwaccel+' -i -';
|
||||
// break;
|
||||
case'h264':case'hls':case'mp4':
|
||||
x.ffmpegCommandString += x.cust_input+x.hwaccel+' -i "'+e.url+'"';
|
||||
break;
|
||||
|
@ -886,7 +921,9 @@ module.exports = function(s,config,onFinish){
|
|||
ffmpeg.buildMainInput(e,x)
|
||||
ffmpeg.buildMainStream(e,x)
|
||||
ffmpeg.buildMainRecording(e,x)
|
||||
ffmpeg.buildAudioDetector(e,x)
|
||||
ffmpeg.buildMainDetector(e,x)
|
||||
ffmpeg.buildCoProcessorFeed(e,x)
|
||||
s.onFfmpegCameraStringCreationExtensions.forEach(function(extender){
|
||||
extender(e,x)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
var spawn = require('child_process').spawn;
|
||||
module.exports = function(s,config,lang,ffmpeg){
|
||||
ffmpeg.buildCoProcessorInput = function(e,x){
|
||||
if(e.details.userLoglevel&&e.details.userLoglevel!==''){x.loglevel='-loglevel '+e.details.userLoglevel;}else{x.loglevel='-loglevel error'}
|
||||
x.input = x.loglevel+' -re -i '+e.sdir+'coProcessor.m3u8'
|
||||
}
|
||||
ffmpeg.buildCoProcessorStream = function(e,x){
|
||||
x.stream_video_filters = []
|
||||
//stream - timestamp
|
||||
if(e.details.stream_timestamp&&e.details.stream_timestamp=="1"&&e.details.vcodec!=='copy'){
|
||||
//font
|
||||
if(e.details.stream_timestamp_font&&e.details.stream_timestamp_font!==''){x.stream_timestamp_font=e.details.stream_timestamp_font}else{x.stream_timestamp_font='/usr/share/fonts/truetype/freefont/FreeSans.ttf'}
|
||||
//position x
|
||||
if(e.details.stream_timestamp_x&&e.details.stream_timestamp_x!==''){x.stream_timestamp_x=e.details.stream_timestamp_x}else{x.stream_timestamp_x='(w-tw)/2'}
|
||||
//position y
|
||||
if(e.details.stream_timestamp_y&&e.details.stream_timestamp_y!==''){x.stream_timestamp_y=e.details.stream_timestamp_y}else{x.stream_timestamp_y='0'}
|
||||
//text color
|
||||
if(e.details.stream_timestamp_color&&e.details.stream_timestamp_color!==''){x.stream_timestamp_color=e.details.stream_timestamp_color}else{x.stream_timestamp_color='white'}
|
||||
//box color
|
||||
if(e.details.stream_timestamp_box_color&&e.details.stream_timestamp_box_color!==''){x.stream_timestamp_box_color=e.details.stream_timestamp_box_color}else{x.stream_timestamp_box_color='0x00000000@1'}
|
||||
//text size
|
||||
if(e.details.stream_timestamp_font_size&&e.details.stream_timestamp_font_size!==''){x.stream_timestamp_font_size=e.details.stream_timestamp_font_size}else{x.stream_timestamp_font_size='10'}
|
||||
|
||||
x.stream_video_filters.push('drawtext=fontfile='+x.stream_timestamp_font+':text=\'%{localtime}\':x='+x.stream_timestamp_x+':y='+x.stream_timestamp_y+':fontcolor='+x.stream_timestamp_color+':box=1:boxcolor='+x.stream_timestamp_box_color+':fontsize='+x.stream_timestamp_font_size);
|
||||
}
|
||||
//stream - watermark for -vf
|
||||
if(e.details.stream_watermark&&e.details.stream_watermark=="1"&&e.details.stream_watermark_location&&e.details.stream_watermark_location!==''){
|
||||
switch(e.details.stream_watermark_position){
|
||||
case'tl'://top left
|
||||
x.stream_watermark_position='10:10'
|
||||
break;
|
||||
case'tr'://top right
|
||||
x.stream_watermark_position='main_w-overlay_w-10:10'
|
||||
break;
|
||||
case'bl'://bottom left
|
||||
x.stream_watermark_position='10:main_h-overlay_h-10'
|
||||
break;
|
||||
default://bottom right
|
||||
x.stream_watermark_position='(main_w-overlay_w-10)/2:(main_h-overlay_h-10)/2'
|
||||
break;
|
||||
}
|
||||
x.stream_video_filters.push('movie='+e.details.stream_watermark_location+'[watermark],[in][watermark]overlay='+x.stream_watermark_position+'[out]');
|
||||
}
|
||||
//stream - rotation
|
||||
if(e.details.rotate_stream&&e.details.rotate_stream!==""&&e.details.rotate_stream!=="no"&&e.details.stream_vcodec!=='copy'){
|
||||
x.stream_video_filters.push('transpose='+e.details.rotate_stream);
|
||||
}
|
||||
if(e.details.svf&&e.details.svf!==''){
|
||||
x.stream_video_filters.push(e.details.svf)
|
||||
}
|
||||
if(x.stream_video_filters.length>0){
|
||||
x.stream_video_filters=' -vf '+x.stream_video_filters.join(',')
|
||||
}else{
|
||||
x.stream_video_filters=''
|
||||
}
|
||||
if(e.details.cust_stream&&e.details.cust_stream!==''){x.cust_stream=' '+e.details.cust_stream}else{x.cust_stream=''}
|
||||
if(e.details.stream_fps&&e.details.stream_fps!==''){x.stream_fps=' -r '+e.details.stream_fps}else{x.stream_fps=''}
|
||||
if(e.details.stream_vcodec !== 'copy' || e.details.stream_type === 'mjpeg' || e.details.stream_type === 'b64'){
|
||||
x.cust_stream += x.stream_fps
|
||||
}
|
||||
switch(e.details.stream_type){
|
||||
case'mjpeg':
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality;
|
||||
if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions}
|
||||
x.pipe += ' -an -c:v mjpeg -f mpjpeg -boundary_tag shinobi'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
break;
|
||||
case'b64':case'':case undefined:case null://base64
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality;
|
||||
if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions}
|
||||
x.pipe += ' -an -c:v mjpeg -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
break;
|
||||
}
|
||||
}
|
||||
ffmpeg.buildCoProcessorDetector = function(e,x){
|
||||
//detector frames
|
||||
x.cust_detect=' '
|
||||
if(e.details.detector === '1'){
|
||||
if(e.details.detector_fps && e.details.detector_fps !== ''){
|
||||
x.detector_fps = e.details.detector_fps
|
||||
}else{
|
||||
x.detector_fps = '2'
|
||||
}
|
||||
if(e.details.detector_scale_x && e.details.detector_scale_x !== '' && e.details.detector_scale_y && e.details.detector_scale_y !== ''){
|
||||
x.dratio=' -s '+e.details.detector_scale_x+'x'+e.details.detector_scale_y
|
||||
}else{
|
||||
x.dratio=' -s 320x240'
|
||||
}
|
||||
|
||||
if(e.details.cust_detect&&e.details.cust_detect!==''){x.cust_detect+=e.details.cust_detect;}
|
||||
if(e.details.detector_pam==='1'){
|
||||
x.pipe += ' -an -c:v pam -pix_fmt gray -f image2pipe -r '+x.detector_fps+x.cust_detect+x.dratio+' pipe:3'
|
||||
if(e.details.detector_use_detect_object === '1'){
|
||||
if(e.details.detector_use_motion === '1'){
|
||||
if(e.details.detector_scale_x_object && e.details.detector_scale_x_object !== '' && e.details.detector_scale_y_object && e.details.detector_scale_y_object !== ''){
|
||||
x.dratio=' -s '+e.details.detector_scale_x_object+'x'+e.details.detector_scale_y_object
|
||||
}
|
||||
if(e.details.detector_fps_object && e.details.detector_fps_object !== ''){
|
||||
x.detector_fps = e.details.detector_fps_object
|
||||
}
|
||||
}
|
||||
//for object detection
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
x.pipe += ' -f singlejpeg -vf fps='+x.detector_fps+x.cust_detect+x.dratio+' pipe:4';
|
||||
}
|
||||
}else{
|
||||
x.pipe+=' -f singlejpeg -vf fps='+x.detector_fps+x.cust_detect+x.dratio+' pipe:3';
|
||||
}
|
||||
}
|
||||
}
|
||||
ffmpeg.buildCoProcessorJpegApi = function(e,x){
|
||||
//snapshot frames
|
||||
if(e.details.snap === '1'){
|
||||
if(!e.details.snap_fps || e.details.snap_fps === ''){e.details.snap_fps = 1}
|
||||
if(e.details.snap_vf && e.details.snap_vf !== ''){x.snap_vf=' -vf '+e.details.snap_vf}else{x.snap_vf=''}
|
||||
if(e.details.snap_scale_x && e.details.snap_scale_x !== '' && e.details.snap_scale_y && e.details.snap_scale_y !== ''){x.snap_ratio = ' -s '+e.details.snap_scale_x+'x'+e.details.snap_scale_y}else{x.snap_ratio=''}
|
||||
if(e.details.cust_snap && e.details.cust_snap !== ''){x.cust_snap = ' '+e.details.cust_snap}else{x.cust_snap=''}
|
||||
x.pipe += ' -update 1 -r '+e.details.snap_fps+x.cust_snap+x.snap_ratio+x.snap_vf+' "'+e.sdir+'s.jpg" -y';
|
||||
}
|
||||
}
|
||||
ffmpeg.buildCoProcessorPipeArray = function(e,x){
|
||||
x.stdioPipes = [];
|
||||
var times = config.pipeAddition;
|
||||
if(e.details.stream_channels){
|
||||
times+=e.details.stream_channels.length
|
||||
}
|
||||
for(var i=0; i < times; i++){
|
||||
x.stdioPipes.push('pipe')
|
||||
}
|
||||
}
|
||||
s.ffmpegCoProcessor = function(e){
|
||||
if(e.coProcessor === false)return;
|
||||
var x = {}
|
||||
x.pipe = ''
|
||||
ffmpeg.buildCoProcessorInput(e,x)
|
||||
ffmpeg.buildCoProcessorStream(e,x)
|
||||
ffmpeg.buildCoProcessorDetector(e,x)
|
||||
ffmpeg.buildCoProcessorJpegApi(e,x)
|
||||
ffmpeg.buildCoProcessorPipeArray(e,x)
|
||||
var commandString = x.input + x.pipe
|
||||
if(commandString === x.input){
|
||||
return false
|
||||
}
|
||||
s.group[e.ke].mon[e.mid].coProcessorCmd = commandString
|
||||
return spawn(config.ffmpegDir,s.splitForFFPMEG((commandString).replace(/\s+/g,' ').trim()),{detached: true,stdio:x.stdioPipes})
|
||||
}
|
||||
s.coSpawnLauncher = function(e){
|
||||
if(s.group[e.ke].mon[e.id].isStarted === true && e.coProcessor === true){
|
||||
s.coSpawnClose(e)
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor = s.ffmpegCoProcessor(e)
|
||||
if(s.group[e.ke].mon[e.id].coSpawnProcessor === false){
|
||||
return
|
||||
}
|
||||
s.userLog(e,{type:lang['coProcessor Started'],msg:{msg:lang.coProcessorTextStarted,cmd:s.group[e.ke].mon[e.id].coProcessorCmd}});
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessorExit = function(){
|
||||
s.userLog(e,{type:lang['coProcess Unexpected Exit'],msg:{msg:lang['coProcess Crashed for Monitor']+' : '+e.id,cmd:s.group[e.ke].mon[e.id].coProcessorCmd}});
|
||||
setTimeout(function(){
|
||||
s.coSpawnLauncher(e)
|
||||
},2000)
|
||||
}
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.on('end',s.group[e.ke].mon[e.id].coSpawnProcessorExit)
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.on('exit',s.group[e.ke].mon[e.id].coSpawnProcessorExit)
|
||||
var checkLog = function(d,x){return d.indexOf(x)>-1;}
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stderr.on('data',function(d){
|
||||
d=d.toString();
|
||||
switch(true){
|
||||
case checkLog(d,'deprecated pixel format used'):
|
||||
case checkLog(d,'[hls @'):
|
||||
case checkLog(d,'Past duration'):
|
||||
case checkLog(d,'Last message repeated'):
|
||||
case checkLog(d,'pkt->duration = 0'):
|
||||
case checkLog(d,'Non-monotonous DTS'):
|
||||
case checkLog(d,'NULL @'):
|
||||
return
|
||||
break;
|
||||
}
|
||||
s.userLog(e,{type:lang.coProcessor,msg:d});
|
||||
})
|
||||
if(e.frame_to_stream){
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stdout.on('data',e.frame_to_stream)
|
||||
}
|
||||
if(e.details.detector === '1'){
|
||||
s.ocvTx({f:'init_monitor',id:e.id,ke:e.ke})
|
||||
//frames from motion detect
|
||||
if(e.details.detector_pam === '1'){
|
||||
s.createPamDiffEngine(e)
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[3].pipe(s.group[e.ke].mon[e.id].p2p).pipe(s.group[e.ke].mon[e.id].pamDiff)
|
||||
if(e.details.detector_use_detect_object === '1'){
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[4].on('data',function(d){
|
||||
s.group[e.ke].mon[e.id].lastJpegDetectorFrame = d
|
||||
})
|
||||
}
|
||||
}else if(s.ocv){
|
||||
if(s.ocv.connectionType !== 'ram'){
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[3].on('data',function(d){
|
||||
s.ocvTx({f:'frame',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frame:d});
|
||||
})
|
||||
}else{
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stdio[3].on('data',function(d){
|
||||
if(!s.group[e.ke].mon[e.id].detectorFrameSaveBuffer){
|
||||
s.group[e.ke].mon[e.id].detectorFrameSaveBuffer=[d]
|
||||
}else{
|
||||
s.group[e.ke].mon[e.id].detectorFrameSaveBuffer.push(d)
|
||||
}
|
||||
if(d[d.length-2] === 0xFF && d[d.length-1] === 0xD9){
|
||||
var buffer = Buffer.concat(s.group[e.ke].mon[e.id].detectorFrameSaveBuffer);
|
||||
var frameLocation = s.dir.streams + e.ke + '/' + e.id + '/' + s.gid(5) + '.jpg'
|
||||
if(s.ocv){
|
||||
fs.writeFile(frameLocation,buffer,function(err){
|
||||
if(err){
|
||||
s.debugLog(err)
|
||||
}else{
|
||||
s.ocvTx({f:'frameFromRam',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frameLocation:frameLocation})
|
||||
}
|
||||
})
|
||||
}
|
||||
s.group[e.ke].mon[e.id].detectorFrameSaveBuffer = null;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s.coSpawnClose = function(e){
|
||||
if(s.group[e.ke].mon[e.id].coSpawnProcessor){
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.removeListener('end',s.group[e.ke].mon[e.id].coSpawnProcessorExit);
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.removeListener('exit',s.group[e.ke].mon[e.id].coSpawnProcessorExit);
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.stdin.pause()
|
||||
s.group[e.ke].mon[e.id].coSpawnProcessor.kill()
|
||||
delete(s.group[e.ke].mon[e.id].coSpawnProcessor)
|
||||
s.userLog(e,{type:lang['coProcessor Stopped'],msg:{msg:lang.coProcessorTextStopped+' : '+e.id}});
|
||||
}
|
||||
}
|
||||
}
|
139
libs/monitor.js
139
libs/monitor.js
|
@ -6,6 +6,7 @@ var Mp4Frag = require('mp4frag');
|
|||
var onvif = require('node-onvif');
|
||||
var request = require('request');
|
||||
var connectionTester = require('connection-tester')
|
||||
var SoundDetection = require('shinobi-sound-detection')
|
||||
var URL = require('url')
|
||||
module.exports = function(s,config,lang){
|
||||
s.initiateMonitorObject = function(e){
|
||||
|
@ -21,6 +22,7 @@ module.exports = function(s,config,lang){
|
|||
if(!s.group[e.ke].mon[e.mid].eventBasedRecording){s.group[e.ke].mon[e.mid].eventBasedRecording={}};
|
||||
if(!s.group[e.ke].mon[e.mid].watch){s.group[e.ke].mon[e.mid].watch={}};
|
||||
if(!s.group[e.ke].mon[e.mid].fixingVideos){s.group[e.ke].mon[e.mid].fixingVideos={}};
|
||||
if(!s.group[e.ke].mon[e.mid].parsedObjects){s.group[e.ke].mon[e.mid].parsedObjects={}};
|
||||
if(!s.group[e.ke].mon[e.mid].isStarted){s.group[e.ke].mon[e.mid].isStarted = false};
|
||||
if(s.group[e.ke].mon[e.mid].delete){clearTimeout(s.group[e.ke].mon[e.mid].delete)}
|
||||
if(!s.group[e.ke].mon_conf){s.group[e.ke].mon_conf={}}
|
||||
|
@ -103,7 +105,7 @@ module.exports = function(s,config,lang){
|
|||
var snapBuffer = []
|
||||
var snapProcess = spawn(config.ffmpegDir,('-loglevel quiet -re -i '+url+options+' -frames:v 1 -f image2pipe pipe:1').split(' '),{detached: true})
|
||||
snapProcess.stdout.on('data',function(data){
|
||||
snapBuffer.push(data)
|
||||
if(snapBuffer)snapBuffer.push(data)
|
||||
})
|
||||
snapProcess.stderr.on('data',function(data){
|
||||
console.log(data.toString())
|
||||
|
@ -266,6 +268,7 @@ module.exports = function(s,config,lang){
|
|||
if(s.group[e.ke].mon[e.id].childNode){
|
||||
s.cx({f:'kill',d:s.cleanMonitorObject(e)},s.group[e.ke].mon[e.id].childNodeId)
|
||||
}else{
|
||||
s.coSpawnClose(e)
|
||||
if(!x||x===1){return};
|
||||
p=x.pid;
|
||||
if(s.group[e.ke].mon_conf[e.id].type===('dashcam'||'socket'||'jpeg'||'pipe')){
|
||||
|
@ -282,12 +285,20 @@ module.exports = function(s,config,lang){
|
|||
s.cameraCheckObjectsInDetails = function(e){
|
||||
//parse Objects
|
||||
(['detector_cascades','cords','detector_filters','input_map_choices']).forEach(function(v){
|
||||
if(e.details&&e.details[v]&&(e.details[v] instanceof Object)===false){
|
||||
if(e.details && e.details[v]){
|
||||
try{
|
||||
if(e.details[v] === '') e.details[v] = '{}'
|
||||
e.details[v]=JSON.parse(e.details[v]);
|
||||
if(!e.details[v])e.details[v]={};
|
||||
s.group[e.ke].mon[e.id].details = e.details;
|
||||
if(!e.details[v] || e.details[v] === '')e.details[v] = '{}'
|
||||
e.details[v] = s.parseJSON(e.details[v])
|
||||
if(!e.details[v])e.details[v] = {}
|
||||
s.group[e.ke].mon[e.id].details = e.details
|
||||
switch(v){
|
||||
case'cords':
|
||||
s.group[e.ke].mon[e.id].parsedObjects[v] = Object.values(s.parseJSON(e.details[v]))
|
||||
break;
|
||||
default:
|
||||
s.group[e.ke].mon[e.id].parsedObjects[v] = s.parseJSON(e.details[v])
|
||||
break;
|
||||
}
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
|
@ -776,7 +787,47 @@ module.exports = function(s,config,lang){
|
|||
if(e.type==='jpeg'){
|
||||
s.cameraPullJpegStream(e)
|
||||
}
|
||||
if(e.details.detector === '1'){
|
||||
if(e.details.detector_audio === '1'){
|
||||
var triggerLevel
|
||||
var triggerLevelMax
|
||||
if(e.details.detector_audio_min_db && e.details.detector_audio_min_db !== ''){
|
||||
triggerLevel = parseInt(e.details.detector_audio_min_db)
|
||||
}else{
|
||||
triggerLevel = 5
|
||||
}
|
||||
if(e.details.detector_audio_max_db && e.details.detector_audio_max_db !== ''){
|
||||
triggerLevelMax = parseInt(e.details.detector_audio_max_db)
|
||||
}
|
||||
var audioDetector = new SoundDetection({
|
||||
format: {
|
||||
bitDepth: 16,
|
||||
numberOfChannels: 1,
|
||||
signed: true
|
||||
},
|
||||
triggerLevel: triggerLevel,
|
||||
triggerLevelMax: triggerLevelMax
|
||||
},function(dB) {
|
||||
s.triggerEvent({
|
||||
f:'trigger',
|
||||
id:e.id,
|
||||
ke:e.ke,
|
||||
name: 'db',
|
||||
details:{
|
||||
plug:'audio',
|
||||
name:'db',
|
||||
reason:'soundChange',
|
||||
confidence:dB
|
||||
},
|
||||
plates:[],
|
||||
imgHeight:e.details.detector_scale_y,
|
||||
imgWidth:e.details.detector_scale_x
|
||||
})
|
||||
})
|
||||
s.group[e.ke].mon[e.id].audioDetector = audioDetector
|
||||
audioDetector.start()
|
||||
s.group[e.ke].mon[e.id].spawn.stdio[6].pipe(audioDetector.streamDecoder)
|
||||
}
|
||||
if(e.details.detector === '1' && e.coProcessor === false){
|
||||
s.ocvTx({f:'init_monitor',id:e.id,ke:e.ke})
|
||||
//frames from motion detect
|
||||
if(e.details.detector_pam === '1'){
|
||||
|
@ -865,7 +916,11 @@ module.exports = function(s,config,lang){
|
|||
break;
|
||||
}
|
||||
if(e.frameToStream){
|
||||
s.group[e.ke].mon[e.id].spawn.stdout.on('data',e.frameToStream)
|
||||
if(e.coProcessor === true && e.details.stream_type === ('b64'||'mjpeg')){
|
||||
|
||||
}else{
|
||||
s.group[e.ke].mon[e.id].spawn.stdout.on('data',e.frameToStream)
|
||||
}
|
||||
}
|
||||
if(e.details.stream_channels && e.details.stream_channels !== ''){
|
||||
var createStreamEmitter = function(channel,number){
|
||||
|
@ -911,6 +966,12 @@ module.exports = function(s,config,lang){
|
|||
s.group[e.ke].mon[e.id].spawn.stderr.on('data',function(d){
|
||||
d=d.toString();
|
||||
switch(true){
|
||||
// case checkLog(d,'No space left on device'):
|
||||
//
|
||||
// break;
|
||||
case checkLog(d,'error while decoding'):
|
||||
s.userLog(e,{type:lang['Error While Decoding'],msg:lang.ErrorWhileDecodingText});
|
||||
break;
|
||||
case checkLog(d,'[hls @'):
|
||||
case checkLog(d,'Past duration'):
|
||||
case checkLog(d,'Last message repeated'):
|
||||
|
@ -938,6 +999,7 @@ module.exports = function(s,config,lang){
|
|||
case checkLog(d,'mjpeg_decode_dc'):
|
||||
case checkLog(d,'bad vlc'):
|
||||
case checkLog(d,'error dc'):
|
||||
case checkLog(d,'No route to host'):
|
||||
s.launchMonitorProcesses(e)
|
||||
break;
|
||||
case /T[0-9][0-9]-[0-9][0-9]-[0-9][0-9]./.test(d):
|
||||
|
@ -999,7 +1061,7 @@ module.exports = function(s,config,lang){
|
|||
e.detector_notrigger_timeout = parseFloat(e.details.detector_notrigger_timeout)*1000*60;
|
||||
s.group[e.ke].mon[e.id].detector_notrigger_timeout_function = function(){
|
||||
s.onDetectorNoTriggerTimeoutExtensions.forEach(function(extender){
|
||||
extender(r,e)
|
||||
extender(e)
|
||||
})
|
||||
}
|
||||
clearInterval(s.group[e.ke].mon[e.id].detector_notrigger_timeout)
|
||||
|
@ -1012,7 +1074,11 @@ module.exports = function(s,config,lang){
|
|||
if(s.group[e.ke].mon[e.id].isStarted === true){
|
||||
fs.stat(e.sdir+'s.jpg',function(err,snap){
|
||||
var notStreaming = function(){
|
||||
s.launchMonitorProcesses(e)
|
||||
if(e.coProcessor === true){
|
||||
s.coSpawnLauncher(e)
|
||||
}else{
|
||||
s.launchMonitorProcesses(e)
|
||||
}
|
||||
s.userLog(e,{type:lang['Camera is not streaming'],msg:{msg:lang['Restarting Process']}})
|
||||
s.orphanedVideoCheck(e,2,null,true)
|
||||
}
|
||||
|
@ -1097,6 +1163,11 @@ module.exports = function(s,config,lang){
|
|||
){
|
||||
s.cameraFilterFfmpegLog(e)
|
||||
}
|
||||
if(e.coProcessor === true){
|
||||
setTimeout(function(){
|
||||
s.coSpawnLauncher(e)
|
||||
},6000)
|
||||
}
|
||||
s.onMonitorStartExtensions.forEach(function(extender){
|
||||
extender(Object.assign(s.group[e.ke].mon_conf[e.id],{}),e)
|
||||
})
|
||||
|
@ -1435,8 +1506,8 @@ module.exports = function(s,config,lang){
|
|||
s.group[e.ke].mon[e.mid].isRecording = false
|
||||
}
|
||||
//set up fatal error handler
|
||||
if(e.details.fatal_max===''){
|
||||
e.details.fatal_max = 10
|
||||
if(e.details.fatal_max === ''){
|
||||
e.details.fatal_max = 0
|
||||
}else{
|
||||
e.details.fatal_max = parseFloat(e.details.fatal_max)
|
||||
}
|
||||
|
@ -1454,4 +1525,48 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
if(typeof cn === 'function'){setTimeout(function(){cn()},1000)}
|
||||
}
|
||||
//
|
||||
s.activateMonitorStates = function(groupKey,stateName,user,callback){
|
||||
var endData = {
|
||||
ok: false
|
||||
}
|
||||
s.findPreset([groupKey,'monitorStates',stateName],function(notFound,preset){
|
||||
if(notFound === false){
|
||||
var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND '
|
||||
var monitorQuery = []
|
||||
var sqlQueryValues = [groupKey]
|
||||
var monitorPresets = {}
|
||||
preset.details.monitors.forEach(function(monitor){
|
||||
monitorQuery.push('mid=?')
|
||||
sqlQueryValues.push(monitor.mid)
|
||||
monitorPresets[monitor.mid] = monitor
|
||||
})
|
||||
sqlQuery += '('+monitorQuery.join(' OR ')+')'
|
||||
s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){
|
||||
if(monitors && monitors[0]){
|
||||
monitors.forEach(function(monitor){
|
||||
s.checkDetails(monitor)
|
||||
s.checkDetails(monitorPresets[monitor.mid])
|
||||
var monitorPreset = monitorPresets[monitor.mid]
|
||||
monitorPreset.details = Object.assign(monitor.details,monitorPreset.details)
|
||||
monitor = s.cleanMonitorObjectForDatabase(Object.assign(monitor,monitorPreset))
|
||||
monitor.details = JSON.stringify(monitor.details)
|
||||
s.addOrEditMonitor(Object.assign(monitor,{}),function(err,endData){
|
||||
|
||||
},user)
|
||||
})
|
||||
endData.ok = true
|
||||
s.tx({f:'change_group_state',ke:groupKey,name:stateName},'GRP_'+groupKey)
|
||||
callback(endData)
|
||||
}else{
|
||||
endData.msg = user.lang['State Configuration has no monitors associated']
|
||||
callback(endData)
|
||||
}
|
||||
})
|
||||
}else{
|
||||
endData.msg = user.lang['State Configuration Not Found']
|
||||
callback(endData)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
var fs = require("fs")
|
||||
var Discord = require("discord.js")
|
||||
module.exports = function(s,config,lang){
|
||||
//discord bot
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
module.exports = function(s,config,lang,app,io){
|
||||
s.schedules = {}
|
||||
//Get all Schedules
|
||||
s.getAllSchedules = function(callback){
|
||||
s.schedules = {}
|
||||
s.sqlQuery('SELECT * FROM Schedules',function(err,rows){
|
||||
rows.forEach(function(schedule){
|
||||
s.updateSchedule(schedule)
|
||||
})
|
||||
if(callback)callback()
|
||||
})
|
||||
}
|
||||
//update schedule
|
||||
s.updateSchedule = function(row){
|
||||
var schedule = Object.assign(row,{})
|
||||
if(!s.schedules[schedule.ke])s.schedules[schedule.ke] = {}
|
||||
s.checkDetails(schedule)
|
||||
if(!s.schedules[schedule.ke][schedule.name]){
|
||||
s.schedules[schedule.ke][schedule.name] = schedule
|
||||
}else{
|
||||
s.schedules[schedule.ke][schedule.name] = Object.assign(s.schedules[schedule.ke][schedule.name],schedule)
|
||||
}
|
||||
}
|
||||
//check time in schedule
|
||||
s.checkTimeAgainstSchedule = function(start,end,callback){
|
||||
try{
|
||||
if(
|
||||
start
|
||||
){
|
||||
var checkStartTime = new Date()
|
||||
var startSplit = start.split(':')
|
||||
var startHour = parseInt(startSplit[0])
|
||||
var startMin = parseInt(startSplit[1])
|
||||
checkStartTime.setHours(startHour)
|
||||
checkStartTime.setMinutes(startMin)
|
||||
if(end){
|
||||
var checkEndTime = new Date()
|
||||
var endSplit = end.split(':')
|
||||
var endHour = parseInt(endSplit[0])
|
||||
var endMin = parseInt(endSplit[1])
|
||||
checkEndTime.setHours(endHour)
|
||||
checkEndTime.setMinutes(endMin)
|
||||
}
|
||||
var currentDate = new Date()
|
||||
if(
|
||||
(
|
||||
currentDate >= checkStartTime &&
|
||||
currentDate <= checkEndTime
|
||||
) ||
|
||||
currentDate >= checkStartTime && !end
|
||||
){
|
||||
callback()
|
||||
}else{
|
||||
callback({
|
||||
currentDate : currentDate,
|
||||
startTime : checkStartTime,
|
||||
endTime : checkEndTime
|
||||
})
|
||||
}
|
||||
}else{
|
||||
callback()
|
||||
}
|
||||
}catch(err){
|
||||
console.log(err)
|
||||
callback()
|
||||
}
|
||||
}
|
||||
//check all Schedules
|
||||
s.checkSchedules = function(v,callback){
|
||||
var groupKeys = Object.keys(s.schedules)
|
||||
groupKeys.forEach(function(key){
|
||||
var scheduleNames = Object.keys(s.schedules[key])
|
||||
scheduleNames.forEach(function(name){
|
||||
var schedule = s.schedules[key][name]
|
||||
if(!schedule.active && schedule.enabled === 1 && schedule.start && schedule.details.monitorStates){
|
||||
s.checkTimeAgainstSchedule(schedule.start,schedule.end,function(err){
|
||||
if(!err){
|
||||
schedule.active = true
|
||||
var monitorStates = schedule.details.monitorStates
|
||||
monitorStates.forEach(function(stateName){
|
||||
s.activateMonitorStates(key,stateName,{
|
||||
ke: key,
|
||||
uid: 'System',
|
||||
details: {},
|
||||
permissions: {},
|
||||
lang: lang
|
||||
},function(endData){
|
||||
// console.log(endData)
|
||||
})
|
||||
})
|
||||
}else{
|
||||
schedule.active = false
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
//
|
||||
s.findSchedule = function(groupKey,name,callback){
|
||||
//presetQueryVals = [ke, type, name]
|
||||
s.sqlQuery("SELECT * FROM Schedules WHERE ke=? AND name=? LIMIT 1",[groupKey,name],function(err,schedules){
|
||||
var schedule
|
||||
var notFound = false
|
||||
if(schedules && schedules[0]){
|
||||
schedule = schedules[0]
|
||||
s.checkDetails(schedule)
|
||||
}else{
|
||||
notFound = true
|
||||
}
|
||||
callback(notFound,schedule)
|
||||
})
|
||||
}
|
||||
//
|
||||
var onProcessReady = function(){
|
||||
s.getAllSchedules(function(){
|
||||
s.checkSchedules()
|
||||
})
|
||||
setInterval(function(){
|
||||
s.checkSchedules()
|
||||
},1000 * 60 * 5)
|
||||
}
|
||||
/**
|
||||
* WebServerPath : API : Get Schedule
|
||||
*/
|
||||
app.all([
|
||||
config.webPaths.apiPrefix+':auth/schedule/:ke',
|
||||
config.webPaths.adminApiPrefix+':auth/schedule/:ke',
|
||||
config.webPaths.apiPrefix+':auth/schedule/:ke/:name',
|
||||
config.webPaths.adminApiPrefix+':auth/schedule/:ke/:name',
|
||||
config.webPaths.apiPrefix+':auth/schedules/:ke',
|
||||
config.webPaths.adminApiPrefix+':auth/schedules/:ke',
|
||||
config.webPaths.apiPrefix+':auth/schedules/:ke/:name',
|
||||
config.webPaths.adminApiPrefix+':auth/schedules/:ke/:name',
|
||||
],function (req,res){
|
||||
s.auth(req.params,function(user){
|
||||
var endData = {
|
||||
ok : false
|
||||
}
|
||||
if(user.details.sub){
|
||||
endData.msg = user.lang['Not Permitted']
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var theQuery = "SELECT * FROM Schedules WHERE ke=?"
|
||||
var theQueryValues = [req.params.ke]
|
||||
if(req.params.name){
|
||||
theQuery += ' AND name=?'
|
||||
theQueryValues.push(req.params.name)
|
||||
}
|
||||
s.sqlQuery(theQuery,theQueryValues,function(err,schedules){
|
||||
if(schedules && schedules[0]){
|
||||
endData.ok = true
|
||||
schedules.forEach(function(schedule){
|
||||
s.checkDetails(schedule)
|
||||
})
|
||||
endData.schedules = schedules
|
||||
}else{
|
||||
endData.msg = user.lang['Not Found']
|
||||
}
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
})
|
||||
})
|
||||
/**
|
||||
* WebServerPath : API : Update Schedule
|
||||
*/
|
||||
app.all([
|
||||
config.webPaths.apiPrefix+':auth/schedule/:ke/:name/:action',
|
||||
config.webPaths.adminApiPrefix+':auth/schedule/:ke/:name/:action',
|
||||
config.webPaths.apiPrefix+':auth/schedules/:ke/:name/:action',
|
||||
config.webPaths.adminApiPrefix+':auth/schedules/:ke/:name/:action'
|
||||
],function (req,res){
|
||||
s.auth(req.params,function(user){
|
||||
var endData = {
|
||||
ok : false
|
||||
}
|
||||
if(user.details.sub){
|
||||
endData.msg = user.lang['Not Permitted']
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
switch(req.params.action){
|
||||
case'insert':case'edit':
|
||||
var form = s.getPostData(req)
|
||||
s.checkDetails(form)
|
||||
if(!form || !form.details){
|
||||
endData.msg = user.lang['Form Data Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
form.enabled = parseInt(form.enabled) || 1;
|
||||
s.findSchedule(req.params.ke,req.params.name,function(notFound,preset){
|
||||
if(notFound === true){
|
||||
endData.msg = lang["Inserted Schedule Configuration"]
|
||||
var insertData = {
|
||||
ke: req.params.ke,
|
||||
name: req.params.name,
|
||||
details: s.stringJSON(form.details),
|
||||
start: form.start,
|
||||
end: form.end,
|
||||
enabled: form.enabled
|
||||
}
|
||||
s.sqlQuery('INSERT INTO Schedules ('+Object.keys(insertData).join(',')+') VALUES (?,?,?,?,?,?)',Object.values(insertData))
|
||||
s.tx({
|
||||
f: 'add_schedule',
|
||||
insertData: insertData,
|
||||
ke: req.params.ke,
|
||||
name: req.params.name
|
||||
},'GRP_'+req.params.ke)
|
||||
}else{
|
||||
endData.msg = lang["Edited Schedule Configuration"]
|
||||
var insertData = {
|
||||
details: s.stringJSON(form.details),
|
||||
start: form.start,
|
||||
end: form.end,
|
||||
enabled: form.enabled,
|
||||
ke: req.params.ke,
|
||||
name: req.params.name
|
||||
}
|
||||
s.sqlQuery('UPDATE Schedules SET details=?,start=?,end=?,enabled=? WHERE ke=? AND name=?',Object.values(insertData))
|
||||
s.tx({
|
||||
f: 'edit_schedule',
|
||||
insertData: insertData,
|
||||
ke: req.params.ke,
|
||||
name: req.params.name
|
||||
},'GRP_'+req.params.ke)
|
||||
}
|
||||
s.updateSchedule({
|
||||
ke: req.params.ke,
|
||||
name: req.params.name,
|
||||
details: s.stringJSON(form.details),
|
||||
start: form.start,
|
||||
end: form.end,
|
||||
enabled: form.enabled
|
||||
})
|
||||
endData.ok = true
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
break;
|
||||
case'delete':
|
||||
s.findSchedule(req.params.ke,req.params.name,function(notFound,schedule){
|
||||
if(notFound === true){
|
||||
endData.msg = user.lang['Schedule Configuration Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
}else{
|
||||
s.sqlQuery('DELETE FROM Schedules WHERE ke=? AND name=?',[req.params.ke,req.params.name],function(err){
|
||||
if(!err){
|
||||
endData.msg = lang["Deleted Schedule Configuration"]
|
||||
endData.ok = true
|
||||
if(s.schedules[schedule.ke])delete(s.schedules[schedule.ke][schedule.name])
|
||||
}
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
}
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
//bind events
|
||||
s.onProcessReady(onProcessReady)
|
||||
}
|
|
@ -1365,7 +1365,7 @@ module.exports = function(s,config,lang,io){
|
|||
if(cn.cron){
|
||||
delete(s.cron);
|
||||
}
|
||||
if(cn.ocv){
|
||||
if(cn.ocv && s.ocv){
|
||||
s.tx({f:'detector_unplugged',plug:s.ocv.plug},'CPU')
|
||||
delete(s.ocv);
|
||||
delete(s.api[cn.id])
|
||||
|
|
10
libs/sql.js
10
libs/sql.js
|
@ -10,6 +10,12 @@ module.exports = function(s,config){
|
|||
if(s.databaseOptions.client.indexOf('sqlite')>-1){
|
||||
s.databaseOptions.client = 'sqlite3';
|
||||
s.databaseOptions.useNullAsDefault = true;
|
||||
try{
|
||||
require('sqlite3')
|
||||
}catch(err){
|
||||
console.log('Installing SQlite3 Module...')
|
||||
require('child_process').execSync('npm install sqlite3 --unsafe-perm')
|
||||
}
|
||||
}
|
||||
if(s.databaseOptions.client === 'sqlite3' && s.databaseOptions.connection.filename === undefined){
|
||||
s.databaseOptions.connection.filename = s.mainDirectory+"/shinobi.sqlite"
|
||||
|
@ -99,6 +105,10 @@ module.exports = function(s,config){
|
|||
},true)
|
||||
}
|
||||
},true)
|
||||
//add Schedules table, will remove in future
|
||||
s.sqlQuery("CREATE TABLE IF NOT EXISTS `Schedules` (`ke` varchar(50) DEFAULT NULL,`name` text,`details` text,`start` varchar(10) DEFAULT NULL,`end` varchar(10) DEFAULT NULL,`enabled` int(1) NOT NULL DEFAULT '1')" + mySQLtail + ';',[],function(err){
|
||||
if(err)console.error(err)
|
||||
},true)
|
||||
//add Cloud Videos table, will remove in future
|
||||
s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\',`details` text)' + mySQLtail + ';',[],function(err){
|
||||
if(err)console.error(err)
|
||||
|
|
|
@ -4,16 +4,33 @@ var moment = require('moment');
|
|||
var crypto = require('crypto');
|
||||
var exec = require('child_process').exec;
|
||||
var execSync = require('child_process').execSync;
|
||||
module.exports = function(s,config,lang,io,processReady){
|
||||
module.exports = function(s,config,lang,io,){
|
||||
console.log('FFmpeg version : '+s.ffmpegVersion)
|
||||
console.log('Node.js version : '+execSync("node -v"))
|
||||
s.processReady = function(){
|
||||
s.systemLog(lang.startUpText5)
|
||||
process.send('ready')
|
||||
s.onProcessReadyExtensions.forEach(function(extender){
|
||||
extender(true)
|
||||
})
|
||||
if(processReady)processReady()
|
||||
process.send('ready')
|
||||
}
|
||||
var checkForTerminalCommands = function(callback){
|
||||
var next = function(){
|
||||
if(callback)callback()
|
||||
}
|
||||
if(!s.isWin){
|
||||
var etcPath = '/etc/shinobisystems/cctv.txt'
|
||||
fs.stat(etcPath,function(err,stat){
|
||||
if(err || !stat){
|
||||
exec('node '+ s.mainDirectory + '/INSTALL/terminalCommands.js',function(err){
|
||||
if(err)console.log(err)
|
||||
})
|
||||
}
|
||||
next()
|
||||
})
|
||||
}else{
|
||||
next()
|
||||
}
|
||||
}
|
||||
var loadedAccounts = []
|
||||
var loadMonitors = function(callback){
|
||||
|
@ -151,6 +168,9 @@ module.exports = function(s,config,lang,io,processReady){
|
|||
})
|
||||
})
|
||||
},10000)
|
||||
//hourly check to see if sizePurge has failed to unlock
|
||||
//checks to see if request count is the number of monitors + 10
|
||||
s.checkForStalePurgeLocks()
|
||||
//run prerequsite queries, load users and monitors
|
||||
if(config.childNodes.mode !== 'child'){
|
||||
//sql/database connection with knex
|
||||
|
@ -158,11 +178,13 @@ module.exports = function(s,config,lang,io,processReady){
|
|||
//run prerequsite queries
|
||||
s.preQueries()
|
||||
setTimeout(function(){
|
||||
//load administrators (groups)
|
||||
loadAdminUsers(function(){
|
||||
//load monitors (for groups)
|
||||
loadMonitors(function(){
|
||||
s.processReady()
|
||||
checkForTerminalCommands(function(){
|
||||
//load administrators (groups)
|
||||
loadAdminUsers(function(){
|
||||
//load monitors (for groups)
|
||||
loadMonitors(function(){
|
||||
s.processReady()
|
||||
})
|
||||
})
|
||||
})
|
||||
},1500)
|
||||
|
|
49
libs/user.js
49
libs/user.js
|
@ -15,7 +15,7 @@ module.exports = function(s,config){
|
|||
if(s.group[e.ke].sizePurgeQueue.length > 0){
|
||||
checkQueue()
|
||||
}else{
|
||||
s.group[e.ke].sizePurging=false
|
||||
s.group[e.ke].sizePurging = false
|
||||
s.sendDiskUsedAmountToClients(e)
|
||||
}
|
||||
}
|
||||
|
@ -260,11 +260,11 @@ module.exports = function(s,config){
|
|||
d.form.details.use_admin=d.d.use_admin
|
||||
d.form.details.use_ldap=d.d.use_ldap
|
||||
//check
|
||||
if(d.d.edit_days=="0"){
|
||||
d.form.details.days=d.d.days;
|
||||
if(d.d.edit_days == "0"){
|
||||
d.form.details.days = d.d.days;
|
||||
}
|
||||
if(d.d.edit_size=="0"){
|
||||
d.form.details.size=d.d.size;
|
||||
if(d.d.edit_size == "0"){
|
||||
d.form.details.size = d.d.size;
|
||||
}
|
||||
if(d.d.sub){
|
||||
d.form.details.sub=d.d.sub;
|
||||
|
@ -308,4 +308,43 @@ module.exports = function(s,config){
|
|||
}
|
||||
})
|
||||
}
|
||||
s.findPreset = function(presetQueryVals,callback){
|
||||
//presetQueryVals = [ke, type, name]
|
||||
s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",presetQueryVals,function(err,presets){
|
||||
var preset
|
||||
var notFound = false
|
||||
if(presets && presets[0]){
|
||||
preset = presets[0]
|
||||
s.checkDetails(preset)
|
||||
}else{
|
||||
notFound = true
|
||||
}
|
||||
callback(notFound,preset)
|
||||
})
|
||||
}
|
||||
if(config.cron.deleteOverMax === true){
|
||||
s.checkForStalePurgeLocks = function(){
|
||||
var doCheck = function(){
|
||||
Object.keys(s.group).forEach(function(groupKey){
|
||||
var userGroup = s.group[groupKey]
|
||||
var monitorCount = 10
|
||||
if(userGroup.mon)monitorCount = Object.keys(userGroup.mon).length
|
||||
var purgeRequestCount = userGroup.sizePurgeQueue.length
|
||||
var isLocked = (userGroup.sizePurging === true)
|
||||
if(isLocked && purgeRequestCount > monitorCount + 10){
|
||||
s.group[groupKey].sizePurgeQueue = []
|
||||
s.group[groupKey].sizePurging = false
|
||||
s.systemLog(lang.sizePurgeLockedText + ' : ' + groupKey)
|
||||
}
|
||||
})
|
||||
}
|
||||
clearTimeout(s.checkForStalePurgeLocksInterval)
|
||||
s.checkForStalePurgeLocksInterval = setInterval(function(){
|
||||
doCheck()
|
||||
},1000 * 60 * 60)
|
||||
doCheck()
|
||||
}
|
||||
}else{
|
||||
s.checkForStalePurgeLocks = function(){}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -419,19 +419,7 @@ module.exports = function(s,config,lang,app){
|
|||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var findPreset = function(callback){
|
||||
s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",[req.params.ke,'monitorStates',req.params.stateName],function(err,presets){
|
||||
var preset
|
||||
var notFound = false
|
||||
if(presets && presets[0]){
|
||||
preset = presets[0]
|
||||
s.checkDetails(preset)
|
||||
}else{
|
||||
notFound = true
|
||||
}
|
||||
callback(notFound,preset)
|
||||
})
|
||||
}
|
||||
var presetQueryVals = [req.params.ke,'monitorStates',req.params.stateName]
|
||||
switch(req.params.action){
|
||||
case'insert':case'edit':
|
||||
var form = s.getPostData(req)
|
||||
|
@ -441,7 +429,7 @@ module.exports = function(s,config,lang,app){
|
|||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
findPreset(function(notFound,preset){
|
||||
s.findPreset(presetQueryVals,function(notFound,preset){
|
||||
if(notFound === true){
|
||||
endData.msg = lang["Inserted State Configuration"]
|
||||
var details = {
|
||||
|
@ -478,7 +466,7 @@ module.exports = function(s,config,lang,app){
|
|||
})
|
||||
break;
|
||||
case'delete':
|
||||
findPreset(function(notFound,preset){
|
||||
s.findPreset(presetQueryVals,function(notFound,preset){
|
||||
if(notFound === true){
|
||||
endData.msg = user.lang['State Configuration Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
|
@ -494,43 +482,8 @@ module.exports = function(s,config,lang,app){
|
|||
})
|
||||
break;
|
||||
default://change monitors according to state
|
||||
findPreset(function(notFound,preset){
|
||||
if(notFound === false){
|
||||
var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND '
|
||||
var monitorQuery = []
|
||||
var sqlQueryValues = [req.params.ke]
|
||||
var monitorPresets = {}
|
||||
preset.details.monitors.forEach(function(monitor){
|
||||
monitorQuery.push('mid=?')
|
||||
sqlQueryValues.push(monitor.mid)
|
||||
monitorPresets[monitor.mid] = monitor
|
||||
})
|
||||
sqlQuery += '('+monitorQuery.join(' OR ')+')'
|
||||
s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){
|
||||
if(monitors && monitors[0]){
|
||||
monitors.forEach(function(monitor){
|
||||
s.checkDetails(monitor)
|
||||
s.checkDetails(monitorPresets[monitor.mid])
|
||||
var monitorPreset = monitorPresets[monitor.mid]
|
||||
monitorPreset.details = Object.assign(monitor.details,monitorPreset.details)
|
||||
monitor = s.cleanMonitorObjectForDatabase(Object.assign(monitor,monitorPreset))
|
||||
monitor.details = JSON.stringify(monitor.details)
|
||||
s.addOrEditMonitor(Object.assign(monitor,{}),function(err,endData){
|
||||
|
||||
},user)
|
||||
})
|
||||
endData.ok = true
|
||||
s.tx({f:'change_group_state',ke:req.params.ke,name:req.params.stateName},'GRP_'+req.params.ke)
|
||||
s.closeJsonResponse(res,endData)
|
||||
}else{
|
||||
endData.msg = user.lang['State Configuration has no monitors associated']
|
||||
s.closeJsonResponse(res,endData)
|
||||
}
|
||||
})
|
||||
}else{
|
||||
endData.msg = user.lang['State Configuration Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
}
|
||||
s.activateMonitorStates(req.params.ke,req.params.stateName,user,function(endData){
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ var execSync = require('child_process').execSync;
|
|||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
var httpProxy = require('http-proxy');
|
||||
var onvif = require('node-onvif');
|
||||
var proxy = httpProxy.createProxyServer({})
|
||||
var ejs = require('ejs');
|
||||
var CircularJSON = require('circular-json');
|
||||
|
@ -286,7 +287,8 @@ module.exports = function(s,config,lang,app,io){
|
|||
// config: config,
|
||||
$user: req.resp,
|
||||
lang: r.lang,
|
||||
define: s.getDefinitonFile(r.details.lang)
|
||||
define: s.getDefinitonFile(r.details.lang),
|
||||
customAutoLoad: s.customAutoLoadTree
|
||||
})
|
||||
})
|
||||
break;
|
||||
|
@ -297,7 +299,8 @@ module.exports = function(s,config,lang,app,io){
|
|||
// config: config,
|
||||
$user: req.resp,
|
||||
lang: r.lang,
|
||||
define: s.getDefinitonFile(r.details.lang)
|
||||
define: s.getDefinitonFile(r.details.lang),
|
||||
customAutoLoad: s.customAutoLoadTree
|
||||
})
|
||||
})
|
||||
break;
|
||||
|
@ -311,17 +314,36 @@ module.exports = function(s,config,lang,app,io){
|
|||
$subs: rr,
|
||||
$mons: rrr,
|
||||
lang: r.lang,
|
||||
define: s.getDefinitonFile(r.details.lang)
|
||||
define: s.getDefinitonFile(r.details.lang),
|
||||
customAutoLoad: s.customAutoLoadTree
|
||||
})
|
||||
})
|
||||
})
|
||||
}else{
|
||||
//not admin user
|
||||
renderPage(config.renderPaths.home,{$user:req.resp,config:config,lang:r.lang,define:s.getDefinitonFile(r.details.lang),addStorage:s.dir.addStorage,fs:fs,__dirname:s.mainDirectory});
|
||||
renderPage(config.renderPaths.home,{
|
||||
$user:req.resp,
|
||||
config:config,
|
||||
lang:r.lang,
|
||||
define:s.getDefinitonFile(r.details.lang),
|
||||
addStorage:s.dir.addStorage,
|
||||
fs:fs,
|
||||
__dirname:s.mainDirectory,
|
||||
customAutoLoad: s.customAutoLoadTree
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
renderPage(config.renderPaths.home,{$user:req.resp,config:config,lang:r.lang,define:s.getDefinitonFile(r.details.lang),addStorage:s.dir.addStorage,fs:fs,__dirname:s.mainDirectory});
|
||||
renderPage(config.renderPaths.home,{
|
||||
$user:req.resp,
|
||||
config:config,
|
||||
lang:r.lang,
|
||||
define:s.getDefinitonFile(r.details.lang),
|
||||
addStorage:s.dir.addStorage,
|
||||
fs:fs,
|
||||
__dirname:s.mainDirectory,
|
||||
customAutoLoad: s.customAutoLoadTree
|
||||
});
|
||||
break;
|
||||
}
|
||||
s.userLog({ke:r.ke,mid:'$USER'},{type:r.lang['New Authentication Token'],msg:{for:req.body.function,mail:r.mail,id:r.uid,ip:req.ip}})
|
||||
|
@ -511,6 +533,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
r=[]
|
||||
}
|
||||
data.Logs = r
|
||||
data.customAutoLoad = s.customAutoLoadTree
|
||||
fs.readFile(s.location.config,'utf8',function(err,file){
|
||||
data.plainConfig = JSON.parse(file)
|
||||
renderPage(config.renderPaths.super,data)
|
||||
|
@ -1375,7 +1398,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
values.push(time)
|
||||
})
|
||||
s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){
|
||||
var resp = {ok:false}
|
||||
var resp = {ok: false}
|
||||
if(r && r[0]){
|
||||
resp.ok = true
|
||||
var zipDownload = null
|
||||
|
@ -1396,7 +1419,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
fs.mkdirSync(fileBinDir);
|
||||
}
|
||||
r.forEach(function(video){
|
||||
timeFormatted = s.formattedTime(video.time)
|
||||
var timeFormatted = s.formattedTime(video.time)
|
||||
video.filename = timeFormatted+'.'+video.ext
|
||||
var dir = s.getVideoDirectory(video)+video.filename
|
||||
var tempVideoFile = timeFormatted+' - '+video.mid+'.'+video.ext
|
||||
|
@ -1418,16 +1441,27 @@ module.exports = function(s,config,lang,app,io){
|
|||
var zipDownload = fs.createReadStream(zippedFile)
|
||||
zipDownload.pipe(res)
|
||||
zipDownload.on('error', function (error) {
|
||||
s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Download Error',msg:error.toString()})
|
||||
var errorString = error.toString()
|
||||
s.userLog({
|
||||
ke: req.params.ke,
|
||||
mid: '$USER'
|
||||
},{
|
||||
title: 'Zip Download Error',
|
||||
msg: errorString
|
||||
})
|
||||
if(zipDownload && zipDownload.destroy){
|
||||
zipDownload.destroy()
|
||||
}
|
||||
});
|
||||
res.end(s.prettyPrint({
|
||||
ok: false,
|
||||
msg: errorString
|
||||
}))
|
||||
})
|
||||
zipDownload.on('close', function () {
|
||||
res.end()
|
||||
zipDownload.destroy();
|
||||
fs.unlinkSync(zippedFile);
|
||||
});
|
||||
zipDownload.destroy()
|
||||
fs.unlinkSync(zippedFile)
|
||||
})
|
||||
})
|
||||
}else{
|
||||
failed({ok:false,msg:'No Videos Found'})
|
||||
|
@ -1437,7 +1471,121 @@ module.exports = function(s,config,lang,app,io){
|
|||
}else{
|
||||
failed({ok:false,msg:'"videos" query variable is missing from request.'})
|
||||
}
|
||||
});
|
||||
})
|
||||
/**
|
||||
* API : Zip Cloud Videos and Get Link from fileBin
|
||||
*/
|
||||
app.get(config.webPaths.apiPrefix+':auth/zipCloudVideos/:ke', function (req,res){
|
||||
res.header("Access-Control-Allow-Origin",req.headers.origin);
|
||||
var failed = function(resp){
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(s.prettyPrint(resp))
|
||||
}
|
||||
if(req.query.videos && req.query.videos !== ''){
|
||||
s.auth(req.params,function(user){
|
||||
var videosSelected = JSON.parse(req.query.videos)
|
||||
var where = []
|
||||
var values = []
|
||||
videosSelected.forEach(function(video){
|
||||
where.push("(ke=? AND mid=? AND `time`=?)")
|
||||
if(!video.ke)video.ke = req.params.ke
|
||||
values.push(video.ke)
|
||||
values.push(video.mid)
|
||||
var time = s.nameToTime(video.filename)
|
||||
if(req.query.isUTC === 'true'){
|
||||
time = s.utcToLocal(time)
|
||||
}
|
||||
time = new Date(time)
|
||||
values.push(time)
|
||||
})
|
||||
s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE '+where.join(' OR '),values,function(err,r){
|
||||
var resp = {ok: false}
|
||||
if(r && r[0]){
|
||||
resp.ok = true
|
||||
var zipDownload = null
|
||||
var tempFiles = []
|
||||
var fileId = s.gid()
|
||||
var fileBinDir = s.dir.fileBin+req.params.ke+'/'
|
||||
var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh'
|
||||
var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Cloud_Backed_Recordings.zip'
|
||||
var zippedFile = fileBinDir+zippedFilename
|
||||
var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile
|
||||
res.on('close', () => {
|
||||
if(zipDownload && zipDownload.destroy){
|
||||
zipDownload.destroy()
|
||||
}
|
||||
fs.unlink(zippedFile);
|
||||
})
|
||||
if(!fs.existsSync(fileBinDir)){
|
||||
fs.mkdirSync(fileBinDir);
|
||||
}
|
||||
var cloudDownloadCount = 0
|
||||
var getFile = function(video,completed){
|
||||
if(!video)completed();
|
||||
s.checkDetails(video)
|
||||
var filename = video.href.split('/')
|
||||
filename = filename[filename.length - 1]
|
||||
var timeFormatted = s.formattedTime(video.time)
|
||||
var tempVideoFile = video.details.type + '-' + video.mid + '-' + filename
|
||||
var tempFileWriteStream = fs.createWriteStream(fileBinDir+tempVideoFile)
|
||||
tempFileWriteStream.on('finish', function() {
|
||||
++cloudDownloadCount
|
||||
getFile(r[cloudDownloadCount],completed)
|
||||
})
|
||||
var cloudVideoDownload = request(video.href)
|
||||
cloudVideoDownload.on('response', function (res) {
|
||||
res.pipe(tempFileWriteStream)
|
||||
})
|
||||
tempFiles.push(fileBinDir+tempVideoFile)
|
||||
script += ' "'+tempVideoFile+'"'
|
||||
}
|
||||
getFile(r[cloudDownloadCount],function(){
|
||||
fs.writeFileSync(tempScript,script,'utf8')
|
||||
var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true})
|
||||
zipCreate.stderr.on('data',function(data){
|
||||
s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()})
|
||||
})
|
||||
zipCreate.on('exit',function(data){
|
||||
fs.unlinkSync(tempScript)
|
||||
tempFiles.forEach(function(file){
|
||||
fs.unlink(file,function(){})
|
||||
})
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="' + zippedFilename + '"')
|
||||
var zipDownload = fs.createReadStream(zippedFile)
|
||||
zipDownload.pipe(res)
|
||||
zipDownload.on('error', function (error) {
|
||||
var errorString = error.toString()
|
||||
s.userLog({
|
||||
ke: req.params.ke,
|
||||
mid: '$USER'
|
||||
},{
|
||||
title: 'Zip Download Error',
|
||||
msg: errorString
|
||||
})
|
||||
if(zipDownload && zipDownload.destroy){
|
||||
zipDownload.destroy()
|
||||
}
|
||||
res.end(s.prettyPrint({
|
||||
ok: false,
|
||||
msg: errorString
|
||||
}))
|
||||
})
|
||||
zipDownload.on('close', function () {
|
||||
res.end()
|
||||
zipDownload.destroy()
|
||||
fs.unlinkSync(zippedFile)
|
||||
})
|
||||
})
|
||||
})
|
||||
}else{
|
||||
failed({ok:false,msg:'No Videos Found'})
|
||||
}
|
||||
})
|
||||
},res,req);
|
||||
}else{
|
||||
failed({ok:false,msg:'"videos" query variable is missing from request.'})
|
||||
}
|
||||
})
|
||||
/**
|
||||
* API : Get Cloud Video File (proxy)
|
||||
*/
|
||||
|
@ -1524,27 +1672,34 @@ module.exports = function(s,config,lang,app,io){
|
|||
/**
|
||||
* API : Motion Trigger via GET request
|
||||
*/
|
||||
app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){
|
||||
s.auth(req.params,function(user){
|
||||
if(req.query.data){
|
||||
try{
|
||||
var d={id:req.params.id,ke:req.params.ke,details:JSON.parse(req.query.data)};
|
||||
}catch(err){
|
||||
res.end('Data Broken',err);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
res.end('No Data');
|
||||
return;
|
||||
}
|
||||
if(!d.ke||!d.id||!s.group[d.ke]){
|
||||
res.end(user.lang['No Group with this key exists']);
|
||||
return;
|
||||
}
|
||||
s.triggerEvent(d)
|
||||
res.end(user.lang['Trigger Successful'])
|
||||
},res,req);
|
||||
})
|
||||
app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){
|
||||
s.auth(req.params,function(user){
|
||||
var endData = {
|
||||
|
||||
}
|
||||
if(req.query.data){
|
||||
try{
|
||||
var d = {
|
||||
id: req.params.id,
|
||||
ke: req.params.ke,
|
||||
details: JSON.parse(req.query.data)
|
||||
}
|
||||
}catch(err){
|
||||
res.end('Data Broken',err)
|
||||
return
|
||||
}
|
||||
}else{
|
||||
res.end('No Data')
|
||||
return
|
||||
}
|
||||
if(!d.ke||!d.id||!s.group[d.ke]){
|
||||
res.end(user.lang['No Group with this key exists'])
|
||||
return
|
||||
}
|
||||
s.triggerEvent(d)
|
||||
res.end(user.lang['Trigger Successful'])
|
||||
},res,req)
|
||||
})
|
||||
/**
|
||||
* API : WebHook Tester
|
||||
*/
|
||||
|
|
|
@ -622,4 +622,16 @@ module.exports = function(s,config,lang,app){
|
|||
}
|
||||
},res,req)
|
||||
})
|
||||
/**
|
||||
* API : Superuser : Force Check for Stale Purge Locks
|
||||
*/
|
||||
app.all(config.webPaths.superApiPrefix+':auth/system/checkForStalePurgeLocks', function (req,res){
|
||||
s.superAuth(req.params,function(resp){
|
||||
var endData = {
|
||||
ok : true
|
||||
}
|
||||
s.checkForStalePurgeLocks()
|
||||
res.end(s.prettyPrint(endData))
|
||||
},res,req)
|
||||
})
|
||||
}
|
||||
|
|
29
package.json
29
package.json
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "shinobi",
|
||||
"productName": "Shinobi",
|
||||
"version": "1.0.38",
|
||||
"version": "2.0.0",
|
||||
"description": "CCTV and NVR in Node.js",
|
||||
"main": "camera.js",
|
||||
"bin": "camera.js",
|
||||
"scripts": {
|
||||
"test": "node test.js",
|
||||
"test": "node camera.js test",
|
||||
"start": "chmod +x INSTALL/start.sh && INSTALL/start.sh"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -19,30 +19,33 @@
|
|||
},
|
||||
"homepage": "https://gitlab.com/Shinobi-Systems/Shinobi#readme",
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.279.1",
|
||||
"backblaze-b2": "^1.0.4",
|
||||
"body-parser": "^1.15.2",
|
||||
"circular-json": "0.3.1",
|
||||
"connection-tester": "^0.1.1",
|
||||
"mp4frag": "^0.0.22",
|
||||
"discord.js": "^11.3.2",
|
||||
"ejs": "^2.5.5",
|
||||
"express": "^4.14.0",
|
||||
"http-proxy": "^1.17.0",
|
||||
"jsonfile": "^3.0.1",
|
||||
"moment": "^2.17.0",
|
||||
"mysql": "^2.12.0",
|
||||
"knex": "^0.14.2",
|
||||
"aws-sdk": "^2.279.1",
|
||||
"pam-diff": "^0.10.2",
|
||||
"pipe2pam": "^0.6.2",
|
||||
"nodemailer": "^4.0.1",
|
||||
"ldapauth-fork": "^4.0.2",
|
||||
"moment": "^2.17.0",
|
||||
"mp4frag": "^0.0.22",
|
||||
"mysql": "^2.12.0",
|
||||
"node-onvif": "^0.1.4",
|
||||
"nodemailer": "^4.0.1",
|
||||
"pam-diff": "^0.10.2",
|
||||
"path": "^0.12.7",
|
||||
"pipe2pam": "^0.6.2",
|
||||
"request": "^2.79.0",
|
||||
"socket.io": "^1.7.1",
|
||||
"socket.io-client": "^1.7.2",
|
||||
"http-proxy": "^1.17.0",
|
||||
"sqlite3": "^4.0.4",
|
||||
"webdav-fs": "^1.11.0",
|
||||
"discord.js": "^11.3.2",
|
||||
"backblaze-b2": "^1.0.4",
|
||||
"ldapauth-fork": "^4.0.2"
|
||||
"sat": "^0.7.1",
|
||||
"shinobi-sound-detection": "^0.1.7"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
DIR=`dirname $0`
|
||||
INSTALLERS_DIR="$DIR/../../INSTALL"
|
||||
if ! [ -x "$(command -v dos2unix)" ]; then
|
||||
echo "-----------------------------------"
|
||||
echo "Installing dos2unix"
|
||||
apt install dos2unix -y
|
||||
fi
|
||||
echo "-----------------------------------"
|
||||
if ! [ -x "$(command -v alpr)" ]; then
|
||||
echo "Installing OpenALPR"
|
||||
echo "Do you want to Install OpenALPR with CUDA enabled?"
|
||||
echo "(Y)es or (n)o?"
|
||||
echo "Press [ENTER] for default (Yes)"
|
||||
read openalprcudaenabled
|
||||
if [ "$openalprcudaenabled" = "n" ] || [ "$openalprcudaenabled" = "N" ]; then
|
||||
sed -i -e 's/detector = lbpgpu/detector = lbpcpu/g' "$DIR/openalpr.conf"
|
||||
dos2unix $INSTALLERS_DIR/openalpr-cpu-easy.sh
|
||||
sh $INSTALLERS_DIR/openalpr-cpu-easy.sh
|
||||
else
|
||||
sed -i -e 's/detector = lbpcpu/detector = lbpgpu/g' "$DIR/openalpr.conf"
|
||||
dos2unix $INSTALLERS_DIR/openalpr-gpu-easy.sh
|
||||
sh $INSTALLERS_DIR/openalpr-gpu-easy.sh
|
||||
fi
|
||||
else
|
||||
echo "OpenALPR found... : $(alpr --version)"
|
||||
fi
|
||||
echo "-----------------------------------"
|
||||
if [ ! -e "$DIR/conf.json" ]; then
|
||||
echo "Creating conf.json"
|
||||
cp $DIR/conf.sample.json $DIR/conf.json
|
||||
else
|
||||
echo "conf.json already exists..."
|
||||
fi
|
||||
echo "-----------------------------------"
|
||||
echo "Installing Modules.."
|
||||
npm install --unsafe-perm
|
||||
echo "Finding and Fixing Module Vulnerabilities.."
|
||||
npm audit fix --force
|
||||
echo "Shinobi - Do you want to start the plugin?"
|
||||
echo "(Y)es or (n)o?"
|
||||
echo "Press [ENTER] for default (Yes)"
|
||||
read startplugin
|
||||
if [ "$startplugin" = "n" ] || [ "$startplugin" = "N" ]; then
|
||||
echo "-----------------------------------"
|
||||
echo "Start the plugin with pm2 like so :"
|
||||
echo "pm2 start $DIR/shinobi-openalpr.js"
|
||||
echo "-----------------------------------"
|
||||
echo "Start the plugin without pm2 :"
|
||||
echo "node $DIR/shinobi-openalpr.js"
|
||||
else
|
||||
pm2 start shinobi-openalpr.js
|
||||
pm2 save
|
||||
fi
|
|
@ -1,49 +1,32 @@
|
|||
# OpenALPR and Motion Detector
|
||||
# OpenALPR
|
||||
|
||||
Install required libraries.
|
||||
|
||||
**Ubuntu and Debian only**
|
||||
**Ubuntu 17.10 and 18.04 only**
|
||||
|
||||
```
|
||||
sudo apt update && sudo apt install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev build-essential g++ openalpr openalpr-daemon openalpr-utils libopenalpr-dev -y
|
||||
```
|
||||
> By default plugins run as a client. `camera.js` is running as the host awaiting a plugin to connect to it. To learn about how to connect a plugin as a Host please review the "Run the plugin as a Host" section at the end of this README.
|
||||
|
||||
**Install the Node.js Canvas engine**
|
||||
1. Go to the plugin's directory and run the installer for OpenALPR. **/home/Shinobi** is the default directory for where Shinobi is installed.
|
||||
```
|
||||
cd /home/Shinobi/plugins/openalpr
|
||||
sh INSTALL.sh
|
||||
```
|
||||
|
||||
```
|
||||
sudo npm install canvas@1.6
|
||||
```
|
||||
Go to the Shinobi directory. **Below is an example.**
|
||||
2. Then add the plugin key to the **Main Configuration** file, the `conf.json` located in **/home/Shinobi**. You will find the `pluginKeys` object empty on a new install as seen below.
|
||||
```
|
||||
"pluginKeys":{}
|
||||
```
|
||||
> Add the key so it looks something like this.
|
||||
|
||||
```
|
||||
cd /home/Shinobi
|
||||
```
|
||||
```
|
||||
"pluginKeys":{
|
||||
"OpenALPR": "SomeOpenALPRkeySoPeopleDontMessWithYourShinobi"
|
||||
}
|
||||
```
|
||||
|
||||
Copy the config file.
|
||||
3. Restart Shinobi to apply the Plugin Key. Shinobi does not need to be restarted when a plugin is initiated or stopped after applying changes to the Main Configuration file.
|
||||
|
||||
```
|
||||
cp plugins/openalpr/conf.sample.json plugins/openalpr/conf.json
|
||||
```
|
||||
|
||||
Edit it the new file. Host should be `localhost` and port should match the `listening port for camera.js`.
|
||||
|
||||
```
|
||||
nano plugins/openalpr/conf.json
|
||||
```
|
||||
|
||||
Start the plugin.
|
||||
|
||||
```
|
||||
node plugins/openalpr/shinobi-openalpr.js
|
||||
```
|
||||
|
||||
Or to daemonize with PM2.
|
||||
|
||||
```
|
||||
pm2 start plugins/openalpr/shinobi-openalpr.js
|
||||
```
|
||||
|
||||
Doing this will reveal options in the monitor configuration. Shinobi does not need to be restarted when a plugin is initiated or stopped.
|
||||
> You should change `SomeOpenALPRkeySoPeopleDontMessWithYourShinobi` to something else in both the main configuration and plugin configuration. Both files changed need to be matching keys of course.
|
||||
|
||||
## Run the plugin as a Host
|
||||
> The main app (Shinobi) will be the client and the plugin will be the host. The purpose of allowing this method is so that you can use one plugin for multiple Shinobi instances. Allowing you to easily manage connections without starting multiple processes.
|
||||
|
@ -51,7 +34,7 @@ Doing this will reveal options in the monitor configuration. Shinobi does not ne
|
|||
Edit your plugins configuration file. Set the `hostPort` **to be different** than the `listening port for camera.js`.
|
||||
|
||||
```
|
||||
nano plugins/openalpr/conf.json
|
||||
nano conf.json
|
||||
```
|
||||
|
||||
Here is a sample of a Host configuration for the plugin.
|
||||
|
@ -70,7 +53,7 @@ Here is a sample of a Host configuration for the plugin.
|
|||
}
|
||||
```
|
||||
|
||||
Now modify the **main configuration file** located in the main directory of Shinobi. *Where you currently should be.*
|
||||
Now modify the **Main Configuration** file located in the main directory of Shinobi. *Where you currently should be.*
|
||||
|
||||
```
|
||||
nano conf.json
|
||||
|
@ -90,4 +73,4 @@ Add the `plugins` array if you don't already have it. Add the following *object
|
|||
"type" : "detector"
|
||||
}
|
||||
],
|
||||
```
|
||||
```
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"description": "OpenALPR plugin for Shinobi",
|
||||
"main": "shinobi-openalpr.js",
|
||||
"dependencies": {
|
||||
"canvas": "^1.6.7",
|
||||
"express": "^4.16.2",
|
||||
"moment": "^2.19.2",
|
||||
"socket.io": "^2.0.4"
|
||||
|
|
|
@ -26,7 +26,9 @@ try{
|
|||
}
|
||||
// Base Init />>
|
||||
// OpenALPR Init >>
|
||||
if(config.alprConfig===undefined){config.alprConfig=__dirname+'/openalpr.conf'}
|
||||
if(config.alprConfig === undefined){
|
||||
config.alprConfig = __dirname + '/openalpr.conf'
|
||||
}
|
||||
// OpenALPR Init />>
|
||||
s.detectObject = function(buffer,d,tx,frameLocation){
|
||||
var detectStuff = function(frame){
|
||||
|
|
|
@ -125,6 +125,18 @@ CREATE TABLE IF NOT EXISTS `Files` (
|
|||
`status` int(1) NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `Files` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
-- Dumping structure for table ccio.Schedules
|
||||
CREATE TABLE IF NOT EXISTS `Schedules` (
|
||||
`ke` varchar(50) DEFAULT NULL,
|
||||
`name` text,
|
||||
`details` text,
|
||||
`start` varchar(10) DEFAULT NULL,
|
||||
`end` varchar(10) DEFAULT NULL,
|
||||
`enabled` int(1) NOT NULL DEFAULT '1'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
|
||||
|
|
|
@ -12,7 +12,7 @@ processArgv.forEach(function(val) {
|
|||
var theSplit = val.split('=');
|
||||
var index = theSplit[0];
|
||||
var value = theSplit[1];
|
||||
if(index === 'addToConfig'){
|
||||
if(index.indexOf('addToConfig') > -1){
|
||||
try{
|
||||
value = JSON.parse(value)
|
||||
config = Object.assign(config,value)
|
||||
|
@ -36,4 +36,4 @@ processArgv.forEach(function(val) {
|
|||
jsonfile.writeFile(configLocation,config,{spaces: 2},function(){
|
||||
console.log('Changes Complete. Here is what it is now.')
|
||||
console.log(JSON.stringify(config,null,2))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*Cusotm Bootstrap*/
|
||||
.col-5ths,
|
||||
.col-sm-5ths,
|
||||
.col-md-5ths,
|
||||
.col-lg-5ths {
|
||||
position: relative;
|
||||
min-height: 1px;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.col-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.col-sm-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.col-md-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color:#bd9565;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color:#bd9565;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 10px;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
/**/
|
||||
.flex{display:flex}
|
||||
.flex>div{flex:1}
|
||||
.flex-block{display:inline-flex;width:100%;flex-flow: row wrap;}
|
||||
.flex-unit-3{flex:3}
|
||||
.flex-inline{display: inline-flex;position:relative}
|
||||
@import (less) "../less/pie.less";
|
||||
ul{list-style:none}
|
||||
*{transition:0.2s;box-sizing:border-box}
|
||||
.affix-top{position:fixed}
|
||||
.no-padding{padding:0!important}
|
||||
.no-margin{margin:0!important}
|
||||
.pre-inline{white-space: normal;word-break: normal}
|
||||
.pre-inline>ul{margin:0;padding:0}
|
||||
a{cursor:pointer}
|
||||
nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-transform:uppercase;letter-spacing:2px}
|
||||
.m-r{margin-right:10px}
|
||||
.m-b{margin-bottom:10px}
|
||||
.m-t{margin-top:10px}
|
||||
.m-l{margin-left:10px}
|
||||
.overflow-hidden{overflow: hidden!important}
|
||||
.list-inline{list-style:none}
|
||||
.list-inline li{display:inline-block;vertical-align: top;margin:0;}
|
||||
.truncate{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
||||
img{max-width:100%}
|
||||
.display-table{display:table;width:100%}
|
||||
.display-inline{display:inline-block}
|
||||
.display-table-cell{display:table-cell}
|
||||
.small{font-size:80%}
|
||||
.super-center{position:absolute;left:0;top:0;right:0;bottom:0;margin:auto;width: 4em;height: 1em;}
|
||||
.permission_monitor_edit{display:none}
|
||||
.permission_video_delete{display:none}
|
||||
.nodata .divider{margin:5px 0}
|
||||
.loading .divider{margin:5px 0}
|
||||
/* Video Grid */
|
||||
.video_grid{overflow: auto;height: 100%;display: block;}
|
||||
.video_grid .col-md-2{padding-left:5px;padding-right:5px;padding-bottom:10px}
|
||||
.video_grid .thumb{width:100%;height:150px;display:inline-block;background-size:cover;position:relative;overflow:hidden;border-radius:4px;border:1px solid #000;box-shadow:0 0 10px #151515}
|
||||
.video_grid .thumb .title-strip, .video_grid .thumb .button-strip{width:100%;position:absolute;left:0;background:rgba(0,0,0,0.7);color:#fff;padding:4px}
|
||||
.video_grid .thumb .title-strip{top:0;opacity:0.5}
|
||||
.video_grid .thumb .button-strip{bottom:0;opacity:0}
|
||||
.video_grid .thumb:hover .title-strip, .video_grid .thumb:hover .button-strip{opacity:1}
|
|
@ -0,0 +1,44 @@
|
|||
form.modal-body{margin:0}
|
||||
.form-group label span{padding:5px;font-weight: 400;color: #2d2d2d;display:block;border-bottom: 1px dotted #ddd;font-size: 10pt;}
|
||||
.form-group label{display:table}
|
||||
.form-group label>div{display:table-cell}
|
||||
.form-group label>div:nth-child(2n-1){width:30%}
|
||||
.form-group label>div:nth-child(2){width:70%;padding:5px;border:1px solid #dedede;border-radius:5px}
|
||||
.dark .form-group label>div,.dark .form-group label>div>span{border-color:#454545;color:#fff}
|
||||
.important.form-group label>div:nth-child(2),.important.form-group label>div>span{border-color:red}
|
||||
.form-group label span small{margin-left: 2px;display:block;font-weight: 600;}
|
||||
.form-group-group .round-left{border-radius: 50px 0 0 50px;margin-left:10px}
|
||||
.form-group-group blockquote:before,.form-group-group blockquote:after{display:none!important}
|
||||
.form-group-group blockquote{letter-spacing:normal;font-style:normal}
|
||||
.form-group-group blockquote p:empty{display:none}
|
||||
.form-group-group blockquote p{font-size:inherit}
|
||||
.form-group-group blockquote p:last-child{margin-bottom:0}
|
||||
.form-group-group-group>div,.form-group-group-group .h_us_advanced>div{margin-bottom:15px;}
|
||||
.form-group-group{padding:0 10px 10px 10px;overflow:hidden;margin-bottom:15px;border-radius:5px;border:1px solid #ddd;background:#fff}
|
||||
.form-group-group table{width:100%}
|
||||
.form-group-group table tr td{padding:10px 5px}
|
||||
.form-group-group table tr:not(:last-child) td{border-bottom:1px dotted #eee}
|
||||
.form-group-group .mdl-list__item{border-bottom:1px solid #eee;}
|
||||
.form-group-group .mdl-list__item:hover{background:#e6e6e6;border-radius:4px;}
|
||||
.dark .form-group-group .mdl-list__item{color:#fff;border-bottom:1px solid #444;}
|
||||
.dark .form-group-group .mdl-list__item:hover{background:#555;}
|
||||
.form-group-group:last-child,.form-group-group > .form-group:last-child{margin-bottom:0}
|
||||
.form-group-group h4{margin:0 -10px 15px -10px;padding:15px;background:#ddd;}
|
||||
.form-group-group h4 small{color:#fff;}
|
||||
.form-group-group.red{border-color:#d9534f}
|
||||
.form-group-group.red h4{background:#d9534f;color:#fff}
|
||||
.form-group-group.purple{border-color:#3f51b5}
|
||||
.form-group-group.purple h4{background:#3f51b5;color:#fff}
|
||||
.form-group-group.blue{border-color:#337ab7}
|
||||
.form-group-group.blue h4{background:#337ab7;color:#fff}
|
||||
.form-group-group.navy{border-color:#31708f}
|
||||
.form-group-group.navy h4{background:#31708f;color:#fff}
|
||||
.form-group-group.green{border-color:#449d44}
|
||||
.form-group-group.green h4{background:#449d44;color:#fff}
|
||||
.form-group-group.forestgreen{border-color:#1e4046}
|
||||
.form-group-group.forestgreen h4{background:#1e4046;color:#fff}
|
||||
.form-group-group.orange{border-color:#c49a68}
|
||||
.form-group-group.orange h4{background:#c49a68;color:#fff}
|
||||
.form-group-group.grey{border-color:#777}
|
||||
.form-group-group.grey h4{background:#777;color:#fff}
|
||||
.dark .form-group-group{background:#222}
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
.jpegMode .cpu_load .progress-bar,.jpegMode .ram_load .progress-bar{background-color:#5cb85c}
|
||||
.jpegMode [system="jpegToggle"],[system].text-success{color:#5cb85c!important}
|
||||
|
||||
.monitor_item .stream-hud{opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2}
|
||||
.monitor_item .stream-hud .camera_cpu_usage{position:absolute;top:0;left:0;width: 100%;}
|
||||
.monitor_item .stream-hud .camera_cpu_usage .progress{width: 100%;}
|
||||
.monitor_item .stream-hud .camera_cpu_usage:hover .progress{height:20px;transition:0.2s}
|
||||
.monitor_item .stream-hud .controls{position:absolute;top:10px;left:10px;}
|
||||
.monitor_item .stream-hud:hover{opacity:1}
|
||||
.monitor_item .stream-hud .bottom-text{position:absolute;bottom:0;left:0;width:70%;padding:5px;text-shadow: 0 0 10px #333;}
|
||||
.monitor_item .stream-hud:hover .bottom-text{top:0;}
|
||||
.monitor_item .stream-hud .bottom-text .detector-fade{background: rgba(0,0,0,0.4);padding:10px 20px;border-radius:10px}
|
||||
.monitor_item .stream-hud .lamp{position:absolute;top:5px;right:5px;z-index:1;text-shadow: 0 0 15px #333;}
|
||||
.monitor_item[mode="Disabled"] .stream-hud .lamp{color:#5d5d5d}
|
||||
.monitor_item[mode="Watch Only"] .stream-hud .lamp{color:#5da8e8}
|
||||
.monitor_item[mode="Idle"] .stream-hud .lamp{color:#fff}
|
||||
.monitor_item[mode="Record"] .stream-hud .lamp{color:#d9534f}
|
||||
/*.data-menu{max-height:700px}*/
|
||||
.data-menu:not(:last-child){border-right:1px solid #fff;}
|
||||
.data-menu.logs{list-style:none;}
|
||||
.monitor_item .motionVision{display:none}
|
||||
|
||||
.monitor_item .grid-stack-item-content{width:100%!important;left:0!important;right:0!important}
|
||||
.monitor_item .ui-resizable-se {bottom: 10px!important;}
|
||||
.monitor_item .stream-block{position: relative;text-align: center}
|
||||
.monitor_item .mdl-data_window{overflow-x: auto;background:rgba(0,0,0,0.7);color:#fff;height:100%}
|
||||
.monitor_item .mdl-data_window:not(.col-md-6){width:0;min-width:0;height:0px;min-height:0}
|
||||
|
||||
|
||||
.monitor_item.fullscreen img.stream-element{height:100%;width:auto}
|
||||
.monitor_item.fullscreen canvas.stream-element{height:auto;width:auto;background-color:black;}
|
||||
.monitor_item .stream-element{border: 0;object-fit: fill;height: 100%;width:100%}
|
||||
.monitor_item{position:relative;padding:0;transition:none;background:#000}
|
||||
.monitor_item .mdl-card{min-height:auto;border:1px solid #272727;border-radius:0px;overflow:hidden}
|
||||
.monitor_item .mdl-card__media{position:relative;padding:0!important;display:block!important;background:#000;}
|
||||
.monitor_item.selected .stream-element{height:600px}
|
||||
.monitor_item.selected .fa-expand:before{content:"\f066"}
|
||||
.monitor_item .mdl-card__supporting-text{background:#222;color:#fff!important;display:block;min-height:auto!important}
|
||||
.monitor_item.detector_triggered .detector-fade{opacity:1}
|
||||
.monitor_item .detector-fade{opacity:0}
|
||||
.monitor_item .indifference{position:absolute;width:100%;left:0;top:0;transition:0.2s;}
|
||||
.monitor_item .progress{width:100%;background:#333;box-shadow:0;}
|
||||
.monitor_item .indifference:hover .progress{height:20px;transition:0.2s}
|
||||
.hide_indifference .indifference{display:none!important}
|
||||
.hide_indifference [class_toggle="hide_indifference"]{color:#d9534f!important}
|
||||
.monitor_item .mdl-card:not(.mdl-cell--4-col-desktop) .mdl-card__supporting-text .monitor_details{display:none;font-size:90%;margin-bottom:10px}
|
||||
.monitor_item[mode="Record"] [mode="record"]{display:none}
|
||||
.monitor_item[mode="Watch Only"] [mode="start"]{display:none}
|
||||
.monitor_item .stream-hud .controls .btn{opacity:0.7}
|
||||
.monitor_item.doObjectDetection .progress-bar{background-color: #57d94f}
|
||||
|
||||
.data-menu{text-align:left}
|
||||
.data-menu ul,.side-menu ul{list-style:none;margin:0;padding:0;}
|
||||
.data-menu li,.side-menu li:not(.mdl-menu__item){
|
||||
border-bottom:1px solid #54502d;padding:10px;
|
||||
}
|
||||
.data-menu .progress-circle{margin:0 10px 0 0;position:relative;height:40px;width:40px;float:left}
|
||||
.data-menu .progress-circle span:after{content:''}
|
||||
img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px}
|
||||
.circle-img.sm{height:25px;width:25px}
|
||||
|
||||
@media screen and (max-width:1500px){
|
||||
.monitor_item .mdl-card__supporting-text .btn{
|
||||
padding: 5px 10px;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
#monitors_live .monitor_item [class_toggle="show_logs"]{display:none}
|
||||
#monitors_live .monitor_item .indifference{top:-5px}
|
||||
#monitors_live .monitor_item .mdl-cell--8-col{width:100%;border:0;border-radius:0;margin:0;position:relative}
|
||||
#monitors_live .monitor_item .mdl-cell--4-col-desktop,.monitor_item .mdl-card__supporting-text{display:none}
|
||||
#monitors_live .monitor_item .mdl-card__supporting-text .monitor_details,#monitors_live .monitor_item .mdl-card__supporting-text .btn-group{display:none;text-align:center}
|
||||
#monitors_live .monitor_item .mdl-card__supporting-text:not(.meta){display:block;position:absolute;bottom:0;left:0;height:0;padding:0;overflow:visible}
|
||||
#monitors_live .monitor_item.show_data .mdl-card__supporting-text:not(.meta){width:50%}
|
||||
#monitors_live .monitor_item.detector_triggered .mdl-card__supporting-text:not(.meta) .indifference{opacity:0.5;}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text:not(.meta){padding:15px;z-index:15;height:auto;}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text .monitor_details{display:block}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text .btn-group{display:inline-block}
|
||||
|
||||
.signal.green{background:#5cb85c}
|
||||
[status="1"] .btn[video="launch"],[data-status="1"] .btn[video="launch"]{background:#337ab7;border-color:#337ab7}
|
||||
[status="2"] .btn[launch="video"],[status="2"] .btn[video="launch"],[data-status="2"] .btn[video="launch"]{background:#a59100;border-color:#a59100}
|
||||
.signal.red{background:#c9302c}
|
|
@ -0,0 +1,8 @@
|
|||
#pvideo_viewer iframe{border:0;width:100%;height:350px;margin-bottom:10px;overflow:hidden}
|
||||
#pvideo_viewer video{max-height:300px;max-width:100%;}
|
||||
#pvideo_viewer .holder{height:300px;}
|
||||
#pvideo_viewer h3{margin-top:0}
|
||||
#pvideo_viewer .progressBar{position:relative;}
|
||||
#pvideo_viewer .bufferBar{position:absolute;left:0;top:0;opacity:0.4}
|
||||
#pvideo_viewer .timeBar{position:relative;z-index: 222;background:transparent}
|
||||
#pvideo_viewer h3{font-family:monospace}
|
|
@ -0,0 +1,89 @@
|
|||
/*Control Pad*/
|
||||
.PTZ_controls {
|
||||
z-index: 111;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
margin:0;
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
}
|
||||
.PTZ_controls .btn-group{margin-top:10px}
|
||||
.PTZ_controls .pad {
|
||||
position: relative;
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
background: #b7b7b7;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4);
|
||||
}
|
||||
.PTZ_controls .control {
|
||||
position: absolute;
|
||||
}
|
||||
.PTZ_controls .pad .control {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background: #636363;
|
||||
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.PTZ_controls .zoom_in{
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .zoom_out{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .nv_enabled{
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .nv_disable{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .pad .top {
|
||||
top: 15px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -15px;
|
||||
}
|
||||
.PTZ_controls .pad .left {
|
||||
top: 45px;
|
||||
left: 15px;
|
||||
}
|
||||
.PTZ_controls .pad .right {
|
||||
top: 45px;
|
||||
right: 15px;
|
||||
}
|
||||
.PTZ_controls .pad .control.right:before {
|
||||
transform: rotate(90deg) translate(-3px, -5px);
|
||||
}
|
||||
.PTZ_controls .pad .bottom {
|
||||
bottom: 15px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -15px;
|
||||
}
|
||||
/* Overlap the other controls to hide box-shadow */
|
||||
.PTZ_controls .pad .middle {
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
z-index: 5;
|
||||
top: 43px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -17px;
|
||||
box-shadow: none;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.PTZ_controls .pad .middle:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -35% 0 0 -35%;
|
||||
content: '';
|
||||
background: #636363;
|
||||
height: 70%;
|
||||
width: 70%;
|
||||
border-radius: 100%;
|
||||
box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#region_editor .modal-body{text-align:center;overflow:auto;max-height:800px}
|
||||
#region_editor .canvas_holder{position:relative;display:inline-block;overflow:auto;min-height:450px}
|
||||
#region_editor .cord_element{position:absolute;background:rgba(221, 221, 221, 0.8);z-index:11;padding:5px;}
|
||||
#region_editor .cord_element.selected{z-index:12;}
|
||||
#region_editor .cord_element .controls{margin-bottom:5px;}
|
|
@ -0,0 +1,11 @@
|
|||
.right-to-left {text-align:right}
|
||||
.right-to-left select{direction: rtl;}
|
||||
.right-to-left input,.right-to-left textarea{direction: rtl;text-align:right}
|
||||
.right-to-left .form-group label span{padding-right:10px}
|
||||
.right-to-left .modal-footer{text-align:left}
|
||||
.right-to-left .mdl-menu__item>div>*{flex:1}
|
||||
.right-to-left .mdl-menu__item>div>i{margin-right:0;margin-left:5px}
|
||||
.right-to-left .mdl-menu__item{text-align:right}
|
||||
.right-to-left .mdl-menu__item i{float:right}
|
||||
.right-to-left .pull-right,.right-to-left .close{float:left!important}
|
||||
.right-to-left .pull-left,.right-to-left .mdl-menu__item span{float:right!important}
|
|
@ -0,0 +1,13 @@
|
|||
#timelapse_video_line{overflow-y:scroll;overflow-x:hidden;max-height:400px;margin:0;text-align:left}
|
||||
#timelapse_video_display .videoBefore,#timelapse_video_display .videoAfter{display:none}
|
||||
.timelapse_video:not(:last-child){border-bottom:1px solid #444;}
|
||||
.timelapse_video .frame{width:50px;height:50px;background-size:cover;background-position:center;border-radius:5px}
|
||||
.timelapse_video>div>div:not(:last-child){padding-right:10px}
|
||||
.timelapse_video .flex-block:not(:last-child){padding-bottom:10px}
|
||||
.timelapse_video.list-group-item{padding:10px}
|
||||
.timelapse_hud{position: relative;background:#000}
|
||||
.timelapse_hud .timelapse_playRate{position: absolute;font-family: monospace;top:10px;right:0;left:0;margin:auto;font-size:23px}
|
||||
#timelapse .progress-bar{transition:0.5s!important}
|
||||
.timelapse_hud .controlBar{position: absolute;background:rgba(22,22,22,0.8);width:100%;left:0;bottom:0;}
|
||||
.timelapse_hud .hover-hide{opacity:0}
|
||||
.timelapse_hud:hover .hover-hide{opacity:1;z-index:5}
|
|
@ -1,87 +1,3 @@
|
|||
/*Cusotm Bootstrap*/
|
||||
.col-5ths,
|
||||
.col-sm-5ths,
|
||||
.col-md-5ths,
|
||||
.col-lg-5ths {
|
||||
position: relative;
|
||||
min-height: 1px;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.col-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.col-sm-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.col-md-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color:#bd9565;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color:#bd9565;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 10px;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
/**/
|
||||
.flex{display:flex}
|
||||
.flex>div{flex:1}
|
||||
.flex-block{display:inline-flex;width:100%;flex-flow: row wrap;}
|
||||
.flex-unit-3{flex:3}
|
||||
.flex-inline{display: inline-flex;position:relative}
|
||||
@import (less) "../less/pie.less";
|
||||
ul{list-style:none}
|
||||
*{transition:0.2s;box-sizing:border-box}
|
||||
.affix-top{position:fixed}
|
||||
.no-padding{padding:0!important}
|
||||
.no-margin{margin:0!important}
|
||||
.pre-inline{white-space: normal;word-break: normal}
|
||||
.pre-inline>ul{margin:0;padding:0}
|
||||
a{cursor:pointer}
|
||||
nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-transform:uppercase;letter-spacing:2px}
|
||||
.m-r{margin-right:10px}
|
||||
.m-b{margin-bottom:10px}
|
||||
.m-t{margin-top:10px}
|
||||
.m-l{margin-left:10px}
|
||||
.overflow-hidden{overflow: hidden!important}
|
||||
.list-inline{list-style:none}
|
||||
.list-inline li{display:inline-block;vertical-align: top;margin:0;}
|
||||
.truncate{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
||||
img{max-width:100%}
|
||||
.display-table{display:table;width:100%}
|
||||
.display-inline{display:inline-block}
|
||||
.display-table-cell{display:table-cell}
|
||||
.small{font-size:80%}
|
||||
.super-center{position:absolute;left:0;top:0;right:0;bottom:0;margin:auto;width: 4em;height: 1em;}
|
||||
.jpegMode .cpu_load .progress-bar,.jpegMode .ram_load .progress-bar{background-color:#5cb85c}
|
||||
.jpegMode [system="jpegToggle"],[system].text-success{color:#5cb85c!important}
|
||||
.permission_monitor_edit{display:none}
|
||||
.permission_video_delete{display:none}
|
||||
.nodata .divider{margin:5px 0}
|
||||
.loading .divider{margin:5px 0}
|
||||
|
||||
#accbtn{
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
@ -89,75 +5,6 @@ img{max-width:100%}
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
.monitor_item .stream-hud{opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2}
|
||||
.monitor_item .stream-hud .camera_cpu_usage{position:absolute;top:0;left:0;width: 100%;}
|
||||
.monitor_item .stream-hud .camera_cpu_usage .progress{width: 100%;}
|
||||
.monitor_item .stream-hud .camera_cpu_usage:hover .progress{height:20px;transition:0.2s}
|
||||
.monitor_item .stream-hud .controls{position:absolute;top:10px;left:10px;}
|
||||
.monitor_item .stream-hud:hover{opacity:1}
|
||||
.monitor_item .stream-hud .bottom-text{position:absolute;bottom:0;left:0;width:100%;padding:5px;text-shadow: 0 0 10px #333;}
|
||||
.monitor_item .stream-hud .bottom-text .detector-fade{background: rgba(0,0,0,0.4);padding:10px 20px;border-radius:10px}
|
||||
.monitor_item .stream-hud .lamp{position:absolute;top:5px;right:5px;z-index:1;text-shadow: 0 0 15px #333;}
|
||||
.monitor_item[mode="Disabled"] .stream-hud .lamp{color:#5d5d5d}
|
||||
.monitor_item[mode="Watch Only"] .stream-hud .lamp{color:#5da8e8}
|
||||
.monitor_item[mode="Idle"] .stream-hud .lamp{color:#fff}
|
||||
.monitor_item[mode="Record"] .stream-hud .lamp{color:#d9534f}
|
||||
/*.data-menu{max-height:700px}*/
|
||||
.data-menu:not(:last-child){border-right:1px solid #fff;}
|
||||
.data-menu.logs{list-style:none;}
|
||||
.monitor_item .motionVision{display:none}
|
||||
|
||||
.monitor_item .grid-stack-item-content{width:100%!important;left:0!important;right:0!important}
|
||||
.monitor_item .ui-resizable-se {bottom: 10px!important;}
|
||||
.monitor_item .stream-block{position: relative;text-align: center}
|
||||
.monitor_item .mdl-data_window{overflow-x: auto;background:rgba(0,0,0,0.7);color:#fff;height:100%}
|
||||
.monitor_item .mdl-data_window:not(.col-md-6){width:0;min-width:0;height:0px;min-height:0}
|
||||
|
||||
|
||||
.monitor_item.fullscreen img.stream-element{height:100%;width:auto}
|
||||
.monitor_item.fullscreen canvas.stream-element{height:auto;width:auto;background-color:black;}
|
||||
.monitor_item .stream-element{border: 0;object-fit: fill;height: 100%;width:100%}
|
||||
.monitor_item{position:relative;padding:0;transition:none;background:#000}
|
||||
.monitor_item .mdl-card{min-height:auto;border:1px solid #272727;border-radius:0px;overflow:hidden}
|
||||
.monitor_item .mdl-card__media{position:relative;padding:0!important;display:block!important;background:#000;}
|
||||
.monitor_item.selected .stream-element{height:600px}
|
||||
.monitor_item.selected .fa-expand:before{content:"\f066"}
|
||||
.monitor_item .mdl-card__supporting-text{background:#222;color:#fff!important;display:block;min-height:auto!important}
|
||||
.monitor_item.detector_triggered .detector-fade{opacity:1}
|
||||
.monitor_item .detector-fade{opacity:0}
|
||||
.monitor_item .indifference{position:absolute;width:100%;left:0;top:0;transition:0.2s;}
|
||||
.monitor_item .progress{width:100%;background:#333;box-shadow:0;}
|
||||
.monitor_item .indifference:hover .progress{height:20px;transition:0.2s}
|
||||
.hide_indifference .indifference{display:none!important}
|
||||
.hide_indifference [class_toggle="hide_indifference"]{color:#d9534f!important}
|
||||
.monitor_item .mdl-card:not(.mdl-cell--4-col-desktop) .mdl-card__supporting-text .monitor_details{display:none;font-size:90%;margin-bottom:10px}
|
||||
.monitor_item[mode="Record"] [mode="record"]{display:none}
|
||||
.monitor_item[mode="Watch Only"] [mode="start"]{display:none}
|
||||
.monitor_item .stream-hud .controls .btn{opacity:0.7}
|
||||
.monitor_item.doObjectDetection .progress-bar{background-color: #57d94f}
|
||||
|
||||
@media screen and (max-width:1500px){
|
||||
.monitor_item .mdl-card__supporting-text .btn{
|
||||
padding: 5px 10px;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
#monitors_live .monitor_item [class_toggle="show_logs"]{display:none}
|
||||
#monitors_live .monitor_item .indifference{top:-5px}
|
||||
#monitors_live .monitor_item .mdl-cell--8-col{width:100%;border:0;border-radius:0;margin:0;position:relative}
|
||||
#monitors_live .monitor_item .mdl-cell--4-col-desktop,.monitor_item .mdl-card__supporting-text{display:none}
|
||||
#monitors_live .monitor_item .mdl-card__supporting-text .monitor_details,#monitors_live .monitor_item .mdl-card__supporting-text .btn-group{display:none;text-align:center}
|
||||
#monitors_live .monitor_item .mdl-card__supporting-text:not(.meta){display:block;position:absolute;bottom:0;left:0;height:0;padding:0;}
|
||||
#monitors_live .monitor_item.show_data .mdl-card__supporting-text:not(.meta){width:50%}
|
||||
#monitors_live .monitor_item.detector_triggered .mdl-card__supporting-text:not(.meta) .indifference{opacity:0.5;}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text:not(.meta){padding:15px;z-index:15;height:auto;}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text .monitor_details{display:block}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text .btn-group{display:inline-block}
|
||||
|
||||
|
||||
|
||||
#vis_pwrvideo{height:250px}
|
||||
#monSectionStreamChannels,#monSectionInputMaps{margin-bottom: 15px;}
|
||||
#monSectionStreamChannels:empty,#monSectionInputMaps:empty{display:none}
|
||||
|
@ -169,19 +16,12 @@ img{max-width:100%}
|
|||
|
||||
.demo-blog .demo-blog__posts.montage{max-width:100%}
|
||||
|
||||
|
||||
.mdl-layout__drawer{overflow-y: visible!important}
|
||||
.hide-side .mdl-layout__drawer{overflow-y: hidden}
|
||||
.mdl-layout__header-row{padding-left:10!important}
|
||||
.mdl-layout__header-row .nav>li>a{border-radius:50%;}
|
||||
.mdl-layout__drawer-button i{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;height:1em;color:#fff}
|
||||
.data-menu{text-align:left}
|
||||
.data-menu ul,.side-menu ul{list-style:none;margin:0;padding:0;}
|
||||
.data-menu li,.side-menu li{
|
||||
border-bottom:1px solid #54502d;padding:10px;
|
||||
}
|
||||
.data-menu .progress-circle{margin:0 10px 0 0;position:relative;height:40px;width:40px;float:left}
|
||||
.data-menu .progress-circle span:after{content:''}
|
||||
img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px}
|
||||
.circle-img.sm{height:25px;width:25px}
|
||||
|
||||
|
||||
.video_video{margin:auto;max-width:100%;max-height:600px;}
|
||||
#confirm_window .video_video{margin-top:15px}
|
||||
|
@ -200,60 +40,9 @@ img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px}
|
|||
.flex-container-modal-body .flex-block>div{flex:1;float:none}
|
||||
|
||||
.modal{overflow:auto!important}
|
||||
form.modal-body{margin:0}
|
||||
#region_editor .modal-body{text-align:center;overflow:auto;max-height:800px}
|
||||
#region_editor .canvas_holder{position:relative;display:inline-block;overflow:auto;min-height:450px}
|
||||
#region_editor .cord_element{position:absolute;background:rgba(221, 221, 221, 0.8);z-index:11;padding:5px;}
|
||||
#region_editor .cord_element.selected{z-index:12;}
|
||||
#region_editor .cord_element .controls{margin-bottom:5px;}
|
||||
.form-group label span{padding:5px;font-weight: 400;color: #2d2d2d;display:block;border-bottom: 1px dotted #ddd;font-size: 10pt;}
|
||||
.form-group label{display:table}
|
||||
.form-group label>div{display:table-cell}
|
||||
.form-group label>div:nth-child(2n-1){width:30%}
|
||||
.form-group label>div:nth-child(2){width:70%;padding:5px;border:1px solid #dedede;border-radius:5px}
|
||||
.dark .form-group label>div,.dark .form-group label>div>span{border-color:#454545;color:#fff}
|
||||
.important.form-group label>div:nth-child(2),.important.form-group label>div>span{border-color:red}
|
||||
.form-group label span small{margin-left: 2px;display:block;font-weight: 600;}
|
||||
.form-group-group .round-left{border-radius: 50px 0 0 50px;margin-left:10px}
|
||||
.form-group-group blockquote:before,.form-group-group blockquote:after{display:none!important}
|
||||
.form-group-group blockquote{letter-spacing:normal;font-style:normal}
|
||||
.form-group-group blockquote p:empty{display:none}
|
||||
.form-group-group blockquote p{font-size:inherit}
|
||||
.form-group-group blockquote p:last-child{margin-bottom:0}
|
||||
.form-group-group-group>div,.form-group-group-group .h_us_advanced>div{margin-bottom:15px;}
|
||||
.form-group-group{padding:0 10px 10px 10px;overflow:hidden;margin-bottom:15px;border-radius:5px;border:1px solid #ddd;background:#fff}
|
||||
.form-group-group table{width:100%}
|
||||
.form-group-group table tr td{padding:10px 5px}
|
||||
.form-group-group table tr:not(:last-child) td{border-bottom:1px dotted #eee}
|
||||
.form-group-group .mdl-list__item{border-bottom:1px solid #eee;}
|
||||
.form-group-group .mdl-list__item:hover{background:#e6e6e6;border-radius:4px;}
|
||||
.dark .form-group-group .mdl-list__item{color:#fff;border-bottom:1px solid #444;}
|
||||
.dark .form-group-group .mdl-list__item:hover{background:#555;}
|
||||
.form-group-group:last-child,.form-group-group > .form-group:last-child{margin-bottom:0}
|
||||
.form-group-group h4{margin:0 -10px 15px -10px;padding:15px;background:#ddd;}
|
||||
.form-group-group h4 small{color:#fff;}
|
||||
.form-group-group.red{border-color:#d9534f}
|
||||
.form-group-group.red h4{background:#d9534f;color:#fff}
|
||||
.form-group-group.purple{border-color:#3f51b5}
|
||||
.form-group-group.purple h4{background:#3f51b5;color:#fff}
|
||||
.form-group-group.blue{border-color:#337ab7}
|
||||
.form-group-group.blue h4{background:#337ab7;color:#fff}
|
||||
.form-group-group.navy{border-color:#31708f}
|
||||
.form-group-group.navy h4{background:#31708f;color:#fff}
|
||||
.form-group-group.green{border-color:#449d44}
|
||||
.form-group-group.green h4{background:#449d44;color:#fff}
|
||||
.form-group-group.forestgreen{border-color:#1e4046}
|
||||
.form-group-group.forestgreen h4{background:#1e4046;color:#fff}
|
||||
.form-group-group.orange{border-color:#c49a68}
|
||||
.form-group-group.orange h4{background:#c49a68;color:#fff}
|
||||
.form-group-group.grey{border-color:#777}
|
||||
.form-group-group.grey h4{background:#777;color:#fff}
|
||||
.dark .form-group-group{background:#222}
|
||||
|
||||
.videos_list .title{font-size:12pt;padding:0 10px}
|
||||
[status="1"] .btn[video="launch"],[data-status="1"] .btn[video="launch"]{background:#337ab7;border-color:#337ab7}
|
||||
[status="2"] .btn[launch="video"],[status="2"] .btn[video="launch"],[data-status="2"] .btn[video="launch"]{background:#a59100;border-color:#a59100}
|
||||
.signal.red{background:#c9302c}
|
||||
.signal.green{background:#5cb85c}
|
||||
|
||||
.demo-drawer{background:#2b2a2a;color:#fff;}
|
||||
.demo-drawer.mdl-layout__drawer .mdl-navigation{padding-top:0;}
|
||||
.demo-drawer::-webkit-scrollbar{display:none;}
|
||||
|
@ -285,6 +74,8 @@ form.modal-body{margin:0}
|
|||
.nav-xs.side-menu.list-blocks .monitor_block img{width:40px;height:40px;}
|
||||
.side-menu.list-blocks .monitor_block .box{width:calc(100% - 70px);display:inline-block}
|
||||
.nav-xs.side-menu.list-blocks .monitor_block .list-data{display:none}
|
||||
.side-menu .mdl-menu{z-index: 12}
|
||||
|
||||
#monitors_list .monitor_block{transition:none}
|
||||
.dropdown-menu.scrollable{max-height:300px}
|
||||
.upload_file input{display:none}
|
||||
|
@ -306,39 +97,11 @@ form.modal-body{margin:0}
|
|||
|
||||
.form-group label{width:100%}
|
||||
|
||||
#pvideo_viewer iframe{border:0;width:100%;height:350px;margin-bottom:10px;overflow:hidden}
|
||||
#pvideo_viewer video{max-height:300px;max-width:100%;}
|
||||
#pvideo_viewer .holder{height:300px;}
|
||||
#pvideo_viewer h3{margin-top:0}
|
||||
#pvideo_viewer .progressBar{position:relative;}
|
||||
#pvideo_viewer .bufferBar{position:absolute;left:0;top:0;opacity:0.4}
|
||||
#pvideo_viewer .timeBar{position:relative;z-index: 222;background:transparent}
|
||||
#pvideo_viewer h3{font-family:monospace}
|
||||
|
||||
|
||||
#vis_monitors{overflow:auto;max-height:400px}
|
||||
#vis_monitors .btn-group-vertical{width:100%}
|
||||
|
||||
/*timeline*/
|
||||
#timelapse_video_line{overflow-y:scroll;overflow-x:hidden;max-height:400px;margin:0;text-align:left}
|
||||
#timelapse_video_display .videoBefore,#timelapse_video_display .videoAfter{display:none}
|
||||
.timelapse_video:not(:last-child){border-bottom:1px solid #444;}
|
||||
.timelapse_video .frame{width:50px;height:50px;background-size:cover;background-position:center;border-radius:5px}
|
||||
.timelapse_video>div>div:not(:last-child){padding-right:10px}
|
||||
.timelapse_video .flex-block:not(:last-child){padding-bottom:10px}
|
||||
.timelapse_video.list-group-item{padding:10px}
|
||||
.timelapse_hud{position: relative;background:#000}
|
||||
.timelapse_hud .timelapse_playRate{position: absolute;font-family: monospace;top:10px;right:0;left:0;margin:auto;font-size:23px}
|
||||
#timelapse .progress-bar{transition:0.5s!important}
|
||||
.timelapse_hud .controlBar{position: absolute;background:rgba(22,22,22,0.8);width:100%;left:0;bottom:0;}
|
||||
.timelapse_hud .hover-hide{opacity:0}
|
||||
.timelapse_hud:hover .hover-hide{opacity:1;z-index:5}
|
||||
.video_grid{overflow: auto;height: 100%;display: block;}
|
||||
.video_grid .col-md-2{padding-left:5px;padding-right:5px;padding-bottom:10px}
|
||||
.video_grid .thumb{width:100%;height:150px;display:inline-block;background-size:cover;position:relative;overflow:hidden;border-radius:4px;border:1px solid #000;box-shadow:0 0 10px #151515}
|
||||
.video_grid .thumb .title-strip, .video_grid .thumb .button-strip{width:100%;position:absolute;left:0;background:rgba(0,0,0,0.7);color:#fff;padding:4px}
|
||||
.video_grid .thumb .title-strip{top:0;opacity:0.5}
|
||||
.video_grid .thumb .button-strip{bottom:0;opacity:0}
|
||||
.video_grid .thumb:hover .title-strip, .video_grid .thumb:hover .button-strip{opacity:1}
|
||||
|
||||
.table-striped>tbody>tr>td{vertical-align:middle}
|
||||
.table-striped .thumbnail{width:100px;height:80px;border-radius:5px;margin:0;display:inline-block;}
|
||||
|
@ -352,13 +115,6 @@ form.modal-body{margin:0}
|
|||
background-color: #c49a68;
|
||||
border-color: #c49a68;
|
||||
}
|
||||
|
||||
.dark.modal .modal-header,.dark.modal .modal-footer{background:#333;border-color:#444;}
|
||||
.dark.modal .modal-header{color:#fff;}
|
||||
.dark.modal .modal-footer>*:not(.btn){color:#fff;}
|
||||
.dark.modal .modal-body{background:#333;}
|
||||
.dark.modal .close{color:#fff;}
|
||||
.dark.modal{color:#fff;}
|
||||
.dark .table-striped>tbody>tr:nth-of-type(even){background:#616161}
|
||||
.dark .table-striped>tbody>tr>td{border-color:#222;color:#fff}
|
||||
.dark .table-striped>thead>tr>th{border-color:#222;color:#fff;background:#616161;vertical-align:middle;}
|
||||
|
@ -481,95 +237,10 @@ ul.msg_list li .message {
|
|||
.mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__header{
|
||||
margin-left: 0px;width:100%;transition:0.2s
|
||||
}
|
||||
/*Control Pad*/
|
||||
.PTZ_controls {
|
||||
z-index: 111;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
margin:0;
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
}
|
||||
.PTZ_controls .btn-group{margin-top:10px}
|
||||
.PTZ_controls .pad {
|
||||
position: relative;
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
background: #b7b7b7;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4);
|
||||
}
|
||||
.PTZ_controls .control {
|
||||
position: absolute;
|
||||
}
|
||||
.PTZ_controls .pad .control {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background: #636363;
|
||||
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.PTZ_controls .zoom_in{
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .zoom_out{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .nv_enabled{
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .nv_disable{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .pad .top {
|
||||
top: 15px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -15px;
|
||||
}
|
||||
.PTZ_controls .pad .left {
|
||||
top: 45px;
|
||||
left: 15px;
|
||||
}
|
||||
.PTZ_controls .pad .right {
|
||||
top: 45px;
|
||||
right: 15px;
|
||||
}
|
||||
.PTZ_controls .pad .control.right:before {
|
||||
transform: rotate(90deg) translate(-3px, -5px);
|
||||
}
|
||||
.PTZ_controls .pad .bottom {
|
||||
bottom: 15px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -15px;
|
||||
}
|
||||
/* Overlap the other controls to hide box-shadow */
|
||||
.PTZ_controls .pad .middle {
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
z-index: 5;
|
||||
top: 43px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -17px;
|
||||
box-shadow: none;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.PTZ_controls .pad .middle:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -35% 0 0 -35%;
|
||||
content: '';
|
||||
background: #636363;
|
||||
height: 70%;
|
||||
width: 70%;
|
||||
border-radius: 100%;
|
||||
box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2);
|
||||
}
|
||||
.mdl-menu__item>div{display:flex;align-items: center;width:100%}
|
||||
.mdl-menu__item>div>i{margin-right:5px}
|
||||
|
||||
|
||||
/*Digital Zoom*/
|
||||
.stream-block{
|
||||
position: relative;
|
||||
|
@ -663,20 +334,7 @@ ul.msg_list li .message {
|
|||
-moz-animation: blink 1s linear infinite;
|
||||
animation: blink 1s linear infinite;
|
||||
}
|
||||
.mdl-menu__item>div{display:flex;align-items: center;width:100%}
|
||||
.mdl-menu__item>div>i{margin-right:5px}
|
||||
/*For languages that are right to left*/
|
||||
.right-to-left {text-align:right}
|
||||
.right-to-left select{direction: rtl;}
|
||||
.right-to-left input,.right-to-left textarea{direction: rtl;text-align:right}
|
||||
.right-to-left .form-group label span{padding-right:10px}
|
||||
.right-to-left .modal-footer{text-align:left}
|
||||
.right-to-left .mdl-menu__item>div>*{flex:1}
|
||||
.right-to-left .mdl-menu__item>div>i{margin-right:0;margin-left:5px}
|
||||
.right-to-left .mdl-menu__item{text-align:right}
|
||||
.right-to-left .mdl-menu__item i{float:right}
|
||||
.right-to-left .pull-right,.right-to-left .close{float:left!important}
|
||||
.right-to-left .pull-left,.right-to-left .mdl-menu__item span{float:right!important}
|
||||
|
||||
/* All-CSS Toggle Switch (Checkbox Hack) by Marcus Burnette - https://codepen.io/mburnette/pen/LxNxNg */
|
||||
.marc-toggle {
|
||||
width: 50px;
|
||||
|
|
|
@ -0,0 +1,742 @@
|
|||
/*Cusotm Bootstrap*/
|
||||
.col-5ths,
|
||||
.col-sm-5ths,
|
||||
.col-md-5ths,
|
||||
.col-lg-5ths {
|
||||
position: relative;
|
||||
min-height: 1px;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.col-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.col-sm-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.col-md-5ths {
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 20%;
|
||||
-ms-flex: 0 0 20%;
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color:#bd9565;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color:#bd9565;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 10px;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
/**/
|
||||
.flex{display:flex}
|
||||
.flex>div{flex:1}
|
||||
.flex-block{display:inline-flex;width:100%;flex-flow: row wrap;}
|
||||
.flex-unit-3{flex:3}
|
||||
.flex-inline{display: inline-flex;position:relative}
|
||||
@import (less) "../less/pie.less";
|
||||
ul{list-style:none}
|
||||
*{transition:0.2s;box-sizing:border-box}
|
||||
.affix-top{position:fixed}
|
||||
.no-padding{padding:0!important}
|
||||
.no-margin{margin:0!important}
|
||||
.pre-inline{white-space: normal;word-break: normal}
|
||||
.pre-inline>ul{margin:0;padding:0}
|
||||
a{cursor:pointer}
|
||||
nav h4{cursor:default;font-size:95%;padding:16px 40px;font-weight:100;text-transform:uppercase;letter-spacing:2px}
|
||||
.m-r{margin-right:10px}
|
||||
.m-b{margin-bottom:10px}
|
||||
.m-t{margin-top:10px}
|
||||
.m-l{margin-left:10px}
|
||||
.overflow-hidden{overflow: hidden!important}
|
||||
.list-inline{list-style:none}
|
||||
.list-inline li{display:inline-block;vertical-align: top;margin:0;}
|
||||
.truncate{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
||||
img{max-width:100%}
|
||||
.display-table{display:table;width:100%}
|
||||
.display-inline{display:inline-block}
|
||||
.display-table-cell{display:table-cell}
|
||||
.small{font-size:80%}
|
||||
.super-center{position:absolute;left:0;top:0;right:0;bottom:0;margin:auto;width: 4em;height: 1em;}
|
||||
.jpegMode .cpu_load .progress-bar,.jpegMode .ram_load .progress-bar{background-color:#5cb85c}
|
||||
.jpegMode [system="jpegToggle"],[system].text-success{color:#5cb85c!important}
|
||||
.permission_monitor_edit{display:none}
|
||||
.permission_video_delete{display:none}
|
||||
.nodata .divider{margin:5px 0}
|
||||
.loading .divider{margin:5px 0}
|
||||
|
||||
#accbtn{
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.monitor_item .stream-hud{opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2}
|
||||
.monitor_item .stream-hud .camera_cpu_usage{position:absolute;top:0;left:0;width: 100%;}
|
||||
.monitor_item .stream-hud .camera_cpu_usage .progress{width: 100%;}
|
||||
.monitor_item .stream-hud .camera_cpu_usage:hover .progress{height:20px;transition:0.2s}
|
||||
.monitor_item .stream-hud .controls{position:absolute;top:10px;left:10px;}
|
||||
.monitor_item .stream-hud:hover{opacity:1}
|
||||
.monitor_item .stream-hud .bottom-text{position:absolute;bottom:0;left:0;width:100%;padding:5px;text-shadow: 0 0 10px #333;}
|
||||
.monitor_item .stream-hud .bottom-text .detector-fade{background: rgba(0,0,0,0.4);padding:10px 20px;border-radius:10px}
|
||||
.monitor_item .stream-hud .lamp{position:absolute;top:5px;right:5px;z-index:1;text-shadow: 0 0 15px #333;}
|
||||
.monitor_item[mode="Disabled"] .stream-hud .lamp{color:#5d5d5d}
|
||||
.monitor_item[mode="Watch Only"] .stream-hud .lamp{color:#5da8e8}
|
||||
.monitor_item[mode="Idle"] .stream-hud .lamp{color:#fff}
|
||||
.monitor_item[mode="Record"] .stream-hud .lamp{color:#d9534f}
|
||||
/*.data-menu{max-height:700px}*/
|
||||
.data-menu:not(:last-child){border-right:1px solid #fff;}
|
||||
.data-menu.logs{list-style:none;}
|
||||
.monitor_item .motionVision{display:none}
|
||||
|
||||
.monitor_item .grid-stack-item-content{width:100%!important;left:0!important;right:0!important}
|
||||
.monitor_item .ui-resizable-se {bottom: 10px!important;}
|
||||
.monitor_item .stream-block{position: relative;text-align: center}
|
||||
.monitor_item .mdl-data_window{overflow-x: auto;background:rgba(0,0,0,0.7);color:#fff;height:100%}
|
||||
.monitor_item .mdl-data_window:not(.col-md-6){width:0;min-width:0;height:0px;min-height:0}
|
||||
|
||||
|
||||
.monitor_item.fullscreen img.stream-element{height:100%;width:auto}
|
||||
.monitor_item.fullscreen canvas.stream-element{height:auto;width:auto;background-color:black;}
|
||||
.monitor_item .stream-element{border: 0;object-fit: fill;height: 100%;width:100%}
|
||||
.monitor_item{position:relative;padding:0;transition:none;background:#000}
|
||||
.monitor_item .mdl-card{min-height:auto;border:1px solid #272727;border-radius:0px;overflow:hidden}
|
||||
.monitor_item .mdl-card__media{position:relative;padding:0!important;display:block!important;background:#000;}
|
||||
.monitor_item.selected .stream-element{height:600px}
|
||||
.monitor_item.selected .fa-expand:before{content:"\f066"}
|
||||
.monitor_item .mdl-card__supporting-text{background:#222;color:#fff!important;display:block;min-height:auto!important}
|
||||
.monitor_item.detector_triggered .detector-fade{opacity:1}
|
||||
.monitor_item .detector-fade{opacity:0}
|
||||
.monitor_item .indifference{position:absolute;width:100%;left:0;top:0;transition:0.2s;}
|
||||
.monitor_item .progress{width:100%;background:#333;box-shadow:0;}
|
||||
.monitor_item .indifference:hover .progress{height:20px;transition:0.2s}
|
||||
.hide_indifference .indifference{display:none!important}
|
||||
.hide_indifference [class_toggle="hide_indifference"]{color:#d9534f!important}
|
||||
.monitor_item .mdl-card:not(.mdl-cell--4-col-desktop) .mdl-card__supporting-text .monitor_details{display:none;font-size:90%;margin-bottom:10px}
|
||||
.monitor_item[mode="Record"] [mode="record"]{display:none}
|
||||
.monitor_item[mode="Watch Only"] [mode="start"]{display:none}
|
||||
.monitor_item .stream-hud .controls .btn{opacity:0.7}
|
||||
.monitor_item.doObjectDetection .progress-bar{background-color: #57d94f}
|
||||
|
||||
@media screen and (max-width:1500px){
|
||||
.monitor_item .mdl-card__supporting-text .btn{
|
||||
padding: 5px 10px;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
#monitors_live .monitor_item [class_toggle="show_logs"]{display:none}
|
||||
#monitors_live .monitor_item .indifference{top:-5px}
|
||||
#monitors_live .monitor_item .mdl-cell--8-col{width:100%;border:0;border-radius:0;margin:0;position:relative}
|
||||
#monitors_live .monitor_item .mdl-cell--4-col-desktop,.monitor_item .mdl-card__supporting-text{display:none}
|
||||
#monitors_live .monitor_item .mdl-card__supporting-text .monitor_details,#monitors_live .monitor_item .mdl-card__supporting-text .btn-group{display:none;text-align:center}
|
||||
#monitors_live .monitor_item .mdl-card__supporting-text:not(.meta){display:block;position:absolute;bottom:0;left:0;height:0;padding:0;overflow:visible;}
|
||||
#monitors_live .monitor_item.show_data .mdl-card__supporting-text:not(.meta){width:50%}
|
||||
#monitors_live .monitor_item.detector_triggered .mdl-card__supporting-text:not(.meta) .indifference{opacity:0.5;}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text:not(.meta){padding:15px;z-index:15;height:auto;}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text .monitor_details{display:block}
|
||||
#monitors_live .monitor_item:hover .mdl-card__supporting-text .btn-group{display:inline-block}
|
||||
|
||||
|
||||
|
||||
#vis_pwrvideo{height:250px}
|
||||
#monSectionStreamChannels,#monSectionInputMaps{margin-bottom: 15px;}
|
||||
#monSectionStreamChannels:empty,#monSectionInputMaps:empty{display:none}
|
||||
#region_editor_live iframe,.canvas_holder canvas{border:0;position:absolute;left:0;top:0}
|
||||
.canvas_holder canvas{z-index:11}
|
||||
|
||||
.demo-blog .mdl-card__media ~ .mdl-card__supporting-text{position:relative;overflow:initial;cursor:move}
|
||||
.demo-blog .mdl-card__media ~ .mdl-card__supporting-text .btn-group{cursor: default}
|
||||
|
||||
.demo-blog .demo-blog__posts.montage{max-width:100%}
|
||||
|
||||
|
||||
.mdl-layout__header-row{padding-left:10!important}
|
||||
.mdl-layout__header-row .nav>li>a{border-radius:50%;}
|
||||
.mdl-layout__drawer-button i{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;height:1em;color:#fff}
|
||||
.data-menu{text-align:left}
|
||||
.data-menu ul,.side-menu ul{list-style:none;margin:0;padding:0;}
|
||||
.data-menu li,.side-menu li{
|
||||
border-bottom:1px solid #54502d;padding:10px;
|
||||
}
|
||||
.data-menu .progress-circle{margin:0 10px 0 0;position:relative;height:40px;width:40px;float:left}
|
||||
.data-menu .progress-circle span:after{content:''}
|
||||
img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px}
|
||||
.circle-img.sm{height:25px;width:25px}
|
||||
|
||||
.video_video{margin:auto;max-width:100%;max-height:600px;}
|
||||
#confirm_window .video_video{margin-top:15px}
|
||||
#confirm_window .info-table{margin-top:15px}
|
||||
@media (max-width: 768px){
|
||||
.full.modal .modal-body,.medium.modal .modal-body{max-height:400px;overflow:auto}
|
||||
}
|
||||
@media (min-width: 768px){
|
||||
.modal.full,.modal.medium{padding-left:0!important;}
|
||||
.modal.full .modal-dialog{width:calc(100% - 10px)!important;margin: 30px auto;}
|
||||
.modal.medium .modal-dialog{width:calc(70% - 10px)!important;margin: 30px auto;}
|
||||
.full.modal .modal-body,.medium.modal .modal-body{height:calc(100% - 200px);overflow:auto}
|
||||
}
|
||||
|
||||
.flex-container-modal-body{overflow: auto}
|
||||
.flex-container-modal-body .flex-block>div{flex:1;float:none}
|
||||
|
||||
.modal{overflow:auto!important}
|
||||
form.modal-body{margin:0}
|
||||
#region_editor .modal-body{text-align:center;overflow:auto;max-height:800px}
|
||||
#region_editor .canvas_holder{position:relative;display:inline-block;overflow:auto;min-height:450px}
|
||||
#region_editor .cord_element{position:absolute;background:rgba(221, 221, 221, 0.8);z-index:11;padding:5px;}
|
||||
#region_editor .cord_element.selected{z-index:12;}
|
||||
#region_editor .cord_element .controls{margin-bottom:5px;}
|
||||
.form-group label span{padding:5px;font-weight: 400;color: #2d2d2d;display:block;border-bottom: 1px dotted #ddd;font-size: 10pt;}
|
||||
.form-group label{display:table}
|
||||
.form-group label>div{display:table-cell}
|
||||
.form-group label>div:nth-child(2n-1){width:30%}
|
||||
.form-group label>div:nth-child(2){width:70%;padding:5px;border:1px solid #dedede;border-radius:5px}
|
||||
.dark .form-group label>div,.dark .form-group label>div>span{border-color:#454545;color:#fff}
|
||||
.important.form-group label>div:nth-child(2),.important.form-group label>div>span{border-color:red}
|
||||
.form-group label span small{margin-left: 2px;display:block;font-weight: 600;}
|
||||
.form-group-group .round-left{border-radius: 50px 0 0 50px;margin-left:10px}
|
||||
.form-group-group blockquote:before,.form-group-group blockquote:after{display:none!important}
|
||||
.form-group-group blockquote{letter-spacing:normal;font-style:normal}
|
||||
.form-group-group blockquote p:empty{display:none}
|
||||
.form-group-group blockquote p{font-size:inherit}
|
||||
.form-group-group blockquote p:last-child{margin-bottom:0}
|
||||
.form-group-group-group>div,.form-group-group-group .h_us_advanced>div{margin-bottom:15px;}
|
||||
.form-group-group{padding:0 10px 10px 10px;overflow:hidden;margin-bottom:15px;border-radius:5px;border:1px solid #ddd;background:#fff}
|
||||
.form-group-group table{width:100%}
|
||||
.form-group-group table tr td{padding:10px 5px}
|
||||
.form-group-group table tr:not(:last-child) td{border-bottom:1px dotted #eee}
|
||||
.form-group-group .mdl-list__item{border-bottom:1px solid #eee;}
|
||||
.form-group-group .mdl-list__item:hover{background:#e6e6e6;border-radius:4px;}
|
||||
.dark .form-group-group .mdl-list__item{color:#fff;border-bottom:1px solid #444;}
|
||||
.dark .form-group-group .mdl-list__item:hover{background:#555;}
|
||||
.form-group-group:last-child,.form-group-group > .form-group:last-child{margin-bottom:0}
|
||||
.form-group-group h4{margin:0 -10px 15px -10px;padding:15px;background:#ddd;}
|
||||
.form-group-group h4 small{color:#fff;}
|
||||
.form-group-group.red{border-color:#d9534f}
|
||||
.form-group-group.red h4{background:#d9534f;color:#fff}
|
||||
.form-group-group.purple{border-color:#3f51b5}
|
||||
.form-group-group.purple h4{background:#3f51b5;color:#fff}
|
||||
.form-group-group.blue{border-color:#337ab7}
|
||||
.form-group-group.blue h4{background:#337ab7;color:#fff}
|
||||
.form-group-group.navy{border-color:#31708f}
|
||||
.form-group-group.navy h4{background:#31708f;color:#fff}
|
||||
.form-group-group.green{border-color:#449d44}
|
||||
.form-group-group.green h4{background:#449d44;color:#fff}
|
||||
.form-group-group.forestgreen{border-color:#1e4046}
|
||||
.form-group-group.forestgreen h4{background:#1e4046;color:#fff}
|
||||
.form-group-group.orange{border-color:#c49a68}
|
||||
.form-group-group.orange h4{background:#c49a68;color:#fff}
|
||||
.form-group-group.grey{border-color:#777}
|
||||
.form-group-group.grey h4{background:#777;color:#fff}
|
||||
.dark .form-group-group{background:#222}
|
||||
.videos_list .title{font-size:12pt;padding:0 10px}
|
||||
[status="1"] .btn[video="launch"],[data-status="1"] .btn[video="launch"]{background:#337ab7;border-color:#337ab7}
|
||||
[status="2"] .btn[launch="video"],[status="2"] .btn[video="launch"],[data-status="2"] .btn[video="launch"]{background:#a59100;border-color:#a59100}
|
||||
.signal.red{background:#c9302c}
|
||||
.signal.green{background:#5cb85c}
|
||||
.demo-drawer{background:#2b2a2a;color:#fff;}
|
||||
.demo-drawer.mdl-layout__drawer .mdl-navigation{padding-top:0;}
|
||||
.demo-drawer::-webkit-scrollbar{display:none;}
|
||||
.small-square-img{height:40px;width:40px;border-radius:5px}
|
||||
|
||||
.side-menu .monitor_block{padding:0;position:relative}
|
||||
.side-menu .monitor_block img{width:100%;height:75px;cursor:pointer;border: 0.5px inset #263238;}
|
||||
@media screen and (max-width:1025px){
|
||||
.side-menu .monitor_block img{height:175px;}
|
||||
}
|
||||
.side-menu .monitor_block:hover .icons{opacity:1}
|
||||
.side-menu .monitor_block:hover .title{opacity:1}
|
||||
.side-menu .monitor_block .icons,.side-menu .monitor_block .title{opacity:0;width:100%;bottom:0;left:0;background:rgba(0,0,0,0.6);position:absolute;padding:2.5px;z-index:11;cursor:move}
|
||||
.side-menu .monitor_block .title{bottom:auto;top:0;color:#fff}
|
||||
.nav-xs.side-menu .monitor_block{width:100%}
|
||||
.side-menu .monitor_block .list-data{display:none}
|
||||
.output_data:empty{display:none}
|
||||
.output_data{max-height:500px;font-family:monospace;padding:10px;border-radius:5px;background:#f3f3f3;overflow:auto}
|
||||
.dark .output_data{background:#222;}
|
||||
#probe .output_data div>div{margin-left:10px}
|
||||
.side-menu.list-blocks .monitor_block .icons,.side-menu.list-blocks .monitor_block .title{position:inherit;opacity:1;background:none}
|
||||
.side-menu.list-blocks .monitor_block .title{padding:5px;border-radius:5px;background:#222;}
|
||||
.side-menu.list-blocks .monitor_block:not(:last-child){border-bottom: 1px solid #54502d;}
|
||||
.side-menu.list-blocks .monitor_block:first-child{border-top: 1px solid #54502d;}
|
||||
.side-menu.list-blocks .monitor_block{float:none;width:100%;padding: 10px}
|
||||
.side-menu.list-blocks .monitor_block.ui-sortable-helper{background:rgba(0,0,0,0.6);border-radius:5px;padding:5px;border:0}
|
||||
.side-menu.list-blocks .monitor_block .list-data{display:block}
|
||||
.side-menu.list-blocks .monitor_block img{width:60px;height:60px;cursor:pointer;display:inline-block;margin-right:10px;border-radius:50%;vertical-align:top;border:0}
|
||||
.nav-xs.side-menu.list-blocks .monitor_block img{width:40px;height:40px;}
|
||||
.side-menu.list-blocks .monitor_block .box{width:calc(100% - 70px);display:inline-block}
|
||||
.nav-xs.side-menu.list-blocks .monitor_block .list-data{display:none}
|
||||
#monitors_list .monitor_block{transition:none}
|
||||
.dropdown-menu.scrollable{max-height:300px}
|
||||
.upload_file input{display:none}
|
||||
#video_preview .stream-objects{right:0;margin:auto;display:inline-block;position:relative;width:auto}
|
||||
.stream-block,.stream-objects{overflow: hidden!important}
|
||||
.stream-objects{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}
|
||||
.stream-objects .tag{position:absolute;bottom:100%;left:0;background:red;color:#fff;font-family:monospace;font-size:80%;border-radius:5px 5px 0 0 ;padding:3px 5px;}
|
||||
.stream-objects .stream-detected-object{position:absolute;top:0;left:0;border:3px solid red;background:transparent;border-radius:5px}
|
||||
.stream-objects .stream-detected-point{position:absolute;top:0;left:0;border:3px solid yellow;background:transparent;border-radius:5px}
|
||||
.stream-objects .point{position:absolute;top:0;left:0;border:3px solid red;border-radius:50%}
|
||||
|
||||
|
||||
#side_menu_right.nav-xs{width:0!important;overflow:hidden}
|
||||
.side-menu table{color:#fff;}
|
||||
#main_canvas{background:#333;color:#fff;padding-top:0}
|
||||
#main_header{background:#222;color:#fff;}
|
||||
#logs_modal table tr td:first-child{width:10%}
|
||||
[class_toggle]{cursor:pointer}
|
||||
|
||||
.form-group label{width:100%}
|
||||
|
||||
#pvideo_viewer iframe{border:0;width:100%;height:350px;margin-bottom:10px;overflow:hidden}
|
||||
#pvideo_viewer video{max-height:300px;max-width:100%;}
|
||||
#pvideo_viewer .holder{height:300px;}
|
||||
#pvideo_viewer h3{margin-top:0}
|
||||
#pvideo_viewer .progressBar{position:relative;}
|
||||
#pvideo_viewer .bufferBar{position:absolute;left:0;top:0;opacity:0.4}
|
||||
#pvideo_viewer .timeBar{position:relative;z-index: 222;background:transparent}
|
||||
#pvideo_viewer h3{font-family:monospace}
|
||||
|
||||
#vis_monitors{overflow:auto;max-height:400px}
|
||||
#vis_monitors .btn-group-vertical{width:100%}
|
||||
|
||||
/*timeline*/
|
||||
#timelapse_video_line{overflow-y:scroll;overflow-x:hidden;max-height:400px;margin:0;text-align:left}
|
||||
#timelapse_video_display .videoBefore,#timelapse_video_display .videoAfter{display:none}
|
||||
.timelapse_video:not(:last-child){border-bottom:1px solid #444;}
|
||||
.timelapse_video .frame{width:50px;height:50px;background-size:cover;background-position:center;border-radius:5px}
|
||||
.timelapse_video>div>div:not(:last-child){padding-right:10px}
|
||||
.timelapse_video .flex-block:not(:last-child){padding-bottom:10px}
|
||||
.timelapse_video.list-group-item{padding:10px}
|
||||
.timelapse_hud{position: relative;background:#000}
|
||||
.timelapse_hud .timelapse_playRate{position: absolute;font-family: monospace;top:10px;right:0;left:0;margin:auto;font-size:23px}
|
||||
#timelapse .progress-bar{transition:0.5s!important}
|
||||
.timelapse_hud .controlBar{position: absolute;background:rgba(22,22,22,0.8);width:100%;left:0;bottom:0;}
|
||||
.timelapse_hud .hover-hide{opacity:0}
|
||||
.timelapse_hud:hover .hover-hide{opacity:1;z-index:5}
|
||||
.video_grid{overflow: auto;height: 100%;display: block;}
|
||||
.video_grid .col-md-2{padding-left:5px;padding-right:5px;padding-bottom:10px}
|
||||
.video_grid .thumb{width:100%;height:150px;display:inline-block;background-size:cover;position:relative;overflow:hidden;border-radius:4px;border:1px solid #000;box-shadow:0 0 10px #151515}
|
||||
.video_grid .thumb .title-strip, .video_grid .thumb .button-strip{width:100%;position:absolute;left:0;background:rgba(0,0,0,0.7);color:#fff;padding:4px}
|
||||
.video_grid .thumb .title-strip{top:0;opacity:0.5}
|
||||
.video_grid .thumb .button-strip{bottom:0;opacity:0}
|
||||
.video_grid .thumb:hover .title-strip, .video_grid .thumb:hover .button-strip{opacity:1}
|
||||
|
||||
.table-striped>tbody>tr>td{vertical-align:middle}
|
||||
.table-striped .thumbnail{width:100px;height:80px;border-radius:5px;margin:0;display:inline-block;}
|
||||
#motion_list{height:155px;overflow:auto;border-radius:5px;border:1px solid #444;position:relative;background: #222;margin:0}
|
||||
.dark .list-group-item{border-color: #444;background:#222}
|
||||
.dark .list-group-item.active{background:#c49a68;border-color:#a7865f}
|
||||
.novideos{text-transform: uppercase;text-align: center;border-bottom:0!important;padding-top: 55%!important;letter-spacing:2px}
|
||||
|
||||
.btn-warning {
|
||||
color: #fff;
|
||||
background-color: #c49a68;
|
||||
border-color: #c49a68;
|
||||
}
|
||||
|
||||
.dark.modal .modal-header,.dark.modal .modal-footer{background:#333;border-color:#444;}
|
||||
.dark.modal .modal-header{color:#fff;}
|
||||
.dark.modal .modal-footer>*:not(.btn){color:#fff;}
|
||||
.dark.modal .modal-body{background:#333;}
|
||||
.dark.modal .close{color:#fff;}
|
||||
.dark.modal{color:#fff;}
|
||||
.dark .table-striped>tbody>tr:nth-of-type(even){background:#616161}
|
||||
.dark .table-striped>tbody>tr>td{border-color:#222;color:#fff}
|
||||
.dark .table-striped>thead>tr>th{border-color:#222;color:#fff;background:#616161;vertical-align:middle;}
|
||||
.dark .table-striped>tbody>tr:nth-of-type(odd){background-color: #4c4747;}
|
||||
.dark .table>tbody>tr.active>td{background:inherit;border:0}
|
||||
.dark code{color: #c49a68;background-color: #36333d;}
|
||||
.dark a:not(.btn){color: #c49a68;}
|
||||
.follow-list ul{padding:0;margin:0;font-family:"Roboto","Helvetica","Arial",sans-serif;}
|
||||
.follow-list ul a:not(.btn){color:#fff}
|
||||
.os_bars{width:600px;display:inline-block;padding:5px 0 0 10px}
|
||||
@media screen and (max-width: 600px){
|
||||
.os_bars{width:200px;}
|
||||
.os_bars label{padding:2.5px 0;margin:0;font-size:8pt}
|
||||
}
|
||||
.os_bars .display-table .display-table-cell{padding:5px;vertical-align:center;width:33%}
|
||||
.progress{height:5px;margin:0;}
|
||||
.os_bars label,.os_bars .percent{padding:2.5px 0;margin:0;font-size:7.5pt}
|
||||
.ui-pnotify-hide .ui-pnotify{display:none!important}
|
||||
/*cool dropdown thing*/
|
||||
ul.msg_list li {
|
||||
background: #f7f7f7;color:#333;
|
||||
padding: 5px;
|
||||
display: list-item;
|
||||
margin: 6px 6px 0;
|
||||
width: 96% !important
|
||||
}
|
||||
|
||||
ul.msg_list li div{display:block}
|
||||
|
||||
ul.msg_list li:last-child {
|
||||
margin-bottom: 6px;
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
ul.msg_list li a {
|
||||
padding: 3px 5px !important
|
||||
}
|
||||
ul.msg_list li .progress {
|
||||
height:5px;margin:10px 0 0 0;
|
||||
}
|
||||
|
||||
ul.msg_list li .image img {
|
||||
border-radius: 2px 2px 2px 2px;
|
||||
-webkit-border-radius: 2px 2px 2px 2px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
width: 11%
|
||||
}
|
||||
|
||||
ul.msg_list li .time {
|
||||
font-size: 11px;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
ul.msg_list li .message {
|
||||
display: block !important;
|
||||
font-size: 11px
|
||||
}
|
||||
|
||||
.dropdown-menu.msg_list span {
|
||||
white-space: normal
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
border: medium none;
|
||||
box-shadow: none;
|
||||
display: none;
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
left: 0;
|
||||
list-style: none outside none;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
text-shadow: none;
|
||||
top: 100%;
|
||||
z-index: 9998;
|
||||
border: 1px solid #D9DEE4;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0
|
||||
}
|
||||
|
||||
.dropdown-menu>li>a {
|
||||
color: #5A738E
|
||||
}
|
||||
|
||||
.navbar-nav .open .dropdown-menu {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
margin-top: 0;
|
||||
border: 1px solid #D9DEE4;
|
||||
-webkit-box-shadow: none;
|
||||
right: 0;
|
||||
left: auto;
|
||||
width: 220px
|
||||
}
|
||||
.is-small-screen .nav>li{display:inline-block}
|
||||
.navbar-nav .open .dropdown-menu li a{padding:7px 15px}
|
||||
.navbar-nav .open .dropdown-menu.msg_list {
|
||||
width: 300px
|
||||
}
|
||||
.nav>li>a{color:#fff}
|
||||
.nav>li>a:focus, .nav>li>a:hover,.nav .open>a, .nav .open>a:focus, .nav .open>a:hover{background:#867560}
|
||||
|
||||
.mdl-js-layout.hide-side:not(.is-small-screen){
|
||||
|
||||
}
|
||||
@media screen and (min-width: 1025px){
|
||||
.mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__drawer {
|
||||
width: 0px;transition:0.2s
|
||||
}
|
||||
}
|
||||
.mdl-js-layout.hide-side:not(.is-small-screen) .mdl-layout__header .mdl-layout__drawer-button{
|
||||
display:none;
|
||||
}
|
||||
.mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__content{
|
||||
margin-left: 0px;transition:0.2s
|
||||
}
|
||||
.mdl-js-layout.hide-side:not(.is-small-screen)>.mdl-layout__header{
|
||||
margin-left: 0px;width:100%;transition:0.2s
|
||||
}
|
||||
/*Control Pad*/
|
||||
.PTZ_controls {
|
||||
z-index: 111;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
margin:0;
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
}
|
||||
.PTZ_controls .btn-group{margin-top:10px}
|
||||
.PTZ_controls .pad {
|
||||
position: relative;
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
background: #b7b7b7;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4);
|
||||
}
|
||||
.PTZ_controls .control {
|
||||
position: absolute;
|
||||
}
|
||||
.PTZ_controls .pad .control {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background: #636363;
|
||||
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.PTZ_controls .zoom_in{
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .zoom_out{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .nv_enabled{
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .nv_disable{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.PTZ_controls .pad .top {
|
||||
top: 15px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -15px;
|
||||
}
|
||||
.PTZ_controls .pad .left {
|
||||
top: 45px;
|
||||
left: 15px;
|
||||
}
|
||||
.PTZ_controls .pad .right {
|
||||
top: 45px;
|
||||
right: 15px;
|
||||
}
|
||||
.PTZ_controls .pad .control.right:before {
|
||||
transform: rotate(90deg) translate(-3px, -5px);
|
||||
}
|
||||
.PTZ_controls .pad .bottom {
|
||||
bottom: 15px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -15px;
|
||||
}
|
||||
/* Overlap the other controls to hide box-shadow */
|
||||
.PTZ_controls .pad .middle {
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
z-index: 5;
|
||||
top: 43px;
|
||||
left: 50%;
|
||||
margin: 0 0 0 -17px;
|
||||
box-shadow: none;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.PTZ_controls .pad .middle:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -35% 0 0 -35%;
|
||||
content: '';
|
||||
background: #636363;
|
||||
height: 70%;
|
||||
width: 70%;
|
||||
border-radius: 100%;
|
||||
box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2);
|
||||
}
|
||||
/*Digital Zoom*/
|
||||
.stream-block{
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
}
|
||||
.zoomGlass {
|
||||
overflow: hidden;
|
||||
transition: none;
|
||||
width: 175px; height: 175px;
|
||||
position: absolute;
|
||||
border-radius: 15px;
|
||||
border: 3px solid #ddd;
|
||||
z-index:9999;
|
||||
}
|
||||
.zoomGlass iframe,.zoomGlass canvas{position:absolute;transition: none;}
|
||||
.zoomGlass .hoverShade{position:absolute;width:100%;height:100%}
|
||||
|
||||
.dark.form-control,.dark .form-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: #eee;
|
||||
background-color: #36333d;
|
||||
background-image: none;
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
||||
}
|
||||
|
||||
.dark.form-control:focus,.dark .form-control:focus {
|
||||
color: #ddd;
|
||||
background-color: #333;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/*** custom checkboxes ***/
|
||||
|
||||
.checkbox input[type=checkbox] { display:none; } /* to hide the checkbox itself */
|
||||
.checkbox input[type=checkbox] + label:before {
|
||||
font-family: FontAwesome;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.checkbox input[type=checkbox] + label:before { content: "\f096"; } /* unchecked icon */
|
||||
.checkbox input[type=checkbox] + label:before { letter-spacing: 10px; } /* space between checkbox and label */
|
||||
|
||||
.checkbox input[type=checkbox]:checked + label:before { content: "\f046"; } /* checked icon */
|
||||
.checkbox input[type=checkbox]:checked + label:before { letter-spacing: 5px; } /* allow space for check mark */
|
||||
|
||||
/*Clock*/
|
||||
#time-date {font-size:12px; text-align:center;}
|
||||
@media screen and (min-width:1025px){
|
||||
#clock {padding-right:35px}
|
||||
}
|
||||
#clock ul { width:150px; margin:0 auto; padding:0px; list-style:none; text-align:center; }
|
||||
#clock ul li { display:inline; font-size:1.6em; text-align:center;font-family:monospace;}
|
||||
|
||||
#clock .point { position:relative; -moz-animation:mymove 1s ease infinite; -webkit-animation:mymove 1s ease infinite; }
|
||||
|
||||
/*custom vis.js css*/
|
||||
.vis-timeline{background:#212121;color:#fff;border-color:#444}
|
||||
.vis-time-axis .vis-text{color: #dedede}
|
||||
.vis-item.vis-range .vis-item-content{background:#333;color:#fff}
|
||||
.vis-time-axis .vis-grid.vis-minor{border-color:#444}
|
||||
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
.full.modal .modal-body, .medium.modal .modal-body {
|
||||
height:70%
|
||||
}
|
||||
}
|
||||
|
||||
/*animations*/
|
||||
@keyframes blink {
|
||||
0% { opacity:1 }
|
||||
50% { opacity:0 }
|
||||
100% { opacity:1 }
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
0% { opacity:1 }
|
||||
50% { opacity:0 }
|
||||
100% { opacity:1 }
|
||||
}
|
||||
.blink,[mode="Record"] .lamp {
|
||||
-webkit-animation: blink 1s linear infinite;
|
||||
-moz-animation: blink 1s linear infinite;
|
||||
animation: blink 1s linear infinite;
|
||||
}
|
||||
.mdl-menu__item>div{display:flex;align-items: center;width:100%}
|
||||
.mdl-menu__item>div>i{margin-right:5px}
|
||||
/*For languages that are right to left*/
|
||||
.right-to-left {text-align:right}
|
||||
.right-to-left select{direction: rtl;}
|
||||
.right-to-left input,.right-to-left textarea{direction: rtl;text-align:right}
|
||||
.right-to-left .form-group label span{padding-right:10px}
|
||||
.right-to-left .modal-footer{text-align:left}
|
||||
.right-to-left .mdl-menu__item>div>*{flex:1}
|
||||
.right-to-left .mdl-menu__item>div>i{margin-right:0;margin-left:5px}
|
||||
.right-to-left .mdl-menu__item{text-align:right}
|
||||
.right-to-left .mdl-menu__item i{float:right}
|
||||
.right-to-left .pull-right,.right-to-left .close{float:left!important}
|
||||
.right-to-left .pull-left,.right-to-left .mdl-menu__item span{float:right!important}
|
||||
/* All-CSS Toggle Switch (Checkbox Hack) by Marcus Burnette - https://codepen.io/mburnette/pen/LxNxNg */
|
||||
.marc-toggle {
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
}
|
||||
.marc-toggle.abs-bot-left {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
.marc-toggle.abs-bot-right {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
.marc-toggle input[type=checkbox]{
|
||||
height: 0;
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.marc-toggle label {
|
||||
cursor: pointer;
|
||||
text-indent: -9999px;
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
background: grey;
|
||||
display: block;
|
||||
border-radius: 100px;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.marc-toggle label:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #fff;
|
||||
border-radius: 90px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.marc-toggle input:checked + label {
|
||||
background: #00118c;
|
||||
}
|
||||
|
||||
.marc-toggle input:checked + label:after {
|
||||
left: calc(100% - 5px);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.marc-toggle label:active:after {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
/*hexagon pattern*/
|
||||
.bg-hexagon {
|
||||
background-color: #054e9f;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%23fdfdfd' fill-opacity='0.4' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
|
@ -608,15 +608,6 @@ _:-ms-input-placeholder, :root .demo-graph {
|
|||
opacity: 0.46;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.social-btn__twitter {
|
||||
background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png');
|
||||
}
|
||||
.social-btn__blogger {
|
||||
background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_facebook_black_24dp.png');
|
||||
}
|
||||
.social-btn__gplus {
|
||||
background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_gplus_black_24dp.png');
|
||||
}
|
||||
.social-btn__share {
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
background: transparent;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
$(document).ready(function(e){
|
||||
//api window
|
||||
$.apM={e:$('#apis')};$.apM.f=$.apM.e.find('form');
|
||||
$.apM.md=$.apM.f.find('[detail]');
|
||||
$.apM.md.change($.ccio.form.details).first().change();
|
||||
$.apM.f.submit(function(e){
|
||||
e.preventDefault();e.e=$(this),e.s=e.e.serializeObject();
|
||||
e.er=[];
|
||||
if(!e.s.ip||e.s.ip.length<7){e.er.push('Enter atleast one IP')}
|
||||
if(e.er.length>0){$.apM.e.find('.msg').html(e.er.join('<br>'));return;}
|
||||
$.each(e.s,function(n,v){e.s[n]=v.trim()})
|
||||
// e.s = {
|
||||
// "ip": "",
|
||||
// "details": "{\"get_monitors\":\"1\",\"control_monitors\":\"1\",\"get_logs\":\"1\",\"watch_stream\":\"1\",\"watch_snapshot\":\"1\",\"watch_videos\":\"1\",\"delete_videos\":\"1\"}"
|
||||
// }
|
||||
$.post($.ccio.init('location',$user)+$user.auth_token+'/api/'+$user.ke+'/add',{data:JSON.stringify(e.s)},function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
});
|
||||
$.apM.e.on('click','.delete',function(e){
|
||||
e.e=$(this);e.p=e.e.parents('[api_key]'),e.code=e.p.attr('api_key');
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text('Delete API Key');
|
||||
e.html='Do you want to delete this API key? You cannot recover it.';
|
||||
$.confirm.body.html(e.html);
|
||||
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
|
||||
$.post($.ccio.init('location',$user)+$user.auth_token+'/api/'+$user.ke+'/delete',{data:JSON.stringify({code:e.code})},function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,299 @@
|
|||
$.ccio.permissionCheck = function(toCheck,monitorId){
|
||||
var details = $user.details
|
||||
if(details.sub && details.allmonitors === '0'){
|
||||
var chosenValue = details[toCheck]
|
||||
if(details[toCheck] instanceof Array && chosenValue.indexOf(monitorId) > -1){
|
||||
return true
|
||||
}else if(chosenValue === '1'){
|
||||
return true
|
||||
}
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
$.ccio.op = function(r,rr,rrr){
|
||||
if(!rrr){rrr={};};if(typeof rrr === 'string'){rrr={n:rrr}};if(!rrr.n){rrr.n='ShinobiOptions_'+location.host}
|
||||
ii={o:localStorage.getItem(rrr.n)};try{ii.o=JSON.parse(ii.o)}catch(e){ii.o={}}
|
||||
if(!ii.o){ii.o={}}
|
||||
if(r&&rr&&!rrr.x){
|
||||
ii.o[r]=rr;
|
||||
}
|
||||
switch(rrr.x){
|
||||
case 0:
|
||||
delete(ii.o[r])
|
||||
break;
|
||||
case 1:
|
||||
delete(ii.o[r][rr])
|
||||
break;
|
||||
}
|
||||
localStorage.setItem(rrr.n,JSON.stringify(ii.o))
|
||||
return ii.o
|
||||
}
|
||||
$.ccio.log = function(x,y,z){
|
||||
if($.ccio.op().browserLog==="1"){
|
||||
if(!y){y=''};if(!z){z=''};
|
||||
console.log(x,y,z)
|
||||
}
|
||||
}
|
||||
$.ccio.gid = function(x){
|
||||
if(!x){x=10};var t = "";var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
for( var i=0; i < x; i++ )
|
||||
t += p.charAt(Math.floor(Math.random() * p.length));
|
||||
return t;
|
||||
};
|
||||
$.ccio.downloadJSON = function(jsonToDownload,filename,errorResponse){
|
||||
var arr = jsonToDownload;
|
||||
if(arr.length===0 && errorResponse){
|
||||
errorResponse.type = 'error'
|
||||
$.ccio.init('note',errorResponse);
|
||||
return
|
||||
}
|
||||
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(arr,null,3));
|
||||
$('#temp').html('<a></a>')
|
||||
.find('a')
|
||||
.attr('href',dataStr)
|
||||
.attr('download',filename)
|
||||
[0].click()
|
||||
}
|
||||
$.ccio.timeObject = function(time,isUTC){
|
||||
if(isUTC === true){
|
||||
return moment(time).utc()
|
||||
}
|
||||
return moment(time)
|
||||
}
|
||||
$.ccio.base64ArrayBuffer = function(arrayBuffer) {
|
||||
var base64 = ''
|
||||
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
|
||||
var bytes = new Uint8Array(arrayBuffer)
|
||||
var byteLength = bytes.byteLength
|
||||
var byteRemainder = byteLength % 3
|
||||
var mainLength = byteLength - byteRemainder
|
||||
|
||||
var a, b, c, d
|
||||
var chunk
|
||||
|
||||
// Main loop deals with bytes in chunks of 3
|
||||
for (var i = 0; i < mainLength; i = i + 3) {
|
||||
// Combine the three bytes into a single integer
|
||||
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
|
||||
|
||||
// Use bitmasks to extract 6-bit segments from the triplet
|
||||
a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
|
||||
b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
|
||||
c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
|
||||
d = chunk & 63 // 63 = 2^6 - 1
|
||||
|
||||
// Convert the raw binary segments to the appropriate ASCII encoding
|
||||
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
|
||||
}
|
||||
|
||||
// Deal with the remaining bytes and padding
|
||||
if (byteRemainder == 1) {
|
||||
chunk = bytes[mainLength]
|
||||
|
||||
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
|
||||
|
||||
// Set the 4 least significant bits to zero
|
||||
b = (chunk & 3) << 4 // 3 = 2^2 - 1
|
||||
|
||||
base64 += encodings[a] + encodings[b] + '=='
|
||||
} else if (byteRemainder == 2) {
|
||||
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
|
||||
|
||||
a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
|
||||
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
|
||||
|
||||
// Set the 2 least significant bits to zero
|
||||
c = (chunk & 15) << 2 // 15 = 2^4 - 1
|
||||
|
||||
base64 += encodings[a] + encodings[b] + encodings[c] + '='
|
||||
}
|
||||
|
||||
return base64
|
||||
}
|
||||
$.ccio.snapshot=function(e,cb){
|
||||
var image_data,url;
|
||||
e.details=JSON.parse(e.mon.details);
|
||||
if($.ccio.op().jpeg_on!==true){
|
||||
var extend=function(image_data,width,height){
|
||||
var len = image_data.length
|
||||
var arraybuffer = new Uint8Array( len );
|
||||
for (var i = 0; i < len; i++) {
|
||||
arraybuffer[i] = image_data.charCodeAt(i);
|
||||
}
|
||||
try {
|
||||
var blob = new Blob([arraybuffer], {type: 'application/octet-stream'});
|
||||
} catch (e) {
|
||||
var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder);
|
||||
bb.append(arraybuffer);
|
||||
var blob = bb.getBlob('application/octet-stream');
|
||||
}
|
||||
url = (window.URL || window.webkitURL).createObjectURL(blob);
|
||||
finish(url,image_data,width,height);
|
||||
try{
|
||||
setTimeout(function(){
|
||||
URL.revokeObjectURL(url)
|
||||
},10000)
|
||||
}catch(er){}
|
||||
}
|
||||
var finish = function(url,image_data,width,height){
|
||||
cb(url,image_data,width,height);
|
||||
}
|
||||
switch(JSON.parse(e.mon.details).stream_type){
|
||||
case'hls':case'flv':case'mp4':
|
||||
$.ccio.snapshotVideo($('[mid='+e.mon.mid+'].monitor_item video')[0],function(base64,video_data,width,height){
|
||||
extend(video_data,width,height)
|
||||
})
|
||||
break;
|
||||
case'mjpeg':
|
||||
$('#temp').html('<canvas></canvas>')
|
||||
var c = $('#temp canvas')[0];
|
||||
var img = $('img',$('[mid='+e.mon.mid+'].monitor_item .stream-element').contents())[0];
|
||||
c.width = img.width;
|
||||
c.height = img.height;
|
||||
var ctx = c.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0,c.width,c.height);
|
||||
extend(atob(c.toDataURL('image/jpeg').split(',')[1]),c.width,c.height)
|
||||
break;
|
||||
case'h265':
|
||||
var c = $('[mid='+e.mon.mid+'].monitor_item canvas')[0];
|
||||
var ctx = c.getContext('2d');
|
||||
extend(atob(c.toDataURL('image/jpeg').split(',')[1]),c.width,c.height)
|
||||
break;
|
||||
case'b64':
|
||||
base64 = e.mon.last_frame.split(',')[1];
|
||||
var image_data = new Image();
|
||||
image_data.src = base64;
|
||||
extend(atob(base64),image_data.width,image_data.height)
|
||||
break;
|
||||
case'jpeg':case'h265':
|
||||
url=e.p.find('.stream-element').attr('src');
|
||||
image_data = new Image();
|
||||
image_data.src = url;
|
||||
finish(url,image_data,image_data.width,image_data.height);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
url=e.p.find('.stream-element').attr('src');
|
||||
image_data = new Image();
|
||||
image_data.src = url;
|
||||
cb(url,image_data,image_data.width,image_data.height);
|
||||
}
|
||||
}
|
||||
$.ccio.snapshotVideo=function(videoElement,cb){
|
||||
var image_data;
|
||||
var base64
|
||||
$('#temp').html('<canvas></canvas>')
|
||||
var c = $('#temp canvas')[0];
|
||||
var img = videoElement;
|
||||
c.width = img.videoWidth;
|
||||
c.height = img.videoHeight;
|
||||
var ctx = c.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0,c.width,c.height);
|
||||
base64=c.toDataURL('image/jpeg')
|
||||
image_data=atob(base64.split(',')[1]);
|
||||
var arraybuffer = new ArrayBuffer(image_data.length);
|
||||
var view = new Uint8Array(arraybuffer);
|
||||
for (var i=0; i<image_data.length; i++) {
|
||||
view[i] = image_data.charCodeAt(i) & 0xff;
|
||||
}
|
||||
try {
|
||||
var blob = new Blob([arraybuffer], {type: 'application/octet-stream'});
|
||||
} catch (e) {
|
||||
var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder);
|
||||
bb.append(arraybuffer);
|
||||
var blob = bb.getBlob('application/octet-stream');
|
||||
}
|
||||
cb(base64,image_data,c.width,c.height);
|
||||
}
|
||||
$.ccio.magnifyStream = function(e){
|
||||
if(!e.p){
|
||||
e.e=$(this),
|
||||
e.p=e.e.parents('[mid]')
|
||||
}
|
||||
if(e.animate === true){
|
||||
var zoomGlassAnimate = 'animate'
|
||||
}else{
|
||||
var zoomGlassAnimate = 'css'
|
||||
}
|
||||
if(e.auto === true){
|
||||
var streamBlockOperator = 'position'
|
||||
}else{
|
||||
var streamBlockOperator = 'offset'
|
||||
}
|
||||
if(e.useCanvas === true){
|
||||
var magnifiedElement = 'canvas'
|
||||
}else{
|
||||
var magnifiedElement = 'iframe'
|
||||
}
|
||||
e.ke=e.p.attr('ke'),//group key
|
||||
e.mid=e.p.attr('mid'),//monitor id
|
||||
e.auth=e.p.attr('auth'),//authkey
|
||||
e.mon=$.ccio.mon[e.ke+e.mid+e.auth]//monitor configuration
|
||||
if(e.zoomAmount)e.mon.zoomAmount=3;
|
||||
if(!e.mon.zoomAmount)e.mon.zoomAmount=3;
|
||||
e.height=parseFloat(e.p.attr('realHeight')) * e.mon.zoomAmount//height of stream
|
||||
e.width=parseFloat(e.p.attr('realWidth')) * e.mon.zoomAmount;//width of stream
|
||||
var targetForZoom = e.p.find('.stream-element');
|
||||
zoomGlass = e.p.find(".zoomGlass");
|
||||
var zoomFrame = function(){
|
||||
var magnify_offset = e.p.find('.stream-block')[streamBlockOperator]();
|
||||
var mx = e.pageX - magnify_offset.left;
|
||||
var my = e.pageY - magnify_offset.top;
|
||||
var rx = Math.round(mx/targetForZoom.width()*e.width - zoomGlass.width()/2)*-1;
|
||||
var ry = Math.round(my/targetForZoom.height()*e.height - zoomGlass.height()/2)*-1;
|
||||
var px = mx - zoomGlass.width()/2;
|
||||
var py = my - zoomGlass.height()/2;
|
||||
zoomGlass[zoomGlassAnimate]({left: px, top: py}).find(magnifiedElement)[zoomGlassAnimate]({left: rx, top: ry});
|
||||
}
|
||||
if(!e.height||!e.width||zoomGlass.length===0){
|
||||
$.ccio.snapshot(e,function(url,buffer,width,height){
|
||||
e.width = width * e.mon.zoomAmount;
|
||||
e.height = height * e.mon.zoomAmount;
|
||||
e.p.attr('realWidth',width)
|
||||
e.p.attr('realHeight',height)
|
||||
zoomGlass = e.p.find(".zoomGlass");
|
||||
if(zoomGlass.length===0){
|
||||
if(e.useCanvas === true){
|
||||
e.p.append('<div class="zoomGlass"><canvas class="blenderCanvas"></canvas></div>');
|
||||
}else{
|
||||
e.p.append('<div class="zoomGlass"><iframe src="'+e.auth+'/embed/'+e.ke+'/'+e.mid+'/fullscreen|jquery|relative"/><div class="hoverShade"></div></div>');
|
||||
}
|
||||
zoomGlass = e.p.find(".zoomGlass");
|
||||
}
|
||||
zoomGlass.find(magnifiedElement).css({height:e.height,width:e.width});
|
||||
zoomFrame()
|
||||
})
|
||||
}else{
|
||||
zoomGlass.find(magnifiedElement).css({height:e.height,width:e.width});
|
||||
zoomFrame()
|
||||
}
|
||||
}
|
||||
$.ccio.destroyStream = function(d,user,killElement){
|
||||
if(d.mid && !d.id)d.id = d.mid
|
||||
console.log(d.ke+d.id+user.auth_token)
|
||||
console.log($.ccio.mon[d.ke+d.id+user.auth_token])
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token]){
|
||||
console.log('destroy')
|
||||
$.ccio.init('closeVideo',{mid:d.id,ke:d.ke},user);
|
||||
$.ccio.init('jpegModeStop',{mid:d.id,ke:d.ke},user);
|
||||
$.ccio.init('clearTimers',d,user)
|
||||
clearInterval($.ccio.mon[d.ke+d.id+user.auth_token].signal);delete($.ccio.mon[d.ke+d.id+user.auth_token].signal);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].watch = 0;
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount = 0
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].hls){$.ccio.mon[d.ke+d.id+user.auth_token].hls.destroy()}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].Poseidon){$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.stop()}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].Base64){$.ccio.mon[d.ke+d.id+user.auth_token].Base64.disconnect()}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].h265Socket){$.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.disconnect()}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].h265Player){$.ccio.mon[d.ke+d.id+user.auth_token].h265Player.stop()}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].dash){$.ccio.mon[d.ke+d.id+user.auth_token].dash.reset()}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream && $.ccio.mon[d.ke+d.id+user.auth_token].abort){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream.abort()
|
||||
}
|
||||
if(killElement){
|
||||
$.grid.data().removeWidget($('#monitor_live_'+d.id+user.auth_token))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
$.ccio={
|
||||
fr:$('#files_recent'),
|
||||
mon:{},
|
||||
useUTC: <%- config.useUTC || false %>,
|
||||
definitions: <%-JSON.stringify(define)%>,
|
||||
libURL: '<%-window.libURL%>'
|
||||
};
|
||||
<% if(config.DropboxAppKey){ %>
|
||||
$.ccio.DropboxAppKey = '<%-window.DropboxAppKey%>'
|
||||
<% } %>
|
||||
$.ccio.HWAccelChoices = [
|
||||
<% if(config.availableHWAccels) {
|
||||
var methods = {
|
||||
auto: {label:lang['Auto'],value:'auto'},
|
||||
drm: {label:lang['drm'],value:'drm'},
|
||||
cuvid: {label:lang['cuvid'],value:'cuvid'},
|
||||
vaapi: {label:lang['vaapi'],value:'vaapi'},
|
||||
qsv: {label:lang['qsv'],value:'qsv'},
|
||||
vdpau: {label:lang['vdpau'],value:'vdpau'},
|
||||
dxva2: {label:lang['dxva2'],value:'dxva2'},
|
||||
vdpau: {label:lang['vdpau'],value:'vdpau'},
|
||||
videotoolbox: {label:lang['videotoolbox'],value:'videotoolbox'}
|
||||
}
|
||||
config.availableHWAccels.forEach(function(availibleMethod){
|
||||
if(methods[availibleMethod]){ %>
|
||||
<%- JSON.stringify(methods[availibleMethod]) %>,
|
||||
<% }
|
||||
})
|
||||
}
|
||||
%>
|
||||
]
|
||||
try{
|
||||
$user.details = JSON.parse($user.details)
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
if(!$user.details.lang||$user.details.lang==''){
|
||||
$user.details.lang="<%-config.language%>"
|
||||
}
|
||||
switch($user.details.lang){
|
||||
case'ar'://Arabic
|
||||
case'bn'://Bengali
|
||||
$('body').addClass('right-to-left')
|
||||
$('.mdl-menu__item').each(function(n,v){
|
||||
v=$(v).find('i')
|
||||
v.appendTo(v.parent())
|
||||
})
|
||||
break;
|
||||
}
|
||||
window.chartColors = {
|
||||
red: 'rgb(255, 99, 132)',
|
||||
orange: 'rgb(255, 159, 64)',
|
||||
yellow: 'rgb(255, 205, 86)',
|
||||
green: 'rgb(75, 192, 192)',
|
||||
blue: 'rgb(54, 162, 235)',
|
||||
purple: 'rgb(153, 102, 255)',
|
||||
grey: 'rgb(201, 203, 207)'
|
||||
};
|
||||
//global form functions
|
||||
$.ccio.form={};
|
||||
$.ccio.form.details=function(e){
|
||||
e.ar={},e.f=$(this).parents('form');
|
||||
$.each(e.f.find('[detail]'),function(n,v){
|
||||
v=$(v);e.ar[v.attr('detail')]=v.val();
|
||||
});
|
||||
e.f.find('[name="details"]').val(JSON.stringify(e.ar));
|
||||
};
|
||||
$(document).ready(function(e){
|
||||
|
||||
//check switch UI
|
||||
e.o=$.ccio.op().switches;
|
||||
if(e.o){
|
||||
$.each(e.o,function(n,v){
|
||||
$('[system="switch"][switch="'+n+'"]').each(function(m,b){
|
||||
b=$(b);
|
||||
switch(b.attr('type')){
|
||||
case'text':
|
||||
if(v===1){
|
||||
b.addClass('text-success')
|
||||
}else{
|
||||
b.removeClass('text-success')
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
}else{
|
||||
$.ccio.op('switches',{notifyHide:0})
|
||||
}
|
||||
//set class toggle preferences
|
||||
e.o=$.ccio.op().class_toggle;
|
||||
if(e.o){
|
||||
$.each(e.o,function(n,v){
|
||||
if(v[1]===1){
|
||||
$(n).addClass(v[0])
|
||||
}else{
|
||||
$(n).removeClass(v[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
//set dropdown toggle preferences
|
||||
e.o = $.ccio.op().dropdown_toggle
|
||||
if(e.o){
|
||||
$.each(e.o,function(n,v){
|
||||
$('[dropdown_toggle="'+n+'"]').val(v).change()
|
||||
})
|
||||
}
|
||||
//set localStorage input values
|
||||
e.o = $.ccio.op()
|
||||
if(e.o){
|
||||
$.each(e.o,function(n,v){
|
||||
if(typeof v==='string'){
|
||||
var el = $('[localStorage="'+n+'"]')
|
||||
if(el.is(':checkbox') === false){
|
||||
el.val(v)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
document.addEventListener("fullscreenchange", onFullScreenChange, false);
|
||||
document.addEventListener("webkitfullscreenchange", onFullScreenChange, false);
|
||||
document.addEventListener("mozfullscreenchange", onFullScreenChange, false);
|
||||
function onFullScreenChange() {
|
||||
var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement;
|
||||
if(!fullscreenElement){
|
||||
$('.fullscreen').removeClass('fullscreen')
|
||||
setTimeout(function(){
|
||||
$('canvas.stream-element').resize();
|
||||
},2000)
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,61 @@
|
|||
$(document).ready(function(e){
|
||||
//filters window
|
||||
if(!$user.details.filters)$user.details.filters={};
|
||||
$.fI={e:$('#filters')};$.fI.f=$.fI.e.find('form');
|
||||
$.fI.md=$.fI.f.find('[detail]');
|
||||
$.ccio.init('filters');
|
||||
$.ccio.tm('filters-where');
|
||||
$.fI.e.on('click','.where .add',function(e){
|
||||
$.ccio.tm('filters-where');
|
||||
})
|
||||
$.fI.e.on('click','.where .remove',function(e){
|
||||
e.e=$('#filters_where .row');
|
||||
if(e.e.length>1){
|
||||
e.e.last().remove();
|
||||
}
|
||||
})
|
||||
$('#saved_filters').change(function(e){
|
||||
e.e=$(this),e.id=e.e.val();
|
||||
$('#filters_where').empty()
|
||||
if(e.id&&e.id!==''){
|
||||
e.name=$user.details.filters[e.id].name;
|
||||
$.each($user.details.filters[e.id].where,function(n,v){
|
||||
$.ccio.tm('filters-where',v)
|
||||
});
|
||||
$.each($user.details.filters[e.id],function(n,v){
|
||||
if(n==='where'){return}
|
||||
$.fI.f.find('[name="'+n+'"]').val(v);
|
||||
});
|
||||
}else{
|
||||
e.name=lang['Add New'];
|
||||
$.fI.f.find('[name="id"]').val($.ccio.gid(5));
|
||||
$.ccio.tm('filters-where');
|
||||
}
|
||||
$.fI.e.find('.filter_name').text(e.name)
|
||||
}).change()
|
||||
$.fI.f.find('.delete').click(function(e){
|
||||
e.s=$.fI.f.serializeObject();
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete Filter']);
|
||||
e.html=lang.confirmDeleteFilter;
|
||||
$.confirm.body.html(e.html);
|
||||
$.confirm.click({title:lang['Delete Filter'],class:'btn-danger'},function(){
|
||||
$.ccio.cx({f:'settings',ff:'filters',fff:'delete',form:e.s})
|
||||
});
|
||||
})
|
||||
$.fI.f.submit(function(e){
|
||||
e.preventDefault();e.e=$(this),e.s=e.e.serializeObject();
|
||||
e.er=[];
|
||||
$.each(e.s,function(n,v){e.s[n]=v.trim()})
|
||||
e.s.where=[];
|
||||
e.e.find('.where-row').each(function(n,v){
|
||||
n={};
|
||||
$(v).find('[where]').each(function(m,b){
|
||||
b=$(b);
|
||||
n[b.attr('where')]=b.val().trim();
|
||||
})
|
||||
e.s.where.push(n)
|
||||
})
|
||||
$.ccio.cx({f:'settings',ff:'filters',fff:'save',form:e.s})
|
||||
});
|
||||
})
|
|
@ -0,0 +1,143 @@
|
|||
$(document).ready(function(e){
|
||||
//detector filters window
|
||||
$.detectorFilters={e:$('#detector_filter')};
|
||||
$.detectorFilters.f=$.detectorFilters.e.find('form');
|
||||
$.detectorFilters.md=$.detectorFilters.f.find('[detail]');
|
||||
$.detectorFilters.getSelected = function(){
|
||||
return $('#detector_filters').val()
|
||||
}
|
||||
$.detectorFilters.drawOptions = function(){
|
||||
var dFilters = $.detectorFilters.getCurrent()
|
||||
$('#detector_filters optgroup').empty()
|
||||
$.each(dFilters,function(n,dFilter){
|
||||
$.ccio.tm('option',{auth_token:$user.auth_token,id:dFilter.id,name:dFilter.filter_name},'#detector_filters optgroup')
|
||||
})
|
||||
}
|
||||
$.detectorFilters.getCurrent = function(){
|
||||
try{
|
||||
return JSON.parse($.aM.e.find('[detail="detector_filters"]').val())
|
||||
}catch(err){
|
||||
return {}
|
||||
}
|
||||
}
|
||||
$.detectorFilters.save = function(){
|
||||
var currentVals = $.detectorFilters.getCurrent()
|
||||
currentVals[$.detectorFilters.lastSave.id] = $.detectorFilters.lastSave
|
||||
$.aM.e.find('[detail="detector_filters"]').val(JSON.stringify(currentVals)).change()
|
||||
}
|
||||
$.ccio.tm('detector-filters-where');
|
||||
$.detectorFilters.e.on('change','[where="p1"]',function(e){
|
||||
var el = $(this)
|
||||
var p1v = el.val()
|
||||
var parent = el.parents('.row')
|
||||
var p3 = parent.find('[where="p3"]')
|
||||
var options = []
|
||||
switch(p1v){
|
||||
case'time':
|
||||
options = [
|
||||
'00:00:00'
|
||||
]
|
||||
break;
|
||||
case'reason':
|
||||
options = [
|
||||
'licensePlate',
|
||||
'object',
|
||||
'motion',
|
||||
]
|
||||
break;
|
||||
case'plug':
|
||||
options = [
|
||||
'PythonYolo',
|
||||
'OpenCV',
|
||||
'built-in',
|
||||
]
|
||||
break;
|
||||
case'tag':
|
||||
options = [
|
||||
'car',
|
||||
'tree',
|
||||
'pottedplant',
|
||||
]
|
||||
break;
|
||||
}
|
||||
var msg = 'Value'
|
||||
if(options.length > 0){
|
||||
msg = 'Example : '+options.join(', ')
|
||||
}
|
||||
p3.attr('placeholder',msg)
|
||||
})
|
||||
$.detectorFilters.e.on('shown.bs.modal',function(e){
|
||||
$.detectorFilters.drawOptions()
|
||||
})
|
||||
$.detectorFilters.e.on('click','.where .add',function(e){
|
||||
$.ccio.tm('detector-filters-where');
|
||||
})
|
||||
$.detectorFilters.e.on('click','.where .remove',function(e){
|
||||
e.e=$('#detector_filters_where .row');
|
||||
if(e.e.length>1){
|
||||
e.e.last().remove();
|
||||
$('#detector_filters_where .row:last [where="p4"]').prop('disabled',true)
|
||||
}
|
||||
})
|
||||
$.detectorFilters.f.find('.delete').click(function(e){
|
||||
var currentVals = $.detectorFilters.getCurrent()
|
||||
var newObject = {}
|
||||
var deleteId = $.detectorFilters.getSelected()
|
||||
$.each(currentVals,function(id,obj){
|
||||
if(id === deleteId)return false;
|
||||
newObject[id] = obj
|
||||
})
|
||||
$.aM.e.find('[detail="detector_filters"]').val(JSON.stringify(newObject)).change()
|
||||
$.detectorFilters.drawOptions()
|
||||
})
|
||||
$('#detector_filters').change(function(){
|
||||
e = {}
|
||||
e.e=$(this),e.id=e.e.val();
|
||||
$('#detector_filters_where').empty()
|
||||
if(e.id&&e.id!==''){
|
||||
var currentFilter = $.detectorFilters.getCurrent()[e.id]
|
||||
e.name=currentFilter.name;
|
||||
$.each(currentFilter.where,function(n,v){
|
||||
$.ccio.tm('detector-filters-where',v)
|
||||
});
|
||||
$.each(currentFilter.actions,function(action,val){
|
||||
$.detectorFilters.e.find('[actions="'+action+'"]').val(val)
|
||||
});
|
||||
$.each(currentFilter,function(n,v){
|
||||
if(n==='where'){return}
|
||||
$.detectorFilters.f.find('[name="'+n+'"]').val(v);
|
||||
});
|
||||
}else{
|
||||
e.name=lang['Add New'];
|
||||
$.detectorFilters.f.find('[name="id"]').val($.ccio.gid(5));
|
||||
$.ccio.tm('detector-filters-where');
|
||||
}
|
||||
$.detectorFilters.e.find('.filter_name').text(e.name)
|
||||
}).change()
|
||||
$.detectorFilters.f.submit(function(ee){
|
||||
ee.preventDefault()
|
||||
e = {}
|
||||
e.e=$(this),e.s=e.e.serializeObject();
|
||||
e.er=[];
|
||||
$.each(e.s,function(n,v){e.s[n]=v.trim()})
|
||||
//create conditions object (where)
|
||||
e.s.where=[];
|
||||
e.e.find('.where-row').each(function(n,v){
|
||||
n={};
|
||||
$(v).find('[where]').each(function(m,b){
|
||||
b=$(b);
|
||||
n[b.attr('where')]=b.val().trim();
|
||||
})
|
||||
e.s.where.push(n)
|
||||
})
|
||||
// create actions object (do)
|
||||
e.s.actions={};
|
||||
e.e.find('.actions-row').each(function(n,v){
|
||||
b=$(v).find('[actions]');
|
||||
e.s.actions[b.attr('actions')] = b.val()
|
||||
})
|
||||
$.detectorFilters.lastSave = e.s
|
||||
$.detectorFilters.save()
|
||||
$.detectorFilters.e.modal('hide')
|
||||
});
|
||||
})
|
|
@ -0,0 +1,915 @@
|
|||
$.ccio.tm=function(x,d,z,user){
|
||||
var tmp='';if(!d){d={}};
|
||||
var k={}
|
||||
if(d&&d.user){
|
||||
user=d.user
|
||||
}
|
||||
if(!user){
|
||||
user=$user
|
||||
}
|
||||
if(d.id&&!d.mid){d.mid=d.id;}
|
||||
switch(x){
|
||||
case 0://video
|
||||
var url = $.ccio.init('videoUrlBuild',d)
|
||||
href = 'href="'+url+'"'
|
||||
// if(!d.filename){d.filename=$.ccio.init('tf',d.time)+'.'+d.ext;}
|
||||
d.dlname=d.mid+'-'+d.filename;
|
||||
d.startMoment=$.ccio.timeObject(d.time),
|
||||
d.endMoment=$.ccio.timeObject(d.end),
|
||||
d.hr=parseInt(d.startMoment.format('HH')),
|
||||
d.per=parseInt(d.hr/24*100);
|
||||
d.circle='<div title="at '+d.hr+' hours of '+d.startMoment.format('MMMM DD')+'" '+href+' video="launch" class="progress-circle progress-'+d.per+'"><span>'+d.hr+'</span></div>'
|
||||
tmp+='<li class="video-item glM'+d.mid+user.auth_token+'" auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" status="'+d.status+'" status="'+d.status+'" file="'+d.filename+'">'+d.circle+'<div><span title="'+d.endMoment.format()+'" class="livestamp"></span></div><div><div class="small"><b>'+lang.Start+'</b> : '+d.startMoment.format('h:mm:ss , MMMM Do YYYY')+'</div><div class="small"><b>'+lang.End+'</b> : '+d.endMoment.format('h:mm:ss , MMMM Do YYYY')+'</div></div><div><span class="pull-right">'+(parseInt(d.size)/1000000).toFixed(2)+'mb</span><div class="controls btn-group"><a class="btn btn-sm btn-primary" video="launch" '+href+'><i class="fa fa-play-circle"></i></a> <a download="'+d.dlname+'" '+href+' class="btn btn-sm btn-default"><i class="fa fa-download"></i></a>'
|
||||
if($.ccio.DropboxAppKey){ tmp+='<a video="download" host="dropbox" download="'+d.dlname+'" '+href+' class="btn btn-sm btn-default"><i class="fa fa-dropbox"></i></a>' }
|
||||
tmp+='<a title="'+lang['Delete Video']+'" video="delete" href="'+$.ccio.init('videoHrefToDelete',url)+'" class="btn btn-sm btn-danger permission_video_delete"><i class="fa fa-trash"></i></a></div></div></li>';
|
||||
$(z).each(function(n,v){
|
||||
v=$(v);
|
||||
if(v.find('.video-item').length>10){v.find('.video-item:last').remove()}
|
||||
})
|
||||
break;
|
||||
case 1://monitor icon
|
||||
d.src=placeholder.getData(placeholder.plcimg({bgcolor:'#b57d00',text:'...'}));
|
||||
tmp+='<div auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" title="'+d.mid+' : '+d.name+'" class="monitor_block glM'+d.mid+user.auth_token+' col-md-4"><img monitor="watch" class="snapshot" src="'+d.src+'"><div class="box"><div class="title monitor_name truncate">'+d.name+'</div><div class="list-data"><div class="monitor_mid">'+d.mid+'</div><div><b>'+lang['Save as']+' :</b> <span class="monitor_ext">'+d.ext+'</span></div><div><b>Status :</b> <span class="monitor_status">'+d.status+'</span></div></div><div class="icons text-center">'
|
||||
tmp+='<div class="btn-group btn-group-xs">'
|
||||
var buttons = {
|
||||
"Pop": {
|
||||
"label": "Pop",
|
||||
"attr": "monitor=\"pop\"",
|
||||
"class": "default",
|
||||
"icon": "external-link"
|
||||
},
|
||||
"Power Viewer": {
|
||||
"label": "Power Viewer",
|
||||
"attr": "monitor=\"powerview\"",
|
||||
"class": "default",
|
||||
"icon": "map-marker"
|
||||
},
|
||||
"Videos List": {
|
||||
"label": "Videos List",
|
||||
"attr": "monitor=\"videos_table\"",
|
||||
"class": "default",
|
||||
"icon": "film"
|
||||
},
|
||||
"Monitor Settings": {
|
||||
"label": "Monitor Settings",
|
||||
"attr": "monitor=\"edit\"",
|
||||
"class": "default",
|
||||
"icon": "wrench"
|
||||
}
|
||||
}
|
||||
if(!$.ccio.permissionCheck('video_view',d.mid)){
|
||||
delete(buttons["Videos List"])
|
||||
delete(buttons["Power Viewer"])
|
||||
}
|
||||
if(!$.ccio.permissionCheck('monitor_edit',d.mid)){
|
||||
delete(buttons["Monitor Settings"])
|
||||
}
|
||||
$.each(buttons,function(n,v){
|
||||
tmp+='<a class="btn btn-'+v.class+'" '+v.attr+' title="'+v.label+'"><i class="fa fa-'+v.icon+'"></i></a>'
|
||||
})
|
||||
tmp+='</div>\
|
||||
</div></div></div>';
|
||||
delete(d.src);
|
||||
break;
|
||||
case 2://monitor stream
|
||||
try{k.d=JSON.parse(d.details);}catch(er){k.d=d.details;}
|
||||
k.mode=$.ccio.init('humanReadMode',d.mode);
|
||||
var dataTarget = '.monitor_item[mid=\''+d.mid+'\'][ke=\''+d.ke+'\'][auth=\''+user.auth_token+'\']';
|
||||
tmp+='<div id="monitor_live_'+d.mid+user.auth_token+'" auth="'+user.auth_token+'" mid="'+d.mid+'" ke="'+d.ke+'" mode="'+k.mode+'" class="grid-stack-item monitor_item glM'+d.mid+user.auth_token+'"><div class="grid-stack-item-content">';
|
||||
tmp+='<div class="stream-block no-padding mdl-card__media mdl-color-text--grey-50">';
|
||||
tmp+='<div class="stream-objects"></div>';
|
||||
tmp+='<div class="stream-hud">'
|
||||
tmp+='<div class="camera_cpu_usage"><div class="progress"><div class="progress-bar progress-bar-danger" role="progressbar"><span></span></div></div></div>';
|
||||
tmp+='<div class="lamp" title="'+k.mode+'"><i class="fa fa-eercast"></i></div><div class="controls"><span title="'+lang['Currently viewing']+'" class="label label-default"><span class="viewers"></span></span> <a class="btn-xs btn-danger btn" monitor="mode" mode="record"><i class="fa fa-circle"></i> '+lang['Start Recording']+'</a> <a class="btn-xs btn-primary btn" monitor="mode" mode="start"><i class="fa fa-eye"></i> '+lang['Set to Watch Only']+'</a></div></div></div></div>'
|
||||
tmp+='<div class="mdl-card__supporting-text text-center">';
|
||||
tmp+='<div class="indifference detector-fade"><div class="progress"><div class="progress-bar progress-bar-danger" role="progressbar"><span></span></div></div></div>';
|
||||
tmp+='<div class="monitor_details">';
|
||||
tmp+='<div><span class="monitor_name">'+d.name+'</span><span class="monitor_not_record_copy">, '+lang['Recording FPS']+' : <span class="monitor_fps">'+d.fps+'</span></span></div>';
|
||||
tmp+='</div>';
|
||||
tmp+='<div class="btn-group btn-group-sm">'//start of btn list
|
||||
var buttons = {
|
||||
"Snapshot": {
|
||||
"label": "Snapshot",
|
||||
"attr": "monitor=\"snapshot\"",
|
||||
"class": "primary",
|
||||
"icon": "camera"
|
||||
},
|
||||
"Show Logs": {
|
||||
"label": "Show Logs",
|
||||
"attr": "monitor=\"show_data\"",
|
||||
"class": "warning",
|
||||
"icon": "exclamation-triangle"
|
||||
},
|
||||
"Control": {
|
||||
"label": "Control",
|
||||
"attr": "monitor=\"control_toggle\"",
|
||||
"class": "default arrows",
|
||||
"icon": "arrows"
|
||||
},
|
||||
"Status Indicator": {
|
||||
"label": "Status Indicator",
|
||||
"attr": "monitor=\"watch_on\"",
|
||||
"class": "success signal",
|
||||
"icon": "plug"
|
||||
},
|
||||
"Pop": {
|
||||
"label": "Pop",
|
||||
"attr": "monitor=\"pop\"",
|
||||
"class": "default",
|
||||
"icon": "external-link"
|
||||
},
|
||||
"Calendar": {
|
||||
"label": "Calendar",
|
||||
"attr": "monitor=\"calendar\"",
|
||||
"class": "default ",
|
||||
"icon": "calendar"
|
||||
},
|
||||
"Power Viewer": {
|
||||
"label": "Power Viewer",
|
||||
"attr": "monitor=\"powerview\"",
|
||||
"class": "default",
|
||||
"icon": "map-marker"
|
||||
},
|
||||
"Time-lapse": {
|
||||
"label": "Time-lapse",
|
||||
"attr": "monitor=\"timelapse\"",
|
||||
"class": "default",
|
||||
"icon": "angle-double-right"
|
||||
},
|
||||
"Video Grid": {
|
||||
"label": "Video Grid",
|
||||
"attr": "monitor=\"video_grid\"",
|
||||
"class": "default",
|
||||
"icon": "th"
|
||||
},
|
||||
"Videos List": {
|
||||
"label": "Videos List",
|
||||
"attr": "monitor=\"videos_table\"",
|
||||
"class": "default",
|
||||
"icon": "film"
|
||||
},
|
||||
"Monitor Settings": {
|
||||
"label": "Monitor Settings",
|
||||
"attr": "monitor=\"edit\"",
|
||||
"class": "default",
|
||||
"icon": "wrench"
|
||||
},
|
||||
"Fullscreen": {
|
||||
"label": "Fullscreen",
|
||||
"attr": "monitor=\"fullscreen\"",
|
||||
"class": "default",
|
||||
"icon": "arrows-alt"
|
||||
},
|
||||
"Close": {
|
||||
"label": "Close",
|
||||
"attr": "monitor=\"watch_off\"",
|
||||
"class": "danger",
|
||||
"icon": "times"
|
||||
}
|
||||
}
|
||||
if(!$.ccio.permissionCheck('video_view',d.mid)){
|
||||
delete(buttons["Videos List"])
|
||||
delete(buttons["Time-lapse"])
|
||||
delete(buttons["Power Viewer"])
|
||||
delete(buttons["Calendar"])
|
||||
}
|
||||
if(!$.ccio.permissionCheck('monitor_edit',d.mid)){
|
||||
delete(buttons["Monitor Settings"])
|
||||
}
|
||||
$.each(buttons,function(n,v){
|
||||
tmp+='<a class="btn btn-'+v.class+'" '+v.attr+' title="'+v.label+'"><i class="fa fa-'+v.icon+'"></i></a>'
|
||||
})
|
||||
tmp+='</div>';//end of btn list
|
||||
tmp+='</div>';//.stream-block
|
||||
tmp+='<div class="mdl-data_window pull-right">';
|
||||
tmp+='<div>';
|
||||
tmp+='<div class="data-menu col-md-6 no-padding videos_monitor_list glM'+d.mid+user.auth_token+' scrollable"><ul></ul></div>';
|
||||
tmp+='<div class="data-menu col-md-6 no-padding logs scrollable"></div>';
|
||||
tmp+='</div>';
|
||||
tmp+='</div>';//.mdl-data_window
|
||||
tmp+='</div>';//.grid-stack-content
|
||||
tmp+='</div>';//#monitor_live_...
|
||||
break;
|
||||
case 3://api key row
|
||||
tmp+='<tr api_key="'+d.code+'"><td class="code">'+d.code+'</td><td class="ip">'+d.ip+'</td><td class="time">'+d.time+'</td><td class="text-right"><a class="delete btn btn-xs btn-danger"> <i class="fa fa-trash"></i> </a></td></tr>';
|
||||
break;
|
||||
case 4://log row, draw to global and monitor
|
||||
if(!d.time){d.time=$.ccio.init('t')}
|
||||
tmp+='<li class="log-item">'
|
||||
tmp+='<span>'
|
||||
tmp+='<div>'+d.ke+' : <b>'+d.mid+'</b></div>'
|
||||
tmp+='<span>'+d.log.type+'</span> '
|
||||
tmp+='<b class="time livestamp" title="'+d.time+'"></b>'
|
||||
tmp+='</span>'
|
||||
tmp+='<div class="message">'
|
||||
tmp+=$.ccio.init('jsontoblock',d.log.msg);
|
||||
tmp+='</div>'
|
||||
tmp+='</li>';
|
||||
$(z).each(function(n,v){
|
||||
v=$(v);
|
||||
if(v.find('.log-item').length>10){v.find('.log-item:last').remove()}
|
||||
})
|
||||
break;
|
||||
case 6://notification row
|
||||
if(!d.time){d.time=$.ccio.init('t')}
|
||||
if(!d.note.class){d.note.class=''}
|
||||
tmp+='<li class="note-item '+d.note.class+'" ke="'+d.ke+'" auth="'+user.auth_token+'" mid="'+d.id+'">'
|
||||
tmp+='<span>'
|
||||
tmp+='<div>'+d.ke+' : <b>'+d.id+'</b></div>'
|
||||
tmp+='<span>'+d.note.type+'</span> '
|
||||
tmp+='<b class="time livestamp" title="'+d.time+'"></b>'
|
||||
tmp+='</span>'
|
||||
tmp+='<div class="message">'
|
||||
tmp+=d.note.msg
|
||||
tmp+='</div>'
|
||||
tmp+='</li>';
|
||||
break;
|
||||
case'option':
|
||||
var selected = ''
|
||||
if(d.selected === true){selected = ' selected'}
|
||||
tmp+='<option auth="'+user.auth_token+'"'+selected+' value="'+d.id+'">'+d.name+'</option>'
|
||||
break;
|
||||
case'stream-element':
|
||||
try{k.d=JSON.parse(d.details);}catch(er){k.d=d.details}
|
||||
if($.ccio.mon[d.ke+d.mid+user.auth_token]&&$.ccio.mon[d.ke+d.mid+user.auth_token].previousStreamType===k.d.stream_type){
|
||||
return;
|
||||
}
|
||||
k.e=$('#monitor_live_'+d.mid+user.auth_token+' .stream-block');
|
||||
k.e.find('.stream-element').remove();
|
||||
if($.ccio.op().jpeg_on===true){
|
||||
tmp+='<img class="stream-element">';
|
||||
}else{
|
||||
switch(k.d.stream_type){
|
||||
case'hls':case'flv':case'mp4':
|
||||
tmp+='<video class="stream-element" autoplay></video>';
|
||||
break;
|
||||
case'mjpeg':
|
||||
tmp+='<iframe class="stream-element"></iframe>';
|
||||
break;
|
||||
case'jpeg':
|
||||
tmp+='<img class="stream-element">';
|
||||
break;
|
||||
default://base64//h265
|
||||
tmp+='<canvas class="stream-element"></canvas>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
k.e.append(tmp).find('.stream-element').resize();
|
||||
if($.ccio.op().switches.monitorMuteAudio === 1){
|
||||
k.e.find('video').each(function(n,el){
|
||||
el.muted = "muted"
|
||||
})
|
||||
}
|
||||
break;
|
||||
case'user-row':
|
||||
d.e=$('.user-row[uid="'+d.uid+'"][ke="'+d.ke+'"]')
|
||||
if(d.e.length===0){
|
||||
tmp+='<li class="user-row" uid="'+d.uid+'" ke="'+d.ke+'">';
|
||||
tmp+='<span><div><span class="mail">'+d.mail+'</span> : <b class="uid">'+d.uid+'</b></div><span>Logged in</span> <b class="time livestamped" title="'+d.logged_in_at+'"></b></span>';
|
||||
tmp+='</li>';
|
||||
}else{
|
||||
d.e.find('.mail').text(d.mail)
|
||||
d.e.find('.time').livestamp('destroy').toggleClass('livestamped livestamp').text(d.logged_in_at)
|
||||
}
|
||||
$.ccio.init('ls')
|
||||
break;
|
||||
case'detector-filters-where':
|
||||
if(!d)d={};
|
||||
d.id=$('#filters_where .row').length;
|
||||
if(!d.p1){d.p1='indifference'}
|
||||
if(!d.p2){d.p2='='}
|
||||
if(!d.p3){d.p3=''}
|
||||
if(!d.p4){d.p4='&&'}
|
||||
tmp+='<div class="row where-row">'
|
||||
tmp+=' <div class="form-group col-md-3">'
|
||||
tmp+=' <label>'
|
||||
tmp+=' <select class="form-control" where="p1">'
|
||||
tmp+=' <option value="indifference" selected>'+lang['Indifference']+'</option>'
|
||||
tmp+=' <option value="name">'+lang['Region Name']+'</option>'
|
||||
tmp+=' <option value="reason">'+lang['Reason']+'</option>'
|
||||
tmp+=' <option value="time">'+lang['Time']+'</option>'
|
||||
tmp+=' <option value="plug">'+lang['Detection Engine']+'</option>'
|
||||
tmp+=' <optgroup label="Matrix">'
|
||||
tmp+=' <option value="tag">'+lang['Object Tag']+'</option>'
|
||||
tmp+=' <option value="confidence">'+lang['Confidence']+'</option>'
|
||||
tmp+=' <option value="x">'+lang['X Point']+'</option>'
|
||||
tmp+=' <option value="y">'+lang['Y Point']+'</option>'
|
||||
tmp+=' <option value="height">'+lang['Height']+'</option>'
|
||||
tmp+=' <option value="width">'+lang['Width']+'</option>'
|
||||
tmp+=' </optgroup>'
|
||||
tmp+=' </select>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group col-md-3">'
|
||||
tmp+=' <label>'
|
||||
tmp+=' <select class="form-control" where="p2">'
|
||||
tmp+=' <option value="===" selected>'+lang['Equal to']+'</option>'
|
||||
tmp+=' <option value="!==">'+lang['Not Equal to']+'</option>'
|
||||
tmp+=' <option value="indexOf">'+lang['Contains']+'</option>'
|
||||
tmp+=' <option value="!indexOf">'+lang['Does Not Contain']+'</option>'
|
||||
tmp+=' <optgroup label="For Numbers">'
|
||||
tmp+=' <option value=">=">'+lang['Greater Than or Equal to']+'</option>'
|
||||
tmp+=' <option value=">">'+lang['Greater Than']+'</option>'
|
||||
tmp+=' <option value="<">'+lang['Less Than']+'</option>'
|
||||
tmp+=' <option value="<=">'+lang['Less Than or Equal to']+'</option>'
|
||||
tmp+=' </optgroup>'
|
||||
tmp+=' </select>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group col-md-3">'
|
||||
tmp+=' <label>'
|
||||
tmp+=' <input class="form-control" placeholder="Value" title="'+lang.Value+'" where="p3">'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group col-md-3">'
|
||||
tmp+=' <label>'
|
||||
tmp+=' <select class="form-control" where="p4">'
|
||||
tmp+=' <option value="&&" selected>'+lang['AND']+'</option>'
|
||||
tmp+=' <option value="||">'+lang['OR']+'</option>'
|
||||
tmp+=' </select>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+='</div>'
|
||||
break;
|
||||
case'filters-where':
|
||||
if(!d)d={};
|
||||
d.id=$('#filters_where .row').length;
|
||||
if(!d.p1){d.p1='mid'}
|
||||
if(!d.p2){d.p2='='}
|
||||
if(!d.p3){d.p3=''}
|
||||
tmp+='<div class="row where-row">';
|
||||
tmp+=' <div class="form-group col-md-4">';
|
||||
tmp+=' <label>';
|
||||
tmp+=' <select class="form-control" where="p1">';
|
||||
tmp+=' <option value="mid" selected>'+lang['Monitor ID']+'</option>';
|
||||
tmp+=' <option value="ext">'+lang['File Type']+'</option>';
|
||||
tmp+=' <option value="time">'+lang['Start Time']+'</option>';
|
||||
tmp+=' <option value="end">'+lang['End Time']+'</option>';
|
||||
tmp+=' <option value="size">'+lang['Filesize']+'</option>';
|
||||
tmp+=' <option value="status">'+lang['Video Status']+'</option>';
|
||||
tmp+=' </select>';
|
||||
tmp+=' </label>';
|
||||
tmp+=' </div>';
|
||||
tmp+=' <div class="form-group col-md-4">';
|
||||
tmp+=' <label>';
|
||||
tmp+=' <select class="form-control" where="p2">';
|
||||
tmp+=' <option value="=" selected>'+lang['Equal to']+'</option>';
|
||||
tmp+=' <option value="!=">'+lang['Not Equal to']+'</option>';
|
||||
tmp+=' <option value=">=">'+lang['Greater Than or Equal to']+'</option>';
|
||||
tmp+=' <option value=">">'+lang['Greater Than']+'</option>';
|
||||
tmp+=' <option value="<">'+lang['Less Than']+'</option>';
|
||||
tmp+=' <option value="<=">'+lang['Less Than or Equal to']+'</option>';
|
||||
tmp+=' <option value="LIKE">'+lang['Like']+'</option>';
|
||||
tmp+=' <option value="=~">'+lang['Matches']+'</option>';
|
||||
tmp+=' <option value="!~">'+lang['Not Matches']+'</option>';
|
||||
tmp+=' <option value="=[]">'+lang['In']+'</option>';
|
||||
tmp+=' <option value="![]">'+lang['Not In']+'</option>';
|
||||
tmp+=' </select>';
|
||||
tmp+=' </label>';
|
||||
tmp+=' </div>';
|
||||
tmp+=' <div class="form-group col-md-4">';
|
||||
tmp+=' <label>';
|
||||
tmp+=' <input class="form-control" placeholder="Value" title="'+lang.Value+'" where="p3">';
|
||||
tmp+=' </label>';
|
||||
tmp+=' </div>';
|
||||
tmp+='</div>';
|
||||
break;
|
||||
case 'link-set'://Link Shinobi - 1 set
|
||||
if(!d.host){d.host=''}
|
||||
if(!d.ke){d.ke=''}
|
||||
if(!d.api){d.api=''}
|
||||
if(!d.secure){d.secure="0"}
|
||||
tmp+='<div class="linksGroup" links="'+d.host+'">'
|
||||
tmp+='<h4 class="round-left">'+d.host+' <small>'+d.ke+'</small> <div class="pull-right"><a class="btn btn-danger btn-xs delete"><i class="fa fa-trash-o"></i></a></div></h4>'
|
||||
tmp+='<div class="form-group"><label><div><span>'+lang.Host+'</span></div><div><input class="form-control" link="host" value="'+d.host+'"></div></label></div>'
|
||||
tmp+='<div class="form-group"><label><div><span>'+lang['Group Key']+'</span></div><div><input class="form-control" link="ke" value="'+d.ke+'"></div></label></div>'
|
||||
tmp+='<div class="form-group"><label><div><span>'+lang['API Key']+'</span></div><div><input class="form-control" link="api" value="'+d.api+'"></div></label></div>'
|
||||
tmp+='<div class="form-group"><label><div><span>'+lang.Secure+' (HTTPS/WSS)</span></div><div><select class="form-control" link="secure"><option value="1">'+lang.Yes+'</option><option selected value="0">'+lang.No+'</option></select></div></label></div>'
|
||||
tmp+='</div>';
|
||||
break;
|
||||
case 'form-group'://Input Map Selector
|
||||
var fields = []
|
||||
if(d.fields){
|
||||
if(d.fields instanceof Object){
|
||||
fields = [d]
|
||||
}else{
|
||||
fields = d
|
||||
}
|
||||
}
|
||||
$.each(fields,function(n,v){
|
||||
var value,hidden
|
||||
if(!v.attribute)v.attribute='';
|
||||
if(!v.placeholder)v.placeholder='';
|
||||
if(!v.class)v.class='';
|
||||
if(!v.inputType)v.inputType='value';
|
||||
if(v.hidden){hidden='style="display:none"'}else{hidden=''};
|
||||
if(v.value){value='value=""'}else{value=''};
|
||||
tmp+=' <div class="form-group '+v.class+'" '+hidden+'>'
|
||||
tmp+=' <label><div><span>'+v.label+'</span></div>'
|
||||
tmp+=' <div>'
|
||||
switch(v.type){
|
||||
case'text':
|
||||
tmp+='<input class="form-control" '+v.inputType+'="'+v.name+'" placeholder="'+v.placeholder+'" "'+value+'" '+v.attribute+'>'
|
||||
break;
|
||||
case'selector':
|
||||
tmp+='<select class="form-control" '+v.inputType+'="'+v.name+'" placeholder="'+v.placeholder+'" '+v.attribute+'>'
|
||||
$.each(v.choices,function(m,b){
|
||||
tmp+='<option value="'+b.value+'">'+b.label+'</option>'
|
||||
})
|
||||
tmp+='</select>'
|
||||
break;
|
||||
}
|
||||
tmp+=' </div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
})
|
||||
break;
|
||||
case 'input-map-selector'://Input Map Selector
|
||||
if(!d.map){d.map=''}
|
||||
tmp+=' <div class="form-group map-row">'
|
||||
tmp+=' <label><div><span>'+lang['Map']+'</span></div>'
|
||||
tmp+=' <div>'
|
||||
tmp+=' <div class="input-group input-group-sm">'
|
||||
tmp+='<input class="form-control" map-input="map" value="'+d.map+'" placeholder="0">'
|
||||
tmp+=' <div class="input-group-btn">'
|
||||
tmp+=' <a class="btn btn-danger delete_map_row"> <i class="fa fa-trash-o"></i> </a>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
break;
|
||||
case 'input-map'://Input Map Options
|
||||
var tempID = $.ccio.gid();
|
||||
if(!d.channel){
|
||||
var numberOfChannelsDrawn = $('#monSectionInputMaps .input-map').length
|
||||
d.channel=numberOfChannelsDrawn+1
|
||||
}
|
||||
var fields = [
|
||||
// {
|
||||
// name:'',
|
||||
// class:'',
|
||||
// placeholder:'',
|
||||
// default:'',
|
||||
// attribute:'',
|
||||
// type:'text',
|
||||
// },
|
||||
{
|
||||
name:'type',
|
||||
label:lang['Input Type'],
|
||||
default:'h264',
|
||||
attribute:'selector="h_i_'+tempID+'"',
|
||||
type:'selector',
|
||||
choices:[
|
||||
{label:lang['H.264 / H.265 / H.265+'],value:'h264'},
|
||||
{label:lang['JPEG'],value:'jpeg'},
|
||||
{label:lang['MJPEG'],value:'mjpeg'},
|
||||
{label:lang['HLS (.m3u8)'],value:'hls'},
|
||||
{label:lang['MPEG-4 (.mp4 / .ts)'],value:'mp4'},
|
||||
{label:lang['Local'],value:'local'},
|
||||
{label:lang['Raw'],value:'raw'},
|
||||
]
|
||||
},
|
||||
{
|
||||
name:'fulladdress',
|
||||
label:lang['Full URL Path'],
|
||||
placeholder:'Example : rtsp://admin:password@123.123.123.123/stream/1',
|
||||
type:'text',
|
||||
},
|
||||
{
|
||||
name:'sfps',
|
||||
label:lang['Monitor Capture Rate'],
|
||||
placeholder:'',
|
||||
type:'text',
|
||||
},
|
||||
{
|
||||
name:'aduration',
|
||||
label:lang['Analyzation Duration'],
|
||||
placeholder:'Example : 1000000',
|
||||
type:'text',
|
||||
},
|
||||
{
|
||||
name:'probesize',
|
||||
label:lang['Probe Size'],
|
||||
placeholder:'Example : 1000000',
|
||||
type:'text',
|
||||
},
|
||||
{
|
||||
name:'stream_loop',
|
||||
label:lang['Loop Stream'],
|
||||
class:'h_i_'+tempID+'_input h_i_'+tempID+'_mp4 h_i_'+tempID+'_raw',
|
||||
hidden:true,
|
||||
default:'0',
|
||||
type:'selector',
|
||||
choices:[
|
||||
{label:'No',value:'0'},
|
||||
{label:'Yes',value:'1'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name:'rtsp_transport',
|
||||
label:lang['RTSP Transport'],
|
||||
class:'h_i_'+tempID+'_input h_i_'+tempID+'_h264',
|
||||
default:'0',
|
||||
type:'selector',
|
||||
choices:[
|
||||
{label:'Auto',value:''},
|
||||
{label:'TCP',value:'tcp'},
|
||||
{label:'UDP',value:'udp'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name:'accelerator',
|
||||
label:lang['Accelerator'],
|
||||
attribute:'selector="h_accel_'+tempID+'"',
|
||||
default:'0',
|
||||
type:'selector',
|
||||
choices:[
|
||||
{label:'No',value:'0'},
|
||||
{label:'Yes',value:'1'},
|
||||
]
|
||||
},
|
||||
{
|
||||
name:'hwaccel',
|
||||
label:lang['hwaccel'],
|
||||
class:'h_accel_'+tempID+'_input h_accel_'+tempID+'_1',
|
||||
hidden:true,
|
||||
default:'',
|
||||
type:'selector',
|
||||
choices: $.ccio.HWAccelChoices
|
||||
},
|
||||
{
|
||||
name:'hwaccel_vcodec',
|
||||
label:lang['hwaccel_vcodec'],
|
||||
class:'h_accel_'+tempID+'_input h_accel_'+tempID+'_1',
|
||||
hidden:true,
|
||||
default:'auto',
|
||||
type:'selector',
|
||||
choices:[
|
||||
{label:lang['Auto'],value:'auto'},
|
||||
{label:lang['h264_cuvid'],value:'h264_cuvid',group:'NVIDIA'},
|
||||
{label:lang['hevc_cuvid'],value:'hevc_cuvid',group:'NVIDIA'},
|
||||
{label:lang['mjpeg_cuvid'],value:'mjpeg_cuvid',group:'NVIDIA'},
|
||||
{label:lang['mpeg4_cuvid'],value:'mpeg4_cuvid',group:'NVIDIA'},
|
||||
{label:lang['h264_qsv'],value:'h264_qsv',group:'Quick Sync Video'},
|
||||
{label:lang['hevc_qsv'],value:'hevc_qsv',group:'Quick Sync Video'},
|
||||
{label:lang['mpeg2_qsv'],value:'mpeg2_qsv',group:'Quick Sync Video'},
|
||||
{label:lang['h264_mmal'],value:'h264_mmal',group:'Raspberry Pi'},
|
||||
{label:lang['mpeg2_mmal'],value:'mpeg2_mmal',group:'Raspberry Pi'},
|
||||
{label:lang['mpeg4_mmal'],value:'mpeg4_mmal',group:'Raspberry Pi'},
|
||||
]
|
||||
},
|
||||
{
|
||||
name:'hwaccel_device',
|
||||
label:lang['hwaccel_device'],
|
||||
class:'h_accel_'+tempID+'_input h_accel_'+tempID+'_1',
|
||||
hidden:true,
|
||||
placeholder:'Example : /dev/dri/video0',
|
||||
type:'text',
|
||||
},
|
||||
];
|
||||
tmp+='<div class="form-group-group forestgreen input-map" section id="monSectionMap'+tempID+'">'
|
||||
tmp+=' <h4>'+lang["Input"]+' <b>'+lang["Map"]+' : <span class="place">'+d.channel+'</span></b>'
|
||||
tmp+=' <div class="pull-right"><a class="btn btn-danger btn-xs delete"><i class="fa fa-trash-o"></i></a></div>'
|
||||
tmp+=' </h4>'
|
||||
$.each(fields,function(n,v){
|
||||
if(!v.attribute)v.attribute='';
|
||||
if(!v.placeholder)v.placeholder='';
|
||||
if(!v.class)v.class='';
|
||||
if(v.hidden){v.hidden='style="display:none"'}else{v.hidden=''};
|
||||
tmp+=' <div class="form-group '+v.class+'" '+v.hidden+'>'
|
||||
tmp+=' <label><div><span>'+v.label+'</span></div>'
|
||||
tmp+=' <div>'
|
||||
switch(v.type){
|
||||
case'text':
|
||||
tmp+='<input class="form-control" map-detail="'+v.name+'" placeholder="'+v.placeholder+'" '+v.attribute+'>'
|
||||
break;
|
||||
case'selector':
|
||||
tmp+='<select class="form-control" map-detail="'+v.name+'" placeholder="'+v.placeholder+'" '+v.attribute+'>'
|
||||
$.each(v.choices,function(m,b){
|
||||
tmp+='<option value="'+b.value+'">'+b.label+'</option>'
|
||||
})
|
||||
tmp+='</select>'
|
||||
break;
|
||||
}
|
||||
tmp+=' </div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
})
|
||||
tmp+='</div>'
|
||||
break;
|
||||
case 'stream-channel'://Stream Channel
|
||||
var tempID = $.ccio.gid();
|
||||
if(!d.channel){
|
||||
var numberOfChannelsDrawn = $('#monSectionStreamChannels .stream-channel').length
|
||||
d.channel=numberOfChannelsDrawn
|
||||
}
|
||||
tmp+='<div class="form-group-group blue stream-channel" section id="monSectionChannel'+tempID+'">'
|
||||
tmp+=' <h4>'+lang["Stream Channel"]+' <span class="place">'+d.channel+'</span>'
|
||||
tmp+=' <div class="pull-right"><a class="btn btn-danger btn-xs delete"><i class="fa fa-trash-o"></i></a></div>'
|
||||
tmp+=' </h4>'
|
||||
// tmp+=' <div class="form-group">'
|
||||
// tmp+=' <label><div><span>'+lang["Input Selector"]+'</span></div>'
|
||||
// tmp+=' <div><input class="form-control" channel-detail="stream_map" placeholder="0"></div>'
|
||||
// tmp+=' </label>'
|
||||
// tmp+=' </div>'
|
||||
tmp+='<div class="form-group-group forestgreen" input-mapping="stream_channel-'+d.channel+'">'
|
||||
tmp+=' <h4>'+lang['Input Feed']
|
||||
tmp+=' <div class="pull-right">'
|
||||
tmp+=' <a class="btn btn-success btn-xs add_map_row"><i class="fa fa-plus-square-o"></i></a>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </h4>'
|
||||
tmp+=' <div class="choices"></div>'
|
||||
tmp+='</div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Stream Type"]+'</span></div>'
|
||||
tmp+=' <div><select class="form-control" channel-detail="stream_type" selector="h_st_channel_'+tempID+'" triggerChange="#monSectionChannel'+tempID+' [channel-detail=stream_vcodec]" triggerChangeIgnore="b64,mjpeg">'
|
||||
tmp+=' <option value="mp4">'+lang["Poseidon"]+'</option>'
|
||||
tmp+=' <option value="rtmp">'+lang["RTMP Stream"]+'</option>'
|
||||
tmp+=' <option value="flv">'+lang["FLV"]+'</option>'
|
||||
tmp+=' <option value="h264">'+lang["Raw H.264 Stream"]+'</option>'
|
||||
tmp+=' <option value="hls">'+lang["HLS (includes Audio)"]+'</option>'
|
||||
tmp+=' <option value="mjpeg">'+lang["MJPEG"]+'</option>'
|
||||
tmp+=' </select></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="h_st_channel_'+tempID+'_input h_st_channel_'+tempID+'_rtmp">'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Server URL"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="rtmp_server_url" placeholder="Example : rtmp://live-api.facebook.com:80/rtmp/"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Stream Key"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="rtmp_stream_key" placeholder="Example : 1111111111?ds=1&a=xxxxxxxxxx"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group h_st_channel_'+tempID+'_input h_st_channel_'+tempID+'_mjpeg" style="display:none">'
|
||||
tmp+=' <label><div><span>'+lang["# of Allow MJPEG Clients"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="stream_mjpeg_clients" placeholder="20"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="h_st_channel_'+tempID+'_input h_st_channel_'+tempID+'_hls h_st_channel_'+tempID+'_rtmp h_st_channel_'+tempID+'_flv h_st_channel_'+tempID+'_mp4 h_st_channel_'+tempID+'_h264">'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["HLS Video Encoder"]+'</span></div>'
|
||||
tmp+=' <div><select class="form-control" channel-detail="stream_vcodec" selector="h_hls_v_channel_'+tempID+'">'
|
||||
tmp+=' <option value="no" selected>'+lang["Auto"]+'</option>'
|
||||
tmp+=' <option value="libx264">'+lang["libx264"]+'</option>'
|
||||
tmp+=' <option value="libx265">'+lang["libx265"]+'</option>'
|
||||
tmp+=' <option value="copy" selected>'+lang["copy"]+'</option>'
|
||||
tmp+=' <optgroup label="'+lang["Hardware Accelerated"]+'">'
|
||||
tmp+=' <option value="h264_vaapi">'+lang["h264_vaapi"]+'</option>'
|
||||
tmp+=' <option value="hevc_vaapi">'+lang["hevc_vaapi"]+'</option>'
|
||||
tmp+=' <option value="h264_nvenc">'+lang["h264_nvenc"]+'</option>'
|
||||
tmp+=' <option value="hevc_nvenc">'+lang["hevc_nvenc"]+'</option>'
|
||||
tmp+=' <option value="h264_qsv">'+lang["h264_qsv"]+'</option>'
|
||||
tmp+=' <option value="hevc_qsv">'+lang["hevc_qsv"]+'</option>'
|
||||
tmp+=' <option value="mpeg2_qsv">'+lang["mpeg2_qsv"]+'</option>'
|
||||
tmp+=' <option value="h264_omx">'+lang["h264_omx"]+'</option>'
|
||||
tmp+=' </optgroup>'
|
||||
tmp+=' </select></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["HLS Audio Encoder"]+'</span></div>'
|
||||
tmp+=' <div><select class="form-control" channel-detail="stream_acodec">'
|
||||
tmp+=' <option value="no" selected>'+lang["No Audio"]+'</option>'
|
||||
tmp+=' <option value="">'+lang["Auto"]+'</option>'
|
||||
tmp+=' <option value="aac">'+lang["aac"]+'</option>'
|
||||
tmp+=' <option value="ac3">'+lang["ac3"]+'</option>'
|
||||
tmp+=' <option value="libmp3lame">'+lang["libmp3lame"]+'</option>'
|
||||
tmp+=' <option value="copy">'+lang["copy"]+'</option>'
|
||||
tmp+=' </select></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Rate"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="stream_fps" placeholder=""></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="h_st_channel_'+tempID+'_input h_st_channel_'+tempID+'_hls" style="display:none">'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["HLS Segment Length"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="hls_time" placeholder="2"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["HLS Preset"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="preset_stream" placeholder="ultrafast"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["HLS List Size"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="hls_list_size" placeholder="2"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="h_st_channel_'+tempID+'_input h_st_channel_'+tempID+'_mjpeg h_st_channel_'+tempID+'_hls h_st_channel_'+tempID+'_rtmp h_st_channel_'+tempID+'_jsmpeg h_st_channel_'+tempID+'_flv h_st_channel_'+tempID+'_mp4 h_st_channel_'+tempID+'_h264 h_hls_v_channel_'+tempID+'_input h_hls_v_channel_'+tempID+'_libx264 h_hls_v_channel_'+tempID+'_libx265 h_hls_v_channel_'+tempID+'_h264_nvenc h_hls_v_channel_'+tempID+'_hevc_nvenc h_hls_v_channel_'+tempID+'_no" style="display:none">'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Quality"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" placeholder="23" channel-detail="stream_quality"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="h_st_channel_'+tempID+'_input h_st_channel_'+tempID+'_rtmp">'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Video Bit Rate"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="stream_v_br" placeholder=""></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Audio Bit Rate"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="stream_a_br" placeholder="128k"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Width"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" type="number" min="1" channel-detail="stream_scale_x" placeholder="Example : 640"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Height"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" type="number" min="1" channel-detail="stream_scale_y" placeholder="Example : 480"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Rotate"]+'</span></div>'
|
||||
tmp+=' <div><select class="form-control" channel-detail="rotate_stream">'
|
||||
tmp+=' <option value="no" selected>'+lang["No Rotation"]+'</option>'
|
||||
tmp+=' <option value="2,transpose=2">'+lang["180 Degrees"]+'</option>'
|
||||
tmp+=' <option value="0">'+lang["90 Counter Clockwise and Vertical Flip (default)"]+'</option>'
|
||||
tmp+=' <option value="1">'+lang["90 Clockwise"]+'</option>'
|
||||
tmp+=' <option value="2">'+lang["90 Clockwise and Vertical Flip"]+'</option>'
|
||||
tmp+=' <option value="3">'+lang["90 Clockwise and Vertical Flip"]+'</option>'
|
||||
tmp+=' </select></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Video Filter"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="svf"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' <div class="form-group">'
|
||||
tmp+=' <label><div><span>'+lang["Stream Flags"]+'</span></div>'
|
||||
tmp+=' <div><input class="form-control" channel-detail="cust_stream"></div>'
|
||||
tmp+=' </label>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
tmp+=' </div>'
|
||||
break;
|
||||
}
|
||||
if(z && x !== 2){
|
||||
$(z).prepend(tmp)
|
||||
}
|
||||
switch(x){
|
||||
case 1:
|
||||
z='#monitors_list .link-monitors-list[auth="'+user.auth_token+'"][ke="'+d.ke+'"]'
|
||||
if($('.link-monitors-list[auth="'+user.auth_token+'"][ke="'+d.ke+'"]').length===0){
|
||||
$("#monitors_list").append('<div class="link-monitors-list" auth="'+user.auth_token+'" ke="'+d.ke+'"></div>')
|
||||
var options = {
|
||||
cellHeight: 80,
|
||||
verticalMargin: 10,
|
||||
};
|
||||
//monitor="watch_off"
|
||||
$(z).gridstack(options);
|
||||
$(z).on('change', function(event, ui) {
|
||||
var monitors = {}
|
||||
$.grid.e.find(" .monitor_item").each(function(n,v){
|
||||
var el = $(v)
|
||||
var item = {}
|
||||
item.ke = el.attr('ke')
|
||||
item.mid = el.attr('mid')
|
||||
item.x = el.attr('data-gs-x')
|
||||
item.y = el.attr('data-gs-y')
|
||||
item.height = el.attr('data-gs-height')
|
||||
item.width = el.attr('data-gs-width')
|
||||
monitors[item.ke+item.mid] = item
|
||||
})
|
||||
user.details.monitorOrder=monitors;
|
||||
$.ccio.cx({f:'monitorOrder',monitorOrder:monitors},user)
|
||||
});
|
||||
}
|
||||
$(z).prepend(tmp)
|
||||
componentHandler.upgradeAllRegistered()
|
||||
break;
|
||||
case 0:case 4:
|
||||
$.ccio.init('ls');
|
||||
break;
|
||||
case 2:
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var width = $.grid.getMonitorsPerRow()
|
||||
var height = width;
|
||||
if(user.details && user.details.monitorOrder && user.details.monitorOrder[d.ke+d.mid]){
|
||||
var saved = user.details.monitorOrder[d.ke+d.mid];
|
||||
x = saved.x;
|
||||
y = saved.y;
|
||||
width = saved.width;
|
||||
height = saved.height;
|
||||
}
|
||||
var autoPlacement = false
|
||||
if($.ccio.op().switches.monitorOrder !== 1){
|
||||
autoPlacement = true
|
||||
}
|
||||
$(z).data('gridstack').addWidget($(tmp), x, y, width, height, autoPlacement);
|
||||
k.e=$('#monitor_live_'+d.mid+user.auth_token);
|
||||
try{
|
||||
if(JSON.parse(d.details).control=="1"){
|
||||
k.e.find('[monitor="control_toggle"]').show()
|
||||
}else{
|
||||
k.e.find('.pad').remove();
|
||||
k.e.find('[monitor="control_toggle"]').hide()
|
||||
}
|
||||
$.ccio.tm('stream-element',d,null,user)
|
||||
}catch(re){$.ccio.log(re)}
|
||||
k.mid=d.mid
|
||||
k.mon=$.ccio.mon[d.ke+d.mid+user.auth_token]
|
||||
$.ccio.init('monitorInfo',k)
|
||||
break;
|
||||
case'detector-filters-where':
|
||||
$('#detector_filters_where').append(tmp);
|
||||
$('#detector_filters_where .row [where="p4"][disabled]').prop('disabled',false)
|
||||
$('#detector_filters_where .row:last [where="p1"]').val(d.p1)
|
||||
$('#detector_filters_where .row:last [where="p2"]').val(d.p2)
|
||||
$('#detector_filters_where .row:last [where="p3"]').val(d.p3)
|
||||
$('#detector_filters_where .row:last [where="p4"]').val(d.p4).prop('disabled',true)
|
||||
break;
|
||||
case'filters-where':
|
||||
$('#filters_where').append(tmp);
|
||||
$('#filters_where .row:last [where="p1"]').val(d.p1)
|
||||
$('#filters_where .row:last [where="p2"]').val(d.p2)
|
||||
$('#filters_where .row:last [where="p3"]').val(d.p3)
|
||||
break;
|
||||
case'input-map':
|
||||
var mapsList = $.aM.maps
|
||||
mapsList.append(tmp)
|
||||
mapsList.find('.input-map').last().find('[map-detail="aduration"]').change()
|
||||
return tempID;
|
||||
break;
|
||||
case'stream-channel':
|
||||
var channeList = $.aM.channels
|
||||
channeList.append(tmp)
|
||||
channeList.find('.stream-channel').last().find('[channel-detail="stream_vcodec"]').change()
|
||||
return tempID;
|
||||
break;
|
||||
case'link-set':
|
||||
$('[links="'+d.host+'"] [link="secure"]').val(d.secure).change()
|
||||
break;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
$.ccio.pm=function(x,d,z,user){
|
||||
var tmp='';if(!d){d={}};
|
||||
if(!user){
|
||||
user=$user
|
||||
}
|
||||
switch(x){
|
||||
case 0:
|
||||
d.mon=$.ccio.mon[d.ke+d.mid+user.auth_token];
|
||||
d.ev='.glM'+d.mid+user.auth_token+'.videos_list ul,.glM'+d.mid+user.auth_token+'.videos_monitor_list ul';d.fr=$.ccio.fr.find(d.ev),d.tmp='';
|
||||
if(d.fr.length===0){$.ccio.fr.append('<div class="videos_list glM'+d.mid+user.auth_token+'"><h3 class="title">'+d.mon.name+'</h3><ul></ul></div>')}
|
||||
if(d.videos&&d.videos.length>0){
|
||||
$.each(d.videos,function(n,v){
|
||||
if(v.status!==0){
|
||||
tmp+=$.ccio.tm(0,v,null,user)
|
||||
}
|
||||
})
|
||||
}else{
|
||||
$('.glM'+d.mid+user.auth_token+'.videos_list,.glM'+d.mid+user.auth_token+'.videos_monitor_list').appendTo($.ccio.fr)
|
||||
tmp+='<li class="notice novideos">No videos</li>';
|
||||
}
|
||||
$(d.ev).html(tmp);
|
||||
$.ccio.init('ls');
|
||||
break;
|
||||
case 3:
|
||||
z='#api_list';
|
||||
$(z).empty();
|
||||
$.each(d,function(n,v){
|
||||
tmp+=$.ccio.tm(3,v,null,user);
|
||||
})
|
||||
break;
|
||||
case'option':
|
||||
$.each(d,function(n,v){
|
||||
tmp+=$.ccio.tm('option',v,null,user);
|
||||
})
|
||||
break;
|
||||
case'user-row':
|
||||
$.each(d,function(n,v){
|
||||
tmp+=$.ccio.tm('user-row',v,null,user);
|
||||
})
|
||||
z='#users_online'
|
||||
break;
|
||||
case'link-set':
|
||||
$.sM.links.empty()
|
||||
$.each(d,function(n,v){
|
||||
tmp+=$.ccio.tm('link-set',v,'#linkShinobi',user)
|
||||
})
|
||||
break;
|
||||
}
|
||||
if(z){
|
||||
$(z).prepend(tmp)
|
||||
}
|
||||
return tmp;
|
||||
}
|
|
@ -0,0 +1,767 @@
|
|||
$(document).ready(function(e){
|
||||
console.log("%cWarning!", "font: 2em monospace; color: red;");
|
||||
console.log('%cLeaving the developer console open is fine if you turn off "Network Recording". This is because it will keep a log of all files, including frames and videos segments.', "font: 1.2em monospace; ");
|
||||
if(!$.ccio.permissionCheck('monitor_create')){
|
||||
$('#add_monitor_button_main').remove()
|
||||
}
|
||||
$.each(['user_change','monitor_create','view_logs'],function(n,permission){
|
||||
if(!$.ccio.permissionCheck(permission)){
|
||||
$('.permission_'+permission).remove()
|
||||
}
|
||||
})
|
||||
|
||||
//Group Selector
|
||||
$.gR={e:$('#group_list'),b:$('#group_list_button')};
|
||||
$.gR.drawList=function(){
|
||||
var e={};
|
||||
e.tmp='';
|
||||
$.each($.ccio.init('monGroup'),function(n,v){
|
||||
if($user.mon_groups[n]){
|
||||
e.tmp+='<li class="mdl-menu__item" groups="'+n+'">'+$user.mon_groups[n].name+'</li>'
|
||||
}
|
||||
})
|
||||
$.gR.e.html(e.tmp)
|
||||
}
|
||||
$.gR.e.on('click','[groups]',function(){
|
||||
var e={};
|
||||
e.e=$(this),
|
||||
e.a=e.e.attr('groups');
|
||||
var user=$.users[e.e.attr('auth')];
|
||||
if(!user){user=$user}
|
||||
if(user===$user){
|
||||
e.chosen_set='watch_on'
|
||||
}else{
|
||||
e.chosen_set='watch_on_links'
|
||||
}
|
||||
$.each($.ccio.op()[e.chosen_set],function(n,v){
|
||||
$.each(v,function(m,b){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_off',id:m,ke:n},user)
|
||||
})
|
||||
})
|
||||
$.each($.ccio.mon_groups[e.a],function(n,v){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:v.mid,ke:v.ke},user)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
//open all monitors
|
||||
$('[class_toggle="list-blocks"][data-target="#left_menu"]').dblclick(function(){
|
||||
$('#monitors_list .monitor_block').each(function(n,v){
|
||||
var el = $(v)
|
||||
var ke = el.attr('ke')
|
||||
var mid = el.attr('mid')
|
||||
var auth = el.attr('auth')
|
||||
var monItem = $('.monitor_item[ke='+ke+'][mid='+mid+'][auth='+auth+']')
|
||||
if(monItem.length > 0){
|
||||
monItem.find('[monitor="watch_on"]').click()
|
||||
}else{
|
||||
el.find('[monitor="watch"]').click()
|
||||
}
|
||||
})
|
||||
})
|
||||
//search monitors list
|
||||
$('#monitors_list_search').keyup(function(){
|
||||
var monitorBlocks = $('.monitor_block');
|
||||
var searchTerms = $(this).val().toLowerCase().split(' ')
|
||||
if(searchTerms.length === 0 || searchTerms[0] === ''){
|
||||
monitorBlocks.show()
|
||||
return
|
||||
}
|
||||
monitorBlocks.hide()
|
||||
$.each($.ccio.mon,function(n,monitor){
|
||||
var searchThis = JSON.stringify($.ccio.init('cleanMon',monitor)).toLowerCase().replace('"','');
|
||||
$.each(searchTerms,function(m,term){
|
||||
if(searchThis.indexOf(term) >-1 ){
|
||||
$('.monitor_block[ke="'+monitor.ke+'"][mid="'+monitor.mid+'"]').show()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
//dynamic bindings
|
||||
$.ccio.windowFocus = true
|
||||
$(window).focus(function() {
|
||||
$.ccio.windowFocus = true
|
||||
clearInterval($.ccio.soundAlarmInterval)
|
||||
}).blur(function() {
|
||||
$.ccio.windowFocus = false
|
||||
});
|
||||
$('body')
|
||||
.on('click','.logout',function(e){
|
||||
var logout = function(user,callback){
|
||||
$.get($.ccio.init('location',user)+user.auth_token+'/logout/'+user.ke+'/'+user.uid,callback)
|
||||
}
|
||||
$.each($.users,function(n,linkedShinobiUser){
|
||||
logout(linkedShinobiUser,function(){});
|
||||
})
|
||||
logout($user,function(data){
|
||||
console.log(data)
|
||||
localStorage.removeItem('ShinobiLogin_'+location.host);
|
||||
location.href=location.href;
|
||||
});
|
||||
})
|
||||
.on('click','[video]',function(e){
|
||||
e.e=$(this),
|
||||
e.a=e.e.attr('video'),
|
||||
e.p=e.e.parents('[mid]'),
|
||||
e.ke=e.p.attr('ke'),
|
||||
e.mid=e.p.attr('mid'),
|
||||
e.file=e.p.attr('file');
|
||||
e.auth=e.p.attr('auth');
|
||||
e.status=e.p.attr('status');
|
||||
if(!e.ke||!e.mid){
|
||||
//for calendar plugin
|
||||
e.p=e.e.parents('[data-mid]'),
|
||||
e.ke=e.p.data('ke'),
|
||||
e.mid=e.p.data('mid'),
|
||||
e.file=e.p.data('file');
|
||||
e.auth=e.p.data('auth');
|
||||
e.status=e.p.data('status');
|
||||
}
|
||||
e.mon=$.ccio.mon[e.ke+e.mid+e.auth];
|
||||
switch(e.a){
|
||||
case'launch':
|
||||
e.preventDefault();
|
||||
e.href=$(this).attr('href')
|
||||
var el = $('#video_viewer')
|
||||
var modalBody = el.find('.modal-body')
|
||||
el.find('.modal-title span').html(e.mon.name+' - '+e.file)
|
||||
var html = '<video class="video_video" video="'+e.href+'" autoplay loop controls><source src="'+e.href+'" type="video/'+e.mon.ext+'"></video><br><small class="msg"></small>'
|
||||
modalBody.html(html)
|
||||
el.find('video')[0].onerror = function(){
|
||||
modalBody.find('.msg').text(lang.h265BrowserText1)
|
||||
}
|
||||
el.attr('mid',e.mid);
|
||||
footer = el.find('.modal-footer');
|
||||
footer.find('.download_link').attr('href',e.href).attr('download',e.file);
|
||||
footer.find('[monitor="download"][host="dropbox"]').attr('href',e.href);
|
||||
el.modal('show')
|
||||
.attr('ke',e.ke)
|
||||
.attr('mid',e.mid)
|
||||
.attr('auth',e.auth)
|
||||
.attr('file',e.file);
|
||||
if(e.status==1){
|
||||
$.get($.ccio.init('videoHrefToRead',e.href),function(d){
|
||||
if(d.ok !== true)console.log(d,new Error())
|
||||
})
|
||||
}
|
||||
break;
|
||||
case'delete':
|
||||
e.preventDefault();
|
||||
var videoLink = e.p.find('[download]').attr('href')
|
||||
var href = $(this).attr('href')
|
||||
console.log('videoLink',videoLink)
|
||||
console.log(href)
|
||||
if(!href){
|
||||
href = $.ccio.init('location',$.users[e.auth])+e.auth+'/videos/'+e.ke+'/'+e.mid+'/'+e.file+'/delete<% if(config.useUTC === true){%>?isUTC=true<%}%>'
|
||||
}
|
||||
console.log(href)
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete Video']+' : '+e.file)
|
||||
e.html=lang.DeleteVideoMsg
|
||||
e.html+='<video class="video_video" autoplay loop controls><source src="'+videoLink+'" type="video/'+e.mon.ext+'"></video>';
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click({title:'Delete Video',class:'btn-danger'},function(){
|
||||
$.getJSON(href,function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
});
|
||||
break;
|
||||
case'download':
|
||||
e.preventDefault();
|
||||
switch(e.e.attr('host')){
|
||||
case'dropbox':
|
||||
if($.ccio.DropboxAppKey){
|
||||
Dropbox.save(e.e.attr('href'),e.e.attr('download'),{progress: function (progress) {$.ccio.log(progress)},success: function () {
|
||||
$.ccio.log(lang.dropBoxSuccess);
|
||||
}});
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
.on('change','[localStorage]',function(){
|
||||
e = {}
|
||||
e.e=$(this)
|
||||
e.localStorage = e.e.attr('localStorage')
|
||||
e.value = e.e.val()
|
||||
$.ccio.op(e.localStorage,e.value)
|
||||
})
|
||||
.on('click','[system]',function(e){
|
||||
var e={};
|
||||
e.e=$(this),
|
||||
e.a=e.e.attr('system');//the function
|
||||
switch(e.a){
|
||||
case'switch':
|
||||
e.switch=e.e.attr('switch');
|
||||
e.o=$.ccio.op().switches
|
||||
if(!e.o){
|
||||
e.o={}
|
||||
}
|
||||
if(!e.o[e.switch]){
|
||||
e.o[e.switch]=0
|
||||
}
|
||||
if(e.o[e.switch]===1){
|
||||
e.o[e.switch]=0
|
||||
}else{
|
||||
e.o[e.switch]=1
|
||||
}
|
||||
$.ccio.op('switches',e.o)
|
||||
switch(e.switch){
|
||||
case'monitorOrder':
|
||||
if(e.o[e.switch] !== 1){
|
||||
$('.monitor_item').attr('data-gs-auto-position','yes')
|
||||
}else{
|
||||
$('.monitor_item').attr('data-gs-auto-position','no')
|
||||
}
|
||||
break;
|
||||
case'monitorMuteAudio':
|
||||
$('.monitor_item video').each(function(n,el){
|
||||
if(e.o[e.switch] === 1){
|
||||
el.muted = true
|
||||
}else{
|
||||
el.muted = false
|
||||
}
|
||||
})
|
||||
break;
|
||||
}
|
||||
switch(e.e.attr('type')){
|
||||
case'text':
|
||||
if(e.o[e.switch]===1){
|
||||
e.e.addClass('text-success')
|
||||
}else{
|
||||
e.e.removeClass('text-success')
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case'cronStop':
|
||||
$.ccio.cx({f:'cron',ff:'stop'})
|
||||
break;
|
||||
case'cronRestart':
|
||||
$.ccio.cx({f:'cron',ff:'restart'})
|
||||
break;
|
||||
case'jpegToggle':
|
||||
e.cx={f:'monitor',ff:'jpeg_on'};
|
||||
if($.ccio.op().jpeg_on===true){
|
||||
e.cx.ff='jpeg_off';
|
||||
}
|
||||
$.ccio.cx(e.cx)
|
||||
break;
|
||||
}
|
||||
})
|
||||
.on('click','[class_toggle]',function(e){
|
||||
e.e=$(this);
|
||||
e.n=e.e.attr('data-target');
|
||||
e.v=e.e.attr('class_toggle');
|
||||
e.o=$.ccio.op().class_toggle;
|
||||
if($(e.n).hasClass(e.v)){e.t=0}else{e.t=1}
|
||||
if(!e.o)e.o={};
|
||||
e.o[e.n]=[e.v,e.t];
|
||||
$.ccio.op('class_toggle',e.o)
|
||||
$(e.n).toggleClass(e.v);
|
||||
})
|
||||
.on('change','[dropdown_toggle]',function(e){
|
||||
e.e=$(this);
|
||||
e.n=e.e.attr('dropdown_toggle');
|
||||
e.v=e.e.val();
|
||||
e.o=$.ccio.op().dropdown_toggle;
|
||||
if(!e.o)e.o={};
|
||||
e.o[e.n]=e.v;
|
||||
$.ccio.op('dropdown_toggle',e.o)
|
||||
})
|
||||
//monitor functions
|
||||
.on('click','[monitor]',function(){
|
||||
var e={};
|
||||
e.e=$(this),
|
||||
e.a=e.e.attr('monitor'),//the function
|
||||
e.p=e.e.parents('[mid]'),//the parent element for monitor item
|
||||
e.ke=e.p.attr('ke'),//group key
|
||||
e.mid=e.p.attr('mid'),//monitor id
|
||||
e.auth=e.p.attr('auth'),//authkey
|
||||
e.mon=$.ccio.mon[e.ke+e.mid+e.auth];//monitor configuration
|
||||
var user
|
||||
if($.users[e.auth]){user=$.users[e.auth]}else{user=$user}
|
||||
if(!user){
|
||||
user=$user
|
||||
}
|
||||
switch(e.a){
|
||||
case'show_data':
|
||||
e.p.toggleClass('show_data')
|
||||
var dataBlocks = e.p.find('.stream-block,.mdl-data_window')
|
||||
if(e.p.hasClass('show_data')){
|
||||
dataBlocks.addClass('col-md-6').removeClass('col-md-12')
|
||||
}else{
|
||||
dataBlocks.addClass('col-md-12').removeClass('col-md-6')
|
||||
}
|
||||
break;
|
||||
case'motion':
|
||||
if(!e.mon.motionDetectionRunning){
|
||||
$.ccio.init('streamMotionDetectOn',e,user)
|
||||
}else{
|
||||
$.ccio.init('streamMotionDetectOff',e,user)
|
||||
}
|
||||
break;
|
||||
case'pop':
|
||||
e.fin=function(img){
|
||||
if($.ccio.mon[e.ke+e.mid+user.auth_token].popOut){
|
||||
$.ccio.mon[e.ke+e.mid+user.auth_token].popOut.close()
|
||||
}
|
||||
$.ccio.mon[e.ke+e.mid+user.auth_token].popOut = window.open($.ccio.init('location',user)+user.auth_token+'/embed/'+e.ke+'/'+e.mid+'/fullscreen|jquery|relative|gui','pop_'+e.mid+user.auth_token,'height='+img.height+',width='+img.width);
|
||||
}
|
||||
if(e.mon.watch===1){
|
||||
$.ccio.snapshot(e,function(url){
|
||||
$('#temp').html('<img>')
|
||||
var img=$('#temp img')[0]
|
||||
img.onload=function(){
|
||||
e.fin(img)
|
||||
}
|
||||
img.src=url
|
||||
})
|
||||
}else{
|
||||
var img={height:720,width:1280}
|
||||
e.fin(img)
|
||||
}
|
||||
break;
|
||||
case'mode':
|
||||
e.mode=e.e.attr('mode')
|
||||
if(e.mode){
|
||||
$.getJSON($.ccio.init('location',user)+user.auth_token+'/monitor/'+e.ke+'/'+e.mid+'/'+e.mode,function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
}
|
||||
break;
|
||||
case'timelapse':
|
||||
$.timelapse.e.modal('show')
|
||||
$.timelapse.monitors.find('.monitor').remove()
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
$.timelapse.monitors.append('<option class="monitor" value="'+v.mid+'">'+v.name+'</option>')
|
||||
})
|
||||
e.e=$.timelapse.monitors.find('.monitor').prop('selected',false)
|
||||
if(e.mid!==''){
|
||||
e.e=$.timelapse.monitors.find('.monitor[value="'+e.mid+'"]')
|
||||
}
|
||||
e.e.first().prop('selected',true)
|
||||
$.timelapse.f.submit()
|
||||
break;
|
||||
case'powerview':
|
||||
$.pwrvid.e.modal('show')
|
||||
$.pwrvid.m.empty()
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
$.pwrvid.m.append('<option value="'+v.mid+'">'+v.name+'</option>')
|
||||
})
|
||||
e.e=$.pwrvid.m.find('option').prop('selected',false)
|
||||
if(e.mid!==''){
|
||||
e.e=$.pwrvid.m.find('[value="'+e.mid+'"]')
|
||||
}
|
||||
e.e.first().prop('selected',true)
|
||||
$.pwrvid.f.submit()
|
||||
break;
|
||||
case'region':
|
||||
if(!e.mon){
|
||||
$.ccio.init('note',{title:lang['Unable to Launch'],text:lang.UnabletoLaunchText,type:'error'});
|
||||
return;
|
||||
}
|
||||
e.d=JSON.parse(e.mon.details);
|
||||
e.width=$.aM.e.find('[detail="detector_scale_x"]');
|
||||
e.height=$.aM.e.find('[detail="detector_scale_y"]');
|
||||
e.d.cords=$.aM.e.find('[detail="cords"]').val();
|
||||
if(e.width.val()===''){
|
||||
e.d.detector_scale_x=320;
|
||||
e.d.detector_scale_y=240;
|
||||
$.aM.e.find('[detail="detector_scale_x"]').val(e.d.detector_scale_x);
|
||||
$.aM.e.find('[detail="detector_scale_y"]').val(e.d.detector_scale_y);
|
||||
}else{
|
||||
e.d.detector_scale_x=e.width.val();
|
||||
e.d.detector_scale_y=e.height.val();
|
||||
}
|
||||
|
||||
$.zO.e.modal('show');
|
||||
$.zO.o().attr('width',e.d.detector_scale_x).attr('height',e.d.detector_scale_y);
|
||||
$.zO.c.css({width:e.d.detector_scale_x,height:e.d.detector_scale_y});
|
||||
if(e.d.cords&&(e.d.cords instanceof Object)===false){
|
||||
try{e.d.cords=JSON.parse(e.d.cords);}catch(er){}
|
||||
}
|
||||
if(!e.d.cords||e.d.cords===''){
|
||||
e.d.cords={
|
||||
red:{ name:"red",sensitivity:0.0005, max_sensitivity:"",color_threshold:"",points:[[0,0],[0,100],[100,0]] },
|
||||
}
|
||||
}
|
||||
$.zO.regionViewerDetails=e.d;
|
||||
$.zO.initRegionList()
|
||||
break;
|
||||
case'detector_filters':
|
||||
$.detectorFilters.e.modal('show');
|
||||
break;
|
||||
case'snapshot':
|
||||
$.ccio.snapshot(e,function(url){
|
||||
$('#temp').html('<a href="'+url+'" download="'+$.ccio.init('tf')+'_'+e.ke+'_'+e.mid+'.jpg">a</a>').find('a')[0].click();
|
||||
});
|
||||
break;
|
||||
case'control':
|
||||
e.a=e.e.attr('control')
|
||||
$.ccio.cx({f:'monitor',ff:'control',direction:e.a,mid:e.mid,ke:e.ke},user)
|
||||
break;
|
||||
case'videos_table':case'calendar':case'video_grid'://call videos table or calendar or video grid
|
||||
$.vidview.launcher=$(this);
|
||||
e.limit=$.vidview.limit.val();
|
||||
if(!$.vidview.current_mid||$.vidview.current_mid!==e.mid){
|
||||
$.vidview.current_mid=e.mid
|
||||
$.vidview.current_page=1;
|
||||
if(e.limit.replace(/ /g,'')===''){
|
||||
e.limit='100';
|
||||
}
|
||||
if(e.limit.indexOf(',')===-1){
|
||||
e.limit='0,'+e.limit
|
||||
}else{
|
||||
e.limit='0,'+e.limit.split(',')[1]
|
||||
}
|
||||
if(e.limit=='0,0'){
|
||||
e.limit='0'
|
||||
}
|
||||
$.vidview.limit.val(e.limit)
|
||||
}
|
||||
e.dateRange=$('#videos_viewer_daterange').data('daterangepicker');
|
||||
var videoSet = 'videos'
|
||||
switch($.vidview.set.val()){
|
||||
case'cloud':
|
||||
videoSet = 'cloudVideos'
|
||||
break;
|
||||
}
|
||||
e.videoURL=$.ccio.init('location',user)+user.auth_token+'/'+videoSet+'/'+e.ke+'/'+e.mid+'?limit='+e.limit+'&start='+$.ccio.init('th',e.dateRange.startDate)+'&end='+$.ccio.init('th',e.dateRange.endDate);
|
||||
$.getJSON(e.videoURL,function(d){
|
||||
d.pages=d.total/100;
|
||||
$('.video_viewer_total').text(d.total)
|
||||
if(d.pages+''.indexOf('.')>-1){++d.pages}
|
||||
$.vidview.page_count=d.pages;
|
||||
d.count=1
|
||||
$.vidview.pages.empty()
|
||||
d.fn=function(drawOne){
|
||||
if(d.count<=$.vidview.page_count){
|
||||
$.vidview.pages.append('<a class="btn btn-primary" page="'+d.count+'">'+d.count+'</a> ')
|
||||
++d.count;
|
||||
d.fn()
|
||||
}
|
||||
}
|
||||
d.fn()
|
||||
$.vidview.pages.find('[page="'+$.vidview.current_page+'"]').addClass('active')
|
||||
e.v=$.vidview.e;
|
||||
$.vidview.loadedVideos = {}
|
||||
e.b=e.v.modal('show').find('.modal-body .contents');
|
||||
e.t=e.v.find('.modal-title i');
|
||||
switch(e.a){
|
||||
case'calendar':
|
||||
$.vidview.e.removeClass('dark')
|
||||
e.t.attr('class','fa fa-calendar')
|
||||
e.ar=[];
|
||||
if(d.videos[0]){
|
||||
$.each(d.videos,function(n,v){
|
||||
if(v.status !== 0){
|
||||
$.vidview.loadedVideos[v.filename] = Object.assign(v,{})
|
||||
var n=$.ccio.mon[v.ke+v.mid+user.auth_token];
|
||||
if(n){v.title=n.name+' - '+(parseInt(v.size)/1000000).toFixed(2)+'mb';}
|
||||
v.start=v.time;
|
||||
// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
e.ar.push(v);
|
||||
}
|
||||
})
|
||||
e.b.html('')
|
||||
try{e.b.fullCalendar('destroy')}catch(er){}
|
||||
e.b.fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listWeek'
|
||||
},
|
||||
defaultDate: $.ccio.timeObject(d.videos[0].time).format('YYYY-MM-DD'),
|
||||
navLinks: true,
|
||||
eventLimit: true,
|
||||
events:e.ar,
|
||||
eventClick:function(f){
|
||||
$('#temp').html('<div mid="'+f.mid+'" ke="'+f.ke+'" auth="'+user.auth_token+'" file="'+f.filename+'"><div video="launch" href="'+$.ccio.init('videoUrlBuild',f)+'"></div></div>').find('[video="launch"]').click();
|
||||
$(this).css('border-color', 'red');
|
||||
}
|
||||
});
|
||||
setTimeout(function(){e.b.fullCalendar('changeView','month');e.b.find('.fc-scroller').css('height','auto')},500)
|
||||
}else{
|
||||
e.b.html('<div class="text-center">'+lang.NoVideosFoundForDateRange+'</div>')
|
||||
}
|
||||
break;
|
||||
case'video_grid':
|
||||
$.vidview.e.addClass('dark')
|
||||
var tmp = '<di class="video_grid row">';
|
||||
$.each(d.videos,function(n,v){
|
||||
var href = $.ccio.init('videoUrlBuild',v)
|
||||
v.mon = $.ccio.mon[v.ke+v.mid+user.auth_token]
|
||||
var parentTag = 'ke="'+v.ke+'" status="'+v.status+'" mid="'+v.mid+'" file="'+v.filename+'" auth="'+v.mon.user.auth_token+'"'
|
||||
tmp += '<div class="col-md-2" '+parentTag+'>'
|
||||
tmp += '<div class="thumb">'
|
||||
tmp += '<div class="title-strip">'+$.ccio.timeObject(v.time).format('h:mm:ss A, MMMM Do YYYY')+'</div>'
|
||||
tmp += '<div class="button-strip">'
|
||||
tmp += '<div class="btn-group">'
|
||||
tmp += '<a class="btn btn-xs btn-primary" video="launch" href="'+href+'"> <i class="fa fa-play-circle"></i> </a>'
|
||||
tmp += '<a class="btn btn-xs btn-default preview" href="'+href+'"> <i class="fa fa-play-circle"></i> </a>'
|
||||
tmp += '<a class="btn btn-xs btn-default" download="'+v.mid+'-'+v.filename+'" href="'+href+'"> <i class="fa fa-download"></i> </a>'
|
||||
tmp += '</div>'
|
||||
tmp += '</div>'
|
||||
tmp += '</div>'
|
||||
tmp += '</div>'
|
||||
})
|
||||
tmp += '</div>'
|
||||
e.b.html(tmp)
|
||||
var i = 0
|
||||
var getThumbnail = function(){
|
||||
var v = d.videos[i]
|
||||
if(v){
|
||||
tool.getVideoImage($.ccio.init('videoUrlBuild',v),0,function(err,base64){
|
||||
if(base64){
|
||||
$('[ke="'+v.ke+'"][mid="'+v.mid+'"][file="'+v.filename+'"] .thumb').css('background-image','url('+base64+')')
|
||||
}
|
||||
++i
|
||||
getThumbnail()
|
||||
})
|
||||
}
|
||||
}
|
||||
getThumbnail()
|
||||
break;
|
||||
case'videos_table':
|
||||
var showThumbnail = $.ccio.op().showThumbnail === '1'
|
||||
$.vidview.e.removeClass('dark')
|
||||
e.t.attr('class','fa fa-film')
|
||||
var tmp = '<table class="table table-striped" style="max-height:500px">';
|
||||
tmp+='<thead>';
|
||||
tmp+='<tr>';
|
||||
tmp+='<th><div class="checkbox"><input id="videos_select_all" type="checkbox"><label for="videos_select_all"></label></div></th>';
|
||||
if(showThumbnail)tmp+='<th data-field="Thumbnail" data-sortable="true">'+lang.Thumbnail+'</th>';
|
||||
tmp+='<th data-field="Closed" data-sortable="true">'+lang.Closed+'</th>';
|
||||
tmp+='<th data-field="Ended" data-sortable="true">'+lang.Ended+'</th>';
|
||||
tmp+='<th data-field="Started" data-sortable="true">'+lang.Started+'</th>';
|
||||
tmp+='<th data-field="Monitor" data-sortable="true">'+lang.Monitor+'</th>';
|
||||
tmp+='<th data-field="Filename" data-sortable="true">'+lang.Filename+'</th>';
|
||||
tmp+='<th data-field="Size" data-sortable="true">'+lang['Size (mb)']+'</th>';
|
||||
tmp+='<th data-field="Preview" data-sortable="true">'+lang.Preview+'</th>';
|
||||
tmp+='<th data-field="Watch" data-sortable="true">'+lang.Watch+'</th>';
|
||||
tmp+='<th data-field="Download" data-sortable="true">'+lang.Download+'</th>';
|
||||
tmp+='<th class="permission_video_delete" data-field="Delete" data-sortable="true">'+lang.Delete+'</th>';
|
||||
// tmp+='<th class="permission_video_delete" data-field="Fix" data-sortable="true">'+lang.Fix+'</th>';
|
||||
tmp+='</tr>';
|
||||
tmp+='</thead>';
|
||||
tmp+='<tbody>';
|
||||
$.each(d.videos,function(n,v){
|
||||
if(v.status!==0){
|
||||
$.vidview.loadedVideos[v.filename] = Object.assign(v,{})
|
||||
var href = $.ccio.init('videoUrlBuild',v)
|
||||
v.mon=$.ccio.mon[v.ke+v.mid+user.auth_token];
|
||||
v.start=v.time;
|
||||
// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
tmp+='<tr data-ke="'+v.ke+'" data-status="'+v.status+'" data-mid="'+v.mid+'" data-file="'+v.filename+'" data-auth="'+v.mon.user.auth_token+'">';
|
||||
tmp+='<td><div class="checkbox"><input id="'+v.ke+'_'+v.filename+'" name="'+v.filename+'" value="'+v.mid+'" type="checkbox"><label for="'+v.ke+'_'+v.filename+'"></label></div></td>';
|
||||
if(showThumbnail)tmp+='<td class="text-center"><img class="thumbnail"></td>';
|
||||
tmp+='<td><span class="livestamp" title="'+$.ccio.timeObject(v.end).format('YYYY-MM-DD HH:mm:ss')+'"></span></td>';
|
||||
tmp+='<td title="'+v.end+'">'+$.ccio.timeObject(v.end).format('h:mm:ss A, MMMM Do YYYY')+'</td>';
|
||||
tmp+='<td title="'+v.time+'">'+$.ccio.timeObject(v.time).format('h:mm:ss A, MMMM Do YYYY')+'</td>';
|
||||
tmp+='<td>'+v.mon.name+'</td>';
|
||||
tmp+='<td>'+v.filename+'</td>';
|
||||
tmp+='<td>'+(parseInt(v.size)/1000000).toFixed(2)+'</td>';
|
||||
tmp+='<td><a class="btn btn-sm btn-default preview" href="'+href+'"> <i class="fa fa-play-circle"></i> </a></td>';
|
||||
tmp+='<td><a class="btn btn-sm btn-primary" video="launch" href="'+href+'"> <i class="fa fa-play-circle"></i> </a></td>';
|
||||
tmp+='<td><a class="btn btn-sm btn-success" download="'+v.mid+'-'+v.filename+'" href="'+href+'"> <i class="fa fa-download"></i> </a></td>';
|
||||
tmp+='<td class="permission_video_delete"><a class="btn btn-sm btn-danger" video="delete" href="'+$.ccio.init('videoHrefToDelete',href)+'"> <i class="fa fa-trash"></i> </a></td>';
|
||||
// tmp+='<td class="permission_video_delete"><a class="btn btn-sm btn-warning" video="fix"> <i class="fa fa-wrench"></i> </a></td>';
|
||||
tmp+='</tr>';
|
||||
}
|
||||
})
|
||||
tmp+='</tbody>';
|
||||
tmp+='</table>';
|
||||
e.b.html(tmp)
|
||||
if(showThumbnail){
|
||||
var i = 0
|
||||
var getThumbnail = function(){
|
||||
var v = d.videos[i]
|
||||
if(v){
|
||||
tool.getVideoImage($.ccio.init('videoUrlBuild',v),0,function(err,base64){
|
||||
if(base64){
|
||||
$('[data-ke="'+v.ke+'"][data-mid="'+v.mid+'"][data-file="'+v.filename+'"] .thumbnail')[0].src = base64
|
||||
}
|
||||
++i
|
||||
getThumbnail()
|
||||
})
|
||||
}
|
||||
}
|
||||
getThumbnail()
|
||||
}
|
||||
$.ccio.init('ls');
|
||||
$.vidview.e.find('table').bootstrapTable();
|
||||
break;
|
||||
}
|
||||
})
|
||||
break;
|
||||
case'fullscreen':
|
||||
e.e=e.e.parents('.monitor_item');
|
||||
e.e.addClass('fullscreen')
|
||||
e.vid=e.e.find('.stream-element')
|
||||
if(e.vid.is('canvas')){
|
||||
e.doc=$('body')
|
||||
e.vid.attr('height',e.doc.height())
|
||||
e.vid.attr('width',e.doc.width())
|
||||
}
|
||||
$.ccio.init('fullscreen',e.vid[0])
|
||||
break;
|
||||
case'watch_on':
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:e.mid},user)
|
||||
break;
|
||||
case'control_toggle':
|
||||
e.e=e.p.find('.PTZ_controls');
|
||||
if(e.e.length>0){
|
||||
e.e.remove()
|
||||
}else{
|
||||
var html = '<div class="PTZ_controls">'
|
||||
html += '<div class="pad">'
|
||||
html += '<div class="control top" monitor="control" control="up"></div>'
|
||||
html += '<div class="control left" monitor="control" control="left"></div>'
|
||||
html += '<div class="control right" monitor="control" control="right"></div>'
|
||||
html += '<div class="control bottom" monitor="control" control="down"></div>'
|
||||
html += '<div class="control middle" monitor="control" control="center"></div>'
|
||||
html += '</div>'
|
||||
html += '<div class="btn-group btn-group-sm btn-group-justified">'
|
||||
html += '<a title="'+lang['Zoom In']+'" class="zoom_in btn btn-default" monitor="control" control="zoom_in"><i class="fa fa-search-plus"></i></a>'
|
||||
html += '<a title="'+lang['Zoom Out']+'" class="zoom_out btn btn-default" monitor="control" control="zoom_out"><i class="fa fa-search-minus"></i></a>'
|
||||
html += '</div>'
|
||||
html += '<div class="btn-group btn-group-sm btn-group-justified">'
|
||||
html += '<a title="'+lang['Enable Nightvision']+'" class="nv_enable btn btn-default" monitor="control" control="enable_nv"><i class="fa fa-moon-o"></i></a>'
|
||||
html += '<a title="'+lang['Disable Nightvision']+'" class="nv_disable btn btn-default" monitor="control" control="disable_nv"><i class="fa fa-sun-o"></i></a>'
|
||||
html += '</div>'
|
||||
html += '</div>'
|
||||
e.p.append(html)
|
||||
}
|
||||
break;
|
||||
case'watch':
|
||||
if($("#monitor_live_"+e.mid+user.auth_token).length===0||$.ccio.mon[e.ke+e.mid+user.auth_token].watch!==1){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:e.mid},user)
|
||||
}else{
|
||||
$("#main_canvas").animate({scrollTop:$("#monitor_live_"+e.mid+user.auth_token).offset().top-($('#main_header').height()+10)},500);
|
||||
}
|
||||
break;
|
||||
case'watch_off':
|
||||
$.ccio.cx({f:'monitor',ff:'watch_off',id:e.mid},user)
|
||||
break;
|
||||
case'delete':
|
||||
e.m=$('#confirm_window').modal('show');e.f=e.e.attr('file');
|
||||
$.confirm.title.text(lang['Delete Monitor']+' : '+e.mon.name)
|
||||
e.html=lang.DeleteMonitorText
|
||||
e.html+='<table class="info-table table table-striped"><tr>';
|
||||
$.each($.ccio.init('cleanMon',e.mon),function(n,v,g){
|
||||
if(n==='host'&&v.indexOf('@')>-1){g=v.split('@')[1]}else{g=v};
|
||||
try{JSON.parse(g);return}catch(err){}
|
||||
e.html+='<tr><td><b>'+n+'</b></td><td>'+g+'</td></tr>';
|
||||
})
|
||||
e.html+='</tr></table>';
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click([
|
||||
{
|
||||
title:'Delete Monitor',
|
||||
class:'btn-danger',
|
||||
callback:function(){
|
||||
$.get($.ccio.init('location',user)+user.auth_token+'/configureMonitor/'+user.ke+'/'+e.mon.mid+'/delete',function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title:'Delete Monitor and Files',
|
||||
class:'btn-danger',
|
||||
callback:function(){
|
||||
$.get($.ccio.init('location',user)+user.auth_token+'/configureMonitor/'+user.ke+'/'+e.mon.mid+'/delete?deleteFiles=true',function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
}
|
||||
}
|
||||
])
|
||||
break;
|
||||
case'edit':
|
||||
e.p=$('#add_monitor'),e.mt=e.p.find('.modal-title')
|
||||
e.p.find('.am_notice').hide()
|
||||
e.p.find('[detailcontainer="detector_cascades"]').prop('checked',false).parents('.mdl-js-switch').removeClass('is-checked')
|
||||
if(!$.ccio.mon[e.ke+e.mid+user.auth_token]){
|
||||
e.p.find('.am_notice_new').show()
|
||||
//new monitor
|
||||
e.p.find('[monitor="delete"]').hide()
|
||||
e.mt.find('span').text('Add'),e.mt.find('i').attr('class','fa fa-plus');
|
||||
//default values
|
||||
e.values=$.aM.generateDefaultMonitorSettings();
|
||||
}else{
|
||||
e.p.find('.am_notice_edit').show()
|
||||
//edit monitor
|
||||
e.p.find('[monitor="delete"]').show()
|
||||
e.mt.find('span').text(lang.Edit);
|
||||
e.mt.find('i').attr('class','fa fa-wrench');
|
||||
e.values=$.ccio.mon[e.ke+e.mid+user.auth_token];
|
||||
}
|
||||
$.aM.selected=e.values;
|
||||
// e.openTabs=$.ccio.op().tabsOpen
|
||||
// if(e.openTabs[e.mid]){
|
||||
// e.values=e.openTabs[e.mid]
|
||||
// }
|
||||
$.aM.import(e)
|
||||
$('#add_monitor').modal('show')
|
||||
break;
|
||||
}
|
||||
})
|
||||
.on('dblclick','[type="password"],.password_field',function(){
|
||||
var _this = $(this)
|
||||
var type = 'password'
|
||||
_this.addClass('password_field')
|
||||
if(_this.attr('type') === 'password'){
|
||||
type = 'text'
|
||||
}
|
||||
_this.attr('type',type)
|
||||
})
|
||||
|
||||
$('.modal').on('hidden.bs.modal',function(){
|
||||
$(this).find('video').remove();
|
||||
$(this).find('iframe').attr('src','about:blank');
|
||||
});
|
||||
$('.modal').on('shown.bs.modal',function(){
|
||||
e={e:$(this).find('.flex-container-modal-body')}
|
||||
if(e.e.length>0){
|
||||
e.e.resize()
|
||||
}
|
||||
});
|
||||
|
||||
$('body')
|
||||
.on('click','.scrollTo',function(ee){
|
||||
ee.preventDefault()
|
||||
var e = {e:$(this)};
|
||||
e.parent=e.e.attr('scrollToParent')
|
||||
if(!e.parent){
|
||||
e.parent='body,html'
|
||||
}
|
||||
$(e.parent).animate({
|
||||
scrollTop: $(e.e.attr('href')).position().top
|
||||
}, 400);
|
||||
})
|
||||
.on('resize','.flex-container-modal-body',function(e){
|
||||
e=$(this)
|
||||
e.find('.flex-modal-block').css('height',e.height())
|
||||
})
|
||||
.on('resize','#monitors_live .monitor_item',function(e){
|
||||
e.e=$(this).find('.stream-block');
|
||||
e.c=e.e.find('canvas');
|
||||
e.c.attr('height',e.e.height());
|
||||
e.c.attr('width',e.e.width());
|
||||
})
|
||||
.on('keyup','.search-parent .search-controller',function(){
|
||||
_this = this;
|
||||
$.each($(".search-parent .search-body .search-row"), function() {
|
||||
if($(this).text().toLowerCase().indexOf($(_this).val().toLowerCase()) === -1)
|
||||
$(this).hide();
|
||||
else
|
||||
$(this).show();
|
||||
});
|
||||
})
|
||||
.on('dblclick','.stream-hud',function(){
|
||||
$(this).parents('[mid]').find('[monitor="fullscreen"]').click();
|
||||
})
|
||||
//.on('mousemove',".magnifyStream",$.ccio.magnifyStream)
|
||||
//.on('touchmove',".magnifyStream",$.ccio.magnifyStream);
|
||||
})
|
|
@ -0,0 +1,61 @@
|
|||
$(document).ready(function(e){
|
||||
//monitor grid
|
||||
$.grid={e:$('#monitors_live')}
|
||||
$.grid.data = function(){
|
||||
return $.grid.e.data('gridstack')
|
||||
}
|
||||
$.grid.getMonitorsPerRow = function(){
|
||||
var x
|
||||
switch($.ccio.op().montage){
|
||||
case'1':
|
||||
x = '12'
|
||||
break;
|
||||
case'2':
|
||||
x = '6'
|
||||
break;
|
||||
case'3':
|
||||
x = '4'
|
||||
break;
|
||||
case'4':
|
||||
x = '3'
|
||||
break;
|
||||
case'5':
|
||||
x = '5'
|
||||
break;
|
||||
case'6':
|
||||
x = '2'
|
||||
break;
|
||||
default://3
|
||||
x = '4'
|
||||
break;
|
||||
}
|
||||
return x
|
||||
}
|
||||
$.grid.saveElementPositions = function() {
|
||||
var monitors = {}
|
||||
$.grid.e.find(" .monitor_item").each(function(n,v){
|
||||
var el = $(v)
|
||||
var item = {}
|
||||
item.ke = el.attr('ke')
|
||||
item.mid = el.attr('mid')
|
||||
item.x = el.attr('data-gs-x')
|
||||
item.y = el.attr('data-gs-y')
|
||||
item.height = el.attr('data-gs-height')
|
||||
item.width = el.attr('data-gs-width')
|
||||
monitors[item.ke+item.mid] = item
|
||||
})
|
||||
$user.details.monitorOrder=monitors;
|
||||
$.ccio.cx({f:'monitorOrder',monitorOrder:monitors})
|
||||
}
|
||||
$.grid.e
|
||||
.gridstack({
|
||||
cellHeight: 80,
|
||||
verticalMargin: 0,
|
||||
})
|
||||
.on('dragstop', function(event,ui){
|
||||
setTimeout(function(){
|
||||
$.grid.saveElementPositions()
|
||||
},700)
|
||||
})
|
||||
.on('gsresizestop', $.grid.saveElementPositions);
|
||||
})
|
|
@ -0,0 +1,612 @@
|
|||
$.ccio.init=function(x,d,user,k){
|
||||
if(!k){k={}};k.tmp='';
|
||||
if(d&&d.user){
|
||||
user=d.user
|
||||
}
|
||||
if(!user){
|
||||
user=$user
|
||||
}
|
||||
switch(x){
|
||||
case'cleanMon':
|
||||
var acceptedFields = [
|
||||
'mid',
|
||||
'ke',
|
||||
'name',
|
||||
'shto',
|
||||
'shfr',
|
||||
'details',
|
||||
'type',
|
||||
'ext',
|
||||
'protocol',
|
||||
'host',
|
||||
'path',
|
||||
'port',
|
||||
'fps',
|
||||
'mode',
|
||||
'width',
|
||||
'height'
|
||||
]
|
||||
var row = {};
|
||||
$.each(d,function(m,b){
|
||||
if(acceptedFields.indexOf(m)>-1){
|
||||
row[m]=b;
|
||||
}
|
||||
})
|
||||
return row
|
||||
break;
|
||||
case'cleanMons':
|
||||
if(d==='object'){
|
||||
var arr={}
|
||||
}else{
|
||||
var arr=[]
|
||||
}
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
var row = $.ccio.init('cleanMon',v)
|
||||
if(d==='object'){
|
||||
arr[n]=row
|
||||
}else{
|
||||
arr.push(row)
|
||||
}
|
||||
})
|
||||
return arr;
|
||||
break;
|
||||
case'location':
|
||||
var url
|
||||
if(d&&d.info&&d.info.URL){
|
||||
url=d.info.URL
|
||||
if(url.charAt(url.length-1)!=='/'){
|
||||
url=url+'/'
|
||||
}
|
||||
}else{
|
||||
url = $.ccio.libURL
|
||||
}
|
||||
return url
|
||||
break;
|
||||
case'videoUrlBuild':
|
||||
var url
|
||||
if(d.href){
|
||||
url = d.href
|
||||
}else if(!d.href && d.hrefNoAuth){
|
||||
url = $.ccio.init('location',user)+user.auth_token+d.hrefNoAuth
|
||||
}
|
||||
if(user!==$user&&url.charAt(0)==='/'){
|
||||
url = $.ccio.init('location',user)+d.href.substring(1)
|
||||
}
|
||||
return url
|
||||
break;
|
||||
case'videoHrefToDelete':
|
||||
var urlSplit = d.split('?')
|
||||
var url = urlSplit[0]+'/delete'
|
||||
if(urlSplit[1])url += '?' + urlSplit[1]
|
||||
return url
|
||||
break;
|
||||
case'videoHrefToUnread':
|
||||
var urlSplit = d.split('?')
|
||||
var url = urlSplit[0]+'/status/1'
|
||||
if(urlSplit[1])url += '?' + urlSplit[1]
|
||||
return url
|
||||
break;
|
||||
case'videoHrefToRead':
|
||||
var urlSplit = d.split('?')
|
||||
var url = urlSplit[0]+'/status/2'
|
||||
if(urlSplit[1])url += '?' + urlSplit[1]
|
||||
return url
|
||||
break;
|
||||
// case'streamWindow':
|
||||
// return $('.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]')
|
||||
// break;
|
||||
case'streamMotionDetectRestart':
|
||||
$.ccio.init('streamMotionDetectOff',d,user)
|
||||
$.ccio.init('streamMotionDetectOn',d,user)
|
||||
break;
|
||||
case'streamMotionDetectOff':
|
||||
d.mon.motionDetectionRunning = false
|
||||
$('.monitor_item[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]').find('.stream-detected-object,.zoomGlass').remove()
|
||||
clearInterval(d.mon.motionDetector)
|
||||
break;
|
||||
case'streamMotionDetectOn':
|
||||
switch(JSON.parse(d.mon.details).stream_type){
|
||||
case'hls':case'flv':case'mp4':
|
||||
//pass
|
||||
break;
|
||||
default:
|
||||
return $.ccio.init('note',{title:'Client-side Detector',text:'Could not be started. Only <b>FLV</b> and <b>HLS</b> can use this feature.',type:'error'});
|
||||
break;
|
||||
|
||||
}
|
||||
d.mon.motionDetectorNextDraw = true
|
||||
d.mon.motionDetectionRunning = true
|
||||
$.ccio.snapshot(d,function(url){
|
||||
$('#temp').html('<img>')
|
||||
var img=$('#temp img')[0]
|
||||
img.onload=function(){
|
||||
var frameNumber = 0,
|
||||
mainWindow = $('.monitor_item[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]'),
|
||||
blenderCanvas = mainWindow.find(".blenderCanvas"),
|
||||
motionVision = mainWindow.find(".motionVision"),
|
||||
streamElement = mainWindow.find('.stream-element'),
|
||||
streamElementTag = streamElement[0],
|
||||
lastURL = null,
|
||||
currentImage = null,
|
||||
f = [],
|
||||
drawMatrices = {
|
||||
e:mainWindow,
|
||||
monitorDetails:JSON.parse(d.mon.details),
|
||||
stream:streamElement,
|
||||
streamObjects:mainWindow.find('.stream-objects'),
|
||||
details:{
|
||||
name:'clientSideDetection',
|
||||
}
|
||||
};
|
||||
widthRatio = streamElement.width() / img.width
|
||||
heightRatio = streamElement.height() / img.height
|
||||
drawMatrices.monitorDetails.detector_scale_x = img.width;
|
||||
drawMatrices.monitorDetails.detector_scale_y = img.height;
|
||||
function checkForMotion() {
|
||||
blenderCanvas.width = img.width;
|
||||
blenderCanvas.height = img.height;
|
||||
blenderCanvasContext.drawImage(streamElementTag, 0, 0);
|
||||
f[frameNumber] = blenderCanvasContext.getImageData(0, 0, blenderCanvas.width, blenderCanvas.height);
|
||||
frameNumber = 0 == frameNumber ? 1 : 0;
|
||||
currentImage = blenderCanvasContext.getImageData(0, 0, blenderCanvas.width, blenderCanvas.height);
|
||||
foundPixels = [];
|
||||
for (var currentImageLength = currentImage.data.length * 0.25, b = 0; b < currentImageLength;){
|
||||
var pos = b * 4
|
||||
currentImage.data[pos] = .5 * (255 - currentImage.data[pos]) + .5 * f[frameNumber].data[pos];
|
||||
currentImage.data[pos + 1] = .5 * (255 - currentImage.data[pos + 1]) + .5 * f[frameNumber].data[pos + 1];
|
||||
currentImage.data[pos + 2] = .5 * (255 - currentImage.data[pos + 2]) + .5 * f[frameNumber].data[pos + 2];
|
||||
currentImage.data[pos + 3] = 255;
|
||||
var score = (currentImage.data[pos] + currentImage.data[pos + 1] + currentImage.data[pos + 2]) / 3;
|
||||
if(score>170){
|
||||
var x = (pos / 4) % img.width;
|
||||
var y = Math.floor((pos / 4) / img.width);
|
||||
foundPixels.push([x,y])
|
||||
}
|
||||
b += 4;
|
||||
}
|
||||
var groupedPoints = Object.assign({},Cluster);
|
||||
groupedPoints.iterations(25);
|
||||
groupedPoints.data(foundPixels);
|
||||
var groupedPoints = groupedPoints.clusters()
|
||||
drawMatrices.details.matrices=[]
|
||||
var mostHeight = 0;
|
||||
var mostWidth = 0;
|
||||
var mostWithMotion = null;
|
||||
groupedPoints.forEach(function(v,n){
|
||||
var matrix = {
|
||||
topLeft:[img.width,img.height],
|
||||
topRight:[0,img.height],
|
||||
bottomRight:[0,0],
|
||||
bottomLeft:[img.width,0],
|
||||
}
|
||||
v.points.forEach(function(b){
|
||||
var x = b[0]
|
||||
var y = b[1]
|
||||
if(x<matrix.topLeft[0])matrix.topLeft[0]=x;
|
||||
if(y<matrix.topLeft[1])matrix.topLeft[1]=y;
|
||||
//Top Right point
|
||||
if(x>matrix.topRight[0])matrix.topRight[0]=x;
|
||||
if(y<matrix.topRight[1])matrix.topRight[1]=y;
|
||||
//Bottom Right point
|
||||
if(x>matrix.bottomRight[0])matrix.bottomRight[0]=x;
|
||||
if(y>matrix.bottomRight[1])matrix.bottomRight[1]=y;
|
||||
//Bottom Left point
|
||||
if(x<matrix.bottomLeft[0])matrix.bottomLeft[0]=x;
|
||||
if(y>matrix.bottomLeft[1])matrix.bottomLeft[1]=y;
|
||||
})
|
||||
matrix.x = matrix.topLeft[0];
|
||||
matrix.y = matrix.topLeft[1];
|
||||
matrix.width = matrix.topRight[0] - matrix.topLeft[0]
|
||||
matrix.height = matrix.bottomLeft[1] - matrix.topLeft[1]
|
||||
|
||||
if(matrix.width>mostWidth&&matrix.height>mostHeight){
|
||||
mostWidth = matrix.width;
|
||||
mostHeight = matrix.height;
|
||||
mostWithMotion = matrix;
|
||||
}
|
||||
|
||||
drawMatrices.details.matrices.push(matrix)
|
||||
})
|
||||
$.ccio.magnifyStream({
|
||||
p:mainWindow,
|
||||
useCanvas:true,
|
||||
zoomAmount:1,
|
||||
auto:true,
|
||||
animate:true,
|
||||
pageX:((mostWithMotion.width / 2) + mostWithMotion.x) * widthRatio,
|
||||
pageY:((mostWithMotion.height / 2) + mostWithMotion.y) * heightRatio
|
||||
})
|
||||
$.ccio.init('drawMatrices',drawMatrices)
|
||||
if(d.mon.motionDetectorNextDraw===true){
|
||||
clearTimeout(d.mon.motionDetectorNextDrawTimeout)
|
||||
d.mon.motionDetectorNextDrawTimeout=setTimeout(function(){
|
||||
d.mon.motionDetectorNextDraw = true;
|
||||
},1000)
|
||||
d.mon.motionDetectorNextDraw = false;
|
||||
// console.log({
|
||||
// p:mainWindow,
|
||||
// pageX:((matrix.width / 2) + matrix.x) * widthRatio,
|
||||
// pageY:((matrix.height / 2) + matrix.y) * heightRatio
|
||||
// })
|
||||
}
|
||||
return drawMatrices.details.matrices;
|
||||
}
|
||||
if(blenderCanvas.length === 0){
|
||||
mainWindow.append('<div class="zoomGlass"><canvas class="blenderCanvas"></canvas></div>')
|
||||
blenderCanvas = mainWindow.find(".blenderCanvas")
|
||||
}
|
||||
blenderCanvas = blenderCanvas[0];
|
||||
var blenderCanvasContext = blenderCanvas.getContext("2d");
|
||||
clearInterval(d.mon.motionDetector)
|
||||
d.mon.motionDetector = setInterval(checkForMotion,2000)
|
||||
}
|
||||
img.src=url
|
||||
})
|
||||
break;
|
||||
case'streamURL':
|
||||
var streamURL
|
||||
switch(JSON.parse(d.details).stream_type){
|
||||
case'jpeg':
|
||||
streamURL=$.ccio.init('location',user)+user.auth_token+'/jpeg/'+d.ke+'/'+d.mid+'/s.jpg'
|
||||
break;
|
||||
case'mjpeg':
|
||||
streamURL=$.ccio.init('location',user)+user.auth_token+'/mjpeg/'+d.ke+'/'+d.mid
|
||||
break;
|
||||
case'hls':
|
||||
streamURL=$.ccio.init('location',user)+user.auth_token+'/hls/'+d.ke+'/'+d.mid+'/s.m3u8'
|
||||
break;
|
||||
case'flv':
|
||||
streamURL=$.ccio.init('location',user)+user.auth_token+'/flv/'+d.ke+'/'+d.mid+'/s.flv'
|
||||
break;
|
||||
case'h265':
|
||||
streamURL=$.ccio.init('location',user)+user.auth_token+'/h265/'+d.ke+'/'+d.mid+'/s.hevc'
|
||||
break;
|
||||
case'mp4':
|
||||
streamURL=$.ccio.init('location',user)+user.auth_token+'/mp4/'+d.ke+'/'+d.mid+'/s.mp4'
|
||||
break;
|
||||
case'b64':
|
||||
streamURL='Websocket'
|
||||
break;
|
||||
case'pam':
|
||||
streamURL='Websocket'
|
||||
break;
|
||||
}
|
||||
return streamURL
|
||||
break;
|
||||
case'humanReadMode':
|
||||
switch(d){
|
||||
case'idle':
|
||||
k.mode=lang['Idle']
|
||||
break;
|
||||
case'stop':
|
||||
k.mode=lang['Disabled']
|
||||
break;
|
||||
case'record':
|
||||
k.mode=lang['Record']
|
||||
break;
|
||||
case'start':
|
||||
k.mode=lang['Watch Only']
|
||||
break;
|
||||
}
|
||||
return k.mode
|
||||
break;
|
||||
case'monitorInfo':
|
||||
d.e=$('.glM'+d.mon.mid+user.auth_token);
|
||||
if(JSON.parse(d.mon.details).vcodec!=='copy'&&d.mon.mode=='record'){
|
||||
d.e.find('.monitor_not_record_copy').show()
|
||||
}else{
|
||||
d.e.find('.monitor_not_record_copy').hide()
|
||||
}
|
||||
d.e.find('.monitor_name').text(d.mon.name)
|
||||
d.e.find('.monitor_mid').text(d.mon.mid)
|
||||
d.e.find('.monitor_ext').text(d.mon.ext);
|
||||
d.mode=$.ccio.init('humanReadMode',d.mon.mode,user)
|
||||
d.e.find('.monitor_mode').text(d.mode)
|
||||
d.e.find('.monitor_status').text(d.status)
|
||||
d.e.attr('mode',d.mode)
|
||||
d.e.find('.lamp').attr('title',d.mode)
|
||||
break;
|
||||
case'fullscreen':
|
||||
if (d.requestFullscreen) {
|
||||
d.requestFullscreen();
|
||||
} else if (d.mozRequestFullScreen) {
|
||||
d.mozRequestFullScreen();
|
||||
} else if (d.webkitRequestFullscreen) {
|
||||
d.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||
}
|
||||
break;
|
||||
case'drawPoints':
|
||||
d.height=d.stream.height()
|
||||
d.width=d.stream.width()
|
||||
if(d.monitorDetails.detector_scale_x===''){d.monitorDetails.detector_scale_x=320}
|
||||
if(d.monitorDetails.detector_scale_y===''){d.monitorDetails.detector_scale_y=240}
|
||||
|
||||
d.widthRatio=d.width/d.monitorDetails.detector_scale_x
|
||||
d.heightRatio=d.height/d.monitorDetails.detector_scale_y
|
||||
|
||||
d.streamObjects.find('.stream-detected-point[name="'+d.details.name+'"]').remove()
|
||||
d.tmp=''
|
||||
$.each(d.details.points,function(n,v){
|
||||
d.tmp+='<div class="stream-detected-point" name="'+d.details.name+'" style="height:'+1+'px;width:'+1+'px;top:'+(d.heightRatio*v.x)+'px;left:'+(d.widthRatio*v.y)+'px;">'
|
||||
if(v.tag){d.tmp+='<span class="tag">'+v.tag+'</span>'}
|
||||
d.tmp+='</div>'
|
||||
})
|
||||
d.streamObjects.append(d.tmp)
|
||||
break;
|
||||
case'drawMatrices':
|
||||
d.height=d.stream.height()
|
||||
d.width=d.stream.width()
|
||||
if(d.monitorDetails.detector_scale_x===''){d.monitorDetails.detector_scale_x=320}
|
||||
if(d.monitorDetails.detector_scale_y===''){d.monitorDetails.detector_scale_y=240}
|
||||
|
||||
d.widthRatio=d.width/d.monitorDetails.detector_scale_x
|
||||
d.heightRatio=d.height/d.monitorDetails.detector_scale_y
|
||||
|
||||
d.streamObjects.find('.stream-detected-object[name="'+d.details.name+'"]').remove()
|
||||
d.tmp=''
|
||||
$.each(d.details.matrices,function(n,v){
|
||||
d.tmp+='<div class="stream-detected-object" name="'+d.details.name+'" style="height:'+(d.heightRatio*v.height)+'px;width:'+(d.widthRatio*v.width)+'px;top:'+(d.heightRatio*v.y)+'px;left:'+(d.widthRatio*v.x)+'px;">'
|
||||
if(v.tag){d.tmp+='<span class="tag">'+v.tag+'</span>'}
|
||||
d.tmp+='</div>'
|
||||
})
|
||||
d.streamObjects.append(d.tmp)
|
||||
break;
|
||||
case'clearTimers':
|
||||
if(!d.mid){d.mid=d.id}
|
||||
if($.ccio.mon[d.ke+d.mid+user.auth_token]){
|
||||
clearTimeout($.ccio.mon[d.ke+d.mid+user.auth_token]._signal);
|
||||
clearInterval($.ccio.mon[d.ke+d.mid+user.auth_token].hlsGarbageCollectorTimer)
|
||||
clearTimeout($.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval);
|
||||
clearInterval($.ccio.mon[d.ke+d.mid+user.auth_token].signal);
|
||||
clearInterval($.ccio.mon[d.ke+d.mid+user.auth_token].m3uCheck);
|
||||
if($.ccio.mon[d.ke+d.mid+user.auth_token].Base64 && $.ccio.mon[d.ke+d.mid+user.auth_token].Base64.connected){
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token].Base64.disconnect()
|
||||
}
|
||||
if($.ccio.mon[d.ke+d.mid+user.auth_token].Poseidon){
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token].Poseidon.stop()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case'note':
|
||||
k.o=$.ccio.op().switches
|
||||
if(k.o&&k.o.notifyHide!==1){
|
||||
new PNotify(d)
|
||||
if(user.details.audio_note && user.details.audio_note !== ''){
|
||||
var audio = new Audio('libs/audio/'+user.details.audio_note);
|
||||
audio.play()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case'monGroup':
|
||||
$.ccio.mon_groups={};
|
||||
$.each($.ccio.mon,function(n,v,x){
|
||||
if(typeof v.details==='string'){
|
||||
k.d=JSON.parse(v.details)
|
||||
}else{
|
||||
k.d=v.details
|
||||
}
|
||||
try{
|
||||
k.groups=JSON.parse(k.d.groups)
|
||||
$.each(k.groups,function(m,b){
|
||||
if(!$.ccio.mon_groups[b])$.ccio.mon_groups[b]={}
|
||||
$.ccio.mon_groups[b][v.mid]=v;
|
||||
})
|
||||
}catch(er){
|
||||
|
||||
}
|
||||
})
|
||||
return $.ccio.mon_groups;
|
||||
break;
|
||||
case'closeVideo':
|
||||
var el = $('#monitor_live_'+d.mid+user.auth_token)
|
||||
var video = el.find('video')
|
||||
if(video.length === 1){
|
||||
if(!video[0].paused){
|
||||
video[0].onerror = function(){}
|
||||
video[0].pause()
|
||||
}
|
||||
video.prop('src','');
|
||||
video.find('source').remove();
|
||||
video.remove();
|
||||
}
|
||||
break;
|
||||
case'jpegModeStop':
|
||||
clearTimeout($.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval);
|
||||
delete($.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval);
|
||||
$('#monitor_live_'+d.mid+user.auth_token+' .stream-element').unbind('load')
|
||||
break;
|
||||
case'jpegMode':
|
||||
if(d.watch===1){
|
||||
k=JSON.parse(d.details);
|
||||
k.jpegInterval=parseFloat(k.jpegInterval);
|
||||
if(!k.jpegInterval||k.jpegInterval===''||isNaN(k.jpegInterval)){k.jpegInterval=1}
|
||||
$.ccio.tm('stream-element',$.ccio.mon[d.ke+d.mid+user.auth_token]);
|
||||
k.e=$('#monitor_live_'+d.mid+user.auth_token+' .stream-element');
|
||||
$.ccio.init('jpegModeStop',d,user);
|
||||
k.run=function(){
|
||||
k.e.attr('src',$.ccio.init('location',user)+user.auth_token+'/jpeg/'+d.ke+'/'+d.mid+'/s.jpg?time='+(new Date()).getTime())
|
||||
}
|
||||
k.e.load(function(){
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval=setTimeout(k.run,1000/k.jpegInterval);
|
||||
}).error(function(){
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token].jpegInterval=setTimeout(k.run,1000/k.jpegInterval);
|
||||
})
|
||||
k.run()
|
||||
};
|
||||
break;
|
||||
case'jpegModeAll':
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
$.ccio.init('jpegMode',v,user)
|
||||
});
|
||||
break;
|
||||
case'getLocation':
|
||||
var l = document.createElement("a");
|
||||
l.href = d;
|
||||
return l;
|
||||
break;
|
||||
case 'ls'://livestamp all
|
||||
g={e:jQuery('.livestamp')};
|
||||
g.e.each(function(){g.v=jQuery(this),g.t=g.v.attr('title');if(!g.t){return};g.v.toggleClass('livestamp livestamped').attr('title',$.ccio.init('t',g.t,user)).livestamp(g.t);})
|
||||
return g.e
|
||||
break;
|
||||
case't'://format time
|
||||
if(!d){d=new Date();}
|
||||
return $.ccio.timeObject(d).format('YYYY-MM-DD HH:mm:ss')
|
||||
break;
|
||||
case'th'://format time hy
|
||||
if(!d){d=new Date();}
|
||||
return $.ccio.timeObject(d).format('YYYY-MM-DDTHH:mm:ss')
|
||||
break;
|
||||
case'tf'://time to filename
|
||||
if(!d){d=new Date();}
|
||||
return $.ccio.timeObject(d).format('YYYY-MM-DDTHH-mm-ss')
|
||||
break;
|
||||
case'fn'://row to filename
|
||||
return $.ccio.init('tf',d.time,user)+'.'+d.ext
|
||||
break;
|
||||
case'filters':
|
||||
k.tmp='<option value="" selected>'+lang['Add New']+'</option>';
|
||||
$.each(user.details.filters,function(n,v){
|
||||
k.tmp+='<option value="'+v.id+'">'+v.name+'</option>'
|
||||
});
|
||||
$('#saved_filters').html(k.tmp)
|
||||
break;
|
||||
case'id':
|
||||
$('.usermail').html(d.mail)
|
||||
try{k.d=JSON.parse(d.details);}catch(er){k.d=d.details;}
|
||||
try{user.mon_groups=JSON.parse(k.d.mon_groups);}catch(er){}
|
||||
if(!user.mon_groups)user.mon_groups={};
|
||||
$.sM.reDrawMonGroups()
|
||||
$.each(user,function(n,v){$.sM.e.find('[name="'+n+'"]').val(v).change()})
|
||||
$.each(k.d,function(n,v){$.sM.e.find('[detail="'+n+'"]').val(v).change()})
|
||||
$.gR.drawList();
|
||||
$.ccio.pm('link-set',k.d.links,null,user)
|
||||
break;
|
||||
case'jsontoblock'://draw json as block
|
||||
if(d instanceof Object){
|
||||
$.each(d,function(n,v){
|
||||
k.tmp+='<div>';
|
||||
k.tmp+='<b>'+n+'</b> : '+$.ccio.init('jsontoblock',v,user);
|
||||
k.tmp+='</div>';
|
||||
})
|
||||
}else{
|
||||
k.tmp+='<span>';
|
||||
k.tmp+=d;
|
||||
k.tmp+='</span>';
|
||||
}
|
||||
break;
|
||||
case'url':
|
||||
var porty
|
||||
if(d.port && d.port !== ''){
|
||||
porty = ':' + d.port
|
||||
}else{
|
||||
porty = ''
|
||||
}
|
||||
d.url = d.protocol + '://' + d.host + porty
|
||||
return d.url
|
||||
break;
|
||||
case'data-video':
|
||||
if(!d){
|
||||
$('[data-mid]').each(function(n,v){
|
||||
v=$(v);v.attr('mid',v.attr('data-mid'))
|
||||
});
|
||||
$('[data-ke]').each(function(n,v){
|
||||
v=$(v);v.attr('ke',v.attr('data-ke'))
|
||||
});
|
||||
$('[data-file]').each(function(n,v){
|
||||
v=$(v);v.attr('file',v.attr('data-file'))
|
||||
});
|
||||
$('[data-status]').each(function(n,v){
|
||||
v=$(v);v.attr('status',v.attr('data-status'))
|
||||
});
|
||||
$('[data-auth]').each(function(n,v){
|
||||
v=$(v);v.attr('auth',v.attr('data-auth'))
|
||||
});
|
||||
}else{
|
||||
$('[data-ke="'+d.ke+'"][data-mid="'+d.mid+'"][data-file="'+d.filename+'"][auth="'+user.auth_token+'"]').attr('mid',d.mid).attr('ke',d.ke).attr('status',d.status).attr('file',d.filename).attr('auth',user.auth_token);
|
||||
}
|
||||
break;
|
||||
case'signal':
|
||||
d.mon=$.ccio.mon[d.ke+d.id+user.auth_token];d.e=$('#monitor_live_'+d.id+user.auth_token+' .signal').addClass('btn-success').removeClass('btn-danger');d.signal=parseFloat(JSON.parse(d.mon.details).signal_check);
|
||||
if(!d.signal||d.signal==NaN){d.signal=10;};d.signal=d.signal*1000*60;
|
||||
clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token]._signal);$.ccio.mon[d.ke+d.id+user.auth_token]._signal=setTimeout(function(){d.e.addClass('btn-danger').removeClass('btn-success');},d.signal)
|
||||
break;
|
||||
case'signal-check':
|
||||
try{
|
||||
d.mon=$.ccio.mon[d.ke+d.id+user.auth_token];d.p=$('#monitor_live_'+d.id+user.auth_token);
|
||||
try{d.d=JSON.parse(d.mon.details)}catch(er){d.d=d.mon.details;}
|
||||
d.check={c:0};
|
||||
d.fn=function(){
|
||||
if(!d.speed){d.speed=1000}
|
||||
switch(d.d.stream_type){
|
||||
case'b64':case'h265':
|
||||
d.p.resize()
|
||||
break;
|
||||
case'hls':case'flv':case'mp4':
|
||||
if(d.p.find('video')[0].paused){
|
||||
if(d.d.signal_check_log==1){
|
||||
d.log={type:'Stream Check',msg:lang.clientStreamFailedattemptingReconnect}
|
||||
$.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs')
|
||||
}
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user);
|
||||
}else{
|
||||
if(d.d.signal_check_log==1){
|
||||
d.log={type:'Stream Check',msg:'Success'}
|
||||
$.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs')
|
||||
}
|
||||
$.ccio.init('signal',d,user);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if($.ccio.op().jpeg_on===true){return}
|
||||
$.ccio.snapshot(d,function(url){
|
||||
d.check.f=url;
|
||||
setTimeout(function(){
|
||||
$.ccio.snapshot(d,function(url){
|
||||
if(d.check.f===url){
|
||||
if(d.check.c<3){
|
||||
++d.check.c;
|
||||
setTimeout(function(){
|
||||
d.fn();
|
||||
},d.speed)
|
||||
}else{
|
||||
if(d.d.signal_check_log==1){
|
||||
d.log={type:'Stream Check',msg:'Client side ctream check failed, attempting reconnect.'}
|
||||
$.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs')
|
||||
}
|
||||
delete(d.check)
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user);
|
||||
}
|
||||
}else{
|
||||
if(d.d.signal_check_log==1){
|
||||
d.log={type:'Stream Check',msg:'Success'}
|
||||
$.ccio.tm(4,d,'#logs,.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .logs')
|
||||
}
|
||||
delete(d.check)
|
||||
$.ccio.init('signal',d,user);
|
||||
}
|
||||
});
|
||||
},d.speed)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
d.fn();
|
||||
}catch(er){
|
||||
er=er.stack;
|
||||
d.in=function(x){return er.indexOf(x)>-1}
|
||||
switch(true){
|
||||
case d.in("The HTMLImageElement provided is in the 'broken' state."):
|
||||
delete(d.check)
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user);
|
||||
break;
|
||||
default:
|
||||
$.ccio.log('signal-check',er)
|
||||
break;
|
||||
}
|
||||
clearInterval($.ccio.mon[d.ke+d.id+user.auth_token].signal);delete($.ccio.mon[d.ke+d.id+user.auth_token].signal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return k.tmp;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
$(document).ready(function(e){
|
||||
//log viewer
|
||||
$.log = {
|
||||
e : $('#logs_modal'),
|
||||
lm : $('#log_monitors'),
|
||||
dateRange : $('#logs_daterange'),
|
||||
loaded : {}
|
||||
}
|
||||
$.log.dateRange.daterangepicker({
|
||||
startDate:$.ccio.timeObject().subtract(moment.duration("5:00:00")),
|
||||
endDate:$.ccio.timeObject().add(moment.duration("24:00:00")),
|
||||
timePicker: true,
|
||||
timePicker24Hour: true,
|
||||
timePickerSeconds: true,
|
||||
timePickerIncrement: 30,
|
||||
locale: {
|
||||
format: 'MM/DD/YYYY h:mm A'
|
||||
}
|
||||
},function(start, end, label){
|
||||
//change daterange
|
||||
$.log.lm.change()
|
||||
});
|
||||
$.log.table = $.log.e.find('table')
|
||||
$.log.e.on('shown.bs.modal', function () {
|
||||
$.log.lm.find('option:not(.hard)').remove()
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
v.id = v.mid
|
||||
$.ccio.tm('option',v,'#log_monitors')
|
||||
})
|
||||
$.log.lm.change()
|
||||
})
|
||||
$.log.lm.change(function(){
|
||||
e = {}
|
||||
e.v = $(this).val();
|
||||
e.urlSelector = e.v+'';
|
||||
if(e.v === 'all'){
|
||||
e.urlSelector = ''
|
||||
}
|
||||
e.dateRange = $.log.dateRange.data('daterangepicker');
|
||||
$.log.loaded.startDate = e.dateRange.startDate
|
||||
$.log.loaded.endDate = e.dateRange.endDate
|
||||
var url = $.ccio.init('location',$user)+$user.auth_token+'/logs/'+$user.ke+'/'+e.urlSelector+'?start='+$.ccio.init('th',$.log.loaded.startDate)+'&end='+$.ccio.init('th',$.log.loaded.endDate)
|
||||
$.get(url,function(d){
|
||||
$.log.loaded.url = url
|
||||
$.log.loaded.query = e.v
|
||||
$.log.loaded.rows = d
|
||||
e.tmp='';
|
||||
if(d.length === 0){
|
||||
e.tmp = '<tr class="text-center"><td>'+lang.NoLogsFoundForDateRange+'</td></tr>'
|
||||
}else{
|
||||
$.each(d,function(n,v){
|
||||
e.tmp+='<tr class="search-row"><td title="'+v.time+'" class="livestamp"></td><td>'+v.time+'</td><td>'+v.mid+'</td><td>'+$.ccio.init('jsontoblock',v.info)+'</td></tr>'
|
||||
})
|
||||
}
|
||||
$.log.table.find('tbody').html(e.tmp)
|
||||
// $.log.table.bootstrapTable()
|
||||
$.ccio.init('ls')
|
||||
})
|
||||
})
|
||||
$.log.e.find('[download]').click(function(){
|
||||
$.ccio.downloadJSON($.log.loaded,'Shinobi_Logs_'+(new Date())+'.json',{
|
||||
title : 'No Logs Found',
|
||||
text : 'No file will be downloaded.',
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,773 @@
|
|||
$(document).ready(function(e){
|
||||
|
||||
//Monitor Editor
|
||||
$.aM={e:$('#add_monitor'),monitorsForCopy:$('#copy_settings_monitors')};
|
||||
$.aM.f=$.aM.e.find('form')
|
||||
$.aM.channels=$('#monSectionStreamChannels')
|
||||
$.aM.maps=$('#monSectionInputMaps')
|
||||
$.aM.e.find('.follow-list ul').affix();
|
||||
$.each($.ccio.definitions["Monitor Settings"].blocks,function(n,v){
|
||||
$.each(v.info,function(m,b){
|
||||
if(!b.name){
|
||||
console.log(b)
|
||||
return
|
||||
}
|
||||
if(b.name.indexOf('detail=')>-1){
|
||||
b.name=b.name.replace('detail=','')
|
||||
v.element=$.aM.e.find('[detail="'+b.name+'"]')
|
||||
}else{
|
||||
v.element=$.aM.e.find('[name="'+b.name+'"]')
|
||||
}
|
||||
v.parent=v.element.parents('.form-group').find('label div:first-child span')
|
||||
v.parent.find('small').remove()
|
||||
v.parent.append('<small class="hover">'+b.description+'</small>')
|
||||
})
|
||||
})
|
||||
$.aM.generateDefaultMonitorSettings=function(){
|
||||
return {
|
||||
"mode": "start",
|
||||
"mid": $.ccio.gid(),
|
||||
"name": "Some Stream",
|
||||
"type": "h264",
|
||||
"protocol": "rtsp",
|
||||
"host": "",
|
||||
"port": "",
|
||||
"path": "",
|
||||
"ext": "mp4",
|
||||
"fps": "1",
|
||||
"width": "640",
|
||||
"height": "480",
|
||||
"details": JSON.stringify({
|
||||
"fatal_max": "0",
|
||||
"notes": "",
|
||||
"dir": "",
|
||||
"auto_host_enable": "1",
|
||||
"auto_host": "",
|
||||
"rtsp_transport": "tcp",
|
||||
"muser": "",
|
||||
"mpass": "",
|
||||
"port_force": "0",
|
||||
"aduration": "1000000",
|
||||
"probesize": "1000000",
|
||||
"stream_loop": "0",
|
||||
"sfps": "",
|
||||
"accelerator": "0",
|
||||
"hwaccel": "auto",
|
||||
"hwaccel_vcodec": "",
|
||||
"hwaccel_device": "",
|
||||
"stream_type": "mp4",
|
||||
"stream_flv_type": "ws",
|
||||
"stream_mjpeg_clients": "",
|
||||
"stream_vcodec": "copy",
|
||||
"stream_acodec": "no",
|
||||
"hls_time": "2",
|
||||
"preset_stream": "ultrafast",
|
||||
"hls_list_size": "3",
|
||||
"signal_check": "10",
|
||||
"signal_check_log": "0",
|
||||
"stream_quality": "15",
|
||||
"stream_fps": "2",
|
||||
"stream_scale_x": "",
|
||||
"stream_scale_y": "",
|
||||
"rotate_stream": "no",
|
||||
"svf": "",
|
||||
"rtmp_vcodec": "h264",
|
||||
"rtmp_acodec": "aac",
|
||||
"stream_timestamp": "0",
|
||||
"stream_timestamp_font": "",
|
||||
"stream_timestamp_font_size": "",
|
||||
"stream_timestamp_color": "",
|
||||
"stream_timestamp_box_color": "",
|
||||
"stream_timestamp_x": "",
|
||||
"stream_timestamp_y": "",
|
||||
"stream_watermark": "0",
|
||||
"stream_watermark_location": "",
|
||||
"stream_watermark_position": "tr",
|
||||
"snap": "0",
|
||||
"snap_fps": "",
|
||||
"snap_scale_x": "",
|
||||
"snap_scale_y": "",
|
||||
"snap_vf": "",
|
||||
"rawh264": "0",
|
||||
"rawh264_vcodec": "copy",
|
||||
"rawh264_acodec": "",
|
||||
"rawh264_fps": "",
|
||||
"rawh264_scale_x": "",
|
||||
"rawh264_scale_y": "",
|
||||
"rawh264_crf": "",
|
||||
"rawh264_vf": "",
|
||||
"vcodec": "copy",
|
||||
"crf": "1",
|
||||
"preset_record": "",
|
||||
"acodec": "no",
|
||||
"dqf": "0",
|
||||
"cutoff": "15",
|
||||
"rotate_record": "no",
|
||||
"vf": "",
|
||||
"timestamp": "0",
|
||||
"timestamp_font": "",
|
||||
"timestamp_font_size": "10",
|
||||
"timestamp_color": "white",
|
||||
"timestamp_box_color": "0x00000000@1",
|
||||
"timestamp_x": "(w-tw)/2",
|
||||
"timestamp_y": "0",
|
||||
"watermark": "0",
|
||||
"watermark_location": "",
|
||||
"watermark_position": "tr",
|
||||
"cust_input": "",
|
||||
"cust_snap": "",
|
||||
"cust_rawh264": "",
|
||||
"cust_detect": "",
|
||||
"cust_stream": "",
|
||||
"cust_stream_server": "",
|
||||
"cust_record": "",
|
||||
"custom_output": "",
|
||||
"detector": "0",
|
||||
"detector_pam": "1",
|
||||
"detector_webhook": "0",
|
||||
"detector_webhook_url": "",
|
||||
"detector_command_enable": "0",
|
||||
"detector_command": "",
|
||||
"detector_command_timeout": "",
|
||||
"detector_lock_timeout": "",
|
||||
"detector_save": "0",
|
||||
"detector_frame_save": "0",
|
||||
"detector_mail": "0",
|
||||
"detector_mail_timeout": "",
|
||||
"detector_record_method": "sip",
|
||||
"detector_trigger": "1",
|
||||
"detector_trigger_record_fps": "",
|
||||
"detector_timeout": "10",
|
||||
"watchdog_reset": "0",
|
||||
"detector_delete_motionless_videos": "0",
|
||||
"detector_send_frames": "1",
|
||||
"detector_region_of_interest": "0",
|
||||
"detector_fps": "",
|
||||
"detector_scale_x": "640",
|
||||
"detector_scale_y": "480",
|
||||
"detector_use_motion": "1",
|
||||
"detector_use_detect_object": "0",
|
||||
"detector_frame": "0",
|
||||
"detector_sensitivity": "",
|
||||
"detector_max_sensitivity": "",
|
||||
"detector_threshold": "1",
|
||||
"detector_color_threshold": "",
|
||||
"cords": "[]",
|
||||
"detector_buffer_vcodec": "auto",
|
||||
"detector_buffer_fps": "",
|
||||
"detector_buffer_hls_time": "",
|
||||
"detector_buffer_hls_list_size": "",
|
||||
"detector_buffer_start_number": "",
|
||||
"detector_buffer_live_start_index": "",
|
||||
"detector_lisence_plate": "0",
|
||||
"detector_lisence_plate_country": "us",
|
||||
"detector_notrigger": "0",
|
||||
"detector_notrigger_mail": "0",
|
||||
"detector_notrigger_timeout": "",
|
||||
"control": "0",
|
||||
"control_base_url": "",
|
||||
"control_stop": "0",
|
||||
"control_url_stop_timeout": "",
|
||||
"control_url_center": "",
|
||||
"control_url_left": "",
|
||||
"control_url_left_stop": "",
|
||||
"control_url_right": "",
|
||||
"control_url_right_stop": "",
|
||||
"control_url_up": "",
|
||||
"control_url_up_stop": "",
|
||||
"control_url_down": "",
|
||||
"control_url_down_stop": "",
|
||||
"control_url_enable_nv": "",
|
||||
"control_url_disable_nv": "",
|
||||
"control_url_zoom_out": "",
|
||||
"control_url_zoom_out_stop": "",
|
||||
"control_url_zoom_in": "",
|
||||
"control_url_zoom_in_stop": "",
|
||||
"tv_channel": "0",
|
||||
"groups": "[]",
|
||||
"loglevel": "warning",
|
||||
"sqllog": "0",
|
||||
"detector_cascades": ""
|
||||
}),
|
||||
"shto": "[]",
|
||||
"shfr": "[]"
|
||||
}
|
||||
}
|
||||
$.aM.drawList=function(){
|
||||
e={list:$.aM.e.find('.follow-list ul'),html:''}
|
||||
$.aM.e.find('[section]:visible').each(function(n,v){
|
||||
e.e=$(v)
|
||||
e.id = e.e.attr('id');
|
||||
e.title = e.e.find('h4').first().html();
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = e.title;
|
||||
var elements = div.getElementsByTagName('a');
|
||||
while (elements[0])
|
||||
elements[0].parentNode.removeChild(elements[0])
|
||||
var elements = div.getElementsByTagName('small');
|
||||
while (elements[0])
|
||||
elements[0].parentNode.removeChild(elements[0])
|
||||
var repl = div.innerHTML;
|
||||
e.html += '<li><a class="scrollTo" href="#'+e.id+'" scrollToParent="#add_monitor .modal-body">'+repl+'</a></li>'
|
||||
})
|
||||
e.list.html(e.html)
|
||||
}
|
||||
$.aM.import=function(e){
|
||||
$.get($.ccio.init('location',$user)+$user.auth_token+'/hls/'+e.values.ke+'/'+e.values.mid+'/detectorStream.m3u8',function(data){
|
||||
$('#monEditBufferPreview').html(data)
|
||||
})
|
||||
$.aM.e.find('.edit_id').text(e.values.mid);
|
||||
$.aM.e.attr('mid',e.values.mid).attr('ke',e.values.ke).attr('auth',e.auth)
|
||||
$.each(e.values,function(n,v){
|
||||
$.aM.e.find('[name="'+n+'"]').val(v).change()
|
||||
})
|
||||
e.ss=JSON.parse(e.values.details);
|
||||
//get maps
|
||||
$.aM.maps.empty()
|
||||
if(e.ss.input_maps&&e.ss.input_maps!==''){
|
||||
var input_maps
|
||||
try{
|
||||
input_maps = JSON.parse(e.ss.input_maps)
|
||||
}catch(er){
|
||||
input_maps = e.ss.input_maps;
|
||||
}
|
||||
var mapContainers = $('[input-mapping]')
|
||||
if(input_maps.length>0){
|
||||
mapContainers.show()
|
||||
$.each(input_maps,function(n,v){
|
||||
var tempID = $.ccio.tm('input-map')
|
||||
var parent = $('#monSectionMap'+tempID)
|
||||
$.each(v,function(m,b){
|
||||
parent.find('[map-detail="'+m+'"]').val(b).change()
|
||||
})
|
||||
})
|
||||
}else{
|
||||
mapContainers.hide()
|
||||
}
|
||||
}
|
||||
//get channels
|
||||
$.aM.channels.empty()
|
||||
if(e.ss.stream_channels&&e.ss.stream_channels!==''){
|
||||
var stream_channels
|
||||
try{
|
||||
stream_channels = JSON.parse(e.ss.stream_channels)
|
||||
}catch(er){
|
||||
stream_channels = e.ss.stream_channels;
|
||||
}
|
||||
$.each(stream_channels,function(n,v){
|
||||
var tempID = $.ccio.tm('stream-channel')
|
||||
var parent = $('#monSectionChannel'+tempID)
|
||||
$.each(v,function(m,b){
|
||||
parent.find('[channel-detail="'+m+'"]').val(b)
|
||||
})
|
||||
})
|
||||
}
|
||||
//get map choices for outputs
|
||||
$('[input-mapping] .choices').empty()
|
||||
if(e.ss.input_map_choices&&e.ss.input_map_choices!==''){
|
||||
var input_map_choices
|
||||
try{
|
||||
input_map_choices = JSON.parse(e.ss.input_map_choices)
|
||||
}catch(er){
|
||||
input_map_choices = e.ss.input_map_choices;
|
||||
}
|
||||
$.each(input_map_choices,function(n,v){
|
||||
$.each(v,function(m,b){
|
||||
var parent = $('[input-mapping="'+n+'"] .choices')
|
||||
$.ccio.tm('input-map-selector',b,parent)
|
||||
})
|
||||
})
|
||||
}
|
||||
$.aM.e.find('[detail]').each(function(n,v){
|
||||
v=$(v).attr('detail');if(!e.ss[v]){e.ss[v]=''}
|
||||
})
|
||||
$.each(e.ss,function(n,v){
|
||||
var theVal = v;
|
||||
if(v instanceof Object){
|
||||
theVal = JSON.stringify(v);
|
||||
}
|
||||
$.aM.e.find('[detail="'+n+'"]').val(theVal).change();
|
||||
});
|
||||
$.each(e.ss,function(n,v){
|
||||
try{
|
||||
var variable=JSON.parse(v)
|
||||
}catch(err){
|
||||
var variable=v
|
||||
}
|
||||
if(variable instanceof Object){
|
||||
$('[detailContainer="'+n+'"][detailObject]').prop('checked',false)
|
||||
$('[detailContainer="'+n+'"][detailObject]').parents('.mdl-js-switch').removeClass('is-checked')
|
||||
if(variable instanceof Array){
|
||||
$.each(variable,function(m,b,parentOfObject){
|
||||
$('[detailContainer="'+n+'"][detailObject="'+b+'"]').prop('checked',true)
|
||||
parentOfObject=$('[detailContainer="'+n+'"][detailObject="'+b+'"]').parents('.mdl-js-switch')
|
||||
parentOfObject.addClass('is-checked')
|
||||
})
|
||||
}else{
|
||||
$.each(variable,function(m,b){
|
||||
if(typeof b ==='string'){
|
||||
$('[detailContainer="'+n+'"][detailObject="'+m+'"]').val(b).change()
|
||||
}else{
|
||||
$('[detailContainer="'+n+'"][detailObject="'+m+'"]').prop('checked',true)
|
||||
parentOfObject=$('[detailContainer="'+n+'"][detailObject="'+m+'"]').parents('.mdl-js-switch')
|
||||
parentOfObject.addClass('is-checked')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
try{
|
||||
$.each(['groups','group_detector'],function(m,b){
|
||||
var tmp=''
|
||||
$.each($user.mon_groups,function(n,v){
|
||||
tmp+='<li class="mdl-list__item">';
|
||||
tmp+='<span class="mdl-list__item-primary-content">';
|
||||
tmp+=v.name;
|
||||
tmp+='</span>';
|
||||
tmp+='<span class="mdl-list__item-secondary-action">';
|
||||
tmp+='<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">';
|
||||
tmp+='<input type="checkbox" '+b+' value="'+v.id+'" class="mdl-switch__input"';
|
||||
if(!e.ss[b]){
|
||||
e.ss[b]=[]
|
||||
}
|
||||
if(e.ss[b].indexOf(v.id)>-1){tmp+=' checked';}
|
||||
tmp+=' />';
|
||||
tmp+='</label>';
|
||||
tmp+='</span>';
|
||||
tmp+='</li>';
|
||||
})
|
||||
$('#monitor_'+b).html(tmp)
|
||||
})
|
||||
componentHandler.upgradeAllRegistered()
|
||||
}catch(er){
|
||||
console.log(er)
|
||||
//no group, this 'try' will be removed in future.
|
||||
};
|
||||
$('#copy_settings').val('0').change()
|
||||
var tmp = '';
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
if(v.ke === $user.ke){
|
||||
tmp += $.ccio.tm('option',{auth_token:$user.auth_token,id:v.mid,name:v.name},null,$user);
|
||||
}
|
||||
})
|
||||
$.aM.monitorsForCopy.find('optgroup').html(tmp)
|
||||
setTimeout(function(){$.aM.drawList()},1000)
|
||||
}
|
||||
//parse "Automatic" field in "Input" Section
|
||||
$.aM.e.on('change','.auto_host_fill input,.auto_host_fill select',function(e){
|
||||
var theSwitch = $.aM.e.find('[detail="auto_host_enable"]').val()
|
||||
if(!theSwitch||theSwitch===''){
|
||||
theSwitch='1'
|
||||
}
|
||||
if(theSwitch==='1'){
|
||||
return
|
||||
}
|
||||
if($.aM.e.find('[name="host"]').val() !== ''){
|
||||
$.aM.e.find('[detail="auto_host"]').val($.aM.buildMonitorURL())
|
||||
}
|
||||
})
|
||||
$.aM.e.on('change','[detail="auto_host"]',function(e){
|
||||
var isRTSP = false
|
||||
var inputType = $.aM.e.find('[name="type"]').val()
|
||||
var url = $(this).val()
|
||||
var theSwitch = $.aM.e.find('[detail="auto_host_enable"]')
|
||||
var disabled = theSwitch.val()
|
||||
if(!disabled||disabled===''){
|
||||
//if no value, then probably old version of monitor config. Set to Manual to avoid confusion.
|
||||
disabled='0'
|
||||
theSwitch.val('0').change()
|
||||
}
|
||||
if(disabled==='0'){
|
||||
return
|
||||
}
|
||||
if(inputType === 'local'){
|
||||
$.aM.e.find('[name="path"]').val(url).change()
|
||||
}else{
|
||||
var urlSplitByDots = url.split('.')
|
||||
var has = function(query,searchIn){if(!searchIn){searchIn=url;};return url.indexOf(query)>-1}
|
||||
var protocol = url.split('://')[0]
|
||||
console.log(url.split('://'))
|
||||
//switch RTSP, RTMP and RTMPS to parse URL
|
||||
if(has('rtsp://')){
|
||||
isRTSP = true;
|
||||
url = url.replace('rtsp://','http://')
|
||||
}
|
||||
if(has('rtmp://')){
|
||||
isRTMP = true;
|
||||
url = url.replace('rtmp://','http://')
|
||||
}
|
||||
if(has('rtmps://')){
|
||||
isRTMPS = true;
|
||||
url = url.replace('rtmps://','http://')
|
||||
}
|
||||
//parse URL
|
||||
var parsedURL = document.createElement('a');
|
||||
parsedURL.href = url;
|
||||
var pathname = parsedURL.pathname
|
||||
if(url.indexOf('?') > -1){
|
||||
pathname += '?'+url.split('?')[1]
|
||||
}
|
||||
$.aM.e.find('[name="protocol"]').val(protocol).change()
|
||||
if(isRTSP){
|
||||
$.aM.e.find('[detail="rtsp_transport"]').val('tcp').change()
|
||||
$.aM.e.find('[detail="aduration"]').val(1000000).change()
|
||||
$.aM.e.find('[detail="probesize"]').val(1000000).change()
|
||||
}
|
||||
$.aM.e.find('[detail="muser"]').val(parsedURL.username).change()
|
||||
$.aM.e.find('[detail="mpass"]').val(parsedURL.password).change()
|
||||
$.aM.e.find('[name="host"]').val(parsedURL.hostname).change()
|
||||
$.aM.e.find('[name="port"]').val(parsedURL.port).change()
|
||||
$.aM.e.find('[name="path"]').val(pathname).change()
|
||||
delete(parsedURL)
|
||||
}
|
||||
})
|
||||
$.aM.e.find('.refresh_cascades').click(function(e){
|
||||
$.ccio.cx({f:'ocv_in',data:{f:'refreshPlugins',ke:$user.ke}})
|
||||
})
|
||||
$.aM.f.submit(function(ee){
|
||||
ee.preventDefault();
|
||||
e={e:$(this)};
|
||||
e.s=e.e.serializeObject();
|
||||
e.er=[];
|
||||
$.each(e.s,function(n,v){e.s[n]=v.trim()});
|
||||
e.s.mid=e.s.mid.replace(/[^\w\s]/gi,'').replace(/ /g,'')
|
||||
if(e.s.mid.length<3){e.er.push('Monitor ID too short')}
|
||||
if(e.s.port==''){
|
||||
if(e.s.protocol === 'https'){
|
||||
e.s.port = 443
|
||||
}else{
|
||||
e.s.port = 80
|
||||
}
|
||||
}
|
||||
if(e.s.name==''){e.er.push('Monitor Name cannot be blank')}
|
||||
// if(e.s.protocol=='rtsp'){e.s.ext='mp4',e.s.type='rtsp'}
|
||||
if(e.er.length>0){
|
||||
$.sM.e.find('.msg').html(e.er.join('<br>'));
|
||||
$.ccio.init('note',{title:'Configuration Invalid',text:e.er.join('<br>'),type:'error'});
|
||||
return;
|
||||
}
|
||||
$.post($.ccio.init('location',$user)+$user.auth_token+'/configureMonitor/'+$user.ke+'/'+e.s.mid,{data:JSON.stringify(e.s)},function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
//
|
||||
if($('#copy_settings').val() === '1'){
|
||||
e.s.details = JSON.parse(e.s.details);
|
||||
var copyMonitors = $.aM.monitorsForCopy.val();
|
||||
var chosenSections = [];
|
||||
var chosenMonitors = {};
|
||||
|
||||
if(!copyMonitors||copyMonitors.length===0){
|
||||
$.ccio.init('note',{title:lang['No Monitors Selected'],text:lang.monSavedButNotCopied})
|
||||
return
|
||||
}
|
||||
|
||||
$.aM.e.find('[copy]').each(function(n,v){
|
||||
var el = $(v)
|
||||
if(el.val() === '1'){
|
||||
chosenSections.push(el.attr('copy'))
|
||||
}
|
||||
})
|
||||
var alterSettings = function(settingsToAlter,monitor){
|
||||
monitor.details = JSON.parse(monitor.details);
|
||||
$.aM.e.find(settingsToAlter).find('input,select,textarea').each(function(n,v){
|
||||
var el = $(v);
|
||||
var name = el.attr('name')
|
||||
var detail = el.attr('detail')
|
||||
var value
|
||||
switch(true){
|
||||
case !!name:
|
||||
var value = e.s[name]
|
||||
monitor[name] = value;
|
||||
break;
|
||||
case !!detail:
|
||||
detail = detail.replace('"','')
|
||||
var value = e.s.details[detail]
|
||||
monitor.details[detail] = value;
|
||||
break;
|
||||
}
|
||||
})
|
||||
monitor.details = JSON.stringify(monitor.details);
|
||||
return monitor;
|
||||
}
|
||||
$.each(copyMonitors,function(n,id){
|
||||
var monitor
|
||||
if(id === '$New'){
|
||||
monitor = $.aM.generateDefaultMonitorSettings();
|
||||
//connection
|
||||
monitor.name = e.s.name+' - '+monitor.mid
|
||||
monitor.type = e.s.type
|
||||
monitor.protocol = e.s.protocol
|
||||
monitor.host = e.s.host
|
||||
monitor.port = e.s.port
|
||||
monitor.path = e.s.path
|
||||
monitor.details.fatal_max = e.s.details.fatal_max
|
||||
monitor.details.port_force = e.s.details.port_force
|
||||
monitor.details.muser = e.s.details.muser
|
||||
monitor.details.password = e.s.details.password
|
||||
monitor.details.rtsp_transport = e.s.details.rtsp_transport
|
||||
monitor.details.auto_host = e.s.details.auto_host
|
||||
monitor.details.auto_host_enable = e.s.details.auto_host_enable
|
||||
//input
|
||||
monitor.details.aduration = e.s.details.aduration
|
||||
monitor.details.probesize = e.s.details.probesize
|
||||
monitor.details.stream_loop = e.s.details.stream_loop
|
||||
monitor.details.sfps = e.s.details.sfps
|
||||
monitor.details.accelerator = e.s.details.accelerator
|
||||
monitor.details.hwaccel = e.s.details.hwaccel
|
||||
monitor.details.hwaccel_vcodec = e.s.details.hwaccel_vcodec
|
||||
monitor.details.hwaccel_device = e.s.details.hwaccel_device
|
||||
}else{
|
||||
monitor = Object.assign({},$.ccio.init('cleanMon',$.ccio.mon[$user.ke+id+$user.auth_token]));
|
||||
}
|
||||
$.each(chosenSections,function(n,section){
|
||||
monitor = alterSettings(section,monitor)
|
||||
})
|
||||
console.log(monitor)
|
||||
$.post($.ccio.init('location',$user)+$user.auth_token+'/configureMonitor/'+$user.ke+'/'+monitor.mid,{data:JSON.stringify(monitor)},function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
chosenMonitors[monitor.mid] = monitor;
|
||||
})
|
||||
console.log(chosenMonitors)
|
||||
}
|
||||
|
||||
$.aM.e.modal('hide')
|
||||
return false;
|
||||
});
|
||||
//////////////////
|
||||
//Input Map (Feed)
|
||||
$.aM.mapPlacementInit = function(){
|
||||
$('.input-map').each(function(n,v){
|
||||
var _this = $(this)
|
||||
_this.find('.place').text(n+1)
|
||||
})
|
||||
}
|
||||
$.aM.mapSave = function(){
|
||||
var e={};
|
||||
var mapContainers = $('[input-mapping]');
|
||||
var stringForSave={}
|
||||
mapContainers.each(function(q,t){
|
||||
var mapRowElement = $(t).find('.map-row');
|
||||
var mapRow = []
|
||||
mapRowElement.each(function(n,v){
|
||||
var map={}
|
||||
$.each($(v).find('[map-input]'),function(m,b){
|
||||
map[$(b).attr('map-input')]=$(b).val()
|
||||
});
|
||||
mapRow.push(map)
|
||||
});
|
||||
stringForSave[$(t).attr('input-mapping')] = mapRow;
|
||||
});
|
||||
$.aM.e.find('[detail="input_map_choices"]').val(JSON.stringify(stringForSave)).change();
|
||||
}
|
||||
$.aM.maps.on('click','.delete',function(){
|
||||
$(this).parents('.input-map').remove()
|
||||
var inputs = $('[map-detail]')
|
||||
var mapContainers = $('[input-mapping]');
|
||||
if(inputs.length===0){
|
||||
$.aM.e.find('[detail="input_maps"]').val('[]').change()
|
||||
mapContainers.hide();
|
||||
}else{
|
||||
inputs.first().change()
|
||||
mapContainers.show();
|
||||
}
|
||||
$.aM.mapPlacementInit()
|
||||
})
|
||||
$.aM.e.on('change','[map-detail]',function(){
|
||||
var e={};
|
||||
e.e=$.aM.maps.find('.input-map')
|
||||
e.s=[]
|
||||
e.e.each(function(n,v){
|
||||
var map={}
|
||||
$.each($(v).find('[map-detail]'),function(m,b){
|
||||
map[$(b).attr('map-detail')]=$(b).val()
|
||||
});
|
||||
e.s.push(map)
|
||||
});
|
||||
$.aM.e.find('[detail="input_maps"]').val(JSON.stringify(e.s)).change()
|
||||
})
|
||||
$.aM.e.on('click','[input-mapping] .add_map_row',function(){
|
||||
$.ccio.tm('input-map-selector',{},$(this).parents('[input-mapping]').find('.choices'))
|
||||
$.aM.mapSave()
|
||||
})
|
||||
$.aM.e.on('click','[input-mapping] .delete_map_row',function(){
|
||||
$(this).parents('.map-row').remove()
|
||||
$.aM.mapSave()
|
||||
})
|
||||
$.aM.e.on('change','[map-input]',function(){
|
||||
$.aM.mapSave()
|
||||
})
|
||||
//////////////////
|
||||
//Stream Channels
|
||||
$.aM.channelSave = function(){
|
||||
var e={};
|
||||
e.e=$.aM.channels.find('.stream-channel')
|
||||
e.s=[]
|
||||
e.e.each(function(n,v){
|
||||
var channel={}
|
||||
$.each($(v).find('[channel-detail]'),function(m,b){
|
||||
channel[$(b).attr('channel-detail')]=$(b).val()
|
||||
});
|
||||
e.s.push(channel)
|
||||
});
|
||||
$.aM.e.find('[detail="stream_channels"]').val(JSON.stringify(e.s)).change()
|
||||
}
|
||||
$.aM.channelPlacementInit = function(){
|
||||
$('.stream-channel').each(function(n,v){
|
||||
var _this = $(this)
|
||||
_this.attr('stream-channel',n)
|
||||
_this.find('.place').text(n)
|
||||
_this.find('[input-mapping]').attr('input-mapping','stream_channel-'+n)
|
||||
$.aM.mapSave()
|
||||
})
|
||||
}
|
||||
$.aM.buildMonitorURL = function(){
|
||||
var e={};
|
||||
e.user=$.aM.e.find('[detail="muser"]').val();
|
||||
e.pass=$.aM.e.find('[detail="mpass"]').val();
|
||||
e.host=$.aM.e.find('[name="host"]').val();
|
||||
e.protocol=$.aM.e.find('[name="protocol"]').val();
|
||||
e.port=$.aM.e.find('[name="port"]').val();
|
||||
e.path=$.aM.e.find('[name="path"]').val();
|
||||
if($.aM.e.find('[name="type"]').val()==='local'){
|
||||
e.url=e.path;
|
||||
}else{
|
||||
if(e.host.indexOf('@')===-1&&e.user!==''){
|
||||
e.host=e.user+':'+e.pass+'@'+e.host;
|
||||
}
|
||||
e.url=$.ccio.init('url',e)+e.path;
|
||||
}
|
||||
return e.url
|
||||
}
|
||||
$.aM.channels.on('click','.delete',function(){
|
||||
$(this).parents('.stream-channel').remove()
|
||||
$.aM.channelSave()
|
||||
$.aM.channelPlacementInit()
|
||||
})
|
||||
$.aM.e.on('change','[channel-detail]',function(){
|
||||
$.aM.channelSave()
|
||||
})
|
||||
//////////////////
|
||||
$.aM.e.on('change','[groups]',function(){
|
||||
var e={};
|
||||
e.e=$.aM.e.find('[groups]:checked');
|
||||
e.s=[];
|
||||
e.e.each(function(n,v){
|
||||
e.s.push($(v).val())
|
||||
});
|
||||
$.aM.e.find('[detail="groups"]').val(JSON.stringify(e.s)).change()
|
||||
})
|
||||
$.aM.e.on('change','.detector_cascade_selection',function(){
|
||||
var e={};
|
||||
e.e=$.aM.e.find('.detector_cascade_selection:checked');
|
||||
e.s={};
|
||||
e.e.each(function(n,v){
|
||||
e.s[$(v).val()]={}
|
||||
});
|
||||
$.aM.e.find('[detail="detector_cascades"]').val(JSON.stringify(e.s)).change()
|
||||
})
|
||||
//$.aM.e.on('change','.detector_cascade_selection',function(){
|
||||
// var e={};
|
||||
// e.details=$.aM.e.find('[name="details"]')
|
||||
// try{
|
||||
// e.detailsVal=JSON.parse(e.details.val())
|
||||
// }catch(err){
|
||||
// e.detailsVal={}
|
||||
// }
|
||||
// e.detailsVal.detector_cascades=[];
|
||||
// e.e=$.aM.e.find('.detector_cascade_selection:checked');
|
||||
// e.e.each(function(n,v){
|
||||
// e.detailsVal.detector_cascades.push($(v).val())
|
||||
// });
|
||||
// e.details.val(JSON.stringify(e.detailsVal))
|
||||
//})
|
||||
$.aM.e.find('.probe_config').click(function(){
|
||||
$.pB.e.find('[name="url"]').val($.aM.buildMonitorURL());
|
||||
$.pB.f.submit();
|
||||
$.pB.e.modal('show');
|
||||
})
|
||||
$.aM.e.find('.import_config').click(function(e){
|
||||
var e={};e.e=$(this);e.mid=e.e.parents('[mid]').attr('mid');
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Import Monitor Configuration'])
|
||||
e.html=lang.ImportMonitorConfigurationText+'<div style="margin-top:15px"><div class="form-group"><textarea placeholder="'+lang['Paste JSON here.']+'" class="form-control"></textarea></div><label class="upload_file btn btn-primary btn-block"> Upload File <input class="upload" type=file name="files[]"></label></div>';
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.e.find('.upload').change(function(e){
|
||||
var files = e.target.files; // FileList object
|
||||
f = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(ee) {
|
||||
$.confirm.e.find('textarea').val(ee.target.result);
|
||||
}
|
||||
reader.readAsText(f);
|
||||
});
|
||||
$.confirm.click({title:'Import',class:'btn-primary'},function(){
|
||||
try{
|
||||
e.values=JSON.parse($.confirm.e.find('textarea').val());
|
||||
$.aM.import(e)
|
||||
$.aM.e.modal('show')
|
||||
}catch(err){
|
||||
$.ccio.log(err)
|
||||
$.ccio.init('note',{title:lang['Invalid JSON'],text:lang.InvalidJSONText,type:'error'})
|
||||
}
|
||||
});
|
||||
});
|
||||
$.aM.e.find('.save_config').click(function(e){
|
||||
var e={};e.e=$(this);e.mid=e.e.parents('[mid]').attr('mid');e.s=$.aM.f.serializeObject();
|
||||
if(!e.mid||e.mid===''){
|
||||
e.mid='NewMonitor'
|
||||
}
|
||||
e.dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(e.s));
|
||||
$('#temp').html('<a></a>')
|
||||
.find('a')
|
||||
.attr('href',e.dataStr)
|
||||
.attr('download','Shinobi_'+e.mid+'_config.json')
|
||||
[0].click()
|
||||
});
|
||||
$.aM.e.find('.add_map').click(function(e){
|
||||
$('[input-mapping]').show()
|
||||
$.ccio.tm('input-map')
|
||||
});
|
||||
$.aM.e.find('.add_channel').click(function(e){
|
||||
$.ccio.tm('stream-channel')
|
||||
});
|
||||
$.aM.f.find('[detail="stream_type"]').change(function(e){
|
||||
e.e=$(this);
|
||||
if(e.e.val()==='jpeg'){$.aM.f.find('[detail="snap"]').val('1').change()}
|
||||
})
|
||||
$.aM.f.find('[name="type"]').change(function(e){
|
||||
e.e=$(this);
|
||||
if(e.e.val()==='h264'){$.aM.f.find('[name="protocol"]').val('rtsp').change()}
|
||||
})
|
||||
$.aM.md=$.aM.f.find('[detail]');
|
||||
$.aM.md.change($.ccio.form.details)
|
||||
$.aM.f.on('change','[selector]',function(){
|
||||
e={e:$(this)}
|
||||
e.v=e.e.val();
|
||||
e.a=e.e.attr('selector')
|
||||
e.triggerChange=e.e.attr('triggerchange')
|
||||
e.triggerChangeIgnore=e.e.attr('triggerChangeIgnore')
|
||||
$.aM.f.find('.'+e.a+'_input').hide()
|
||||
$.aM.f.find('.'+e.a+'_'+e.v).show();
|
||||
$.aM.f.find('.'+e.a+'_text').text($(this).find('option:selected').text())
|
||||
if(e.triggerChange && e.triggerChange !== '' && !e.triggerChangeIgnore || (e.triggerChangeIgnore && e.triggerChangeIgnore.split(',').indexOf(e.v) === -1)){
|
||||
console.log(e.triggerChange)
|
||||
$(e.triggerChange).trigger('change')
|
||||
}
|
||||
$.aM.drawList()
|
||||
});
|
||||
$.aM.f.find('[name="type"]').change(function(e){
|
||||
e.e=$(this);
|
||||
e.v=e.e.val();
|
||||
e.h=$.aM.f.find('[name="path"]');
|
||||
e.p=e.e.parents('.form-group');
|
||||
switch(e.v){
|
||||
case'local':case'socket':
|
||||
e.h.attr('placeholder','/dev/video0')
|
||||
break;
|
||||
default:
|
||||
e.h.attr('placeholder','/videostream.cgi?1')
|
||||
break;
|
||||
}
|
||||
});
|
||||
})
|
|
@ -0,0 +1,192 @@
|
|||
$(document).ready(function(e){
|
||||
//multi monitor manager
|
||||
$.multimon={e:$('#multi_mon')};
|
||||
$.multimon.table=$.multimon.e.find('.tableData tbody');
|
||||
$.multimon.f=$.multimon.e.find('form');
|
||||
$.multimon.f.on('change','#multimon_select_all',function(e){
|
||||
e.e=$(this);
|
||||
e.p=e.e.prop('checked')
|
||||
e.a=$.multimon.f.find('input[type=checkbox][name]')
|
||||
if(e.p===true){
|
||||
e.a.prop('checked',true)
|
||||
}else{
|
||||
e.a.prop('checked',false)
|
||||
}
|
||||
})
|
||||
$.multimon.e.find('.import_config').click(function(){
|
||||
var e={};e.e=$(this);e.mid=e.e.parents('[mid]').attr('mid');
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Import Monitor Configuration'])
|
||||
e.html=lang.ImportMultiMonitorConfigurationText+'<div style="margin-top:15px"><div class="form-group"><textarea placeholder="'+lang['Paste JSON here.']+'" class="form-control"></textarea></div><label class="upload_file btn btn-primary btn-block"> Upload File <input class="upload" type=file name="files[]"></label></div>';
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.e.find('.upload').change(function(e){
|
||||
var files = e.target.files; // FileList object
|
||||
f = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(ee) {
|
||||
$.confirm.e.find('textarea').val(ee.target.result);
|
||||
}
|
||||
reader.readAsText(f);
|
||||
});
|
||||
$.confirm.click({title:'Import',class:'btn-primary'},function(){
|
||||
// setTimeout(function(){
|
||||
// $.confirm.e.modal('show');
|
||||
// },1000)
|
||||
// $.confirm.title.text(lang['Are you sure?'])
|
||||
// $.confirm.body.html(lang.ImportMultiMonitorConfigurationText)
|
||||
// $.confirm.click({title:'Save Set',class:'btn-danger'},function(){
|
||||
try{
|
||||
var postMonitor = function(v){
|
||||
$.post($.ccio.init('location',$user)+$user.auth_token+'/configureMonitor/'+$user.ke+'/'+v.mid,{data:JSON.stringify(v,null,3)},function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
}
|
||||
var parseZmMonitor = function(Monitor){
|
||||
console.log(Monitor)
|
||||
var newMon = $.aM.generateDefaultMonitorSettings()
|
||||
newMon.details = JSON.parse(newMon.details)
|
||||
newMon.details.stream_type = 'jpeg'
|
||||
switch(Monitor.Type.toLowerCase()){
|
||||
case'ffmpeg':case'libvlc':
|
||||
newMon.details.auto_host_enable = '1'
|
||||
newMon.details.auto_host = Monitor.Path
|
||||
if(newMon.auto_host.indexOf('rtsp://') > -1 || newMon.auto_host.indexOf('rtmp://') > -1 || newMon.auto_host.indexOf('rtmps://') > -1){
|
||||
newMon.type = 'h264'
|
||||
}else{
|
||||
$.ccio.init('note',{title:lang['Please Check Your Settings'],text:lang.migrateText1,type:'error'})
|
||||
}
|
||||
break;
|
||||
case'local':
|
||||
newMon.details.auto_host = Monitor.Device
|
||||
break;
|
||||
case'remote':
|
||||
|
||||
break;
|
||||
}
|
||||
newMon.details = JSON.stringify(newMon.details)
|
||||
console.log(newMon)
|
||||
return newMon
|
||||
}
|
||||
parsedData=JSON.parse($.confirm.e.find('textarea').val());
|
||||
//zoneminder one monitor
|
||||
if(parsedData.monitor){
|
||||
$.aM.import({
|
||||
values : parseZmMonitor(parsedData.monitor.Monitor)
|
||||
})
|
||||
$.aM.e.modal('show')
|
||||
}else
|
||||
//zoneminder multiple monitors
|
||||
if(parsedData.monitors){
|
||||
$.each(parsedData.monitors,function(n,v){
|
||||
$.aM.import({
|
||||
values : parseZmMonitor(parsedData.Monitor)
|
||||
})
|
||||
parseZmMonitor(v.Monitor)
|
||||
})
|
||||
}else
|
||||
//shinobi one monitor
|
||||
if(parsedData.mid){
|
||||
postMonitor(parsedData)
|
||||
}else
|
||||
//shinobi multiple monitors
|
||||
if(parsedData[0] && parsedData[0].mid){
|
||||
$.each(parsedData,function(n,v){
|
||||
postMonitor(v)
|
||||
})
|
||||
}
|
||||
}catch(err){
|
||||
$.ccio.log(err)
|
||||
$.ccio.init('note',{title:lang['Invalid JSON'],text:lang.InvalidJSONText,type:'error'})
|
||||
}
|
||||
// });
|
||||
});
|
||||
})
|
||||
$.multimon.getSelectedMonitors = function(unclean){
|
||||
var arr=[];
|
||||
if(unclean === true){
|
||||
var monitors = $.ccio.mon
|
||||
}else{
|
||||
var monitors = $.ccio.init('cleanMons','object')
|
||||
}
|
||||
$.each($.multimon.f.serializeObject(),function(n,v){
|
||||
arr.push(monitors[n])
|
||||
})
|
||||
return arr;
|
||||
}
|
||||
$.multimon.e.find('.delete').click(function(){
|
||||
var arr=$.multimon.getSelectedMonitors(true);
|
||||
if(arr.length===0){
|
||||
$.ccio.init('note',{title:'No Monitors Selected',text:'Select atleast one monitor to delete.',type:'error'});
|
||||
return
|
||||
}
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete']+' '+lang['Monitors'])
|
||||
e.html='<p>'+lang.DeleteMonitorsText+'</p>';
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click([
|
||||
{
|
||||
title:'Delete Monitors',
|
||||
class:'btn-danger',
|
||||
callback:function(){
|
||||
$.each(arr,function(n,v){
|
||||
$.get($.ccio.init('location',$user)+v.user.auth_token+'/configureMonitor/'+v.ke+'/'+v.mid+'/delete',function(data){
|
||||
console.log(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title:'Delete Monitors and Files',
|
||||
class:'btn-danger',
|
||||
callback:function(){
|
||||
$.each(arr,function(n,v){
|
||||
$.get($.ccio.init('location',$user)+v.user.auth_token+'/configureMonitor/'+v.ke+'/'+v.mid+'/delete?deleteFiles=true',function(data){
|
||||
console.log(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
]);
|
||||
})
|
||||
//$.multimon.e.find('.edit_all').click(function(){
|
||||
// var arr=$.multimon.getSelectedMonitors();
|
||||
// var arrObject={}
|
||||
// if(arr.length===0){
|
||||
// $.ccio.init('note',{title:'No Monitors Selected',text:'Select atleast one monitor to delete.',type:'error'});
|
||||
// return
|
||||
// }
|
||||
// $.multimonedit.selectedList = arr;
|
||||
// $.multimonedit.e.modal('show')
|
||||
//})
|
||||
$.multimon.e.find('.save_config').click(function(){
|
||||
var e={};e.e=$(this);
|
||||
var arr=$.multimon.getSelectedMonitors();
|
||||
if(arr.length===0){
|
||||
$.ccio.init('note',{title:'No Monitors Selected',text:'Select atleast one monitor to delete.',type:'error'});
|
||||
return
|
||||
}
|
||||
e.dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(arr));
|
||||
$('#temp').html('<a></a>')
|
||||
.find('a')
|
||||
.attr('href',e.dataStr)
|
||||
.attr('download','Shinobi_Monitors_'+(new Date())+'.json')
|
||||
[0].click()
|
||||
})
|
||||
$.multimon.e.on('shown.bs.modal',function() {
|
||||
var tmp=''
|
||||
$.each($.ccio.mon,function(n,v){
|
||||
var streamURL = $.ccio.init('streamURL',v)
|
||||
if(streamURL!=='Websocket'&&v.mode!==('idle'&&'stop')){
|
||||
streamURL='<a target="_blank" href="'+streamURL+'">'+streamURL+'</a>'
|
||||
}
|
||||
var img = $('#left_menu [mid="'+v.mid+'"][auth="'+v.user.auth_token+'"] [monitor="watch"]').attr('src')
|
||||
tmp+='<tr mid="'+v.mid+'" ke="'+v.ke+'" auth="'+v.user.auth_token+'">'
|
||||
tmp+='<td><div class="checkbox"><input id="multimonCheck_'+v.ke+v.mid+v.user.auth_token+'" type="checkbox" name="'+v.ke+v.mid+v.user.auth_token+'" value="1"><label for="multimonCheck_'+v.ke+v.mid+v.user.auth_token+'"></label></div></td>'
|
||||
tmp+='<td><a monitor="watch"><img class="small-square-img" src="'+img+'"></a></td><td>'+v.name+'<br><small>'+v.mid+'</small></td><td class="monitor_status">'+v.status+'</td><td>'+streamURL+'</td>'
|
||||
//buttons
|
||||
tmp+='<td class="text-right"><a title="'+lang.Pop+'" monitor="pop" class="btn btn-primary"><i class="fa fa-external-link"></i></a> <a title="'+lang.Calendar+'" monitor="calendar" class="btn btn-default"><i class="fa fa-calendar"></i></a> <a title="'+lang['Power Viewer']+'" class="btn btn-default" monitor="powerview"><i class="fa fa-map-marker"></i></a> <a title="'+lang['Time-lapse']+'" class="btn btn-default" monitor="timelapse"><i class="fa fa-angle-double-right"></i></a> <a title="'+lang['Videos List']+'" monitor="videos_table" class="btn btn-default"><i class="fa fa-film"></i></a> <a title="'+lang['Monitor Settings']+'" class="btn btn-default" monitor="edit"><i class="fa fa-wrench"></i></a></td>'
|
||||
tmp+='</tr>'
|
||||
})
|
||||
$.multimon.table.html(tmp)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,60 @@
|
|||
$(document).ready(function(e){
|
||||
//onvif probe
|
||||
$.oB={
|
||||
e:$('#onvif_probe'),
|
||||
v:$('#onvif_video'),
|
||||
};
|
||||
$.oB.f=$.oB.e.find('form');$.oB.o=$.oB.e.find('.output_data');
|
||||
$.oB.f.submit(function(ee){
|
||||
ee.preventDefault();
|
||||
e={};
|
||||
$.oB.foundMonitors={}
|
||||
e.e=$(this),e.s=e.e.serializeObject();
|
||||
$.oB.o.empty();
|
||||
$.oB.e.find('._loading').show()
|
||||
$.oB.e.find('[type="submit"]').prop('disabled',true)
|
||||
$.ccio.cx({f:'onvif',ip:e.s.ip,port:e.s.port,user:e.s.user,pass:e.s.pass})
|
||||
clearTimeout($.oB.checkTimeout)
|
||||
$.oB.checkTimeout=setTimeout(function(){
|
||||
if($.oB.o.find('tr').length===0){
|
||||
$.oB.e.find('._loading').hide()
|
||||
$.oB.e.find('[type="submit"]').prop('disabled',false)
|
||||
$.oB.o.append('<td class="text-center _notfound">Sorry, nothing was found.</td>')
|
||||
}
|
||||
},5000)
|
||||
return false;
|
||||
});
|
||||
$.oB.e.on('click','.copy',function(){
|
||||
$('.hidden-xs [monitor="edit"]').click();
|
||||
e={};
|
||||
e.e = $(this).parents('[onvif_row]');
|
||||
var id = e.e.attr('onvif_row');
|
||||
var onvifRecord = $.oB.foundMonitors[id];
|
||||
var streamURL = onvifRecord.uri;
|
||||
if($.oB.e.find('[name="user"]').val()!==''){
|
||||
streamURL = streamURL.split('://')
|
||||
streamURL = streamURL[0]+'://'+$.oB.e.find('[name="user"]').val()+':'+$.oB.e.find('[name="pass"]').val()+'@'+streamURL[1];
|
||||
}
|
||||
$.aM.e.find('[detail="auto_host"]').val(streamURL).change()
|
||||
$.aM.e.find('[name="mode"]').val('start')
|
||||
$.oB.e.modal('hide')
|
||||
})
|
||||
$.oB.e.find('[name="ip"]').change(function(e){
|
||||
$.ccio.op('onvif_probe_ip',$(this).val());
|
||||
})
|
||||
if($.ccio.op().onvif_probe_ip){
|
||||
$.oB.e.find('[name="ip"]').val($.ccio.op().onvif_probe_ip)
|
||||
}
|
||||
$.oB.e.find('[name="port"]').change(function(e){
|
||||
$.ccio.op('onvif_probe_port',$(this).val());
|
||||
})
|
||||
if($.ccio.op().onvif_probe_port){
|
||||
$.oB.e.find('[name="port"]').val($.ccio.op().onvif_probe_port)
|
||||
}
|
||||
$.oB.e.find('[name="user"]').change(function(e){
|
||||
$.ccio.op('onvif_probe_user',$(this).val());
|
||||
})
|
||||
if($.ccio.op().onvif_probe_user){
|
||||
$.oB.e.find('[name="user"]').val($.ccio.op().onvif_probe_user)
|
||||
}
|
||||
})
|
|
@ -0,0 +1,298 @@
|
|||
$(document).ready(function(e){
|
||||
//POWER videos window
|
||||
$.pwrvid={e:$('#pvideo_viewer')};
|
||||
$.pwrvid.f=$.pwrvid.e.find('form'),
|
||||
$.pwrvid.d=$('#vis_pwrvideo'),
|
||||
$.pwrvid.mL=$('#motion_list'),
|
||||
$.pwrvid.m=$('#vis_monitors'),
|
||||
$.pwrvid.lv=$('#live_view'),
|
||||
$.pwrvid.dr=$('#pvideo_daterange'),
|
||||
$.pwrvid.vp=$('#video_preview'),
|
||||
$.pwrvid.seekBar=$('#pwrvid_seekBar'),
|
||||
$.pwrvid.seekBarProgress=$.pwrvid.seekBar.find('.progress-bar'),
|
||||
$.pwrvid.playRate = 1;
|
||||
$.pwrvid.dr.daterangepicker({
|
||||
startDate:$.ccio.timeObject().subtract(moment.duration("24:00:00")),
|
||||
endDate:$.ccio.timeObject().add(moment.duration("24:00:00")),
|
||||
timePicker: true,
|
||||
timePicker24Hour: true,
|
||||
timePickerSeconds: true,
|
||||
timePickerIncrement: 30,
|
||||
locale: {
|
||||
format: 'MM/DD/YYYY h:mm A'
|
||||
}
|
||||
},function(start, end, label){
|
||||
$.pwrvid.drawTimeline()
|
||||
$.pwrvid.dr.focus()
|
||||
});
|
||||
$('#pvideo_show_events').change(function(){
|
||||
$.pwrvid.drawTimeline()
|
||||
})
|
||||
$.pwrvid.e.on('click','[preview]',function(e){
|
||||
e.e=$(this);
|
||||
e.video=$.pwrvid.vp.find('video')[0];
|
||||
if(e.video){
|
||||
e.duration=e.video.duration;
|
||||
e.now=e.video.currentTime;
|
||||
}
|
||||
if($.pwrvid.video){
|
||||
clearInterval($.pwrvid.video.interval);
|
||||
}
|
||||
switch(e.e.attr('preview')){
|
||||
case'fullscreen':
|
||||
$.ccio.init('fullscreen',e.video)
|
||||
break;
|
||||
case'mute':
|
||||
e.video.muted = !e.video.muted
|
||||
e.e.find('i').toggleClass('fa-volume-off fa-volume-up')
|
||||
e.e.toggleClass('btn-danger')
|
||||
break;
|
||||
case'play':
|
||||
e.video.playbackRate = 1;
|
||||
$.pwrvid.vpOnPlayPause(1)
|
||||
break;
|
||||
case'stepFrontFront':
|
||||
e.add=e.e.attr('add')
|
||||
e.stepFrontFront=parseInt(e.e.attr('stepFrontFront'))
|
||||
if(!e.stepFrontFront||isNaN(e.stepFrontFront)){e.stepFrontFront = 5}
|
||||
if(e.add==="0"){
|
||||
$.pwrvid.playRate = e.stepFrontFront
|
||||
}else{
|
||||
$.pwrvid.playRate += e.stepFrontFront
|
||||
}
|
||||
e.video.playbackRate = $.pwrvid.playRate;
|
||||
e.video.play()
|
||||
break;
|
||||
case'stepFront':
|
||||
e.video.currentTime += 1;
|
||||
e.video.pause()
|
||||
break;
|
||||
case'stepBackBack':
|
||||
$.pwrvid.video.interval = setInterval(function(){
|
||||
e.video.playbackRate = 1.0;
|
||||
if(e.video.currentTime == 0){
|
||||
clearInterval($.pwrvid.video.interval);
|
||||
e.video.pause();
|
||||
}
|
||||
else{
|
||||
e.video.currentTime += -.2;
|
||||
}
|
||||
},30);
|
||||
break;
|
||||
case'stepBack':
|
||||
e.video.currentTime += -1;
|
||||
e.video.pause()
|
||||
break;
|
||||
case'video':
|
||||
// e.preventDefault();
|
||||
e.p=e.e.parents('[mid]');
|
||||
e.filename=e.p.attr('file');
|
||||
$.pwrvid.vp.find('h3').text(e.filename)
|
||||
e.href=e.e.attr('href');
|
||||
e.status=e.p.attr('status');
|
||||
e.mon=$.ccio.mon[e.p.attr('ke')+e.p.attr('mid')+$user.auth_token];
|
||||
$.pwrvid.vp.find('.holder').html('<video class="video_video" video="'+e.href+'"><source src="'+e.href+'" type="video/'+e.mon.ext+'"></video>');
|
||||
$.pwrvid.vp
|
||||
.attr('mid',e.mon.mid)
|
||||
.attr('mid',e.mon.user.auth_token)
|
||||
.attr('ke',e.mon.ke)
|
||||
.attr('status',e.status)
|
||||
.attr('file',e.filename)
|
||||
.find('[download],[video="download"]')
|
||||
.attr('download',e.filename)
|
||||
.attr('href',e.href)
|
||||
$.pwrvid.vp.find('video').off('loadeddata').on('loadeddata',function(){
|
||||
$.pwrvid.vp.find('.stream-objects .stream-detected-object').remove()
|
||||
})
|
||||
if(e.status==1){
|
||||
$.get($.ccio.init('videoHrefToRead',e.href),function(d){
|
||||
|
||||
})
|
||||
}
|
||||
var labels=[]
|
||||
var Dataset1=[]
|
||||
var events=$.pwrvid.currentDataObject[e.filename].motion
|
||||
var eventsLabeledByTime={}
|
||||
$.each(events,function(n,v){
|
||||
if(!v.details.confidence){v.details.confidence=0}
|
||||
var time=$.ccio.timeObject(v.time).format('MM/DD/YYYY HH:mm:ss')
|
||||
labels.push(time)
|
||||
Dataset1.push(v.details.confidence)
|
||||
eventsLabeledByTime[time]=v;
|
||||
})
|
||||
if(events.length>0){
|
||||
$.pwrvid.mL.html("<canvas></canvas>")
|
||||
var timeFormat = 'MM/DD/YYYY HH:mm:ss';
|
||||
var color = Chart.helpers.color;
|
||||
Chart.defaults.global.defaultFontColor = '#fff';
|
||||
var config = {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
type: 'line',
|
||||
label: 'Motion Confidence',
|
||||
backgroundColor: color(window.chartColors.red).alpha(0.2).rgbString(),
|
||||
borderColor: window.chartColors.red,
|
||||
data: Dataset1,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
title: {
|
||||
fontColor: "white",
|
||||
text:"Events in this video"
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
display: true,
|
||||
time: {
|
||||
format: timeFormat,
|
||||
// round: 'day'
|
||||
}
|
||||
}],
|
||||
},
|
||||
}
|
||||
};
|
||||
var ctx = $.pwrvid.mL.find('canvas')[0].getContext("2d");
|
||||
$.pwrvid.miniChart = new Chart(ctx, config);
|
||||
$.pwrvid.mL.find('canvas').click(function(f) {
|
||||
var target = $.pwrvid.miniChart.getElementsAtEvent(f)[0];
|
||||
if(!target){return false}
|
||||
var video = $.pwrvid.currentDataObject[e.filename];
|
||||
var event = video.motion[target._index];
|
||||
var video1 = $('#video_preview video')[0];
|
||||
video1.currentTime=$.ccio.timeObject(event.time).diff($.ccio.timeObject(video.row.time),'seconds')
|
||||
video1.play()
|
||||
});
|
||||
var colorNames = Object.keys(window.chartColors);
|
||||
|
||||
}else{
|
||||
$.pwrvid.mL.html('<div class="super-center text-center" style="width:auto">'+lang['No Events found for this video']+'</div>')
|
||||
}
|
||||
$.pwrvid.video={filename:e.filename,href:e.href,mid:e.mon.mid,ke:e.mon.ke}
|
||||
$.pwrvid.vpOnPlayPause=function(x,e){
|
||||
var e={}
|
||||
e.video=$.pwrvid.vp.find('video')[0]
|
||||
e.i=$.pwrvid.vp.find('[preview="play"]').find('i')
|
||||
if(e.video.paused===true){
|
||||
e.i.removeClass('fa-pause').addClass('fa-play')
|
||||
if(x==1)e.video.play();
|
||||
}else{
|
||||
e.i.removeClass('fa-play').addClass('fa-pause')
|
||||
if(x==1)e.video.pause();
|
||||
}
|
||||
}
|
||||
var videoElement=$.pwrvid.vp.find('video')[0]
|
||||
$.pwrvid.vp.find('video')
|
||||
.off('loadeddata').on('loadeddata', function() {
|
||||
this.playbackRate = $.pwrvid.playRate;
|
||||
this.play()
|
||||
})
|
||||
.off("pause").on("pause",$.pwrvid.vpOnPlayPause)
|
||||
.off("play").on("play",$.pwrvid.vpOnPlayPause)
|
||||
.off("timeupdate").on("timeupdate",function(){
|
||||
var video = $.pwrvid.currentDataObject[e.filename];
|
||||
var videoTime=$.ccio.timeObject(video.row.time).add(parseInt(videoElement.currentTime),'seconds').format('MM/DD/YYYY HH:mm:ss');
|
||||
var event = eventsLabeledByTime[videoTime];
|
||||
if(event){
|
||||
if(event.details.plates){
|
||||
console.log('licensePlateVideo',event)
|
||||
}
|
||||
if(event.details.matrices){
|
||||
event.monitorDetails=JSON.parse(e.mon.details)
|
||||
event.stream=$(videoElement)
|
||||
event.streamObjects=$.pwrvid.vp.find('.stream-objects')
|
||||
$.ccio.init('drawMatrices',event)
|
||||
}
|
||||
if(event.details.confidence){
|
||||
$.pwrvid.vp.find('.motion-meter .progress-bar').css('width',event.details.confidence+'px').find('span').text(event.details.confidence)
|
||||
}
|
||||
}
|
||||
var value= (( videoElement.currentTime / videoElement.duration ) * 100)+"%"
|
||||
$.pwrvid.seekBarProgress.css("width",value);
|
||||
})
|
||||
$.pwrvid.seekBar.off("click").on("click", function(seek){
|
||||
var offset = $(this).offset();
|
||||
var left = (seek.pageX - offset.left);
|
||||
var totalWidth = $.pwrvid.seekBar.width();
|
||||
var percentage = ( left / totalWidth );
|
||||
var vidTime = videoElement.duration * percentage;
|
||||
videoElement.currentTime = vidTime;
|
||||
});
|
||||
break;
|
||||
}
|
||||
})
|
||||
$.pwrvid.drawTimeline=function(getData){
|
||||
var e={};
|
||||
$.pwrvid.e.find('.nodata').hide()
|
||||
if(getData===undefined){getData=true}
|
||||
var mid=$.pwrvid.m.val();
|
||||
$.pwrvid.e.find('.loading').show()
|
||||
e.live_header=$.pwrvid.lv.find('h3 span');
|
||||
e.live=$.pwrvid.lv.find('iframe');
|
||||
e.dateRange=$.pwrvid.dr.data('daterangepicker');
|
||||
e.videoLimit = $('#pvideo_video_limit').val();
|
||||
e.eventLimit = $('#pvideo_event_limit').val();
|
||||
if(e.eventLimit===''||isNaN(e.eventLimit)){e.eventLimit=500}
|
||||
if(e.videoLimit===''||isNaN(e.videoLimit)){e.videoLimit=0}
|
||||
|
||||
var getTheData = function(){
|
||||
e.live_header.text($.ccio.mon[$user.ke+mid+$user.auth_token].name)
|
||||
e.live.attr('src',$.ccio.init('location',$user)+$user.auth_token+'/embed/'+$user.ke+'/'+mid+'/fullscreen|jquery|relative|gui')
|
||||
|
||||
var pulseLoading = function(){
|
||||
var loading = $.pwrvid.e.find('.loading')
|
||||
var currentColor = loading.css('color')
|
||||
loading.animate('color','red')
|
||||
setTimeout(function(){
|
||||
loading.css('color',currentColor)
|
||||
},500)
|
||||
}
|
||||
if(getData===true){
|
||||
$.ccio.cx({
|
||||
f:'monitor',
|
||||
ff:'get',
|
||||
fff:'videos&events',
|
||||
videoLimit:e.videoLimit,
|
||||
eventLimit:e.eventLimit,
|
||||
startDate:$.ccio.init('th',e.dateRange.startDate),
|
||||
endDate:$.ccio.init('th',e.dateRange.endDate),
|
||||
ke:e.ke,
|
||||
mid:mid
|
||||
});
|
||||
}else{
|
||||
$.pwrvid.e.find('.loading').hide()
|
||||
e.next($.pwrvid.currentVideos,$.pwrvid.currentEvents)
|
||||
}
|
||||
}
|
||||
if(parseInt(e.eventLimit) >= 1000){
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Warning']+'!')
|
||||
e.html=lang.powerVideoEventLimit
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click({title:lang.Request,class:'btn-primary'},function(){
|
||||
getTheData()
|
||||
});
|
||||
}else{
|
||||
getTheData()
|
||||
}
|
||||
}
|
||||
$('#vis_monitors,#pvideo_event_limit,#pvideo_video_limit').change(function(){
|
||||
$.pwrvid.f.submit()
|
||||
})
|
||||
$.pwrvid.f.submit(function(e){
|
||||
e.preventDefault();
|
||||
$.pwrvid.drawTimeline()
|
||||
return false;
|
||||
})
|
||||
$.pwrvid.e.on('hidden.bs.modal',function(e){
|
||||
$(this).find('iframe').attr('src','about:blank')
|
||||
$.pwrvid.vp.find('.holder').empty()
|
||||
delete($.pwrvid.currentDataObject)
|
||||
delete($.pwrvid.currentData)
|
||||
$.pwrvid.mL.empty()
|
||||
$.pwrvid.d.empty()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,48 @@
|
|||
$(document).ready(function(e){
|
||||
//probe
|
||||
$.pB={e:$('#probe')};$.pB.f=$.pB.e.find('form');$.pB.o=$.pB.e.find('.output_data');
|
||||
$.pB.f.submit(function(e){
|
||||
|
||||
$.pB.e.find('._loading').show()
|
||||
$.pB.o.empty();
|
||||
$.pB.e.find('.stop').show();
|
||||
$.pB.e.find('[type="submit"]').hide();
|
||||
|
||||
e.preventDefault();e.e=$(this),e.s=e.e.serializeObject();
|
||||
e.s.url=e.s.url.trim();
|
||||
var flags = '';
|
||||
switch(e.s.mode){
|
||||
case'json':
|
||||
flags = '-v quiet -print_format json -show_format -show_streams';
|
||||
break;
|
||||
}
|
||||
// if(e.s.url.indexOf('{{JSON}}')>-1){
|
||||
// e.s.url='-v quiet -print_format json -show_format -show_streams '+e.s.url
|
||||
// }
|
||||
$.get($.ccio.init('location',$user)+$user.auth_token+'/probe/'+$user.ke+'?url='+e.s.url+'&flags='+flags,function(data){
|
||||
if(data.ok===true){
|
||||
var html
|
||||
try{
|
||||
html = $.ccio.init('jsontoblock',JSON.parse(data.result))
|
||||
}catch(err){
|
||||
html = data.result
|
||||
}
|
||||
$.pB.o.append(html)
|
||||
}else{
|
||||
$.ccio.init('note',{title:'Failed to Probe',text:data.error,type:'error'});
|
||||
}
|
||||
$.pB.e.find('._loading').hide()
|
||||
$.pB.o.append('<div><b>END</b></div>');
|
||||
$.pB.e.find('.stop').hide();
|
||||
$.pB.e.find('[type="submit"]').show();
|
||||
})
|
||||
return false;
|
||||
});
|
||||
$.pB.e.on('hidden.bs.modal',function(){
|
||||
$.pB.o.empty()
|
||||
})
|
||||
$.pB.e.find('.stop').click(function(e){
|
||||
e.e=$(this);
|
||||
// $.ccio.cx({f:'ffprobe',ff:'stop'})
|
||||
});
|
||||
})
|
|
@ -0,0 +1,200 @@
|
|||
$(document).ready(function(e){
|
||||
//Region Editor
|
||||
$.zO={e:$('#region_editor')};
|
||||
$.zO.f=$.zO.e.find('form');
|
||||
$.zO.o=function(){return $.zO.e.find('canvas')};
|
||||
$.zO.c=$.zO.e.find('.canvas_holder');
|
||||
$.zO.name=$.zO.e.find('[name="name"]');
|
||||
$.zO.rl=$('#regions_list');
|
||||
$.zO.rp=$('#regions_points');
|
||||
$.zO.ca=$('#regions_canvas');
|
||||
$.zO.saveCoords=function(){
|
||||
$.aM.e.find('[detail="cords"]').val(JSON.stringify($.zO.regionViewerDetails.cords)).change()
|
||||
}
|
||||
$.zO.initRegionList=function(){
|
||||
$('#regions_list,#region_points').empty();
|
||||
$.each($.zO.regionViewerDetails.cords,function(n,v){
|
||||
if(v&&v.name){
|
||||
$.zO.rl.append('<option value="'+n+'">'+v.name+'</option>')
|
||||
}
|
||||
});
|
||||
$.zO.rl.change();
|
||||
}
|
||||
$.zO.rl.change(function(e){
|
||||
$.zO.initCanvas();
|
||||
})
|
||||
$.zO.initLiveStream=function(e){
|
||||
var e={}
|
||||
e.re=$('#region_editor_live');
|
||||
e.re.find('iframe,img').attr('src','about:blank').hide()
|
||||
if($('#region_still_image').is(':checked')){
|
||||
e.re=e.re.find('img')
|
||||
e.choice='jpeg'
|
||||
}else{
|
||||
e.re=e.re.find('iframe')
|
||||
e.choice='embed'
|
||||
}
|
||||
e.src=$.ccio.init('location',$user)+$user.auth_token+'/'+e.choice+'/'+$user.ke+'/'+$.aM.selected.mid
|
||||
if(e.choice=='embed'){
|
||||
e.src+='/fullscreen|jquery|relative'
|
||||
}else{
|
||||
e.src+='/s.jpg'
|
||||
}
|
||||
if(e.re.attr('src')!==e.src){
|
||||
e.re.attr('src',e.src).show()
|
||||
}
|
||||
e.re.attr('width',$.zO.regionViewerDetails.detector_scale_x)
|
||||
e.re.attr('height',$.zO.regionViewerDetails.detector_scale_y)
|
||||
}
|
||||
$('#region_still_image').change(function(e){
|
||||
e.o=$.ccio.op().switches
|
||||
if(!e.o){e.o={}}
|
||||
if($(this).is(':checked')){
|
||||
e.o.regionStillImage=1
|
||||
}else{
|
||||
e.o.regionStillImage="0"
|
||||
}
|
||||
$.ccio.op('switches',e.o)
|
||||
$.zO.initLiveStream()
|
||||
}).ready(function(e){
|
||||
e.switches=$.ccio.op().switches
|
||||
if(e.switches&&e.switches.regionStillImage===1){
|
||||
$('#region_still_image').prop('checked',true)
|
||||
}
|
||||
})
|
||||
$.zO.initCanvas=function(){
|
||||
var e={};
|
||||
e.ar=[];
|
||||
e.val=$.zO.rl.val();
|
||||
if(!e.val){
|
||||
$.zO.f.find('[name="name"]').val('')
|
||||
$.zO.f.find('[name="sensitivity"]').val('')
|
||||
$.zO.f.find('[name="max_sensitivity"]').val('')
|
||||
$.zO.f.find('[name="threshold"]').val('')
|
||||
$.zO.f.find('[name="color_threshold"]').val('')
|
||||
$.zO.rp.empty()
|
||||
}else{
|
||||
e.cord=$.zO.regionViewerDetails.cords[e.val];
|
||||
if(!e.cord.points){e.cord.points=[[0,0],[0,100],[100,0]]}
|
||||
$.each(e.cord.points,function(n,v){
|
||||
e.ar=e.ar.concat(v)
|
||||
});
|
||||
if(isNaN(e.cord.sensitivity)){
|
||||
e.cord.sensitivity=$.zO.regionViewerDetails.detector_sensitivity;
|
||||
}
|
||||
$.zO.f.find('[name="name"]').val(e.val)
|
||||
$.zO.e.find('.cord_name').text(e.val)
|
||||
$.zO.f.find('[name="sensitivity"]').val(e.cord.sensitivity)
|
||||
$.zO.f.find('[name="max_sensitivity"]').val(e.cord.max_sensitivity)
|
||||
$.zO.f.find('[name="threshold"]').val(e.cord.threshold)
|
||||
$.zO.f.find('[name="color_threshold"]').val(e.cord.color_threshold)
|
||||
$.zO.e.find('.canvas_holder canvas').remove();
|
||||
|
||||
$.zO.initLiveStream()
|
||||
e.e=$.zO.ca.val(e.ar.join(','))
|
||||
e.e.canvasAreaDraw({
|
||||
imageUrl:placeholder.getData(placeholder.plcimg({
|
||||
bgcolor:'transparent',
|
||||
text:' ',
|
||||
size:$.zO.regionViewerDetails.detector_scale_x+'x'+$.zO.regionViewerDetails.detector_scale_y
|
||||
}))
|
||||
});
|
||||
e.e.change();
|
||||
}
|
||||
}
|
||||
$.zO.e.on('change','[name]:not([name="name"])',function(){
|
||||
var el = $(this)
|
||||
var val = el.val()
|
||||
var key = el.attr('name')
|
||||
$.zO.regionViewerDetails.cords[$.zO.rl.val()][key] = val
|
||||
$.zO.saveCoords()
|
||||
})
|
||||
$.zO.e.on('change','[name="name"]',function(e){
|
||||
e.old=$.zO.rl.val();
|
||||
e.new=$.zO.name.val();
|
||||
$.zO.regionViewerDetails.cords[e.new]=$.zO.regionViewerDetails.cords[e.old];
|
||||
delete($.zO.regionViewerDetails.cords[e.old]);
|
||||
$.zO.rl.find('option[value="'+e.old+'"]').attr('value',e.new).text(e.new)
|
||||
$.zO.saveCoords()
|
||||
})
|
||||
$.zO.e.on('change','[point]',function(e){
|
||||
e.points=[];
|
||||
$('[points]').each(function(n,v){
|
||||
v=$(v);
|
||||
n=v.find('[point="x"]').val();
|
||||
if(n){
|
||||
e.points.push([n,v.find('[point="y"]').val()])
|
||||
}
|
||||
})
|
||||
$.zO.regionViewerDetails.cords[$.zO.name.val()].points=e.points;
|
||||
$.zO.initCanvas();
|
||||
})
|
||||
$.zO.e.find('.erase').click(function(e){
|
||||
e.arr=[]
|
||||
$.each($.zO.regionViewerDetails.cords,function(n,v){
|
||||
if(v&&v!==$.zO.regionViewerDetails.cords[$.zO.rl.val()]){
|
||||
e.arr.push(v)
|
||||
}
|
||||
})
|
||||
$.zO.regionViewerDetails.cords=e.arr.concat([]);
|
||||
if(Object.keys($.zO.regionViewerDetails.cords).length>0){
|
||||
$.zO.initRegionList();
|
||||
}else{
|
||||
$.zO.f.find('input').prop('disabled',true)
|
||||
$('#regions_points tbody').empty()
|
||||
$('#regions_list [value="'+$.zO.rl.val()+'"]').remove()
|
||||
$.aM.e.find('[detail="cords"]').val('[]')
|
||||
}
|
||||
});
|
||||
//$.zO.e.find('.new').click(function(e){
|
||||
// $.zO.regionViewerDetails.cords[$.zO.rl.val()]
|
||||
// $.zO.initRegionList();
|
||||
//})
|
||||
$.zO.e.on('changed','#regions_canvas',function(e){
|
||||
e.val=$(this).val().replace(/(,[^,]*),/g, '$1;').split(';');
|
||||
e.ar=[];
|
||||
$.each(e.val,function(n,v){
|
||||
v=v.split(',')
|
||||
if(v[1]){
|
||||
e.ar.push([v[0],v[1]])
|
||||
}
|
||||
})
|
||||
$.zO.regionViewerDetails.cords[$.zO.rl.val()].points=e.ar;
|
||||
e.selected=$.zO.regionViewerDetails.cords[$.zO.rl.val()];
|
||||
e.e=$('#regions_points tbody').empty();
|
||||
$.each($.zO.regionViewerDetails.cords[$.zO.rl.val()].points,function(n,v){
|
||||
if(isNaN(v[0])){v[0]=20}
|
||||
if(isNaN(v[1])){v[1]=20}
|
||||
e.e.append('<tr points="'+n+'"><td><input class="form-control" placeholder="X" point="x" value="'+v[0]+'"></td><td><input class="form-control" placeholder="Y" point="y" value="'+v[1]+'"></td><td class="text-right"><a class="delete btn btn-danger"><i class="fa fa-trash-o"></i></a></td></tr>')
|
||||
});
|
||||
$.zO.saveCoords()
|
||||
})
|
||||
$.zO.f.submit(function(e){
|
||||
e.preventDefault();e.e=$(this),e.s=e.e.serializeObject();
|
||||
|
||||
return false;
|
||||
});
|
||||
$('#regions_points')
|
||||
.on('click','.delete',function(e){
|
||||
e.p=$(this).parents('tr'),e.row=e.p.attr('points');
|
||||
delete($.zO.regionViewerDetails.cords[$.zO.rl.val()].points[e.row])
|
||||
$.zO.saveCoords()
|
||||
e.p.remove();
|
||||
$.zO.rl.change();
|
||||
})
|
||||
$.zO.e.on('click','.add',function(e){
|
||||
$.zO.f.find('input').prop('disabled',false)
|
||||
e.gid=$.ccio.gid(5);
|
||||
e.save={};
|
||||
$.each($.zO.regionViewerDetails.cords,function(n,v){
|
||||
if(v&&v!==null&&v!=='null'){
|
||||
e.save[n]=v;
|
||||
}
|
||||
})
|
||||
$.zO.regionViewerDetails.cords=e.save;
|
||||
$.zO.regionViewerDetails.cords[e.gid]={name:e.gid,sensitivity:0.0005,max_sensitivity:'',threshold:1,color_threshold:9,points:[[0,0],[0,100],[100,0]]};
|
||||
$.zO.rl.append('<option value="'+e.gid+'">'+e.gid+'</option>');
|
||||
$.zO.rl.val(e.gid)
|
||||
$.zO.rl.change();
|
||||
});
|
||||
})
|
|
@ -0,0 +1,933 @@
|
|||
$(document).ready(function(e){
|
||||
//websocket functions
|
||||
$.users = {}
|
||||
$.ccio.cx=function(x,user){
|
||||
if(!user){user=$user}
|
||||
if(!x.ke){x.ke=user.ke;};
|
||||
if(!x.uid){x.uid=user.uid;};
|
||||
return user.ws.emit('f',x)
|
||||
}
|
||||
$.ccio.globalWebsocket=function(d,user){
|
||||
if(d.f!=='monitor_frame'&&d.f!=='os'&&d.f!=='video_delete'&&d.f!=='detector_trigger'&&d.f!=='detector_record_timeout_start'&&d.f!=='log'){$.ccio.log(d);}
|
||||
if(!user){
|
||||
user=$user
|
||||
}
|
||||
if(d.viewers){
|
||||
$('[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"] .viewers').html(d.viewers);
|
||||
}
|
||||
switch(d.f){
|
||||
case'note':
|
||||
$.ccio.init('note',d.note,user);
|
||||
break;
|
||||
case'monitor_status':
|
||||
console.log(d)
|
||||
$('[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"] .monitor_status').html(d.status);
|
||||
break;
|
||||
case'detector_trigger':
|
||||
d.e=$('.monitor_item[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"]')
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token]&&d.e.length>0){
|
||||
if(d.doObjectDetection === true){
|
||||
d.e.addClass('doObjectDetection')
|
||||
clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_doObjectDetection_timeout)
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_doObjectDetection_timeout = setTimeout(function(){
|
||||
d.e.removeClass('doObjectDetection')
|
||||
},3000)
|
||||
}else{
|
||||
d.e.removeClass('doObjectDetection')
|
||||
}
|
||||
if(d.details.plates&&d.details.plates.length>0){
|
||||
console.log('licensePlateStream',d.id,d)
|
||||
}
|
||||
if(d.details.matrices&&d.details.matrices.length>0){
|
||||
d.monitorDetails=JSON.parse($.ccio.mon[d.ke+d.id+user.auth_token].details)
|
||||
d.stream=d.e.find('.stream-element')
|
||||
d.streamObjects=d.e.find('.stream-objects')
|
||||
$.ccio.init('drawMatrices',d)
|
||||
}
|
||||
if(d.details.points&&Object.keys(d.details.points).length>0){
|
||||
d.monitorDetails=JSON.parse($.ccio.mon[d.ke+d.id+user.auth_token].details)
|
||||
d.stream=d.e.find('.stream-element')
|
||||
d.streamObjects=d.e.find('.stream-objects')
|
||||
$.ccio.init('drawPoints',d)
|
||||
}
|
||||
if(d.details.confidence){
|
||||
d.tt=d.details.confidence;
|
||||
if (d.tt > 100) { d.tt = 100 }
|
||||
d.e.find('.indifference .progress-bar').css('width',d.tt + '%').find('span').html(d.details.confidence+'% change in <b>'+d.details.name+'</b>')
|
||||
}
|
||||
d.e.addClass('detector_triggered')
|
||||
clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_timeout);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].detector_trigger_timeout=setTimeout(function(){
|
||||
$('.monitor_item[ke="'+d.ke+'"][mid="'+d.id+'"][auth="'+user.auth_token+'"]').removeClass('detector_triggered').find('.stream-detected-object,.stream-detected-point').remove()
|
||||
},5000);
|
||||
//noise alert
|
||||
if(user.details.audio_alert && user.details.audio_alert !== '' && $.ccio.soundAlarmed !== true){
|
||||
$.ccio.soundAlarmed = true
|
||||
var audio = new Audio('libs/audio/'+user.details.audio_alert);
|
||||
audio.onended = function(){
|
||||
setTimeout(function(){
|
||||
$.ccio.soundAlarmed = false
|
||||
},user.details.audio_delay * 1000)
|
||||
}
|
||||
if($.ccio.windowFocus = true){
|
||||
audio.play()
|
||||
}else{
|
||||
clearInterval($.ccio.soundAlarmInterval)
|
||||
if(!user.details.audio_delay || user.details.audio_delay === ''){
|
||||
user.details.audio_delay = 1
|
||||
}else{
|
||||
user.details.audio_delay = parseFloat(user.details.audio_delay)
|
||||
}
|
||||
$.ccio.soundAlarmInterval = setInterval(function(){
|
||||
audio.play()
|
||||
},user.details.audio_delay * 1000)
|
||||
}
|
||||
}
|
||||
if(user.details.event_mon_pop === '1' && (!$.ccio.mon[d.ke+d.id+user.auth_token].popOut || $.ccio.mon[d.ke+d.id+user.auth_token].popOut.closed === true)){
|
||||
d.e.find('[monitor="pop"]').click()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case'init_success':
|
||||
$('#monitors_list .link-monitors-list[auth="'+user.auth_token+'"][ke="'+user.ke+'"]').empty();
|
||||
if(user===$user){
|
||||
d.chosen_set='watch_on'
|
||||
}else{
|
||||
d.chosen_set='watch_on_links'
|
||||
}
|
||||
d.o=$.ccio.op()[d.chosen_set];
|
||||
if(!d.o){d.o={}};
|
||||
$.getJSON($.ccio.init('location',user)+user.auth_token+'/monitor/'+user.ke,function(f,g){
|
||||
g=function(n,v){
|
||||
$.ccio.mon[v.ke+v.mid+user.auth_token]=v;
|
||||
v.user=user;
|
||||
$.ccio.tm(1,v,null,user)
|
||||
if(d.o[v.ke]&&d.o[v.ke][v.mid]===1){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:v.mid},user)
|
||||
}
|
||||
}
|
||||
if(f.mid){
|
||||
g(null,f)
|
||||
}else{
|
||||
$.each(f,g);
|
||||
}
|
||||
if($.ccio.op().jpeg_on===true){
|
||||
$.ccio.cx({f:'monitor',ff:'jpeg_on'},user)
|
||||
}
|
||||
$.gR.drawList();
|
||||
})
|
||||
$.ccio.pm(3,d.apis,null,user);
|
||||
$('.os_platform').html(d.os.platform)
|
||||
$('.os_cpuCount').html(d.os.cpuCount)
|
||||
$('.os_totalmem').html((d.os.totalmem/1000000).toFixed(2))
|
||||
if(d.os.cpuCount>1){
|
||||
$('.os_cpuCount_trailer').html('s')
|
||||
}
|
||||
break;
|
||||
case'get_videos':
|
||||
$.ccio.pm(0,d,null,user)
|
||||
break;
|
||||
case'log':
|
||||
var attr = '[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]'
|
||||
$.ccio.tm(4,d,'#logs,'+attr+'.monitor_item .logs:visible,'+attr+'#add_monitor:visible .logs',user)
|
||||
break;
|
||||
case'camera_cpu_usage':
|
||||
var el = $('.monitor_item[auth="'+user.auth_token+'"][ke="'+d.ke+'"][mid="'+d.id+'"] .camera_cpu_usage')
|
||||
.attr('title',d.percent + '% ' + lang['CPU used by this stream'])
|
||||
el.find('.progress-bar').css('width',d.percent)
|
||||
el.find('.percent').html(d.percent + '%')
|
||||
break;
|
||||
case'os'://indicator
|
||||
//cpu
|
||||
d.cpu=parseFloat(d.cpu).toFixed(0)+'%';
|
||||
$('.cpu_load .progress-bar').css('width',d.cpu);
|
||||
$('.cpu_load .percent').html(d.cpu);
|
||||
//ram
|
||||
d.ram=(100-parseFloat(d.ram)).toFixed(0)+'%';
|
||||
$('.ram_load .progress-bar').css('width',d.ram);
|
||||
$('.ram_load .percent').html(d.ram);
|
||||
break;
|
||||
case'diskUsed':
|
||||
if(!d.limit||d.limit===''){d.limit=10000}
|
||||
d.percent=parseInt((d.size/d.limit)*100)+'%';
|
||||
d.human=parseFloat(d.size)
|
||||
if(d.human>1000){d.human=(d.human/1000).toFixed(2)+' GB'}else{d.human=d.human.toFixed(2)+' MB'}
|
||||
$('.diskUsed .value').html(d.human)
|
||||
$('.diskUsed .percent').html(d.percent)
|
||||
$('.diskUsed .progress-bar').css('width',d.percent)
|
||||
break;
|
||||
case'video_fix_success':case'video_fix_start':
|
||||
switch(d.f){
|
||||
case'video_fix_success':
|
||||
d.addClass='fa-wrench'
|
||||
d.removeClass='fa-pulse fa-spinner'
|
||||
break;
|
||||
case'video_fix_start':
|
||||
d.removeClass='fa-wrench'
|
||||
d.addClass='fa-pulse fa-spinner'
|
||||
break;
|
||||
}
|
||||
$('[mid="'+d.mid+'"][ke="'+d.ke+'"][file="'+d.filename+'"][auth="'+user.auth_token+'"] [video="fix"] i,[data-mid="'+d.mid+'"][data-ke="'+d.ke+'"][data-file="'+d.filename+'"][data-auth="'+user.auth_token+'"] [video="fix"] i').addClass(d.addClass).removeClass(d.removeClass)
|
||||
break;
|
||||
case'video_edit':case'video_archive':
|
||||
$.ccio.init('data-video',d)
|
||||
d.e=$('[file="'+d.filename+'"][mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"],[data-file="'+d.filename+'"][data-mid="'+d.mid+'"][data-ke="'+d.ke+'"][data-auth="'+user.auth_token+'"]');
|
||||
d.e.attr('status',d.status),d.e.attr('data-status',d.status);
|
||||
console.log(d)
|
||||
|
||||
break;
|
||||
case'video_delete':
|
||||
// if($('.modal[mid="'+d.mid+'"][auth="'+user.auth_token+'"]').length>0){$('#video_viewer[mid="'+d.mid+'"]').attr('file',null).attr('ke',null).attr('mid',null).attr('auth',null).modal('hide')}
|
||||
$('[file="'+d.filename+'"][mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]:not(.modal)').remove();
|
||||
$('[data-file="'+d.filename+'"][data-mid="'+d.mid+'"][data-ke="'+d.ke+'"][data-auth="'+user.auth_token+'"]:not(.modal)').remove();
|
||||
if($.pwrvid.currentDataObject&&$.pwrvid.currentDataObject[d.filename]){
|
||||
delete($.timelapse.currentVideos[$.pwrvid.currentDataObject[d.filename].position])
|
||||
$.pwrvid.drawTimeline(false)
|
||||
}
|
||||
if($.timelapse.currentVideos&&$.timelapse.currentVideos[d.filename]){
|
||||
delete($.timelapse.currentVideosArray.videos[$.timelapse.currentVideos[d.filename].position])
|
||||
$.timelapse.drawTimeline(false)
|
||||
}
|
||||
if($.vidview.loadedVideos && $.vidview.loadedVideos[d.filename])delete($.vidview.loadedVideos[d.filename])
|
||||
break;
|
||||
case'video_build_success':
|
||||
if(!d.mid){d.mid=d.id;};d.status=1;
|
||||
d.e='.glM'+d.mid+user.auth_token+'.videos_list ul,.glM'+d.mid+user.auth_token+'.videos_monitor_list ul';$(d.e).find('.notice.novideos').remove();
|
||||
$.ccio.tm(0,d,d.e,user)
|
||||
break;
|
||||
case'monitor_snapshot':
|
||||
setTimeout(function(){
|
||||
var snapElement = $('[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"] .snapshot')
|
||||
switch(d.snapshot_format){
|
||||
case'plc':
|
||||
snapElement.attr('src',placeholder.getData(placeholder.plcimg(d.snapshot)))
|
||||
break;
|
||||
case'ab':
|
||||
d.reader = new FileReader();
|
||||
d.reader.addEventListener("loadend",function(){snapElement.attr('src',d.reader.result)});
|
||||
d.reader.readAsDataURL(new Blob([d.snapshot],{type:"image/jpeg"}));
|
||||
break;
|
||||
case'b64':
|
||||
snapElement.attr('src','data:image/jpeg;base64,'+d.snapshot)
|
||||
break;
|
||||
}
|
||||
},1000)
|
||||
break;
|
||||
case'monitor_delete':
|
||||
$('[mid="'+d.mid+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]:not(.modal)').remove();
|
||||
$.ccio.init('clearTimers',d)
|
||||
delete($.ccio.mon[d.ke+d.mid+user.auth_token]);
|
||||
break;
|
||||
case'monitor_watch_off':case'monitor_stopping':
|
||||
if(user===$user){
|
||||
d.chosen_set='watch_on'
|
||||
}else{
|
||||
d.chosen_set='watch_on_links'
|
||||
}
|
||||
d.o=$.ccio.op()[d.chosen_set];
|
||||
if(!d.o[d.ke]){d.o[d.ke]={}};d.o[d.ke][d.id]=0;$.ccio.op(d.chosen_set,d.o);
|
||||
$.ccio.destroyStream(d,user,(d.f === 'monitor_watch_off'))
|
||||
break;
|
||||
case'monitor_watch_on':
|
||||
if(user===$user){
|
||||
d.chosen_set='watch_on'
|
||||
}else{
|
||||
d.chosen_set='watch_on_links'
|
||||
}
|
||||
d.o=$.ccio.op()[d.chosen_set];
|
||||
if(!d.o){d.o={}};if(!d.o[d.ke]){d.o[d.ke]={}};d.o[d.ke][d.id]=1;$.ccio.op(d.chosen_set,d.o);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].watch=1;
|
||||
delete($.ccio.mon[d.ke+d.id+user.auth_token].image)
|
||||
delete($.ccio.mon[d.ke+d.id+user.auth_token].ctx)
|
||||
d.e=$('#monitor_live_'+d.id+user.auth_token);
|
||||
d.e.find('.stream-detected-object').remove()
|
||||
$.ccio.init('clearTimers',d)
|
||||
if(d.e.length === 1){
|
||||
$.ccio.init('closeVideo',{mid:d.id,ke:d.ke},user);
|
||||
}
|
||||
if(d.e.length === 0){
|
||||
$.ccio.tm(2,$.ccio.mon[d.ke+d.id+user.auth_token],'#monitors_live',user);
|
||||
}
|
||||
d.d=JSON.parse($.ccio.mon[d.ke+d.id+user.auth_token].details);
|
||||
$.ccio.tm('stream-element',$.ccio.mon[d.ke+d.id+user.auth_token],null,user);
|
||||
if($.ccio.op().jpeg_on===true){
|
||||
$.ccio.init('jpegMode',$.ccio.mon[d.ke+d.id+user.auth_token]);
|
||||
}else{
|
||||
var path = tool.checkCorrectPathEnding(location.pathname)+'socket.io'
|
||||
switch(d.d.stream_type){
|
||||
case'jpeg':
|
||||
$.ccio.init('jpegMode',$.ccio.mon[d.ke+d.id+user.auth_token]);
|
||||
break;
|
||||
case'b64':
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].Base64 && $.ccio.mon[d.ke+d.id+user.auth_token].Base64.connected){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Base64.disconnect()
|
||||
}
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Base64 = io(location.origin,{ path: path, transports: ['websocket'], forceNew: false})
|
||||
var ws = $.ccio.mon[d.ke+d.id+user.auth_token].Base64
|
||||
var buffer
|
||||
ws.on('diconnect',function(){
|
||||
console.log('Base64 Stream Disconnected')
|
||||
})
|
||||
ws.on('connect',function(){
|
||||
ws.emit('Base64',{
|
||||
auth: user.auth_token,
|
||||
uid: user.uid,
|
||||
ke: d.ke,
|
||||
id: d.id,
|
||||
// channel: channel
|
||||
})
|
||||
if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].ctx = $('#monitor_live_'+d.id+user.auth_token+' canvas');
|
||||
}
|
||||
var ctx = $.ccio.mon[d.ke+d.id+user.auth_token].ctx[0]
|
||||
var ctx2d = ctx.getContext("2d")
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].image = new Image()
|
||||
var image = $.ccio.mon[d.ke+d.id+user.auth_token].image
|
||||
image.onload = function() {
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = false
|
||||
d.x = 0
|
||||
d.y = 0
|
||||
// d.ratio = Math.min(ctx.width/image.width,ctx.height/image.height)
|
||||
// d.height = image.height * d.ratio
|
||||
// d.width = image.width * d.ratio
|
||||
// if(d.width < ctx.width){
|
||||
// d.x = (ctx.width / 2) - (d.width / 2)
|
||||
// }
|
||||
// if(d.height < ctx.height){
|
||||
// d.y = (ctx.height / 2) - (d.height / 2)
|
||||
// }
|
||||
// ctx.getContext("2d").drawImage(image,d.x,d.y,d.width,d.height)
|
||||
ctx.getContext("2d").drawImage(image,d.x,d.y,ctx.width,ctx.height)
|
||||
URL.revokeObjectURL($.ccio.mon[d.ke+d.id+user.auth_token].imageUrl)
|
||||
}
|
||||
ws.on('data',function(imageData){
|
||||
try{
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].imageLoading === true)return console.log('drop');
|
||||
// var base64Frame = 'data:image/jpeg;base64,'+$.ccio.base64ArrayBuffer(imageData)
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = true
|
||||
// $.ccio.mon[d.ke+d.id+user.auth_token].image.src = base64Frame
|
||||
var arrayBufferView = new Uint8Array(imageData);
|
||||
var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].imageUrl = URL.createObjectURL( blob );
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].image.src = $.ccio.mon[d.ke+d.id+user.auth_token].imageUrl
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].last_frame = 'data:image/jpeg;base64,'+$.ccio.base64ArrayBuffer(imageData)
|
||||
}catch(er){
|
||||
console.log(er)
|
||||
$.ccio.log('base64 frame')
|
||||
}
|
||||
$.ccio.init('signal',d);
|
||||
})
|
||||
})
|
||||
break;
|
||||
case'mp4':
|
||||
setTimeout(function(){
|
||||
var stream = d.e.find('.stream-element');
|
||||
var onPoseidonError = function(){
|
||||
// setTimeout(function(){
|
||||
// $.ccio.cx({f:'monitor',ff:'watch_on',id:d.id},user)
|
||||
// },5000)
|
||||
}
|
||||
if(!$.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount)$.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount = 0
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].PoseidonErrorCount >= 5)return
|
||||
if(d.d.stream_flv_type==='ws'){
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].Poseidon){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.stop()
|
||||
}
|
||||
try{
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon = new Poseidon({
|
||||
video: stream[0],
|
||||
auth_token:user.auth_token,
|
||||
ke:d.ke,
|
||||
uid:user.uid,
|
||||
id:d.id,
|
||||
url: location.origin,
|
||||
path: path,
|
||||
onError : onPoseidonError
|
||||
})
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.start();
|
||||
}catch(err){
|
||||
// onPoseidonError()
|
||||
console.log('onTryPoseidonError',err)
|
||||
}
|
||||
}else{
|
||||
stream.attr('src',$.ccio.init('location',user)+user.auth_token+'/mp4/'+d.ke+'/'+d.id+'/s.mp4')
|
||||
stream[0].onerror = function(err){
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
},2000)
|
||||
break;
|
||||
case'flv':
|
||||
if (flvjs.isSupported()) {
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].flv){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].flv.destroy()
|
||||
}
|
||||
var options = {};
|
||||
if(d.d.stream_flv_type==='ws'){
|
||||
if(d.d.stream_flv_maxLatency&&d.d.stream_flv_maxLatency!==''){
|
||||
d.d.stream_flv_maxLatency = parseInt(d.d.stream_flv_maxLatency)
|
||||
}else{
|
||||
d.d.stream_flv_maxLatency = 20000;
|
||||
}
|
||||
options = {
|
||||
type: 'flv',
|
||||
isLive: true,
|
||||
auth_token:user.auth_token,
|
||||
ke:d.ke,
|
||||
uid:user.uid,
|
||||
id:d.id,
|
||||
maxLatency:d.d.stream_flv_maxLatency,
|
||||
hasAudio:false,
|
||||
url: location.origin,
|
||||
path: path
|
||||
}
|
||||
}else{
|
||||
options = {
|
||||
type: 'flv',
|
||||
isLive: true,
|
||||
url: $.ccio.init('location',user)+user.auth_token+'/flv/'+d.ke+'/'+d.id+'/s.flv'
|
||||
}
|
||||
}
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].flv = flvjs.createPlayer(options);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].flv.attachMediaElement($('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0]);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].flv.on('error',function(err){
|
||||
console.log(err)
|
||||
});
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].flv.load();
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].flv.play();
|
||||
}else{
|
||||
$.ccio.init('note',{title:'Stream cannot be started',text:'FLV.js is not supported on this browser. Try another stream type.',type:'error'});
|
||||
}
|
||||
break;
|
||||
case'hls':
|
||||
d.fn=function(){
|
||||
clearTimeout($.ccio.mon[d.ke+d.id+user.auth_token].m3uCheck)
|
||||
d.url=$.ccio.init('location',user)+user.auth_token+'/hls/'+d.ke+'/'+d.id+'/s.m3u8';
|
||||
$.get(d.url,function(m3u){
|
||||
if(m3u=='File Not Found'){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].m3uCheck=setTimeout(function(){
|
||||
d.fn()
|
||||
},2000)
|
||||
}else{
|
||||
var video = $('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0];
|
||||
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)||(navigator.userAgent.match(/(Safari)/)&&!navigator.userAgent.match('Chrome'))) {
|
||||
video.src=d.url;
|
||||
if (video.paused) {
|
||||
video.play();
|
||||
}
|
||||
}else{
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollector=function(){
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].hls){$.ccio.mon[d.ke+d.id+user.auth_token].hls.destroy();URL.revokeObjectURL(video.src)}
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hls = new Hls();
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hls.loadSource(d.url);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hls.attachMedia(video);
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hls.on(Hls.Events.MANIFEST_PARSED,function() {
|
||||
if (video.paused) {
|
||||
video.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollector()
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollectorTimer=setInterval($.ccio.mon[d.ke+d.id+user.auth_token].hlsGarbageCollector,1000*60*20)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
d.fn()
|
||||
break;
|
||||
case'mjpeg':
|
||||
$('#monitor_live_'+d.id+user.auth_token+' .stream-element').attr('src',$.ccio.init('location',user)+user.auth_token+'/mjpeg/'+d.ke+'/'+d.id+'/?full=true')
|
||||
break;
|
||||
case'h265':
|
||||
var player = $.ccio.mon[d.ke+d.id+user.auth_token].h265Player
|
||||
var video = $('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0]
|
||||
if (player) {
|
||||
player.stop()
|
||||
}
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].h265Player = new libde265.RawPlayer(video)
|
||||
var player = $.ccio.mon[d.ke+d.id+user.auth_token].h265Player
|
||||
player.set_status_callback(function(msg, fps) {
|
||||
})
|
||||
player.launch()
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].h265Socket && $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.connected){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.disconnect()
|
||||
}
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream && $.ccio.mon[d.ke+d.id+user.auth_token].abort){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream.abort()
|
||||
}
|
||||
if(d.d.stream_flv_type==='ws'){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].h265Socket = io(location.origin,{ path: path, transports: ['websocket'], forceNew: false})
|
||||
var ws = $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket
|
||||
ws.on('diconnect',function(){
|
||||
console.log('h265Socket Stream Disconnected')
|
||||
})
|
||||
ws.on('connect',function(){
|
||||
ws.emit('h265',{
|
||||
auth: user.auth_token,
|
||||
uid: user.uid,
|
||||
ke: d.ke,
|
||||
id: d.id,
|
||||
// channel: channel
|
||||
})
|
||||
ws.on('data',function(imageData){
|
||||
player._handle_onChunk(imageData)
|
||||
})
|
||||
})
|
||||
}else{
|
||||
var url = $.ccio.init('location',user)+user.auth_token+'/h265/'+d.ke+'/'+d.id+'/s.hevc';
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream = player.createHttpStream(url)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
d.signal=parseFloat(d.d.signal_check);
|
||||
if(!d.signal||d.signal==NaN){d.signal=10;};d.signal=d.signal*1000*60;
|
||||
if(d.signal>0){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].signal=setInterval(function(){$.ccio.init('signal-check',{id:d.id,ke:d.ke})},d.signal);
|
||||
}
|
||||
d.e=$('.monitor_item[mid="'+d.id+'"][ke="'+d.ke+'"][auth="'+user.auth_token+'"]').resize()
|
||||
if(d.e.find('.videos_monitor_list li').length===0){
|
||||
d.dr=$('#videos_viewer_daterange').data('daterangepicker');
|
||||
$.getJSON($.ccio.init('location',user)+user.auth_token+'/videos/'+d.ke+'/'+d.id+'?limit=10',function(f){
|
||||
$.ccio.pm(0,{videos:f.videos,ke:d.ke,mid:d.id},null,user)
|
||||
})
|
||||
}
|
||||
setTimeout(function(){
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].motionDetectionRunning===true){
|
||||
$.ccio.init('streamMotionDetectRestart',{mid:d.id,ke:d.ke,mon:$.ccio.mon[d.ke+d.id+user.auth_token]},user);
|
||||
}
|
||||
},3000)
|
||||
break;
|
||||
case'pam_frame':
|
||||
if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].ctx = $('#monitor_live_'+d.id+user.auth_token+' canvas');
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].ctxContext = $.ccio.mon[d.ke+d.id+user.auth_token].ctx[0].getContext('2d');
|
||||
}
|
||||
var ctx = $.ccio.mon[d.ke+d.id+user.auth_token].ctxContext;
|
||||
d.x = 0,d.y = 0;
|
||||
d.ratio = Math.min($.ccio.mon[d.ke+d.id+user.auth_token].ctx.width()/d.imageData.width,$.ccio.mon[d.ke+d.id+user.auth_token].ctx.height()/d.imageData.height);
|
||||
d.height = d.imageData.height*d.ratio;
|
||||
d.width = d.imageData.width*d.ratio;
|
||||
if( d.width < $.ccio.mon[d.ke+d.id+user.auth_token].ctx.width() )
|
||||
d.x = ($.ccio.mon[d.ke+d.id+user.auth_token].ctx.width() / 2) - (d.width / 2);
|
||||
if( d.height < $.ccio.mon[d.ke+d.id+user.auth_token].ctx.height() )
|
||||
d.y = ($.ccio.mon[d.ke+d.id+user.auth_token].ctx.height() / 2) - (d.height / 2);
|
||||
var imageData = ctx.createImageData(d.width,d.height)
|
||||
imageData.data.set(new Uint8ClampedArray(d.imageData.data))
|
||||
console.log(imageData)
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
break;
|
||||
case'monitor_frame':
|
||||
try{
|
||||
if($.ccio.mon[d.ke+d.id+user.auth_token].imageLoading === true)return
|
||||
if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].ctx = $('#monitor_live_'+d.id+user.auth_token+' canvas');
|
||||
}
|
||||
var ctx = $.ccio.mon[d.ke+d.id+user.auth_token].ctx[0]
|
||||
if(!$.ccio.mon[d.ke+d.id+user.auth_token].image){
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].image = new Image()
|
||||
var image = $.ccio.mon[d.ke+d.id+user.auth_token].image
|
||||
image.onload = function() {
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = false
|
||||
d.x = 0
|
||||
d.y = 0
|
||||
// d.ratio = Math.min(ctx.width/image.width,ctx.height/image.height)
|
||||
// d.height = image.height * d.ratio
|
||||
// d.width = image.width * d.ratio
|
||||
// if(d.width < ctx.width){
|
||||
// d.x = (ctx.width / 2) - (d.width / 2)
|
||||
// }
|
||||
// if(d.height < ctx.height){
|
||||
// d.y = (ctx.height / 2) - (d.height / 2)
|
||||
// }
|
||||
// ctx.getContext("2d").drawImage(image,d.x,d.y,d.width,d.height)
|
||||
ctx.getContext("2d").drawImage(image,d.x,d.y,ctx.width,ctx.height)
|
||||
}
|
||||
}
|
||||
var base64Frame = 'data:image/jpeg;base64,'+d.frame
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].imageLoading = true
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].image.src = base64Frame
|
||||
$.ccio.mon[d.ke+d.id+user.auth_token].last_frame = base64Frame
|
||||
}catch(er){
|
||||
console.log(er)
|
||||
$.ccio.log('base64 frame')
|
||||
}
|
||||
$.ccio.init('signal',d);
|
||||
break;
|
||||
case'monitor_edit':
|
||||
$.ccio.init('clearTimers',d)
|
||||
d.e=$('[mid="'+d.mon.mid+'"][ke="'+d.mon.ke+'"][auth="'+user.auth_token+'"]');
|
||||
d.e=$('#monitor_live_'+d.mid+user.auth_token);
|
||||
d.e.find('.stream-detected-object').remove()
|
||||
if(d.mon.details.control=="1"){d.e.find('[monitor="control_toggle"]').show()}else{d.e.find('.pad').remove();d.e.find('[monitor="control_toggle"]').hide()}
|
||||
if(user===$user){
|
||||
d.chosen_set='watch_on'
|
||||
}else{
|
||||
d.chosen_set='watch_on_links'
|
||||
}
|
||||
d.o=$.ccio.op()[d.chosen_set];
|
||||
if(!d.o){d.o={}}
|
||||
if(d.mon.details.cords instanceof Object){d.mon.details.cords=JSON.stringify(d.mon.details.cords);}
|
||||
d.mon.details=JSON.stringify(d.mon.details);
|
||||
if(!$.ccio.mon[d.ke+d.mid+user.auth_token]){$.ccio.mon[d.ke+d.mid+user.auth_token]={}}
|
||||
$.ccio.init('jpegModeStop',d);
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token].previousStreamType=d.mon.details.stream_type
|
||||
$.each(d.mon,function(n,v){
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token][n]=v;
|
||||
});
|
||||
$.ccio.mon[d.ke+d.mid+user.auth_token].user=user
|
||||
if(d.new===true){$.ccio.tm(1,d.mon,null,user)}
|
||||
switch(d.mon.mode){
|
||||
case'start':case'record':
|
||||
if(d.o[d.ke]&&d.o[d.ke][d.mid]===1){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:d.mid},user)
|
||||
}
|
||||
break;
|
||||
}
|
||||
$.ccio.init('monitorInfo',d)
|
||||
$.gR.drawList();
|
||||
if(!d.silenceNote){
|
||||
$.ccio.init('note',{title:'Monitor Saved',text:'<b>'+d.mon.name+'</b> <small>'+d.mon.mid+'</small> has been saved.',type:'success'});
|
||||
}
|
||||
break;
|
||||
case'monitor_starting':
|
||||
// switch(d.mode){case'start':d.mode='Watch';break;case'record':d.mode='Record';break;}
|
||||
// $.ccio.init('note',{title:'Monitor Starting',text:'Monitor <b>'+d.mid+'</b> is now running in mode <b>'+d.mode+'</b>',type:'success'});
|
||||
d.e=$('#monitor_live_'+d.mid+user.auth_token)
|
||||
if(d.e.length>0){$.ccio.cx({f:'monitor',ff:'watch_on',id:d.mid},user)}
|
||||
break;
|
||||
case'mode_jpeg_off':
|
||||
$.ccio.op('jpeg_on',"0");
|
||||
$.each($.ccio.mon,function(n,v,x){
|
||||
$.ccio.init('jpegModeStop',v);
|
||||
if(v.watch===1){
|
||||
$.ccio.cx({f:'monitor',ff:'watch_on',id:v.mid},user)
|
||||
}
|
||||
});
|
||||
$('body').removeClass('jpegMode')
|
||||
break;
|
||||
case'mode_jpeg_on':
|
||||
$.ccio.op('jpeg_on',true);
|
||||
$.ccio.init('jpegModeAll');
|
||||
$('body').addClass('jpegMode')
|
||||
break;
|
||||
case'drawPowerVideoMainTimeLine':
|
||||
var videos = d.videos;
|
||||
var events = d.events;
|
||||
// $.pwrvid.currentlyLoading = false
|
||||
$.pwrvid.currentVideos=videos
|
||||
$.pwrvid.currentEvents=events
|
||||
$.pwrvid.e.find('.loading').hide()
|
||||
$.pwrvid.e.find('.nodata').hide()
|
||||
//$.pwrvid.drawTimeLine
|
||||
if($.pwrvid.t&&$.pwrvid.t.destroy){$.pwrvid.t.destroy()}
|
||||
data={};
|
||||
$.each(videos.videos,function(n,v){
|
||||
if(!v||!v.mid){return}
|
||||
v.mon=$.ccio.mon[v.ke+v.mid+$user.auth_token];
|
||||
// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
if(v.status>0){
|
||||
// data.push({src:v,x:v.time,y:$.ccio.timeObject(v.time).diff($.ccio.timeObject(v.end),'minutes')/-1})
|
||||
data[v.filename]={
|
||||
filename:v.filename,
|
||||
time:v.time,
|
||||
timeFormatted:$.ccio.timeObject(v.time).format('MM/DD/YYYY HH:mm'),
|
||||
endTime:v.end,
|
||||
close:$.ccio.timeObject(v.time).diff($.ccio.timeObject(v.end),'minutes')/-1,
|
||||
motion:[],
|
||||
row:v,
|
||||
position:n
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var eventsToCheck = Object.assign({},events)
|
||||
$.each(data,function(m,b){
|
||||
startTimeFormatted = $.ccio.timeObject(b.time).format('YYYY-MM-DD HH:mm:ss');
|
||||
startTime = $.ccio.timeObject(b.time).format();
|
||||
endTime = $.ccio.timeObject(b.endTime).format();
|
||||
var newSetOfEventsWithoutChecked = {};
|
||||
var eventTime
|
||||
$.each(eventsToCheck,function(n,v){
|
||||
try{
|
||||
if(v.details.videoTime.indexOf('T') > -1){
|
||||
eventTime = v.details.videoTime.split('T');
|
||||
}else{
|
||||
eventTime = v.details.videoTime.split(' ');
|
||||
}
|
||||
}catch(err){
|
||||
if(v.time.indexOf('T') > -1){
|
||||
eventTime = v.time.split('T');
|
||||
}else{
|
||||
eventTime = v.time.split(' ');
|
||||
}
|
||||
}
|
||||
eventTime[1] = eventTime[1].replace(/-/g,':'),eventTime = eventTime.join(' ');
|
||||
if(eventTime === startTimeFormatted){
|
||||
data[m].motion.push(v)
|
||||
}else if ($.ccio.timeObject(v.time).isBetween(startTime,$.ccio.timeObject(b.endTime).format())) {
|
||||
data[m].motion.push(v)
|
||||
}else{
|
||||
newSetOfEventsWithoutChecked[n] = v;
|
||||
}
|
||||
})
|
||||
eventsToCheck = newSetOfEventsWithoutChecked;
|
||||
});
|
||||
$.pwrvid.currentDataObject=data;
|
||||
if($.pwrvid.chart){
|
||||
$.pwrvid.d.empty()
|
||||
delete($.pwrvid.chart)
|
||||
}
|
||||
$.pwrvid.currentData=Object.values(data);
|
||||
if($.pwrvid.currentData.length>0){
|
||||
var labels=[]
|
||||
var Dataset1=[]
|
||||
var Dataset2=[]
|
||||
$.each(data,function(n,v){
|
||||
labels.push(v.timeFormatted)
|
||||
Dataset1.push(v.close)
|
||||
Dataset2.push(v.motion.length)
|
||||
})
|
||||
$.pwrvid.d.html("<canvas></canvas>")
|
||||
var timeFormat = 'MM/DD/YYYY HH:mm';
|
||||
var color = Chart.helpers.color;
|
||||
Chart.defaults.global.defaultFontColor = '#fff';
|
||||
var config = {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
type: 'line',
|
||||
label: lang['Video and Time Span (Minutes)'],
|
||||
backgroundColor: color(window.chartColors.blue).alpha(0.2).rgbString(),
|
||||
borderColor: window.chartColors.blue,
|
||||
data: Dataset1,
|
||||
}, {
|
||||
type: 'bar',
|
||||
showTooltip: false,
|
||||
label: lang['Counts of Motion'],
|
||||
backgroundColor: color(window.chartColors.red).alpha(0.5).rgbString(),
|
||||
borderColor: window.chartColors.red,
|
||||
data:Dataset2,
|
||||
}, ]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
title: {
|
||||
fontColor: "white",
|
||||
text: lang['Video Length (minutes) and Motion Count per video']
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
display: true,
|
||||
time: {
|
||||
format: timeFormat,
|
||||
// round: 'day'
|
||||
}
|
||||
}],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
var ctx = $.pwrvid.d.find('canvas')[0].getContext("2d");
|
||||
$.pwrvid.chart = new Chart(ctx, config);
|
||||
$.pwrvid.d.find('canvas').click(function(e) {
|
||||
var target = $.pwrvid.chart.getElementsAtEvent(e)[0];
|
||||
if(!target){return false}
|
||||
target = $.pwrvid.currentData[target._index];
|
||||
$.pwrvid.e.find('.temp').html('<li class="glM'+target.row.mid+$user.auth_token+'" mid="'+target.row.mid+'" ke="'+target.row.ke+'" status="'+target.row.status+'" file="'+target.row.filename+'" auth="'+$user.auth_token+'"><a class="btn btn-sm btn-primary" preview="video" href="'+target.row.href+'"><i class="fa fa-play-circle"></i></a></li>').find('a').click()
|
||||
});
|
||||
var colorNames = Object.keys(window.chartColors);
|
||||
}else{
|
||||
$.pwrvid.e.find('.nodata').show()
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
$user.ws=io(location.origin,{
|
||||
path : tool.checkCorrectPathEnding(location.pathname)+'socket.io'
|
||||
});
|
||||
$user.ws.on('connect',function (d){
|
||||
$(document).ready(function(e){
|
||||
$.ccio.init('id',$user);
|
||||
$.ccio.cx({f:'init',ke:$user.ke,auth:$user.auth_token,uid:$user.uid})
|
||||
if($user.details&&$user.details.links){
|
||||
$.each($user.details.links,function(n,v){
|
||||
if(v.secure==='0'){
|
||||
v.protocol='http'
|
||||
}else{
|
||||
v.protocol='https'
|
||||
}
|
||||
if(v.host.indexOf('://')>-1){
|
||||
v.URL=v.protocol+'://'+v.host.split('://')[1]
|
||||
}else{
|
||||
v.URL=v.protocol+'://'+v.host
|
||||
}
|
||||
$.get(v.URL+'/'+v.api+'/userInfo/'+v.ke,function(e){
|
||||
if(e.ok===true){
|
||||
e.user.auth_token=v.api
|
||||
$.users[v.api]=e.user
|
||||
$.users[v.api].info=v
|
||||
$.users[v.api].ws=io(v.host)
|
||||
$.users[v.api].ws.on('ping', function(d){
|
||||
$.users[v.api].ws.emit('pong',{beat:1});
|
||||
});
|
||||
$.users[v.api].ws.on('connect',function (d){
|
||||
console.log(v.host,'connected')
|
||||
$.ccio.cx({f:'init',ke:e.user.ke,auth:v.api,uid:e.user.uid},$.users[v.api])
|
||||
})
|
||||
$.users[v.api].ws.on('f',function (d){
|
||||
$.ccio.globalWebsocket(d,$.users[v.api])
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
PNotify.prototype.options.styling = "fontawesome";
|
||||
$user.ws.on('ping', function(d){
|
||||
$user.ws.emit('pong',{beat:1});
|
||||
});
|
||||
$user.ws.on('f',function (d){
|
||||
$.ccio.globalWebsocket(d)
|
||||
switch(d.f){
|
||||
case'api_key_deleted':
|
||||
if($user.uid === d.uid){
|
||||
$.ccio.init('note',{title:lang['API Key Deleted'],text:lang.APIKeyDeletedText,type:'notice'});
|
||||
$('[api_key="'+d.form.code+'"]').remove()
|
||||
}
|
||||
break;
|
||||
case'api_key_added':
|
||||
if($user.uid === d.uid){
|
||||
$.ccio.init('note',{title:lang['API Key Added'],text:lang.FiltersUpdatedText,type:'success'});
|
||||
$.ccio.tm(3,d.form,'#api_list')
|
||||
}
|
||||
break;
|
||||
case'filters_change':
|
||||
$.ccio.init('note',{title:lang['Filters Updated'],text:lang.FiltersUpdatedText,type:'success'});
|
||||
$user.details.filters=d.filters;
|
||||
$.ccio.init('filters');
|
||||
break;
|
||||
case'user_settings_change':
|
||||
$.ccio.init('note',{title:lang['Settings Changed'],text:lang.SettingsChangedText,type:'success'});
|
||||
$.ccio.init('id',d.form);
|
||||
d.form.details=JSON.parse(d.form.details)
|
||||
$('#custom_css').append(d.form.details.css)
|
||||
if(d.form.details){
|
||||
$user.details=d.form.details
|
||||
}
|
||||
break;
|
||||
case'users_online':
|
||||
$.ccio.pm('user-row',d.users);
|
||||
break;
|
||||
case'user_status_change':
|
||||
if(d.status===1){
|
||||
$.ccio.tm('user-row',d.user,null)
|
||||
}else{
|
||||
$('.user-row[uid="'+d.uid+'"][ke="'+d.ke+'"]').remove()
|
||||
}
|
||||
break;
|
||||
case'ffprobe_stop':
|
||||
$.pB.e.find('._loading').hide()
|
||||
$.pB.o.append('<div><b>END</b></div>');
|
||||
$.pB.e.find('.stop').hide();
|
||||
$.pB.e.find('[type="submit"]').show();
|
||||
break;
|
||||
case'ffprobe_start':
|
||||
$.pB.e.find('._loading').show()
|
||||
$.pB.o.empty();
|
||||
$.pB.e.find('.stop').show();
|
||||
$.pB.e.find('[type="submit"]').hide();
|
||||
break;
|
||||
case'ffprobe_data':
|
||||
$.pB.results=JSON.parse(d.data)
|
||||
$.pB.o.append($.ccio.init('jsontoblock',$.pB.results))
|
||||
break;
|
||||
case'detector_cascade_list':
|
||||
d.tmp=''
|
||||
$.each(d.cascades,function(n,v){
|
||||
d.tmp+='<li class="mdl-list__item">';
|
||||
d.tmp+='<span class="mdl-list__item-primary-content">';
|
||||
d.tmp+=v;
|
||||
d.tmp+='</span>';
|
||||
d.tmp+='<span class="mdl-list__item-secondary-action">';
|
||||
d.tmp+='<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">';
|
||||
d.tmp+='<input type="checkbox" value="'+v+'" detailContainer="detector_cascades" detailObject="'+v+'" class="detector_cascade_selection mdl-switch__input"/>';
|
||||
d.tmp+='</label>';
|
||||
d.tmp+='</span>';
|
||||
d.tmp+='</li>';
|
||||
})
|
||||
$('#detector_cascade_list').html(d.tmp)
|
||||
componentHandler.upgradeAllRegistered()
|
||||
//add auto select for preferences
|
||||
d.currentlyEditing=$.aM.e.attr('mid')
|
||||
if(d.currentlyEditing&&d.currentlyEditing!==''){
|
||||
d.currentlyEditing=JSON.parse(JSON.parse($.ccio.mon[d.currentlyEditing].details).detector_cascades)
|
||||
$.each(d.currentlyEditing,function(m,b){
|
||||
d.e=$('.detector_cascade_selection[value="'+m+'"]').prop('checked',true)
|
||||
d.p=d.e.parents('.mdl-js-switch')
|
||||
if(d.p.length>0){
|
||||
d.p.addClass('is-checked')
|
||||
}
|
||||
})
|
||||
}
|
||||
break;
|
||||
case'detector_plugged':
|
||||
if(!d.notice){d.notice=''}
|
||||
$('.shinobi-detector').show()
|
||||
$('.shinobi-detector-msg').html(d.notice)
|
||||
$('.shinobi-detector_name').text(d.plug)
|
||||
$('.shinobi-detector-'+d.plug).show()
|
||||
$('.shinobi-detector-invert').hide()
|
||||
$.aM.drawList()
|
||||
break;
|
||||
case'detector_unplugged':
|
||||
$('.stream-objects .stream-detected-object').remove()
|
||||
$('.shinobi-detector').hide()
|
||||
$('.shinobi-detector-msg').empty()
|
||||
$('.shinobi-detector_name').empty()
|
||||
$('.shinobi-detector_plug').hide()
|
||||
$('.shinobi-detector-invert').show()
|
||||
$.aM.drawList()
|
||||
break;
|
||||
case'monitor_edit_failed':
|
||||
d.pnote={title:'Monitor Not Saved',text:'<b>'+d.mon.name+'</b> <small>'+d.mon.mid+'</small> has not been saved.',type:'error'}
|
||||
switch(d.ff){
|
||||
case'max_reached':
|
||||
d.pnote.text+=' '+lang.monitorEditFailedMaxReached
|
||||
break;
|
||||
}
|
||||
$.ccio.init('note',d.pnote);
|
||||
break;
|
||||
// case'onvif_end':
|
||||
// if(Object.keys($.oB.foundMonitorsCount).length===0){
|
||||
// $.oB.e.find('._loading').hide()
|
||||
// $.oB.e.find('[type="submit"]').prop('disabled',false)
|
||||
// $.oB.o.append('<td class="text-center _notfound">Sorry, nothing was found.</td>')
|
||||
// }
|
||||
// break;
|
||||
case'onvif':
|
||||
var tempID = $.ccio.gid();
|
||||
$.oB.foundMonitors[tempID] = Object.assign({},d);
|
||||
$.oB.e.find('._loading').hide()
|
||||
$.oB.e.find('._notfound').remove()
|
||||
$.oB.e.find('[type="submit"]').prop('disabled',false)
|
||||
d.info=$.ccio.init('jsontoblock',d.info)
|
||||
if(d.uri){
|
||||
d.stream=d.uri
|
||||
}else{
|
||||
d.stream='URL not Found'
|
||||
}
|
||||
$('#onvif_probe .output_data').append('<tr onvif_row="'+tempID+'"><td><a class="btn btn-sm btn-primary copy"> <i class="fa fa-copy"></i> </a></td><td class="ip">'+d.ip+'</td><td class="port">'+d.port+'</td><td>'+$.ccio.init('jsontoblock',d.info)+'</td><td class="url">'+d.stream+'</td></tr>')
|
||||
break;
|
||||
}
|
||||
delete(d);
|
||||
});
|
||||
})
|
|
@ -0,0 +1,334 @@
|
|||
$(document).ready(function(e){
|
||||
//Timelapse Window
|
||||
$.timelapse={e:$('#timelapse')}
|
||||
$.timelapse.f=$.timelapse.e.find('form'),
|
||||
$.timelapse.meter=$.timelapse.e.find('.motion-meter'),
|
||||
$.timelapse.line=$('#timelapse_video_line'),
|
||||
$.timelapse.display=$('#timelapse_video_display'),
|
||||
$.timelapse.seekBar=$('#timelapse_seekBar'),
|
||||
$.timelapse.seekBarProgress=$.timelapse.seekBar.find('.progress-bar'),
|
||||
$.timelapse.dr=$('#timelapse_daterange'),
|
||||
$.timelapse.mL=$.timelapse.e.find('.motion_list'),
|
||||
$.timelapse.monitors=$.timelapse.e.find('.monitors_list');
|
||||
$.timelapse.playDirection='videoAfter'
|
||||
$.timelapse.playRate=15
|
||||
$.timelapse.placeholder=placeholder.getData(placeholder.plcimg({bgcolor:'#b57d00',text:'...'}))
|
||||
$.timelapse.dr.daterangepicker({
|
||||
startDate:$.ccio.timeObject().subtract(moment.duration("24:00:00")),
|
||||
endDate:$.ccio.timeObject().add(moment.duration("24:00:00")),
|
||||
timePicker: true,
|
||||
timePicker24Hour: true,
|
||||
timePickerSeconds: true,
|
||||
timePickerIncrement: 30,
|
||||
locale: {
|
||||
format: 'MM/DD/YYYY h:mm A'
|
||||
}
|
||||
},function(start, end, label){
|
||||
$.timelapse.drawTimeline()
|
||||
$.timelapse.dr.focus()
|
||||
});
|
||||
$.timelapse.f.find('input,select').change(function(){
|
||||
$.timelapse.f.submit()
|
||||
})
|
||||
$.timelapse.f.submit(function(e){
|
||||
e.preventDefault();
|
||||
$.timelapse.drawTimeline()
|
||||
return false;
|
||||
})
|
||||
$.timelapse.drawTimeline=function(getData){
|
||||
var e={};
|
||||
if(getData===undefined){getData=true}
|
||||
var mid = $.timelapse.monitors.val()
|
||||
e.dateRange=$.timelapse.dr.data('daterangepicker');
|
||||
e.dateRange={startDate:e.dateRange.startDate,endDate:e.dateRange.endDate}
|
||||
e.videoURL=$.ccio.init('location',$user)+$user.auth_token+'/videos/'+$user.ke+'/'+mid;
|
||||
e.videoURL+='?limit=100&start='+$.ccio.init('th',e.dateRange.startDate)+'&end='+$.ccio.init('th',e.dateRange.endDate);
|
||||
e.next=function(videos){
|
||||
$.timelapse.currentVideos={}
|
||||
e.tmp=''
|
||||
$.each(videos.videos,function(n,v){
|
||||
if(!v||!v.time){return}
|
||||
// v.filename=$.ccio.init('tf',v.time)+'.'+v.ext;
|
||||
v.videoBefore=videos.videos[n-1];
|
||||
v.videoAfter=videos.videos[n+1];
|
||||
// if(v.href.charAt(0)==='/'){
|
||||
// v.href=$.ccio.init('location',user)+(v.href.substring(1))
|
||||
// v.videoURL=$.ccio.init('location',user)+(v.videoURL.substring(1))
|
||||
// }
|
||||
v.position=n;
|
||||
$.timelapse.currentVideos[v.filename]=v;
|
||||
e.tmp+='<li class="glM'+v.mid+$user.auth_token+' list-group-item timelapse_video flex-block" timelapse="video" file="'+v.filename+'" href="'+v.href+'" mid="'+v.mid+'" ke="'+v.ke+'" auth="'+$user.auth_token+'">'
|
||||
e.tmp+='<div class="flex-block">'
|
||||
e.tmp+='<div class="flex-unit-3"><div class="frame" style="background-image:url('+$.timelapse.placeholder+')"></div></div>'
|
||||
e.tmp+='<div class="flex-unit-3"><div><span title="'+v.time+'" class="livestamp"></span></div><div>'+v.filename+'</div></div>'
|
||||
e.tmp+='<div class="flex-unit-3 text-right"><a class="btn btn-default" download="'+v.mid+'-'+v.filename+'" href="'+v.href+'"> <i class="fa fa-download"></i> </a> <a class="btn btn-danger" video="delete" href="'+$.ccio.init('videoHrefToDelete',v.href)+'"> <i class="fa fa-trash-o"></i> </a></div>'
|
||||
e.tmp+='</div>'
|
||||
e.tmp+='<div class="flex-block">'
|
||||
e.tmp+='<div class="flex-unit-3"><div class="progress"><div class="progress-bar progress-bar-primary" role="progressbar" style="width:0%"></div></div></div>'
|
||||
e.tmp+='</div>'
|
||||
e.tmp+='</li>'
|
||||
})
|
||||
$.timelapse.line.html(e.tmp)
|
||||
$.ccio.init('ls')
|
||||
if(getData===true){
|
||||
e.timeout=50
|
||||
}else{
|
||||
e.timeout=2000
|
||||
}
|
||||
setTimeout(function(){
|
||||
if($.timelapse.e.find('.timelapse_video.active').length===0){
|
||||
$.timelapse.e.find('[timelapse="video"]').first().click()
|
||||
}
|
||||
},e.timeout)
|
||||
}
|
||||
if(getData===true){
|
||||
$.getJSON(e.videoURL,function(videos){
|
||||
videos.videos=videos.videos.reverse()
|
||||
$.timelapse.currentVideosArray=videos
|
||||
e.next(videos)
|
||||
})
|
||||
}else{
|
||||
e.next($.timelapse.currentVideosArray)
|
||||
}
|
||||
}
|
||||
$.timelapse.playButtonIcon = $.timelapse.e.find('[timelapse="play"]').find('i')
|
||||
$.timelapse.timelapseSpeedUseBasicSwitch = $('#timelapseSpeedUseBasic')
|
||||
$.timelapse.timelapseSpeedUseBasicSwitch.on('change',function(){
|
||||
var el = $.timelapse.e.find('.timelapseSpeedUseBasicSwitch')
|
||||
if($(this).is(':checked')){
|
||||
el.hide()
|
||||
}else{
|
||||
el.show()
|
||||
}
|
||||
$.timelapse.play()
|
||||
})
|
||||
$.timelapse.getUseBasicStatus = function(){return $.timelapse.timelapseSpeedUseBasicSwitch.prop('checked')}
|
||||
$.timelapse.onPlayPause = function(toggleGui,secondWind){
|
||||
if($.timelapse.paused === true){
|
||||
$.timelapse.paused = false
|
||||
if(toggleGui === true)$.timelapse.play();
|
||||
}else{
|
||||
$.timelapse.paused = true
|
||||
if(toggleGui === true)$.timelapse.pause(secondWind);
|
||||
}
|
||||
}
|
||||
$.timelapse.pause = function(secondWind){
|
||||
//secondWind is used because sometimes pause can be pressed just as a video ends and the pause command does not register on the next video.
|
||||
var videoNow = $.timelapse.display.find('video.videoNow')[0]
|
||||
var pause = function(){
|
||||
if(videoNow.paused == false)videoNow.pause()
|
||||
clearInterval($.timelapse.interval)
|
||||
$.timelapse.playButtonIcon.removeClass('fa-pause').addClass('fa-play')
|
||||
}
|
||||
pause()
|
||||
if(secondWind === true)setTimeout(pause,250);
|
||||
}
|
||||
$.timelapse.play = function(x){
|
||||
var videoNow = $.timelapse.display.find('video.videoNow')[0]
|
||||
$.timelapse.pause()
|
||||
clearInterval($.timelapse.interval)
|
||||
if($.timelapse.getUseBasicStatus()){
|
||||
videoNow.playbackRate = $.timelapse.playRate
|
||||
if(videoNow.paused)videoNow.play()
|
||||
}else{
|
||||
videoNow.playbackRate = 1.0
|
||||
$.timelapse.interval = setInterval(function(){
|
||||
if(videoNow.currentTime >= videoNow.duration - .2){
|
||||
clearInterval($.timelapse.interval)
|
||||
videoNow.currentTime = videoNow.duration
|
||||
}else{
|
||||
videoNow.currentTime += .5
|
||||
}
|
||||
},500 / $.timelapse.playRate)
|
||||
}
|
||||
$.timelapse.playButtonIcon.removeClass('fa-play').addClass('fa-pause')
|
||||
}
|
||||
$.timelapse.rewind = function(e){
|
||||
var videoNow = $.timelapse.display.find('video.videoNow')[0]
|
||||
$.timelapse.pause()
|
||||
videoNow.playbackRate = 1.0
|
||||
clearInterval($.timelapse.interval)
|
||||
$.timelapse.interval = setInterval(function(){
|
||||
if(videoNow.currentTime <= 0.2){
|
||||
clearInterval($.timelapse.interval)
|
||||
videoNow.currentTime = 0
|
||||
$('[timelapse][href="'+e.videoCurrentBefore.attr('video')+'"]').click()
|
||||
var videoNowNew = $.timelapse.display.find('video.videoNow')[0]
|
||||
videoNowNew.pause()
|
||||
videoNowNew.currentTime = videoNowNew.duration - 0.1
|
||||
$.timelapse.e.find('[timelapse="stepBackBack"]').click()
|
||||
}else{
|
||||
videoNow.currentTime += -.5
|
||||
}
|
||||
},500 / $.timelapse.playRate)
|
||||
$.timelapse.playButtonIcon.removeClass('fa-play').addClass('fa-pause')
|
||||
}
|
||||
$.timelapse.e.on('click','[timelapse]',function(){
|
||||
var e={}
|
||||
e.e=$(this)
|
||||
e.videoCurrentNow=$.timelapse.display.find('.videoNow')
|
||||
e.videoCurrentAfter=$.timelapse.display.find('.videoAfter')
|
||||
e.videoCurrentBefore=$.timelapse.display.find('.videoBefore')
|
||||
if($.timelapse.videoInterval){
|
||||
clearInterval($.timelapse.videoInterval);
|
||||
}
|
||||
switch(e.e.attr('timelapse')){
|
||||
case'download':
|
||||
$.timelapse.line.find('.active [download]').click()
|
||||
break;
|
||||
case'mute':
|
||||
e.videoCurrentNow[0].muted = !e.videoCurrentNow[0].muted
|
||||
$.timelapse.videoNowIsMuted = e.videoCurrentNow[0].muted
|
||||
e.e.find('i').toggleClass('fa-volume-off fa-volume-up')
|
||||
e.e.toggleClass('btn-danger')
|
||||
break;
|
||||
case'play':
|
||||
e.videoCurrentNow[0].playbackRate = $.timelapse.playRate;
|
||||
$.timelapse.onPlayPause(true,true)
|
||||
break;
|
||||
case'setPlayBackRate':
|
||||
$.timelapse.pause()
|
||||
$.timelapse.playRate = parseFloat(e.e.attr('playRate'))
|
||||
$.timelapse.play()
|
||||
break;
|
||||
case'stepFrontFront':
|
||||
e.add=e.e.attr('add')
|
||||
e.stepFrontFront=parseInt(e.e.attr('stepFrontFront'))
|
||||
if(!e.stepFrontFront||isNaN(e.stepFrontFront)){e.stepFrontFront = 5}
|
||||
if(e.add==="0"){
|
||||
$.timelapse.playRate = e.stepFrontFront
|
||||
}else{
|
||||
$.timelapse.playRate += e.stepFrontFront
|
||||
}
|
||||
e.videoCurrentNow[0].playbackRate = $.timelapse.playRate;
|
||||
e.videoCurrentNow[0].play()
|
||||
break;
|
||||
case'stepFront':
|
||||
e.videoCurrentNow[0].currentTime += 5;
|
||||
e.videoCurrentNow[0].pause()
|
||||
break;
|
||||
case'stepBackBack':
|
||||
// e.videoCurrentNow=$.timelapse.display.find('.videoNow')
|
||||
// e.videoCurrentAfter=$.timelapse.display.find('.videoAfter')
|
||||
// e.videoCurrentBefore=$.timelapse.display.find('.videoBefore')
|
||||
$.timelapse.rewind(e)
|
||||
break;
|
||||
case'stepBack':
|
||||
e.videoCurrentNow[0].currentTime += -5;
|
||||
e.videoCurrentNow[0].pause()
|
||||
break;
|
||||
case'video':
|
||||
$.timelapse.e.find('video').each(function(n,v){
|
||||
v.pause()
|
||||
})
|
||||
e.drawVideoHTML=function(position){
|
||||
var video
|
||||
var exisitingElement=$.timelapse.display.find('.'+position)
|
||||
if(position){
|
||||
video=e.video[position]
|
||||
}else{
|
||||
position='videoNow'
|
||||
video=e.video
|
||||
}
|
||||
if(video){
|
||||
$.timelapse.display.append('<video class="video_video '+position+'" video="'+video.href+'" preload><source src="'+video.href+'" type="video/'+video.ext+'"></video>')
|
||||
}
|
||||
}
|
||||
e.filename=e.e.attr('file')
|
||||
e.video=$.timelapse.currentVideos[e.filename]
|
||||
e.videoIsSame=(e.video.href==e.videoCurrentNow.attr('video'))
|
||||
e.videoIsAfter=(e.video.href==e.videoCurrentAfter.attr('video'))
|
||||
e.videoIsBefore=(e.video.href==e.videoCurrentBefore.attr('video'))
|
||||
if(e.videoIsSame||e.videoIsAfter||e.videoIsBefore){
|
||||
switch(true){
|
||||
case e.videoIsSame:
|
||||
$.ccio.log('$.timelapse','videoIsSame')
|
||||
e.videoNow=$.timelapse.display.find('video.videoNow')
|
||||
if(e.videoNow[0].paused===true){
|
||||
e.videoNow[0].play()
|
||||
}else{
|
||||
e.videoNow[0].pause()
|
||||
}
|
||||
return
|
||||
break;
|
||||
case e.videoIsAfter:
|
||||
$.ccio.log('$.timelapse','videoIsAfter')
|
||||
e.videoCurrentBefore.remove()
|
||||
e.videoCurrentAfter.removeClass('videoAfter').addClass('videoNow')
|
||||
e.videoCurrentNow.removeClass('videoNow').addClass('videoBefore')
|
||||
e.drawVideoHTML('videoAfter')
|
||||
break;
|
||||
case e.videoIsBefore:
|
||||
$.ccio.log('$.timelapse','videoIsBefore')
|
||||
e.videoCurrentAfter.remove()
|
||||
e.videoCurrentBefore.removeClass('videoBefore').addClass('videoNow')
|
||||
e.videoCurrentNow.removeClass('videoNow').addClass('videoAfter')
|
||||
e.drawVideoHTML('videoBefore')
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
$.ccio.log('$.timelapse','newSetOf3')
|
||||
$.timelapse.display.empty()
|
||||
e.drawVideoHTML()//videoNow
|
||||
e.drawVideoHTML('videoBefore')
|
||||
e.drawVideoHTML('videoAfter')
|
||||
}
|
||||
$.timelapse.display.find('video').each(function(n,v){
|
||||
v.addEventListener('loadeddata', function() {
|
||||
e.videoCurrentAfterPreview=$('.timelapse_video[href="'+$(v).attr('video')+'"] .frame')
|
||||
if(e.videoCurrentAfterPreview.attr('set')!=='1'){
|
||||
$.ccio.snapshotVideo(v,function(url,buffer){
|
||||
e.videoCurrentAfterPreview.attr('set','1').css('background-image','url('+url+')')
|
||||
if($(v).hasClass('videoAfter')){
|
||||
v.currentTime=0
|
||||
v.pause()
|
||||
}
|
||||
})
|
||||
}
|
||||
}, false);
|
||||
})
|
||||
e.videoNow=$.timelapse.display.find('video.videoNow')[0]
|
||||
if($.timelapse.videoNowIsMuted){
|
||||
e.videoNow.muted=true
|
||||
}
|
||||
$.timelapse.playButtonIcon.removeClass('fa-pause').addClass('fa-play')
|
||||
$.timelapse.onended = function() {
|
||||
$.timelapse.line.find('[file="'+e.video[$.timelapse.playDirection].filename+'"]').click()
|
||||
};
|
||||
e.videoNow.onended = $.timelapse.onended
|
||||
e.videoNow.onerror = $.timelapse.onended
|
||||
//
|
||||
$(e.videoNow)
|
||||
.off('play').on('play',$.timelapse.play)
|
||||
.off('pause').on('pause',$.timelapse.onPlayPause)
|
||||
.off('timeupdate').on('timeupdate',function(){
|
||||
var value= (( e.videoNow.currentTime / e.videoNow.duration ) * 100)+"%"
|
||||
$.timelapse.seekBarProgress.css("width",value);
|
||||
$.timelapse.e.find('.timelapse_video[file="'+e.filename+'"] .progress-bar').css("width",value);
|
||||
})
|
||||
$.timelapse.play()
|
||||
$.timelapse.seekBar.off("click").on("click", function(seek){
|
||||
var offset = $(this).offset();
|
||||
var left = (seek.pageX - offset.left);
|
||||
var totalWidth = $.timelapse.seekBar.width();
|
||||
var percentage = ( left / totalWidth );
|
||||
var vidTime = e.videoNow.duration * percentage;
|
||||
e.videoNow.currentTime = vidTime;
|
||||
});
|
||||
|
||||
$.ccio.log('$.timelapse',e.video)
|
||||
$.timelapse.line.find('.timelapse_video').removeClass('active')
|
||||
e.videoCurrentNow=$.timelapse.display.find('.videoNow')
|
||||
e.e.addClass('active')
|
||||
if ($('#timelapse_video_line:hover').length === 0) {
|
||||
$.timelapse.line.animate({scrollTop:$.timelapse.line.scrollTop() + e.e.position().top - $.timelapse.line.height()/2 + e.e.height()/2 - 40});
|
||||
}
|
||||
break;
|
||||
}
|
||||
$.timelapse.e.find('.timelapse_playRate').text('x'+$.timelapse.playRate)
|
||||
})
|
||||
$.timelapse.e.on('hidden.bs.modal',function(e){
|
||||
delete($.timelapse.currentVideos)
|
||||
delete($.timelapse.currentVideosArray)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,101 @@
|
|||
$(document).ready(function(e){
|
||||
//settings window
|
||||
$.sM={e:$('#settings')};
|
||||
$.sM.f=$.sM.e.find('form');
|
||||
$.sM.links=$('#linkShinobi');
|
||||
$.sM.g=$('#settings_mon_groups');
|
||||
$.sM.md=$.sM.f.find('[detail]');
|
||||
$.sM.md.change($.ccio.form.details);
|
||||
$.sM.f.find('[selector]').change(function(e){
|
||||
e.v=$(this).val();e.a=$(this).attr('selector')
|
||||
$.sM.f.find('.'+e.a+'_input').hide()
|
||||
$.sM.f.find('.'+e.a+'_'+e.v).show();
|
||||
$.sM.f.find('.'+e.a+'_text').text($(this).find('option:selected').text())
|
||||
});
|
||||
$.sM.writewMonGroups=function(){
|
||||
$.sM.f.find('[detail="mon_groups"]').val(JSON.stringify($user.mon_groups)).change()
|
||||
}
|
||||
$.sM.reDrawMonGroups=function(){
|
||||
$.sM.g.empty();
|
||||
$.ccio.pm('option',$user.mon_groups,'#settings_mon_groups')
|
||||
$.sM.g.change();
|
||||
};
|
||||
$.sM.f.submit(function(e){
|
||||
e.preventDefault();
|
||||
$.sM.writewMonGroups()
|
||||
$.sM.linkChange()
|
||||
e.e=$(this),e.s=e.e.serializeObject();
|
||||
e.er=[];
|
||||
if(e.s.pass!==''&&e.password_again===e.s.pass){e.er.push(lang['Passwords don\'t match'])};
|
||||
if(e.er.length>0){$.sM.e.find('.msg').html(e.er.join('<br>'));return;}
|
||||
$.each(e.s,function(n,v){e.s[n]=v.trim()})
|
||||
$.ccio.cx({f:'settings',ff:'edit',form:e.s})
|
||||
$.sM.e.modal('hide')
|
||||
});
|
||||
$.sM.e.on('shown.bs.modal',function(){
|
||||
$.sM.reDrawMonGroups()
|
||||
})
|
||||
$.sM.g.change(function(e){
|
||||
e.v=$(this).val();
|
||||
e.group=$user.mon_groups[e.v];
|
||||
if(!e.group){return}
|
||||
$.sM.selectedMonGroup=e.group;
|
||||
$.each(e.group,function(n,v){
|
||||
$.sM.f.find('[group="'+n+'"]').val(v)
|
||||
})
|
||||
});
|
||||
$.sM.f.find('[group]').change(function(){
|
||||
e = {}
|
||||
e.v = $.sM.g.val()
|
||||
if(!e.v||e.v==''){
|
||||
e.e = $.sM.f.find('[group="name"]')
|
||||
e.name = e.e.val()
|
||||
$('.mon_groups .add').click();
|
||||
e.v = $.sM.g.val()
|
||||
e.e.val(e.name)
|
||||
}
|
||||
e.group=$user.mon_groups[e.v];
|
||||
$.sM.f.find('[group]').each(function(n,v){
|
||||
v=$(v)
|
||||
e.group[v.attr('group')]=v.val()
|
||||
});
|
||||
$user.mon_groups[e.v]=e.group;
|
||||
$.sM.g.find('option[value="'+$.sM.g.val()+'"]').text(e.group.name)
|
||||
$.sM.writewMonGroups()
|
||||
})
|
||||
$.sM.f.on('click','.mon_groups .delete',function(e){
|
||||
e.v=$.sM.g.val();
|
||||
delete($user.mon_groups[e.v]);
|
||||
$.sM.reDrawMonGroups()
|
||||
})
|
||||
$.sM.f.on('click','.mon_groups .add',function(e){
|
||||
e.gid=$.ccio.gid(5);
|
||||
$user.mon_groups[e.gid]={id:e.gid,name:e.gid};
|
||||
$.sM.g.append($.ccio.tm('option',$user.mon_groups[e.gid]));
|
||||
$.sM.g.val(e.gid)
|
||||
$.sM.g.change();
|
||||
});
|
||||
$.sM.linkChange=function(){
|
||||
var e={};
|
||||
e.e=$.sM.e.find('[name="details"]')
|
||||
e.details=JSON.parse(e.e.val())
|
||||
e.details.links=[]
|
||||
$.sM.links.find('.linksGroup').each(function(n,v){
|
||||
var arr={}
|
||||
$(v).find('[link]').each(function(m,b){
|
||||
arr[$(b).attr('link')]=$(b).val()
|
||||
})
|
||||
e.details.links.push(arr)
|
||||
})
|
||||
e.e.val(JSON.stringify(e.details))
|
||||
}
|
||||
$.sM.f.on('change','[link]',$.sM.linkChange)
|
||||
$.sM.e.on('click','.linkShinobi .delete',function(){
|
||||
$(this).parents('.linksGroup').remove()
|
||||
$.sM.linkChange()
|
||||
})
|
||||
$.sM.e.find('.linkShinobi .add').click(function(){
|
||||
$.ccio.tm('link-set',{},'#linkShinobi')
|
||||
$.sM.linkChange()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,147 @@
|
|||
$(document).ready(function(e){
|
||||
//videos window
|
||||
$.vidview={
|
||||
e:$('#videos_viewer'),
|
||||
pages:$('#videos_viewer_pages'),
|
||||
limit:$('#videos_viewer_limit'),
|
||||
dr:$('#videos_viewer_daterange'),
|
||||
preview:$('#videos_viewer_preview'),
|
||||
set:$('#videos_viewer_set')
|
||||
}
|
||||
$.vidview.set.change(function(){
|
||||
var el = $(this)
|
||||
var isCloud = (el.val() === 'cloud')
|
||||
var zipDlButton = $.vidview.e.find('.export_selected')
|
||||
if(isCloud){
|
||||
zipDlButton.hide()
|
||||
}else{
|
||||
zipDlButton.show()
|
||||
}
|
||||
|
||||
})
|
||||
$.vidview.f=$.vidview.e.find('form')
|
||||
$.vidview.dr.daterangepicker({
|
||||
startDate:$.ccio.timeObject().subtract(moment.duration("24:00:00")),
|
||||
endDate:$.ccio.timeObject().add(moment.duration("24:00:00")),
|
||||
timePicker: true,
|
||||
timePicker24Hour: true,
|
||||
timePickerSeconds: true,
|
||||
timePickerIncrement: 30,
|
||||
locale: {
|
||||
format: 'MM/DD/YYYY h:mm A'
|
||||
}
|
||||
},function(start, end, label){
|
||||
$.vidview.launcher.click()
|
||||
$.vidview.dr.focus()
|
||||
});
|
||||
$.vidview.e.on('change','#videos_select_all',function(e){
|
||||
e.e=$(this);
|
||||
e.p=e.e.prop('checked')
|
||||
e.a=$.vidview.e.find('input[type=checkbox][name]')
|
||||
if(e.p===true){
|
||||
e.a.prop('checked',true)
|
||||
}else{
|
||||
e.a.prop('checked',false)
|
||||
}
|
||||
})
|
||||
$.vidview.f.submit(function(e){
|
||||
e.preventDefault();
|
||||
$.vidview.launcher.click()
|
||||
return false;
|
||||
})
|
||||
$('#videos_viewer_limit,#videos_viewer_daterange,#videos_viewer_set').change(function(){
|
||||
$.vidview.f.submit()
|
||||
})
|
||||
$.vidview.getSelected = function(getArray){
|
||||
var arr = {}
|
||||
if(getArray){
|
||||
arr = []
|
||||
}
|
||||
$.vidview.f.find('[data-ke] input:checked').each(function(n,v){
|
||||
v=$(v).parents('tr')
|
||||
if(getArray){
|
||||
arr.push({filename:v.attr('data-file'),mid:v.attr('data-mid'),auth:v.attr('data-auth')})
|
||||
}else{
|
||||
arr[v.attr('data-file')]={mid:v.attr('data-mid'),auth:v.attr('data-auth')}
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
$.vidview.e.find('.delete_selected').click(function(){
|
||||
e = {}
|
||||
e.s = $.vidview.getSelected()
|
||||
if(Object.keys(e.s).length === 0){
|
||||
$.ccio.init('note',{
|
||||
title:'No Videos Selected',
|
||||
text:'You must choose at least one video.',
|
||||
type:'error'
|
||||
},$user);
|
||||
return
|
||||
}
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete Selected Videos'])
|
||||
e.html=lang.DeleteSelectedVideosMsg+'<div style="margin-bottom:15px"></div>'
|
||||
var deleteLinks = []
|
||||
$.each(e.s,function(n,v){
|
||||
e.html+=n+'<br>';
|
||||
if($.vidview.loadedVideos[n])deleteLinks.push($.vidview.loadedVideos[n].links.deleteVideo)
|
||||
})
|
||||
$.confirm.body.html(e.html)
|
||||
$.confirm.click({title:'Delete Video',class:'btn-danger'},function(){
|
||||
$.each(deleteLinks,function(n,link){
|
||||
$.getJSON(link,function(d){
|
||||
$.ccio.log(d)
|
||||
})
|
||||
})
|
||||
});
|
||||
})
|
||||
$.vidview.e.find('.export_selected').click(function(){
|
||||
e = {}
|
||||
var videos = $.vidview.getSelected(true)
|
||||
if(videos.length === 0){
|
||||
$.ccio.init('note',{
|
||||
title:'No Videos Selected',
|
||||
text:'You must choose at least one video.',
|
||||
type:'error'
|
||||
},$user);
|
||||
return
|
||||
}
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Export Selected Videos'])
|
||||
var html = lang.ExportSelectedVideosMsg+'<div style="margin-bottom:15px"></div>'
|
||||
$.each(videos,function(n,v){
|
||||
html+=v.filename+'<br>';
|
||||
})
|
||||
$.confirm.body.html(html)
|
||||
$.confirm.click({title:'Export Video',class:'btn-danger'},function(){
|
||||
var queryVariables = []
|
||||
queryVariables.push('videos='+JSON.stringify(videos))
|
||||
if($.ccio.useUTC === true){
|
||||
queryVariables.push('isUTC=true')
|
||||
}
|
||||
console.log(queryVariables)
|
||||
var downloadZip = $.ccio.init('location',$user)+$user.auth_token+'/zipVideos/'+$user.ke+'?'+queryVariables.join('&')
|
||||
$('#temp').html('<iframe>a</iframe>').find('iframe').attr('src',downloadZip);
|
||||
});
|
||||
})
|
||||
$.vidview.pages.on('click','[page]',function(e){
|
||||
e.limit=$.vidview.limit.val();
|
||||
e.page=$(this).attr('page');
|
||||
$.vidview.current_page=e.page;
|
||||
if(e.limit.replace(/ /g,'')===''){
|
||||
e.limit='100';
|
||||
}
|
||||
if(e.limit.indexOf(',')>-1){
|
||||
e.limit=parseInt(e.limit.split(',')[1])
|
||||
}else{
|
||||
e.limit=parseInt(e.limit)
|
||||
}
|
||||
$.vidview.limit.val((parseInt(e.page)-1)+'00,'+e.limit)
|
||||
$.vidview.launcher.click()
|
||||
})
|
||||
$.vidview.e.on('click','.preview',function(e){
|
||||
e.preventDefault()
|
||||
e=$(this)
|
||||
$.vidview.preview.html('<video class="video_video" video="'+e.attr('href')+'" preload controls autoplay><source src="'+e.attr('href')+'" type="video/mp4"></video>')
|
||||
})
|
||||
})
|
|
@ -1156,7 +1156,9 @@ switch($user.details.lang){
|
|||
tmp+='</li>';
|
||||
break;
|
||||
case'option':
|
||||
tmp+='<option auth="'+user.auth_token+'" value="'+d.id+'">'+d.name+'</option>'
|
||||
var selected = ''
|
||||
if(d.selected === true){selected = ' selected'}
|
||||
tmp+='<option auth="'+user.auth_token+'"'+selected+' value="'+d.id+'">'+d.name+'</option>'
|
||||
break;
|
||||
case'stream-element':
|
||||
try{k.d=JSON.parse(d.details);}catch(er){k.d=d.details}
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/fullcalendar.min.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/bootstrap-table.min.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/main.dash2.css">
|
||||
<% customAutoLoad.adminLibsCss.forEach(function(lib){ %>
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/<%-lib%>">
|
||||
<% }) %>
|
||||
<body class="shinobi-bg">
|
||||
<div class="container-fluid">
|
||||
<div class="container">
|
||||
|
@ -80,8 +83,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var adminApiPrefix = "<%=originalURL%><%=config.webPaths.adminApiPrefix%>"
|
||||
</script>
|
||||
<% include blocks/confirm.ejs %>
|
||||
<% include blocks/subpermissions.ejs %>
|
||||
<% customAutoLoad.adminPageBlocks.forEach(function(block){ %>
|
||||
<%- include(block) %>
|
||||
<% }) %>
|
||||
</body>
|
||||
<script><% include ../libs/js/basic.js %></script>
|
||||
<script><% include ../libs/js/socket.io.js %></script>
|
||||
|
@ -275,3 +284,6 @@ $('body')
|
|||
localStorage.removeItem('ShinobiLogin_'+location.host);location.href=location.href;
|
||||
})
|
||||
</script>
|
||||
<% customAutoLoad.adminLibsJs.forEach(function(lib){ %>
|
||||
<script src="<%-window.libURL%>libs/js/<%-lib%>"></script>
|
||||
<% }) %>
|
||||
|
|
|
@ -93,3 +93,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.apiwindow.js"></script>
|
||||
|
|
|
@ -259,3 +259,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.detectorfilter.js"></script>
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
<div class="form-group-group blue where">
|
||||
<h4><%- lang['Find Where'] %>
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-default btn-xs add"> <i class="fa fa-plus"></i> </a>
|
||||
<a class="btn btn-danger btn-xs remove"> <i class="fa fa-minus"></i> </a>
|
||||
<a class="btn btn-default btn-xs add"> <i class="fa fa-plus"></i> </a>
|
||||
<a class="btn btn-danger btn-xs remove"> <i class="fa fa-minus"></i> </a>
|
||||
</div>
|
||||
</h4>
|
||||
<div id="filters_where">
|
||||
|
@ -39,20 +39,20 @@
|
|||
<div class="form-group col-md-4">
|
||||
<label>
|
||||
<div><select class="form-control" name="sort_by">
|
||||
<option value="time" selected><%- lang['Start Time'] %></option>
|
||||
<option value="end"><%- lang['End Time'] %></option>
|
||||
<option value="time" selected><%- lang['Start Time'] %></option>
|
||||
<option value="end"><%- lang['End Time'] %></option>
|
||||
<option value="mid"><%- lang['Monitor ID'] %></option>
|
||||
<option value="ext"><%- lang['File Type'] %></option>
|
||||
<option value="size"><%- lang['Filesize'] %></option>
|
||||
<option value="status"><%- lang['Video Status'] %></option>
|
||||
<option value="ext"><%- lang['File Type'] %></option>
|
||||
<option value="size"><%- lang['Filesize'] %></option>
|
||||
<option value="status"><%- lang['Video Status'] %></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label>
|
||||
<div><select class="form-control" name="sort_by_direction">
|
||||
<option value="ASC" selected><%- lang['ASC'] %></option>
|
||||
<option value="DESC"><%- lang['DESC'] %></option>
|
||||
<option value="ASC" selected><%- lang['ASC'] %></option>
|
||||
<option value="DESC"><%- lang['DESC'] %></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -68,8 +68,8 @@
|
|||
<div class="form-group">
|
||||
<label><div><span><%- lang['Enabled'] %></span></div>
|
||||
<div><select class="form-control" name="enabled">
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -77,24 +77,24 @@
|
|||
<div class="form-group col-md-12 hidden">
|
||||
<label><div><span><%- lang['Archive'] %></span></div>
|
||||
<div><select class="form-control" name="archive">
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label><div><span><%- lang['Email Details'] %></span></div>
|
||||
<div><select class="form-control" name="email">
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label><div><span><%- lang['Delete Matches'] %></span></div>
|
||||
<div><select class="form-control" name="delete">
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
<option value="0" selected><%- lang['No'] %></option>
|
||||
<option value="1"><%- lang['Yes'] %></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -115,4 +115,5 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.cronfilter.js"></script>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<div class="fixed-table-container">
|
||||
<div class="fixed-table-body">
|
||||
<table class="table table-striped">
|
||||
<tbody class="search-body"></tbody>
|
||||
<tbody class="search-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -48,4 +48,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.logviewer.js"></script>
|
||||
|
|
|
@ -185,7 +185,7 @@
|
|||
<script>
|
||||
//add new
|
||||
$.aN={e:$('#add_edit')};$.aN.f=$.aN.e.find('form')
|
||||
$.aN.modeIsEdit = false
|
||||
$.aN.modeIsEdit = function(){return $('#edit').is(':checked')}
|
||||
$.aN.f.submit(function(e){
|
||||
e.preventDefault();
|
||||
var formValues = $.aN.f.serializeObject()
|
||||
|
@ -193,7 +193,7 @@ $.aN.f.submit(function(e){
|
|||
data: formValues
|
||||
}
|
||||
var webPath = 'registerAdmin'
|
||||
if($.aN.modeIsEdit){
|
||||
if($.aN.modeIsEdit()){
|
||||
webPath = 'editAdmin'
|
||||
postData.account = $.aN.selected
|
||||
}
|
||||
|
@ -210,14 +210,23 @@ $.aN.e.on('change','[name="mail"]',function(){
|
|||
var thisVal = $(this).val()
|
||||
$.each(users,function(n,user){
|
||||
if($.aN.selected && user.ke !== $.aN.selected.ke && thisVal.toLowerCase() === user.mail.toLowerCase()){
|
||||
new PNotify({text:"<%=lang['Email address is in use.']%>",type:'error'})
|
||||
new PNotify({text:lang['Email address is in use.'],type:'error'})
|
||||
}
|
||||
})
|
||||
})
|
||||
//client side group key check
|
||||
$.aN.e.on('change','[name="ke"]',function(){
|
||||
var thisVal = $(this).val()
|
||||
$.each(users,function(n,user){
|
||||
if(!$.aN.modeIsEdit() && user.ke === thisVal){
|
||||
new PNotify({text:lang['Group Key is in use.'] + ' ' + lang['Create Sub-Accounts at /admin'],type:'error'})
|
||||
}
|
||||
})
|
||||
})
|
||||
$.aN.e.on('change','[detail]',function(){
|
||||
e = {}
|
||||
e.ar = {}
|
||||
if($.aN.modeIsEdit){
|
||||
if($.aN.modeIsEdit()){
|
||||
try{
|
||||
e.ar = Object.assign(JSON.parse($.aN.selected.details),{})
|
||||
}catch(err){
|
||||
|
@ -232,12 +241,10 @@ $.aN.e.on('change','[detail]',function(){
|
|||
})
|
||||
$('#edit').change(function(e){
|
||||
if($('#edit').is(':checked')){
|
||||
$.aN.modeIsEdit = true
|
||||
$('#title').text("<%-lang['Edit']%>")
|
||||
$('#title').text(lang['Edit'])
|
||||
$.aN.e.find('[name="ke"]').prop('disabled',true)
|
||||
}else{
|
||||
$.aN.modeIsEdit = false
|
||||
$('#title').text("<%-lang['Add New']%>")
|
||||
$('#title').text(lang['Add New'])
|
||||
$.aN.e.find('input,select').prop('disabled',false)
|
||||
}
|
||||
$.aN.e.find('[detail]').first().change()
|
||||
|
@ -288,6 +295,7 @@ $.aC.e.on('click','.delete',function(e){
|
|||
});
|
||||
})
|
||||
$.aC.e.on('click','.permission',function(e){
|
||||
$('#edit').prop('checked',true).change().parent().addClass('is-checked')
|
||||
$.aN.e.modal('show')
|
||||
e.e=$(this).parents('tr');
|
||||
e.u=e.e.attr('ke');
|
||||
|
@ -303,7 +311,6 @@ $.aC.e.on('click','.permission',function(e){
|
|||
$.each(JSON.parse(e.account.details),function(n,v){
|
||||
$.aN.e.find('[detail="'+n+'"]').val(v)
|
||||
})
|
||||
$('#edit').prop('checked',true).change().parent().addClass('is-checked')
|
||||
// $.pR.e.modal('show');
|
||||
|
||||
})
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
<div class="modal dark fade" id="monitorStates" role="dialog" aria-labelledby="monitorStatesLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title" id="monitorStatesLabel"><i class="fa fa-align-right"></i> <%-lang['Monitor States']%></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<div><select class="form-control" id="monitorStatesSelector">
|
||||
<option value=""><%-lang['Add New']%></option>
|
||||
<optgroup label="<%-lang['Saved Presets']%>"></optgroup>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group-group green">
|
||||
<h4><%- lang['Preset'] %>
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-danger btn-xs delete" style="display:none"> <i class="fa fa-trash-o"></i> </a>
|
||||
</div>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Name']%></span></div>
|
||||
<div><input class="form-control" name="name"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group-group blue">
|
||||
<h4><%- lang['Monitors'] %>
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-default btn-xs add"> <i class="fa fa-plus"></i> </a>
|
||||
</div>
|
||||
</h4>
|
||||
<div id="monitorStatesMonitors">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal"><i class="fa fa-times"></i> <%-lang.Close%></button>
|
||||
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#schedules"><i class="fa fa-clock-o"></i> <%-lang.Schedules%></button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-check"></i> <%-lang.Save%></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$.monitorStates = {
|
||||
e: $('#monitorStates'),
|
||||
selector: $('#monitorStatesSelector'),
|
||||
monitors: $('#monitorStatesMonitors'),
|
||||
loaded: {}
|
||||
}
|
||||
$.monitorStates.f = $.monitorStates.e.find('form')
|
||||
$.monitorStates.loadPresets = function(callback){
|
||||
$.get($.ccio.init('location',$user) + $user.auth_token + '/monitorStates/' + $user.ke,function(d){
|
||||
var html = ''
|
||||
$.each(d.presets,function(n,v){
|
||||
$.monitorStates.loaded[v.name] = v
|
||||
html += '<option value="' + v.name + '">' + v.name + '</option>'
|
||||
})
|
||||
$.monitorStates.selector.find('optgroup').html(html)
|
||||
if(callback)callback()
|
||||
})
|
||||
}
|
||||
$.monitorStates.e.on('shown.bs.modal', function (e) {
|
||||
if($.monitorStates.selector.val() === '')$.monitorStates.loadPresets()
|
||||
})
|
||||
$.monitorStates.add = function(loaded,doAppend){
|
||||
if(!loaded){
|
||||
json = ''
|
||||
}else{
|
||||
json = JSON.stringify(loaded,null,3)
|
||||
}
|
||||
var html = '<div class="state-monitor-row"><h4 style="margin-top:7.5px;margin-bottom:7.5px"><small> </small><div class="pull-right"><a class="btn btn-danger btn-xs delete-monitor"><i class="fa fa-trash-o"></i></a></div></h4><textarea class="json form-control" style="width:100%;height:300px">' + json +'</textarea></div>'
|
||||
if(doAppend)$.monitorStates.monitors.append(html)
|
||||
return html
|
||||
}
|
||||
$.monitorStates.e.find('.add').click(function(e){
|
||||
$.monitorStates.add(null,true)
|
||||
})
|
||||
$.monitorStates.e.on('change','.json',function(e){
|
||||
var el = $(this)
|
||||
var val = el.val()
|
||||
try{
|
||||
el.css('border-color','green')
|
||||
var parsed = JSON.parse(val)
|
||||
el.val(JSON.stringify(parsed,null,3))
|
||||
}catch(err){
|
||||
el.css('border-color','red')
|
||||
return $.ccio.init('note',{title:lang['Invalid JSON'],text:lang.InvalidJSONText,type:'error'})
|
||||
}
|
||||
})
|
||||
$.monitorStates.e.on('click','.delete',function(e){
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete Monitor States Preset']);
|
||||
$.confirm.body.html(lang.deleteMonitorStateText1);
|
||||
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
|
||||
var form = $.monitorStates.f.serializeObject()
|
||||
$.post($.ccio.init('location',$user) + $user.auth_token + '/monitorStates/' + $user.ke + '/' + form.name + '/delete',function(d){
|
||||
$.ccio.log(d)
|
||||
if(d.ok === true){
|
||||
$.monitorStates.loadPresets()
|
||||
$.ccio.init('note',{title:lang.Success,text:d.msg,type:'success'})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
$.monitorStates.e.on('click','.delete-monitor',function(e){
|
||||
var el = $(this).parents('.state-monitor-row')
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete Monitor State']);
|
||||
$.confirm.body.html(lang.deleteMonitorStateText2)
|
||||
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
|
||||
el.remove()
|
||||
})
|
||||
})
|
||||
$.monitorStates.selector.change(function(e){
|
||||
var selected = $(this).val()
|
||||
var loaded = $.monitorStates.loaded[selected]
|
||||
var namespace = $.monitorStates.e.find('[name="name"]')
|
||||
var deleteButton = $.monitorStates.e.find('.delete')
|
||||
if(loaded){
|
||||
namespace.val(loaded.name)
|
||||
var html = ''
|
||||
$.each(loaded.details.monitors,function(n,v){
|
||||
html += $.monitorStates.add(v)
|
||||
})
|
||||
$.monitorStates.monitors.html(html)
|
||||
deleteButton.show()
|
||||
}else{
|
||||
namespace.val('')
|
||||
$.monitorStates.monitors.empty()
|
||||
deleteButton.hide()
|
||||
}
|
||||
})
|
||||
$.monitorStates.f.submit(function(e){
|
||||
e.preventDefault()
|
||||
var el = $(this)
|
||||
var form = el.serializeObject()
|
||||
var monitors = []
|
||||
var failedToParseAJson = false
|
||||
var rows = $.monitorStates.monitors.find('.state-monitor-row')
|
||||
if(form.name === ''){
|
||||
return $.ccio.init('note',{title:lang['Invalid Data'],text:lang['Name cannot be empty.'],type:'error'})
|
||||
}
|
||||
if(rows.length === 0){
|
||||
return $.ccio.init('note',{title:lang['Invalid Data'],text:lang['Must be atleast one row'],type:'error'})
|
||||
}
|
||||
rows.each(function(n,v){
|
||||
var el = $(v)
|
||||
try{
|
||||
console.log(el.find('.json').val())
|
||||
var json = JSON.parse(el.find('.json').val())
|
||||
if(json.mid)monitors.push(json)
|
||||
}catch(err){
|
||||
console.log(err)
|
||||
failedToParseAJson = true
|
||||
}
|
||||
})
|
||||
if(failedToParseAJson === true){
|
||||
return $.ccio.init('note',{title:lang['Invalid JSON'],text:lang.InvalidJSONText,type:'error'})
|
||||
}
|
||||
var data = {
|
||||
monitors: monitors
|
||||
}
|
||||
$.post($.ccio.init('location',$user) + $user.auth_token + '/monitorStates/' + $user.ke + '/' + form.name + '/insert',{data:data},function(d){
|
||||
$.ccio.log(d)
|
||||
if(d.ok === true){
|
||||
$.monitorStates.loadPresets(function(){
|
||||
$.monitorStates.selector.val(form.name)
|
||||
})
|
||||
$.ccio.init('note',{title:lang.Success,text:d.msg,type:'success'})
|
||||
}
|
||||
})
|
||||
return false;
|
||||
})
|
||||
})
|
||||
</script>
|
|
@ -169,7 +169,7 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Retry Connection']%></span></div>
|
||||
<div><input class="form-control" detail="fatal_max" placeholder="10"></div>
|
||||
<div><input class="form-control" detail="fatal_max" placeholder="0"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -284,6 +284,14 @@
|
|||
<div><input class="form-control" detail="hwaccel_device"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Use coProcessor']%></span></div>
|
||||
<div><select class="form-control" detail="use_coprocessor">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END of Input -->
|
||||
|
@ -842,6 +850,11 @@
|
|||
<div><input class="form-control" detail="cust_record"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group h_rec_mtd_input h_rec_mtd_sip" style="display:none">
|
||||
<label><div><span><%-lang['Traditional Recording Flags']%></span></div>
|
||||
<div><input class="form-control" detail="cust_sip_record"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Output Method']%></span></div>
|
||||
<div><input class="form-control" detail="custom_output" placeholder="-f flv rtmp://.."></div>
|
||||
|
@ -1065,14 +1078,6 @@
|
|||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group h_det_pam_input h_det_pam_1">
|
||||
<label><div><span><%-lang['Show Matrices']%></span></div>
|
||||
<div><select class="form-control" detail="detector_show_matrix">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Indifference']%></span></div>
|
||||
<div><input class="form-control" detail="detector_sensitivity" placeholder="0.5"></div>
|
||||
|
@ -1114,16 +1119,6 @@
|
|||
<div><input class="form-control" detail="detector_noise_filter_range" placeholder="6"></div>
|
||||
</label>
|
||||
</div>
|
||||
<!--
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Show Regions of Interest']%></span></div>
|
||||
<div><select class="form-control" detail="detector_region_of_interest">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
-->
|
||||
<div class="form-group-group orange" section id="monSectionNoMotionDetector">
|
||||
<h4><%-lang['"No Motion" Detector']%></h4>
|
||||
<div class="form-group">
|
||||
|
@ -1149,6 +1144,29 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Start of Audio Detection -->
|
||||
<div class="form-group-group orange" section id="monSectionAudioDetector">
|
||||
<h4><%-lang['Audio Detector']%></h4>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Enabled']%></span></div>
|
||||
<div><select class="form-control" detail="detector_audio">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Minimum dB']%></span></div>
|
||||
<div><input class="form-control" detail="detector_audio_min_db" placeholder="5"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Maximum dB']%></span></div>
|
||||
<div><input class="form-control" detail="detector_audio_max_db" placeholder=""></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END of Audio Detection -->
|
||||
<div class="form-group-group orange shinobi-detector-opencv shinobi-detector-openalpr shinobi-detector-yolo shinobi-detector-dlib shinobi-detector_plug" section id="monSectionDetectorObject">
|
||||
<h4><%-lang['Object Detection']%> <small><%-lang['Plugin']%> : <b class="shinobi-detector_name"></b> <b class="shinobi-detector-invert"><%-lang['Not Connected']%></b><b class="shinobi-detector" style="display:none"><%-lang['Connected']%></b></small></h4>
|
||||
<div class="form-group">
|
||||
|
@ -1159,6 +1177,14 @@
|
|||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Require Object to be in Region']%></span></div>
|
||||
<div><select class="form-control" detail="detector_obj_region">
|
||||
<option value="0" selected><%-lang.No%></option>
|
||||
<option value="1"><%-lang.Yes%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Check for Motion First']%></span></div>
|
||||
<div><select class="form-control" detail="detector_use_motion" selector="h_det_mot_fir">
|
||||
|
@ -1597,3 +1623,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.monitoredit.js"></script>
|
||||
|
|
|
@ -35,4 +35,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.multimon.js"></script>
|
||||
|
|
|
@ -84,3 +84,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.powervideo.js"></script>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal"><i class="fa fa-times"></i> <%-lang.Close%></button>
|
||||
<a class="btn btn-danger stop" style="display:none"><%-lang.Stop%><span> <i class="fa fa-pulse fa-spinner"></i></span></a>
|
||||
<a class="btn btn-danger stop" style="display:none"><%-lang.Stop%><span> <i class="fa fa-pulse fa-spinner"></i></span></a>
|
||||
<button type="submit" class="btn btn-success"><%-lang.Check%></button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -91,4 +91,7 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<script src="<%-window.libURL%>libs/js/dash2.probe.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.onvifscanner.js"></script>
|
||||
|
|
|
@ -81,3 +81,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.regioneditor.js"></script>
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
<div class="modal dark fade" id="schedules" role="dialog" aria-labelledby="schedulesLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title" id="schedulesLabel"><i class="fa fa-clock-o"></i> <%-lang['Schedules']%></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<div><select class="form-control" id="schedulesSelector">
|
||||
<option value=""><%-lang['Add New']%></option>
|
||||
<optgroup label="<%-lang['Saved Schedules']%>"></optgroup>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group-group green">
|
||||
<h4><%- lang['Schedule'] %>
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-danger btn-xs delete" style="display:none"> <i class="fa fa-trash-o"></i> </a>
|
||||
</div>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Name']%></span></div>
|
||||
<div><input class="form-control" name="name"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Enabled']%></span></div>
|
||||
<div><select class="form-control" name="enabled">
|
||||
<option value="1" selected><%-lang.Yes%></option>
|
||||
<option value="0"><%-lang.No%></option>
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Start']%></span></div>
|
||||
<div><input class="form-control" name="start" placeholder="HH:ss"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['End']%></span></div>
|
||||
<div><input class="form-control" name="end" placeholder="HH:ss"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><div><span><%-lang['Monitor States']%></span></div>
|
||||
<div><select class="form-control" style="min-height:100px" multiple name="monitorStates">
|
||||
</select></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal"><i class="fa fa-times"></i> <%-lang.Close%></button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-check"></i> <%-lang.Save%></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$.schedules = {
|
||||
e: $('#schedules'),
|
||||
selector: $('#schedulesSelector'),
|
||||
loadedMonitorStates: {},
|
||||
loadedSchedules: {}
|
||||
}
|
||||
$.schedules.f = $.schedules.e.find('form')
|
||||
$.schedules.selectedStates = $.schedules.e.find('[name="monitorStates"]')
|
||||
$.schedules.loadSchedules = function(callback){
|
||||
$.get($.ccio.init('location',$user) + $user.auth_token + '/schedule/' + $user.ke,function(d){
|
||||
console.log(d)
|
||||
var html = ''
|
||||
$.each(d.schedules,function(n,v){
|
||||
$.schedules.loadedSchedules[v.name] = v
|
||||
html += $.ccio.tm('option',{
|
||||
id: v.name,
|
||||
name: v.name
|
||||
})
|
||||
})
|
||||
$.schedules.selector.find('optgroup').html(html)
|
||||
if(callback)callback()
|
||||
})
|
||||
}
|
||||
$.schedules.loadMonitorStates = function(){
|
||||
$.get($.ccio.init('location',$user) + $user.auth_token + '/monitorStates/' + $user.ke,function(d){
|
||||
var html = ''
|
||||
$.each(d.presets,function(n,v){
|
||||
$.schedules.loadedMonitorStates[v.name] = v
|
||||
html += $.ccio.tm('option',{
|
||||
id: v.name,
|
||||
name: v.name
|
||||
})
|
||||
})
|
||||
$.schedules.selectedStates.html(html)
|
||||
})
|
||||
}
|
||||
$.schedules.e.on('shown.bs.modal', function (e) {
|
||||
$.schedules.loadMonitorStates()
|
||||
$.schedules.loadSchedules()
|
||||
})
|
||||
$.schedules.e.on('click','.delete',function(e){
|
||||
$.confirm.e.modal('show');
|
||||
$.confirm.title.text(lang['Delete Monitor States Preset']);
|
||||
$.confirm.body.html(lang.deleteMonitorStateText1);
|
||||
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
|
||||
var form = $.schedules.f.serializeObject()
|
||||
$.post($.ccio.init('location',$user) + $user.auth_token + '/schedule/' + $user.ke + '/' + form.name + '/delete',function(d){
|
||||
$.ccio.log(d)
|
||||
if(d.ok === true){
|
||||
$.schedules.loadSchedules()
|
||||
$.ccio.init('note',{title:lang.Success,text:d.msg,type:'success'})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
$.schedules.selector.change(function(e){
|
||||
var selected = $(this).val()
|
||||
var loaded = $.schedules.loadedSchedules[selected]
|
||||
var namespace = $.schedules.e.find('[name="name"]')
|
||||
var deleteButton = $.schedules.e.find('.delete')
|
||||
$.schedules.selectedStates.find('option:selected').removeAttr('selected')
|
||||
if(loaded){
|
||||
namespace.val(loaded.name)
|
||||
var html = ''
|
||||
$.each(loaded,function(n,v){
|
||||
$.schedules.f.find('[name="' + n + '"]').val(v)
|
||||
})
|
||||
$.each(loaded.details.monitorStates,function(n,v){
|
||||
$.schedules.selectedStates.find('option[value="' + v + '"]').prop('selected',true)
|
||||
})
|
||||
deleteButton.show()
|
||||
}else{
|
||||
namespace.val('')
|
||||
deleteButton.hide()
|
||||
}
|
||||
})
|
||||
$.schedules.f.submit(function(e){
|
||||
e.preventDefault()
|
||||
var el = $(this)
|
||||
var form = el.serializeObject()
|
||||
var monitors = []
|
||||
var failedToParseAJson = false
|
||||
var rows = $.monitorStates.monitors.find('.state-monitor-row')
|
||||
if(form.name === ''){
|
||||
return $.ccio.init('note',{title:lang['Invalid Data'],text:lang['Name cannot be empty.'],type:'error'})
|
||||
}
|
||||
if(form.start === ''){
|
||||
return $.ccio.init('note',{title:lang['Invalid Data'],text:lang['Start Time cannot be empty.'],type:'error'})
|
||||
}
|
||||
if(form.monitorStates instanceof Array === false){
|
||||
form.monitorStates = [form.monitorStates]
|
||||
}
|
||||
console.log(form.monitorStates)
|
||||
|
||||
var data = {
|
||||
start: form.start,
|
||||
end: form.end,
|
||||
enabled: form.enabled,
|
||||
details:{
|
||||
monitorStates: form.monitorStates
|
||||
}
|
||||
}
|
||||
$.post($.ccio.init('location',$user) + $user.auth_token + '/schedule/' + $user.ke + '/' + form.name + '/insert',{data:data},function(d){
|
||||
$.ccio.log(d)
|
||||
if(d.ok === true){
|
||||
$.schedules.loadSchedules(function(){
|
||||
$.schedules.selector.val(form.name)
|
||||
})
|
||||
$.ccio.init('note',{title:lang.Success,text:d.msg,type:'success'})
|
||||
}
|
||||
})
|
||||
return false;
|
||||
})
|
||||
})
|
||||
</script>
|
|
@ -503,3 +503,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.usersettings.js"></script>
|
||||
|
|
|
@ -77,4 +77,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.timelapse.js"></script>
|
||||
|
|
|
@ -77,3 +77,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.vidview.js"></script>
|
||||
|
|
|
@ -14,7 +14,22 @@
|
|||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/gridstack.min.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/gridstack-extra.min.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/bootstrap-table.min.css">
|
||||
<!--
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.basic.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.forms.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.modal.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.monitors.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.powervideo.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.ptzcontrols.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.regioneditor.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.rightotleft.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/dash2.timelapse.css">
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/main.dash2.css">
|
||||
-->
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/main.dash2.old.css">
|
||||
<% customAutoLoad.LibsCss.forEach(function(lib){ %>
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/<%-lib%>">
|
||||
<% }) %>
|
||||
<style id="theme">
|
||||
<% if(details.theme&&details.theme!==''){ %><%- include(__dirname+'/web/libs/themes/'+details.theme+'/style.css'); %><% } %>
|
||||
</style>
|
||||
|
@ -121,6 +136,8 @@
|
|||
<% if(!details.sub){ %>
|
||||
<li class="mdl-menu__item" data-toggle="modal" data-target="#onvif_probe"><div><i class="fa fa-rss"></i><div><%- lang.ONVIF %></div></div></li>
|
||||
<li class="mdl-menu__item" data-toggle="modal" data-target="#probe"><div><i class="fa fa-search"></i><div><%- lang.FFprobe %></div></div></li>
|
||||
<li class="mdl-menu__item" data-toggle="modal" data-target="#monitorStates"><div><i class="fa fa-align-right"></i><div><%- lang['Monitor States'] %></div></div></li>
|
||||
<li class="mdl-menu__item" data-toggle="modal" data-target="#schedules"><div><i class="fa fa-clock-o"></i><div><%- lang['Schedules'] %></div></div></li>
|
||||
<li class="mdl-menu__item" data-toggle="modal" data-target="#filters"><div><i class="fa fa-filter"></i><div><%- lang.Filters %></div></div></li>
|
||||
<% } %>
|
||||
<li class="mdl-menu__item permission_view_logs" data-toggle="modal" data-target="#logs_modal"><div><i class="fa fa-exclamation-triangle"></i><div><%- lang.Logs %></div></div></li>
|
||||
|
@ -167,7 +184,12 @@
|
|||
<% include blocks/probe.ejs %>
|
||||
<% include blocks/region.ejs %>
|
||||
<% include blocks/detectorfilters.ejs %>
|
||||
<% include blocks/monitorStates.ejs %>
|
||||
<% include blocks/schedules.ejs %>
|
||||
<% include blocks/confirm.ejs %>
|
||||
<% customAutoLoad.PageBlocks.forEach(function(block){ %>
|
||||
<%- include(block) %>
|
||||
<% }) %>
|
||||
<% if(config.DropboxAppKey){ %>
|
||||
<!--Dropbox Library, Change data-app-key to your app key. -->
|
||||
<script type="text/javascript" src="https://www.dropbox.com/static/api/2/dropins.js" id="dropboxjs" data-app-key="<%= config.DropboxAppKey %>"></script>
|
||||
|
@ -198,5 +220,15 @@
|
|||
<script src="<%-window.libURL%>libs/js/gridstack.min.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/gridstack.jQueryUI.min.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/basic.js"></script>
|
||||
<script><% include ../libs/js/main.dash2.js %></script>
|
||||
<script><% include ../libs/js/dash2.config.js %></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.basic.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.confirm.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.socketio.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.gridstack.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.elements.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.elementbuilder.js"></script>
|
||||
<script src="<%-window.libURL%>libs/js/dash2.init.js"></script>
|
||||
<% customAutoLoad.LibsJs.forEach(function(lib){ %>
|
||||
<script src="<%-window.libURL%>libs/js/<%-lib%>"></script>
|
||||
<% }) %>
|
||||
<% include blocks/help.ejs %>
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
.list-group li .form-group {margin:0}
|
||||
a {cursor:pointer}
|
||||
</style>
|
||||
<% customAutoLoad.superLibsCss.forEach(function(lib){ %>
|
||||
<link rel="stylesheet" href="<%-window.libURL%>libs/css/<%-lib%>">
|
||||
<% }) %>
|
||||
</head>
|
||||
|
||||
<body class="index-page sidebar-collapse bg-hexagon">
|
||||
|
@ -62,7 +65,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="main-card" class="card">
|
||||
<ul class="nav nav-tabs nav-tabs-neutral justify-content-center bg-primary" role="tablist">
|
||||
<ul class="nav nav-tabs nav-tabs-neutral justify-content-center bg-primary" id="tablist" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#accounts" role="tab">Accounts</a>
|
||||
</li>
|
||||
|
@ -169,8 +172,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="temp" style="display:none"></div>
|
||||
</body>
|
||||
<script>
|
||||
var superApiPrefix = "<%=originalURL%><%=config.webPaths.superApiPrefix%>"
|
||||
</script>
|
||||
<% include blocks/confirm.ejs %>
|
||||
<% customAutoLoad.superPageBlocks.forEach(function(block){ %>
|
||||
<%- include(block) %>
|
||||
<% }) %>
|
||||
<script src="<%-window.libURL%>libs/js/pnotify.custom.min.js" type="text/javascript"></script>
|
||||
<script><% include ../libs/js/moment.js %></script>
|
||||
<script src="<%-window.libURL%>libs/js/livestamp.min.js" type="text/javascript"></script>
|
||||
|
@ -178,6 +188,7 @@
|
|||
<script src="<%-window.libURL%>libs/js/placeholder.js" type="text/javascript"></script>
|
||||
<script src="<%-window.libURL%>libs/js/now-ui-kit.js?v=1.1.0" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
var lang = <%- JSON.stringify(lang) || {} %>;
|
||||
PNotify.prototype.options.styling = "fontawesome";
|
||||
$(document).ready(function() {
|
||||
// the body of this function is in assets/js/now-ui-kit.js
|
||||
|
@ -530,4 +541,7 @@ $('body')
|
|||
})
|
||||
</script>
|
||||
<% include blocks/mainpermissions.ejs %>
|
||||
<% customAutoLoad.superLibsJs.forEach(function(lib){ %>
|
||||
<script src="<%-window.libURL%>libs/js/<%-lib%>"></script>
|
||||
<% }) %>
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue