...
 
Commits (76)
......@@ -28,6 +28,20 @@ fi
echo "Shinobi - Run yum update"
sudo yum update -y
sudo yum install make zip -y
if ! [ -x "$(command -v node)" ]; then
echo "============="
echo "Shinobi - Installing Node.js"
sudo wget https://rpm.nodesource.com/setup_8.x
sudo chmod +x setup_8.x
./setup_8.x
sudo yum install nodejs -y
else
echo "Node.js Found..."
echo "Version : $(node -v)"
fi
if ! [ -x "$(command -v npm)" ]; then
sudo apt install npm -y
fi
echo "============="
echo "Shinobi - Do you want to Install FFMPEG?"
echo "(y)es or (N)o"
......@@ -48,15 +62,6 @@ if [ "$ffmpeginstall" = "y" ] || [ "$ffmpeginstall" = "Y" ]; then
sudo npm install ffbinaries
fi
fi
echo "Shinobi - Do you want to Install Node.js?"
echo "(y)es or (N)o"
read nodejsinstall
if [ "$nodejsinstall" = "y" ] || [ "$nodejsinstall" = "Y" ]; then
sudo wget https://rpm.nodesource.com/setup_8.x
sudo chmod +x setup_8.x
./setup_8.x
sudo yum install nodejs -y
fi
echo "============="
echo "Shinobi - Do you want to use MariaDB or SQLite3?"
echo "SQLite3 is better for small installs"
......@@ -108,7 +113,7 @@ sudo npm install --unsafe-perm
sudo npm audit fix --force
echo "============="
echo "Shinobi - Install PM2"
sudo npm install pm2 -g
sudo npm install pm2@3.0.0 -g
echo "Shinobi - Finished"
sudo chmod -R 755 .
touch INSTALL/installed.txt
......
......@@ -3,12 +3,32 @@ echo "------------------------------------------"
echo "-- Installing CUDA Toolkit and CUDA DNN --"
echo "------------------------------------------"
# Install CUDA Drivers and Toolkit
wget https://cdn.shinobi.video/installers/cuda-repo-ubuntu1710_9.2.148-1_amd64.deb -O cuda.deb
sudo dpkg -i cuda.deb
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1710/x86_64/7fa2af80.pub
echo "============="
echo " Detecting Ubuntu Version"
echo "============="
getubuntuversion=$(lsb_release -r | awk '{print $2}' | cut -d . -f1)
echo "============="
echo " Ubuntu Version: $getubuntuversion"
echo "============="
if [ "$getubuntuversion" = "17" ] || [ "$getubuntuversion" > "17" ]; then
wget https://cdn.shinobi.video/installers/cuda-repo-ubuntu1710_9.2.148-1_amd64.deb -O cuda.deb
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1710/x86_64/7fa2af80.pub
sudo dpkg -i cuda.deb
fi
if [ "$getubuntuversion" = "16" ]; then
wget https://cdn.shinobi.video/installers/cuda-repo-ubuntu1604_9.2.148-1_amd64.deb -O cuda.deb
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
sudo dpkg -i cuda.deb
fi
sudo apt-get update -y
sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda -y
sudo apt-get -o Dpkg::Options::="--force-overwrite" install --fix-broken -y
if [ "$getubuntuversion" = "17" ] || [ "$getubuntuversion" > "17" ]; then
sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda -y --no-install-recommends
sudo apt-get -o Dpkg::Options::="--force-overwrite" install --fix-broken -y
fi
if [ "$getubuntuversion" = "16" ]; then
sudo apt-get install libcuda1-384 -y --no-install-recommends
sudo apt-get install nvidia-cuda-toolkit -y
fi
# Install CUDA DNN
wget https://cdn.shinobi.video/installers/libcudnn7_7.2.1.38-1+cuda9.2_amd64.deb -O cuda-dnn.deb
sudo dpkg -i cuda-dnn.deb
......
......@@ -46,7 +46,7 @@ npm install --unsafe-perm
sudo npm audit fix --force
echo "============="
echo "Shinobi - Install PM2"
npm install pm2 -g
npm install pm2@3.0.0 -g
if (! -e "./conf.json" ) then
cp conf.sample.json conf.json
endif
......
......@@ -21,7 +21,7 @@ npm i npm -g
#There are some errors in here that I don't want you to see. Redirecting to dev null :D
npm install --unsafe-perm > & /dev/null
npm audit fix --force > & /dev/null
npm install pm2 -g
npm install pm2@3.0.0 -g
cp conf.sample.json conf.json
cp super.sample.json super.json
pm2 start camera.js
......
if [ -f /etc/os-release ]; then
# freedesktop.org and systemd
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
elif type lsb_release >/dev/null 2>&1; then
# linuxbase.org
OS=$(lsb_release -si)
VER=$(lsb_release -sr)
elif [ -f /etc/lsb-release ]; then
# For some versions of Debian/Ubuntu without lsb_release command
. /etc/lsb-release
OS=$DISTRIB_ID
VER=$DISTRIB_RELEASE
elif [ -f /etc/debian_version ]; then
# Older Debian/Ubuntu/etc.
OS=Debian
VER=$(cat /etc/debian_version)
elif [ -f /etc/SuSe-release ]; then
# Older SuSE/etc.
...
elif [ -f /etc/redhat-release ]; then
# Older Red Hat, CentOS, etc.
...
else
# Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
OS=$(uname -s)
VER=$(uname -r)
fi
echo $OS
......@@ -9,13 +9,8 @@ echo "(y)es or (N)o"
read mysqlagreeData
if [ "$mysqlagreeData" = "y" ]; then
echo "Shinobi will now use root for database installation..."
echo "What is your SQL Username?"
read sqluser
echo "What is your SQL Password?"
read sqlpass
echo "You may now be asked for your Administator (root for Mac OS, not MySQL) password"
sudo mysql -u $sqluser -p$sqlpass -e "source sql/user.sql" || true
sudo mysql -u $sqluser -p$sqlpass -e "source sql/framework.sql" || true
sudo mysql -e "source sql/user.sql" || true
sudo mysql -e "source sql/framework.sql" || true
fi
echo "============="
echo "Shinobi - Install NPM Libraries"
......@@ -24,7 +19,7 @@ sudo npm install --unsafe-perm
sudo npm audit fix --unsafe-perm
echo "============="
echo "Shinobi - Install PM2"
sudo npm install pm2 -g
sudo npm install pm2@3.0.0 -g
if [ ! -e "./conf.json" ]; then
sudo cp conf.sample.json conf.json
fi
......@@ -35,6 +30,8 @@ if [ ! -e "./super.json" ]; then
fi
echo "Shinobi - Finished"
touch INSTALL/installed.txt
dos2unix /home/Shinobi/INSTALL/shinobi
ln -s /home/Shinobi/INSTALL/shinobi /usr/bin/shinobi
sudo chmod -R 755 .
echo "=====================================" > INSTALL/installed.txt
echo "======= Login Credentials =======" >> INSTALL/installed.txt
......
......@@ -24,27 +24,59 @@ if [ "$ffmpeginstall" = "y" ]; then
curl -o ffmpeg.zip https://cdn.shinobi.video/installers/ffmpeg-3.4.1-macos.zip
sudo unzip ffmpeg.zip
sudo rm ffmpeg.zip
sudo mv ffmpeg-3.4.1-macos/ffmpeg /usr/bin/ffmpeg
sudo mv ffmpeg-3.4.1-macos/ffplay /usr/bin/ffplay
sudo mv ffmpeg-3.4.1-macos/ffprobe /usr/bin/ffprobe
sudo mv ffmpeg-3.4.1-macos/ffserver /usr/bin/ffserver
sudo mv ffmpeg-3.4.1-macos/ffmpeg /usr/local/bin/ffmpeg
sudo mv ffmpeg-3.4.1-macos/ffplay /usr/local/bin/ffplay
sudo mv ffmpeg-3.4.1-macos/ffprobe /usr/local/bin/ffprobe
sudo mv ffmpeg-3.4.1-macos/ffserver /usr/local/bin/ffserver
sudo chmod +x /usr/local/bin/ffmpeg
sudo chmod +x /usr/local/bin/ffplay
sudo chmod +x /usr/local/bin/ffprobe
sudo chmod +x /usr/local/bin/ffserver
fi
echo "============="
echo "Shinobi - Do you want to Install MySQL? Choose No if you have MySQL or MySQL already."
echo "(y)es or (N)o"
read mysqlagree
if [ "$mysqlagree" = "y" ]; then
echo "Shinobi - Installing MySQL"
bash <(curl -Ls http://git.io/eUx7rg)
if [ ! -e "./shinobi.sqlite" ]; then
sudo npm install jsonfile
sudo cp sql/shinobi.sample.sqlite shinobi.sqlite
sudo node tools/modifyConfiguration.js databaseType=sqlite3
fi
echo "Shinobi - Install NPM Libraries"
sudo npm i npm -g
sudo npm install --unsafe-perm
sudo npm audit fix --unsafe-perm
echo "============="
echo "============="
echo "You must now close this terminal window and reopen it."
echo "Reopen the Shinobi folder and run"
echo "sudo sh INSTALL/macos-part2.sh"
echo "============="
echo "============="
\ No newline at end of file
echo "Shinobi - Install PM2"
sudo npm install pm2@3.0.0 -g
if [ ! -e "./conf.json" ]; then
sudo cp conf.sample.json conf.json
fi
if [ ! -e "./super.json" ]; then
echo "Default Superuser : admin@shinobi.video"
echo "Default Password : admin"
sudo cp super.sample.json super.json
fi
echo "Shinobi - Finished"
sudo chmod -R 755 .
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
echo "Shinobi - Start Shinobi and set to start on boot?"
echo "(y)es or (N)o"
read startShinobi
if [ "$startShinobi" = "y" ]; then
pm2 start camera.js
pm2 startup
pm2 save
pm2 list
fi
echo "details written to INSTALL/installed.txt"
echo "====================================="
echo "======= Login Credentials ======="
echo "|| Username : $userEmail"
echo "|| Password : $userPasswordPlain"
echo "|| API Key : $apiKey"
echo "====================================="
echo "====================================="
......@@ -9,6 +9,9 @@ if ! [ -x "$(command -v opencv_version)" ]; then
else
echo "OpenCV found... : $(opencv_version)"
fi
# get tesseract repo because ubuntu repo is serving a broken version
sudo add-apt-repository ppa:alex-p/tesseract-ocr -y
sudo apt-get update -y
# 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
......
......@@ -11,7 +11,7 @@ else
fi
# get tesseract repo because ubuntu repo is serving a broken version
sudo add-apt-repository ppa:alex-p/tesseract-ocr -y
sudo apt-get update
sudo apt-get update -y
# 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
......
......@@ -109,7 +109,7 @@ npm install --unsafe-perm
sudo npm audit fix --force
echo "============="
echo "Shinobi - Install PM2"
sudo npm install pm2 -g
sudo npm install pm2@3.0.0 -g
echo "Shinobi - Finished"
sudo chmod -R 755 .
touch INSTALL/installed.txt
......
......@@ -154,7 +154,7 @@ echo "============="
#Install PM2
echo "Shinobi - Install PM2"
sudo npm install pm2 -g
sudo npm install pm2@3.0.0 -g
if [ ! -e "./conf.json" ]; then
cp conf.sample.json conf.json
fi
......
......@@ -18,6 +18,9 @@ if [ "$getubuntuversion" = "18" ] || [ "$getubuntuversion" > "18" ]; then
sudo apt install -y software-properties-common
sudo add-apt-repository universe -y
fi
if [ "$getubuntuversion" = "16" ]; then
apt install gnupg-curl -y
fi
#create conf.json
if [ ! -e "./conf.json" ]; then
sudo cp conf.sample.json conf.json
......@@ -121,7 +124,7 @@ sudo npm install --unsafe-perm
sudo npm audit fix --force
echo "============="
echo "Shinobi - Install PM2"
sudo npm install pm2 -g
sudo npm install pm2@3.0.0 -g
echo "Shinobi - Finished"
sudo chmod -R 755 .
touch INSTALL/installed.txt
......
......@@ -19,20 +19,20 @@ var s = loadLib('process')(process,__dirname)
loadLib('extenders')(s)
//configuration loader
var config = loadLib('config')(s)
//basic functions
loadLib('basic')(s,config)
//working directories : videos, streams, fileBin..
loadLib('folders')(s,config)
//language loader
var lang = loadLib('language')(s,config)
//code test module
loadLib('codeTester')(s,config,lang)
//basic functions
loadLib('basic')(s,config)
//video processing engine
loadLib('ffmpeg')(s,config,function(ffmpeg){
loadLib('ffmpeg')(s,config,lang,function(ffmpeg){
//ffmpeg coProcessor
loadLib('ffmpegCoProcessor')(s,config,lang,ffmpeg)
//database connection : mysql, sqlite3..
loadLib('sql')(s,config)
//working directories : videos, streams, fileBin..
loadLib('folders')(s,config)
//authenticator functions : API, dashboard login..
loadLib('auth')(s,config,lang)
//express web server with ejs
......@@ -48,7 +48,7 @@ loadLib('ffmpeg')(s,config,function(ffmpeg){
//websocket connection handlers : login and streams..
loadLib('socketio')(s,config,lang,io)
//user and group functions
loadLib('user')(s,config)
loadLib('user')(s,config,lang)
//monitor/camera handlers
loadLib('monitor')(s,config,lang)
//event functions : motion, object matrix handler
......@@ -57,8 +57,10 @@ loadLib('ffmpeg')(s,config,function(ffmpeg){
loadLib('detector')(s,config)
//recording functions
loadLib('videos')(s,config,lang)
//branding functions and config defaults
loadLib('videoDropInServer')(s,config,lang,app,io)
//plugins : websocket connected services..
loadLib('plugins')(s,config,lang)
loadLib('plugins')(s,config,lang,io)
//health : cpu and ram trackers..
loadLib('health')(s,config,lang,io)
//cluster module
......@@ -71,6 +73,10 @@ loadLib('ffmpeg')(s,config,function(ffmpeg){
loadLib('rtmpserver')(s,config,lang)
//dropInEvents server (file manipulation to create event trigger)
loadLib('dropInEvents')(s,config,lang,app,io)
//form fields to drive the internals
loadLib('definitions')(s,config,lang,app,io)
//branding functions and config defaults
loadLib('branding')(s,config,lang,app,io)
//custom module loader
loadLib('customAutoLoad')(s,config,lang,app,io)
//scheduling engine
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -17,6 +17,8 @@
"Password": "Password",
"Password Again": "Password Again",
"Remember Me": "Remember Me",
"Process Already Running": "Process Already Running",
"Process Not Running": "Process Not Running",
"RAM": "RAM",
"CPU": "CPU",
"on": "on",
......@@ -26,6 +28,7 @@
"Montage": "Montage",
"Accounts": "Accounts",
"Settings": "Settings",
"Cards": "Cards",
"Recording FPS": "Recording FPS",
"Input Selector": "Input Selector",
"Input Settings": "Input Settings",
......@@ -76,6 +79,7 @@
"Zoom Out": "Zoom Out <small>URL Address</small>",
"Enable Nightvision": "Enable Nightvision",
"Disable Nightvision": "Disable Nightvision",
"Date": "Date",
"Current": "Current",
"Monitors": "Monitors",
"Video": "Video",
......@@ -92,6 +96,9 @@
"New Monitor": "New Monitor",
"Please Check Your Settings": "Please Check Your Settings",
"migrateText1": "<b>Input Type</b> could not be parsed. Please set it manually.",
"Build": "Build",
"Building": "Building",
"Started Building": "Started Building",
"Add": "Add",
"Save": "Save",
"Close": "Close",
......@@ -207,11 +214,14 @@
"Region Name": "Region Name",
"Regions": "Regions",
"Again": "Again",
"Landing Page": "Landing Page",
"Account Info": "Account Info",
"blankPassword": "Leave blank to keep same password",
"2-Factor Authentication": "2-Factor Authentication",
"Use Max Storage Amount": "Use Max Storage Amount",
"Max Storage Amount": "Max Storage Amount <small>in Megabytes</small>",
"Max Storage Amount": "Max Storage Amount",
"Video Share": "Video Share",
"Timelapse Frames Share": "Timelapse Frames Share",
"Number of Days to keep": "Number of Days to keep",
"Monitor Groups": "Monitor Groups",
"Group Name": "Group Name",
......@@ -228,14 +238,20 @@
"Database": "Database",
"Database Not Found": "Database Not Found",
"User Not Found": "User Not Found",
"Not Found": "Not Found",
"Save Links to Database": "Save Links to Database",
"Uploaders": "Uploaders",
"Upload File": "Upload File",
"Endpoint": "Endpoint",
"Endpoint Address": "Endpoint Address",
"Custom Endpoint": "Custom Endpoint",
"Bucket": "Bucket",
"Region": "Region",
"Use Global Amazon S3 Video Storage": "Use Global Amazon S3 Video Storage",
"Use Global Wasabi Hot Cloud Storage Video Storage": "Use Global Wasabi Hot Cloud Storage Video Storage",
"Use Global Backblaze B2 Video Storage": "Use Global Backblaze B2 Video Storage",
"Use Global WebDAV Video Storage": "Use Global WebDAV Video Storage",
"S3-Based Network Storage": "S3-Based Network Storage",
"Amazon S3 Upload Error": "Amazon S3 Upload Error",
"Wasabi Hot Cloud Storage Upload Error": "Wasabi Hot Cloud Storage Upload Error",
"accountId": "Account ID",
......@@ -263,6 +279,8 @@
"Currently viewing": "Currently viewing",
"Status Indicator": "Status Indicator",
"Show Logs": "Show Logs",
"Time Occurred": "Time Occurred",
"Recent Videos": "Recent Videos",
"Videos List": "Videos List",
"Monitor Settings": "Monitor Settings",
"Enlarge": "Enlarge",
......@@ -271,6 +289,7 @@
"Idle": "Idle",
"Disabled": "Disabled",
"Record": "Record",
"Watch-Only": "Watch-Only",
"Watch Only": "Watch Only",
"Toggle Sidebar": "Toggle Sidebar",
"Add Monitor": "Add Monitor",
......@@ -352,7 +371,7 @@
"Stream": "Stream",
"Stream Timestamp": "Stream Timestamp",
"Stream Watermark": "Stream Watermark",
"JPEG API": "JPEG API <small>Snapshot (cgi-bin)</small>",
"JPEG API": "JPEG API",
"Raw H.264 Stream": "Raw H.264 Stream",
"Recording": "Recording",
"Recording Timestamp": "Recording Timestamp",
......@@ -374,14 +393,20 @@
"Refresh List of Cascades": "Refresh List of Cascades",
"\"No Motion\" Detector": "\"No Motion\" Detector",
"Control": "Control",
"Grouping": "Grouping <small>Add groups in <b>Settings</b></small>",
"Grouping": "Grouping",
"Detector Grouping": "Detector Grouping <small>Add groups in <b>Settings</b></small>",
"Detector Recording Process Exited Prematurely. Restarting.": "Detector Recording Process Exited Prematurely. Restarting.",
"Detector Recording Complete": "Detector Recording Complete",
"Clear Recorder Process": "Clear Recorder Process",
"Logging": "Logging",
"Timelapse": "Timelapse",
"Nothing exists": "Nothing exists",
"Already exists": "Already exists",
"Creation Interval": "Creation Interval",
"Plugin": "Plugin",
"IdentityText1": "This is how the system will identify the data for this stream. You cannot change the <b>Monitor ID</b> once you have pressed save. If you want you can make the <b>Monitor ID</b> more human readable before you continue.",
"IdentityText2": "You can duplicate a monitor by modifying the <b>Monitor ID</b> then pressing save. You <b>cannot</b> use the ID of a monitor that already exists or it will save over that monitor's database information.",
"opencvCascadesText": "If you see nothing here then just download this package of <a href=\"https://cdn.shinobi.video/weights/cascades.zip\">cascades</a>. Drop them into <code>plugins/opencv/cascades</code> then press refresh <i class=\"fa fa-retweet\"></i>.",
"noSpecialCharacters": "No spaces or special characters.",
"NotesPlacholder": "Comments you want to leave for this cameras settings.",
"InputText1": "This section tells Shinobi how to consume a stream. For optimal performance try tuning your camera's internal settings. Find the following options and set them as shown. To find your camera you can use the <b>built in ONVIF Scanner</b> of Shinobi. Some ONVIF cameras require the use of a management tool to modify their internal settings. If you can't find your cameras you can try <a href=\"https://s3.amazonaws.com/cloudcamio/odm-v2.2.250.msi\">ONVIF Device Manager for Windows</a>.",
......@@ -433,7 +458,7 @@
"Position Y": "Position Y",
"Image Location": "Image Location <small>Absolute Path or leave blank to use global</small>",
"Image Position": "Image Position",
"Frame Rate": "Frame Rate <small>(FPS)</small>",
"Frame Rate": "Frame Rate",
"Image Width": "Image Width",
"Image Height": "Image Height",
"Record File Type": "Record File Type",
......@@ -783,6 +808,10 @@
"hevc_cuvid": "H.265 CUVID",
"mjpeg_cuvid": "MJPEG CUVID",
"mpeg4_cuvid": "MPEG4 CUVID",
"NVIDIA": "NVIDIA",
"VA-API": "VA-API",
"Raspberry Pi": "Raspberry Pi",
"Quick Sync Video": "Quick Sync Video",
"h264_qsv": "H.264 (Quick Sync Video)",
"hevc_qsv": "H.265 (Quick Sync Video)",
"vp8_qsv": "VP8 (Quick Sync Video)",
......@@ -840,7 +869,10 @@
"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.",
"openImagesDownloadConfirm":"Are you sure you want to begin download images and bounding boxes (preset Matrices) from OpenImages?",
"openImagesDownloadConfirmStop":"Are you sure you want to stop training?",
"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 and/or CPU.",
"TrainConfirmStop":"Are you sure you want to stop training?",
"Batch":"Batch",
"Subdivision":"Subdivision",
"Map":"Map",
......@@ -864,6 +896,7 @@
"Edit Selected":"Edit Selected",
"Copy Settings":"Copy Settings",
"Copy to Settings":"Copy to Settings",
"Copy Mode":"Copy Mode",
"Copy Group Settings":"Copy Group Settings",
"Copy Connection Settings":"Copy Connection Settings",
"Copy Custom Settings":"Copy Custom Settings",
......
This diff is collapsed.
......@@ -121,7 +121,9 @@ module.exports = function(s,config,lang){
var adminUsersSelected = null
try{
var success = function(){
var chosenConfig = config
if(req && res){
chosenConfig = s.getConfigWithBranding(req.hostname)
res.setHeader('Content-Type', 'application/json');
var ip = req.headers['cf-connecting-ip']||req.headers["CF-Connecting-IP"]||req.headers["'x-forwarded-for"]||req.connection.remoteAddress;
var resp = {
......@@ -143,7 +145,7 @@ module.exports = function(s,config,lang){
ip : ip,
$user:userSelected,
users:adminUsersSelected,
config:config,
config: chosenConfig,
lang:lang
})
}
......@@ -199,4 +201,31 @@ module.exports = function(s,config,lang){
return false
}
}
s.basicOrApiAuthentication = function(username,password,callback){
var splitUsername = username.split('@')
if(splitUsername[1] !== 'Shinobi' && splitUsername[1] !== 'shinobi'){
s.sqlQuery('SELECT ke,uid FROM Users WHERE mail=? AND (pass=? OR pass=?)',[
username,
password,
s.createHash(password)
],function(err,r){
var user
if(r && r[0]){
user = r[0]
}
callback(err,user)
})
}else{
s.sqlQuery('SELECT ke,uid FROM API WHERE code=? AND ke=?',[
splitUsername[0], //code
password //ke
],function(err,r){
var apiKey
if(r && r[0]){
apiKey = r[0]
}
callback(err,apiKey)
})
}
}
}
......@@ -75,7 +75,12 @@ module.exports = function(s,config){
break;
}
//load camera controller vars
s.nameToTime=function(x){x=x.split('.')[0].split('T'),x[1]=x[1].replace(/-/g,':');x=x.join(' ');return x;}
s.nameToTime=function(x){
x = x.split('.')[0].split('T')
if(x[1])x[1] = x[1].replace(/-/g,':')
x = x.join(' ')
return x
}
s.ratio=function(width,height,ratio){ratio = width / height;return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9';}
s.randomNumber=function(x){
if(!x){x=10};
......@@ -241,6 +246,9 @@ module.exports = function(s,config){
if(callback)callback()
},theTimeout)
}
s.isCorrectFilenameSyntax = function(string){
return RegExp('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]-[0-9][0-9]-[0-9][0-9]').test(string)
}
Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize){
var temporal = [];
......
module.exports = function(s,config,lang,app,io){
if(config.showPoweredByShinobi === undefined){config.showPoweredByShinobi=true}
if(config.poweredByShinobi === undefined){config.poweredByShinobi='Powered by Shinobi.Systems'}
if(config.poweredByShinobiClass === undefined){config.poweredByShinobiClass='margin:15px 0 0 0;text-align:center;color:#777;font-family: sans-serif;text-transform: uppercase;letter-spacing: 3;font-size: 8pt;'}
if(config.webPageTitle === undefined){config.webPageTitle='Shinobi'}
if(config.showLoginCardHeader === undefined){config.showLoginCardHeader=true}
if(config.webFavicon === undefined){config.webFavicon='libs/img/icon/favicon.ico'}
if(config.logoLocation76x76 === undefined){config.logoLocation76x76='libs/img/icon/apple-touch-icon-76x76.png'}
if(config.logoLocation76x76Link === undefined){config.logoLocation76x76Link='https://shinobi.video'}
if(config.logoLocation76x76Style === undefined){config.logoLocation76x76Style='border-radius:50%'}
if(config.showLoginSelector === undefined){config.showLoginSelector=true}
s.getConfigWithBranding = function(domain){
var configCopy = Object.assign({},config)
if(config.brandingConfig && config.brandingConfig[domain]){
return Object.assign(configCopy,config.brandingConfig[domain])
}
return config
}
}
......@@ -6,7 +6,7 @@ module.exports = function(s){
}
var config = require(s.location.config);
if(!config.productType){
config.productType='CE'
config.productType = 'CE'
}
//config defaults
if(config.cpuUsageMarker === undefined){config.cpuUsageMarker='%Cpu'}
......
var fs = require('fs')
var express = require('express')
module.exports = function(s,config,lang,app,io){
function mergeDeep(...objects) {
const isObject = obj => obj && typeof obj === 'object';
return objects.reduce((prev, obj) => {
Object.keys(obj).forEach(key => {
const pVal = prev[key];
const oVal = obj[key];
if (Array.isArray(pVal) && Array.isArray(oVal)) {
prev[key] = pVal.concat(...oVal);
}
else if (isObject(pVal) && isObject(oVal)) {
prev[key] = mergeDeep(pVal, oVal);
}
else {
prev[key] = oVal;
}
});
return prev;
}, {});
}
s.customAutoLoadModules = {}
s.customAutoLoadTree = {
pages: [],
......@@ -14,7 +36,7 @@ module.exports = function(s,config,lang,app,io){
superLibsJs: [],
superLibsCss: []
}
var folderPath = __dirname + '/customAutoLoad'
var folderPath = s.mainDirectory + '/libs/customAutoLoad'
var search = function(searchFor,searchIn){return searchIn.indexOf(searchFor) > -1}
fs.readdir(folderPath,function(err,folderContents){
if(!err && folderContents){
......@@ -117,6 +139,24 @@ module.exports = function(s,config,lang,app,io){
})
})
break;
case'definitions':
var definitionsFolder = s.checkCorrectPathEnding(customModulePath) + 'definitions/'
fs.readdir(definitionsFolder,function(err,files){
if(err)return console.log(err);
files.forEach(function(filename){
var fileData = require(definitionsFolder + filename)
var rule = filename.replace('.json','').replace('.js','')
if(config.language === rule){
s.definitions = mergeDeep(s.definitions,fileData)
}
if(s.loadedDefinitons[rule]){
s.loadedDefinitons[rule] = mergeDeep(s.loadedDefinitons[rule],fileData)
}else{
s.loadedDefinitons[rule] = mergeDeep(s.copySystemDefaultDefinitions(),fileData)
}
})
})
break;
}
})
})
......
var fs = require('fs')
var express = require('express')
module.exports = function(s,config,lang,app,io){
s.location.definitions = s.mainDirectory+'/definitions'
try{
var definitions = require(s.location.definitions+'/'+config.language+'.js')(s,config,lang)
}catch(er){
console.error(er)
console.log('There was an error loading your definition file.')
try{
var definitions = require(s.location.definitions+'/en_CA.js')(s,config,lang)
}catch(er){
console.error(er)
console.log('There was an error loading your definition file.')
var definitions = require(s.location.definitions+'/en_CA.json');
}
}
//load defintions dynamically
s.definitions = definitions
s.copySystemDefaultDefinitions = function(){
//en_CA
return Object.assign(s.definitions,{})
}
s.loadedDefinitons={}
s.loadedDefinitons[config.language] = s.copySystemDefaultDefinitions()
s.getDefinitonFile = function(rule){
if(rule && rule !== ''){
var file = s.loadedDefinitons[rule]
if(!file){
try{
s.loadedDefinitons[rule] = require(s.location.definitions+'/'+rule+'.js')(s,config,lang)
s.loadedDefinitons[rule] = Object.assign(s.copySystemDefaultDefinitions(),s.loadedDefinitons[rule])
file = s.loadedDefinitons[rule]
}catch(err){
file = s.copySystemDefaultDefinitions()
}
}
}else{
file = s.copySystemDefaultDefinitions()
}
return file
}
return definitions
}
......@@ -57,12 +57,14 @@ module.exports = function(s,config){
e.triggerTimer = {}
var regions = s.createPamDiffRegionArray(regionJson,globalColorThreshold,globalSensitivity,fullFrame)
s.group[e.ke].mon[e.id].pamDiff = new PamDiff({
var pamDiffOptions = {
grayscale: 'luminosity',
regions : regions.forPam,
drawMatrix : e.details.detector_show_matrix
});
regions : regions.forPam
}
if(e.details.detector_show_matrix==='1'){
pamDiffOptions.response = 'bounds'
}
s.group[e.ke].mon[e.id].pamDiff = new PamDiff(pamDiffOptions);
s.group[e.ke].mon[e.id].p2p = new P2P()
var regionArray = Object.values(regionJson)
if(config.detectorMergePamRegionTriggers === true){
......@@ -94,7 +96,7 @@ module.exports = function(s,config){
++filteredCount
if(!err1 && !err2)++filteredCountSuccess
if(filteredCount === trigger.merged.length && filteredCountSuccess > 0){
detectorObject.doObjectDetection = (s.ocv && e.details.detector_use_detect_object === '1')
detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1')
s.triggerEvent(detectorObject)
}
})
......@@ -106,7 +108,7 @@ module.exports = function(s,config){
s.checkMaximumSensitivity(e, region, detectorObject, function(err1) {
s.checkTriggerThreshold(e, region, detectorObject, function(err2) {
if(!err1 && !err2){
detectorObject.doObjectDetection = (s.ocv && e.details.detector_use_detect_object === '1')
detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1')
s.triggerEvent(detectorObject)
}
})
......@@ -161,7 +163,7 @@ module.exports = function(s,config){
s.checkMaximumSensitivity(e, region, detectorObject, function(err1) {
s.checkTriggerThreshold(e, region, detectorObject, function(err2) {
if(!err1 && ! err2){
detectorObject.doObjectDetection = (s.ocv && e.details.detector_use_detect_object === '1')
detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1')
s.triggerEvent(detectorObject)
}
})
......@@ -176,13 +178,17 @@ module.exports = function(s,config){
s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => {
data.trigger.forEach(function(trigger){
s.filterTheNoise(e,noiseFilterArray,regions,trigger,function(){
s.createMatrixFromPamTrigger(trigger)
buildTriggerEvent(trigger)
})
})
})
}else{
s.group[e.ke].mon[e.id].pamDiff.on('diff', (data) => {
data.trigger.forEach(buildTriggerEvent)
data.trigger.forEach(function(trigger){
s.createMatrixFromPamTrigger(trigger)
buildTriggerEvent(trigger)
})
})
}
}
......@@ -305,6 +311,7 @@ module.exports = function(s,config){
name.push(trigger.name + ' ('+trigger.percent+'%)')
++n
sum += trigger.percent
s.createMatrixFromPamTrigger(trigger)
if(trigger.matrix)matrices.push(trigger.matrix)
})
var average = sum / n
......@@ -318,6 +325,7 @@ module.exports = function(s,config){
}
}else{
var trigger = data.trigger[0]
s.createMatrixFromPamTrigger(trigger)
trigger.matrices = [trigger.matrix]
}
return trigger
......@@ -357,4 +365,28 @@ module.exports = function(s,config){
if(callback)callback(foundInRegion,collisions)
return foundInRegion
}
s.createMatrixFromPamTrigger = function(trigger){
if(
trigger.minX &&
trigger.maxX &&
trigger.minY &&
trigger.maxY
){
var coordinates = [
{"x" : trigger.minX, "y" : trigger.minY},
{"x" : trigger.maxX, "y" : trigger.minY},
{"x" : trigger.maxX, "y" : trigger.maxY}
]
var width = Math.sqrt( Math.pow(coordinates[1].x - coordinates[0].x, 2) + Math.pow(coordinates[1].y - coordinates[0].y, 2));
var height = Math.sqrt( Math.pow(coordinates[2].x - coordinates[1].x, 2) + Math.pow(coordinates[2].y - coordinates[1].y, 2))
trigger.matrix = {
x: coordinates[0].x,
y: coordinates[0].y,
width: width,
height: height,
tag: trigger.name
}
}
return trigger
}
}
......@@ -3,33 +3,6 @@ var execSync = require('child_process').execSync
module.exports = function(s,config,lang,app,io){
if(config.dropInEventServer === true){
if(config.dropInEventDeleteFileAfterTrigger === undefined)config.dropInEventDeleteFileAfterTrigger = true
var authenticateUser = function(username,password,callback){
var splitUsername = username.split('@')
if(splitUsername[1] !== 'Shinobi' && splitUsername[1] !== 'shinobi'){
s.sqlQuery('SELECT ke,uid FROM Users WHERE mail=? AND (pass=? OR pass=?)',[
username,
password,
s.createHash(password)
],function(err,r){
var user
if(r && r[0]){
user = r[0]
}
callback(err,user)
})
}else{
s.sqlQuery('SELECT ke,uid FROM API WHERE code=? AND ke=?',[
splitUsername[0], //code
password //ke
],function(err,r){
var apiKey
if(r && r[0]){
apiKey = r[0]
}
callback(err,apiKey)
})
}
}
var beforeMonitorsLoadedOnStartup = function(){
if(!config.dropInEventsDir){
config.dropInEventsDir = s.dir.streams + 'dropInEvents/'
......@@ -133,7 +106,7 @@ module.exports = function(s,config,lang,app,io){
ftpServer.on('login', (data, resolve, reject) => {
var username = data.username
var password = data.password
authenticateUser(username,password,function(err,user){
s.basicOrApiAuthentication(username,password,function(err,user){
if(user){
resolve({root: s.dir.dropInEvents + user.ke})
}else{
......@@ -162,7 +135,7 @@ module.exports = function(s,config,lang,app,io){
onAuth(auth, session, callback) {
var username = auth.username
var password = auth.password
authenticateUser(username,password,function(err,user){
s.basicOrApiAuthentication(username,password,function(err,user){
if(user){
callback(null, {user: user.ke})
}else{
......
......@@ -185,6 +185,7 @@ module.exports = function(s,config,lang){
d.details.matrices = reviewedMatrix
}
}
var eventTime = new Date()
//motion counter
if(filter.addToMotionCounter && filter.record){
if(!s.group[d.ke].mon[d.id].detector_motion_count){
......@@ -254,7 +255,7 @@ module.exports = function(s,config,lang){
}
//save this detection result in SQL, only coords. not image.
if(filter.save && currentConfig.detector_save === '1'){
s.sqlQuery('INSERT INTO Events (ke,mid,details,time) VALUES (?,?,?,?)',[d.ke,d.id,detailString,new Date()])
s.sqlQuery('INSERT INTO Events (ke,mid,details,time) VALUES (?,?,?,?)',[d.ke,d.id,detailString,eventTime])
}
if(currentConfig.detector_notrigger === '1'){
var detector_notrigger_timeout
......@@ -273,7 +274,7 @@ module.exports = function(s,config,lang){
detector_timeout = parseFloat(currentConfig.detector_timeout)
}
if(filter.record && d.mon.mode=='start'&&currentConfig.detector_trigger==='1'&&currentConfig.detector_record_method==='sip'){
s.createEventBasedRecording(d)
s.createEventBasedRecording(d,moment(eventTime).subtract(5,'seconds').format('YYYY-MM-DDTHH-mm-ss'))
}else if(filter.record && d.mon.mode!=='stop'&&currentConfig.detector_trigger=='1'&&currentConfig.detector_record_method==='hot'){
if(!d.auth){
d.auth=s.gid();
......@@ -331,7 +332,8 @@ module.exports = function(s,config,lang){
d.cx={f:'detector_trigger',id:d.id,ke:d.ke,details:d.details,doObjectDetection:d.doObjectDetection};
s.tx(d.cx,'DETECTOR_'+d.ke+d.id);
}
s.createEventBasedRecording = function(d){
s.createEventBasedRecording = function(d,fileTime){
if(!fileTime)fileTime = s.formattedTime()
d.mon = s.group[d.ke].mon_conf[d.id]
var currentConfig = s.group[d.ke].mon[d.id].details
if(currentConfig.detector !== '1'){
......@@ -355,7 +357,7 @@ module.exports = function(s,config,lang){
if(!s.group[d.ke].mon[d.id].eventBasedRecording.process){
s.group[d.ke].mon[d.id].eventBasedRecording.allowEnd = false;
var runRecord = function(){
var filename = s.formattedTime()+'.mp4'
var filename = fileTime+'.mp4'
s.userLog(d,{type:lang["Traditional Recording"],msg:lang["Started"]})
//-t 00:'+s.timeObject(new Date(detector_timeout * 1000 * 60)).format('mm:ss')+'
s.group[d.ke].mon[d.id].eventBasedRecording.process = spawn(config.ffmpegDir,s.splitForFFPMEG(('-loglevel warning -analyzeduration 1000000 -probesize 1000000 -re -i "'+s.dir.streams+'/'+d.ke+'/'+d.id+'/detectorStream.m3u8" -c:v copy -strftime 1 "'+s.getVideoDirectory(d.mon) + filename + '"')))
......
......@@ -143,4 +143,24 @@ module.exports = function(s,config){
s.onWebSocketDisconnectionExtensions.push(callback)
}
//
s.onGetCpuUsageExtensions = []
s.onGetCpuUsage = function(callback){
s.onGetCpuUsageExtensions.push(callback)
}
//
s.onGetRamUsageExtensions = []
s.onGetRamUsage = function(callback){
s.onGetRamUsageExtensions.push(callback)
}
//
/////// VIDEOS ////////
s.insertCompletedVideoExtensions = []
s.insertCompletedVideoExtender = function(callback){
s.insertCompletedVideoExtensions.push(callback)
}
/////// TIMELAPSE ////////
s.onInsertTimelapseFrameExtensions = []
s.onInsertTimelapseFrame = function(callback){
s.onInsertTimelapseFrameExtensions.push(callback)
}
}
var fs = require('fs');
var spawn = require('child_process').spawn;
var execSync = require('child_process').execSync;
module.exports = function(s,config,onFinish){
module.exports = function(s,config,lang,onFinish){
var ffmpeg = {}
var downloadingFfmpeg = false;
//check local ffmpeg
......@@ -98,6 +98,27 @@ module.exports = function(s,config,onFinish){
config.availableHWAccels = availableHWAccels
config.availableHWAccels = ['auto'].concat(config.availableHWAccels)
console.log('Available Hardware Acceleration Methods : ',availableHWAccels.join(', '))
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'}
}
s.listOfHwAccels = []
config.availableHWAccels.forEach(function(availibleMethod){
if(methods[availibleMethod]){
var method = methods[availibleMethod]
s.listOfHwAccels.push({
name: method.label,
value: method.value,
})
}
})
}
callback()
}
......@@ -638,8 +659,8 @@ module.exports = function(s,config,onFinish){
x.record_video_filters = []
x.record_string = ''
//record - resolution
if(e.width!==''&&e.height!==''&&!isNaN(e.width)&&!isNaN(e.height)){
x.record_dimensions=' -s '+e.width+'x'+e.height
if(e.record_scale_x!==''&&e.record_scale_y!==''&&e.record_scale_x!=='0'&&e.record_scale_y!=='0'&&!isNaN(e.record_scale_x)&&!isNaN(e.record_scale_y)){
x.record_dimensions=' -s '+e.record_scale_x+'x'+e.record_scale_y
}else{
x.record_dimensions=''
}
......@@ -884,6 +905,24 @@ module.exports = function(s,config,onFinish){
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.buildTimelapseOutput = function(e,x){
if(e.details.record_timelapse === '1'){
if(e.details.input_map_choices&&e.details.input_map_choices.record_timelapse){
//add input feed map
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.record_timelapse)
}
var flags = []
if(e.details.record_timelapse_fps && e.details.record_timelapse_fps !== ''){
flags.push('-r 1/' + e.details.record_timelapse_fps)
}else{
flags.push('-r 1/900') // 15 minutes
}
if(e.details.record_timelapse_vf && e.details.record_timelapse_vf !== '')flags.push('-vf ' + e.details.record_timelapse_vf)
if(e.details.record_timelapse_scale_x && e.details.record_timelapse_scale_x !== '' && e.details.record_timelapse_scale_y && e.details.record_timelapse_scale_y !== '')flags.push(`-s ${e.details.record_timelapse_scale_x}x${e.details.record_timelapse_scale_y}`)
// x.pipe+=` -strftime 1 ${flags.join(' ')} -an -q:v 1 "${e.dirTimelapse}%Y-%m-%d/%Y-%m-%dT%H-%M-%S.jpg"`
x.pipe+=` -f singlejpeg ${flags.join(' ')} -an -q:v 1 pipe:7`
}
}
ffmpeg.assembleMainPieces = function(e,x){
//create executeable FFMPEG command
x.ffmpegCommandString = x.loglevel+x.input_fps;
......@@ -941,6 +980,7 @@ module.exports = function(s,config,onFinish){
ffmpeg.buildAudioDetector(e,x)
ffmpeg.buildMainDetector(e,x)
ffmpeg.buildCoProcessorFeed(e,x)
ffmpeg.buildTimelapseOutput(e,x)
s.onFfmpegCameraStringCreationExtensions.forEach(function(extender){
extender(e,x)
})
......
......@@ -40,10 +40,44 @@ module.exports = function(s,config){
fs.mkdirSync(s.dir.fileBin);
}
//additional storage areas
s.listOfStorage = [{
name: "Main",
value: ""
}]
s.dir.addStorage.forEach(function(v,n){
v.path = s.checkCorrectPathEnding(v.path)
if(!fs.existsSync(v.path)){
fs.mkdirSync(v.path);
}
s.listOfStorage.push({
name: v.name,
value: v.path
})
})
//get audio files list
s.listOfAudioFiles = [
{
name:"No Sound",
value:""
}
]
fs.readdirSync(s.mainDirectory + '/web/libs/audio').forEach(function(file){
s.listOfAudioFiles.push({
name: file,
value: file
})
})
//get themes list
s.listOfThemes = [
{
name:"Default",
value:""
}
]
fs.readdirSync(s.mainDirectory + '/web/libs/themes').forEach(function(folder){
s.listOfThemes.push({
name: folder,
value: folder
})
})
}
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
module.exports = function(s,config,lang,io){
s.sendDiskUsedAmountToClients = function(e){
//send the amount used disk space to connected users
if(s.group[e.ke]&&s.group[e.ke].init){
s.tx({f:'diskUsed',size:s.group[e.ke].usedSpace,limit:s.group[e.ke].sizeLimit},'GRP_'+e.ke);
}
}
s.heartBeat = function(){
setTimeout(s.heartBeat, 8000);
io.sockets.emit('ping',{beat:1});
......@@ -34,14 +28,20 @@ module.exports = function(s,config,lang,io){
d = d.replace(/(\r\n|\n|\r)/gm, "").replace(/%/g, "")
}
callback(d)
});
s.onGetCpuUsageExtensions.forEach(function(extender){
extender(d)
})
})
} else if(k.cmd){
exec(k.cmd,{encoding:'utf8',detached: true},function(err,d){
if(s.isWin===true){
d=d.replace(/(\r\n|\n|\r)/gm,"").replace(/%/g,"")
}
callback(d)
});
s.onGetCpuUsageExtensions.forEach(function(extender){
extender(d)
})
})
} else {
callback(0)
}
......@@ -68,7 +68,10 @@ module.exports = function(s,config,lang,io){
d=(parseInt(d.split('=')[1])/(s.totalmem/1000))*100
}
callback(d)
});
s.onGetRamUsageExtensions.forEach(function(extender){
extender(d)
})
})
}else{
callback(0)
}
......
var fs = require('fs')
module.exports = function(s,config){
if(!config.language){
config.language='en_CA'
......@@ -9,19 +10,19 @@ module.exports = function(s,config){
console.log('There was an error loading your language file.')
var lang = require(s.location.languages+'/en_CA.json');
}