From bcf8d0eaf9b04d677d4d4083167d90f2abb515f0 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Thu, 11 Apr 2019 11:37:40 -0400 Subject: #806 support --- www/js/NVR.js | 1271 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 647 insertions(+), 624 deletions(-) (limited to 'www/js/NVR.js') diff --git a/www/js/NVR.js b/www/js/NVR.js index 80b953fd..2f30df48 100644 --- a/www/js/NVR.js +++ b/www/js/NVR.js @@ -192,6 +192,9 @@ angular.module('zmApp.controllers') 'montageReviewCollapse': true, 'objectDetectionFilter': false, 'enableEventRefresh': true, + 'lastEventCheckTimes':{}, + 'enableMontageOverlays': true + }; @@ -597,930 +600,949 @@ angular.module('zmApp.controllers') return 0; } - //-------------------------------------------------------------------------- - // Banner display of messages - //-------------------------------------------------------------------------- - function displayBanner(mytype, mytext, myinterval, mytimer) { + function _checkInitSanity(loginData) { + // old version hacks for new variables - var contentBannerInstance = - $ionicContentBanner.show({ - text: mytext || 'no text', - interval: myinterval || 2000, - //autoClose: mytimer || 6000, - type: mytype || 'info', - transition: 'vertical', - //cancelOnStateChange: false - }); + // always true Oct 27 2016 + loginData.persistMontageOrder = true; + loginData.enableh264 = true; - $timeout(function () { - contentBannerInstance(); - }, mytimer || 6000); - } + if (typeof loginData.isUseBasicAuth === 'undefined') { + loginData.isUseBasicAuth = false; + loginData.basicAuthUser = ''; + loginData.basicAuthPassword = ''; + $rootScope.basicAuthHeader = ''; + $rootScope.basicAuthToken = ''; + } - function setCurrentServerMultiPortSupported(val) { - debug("Setting multi-port to:" + val); - currentServerMultiPortSupported = val; - } + if (loginData.url.indexOf('@') != -1) { + log(">> " + loginData.url); + log(">>User/Password detected in URL, changing to new auth handling..."); + loginData.isUseBasicAuth = true; - function setCurrentServerVersion(val) { - loginData.currentServerVersion = val; - setLogin(loginData); - debug("Setting server version to:" + val); - } + var components = URI.parse(loginData.url); + loginData.url = components.scheme + "://" + components.host; + if (components.port) loginData.url = loginData.url + ":" + components.port; + if (components.path) loginData.url = loginData.url + components.path; + components = URI.parse(loginData.streamingurl); + loginData.streamingurl = components.scheme + "://" + components.host; + if (components.port) loginData.streamingurl = loginData.streamingurl + ":" + components.port; + if (components.path) loginData.streamingurl = loginData.streamingurl + components.path; - return { + components = URI.parse(loginData.apiurl); + loginData.apiurl = components.scheme + "://" + components.host; + if (components.port) loginData.apiurl = loginData.apiurl + ":" + components.port; + if (components.path) loginData.apiurl = loginData.apiurl + components.path; - insertBasicAuthToken: function () { + $rootScope.basicAuthToken = btoa(components.userinfo); + $rootScope.basicAuthHeader = 'Basic ' + $rootScope.basicAuthToken; + //console.log (">>>> SET BASIC AUTH TO " + $rootScope.basicAuthHeader); - return loginData.insertBasicAuthToken && $rootScope.basicAuthToken ? "&basicauth=" + $rootScope.basicAuthToken : ""; + var up = components.userinfo.split(':'); + loginData.basicAuthPassword = up[1]; + loginData.basicAuthUser = up[0]; + //console.log ("SETTING "+loginData.basicAuthUser+" "+loginData.basicAuthPassword); - }, + } - setCurrentServerMultiPortSupported: function (val) { - setCurrentServerMultiPortSupported(val); - }, + if (loginData.isUseBasicAuth) { + $rootScope.basicAuthToken = btoa(loginData.basicAuthUser + ':' + loginData.basicAuthPassword); + $rootScope.basicAuthHeader = 'Basic ' + $rootScope.basicAuthToken; + debug("Basic authentication detected, constructing Authorization Header"); - setCurrentServerVersion: function (val) { - setCurrentServerVersion(val); - }, + // console.log ("BASIC AUTH SET TO:"+$rootScope.basicAuthHeader); + } - getCurrentServerMultiPortSupported: function () { - return (currentServerMultiPortSupported); - }, - isMultiPortDisabled: function () { - return loginData.disableSimulStreaming; - }, + if (typeof loginData.enableAlarmCount === 'undefined') { + debug("enableAlarmCount does not exist, setting to true"); + loginData.enableAlarmCount = true; + } - getCurrentServerVersion: function () { - return (loginData.currentServerVersion); - }, + if (typeof loginData.onTapScreen == 'undefined') { + loginData.onTapScreen = $translate.instant('kTapMontage'); + } + if (loginData.onTapScreen != $translate.instant('kTapMontage') && + loginData.onTapScreen != $translate.instant('kTapEvents') && + loginData.onTapScreen != $translate.instant('kTapLiveMonitor')) { + log("Invalid onTap setting found, resetting. I got " + loginData.onTapScreen); + loginData.onTapScreen = $translate.instant('kMontage'); + } - //------------------------------------------------------------- - // used by various controllers to log messages to file - //------------------------------------------------------------- + if (typeof loginData.minAlarmCount === 'undefined') { + debug("minAlarmCount does not exist, setting to true"); + loginData.minAlarmCount = 1; + } - migrationComplete: function () { - migrationComplete = true; - }, + if (typeof loginData.montageSize == 'undefined') { + debug("montageSize does not exist, setting to 2 (2 per col)"); + loginData.montageSize = 2; + } - isEmpty: function (obj) { - return isEmpty(obj); - }, + if (typeof loginData.useNphZms == 'undefined') { + debug("useNphZms does not exist. Setting to true"); + loginData.useNphZms = true; + } - log: function (val, type) { - var logtype = 'info'; - if (type != undefined) - logtype = type; - log(val, logtype); + if (typeof loginData.useNphZmsForEvents == 'undefined') { + debug("useNphZmsForEvents does not exist. Setting to true"); + loginData.useNphZmsForEvents = true; + } - }, + if (typeof loginData.forceImageModePath == 'undefined') { + debug("forceImageModePath does not exist. Setting to false"); + loginData.forceImageModePath = false; + } - debug: function (val) { + if (typeof loginData.reachability == 'undefined') { + debug("reachability does not exist. Setting to true"); + loginData.reachability = true; + } - debug(val); - }, - evaluateTappedNotification: function () { + // force it - this may not be the problem + loginData.reachability = true; - var state = ""; - var stateParams1 = {}; - var stateParams2 = {}; + // and now, force enable it + loginData.useNphZms = true; + loginData.useNphZmsForEvents = true; - debug("Inside evaluateNotifications"); + if (typeof loginData.packMontage == 'undefined') { + debug("packMontage does not exist. Setting to false"); + loginData.packMontage = false; + } - if ($rootScope.tappedNotification == 2) { // url launch - debug("Came via app url launch with mid=" + $rootScope.tappedMid); - debug("Came via app url launch with eid=" + $rootScope.tappedEid); + if (typeof loginData.forceNetworkStop == 'undefined') { + debug("forceNetwork does not exist. Setting to false"); + loginData.forceNetworkStop = false; + } + if (typeof loginData.enableLogs == 'undefined') { + debug("enableLogs does not exist. Setting to true"); + loginData.enableLogs = true; + } - if (parseInt($rootScope.tappedMid) > 0) { - debug("Going to live view "); - state = "app.monitors"; + if (typeof loginData.defaultPushSound == 'undefined') { + debug("defaultPushSound does not exist. Setting to false"); + loginData.defaultPushSound = false; + } - } else if (parseInt($rootScope.tappedEid) > 0) { - debug("Going to events with EID=" + $rootScope.tappedEid); - state = "app.events"; - stateParams1 = { - "id": 0, - "playEvent": true - }; - stateParams2 = { - reload: true - }; - } + //console.log("INIT SIMUL=" + loginData.disableSimulStreaming); + //console.log("INIT PLATFORM IS=" + $rootScope.platformOS); + if (typeof loginData.disableSimulStreaming == 'undefined') { - } // 2 - else if ($rootScope.tappedNotification == 1) // push - { + loginData.disableSimulStreaming = false; + //console.log("INIT DISABLING SIMUL:" + loginData.disableSimulStreaming); + } - debug("Came via push tap. onTapScreen=" + loginData.onTapScreen); - if (loginData.onTapScreen == $translate.instant('kTapMontage')) { - debug("Going to montage"); - state = "app.montage"; + if (typeof loginData.exitOnSleep == 'undefined') { + debug("exitOnSleep does not exist. Setting to false"); + loginData.exitOnSleep = false; + } + if (typeof loginData.enableBlog == 'undefined') { + debug("enableBlog does not exist. Setting to true"); + loginData.enableBlog = true; - } else if (loginData.onTapScreen == $translate.instant('kTapEvents')) { - debug("Going to events"); - state = "app.events"; - stateParams1 = { - "id": 0, - "playEvent": true - }; + } - } else // we go to live - { - debug("Going to live view "); - state = "app.monitors"; + if (typeof loginData.packeryPositionsArray == 'undefined') { + debug("packeryPositionsArray does not exist. Setting to empty"); + loginData.packeryPositionsArray = {}; - } - } - $rootScope.tappedNotification = 0; - return [state, stateParams1, stateParams2]; - }, + } - setLastUpdateCheck: function (val) { - lastUpdateCheck = val; - localforage.setItem("lastUpdateCheck", lastUpdateCheck); - }, - getLastUpdateCheck: function () { - return lastUpdateCheck; - }, + if (typeof loginData.packeryPositions == 'undefined') { + debug("packeryPositions does not exist. Setting to empty"); + loginData.packeryPositions = ""; - setLatestBlogPostChecked: function (val) { - //console.log(">>>>>>>>>>>> Setting blog date: " + val); - latestBlogPostChecked = val; - localforage.setItem("latestBlogPostChecked", latestBlogPostChecked); - }, + } - getLatestBlogPostChecked: function () { - return latestBlogPostChecked; - }, + if (typeof loginData.EHpackeryPositions == 'undefined') { + debug("EHpackeryPositions does not exist. Setting to empty"); + loginData.EHpackeryPositions = ""; + } + if (typeof loginData.packerySizes == 'undefined') { + debug("packerySizes does not exist. Setting to empty"); + loginData.packerySizes = ""; - // This function is called when the app is ready to run - // sets up various variables - // including persistent login data for the ZM apis and portal - // The reason I need both is because as of today, there is no way - // to access images using the API and they are authenticated via - // the ZM portal authentication, which is pretty messy. But unless - // the ZM authors fix this and streamline the access of images - // from APIs, I don't have an option - - + } - // used when an empty server profile is created - getDefaultLoginObject: function () { - return angular.copy(defaultLoginData); - }, + if (typeof loginData.use24hr == 'undefined') { + debug("use24hr does not exist. Setting to false"); + loginData.use24hr = false; - getReachableConfig: function (skipFirst) { - var d = $q.defer(); - if (loginData.serverName == "") { - log("Reachable: No server name configured, likely first use?"); - d.reject("No servers"); - return d.promise; - } + } - var chainURLs = []; - var savedLoginData = angular.copy(loginData); + if (typeof timelineModalGraphType == 'undefined') { + debug("timeline graph type not set. Setting to all"); + loginData.timelineModalGraphType = $translate.instant('kGraphAll'); + //console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + loginData.timelineModalGraphType); + } - //log ("Making sure " + loginData.serverName + " is reachable..."); - var tLd = serverGroupList[loginData.serverName]; - if (skipFirst && tLd.fallbackConfiguration) { - tLd = serverGroupList[tLd.fallbackConfiguration]; - if (!tLd) { - d.reject("No available severs"); - loginData = savedLoginData; - return d.promise; + if (typeof loginData.resumeDelay == 'undefined') { + debug("resumeDelay does not exist. Setting to 0"); + loginData.resumeDelay = 0; - } - } + } + // override resumeDelay - it was developed on a wrong assumption + loginData.resumeDelay = 0; - var keepBuilding = true; - while (keepBuilding == true && tLd) { - if (arrayObjectIndexOf(chainURLs, tLd.url + "/index.php?view=console", "url") == -1 && tLd.url !== undefined && tLd.url != '') // no loop - { - log("Adding to chain stack: " + tLd.serverName + ">" + tLd.url); - chainURLs.push({ - url: tLd.url + "/index.php?view=console", - server: tLd.serverName - }); - log("Fallback of " + tLd.serverName + " is " + tLd.fallbackConfiguration); - if (tLd.fallbackConfiguration) { - tLd = serverGroupList[tLd.fallbackConfiguration]; - if (tLd === undefined) { - // This can happen if the fallback profile was deleted - log("Looks like a server object was deleted, but is still in fallback"); - keepBuilding = false; - } - } else { - log("reached end of chain loop"); - } - } else { - log("detected loop when " + tLd.serverName + " fallsback to " + tLd.fallbackConfiguration); - keepBuilding = false; - } - } + if (typeof loginData.montageHistoryQuality == 'undefined') { + debug("montageHistoryQuality does not exist. Setting to 50"); + loginData.montageHistoryQuality = "50"; - //contactedServers.push(loginData.serverName); - findFirstReachableUrl(chainURLs).then(function (firstReachableUrl) { - d.resolve(firstReachableUrl); - // also make sure loginData points to this now + } - loginData = angular.copy(serverGroupList[firstReachableUrl.server]); - setLogin(loginData); - //$localstorage.set("defaultServerName",firstReachableUrl.server); - log("Based on reachability, first serverName will be " + firstReachableUrl.server); - //console.log("set login Data to " + JSON.stringify(loginData)); + if (typeof loginData.vibrateOnPush == 'undefined') { + debug("vibrate on push not found, setting to true"); + loginData.vibrateOnPush = true; - return d.promise; - // OK: do something with firstReachableUrl - }, function () { - d.reject("No servers reachable"); - loginData = savedLoginData; - return d.promise; - // KO: no url could be reached - }); + } - function arrayObjectIndexOf(myArray, searchTerm, property) { - for (var i = 0, len = myArray.length; i < len; i++) { - if (myArray[i][property] === searchTerm) - return i; - } - return -1; - } + if (typeof loginData.isFullScreen == 'undefined') { - function findFirstReachableUrl(urls) { - if (urls.length > 0 && $rootScope.userCancelledAuth != true) { - $ionicLoading.show({ - template: $translate.instant('kTrying') + ' ' + urls[0].server - }); - log("Reachability test.." + urls[0].url); + loginData.isFullScreen = false; - if (loginData.reachability) { + } - //console.log ("************* AUGH"); - var hDelay = loginData.enableSlowLoading ? zm.largeHttpTimeout : zm.httpTimeout; - return $http({ - method: 'GET', - timeout: hDelay, - url: urls[0].url - }).then(function () { - log("Success: reachability on " + urls[0].url); - $ionicLoading.hide(); - return urls[0]; - }, function (err) { - log("Failed reachability on " + urls[0].url + " with error " + JSON.stringify(err)); - return findFirstReachableUrl(urls.slice(1)); - }); - } else { - log("Reachability is disabled in config, faking this test and returning success on " + urls[0]); - return urls[0]; - } - } else { - $ionicLoading.hide(); - return $q.reject("No reachable URL"); + if (typeof loginData.reloadInMontage == 'undefined') { - } + loginData.reloadInMontage = false; - } + } - return d.promise; + if (typeof loginData.soundOnPush == 'undefined') { + debug("sound on push not found, setting to true"); + loginData.soundOnPush = true; - }, + } - cloudSync: function () { + if (typeof loginData.cycleMonitors == 'undefined') { - var d = $q.defer(); - if (!window.cordova) { - log("Cloud settings plugin not found, skipping cloud sync..."); - d.resolve(true); - return d.promise; - } + loginData.cycleMonitors = false; - /* window.cordova.plugin.cloudsettings.enableDebug(function(){ - console.log("Debug mode enabled"); - });*/ + } - log("CloudSync: Syncing with cloud if enabled..."); + if (typeof loginData.cycleMonitorsInterval == 'undefined') { - var sgl = ""; - var decodedSgl = ""; - var dsn = ""; + loginData.cycleMonitorsInterval = 10; - localforage.getItem("serverGroupList") - .then(function (_sgl) { - sgl = _sgl; - return localforage.getItem("defaultServerName"); - }) - .then(function (_dsn) { - dsn = _dsn; - return true; - }) - .then(function () { - if (sgl && dsn) { + } - if (typeof sgl == 'string') { - log("user profile encrypted, decoding..."); - var bytes = CryptoJS.AES.decrypt(sgl.toString(), zm.cipherKey); - decodedSgl = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); + if (typeof loginData.cycleMontage == 'undefined') { - } else { - decodedSgl = sgl; - } + loginData.cycleMontage = false; + } - var loadedData = decodedSgl[dsn]; + if (typeof loginData.cycleMontageInterval == 'undefined') { - if (!isEmpty(loadedData)) { + loginData.cycleMontageInterval = 10; - if (!loadedData.saveToCloud) { - log("Cloud sync is disabled, exiting..."); - d.resolve(true); - return d.promise; } - } - log("Found valid local configuration, overwriting cloud settings..."); - //console.log (">>>>>>>>>>>>>>SAVING: " + sgl + dsn); - window.cordova.plugin.cloudsettings.save({ - 'serverGroupList': sgl, - 'defaultServerName': dsn - }, - function () { - log("local data synced with cloud..."); - d.resolve(true); - return d.promise; - }, - function (err) { - log("error syncing cloud data..." + err); - d.resolve(true); - return d.promise; - }, true); - } - // bad or missing local config - else { - log("Did not find a valid local configuration, trying cloud..."); + if (typeof loginData.enableLowBandwidth == 'undefined') { - window.cordova.plugin.cloudsettings.exists(function (exists) { + loginData.enableLowBandwidth = false; - if (exists) { - log("A cloud configuration has been found"); - window.cordova.plugin.cloudsettings.load(function (cloudData) { - //console.log("CLOUD DATA FOUND" + JSON.stringify(cloudData)); - // debug("Cloud data retrieved is:" + JSON.stringify(cloudData)); - if (cloudData && cloudData.defaultServerName && cloudData.serverGroupList) { - log("retrieved a valid cloud config with a defaultServerName of:" + cloudData.defaultServerName); - log("replacing local DB with cloud..."); - localforage.setItem('isFirstUse', false) - .then(function () { - log("cleared first use"); - return localforage.setItem("defaultServerName", cloudData.defaultServerName); - }) - .then(function () { - log("saved defaultServerName"); - return localforage.setItem("serverGroupList", cloudData.serverGroupList); - }) - .then(function () { - log("saved serverGroupList, returning from cloudSync()"); - d.resolve(true); - return d.promise; - }); + } + // wtf is wrong with this ternary? + //$rootScope.runMode = (loginData.enableLowBandwith==true)? "low": "normal"; + if (typeof loginData.autoSwitchBandwidth == 'undefined') { - } - // cloud did not have (useable)data - else { - log("Did not find a valid cloud config"); - d.resolve(true); - return d.promise; - } + loginData.autoSwitchBandwidth = false; - }); - } else { - log("Cloud data does not exist"); - d.resolve(true); - return d.promise; } - }); - } - }); + $rootScope.runMode = getBandwidth(); + log("Setting NVR init bandwidth to: " + $rootScope.runMode); + if (typeof loginData.refreshSecLowBW == 'undefined') { - return d.promise; + loginData.refreshSecLowBW = 8; - }, + } - init: function () { + if (typeof loginData.disableAlarmCheckMontage == 'undefined') { + loginData.disableAlarmCheckMontage = false; - log("ZMData init: checking for stored variables & setting up log file"); + } - localforage.getItem("latestBlogPostChecked") - .then(function (val) { - latestBlogPostChecked = val; - }, - function (err) { - latestBlogPostChecked = null; - }); + if (typeof loginData.useLocalTimeZone == 'undefined') { + loginData.useLocalTimeZone = true; - $ionicLoading.show({ - template: $translate.instant('kRetrievingProfileData'), - }); + } - localforage.getItem("serverGroupList").then(function (val) { - // decrypt it now + if (typeof loginData.fastLogin == 'undefined') { - var decodedVal; + loginData.fastLogin = true; - if (typeof val == 'string') { - log("user profile encrypted, decoding..."); - var bytes = CryptoJS.AES.decrypt(val.toString(), zm.cipherKey); - decodedVal = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); + } - } else { - log("user profile not encrypted"); - decodedVal = val; - } + if (typeof loginData.currentMontageProfile == 'undefined') { - //decodedVal = val; + loginData.currentMontageProfile = ''; - // debug("user profile retrieved:" + JSON.stringify(decodedVal)); + } - $ionicLoading.hide(); - serverGroupList = decodedVal; + if (typeof loginData.followTimeLine == 'undefined') { - var sname; - $ionicLoading.show({ - template: $translate.instant('kRetrievingProfileData'), - }); - localforage.getItem("defaultServerName") - .then(function (val) { - $ionicLoading.hide(); - //console.log ("!!!!!!!!!!!!!!!!!!default server name is " + sname); - sname = val; - // console.log("!!!!!!!!!!!!!!!!!!!Got VAL " + sname); - var loadedData = serverGroupList[sname]; - // console.log(">>>>>>>>>>> loadedData is: " + JSON.stringify(loadedData)); - if (!isEmpty(loadedData)) { - loginData = loadedData; + loginData.followTimeLine = false; - // old version hacks for new variables + } - // always true Oct 27 2016 - loginData.persistMontageOrder = true; - loginData.enableh264 = true; + if (typeof loginData.timelineScale == 'undefined') { + + loginData.timelineScale = -1; - if (typeof loginData.isUseBasicAuth === 'undefined') { - loginData.isUseBasicAuth = false; - loginData.basicAuthUser = ''; - loginData.basicAuthPassword = ''; - $rootScope.basicAuthHeader = ''; - $rootScope.basicAuthToken = ''; } - if (loginData.url.indexOf('@') != -1) { - log(">> " + loginData.url); - log(">>User/Password detected in URL, changing to new auth handling..."); - loginData.isUseBasicAuth = true; - var components = URI.parse(loginData.url); - loginData.url = components.scheme + "://" + components.host; - if (components.port) loginData.url = loginData.url + ":" + components.port; - if (components.path) loginData.url = loginData.url + components.path; + if (typeof loginData.showMontageSubMenu == 'undefined') { - components = URI.parse(loginData.streamingurl); - loginData.streamingurl = components.scheme + "://" + components.host; - if (components.port) loginData.streamingurl = loginData.streamingurl + ":" + components.port; - if (components.path) loginData.streamingurl = loginData.streamingurl + components.path; + loginData.showMontageSubMenu = false; + } - components = URI.parse(loginData.apiurl); - loginData.apiurl = components.scheme + "://" + components.host; - if (components.port) loginData.apiurl = loginData.apiurl + ":" + components.port; - if (components.path) loginData.apiurl = loginData.apiurl + components.path; - $rootScope.basicAuthToken = btoa(components.userinfo); - $rootScope.basicAuthHeader = 'Basic ' + $rootScope.basicAuthToken; - //console.log (">>>> SET BASIC AUTH TO " + $rootScope.basicAuthHeader); - var up = components.userinfo.split(':'); - loginData.basicAuthPassword = up[1]; - loginData.basicAuthUser = up[0]; - //console.log ("SETTING "+loginData.basicAuthUser+" "+loginData.basicAuthPassword); + if (typeof loginData.monSingleImageQuality == 'undefined') { + + loginData.monSingleImageQuality = 100; } - if (loginData.isUseBasicAuth) { - $rootScope.basicAuthToken = btoa(loginData.basicAuthUser + ':' + loginData.basicAuthPassword); - $rootScope.basicAuthHeader = 'Basic ' + $rootScope.basicAuthToken; - debug("Basic authentication detected, constructing Authorization Header"); + if (typeof loginData.hideArchived == 'undefined') { - // console.log ("BASIC AUTH SET TO:"+$rootScope.basicAuthHeader); + loginData.hideArchived = false; } + if (typeof loginData.videoPlaybackSpeed == 'undefined') { - if (typeof loginData.enableAlarmCount === 'undefined') { - debug("enableAlarmCount does not exist, setting to true"); - loginData.enableAlarmCount = true; - } + loginData.videoPlaybackSpeed = 1; - if (typeof loginData.onTapScreen == 'undefined') { - loginData.onTapScreen = $translate.instant('kTapMontage'); } - if (loginData.onTapScreen != $translate.instant('kTapMontage') && - loginData.onTapScreen != $translate.instant('kTapEvents') && - loginData.onTapScreen != $translate.instant('kTapLiveMonitor')) { - log("Invalid onTap setting found, resetting. I got " + loginData.onTapScreen); - loginData.onTapScreen = $translate.instant('kMontage'); - } - if (typeof loginData.minAlarmCount === 'undefined') { - debug("minAlarmCount does not exist, setting to true"); - loginData.minAlarmCount = 1; - } - if (typeof loginData.montageSize == 'undefined') { - debug("montageSize does not exist, setting to 2 (2 per col)"); - loginData.montageSize = 2; - } + if (typeof loginData.enableThumbs == 'undefined') { - if (typeof loginData.useNphZms == 'undefined') { - debug("useNphZms does not exist. Setting to true"); - loginData.useNphZms = true; - } + loginData.enableThumbs = true; - if (typeof loginData.useNphZmsForEvents == 'undefined') { - debug("useNphZmsForEvents does not exist. Setting to true"); - loginData.useNphZmsForEvents = true; } - if (typeof loginData.forceImageModePath == 'undefined') { - debug("forceImageModePath does not exist. Setting to false"); - loginData.forceImageModePath = false; - } + if (typeof loginData.enableSlowLoading == 'undefined') { + + loginData.enableSlowLoading = false; - if (typeof loginData.reachability == 'undefined') { - debug("reachability does not exist. Setting to true"); - loginData.reachability = true; } - // force it - this may not be the problem - loginData.reachability = true; + if (typeof loginData.enableStrictSSL == 'undefined') { - // and now, force enable it - loginData.useNphZms = true; - loginData.useNphZmsForEvents = true; + loginData.enableStrictSSL = false; - if (typeof loginData.packMontage == 'undefined') { - debug("packMontage does not exist. Setting to false"); - loginData.packMontage = false; } - if (typeof loginData.forceNetworkStop == 'undefined') { - debug("forceNetwork does not exist. Setting to false"); - loginData.forceNetworkStop = false; - } + if (typeof loginData.momentGridSize == 'undefined') { - if (typeof loginData.enableLogs == 'undefined') { - debug("enableLogs does not exist. Setting to true"); - loginData.enableLogs = true; - } + loginData.momentGridSize = 40; - if (typeof loginData.defaultPushSound == 'undefined') { - debug("defaultPushSound does not exist. Setting to false"); - loginData.defaultPushSound = false; } + if (typeof loginData.enableMomentSubMenu == 'undefined') { - //console.log("INIT SIMUL=" + loginData.disableSimulStreaming); - //console.log("INIT PLATFORM IS=" + $rootScope.platformOS); - if (typeof loginData.disableSimulStreaming == 'undefined') { - + loginData.enableMomentSubMenu = true; - loginData.disableSimulStreaming = false; - //console.log("INIT DISABLING SIMUL:" + loginData.disableSimulStreaming); } + if (typeof loginData.momentMonitorFilter == 'undefined') { + + loginData.momentMonitorFilter = JSON.stringify([]); - if (typeof loginData.exitOnSleep == 'undefined') { - debug("exitOnSleep does not exist. Setting to false"); - loginData.exitOnSleep = false; } - if (typeof loginData.enableBlog == 'undefined') { - debug("enableBlog does not exist. Setting to true"); - loginData.enableBlog = true; - } + if (typeof loginData.momentArrangeBy == 'undefined') { - if (typeof loginData.packeryPositionsArray == 'undefined') { - debug("packeryPositionsArray does not exist. Setting to empty"); - loginData.packeryPositionsArray = {}; + loginData.momentArrangeBy = "StartTime"; } + if (typeof loginData.insertBasicAuthToken == 'undefined') { - if (typeof loginData.packeryPositions == 'undefined') { - debug("packeryPositions does not exist. Setting to empty"); - loginData.packeryPositions = ""; + loginData.insertBasicAuthToken = false; } - if (typeof loginData.EHpackeryPositions == 'undefined') { - debug("EHpackeryPositions does not exist. Setting to empty"); - loginData.EHpackeryPositions = ""; - } + if (typeof loginData.showLiveForInProgressEvents == 'undefined') { - if (typeof loginData.packerySizes == 'undefined') { - debug("packerySizes does not exist. Setting to empty"); - loginData.packerySizes = ""; + loginData.showLiveForInProgressEvents = true; } - if (typeof loginData.use24hr == 'undefined') { - debug("use24hr does not exist. Setting to false"); - loginData.use24hr = false; - } + if (typeof loginData.loginAPISupported == 'undefined') { + + loginData.loginAPISupported = false; - if (typeof timelineModalGraphType == 'undefined') { - debug("timeline graph type not set. Setting to all"); - loginData.timelineModalGraphType = $translate.instant('kGraphAll'); - //console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + loginData.timelineModalGraphType); } - if (typeof loginData.resumeDelay == 'undefined') { - debug("resumeDelay does not exist. Setting to 0"); - loginData.resumeDelay = 0; + if (typeof loginData.montageResizeSteps == 'undefined') { + + loginData.montageResizeSteps = 5; } - // override resumeDelay - it was developed on a wrong assumption - loginData.resumeDelay = 0; - if (typeof loginData.montageHistoryQuality == 'undefined') { - debug("montageHistoryQuality does not exist. Setting to 50"); - loginData.montageHistoryQuality = "50"; + if (typeof loginData.saveToCloud == 'undefined') { + + loginData.saveToCloud = true; } - if (typeof loginData.vibrateOnPush == 'undefined') { - debug("vibrate on push not found, setting to true"); - loginData.vibrateOnPush = true; + if (typeof loginData.montageReviewCollapse == 'undefined') { + + loginData.montageReviewCollapse = true; } - if (typeof loginData.isFullScreen == 'undefined') { + if (typeof loginData.objectDetectionFilter == 'undefined') { - loginData.isFullScreen = false; + loginData.objectDetectionFilter = false; } - if (typeof loginData.reloadInMontage == 'undefined') { + if (typeof loginData.enableEventRefresh == 'undefined') { - loginData.reloadInMontage = false; + loginData.enableEventRefresh = true; } - if (typeof loginData.soundOnPush == 'undefined') { - debug("sound on push not found, setting to true"); - loginData.soundOnPush = true; + + + if (typeof loginData.lastEventCheckTimes == 'undefined') { + loginData.lastEventCheckTimes = {}; } - if (typeof loginData.cycleMonitors == 'undefined') { - loginData.cycleMonitors = false; + if (typeof loginData.enableMontageOverlays == 'undefined') { + loginData.enableMontageOverlays = true; } - if (typeof loginData.cycleMonitorsInterval == 'undefined') { + loginData.canSwipeMonitors = true; + loginData.forceImageModePath = false; + loginData.enableBlog = true; - loginData.cycleMonitorsInterval = 10; + } - } + //-------------------------------------------------------------------------- + // Banner display of messages + //-------------------------------------------------------------------------- + function displayBanner(mytype, mytext, myinterval, mytimer) { - if (typeof loginData.cycleMontage == 'undefined') { + var contentBannerInstance = + $ionicContentBanner.show({ + text: mytext || 'no text', + interval: myinterval || 2000, + //autoClose: mytimer || 6000, + type: mytype || 'info', + transition: 'vertical', + //cancelOnStateChange: false + }); - loginData.cycleMontage = false; + $timeout(function () { + contentBannerInstance(); + }, mytimer || 6000); + } - } + function setCurrentServerMultiPortSupported(val) { + debug("Setting multi-port to:" + val); + currentServerMultiPortSupported = val; + } - if (typeof loginData.cycleMontageInterval == 'undefined') { + function setCurrentServerVersion(val) { + loginData.currentServerVersion = val; + setLogin(loginData); + debug("Setting server version to:" + val); + } - loginData.cycleMontageInterval = 10; - } + return { - if (typeof loginData.enableLowBandwidth == 'undefined') { - loginData.enableLowBandwidth = false; + insertBasicAuthToken: function () { - } - // wtf is wrong with this ternary? - //$rootScope.runMode = (loginData.enableLowBandwith==true)? "low": "normal"; + return loginData.insertBasicAuthToken && $rootScope.basicAuthToken ? "&basicauth=" + $rootScope.basicAuthToken : ""; - if (typeof loginData.autoSwitchBandwidth == 'undefined') { + }, - loginData.autoSwitchBandwidth = false; + setCurrentServerMultiPortSupported: function (val) { + setCurrentServerMultiPortSupported(val); + }, - } + setCurrentServerVersion: function (val) { + setCurrentServerVersion(val); + }, - $rootScope.runMode = getBandwidth(); - log("Setting NVR init bandwidth to: " + $rootScope.runMode); - if (typeof loginData.refreshSecLowBW == 'undefined') { + getCurrentServerMultiPortSupported: function () { + return (currentServerMultiPortSupported); + }, - loginData.refreshSecLowBW = 8; + isMultiPortDisabled: function () { + return loginData.disableSimulStreaming; + }, - } + getCurrentServerVersion: function () { + return (loginData.currentServerVersion); + }, - if (typeof loginData.disableAlarmCheckMontage == 'undefined') { - loginData.disableAlarmCheckMontage = false; + //------------------------------------------------------------- + // used by various controllers to log messages to file + //------------------------------------------------------------- - } + migrationComplete: function () { + migrationComplete = true; + }, - if (typeof loginData.useLocalTimeZone == 'undefined') { + isEmpty: function (obj) { + return isEmpty(obj); + }, - loginData.useLocalTimeZone = true; + log: function (val, type) { + var logtype = 'info'; + if (type != undefined) + logtype = type; + log(val, logtype); - } + }, - if (typeof loginData.fastLogin == 'undefined') { + debug: function (val) { - loginData.fastLogin = true; + debug(val); + }, - } + evaluateTappedNotification: function () { - if (typeof loginData.currentMontageProfile == 'undefined') { + var state = ""; + var stateParams1 = {}; + var stateParams2 = {}; - loginData.currentMontageProfile = ''; + debug("Inside evaluateNotifications"); - } + if ($rootScope.tappedNotification == 2) { // url launch + debug("Came via app url launch with mid=" + $rootScope.tappedMid); + debug("Came via app url launch with eid=" + $rootScope.tappedEid); - if (typeof loginData.followTimeLine == 'undefined') { - loginData.followTimeLine = false; + if (parseInt($rootScope.tappedMid) > 0) { + debug("Going to live view "); + state = "app.monitors"; - } + } else if (parseInt($rootScope.tappedEid) > 0) { + debug("Going to events with EID=" + $rootScope.tappedEid); + state = "app.events"; + stateParams1 = { + "id": 0, + "playEvent": true + }; + stateParams2 = { + reload: true + }; - if (typeof loginData.timelineScale == 'undefined') { + } - loginData.timelineScale = -1; - } + } // 2 + else if ($rootScope.tappedNotification == 1) // push + { - if (typeof loginData.showMontageSubMenu == 'undefined') { + debug("Came via push tap. onTapScreen=" + loginData.onTapScreen); + if (loginData.onTapScreen == $translate.instant('kTapMontage')) { + debug("Going to montage"); + state = "app.montage"; - loginData.showMontageSubMenu = false; - } + } else if (loginData.onTapScreen == $translate.instant('kTapEvents')) { + debug("Going to events"); + state = "app.events"; + stateParams1 = { + "id": 0, + "playEvent": true + }; + } else // we go to live + { + debug("Going to live view "); + state = "app.monitors"; + } + } + $rootScope.tappedNotification = 0; + return [state, stateParams1, stateParams2]; + }, - if (typeof loginData.monSingleImageQuality == 'undefined') { + setLastUpdateCheck: function (val) { + lastUpdateCheck = val; + localforage.setItem("lastUpdateCheck", lastUpdateCheck); + }, - loginData.monSingleImageQuality = 100; + getLastUpdateCheck: function () { + return lastUpdateCheck; + }, - } + setLatestBlogPostChecked: function (val) { + //console.log(">>>>>>>>>>>> Setting blog date: " + val); + latestBlogPostChecked = val; + localforage.setItem("latestBlogPostChecked", latestBlogPostChecked); + }, - if (typeof loginData.hideArchived == 'undefined') { + getLatestBlogPostChecked: function () { + return latestBlogPostChecked; + }, - loginData.hideArchived = false; - } - if (typeof loginData.videoPlaybackSpeed == 'undefined') { + // This function is called when the app is ready to run + // sets up various variables + // including persistent login data for the ZM apis and portal + // The reason I need both is because as of today, there is no way + // to access images using the API and they are authenticated via + // the ZM portal authentication, which is pretty messy. But unless + // the ZM authors fix this and streamline the access of images + // from APIs, I don't have an option - loginData.videoPlaybackSpeed = 2; - } + // used when an empty server profile is created + getDefaultLoginObject: function () { + return angular.copy(defaultLoginData); + }, + + getReachableConfig: function (skipFirst) { + var d = $q.defer(); + if (loginData.serverName == "") { + log("Reachable: No server name configured, likely first use?"); + d.reject("No servers"); + return d.promise; + } + + var chainURLs = []; + var savedLoginData = angular.copy(loginData); + //log ("Making sure " + loginData.serverName + " is reachable..."); + var tLd = serverGroupList[loginData.serverName]; + if (skipFirst && tLd.fallbackConfiguration) { + tLd = serverGroupList[tLd.fallbackConfiguration]; + if (!tLd) { + d.reject("No available severs"); + loginData = savedLoginData; + return d.promise; - if (typeof loginData.enableThumbs == 'undefined') { + } + } + + var keepBuilding = true; + while (keepBuilding == true && tLd) { + if (arrayObjectIndexOf(chainURLs, tLd.url + "/index.php?view=console", "url") == -1 && tLd.url !== undefined && tLd.url != '') // no loop + { + log("Adding to chain stack: " + tLd.serverName + ">" + tLd.url); + chainURLs.push({ + url: tLd.url + "/index.php?view=console", + server: tLd.serverName + }); + log("Fallback of " + tLd.serverName + " is " + tLd.fallbackConfiguration); + if (tLd.fallbackConfiguration) { + tLd = serverGroupList[tLd.fallbackConfiguration]; + if (tLd === undefined) { + // This can happen if the fallback profile was deleted + log("Looks like a server object was deleted, but is still in fallback"); + keepBuilding = false; + } + } else { + log("reached end of chain loop"); + } + } else { + log("detected loop when " + tLd.serverName + " fallsback to " + tLd.fallbackConfiguration); + keepBuilding = false; + } + } - loginData.enableThumbs = true; + //contactedServers.push(loginData.serverName); + findFirstReachableUrl(chainURLs).then(function (firstReachableUrl) { + d.resolve(firstReachableUrl); + // also make sure loginData points to this now - } + loginData = angular.copy(serverGroupList[firstReachableUrl.server]); - if (typeof loginData.enableSlowLoading == 'undefined') { + setLogin(loginData); + //$localstorage.set("defaultServerName",firstReachableUrl.server); - loginData.enableSlowLoading = false; + log("Based on reachability, first serverName will be " + firstReachableUrl.server); + //console.log("set login Data to " + JSON.stringify(loginData)); - } + return d.promise; + // OK: do something with firstReachableUrl + }, function () { + d.reject("No servers reachable"); + loginData = savedLoginData; + return d.promise; + // KO: no url could be reached + }); + function arrayObjectIndexOf(myArray, searchTerm, property) { + for (var i = 0, len = myArray.length; i < len; i++) { + if (myArray[i][property] === searchTerm) + return i; + } + return -1; + } - if (typeof loginData.enableStrictSSL == 'undefined') { + function findFirstReachableUrl(urls) { + if (urls.length > 0 && $rootScope.userCancelledAuth != true) { + $ionicLoading.show({ + template: $translate.instant('kTrying') + ' ' + urls[0].server + }); + log("Reachability test.." + urls[0].url); - loginData.enableStrictSSL = false; + if (loginData.reachability) { - } + //console.log ("************* AUGH"); + var hDelay = loginData.enableSlowLoading ? zm.largeHttpTimeout : zm.httpTimeout; + return $http({ + method: 'GET', + timeout: hDelay, + url: urls[0].url + }).then(function () { + log("Success: reachability on " + urls[0].url); + $ionicLoading.hide(); + return urls[0]; + }, function (err) { + log("Failed reachability on " + urls[0].url + " with error " + JSON.stringify(err)); + return findFirstReachableUrl(urls.slice(1)); + }); + } else { + log("Reachability is disabled in config, faking this test and returning success on " + urls[0]); + return urls[0]; + } + } else { + $ionicLoading.hide(); + return $q.reject("No reachable URL"); - if (typeof loginData.momentGridSize == 'undefined') { + } - loginData.momentGridSize = 40; + } - } + return d.promise; - if (typeof loginData.enableMomentSubMenu == 'undefined') { + }, - loginData.enableMomentSubMenu = true; + cloudSync: function () { - } + var d = $q.defer(); + if (!window.cordova) { + log("Cloud settings plugin not found, skipping cloud sync..."); + d.resolve(true); + return d.promise; + } - if (typeof loginData.momentMonitorFilter == 'undefined') { + /* window.cordova.plugin.cloudsettings.enableDebug(function(){ + console.log("Debug mode enabled"); + });*/ - loginData.momentMonitorFilter = JSON.stringify([]); + log("CloudSync: Syncing with cloud if enabled..."); - } + var sgl = ""; + var decodedSgl = ""; + var dsn = ""; + localforage.getItem("serverGroupList") + .then(function (_sgl) { + sgl = _sgl; + return localforage.getItem("defaultServerName"); + }) + .then(function (_dsn) { + dsn = _dsn; + return true; + }) + .then(function () { + if (sgl && dsn) { - if (typeof loginData.momentArrangeBy == 'undefined') { + if (typeof sgl == 'string') { + log("user profile encrypted, decoding..."); + var bytes = CryptoJS.AES.decrypt(sgl.toString(), zm.cipherKey); + decodedSgl = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); - loginData.momentArrangeBy = "StartTime"; + } else { + decodedSgl = sgl; + } - } - if (typeof loginData.insertBasicAuthToken == 'undefined') { + var loadedData = decodedSgl[dsn]; - loginData.insertBasicAuthToken = false; + if (!isEmpty(loadedData)) { + if (!loadedData.saveToCloud) { + log("Cloud sync is disabled, exiting..."); + d.resolve(true); + return d.promise; } + } + log("Found valid local configuration, overwriting cloud settings..."); + //console.log (">>>>>>>>>>>>>>SAVING: " + sgl + dsn); + window.cordova.plugin.cloudsettings.save({ + 'serverGroupList': sgl, + 'defaultServerName': dsn + }, + function () { + log("local data synced with cloud..."); + d.resolve(true); + return d.promise; + }, + function (err) { + log("error syncing cloud data..." + err); + d.resolve(true); + return d.promise; + }, true); + } + // bad or missing local config + else { + log("Did not find a valid local configuration, trying cloud..."); - if (typeof loginData.showLiveForInProgressEvents == 'undefined') { - - loginData.showLiveForInProgressEvents = true; - - } + window.cordova.plugin.cloudsettings.exists(function (exists) { + if (exists) { + log("A cloud configuration has been found"); + window.cordova.plugin.cloudsettings.load(function (cloudData) { + //console.log("CLOUD DATA FOUND" + JSON.stringify(cloudData)); + // debug("Cloud data retrieved is:" + JSON.stringify(cloudData)); + if (cloudData && cloudData.defaultServerName && cloudData.serverGroupList) { + log("retrieved a valid cloud config with a defaultServerName of:" + cloudData.defaultServerName); + log("replacing local DB with cloud..."); + localforage.setItem('isFirstUse', false) + .then(function () { + log("cleared first use"); + return localforage.setItem("defaultServerName", cloudData.defaultServerName); + }) + .then(function () { + log("saved defaultServerName"); + return localforage.setItem("serverGroupList", cloudData.serverGroupList); + }) + .then(function () { + log("saved serverGroupList, returning from cloudSync()"); + d.resolve(true); + return d.promise; + }); - if (typeof loginData.loginAPISupported == 'undefined') { - loginData.loginAPISupported = false; + } + // cloud did not have (useable)data + else { + log("Did not find a valid cloud config"); + d.resolve(true); + return d.promise; + } + }); + } else { + log("Cloud data does not exist"); + d.resolve(true); + return d.promise; } + }); - if (typeof loginData.montageResizeSteps == 'undefined') { - - loginData.montageResizeSteps = 5; + } + }); - } - if (typeof loginData.saveToCloud == 'undefined') { + return d.promise; - loginData.saveToCloud = true; + }, - } + checkInitSanity: function (l) { + _checkInitSanity(l); + }, + init: function () { - if (typeof loginData.montageReviewCollapse == 'undefined') { + log("ZMData init: checking for stored variables & setting up log file"); - loginData.montageReviewCollapse = true; + localforage.getItem("latestBlogPostChecked") + .then(function (val) { + latestBlogPostChecked = val; + }, + function (err) { + latestBlogPostChecked = null; + }); - } - if (typeof loginData.objectDetectionFilter == 'undefined') { + $ionicLoading.show({ + template: $translate.instant('kRetrievingProfileData'), + }); - loginData.objectDetectionFilter = false; + localforage.getItem("serverGroupList").then(function (val) { + // decrypt it now - } + var decodedVal; - if (typeof loginData.enableEventRefresh == 'undefined') { + if (typeof val == 'string') { + log("user profile encrypted, decoding..."); + var bytes = CryptoJS.AES.decrypt(val.toString(), zm.cipherKey); + decodedVal = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); - loginData.enableEventRefresh = true; + } else { + log("user profile not encrypted"); + decodedVal = val; + } - } + //decodedVal = val; + // debug("user profile retrieved:" + JSON.stringify(decodedVal)); - loginData.canSwipeMonitors = true; - loginData.forceImageModePath = false; - loginData.enableBlog = true; + $ionicLoading.hide(); + serverGroupList = decodedVal; + var sname; + $ionicLoading.show({ + template: $translate.instant('kRetrievingProfileData'), + }); + localforage.getItem("defaultServerName") + .then(function (val) { + $ionicLoading.hide(); + //console.log ("!!!!!!!!!!!!!!!!!!default server name is " + sname); + sname = val; + // console.log("!!!!!!!!!!!!!!!!!!!Got VAL " + sname); + var loadedData = serverGroupList[sname]; + // console.log(">>>>>>>>>>> loadedData is: " + JSON.stringify(loadedData)); + if (!isEmpty(loadedData)) { + loginData = loadedData; + _checkInitSanity(loginData); log("NVR init retrieved store loginData"); } else { log("defaultServer configuration NOT found. Keeping login at defaults"); @@ -2336,7 +2358,7 @@ angular.module('zmApp.controllers') monitors[i].Monitor.streamingURL = st; monitors[i].Monitor.baseURL = baseurl; monitors[i].Monitor.controlURL = controlURL; - + monitors[i].Monitor.recordingURL = controlURL; debug("Storing baseurl=" + baseurl + " streamingURL=" + st + " recordingURL=" + controlURL); //console.log ("** Streaming="+st+" **base="+baseurl); @@ -2382,6 +2404,7 @@ angular.module('zmApp.controllers') monitors[i].Monitor.streamingURL = st2; monitors[i].Monitor.controlURL = controlURL; + monitors[i].Monitor.recordingURL = controlURL; //debug ("Streaming URL for Monitor " + monitors[i].Monitor.Id + " is " + monitors[i].Monitor.streamingURL ); //console.log ("NO SERVER MATCH CONSTRUCTED STREAMING PATH="+st2); monitors[i].Monitor.baseURL = loginData.url; -- cgit v1.2.3