diff --git a/bak/app/css/aether_native_app_v3.css b/bak/app/css/aether_native_app_v3.css new file mode 100644 index 0000000..d8aff7e --- /dev/null +++ b/bak/app/css/aether_native_app_v3.css @@ -0,0 +1,28 @@ +body { + /* min-height: 100%; + height: 100%; + max-height: 100%; */ + + margin: .1em; + padding: .1em; +} + +section#Main-Body { + /* outline: solid thin red; */ + + /* min-height: 100%; + height: 100%; + max-height: 100%; */ +} + +section#Main-Nav-Menu { + min-height: 100%; + height: 100%; + max-height: 100%; +} + +section#Main-Content { + min-height: 100%; + height: 100%; + max-height: 100%; +} \ No newline at end of file diff --git a/bak/app/img/favicon.ico b/bak/app/img/favicon.ico new file mode 100755 index 0000000..cf49949 Binary files /dev/null and b/bak/app/img/favicon.ico differ diff --git a/bak/app/img/osit_logo_100.png b/bak/app/img/osit_logo_100.png new file mode 100644 index 0000000..1dfa88d Binary files /dev/null and b/bak/app/img/osit_logo_100.png differ diff --git a/bak/app/img/osit_logo_150.png b/bak/app/img/osit_logo_150.png new file mode 100644 index 0000000..64f2487 Binary files /dev/null and b/bak/app/img/osit_logo_150.png differ diff --git a/bak/app/img/osit_logo_32.png b/bak/app/img/osit_logo_32.png new file mode 100644 index 0000000..cf49949 Binary files /dev/null and b/bak/app/img/osit_logo_32.png differ diff --git a/bak/app/index.html b/bak/app/index.html new file mode 100644 index 0000000..9b6a2aa --- /dev/null +++ b/bak/app/index.html @@ -0,0 +1,223 @@ + + + + + + + One Sky IT's Aether App + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Site-Nav-Menu
+ + + +
System-Notifications (and Site-Notifications)
+ +
+
+ + + + +
System-Debug
+ + + + + + + + + + + + + + + diff --git a/bak/app/js/aether_native_app_v3.js b/bak/app/js/aether_native_app_v3.js new file mode 100644 index 0000000..55faf7e --- /dev/null +++ b/bak/app/js/aether_native_app_v3.js @@ -0,0 +1,552 @@ +'use strict'; +const os = require('os'); +const path = require('path'); +const fs = require('fs'); +const fs_promises = require('node:fs/promises'); +const child_process = require('child_process'); +const { ipcRenderer } = require('electron'); + +// import psList from 'ps-list'; +// const ps_list = require('ps-list'); + +let home_directory = require('os').homedir(); +console.log('Home: '+home_directory); + +let tmp_directory = require('os').tmpdir(); +console.log('Temporary: '+tmp_directory); + +let config = null; + +exports.load_config = function () { + console.log('*** Electron framework: load_config() ***'); + + let cwd = process.cwd(); + console.log(`CWD: ${cwd}`); + + try { + if (cwd == '/') { + cwd = home_directory; + } + console.log('Reading directory...'); + let directory_list = fs_promises.readdir(cwd).then(function (read_dir_result) { + console.log('Got contents:'); + for (let file of read_dir_result) { + console.log(file); + } + }); + } catch (err) { + console.error(err); + } + + // let home_directory = require('os').homedir(); + // console.log('Home: '+home_directory); + + // let tmp_directory = require('os').tmpdir(); + // console.log('Temporary: '+tmp_directory); + + // let config = null; + let config_directory = null; + // let default_config_path = path.join(process.cwd(),'config.json.default'); + let default_config_path = 'config.json.default'; + console.log(default_config_path); + let config_path = null; + + // Set the config path for macOS or Linux + if (os.platform == 'darwin') { + config_directory = path.join(home_directory, 'Library/Application Support/OSIT'); + console.log('macOS config directory: '+config_directory); + } else if (os.platform == 'linux') { + config_directory = path.join(home_directory, '.config/OSIT'); + console.log('Linux config directory: '+config_directory); + } + + // Look for the config file and copy the default if not found. + if (fs.existsSync(config_directory)) { + console.log('Config directory found: '+config_directory); + } else { + fs.mkdirSync(config_directory); + console.log('Config directory created: '+config_directory); + + //default_config_path = path.join(process.cwd(),'config.json.default'); + // config_path = path.join(config_directory, 'config.json'); + // fs.copyFileSync(default_config_path, config_path); + // console.log('Default config file copied: '+config_directory); + } + + config_path = path.join(config_directory, 'config.json'); + + // Attempt to open the config file. The preferred location is based on the OS's config directory. + if (fs.existsSync(config_path)) { + console.log(`Config file (config.json) found under ${config_directory}`); + } else if (!fs.existsSync(config_path) && fs.existsSync(default_config_path)) { + fs.copyFileSync(default_config_path, config_path); + console.log('Default config file copied: '+config_directory); + + // config = JSON.parse(fs.readFileSync(config_path)); + // console.log('Config file read.'); + } else if (fs.existsSync(path.join(cwd, 'config.json'))) { + //fs.copyFileSync(default_config_path, config_path); + //console.log('Default config file copied: '+config_directory); + + console.log(`Config file (config.json) not found under ${config_directory}. Using config in CWD. ${cwd}`); + config_path = path.join(cwd, 'config.json'); + + console.log(`Config file (config.json) not found under ${config_directory}. Using config in CWD. ${cwd}`); + found_config_path = path.join(cwd, 'config.json'); + + fs.copyFileSync(found_config_path, config_path); + console.log(`Found config file copied: ${config_directory}`); + } else if (fs.existsSync(path.join(cwd, 'config.json.default'))) { + console.log(`Config file (config.json) not found under ${config_directory} or CWD. Using default config in CWD. ${cwd}`); + default_config_path = path.join(cwd, 'config.json.default'); + + fs.copyFileSync(default_config_path, config_path); + console.log(`Default config file copied: ${config_directory}`); + } else { + console.log('Can not find a config file.'); + + return false; + } + + config = JSON.parse(fs.readFileSync(config_path)); + console.log('Config file read.'); + + config.home_directory = home_directory; // From the OS platform + config.tmp_directory = tmp_directory; // From the OS platform + + config.app_root_path = config.app_root_path.replace('[home]', home_directory); + config.app_root_path = config.app_root_path.replace('[tmp]', tmp_directory); + console.log(config.app_root_path); + + config.host_file_cache_path = config.host_file_cache_path.replace('[home]', home_directory); + config.host_file_cache_path = config.host_file_cache_path.replace('[tmp]', tmp_directory); + console.log(config.host_file_cache_path); + // if (fs.existsSync(config.host_file_cache_path)) { + // } else { + // fs.mkdirSync(config.host_file_cache_path); + // console.log(`Host file cache directory created: ${config.host_file_cache_path}`); + // } + + config.host_file_temp_path = config.host_file_temp_path.replace('[home]', home_directory); + config.host_file_temp_path = config.host_file_temp_path.replace('[tmp]', tmp_directory); + console.log(config.host_file_temp_path); + // if (fs.existsSync(config.host_file_temp_path)) { + // } else { + // fs.mkdirSync(config.host_file_temp_path); + // console.log(`Host file temp directory created: ${config.host_file_temp_path}`); + // } + + let import_config_to_ipc_result = ipcRenderer.invoke('import_config', config).then((result) => { + console.log('IPC import config finished'); + console.log(result); + return true; + }) + + //console.log(config); + return config; +} + + +// Check for local file +// Updated 2022-05-06 +exports.check_local_file = async function ({local_file_path, filename}) { + console.log('*** Electron framework export: check_local_file() ***'); + // console.log('Check for local file'); + console.log(`Local File Path: ${local_file_path}; Filename: ${filename}`); + + let full_local_file_path = path.join(local_file_path, filename); + console.log(full_local_file_path); + + if (fs.existsSync(full_local_file_path)) { + console.log(`Local file exists: ${full_local_file_path}`); + return true; + } else { + return false; + } +} + + +// Check local hash file cache +// Updated 2022-05-06 +exports.check_hash_file_cache = async function ({host_file_cache_path, hash}) { + console.log('*** Electron framework export: check_hash_file_cache() ***'); + // console.log('Check local hash file cache'); + console.log(`Host File Cache Path: ${host_file_cache_path}; Hash: ${hash}`); + + let hash_filename = `${hash}.file`; + + let subdirectory = hash_filename.substring(0,2); + let subdirectory_path = path.join(host_file_cache_path, subdirectory); + if (fs.existsSync(subdirectory_path)) { + } else { + console.log(`Hashed file subdirectory not found in cache: ${subdirectory_path}`); + return false; + } + + let hash_file_cache_path = path.join(subdirectory_path, hash_filename); + // console.log(hash_file_cache_path); + + if (fs.existsSync(hash_file_cache_path)) { + console.log(`Hashed file exists in cache: ${hash_file_cache_path}`); + return true; + } else { + console.log(`Hashed file not found in cache: ${hash_file_cache_path}`); + return false; + } +} + + +// Download hash file to cache +// Updated 2022-05-06 +exports.download_hash_file_to_cache = async function ({host_file_cache_path, event_file_id=null, hash=null}) { + console.log('*** Electron framework export: download_hash_file_to_cache() ***'); + // console.log('Download hash file to cache'); + console.log(`Host File Cache Path: ${host_file_cache_path}; Event File ID: ${event_file_id}; Hash: ${hash}`); + + let endpoint = `/event/file/${event_file_id}/download`; + + let hash_filename = `${hash}.file`; + + let subdirectory = hash_filename.substring(0,2); + let subdirectory_path = path.join(host_file_cache_path, subdirectory); + if (fs.existsSync(subdirectory_path)) { + } else { + fs.mkdirSync(subdirectory_path); + console.log(`Subdirectory directory created: ${subdirectory_path}`); + } + + let hash_file_cache_path = path.join(subdirectory_path, hash_filename); + // console.log(hash_file_cache_path); + + let download_file_result = await ipcRenderer.invoke('download_file', api_server_base_url, endpoint, hash_file_cache_path).then((result) => { + console.log('IPC download file process finished'); + console.log(result); + return true; + }); + + // console.log(download_file_result); + // console.log('End: download_hash_file_to_cache()'); + if (download_file_result) { + console.log('File downloaded successfully'); + return true; + } else { + console.log('File was not downloaded successfully'); + return false; + } +} + + +// Open cached hash file after copying to temp directory +// Updated 2022-05-06 +exports.open_hash_file_to_temp = async function ({host_file_cache_path, hash, host_file_temp_path, filename}) { + console.log('*** Electron framework export: open_hash_file_to_temp() ***'); + // console.log('Open cached hash file after copying to temp directory'); + console.log(`Host File Cache Path: ${host_file_cache_path}; Hash: ${hash}; Host File Temp Path: ${host_file_temp_path}; Filename: ${filename}`); + + let subdirectory = hash.substring(0,2); + let subdirectory_path = path.join(host_file_cache_path, subdirectory); + if (fs.existsSync(subdirectory_path)) { + } else { + console.log(`Hashed file subdirectory not found in cache: ${subdirectory_path}`); + return false; + } + + let open_hash_file_to_temp_result = await ipcRenderer.invoke('open_hash_file_to_temp', subdirectory_path, hash, host_file_temp_path, filename).then((result) => { + console.log('IPC open hash file to temp finished'); + console.log(result); + return true; + }) + + // let result = await ipcRenderer.send('open_local_file', host_file_cache_path, hash, host_file_temp_path, filename); + // console.log(result); + + console.log(open_hash_file_to_temp_result); + console.log('End: open_hash_file_to_temp()'); + if (open_hash_file_to_temp_result) { + console.log('File opened successfully'); + return true; + } else { + console.log('File was not opened successfully'); + return false; + } +} + + +// Open local file +// Updated 2022-03-10 +exports.open_local_file = async function ({local_file_path, filename}) { + console.log('*** Electron framework export: open_local_file() ***'); + // console.log('Open local file'); + console.log(`Local File Path: ${local_file_path}; Filename: ${filename}`); + + // let full_local_file_path = path.join(local_file_path, filename); + // console.log(full_local_file_path); + + // if (fs.existsSync(full_local_file_path)) { + // console.log(`Local file exists: ${full_local_file_path}`); + // // return true; + // } else { + // return false; + // } + + let open_local_file_result = await ipcRenderer.invoke('open_local_file', local_file_path, filename).then((result) => { + console.log('IPC open local file finished'); + console.log(result); + return true; + }) + + console.log(open_local_file_result); + console.log('End: open_local_file()'); + if (open_local_file_result) { + console.log('File opened successfully'); + return true; + } else { + console.log('File was not opened successfully'); + return false; + } +} + + + + +// Check local file cache and download from server if needed. +// Updated 2022-03-09 +// exports.check_file_cache = async function ({host_file_cache_path, event_file_id, hash}) { +exports.check_file_cache = async function ({host_file_cache_path, event_file_id, hash}) { + console.log('*** Electron framework export: check_file_cache() ***'); + // console.log('Check local file cache and download from server if needed.'); + console.log(`Host File Cache Path: ${host_file_cache_path}; Event File ID: ${event_file_id}; Hash: ${hash}`); + + // NOTE: event_file_id is the event_file.id_random or event_file.event_file_id_random + let hash_filename = hash+'.file'; + + let save_path = path.join(host_file_cache_path, hash_filename); + console.log(save_path); + + if (fs.existsSync(save_path)) { + console.log('Hashed file cache already exists: '+save_path); + return true; + } else { + console.log('Hashed file not found in local cache. Downloading file: '+save_path); + let endpoint = `/event/file/${event_file_id}/download`; + let result = await ipcRenderer.send('download_file', api_server_base_url, endpoint, save_path); // Must download file using main node.js thread. + console.log(result); + + return new Promise((resolve, reject) => { + ipcRenderer.once('download_file_reply', function(event, response){ + console.log(response); + return response; + }) + resolve(true); + }); + + // await ipcRenderer.once('download_file_reply', function(event, response){ + // console.log(response); + // return response; + // }); + + // result.then(function (response) { + // console.log('Downloaded!!!???'); + // return true; + // }).catch(function (error) { + // console.log(error); + // return false; + // }); + + // return result; + + // console.log(result); + // if (result) { + // return true; + // } else { + // return false; + // } + } +} + + + +// Check local file cache and download from server if needed. Must use IPC to Main to download file. Set a Promise to wait for download_file_reply. +// Updated 2022-03-09 +async function check_file_cache({host_file_cache_path, event_file_id, hash}) { + console.log('*** Electron framework: check_file_cache() ***'); + // console.log('Check local file cache and download from server if needed.'); + console.log(`Host File Cache Path: ${host_file_cache_path}; Event File ID: ${event_file_id}; Hash: ${hash}`); + + // NOTE: event_file_id is the event_file.id_random or event_file.event_file_id_random + let hash_filename = hash+'.file'; + + let save_path = path.join(host_file_cache_path, hash_filename); + console.log(save_path); + + if (fs.existsSync(save_path)) { + console.log('Hashed file cache already exists: '+save_path); + return true; + } else { + console.log('Hashed file not found in local cache. Downloading file: '+save_path); + let endpoint = `/event/file/${event_file_id}/download`; + let result = await ipcRenderer.send('download_file', api_server_base_url, endpoint, save_path); // Must download file using main node.js thread. + console.log(result); + + return new Promise((resolve, reject) => { + ipcRenderer.once('download_file_reply', function(event, response){ + console.log(response); + return response; + }) + resolve(true); + }); + + // await ipcRenderer.once('download_file_reply', function(event, response){ + // console.log(response); + // return response; + // }); + + // result.then(function (response) { + // console.log('Downloaded!!!???'); + // return true; + // }).catch(function (error) { + // console.log(error); + // return false; + // }); + + // return result; + + // console.log(result); + // if (result) { + // return true; + // } else { + // return false; + // } + } +} + +// IPC to Main: Open local file cache if available. Copy to temp directory with given filename first. +// Updated 2022-03-09 +async function open_local_file({host_file_cache_path, hash, host_file_temp_path, filename}) { + console.log('*** Electron framework: open_local_file() ***'); + // console.log('Open local file cache if available. Copy to temp directory with given filename first.'); + console.log(`Host File Cache Path: ${host_file_cache_path}; Hash: ${hash}; Host File Temp Path: ${host_file_temp_path}; Filename: ${filename}`); + + console.log(host_file_cache_path); + console.log(hash); + console.log(filename); + + let result = await ipcRenderer.send('open_local_file', host_file_cache_path, hash, host_file_temp_path, filename); + console.log(result); + + return true; +} + + +exports.check_file_cache_and_open_local_file = async function ({host_file_cache_path, event_file_id, hash, host_file_temp_path, filename}) { + console.log('*** Electron framework: check_file_cache_and_open_local_file() ***'); + console.log('Checking the local file cache against the remote server and then opening the local file.'); + + let check_file_cache_result = check_file_cache({host_file_cache_path: host_file_cache_path, event_file_id: event_file_id, hash: hash}); + console.log(check_file_cache_result); + + if (check_file_cache_result) { + let open_local_file_result = open_local_file({host_file_cache_path: host_file_cache_path, hash: hash, host_file_temp_path: host_file_temp_path, filename: filename}); + console.log(open_local_file_result); + + return open_local_file_result; + } + + ipcRenderer.once('download_file_reply', function(event, response){ + console.log(response); + + let open_local_file_result = open_local_file({host_file_cache_path: host_file_cache_path, hash: hash, host_file_temp_path: host_file_temp_path, filename: filename}); + console.log(open_local_file_result); + + return open_local_file_result; + }) +} + + +// Kill processes +// Updated 2022-05-06 +exports.kill_processes = async function ({process_name = null}) { + console.log('*** Electron framework export: kill_processes() ***'); + console.log(process_name); // process_name or grep pattern + + let command = ''; + if (os.platform == 'darwin') { + // command = `osascript -e 'quit app "${process_name}" saving no'`; + command = `osascript -e 'quit application "${process_name}" saving no'`; + } else { + command = `pkill ${process_name}`; + } + + child_process.exec(command, (err, stdout, stdin) => { + if (err) throw err; + console.log(stdout); + }); + console.log('Killed processes?'); + + // let command = `ps -aux | grep ${process_name}`; + // child_process.exec(command, (err, stdout, stdin) => { + // if (err) throw err; + // console.log(stdout); + // }); + + // console.log(await psList()); + // console.log(await ps_list()); + + // let signal = 'SIGTERM'; // 'SIGTERM', 'SIGINT', 'SIGHUP' + + // process.kill(pid, signal); + + // process.kill(pid, 0); // Special case test if process exists + return true; +} + + +// Run raw osascript +// Updated 2022-05-07 +exports.run_osascript = async function ({command=null, interactive=false, language=null, flags='h', program_file=null}) { + console.log('*** Electron framework export: kill_processes() ***'); + console.log(command); + + if (os.platform == 'darwin') { + } else { + console.log('Not available for this platform. macOS (darwin) only.'); + return false; + } + + let osascript_str = ''; + + if (Array.isArray(command)) { + console.log('List of command strings'); + let commands_str = ''; + for (let i = 0; i < command.length; i++) { + commands_str += `-e '${command[i]}'`; + } + osascript_str = `osascript ${commands_str}` + + } else if (typeof command === 'string') { + console.log('Single command string'); + osascript_str = `osascript -e '${command}'`; + } else { + return false; + } + + if (language) { + console.log(`Language: ${language}`); + osascript_str = `${osascript_str} -l ${language}`; + } + + if (flags) { + console.log(`Flags: ${flags}`); + osascript_str = `${osascript_str} -s ${flags}`; + } + + console.log(`OSA Script String: ${osascript_str}`); + child_process.exec(osascript_str, (err, stdout, stdin) => { + if (err) throw err; + console.log(stdout); + console.log(stdin); + }); + + console.log('Finished'); + return true; +} \ No newline at end of file diff --git a/bak/app/static/images/favicon.ico b/bak/app/static/images/favicon.ico new file mode 100755 index 0000000..cf49949 Binary files /dev/null and b/bak/app/static/images/favicon.ico differ diff --git a/bak/app/static/images/oneskyit_logo.png b/bak/app/static/images/oneskyit_logo.png new file mode 100644 index 0000000..64f2487 Binary files /dev/null and b/bak/app/static/images/oneskyit_logo.png differ diff --git a/bak/app/static/images/site_background.png b/bak/app/static/images/site_background.png new file mode 100644 index 0000000..fe4b84f Binary files /dev/null and b/bak/app/static/images/site_background.png differ diff --git a/bak/app/static/images/site_background.svg b/bak/app/static/images/site_background.svg new file mode 100644 index 0000000..14e8c60 --- /dev/null +++ b/bak/app/static/images/site_background.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/bak/app/static/images/site_background.webp b/bak/app/static/images/site_background.webp new file mode 100644 index 0000000..e5a15b5 Binary files /dev/null and b/bak/app/static/images/site_background.webp differ diff --git a/bak/app/static/launcher.reset b/bak/app/static/launcher.reset new file mode 100644 index 0000000..3a0225e --- /dev/null +++ b/bak/app/static/launcher.reset @@ -0,0 +1 @@ +launcher reset diff --git a/bak/app/static/test.txt b/bak/app/static/test.txt new file mode 100644 index 0000000..5eb252b --- /dev/null +++ b/bak/app/static/test.txt @@ -0,0 +1 @@ +test txt diff --git a/app/svelte/build/aether_layout.css b/bak/app/svelte/build/aether_layout.css similarity index 100% rename from app/svelte/build/aether_layout.css rename to bak/app/svelte/build/aether_layout.css diff --git a/app/svelte/build/aether_layout_flow.css b/bak/app/svelte/build/aether_layout_flow.css similarity index 100% rename from app/svelte/build/aether_layout_flow.css rename to bak/app/svelte/build/aether_layout_flow.css diff --git a/app/svelte/build/aether_layout_grid.css b/bak/app/svelte/build/aether_layout_grid.css similarity index 100% rename from app/svelte/build/aether_layout_grid.css rename to bak/app/svelte/build/aether_layout_grid.css diff --git a/app/svelte/build/bundle.css b/bak/app/svelte/build/bundle.css similarity index 100% rename from app/svelte/build/bundle.css rename to bak/app/svelte/build/bundle.css diff --git a/app/svelte/build/bundle.js b/bak/app/svelte/build/bundle.js similarity index 100% rename from app/svelte/build/bundle.js rename to bak/app/svelte/build/bundle.js diff --git a/app/svelte/build/bundle.js.map b/bak/app/svelte/build/bundle.js.map similarity index 100% rename from app/svelte/build/bundle.js.map rename to bak/app/svelte/build/bundle.js.map diff --git a/app/svelte/build/reloading.css b/bak/app/svelte/build/reloading.css similarity index 100% rename from app/svelte/build/reloading.css rename to bak/app/svelte/build/reloading.css diff --git a/config.json.default.bak b/config.json.default.bak deleted file mode 100644 index 0f64f81..0000000 --- a/config.json.default.bak +++ /dev/null @@ -1,42 +0,0 @@ -{ - "api_secret_key": "YWAAk39H2qH0edK6lPH0yg", - "api_remote_base_url": "https://api.oneskyit.com", - "api_local_base_url": "http://api.localhost:5001", - "remote_db_server": "db.oneskyit.com", - "remote_db_port": "3306", - "remote_db_name": "onesky_ams_test", - "remote_db_username": "username_here", - "remote_db_password": "password_here", - "local_db_server": "db.localhost", - "local_db_port": "3306", - "local_db_name": "onesky_ams_test", - "local_db_username": "username_here", - "local_db_password": "password_here", - "local_file_cache":"file_cache", - "display_arrangement": "mirror_and_extend", - "display_builtin_resolution": "", - "display_builtin_refresh": "", - "display_builtin_rotation": "", - "display_external_resolution": "", - "display_external_refresh": "", - "display_external_rotation": "", - "audio_out_volume": "", - "audio_in_volume": "", - "fps": 30, - "show_cursor": true, - "highlight_clicks": false, - "screen_id": null, - "audio_device_id": null, - "known_builtin_screen_ids": [69732032, 69733952, 69733248], - "known_builtin_audio_device_ids": [ "AppleHDAEngineInput:1B,0,1,0:1", "BuiltInMicrophoneDevice" ], - "video_codec": "h264", - "recordings_path": "[home]/recordings", - "base_filename": "recording", - "aperture_bin_path": null, - "recording_start_datetime": "2019-10-12 01:01:01Z", - "recording_stop_datetime": "2019-10-31 23:59:59Z", - "recordings_datetime": [ - { "start": "2019-10-11T09:50:00.00", "stop": "2019-10-11T10:15:00.00" }, - { "start": "2019-10-11T10:50:00.00", "stop": "2019-10-11T11:15:00.00" } - ] -}