Merge branch 'dev' into 'master'

PTZ Improvement, P2P, and Some Critical Fixes

See merge request Shinobi-Systems/Shinobi!240
merge-requests/256/head ocean-1
Moe 2020-09-25 16:18:29 +00:00
commit cd9c013916
30 changed files with 1086 additions and 585 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ npm-debug.log
shinobi.sqlite
package-lock.json
dist
._*

View File

@ -26,7 +26,7 @@ require('./libs/codeTester.js')(s,config,lang)
//get version
require('./libs/version.js')(s,config,lang)
//video processing engine
require('./libs/ffmpeg.js')(s,config,lang,function(ffmpeg){
require('./libs/ffmpeg.js')(s,config,lang,async function(ffmpeg){
//ffmpeg coProcessor
require('./libs/ffmpegCoProcessor.js')(s,config,lang,ffmpeg)
//database connection : mysql, sqlite3..
@ -86,5 +86,7 @@ require('./libs/ffmpeg.js')(s,config,lang,function(ffmpeg){
//scheduling engine
require('./libs/scheduler.js')(s,config,lang,app,io)
//on-start actions, daemon(s) starter
require('./libs/startup.js')(s,config,lang)
await require('./libs/startup.js')(s,config,lang)
//p2p, commander
require('./libs/commander.js')(s,config,lang)
})

11
cron.js
View File

@ -135,6 +135,16 @@ s.sqlQuery = function(query,values,onMoveOn){
}
})
}
const cleanSqlWhereObject = (where) => {
const newWhere = {}
Object.keys(where).forEach((key) => {
if(key !== '__separator'){
const value = where[key]
newWhere[key] = value
}
})
return newWhere
}
const processSimpleWhereCondition = (dbQuery,where,didOne) => {
var whereIsArray = where instanceof Array;
if(where[0] === 'or' || where.__separator === 'or'){
@ -261,7 +271,6 @@ const knexQuery = (options,callback) => {
knexError(dbQuery,options,err)
}
}
s.debugLog = function(arg1,arg2){
if(config.debugLog === true){
if(!arg2)arg2 = ''

View File

@ -420,6 +420,25 @@ module.exports = function(s,config,lang){
}
]
},
{
"name": "detail=onvif_non_standard",
"field": lang['Non-Standard ONVIF'],
"description": "Is this a Non-Standard ONVIF camera?",
"default": "0",
"example": "",
"form-group-class": "h_onvif_input h_onvif_1",
"fieldType": "select",
"possible": [
{
"name": lang.No,
"value": "0"
},
{
"name": lang.Yes,
"value": "1"
}
]
},
{
hidden: true,
"name": "detail=onvif_port",
@ -3608,6 +3627,24 @@ module.exports = function(s,config,lang){
"form-group-class": "h_control_call_input h_control_call_GET h_control_call_PUT h_control_call_POST",
"possible": ""
},
{
"name": "detail=control_invert_y",
"field": lang["Invert Y-Axis"],
"description": "For When your camera is mounted upside down or uses inverted vertical controls.",
"default": "0",
"example": "",
"fieldType": "select",
"possible": [
{
"name": lang.No,
"value": "0"
},
{
"name": lang.Yes,
"value": "1"
}
]
},
]
},
"Grouping": {

View File

@ -37,6 +37,7 @@
"Token": "Token",
"OAuth Code": "OAuth Code",
"Google Drive": "Google Drive",
"Invert Y-Axis": "Invert Y-Axis",
"Get Code": "Get Code",
"PTZ Tracking": "PTZ Tracking",
"PTZ Tracking Target": "PTZ Tracking Target",
@ -88,6 +89,9 @@
"Never": "Never",
"API": "API",
"ONVIF": "ONVIF",
"Set Home": "Set Home",
"Set Home Position (ONVIF-only)": "Set Home Position (ONVIF-only)",
"Non-Standard ONVIF": "Non-Standard ONVIF",
"FFprobe": "Probe",
"Monitor States": "Monitor States",
"Schedule": "Schedule",

View File

@ -175,7 +175,7 @@ module.exports = function(s,config,lang){
){
if(!user.lang){
var details = s.parseJSON(user.details).lang
user.lang = s.getDefinitonFile(user.details.lang) || s.copySystemDefaultLanguage()
user.lang = s.getLanguageFile(user.details.lang) || s.copySystemDefaultLanguage()
}
onSuccessComplete(user)
}else{

48
libs/commander.js Normal file
View File

@ -0,0 +1,48 @@
module.exports = function(s,config,lang){
if(config.p2pEnabled){
const { Worker, isMainThread } = require('worker_threads');
const startWorker = () => {
// set the first parameter as a string.
const pathToWorkerScript = __dirname + '/commander/worker.js'
const workerProcess = new Worker(pathToWorkerScript)
workerProcess.on('message',function(data){
switch(data.f){
case'debugLog':
s.debugLog(...data.data)
break;
case'systemLog':
s.systemLog(...data.data)
break;
}
})
setTimeout(() => {
workerProcess.postMessage({
f: 'init',
config: config,
lang: lang
})
},2000)
// workerProcess is an Emitter.
// it also contains a direct handle to the `spawn` at `workerProcess.spawnProcess`
return workerProcess
}
config.machineId = config.p2pApiKey + '' + config.p2pGroupId
config.p2pTargetAuth = config.p2pTargetAuth || s.gid(30)
if(config.p2pTargetGroupId && config.p2pTargetUserId){
startWorker()
}else{
s.knexQuery({
action: "select",
columns: "ke,uid",
table: "Users",
where: [],
limit: 1
},(err,r) => {
const firstUser = r[0]
config.p2pTargetUserId = firstUser.uid
config.p2pTargetGroupId = firstUser.ke
startWorker()
})
}
}
}

230
libs/commander/worker.js Normal file
View File

@ -0,0 +1,230 @@
const { parentPort } = require('worker_threads');
const request = require('request');
const socketIOClient = require('socket.io-client');
const p2pClientConnectionStaticName = 'Commander'
const p2pClientConnections = {}
const runningRequests = {}
const connectedUserWebSockets = {}
const s = {
debugLog: (...args) => {
parentPort.postMessage({
f: 'debugLog',
data: args
})
},
systemLog: (...args) => {
parentPort.postMessage({
f: 'systemLog',
data: args
})
},
}
parentPort.on('message',(data) => {
switch(data.f){
case'init':
initialize(data.config,data.lang)
break;
}
})
const initialize = (config,lang) => {
if(!config.p2pHost)config.p2pHost = 'ws://163.172.180.205:8084'
const parseJSON = function(string){
var parsed = string
try{
parsed = JSON.parse(string)
}catch(err){
}
return parsed
}
const createQueryStringFromObject = function(obj){
var queryString = ''
var keys = Object.keys(obj)
keys.forEach(function(key){
var value = obj[key]
queryString += `&${key}=${value}`
})
return queryString
}
const doRequest = function(url,method,data,callback,onDataReceived){
var requestEndpoint = `${config.sslEnabled ? `https` : 'http'}://localhost:${config.sslEnabled ? config.ssl.port : config.port}` + url
if(method === 'GET' && data){
requestEndpoint += '?' + createQueryStringFromObject(data)
}
return request(requestEndpoint,{
method: method,
json: method !== 'GET' ? (data ? data : null) : null
}, function(err,resp,body){
// var json = parseJSON(body)
if(err)console.error(err,data)
callback(err,body,resp)
}).on('data', function(data) {
onDataReceived(data)
})
}
const createShinobiSocketConnection = (connectionId) => {
const masterConnectionToMachine = socketIOClient(`ws://localhost:${config.port}`, {transports:['websocket']})
p2pClientConnections[connectionId || p2pClientConnectionStaticName] = masterConnectionToMachine
return masterConnectionToMachine
}
//
s.debugLog('p2p',`Connecting to ${config.p2pHost}...`)
const connectionToP2PServer = socketIOClient(config.p2pHost, {transports:['websocket']});
if(!config.p2pApiKey){
s.systemLog('p2p',`Please fill 'p2pApiKey' in your conf.json.`)
}
if(!config.p2pGroupId){
s.systemLog('p2p',`Please fill 'p2pGroupId' in your conf.json.`)
}
connectionToP2PServer.on('connect', () => {
s.systemLog('p2p',`Connected ${config.p2pHost}!`)
connectionToP2PServer.emit('initMachine',{
port: config.port,
apiKey: config.p2pApiKey,
groupId: config.p2pGroupId,
targetUserId: config.p2pTargetUserId,
targetGroupId: config.p2pTargetGroupId,
subscriptionId: config.subscriptionId || 'notActivated'
})
})
connectionToP2PServer.on('httpClose',(requestId) => {
if(runningRequests[requestId] && runningRequests[requestId].abort){
runningRequests[requestId].abort()
delete(runningRequests[requestId])
}
})
connectionToP2PServer.on('http',(rawRequest) => {
runningRequests[rawRequest.rid] = doRequest(
rawRequest.url,
rawRequest.method,
rawRequest.data,
function(err,json,resp){
connectionToP2PServer.emit('httpResponse',{
err: err,
json: rawRequest.bodyOnEnd ? json : null,
rid: rawRequest.rid
})
},
(data) => {
if(!rawRequest.bodyOnEnd)connectionToP2PServer.emit('httpResponseChunk',{
data: data,
rid: rawRequest.rid
})
})
})
const masterConnectionToMachine = createShinobiSocketConnection()
masterConnectionToMachine.on('connect', () => {
masterConnectionToMachine.emit('f',{
f: 'init',
auth: config.p2pTargetAuth,
ke: config.p2pTargetGroupId,
uid: config.p2pTargetUserId
})
})
masterConnectionToMachine.on('f',(data) => {
connectionToP2PServer.emit('f',data)
})
connectionToP2PServer.on('wsInit',(rawRequest) => {
s.debugLog('p2pWsInit',rawRequest)
const user = rawRequest.user
const clientConnectionToMachine = createShinobiSocketConnection(rawRequest.cnid)
connectedUserWebSockets[user.auth_token] = user;
clientConnectionToMachine.on('connect', () => {
s.debugLog('init',user.auth_token)
clientConnectionToMachine.emit('f',{
f: 'init',
auth: user.auth_token,
ke: user.ke,
uid: user.uid,
})
});
([
'f',
]).forEach((target) => {
connectionToP2PServer.on(target,(data) => {
clientConnectionToMachine.emit(target,data)
})
clientConnectionToMachine.on(target,(data) => {
connectionToP2PServer.emit(target,{data: data, cnid: rawRequest.cnid})
})
})
});
([
'a',
'r',
'gps',
'e',
'super',
]).forEach((target) => {
connectionToP2PServer.on(target,(data) => {
var clientConnectionToMachine
if(data.f === 'init'){
clientConnectionToMachine = createShinobiSocketConnection(data.cnid)
clientConnectionToMachine.on('connect', () => {
clientConnectionToMachine.on(target,(fromData) => {
connectionToP2PServer.emit(target,{data: fromData, cnid: data.cnid})
})
clientConnectionToMachine.on('f',(fromData) => {
connectionToP2PServer.emit('f',{data: fromData, cnid: data.cnid})
})
clientConnectionToMachine.emit(target,data)
});
}else{
clientConnectionToMachine = p2pClientConnections[data.cnid]
clientConnectionToMachine.emit(target,data)
}
})
});
([
'h265',
'Base64',
'FLV',
'MP4',
]).forEach((target) => {
connectionToP2PServer.on(target,(initData) => {
if(connectedUserWebSockets[initData.auth]){
const clientConnectionToMachine = createShinobiSocketConnection(initData.auth + initData.ke + initData.id)
clientConnectionToMachine.on('connect', () => {
clientConnectionToMachine.emit(target,initData)
});
clientConnectionToMachine.on('data',(data) => {
connectionToP2PServer.emit('data',{data: data, cnid: initData.cnid})
});
}else{
s.debugLog('disconnect now!')
}
})
});
connectionToP2PServer.on('wsDestroyStream',(clientKey) => {
if(p2pClientConnections[clientKey]){
p2pClientConnections[clientKey].disconnect();
}
delete(p2pClientConnections[clientKey])
});
connectionToP2PServer.on('wsDestroy',(rawRequest) => {
if(p2pClientConnections[rawRequest.cnid]){
p2pClientConnections[rawRequest.cnid].disconnect();
}
delete(p2pClientConnections[rawRequest.cnid])
});
connectionToP2PServer.on('allowDisconnect',(bool) => {
connectionToP2PServer.allowDisconnect = true;
connectionToP2PServer.disconnect()
s.debugLog('p2p','Server Forced Disconnection')
});
const onDisconnect = () => {
s.systemLog('p2p','Disconnected')
if(!connectionToP2PServer.allowDisconnect){
s.systemLog('p2p','Attempting Reconnection...')
setTimeout(() => {
connectionToP2PServer.connect()
},3000)
}
}
connectionToP2PServer.on('error',onDisconnect)
connectionToP2PServer.on('disconnect',onDisconnect)
}

View File

@ -2,5 +2,5 @@ var os = require('os');
var exec = require('child_process').exec;
module.exports = function(s,config,lang,app,io){
require('./control/onvif.js')(s,config,lang,app,io)
const ptz = require('./control/ptz.js')(s,config,lang,app,io)
// const ptz = require('./control/ptz.js')(s,config,lang,app,io)
}

View File

@ -17,13 +17,26 @@ module.exports = function(s,config,lang,app,io){
try{
const info = await device.init()
response.ok = true
response.device = device
}catch(err){
response.msg = 'Device responded with an error'
response.error = error
response.error = err
}
return response
}
const runOnvifMethod = (onvifOptions,callback) => {
const replaceDynamicInOptions = (Camera,options) => {
const newOptions = {}
Object.keys(options).forEach((key) => {
const value = options[key]
if(typeof value === 'string'){
newOptions[key] = value.replace(/__CURRENT_TOKEN/g,Camera.current_profile.token)
}else if(value !== undefined && value !== null){
newOptions[key] = value
}
})
return newOptions
}
const runOnvifMethod = async (onvifOptions,callback) => {
var onvifAuth = onvifOptions.auth
var response = {ok: false}
var errorMessage = function(msg,error){
@ -83,7 +96,8 @@ module.exports = function(s,config,lang,app,io){
var options
var command
if(argNames[0] === 'options' || argNames[0] === 'params'){
options = onvifOptions.options || {}
options = replaceDynamicInOptions(Camera,onvifOptions.options || {})
response.options = options
}
if(onvifAuth.service){
command = Camera.services[onvifAuth.service][onvifAuth.action](options)
@ -94,7 +108,7 @@ module.exports = function(s,config,lang,app,io){
}
}
if(!s.group[onvifAuth.ke].activeMonitors[onvifAuth.id].onvifConnection){
const response = createOnvifDevice(onvifAuth)
const response = await createOnvifDevice(onvifAuth)
if(response.ok){
doAction(response.device)
}else{
@ -112,15 +126,15 @@ module.exports = function(s,config,lang,app,io){
config.webPaths.apiPrefix+':auth/onvif/:ke/:id/:service/:action'
],function (req,res){
s.auth(req.params,function(user){
const options = s.getPostData(req,'options',true) || s.getPostData(req,'params',true)
runOnvifMethod({
auth: {
ke: req.params.ke,
id: req.params.id,
auth: req.params.auth,
action: req.params.action,
service: req.params.service,
},
options: s.getPostData(req,'options',true) || s.getPostData(req,'params',true),
options: options,
},(endData) => {
s.closeJsonResponse(res,endData)
})

View File

@ -1,8 +1,9 @@
var os = require('os');
var exec = require('child_process').exec;
var request = require('request')
module.exports = function(s,config,lang,app,io){
module.exports = function(s,config,lang){
const moveLock = {}
const ptzTimeoutsUntilResetToHome = {}
const startMove = async function(options,callback){
const device = s.group[options.ke].activeMonitors[options.id].onvifConnection
if(!device){
@ -41,6 +42,7 @@ module.exports = function(s,config,lang,app,io){
}
const moveOnvifCamera = function(options,callback){
const monitorConfig = s.group[options.ke].rawMonitorConfigurations[options.id]
const invertedVerticalAxis = monitorConfig.details.control_invert_y === '1'
const controlUrlStopTimeout = parseInt(monitorConfig.details.control_url_stop_timeout) || 1000
switch(options.direction){
case'center':
@ -68,8 +70,8 @@ module.exports = function(s,config,lang,app,io){
var onvifDirections = {
"left": [-1.0,'x'],
"right": [1.0,'x'],
"down": [-1.0,'y'],
"up": [1.0,'y'],
"down": [invertedVerticalAxis ? 1.0 : -1.0,'y'],
"up": [invertedVerticalAxis ? -1.0 : 1.0,'y'],
"zoom_in": [1.0,'z'],
"zoom_out": [-1.0,'z']
}
@ -258,10 +260,123 @@ module.exports = function(s,config,lang,app,io){
}
}
}
s.cameraControl = ptzControl
const getPresetPositions = (options,callback) => {
const profileToken = options.ProfileToken || "__CURRENT_TOKEN"
return s.runOnvifMethod({
auth: {
ke: options.ke,
id: options.id,
service: 'ptz',
action: 'getPresets',
},
options: {
ProfileToken: profileToken
},
},callback)
}
const setPresetForCurrentPosition = (options,callback) => {
const nonStandardOnvif = s.group[options.ke].rawMonitorConfigurations[options.id].details.onvif_non_standard === '1'
const profileToken = options.ProfileToken || "__CURRENT_TOKEN"
s.runOnvifMethod({
auth: {
ke: options.ke,
id: options.id,
service: 'ptz',
action: 'setPreset',
},
options: {
ProfileToken: profileToken,
PresetToken: nonStandardOnvif ? null : options.PresetToken || profileToken,
PresetName: options.PresetName || nonStandardOnvif ? '1' : profileToken
},
},(endData) => {
callback(endData)
})
}
const moveToPresetPosition = (options,callback) => {
const nonStandardOnvif = s.group[options.ke].rawMonitorConfigurations[options.id].details.onvif_non_standard === '1'
const profileToken = options.ProfileToken || "__CURRENT_TOKEN"
return s.runOnvifMethod({
auth: {
ke: options.ke,
id: options.id,
service: 'ptz',
action: 'gotoPreset',
},
options: {
ProfileToken: profileToken,
PresetToken: options.PresetToken || nonStandardOnvif ? '1' : profileToken,
Speed: {
"x": 1,
"y": 1,
"z": 1
},
},
},callback)
}
const getLargestMatrix = (matrices) => {
var largestMatrix = {width: 0, height: 0}
matrices.forEach((matrix) => {
if(matrix.width > largestMatrix.width && matrix.height > largestMatrix.height)largestMatrix = matrix
})
return largestMatrix.x ? largestMatrix : null
}
const moveCameraPtzToMatrix = function(event,trackingTarget){
if(moveLock[event.ke + event.id])return;
clearTimeout(moveLock[event.ke + event.id])
moveLock[event.ke + event.id] = setTimeout(() => {
delete(moveLock[event.ke + event.id])
},1000)
const imgHeight = event.details.imgHeight
const imgWidth = event.details.imgWidth
const thresholdX = imgWidth * 0.125
const thresholdY = imgHeight * 0.125
const imageCenterX = imgWidth / 2
const imageCenterY = imgHeight / 2
const matrices = event.details.matrices
const largestMatrix = getLargestMatrix(matrices.filter(matrix => matrix.tag === (trackingTarget || 'person')))
// console.log(matrices.find(matrix => matrix.tag === 'person'))
if(!largestMatrix)return;
const matrixCenterX = largestMatrix.x + (largestMatrix.width / 2)
const matrixCenterY = largestMatrix.y + (largestMatrix.height / 2)
const rawDistanceX = (matrixCenterX - imageCenterX)
const rawDistanceY = (matrixCenterY - imageCenterY)
const distanceX = imgWidth / rawDistanceX
const distanceY = imgHeight / rawDistanceY
const axisX = rawDistanceX > thresholdX || rawDistanceX < -thresholdX ? distanceX : 0
const axisY = largestMatrix.y < 30 && largestMatrix.height > imgHeight * 0.8 ? 0.5 : rawDistanceY > thresholdY || rawDistanceY < -thresholdY ? -distanceY : 0
if(axisX !== 0 || axisY !== 0){
ptzControl({
axis: [
{direction: 'x', amount: axisX === 0 ? 0 : axisX > 0 ? 0.01 : -0.01},
{direction: 'y', amount: axisY === 0 ? 0 : axisY > 0 ? 0.01 : -0.01},
{direction: 'z', amount: 0},
],
// axis: [{direction: 'x', amount: 1.0}],
id: event.id,
ke: event.ke
},(msg) => {
s.userLog(event,msg)
// console.log(msg)
clearTimeout(ptzTimeoutsUntilResetToHome[event.ke + event.id])
ptzTimeoutsUntilResetToHome[event.ke + event.id] = setTimeout(() => {
moveToPresetPosition({
ke: event.ke,
id: event.id,
},(endData) => {
console.log(endData)
})
},7000)
})
}
}
return {
control: ptzControl,
ptzControl: ptzControl,
startMove: startMove,
stopMove: stopMove,
getPresetPositions: getPresetPositions,
setPresetForCurrentPosition: setPresetForCurrentPosition,
moveToPresetPosition: moveToPresetPosition,
moveCameraPtzToMatrix: moveCameraPtzToMatrix
}
}

View File

@ -383,6 +383,35 @@ module.exports = async (s,config,lang,app,io) => {
}
},res,req)
})
// /**
// * API : Superuser : Custom Auto Load Package Update.
// */
// app.post(config.webPaths.superApiPrefix+':auth/package/update', async (req,res) => {
// s.superAuth(req.params, async (resp) => {
// try{
// const url = req.body.downloadUrl
// const packageRoot = req.body.packageRoot || ''
// const packageName = req.body.packageName || extractNameFromPackage(url)
// const modulePath = getModulePath(packageName)
// await downloadModule(url,packageName)
// const properties = getModuleProperties(packageName)
// const newName = await moveModuleToNameInProperties(modulePath,packageRoot,properties)
// const chosenName = newName ? newName : packageName
//
// disableModule(chosenName,true)
// s.closeJsonResponse(res,{
// ok: true,
// moduleName: chosenName,
// newModule: getModule(chosenName)
// })
// }catch(err){
// s.closeJsonResponse(res,{
// ok: false,
// error: err
// })
// }
// },res,req)
// })
/**
* API : Superuser : Custom Auto Load Package Install.
*/

View File

@ -10,7 +10,9 @@ var P = SAT.Polygon;
var B = SAT.Box;
// Matrix In Region Libs />
module.exports = function(s,config,lang){
const ptz = require('./control/ptz.js')(s,config,lang)
const {
moveCameraPtzToMatrix,
} = require('./control/ptz.js')(s,config,lang)
const countObjects = async (event) => {
const matrices = event.details.matrices
const eventsCounted = s.group[event.ke].activeMonitors[event.id].eventsCounted || {}
@ -78,54 +80,6 @@ module.exports = function(s,config,lang){
return collisions
}
const nonEmpty = (element) => element.length !== 0;
const moveLock = {}
const getLargestMatrix = (matrices) => {
var largestMatrix = {width: 0, height: 0}
matrices.forEach((matrix) => {
if(matrix.width > largestMatrix.width && matrix.height > largestMatrix.height)largestMatrix = matrix
})
return largestMatrix.x ? largestMatrix : null
}
const moveCameraPtzToMatrix = function(event,trackingTarget){
if(moveLock[event.ke + event.id])return;
clearTimeout(moveLock[event.ke + event.id])
moveLock[event.ke + event.id] = setTimeout(() => {
delete(moveLock[event.ke + event.id])
},1000)
const imgHeight = event.details.imgHeight
const imgWidth = event.details.imgWidth
const thresholdX = imgWidth * 0.125
const thresholdY = imgHeight * 0.125
const imageCenterX = imgWidth / 2
const imageCenterY = imgHeight / 2
const matrices = event.details.matrices
const largestMatrix = getLargestMatrix(matrices.filter(matrix => matrix.tag === (trackingTarget || 'person')))
// console.log(matrices.find(matrix => matrix.tag === 'person'))
if(!largestMatrix)return;
const matrixCenterX = largestMatrix.x + (largestMatrix.width / 2)
const matrixCenterY = largestMatrix.y + (largestMatrix.height / 2)
const rawDistanceX = (matrixCenterX - imageCenterX)
const rawDistanceY = (matrixCenterY - imageCenterY)
const distanceX = imgWidth / rawDistanceX
const distanceY = imgHeight / rawDistanceY
const axisX = rawDistanceX > thresholdX || rawDistanceX < -thresholdX ? distanceX : 0
const axisY = largestMatrix.y < 30 && largestMatrix.height > imgHeight * 0.8 ? 0.5 : rawDistanceY > thresholdY || rawDistanceY < -thresholdY ? -distanceY : 0
if(axisX !== 0 || axisY !== 0){
ptz.control({
axis: [
{direction: 'x', amount: axisX === 0 ? 0 : axisX > 0 ? 0.01 : -0.01},
{direction: 'y', amount: axisY === 0 ? 0 : axisY > 0 ? 0.01 : -0.01},
{direction: 'z', amount: 0},
],
// axis: [{direction: 'x', amount: 1.0}],
id: event.id,
ke: event.ke
},(msg) => {
s.userLog(event,msg)
// console.log(msg)
})
}
}
s.addEventDetailsToString = function(eventData,string,addOps){
//d = event data
if(!addOps)addOps = {}

View File

@ -13,6 +13,9 @@ const URL = require('url')
const { copyObject, createQueue } = require('./common.js')
module.exports = function(s,config,lang){
const { cameraDestroy } = require('./monitor/utils.js')(s,config,lang)
const {
setPresetForCurrentPosition
} = require('./control/ptz.js')(s,config,lang)
const startMonitorInQueue = createQueue(1, 3)
s.initiateMonitorObject = function(e){
if(!s.group[e.ke]){s.group[e.ke]={}};
@ -455,7 +458,7 @@ module.exports = function(s,config,lang){
ke: e.ke
},'GRP_'+e.ke)
}else{
console.log('not image')
s.debugLog('Damaged Snapshot Data')
s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke)
}
}else{
@ -634,21 +637,25 @@ module.exports = function(s,config,lang){
},60000*1);
}
const onDetectorJpegOutputAlone = (e,d) => {
s.ocvTx({
f: 'frame',
mon: s.group[e.ke].rawMonitorConfigurations[e.id].details,
ke: e.ke,
id: e.id,
time: s.formattedTime(),
frame: d
})
if(s.isAtleatOneDetectorPluginConnected){
s.ocvTx({
f: 'frame',
mon: s.group[e.ke].rawMonitorConfigurations[e.id].details,
ke: e.ke,
id: e.id,
time: s.formattedTime(),
frame: d
})
}
}
const onDetectorJpegOutputSecondary = (e,buffer) => {
const theArray = s.group[e.ke].activeMonitors[e.id].pipe4BufferPieces
theArray.push(buffer)
if(buffer[buffer.length-2] === 0xFF && buffer[buffer.length-1] === 0xD9){
s.group[e.ke].activeMonitors[e.id].lastJpegDetectorFrame = Buffer.concat(theArray)
s.group[e.ke].activeMonitors[e.id].pipe4BufferPieces = []
if(s.isAtleatOneDetectorPluginConnected){
const theArray = s.group[e.ke].activeMonitors[e.id].pipe4BufferPieces
theArray.push(buffer)
if(buffer[buffer.length-2] === 0xFF && buffer[buffer.length-1] === 0xD9){
s.group[e.ke].activeMonitors[e.id].lastJpegDetectorFrame = Buffer.concat(theArray)
s.group[e.ke].activeMonitors[e.id].pipe4BufferPieces = []
}
}
}
const createCameraFfmpegProcess = (e) => {
@ -856,19 +863,13 @@ module.exports = function(s,config,lang){
onDetectorJpegOutputSecondary(e,data)
})
}
}else if(s.isAtleatOneDetectorPluginConnected){
if(e.details.detector_use_detect_object === '1' && e.details.detector_send_frames !== '1'){
s.group[e.ke].activeMonitors[e.id].spawn.stdio[4].on('data',function(data){
onDetectorJpegOutputSecondary(e,data)
})
}else{
s.group[e.ke].activeMonitors[e.id].spawn.stdio[4].on('data',function(data){
onDetectorJpegOutputAlone(e,data)
})
}
}else if(e.details.detector_use_detect_object === '1' && e.details.detector_send_frames !== '1'){
s.group[e.ke].activeMonitors[e.id].spawn.stdio[4].on('data',function(data){
onDetectorJpegOutputSecondary(e,data)
})
}else{
s.group[e.ke].activeMonitors[e.id].spawn.stdio[4].on('data',function(data){
// set so ffmpeg doesnt hang
onDetectorJpegOutputAlone(e,data)
})
}
}
@ -1609,6 +1610,34 @@ module.exports = function(s,config,lang){
break;
}
}
if(e.details.detector_ptz_follow === '1'){
setTimeout(() => {
setPresetForCurrentPosition({
ke: e.ke,
id: e.id
},(endData) => {
if(endData.ok === false){
setTimeout(() => {
setPresetForCurrentPosition({
ke: e.ke,
id: e.id
},(endData) => {
if(endData.ok === false){
setTimeout(() => {
setPresetForCurrentPosition({
ke: e.ke,
id: e.id
},(endData) => {
console.log(endData)
})
},5000)
}
})
},5000)
}
})
},5000)
}
launchMonitorProcesses(e)
break;
default:

View File

@ -54,7 +54,7 @@ module.exports = function(s,config,lang,app,io){
ip = addressRange.join(',')
}
if(ports === ''){
ports = '80,8080,8000,7575,8081,9080,8090,8999'
ports = '80,8080,8000,7575,8081,9080,8090,8999,8899'
}
if(ports.indexOf('-') > -1){
ports = ports.split('-')

View File

@ -118,10 +118,11 @@ module.exports = function(s,config,lang,app,io){
var scheduleNames = Object.keys(s.schedules[key])
scheduleNames.forEach(function(name){
var schedule = s.schedules[key][name]
if(!schedule.active && schedule.enabled === 1 && schedule.start && schedule.details.monitorStates){
if(schedule.enabled === 1 && schedule.start && schedule.details.monitorStates){
var timePasses = checkTimeAgainstSchedule(schedule)
var daysPasses = checkDaysAgainstSchedule(schedule)
if(timePasses && daysPasses){
var passed = timePasses && daysPasses
if(passed && !schedule.active){
schedule.active = true
var monitorStates = schedule.details.monitorStates
monitorStates.forEach(function(stateName){
@ -135,7 +136,7 @@ module.exports = function(s,config,lang,app,io){
// console.log(endData)
})
})
}else{
}else if(!passed && schedule.active){
schedule.active = false
}
}

View File

@ -4,6 +4,9 @@ var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var jsonfile = require("jsonfile");
module.exports = function(s,config,lang,io){
const {
ptzControl
} = require('./control/ptz.js')(s,config,lang)
s.clientSocketConnection = {}
//send data to socket client function
s.tx = function(z,y,x){
@ -51,17 +54,21 @@ module.exports = function(s,config,lang,io){
}
}
const streamConnectionAuthentication = (options) => {
const streamConnectionAuthentication = (options,ipAddress) => {
return new Promise( (resolve,reject) => {
var isInternal = false
if(ipAddress.indexOf('localhost') > -1 || ipAddress.indexOf('127.0.0.1') > -1){
isInternal = true
}
const baseWheres = [
['ke','=',options.ke],
['uid','=',options.uid],
]
s.knexQuery({
action: "select",
columns: "ke,uid,auth,mail,details",
table: "Users",
where: [
['ke','=',options.ke],
['auth','=',options.auth],
['uid','=',options.uid],
]
where: baseWheres.concat(!isInternal ? [['auth','=',options.auth]] : [])
},(err,r) => {
if(r&&r[0]){
resolve(r)
@ -70,11 +77,7 @@ module.exports = function(s,config,lang,io){
action: "select",
columns: "*",
table: "API",
where: [
['ke','=',options.ke],
['code','=',options.auth],
['uid','=',options.uid],
]
where: baseWheres.concat(!isInternal ? [['code','=',options.auth]] : [])
},(err,r) => {
if(r && r[0]){
r = r[0]
@ -165,7 +168,7 @@ module.exports = function(s,config,lang,io){
if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){
onSuccess(s.group[d.ke].users[d.auth]);
}else{
streamConnectionAuthentication(d).then(onSuccess).catch(onFail)
streamConnectionAuthentication(d,cn.ip).then(onSuccess).catch(onFail)
}
})
//unique Base64 socket stream
@ -198,7 +201,7 @@ module.exports = function(s,config,lang,io){
if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){
onSuccess(s.group[d.ke].users[d.auth]);
}else{
streamConnectionAuthentication(d).then(onSuccess).catch(onFail)
streamConnectionAuthentication(d,cn.ip).then(onSuccess).catch(onFail)
}
})
//unique FLV socket stream
@ -231,7 +234,7 @@ module.exports = function(s,config,lang,io){
if(s.group[d.ke] && s.group[d.ke].users && s.group[d.ke].users[d.auth]){
onSuccess(s.group[d.ke].users[d.auth]);
}else{
streamConnectionAuthentication(d).then(onSuccess).catch(onFail)
streamConnectionAuthentication(d,cn.ip).then(onSuccess).catch(onFail)
}
})
//unique MP4 socket stream
@ -312,7 +315,7 @@ module.exports = function(s,config,lang,io){
if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){
onSuccess(s.group[d.ke].users[d.auth]);
}else{
streamConnectionAuthentication(d).then(onSuccess).catch(onFail)
streamConnectionAuthentication(d,cn.ip).then(onSuccess).catch(onFail)
}
})
//main socket control functions
@ -393,7 +396,7 @@ module.exports = function(s,config,lang,io){
extender(r,cn,d,tx)
})
}
streamConnectionAuthentication(d).then(onSuccess).catch(onFail)
streamConnectionAuthentication(d,cn.ip).then(onSuccess).catch(onFail)
return;
}
if((d.id||d.uid||d.mid)&&cn.ke){
@ -649,7 +652,7 @@ module.exports = function(s,config,lang,io){
}
break;
case'control':
s.cameraControl(d,function(msg){
ptzControl(d,function(msg){
s.userLog(d,msg)
tx({f:'control',response:msg})
})

View File

@ -172,7 +172,7 @@ module.exports = function(s,config){
dbQuery.limit(options.limit)
}else{
const limitParts = `${options.limit}`.split(',')
dbQuery.limit(limitParts[0]).offset(limitParts[1])
dbQuery.limit(limitParts[1]).offset(limitParts[0])
}
}
if(config.debugLog === true){
@ -203,7 +203,7 @@ module.exports = function(s,config){
['ke','=',options.groupKey],
]
const monitorRestrictions = options.monitorRestrictions
var frameLimit = parseInt(options.limit) || 500
var frameLimit = options.limit
const endIsStartTo = options.endIsStartTo
const chosenDate = options.date
const startDate = options.startDate ? s.stringToSqlTime(options.startDate) : null
@ -511,8 +511,6 @@ module.exports = function(s,config){
type: 'count',
endIsStartTo: endIsStartTo
},(response) => {
console.log('count')
console.log(response)
const count = response.count
var skipOver = 0
if(limitString.indexOf(',') > -1){

View File

@ -6,443 +6,446 @@ var crypto = require('crypto');
var exec = require('child_process').exec;
var execSync = require('child_process').execSync;
module.exports = function(s,config,lang,io){
var checkedAdminUsers = {}
console.log('FFmpeg version : '+s.ffmpegVersion)
console.log('Node.js version : '+process.version)
s.processReady = function(){
delete(checkedAdminUsers)
s.systemLog(lang.startUpText5)
s.onProcessReadyExtensions.forEach(function(extender){
extender(true)
})
process.send('ready')
}
var checkForTerminalCommands = function(callback){
var next = function(){
if(callback)callback()
}
if(!s.isWin && s.packageJson.mainDirectory !== '.'){
var etcPath = '/etc/shinobisystems/cctv.txt'
fs.stat(etcPath,function(err,stat){
if(err || !stat){
exec('node '+ s.mainDirectory + '/INSTALL/terminalCommands.js',function(err){
if(err)console.log(err)
})
}
next()
return new Promise((resolve, reject) => {
var checkedAdminUsers = {}
console.log('FFmpeg version : '+s.ffmpegVersion)
console.log('Node.js version : '+process.version)
s.processReady = function(){
delete(checkedAdminUsers)
resolve()
s.systemLog(lang.startUpText5)
s.onProcessReadyExtensions.forEach(function(extender){
extender(true)
})
}else{
next()
process.send('ready')
}
}
var loadedAccounts = []
var foundMonitors = []
var loadMonitors = function(callback){
s.beforeMonitorsLoadedOnStartupExtensions.forEach(function(extender){
extender()
})
s.systemLog(lang.startUpText4)
//preliminary monitor start
s.knexQuery({
action: "select",
columns: "*",
table: "Monitors",
},function(err,monitors) {
foundMonitors = monitors
if(err){s.systemLog(err)}
if(monitors && monitors[0]){
var didNotLoad = 0
var loadCompleted = 0
var orphanedVideosForMonitors = {}
var loadMonitor = function(monitor){
const checkAnother = function(){
++loadCompleted
if(monitors[loadCompleted]){
loadMonitor(monitors[loadCompleted])
var checkForTerminalCommands = function(callback){
var next = function(){
if(callback)callback()
}
if(!s.isWin && s.packageJson.mainDirectory !== '.'){
var etcPath = '/etc/shinobisystems/cctv.txt'
fs.stat(etcPath,function(err,stat){
if(err || !stat){
exec('node '+ s.mainDirectory + '/INSTALL/terminalCommands.js',function(err){
if(err)console.log(err)
})
}
next()
})
}else{
next()
}
}
var loadedAccounts = []
var foundMonitors = []
var loadMonitors = function(callback){
s.beforeMonitorsLoadedOnStartupExtensions.forEach(function(extender){
extender()
})
s.systemLog(lang.startUpText4)
//preliminary monitor start
s.knexQuery({
action: "select",
columns: "*",
table: "Monitors",
},function(err,monitors) {
foundMonitors = monitors
if(err){s.systemLog(err)}
if(monitors && monitors[0]){
var didNotLoad = 0
var loadCompleted = 0
var orphanedVideosForMonitors = {}
var loadMonitor = function(monitor){
const checkAnother = function(){
++loadCompleted
if(monitors[loadCompleted]){
loadMonitor(monitors[loadCompleted])
}else{
if(didNotLoad > 0)console.log(`${didNotLoad} Monitor${didNotLoad === 1 ? '' : 's'} not loaded because Admin user does not exist for them. It may have been deleted.`);
callback()
}
}
if(checkedAdminUsers[monitor.ke]){
setTimeout(function(){
if(!orphanedVideosForMonitors[monitor.ke])orphanedVideosForMonitors[monitor.ke] = {}
if(!orphanedVideosForMonitors[monitor.ke][monitor.mid])orphanedVideosForMonitors[monitor.ke][monitor.mid] = 0
s.initiateMonitorObject(monitor)
s.group[monitor.ke].rawMonitorConfigurations[monitor.mid] = monitor
s.sendMonitorStatus({id:monitor.mid,ke:monitor.ke,status:'Stopped'});
var monObj = Object.assign(monitor,{id : monitor.mid})
s.camera(monitor.mode,monObj)
checkAnother()
},1000)
}else{
if(didNotLoad > 0)console.log(`${didNotLoad} Monitor${didNotLoad === 1 ? '' : 's'} not loaded because Admin user does not exist for them. It may have been deleted.`);
callback()
++didNotLoad
checkAnother()
}
}
if(checkedAdminUsers[monitor.ke]){
setTimeout(function(){
if(!orphanedVideosForMonitors[monitor.ke])orphanedVideosForMonitors[monitor.ke] = {}
if(!orphanedVideosForMonitors[monitor.ke][monitor.mid])orphanedVideosForMonitors[monitor.ke][monitor.mid] = 0
s.initiateMonitorObject(monitor)
s.group[monitor.ke].rawMonitorConfigurations[monitor.mid] = monitor
s.sendMonitorStatus({id:monitor.mid,ke:monitor.ke,status:'Stopped'});
var monObj = Object.assign(monitor,{id : monitor.mid})
s.camera(monitor.mode,monObj)
checkAnother()
},1000)
}else{
++didNotLoad
checkAnother()
}
loadMonitor(monitors[loadCompleted])
}else{
callback()
}
loadMonitor(monitors[loadCompleted])
})
}
var checkForOrphanedVideos = function(callback){
var monitors = foundMonitors
if(monitors && monitors[0]){
var loadCompleted = 0
var orphanedVideosForMonitors = {}
var checkForOrphanedVideosForMonitor = function(monitor){
if(!orphanedVideosForMonitors[monitor.ke])orphanedVideosForMonitors[monitor.ke] = {}
if(!orphanedVideosForMonitors[monitor.ke][monitor.mid])orphanedVideosForMonitors[monitor.ke][monitor.mid] = 0
s.orphanedVideoCheck(monitor,null,function(orphanedFilesCount){
if(orphanedFilesCount){
orphanedVideosForMonitors[monitor.ke][monitor.mid] += orphanedFilesCount
}
++loadCompleted
if(monitors[loadCompleted]){
checkForOrphanedVideosForMonitor(monitors[loadCompleted])
}else{
s.systemLog(lang.startUpText6+' : '+s.s(orphanedVideosForMonitors))
delete(foundMonitors)
callback()
}
})
}
checkForOrphanedVideosForMonitor(monitors[loadCompleted])
}else{
callback()
}
})
}
var checkForOrphanedVideos = function(callback){
var monitors = foundMonitors
if(monitors && monitors[0]){
var loadCompleted = 0
var orphanedVideosForMonitors = {}
var checkForOrphanedVideosForMonitor = function(monitor){
if(!orphanedVideosForMonitors[monitor.ke])orphanedVideosForMonitors[monitor.ke] = {}
if(!orphanedVideosForMonitors[monitor.ke][monitor.mid])orphanedVideosForMonitors[monitor.ke][monitor.mid] = 0
s.orphanedVideoCheck(monitor,null,function(orphanedFilesCount){
if(orphanedFilesCount){
orphanedVideosForMonitors[monitor.ke][monitor.mid] += orphanedFilesCount
}
++loadCompleted
if(monitors[loadCompleted]){
checkForOrphanedVideosForMonitor(monitors[loadCompleted])
}else{
s.systemLog(lang.startUpText6+' : '+s.s(orphanedVideosForMonitors))
delete(foundMonitors)
callback()
}
})
}
checkForOrphanedVideosForMonitor(monitors[loadCompleted])
}else{
callback()
}
}
var loadDiskUseForUser = function(user,callback){
s.systemLog(user.mail+' : '+lang.startUpText0)
var userDetails = JSON.parse(user.details)
s.group[user.ke].sizeLimit = parseFloat(userDetails.size) || 10000
s.group[user.ke].sizeLimitVideoPercent = parseFloat(userDetails.size_video_percent) || 90
s.group[user.ke].sizeLimitTimelapseFramesPercent = parseFloat(userDetails.size_timelapse_percent) || 10
s.knexQuery({
action: "select",
columns: "*",
table: "Videos",
where: [
['ke','=',user.ke],
['status','!=',0],
]
},function(err,videos) {
var loadDiskUseForUser = function(user,callback){
s.systemLog(user.mail+' : '+lang.startUpText0)
var userDetails = JSON.parse(user.details)
s.group[user.ke].sizeLimit = parseFloat(userDetails.size) || 10000
s.group[user.ke].sizeLimitVideoPercent = parseFloat(userDetails.size_video_percent) || 90
s.group[user.ke].sizeLimitTimelapseFramesPercent = parseFloat(userDetails.size_timelapse_percent) || 10
s.knexQuery({
action: "select",
columns: "*",
table: "Timelapse Frames",
where: [
['ke','=',user.ke],
]
},function(err,timelapseFrames) {
s.knexQuery({
action: "select",
columns: "*",
table: "Files",
where: [
['ke','=',user.ke],
]
},function(err,files) {
var usedSpaceVideos = 0
var usedSpaceTimelapseFrames = 0
var usedSpaceFilebin = 0
var addStorageData = {
files: [],
videos: [],
timelapeFrames: [],
}
if(videos && videos[0]){
videos.forEach(function(video){
video.details = s.parseJSON(video.details)
if(!video.details.dir){
usedSpaceVideos += video.size
}else{
addStorageData.videos.push(video)
}
})
}
if(timelapseFrames && timelapseFrames[0]){
timelapseFrames.forEach(function(frame){
frame.details = s.parseJSON(frame.details)
if(!frame.details.dir){
usedSpaceTimelapseFrames += frame.size
}else{
addStorageData.timelapeFrames.push(frame)
}
})
}
if(files && files[0]){
files.forEach(function(file){
file.details = s.parseJSON(file.details)
if(!file.details.dir){
usedSpaceFilebin += file.size
}else{
addStorageData.files.push(file)
}
})
}
s.group[user.ke].usedSpace = (usedSpaceVideos + usedSpaceTimelapseFrames + usedSpaceFilebin) / 1048576
s.group[user.ke].usedSpaceVideos = usedSpaceVideos / 1048576
s.group[user.ke].usedSpaceFilebin = usedSpaceFilebin / 1048576
s.group[user.ke].usedSpaceTimelapseFrames = usedSpaceTimelapseFrames / 1048576
loadAddStorageDiskUseForUser(user,addStorageData,function(){
callback()
})
})
})
})
}
var loadCloudDiskUseForUser = function(user,callback){
var userDetails = JSON.parse(user.details)
user.cloudDiskUse = {}
user.size = 0
user.limit = userDetails.size
s.cloudDisksLoaded.forEach(function(storageType){
user.cloudDiskUse[storageType] = {
usedSpace : 0,
firstCount : 0
}
if(s.cloudDiskUseStartupExtensions[storageType])s.cloudDiskUseStartupExtensions[storageType](user,userDetails)
})
var loadCloudVideos = function(callback){
s.knexQuery({
action: "select",
columns: "*",
table: "Cloud Videos",
table: "Videos",
where: [
['ke','=',user.ke],
['status','!=',0],
]
},function(err,videos) {
if(videos && videos[0]){
videos.forEach(function(video){
var storageType = JSON.parse(video.details).type
if(!storageType)storageType = 's3'
var videoSize = video.size / 1048576
user.cloudDiskUse[storageType].usedSpace += videoSize
user.cloudDiskUse[storageType].usedSpaceVideos += videoSize
++user.cloudDiskUse[storageType].firstCount
s.knexQuery({
action: "select",
columns: "*",
table: "Timelapse Frames",
where: [
['ke','=',user.ke],
]
},function(err,timelapseFrames) {
s.knexQuery({
action: "select",
columns: "*",
table: "Files",
where: [
['ke','=',user.ke],
]
},function(err,files) {
var usedSpaceVideos = 0
var usedSpaceTimelapseFrames = 0
var usedSpaceFilebin = 0
var addStorageData = {
files: [],
videos: [],
timelapeFrames: [],
}
if(videos && videos[0]){
videos.forEach(function(video){
video.details = s.parseJSON(video.details)
if(!video.details.dir){
usedSpaceVideos += video.size
}else{
addStorageData.videos.push(video)
}
})
}
if(timelapseFrames && timelapseFrames[0]){
timelapseFrames.forEach(function(frame){
frame.details = s.parseJSON(frame.details)
if(!frame.details.dir){
usedSpaceTimelapseFrames += frame.size
}else{
addStorageData.timelapeFrames.push(frame)
}
})
}
if(files && files[0]){
files.forEach(function(file){
file.details = s.parseJSON(file.details)
if(!file.details.dir){
usedSpaceFilebin += file.size
}else{
addStorageData.files.push(file)
}
})
}
s.group[user.ke].usedSpace = (usedSpaceVideos + usedSpaceTimelapseFrames + usedSpaceFilebin) / 1048576
s.group[user.ke].usedSpaceVideos = usedSpaceVideos / 1048576
s.group[user.ke].usedSpaceFilebin = usedSpaceFilebin / 1048576
s.group[user.ke].usedSpaceTimelapseFrames = usedSpaceTimelapseFrames / 1048576
loadAddStorageDiskUseForUser(user,addStorageData,function(){
callback()
})
})
s.cloudDisksLoaded.forEach(function(storageType){
var firstCount = user.cloudDiskUse[storageType].firstCount
s.systemLog(user.mail+' : '+lang.startUpText1+' : '+firstCount,storageType,user.cloudDiskUse[storageType].usedSpace)
delete(user.cloudDiskUse[storageType].firstCount)
})
}
callback()
})
})
}
var loadCloudTimelapseFrames = function(callback){
var loadCloudDiskUseForUser = function(user,callback){
var userDetails = JSON.parse(user.details)
user.cloudDiskUse = {}
user.size = 0
user.limit = userDetails.size
s.cloudDisksLoaded.forEach(function(storageType){
user.cloudDiskUse[storageType] = {
usedSpace : 0,
firstCount : 0
}
if(s.cloudDiskUseStartupExtensions[storageType])s.cloudDiskUseStartupExtensions[storageType](user,userDetails)
})
var loadCloudVideos = function(callback){
s.knexQuery({
action: "select",
columns: "*",
table: "Cloud Videos",
where: [
['ke','=',user.ke],
['status','!=',0],
]
},function(err,videos) {
if(videos && videos[0]){
videos.forEach(function(video){
var storageType = JSON.parse(video.details).type
if(!storageType)storageType = 's3'
var videoSize = video.size / 1048576
user.cloudDiskUse[storageType].usedSpace += videoSize
user.cloudDiskUse[storageType].usedSpaceVideos += videoSize
++user.cloudDiskUse[storageType].firstCount
})
s.cloudDisksLoaded.forEach(function(storageType){
var firstCount = user.cloudDiskUse[storageType].firstCount
s.systemLog(user.mail+' : '+lang.startUpText1+' : '+firstCount,storageType,user.cloudDiskUse[storageType].usedSpace)
delete(user.cloudDiskUse[storageType].firstCount)
})
}
callback()
})
}
var loadCloudTimelapseFrames = function(callback){
s.knexQuery({
action: "select",
columns: "*",
table: "Cloud Timelapse Frames",
where: [
['ke','=',user.ke],
]
},function(err,frames) {
if(frames && frames[0]){
frames.forEach(function(frame){
var storageType = JSON.parse(frame.details).type
if(!storageType)storageType = 's3'
var frameSize = frame.size / 1048576
user.cloudDiskUse[storageType].usedSpace += frameSize
user.cloudDiskUse[storageType].usedSpaceTimelapseFrames += frameSize
})
}
callback()
})
}
loadCloudVideos(function(){
loadCloudTimelapseFrames(function(){
s.group[user.ke].cloudDiskUse = user.cloudDiskUse
callback()
})
})
}
var loadAddStorageDiskUseForUser = function(user,data,callback){
var videos = data.videos
var timelapseFrames = data.timelapseFrames
var files = data.files
var userDetails = JSON.parse(user.details)
var userAddStorageData = s.parseJSON(userDetails.addStorage) || {}
var currentStorageNumber = 0
var readStorageArray = function(){
var storage = s.listOfStorage[currentStorageNumber]
if(!storage){
//done all checks, move on to next user
callback()
return
}
var path = storage.value
if(path === ''){
++currentStorageNumber
readStorageArray()
return
}
var storageId = path
var storageData = userAddStorageData[storageId] || {}
if(!s.group[user.ke].addStorageUse[storageId])s.group[user.ke].addStorageUse[storageId] = {}
var storageIndex = s.group[user.ke].addStorageUse[storageId]
storageIndex.name = storage.name
storageIndex.path = path
storageIndex.usedSpace = 0
storageIndex.sizeLimit = parseFloat(storageData.limit) || parseFloat(userDetails.size) || 10000
var usedSpaceVideos = 0
var usedSpaceTimelapseFrames = 0
var usedSpaceFilebin = 0
if(videos && videos[0]){
videos.forEach(function(video){
if(video.details.dir === storage.value){
usedSpaceVideos += video.size
}
})
}
if(timelapseFrames && timelapseFrames[0]){
timelapseFrames.forEach(function(frame){
if(video.details.dir === storage.value){
usedSpaceTimelapseFrames += frame.size
}
})
}
if(files && files[0]){
files.forEach(function(file){
if(video.details.dir === storage.value){
usedSpaceFilebin += file.size
}
})
}
storageIndex.usedSpace = (usedSpaceVideos + usedSpaceTimelapseFrames + usedSpaceFilebin) / 1048576
storageIndex.usedSpaceVideos = usedSpaceVideos / 1048576
storageIndex.usedSpaceFilebin = usedSpaceFilebin / 1048576
storageIndex.usedSpaceTimelapseFrames = usedSpaceTimelapseFrames / 1048576
s.systemLog(user.mail+' : '+path+' : '+videos.length,storageIndex.usedSpace)
++currentStorageNumber
readStorageArray()
}
readStorageArray()
}
var loadAdminUsers = function(callback){
//get current disk used for each isolated account (admin user) on startup
s.knexQuery({
action: "select",
columns: "*",
table: "Cloud Timelapse Frames",
table: "Users",
where: [
['ke','=',user.ke],
['details','NOT LIKE','%"sub"%']
]
},function(err,frames) {
if(frames && frames[0]){
frames.forEach(function(frame){
var storageType = JSON.parse(frame.details).type
if(!storageType)storageType = 's3'
var frameSize = frame.size / 1048576
user.cloudDiskUse[storageType].usedSpace += frameSize
user.cloudDiskUse[storageType].usedSpaceTimelapseFrames += frameSize
})
}
callback()
})
}
loadCloudVideos(function(){
loadCloudTimelapseFrames(function(){
s.group[user.ke].cloudDiskUse = user.cloudDiskUse
callback()
})
})
}
var loadAddStorageDiskUseForUser = function(user,data,callback){
var videos = data.videos
var timelapseFrames = data.timelapseFrames
var files = data.files
var userDetails = JSON.parse(user.details)
var userAddStorageData = s.parseJSON(userDetails.addStorage) || {}
var currentStorageNumber = 0
var readStorageArray = function(){
var storage = s.listOfStorage[currentStorageNumber]
if(!storage){
//done all checks, move on to next user
callback()
return
}
var path = storage.value
if(path === ''){
++currentStorageNumber
readStorageArray()
return
}
var storageId = path
var storageData = userAddStorageData[storageId] || {}
if(!s.group[user.ke].addStorageUse[storageId])s.group[user.ke].addStorageUse[storageId] = {}
var storageIndex = s.group[user.ke].addStorageUse[storageId]
storageIndex.name = storage.name
storageIndex.path = path
storageIndex.usedSpace = 0
storageIndex.sizeLimit = parseFloat(storageData.limit) || parseFloat(userDetails.size) || 10000
var usedSpaceVideos = 0
var usedSpaceTimelapseFrames = 0
var usedSpaceFilebin = 0
if(videos && videos[0]){
videos.forEach(function(video){
if(video.details.dir === storage.value){
usedSpaceVideos += video.size
}
})
}
if(timelapseFrames && timelapseFrames[0]){
timelapseFrames.forEach(function(frame){
if(video.details.dir === storage.value){
usedSpaceTimelapseFrames += frame.size
}
})
}
if(files && files[0]){
files.forEach(function(file){
if(video.details.dir === storage.value){
usedSpaceFilebin += file.size
}
})
}
storageIndex.usedSpace = (usedSpaceVideos + usedSpaceTimelapseFrames + usedSpaceFilebin) / 1048576
storageIndex.usedSpaceVideos = usedSpaceVideos / 1048576
storageIndex.usedSpaceFilebin = usedSpaceFilebin / 1048576
storageIndex.usedSpaceTimelapseFrames = usedSpaceTimelapseFrames / 1048576
s.systemLog(user.mail+' : '+path+' : '+videos.length,storageIndex.usedSpace)
++currentStorageNumber
readStorageArray()
}
readStorageArray()
}
var loadAdminUsers = function(callback){
//get current disk used for each isolated account (admin user) on startup
s.knexQuery({
action: "select",
columns: "*",
table: "Users",
where: [
['details','NOT LIKE','%"sub"%']
]
},function(err,users) {
if(users && users[0]){
users.forEach(function(user){
checkedAdminUsers[user.ke] = user
})
var loadLocalDiskUse = function(callback){
var count = users.length
var countFinished = 0
},function(err,users) {
if(users && users[0]){
users.forEach(function(user){
s.loadGroup(user)
s.loadGroupApps(user)
loadedAccounts.push(user.ke)
loadDiskUseForUser(user,function(){
++countFinished
if(countFinished === count){
callback()
}
checkedAdminUsers[user.ke] = user
})
var loadLocalDiskUse = function(callback){
var count = users.length
var countFinished = 0
users.forEach(function(user){
s.loadGroup(user)
s.loadGroupApps(user)
loadedAccounts.push(user.ke)
loadDiskUseForUser(user,function(){
++countFinished
if(countFinished === count){
callback()
}
})
})
}
var loadCloudDiskUse = function(callback){
var count = users.length
var countFinished = 0
users.forEach(function(user){
loadCloudDiskUseForUser(user,function(){
++countFinished
if(countFinished === count){
callback()
}
})
})
}
loadLocalDiskUse(function(){
loadCloudDiskUse(function(){
callback()
})
})
}else{
s.processReady()
}
var loadCloudDiskUse = function(callback){
var count = users.length
var countFinished = 0
users.forEach(function(user){
loadCloudDiskUseForUser(user,function(){
++countFinished
if(countFinished === count){
callback()
}
})
})
}
loadLocalDiskUse(function(){
loadCloudDiskUse(function(){
callback()
})
})
}
config.userHasSubscribed = false
var checkSubscription = function(callback){
var subscriptionFailed = function(){
console.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
console.error('This Install of Shinobi is NOT Activated')
console.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
s.systemLog('This Install of Shinobi is NOT Activated')
console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
console.log('https://licenses.shinobi.video/subscribe')
}
if(config.subscriptionId && config.subscriptionId !== 'sub_XXXXXXXXXXXX'){
var url = 'https://licenses.shinobi.video/subscribe/check?subscriptionId=' + config.subscriptionId
request(url,{
method: 'GET',
timeout: 30000
}, function(err,resp,body){
var json = s.parseJSON(body)
if(err)console.log(err,json)
var hasSubcribed = json && !!json.ok
config.userHasSubscribed = hasSubcribed
callback(hasSubcribed)
if(config.userHasSubscribed){
s.systemLog('This Install of Shinobi is Activated')
if(!json.expired){
s.systemLog(`This License expires on ${json.timeExpires}`)
}
}else{
subscriptionFailed()
}
})
}else{
s.processReady()
subscriptionFailed()
callback(false)
}
})
}
config.userHasSubscribed = false
var checkSubscription = function(callback){
var subscriptionFailed = function(){
console.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
console.error('This Install of Shinobi is NOT Activated')
console.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
s.systemLog('This Install of Shinobi is NOT Activated')
console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
console.log('https://licenses.shinobi.video/subscribe')
}
if(config.subscriptionId && config.subscriptionId !== 'sub_XXXXXXXXXXXX'){
var url = 'https://licenses.shinobi.video/subscribe/check?subscriptionId=' + config.subscriptionId
request(url,{
method: 'GET',
timeout: 30000
}, function(err,resp,body){
var json = s.parseJSON(body)
if(err)console.log(err,json)
var hasSubcribed = json && !!json.ok
config.userHasSubscribed = hasSubcribed
callback(hasSubcribed)
if(config.userHasSubscribed){
s.systemLog('This Install of Shinobi is Activated')
if(!json.expired){
s.systemLog(`This License expires on ${json.timeExpires}`)
}
}else{
subscriptionFailed()
}
})
}else{
subscriptionFailed()
callback(false)
//check disk space every 20 minutes
if(config.autoDropCache===true){
setInterval(function(){
exec('echo 3 > /proc/sys/vm/drop_caches',{detached: true})
},60000*20)
}
}
//check disk space every 20 minutes
if(config.autoDropCache===true){
setInterval(function(){
exec('echo 3 > /proc/sys/vm/drop_caches',{detached: true})
},60000*20)
}
if(config.childNodes.mode !== 'child'){
//master node - startup functions
//hourly check to see if sizePurge has failed to unlock
//checks to see if request count is the number of monitors + 10
s.checkForStalePurgeLocks()
//run prerequsite queries, load users and monitors
//sql/database connection with knex
s.databaseEngine = require('knex')(s.databaseOptions)
//run prerequsite queries
s.preQueries()
setTimeout(() => {
//check for subscription
checkSubscription(function(){
//check terminal commander
checkForTerminalCommands(function(){
//load administrators (groups)
loadAdminUsers(function(){
//load monitors (for groups)
loadMonitors(function(){
//check for orphaned videos
checkForOrphanedVideos(async () => {
s.processReady()
if(config.childNodes.mode !== 'child'){
//master node - startup functions
//hourly check to see if sizePurge has failed to unlock
//checks to see if request count is the number of monitors + 10
s.checkForStalePurgeLocks()
//run prerequsite queries, load users and monitors
//sql/database connection with knex
s.databaseEngine = require('knex')(s.databaseOptions)
//run prerequsite queries
s.preQueries()
setTimeout(() => {
//check for subscription
checkSubscription(function(){
//check terminal commander
checkForTerminalCommands(function(){
//load administrators (groups)
loadAdminUsers(function(){
//load monitors (for groups)
loadMonitors(function(){
//check for orphaned videos
checkForOrphanedVideos(async () => {
s.processReady()
})
})
})
})
})
})
},1500)
}
},1500)
}
})
}

View File

@ -57,7 +57,9 @@ module.exports = function(s,config,lang,io){
//SSL options
var wellKnownDirectory = s.mainDirectory + '/web/.well-known'
if(fs.existsSync(wellKnownDirectory))app.use('/.well-known',express.static(wellKnownDirectory))
config.sslEnabled = false
if(config.ssl&&config.ssl.key&&config.ssl.cert){
config.sslEnabled = true
config.ssl.key=fs.readFileSync(s.checkRelativePath(config.ssl.key),'utf8')
config.ssl.cert=fs.readFileSync(s.checkRelativePath(config.ssl.cert),'utf8')
if(config.ssl.port === undefined){

View File

@ -12,6 +12,10 @@ var proxy = httpProxy.createProxyServer({})
var ejs = require('ejs');
var fileupload = require("express-fileupload");
module.exports = function(s,config,lang,app,io){
const {
ptzControl,
setPresetForCurrentPosition
} = require('./control/ptz.js')(s,config,lang,app,io)
if(config.productType === 'Pro'){
var LdapAuth = require('ldapauth-fork');
}
@ -1453,7 +1457,6 @@ module.exports = function(s,config,lang,app,io){
videoRowCaches[cacheName] = videoRow
clearTimeout(videoRowCacheTimeouts[cacheName])
videoRowCacheTimeouts[cacheName] = setTimeout(() => {
console.log('clear cache',cacheName)
delete(videoRowCaches[cacheName])
},60000)
}
@ -1656,16 +1659,25 @@ module.exports = function(s,config,lang,app,io){
app.get(config.webPaths.apiPrefix+':auth/control/:ke/:id/:direction', function (req,res){
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){
s.cameraControl(req.params,function(msg){
s.userLog({
if(req.params.direction === 'setHome'){
setPresetForCurrentPosition({
id: req.params.id,
ke: req.params.ke,
},{
msg: msg,
direction: req.params.direction,
},(response) => {
res.end(s.prettyPrint(response))
})
res.end(s.prettyPrint(msg))
});
}else{
ptzControl(req.params,function(msg){
s.userLog({
id: req.params.id,
ke: req.params.ke,
},{
msg: msg,
direction: req.params.direction,
})
res.end(s.prettyPrint(msg))
})
}
},res,req);
})
/**

View File

@ -13,9 +13,6 @@
position: relative;
height: 120px;
width: 120px;
background: #b7b7b7;
border-radius: 50%;
box-shadow: inset 0 0 1px rgba(120, 120, 120, 0.6), inset 0 2px 2px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.4);
}
.PTZ_controls .control {
position: absolute;
@ -23,9 +20,10 @@
.PTZ_controls .pad .control {
height: 30px;
width: 30px;
background: #636363;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(60, 60, 60, 0.2), 0 0 0 4px rgba(60, 60, 60, 0.2);
background: #101f54;
box-shadow: 0 0 15px rgba(0,0,0,0.4);
border-radius: 2px;
cursor: pointer;
}
.PTZ_controls .zoom_in{
top: 0;
@ -44,25 +42,29 @@
right: 0;
}
.PTZ_controls .pad .top {
top: 15px;
left: 50%;
margin: 0 0 0 -15px;
top: 10px;
border-radius: 10px 10px 50px 50px;
}
.PTZ_controls .pad .left {
top: 45px;
left: 15px;
left: 10px;
border-radius: 10px 50px 50px 10px;
}
.PTZ_controls .pad .right {
top: 45px;
right: 15px;
right: 10px;
border-radius: 50px 10px 10px 50px;
}
.PTZ_controls .pad .control.right:before {
transform: rotate(90deg) translate(-3px, -5px);
}
.PTZ_controls .pad .bottom {
bottom: 15px;
left: 50%;
margin: 0 0 0 -15px;
bottom: 10px;
border-radius: 50px 50px 10px 10px;
}
/* Overlap the other controls to hide box-shadow */
.PTZ_controls .pad .middle {
@ -72,18 +74,6 @@
top: 43px;
left: 50%;
margin: 0 0 0 -17px;
box-shadow: none;
border-radius: 3px;
}
.PTZ_controls .pad .middle:after {
position: absolute;
top: 50%;
left: 50%;
margin: -35% 0 0 -35%;
content: '';
background: #636363;
height: 70%;
width: 70%;
border-radius: 100%;
box-shadow: inset 0 0 2px rgba(120, 120, 120, 0.6), inset 0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 2px rgba(240, 240, 240, 0.2);
border-radius: 50%;
background: #1f396c;
}

View File

@ -3,7 +3,7 @@ $.ccio={
mon:{},
useUTC: <%- config.useUTC || false %>,
definitions: <%-JSON.stringify(define)%>,
libURL: location.search === '?assemble=1' ? location.pathname + '/' : '<%-window.libURL%>',
libURL: location.search === '?p2p=1' ? location.pathname + '/' : '<%-window.libURL%>',
isAppleDevice: navigator.userAgent.match(/(iPod|iPhone|iPad)/)||(navigator.userAgent.match(/(Safari)/)&&!navigator.userAgent.match('Chrome'))
};
<% if(config.DropboxAppKey){ %>
@ -154,6 +154,7 @@ $(document).ready(function(e){
function onFullScreenChange() {
var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement;
if(!fullscreenElement){
$('.videoPlayer-detection-info').removeClass('hide')
$('.fullscreen').removeClass('fullscreen')
setTimeout(function(){
$('canvas.stream-element').resize();

View File

@ -456,8 +456,23 @@ $(document).ready(function(e){
});
break;
case'control':
e.a=e.e.attr('control')
$.ccio.cx({f:'monitor',ff:'control',direction:e.a,id:e.mid,ke:e.ke},user)
var switchChosen = e.e.attr('control')
switch(switchChosen){
case'setHome':
$.get(getApiPrefix() + '/control' + '/' + $user.ke + '/' + e.mid + '/setHome',function(data){
console.log(data)
})
break;
default:
$.ccio.cx({
f: 'monitor',
ff: 'control',
direction: switchChosen,
id: e.mid,
ke: e.ke
},user)
break;
}
break;
case'videos_table':case'calendar':case'video_grid'://call videos table or calendar or video grid
$.vidview.launcher=$(this);
@ -685,23 +700,27 @@ $(document).ready(function(e){
if(e.e.length>0){
e.e.remove()
}else{
var html = '<div class="PTZ_controls">'
html += '<div class="pad">'
html += '<div class="control top" monitor="control" control="up"></div>'
html += '<div class="control left" monitor="control" control="left"></div>'
html += '<div class="control right" monitor="control" control="right"></div>'
html += '<div class="control bottom" monitor="control" control="down"></div>'
html += '<div class="control middle" monitor="control" control="center"></div>'
html += '</div>'
html += '<div class="btn-group btn-group-sm btn-group-justified">'
html += '<a title="'+lang['Zoom In']+'" class="zoom_in btn btn-default" monitor="control" control="zoom_in"><i class="fa fa-search-plus"></i></a>'
html += '<a title="'+lang['Zoom Out']+'" class="zoom_out btn btn-default" monitor="control" control="zoom_out"><i class="fa fa-search-minus"></i></a>'
html += '</div>'
html += '<div class="btn-group btn-group-sm btn-group-justified">'
html += '<a title="'+lang['Enable Nightvision']+'" class="nv_enable btn btn-default" monitor="control" control="enable_nv"><i class="fa fa-moon-o"></i></a>'
html += '<a title="'+lang['Disable Nightvision']+'" class="nv_disable btn btn-default" monitor="control" control="disable_nv"><i class="fa fa-sun-o"></i></a>'
html += '</div>'
html += '</div>'
var html = `<div class="PTZ_controls">
<div class="pad">
<div class="control top" monitor="control" control="up"></div>
<div class="control left" monitor="control" control="left"></div>
<div class="control right" monitor="control" control="right"></div>
<div class="control bottom" monitor="control" control="down"></div>
<div class="control middle" monitor="control" control="center"></div>
</div>
<div class="btn-group btn-group-sm btn-group-justified">
<a title="${lang['Zoom In']}" class="zoom_in btn btn-default" monitor="control" control="zoom_in"><i class="fa fa-search-plus"></i></a>
<a title="${lang['Zoom Out']}" class="zoom_out btn btn-default" monitor="control" control="zoom_out"><i class="fa fa-search-minus"></i></a>
</div>
<div class="btn-group btn-group-sm btn-group-justified">
<a title="${lang['Enable Nightvision']}" class="nv_enable btn btn-default" monitor="control" control="enable_nv"><i class="fa fa-moon-o"></i></a>
<a title="${lang['Disable Nightvision']}" class="nv_disable btn btn-default" monitor="control" control="disable_nv"><i class="fa fa-sun-o"></i></a>
</div>
${$.parseJSON($.ccio.mon[$user.ke + e.mid + $user.auth_token].details,{}).is_onvif === '1' ? `
<div class="btn-group btn-group-sm btn-group-justified">
<a title="${lang['Set Home Position (ONVIF-only)']}" class="btn btn-default" monitor="control" control="setHome"><i class="fa fa-h-square"></i> ${lang['Set Home']}</a>
</div>` : ``}
</div>`
e.p.append(html)
}
break;

View File

@ -611,6 +611,7 @@ $(document).ready(function(e){
$('body')
.on('dblclick','.videoPlayer',function(){
var el = $(this)
$('.videoPlayer-detection-info').addClass('hide')
$.ccio.init('fullscreen',this)
})
.on('click','[data-monitor]',function(){

View File

@ -277,7 +277,7 @@ $.ccio.globalWebsocket=function(d,user){
if($.ccio.op().jpeg_on===true){
$.ccio.init('jpegMode',$.ccio.mon[d.ke+d.id+user.auth_token]);
}else{
if(location.search === '?assemble=1'){
if(location.search === '?p2p=1'){
var path = '/socket.io'
}else{
var path = tool.checkCorrectPathEnding(location.pathname)+'socket.io'
@ -302,7 +302,6 @@ $.ccio.globalWebsocket=function(d,user){
uid: user.uid,
ke: d.ke,
id: d.id,
subscriptionId: subscriptionId,
// channel: channel
})
if(!$.ccio.mon[d.ke+d.id+user.auth_token].ctx||$.ccio.mon[d.ke+d.id+user.auth_token].ctx.length===0){
@ -690,7 +689,7 @@ $.ccio.globalWebsocket=function(d,user){
break;
}
}
if(location.search === '?assemble=1'){
if(location.search === '?p2p=1'){
$user.ws=io(location.origin,{
path : '/socket.io'
});
@ -702,16 +701,16 @@ if(location.search === '?assemble=1'){
$user.ws.on('connect',function (d){
$(document).ready(function(e){
$.ccio.init('id',$user);
if(location.search === '?assemble=1'){
$user.ws.emit('initUser',{
subscriptionId: subscriptionId,
if(location.search === '?p2p=1'){
$user.ws.emit('p2pInitUser',{
user: {
ke: $user.ke,
mail: $user.mail,
auth_token: $user.auth_token,
details: $user.details,
uid: $user.uid,
}
},
machineId: machineId
})
}else{
$.ccio.cx({f:'init',ke:$user.ke,auth:$user.auth_token,uid:$user.uid})

View File

@ -86,7 +86,7 @@
</div>
</div>
<script>
var adminApiPrefix = "<%=originalURL%><%=config.webPaths.adminApiPrefix%>"
var adminApiPrefix = location.search === '?p2p=1' ? location.pathname + '/' : "<%=originalURL%><%=config.webPaths.adminApiPrefix%>"
</script>
<% include blocks/confirm.ejs %>
<% include blocks/subpermissions.ejs %>
@ -104,7 +104,7 @@
<script><% include ../libs/js/bootstrap-table.min.js %></script>
<script>
$.ccio={subs:{}};$.ls=localStorage;
if(location.search === '?assemble=1'){
if(location.search === '?p2p=1'){
$.ccio.ws=io(location.origin,{
path : '/socket.io'
});
@ -115,7 +115,7 @@ if(location.search === '?assemble=1'){
}
$.ccio.cx=function(x){if(!x.ke){x.ke=$user.ke;};if(!x.uid){x.uid=$user.uid;};return $.ccio.ws.emit('a',x)}
$.ccio.ws.on('connect',function(d){
$.ccio.cx({f:'init',auth:$user.auth_token});
$.ccio.cx({f:'init',auth:$user.auth_token,machineId: `<%- config.machineId %>`});
})
PNotify.prototype.options.styling = "fontawesome";
$.ccio.ws.on('f',function(d){
@ -179,7 +179,7 @@ $.aN.e.submit(function(e){
e.preventDefault();
e.s = $.aN.e.serializeObject()
e.m = $('#msg').empty()
$.post('<%=originalURL%><%=config.webPaths.adminApiPrefix%>'+$user.auth_token+'/accounts/'+$user.ke+'/register',{data:e.s},function(d){
$.post(adminApiPrefix + $user.auth_token+'/accounts/'+$user.ke+'/register',{data:e.s},function(d){
if(d.msg){
e.m.text(d.msg)
}
@ -197,7 +197,7 @@ $.sU.e.on('click','.delete',function(e){
var html = 'Do you want to delete <b>'+subAccountEmail+'</b>? You cannot recover this account.'
$.confirm.body.html(html)
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
$.post('<%=originalURL%><%=config.webPaths.adminApiPrefix%>'+$user.auth_token+'/accounts/'+$user.ke+'/delete',{
$.post(adminApiPrefix + $user.auth_token+'/accounts/'+$user.ke+'/delete',{
uid: subAccountUid,
mail: subAccountEmail
},function(data){})
@ -269,7 +269,7 @@ $.pR.e.on('change','[monitor]',function(e){
$.pR.f.submit(function(e){
e.preventDefault()
var form = $(this).serializeObject()
$.post('<%=originalURL%><%=config.webPaths.adminApiPrefix%>'+$user.auth_token+'/accounts/'+$user.ke+'/edit',{
$.post(adminApiPrefix + $user.auth_token+'/accounts/'+$user.ke+'/edit',{
uid: $.pR.user,
mail: $.ccio.subs[$.pR.user].mail,
data: form

View File

@ -22,4 +22,4 @@
if(!string){string=''}
return string.replace(/'/g,"\\'")
}%>
<script>var subscriptionId = '<%- config.subscriptionId || 'notActivated' %>'</script>
<script>var machineId = '<%- config.machineId || 'noMachineIdSet' %>'</script>

View File

@ -213,7 +213,7 @@ $.aN.f.submit(function(e){
webPath = 'editAdmin'
postData.account = $.aN.selected
}
$.post('<%=originalURL%><%=config.webPaths.superApiPrefix%>'+$user.sessionKey+'/accounts/'+webPath,postData,function(data){
$.post(superApiPrefix + $user.sessionKey+'/accounts/'+webPath,postData,function(data){
console.log(data)
if(data.ok === true){
$.aN.e.modal('hide')
@ -295,7 +295,7 @@ $.aC.e.on('click','.delete',function(e){
e.html='Do you want to delete <b>'+e.account.mail+'</b>? You cannot recover this account. Files will remain in the filesystem. If you choose to create an account with the same Group Key it will have the previous events activated in that account.'
$.confirm.body.html(e.html)
$.confirm.click({title:'Delete',class:'btn-danger'},function(){
$.post('<%=originalURL%><%=config.webPaths.superApiPrefix%>'+$user.sessionKey+'/accounts/deleteAdmin',{
$.post(superApiPrefix + $user.sessionKey+'/accounts/deleteAdmin',{
account : e.account,
// "deleteSubAccounts" : "1",
// "deleteMonitors" : "1",

View File

@ -33,7 +33,7 @@
a {cursor:pointer}
</style>
<script>
var superApiPrefix = "<%=originalURL%><%=config.webPaths.superApiPrefix%>"
var superApiPrefix = location.search === '?p2p=1' ? location.pathname + '/' : "<%=originalURL%><%=config.webPaths.superApiPrefix%>"
var shinobiConfig = <%- JSON.stringify(plainConfig) %>
</script>
<% customAutoLoad.superLibsCss.forEach(function(lib){ %>
@ -173,7 +173,7 @@ switch($user.lang){
})
break;
}
if(location.search === '?assemble=1'){
if(location.search === '?p2p=1'){
$.ccio.ws=io(location.origin,{
path : '/socket.io'
});
@ -184,7 +184,7 @@ if(location.search === '?assemble=1'){
}
$.ccio.cx=function(x){return $.ccio.ws.emit('super',x)}
$.ccio.ws.on('connect',function(d){
$.ccio.cx({f:'init',mail:$user.mail,pass:$user.pass})
$.ccio.cx({f:'init',mail:$user.mail,pass:$user.pass,machineId: `<%- config.machineId %>`})
})
$.ccio.ws.on('f',function(d){
switch(d.f){