diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..90e4911 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +docker-entrypoint.sh text eol=lf diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..4b967b7 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,3 @@ +**Detailed Instructions for multiple Operating Systems can now be found in the docs.** + +https://shinobi.video/docs/start \ No newline at end of file diff --git a/INSTALL/cuda9-part1.sh b/INSTALL/cuda9-part1.sh index cc09bf7..88a9ce5 100644 --- a/INSTALL/cuda9-part1.sh +++ b/INSTALL/cuda9-part1.sh @@ -1,10 +1,10 @@ #https://devtalk.nvidia.com/default/topic/1000340/cuda-setup-and-installation/-quot-nvidia-smi-has-failed-because-it-couldn-t-communicate-with-the-nvidia-driver-quot-ubuntu-16-04/4 sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub -sudo echo "# NVIDIA Graphics Driver Repo (Added by Shinobi installer)" | sudo tee -a /etc/apt/sources.list -sudo echo "# Public Key : sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub" | sudo tee -a /etc/apt/sources.list -sudo echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64 /" | sudo tee -a /etc/apt/sources.list -apt update -sudo apt -y install cuda-drivers +sudo echo "# NVIDIA Graphics Driver Repo (Added by Shinobi installer)" >> /etc/apt/sources.list +sudo echo "# Public Key : sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub" >> /etc/apt/sources.list +sudo echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64 /" >> /etc/apt/sources.list +sudo apt update +sudo apt-get -y install cuda-drivers echo "After rebooting you need to run part 2. The file is named `cuda9-part2-after-reboot.sh`." echo "Reboot is required. Do it now?" diff --git a/INSTALL/opencv-cuda.sh b/INSTALL/opencv-cuda.sh index c9f1045..1a1ee50 100644 --- a/INSTALL/opencv-cuda.sh +++ b/INSTALL/opencv-cuda.sh @@ -1,13 +1,10 @@ #!/bin/bash -#dlib -echo "=================" -echo "Installing OpenCV" -echo "=================" +# OpenCV CUDA if [ $(dpkg-query -W -f='${Status}' git 2>/dev/null | grep -c "ok installed") -eq 0 ]; then echo "Installing Git..." apt install git -y; fi -sudo apt-get install libopenblas-dev -y + if [ ! -e "./opencv" ]; then echo "Downloading OpenCV..." git clone https://github.com/opencv/opencv.git @@ -31,64 +28,46 @@ fi echo "Entering OpenCV Build Directory..." cd build echo "*****************" -if [ -f /etc/lsb-release ]; then - flavor=$(cat /var/log/installer/media-info) - echo "$flavor" - echo "*****************" - echo "Adding Additional Repository" - echo "http://security.ubuntu.com/ubuntu" - if [ "$flavor" = *"Artful"* ]; then - sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu artful-security main" - fi - if [ "$flavor" = *"Zesty"* ]; then - sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu zesty-security main" - fi - if [ "$flavor" = *"Xenial"* ]; then - sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main" - fi - if [ "$flavor" = *"Trusty"* ]; then - sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu trusty-security main" - fi - echo "Downloading Libraries" - sudo apt-get install libjpeg-dev libpango1.0-dev libgif-dev build-essential gcc-6 g++-6 -y; - sudo apt-get install libxvidcore-dev libx264-dev -y; - sudo apt-get install libatlas-base-dev gfortran -y; - - sudo apt install build-essential cmake pkg-config unzip ffmpeg qtbase5-dev python-dev python3-dev python-numpy python3-numpy libhdf5-dev libgtk-3-dev libdc1394-22 libdc1394-22-dev libjpeg-dev libtiff5-dev libtesseract-dev -y; - - sudo apt install libavcodec-dev libavformat-dev libswscale-dev libxine2-dev libgstreamer-plugins-base1.0-0 libgstreamer-plugins-base1.0-dev libpng16-16 libpng-dev libv4l-dev libtbb-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev v4l-utils libleptonica-dev -y - - echo "Setting CUDA Paths" - export LD_LIBRARY_PATH=/usr/local/cuda/lib - export PATH=$PATH:/usr/local/cuda/bin - echo "Configure OpenCV Build" - - cmake -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_NVCUVID=ON -D FORCE_VTK=ON -D WITH_XINE=ON -D WITH_CUDA=ON -D WITH_OPENGL=ON -D WITH_TBB=ON -D WITH_OPENCL=ON -D CMAKE_BUILD_TYPE=RELEASE -D CUDA_NVCC_FLAGS="-D_FORCE_INLINES --expt-relaxed-constexpr" -D WITH_GDAL=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules/ -D ENABLE_FAST_MATH=1 -D CUDA_FAST_MATH=1 -D WITH_CUBLAS=1 -D CXXFLAGS="-std=c++11" -DCMAKE_CXX_COMPILER=g++-6 -DCMAKE_C_COMPILER=gcc-6 .. - - echo "Start OpenCV Build" - make -j "$(nproc)" - echo "Install OpenCV Build" - sudo make install - sudo /bin/bash -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf' - sudo ldconfig - sudo apt-get update +flavor=$(cat /var/log/installer/media-info) +echo "$flavor" +echo "*****************" +echo "Adding Additional Repository" +echo "http://security.ubuntu.com/ubuntu" +if [ "$flavor" = *"Artful"* ]; then + sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu artful-security main" fi -if [ -f /etc/redhat-release ]; then - yum install -y \ - protobuf-devel \ - leveldb-devel \ - snappy-devel \ - opencv-devel \ - boost-devel \ - hdf5-devel \ - gflags-devel \ - glog-devel \ - lmdb-devel \ - cmake +if [ "$flavor" = *"Zesty"* ]; then + sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu zesty-security main" fi -echo "Leaving OpenCV Directory" -cd ../.. +if [ "$flavor" = *"Xenial"* ]; then + sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main" +fi +if [ "$flavor" = *"Trusty"* ]; then + sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu trusty-security main" +fi +echo "Downloading Libraries" +sudo apt-get install libjpeg-dev libpango1.0-dev libgif-dev build-essential gcc-6 g++-6 -y; +sudo apt-get install libxvidcore-dev libx264-dev -y; +sudo apt-get install libatlas-base-dev gfortran -y; +sudo apt install build-essential cmake pkg-config unzip ffmpeg qtbase5-dev python-dev python3-dev python-numpy python3-numpy libhdf5-dev libgtk-3-dev libdc1394-22 libdc1394-22-dev libjpeg-dev libtiff5-dev libtesseract-dev -y; + +sudo apt install libavcodec-dev libavformat-dev libswscale-dev libxine2-dev libgstreamer-plugins-base1.0-0 libgstreamer-plugins-base1.0-dev libpng16-16 libpng-dev libv4l-dev libtbb-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev v4l-utils libleptonica-dev -y + +echo "Setting CUDA Paths" +export LD_LIBRARY_PATH=/usr/local/cuda/lib +export PATH=$PATH:/usr/local/cuda/bin +echo "Configure OpenCV Build" + +cmake -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_NVCUVID=ON -D FORCE_VTK=ON -D WITH_XINE=ON -D WITH_CUDA=ON -D WITH_OPENGL=ON -D WITH_TBB=ON -D WITH_OPENCL=ON -D CMAKE_BUILD_TYPE=RELEASE -D CUDA_NVCC_FLAGS="-D_FORCE_INLINES --expt-relaxed-constexpr" -D WITH_GDAL=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules/ -D ENABLE_FAST_MATH=1 -D CUDA_FAST_MATH=1 -D WITH_CUBLAS=1 -D CXXFLAGS="-std=c++11" -DCMAKE_CXX_COMPILER=g++-6 -DCMAKE_C_COMPILER=gcc-6 .. + +echo "Start OpenCV Build" +make -j "$(nproc)" +echo "Install OpenCV Build" +sudo make install +sudo /bin/bash -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf' +sudo ldconfig +sudo apt-get update echo "=============" echo "Done installing OpenCV!" echo "=============" diff --git a/INSTALL/start.sh b/INSTALL/start.sh index a2439f7..64df53e 100644 --- a/INSTALL/start.sh +++ b/INSTALL/start.sh @@ -3,6 +3,7 @@ if [ -e "INSTALL/installed.txt" ]; then echo "Starting Shinobi" pm2 start camera.js pm2 start cron.js + pm2 logs fi if [ ! -e "INSTALL/installed.txt" ]; then chmod +x INSTALL/now.sh&&INSTALL/now.sh diff --git a/README.md b/README.md index 1c5c965..03c1f9f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Shinobi Pro -### (GPLv3) +### (Creative Commons v4.0) Shinobi is the Open Source CCTV Solution written in Node.JS. Designed with multiple account system, Streams by WebSocket, and Save to WebM. Shinobi can record IP Cameras and Local Cameras. diff --git a/camera.js b/camera.js index 1e4e029..fc3c331 100644 --- a/camera.js +++ b/camera.js @@ -1067,7 +1067,6 @@ s.video=function(x,e,k){ if(s.group[e.ke].usedSpace>(s.group[e.ke].sizeLimit*config.cron.deleteOverMaxOffset)){ s.sqlQuery('SELECT * FROM Videos WHERE status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ke=? ORDER BY `time` ASC LIMIT 2',[e.ke],function(err,evs){ k.del=[];k.ar=[e.ke]; - if(!evs)return console.log(err) evs.forEach(function(ev){ ev.dir=s.video('getDir',ev)+s.formattedTime(ev.time)+'.'+ev.ext; k.del.push('(mid=? AND time=?)'); @@ -4408,43 +4407,6 @@ var tx; break; } }) - //functions for retrieving cron announcements - cn.on('cron',function(d){ - if(d.f==='init'){ - if(config.cron.key){ - if(config.cron.key===d.cronKey){ - s.cron={started:moment(),last_run:moment(),id:cn.id}; - }else{ - cn.disconnect() - } - }else{ - s.cron={started:moment(),last_run:moment(),id:cn.id}; - } - }else{ - if(s.cron&&cn.id===s.cron.id){ - delete(d.cronKey) - switch(d.f){ - case'filters': - s.filterEvents(d.ff,d); - break; - case's.tx': - s.tx(d.data,d.to) - break; - case's.video': - s.video(d.data,d.file) - break; - case'start':case'end': - d.mid='_cron';s.log(d,{type:'cron',msg:d.msg}) - break; - default: - s.systemLog('CRON : ',d) - break; - } - }else{ - cn.disconnect() - } - } - }) cn.on('disconnect', function () { if(cn.socketVideoStream){ cn.closeSocketVideoStream() @@ -4471,9 +4433,6 @@ var tx; s.tx({f:'plugin_engine_unplugged',plug:cn.pluginEngine},'CPU') delete(s.api[cn.pluginEngine]) } - if(cn.cron){ - delete(s.cron); - } if(cn.ocv){ s.tx({f:'detector_unplugged',plug:s.ocv.plug},'CPU') delete(s.ocv); diff --git a/cron.js b/cron.js index ea98d8a..e872eed 100644 --- a/cron.js +++ b/cron.js @@ -10,9 +10,7 @@ var spawn = require('child_process').spawn; var config=require('./conf.json'); //set option defaults -s={ - utcOffset : moment().utcOffset() -}; +s={}; if(config.cron===undefined)config.cron={}; if(config.cron.deleteOld===undefined)config.cron.deleteOld=true; if(config.cron.deleteOrphans===undefined)config.cron.deleteOrphans=false; @@ -25,7 +23,6 @@ if(config.cron.deleteFileBins===undefined)config.cron.deleteFileBins=true; if(config.cron.interval===undefined)config.cron.interval=1; if(config.databaseType===undefined){config.databaseType='mysql'} if(config.databaseLogs===undefined){config.databaseLogs=false} -if(config.useUTC===undefined){config.useUTC=false} if(!config.ip||config.ip===''||config.ip.indexOf('0.0.0.0')>-1)config.ip='localhost'; if(!config.videosDir)config.videosDir=__dirname+'/videos/'; @@ -130,12 +127,6 @@ s.moment=function(e,x){ if(!e){e=new Date};if(!x){x='YYYY-MM-DDTHH-mm-ss'}; return moment(e).format(x); } -s.utcToLocal = function(time){ - return moment.utc(time).utcOffset(s.utcOffset).format() -} -s.localToUtc = function(time){ - return moment(time).utc() -} s.nameToTime=function(x){x=x.replace('.webm','').replace('.mp4','').split('T'),x[1]=x[1].replace(/-/g,':');x=x.join(' ');return x;} io = require('socket.io-client')('ws://'+config.ip+':'+config.port);//connect to master s.cx=function(x){x.cronKey=config.cron.key;return io.emit('cron',x)} @@ -269,18 +260,12 @@ s.deleteRowsWithNoVideo=function(v,callback){ if(evs&&evs[0]){ es.del=[];es.ar=[v.ke]; evs.forEach(function(ev){ - var details = JSON.parse(ev.details) - var filename = ev.time - var dir = s.getVideoDirectory(ev)+s.moment(filename)+'.'+ev.ext; - var fileExists = fs.existsSync(dir) - if(details.isUTC === true){ - filename = s.localToUtc(filename).format('YYYY-MM-DDTHH-mm-ss') - dir = s.getVideoDirectory(ev)+filename+'.'+ev.ext; - fileExists = fs.existsSync(dir) - } - if(fileExists !== true){ + ev.dir=s.getVideoDirectory(ev)+s.moment(ev.time)+'.'+ev.ext; + if(fs.existsSync(ev.dir)!==true){ s.video('delete',ev) - s.tx({f:'video_delete',filename:filename+'.'+ev.ext,mid:ev.mid,ke:ev.ke,time:ev.time,end:s.moment(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+ev.ke); + es.del.push('(mid=? AND time=?)'); + es.ar.push(ev.mid),es.ar.push(ev.time); + s.tx({f:'video_delete',filename:s.moment(ev.time)+'.'+ev.ext,mid:ev.mid,ke:ev.ke,time:ev.time,end:s.moment(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+ev.ke); } }); if(es.del.length>0){ @@ -417,7 +402,6 @@ s.processUser = function(number,rows){ //no user object given return } - console.log(v) if(!s.alreadyDeletedRowsWithNoVideosOnStart[v.ke]){ s.alreadyDeletedRowsWithNoVideosOnStart[v.ke]=false; } @@ -431,9 +415,6 @@ s.processUser = function(number,rows){ //days to keep videos if(!v.d.days||v.d.days==''){v.d.days=5}else{v.d.days=parseFloat(v.d.days)}; s.sqlQuery('SELECT * FROM Monitors WHERE ke=?', [v.ke], function(err,rr) { - if(!v.d.filters||v.d.filters==''){ - v.d.filters={}; - } rr.forEach(function(b,m){ b.details=JSON.parse(b.details); if(b.details.max_keep_days&&b.details.max_keep_days!==''){ @@ -462,15 +443,10 @@ s.processUser = function(number,rows){ } }) s.deleteOldLogs(v,function(){ - console.log('deleteOldLogs') s.deleteOldFileBins(v,function(){ - console.log('deleteOldFileBins') s.deleteOldEvents(v,function(){ - console.log('deleteOldEvents') s.checkFilterRules(v,function(){ - console.log('checkFilterRules') s.deleteRowsWithNoVideo(v,function(){ - console.log('deleteRowsWithNoVideo') s.checkForOrphanedFiles(v,function(){ //done user, unlock current, and do next s.overlapLock[v.ke]=false; @@ -482,8 +458,6 @@ s.processUser = function(number,rows){ }) }) }) - }else{ - s.processUser(number+1,rows) } } //recursive function diff --git a/plugins/child/.gitignore b/plugins/child/.gitignore deleted file mode 100644 index bd55664..0000000 --- a/plugins/child/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -conf.json -events -frames \ No newline at end of file diff --git a/plugins/child/child.js b/plugins/child/child.js deleted file mode 100644 index 6b1a17c..0000000 --- a/plugins/child/child.js +++ /dev/null @@ -1,392 +0,0 @@ -var os = require('os'); -var fs = require('fs'); -var path = require('path'); -var mysql = require('mysql'); -var moment = require('moment'); -var request = require("request"); -var spawn = require('child_process').spawn; -var exec = require('child_process').exec; -var execSync = require('child_process').execSync; -var connectionTester = require('connection-tester'); -var config = require('./conf.json'); - -exec("ps aux | grep -ie ffmpeg | awk '{print $2}' | xargs kill -9");//kill any ffmpeg running -process.on('uncaughtException', function (err) { - console.error('uncaughtException',err); -}); -s={connected:false,child_node:true,platform:os.platform(),group:{}}; - -//connect to master -io = require('socket.io-client')('ws://'+config.ws); -//spawn conatiner -s.spawns={}; -//emulate master sql query -sql={ - query:function(x,y,z){ - io.emit('c',{f:'sql',query:x,values:y});if(typeof z==='function'){z();} - } -} -//get this nodes cpu usage -s.cpuUsage=function(e){ - k={} - switch(s.platform){ - case'win32': - k.cmd="@for /f \"skip=1\" %p in ('wmic cpu get loadpercentage') do @echo %p%" - break; - case'darwin': - k.cmd="ps -A -o %cpu | awk '{s+=$1} END {print s}'"; - break; - case'linux': - k.cmd='LANG=C top -b -n 2 | grep "^'+config.cpuUsageMarker+'" | awk \'{print $2}\' | tail -n1'; - break; - } - if(config.customCpuCommand){ - exec(config.customCpuCommand,{encoding:'utf8',detached: true},function(err,d){ - if(s.isWin===true) { - d = d.replace(/(\r\n|\n|\r)/gm, "").replace(/%/g, "") - } - e(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,"") - } - e(d) - }); - } else{ - e(0) - } -} -setInterval(function(){ - s.cpuUsage(function(cpu){ - io.emit('c',{f:'cpu',cpu:parseFloat(cpu)}) - }) -},2000); -//interact with server functions -s.cx=function(x){io.emit('c',x)} -//emulate master socket emitter -s.tx=function(x,y){s.cx({f:'s.tx',data:x,to:y})} -//emulate master logger -s.log=function(x,y){console.log(y);s.cx({f:'s.log',data:s.init('clean',x),to:y})} -//emulate master camera function -s.camera=function(x,y){s.cx({f:'camera',mode:x,data:y})} - -//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.ratio=function(width,height,ratio){ratio = width / height;return ( Math.abs( ratio - 4 / 3 ) < Math.abs( ratio - 16 / 9 ) ) ? '4:3' : '16:9';} -s.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; -}; -s.moment=function(e,x){if(!e){e=new Date};if(!x){x='YYYY-MM-DDTHH-mm-ss'};return moment(e).utcOffset('-0800').format(x)} -s.kill=function(x,e,p){ - if(e&&s.group[e.ke].mon[e.id].record){ - clearTimeout(s.group[e.ke].mon[e.id].record.capturing); - if(s.group[e.ke].mon[e.id].record.request&&s.group[e.ke].mon[e.id].record.request.abort){s.group[e.ke].mon[e.id].record.request.abort();delete(s.group[e.ke].mon[e.id].record.request);} - }; - if(!x||x===1){return};if(!x.stdin){return};p=x.pid;x.stdin.pause();setTimeout(function(){x.kill('SIGTERM');delete(x);setTimeout(function(){exec('kill -9 '+p)},1000)},1000) -} -s.cameraVals=function(e){ - e.t=Object.keys(s.group[e.ke].mon[e.id]);e.a={}; - e.t.forEach(function(n){ - if(s.group[e.ke].mon[e.id][n] instanceof Object){e.a[n]=s.group[e.ke].mon[e.id][n]}; - }); - return e.a; -} -//directories -s.group={}; -s.dir={videos:__dirname+'/videos/',frames:__dirname+'/frames/'}; -if (!fs.existsSync(s.dir.frames)){ - fs.mkdirSync(s.dir.frames); -} -if (!fs.existsSync(s.dir.videos)){ - fs.mkdirSync(s.dir.videos); -} -////Camera Controller -s.init=function(x,e){ - switch(x){ - case 0://camera - if(!s.group[e.ke]){s.group[e.ke]={}}; - if(!s.group[e.ke].mon){s.group[e.ke].mon={}} - if(!s.group[e.ke].mon[e.mid]){s.group[e.ke].mon[e.mid]={}} - if(!s.group[e.ke].mon[e.mid].watch){s.group[e.ke].mon[e.mid].watch={}}; - if(e.type==='record'){e.record=1}else{e.record=0} - if(!s.group[e.ke].mon[e.mid].record){s.group[e.ke].mon[e.mid].record={yes:e.record}}; - if(!s.group[e.ke].mon[e.mid].started){s.group[e.ke].mon[e.mid].started={}}; - if(!s.group[e.ke].mon[e.mid].running){s.group[e.ke].mon[e.mid].running={}}; - break; - case'clean': - if(e instanceof Object){ - x={keys:Object.keys(e),ar:{}}; - x.keys.forEach(function(v){ - if(v!=='record'&&v!=='spawn'&&v!=='running'&&(typeof e[v]!=='function')){x.ar[v]=e[v];} - }); - return x.ar; - } - break; - case'url': - //build a complete url from pieces - e.authd=''; - if(e.details.muser&&e.details.muser!==''&&e.host.indexOf('@')===-1) { - e.authd=e.details.muser+':'+e.details.mpass+'@'; - } - if(e.port==80&&e.details.port_force!=='1'){e.porty=''}else{e.porty=':'+e.port} - e.url=e.protocol+'://'+e.authd+e.host+e.porty+e.path;return e.url; - break; - case'url_no_path': - e.authd=''; - if(!e.details.muser){e.details.muser=''} - if(!e.details.mpass){e.details.mpass=''} - if(e.details.muser!==''&&e.host.indexOf('@')===-1) { - e.authd=e.details.muser+':'+e.details.mpass+'@'; - } - if(e.port==80&&e.details.port_force!=='1'){e.porty=''}else{e.porty=':'+e.port} - e.url=e.protocol+'://'+e.authd+e.host+e.porty;return e.url; - break; - } - if(typeof e.callback==='function'){setTimeout(function(){e.callback();delete(e.callback);},2000);} -} -s.video=function(x,e){ - if(!e){e={}}; - if(e.mid){e.id=e.mid}; - switch(x){ - case'delete': - e.dir=s.dir.videos+e.ke+'/'+e.id+'/'; - e.save=[e.id,e.ke,s.nameToTime(e.filename),0]; - sql.query('DELETE FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=? AND `status`=?',e.save) - s.tx({f:'video_delete',reason:'Camera Error',filename:e.filename+'.'+e.ext,mid:e.id,ke:e.ke,time:s.nameToTime(e.filename),end:moment().format('YYYY-MM-DD HH:mm:ss')},'GRP_'+e.ke); - if(fs.existsSync(e.dir+e.filename+'.'+e.ext)){ - return fs.unlink(e.dir+e.filename+'.'+e.ext); - } - break; - case'close': - e.dir=s.dir.videos+e.ke+'/'+e.id+'/'; - console.log(e.dir+e.filename+'.'+e.ext) - if(fs.existsSync(e.dir+e.filename+'.'+e.ext)){ - e.filesize=fs.statSync(e.dir+e.filename+'.'+e.ext)["size"]; - if((e.filesize/100000).toFixed(2)>0.25){ - e.save=[e.filesize,e.frames,1,e.id,e.ke,s.nameToTime(e.filename)]; - sql.query('UPDATE Videos SET `size`=?,`frames`=?,`status`=? WHERE `mid`=? AND `ke`=? AND `time`=?',e.save) - fs.readFile(e.dir+e.filename+'.'+e.ext,function (err,data) { - s.cx({f:'created_file',mid:e.id,ke:e.ke,created_file:data,filename:e.filename+'.'+e.ext,d:s.init('clean',e)}); - s.tx({f:'video_build_success',filename:e.filename+'.'+e.ext,mid:e.id,ke:e.ke,time:s.nameToTime(e.filename),size:e.filesize,end:s.moment(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+e.ke); - }); - }else{ - s.video('delete',e); - s.log(e,{type:'File Corrupt',msg:{ffmpeg:s.group[e.ke].mon[e.mid].ffmpeg,filesize:(e.filesize/100000).toFixed(2)}}) - } - }else{ - s.video('delete',e); - s.log(e,{type:'File Not Exist',msg:'Cannot save non existant file. Something went wrong.',ffmpeg:s.group[e.ke].mon[e.id].ffmpeg}) - } - break; - } -} -s.ffmpeg=function(e,x){ - if(!x){x={tmp:''}} -// if(!e.details.cutoff||e.details.cutoff===''){x.cutoff=15}else{x.cutoff=parseFloat(e.details.cutoff)};if(isNaN(x.cutoff)===true){x.cutoff=15} -// x.segment=' -f segment -strftime 1 -segment_time '+(60*x.cutoff)+' -segment_format '+e.ext - if(!e.details.timestamp||e.details.timestamp==1){x.time=' -vf drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSans.ttf:text=\'%{localtime}\':x=(w-tw)/2:y=0:fontcolor=white:box=1:boxcolor=0x00000000@1:fontsize=10';}else{x.time=''} - switch(e.ext){ - case'mp4': - x.vcodec='libx265';x.acodec='libfaac'; - if(e.details.vcodec&&e.details.vcodec!==''){x.vcodec=e.details.vcodec} - break; - case'webm': - x.acodec='libvorbis',x.vcodec='libvpx'; - break; - } - if(e.details.acodec&&e.details.acodec!==''){x.acodec=e.details.acodec} - if(x.acodec==='none'){x.acodec=''}else{x.acodec=' -acodec '+x.acodec} - if(x.vcodec!=='none'){x.vcodec=' -vcodec '+x.vcodec} - if(e.fps&&e.fps!==''){x.framerate=' -r '+e.fps}else{x.framerate=''} - if(e.details.vf&&e.details.vf!==''){ - if(x.time===''){x.vf=' -vf '}else{x.vf=','} - x.vf+=e.details.vf; - x.time+=x.vf; - } - if(e.details.svf&&e.details.svf!==''){x.svf=' -vf '+e.details.svf;}else{x.svf='';} -// if(e.details.svf){'-vf "rotate=45*(PI/180)'} - switch(e.type){ - case'socket':case'jpeg':case'pipe': - if(!x.vf||x.vf===','){x.vf=''} - x.tmp='-loglevel warning -pattern_type glob -f image2pipe'+x.framerate+' -vcodec mjpeg -i -'+x.vcodec+x.time+x.framerate+' -use_wallclock_as_timestamps 1 -q:v 1'+x.vf+' '+e.dir+e.filename+'.'+e.ext; - break; - case'mjpeg': - if(e.mode=='record'){ - x.watch=x.vcodec+x.time+' -r 10 -s '+e.width+'x'+e.height+' -use_wallclock_as_timestamps 1 -q:v 1 '+e.dir+e.filename+'.'+e.ext+'' - }else{ - x.watch=''; - }; - x.tmp='-loglevel warning -reconnect 1 -f mjpeg -i '+e.url+''+x.watch+' -f image2pipe'+x.svf+' -s '+e.ratio+' pipe:1'; - break; - case'h264': - if(!x.vf||x.vf===','){x.vf=''} - if(e.mode=='record'){ - x.watch=x.vcodec+x.framerate+x.acodec+' -movflags frag_keyframe+empty_moov -s '+e.width+'x'+e.height+' -use_wallclock_as_timestamps 1 -q:v 1'+x.vf+' '+e.dir+e.filename+'.'+e.ext - }else{ - x.watch=''; - }; - x.tmp='-loglevel warning -i '+e.url+' -stimeout 2000'+x.watch+' -f image2pipe'+x.svf+' -s '+e.ratio+' pipe:1'; - break; - case'local': - if(e.mode=='record'){ - x.watch=x.vcodec+x.time+x.framerate+x.acodec+' -movflags frag_keyframe+empty_moov -s '+e.width+'x'+e.height+' -use_wallclock_as_timestamps 1 '+e.dir+e.filename+'.'+e.ext - }else{ - x.watch=''; - }; - x.tmp='-loglevel warning -i '+e.path+''+x.watch+' -f image2pipe'+x.svf+' -s '+e.ratio+' pipe:1'; - break; - } - s.group[e.ke].mon[e.mid].ffmpeg=x.tmp; - return spawn('ffmpeg',x.tmp.split(' ')); -} - -//child functions -var cn={}; -io.on('connect', function(d){ - console.log('connected'); - io.emit('c',{f:'init',socketKey:config.key,u:{name:config.name}}) -}); -io.on('c',function(d){ - console.log(d.f); - switch(d.f){ - case'init_success': - s.connected=true; - s.other_helpers=d.child_helpers; - break; - case'kill': - s.init(0,d.d); - s.kill(s.group[d.d.ke].mon[d.d.id].spawn,d.d) - break; - case'sync': - s.init(0,d.sync); - Object.keys(d.sync).forEach(function(v){ - s.group[d.sync.ke].mon[d.sync.mid][v]=d.sync[v]; - }); - break; - case'delete_file'://delete video - d.dir=s.dir.videos+d.ke+'/'+d.mid+'/'+d.file; - if(fs.existsSync(d.dir)){ - fs.unlink(d.dir); - } - break; - case'close'://close video - s.video('close',d.d); - break; - case'spawn'://start video - s.init(0,d.d); - s.group[d.d.ke].mon[d.d.id]=d.mon; - if(!s.group[d.d.ke].mon_conf){s.group[d.d.ke].mon_conf={}} - if(!s.group[d.d.ke].mon_conf[d.d.id]){s.group[d.d.ke].mon_conf[d.d.id]=s.init('clean',d.d);} - if(s.group[d.d.ke].mon[d.d.id].spawn&&s.group[d.d.ke].mon[d.d.id].spawn.stdin){return} - if(d.d.mode==='record'){ - console.log(s.group[d.d.ke].mon[d.d.id]) - s.group[d.d.ke].mon[d.d.id].record.yes=1; - d.d.dir=s.dir.videos+d.d.ke+'/'; - if (!fs.existsSync(d.d.dir)){ - fs.mkdirSync(d.d.dir); - } - d.d.dir=s.dir.videos+d.d.ke+'/'+d.d.id+'/'; - if (!fs.existsSync(d.d.dir)){ - fs.mkdirSync(d.d.dir); - } - }else{ - s.group[d.d.ke].mon[d.d.mid].record.yes=0; - } - if(d.d.mode==='record'||d.d.type==='mjpeg'||d.d.type==='h264'||d.d.type==='local'){ - s.group[d.d.ke].mon[d.d.id].spawn = s.ffmpeg(d.d); - s.log(d.d,{type:'FFMPEG Process Starting',msg:{cmd:s.group[d.d.ke].mon[d.d.id].ffmpeg}}); - } - d.d.frames=0; - switch(d.d.type){ - case'jpeg': - if(!d.d.details.sfps||d.d.details.sfps===''){ - d.d.details.sfps=parseFloat(d.d.details.sfps); - if(isNaN(d.d.details.sfps)){d.d.details.sfps=1} - } - d.d.captureOne=function(f){ - s.group[d.d.ke].mon[d.d.id].record.request=request({url:d.d.url,method:'GET',encoding: null,timeout:3000},function(er,data){ - ++d.d.frames; if(s.group[d.d.ke].mon[d.d.id].spawn&&s.group[d.d.ke].mon[d.d.id].spawn.stdin){ - if(er){ - ++d.d.error_count; - s.log(d.d,{type:'Snapshot Error',msg:er}); - return; - } - if(d.d.mode==='record'&&s.group[d.d.ke].mon[d.d.id].spawn&&s.group[d.d.ke].mon[d.d.id].spawn.stdin){ - s.group[d.d.ke].mon[d.d.id].spawn.stdin.write(data.body); - } - if(s.group[d.d.ke].mon[d.d.id].watch&&Object.keys(s.group[d.d.ke].mon[d.d.id].watch).length>0){ - s.tx({f:'monitor_frame',ke:d.d.ke,id:d.d.id,time:s.moment(),frame:data.body.toString('base64'),frame_format:'b64'},'MON_'+d.d.id); - } - s.group[d.d.ke].mon[d.d.id].record.capturing=setTimeout(function(){d.d.captureOne()},1000/d.d.details.sfps); - clearTimeout(d.d.timeOut),d.d.timeOut=setTimeout(function(){d.d.error_count=0;},3000) - } - }).on('error', function(err){ -// if(s.group[d.d.ke]&&s.group[d.d.ke].mon[d.d.id]&&s.group[d.d.ke].mon[d.d.id].record&&s.group[d.d.ke].mon[d.d.id].record.request){s.group[d.d.ke].mon[d.d.id].record.request.abort();} - clearTimeout(s.group[d.d.ke].mon[d.d.id].record.capturing); - if(d.d.error_count>4){d.d.fn();return} - d.d.captureOne(); - }); - } - d.d.captureOne() - break; - case'mjpeg':case'h264'://case'socket':case'local': - if(!s.group[d.d.ke]||!s.group[d.d.ke].mon[d.d.id]){s.init(0,d.d)} - if(s.group[d.d.ke].mon[d.d.id].spawn){ - s.group[d.d.ke].mon[d.d.id].spawn.on('error',function(er){d.d.error({type:'Spawn Error',msg:er})}) - s.group[d.d.ke].mon[d.d.id].spawn.stdout.on('data',function(de){ - s.tx({f:'monitor_frame',ke:d.d.ke,id:d.d.id,time:s.moment(),frame:de.toString('base64'),frame_format:'b64'},'MON_'+d.d.id); - }); - s.group[d.d.ke].mon[d.d.id].spawn.stderr.on('data',function(de){ - de=de.toString(); - d.d.chk=function(x){return de.indexOf(x)>-1;} - switch(true){ -// case d.d.chk('av_interleaved_write_frame'): - case d.d.chk('Connection timed out'): - setTimeout(function(){s.log(d.d,{type:"Can't Connect",msg:'Retrying...'});d.d.error_fatal();},1000)//restart - break; - case d.d.chk('No pixel format specified'): - s.log(d.d,{type:"FFMPEG STDERR",msg:{ffmpeg:s.group[d.d.ke].mon[d.d.id].ffmpeg,msg:de}}) - break; - case d.d.chk('RTP: missed'): - case d.d.chk('deprecated pixel format used, make sure you did set range correctly'): - return - break; - case d.d.chk('No such file or directory'): - case d.d.chk('Unable to open RTSP for listening'): - case d.d.chk('timed out'): - case d.d.chk('Invalid data found when processing input'): - case d.d.chk('Immediate exit requested'): - case d.d.chk('reset by peer'): - if(d.d.frames===0&&x==='record'){s.video('delete',d.d)}; - break; - } - s.log(d.d,{type:"FFMPEG STDERR",msg:de}) - }); - } - break; - } - break; - case'video': - s.video(d.d[0],d.d[1]); - break; - } -}); -io.on('disconnect',function(d){ - s.connected=false; -}); - -//web server -if(config.port===undefined)config.port = 8080; -if(config.ip===undefined||config.ip===''||config.ip.indexOf('0.0.0.0')>-1){config.ip='localhost'}else{config.bindip=config.ip}; -var childNodeHTTP = express(); -var childNodeServer = http.createServer(app); -var childNodeWebsocket = new (require('socket.io'))() -childNodeServer.listen(config.port,config.bindip,function(){ - console.log('SHINOBI CHILD NODE RUNNING ON PORT : '+config.port); -}); -childNodeWebsocket.attach(childNodeServer); \ No newline at end of file diff --git a/plugins/child/conf.sample.json b/plugins/child/conf.sample.json deleted file mode 100644 index d1b2008..0000000 --- a/plugins/child/conf.sample.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name":"childMachine1", - "ws":"192.168.1.48", - "port":8080, - "key":"3123asdasdf1dtj1hjk23sdfaasd12asdasddfdbtnkkfgvesra3asdsd3123afdsfqw345", -} \ No newline at end of file diff --git a/plugins/darknet/INSTALL.sh b/plugins/darknet/INSTALL.sh deleted file mode 100644 index f2cdc4d..0000000 --- a/plugins/darknet/INSTALL.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -ln -s /usr/local/cuda/targets/x86_64-linux/lib/libcurand.so /usr/local/lib/libcurand.so -ln -s /usr/local/cuda/targets/x86_64-linux/lib/libcublas.so /usr/local/lib/libcublas.so -ln -s /usr/local/cuda/targets/x86_64-linux/lib/libcudart.so /usr/local/lib/libcudart.so - -git clone https://github.com/OrKoN/darknet -rm darknet/Makefile -cp modifiedMakefile darknet/Makefile -cd darknet -make OPENCV=1 GPU=1 -make install - -npm install @moovel/yolo --unsafe-perm \ No newline at end of file diff --git a/plugins/darknet/conf.sample.json b/plugins/darknet/conf.sample.json deleted file mode 100644 index 1a4b8dc..0000000 --- a/plugins/darknet/conf.sample.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "plug":"OpenCV", - "host":"localhost", - "port":8080, - "hostPort":8082, - "key":"change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json", - "mode":"client", - "type":"detector" -} \ No newline at end of file diff --git a/plugins/darknet/modifiedMakefile b/plugins/darknet/modifiedMakefile deleted file mode 100644 index d5f61aa..0000000 --- a/plugins/darknet/modifiedMakefile +++ /dev/null @@ -1,119 +0,0 @@ -GPU=0 -CUDNN=0 -OPENCV=1 -OPENMP=0 -DEBUG=0 - -PREFIX = /usr/local - -ARCH= #-gencode arch=compute_20,code=[sm_20,sm_21] \ - -gencode arch=compute_30,code=sm_30 \ - -gencode arch=compute_35,code=sm_35 \ - -gencode arch=compute_50,code=[sm_50,compute_50] \ - -gencode arch=compute_52,code=[sm_52,compute_52] - -# This is what I use, uncomment if you know your arch and want to specify -# ARCH= -gencode arch=compute_52,code=compute_52 - -VPATH=./src/:./examples -SLIB=libdarknet.so -ALIB=libdarknet.a -EXEC=darknet -OBJDIR=./obj/ - -CC=gcc -NVCC=nvcc -AR=ar -ARFLAGS=rcs -OPTS=-Ofast -LDFLAGS= -lm -pthread -COMMON= -Iinclude/ -Isrc/ -CFLAGS=-Wall -Wno-unknown-pragmas -Wfatal-errors -fPIC - -ifeq ($(OPENMP), 1) -CFLAGS+= -fopenmp -endif - -ifeq ($(DEBUG), 1) -OPTS=-O0 -g -endif - -CFLAGS+=$(OPTS) - -ifeq ($(OPENCV), 1) -COMMON+= -DOPENCV -CFLAGS+= -DOPENCV -LDFLAGS+= `pkg-config --libs opencv` -COMMON+= `pkg-config --cflags opencv` -endif - -ifeq ($(GPU), 1) -COMMON+= -DGPU -I/usr/local/cuda/include/ -CFLAGS+= -DGPU -LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand -endif - -ifeq ($(CUDNN), 1) -COMMON+= -DCUDNN -CFLAGS+= -DCUDNN -LDFLAGS+= -lcudnn -endif - -OBJ=gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o detection_layer.o route_layer.o box.o normalization_layer.o avgpool_layer.o layer.o local_layer.o shortcut_layer.o activation_layer.o rnn_layer.o gru_layer.o crnn_layer.o demo.o batchnorm_layer.o region_layer.o reorg_layer.o tree.o lstm_layer.o -EXECOBJA=captcha.o lsd.o super.o voxel.o art.o tag.o cifar.o go.o rnn.o rnn_vid.o compare.o segmenter.o regressor.o classifier.o coco.o dice.o yolo.o detector.o writing.o nightmare.o swag.o darknet.o -ifeq ($(GPU), 1) -LDFLAGS+= -lstdc++ -OBJ+=convolutional_kernels.o deconvolutional_kernels.o activation_kernels.o im2col_kernels.o col2im_kernels.o blas_kernels.o crop_layer_kernels.o dropout_layer_kernels.o maxpool_layer_kernels.o network_kernels.o avgpool_layer_kernels.o -endif - -EXECOBJ = $(addprefix $(OBJDIR), $(EXECOBJA)) -OBJS = $(addprefix $(OBJDIR), $(OBJ)) -DEPS = $(wildcard src/*.h) Makefile include/darknet.h -HEADERS = $(wildcard src/*.h) - -#all: obj backup results $(SLIB) $(ALIB) $(EXEC) -all: obj results $(SLIB) $(ALIB) $(EXEC) - - -$(EXEC): $(EXECOBJ) $(ALIB) - $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(ALIB) - -$(ALIB): $(OBJS) - $(AR) $(ARFLAGS) $@ $^ - -$(SLIB): $(OBJS) - $(CC) $(CFLAGS) -shared $^ -o $@ $(LDFLAGS) - -$(OBJDIR)%.o: %.c $(DEPS) - $(CC) $(COMMON) $(CFLAGS) -c $< -o $@ - -$(OBJDIR)%.o: %.cu $(DEPS) - $(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@ - -darknet.a: $(OBJS) - ar rcs $@ $^ - -obj: - mkdir -p obj -backup: - mkdir -p backup -results: - mkdir -p results - -.PHONY: clean - -clean: - rm -rf $(OBJS) $(SLIB) $(ALIB) $(EXEC) $(EXECOBJ) darknet.a - -.PHONY: install - -install: - mkdir -p $(PREFIX)/include/darknet - cp libdarknet.a $(PREFIX)/lib/libdarknet.a - cp ${HEADERS} include/darknet.h $(PREFIX)/include/darknet - -.PHONY: uninstall - -uninstall: - rm -f $(PREFIX)/lib/libdarknet.a - rm -rf $(PREFIX)/include/darknet diff --git a/plugins/darknet/shinobi-darknet.js b/plugins/darknet/shinobi-darknet.js deleted file mode 100644 index 85f2470..0000000 --- a/plugins/darknet/shinobi-darknet.js +++ /dev/null @@ -1,456 +0,0 @@ -// -// Shinobi - OpenCV Plugin -// Copyright (C) 2016-2025 Moe Alam, moeiscool -// -// # Donate -// -// If you like what I am doing here and want me to continue please consider donating :) -// PayPal : paypal@m03.ca -// -process.on('uncaughtException', function (err) { - console.error('uncaughtException',err); -}); -var fs=require('fs'); -var cv=require('opencv4nodejs'); -var exec = require('child_process').exec; -var moment = require('moment'); -var Canvas = require('canvas'); -var express = require('express'); -var http = require('http'), - app = express(), - server = http.createServer(app); -var config=require('./conf.json'); -if(!config.port){config.port=8080} -if(!config.hostPort){config.hostPort=8082} -if(config.systemLog===undefined){config.systemLog=true} -if(config.cascadesDir===undefined){config.cascadesDir=__dirname+'/cascades/'} -if(config.alprConfig===undefined){config.alprConfig=__dirname+'/openalpr.conf'} -s={ - group:{}, - dir:{ - cascades : config.cascadesDir - }, - isWin:(process.platform==='win32') -} -//default stream folder check -if(!config.streamDir){ - if(s.isWin===false){ - config.streamDir='/dev/shm' - }else{ - config.streamDir=config.windowsTempDir - } - if(!fs.existsSync(config.streamDir)){ - config.streamDir=__dirname+'/streams/' - }else{ - config.streamDir+='/streams/' - } -} -s.dir.streams=config.streamDir; -//streams dir -if(!fs.existsSync(s.dir.streams)){ - fs.mkdirSync(s.dir.streams); -} -s.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; -}; -s.findCascades=function(callback){ - var tmp={}; - tmp.foundCascades=[]; - fs.readdir(s.dir.cascades,function(err,files){ - files.forEach(function(cascade,n){ - if(cascade.indexOf('.xml')>-1){ - tmp.foundCascades.push(cascade.replace('.xml','')) - } - }) - s.cascadesInDir=tmp.foundCascades; - callback(tmp.foundCascades) - }) -} -s.findCascades(function(){ - //get cascades -}) -s.detectLicensePlate=function(buffer,d,tx){ - if(!d.mon.detector_lisence_plate_country||d.mon.detector_lisence_plate_country===''){ - d.mon.detector_lisence_plate_country='us' - } - d.tmpFile=s.gid(5)+'.jpg' - if(!fs.existsSync(s.dir.streams)){ - fs.mkdirSync(s.dir.streams); - } - d.dir=s.dir.streams+d.ke+'/' - if(!fs.existsSync(d.dir)){ - fs.mkdirSync(d.dir); - } - d.dir=s.dir.streams+d.ke+'/'+d.id+'/' - if(!fs.existsSync(d.dir)){ - fs.mkdirSync(d.dir); - } - fs.writeFile(d.dir+d.tmpFile,buffer,function(err){ - if(err) return s.systemLog(err); - exec('alpr -j --config '+config.alprConfig+' -c '+d.mon.detector_lisence_plate_country+' '+d.dir+d.tmpFile,{encoding:'utf8'},(err, scan, stderr) => { - if(err){ - s.systemLog(err); - }else{ - try{ - try{ - scan=JSON.parse(scan.replace('--(!)Loaded CUDA classifier','').trim()) - }catch(err){ - if(!scan||!scan.results){ - return s.systemLog(scan,err); - } - } -// console.log('scan',scan) - if(scan.results.length>0){ - scan.plates=[] - scan.mats=[] - scan.results.forEach(function(v){ - v.candidates.forEach(function(g,n){ - if(v.candidates[n].matches_template) - delete(v.candidates[n].matches_template) - }) - scan.plates.push({coordinates:v.coordinates,candidates:v.candidates,confidence:v.confidence,plate:v.plate}) - var width = Math.sqrt( Math.pow(v.coordinates[1].x - v.coordinates[0].x, 2) + Math.pow(v.coordinates[1].y - v.coordinates[0].y, 2)); - var height = Math.sqrt( Math.pow(v.coordinates[2].x - v.coordinates[1].x, 2) + Math.pow(v.coordinates[2].y - v.coordinates[1].y, 2)) - scan.mats.push({ - x:v.coordinates[0].x, - y:v.coordinates[0].y, - width:width, - height:height, - tag:v.plate - }) - }) - tx({f:'trigger',id:d.id,ke:d.ke,details:{split:true,plug:config.plug,name:'licensePlate',reason:'object',matrices:scan.mats,imgHeight:d.mon.detector_scale_y,imgWidth:d.mon.detector_scale_x,frame:d.base64}}) - } - }catch(err){ - s.systemLog(scan,err); - } - } - exec('rm -rf '+d.dir+d.tmpFile,{encoding:'utf8'}) - }) - }) -} -s.detectObject=function(buffer,d,tx){ - //detect license plate? - if(d.mon.detector_lisence_plate==="1"){ - s.detectLicensePlate(buffer,d,tx) - } - //check selected opencv cascades - var selectedCascades = Object.keys(d.mon.detector_cascades); - if(selectedCascades.length > 0){ - cv.imdecodeAsync(buffer,(err,im) => { - if(err){ - console.log(err) - return - } - selectedCascades.forEach(function(cascade){ - var classifier = new cv.CascadeClassifier(s.dir.cascades+cascade+'.xml') - var matrices = classifier.detectMultiScaleGpu(im).objects - if(matrices.length > 0){ - matrices.forEach(function(v,n){ - v.centerX=v.width/2 - v.centerY=v.height/2 - v.centerXnoParent=v.x+(v.width/2) - v.centerYnoParent=v.y+(v.height/2) - }) - s.cx({ - f:'trigger', - id:d.id, - ke:d.ke, - name:cascade, - details:{ - plug:'built-in-opencv', - name:cascade, - reason:'object', - matrices : matrices, - confidence:d.average - }, - imgHeight:d.mon.detector_scale_y, - imgWidth:d.mon.detector_scale_x - }) - } - }) - }); - } -} -s.systemLog=function(q,w,e){ - if(!w){w=''} - if(!e){e=''} - if(config.systemLog===true){ - return console.log(moment().format(),q,w,e) - } -} - -s.blenderRegion=function(d,cord,tx){ - d.width = d.image.width; - d.height = d.image.height; - if(!s.group[d.ke][d.id].canvas[cord.name]){ - if(!cord.sensitivity||isNaN(cord.sensitivity)){ - cord.sensitivity=d.mon.detector_sensitivity; - } - s.group[d.ke][d.id].canvas[cord.name] = new Canvas(d.width,d.height); - s.group[d.ke][d.id].canvasContext[cord.name] = s.group[d.ke][d.id].canvas[cord.name].getContext('2d'); - s.group[d.ke][d.id].canvasContext[cord.name].fillStyle = '#000'; - s.group[d.ke][d.id].canvasContext[cord.name].fillRect( 0, 0,d.width,d.height); - if(cord.points&&cord.points.length>0){ - s.group[d.ke][d.id].canvasContext[cord.name].beginPath(); - for (var b = 0; b < cord.points.length; b++){ - cord.points[b][0]=parseFloat(cord.points[b][0]); - cord.points[b][1]=parseFloat(cord.points[b][1]); - if(b===0){ - s.group[d.ke][d.id].canvasContext[cord.name].moveTo(cord.points[b][0],cord.points[b][1]); - }else{ - s.group[d.ke][d.id].canvasContext[cord.name].lineTo(cord.points[b][0],cord.points[b][1]); - } - } - s.group[d.ke][d.id].canvasContext[cord.name].clip(); - } - } - if(!s.group[d.ke][d.id].canvasContext[cord.name]){ - return - } - s.group[d.ke][d.id].canvasContext[cord.name].drawImage(d.image, 0, 0, d.width, d.height); - if(!s.group[d.ke][d.id].blendRegion[cord.name]){ - s.group[d.ke][d.id].blendRegion[cord.name] = new Canvas(d.width, d.height); - s.group[d.ke][d.id].blendRegionContext[cord.name] = s.group[d.ke][d.id].blendRegion[cord.name].getContext('2d'); - } - var sourceData = s.group[d.ke][d.id].canvasContext[cord.name].getImageData(0, 0, d.width, d.height); - // create an image if the previous image doesn�t exist - if (!s.group[d.ke][d.id].lastRegionImageData[cord.name]) s.group[d.ke][d.id].lastRegionImageData[cord.name] = s.group[d.ke][d.id].canvasContext[cord.name].getImageData(0, 0, d.width, d.height); - // create a ImageData instance to receive the blended result - var blendedData = s.group[d.ke][d.id].canvasContext[cord.name].createImageData(d.width, d.height); - // blend the 2 images - s.differenceAccuracy(blendedData.data,sourceData.data,s.group[d.ke][d.id].lastRegionImageData[cord.name].data); - // draw the result in a canvas - s.group[d.ke][d.id].blendRegionContext[cord.name].putImageData(blendedData, 0, 0); - // store the current webcam image - s.group[d.ke][d.id].lastRegionImageData[cord.name] = sourceData; - blendedData = s.group[d.ke][d.id].blendRegionContext[cord.name].getImageData(0, 0, d.width, d.height); - var i = 0; - d.average = 0; - while (i < (blendedData.data.length * 0.25)) { - d.average += (blendedData.data[i * 4] + blendedData.data[i * 4 + 1] + blendedData.data[i * 4 + 2]); - ++i; - } - d.average = (d.average / (blendedData.data.length * 0.25))*10; - if (d.average > parseFloat(cord.sensitivity)){ - if(d.mon.detector_use_detect_object==="1"&&d.mon.detector_second!=='1'){ - var buffer=s.group[d.ke][d.id].canvas[cord.name].toBuffer(); - s.detectObject(buffer,d,tx) - }else{ - tx({f:'trigger',id:d.id,ke:d.ke,details:{split:true,plug:config.plug,name:cord.name,reason:'motion',confidence:d.average,frame:d.base64}}) - } - } - s.group[d.ke][d.id].canvasContext[cord.name].clearRect(0, 0, d.width, d.height); - s.group[d.ke][d.id].blendRegionContext[cord.name].clearRect(0, 0, d.width, d.height); -} -function blobToBuffer (blob, cb) { - if (typeof Blob === 'undefined' || !(blob instanceof Blob)) { - throw new Error('first argument must be a Blob') - } - if (typeof cb !== 'function') { - throw new Error('second argument must be a function') - } - - var reader = new FileReader() - - function onLoadEnd (e) { - reader.removeEventListener('loadend', onLoadEnd, false) - if (e.error) cb(e.error) - else cb(null, Buffer.from(reader.result)) - } - - reader.addEventListener('loadend', onLoadEnd, false) - reader.readAsArrayBuffer(blob) -} -function fastAbs(value) { - return (value ^ (value >> 31)) - (value >> 31); -} - -function threshold(value) { - return (value > 0x15) ? 0xFF : 0; -} -s.differenceAccuracy=function(target, data1, data2) { - if (data1.length != data2.length) return null; - var i = 0; - while (i < (data1.length * 0.25)) { - var average1 = (data1[4 * i] + data1[4 * i + 1] + data1[4 * i + 2]) / 3; - var average2 = (data2[4 * i] + data2[4 * i + 1] + data2[4 * i + 2]) / 3; - var diff = threshold(fastAbs(average1 - average2)); - target[4 * i] = diff; - target[4 * i + 1] = diff; - target[4 * i + 2] = diff; - target[4 * i + 3] = 0xFF; - ++i; - } -} -s.checkAreas=function(d,tx){ - if(!s.group[d.ke][d.id].cords){ - if(!d.mon.cords){d.mon.cords={}} - s.group[d.ke][d.id].cords=Object.values(d.mon.cords); - } - if(d.mon.detector_frame==='1'){ - d.mon.cords.frame={name:'FULL_FRAME',s:d.mon.detector_sensitivity,points:[[0,0],[0,d.image.height],[d.image.width,d.image.height],[d.image.width,0]]}; - s.group[d.ke][d.id].cords.push(d.mon.cords.frame); - } - for (var b = 0; b < s.group[d.ke][d.id].cords.length; b++){ - if(!s.group[d.ke][d.id].cords[b]){return} - s.blenderRegion(d,s.group[d.ke][d.id].cords[b],tx) - } - delete(d.image) -} - -s.MainEventController=function(d,cn,tx){ - switch(d.f){ - case'refreshPlugins': - s.findCascades(function(cascades){ - s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:cascades},to:'GRP_'+d.ke}) - }) - break; - case'readPlugins': - s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:s.cascadesInDir},to:'GRP_'+d.ke}) - break; - case'init_plugin_as_host': - if(!cn){ - console.log('No CN',d) - return - } - if(d.key!==config.key){ - console.log(new Date(),'Plugin Key Mismatch',cn.request.connection.remoteAddress,d) - cn.emit('init',{ok:false}) - cn.disconnect() - }else{ - console.log(new Date(),'Plugin Connected to Client',cn.request.connection.remoteAddress) - cn.emit('init',{ok:true,plug:config.plug,notice:config.notice,type:config.type}) - } - break; - case'init_monitor': - if(s.group[d.ke]&&s.group[d.ke][d.id]){ - s.group[d.ke][d.id].canvas={} - s.group[d.ke][d.id].canvasContext={} - s.group[d.ke][d.id].blendRegion={} - s.group[d.ke][d.id].blendRegionContext={} - s.group[d.ke][d.id].lastRegionImageData={} - s.group[d.ke][d.id].numberOfTriggers=0 - delete(s.group[d.ke][d.id].cords) - delete(s.group[d.ke][d.id].buffer) - } - break; - case'init_aws_push': -// console.log('init_aws') - s.group[d.ke][d.id].aws={links:[],complete:0,total:d.total,videos:[],tx:tx} - break; - case'frame': - try{ - if(!s.group[d.ke]){ - s.group[d.ke]={} - } - if(!s.group[d.ke][d.id]){ - s.group[d.ke][d.id]={ - canvas:{}, - canvasContext:{}, - lastRegionImageData:{}, - blendRegion:{}, - blendRegionContext:{}, - } - } - if(!s.group[d.ke][d.id].buffer){ - s.group[d.ke][d.id].buffer=[d.frame]; - }else{ - s.group[d.ke][d.id].buffer.push(d.frame) - } - if(d.frame[d.frame.length-2] === 0xFF && d.frame[d.frame.length-1] === 0xD9){ - s.group[d.ke][d.id].buffer=Buffer.concat(s.group[d.ke][d.id].buffer); - try{ - d.mon.detector_cascades=JSON.parse(d.mon.detector_cascades) - }catch(err){ - - } - if(d.mon.detector_frame_save==="1"){ - d.base64=s.group[d.ke][d.id].buffer.toString('base64') - } - if(d.mon.detector_second==='1'&&d.objectOnly===true){ - s.detectObject(s.group[d.ke][d.id].buffer,d,tx) - }else{ - if((d.mon.detector_pam !== '1' && d.mon.detector_use_motion === "1") || d.mon.detector_use_detect_object !== "1"){ - if((typeof d.mon.cords ==='string')&&d.mon.cords.trim()===''){ - d.mon.cords=[] - }else{ - try{ - d.mon.cords=JSON.parse(d.mon.cords) - }catch(err){ - // console.log('d.mon.cords',err,d) - } - } - s.group[d.ke][d.id].cords=Object.values(d.mon.cords); - d.mon.cords=d.mon.cords; - d.image = new Canvas.Image; - if(d.mon.detector_scale_x===''||d.mon.detector_scale_y===''){ - s.systemLog('Must set detector image size') - return - }else{ - d.image.width=d.mon.detector_scale_x; - d.image.height=d.mon.detector_scale_y; - } - d.width=d.image.width; - d.height=d.image.height; - d.image.onload = function() { - s.checkAreas(d,tx); - } - d.image.src = s.group[d.ke][d.id].buffer; - }else{ - s.detectObject(s.group[d.ke][d.id].buffer,d,tx) - } - } - s.group[d.ke][d.id].buffer=null; - } - }catch(err){ - if(err){ - s.systemLog(err) - delete(s.group[d.ke][d.id].buffer) - } - } - break; - } -} -server.listen(config.hostPort); -//web pages and plugin api -app.get('/', function (req, res) { - res.end(''+config.plug+' for Shinobi is running') -}); -//Conector to Shinobi -if(config.mode==='host'){ - //start plugin as host - var io = require('socket.io')(server); - io.attach(server); - s.connectedClients={}; - io.on('connection', function (cn) { - s.connectedClients[cn.id]={id:cn.id} - s.connectedClients[cn.id].tx = function(data){ - data.pluginKey=config.key;data.plug=config.plug; - return io.to(cn.id).emit('ocv',data); - } - cn.on('f',function(d){ - s.MainEventController(d,cn,s.connectedClients[cn.id].tx) - }); - cn.on('disconnect',function(d){ - delete(s.connectedClients[cn.id]) - }) - }); -}else{ - //start plugin as client - if(!config.host){config.host='localhost'} - var io = require('socket.io-client')('ws://'+config.host+':'+config.port);//connect to master - s.cx=function(x){x.pluginKey=config.key;x.plug=config.plug;return io.emit('ocv',x)} - io.on('connect',function(d){ - s.cx({f:'init',plug:config.plug,notice:config.notice,type:config.type}); - }) - io.on('disconnect',function(d){ - io.connect(); - }) - io.on('f',function(d){ - s.MainEventController(d,null,s.cx) - }) -} \ No newline at end of file diff --git a/plugins/microsoft/conf.sample.json b/plugins/microsoft/conf.sample.json deleted file mode 100644 index 5f9b9dc..0000000 --- a/plugins/microsoft/conf.sample.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "plug":"ComputerVision", - "host":"localhost", - "port":8080, - "key":"UNIQUE KEY HERE", - "computerVision":{ - "apiKey":"YOUR_KEY", - "endpoint":"http://YOUR_ENDPOINT/analyze", - "params":{ - "visualFeatures": "Categories,Description,Color", - "details": "", - "language": "en" - } - }, - "EmotionAPI":{ - "apiKey":"YOUR_KEY", - "endpoint":"http://YOUR_ENDPOINT/recognize", - "params":{} - }, - "FaceAPI":{ - "apiKey":"YOUR_KEY", - "endpoint":"http://YOUR_ENDPOINT/detect", - "params":{ - "returnFaceId": "true", - "returnFaceLandmarks": "false", - "returnFaceAttributes": "age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise" - } - } -} \ No newline at end of file diff --git a/plugins/microsoft/shinobi-ms-vision.js b/plugins/microsoft/shinobi-ms-vision.js deleted file mode 100644 index 938e787..0000000 --- a/plugins/microsoft/shinobi-ms-vision.js +++ /dev/null @@ -1,170 +0,0 @@ -// -// Shinobi - Microsoft Computer Vision Plugin -// Copyright (C) 2016-2025 Moe Alam, moeiscool -// -process.on('uncaughtException', function (err) { - console.error('uncaughtException',err); -}); -var fs=require('fs'); -var exec = require('child_process').exec; -//var http = require('http'); -var request = require('request'); -var moment = require('moment'); -var cognitive = require('cognitive-services'); -var config=require('./conf.json'); -if(config.systemLog===undefined){config.systemLog=true} -s={ - group:{}, - dir:{ - cascades:__dirname+'/cascades/' - }, - isWin:(process.platform==='win32') -} -//default stream folder check -if(!config.streamDir){ - if(s.isWin===false){ - config.streamDir='/dev/shm' - }else{ - config.streamDir=config.windowsTempDir - } - if(!fs.existsSync(config.streamDir)){ - config.streamDir=__dirname+'/streams/' - }else{ - config.streamDir+='/streams/' - } -} -s.dir.streams=config.streamDir; -//streams dir -if(!fs.existsSync(s.dir.streams)){ - fs.mkdirSync(s.dir.streams); -} -s.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; -}; -s.systemLog=function(q,w,e){ - if(!w){w=''} - if(!e){e=''} - if(config.systemLog===true){ - return console.log(moment().format(),q,w,e) - } -} -s.objectToParameter = function(obj){ - return Object.keys(obj).map(function(key) { - return key + '=' + encodeURIComponent(obj[key]); - }).join('&'); -} -s.sendImageToMS=function(sourceImageUrl,API,callback){ - var URL = API.endpoint+'?'+s.objectToParameter(API.params) - request(URL,{ - method: 'POST', - headers:{ - "Ocp-Apim-Subscription-Key":API.apiKey - }, - json: { - url:sourceImageUrl - } - }, callback) -} -s.detectObject=function(buffer,d){ - var sourceImageUrl = 'http://184.105.6.43/'+s.api_key+'/jpeg/'+d.ke+'/'+d.id+'/s.jpg' -// const client = new cognitive.computerVision({ -// apiKey: config.computerVision.apiKey, -// endpoint: config.computerVision.endpoint -// }); -// const parameters = { -// "visualFeatures": "Categories,Tags,Description", -// "details": "Celebrities,Landmarks" -// }; -// const headers = { -// 'Content-type': 'application/json' -// }; -// const body = { -// "url": sourceImageUrl -// }; -// -// client.analyzeImage({ -// parameters, -// headers, -// body -// }).then((response) => { -//// should(response).not.be.undefined(); -//// should(response).have.properties(["categories", "metadata", "requestId"]); -// console.log(response) -// }).catch((err) => { -// console.log('Error',err) -// }); - var responses = {} - s.sendImageToMS(sourceImageUrl,config.computerVision,function(err,resp,body1){ - responses.computerVisionURL = body1 - s.sendImageToMS(sourceImageUrl,config.FaceAPI,function(err,resp,body2){ - responses.faceApiURL = body2 - s.sendImageToMS(sourceImageUrl,config.EmotionAPI,function(err,resp,body3){ - responses.EmotionAPI = body3 - console.log('responses',JSON.stringify(responses,null,3)) - }) - }) - }) -} -s.makeMonitorObject=function(d){ - if(!s.group[d.ke]){ - s.group[d.ke]={} - } - if(!s.group[d.ke][d.id]){ - s.group[d.ke][d.id]={ - port:null, - countStarted:new Date() - } - } -} -io = require('socket.io-client')('ws://'+config.host+':'+config.port);//connect to master -s.cx=function(x){x.pluginKey=config.key;x.plug=config.plug;return io.emit('ocv',x)} -io.on('connect',function(d){ - s.cx({f:'init',plug:config.plug}); -}) -io.on('disconnect',function(d){ - io.connect() -}) -io.on('f',function(d){ - switch(d.f){ - case'api_key': - s.api_key=d.key - break; - case'init_monitor': - if(s.group[d.ke]&&s.group[d.ke][d.id]){ - s.group[d.ke][d.id].buffer=null - s.group[d.ke][d.id].countStarted=new Date() - } - s.makeMonitorObject(d) - break; - case'frame': - d.details={} - try{ - s.makeMonitorObject(d) - if(!s.group[d.ke][d.id].buffer){ - s.group[d.ke][d.id].buffer=[d.frame]; - }else{ - s.group[d.ke][d.id].buffer.push(d.frame) - } - if(d.frame[d.frame.length-2] === 0xFF && d.frame[d.frame.length-1] === 0xD9){ - if(d.mon.detector_frame_save==="1"){ - d.base64=s.group[d.ke][d.id].buffer.toString('base64') - } - if(d.mon.detector_scale_x&&d.mon.detector_scale_x!==''&&d.mon.detector_scale_y&&d.mon.detector_scale_y!==''){ - d.width=d.mon.detector_scale_x; - d.height=d.mon.detector_scale_y; - }else{ - d.width=640 - d.height=480 - } - s.detectObject(Buffer.concat(s.group[d.ke][d.id].buffer),d) - s.group[d.ke][d.id].buffer=null; - } - } catch(err){ - console.error(err) - } - break; - } -}) \ No newline at end of file diff --git a/plugins/opencv/.gitignore b/plugins/opencv/.gitignore new file mode 100644 index 0000000..5881654 --- /dev/null +++ b/plugins/opencv/.gitignore @@ -0,0 +1,2 @@ +conf.json +cascades \ No newline at end of file diff --git a/plugins/opencv/shinobi-opencv-no-motion.js b/plugins/opencv/shinobi-opencv-no-motion.js new file mode 100644 index 0000000..700d672 --- /dev/null +++ b/plugins/opencv/shinobi-opencv-no-motion.js @@ -0,0 +1,212 @@ +// +// Shinobi - OpenCV Plugin +// Copyright (C) 2016-2025 Moe Alam, moeiscool +// +// # Donate +// +// If you like what I am doing here and want me to continue please consider donating :) +// PayPal : paypal@m03.a +// +process.on('uncaughtException', function (err) { + console.error('uncaughtException',err); +}); +var fs=require('fs'); +var cv=require('opencv'); +var exec = require('child_process').exec; +var moment = require('moment'); +var config=require('./conf.json'); +if(config.systemLog===undefined){config.systemLog=true} +s={ + group:{}, + dir:{ + cascades:__dirname+'/cascades/' + }, + isWin:(process.platform==='win32') +} +//default stream folder check +if(!config.streamDir){ + if(s.isWin===false){ + config.streamDir='/dev/shm' + }else{ + config.streamDir=config.windowsTempDir + } + if(!fs.existsSync(config.streamDir)){ + config.streamDir=__dirname+'/streams/' + }else{ + config.streamDir+='/streams/' + } +} +s.dir.streams=config.streamDir; +//streams dir +if(!fs.existsSync(s.dir.streams)){ + fs.mkdirSync(s.dir.streams); +} +s.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; +}; +s.systemLog=function(q,w,e){ + if(!w){w=''} + if(!e){e=''} + if(config.systemLog===true){ + return console.log(moment().format(),q,w,e) + } +} +s.findCascades=function(callback){ + var tmp={}; + tmp.foundCascades=[]; + fs.readdir(s.dir.cascades,function(err,files){ + files.forEach(function(cascade,n){ + if(cascade.indexOf('.xml')>-1){ + tmp.foundCascades.push(cascade.replace('.xml','')) + } + }) + s.cascadesInDir=tmp.foundCascades; + callback(tmp.foundCascades) + }) +} +s.findCascades(function(){ + //get cascades +}) +s.detectObject=function(buffer,d){ + var keys = Object.keys(d.mon.detector_cascades); + if(d.mon.detector_lisence_plate==="1"){ + if(!d.mon.detector_lisence_plate_country||d.mon.detector_lisence_plate_country===''){ + d.mon.detector_lisence_plate_country='us' + } + d.tmpFile=s.gid(5)+'.jpg' + if(!fs.existsSync(s.dir.streams)){ + fs.mkdirSync(s.dir.streams); + } + d.dir=s.dir.streams+d.ke+'/' + if(!fs.existsSync(d.dir)){ + fs.mkdirSync(d.dir); + } + d.dir=s.dir.streams+d.ke+'/'+d.id+'/' + if(!fs.existsSync(d.dir)){ + fs.mkdirSync(d.dir); + } + fs.writeFile(d.dir+d.tmpFile,buffer,function(err){ + if(err) return s.systemLog(err); + exec('alpr -j -c '+d.mon.detector_lisence_plate_country+' '+d.dir+d.tmpFile,{encoding:'utf8'},(err, scan, stderr) => { + if(err){ + s.systemLog(err); + }else{ + try{ + try{ + scan=JSON.parse(scan) + }catch(err){ + if(!scan||!scan.results){ + return s.systemLog(scan,err); + } + } + if(scan.results.length>0){ + scan.plates=[] + scan.mats=[] + scan.results.forEach(function(v){ + v.candidates.forEach(function(g,n){ + if(v.candidates[n].matches_template) + delete(v.candidates[n].matches_template) + }) + scan.plates.push({coordinates:v.coordinates,candidates:v.candidates,confidence:v.confidence,plate:v.plate}) + var width = Math.sqrt( Math.pow(v.coordinates[1].x - v.coordinates[0].x, 2) + Math.pow(v.coordinates[1].y - v.coordinates[0].y, 2)); + var height = Math.sqrt( Math.pow(v.coordinates[2].x - v.coordinates[1].x, 2) + Math.pow(v.coordinates[2].y - v.coordinates[1].y, 2)) + scan.mats.push({ + x:v.coordinates[0].x, + y:v.coordinates[0].y, + width:width, + height:height, + tag:v.plate + }) + }) + tx({f:'trigger',id:d.id,ke:d.ke,details:{plug:config.plug,name:'licensePlate',reason:'object',matrices:scan.mats,confidence:d.average,imgHeight:d.mon.detector_scale_y,imgWidth:d.mon.detector_scale_x,frame:d.base64}}) + } + }catch(err){ + s.systemLog(err); + } + } + exec('rm -rf '+d.dir+d.tmpFile,{encoding:'utf8'}) + }) + }) + } + if(keys.length===0){return false} + cv.readImage(buffer, function(err,im){ + if(err){console.log(err);return false;} + var width = im.width(); + var height = im.height(); + + if (width < 1 || height < 1) { + throw new Error('Image has no size'); + } + keys.forEach(function(v,n){ + im.detectObject(s.dir.cascades+v+'.xml',{}, function(err,mats){ + if(err){console.log(err);return false;} + if(mats&&mats.length>0){ + s.cx({f:'trigger',id:d.id,ke:d.ke,details:{plug:config.plug,name:v,reason:'object',matrices:mats,confidence:d.average,imgHeight:height,imgWidth:width}}) + } + }) + }) + }) +} +io = require('socket.io-client')('ws://'+config.host+':'+config.port);//connect to master +s.cx=function(x){x.pluginKey=config.key;x.plug=config.plug;return io.emit('ocv',x)} +io.on('connect',function(d){ + s.cx({f:'init',plug:config.plug}); +}) +io.on('disconnect',function(d){ + io.connect() +}) +io.on('f',function(d){ + switch(d.f){ + case'refreshPlugins': + s.findCascades(function(cascades){ + s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:cascades},to:'GRP_'+d.ke}) + }) + break; + case'readPlugins': + s.cx({f:'s.tx',data:{f:'detector_cascade_list',cascades:s.cascadesInDir},to:'GRP_'+d.ke}) + break; + case'init_monitor': + if(s.group[d.ke]&&s.group[d.ke][d.id]){ + s.group[d.ke][d.id].canvas={} + s.group[d.ke][d.id].canvasContext={} + s.group[d.ke][d.id].blendRegion={} + s.group[d.ke][d.id].blendRegionContext={} + s.group[d.ke][d.id].lastRegionImageData={} + delete(s.group[d.ke][d.id].cords) + delete(s.group[d.ke][d.id].buffer) + } + break; + case'frame': + d.details={} + try{ + if(!s.group[d.ke]){ + s.group[d.ke]={} + } + if(!s.group[d.ke][d.id]){ + s.group[d.ke][d.id]={ + canvas:{}, + canvasContext:{}, + lastRegionImageData:{}, + blendRegion:{}, + blendRegionContext:{}, + } + } + if(!s.group[d.ke][d.id].buffer){ + s.group[d.ke][d.id].buffer=[d.frame]; + }else{ + s.group[d.ke][d.id].buffer.push(d.frame) + } + if(d.frame[d.frame.length-2] === 0xFF && d.frame[d.frame.length-1] === 0xD9){ + s.group[d.ke][d.id].buffer=Buffer.concat(s.group[d.ke][d.id].buffer); + s.detectObject(s.group[d.ke][d.id].buffer,d) + s.group[d.ke][d.id].buffer=null; + } + } catch(err){ + console.error(err) + } + break; + } +}) \ No newline at end of file diff --git a/sql/.gitignore b/sql/.gitignore index 87b2844..27e9488 100644 --- a/sql/.gitignore +++ b/sql/.gitignore @@ -1,2 +1,3 @@ monitors.sql -users.sql \ No newline at end of file +users.sql +shinobi.sqlite \ No newline at end of file diff --git a/sql/database.sql b/sql/database.sql new file mode 100644 index 0000000..23a15b0 --- /dev/null +++ b/sql/database.sql @@ -0,0 +1,20 @@ +-- -------------------------------------------------------- +-- Host: 192.168.88.58 +-- Server version: 5.7.17-0ubuntu0.16.04.1 - (Ubuntu) +-- Server OS: Linux +-- HeidiSQL Version: 9.3.0.4984 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8mb4 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; + +-- Dumping database structure for ccio +CREATE DATABASE IF NOT EXISTS `ccio` /*!40100 DEFAULT CHARACTER SET utf8 */; +USE `ccio`; + +-- 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) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; \ No newline at end of file diff --git a/sql/default_data.sql b/sql/default_data.sql index 5a66924..c3982ca 100644 --- a/sql/default_data.sql +++ b/sql/default_data.sql @@ -13,7 +13,7 @@ /*!40000 ALTER TABLE `Users` DISABLE KEYS */; INSERT INTO `Users` (`ke`, `uid`, `auth`, `mail`, `pass`, `details`) VALUES ('2Df5hBE', 'XDf5hB3', 'ec49f05c1ddc7d818c61b3343c98cbc6', 'ccio@m03.ca', '5f4dcc3b5aa765d61d8327deb882cf99', '{"days":"10"}'); -INSERT INTO `Monitors` (`mid`, `ke`, `name`, `shto`, `shfr`, `details`, `type`, `ext`, `protocol`, `host`, `path`, `port`, `fps`, `mode`, `width`, `height`) VALUES ('bunny', '2Df5hBE', 'Bunny', '[]', '[]', '{"fatal_max":"","notes":"","dir":"","rtsp_transport":"tcp","muser":"","mpass":"","port_force":"0","sfps":"","aduration":"1000000","probesize":"1000000","accelerator":"0","hwaccel":null,"hwaccel_vcodec":"","hwaccel_device":"","stream_type":"hls","stream_mjpeg_clients":"","stream_vcodec":"copy","stream_acodec":"no","hls_time":"","preset_stream":"","hls_list_size":"","signal_check":"","signal_check_log":null,"stream_quality":"","stream_fps":"1","stream_scale_x":"","stream_scale_y":"","rotate_stream":null,"svf":"","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":null,"snap":"1","snap_fps":"","snap_scale_x":"","snap_scale_y":"","snap_vf":"","vcodec":"copy","crf":"","preset_record":"","acodec":"libvorbis","dqf":null,"cutoff":"10","rotate_record":null,"vf":"","timestamp":"1","timestamp_font":"","timestamp_font_size":"","timestamp_color":"","timestamp_box_color":"","timestamp_x":"","timestamp_y":"","watermark":null,"watermark_location":"","watermark_position":null,"cust_input":"","cust_snap":"","cust_detect":"","cust_stream":"","cust_stream_server":"","cust_record":"","custom_output":"","detector":"0","detector_webhook":null,"detector_webhook_url":"","detector_command_enable":null,"detector_command":"","detector_command_timeout":"","detector_lock_timeout":"","detector_save":null,"detector_frame_save":null,"detector_mail":null,"detector_mail_timeout":"","detector_record_method":null,"detector_trigger":null,"detector_trigger_record_fps":"","detector_timeout":"","watchdog_reset":null,"detector_delete_motionless_videos":null,"detector_send_frames":null,"detector_fps":"","detector_scale_x":"","detector_scale_y":"","detector_use_motion":null,"detector_use_detect_object":null,"detector_frame":null,"detector_sensitivity":"","cords":"","detector_lisence_plate":null,"detector_lisence_plate_country":null,"detector_notrigger":null,"detector_notrigger_mail":null,"detector_notrigger_timeout":"","control":"0","control_base_url":"","control_stop":null,"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":"","groups":"","loglevel":"warning","sqllog":"0","detector_cascades":""}', 'mjpeg', 'mp4', 'http', 'came3.nkansai.ne.jp', '/nphMotionJpeg?Resolution=640x480&Quality=Motion', 81, 15, 'start', 640, 480); +INSERT INTO `Monitors` (`mid`, `ke`, `name`, `shto`, `shfr`, `details`, `type`, `ext`, `protocol`, `host`, `path`, `port`, `fps`, `mode`, `width`, `height`) VALUES ('Demo', '2Df5hBE', 'Demo', '[]', '[]', '{"fatal_max":"","notes":"","dir":"","rtsp_transport":"tcp","muser":"","mpass":"","port_force":"0","sfps":"","aduration":"1000000","probesize":"1000000","accelerator":"0","hwaccel":null,"hwaccel_vcodec":"","hwaccel_device":"","stream_type":"hls","stream_mjpeg_clients":"","stream_vcodec":"copy","stream_acodec":"no","hls_time":"","preset_stream":"","hls_list_size":"","signal_check":"","signal_check_log":null,"stream_quality":"","stream_fps":"1","stream_scale_x":"","stream_scale_y":"","rotate_stream":null,"svf":"","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":null,"snap":"1","snap_fps":"","snap_scale_x":"","snap_scale_y":"","snap_vf":"","vcodec":"copy","crf":"","preset_record":"","acodec":"libvorbis","dqf":null,"cutoff":"10","rotate_record":null,"vf":"","timestamp":"1","timestamp_font":"","timestamp_font_size":"","timestamp_color":"","timestamp_box_color":"","timestamp_x":"","timestamp_y":"","watermark":null,"watermark_location":"","watermark_position":null,"cust_input":"","cust_snap":"","cust_detect":"","cust_stream":"","cust_stream_server":"","cust_record":"","custom_output":"","detector":"0","detector_webhook":null,"detector_webhook_url":"","detector_command_enable":null,"detector_command":"","detector_command_timeout":"","detector_lock_timeout":"","detector_save":null,"detector_frame_save":null,"detector_mail":null,"detector_mail_timeout":"","detector_record_method":null,"detector_trigger":null,"detector_trigger_record_fps":"","detector_timeout":"","watchdog_reset":null,"detector_delete_motionless_videos":null,"detector_send_frames":null,"detector_fps":"","detector_scale_x":"","detector_scale_y":"","detector_use_motion":null,"detector_use_detect_object":null,"detector_frame":null,"detector_sensitivity":"","cords":"","detector_lisence_plate":null,"detector_lisence_plate_country":null,"detector_notrigger":null,"detector_notrigger_mail":null,"detector_notrigger_timeout":"","control":"0","control_base_url":"","control_stop":null,"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":"","groups":"","loglevel":"warning","sqllog":"0","detector_cascades":""}', 'mjpeg', 'mp4', 'http', 'came3.nkansai.ne.jp', '/nphMotionJpeg?Resolution=640x480&Quality=Motion', 81, 15, 'start', 640, 480); /*!40000 ALTER TABLE `Users` ENABLE KEYS */; /*!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) */; diff --git a/sql/postgresql/framework.sql b/sql/postgresql/framework.sql index 21773d8..bf4bfd7 100644 --- a/sql/postgresql/framework.sql +++ b/sql/postgresql/framework.sql @@ -52,7 +52,7 @@ CREATE TABLE IF NOT EXISTS Monitors ( name varchar(50) DEFAULT NULL, shto text, shfr text, - details text, + details longtext, type varchar(50) DEFAULT 'jpeg', ext varchar(50) DEFAULT 'webm', protocol varchar(50) DEFAULT 'http', @@ -82,7 +82,7 @@ CREATE TABLE IF NOT EXISTS Users ( auth varchar(50) DEFAULT NULL, mail varchar(100) DEFAULT NULL, pass varchar(100) DEFAULT NULL, - details text, + details longtext, CONSTRAINT mail UNIQUE (mail) ) ; diff --git a/tools/ffmpegToWeb.js b/tools/ffmpegToWeb.js new file mode 100644 index 0000000..a2c5c9e --- /dev/null +++ b/tools/ffmpegToWeb.js @@ -0,0 +1,54 @@ +// Shinobi (http://shinobi.video) - FFMPEG H.264 over HTTP Test +// How to Use +// 1. Start with `node ffmpegToWeb.js` +// 2. Get the IP address of the computer where you did step 1. Example : 127.0.0.1 +// 3. Open VLC and "Open Network Stream". +// 4. Input the following without quotes : `http://127.0.0.1:8001` and start. + +var child = require('child_process'); +var events = require('events'); +var spawn = child.spawn; +var exec = child.exec; +var Emitter = new events.EventEmitter().setMaxListeners(0) +var config = { + port:8001 +} +//ffmpeg +console.log('Starting FFMPEG') +var ffmpeg = spawn('ffmpeg',('-rtsp_transport tcp -i rtsp://131.95.3.162/axis-media/media.3gp -f mpegts -c:v copy -an -').split(' ')); +ffmpeg.on('close', function (buffer) { + console.log('ffmpeg died') +}) +//ffmpeg.stderr.on('data', function (buffer) { +// console.log(buffer.toString()) +//}); +ffmpeg.stdout.on('data', function (buffer) { + Emitter.emit('data',buffer) +}); +//web app +console.log('Starting Express Web Server on Port '+config.port) +var express = require('express') +var app = express(); +var http = require('http') +var httpServer = http.createServer(app); + +app.get('/', function (req, res) { + var contentWriter + var date = new Date(); + res.writeHead(200, { + 'Date': date.toUTCString(), + 'Connection': 'close', + 'Cache-Control': 'no-cache', + 'Pragma': 'no-cache', + 'Content-Type': 'video/mp4', + 'Server': 'Shinobi H.264 Test Stream', + }); + Emitter.on('data',contentWriter=function(buffer){ + res.write(buffer) + }) + res.on('close', function () { + Emitter.removeListener('data',contentWriter) + }) +}); + +httpServer.listen(config.port); \ No newline at end of file diff --git a/web/libs/img/icon/mstile-310x310-circle.png b/web/libs/img/icon/mstile-310x310-circle.png index d0e1c97..24bb099 100644 Binary files a/web/libs/img/icon/mstile-310x310-circle.png and b/web/libs/img/icon/mstile-310x310-circle.png differ diff --git a/web/pages/blocks/monitoredit.ejs b/web/pages/blocks/monitoredit.ejs index b8f338f..7e1d8f6 100644 --- a/web/pages/blocks/monitoredit.ejs +++ b/web/pages/blocks/monitoredit.ejs @@ -46,6 +46,11 @@
+