Merge tag 'dey-3.2-r3.1' into master

Digi Embedded Yocto 3.2-r3.1

Signed-off-by: Javier Viguera <javier.viguera@digi.com>
This commit is contained in:
Javier Viguera 2022-07-01 10:02:43 +02:00
commit df1d1b70ec
74 changed files with 19037 additions and 3 deletions

View File

@ -31,8 +31,8 @@ The I2C connections for this example depend on the running platform:
- **ConnectCore 6UL SBC Pro**: I2C connector of the board (J28).
- VCC: Pin 3
- GND: Pin 6
- I2C-2 SDA: Pin 2
- I2C-2 SCL: Pin 1
- I2C-1 SDA: Pin 2
- I2C-1 SCL: Pin 1
- **ConnectCore 6UL SBC Express**: Expansion connector of the board (J8).
- VCC: Pin 1
- GND: Pin 6

View File

@ -18,7 +18,6 @@
#include <libgen.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

View File

@ -0,0 +1,40 @@
ConnectCore Demo Application
============================
The ConnectCore demo allows you to monitor and manage your ConnectCore device
from a friendly front-end.
You can monitor device data, such as memory, CPU temperature and statistics, or
network interfaces traffic. It allows you to toggle a user LED, reboot the
device, and upgrade its firmware, as well as test its multimedia capabilities.
This demo is compatible with:
* ConnectCore 8M Mini Development Kit
* ConnectCore 8M Nano Development Kit
* ConnectCore 8X SBC Pro
Running the application
-----------------------
The application is included in `dey-image-webkit` image. For more information,
go to:
* [ConnectCore demo for ConnectCore 8M Mini](https://www.digi.com/resources/documentation/digidocs/embedded/dey/latest/cc8mmini/yocto_c_ccdemo-intro)
* [ConnectCore demo for ConnectCore 8M Nano](https://www.digi.com/resources/documentation/digidocs/embedded/dey/latest/cc8mnano/yocto_c_ccdemo-intro)
* [ConnectCore demo for ConnectCore 8X](https://www.digi.com/resources/documentation/digidocs/embedded/dey/latest/cc8x/yocto_c_ccdemo-intro)
License
-------
Copyright 2022, Digi International Inc.
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appears in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,820 @@
<!DOCTYPE html>
<html>
<head>
<title>
Digi Demo - Dashboard
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./static/css/stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="./static/css/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
<link href="./static/css/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/css/bootstrap-slider.min.css" rel="stylesheet">
<link href="./static/css/fontawesome5.15.4/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="./static/css/general.css">
<link rel="stylesheet" href="./static/css/toastr.css">
<!-- JS, Popper.js, and jQuery -->
<script src="./static/js/code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="./static/js/stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script src="./static/js/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/bootstrap-slider.min.js"></script>
<script type="text/javascript" src="./static/js/common.js"></script>
<script type="text/javascript" src="./static/js/devices.js"></script>
<script type="text/javascript" src="./static/js/jquery.pjax.js"></script>
<script type="text/javascript" src="./static/js/jquery.matchHeight-min.js"></script>
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
</head>
<body>
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<div class="nav-container">
<a id="banner-link" class="navbar-brand align-middle" href="/">
<div class="d-flex align-items-baseline">
<img id="banner-logo" class="banner-icon" src="./static/images/Digi_logo_banner.png">
<p id="banner-text">ConnectCore Demo</p>
</div>
</a>
<div class="nav-right-container">
<div>
<img src="./static/images/board.png" class="device-title-img" title="Device">
</div>
<div id="device-name">DEY DEVICE</div>
</div>
</nav>
<div class="bg-light" id="body-row">
<!-- Sidebar https://www.codeply.com/go/3e0RAjccRO/bootstrap-4-collapsing-sidebar-menu# -->
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block">
<!-- d-* hides the Sidebar in smaller devices. Its items can be kept on the Navbar 'Menu' -->
<div id="sidebar-contents">
<!-- Bootstrap List Group -->
<ul id="sections" data-pjax class="list-group">
<li>
<a data-pjax href="index.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-tachometer-alt fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Dashboard</span>
</div>
</a>
</li>
<li>
<a data-pjax href="multimedia.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-film fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Multimedia</span>
</div>
</a>
</li>
<li>
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-cog fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Management</span>
</div>
</a>
</li>
</ul>
<ul id="collapsator" class="list-group">
<a href="#top" data-toggle="sidebar-collapse" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span id="collapse-icon" class="digi-menu-icon fas fa-fw fa-lg mr-3"></span>
<span id="collapse-text" class="menu-collapsed">Collapse</span>
</div>
</a>
</ul>
</div>
</div>
<div class="container-fluid">
<div id="loading">
<img id="loading-image" src="./static/images/loading.gif" alt="Loading..." />
</div>
<div id="pjax-container">
<input type="file" id="file_to_upload" style="display:none"/>
<div class="row justify-content-lg-center">
<div class="col-lg-12 col-xl-12">
<div class="column main-row">
<div class="card dashboard-device-card">
<div class="card-body">
<div id="dashboard_device" class="dashboard-device">
<div id="loading_popup" class="popup popup-loading shadow">
<img class="popup-item" src="./static/images/loading.gif" alt="Loading..." />
<div id="loading_popup_message" class="popup-text">Loading device...</div>
</div>
<div id="info_popup" class="popup popup-info shadow d-none">
<div id="info_popup_title" class="popup-title">Error</div>
<div id="info_popup_message" class="popup-text">-</div>
</div>
<div id="confirm_dialog" class="confirm-dialog d-none">
<div class="device-card-header">
<span class="fas fa-question-circle fa-lg mr-2"></span>
<span id="confirm_dialog_title"></span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="showPopup(ID_LOADING_WRAPPER, ID_CONFIRM_DIALOG, false)"></div>
</div>
<div id="confirm_dialog_message" class="confirm-dialog-message"></div>
<div class="confirm-dialog-buttons-container">
<div id="confirm_dialog_no_button" class="device-card-button confirm-dialog-button">No</div>
<div id="confirm_dialog_yes_button" class="device-card-button confirm-dialog-button">Yes</div>
</div>
</div>
<div id="loading_wrapper" class="loading-wrapper element-grayed">
<div id="device_board" class="device-board">
<div class="dashboard-top-panel shadow-sm">
<div id="device_toolbar" class="device-toolbar">
<div id="platform_name" class="platform-name"></div>
<div id="device-button-show-info" class="device-button" onclick="setInfoPanelsVisible(true)">
<img id="device-button-show-info-img" src="./static/images/show_info.png" width="32px" data-toggle="tooltip" data-placement="bottom" title="Show all information panels">
</div>
<div id="device-button-hide-info" class="device-button" onclick="setInfoPanelsVisible(false)">
<img id="device-button-hide-info-img" src="./static/images/hide_info.png" width="32px" data-toggle="tooltip" data-placement="bottom" title="Hide all information panels">
</div>
</div>
<div id="board_image_container" class="device-board-container">
<center><img id="board_image" class="device-board-image" width="" src=""/></center>
</div>
</div>
<div id="device_info" class="device-info">
<div id="device_info_panel_header" class="device-card-header" style="cursor: pointer;" onclick="toggleDeviceInfoVisibility()">
<span class="fas fa-info-circle fa-lg mr-2"></span>
<span>Device information</span>
<div id="device_info_toggle_button" class="fas fa-caret-down fa-lg device-card-header-button"></div>
</div>
<div id="device_info_panel_container" class="device-card-content shadow-sm" style="display: none;">
<table>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Serial number:</span>
</td>
<td>
<span id="serial_number" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">DEY version:</span>
</td>
<td>
<span id="dey_version" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Kernel version:</span>
</td>
<td>
<span id="kernel_version" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">U-Boot version:</span>
</td>
<td>
<span id="uboot_version" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Module variant:</span>
</td>
<td>
<span id="module_variant" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Board variant:</span>
</td>
<td>
<span id="board_variant" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Board ID:</span>
</td>
<td>
<span id="board_id" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">MCA FW version:</span>
</td>
<td>
<span id="mca_fw_version" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">MCA HW version:</span>
</td>
<td>
<span id="mca_hw_version" class="device-card-content-value">-</span>
</td>
</tr>
</table>
</div>
</div>
<div id="device-error" class="device-error"></div>
<div id="help_panel_area" class="help-panel-area fas fa-question fa-2x d-flex align-items-center justify-content-center" onclick="toggleHelpPopup()"></div>
<div id="help_panel" class="help-panel">
<span id="help_panel_arrow" class="help-arrow"></span>
<div class="help-panel-content">
<p><b>Welcome to the device dashboard.</b></p>
<span>From this page you can explore and interact with the different device components. Hover and click the green-highlighted panels to discover the board interfaces and specific enabled functionality.</span>
<div class="help-panel-button" onclick="setHelpPopupVisible(false)">Got it!</div>
</div>
</div>
<div id="cpu_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('cpu')">
<span class="panel-tooltip-text">CPU stats</span>
<span id="cpu_panel_icon" class="fas fa-microchip panel-area-icon"></span>
</div>
<div id="cpu_panel" class="device-card cpu-panel shadow-sm">
<span id="cpu_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-microchip fa-lg mr-2"></span>
<span>CPU stats</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('cpu', false)"></div>
</div>
<div class="device-card-content">
<div class="cpu-info">
<table>
<tr style="vertical-align: baseline;">
<td>
<span class="device-card-content-text">Usage:</span>
</td>
<td>
<span id="cpu_load" class="device-card-content-value">-</span> %
</td>
</tr>
<tr style="vertical-align: baseline;">
<td>
<span class="device-card-content-text">Uptime:</span>
</td>
<td>
<span id="cpu_uptime" class="device-card-content-value">-</span>
</td>
</tr>
<tr style="vertical-align: baseline;">
<td>
<span class="device-card-content-text">Frequency:</span>
</td>
<td>
<span id="cpu_frequency" class="device-card-content-value">-</span> MHz
</td>
</tr>
<tr style="vertical-align: baseline;">
<td>
<span class="device-card-content-text">Temperature:</span>
</td>
<td>
<span id="cpu_temperature" class="device-card-content-value">-</span> C
</td>
</tr>
</table>
</div>
<div class="cores">
<div id="core-1" class="core">
<table class="core-table">
<tbody>
<tr>
<td rowspan="2">
<div class="core-name-container">
<span class="digi-icon-color fas fa-microchip fa-2x"></span>
<span>Core 1</span>
</div>
</td>
<td><span id="core-1-usage">-</span> %</td>
</tr>
<tr>
<td><span id="core-1-speed">-</span> MHz</td>
</tr>
</tbody>
</table>
</div>
<div id="core-2" class="core">
<table class="core-table">
<tbody>
<tr>
<td rowspan="2">
<div class="core-name-container">
<span class="digi-icon-color fas fa-microchip fa-2x"></span>
<span>Core 2</span>
</div>
</td>
<td><span id="core-2-usage">-</span> %</td>
</tr>
<tr>
<td><span id="core-2-speed">-</span> MHz</td>
</tr>
</tbody>
</table>
</div>
<div id="core-3" class="core">
<table class="core-table">
<tbody>
<tr>
<td rowspan="2">
<div class="core-name-container">
<span class="digi-icon-color fas fa-microchip fa-2x"></span>
<span>Core 3</span>
</div>
</td>
<td><span id="core-3-usage">-</span> %</td>
</tr>
<tr>
<td><span id="core-3-speed">-</span> MHz</td>
</tr>
</tbody>
</table>
</div>
<div id="core-4" class="core">
<table class="core-table">
<tbody>
<tr>
<td rowspan="2">
<div class="core-name-container">
<span class="digi-icon-color fas fa-microchip fa-2x"></span>
<span>Core 4</span>
</div>
</td>
<td><span id="core-4-usage">-</span> %</td>
</tr>
<tr>
<td><span id="core-4-speed">-</span> MHz</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div id="memory_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('memory')">
<span class="panel-tooltip-text">RAM memory</span>
<span id="memory_panel_icon" class="fas fa-memory panel-area-icon"></span>
</div>
<div id="memory_panel" class="device-card memory-panel shadow-sm">
<span id="memory_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-memory fa-lg mr-2"></span>
<span>RAM memory stats</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('memory', false)"></div>
</div>
<div class="device-card-content">
<table>
<tr>
<td>
<span class="device-card-content-text">Total memory:</span>
</td>
<td>
<span id="memory_total" class="device-card-content-value">-</span> MB
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Used memory:</span>
</td>
<td>
<span id="memory_used" class="device-card-content-value">-</span> MB
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Free memory:</span>
</td>
<td>
<span id="memory_free" class="device-card-content-value">-</span> MB
</td>
</tr>
</table>
</div>
</div>
<div id="filesystem_panel" class="filesystem-panel">
<div class="filesystem-background"></div>
<div id="filesystem_container" class="filesystem-container">
<div id="filesystem_header" class="device-card-header">
<span class="fas fa-folder-open fa-lg mr-2"></span>
<span>Device file system</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="closeFileSystem()"></div>
</div>
<div id="filesystem_hover_background" class="filesystem-hover-background"></div>
<div id="filesystem_dir_name_panel" class="filesystem-dir-name-panel">
<div class="filesystem-dir-name-background"></div>
<div class="filesystem-dir-name-container">
<div class="device-card-header">
<span class="fas fa-folder-plus fa-lg mr-2"></span>
<span>Create new directory</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="closeDirectoryNamePanel()"></div>
</div>
<div class="filesystem-dir-name-label">Enter the new directory name</div>
<input id="filesystem_directory_name" class="filesystem-dir-name-input" type="text"/>
<div id="filesystem_directory_name_error" class="filesystem-dir-name-error"></div>
<div id="filesystem_directory_name_button" class="device-card-button filesystem-dir-name-button filesystem-dir-name-button-disabled" onclick="onCreateDirectory()">Create directory</div>
</div>
</div>
<div id="filesystem_toolbar" class="filesystem-toolbar">
<div class="filesystem-current-directory-container">
<div class="filesystem-current-directory-label">Current dir:</div>
<div id="current_directory" class="filesystem-current-directory"></div>
</div>
<div id="filesystem_toolbar_buttons_container" class="filesystem-toolbar-buttons-container">
<div id="filesystem_create_directory_button" class="filesystem-button fas fa-folder-plus fa-2x" onclick="openDirectoryNamePanel()" title="Create directory"></div>
<div id="filesystem_upload_file_button" class="filesystem-button fas fa-upload fa-2x" onclick="openFileBrowser()" title="Upload file"></div>
<div id="filesystem_download_file_button" class="filesystem-button fas fa-file-download fa-2x" onclick="downloadSelectedFile()" title="Download file"></div>
<div id="filesystem_remove_file_button" class="filesystem-button fas fa-trash fa-2x" onclick="askRemoveFile()" title="Remove file"></div>
</div>
</div>
<div id="filesystem_items_header" class="filesystem-items-header">
<div class="filesystem-entry-icon"></div>
<div class="filesystem-entry-name">Name</div>
<div class="filesystem-entry-size">Size</div>
<div class="filesystem-entry-last-modified">Last modified</div>
</div>
<div id="filesystem_items_container" class="filesystem-items-container"></div>
<div id="filesystem_loading" class="popup shadow" style="top: 33%">
<img class="popup-item" src="./static/images/loading.gif" alt="Loading..." />
<div class="popup-text">Loading...</div>
</div>
</div>
</div>
<div id="wifi_bt_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('wifi-bt')">
<span class="panel-tooltip-text">WiFi/BT stats</span>
<span id="wifi_bt_panel_icon" class="fas fa-wifi panel-area-icon"></span>
</div>
<div id="wifi_bt_panel" class="device-card wifi-panel shadow-sm">
<span id="wifi_bt_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-wifi fa-lg mr-2"></span>
<span>Wi-Fi/BT stats</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('wifi-bt', false)"></div>
</div>
<div class="device-card-content">
<table>
<tr>
<td>
<span class="device-card-content-text">Status:</span>
</td>
<td>
<span id="wifi_state" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">MAC address:</span>
</td>
<td>
<span id="wifi_mac" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">IP address:</span>
</td>
<td>
<span id="wifi_ip" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Sent data:</span>
</td>
<td>
<span id="wifi_sent_data" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Received data:</span>
</td>
<td>
<span id="wifi_received_data" class="device-card-content-value">-</span>
</td>
</tr>
</table>
</div>
<div class="device-card-header">
<span class="fab fa-bluetooth-b fa-lg mr-2"></span>
<span>Bluetooth</span>
</div>
<div class="device-card-content">
<table>
<tr>
<td>
<span class="device-card-content-text">Status:</span>
</td>
<td>
<span id="bluetooth_state" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">MAC address:</span>
</td>
<td>
<span id="bluetooth_mac" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Sent data:</span>
</td>
<td>
<span id="bluetooth_sent_data" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Received data:</span>
</td>
<td>
<span id="bluetooth_received_data" class="device-card-content-value">-</span>
</td>
</tr>
</table>
</div>
</div>
<div id="ethernet_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('ethernet')">
<span class="panel-tooltip-text">Ethernet stats</span>
<span id="ethernet_panel_icon" class="fas fa-ethernet panel-area-icon"></span>
</div>
<div id="ethernet_panel" class="device-card ethernet-panel shadow-sm">
<span id="ethernet_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-ethernet fa-lg mr-2"></span>
<span>Ethernet stats</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('ethernet', false)"></div>
</div>
<div class="device-card-content">
<table>
<tr>
<td>
<span class="device-card-content-text">Status:</span>
</td>
<td>
<span id="ethernet_state" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">MAC address:</span>
</td>
<td>
<span id="ethernet_mac" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">IP address:</span>
</td>
<td>
<span id="ethernet_ip" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Sent data:</span>
</td>
<td>
<span id="ethernet_sent_data" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td>
<span class="device-card-content-text">Received data:</span>
</td>
<td>
<span id="ethernet_received_data" class="device-card-content-value">-</span>
</td>
</tr>
</table>
</div>
</div>
<div id="video_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('video')">
<span class="panel-tooltip-text">Video info</span>
<span id="video_panel_icon" class="fas fa-desktop panel-area-icon"></span>
</div>
<div id="video_panel" class="device-card video-panel shadow-sm">
<span id="video_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-desktop fa-lg mr-2"></span>
<span>Video info</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('video', false)"></div>
</div>
<div class="device-card-content">
<table>
<tr>
<td>
<span class="device-card-content-text">Resolution:</span>
</td>
<td>
<span id="video_resolution" class="device-card-content-value">-</span>
</td>
</tr>
</table>
<div id="video_brightness_container">
<span class="device-card-content-text">Brightness:</span>
<span class="device-card-content-value"> 0%</span>
<input id="video_brightness"/>
<span class="device-card-content-value"> 100%</span>
</div>
</div>
</div>
<div id="audio_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('audio')">
<span class="panel-tooltip-text">Audio control</span>
<span id="audio_panel_icon" class="fas fa-volume-up panel-area-icon"></span>
</div>
<div id="audio_panel" class="device-card audio-panel shadow-sm">
<span id="audio_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-volume-up fa-lg mr-2"></span>
<span>Audio control</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('audio', false)"></div>
</div>
<div class="device-card-content">
<div>
<span class="device-card-content-text">Volume:</span>
<span class="device-card-content-value"> 0%</span>
<input id="audio_volume"/>
<span class="device-card-content-value"> 100%</span>
</div>
</div>
</div>
<div id="led_panel_area" class="led-panel-area-off"></div>
<div id="led_panel" class="led-panel shadow-sm panel-tooltip" onclick="toggleUserLED()">
<span class="panel-tooltip-text">Toggle LED</span>
<span id="led_panel_arrow" class="panel-arrow"></span>
<img id ="led_image" class="led-image" src="./static/images/led_bubble.png"/>
</div>
<div id="flash_memory_panel_area" class="panel-area panel-tooltip" onclick="toggleInfoPanelVisibility('flash_memory')">
<span class="panel-tooltip-text">Flash memory</span>
<span id="flash_memory_panel_icon" class="fas fa-database panel-area-icon"></span>
</div>
<div id="flash_memory_panel" class="device-card flash-memory-panel shadow-sm">
<span id="flash_memory_panel_arrow" class="panel-arrow"></span>
<div class="device-card-header">
<span class="fas fa-database fa-lg mr-2"></span>
<span>Flash memory stats</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('flash_memory', false)"></div>
</div>
<div class="device-card-content">
<table>
<tr>
<td>
<span class="device-card-content-text">Total flash memory:</span>
</td>
<td>
<span id="flash_size" class="device-card-content-value">-</span> GB
</td>
</tr>
</table>
<div class="device-card-button filesystem-explore-button" onclick="openFileSystem()">Explore file system...</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
// Initialize the device.
initDevice();
// Initialize sliders.
initSliders();
// Register resize event.
window.onresize = adjustImageSize;
// Change the color of the device toolbar icons when hovering.
$("#device-button-hide-info").on({
"mouseover" : function() {
$("#device-button-hide-info-img").attr("src", "./static/images/hide_info_green.png");
},
"mouseout" : function() {
$("#device-button-hide-info-img").attr("src", "./static/images/hide_info.png");
}
});
$("#device-button-show-info").on({
"mouseover" : function() {
$("#device-button-show-info-img").attr("src", "./static/images/show_info_green.png");
},
"mouseout" : function() {
$("#device-button-show-info-img").attr("src", "./static/images/show_info.png");
}
});
// Register file upload change event.
$("#file_to_upload").on("change", function(event) {
uploadFile(event.target.files[0]);
});
// Register directory name input changed.
$("#filesystem_directory_name").on("input", function(event) {
validateDirectoryName(event.target.value);
});
// Change image of the LED panel when hovering.
$("#led_panel").on({
"mouseover" : function() {
$("#led_image").attr("src", "./static/images/led_bubble_hover.png");
},
"mouseout" : function() {
$("#led_image").attr("src", "./static/images/led_bubble.png");
}
});
});
</script>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$("#banner-link").on({
"mouseover" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner_gray.png");
},
"mouseout" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner.png");
}
});
});
// Enable the tooltip library.
$(function() {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
<!-- Local JS files and functions -->
<script type="text/javascript" src="./static/js/sidebar.js"></script>
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
<script type="text/javascript" src="./static/js/dashboard.js"></script>
<script type="text/javascript" src="./static/js/multimedia.js"></script>
<script type="text/javascript" src="./static/js/management.js"></script>
<script type="text/javascript" src="./static/js/file-system.js"></script>
<script>
$(document).ready(function() {
// Don't show the loading spinner at the beginning. Initial page
// load is full, so not relying on AJAX.
$("#loading").hide();
// Set up PJAX.
if ($.support.pjax) {
$.pjax.defaults.timeout = 20000;
$.pjax.defaults.fragment = "#pjax-container";
$(document).pjax("a[data-pjax]", "#pjax-container");
$(document).on("pjax:beforeSend", function() {
// Do not load new content if there are unsaved changes.
if ($("#save-schedule").length && !$("#save-schedule").attr("disabled") && !confirm("There are unsaved changes. Do you want to exit?"))
return false;
});
$(document).on("pjax:send", function(e) {
setSelectedSection(e.currentTarget.activeElement);
$("#pjax-container").hide();
$("#loading").show();
});
$(document).on("pjax:complete", function() {
$("#loading").hide();
$("#pjax-container").show();
});
}
// Append the URL parameters to the section links.
var params = new URLSearchParams(window.location.search).toString();
if (params) {
$("#sections li").each(function(i, n) {
n.children[0].href += "?" + params;
});
}
// Set the selected section.
setSelectedSection();
});
// Callback executed when the page loads.
document.addEventListener("DOMContentLoaded", function(event) {
// Start the timer that updates device status.
var statsTimer = setInterval(refreshDevice, 5000);
});
</script>
</body>
</html>

View File

@ -0,0 +1,342 @@
<!DOCTYPE html>
<html>
<head>
<title>
Digi Demo - Management
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./static/css/stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="./static/css/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
<link href="./static/css/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/css/bootstrap-slider.min.css" rel="stylesheet">
<link href="./static/css/fontawesome5.15.4/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="./static/css/general.css">
<link rel="stylesheet" href="./static/css/toastr.css">
<!-- JS, Popper.js, and jQuery -->
<script src="./static/js/code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="./static/js/stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script src="./static/js/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/bootstrap-slider.min.js"></script>
<script type="text/javascript" src="./static/js/common.js"></script>
<script type="text/javascript" src="./static/js/devices.js"></script>
<script type="text/javascript" src="./static/js/jquery.pjax.js"></script>
<script type="text/javascript" src="./static/js/jquery.matchHeight-min.js"></script>
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
</head>
<body>
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<div class="nav-container">
<a id="banner-link" class="navbar-brand align-middle" href="/">
<div class="d-flex align-items-baseline">
<img id="banner-logo" class="banner-icon" src="./static/images/Digi_logo_banner.png">
<p id="banner-text">ConnectCore Demo</p>
</div>
</a>
<div class="nav-right-container">
<div>
<img src="./static/images/board.png" class="device-title-img" title="Device">
</div>
<div id="device-name">DEY DEVICE</div>
</div>
</nav>
<div class="bg-light" id="body-row">
<!-- Sidebar https://www.codeply.com/go/3e0RAjccRO/bootstrap-4-collapsing-sidebar-menu# -->
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block">
<!-- d-* hides the Sidebar in smaller devices. Its items can be kept on the Navbar 'Menu' -->
<div id="sidebar-contents">
<!-- Bootstrap List Group -->
<ul id="sections" data-pjax class="list-group">
<li>
<a data-pjax href="index.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-tachometer-alt fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Dashboard</span>
</div>
</a>
</li>
<li>
<a data-pjax href="multimedia.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-film fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Multimedia</span>
</div>
</a>
</li>
<li>
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-cog fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Management</span>
</div>
</a>
</li>
</ul>
<ul id="collapsator" class="list-group">
<a href="#top" data-toggle="sidebar-collapse" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span id="collapse-icon" class="digi-menu-icon fas fa-fw fa-lg mr-3"></span>
<span id="collapse-text" class="menu-collapsed">Collapse</span>
</div>
</a>
</ul>
</div>
</div>
<div class="container-fluid">
<div id="loading">
<img id="loading-image" src="./static/images/loading.gif" alt="Loading..." />
</div>
<div id="pjax-container">
<!-- <input type="file" id="firmware_file" style="display:none" onchange="firmwareFileChanged()" accept=".swu,.json,.txt"/>-->
<input type="file" id="firmware_file" style="display:none" onchange="firmwareFileChanged()" accept=".swu"/>
<div class="row justify-content-lg-center">
<div class="col-lg-12 col-xl-12">
<div id="loading_popup" class="popup popup-loading shadow">
<img class="popup-item" src="./static/images/loading.gif" alt="Loading..." />
<div id="loading_popup_message" class="popup-text">Loading information...</div>
</div>
<div id="info_popup" class="popup popup-info shadow d-none">
<div id="info_popup_title" class="popup-title">Error</div>
<div id="info_popup_message" class="popup-text">-</div>
</div>
<div id="confirm_dialog" class="confirm-dialog d-none">
<div class="device-card-header">
<span class="fas fa-question-circle fa-lg mr-2"></span>
<span id="confirm_dialog_title"></span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="showPopup(ID_LOADING_WRAPPER, ID_CONFIRM_DIALOG, false)"></div>
</div>
<div id="confirm_dialog_message" class="confirm-dialog-message"></div>
<div class="confirm-dialog-buttons-container">
<div id="confirm_dialog_no_button" class="device-card-button confirm-dialog-button">No</div>
<div id="confirm_dialog_yes_button" class="device-card-button confirm-dialog-button">Yes</div>
</div>
</div>
<div id="rebooted_dialog" class="popup popup-info shadow d-none">
<div class="popup-title"><p><i class="fa fa-check success-message fa-lg"></i> Device rebooted</p></div>
<div class="popup-text">Reload the page to continue.</div>
<div class="confirm-dialog-buttons-container" style="padding-top: 30px;">
<div id="reload_button" class="device-card-button confirm-dialog-button" onclick="document.location.replace('index.html')">Reload</div>
</div>
</div>
<div id="loading_wrapper" class="loading-wrapper element-grayed">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Reboot device</h5>
<div>Click <b>REBOOT</b> to restart your device.</div>
<div id="reboot_button" class="device-card-button reboot-button" onclick="askReboot()">REBOOT</div>
</div>
</div>
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Firmware update</h5>
<table style="margin: 15px;">
<tr>
<td style="width: 180px; vertical-align: top;">
<span class="device-card-content-text">Current DEY version:</span>
</td>
<td>
<span id="dey_version" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Current kernel version:</span>
</td>
<td>
<span id="kernel_version" class="device-card-content-value">-</span>
</td>
</tr>
<tr>
<td style="vertical-align: top;">
<span class="device-card-content-text">Current U-Boot version:</span>
</td>
<td>
<span id="uboot_version" class="device-card-content-value">-</span>
</td>
</tr>
</table>
<div class="firmware-tabs">
<div id="firmware_tab_upload_header" class="firmware-tab-header firmware-tab-header-active" onclick="showFirmwareTab(ID_FIRMWARE_TAB_UPLOAD)">
<span class="fas fa-upload fa-lg"></span>
<span class="firmware-tab-text">Upload file</span>
</div>
</div>
<div class="firmware-tab-container">
<div id="firmware_tab_upload" class="firmware-tab firmware-tab-upload">
<div>Upload and install a firmware file from your computer.</div>
<div class="firmware-file-container">
<div id="select_firmware_button" class="device-card-button browse-firmware-button" onclick="openFirmwareBrowser()">Choose file...</div>
<div id="firmware_file_label" class="firmware-file-label">No file chosen</div>
</div>
</div>
</div>
<div id="update_firmware_progress" class="update-firmware-progress">
<div id="update_firmware_progress_title" class="update-firmware-progress-title">Firmware update in progress...</div>
<div class="progress update-firmware-progress-bar">
<div id="update_firmware_progress_bar" class="progress-bar progress-bar-striped update-firmware-progress-bar update-firmware-progress-bar-info update-firmware-progress-bar-hover" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width:40%">40%</div>
</div>
<span id="update_firmware_progress_message" class="update-firmware-progress-status">Waiting for firmware update...</span>
</div>
<div>
<div id="update_firmware_button" class="device-card-button update-firmware-button management-button-disabled" onclick="askUpdateFirmware()">Update Firmware</div>
</div>
</div> <!-- card body -->
</div> <!-- card shadow -->
<div id="filesystem_panel" class="filesystem-panel">
<div class="filesystem-background"></div>
<div id="filesystem_container" class="filesystem-container">
<div id="filesystem_header" class="device-card-header">
<span class="fas fa-folder-open fa-lg mr-2"></span>
<span>Device's file system</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="closeFileSystem()"></div>
</div>
<div id="filesystem_hover_background" class="filesystem-hover-background"></div>
<div id="filesystem_dir_name_panel" class="filesystem-dir-name-panel">
<div class="filesystem-dir-name-background"></div>
<div class="filesystem-dir-name-container">
<div class="device-card-header">
<span class="fas fa-folder-plus fa-lg mr-2"></span>
<span>Create new directory</span>
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="closeDirectoryNamePanel()"></div>
</div>
<div class="filesystem-dir-name-label">Enter the new directory name</div>
<input id="filesystem_directory_name" class="filesystem-dir-name-input" type="text"/>
<div id="filesystem_directory_name_error" class="filesystem-dir-name-error"></div>
<div id="filesystem_directory_name_button" class="device-card-button filesystem-dir-name-button filesystem-dir-name-button-disabled" onclick="onCreateDirectory()">Create directory</div>
</div>
</div>
<div id="filesystem_toolbar" class="filesystem-toolbar">
<div class="filesystem-current-directory-container">
<div class="filesystem-current-directory-label">Current dir:</div>
<div id="current_directory" class="filesystem-current-directory"></div>
</div>
<div id="filesystem_toolbar_buttons_container" class="filesystem-toolbar-buttons-container">
<div id="filesystem_select_file_button" class="filesystem-button fas fa-bolt fa-2x" onclick="selectFirmwareFile()" title="Select firmware file"></div>
<div id="filesystem_create_directory_button" class="filesystem-button fas fa-folder-plus fa-2x" onclick="openDirectoryNamePanel()" title="Create directory"></div>
<div id="filesystem_upload_file_button" class="filesystem-button fas fa-upload fa-2x" onclick="openFileBrowser()" title="Upload file"></div>
<div id="filesystem_download_file_button" class="filesystem-button fas fa-file-download fa-2x" onclick="downloadSelectedFile()" title="Download file"></div>
<div id="filesystem_remove_file_button" class="filesystem-button fas fa-trash fa-2x" onclick="askRemoveFile()" title="Remove file"></div>
</div>
</div>
<div id="filesystem_items_header" class="filesystem-items-header">
<div class="filesystem-entry-icon"></div>
<div class="filesystem-entry-name">Name</div>
<div class="filesystem-entry-size">Size</div>
<div class="filesystem-entry-last-modified">Last modified</div>
</div>
<div id="filesystem_items_container" class="filesystem-items-container"></div>
<div id="filesystem_loading" class="popup shadow" style="top: 33%">
<img class="popup-item" src="./static/images/loading.gif" alt="Loading..." />
<div class="popup-text">Loading...</div>
</div>
</div> <!-- filesystem_container -->
</div> <!-- filesystem_panel -->
</div> <!-- loading wrapper -->
</div> <!-- col -->
</div> <!-- row justify -->
<script>
$(document).ready(function() {
// Reset variables.
readingManagementInfo = false;
managementInfoRead = false;
deviceRebooting = false;
updatingFirmware = false;
firmwareUpdateTimer = null;
selectedFilesetEntry = null;
filesLoaded = false;
// Initialize page.
initializeManagementPage();
});
</script>
</div> <!-- pjax-container -->
</div> <!-- container fluid -->
</div> <!--bg light -->
<script>
$(document).ready(function() {
$("#banner-link").on({
"mouseover" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner_gray.png");
},
"mouseout" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner.png");
}
});
});
// Enable the tooltip library.
$(function() {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
<!-- Local JS files and functions -->
<script type="text/javascript" src="./static/js/sidebar.js"></script>
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
<script type="text/javascript" src="./static/js/dashboard.js"></script>
<script type="text/javascript" src="./static/js/multimedia.js"></script>
<script type="text/javascript" src="./static/js/management.js"></script>
<script type="text/javascript" src="./static/js/file-system.js"></script>
<script>
$(document).ready(function() {
// Don't show the loading spinner at the beginning. Initial page
// load is full, so not relying on AJAX.
$("#loading").hide();
// Set up PJAX.
if ($.support.pjax) {
$.pjax.defaults.timeout = 20000;
$.pjax.defaults.fragment = "#pjax-container";
$(document).pjax("a[data-pjax]", "#pjax-container");
$(document).on("pjax:beforeSend", function() {
// Do not load new content if there are unsaved changes.
if ($("#save-schedule").length && !$("#save-schedule").attr("disabled") && !confirm("There are unsaved changes. Do you want to exit?"))
return false;
});
$(document).on("pjax:send", function(e) {
setSelectedSection(e.currentTarget.activeElement);
$("#pjax-container").hide();
$("#loading").show();
});
$(document).on("pjax:complete", function() {
$("#loading").hide();
$("#pjax-container").show();
});
}
// Append the URL parameters to the section links.
var params = new URLSearchParams(window.location.search).toString();
if (params) {
$("#sections li").each(function(i, n) {
n.children[0].href += "?" + params;
});
}
// Set the selected section.
setSelectedSection();
});
</script>
</body>
</html>

View File

@ -0,0 +1,283 @@
<!DOCTYPE html>
<html>
<head>
<title>
Digi Demo - Multimedia
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./static/css/stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="./static/css/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
<link href="./static/css/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/css/bootstrap-slider.min.css" rel="stylesheet">
<link href="./static/css/fontawesome5.15.4/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="./static/css/general.css">
<link rel="stylesheet" href="./static/css/toastr.css">
<!-- JS, Popper.js, and jQuery -->
<script src="./static/js/code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="./static/js/stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script src="./static/js/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/bootstrap-slider.min.js"></script>
<script type="text/javascript" src="./static/js/common.js"></script>
<script type="text/javascript" src="./static/js/devices.js"></script>
<script type="text/javascript" src="./static/js/jquery.pjax.js"></script>
<script type="text/javascript" src="./static/js/jquery.matchHeight-min.js"></script>
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
</head>
<body>
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<div class="nav-container">
<a id="banner-link" class="navbar-brand align-middle" href="/">
<div class="d-flex align-items-baseline">
<img id="banner-logo" class="banner-icon" src="./static/images/Digi_logo_banner.png">
<p id="banner-text">ConnectCore Demo</p>
</div>
</a>
<div class="nav-right-container">
<div>
<img src="./static/images/board.png" class="device-title-img" title="Device">
</div>
<div id="device-name">DEY DEVICE</div>
</div>
</nav>
<div class="bg-light" id="body-row">
<!-- Sidebar https://www.codeply.com/go/3e0RAjccRO/bootstrap-4-collapsing-sidebar-menu# -->
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block">
<!-- d-* hides the Sidebar in smaller devices. Its items can be kept on the Navbar 'Menu' -->
<div id="sidebar-contents">
<!-- Bootstrap List Group -->
<ul id="sections" data-pjax class="list-group">
<li>
<a data-pjax href="index.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-tachometer-alt fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Dashboard</span>
</div>
</a>
</li>
<li>
<a data-pjax href="multimedia.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-film fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Multimedia</span>
</div>
</a>
</li>
<li>
<a data-pjax href="management.html" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="digi-menu-icon fas fa-cog fa-fw fa-lg mr-3"></span>
<span class="menu-collapsed">Management</span>
</div>
</a>
</li>
</ul>
<ul id="collapsator" class="list-group">
<a href="#top" data-toggle="sidebar-collapse" class="list-group-item list-group-item-action d-flex align-items-center">
<div class="d-flex w-100 justify-content-start align-items-center">
<span id="collapse-icon" class="digi-menu-icon fas fa-fw fa-lg mr-3"></span>
<span id="collapse-text" class="menu-collapsed">Collapse</span>
</div>
</a>
</ul>
</div>
</div>
<div class="container-fluid">
<div id="loading">
<img id="loading-image" src="./static/images/loading.gif" alt="Loading..." />
</div>
<div id="pjax-container">
<div class="row justify-content-lg-center">
<div class="col-lg-12 col-xl-12">
<div id="loading_popup" class="popup popup-loading shadow">
<img class="popup-item" src="./static/images/loading.gif" alt="Loading..." />
<div id="loading_popup_message" class="popup-text">Loading information...</div>
</div>
<div id="info_popup" class="popup popup-info shadow d-none">
<div id="info_popup_title" class="popup-title">Error</div>
<div id="info_popup_message" class="popup-text">-</div>
</div>
<div id="loading_wrapper" class="loading-wrapper element-grayed">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">WebGL examples</h5>
<!-- Multimedia items section -->
<div class="row">
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=aquarium/aquarium.html'">
<div class="multimedia-title">Aquarium</div>
<img src="./static/images/aquarium.jpg" alt="Aquarium">
</div>
</div>
</div>
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=blob/blob.html'">
<div class="multimedia-title">Blob</div>
<img src="./static/images/blob.jpg" alt="Blob">
</div>
</div>
</div>
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=electricflower/electricflower.html'">
<div class="multimedia-title">Electricflower</div>
<img src="./static/images/electricflower.jpg" alt="Electricflower">
</div>
</div>
</div>
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=multiple-views/multiple-views.html'">
<div class="multimedia-title">Multiple Views</div>
<img src="./static/images/multiple-views.jpg" alt="Multiple Views">
</div>
</div>
</div>
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=spacerocks/spacerocks.html'">
<div class="multimedia-title">Spacerocks</div>
<img src="./static/images/spacerocks.jpg" alt="Spacerocks">
</div>
</div>
</div>
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=toon-shading/toon-shading.html'">
<div class="multimedia-title">Toon Shading</div>
<img src="./static/images/toon-shading.jpg" alt="Toon Shading">
</div>
</div>
</div>
</div> <!-- Multimedia items -->
<div style="padding-top: 20px;">
All the WebGL examples have been obtained from <a href="#" onclick="location.href='multimedia_viewer.html?exampleURL=https://webglsamples.org/'">https://webglsamples.org/</a>
</div>
</div> <!-- card body -->
</div> <!-- card shadow -->
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Videos</h5>
<!-- Videos -->
<div class="row">
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=videos/big_buck_bunny.mov'">
<div class="multimedia-title">Big Buck Bunny (MOV)</div>
<img src="./static/images/big_buck_bunny.jpg" alt="Big Buck Bunny (MOV)">
</div>
</div>
</div>
<div class="col-xl-2 multimedia-container">
<div class="d-flex justify-content-center align-items-center multimedia-box">
<div class="multimedia-item" onclick="location.href='multimedia_viewer.html?exampleURL=videos/big_buck_bunny.webm'">
<div class="multimedia-title">Big Buck Bunny (WEBM)</div>
<img src="./static/images/big_buck_bunny.jpg" alt="Big Buck Bunny (WEBM)">
</div>
</div>
</div>
</div> <!--Videos -->
</div> <!-- card body -->
</div> <!-- card shadow -->
</div> <!-- loading wrapper -->
</div> <!-- col -->
</div> <!-- row justify -->
<script>
$(document).ready(function() {
// Reset variables.
readingMultimediaInfo = false;
multimediaInfoRead = false;
// Initialize page.
initializeMultimediaPage();
});
</script>
</div> <!-- pjax-container -->
</div> <!-- container-fluid -->
</div> <!-- bg-light -->
<script>
$(document).ready(function() {
$("#banner-link").on({
"mouseover" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner_gray.png");
},
"mouseout" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner.png");
}
});
});
// Enable the tooltip library.
$(function() {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
<!-- Local JS files and functions -->
<script type="text/javascript" src="./static/js/sidebar.js"></script>
<script type="text/javascript" src="./static/js/ccimx8mm-dvk.js"></script>
<script type="text/javascript" src="./static/js/ccimx8m-nano.js"></script>
<script type="text/javascript" src="./static/js/ccimx8x-sbc-pro.js"></script>
<script type="text/javascript" src="./static/js/dashboard.js"></script>
<script type="text/javascript" src="./static/js/multimedia.js"></script>
<script type="text/javascript" src="./static/js/management.js"></script>
<script type="text/javascript" src="./static/js/file-system.js"></script>
<script>
$(document).ready(function() {
// Don't show the loading spinner at the beginning. Initial page
// load is full, so not relying on AJAX.
$("#loading").hide();
// Set up PJAX.
if ($.support.pjax) {
$.pjax.defaults.timeout = 20000;
$.pjax.defaults.fragment = "#pjax-container";
$(document).pjax("a[data-pjax]", "#pjax-container");
$(document).on("pjax:beforeSend", function() {
// Do not load new content if there are unsaved changes.
if ($("#save-schedule").length && !$("#save-schedule").attr("disabled") && !confirm("There are unsaved changes. Do you want to exit?"))
return false;
});
$(document).on("pjax:send", function(e) {
setSelectedSection(e.currentTarget.activeElement);
$("#pjax-container").hide();
$("#loading").show();
});
$(document).on("pjax:complete", function() {
$("#loading").hide();
$("#pjax-container").show();
});
}
// Append the URL parameters to the section links.
var params = new URLSearchParams(window.location.search).toString();
if (params) {
$("#sections li").each(function(i, n) {
n.children[0].href += "?" + params;
});
}
// Set the selected section.
setSelectedSection();
});
</script>
</body>
</html>

View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html>
<head>
<title>Digi Demo - Multimedia viewer</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./static/css/stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="./static/css/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
<link href="./static/css/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/css/bootstrap-slider.min.css" rel="stylesheet">
<link href="./static/css/fontawesome5.15.4/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="./static/css/general.css">
<link rel="stylesheet" href="./static/css/toastr.css">
<!-- JS, Popper.js, and jQuery -->
<script src="./static/js/code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="./static/js/stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="./static/js/cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<script src="./static/js/cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/bootstrap-slider.min.js"></script>
<script type="text/javascript" src="./static/js/common.js"></script>
<script type="text/javascript" src="./static/js/devices.js"></script>
<script type="text/javascript" src="./static/js/jquery.pjax.js"></script>
<script type="text/javascript" src="./static/js/jquery.matchHeight-min.js"></script>
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
</head>
<body class="multimedia-viewer">
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<div class="nav-container" style="padding-right: 0px;">
<a id="banner-link" class="navbar-brand align-middle" href="/">
<div class="d-flex align-items-baseline">
<img id="banner-logo" class="banner-icon" src="./static/images/Digi_logo_banner.png">
<p id="banner-text">ConnectCore Demo</p>
</div>
</a>
<div class="nav-right-container">
<div class="stat" style="min-width: 200px">
<div class="status-icon">
<img src="./static/images/cpu.png" height=32px/>
</div>
<div class="status-text">CPU:</div>
<div id="stats-cpu-load" class="status-text">-</div>
</div>
<div class="stat">
<div class="status-icon">
<img src="./static/images/ram.png" height=32px/>
</div>
<div class="status-text">Memory:</div>
<div id="stats-memory" class="status-text">-</div>
</div>
<a href="multimedia.html">
<div id="back-button" class="device-card-button back-button">Back</div>
</a>
</div>
</div>
</nav>
<!-- Demo content container -->
<iframe frameborder="0" class="multimedia-content" id="multimedia-content"></iframe>
<script>
$(document).ready(function() {
$("#banner-link").on({
"mouseover" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner_gray.png");
},
"mouseout" : function() {
$("#banner-logo").attr("src", "./static/images/Digi_logo_banner.png");
}
});
});
// Enable the tooltip library.
$(function() {
$('[data-toggle="tooltip"]').tooltip();
});
document.addEventListener("DOMContentLoaded", function(event) {
// Get the example ID from the URL parameters.
let urlParams = new URLSearchParams(window.location.search);
if (urlParams == null)
return;
let exampleURL = urlParams.get('exampleURL');
if (exampleURL !== null)
// Load the example.
loadExample(exampleURL);
// Start the timer that updates the system stats.
getSystemStats();
var statsTimer = setInterval(getSystemStats, 5000);
});
function loadExample(exampleURL) {
if (exampleURL.startsWith("http"))
document.getElementById('multimedia-content').src = exampleURL;
else
document.getElementById('multimedia-content').src = "./" + exampleURL;
}
function getSystemStats() {
var xmlhttp = new XMLHttpRequest();
var url = "http://" + getServerAddress() + "/ajax/get_device_status";
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var jsonPayload = JSON.parse(this.responseText);
updateStats(jsonPayload);
}
};
xmlhttp.open("POST", url, true);
xmlhttp.send();
}
function updateStats(stats) {
updateValueWithEffect("stats-cpu-load", roundToTwoDecimals(stats[STREAM_CPU_LOAD]) + " %");
updateValueWithEffect("stats-memory", roundToTwoDecimals(kiloBytesToMegaBytes(stats[STREAM_MEMORY_FREE])) + " MB");
}
</script>
</body>
</html>

View File

@ -0,0 +1,10 @@
/*\
|*| ========================================================================
|*| Bootstrap Toggle: bootstrap4-toggle.css v3.6.1
|*| https://gitbrent.github.io/bootstrap4-toggle/
|*| ========================================================================
|*| Copyright 2018-2019 Brent Ely
|*| Licensed under MIT
|*| ========================================================================
\*/
.btn-group-xs>.btn,.btn-xs{padding:.35rem .4rem .25rem .4rem;font-size:.875rem;line-height:.5;border-radius:.2rem}.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-1.25rem;margin-right:.35rem}.toggle{position:relative;overflow:hidden}.toggle.btn.btn-light,.toggle.btn.btn-outline-light{border-color:rgba(0,0,0,.15)}.toggle input[type=checkbox]{display:none}.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}.toggle-group label,.toggle-group span{cursor:pointer}.toggle.off .toggle-group{left:-100%}.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0;box-shadow:none}.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px;background-color:#fff}.toggle.btn-outline-primary .toggle-handle{background-color:var(--primary);border-color:var(--primary)}.toggle.btn-outline-secondary .toggle-handle{background-color:var(--secondary);border-color:var(--secondary)}.toggle.btn-outline-success .toggle-handle{background-color:var(--success);border-color:var(--success)}.toggle.btn-outline-danger .toggle-handle{background-color:var(--danger);border-color:var(--danger)}.toggle.btn-outline-warning .toggle-handle{background-color:var(--warning);border-color:var(--warning)}.toggle.btn-outline-info .toggle-handle{background-color:var(--info);border-color:var(--info)}.toggle.btn-outline-light .toggle-handle{background-color:var(--light);border-color:var(--light)}.toggle.btn-outline-dark .toggle-handle{background-color:var(--dark);border-color:var(--dark)}.toggle[class*=btn-outline]:hover .toggle-handle{background-color:var(--light);opacity:.5}.toggle.btn{min-width:3.7rem;min-height:2.15rem}.toggle-on.btn{padding-right:1.5rem}.toggle-off.btn{padding-left:1.5rem}.toggle.btn-lg{min-width:5rem;min-height:2.815rem}.toggle-on.btn-lg{padding-right:2rem}.toggle-off.btn-lg{padding-left:2rem}.toggle-handle.btn-lg{width:2.5rem}.toggle.btn-sm{min-width:3.125rem;min-height:1.938rem}.toggle-on.btn-sm{padding-right:1rem}.toggle-off.btn-sm{padding-left:1rem}.toggle.btn-xs{min-width:2.19rem;min-height:1.375rem}.toggle-on.btn-xs{padding-right:.8rem}.toggle-off.btn-xs{padding-left:.8rem}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,228 @@
.toast-title {
font-weight: bold;
}
.toast-message {
-ms-word-wrap: break-word;
word-wrap: break-word;
}
.toast-message a,
.toast-message label {
color: #FFFFFF;
}
.toast-message a:hover {
color: #CCCCCC;
text-decoration: none;
}
.toast-close-button {
position: relative;
right: -0.3em;
top: -0.3em;
float: right;
font-size: 20px;
font-weight: bold;
color: #FFFFFF;
-webkit-text-shadow: 0 1px 0 #ffffff;
text-shadow: 0 1px 0 #ffffff;
opacity: 0.8;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
filter: alpha(opacity=80);
line-height: 1;
}
.toast-close-button:hover,
.toast-close-button:focus {
color: #000000;
text-decoration: none;
cursor: pointer;
opacity: 0.4;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
filter: alpha(opacity=40);
}
.rtl .toast-close-button {
left: -0.3em;
float: left;
right: 0.3em;
}
/*Additional properties for button version
iOS requires the button element instead of an anchor tag.
If you want the anchor version, it requires `href="#"`.*/
button.toast-close-button {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
}
.toast-top-center {
top: 0;
right: 0;
width: 100%;
}
.toast-bottom-center {
bottom: 0;
right: 0;
width: 100%;
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%;
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%;
}
.toast-top-left {
top: 12px;
left: 12px;
}
.toast-top-right {
top: 12px;
right: 12px;
}
.toast-bottom-right {
right: 12px;
bottom: 12px;
}
.toast-bottom-left {
bottom: 12px;
left: 12px;
}
#toast-container {
position: fixed;
z-index: 999999;
pointer-events: none;
/*overrides*/
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#toast-container > div {
position: relative;
pointer-events: auto;
overflow: hidden;
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px 3px 3px 3px;
-webkit-border-radius: 3px 3px 3px 3px;
border-radius: 3px 3px 3px 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999999;
-webkit-box-shadow: 0 0 12px #999999;
box-shadow: 0 0 12px #999999;
color: #FFFFFF;
opacity: 0.8;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
filter: alpha(opacity=80);
}
#toast-container > div.rtl {
direction: rtl;
padding: 15px 50px 15px 15px;
background-position: right 15px center;
}
#toast-container > div:hover {
-moz-box-shadow: 0 0 12px #000000;
-webkit-box-shadow: 0 0 12px #000000;
box-shadow: 0 0 12px #000000;
opacity: 1;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
filter: alpha(opacity=100);
cursor: pointer;
}
#toast-container > .toast-info {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
}
#toast-container > .toast-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
}
#toast-container > .toast-success {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
}
#toast-container > .toast-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
}
#toast-container.toast-top-center > div,
#toast-container.toast-bottom-center > div {
width: 300px;
margin-left: auto;
margin-right: auto;
}
#toast-container.toast-top-full-width > div,
#toast-container.toast-bottom-full-width > div {
width: 96%;
margin-left: auto;
margin-right: auto;
}
.toast {
background-color: #030303;
}
.toast-success {
background-color: #51A351;
}
.toast-error {
background-color: #BD362F;
}
.toast-info {
background-color: #2F96B4;
}
.toast-warning {
background-color: #F89406;
}
.toast-progress {
position: absolute;
left: 0;
bottom: 0;
height: 4px;
background-color: #000000;
opacity: 0.4;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
filter: alpha(opacity=40);
}
/*Responsive Design*/
@media all and (max-width: 240px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 11em;
}
#toast-container > div.rtl {
padding: 8px 50px 8px 8px;
}
#toast-container .toast-close-button {
right: -0.2em;
top: -0.2em;
}
#toast-container .rtl .toast-close-button {
left: -0.2em;
right: 0.2em;
}
}
@media all and (min-width: 241px) and (max-width: 480px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 18em;
}
#toast-container > div.rtl {
padding: 8px 50px 8px 8px;
}
#toast-container .toast-close-button {
right: -0.2em;
top: -0.2em;
}
#toast-container .rtl .toast-close-button {
left: -0.2em;
right: 0.2em;
}
}
@media all and (min-width: 481px) and (max-width: 768px) {
#toast-container > div {
padding: 15px 15px 15px 50px;
width: 25em;
}
#toast-container > div.rtl {
padding: 15px 50px 15px 15px;
}
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 730 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 898 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1019 B

View File

@ -0,0 +1,146 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class CCIMX8MNANO extends ConnectCoreDevice {
// Public constants.
static DEVICE_TYPE = "ccimx8mn-dvk";
static PLATFORM_NAME = "ConnectCore 8M-Nano DVK";
// Variables.
BOARD_IMAGE = "ccimx8m-nano_board.png";
BOARD_IMAGE_SCALE = 85;
CPU_COMPONENT_VISIBLE = true;
CPU_COMPONENT_HAS_PANEL = true;
CPU_COMPONENT_HAS_ARROW = true;
CPU_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CPU_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
CPU_COMPONENT_PANEL_HORIZONTAL_PERCENT = 28.5;
CPU_COMPONENT_PANEL_VERTICAL_PERCENT = 57;
CPU_COMPONENT_ARROW_PERCENT = 33.5;
CPU_COMPONENT_AREA_TOP_PERCENT = 45.7;
CPU_COMPONENT_AREA_LEFT_PERCENT = 32.4;
CPU_COMPONENT_AREA_WIDTH_PERCENT = 5.7;
CPU_COMPONENT_AREA_HEIGHT_PERCENT = 9;
MEMORY_COMPONENT_VISIBLE = true;
MEMORY_COMPONENT_HAS_PANEL = true;
MEMORY_COMPONENT_HAS_ARROW = true;
MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 22;
MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 65;
MEMORY_COMPONENT_ARROW_PERCENT = 33.7;
MEMORY_COMPONENT_AREA_TOP_PERCENT = 37;
MEMORY_COMPONENT_AREA_LEFT_PERCENT = 32.4;
MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 6;
MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 7;
WIFI_BT_COMPONENT_VISIBLE = true;
WIFI_BT_COMPONENT_HAS_PANEL = true;
WIFI_BT_COMPONENT_HAS_ARROW = true;
WIFI_BT_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
WIFI_BT_COMPONENT_PANEL_ORIENTATION = VALUE_RIGHT;
WIFI_BT_COMPONENT_PANEL_HORIZONTAL_PERCENT = 73;
WIFI_BT_COMPONENT_PANEL_VERTICAL_PERCENT = 38;
WIFI_BT_COMPONENT_ARROW_PERCENT = 46;
WIFI_BT_COMPONENT_AREA_TOP_PERCENT = 46.5;
WIFI_BT_COMPONENT_AREA_LEFT_PERCENT = 28.3;
WIFI_BT_COMPONENT_AREA_WIDTH_PERCENT = 4;
WIFI_BT_COMPONENT_AREA_HEIGHT_PERCENT = 6;
ETHERNET_COMPONENT_VISIBLE = true;
ETHERNET_COMPONENT_HAS_PANEL = true;
ETHERNET_COMPONENT_HAS_ARROW = true;
ETHERNET_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
ETHERNET_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
ETHERNET_COMPONENT_PANEL_HORIZONTAL_PERCENT = 21;
ETHERNET_COMPONENT_PANEL_VERTICAL_PERCENT = 70;
ETHERNET_COMPONENT_ARROW_PERCENT = 78;
ETHERNET_COMPONENT_AREA_TOP_PERCENT = 77;
ETHERNET_COMPONENT_AREA_LEFT_PERCENT = 11;
ETHERNET_COMPONENT_AREA_WIDTH_PERCENT = 8.5;
ETHERNET_COMPONENT_AREA_HEIGHT_PERCENT = 16;
CONSOLE_COMPONENT_VISIBLE = true;
CONSOLE_COMPONENT_HAS_PANEL = false;
CONSOLE_COMPONENT_HAS_ARROW = false;
CONSOLE_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CONSOLE_COMPONENT_AREA_TOP_PERCENT = 6.5;
CONSOLE_COMPONENT_AREA_LEFT_PERCENT = 26.5;
CONSOLE_COMPONENT_AREA_WIDTH_PERCENT = 3.4;
CONSOLE_COMPONENT_AREA_HEIGHT_PERCENT = 4.5;
VIDEO_COMPONENT_VISIBLE = true;
VIDEO_COMPONENT_HAS_PANEL = true;
VIDEO_COMPONENT_HAS_ARROW = true;
VIDEO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
VIDEO_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
VIDEO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 47.5;
VIDEO_COMPONENT_PANEL_VERTICAL_PERCENT = 18;
VIDEO_COMPONENT_ARROW_PERCENT = 58.5;
VIDEO_COMPONENT_AREA_TOP_PERCENT = 84;
VIDEO_COMPONENT_AREA_LEFT_PERCENT = 57;
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 6;
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 8;
AUDIO_COMPONENT_VISIBLE = false;
AUDIO_COMPONENT_HAS_PANEL = true;
AUDIO_COMPONENT_HAS_ARROW = true;
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 1;
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 19;
AUDIO_COMPONENT_ARROW_PERCENT = 16;
AUDIO_COMPONENT_AREA_TOP_PERCENT = 7;
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 14.5;
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 5.4;
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 11;
LED_COMPONENT_VISIBLE = true;
LED_COMPONENT_HAS_PANEL = true;
LED_COMPONENT_HAS_ARROW = false;
LED_COMPONENT_PANEL_ALWAYS_VISIBLE = true;
LED_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
LED_COMPONENT_PANEL_HORIZONTAL_PERCENT = 61;
LED_COMPONENT_PANEL_VERTICAL_PERCENT = 14;
LED_COMPONENT_AREA_TOP_PERCENT = 8.5;
LED_COMPONENT_AREA_LEFT_PERCENT = 62.6;
LED_COMPONENT_AREA_WIDTH_PERCENT = 1.5;
LED_COMPONENT_AREA_HEIGHT_PERCENT = 4;
FLASH_MEMORY_COMPONENT_VISIBLE = true;
FLASH_MEMORY_COMPONENT_HAS_PANEL = true;
FLASH_MEMORY_COMPONENT_HAS_ARROW = true;
FLASH_MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
FLASH_MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
FLASH_MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 45;
FLASH_MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 36;
FLASH_MEMORY_COMPONENT_ARROW_PERCENT = 38;
FLASH_MEMORY_COMPONENT_AREA_TOP_PERCENT = 36.3;
FLASH_MEMORY_COMPONENT_AREA_LEFT_PERCENT = 38.8;
FLASH_MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 5.4;
FLASH_MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 8;
// Capabilities
SUPPORTS_VIDEO_BRIGHTNESS = false;
// Constructor.
constructor(deviceData) {
super(CCIMX8MNANO.DEVICE_TYPE, CCIMX8MNANO.PLATFORM_NAME, deviceData);
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class CCIMX8MMINI extends ConnectCoreDevice {
// Public constants.
static DEVICE_TYPE = "ccimx8mm-dvk";
static PLATFORM_NAME = "ConnectCore 8M-Mini DVK";
// Variables.
BOARD_IMAGE = "ccimx8m-mini_board.png";
BOARD_IMAGE_SCALE = 85;
CPU_COMPONENT_VISIBLE = true;
CPU_COMPONENT_HAS_PANEL = true;
CPU_COMPONENT_HAS_ARROW = true;
CPU_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CPU_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
CPU_COMPONENT_PANEL_HORIZONTAL_PERCENT = 28.5;
CPU_COMPONENT_PANEL_VERTICAL_PERCENT = 57;
CPU_COMPONENT_ARROW_PERCENT = 33.5;
CPU_COMPONENT_AREA_TOP_PERCENT = 45.7;
CPU_COMPONENT_AREA_LEFT_PERCENT = 32.4;
CPU_COMPONENT_AREA_WIDTH_PERCENT = 5.7;
CPU_COMPONENT_AREA_HEIGHT_PERCENT = 9;
MEMORY_COMPONENT_VISIBLE = true;
MEMORY_COMPONENT_HAS_PANEL = true;
MEMORY_COMPONENT_HAS_ARROW = true;
MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 22;
MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 65;
MEMORY_COMPONENT_ARROW_PERCENT = 33.7;
MEMORY_COMPONENT_AREA_TOP_PERCENT = 37;
MEMORY_COMPONENT_AREA_LEFT_PERCENT = 32.4;
MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 6;
MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 7;
WIFI_BT_COMPONENT_VISIBLE = true;
WIFI_BT_COMPONENT_HAS_PANEL = true;
WIFI_BT_COMPONENT_HAS_ARROW = true;
WIFI_BT_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
WIFI_BT_COMPONENT_PANEL_ORIENTATION = VALUE_RIGHT;
WIFI_BT_COMPONENT_PANEL_HORIZONTAL_PERCENT = 73;
WIFI_BT_COMPONENT_PANEL_VERTICAL_PERCENT = 38;
WIFI_BT_COMPONENT_ARROW_PERCENT = 46;
WIFI_BT_COMPONENT_AREA_TOP_PERCENT = 46.5;
WIFI_BT_COMPONENT_AREA_LEFT_PERCENT = 28.3;
WIFI_BT_COMPONENT_AREA_WIDTH_PERCENT = 4;
WIFI_BT_COMPONENT_AREA_HEIGHT_PERCENT = 6;
ETHERNET_COMPONENT_VISIBLE = true;
ETHERNET_COMPONENT_HAS_PANEL = true;
ETHERNET_COMPONENT_HAS_ARROW = true;
ETHERNET_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
ETHERNET_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
ETHERNET_COMPONENT_PANEL_HORIZONTAL_PERCENT = 21;
ETHERNET_COMPONENT_PANEL_VERTICAL_PERCENT = 70;
ETHERNET_COMPONENT_ARROW_PERCENT = 78;
ETHERNET_COMPONENT_AREA_TOP_PERCENT = 77;
ETHERNET_COMPONENT_AREA_LEFT_PERCENT = 11;
ETHERNET_COMPONENT_AREA_WIDTH_PERCENT = 8.5;
ETHERNET_COMPONENT_AREA_HEIGHT_PERCENT = 16;
CONSOLE_COMPONENT_VISIBLE = true;
CONSOLE_COMPONENT_HAS_PANEL = false;
CONSOLE_COMPONENT_HAS_ARROW = false;
CONSOLE_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CONSOLE_COMPONENT_AREA_TOP_PERCENT = 6.5;
CONSOLE_COMPONENT_AREA_LEFT_PERCENT = 26.5;
CONSOLE_COMPONENT_AREA_WIDTH_PERCENT = 3.4;
CONSOLE_COMPONENT_AREA_HEIGHT_PERCENT = 4.5;
VIDEO_COMPONENT_VISIBLE = true;
VIDEO_COMPONENT_HAS_PANEL = true;
VIDEO_COMPONENT_HAS_ARROW = true;
VIDEO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
VIDEO_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
VIDEO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 47.5;
VIDEO_COMPONENT_PANEL_VERTICAL_PERCENT = 18;
VIDEO_COMPONENT_ARROW_PERCENT = 58.5;
VIDEO_COMPONENT_AREA_TOP_PERCENT = 84;
VIDEO_COMPONENT_AREA_LEFT_PERCENT = 57;
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 6;
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 8;
AUDIO_COMPONENT_VISIBLE = false;
AUDIO_COMPONENT_HAS_PANEL = true;
AUDIO_COMPONENT_HAS_ARROW = true;
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 1;
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 19;
AUDIO_COMPONENT_ARROW_PERCENT = 16;
AUDIO_COMPONENT_AREA_TOP_PERCENT = 7;
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 14.5;
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 5.4;
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 11;
LED_COMPONENT_VISIBLE = true;
LED_COMPONENT_HAS_PANEL = true;
LED_COMPONENT_HAS_ARROW = false;
LED_COMPONENT_PANEL_ALWAYS_VISIBLE = true;
LED_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
LED_COMPONENT_PANEL_HORIZONTAL_PERCENT = 61;
LED_COMPONENT_PANEL_VERTICAL_PERCENT = 14;
LED_COMPONENT_AREA_TOP_PERCENT = 8.5;
LED_COMPONENT_AREA_LEFT_PERCENT = 62.6;
LED_COMPONENT_AREA_WIDTH_PERCENT = 1.5;
LED_COMPONENT_AREA_HEIGHT_PERCENT = 4;
FLASH_MEMORY_COMPONENT_VISIBLE = true;
FLASH_MEMORY_COMPONENT_HAS_PANEL = true;
FLASH_MEMORY_COMPONENT_HAS_ARROW = true;
FLASH_MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
FLASH_MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
FLASH_MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 45;
FLASH_MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 36;
FLASH_MEMORY_COMPONENT_ARROW_PERCENT = 38;
FLASH_MEMORY_COMPONENT_AREA_TOP_PERCENT = 36.3;
FLASH_MEMORY_COMPONENT_AREA_LEFT_PERCENT = 38.8;
FLASH_MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 5.4;
FLASH_MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 8;
// Capabilities
SUPPORTS_VIDEO_BRIGHTNESS = false;
// Constructor.
constructor(deviceData) {
super(CCIMX8MMINI.DEVICE_TYPE, CCIMX8MMINI.PLATFORM_NAME, deviceData);
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class CCIMX8X extends ConnectCoreDevice {
// Public constants.
static DEVICE_TYPE = "ccimx8x-sbc-pro";
static PLATFORM_NAME = "ConnectCore 8X SBC Pro";
// Variables.
BOARD_IMAGE = "ccimx8x-sbc-pro_board.png";
BOARD_IMAGE_SCALE = 60;
CPU_COMPONENT_VISIBLE = true;
CPU_COMPONENT_HAS_PANEL = true;
CPU_COMPONENT_HAS_ARROW = true;
CPU_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CPU_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
CPU_COMPONENT_PANEL_HORIZONTAL_PERCENT = 49;
CPU_COMPONENT_PANEL_VERTICAL_PERCENT = 65;
CPU_COMPONENT_ARROW_PERCENT = 62;
CPU_COMPONENT_AREA_TOP_PERCENT = 40;
CPU_COMPONENT_AREA_LEFT_PERCENT = 54;
CPU_COMPONENT_AREA_WIDTH_PERCENT = 19.5;
CPU_COMPONENT_AREA_HEIGHT_PERCENT = 24;
MEMORY_COMPONENT_VISIBLE = true;
MEMORY_COMPONENT_HAS_PANEL = true;
MEMORY_COMPONENT_HAS_ARROW = true;
MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_RIGHT;
MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 43;
MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 22.5;
MEMORY_COMPONENT_ARROW_PERCENT = 29;
MEMORY_COMPONENT_AREA_TOP_PERCENT = 22.25;
MEMORY_COMPONENT_AREA_LEFT_PERCENT = 57.75;
MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 9.5;
MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 16.5;
WIFI_BT_COMPONENT_VISIBLE = true;
WIFI_BT_COMPONENT_HAS_PANEL = true;
WIFI_BT_COMPONENT_HAS_ARROW = true;
WIFI_BT_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
WIFI_BT_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
WIFI_BT_COMPONENT_PANEL_HORIZONTAL_PERCENT = 83;
WIFI_BT_COMPONENT_PANEL_VERTICAL_PERCENT = 35;
WIFI_BT_COMPONENT_ARROW_PERCENT = 41;
WIFI_BT_COMPONENT_AREA_TOP_PERCENT = 38;
WIFI_BT_COMPONENT_AREA_LEFT_PERCENT = 73.5;
WIFI_BT_COMPONENT_AREA_WIDTH_PERCENT = 8.5;
WIFI_BT_COMPONENT_AREA_HEIGHT_PERCENT = 10;
ETHERNET_COMPONENT_VISIBLE = true;
ETHERNET_COMPONENT_HAS_PANEL = true;
ETHERNET_COMPONENT_HAS_ARROW = true;
ETHERNET_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
ETHERNET_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
ETHERNET_COMPONENT_PANEL_HORIZONTAL_PERCENT = -7;
ETHERNET_COMPONENT_PANEL_VERTICAL_PERCENT = 34;
ETHERNET_COMPONENT_ARROW_PERCENT = 18;
ETHERNET_COMPONENT_AREA_TOP_PERCENT = 68;
ETHERNET_COMPONENT_AREA_LEFT_PERCENT = 12;
ETHERNET_COMPONENT_AREA_WIDTH_PERCENT = 17;
ETHERNET_COMPONENT_AREA_HEIGHT_PERCENT = 27;
CONSOLE_COMPONENT_VISIBLE = true;
CONSOLE_COMPONENT_HAS_PANEL = false;
CONSOLE_COMPONENT_HAS_ARROW = false;
CONSOLE_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CONSOLE_COMPONENT_AREA_TOP_PERCENT = 22.5;
CONSOLE_COMPONENT_AREA_LEFT_PERCENT = 86;
CONSOLE_COMPONENT_AREA_WIDTH_PERCENT = 7;
CONSOLE_COMPONENT_AREA_HEIGHT_PERCENT = 4.5;
VIDEO_COMPONENT_VISIBLE = true;
VIDEO_COMPONENT_HAS_PANEL = true;
VIDEO_COMPONENT_HAS_ARROW = true;
VIDEO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
VIDEO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
VIDEO_COMPONENT_PANEL_HORIZONTAL_PERCENT = -15;
VIDEO_COMPONENT_PANEL_VERTICAL_PERCENT = 18;
VIDEO_COMPONENT_ARROW_PERCENT = 20.75;
VIDEO_COMPONENT_AREA_TOP_PERCENT = 8.5;
VIDEO_COMPONENT_AREA_LEFT_PERCENT = 8.75;
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 27.5;
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 7.5;
AUDIO_COMPONENT_VISIBLE = false;
AUDIO_COMPONENT_HAS_PANEL = true;
AUDIO_COMPONENT_HAS_ARROW = true;
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 1;
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 19;
AUDIO_COMPONENT_ARROW_PERCENT = 16;
AUDIO_COMPONENT_AREA_TOP_PERCENT = 7;
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 14.5;
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 5.4;
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 11;
LED_COMPONENT_VISIBLE = true;
LED_COMPONENT_HAS_PANEL = true;
LED_COMPONENT_HAS_ARROW = false;
LED_COMPONENT_PANEL_ALWAYS_VISIBLE = true;
LED_COMPONENT_PANEL_ORIENTATION = VALUE_LEFT;
LED_COMPONENT_PANEL_HORIZONTAL_PERCENT = 30;
LED_COMPONENT_PANEL_VERTICAL_PERCENT = 52;
LED_COMPONENT_AREA_TOP_PERCENT = 53.5;
LED_COMPONENT_AREA_LEFT_PERCENT = 27;
LED_COMPONENT_AREA_WIDTH_PERCENT = 2.5;
LED_COMPONENT_AREA_HEIGHT_PERCENT = 5;
FLASH_MEMORY_COMPONENT_VISIBLE = true;
FLASH_MEMORY_COMPONENT_HAS_PANEL = true;
FLASH_MEMORY_COMPONENT_HAS_ARROW = true;
FLASH_MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
FLASH_MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_BOTTOM;
FLASH_MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 57.5;
FLASH_MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 79.5;
FLASH_MEMORY_COMPONENT_ARROW_PERCENT = 71.5;
FLASH_MEMORY_COMPONENT_AREA_TOP_PERCENT = 22.25;
FLASH_MEMORY_COMPONENT_AREA_LEFT_PERCENT = 68;
FLASH_MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 10.8;
FLASH_MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 15;
// Capabilities
SUPPORTS_VIDEO_BRIGHTNESS = false;
// Constructor.
constructor(deviceData) {
super(CCIMX8X.DEVICE_TYPE, CCIMX8X.PLATFORM_NAME, deviceData);
}
}

View File

@ -0,0 +1,11 @@
/*\
|*| ========================================================================
|*| Bootstrap Toggle: bootstrap4-toggle.js v3.6.1
|*| https://gitbrent.github.io/bootstrap4-toggle/
|*| ========================================================================
|*| Copyright 2018-2019 Brent Ely
|*| Licensed under MIT
|*| ========================================================================
\*/
!function(a){"use strict";function l(t,e){this.$element=a(t),this.options=a.extend({},this.defaults(),e),this.render()}l.VERSION="3.6.0",l.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"light",size:"normal",style:"",width:null,height:null},l.prototype.defaults=function(){return{on:this.$element.attr("data-on")||l.DEFAULTS.on,off:this.$element.attr("data-off")||l.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||l.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||l.DEFAULTS.offstyle,size:this.$element.attr("data-size")||l.DEFAULTS.size,style:this.$element.attr("data-style")||l.DEFAULTS.style,width:this.$element.attr("data-width")||l.DEFAULTS.width,height:this.$element.attr("data-height")||l.DEFAULTS.height}},l.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var t="large"===this.options.size||"lg"===this.options.size?"btn-lg":"small"===this.options.size||"sm"===this.options.size?"btn-sm":"mini"===this.options.size||"xs"===this.options.size?"btn-xs":"",e=a('<label for="'+this.$element.prop("id")+'" class="btn">').html(this.options.on).addClass(this._onstyle+" "+t),s=a('<label for="'+this.$element.prop("id")+'" class="btn">').html(this.options.off).addClass(this._offstyle+" "+t),o=a('<span class="toggle-handle btn btn-light">').addClass(t),i=a('<div class="toggle-group">').append(e,s,o),l=a('<div class="toggle btn" data-toggle="toggle" role="button">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(t).addClass(this.options.style);this.$element.wrap(l),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:e,$toggleOff:s,$toggleGroup:i}),this.$toggle.append(i);var n=this.options.width||Math.max(e.outerWidth(),s.outerWidth())+o.outerWidth()/2,h=this.options.height||Math.max(e.outerHeight(),s.outerHeight());e.addClass("toggle-on"),s.addClass("toggle-off"),this.$toggle.css({width:n,height:h}),this.options.height&&(e.css("line-height",e.height()+"px"),s.css("line-height",s.height()+"px")),this.update(!0),this.trigger(!0)},l.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},l.prototype.on=function(t){if(this.$element.prop("disabled"))return!1;this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),t||this.trigger()},l.prototype.off=function(t){if(this.$element.prop("disabled"))return!1;this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),t||this.trigger()},l.prototype.enable=function(){this.$toggle.removeClass("disabled"),this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},l.prototype.disable=function(){this.$toggle.addClass("disabled"),this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},l.prototype.update=function(t){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(t):this.off(t)},l.prototype.trigger=function(t){this.$element.off("change.bs.toggle"),t||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},l.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var t=a.fn.bootstrapToggle;a.fn.bootstrapToggle=function(o){var i=Array.prototype.slice.call(arguments,1)[0];return this.each(function(){var t=a(this),e=t.data("bs.toggle"),s="object"==typeof o&&o;e||t.data("bs.toggle",e=new l(this,s)),"string"==typeof o&&e[o]&&"boolean"==typeof i?e[o](i):"string"==typeof o&&e[o]&&e[o]()})},a.fn.bootstrapToggle.Constructor=l,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=t,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(t){a(this).find("input[type=checkbox]").bootstrapToggle("toggle"),t.preventDefault()})}(jQuery);
//# sourceMappingURL=bootstrap4-toggle.min.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,482 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// Constants.
const ID_AREA = "area";
const ID_AREA_HEIGHT = "area-height";
const ID_AREA_LEFT_MARGIN = "area-left-margin";
const ID_AREA_TOP_MARGIN = "area-top-margin";
const ID_AREA_WIDTH = "area-width";
const ID_ARROW = "arrow";
const ID_ARROW_MARGIN = "arrow-margin";
const ID_AUDIO = "audio";
const ID_BLUETOOTH_MAC = "bluetooth_mac";
const ID_BOARD_ID = "board_id";
const ID_BOARD_VARIANT = "board_variant";
const ID_BT_READ_DATA = "bluetooth_received_data";
const ID_BT_SENT_DATA = "bluetooth_sent_data";
const ID_BT_STATE = "bluetooth_state";
const ID_CONSOLE = "console";
const ID_CONFIRM_DIALOG = "confirm_dialog";
const ID_CONFIRM_DIALOG_MESSAGE = "confirm_dialog_message";
const ID_CONFIRM_DIALOG_NO_BUTTON = "confirm_dialog_no_button";
const ID_CONFIRM_DIALOG_TITLE = "confirm_dialog_title";
const ID_CONFIRM_DIALOG_YES_BUTTON = "confirm_dialog_yes_button";
const ID_CPU = "cpu";
const ID_CPU_FREQUENCY = "cpu_frequency";
const ID_CPU_LOAD = "cpu_load";
const ID_CPU_TEMPERATURE = "cpu_temperature";
const ID_CPU_UPTIME = "cpu_uptime";
const ID_CURRENT_DIR = "current_dir";
const ID_DATA = "data";
const ID_DEVICE_NAME = "device-name";
const ID_DEVICE_TYPE = "device_type";
const ID_DEVICES = "devices";
const ID_DEY_VERSION = "dey_version";
const ID_ERROR = "error";
const ID_ERROR_GUIDE = "error_guide";
const ID_ERROR_MESSAGE = "error_msg";
const ID_ERROR_TITLE = "error_title";
const ID_ETHERNET = "ethernet";
const ID_ETHERNET_IP = "ethernet_ip";
const ID_ETHERNET_MAC = "ethernet_mac";
const ID_ETHERNET_READ_DATA = "ethernet_received_data";
const ID_ETHERNET_SENT_DATA = "ethernet_sent_data";
const ID_ETHERNET_STATE = "ethernet_state";
const ID_FILES = "files";
const ID_FLASH_MEMORY = "flash_memory";
const ID_FLASH_SIZE = "flash_size";
const ID_FW_STORE_PATH = "fw_store_path";
const ID_HAS_ARROW = "has-arrow";
const ID_HAS_PANEL = "has-panel";
const ID_ICON = "icon";
const ID_ID = "id";
const ID_INFO_POPUP = "info_popup";
const ID_INFO_POPUP_MESSAGE = "info_popup_message";
const ID_INFO_POPUP_TITLE = "info_popup_title";
const ID_KERNEL_VERSION = "kernel_version";
const ID_LAST_MODIFIED = "last_modified";
const ID_LED = "led";
const ID_LOADING_POPUP = "loading_popup";
const ID_LOADING_POPUP_MESSAGE = "loading_popup_message";
const ID_LOADING_WRAPPER = "loading_wrapper";
const ID_MCA_FW_VERSION = "mca_fw_version";
const ID_MCA_HW_VERSION = "mca_hw_version";
const ID_MEMORY = "memory";
const ID_MEMORY_FREE = "memory_free";
const ID_MEMORY_TOTAL = "memory_total";
const ID_MEMORY_USED = "memory_used";
const ID_MESSAGE = "message";
const ID_MODULE_VARIANT = "module_variant";
const ID_NAME = "name";
const ID_NUM_SAMPLES_UPLOAD = "num_samples_upload";
const ID_ONLINE = "online";
const ID_PANEL = "panel";
const ID_PANEL_ALWAYS_VISIBLE = "panel-always-visible";
const ID_PANEL_HORIZONTAL_MARGIN = "panel-horizontal-margin";
const ID_PANEL_ORIENTATION = "panel-orientation";
const ID_PANEL_VERTICAL_MARGIN = "panel-vertical-margin";
const ID_PATH = "path";
const ID_PROGRESS = "progress";
const ID_SAMPLE_RATE = "sample_rate";
const ID_SERIAL_NUMBER = "serial_number";
const ID_SESSION_ID = "session_id";
const ID_SIZE = "size";
const ID_STATUS = "status";
const ID_STREAM = "stream";
const ID_TIMESTAMP = "timestamp";
const ID_TYPE = "type";
const ID_UBOOT_VERSION = "uboot_version";
const ID_VALUE = "value";
const ID_VIDEO = "video";
const ID_VIDEO_RESOLUTION = "video_resolution";
const ID_VISIBLE = "visible";
const ID_WIFI_BT = "wifi-bt";
const ID_WIFI_IP = "wifi_ip";
const ID_WIFI_MAC = "wifi_mac";
const ID_WIFI_READ_DATA = "wifi_received_data";
const ID_WIFI_SENT_DATA = "wifi_sent_data";
const ID_WIFI_STATE = "wifi_state";
const VALUE_ACTIVE = "active";
const VALUE_ABORT = "abort";
const VALUE_BOTTOM = "bottom";
const VALUE_CANCELED = "canceled";
const VALUE_FAILED = "failed";
const VALUE_LEFT = "left";
const VALUE_OFF = "Off";
const VALUE_ON = "On";
const VALUE_RIGHT = "right";
const VALUE_SUCCESSFUL = "successful";
const VALUE_TOP = "top";
const VALUE_UNKNOWN = "unknown";
const CLASS_D_NONE = "d-none";
const CLASS_DISABLED_DIV = "disabled-div";
const CLASS_ELEMENT_GRAYED = "element-grayed";
const CLASS_SELECTED = "selected";
const CLASS_VALUE_ANIMATION = "value-animation";
const CLASS_VALUE_UPDATED = "value-updated";
const ERROR_ABORTED = "Operation aborted";
const ERROR_URL_NOT_FOUND = "Requested URL not found";
const ERROR_SERVER_ERROR = "Internal server error";
const ERROR_TITLE = "Error";
const ERROR_UNKNOWN_ERROR = "Unknown error";
const PREFIX_STREAM = "system_monitor/";
const STREAM_CPU_LOAD = PREFIX_STREAM + "cpu_load";
const STREAM_MEMORY_FREE = PREFIX_STREAM + "free_memory";
const PATH_IMAGES = "../static/images/";
const PORT = "9090";
String.prototype.format = function() {
var formatted = this;
for (var arg in arguments)
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
return formatted;
};
// Updates the value of the given element ID.
function updateValueWithEffect(elementID, value) {
// Initialize variables.
var htmlElement = document.getElementById(elementID);
// Sanity checks.
if (htmlElement == null || htmlElement == "undefined" || value == null)
return;
// Apply value and classes.
htmlElement.classList.add(CLASS_VALUE_UPDATED);
htmlElement.innerText = value;
htmlElement.classList.add(CLASS_VALUE_ANIMATION);
setTimeout(function() {
htmlElement.classList.remove(CLASS_VALUE_UPDATED);
setTimeout(function() {
htmlElement.classList.remove(CLASS_VALUE_ANIMATION);
}, 3000);
}, 2000);
}
// Returns the server address.
function getServerAddress() {
var host = window.location.hostname;
if (!Boolean(host))
host = "127.0.0.1";
return host + ":" + PORT;
}
function is_local_access() {
var host = window.location.hostname;
return !Boolean(host) || host == "127.0.0.1" || host == "localhost";
}
// Shows/hides a front popup over the given background element.
function showPopup(backElementID, frontElementID, visible) {
// Initialize variables.
var backElement = document.getElementById(backElementID);
var frontElement = document.getElementById(frontElementID);
// Sanity checks.
if (backElement == null || frontElement == null)
return;
// Show/Hide the popup.
if (visible) {
if (!backElement.classList.contains(CLASS_ELEMENT_GRAYED))
backElement.classList.add(CLASS_ELEMENT_GRAYED);
if (frontElement.classList.contains(CLASS_D_NONE))
frontElement.classList.remove(CLASS_D_NONE);
} else {
if (backElement.classList.contains(CLASS_ELEMENT_GRAYED))
backElement.classList.remove(CLASS_ELEMENT_GRAYED);
if (!frontElement.classList.contains(CLASS_D_NONE))
frontElement.classList.add(CLASS_D_NONE);
}
}
// Redirects to the login page.
function redirectToLogin() {
var url = "/access/login?dest=" + window.location.pathname.replaceAll("/", "");
var params = new URLSearchParams(window.location.search);
for (let param of params)
url += "&" + param[0] + "=" + param[1];
window.location.href = url;
}
// Processes the error response of the AJAX request.
function processAjaxErrorResponse(response) {
// Check common error codes.
if (response.status == 401)
redirectToLogin();
var errorMessage = "";
if (response.statusText == VALUE_ABORT)
errorMessage = ERROR_ABORTED;
else if (response.status == 400) {
errorMessage = response.responseJSON[ID_ERROR];
// Show the error message (if any).
if (errorMessage == null)
errorMessage = ERROR_UNKNOWN_ERROR;
} else if (response.status == 404)
errorMessage = ERROR_URL_NOT_FOUND;
else if (response.status == 500)
errorMessage = ERROR_SERVER_ERROR;
else
errorMessage = ERROR_UNKNOWN_ERROR;
// Show toast with the error message.
toastr.error(errorMessage);
// Return the error message.
return errorMessage;
}
// Check if there is any error in the response.
function checkErrorResponse(response, showErrorDialog) {
if (response[ID_ERROR_MESSAGE] != null || response[ID_ERROR] != null) {
// Process error.
var errorTitle = ERROR_TITLE;
var errorMessage = getErrorFromResponse(response);
if (response[ID_ERROR_TITLE] != null)
errorTitle = response[ID_ERROR_TITLE];
// Show toast error.
if (errorMessage != null && errorMessage != "")
toastr.error(errorMessage);
// Hide the loading panel.
showLoadingPopup(false);
// Show error dialog.
if (showErrorDialog)
showInfoPopup(true, errorTitle, errorMessage);
// There was an error, return true.
return true;
}
// No error found.
return false;
}
// Returns the error message from the response.
function getErrorFromResponse(response) {
var error = "";
if (response[ID_ERROR_MESSAGE] != null || response[ID_ERROR] != null) {
if (response[ID_ERROR_MESSAGE] != null) {
error = response[ID_ERROR_MESSAGE];
if (response[ID_ERROR_GUIDE] != null)
error += response[ID_ERROR_GUIDE];
} else
error = response[ID_ERROR];
}
return error;
}
// Shows/hides the loading popup panel.
function showLoadingPopup(visible, message=null) {
// Set loading message only if it is not null and the popup will be visible.
if (visible && message != null)
document.getElementById(ID_LOADING_POPUP_MESSAGE).innerHTML = message;
// Show/Hide the popup.
showPopup(ID_LOADING_WRAPPER, ID_LOADING_POPUP, visible);
}
// Shows/hides the info popup panel.
function showInfoPopup(visible, tittle=null, message=null) {
// Set title and message.
if (visible && tittle != null && message != null) {
// Initialize vars.
var infoPopupTittleElement = document.getElementById(ID_INFO_POPUP_TITLE);
var infoPopupMessageElement = document.getElementById(ID_INFO_POPUP_MESSAGE);
// Set the info title.
if (infoPopupTittleElement != null)
infoPopupTittleElement.innerHTML = tittle;
// Set the info message.
if (infoPopupMessageElement != null)
infoPopupMessageElement.innerHTML = message;
}
// Show/Hide the popup.
showPopup(ID_LOADING_WRAPPER, ID_INFO_POPUP, visible);
}
// Shows the confirm dialog.
function showConfirmDialog(title, message, yesCallback, noCallback) {
// Initialize variables.
var confirmDialogTitleElement = document.getElementById(ID_CONFIRM_DIALOG_TITLE);
var confirmDialogMessageElement = document.getElementById(ID_CONFIRM_DIALOG_MESSAGE);
var confirmDialogYesButtonElement = document.getElementById(ID_CONFIRM_DIALOG_YES_BUTTON);
var confirmDialogNoButtonElement = document.getElementById(ID_CONFIRM_DIALOG_NO_BUTTON);
// Check if the elements are valid.
if (confirmDialogTitleElement != null && confirmDialogMessageElement != null &&
confirmDialogYesButtonElement != null && confirmDialogNoButtonElement != null) {
// Set the dialog title.
confirmDialogTitleElement.innerHTML = title;
// Set the dialog message.
confirmDialogMessageElement.innerHTML = message;
// Show the dialog.
showPopup(ID_LOADING_WRAPPER, ID_CONFIRM_DIALOG, true);
// Set the yes button callback.
confirmDialogYesButtonElement.onclick = function() {
// Hide the dialog.
showPopup(ID_LOADING_WRAPPER, ID_CONFIRM_DIALOG, false);
// Call the callback.
if (yesCallback != null)
yesCallback();
};
// Set the no button callback.
confirmDialogNoButtonElement.onclick = function() {
// Hide the dialog.
showPopup(ID_LOADING_WRAPPER, ID_CONFIRM_DIALOG, false);
// Call the callback.
if (noCallback != null)
noCallback();
};
}
}
// Transforms the given ISO8601 date to human readable date.
function transformDate(iso8601Date) {
// Initialize variables.
var date = new Date(iso8601Date);
var humanReadableDate = "";
// Check if the date is valid.
if (date != null) {
// Transform the date to human readable date.
humanReadableDate = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " +
date.getHours().toString().padStart(2, '0') + ":" + date.getMinutes().toString().padStart(2, '0');
}
// Return the human readable date.
return humanReadableDate;
}
// Transforms the given kilo-bytes to mega-bytes
function kiloBytesToMegaBytes(kiloBytes) {
return (kiloBytes / 1024).toFixed(2);
}
// Format bytes as human-readable text.
function sizeToHumanRead(bytes, si=true, dp=2) {
// Initialize variables.
var threshold = si ? 1000 : 1024;
var units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var unit = -1;
// Check if minimum threshold is reached.
if (Math.abs(bytes) < threshold)
return bytes + ' Bytes';
const r = 10**dp;
do {
bytes /= threshold;
++unit;
} while (Math.round(Math.abs(bytes) * r) / r >= threshold && unit < units.length - 1);
return bytes.toFixed(dp) + ' ' + units[unit];
}
// Rounds the given number to two decimals.
function roundToTwoDecimals(number) {
return Math.round(number * 100) / 100;
}
// Returns human readable time from the given seconds.
function secondsToTime(numSeconds) {
// Initialize variables.
var days = 0;
var hours = 0;
var minutes = 0;
var seconds = 0;
// Calculate the time values.
if (numSeconds < 60)
seconds = numSeconds;
else if (numSeconds < (60 * 60)) {
minutes = Math.floor(numSeconds / 60);
seconds = numSeconds % 60;
} else if (numSeconds < (60 * 60 * 24)) {
hours = Math.floor(numSeconds / (60 * 60));
minutes = Math.floor((numSeconds % (60 * 60)) / 60);
seconds = numSeconds % 60;
} else {
days = Math.floor(numSeconds / (60 * 60 * 24));
hours = Math.floor((numSeconds % (60 * 60 * 24)) / (60 * 60));
minutes = Math.floor((numSeconds % (60 * 60)) / 60);
seconds = numSeconds % 60;
}
// Build time string.
var time = "";
var numFields = 0;
if (days > 0) {
time += days + " day";
if (days > 1)
time += "s";
time += " ";
numFields += 1;
}
if (hours > 0) {
time += hours + " hour";
if (hours > 1)
time += "s";
time += " ";
numFields += 1;
}
if (minutes > 0 && numFields < 2) {
time += minutes + " minute";
if (minutes > 1)
time += "s";
time += " ";
numFields += 1;
}
if ((seconds > 0 && numFields < 2) || time == "") {
time += seconds + " second";
if (seconds > 1)
time += "s";
}
// Return the time string.
return time;
}
// Returns on/off status from the given integer.
function onOffStatus(status) {
return status == 1 ? VALUE_ON : VALUE_OFF;
}
// Updates the given field ID with the given value.
function updateFieldValue(fieldID, value) {
var fieldElement = document.getElementById(fieldID);
if (fieldElement != null && fieldElement != "undefined")
fieldElement.innerText = value;
}
// Rounds the given amount of kilo-bytes to giga bytes.
function roundToGigaBytes(kiloBytes) {
return (kiloBytes / (1024 * 1024)).toFixed(2);
}
// Returns whether the dashboard page is showing or not.
function isDashboardShowing() {
if (window.location.pathname == "/")
return true;
return window.location.pathname.indexOf("index") > -1;
}
// Returns whether the management page is showing or not.
function isManagementShowing() {
return window.location.pathname.indexOf("management") > -1;
}
// Returns whether the multimedia page is showing or not.
function isMultimediaShowing() {
return window.location.pathname.indexOf("multimedia") > -1;
}
// Returns the device name.
function getDeviceName() {
return new URLSearchParams(window.location.search).get(ID_DEVICE_NAME);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,492 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// Constants.
const TEMPLATE_COMPONENT_DATA = "" +
"{" +
" \"" + ID_VISIBLE + "\" : {0}," +
" \"" + ID_HAS_PANEL + "\" : {1}," +
" \"" + ID_HAS_ARROW + "\" : {2}," +
" \"" + ID_PANEL_ALWAYS_VISIBLE + "\" : {3}," +
" \"" + ID_PANEL_ORIENTATION + "\" : \"{4}\"," +
" \"" + ID_PANEL_HORIZONTAL_MARGIN + "\" : {5}," +
" \"" + ID_PANEL_VERTICAL_MARGIN + "\" : {6}," +
" \"" + ID_ARROW_MARGIN + "\" : {7}," +
" \"" + ID_AREA_TOP_MARGIN + "\" : {8}," +
" \"" + ID_AREA_LEFT_MARGIN + "\" : {9}," +
" \"" + ID_AREA_WIDTH + "\" : {10}," +
" \"" + ID_AREA_HEIGHT + "\" : {11}" +
"}"
// Class that represents a ConnectCore device.
class ConnectCoreDevice {
// Variables
// Board image.
BOARD_IMAGE;
BOARD_IMAGE_SCALE;
// CPU panel.
CPU_COMPONENT_VISIBLE = false;
CPU_COMPONENT_HAS_PANEL = false;
CPU_COMPONENT_HAS_ARROW = false;
CPU_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CPU_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
CPU_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
CPU_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
CPU_COMPONENT_ARROW_PERCENT = 0;
CPU_COMPONENT_AREA_TOP_PERCENT = 0;
CPU_COMPONENT_AREA_LEFT_PERCENT = 0;
CPU_COMPONENT_AREA_WIDTH_PERCENT = 0;
CPU_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Memory panel.
MEMORY_COMPONENT_VISIBLE = false;
MEMORY_COMPONENT_HAS_PANEL = false;
MEMORY_COMPONENT_HAS_ARROW = false;
MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
MEMORY_COMPONENT_ARROW_PERCENT = 0;
MEMORY_COMPONENT_AREA_TOP_PERCENT = 0;
MEMORY_COMPONENT_AREA_LEFT_PERCENT = 0;
MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 0;
MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// WiFi/BT panel.
WIFI_BT_COMPONENT_VISIBLE = false;
WIFI_BT_COMPONENT_HAS_PANEL = false;
WIFI_BT_COMPONENT_HAS_ARROW = false;
WIFI_BT_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
WIFI_BT_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
WIFI_BT_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
WIFI_BT_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
WIFI_BT_COMPONENT_ARROW_PERCENT = 0;
WIFI_BT_COMPONENT_AREA_TOP_PERCENT = 0;
WIFI_BT_COMPONENT_AREA_LEFT_PERCENT = 0;
WIFI_BT_COMPONENT_AREA_WIDTH_PERCENT = 0;
WIFI_BT_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Ethernet panel.
ETHERNET_COMPONENT_VISIBLE = false;
ETHERNET_COMPONENT_HAS_PANEL = false;
ETHERNET_COMPONENT_HAS_ARROW = false;
ETHERNET_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
ETHERNET_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
ETHERNET_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
ETHERNET_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
ETHERNET_COMPONENT_ARROW_PERCENT = 0;
ETHERNET_COMPONENT_AREA_TOP_PERCENT = 0;
ETHERNET_COMPONENT_AREA_LEFT_PERCENT = 0;
ETHERNET_COMPONENT_AREA_WIDTH_PERCENT = 0;
ETHERNET_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Console.
CONSOLE_COMPONENT_VISIBLE = false;
CONSOLE_COMPONENT_HAS_PANEL = false;
CONSOLE_COMPONENT_HAS_ARROW = false;
CONSOLE_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
CONSOLE_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
CONSOLE_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
CONSOLE_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
CONSOLE_COMPONENT_ARROW_PERCENT = 0;
CONSOLE_COMPONENT_AREA_TOP_PERCENT = 0;
CONSOLE_COMPONENT_AREA_LEFT_PERCENT = 0;
CONSOLE_COMPONENT_AREA_WIDTH_PERCENT = 0;
CONSOLE_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Video panel.
VIDEO_COMPONENT_VISIBLE = false;
VIDEO_COMPONENT_HAS_PANEL = false;
VIDEO_COMPONENT_HAS_ARROW = false;
VIDEO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
VIDEO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
VIDEO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
VIDEO_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
VIDEO_COMPONENT_ARROW_PERCENT = 0;
VIDEO_COMPONENT_AREA_TOP_PERCENT = 0;
VIDEO_COMPONENT_AREA_LEFT_PERCENT = 0;
VIDEO_COMPONENT_AREA_WIDTH_PERCENT = 0;
VIDEO_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Audio panel.
AUDIO_COMPONENT_VISIBLE = false;
AUDIO_COMPONENT_HAS_PANEL = false;
AUDIO_COMPONENT_HAS_ARROW = false;
AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
AUDIO_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
AUDIO_COMPONENT_ARROW_PERCENT = 0;
AUDIO_COMPONENT_AREA_TOP_PERCENT = 0;
AUDIO_COMPONENT_AREA_LEFT_PERCENT = 0;
AUDIO_COMPONENT_AREA_WIDTH_PERCENT = 0;
AUDIO_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// LED panel.
LED_COMPONENT_VISIBLE = false;
LED_COMPONENT_HAS_PANEL = false;
LED_COMPONENT_HAS_ARROW = false;
LED_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
LED_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
LED_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
LED_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
LED_COMPONENT_ARROW_PERCENT = 0;
LED_COMPONENT_AREA_TOP_PERCENT = 0;
LED_COMPONENT_AREA_LEFT_PERCENT = 0;
LED_COMPONENT_AREA_WIDTH_PERCENT = 0;
LED_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Flash memory panel.
FLASH_MEMORY_COMPONENT_VISIBLE = false;
FLASH_MEMORY_COMPONENT_HAS_PANEL = false;
FLASH_MEMORY_COMPONENT_HAS_ARROW = false;
FLASH_MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE = false;
FLASH_MEMORY_COMPONENT_PANEL_ORIENTATION = VALUE_TOP;
FLASH_MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT = 0;
FLASH_MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT = 0;
FLASH_MEMORY_COMPONENT_ARROW_PERCENT = 0;
FLASH_MEMORY_COMPONENT_AREA_TOP_PERCENT = 0;
FLASH_MEMORY_COMPONENT_AREA_LEFT_PERCENT = 0;
FLASH_MEMORY_COMPONENT_AREA_WIDTH_PERCENT = 0;
FLASH_MEMORY_COMPONENT_AREA_HEIGHT_PERCENT = 0;
// Capabilities
SUPPORTS_VIDEO_BRIGHTNESS;
// Device information.
#deviceType;
#platformName;
#serialNumber;
#ubootVersion;
#kernelVersion;
#deyVersion;
#moduleVariant;
#boardVariant;
#boardID;
#mcaHWVersion;
#mcaFWVersion;
#ethernetMAC;
#ethernetIP;
#wifiMAC;
#wifiIP;
#bluetoothMAC;
#memoryTotal;
#flashSize;
#videoResolution;
#sampleRate;
#numSamplesUpload;
// Class constructor.
constructor(deviceType, platformName, deviceData) {
this.#deviceType = deviceType;
this.#platformName = platformName;
this.#initDevice(deviceData);
}
// Initializes the device with the provided data.
#initDevice(deviceData) {
this.#ubootVersion = deviceData[ID_UBOOT_VERSION];
this.#serialNumber = deviceData[ID_SERIAL_NUMBER];
this.#kernelVersion = deviceData[ID_KERNEL_VERSION];
this.#deyVersion = deviceData[ID_DEY_VERSION];
this.#moduleVariant = deviceData[ID_MODULE_VARIANT];
this.#boardVariant = deviceData[ID_BOARD_VARIANT];
this.#boardID = deviceData[ID_BOARD_ID];
this.#mcaHWVersion = deviceData[ID_MCA_HW_VERSION];
this.#mcaFWVersion = deviceData[ID_MCA_FW_VERSION];
this.#ethernetMAC = deviceData[ID_ETHERNET_MAC];
this.#ethernetIP = deviceData[ID_ETHERNET_IP];
this.#wifiMAC = deviceData[ID_WIFI_MAC];
this.#wifiIP = deviceData[ID_WIFI_IP];
this.#bluetoothMAC = deviceData[ID_BLUETOOTH_MAC];
this.#memoryTotal = deviceData[ID_MEMORY_TOTAL];
this.#flashSize = deviceData[ID_FLASH_SIZE];
this.#videoResolution = deviceData[ID_VIDEO_RESOLUTION];
this.#sampleRate = deviceData[ID_SAMPLE_RATE];
this.#numSamplesUpload = deviceData[ID_NUM_SAMPLES_UPLOAD];
}
refreshIPs(eth_ip, wifi_ip) {
this.#ethernetIP = eth_ip;
this.#wifiIP = wifi_ip;
}
// Returns the device type.
getDeviceType() {
return this.#deviceType;
}
// Returns the platform name.
getPlatformName() {
return this.#platformName;
}
// Returns the device serial number.
getSerialNumber() {
return this.#serialNumber;
}
// Returns the board image file name.
getBoardImage() {
return this.BOARD_IMAGE;
}
// Returns the board image scale.
getBoardImageScale() {
return this.BOARD_IMAGE_SCALE;
}
// Returns the device U-Boot version.
getUbootVersion() {
return this.#ubootVersion;
}
// Returns the device Kernel version.
getKernelVersion() {
return this.#kernelVersion;
}
// Returns the device DEY version.
getDEYVersion() {
return this.#deyVersion;
}
// Returns the device module variant.
getModuleVariant() {
return this.#moduleVariant;
}
// Returns the device board variant.
getBoardVariant() {
return this.#boardVariant;
}
// Returns the device board ID.
getBoardID() {
return this.#boardID;
}
// Returns the device MCA hardware version.
getMCAHWVersion() {
return this.#mcaHWVersion;
}
// Returns the device MCA firmware version.
getMCAFWVersion() {
return this.#mcaFWVersion;
}
// Returns the device Ethernet MAC address.
getEthernetMAC() {
return this.#ethernetMAC;
}
// Returns the device Ethernet IP address.
getEthernetIP() {
return this.#ethernetIP;
}
// Returns the device WiFi MAC address.
getWifiMAC() {
return this.#wifiMAC;
}
// Returns the device WiFi IP address.
getWifiIP() {
return this.#wifiIP;
}
// Returns the device Bluetooth MAC address.
getBluetoothMAC() {
return this.#bluetoothMAC;
}
// Returns the device total memory.
getMemoryTotal() {
return this.#memoryTotal;
}
// Returns the device flash size.
getFlashSize() {
return this.#flashSize;
}
// Returns the video resolution.
getVideoResolution() {
return this.#videoResolution;
}
// Returns the sample rate.
getSampleRate() {
return this.#sampleRate;
}
// Returns the number of samples to upload each batch.
getNumSamplesUpload() {
return this.#numSamplesUpload;
}
// Returns the CPU panel data.
getCPUComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.CPU_COMPONENT_VISIBLE,
this.CPU_COMPONENT_HAS_PANEL,
this.CPU_COMPONENT_HAS_ARROW,
this.CPU_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.CPU_COMPONENT_PANEL_ORIENTATION,
this.CPU_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.CPU_COMPONENT_PANEL_VERTICAL_PERCENT,
this.CPU_COMPONENT_ARROW_PERCENT,
this.CPU_COMPONENT_AREA_TOP_PERCENT,
this.CPU_COMPONENT_AREA_LEFT_PERCENT,
this.CPU_COMPONENT_AREA_WIDTH_PERCENT,
this.CPU_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the Memory panel data.
getMemoryComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.MEMORY_COMPONENT_VISIBLE,
this.MEMORY_COMPONENT_HAS_PANEL,
this.MEMORY_COMPONENT_HAS_ARROW,
this.MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.MEMORY_COMPONENT_PANEL_ORIENTATION,
this.MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT,
this.MEMORY_COMPONENT_ARROW_PERCENT,
this.MEMORY_COMPONENT_AREA_TOP_PERCENT,
this.MEMORY_COMPONENT_AREA_LEFT_PERCENT,
this.MEMORY_COMPONENT_AREA_WIDTH_PERCENT,
this.MEMORY_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the WiFi panel data.
getWifiBtComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.WIFI_BT_COMPONENT_VISIBLE,
this.WIFI_BT_COMPONENT_HAS_PANEL,
this.WIFI_BT_COMPONENT_HAS_ARROW,
this.WIFI_BT_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.WIFI_BT_COMPONENT_PANEL_ORIENTATION,
this.WIFI_BT_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.WIFI_BT_COMPONENT_PANEL_VERTICAL_PERCENT,
this.WIFI_BT_COMPONENT_ARROW_PERCENT,
this.WIFI_BT_COMPONENT_AREA_TOP_PERCENT,
this.WIFI_BT_COMPONENT_AREA_LEFT_PERCENT,
this.WIFI_BT_COMPONENT_AREA_WIDTH_PERCENT,
this.WIFI_BT_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the Ethernet panel data.
getEthernetComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.ETHERNET_COMPONENT_VISIBLE,
this.ETHERNET_COMPONENT_HAS_PANEL,
this.ETHERNET_COMPONENT_HAS_ARROW,
this.ETHERNET_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.ETHERNET_COMPONENT_PANEL_ORIENTATION,
this.ETHERNET_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.ETHERNET_COMPONENT_PANEL_VERTICAL_PERCENT,
this.ETHERNET_COMPONENT_ARROW_PERCENT,
this.ETHERNET_COMPONENT_AREA_TOP_PERCENT,
this.ETHERNET_COMPONENT_AREA_LEFT_PERCENT,
this.ETHERNET_COMPONENT_AREA_WIDTH_PERCENT,
this.ETHERNET_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the Console panel data.
getConsoleComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.CONSOLE_COMPONENT_VISIBLE,
this.CONSOLE_COMPONENT_HAS_PANEL,
this.CONSOLE_COMPONENT_HAS_ARROW,
this.CONSOLE_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.CONSOLE_COMPONENT_PANEL_ORIENTATION,
this.CONSOLE_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.CONSOLE_COMPONENT_PANEL_VERTICAL_PERCENT,
this.CONSOLE_COMPONENT_ARROW_PERCENT,
this.CONSOLE_COMPONENT_AREA_TOP_PERCENT,
this.CONSOLE_COMPONENT_AREA_LEFT_PERCENT,
this.CONSOLE_COMPONENT_AREA_WIDTH_PERCENT,
this.CONSOLE_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the Video panel data.
getVideoComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.VIDEO_COMPONENT_VISIBLE,
this.VIDEO_COMPONENT_HAS_PANEL,
this.VIDEO_COMPONENT_HAS_ARROW,
this.VIDEO_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.VIDEO_COMPONENT_PANEL_ORIENTATION,
this.VIDEO_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.VIDEO_COMPONENT_PANEL_VERTICAL_PERCENT,
this.VIDEO_COMPONENT_ARROW_PERCENT,
this.VIDEO_COMPONENT_AREA_TOP_PERCENT,
this.VIDEO_COMPONENT_AREA_LEFT_PERCENT,
this.VIDEO_COMPONENT_AREA_WIDTH_PERCENT,
this.VIDEO_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the Audio panel data.
getAudioComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.AUDIO_COMPONENT_VISIBLE,
this.AUDIO_COMPONENT_HAS_PANEL,
this.AUDIO_COMPONENT_HAS_ARROW,
this.AUDIO_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.AUDIO_COMPONENT_PANEL_ORIENTATION,
this.AUDIO_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.AUDIO_COMPONENT_PANEL_VERTICAL_PERCENT,
this.AUDIO_COMPONENT_ARROW_PERCENT,
this.AUDIO_COMPONENT_AREA_TOP_PERCENT,
this.AUDIO_COMPONENT_AREA_LEFT_PERCENT,
this.AUDIO_COMPONENT_AREA_WIDTH_PERCENT,
this.AUDIO_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the LED panel data.
getLEDComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.LED_COMPONENT_VISIBLE,
this.LED_COMPONENT_HAS_PANEL,
this.LED_COMPONENT_HAS_ARROW,
this.LED_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.LED_COMPONENT_PANEL_ORIENTATION,
this.LED_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.LED_COMPONENT_PANEL_VERTICAL_PERCENT,
this.LED_COMPONENT_ARROW_PERCENT,
this.LED_COMPONENT_AREA_TOP_PERCENT,
this.LED_COMPONENT_AREA_LEFT_PERCENT,
this.LED_COMPONENT_AREA_WIDTH_PERCENT,
this.LED_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns the flash memory panel data.
getFlashMemoryComponentData() {
return JSON.parse(TEMPLATE_COMPONENT_DATA.format(this.FLASH_MEMORY_COMPONENT_VISIBLE,
this.FLASH_MEMORY_COMPONENT_HAS_PANEL,
this.FLASH_MEMORY_COMPONENT_HAS_ARROW,
this.FLASH_MEMORY_COMPONENT_PANEL_ALWAYS_VISIBLE,
this.FLASH_MEMORY_COMPONENT_PANEL_ORIENTATION,
this.FLASH_MEMORY_COMPONENT_PANEL_HORIZONTAL_PERCENT,
this.FLASH_MEMORY_COMPONENT_PANEL_VERTICAL_PERCENT,
this.FLASH_MEMORY_COMPONENT_ARROW_PERCENT,
this.FLASH_MEMORY_COMPONENT_AREA_TOP_PERCENT,
this.FLASH_MEMORY_COMPONENT_AREA_LEFT_PERCENT,
this.FLASH_MEMORY_COMPONENT_AREA_WIDTH_PERCENT,
this.FLASH_MEMORY_COMPONENT_AREA_HEIGHT_PERCENT));
}
// Returns whether the device supports video brightness or not.
supportsVideoBrightness() {
return this.SUPPORTS_VIDEO_BRIGHTNESS;
}
}

View File

@ -0,0 +1,699 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// Constants.
const ID_CURRENT_DIRECTORY = "current_directory";
const ID_FILE_SYSTEM_CONTAINER = "filesystem_container";
const ID_FILE_SYSTEM_CREATE_DIR_BUTTON = "filesystem_create_directory_button";
const ID_FILE_SYSTEM_DIR_NAME = "filesystem_directory_name";
const ID_FILE_SYSTEM_DIR_NAME_BUTTON = "filesystem_directory_name_button";
const ID_FILE_SYSTEM_DIR_NAME_ERROR = "filesystem_directory_name_error";
const ID_FILE_SYSTEM_DIR_NAME_PANEL = "filesystem_dir_name_panel";
const ID_FILE_SYSTEM_DOWNLOAD_FILE_BUTTON = "filesystem_download_file_button";
const ID_FILE_SYSTEM_HEADER = "filesystem_header";
const ID_FILE_SYSTEM_HOVER_BACKGROUND = "filesystem_hover_background";
const ID_FILE_SYSTEM_ITEMS_CONTAINER = "filesystem_items_container";
const ID_FILE_SYSTEM_ITEMS_HEADER = "filesystem_items_header";
const ID_FILE_SYSTEM_LOADING = "filesystem_loading";
const ID_FILE_SYSTEM_PANEL = "filesystem_panel";
const ID_FILE_SYSTEM_REMOVE_FILE_BUTTON = "filesystem_remove_file_button";
const ID_FILE_SYSTEM_SELECT_FILE_BUTTON = "filesystem_select_file_button";
const ID_FILE_SYSTEM_UPLOAD_FILE_BUTTON = "filesystem_upload_file_button";
const ID_FILE_SYSTEM_TOOLBAR = "filesystem_toolbar";
const ID_FILE_SYSTEM_TOOLBAR_BUTTONS_CONTAINER = "filesystem_toolbar_buttons_container";
const ID_FILE_TO_UPLOAD = "file_to_upload";
const CLASS_FA_FILE = "fa-file";
const CLASS_FILE_SYSTEM_BUTTON_DISABLED = "filesystem-button-disabled";
const CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED = "filesystem-dir-name-button-disabled";
const CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR = "filesystem-dir-name-input-error";
const CLASS_FILE_SYSTEM_ENTRY_SELECTED = "filesystem-entry-selected";
const FS_TYPE_FILE = "file";
const FS_TYPE_DIRECTORY = "dir";
const TITLE_CONFIRM_REMOVE = "Confirm Remove";
const MESSAGE_CONFIRM_REMOVE = "Are you sure you want to remove the selected file?";
const PREFIX_FS = "fs_";
const REGEX_DIRECTORY_NAME = '^[^\\s^\x00-\x1f\\?*:"";<>|\\/.][^\x00-\x1f\\?*:"";<>|\\/]*[^\\s^\x00-\x1f\\?*:"";<>|\\/.]+$';
const TEMPLATE_DIRECTORY = "" +
"<div id='fs_{0}' class='filesystem-entry' title='{1}' onclick='listDirectory(\"{2}\", filters=\"{3}\")'>" +
" <div class='fas fa-folder fa-lg filesystem-entry-icon'></div>" +
" <div class='filesystem-entry-name'>{4}</div>" +
" <div class='filesystem-entry-size'></div>" +
" <div class='filesystem-entry-last-modified'>{5}</div>" +
"</div>";
const TEMPLATE_FILE = "" +
"<div id='fs_{0}' class='filesystem-entry' title='{1}' onclick='selectFileSystemEntry(\"fs_{2}\", filters=\"{3}\")' ondblclick='downloadFile(\"{4}\")'>" +
" <div class='fas fa-file fa-lg filesystem-entry-icon'></div>" +
" <div class='filesystem-entry-name'>{5}</div>" +
" <div class='filesystem-entry-size'>{6}</div>" +
" <div class='filesystem-entry-last-modified'>{7}</div>" +
"</div>";
const ERROR_DIR_NAME_EMPTY = "Directory name cannot be empty.";
const ERROR_DIR_NAME_INVALID = "The entered name is not valid.";
const ROOT_DIRECTORY = "/";
// Variables.
var currentDirectory = null;
var selectedFileSystemEntry = null;
var filesystemResizeObserver = null;
// Opens the file system panel.
function openFileSystem(showButtons=true, filters="") {
// Check if the file system is showing.
if (isFileSystemShowing())
return;
// Reset current directory.
currentDirectory = null;
$("#" + ID_CURRENT_DIRECTORY).text("");
// Unselect all entries.
unselectFileSystemEntries();
// Clear all the file system entries.
clearFileSystemEntries();
// Setup resize observer.
if (filesystemResizeObserver == null || filesystemResizeObserver == "undefined") {
filesystemResizeObserver = new ResizeObserver((entries) => {
resizeFileSystemElements();
})
filesystemResizeObserver.observe(document.getElementById(ID_FILE_SYSTEM_CONTAINER));
}
// Resize filesystem elements.
resizeFileSystemElements();
// Show the file system.
var fileSystemContainer = document.getElementById(ID_FILE_SYSTEM_PANEL);
fileSystemContainer.style.visibility = "visible";
if (!showButtons || is_local_access()) {
document.getElementById(ID_FILE_SYSTEM_DOWNLOAD_FILE_BUTTON).style.display = "none";
document.getElementById(ID_FILE_SYSTEM_UPLOAD_FILE_BUTTON).style.display = "none";
document.getElementById(ID_FILE_SYSTEM_TOOLBAR_BUTTONS_CONTAINER).style.width = "auto";
}
if (!showButtons) {
document.getElementById(ID_FILE_SYSTEM_CREATE_DIR_BUTTON).style.display = "none";
document.getElementById(ID_FILE_SYSTEM_REMOVE_FILE_BUTTON).style.display = "none";
}
// List root directory.
listDirectory(ROOT_DIRECTORY, filters=filters);
}
// Returns whether the file system window is open or not.
function isFileSystemShowing() {
// Sanity checks.
if (!isDashboardShowing() && !isManagementShowing())
return false;
// Initialize variables.
var fileSystemContainer = document.getElementById(ID_FILE_SYSTEM_PANEL);
// Return visibility.
return fileSystemContainer.style.visibility == "visible";
}
// Closes the file system panel.
function closeFileSystem() {
// Check if the file system is showing.
if (!isFileSystemShowing())
return;
// Hide the loading panel.
showFileSystemLoading(false);
// Hide the file system panel.
var fileSystemContainer = document.getElementById(ID_FILE_SYSTEM_PANEL);
fileSystemContainer.style.visibility = "collapse";
}
// Resizes the file system elements.
function resizeFileSystemElements() {
// If file system is not showing just return.
if (!isFileSystemShowing())
return;
// Initialize variables.
var filesystemContainer = document.getElementById(ID_FILE_SYSTEM_CONTAINER);
var filesystemHeader = document.getElementById(ID_FILE_SYSTEM_HEADER);
var filesystemToolbar = document.getElementById(ID_FILE_SYSTEM_TOOLBAR);
var filesystemHoverBackground = document.getElementById(ID_FILE_SYSTEM_HOVER_BACKGROUND);
var filesystemItemsHeader = document.getElementById(ID_FILE_SYSTEM_ITEMS_HEADER);
var filesystemItemsContainer = document.getElementById(ID_FILE_SYSTEM_ITEMS_CONTAINER);
var containerHeight = filesystemContainer.clientHeight;
var headerHeight = filesystemHeader.clientHeight;
var toolbarHeight = filesystemToolbar.clientHeight;
var itemsHeaderHeight = filesystemItemsHeader.clientHeight;
// Set correct heights.
filesystemHoverBackground.style.height = (containerHeight - headerHeight).toString() + "px";
filesystemItemsContainer.style.height = (containerHeight - headerHeight - toolbarHeight - itemsHeaderHeight).toString() + "px";
}
// Shows/hides the file system loading panel.
function showFileSystemLoading(visible) {
// Initialize variables.
var fileSystemHoverBackground = document.getElementById(ID_FILE_SYSTEM_HOVER_BACKGROUND);
var fileSystemLoading = document.getElementById(ID_FILE_SYSTEM_LOADING);
// Apply visibility.
if (visible && isFileSystemShowing()) {
fileSystemHoverBackground.style.visibility = "visible";
fileSystemLoading.style.visibility = "visible";
} else {
fileSystemHoverBackground.style.visibility = "hidden";
fileSystemLoading.style.visibility = "hidden";
}
}
// Clears all the file system entries.
function clearFileSystemEntries() {
// Initialize variables.
var fileSystemEntriesDiv = document.getElementById(ID_FILE_SYSTEM_ITEMS_CONTAINER);
// Clear all file system HTML entries.
while (fileSystemEntriesDiv.firstChild)
fileSystemEntriesDiv.removeChild(fileSystemEntriesDiv.lastChild);
}
// Enables/disabled the file system buttons.
function enableFileSystemButtons(enable, filters="") {
// Initialize variables.
var downloadButton = document.getElementById(ID_FILE_SYSTEM_DOWNLOAD_FILE_BUTTON);
var removeButton = document.getElementById(ID_FILE_SYSTEM_REMOVE_FILE_BUTTON);
var selectFwButton = document.getElementById(ID_FILE_SYSTEM_SELECT_FILE_BUTTON);
// Apply enable state.
if (!enable) {
if (removeButton) {
removeButton.disabled = true;
removeButton.classList.add(CLASS_FILE_SYSTEM_BUTTON_DISABLED);
}
if (downloadButton) {
downloadButton.disabled = true;
downloadButton.classList.add(CLASS_FILE_SYSTEM_BUTTON_DISABLED);
}
if (selectFwButton) {
selectFwButton.disabled = true;
selectFwButton.classList.add(CLASS_FILE_SYSTEM_BUTTON_DISABLED);
}
} else {
if (removeButton) {
removeButton.disabled = false;
removeButton.classList.remove(CLASS_FILE_SYSTEM_BUTTON_DISABLED);
}
if (downloadButton) {
downloadButton.disabled = false;
downloadButton.classList.remove(CLASS_FILE_SYSTEM_BUTTON_DISABLED);
}
if (selectFwButton) {
enable = false;
if (filters) {
var filePath = selectedFileSystemEntry.substring(PREFIX_FS.length);
var filter_list = filters.split(",");
for (var i = 0; i < filter_list.length; i++) {
if (filePath.endsWith(filter_list[i])) {
enable = true;
break;
}
}
}
if (!filters || enable) {
selectFwButton.disabled = false;
selectFwButton.classList.remove(CLASS_FILE_SYSTEM_BUTTON_DISABLED);
}
}
}
}
// Downloads the selected file.
function selectFirmwareFile() {
// Build file path.
var filePath = selectedFileSystemEntry.substring(PREFIX_FS.length);
firmwareFileChanged(filePath);
}
// Selects the given file system entry.
function selectFileSystemEntry(entryID, filters="") {
// Unselect all entries.
unselectFileSystemEntries();
// Set selected style to the selected device div.
var entryElement = document.getElementById(entryID)
if (entryElement != null)
entryElement.classList.add(CLASS_FILE_SYSTEM_ENTRY_SELECTED);
// Save selected entry.
selectedFileSystemEntry = entryID;
// Enable buttons.
enableFileSystemButtons(true, filters=filters);
}
// Unselects all the file system entries.
function unselectFileSystemEntries() {
// Initialize variables.
var fileSystemEntriesDiv = document.getElementById(ID_FILE_SYSTEM_ITEMS_CONTAINER);
var children = fileSystemEntriesDiv.children;
// Remove selected class from all entries.
for (var i = 0; i < children.length; i++) {
var entry = children[i].children[0];
entry.classList.remove(CLASS_FILE_SYSTEM_ENTRY_SELECTED);
}
// Reset selected entry.
selectedFileSystemEntry = null;
// Disable buttons.
enableFileSystemButtons(false);
}
// Lists the contents of the given directory.
function listDirectory(directory, filters="") {
// Build path.
var path = currentDirectory;
if (path == null || currentDirectory == directory)
path = directory;
else {
if (directory.endsWith("..")) {
// Check if last slash must be removed.
if (path.endsWith("/") && path.length > ROOT_DIRECTORY.length)
path = path.substring(0, path.lastIndexOf("/"));
// Move one directory up.
path = path.substring(0, path.lastIndexOf("/"));
if (path == "")
path = ROOT_DIRECTORY;
} else {
if (!path.endsWith("/"))
path = path + "/"
path = path + directory;
}
}
// Show loading panel.
showFileSystemLoading(true);
// Send request.
$.post(
"http://" + getServerAddress() + "/ajax/fs_list_directory",
JSON.stringify({
"directory": path,
"filters": filters,
}),
function(data) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process answer.
processListDirectoryResponse(data, filters=filters);
}
).fail(function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process error.
processAjaxErrorResponse(response);
// Hide the loading status.
showFileSystemLoading(false);
});
}
// Processes the list directory response.
function processListDirectoryResponse(response, filters="") {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
// Hide the loading status.
showFileSystemLoading(false);
// Do not continue.
return;
}
// Unselect all entries.
unselectFileSystemEntries();
// Clear all file system entries.
clearFileSystemEntries();
// Set current directory.
currentDirectory = response[ID_CURRENT_DIR];
if (!currentDirectory.endsWith("/"))
currentDirectory = currentDirectory + "/";
$("#" + ID_CURRENT_DIRECTORY).text(currentDirectory);
// Iterate over all the file system received entries.
if (response[ID_FILES] != null && response[ID_FILES] != "undefined") {
var fileSystemEntriesDiv = document.getElementById(ID_FILE_SYSTEM_ITEMS_CONTAINER);
// Process response entries and create HTML elements.
for (var entry of response[ID_FILES]) {
var name = entry[ID_NAME].substring(currentDirectory.length);
var lastModified = entry[ID_LAST_MODIFIED];
if (lastModified == null || lastModified == "undefined" || lastModified == 0 || name == "..") {
lastModified = "";
} else {
var date = new Date(0); // The 0 there is the key, which sets the date to the epoch
date.setUTCSeconds(lastModified);
lastModified = date.toLocaleString("en-US", { hour12:false });
}
var entryDiv = document.createElement("div");
if (entry[ID_TYPE] == FS_TYPE_FILE)
entryDiv.innerHTML = TEMPLATE_FILE.format(name, name, name, filters, name, name,
sizeToHumanRead(entry[ID_SIZE]), lastModified);
else if (entry[ID_TYPE] == FS_TYPE_DIRECTORY)
entryDiv.innerHTML = TEMPLATE_DIRECTORY.format(name, name, name, filters, name, lastModified);
if (entryDiv.innerHTML != null && entryDiv.innerHTML != "")
fileSystemEntriesDiv.appendChild(entryDiv);
}
}
// Hide the loading status.
showFileSystemLoading(false);
}
// Downloads the selected file.
function downloadSelectedFile() {
// Build file path.
var filePath = selectedFileSystemEntry.substring(PREFIX_FS.length);
// Execute the download action.
downloadFile(filePath);
}
// Attempts to download the given file name.
function downloadFile(fileName) {
// Build file path.
var path = currentDirectory + fileName;
// Show loading panel.
showFileSystemLoading(true);
// Prepare data.
var data = JSON.stringify({
"path": path
});
// Send request
$.ajax({
type: 'POST',
url: "http://" + getServerAddress() + "/ajax/fs_download_file",
data: data,
cache: false,
async: true,
xhr: function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 2) {
if (xhr.status == 200)
xhr.responseType = "blob";
else
xhr.responseType = "text";
}
};
return xhr;
},
success: function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process answer.
processDownloadFileResponse(response);
},
error: function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process error.
processAjaxErrorResponse(response);
// Hide the loading status.
showFileSystemLoading(false);
}
});
}
// Processes the download file response.
function processDownloadFileResponse(response) {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
// Hide the loading status.
showFileSystemLoading(false);
// Do not continue.
return;
}
// Obtain file name.
var fileName = selectedFileSystemEntry.substring(PREFIX_FS.length)
// Convert the Byte Data to BLOB object.
var blob = new Blob([response], { type: "application/octetstream" });
// Check the Browser type and download the File.
var isIE = false || !!document.documentMode;
if (isIE) {
window.navigator.msSaveBlob(blob, fileName);
} else {
var url = window.URL || window.webkitURL;
link = url.createObjectURL(blob);
var a = $("<a />");
a.attr("download", fileName);
a.attr("href", link);
$("body").append(a);
a[0].click();
$("body").remove(a);
}
// Hide the loading status.
showFileSystemLoading(false);
}
// Asks user to confirm file removal.
function askRemoveFile() {
showConfirmDialog(TITLE_CONFIRM_REMOVE, MESSAGE_CONFIRM_REMOVE,
function() {
// Remove the file.
removeSelectedFile();
},
function() {
// Do nothing.
}
);
}
// Removes the selected file.
function removeSelectedFile() {
// Sanity checks.
if (selectedFileSystemEntry == null)
return;
// Initialize variables.
var isFile = false;
var entryElement = document.getElementById(selectedFileSystemEntry);
var iconElement = entryElement.children[0];
// Check if it is a file.
if (iconElement.classList.contains(CLASS_FA_FILE))
isFile = true;
// Execute action.
removeFile(selectedFileSystemEntry.substring(PREFIX_FS.length), isFile);
}
// Attempts to remove the given file name.
function removeFile(fileName, isFile) {
// Build file path.
var path = currentDirectory + fileName;
// Show loading panel.
showFileSystemLoading(true);
// Send request.
$.post(
"http://" + getServerAddress() + "/ajax/fs_remove_file",
JSON.stringify({
"path": path,
"is_file": isFile
}),
function(data) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process answer.
processRemoveFileResponse(data);
}
).fail(function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process error.
processAjaxErrorResponse(response);
// Hide the loading status.
showFileSystemLoading(false);
});
}
// Processes the remove file response.
function processRemoveFileResponse(response) {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
// Hide the loading status.
showFileSystemLoading(false);
} else {
// List directory contents again.
listDirectory(currentDirectory);
}
}
// Opens the file browser.
function openFileBrowser() {
document.getElementById(ID_FILE_TO_UPLOAD).click();
}
// Attempts to upload the given file.
function uploadFile(file) {
// Build file path.
var path = currentDirectory + file.name;
// Show loading panel.
showFileSystemLoading(true);
// Prepare data.
var formData = new FormData();
formData.append("path", path);
formData.append("file", file);
// Send request.
$.ajax({
type: 'POST',
url: "http://" + getServerAddress() + "/ajax/fs_upload_file",
data: formData,
cache: false,
async: true,
processData: false,
contentType: false,
enctype: 'multipart/form-data',
success: function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process answer.
processUploadFileResponse(response);
},
error: function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process error.
processAjaxErrorResponse(response);
// Hide the loading status.
showFileSystemLoading(false);
}
});
}
// Processes the upload file response.
function processUploadFileResponse(response) {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
// Hide the loading status.
showFileSystemLoading(false);
} else {
// List directory contents again.
listDirectory(currentDirectory);
}
}
// Opens the directory name panel.
function openDirectoryNamePanel() {
// Initialize variables.
var fileSystemDirName = document.getElementById(ID_FILE_SYSTEM_DIR_NAME);
var fileSystemDirNameButton = document.getElementById(ID_FILE_SYSTEM_DIR_NAME_BUTTON);
var fileSystemDirNameError = document.getElementById(ID_FILE_SYSTEM_DIR_NAME_ERROR);
// Reset panel state.
fileSystemDirName.value = "";
fileSystemDirNameError.innerHTML = "&nbsp;";
fileSystemDirNameError.style.visibility = "hidden";
if (!fileSystemDirNameButton.classList.contains(CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED))
fileSystemDirNameButton.classList.add(CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED);
if (fileSystemDirName.classList.contains(CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR))
fileSystemDirName.classList.remove(CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR);
// Show panel.
showDirectoryNamePanel(true);
}
// Closes the directory name panel.
function closeDirectoryNamePanel() {
showDirectoryNamePanel(false);
}
// Opens the directory name panel.
function showDirectoryNamePanel(visible) {
// Initialize variables.
var fileSystemDirNamePanel = document.getElementById(ID_FILE_SYSTEM_DIR_NAME_PANEL);
var fileSystemDirNameError = document.getElementById(ID_FILE_SYSTEM_DIR_NAME_ERROR);
// Apply visible state.
if (visible && isFileSystemShowing())
fileSystemDirNamePanel.style.visibility = "visible";
else {
fileSystemDirNamePanel.style.visibility = "hidden";
fileSystemDirNameError.style.visibility = "hidden";
}
}
// Handles what happens when the "Create directory" button is pressed.
function onCreateDirectory() {
var fileSystemDirName = document.getElementById(ID_FILE_SYSTEM_DIR_NAME);
var dirName = fileSystemDirName.value;
createDirectory(dirName);
}
// Validates the directory name.
function validateDirectoryName(dirName) {
// Initialize variables.
var fileSystemDirName = document.getElementById(ID_FILE_SYSTEM_DIR_NAME);
var fileSystemDirNameButton = document.getElementById(ID_FILE_SYSTEM_DIR_NAME_BUTTON);
var fileSystemDirNameError = document.getElementById(ID_FILE_SYSTEM_DIR_NAME_ERROR);
var isValid = true;
var error = ERROR_DIR_NAME_INVALID;
// Check if the directory name is valid.
if (dirName == null || dirName == "") {
isValid = false;
error = ERROR_DIR_NAME_EMPTY;
} else
isValid = dirName.match(REGEX_DIRECTORY_NAME);
// Update controls.
if (isValid) {
if (fileSystemDirNameButton.classList.contains(CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED))
fileSystemDirNameButton.classList.remove(CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED);
if (fileSystemDirName.classList.contains(CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR))
fileSystemDirName.classList.remove(CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR);
fileSystemDirNameError.innerHTML = "&nbsp;";
fileSystemDirNameError.style.visibility = "hidden";
} else {
if (!fileSystemDirNameButton.classList.contains(CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED))
fileSystemDirNameButton.classList.add(CLASS_FILE_SYSTEM_DIR_NAME_BUTTON_DISABLED);
if (!fileSystemDirName.classList.contains(CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR))
fileSystemDirName.classList.add(CLASS_FILE_SYSTEM_DIR_NAME_INPUT_ERROR);
fileSystemDirNameError.innerHTML = error;
fileSystemDirNameError.style.visibility = "visible";
}
}
// Attempts to create the given directory.
function createDirectory(directoryName) {
// Build file path.
var path = currentDirectory + directoryName;
// Close the directory name panel.
closeDirectoryNamePanel();
// Show loading panel.
showFileSystemLoading(true);
// Send request.
$.post(
"http://" + getServerAddress() + "/ajax/fs_create_dir",
JSON.stringify({
"path": path
}),
function(data) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process answer.
processCreateDirectoryResponse(data);
}
).fail(function(response) {
// Process only if the file system window is showing.
if (!isFileSystemShowing())
return;
// Process error.
processAjaxErrorResponse(response);
// Hide the loading status.
showFileSystemLoading(false);
});
}
// Processes the create directory response.
function processCreateDirectoryResponse(response) {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
// Hide the loading status.
showFileSystemLoading(false);
} else {
// List directory contents again.
listDirectory(currentDirectory);
}
}

View File

@ -0,0 +1,12 @@
/*
* jquery-match-height 0.7.2 by @liabru
* http://brm.io/jquery-match-height/
* License MIT
*/
!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):t(jQuery)}(function(t){var e=-1,o=-1,n=function(t){return parseFloat(t)||0},a=function(e){var o=1,a=t(e),i=null,r=[];return a.each(function(){var e=t(this),a=e.offset().top-n(e.css("margin-top")),s=r.length>0?r[r.length-1]:null;null===s?r.push(e):Math.floor(Math.abs(i-a))<=o?r[r.length-1]=s.add(e):r.push(e),i=a}),r},i=function(e){var o={
byRow:!0,property:"height",target:null,remove:!1};return"object"==typeof e?t.extend(o,e):("boolean"==typeof e?o.byRow=e:"remove"===e&&(o.remove=!0),o)},r=t.fn.matchHeight=function(e){var o=i(e);if(o.remove){var n=this;return this.css(o.property,""),t.each(r._groups,function(t,e){e.elements=e.elements.not(n)}),this}return this.length<=1&&!o.target?this:(r._groups.push({elements:this,options:o}),r._apply(this,o),this)};r.version="0.7.2",r._groups=[],r._throttle=80,r._maintainScroll=!1,r._beforeUpdate=null,
r._afterUpdate=null,r._rows=a,r._parse=n,r._parseOptions=i,r._apply=function(e,o){var s=i(o),h=t(e),l=[h],c=t(window).scrollTop(),p=t("html").outerHeight(!0),u=h.parents().filter(":hidden");return u.each(function(){var e=t(this);e.data("style-cache",e.attr("style"))}),u.css("display","block"),s.byRow&&!s.target&&(h.each(function(){var e=t(this),o=e.css("display");"inline-block"!==o&&"flex"!==o&&"inline-flex"!==o&&(o="block"),e.data("style-cache",e.attr("style")),e.css({display:o,"padding-top":"0",
"padding-bottom":"0","margin-top":"0","margin-bottom":"0","border-top-width":"0","border-bottom-width":"0",height:"100px",overflow:"hidden"})}),l=a(h),h.each(function(){var e=t(this);e.attr("style",e.data("style-cache")||"")})),t.each(l,function(e,o){var a=t(o),i=0;if(s.target)i=s.target.outerHeight(!1);else{if(s.byRow&&a.length<=1)return void a.css(s.property,"");a.each(function(){var e=t(this),o=e.attr("style"),n=e.css("display");"inline-block"!==n&&"flex"!==n&&"inline-flex"!==n&&(n="block");var a={
display:n};a[s.property]="",e.css(a),e.outerHeight(!1)>i&&(i=e.outerHeight(!1)),o?e.attr("style",o):e.css("display","")})}a.each(function(){var e=t(this),o=0;s.target&&e.is(s.target)||("border-box"!==e.css("box-sizing")&&(o+=n(e.css("border-top-width"))+n(e.css("border-bottom-width")),o+=n(e.css("padding-top"))+n(e.css("padding-bottom"))),e.css(s.property,i-o+"px"))})}),u.each(function(){var e=t(this);e.attr("style",e.data("style-cache")||null)}),r._maintainScroll&&t(window).scrollTop(c/p*t("html").outerHeight(!0)),
this},r._applyDataApi=function(){var e={};t("[data-match-height], [data-mh]").each(function(){var o=t(this),n=o.attr("data-mh")||o.attr("data-match-height");n in e?e[n]=e[n].add(o):e[n]=o}),t.each(e,function(){this.matchHeight(!0)})};var s=function(e){r._beforeUpdate&&r._beforeUpdate(e,r._groups),t.each(r._groups,function(){r._apply(this.elements,this.options)}),r._afterUpdate&&r._afterUpdate(e,r._groups)};r._update=function(n,a){if(a&&"resize"===a.type){var i=t(window).width();if(i===e)return;e=i;
}n?o===-1&&(o=setTimeout(function(){s(a),o=-1},r._throttle)):s(a)},t(r._applyDataApi);var h=t.fn.on?"on":"bind";t(window)[h]("load",function(t){r._update(!1,t)}),t(window)[h]("resize orientationchange",function(t){r._update(!0,t)})});

View File

@ -0,0 +1,903 @@
/*!
* Copyright 2012, Chris Wanstrath
* Released under the MIT License
* https://github.com/defunkt/jquery-pjax
*/
(function($){
// When called on a container with a selector, fetches the href with
// ajax into the container or with the data-pjax attribute on the link
// itself.
//
// Tries to make sure the back button and ctrl+click work the way
// you'd expect.
//
// Exported as $.fn.pjax
//
// Accepts a jQuery ajax options object that may include these
// pjax specific options:
//
//
// container - String selector for the element where to place the response body.
// push - Whether to pushState the URL. Defaults to true (of course).
// replace - Want to use replaceState instead? That's cool.
//
// For convenience the second parameter can be either the container or
// the options object.
//
// Returns the jQuery object
function fnPjax(selector, container, options) {
options = optionsFor(container, options)
return this.on('click.pjax', selector, function(event) {
var opts = options
if (!opts.container) {
opts = $.extend({}, options)
opts.container = $(this).attr('data-pjax')
}
handleClick(event, opts)
})
}
// Public: pjax on click handler
//
// Exported as $.pjax.click.
//
// event - "click" jQuery.Event
// options - pjax options
//
// Examples
//
// $(document).on('click', 'a', $.pjax.click)
// // is the same as
// $(document).pjax('a')
//
// Returns nothing.
function handleClick(event, container, options) {
options = optionsFor(container, options)
var link = event.currentTarget
var $link = $(link)
if (link.tagName.toUpperCase() !== 'A')
throw "$.fn.pjax or $.pjax.click requires an anchor element"
// Middle click, cmd click, and ctrl click should open
// links in a new tab as normal.
if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
return
// Ignore cross origin links
if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
return
// Ignore case when a hash is being tacked on the current URL
if ( link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location) )
return
// Ignore event with default prevented
if (event.isDefaultPrevented())
return
var defaults = {
url: link.href,
container: $link.attr('data-pjax'),
target: link
}
var opts = $.extend({}, defaults, options)
var clickEvent = $.Event('pjax:click')
$link.trigger(clickEvent, [opts])
if (!clickEvent.isDefaultPrevented()) {
pjax(opts)
event.preventDefault()
$link.trigger('pjax:clicked', [opts])
}
}
// Public: pjax on form submit handler
//
// Exported as $.pjax.submit
//
// event - "click" jQuery.Event
// options - pjax options
//
// Examples
//
// $(document).on('submit', 'form', function(event) {
// $.pjax.submit(event, '[data-pjax-container]')
// })
//
// Returns nothing.
function handleSubmit(event, container, options) {
options = optionsFor(container, options)
var form = event.currentTarget
var $form = $(form)
if (form.tagName.toUpperCase() !== 'FORM')
throw "$.pjax.submit requires a form element"
var defaults = {
type: ($form.attr('method') || 'GET').toUpperCase(),
url: $form.attr('action'),
container: $form.attr('data-pjax'),
target: form
}
if (defaults.type !== 'GET' && window.FormData !== undefined) {
defaults.data = new FormData(form)
defaults.processData = false
defaults.contentType = false
} else {
// Can't handle file uploads, exit
if ($form.find(':file').length) {
return
}
// Fallback to manually serializing the fields
defaults.data = $form.serializeArray()
}
pjax($.extend({}, defaults, options))
event.preventDefault()
}
// Loads a URL with ajax, puts the response body inside a container,
// then pushState()'s the loaded URL.
//
// Works just like $.ajax in that it accepts a jQuery ajax
// settings object (with keys like url, type, data, etc).
//
// Accepts these extra keys:
//
// container - String selector for where to stick the response body.
// push - Whether to pushState the URL. Defaults to true (of course).
// replace - Want to use replaceState instead? That's cool.
//
// Use it just like $.ajax:
//
// var xhr = $.pjax({ url: this.href, container: '#main' })
// console.log( xhr.readyState )
//
// Returns whatever $.ajax returns.
function pjax(options) {
options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
if ($.isFunction(options.url)) {
options.url = options.url()
}
var hash = parseURL(options.url).hash
var containerType = $.type(options.container)
if (containerType !== 'string') {
throw "expected string value for 'container' option; got " + containerType
}
var context = options.context = $(options.container)
if (!context.length) {
throw "the container selector '" + options.container + "' did not match anything"
}
// We want the browser to maintain two separate internal caches: one
// for pjax'd partial page loads and one for normal page loads.
// Without adding this secret parameter, some browsers will often
// confuse the two.
if (!options.data) options.data = {}
if ($.isArray(options.data)) {
options.data.push({name: '_pjax', value: options.container})
} else {
options.data._pjax = options.container
}
function fire(type, args, props) {
if (!props) props = {}
props.relatedTarget = options.target
var event = $.Event(type, props)
context.trigger(event, args)
return !event.isDefaultPrevented()
}
var timeoutTimer
options.beforeSend = function(xhr, settings) {
// No timeout for non-GET requests
// Its not safe to request the resource again with a fallback method.
if (settings.type !== 'GET') {
settings.timeout = 0
}
xhr.setRequestHeader('X-PJAX', 'true')
xhr.setRequestHeader('X-PJAX-Container', options.container)
if (!fire('pjax:beforeSend', [xhr, settings]))
return false
if (settings.timeout > 0) {
timeoutTimer = setTimeout(function() {
if (fire('pjax:timeout', [xhr, options]))
xhr.abort('timeout')
}, settings.timeout)
// Clear timeout setting so jquerys internal timeout isn't invoked
settings.timeout = 0
}
var url = parseURL(settings.url)
if (hash) url.hash = hash
options.requestUrl = stripInternalParams(url)
}
options.complete = function(xhr, textStatus) {
if (timeoutTimer)
clearTimeout(timeoutTimer)
fire('pjax:complete', [xhr, textStatus, options])
fire('pjax:end', [xhr, options])
}
options.error = function(xhr, textStatus, errorThrown) {
var container = extractContainer("", xhr, options)
var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
locationReplace(container.url)
}
}
options.success = function(data, status, xhr) {
var previousState = pjax.state
// If $.pjax.defaults.version is a function, invoke it first.
// Otherwise it can be a static string.
var currentVersion = typeof $.pjax.defaults.version === 'function' ?
$.pjax.defaults.version() :
$.pjax.defaults.version
var latestVersion = xhr.getResponseHeader('X-PJAX-Version')
var container = extractContainer(data, xhr, options)
var url = parseURL(container.url)
if (hash) {
url.hash = hash
container.url = url.href
}
// If there is a layout version mismatch, hard load the new url
if (currentVersion && latestVersion && currentVersion !== latestVersion) {
locationReplace(container.url)
return
}
// If the new response is missing a body, hard load the page
if (!container.contents) {
locationReplace(container.url)
return
}
pjax.state = {
id: options.id || uniqueId(),
url: container.url,
title: container.title,
container: options.container,
fragment: options.fragment,
timeout: options.timeout
}
if (options.push || options.replace) {
window.history.replaceState(pjax.state, container.title, container.url)
}
// Only blur the focus if the focused element is within the container.
var blurFocus = $.contains(context, document.activeElement)
// Clear out any focused controls before inserting new page contents.
if (blurFocus) {
try {
document.activeElement.blur()
} catch (e) { /* ignore */ }
}
if (container.title) document.title = container.title
fire('pjax:beforeReplace', [container.contents, options], {
state: pjax.state,
previousState: previousState
})
context.html(container.contents)
// FF bug: Won't autofocus fields that are inserted via JS.
// This behavior is incorrect. So if theres no current focus, autofocus
// the last field.
//
// http://www.w3.org/html/wg/drafts/html/master/forms.html
var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
if (autofocusEl && document.activeElement !== autofocusEl) {
autofocusEl.focus()
}
executeScriptTags(container.scripts)
var scrollTo = options.scrollTo
// Ensure browser scrolls to the element referenced by the URL anchor
if (hash) {
var name = decodeURIComponent(hash.slice(1))
var target = document.getElementById(name) || document.getElementsByName(name)[0]
if (target) scrollTo = $(target).offset().top
}
if (typeof scrollTo == 'number') $(window).scrollTop(scrollTo)
fire('pjax:success', [data, status, xhr, options])
}
// Initialize pjax.state for the initial page load. Assume we're
// using the container and options of the link we're loading for the
// back button to the initial page. This ensures good back button
// behavior.
if (!pjax.state) {
pjax.state = {
id: uniqueId(),
url: window.location.href,
title: document.title,
container: options.container,
fragment: options.fragment,
timeout: options.timeout
}
window.history.replaceState(pjax.state, document.title)
}
// Cancel the current request if we're already pjaxing
abortXHR(pjax.xhr)
pjax.options = options
var xhr = pjax.xhr = $.ajax(options)
if (xhr.readyState > 0) {
if (options.push && !options.replace) {
// Cache current container element before replacing it
cachePush(pjax.state.id, [options.container, cloneContents(context)])
window.history.pushState(null, "", options.requestUrl)
}
fire('pjax:start', [xhr, options])
fire('pjax:send', [xhr, options])
}
return pjax.xhr
}
// Public: Reload current page with pjax.
//
// Returns whatever $.pjax returns.
function pjaxReload(container, options) {
var defaults = {
url: window.location.href,
push: false,
replace: true,
scrollTo: false
}
return pjax($.extend(defaults, optionsFor(container, options)))
}
// Internal: Hard replace current state with url.
//
// Work for around WebKit
// https://bugs.webkit.org/show_bug.cgi?id=93506
//
// Returns nothing.
function locationReplace(url) {
window.history.replaceState(null, "", pjax.state.url)
window.location.replace(url)
}
var initialPop = true
var initialURL = window.location.href
var initialState = window.history.state
// Initialize $.pjax.state if possible
// Happens when reloading a page and coming forward from a different
// session history.
if (initialState && initialState.container) {
pjax.state = initialState
}
// Non-webkit browsers don't fire an initial popstate event
if ('state' in window.history) {
initialPop = false
}
// popstate handler takes care of the back and forward buttons
//
// You probably shouldn't use pjax on pages with other pushState
// stuff yet.
function onPjaxPopstate(event) {
// Hitting back or forward should override any pending PJAX request.
if (!initialPop) {
abortXHR(pjax.xhr)
}
var previousState = pjax.state
var state = event.state
var direction
if (state && state.container) {
// When coming forward from a separate history session, will get an
// initial pop with a state we are already at. Skip reloading the current
// page.
if (initialPop && initialURL == state.url) return
if (previousState) {
// If popping back to the same state, just skip.
// Could be clicking back from hashchange rather than a pushState.
if (previousState.id === state.id) return
// Since state IDs always increase, we can deduce the navigation direction
direction = previousState.id < state.id ? 'forward' : 'back'
}
var cache = cacheMapping[state.id] || []
var containerSelector = cache[0] || state.container
var container = $(containerSelector), contents = cache[1]
if (container.length) {
if (previousState) {
// Cache current container before replacement and inform the
// cache which direction the history shifted.
cachePop(direction, previousState.id, [containerSelector, cloneContents(container)])
}
var popstateEvent = $.Event('pjax:popstate', {
state: state,
direction: direction
})
container.trigger(popstateEvent)
var options = {
id: state.id,
url: state.url,
container: containerSelector,
push: false,
fragment: state.fragment,
timeout: state.timeout,
scrollTo: false
}
if (contents) {
container.trigger('pjax:start', [null, options])
pjax.state = state
if (state.title) document.title = state.title
var beforeReplaceEvent = $.Event('pjax:beforeReplace', {
state: state,
previousState: previousState
})
container.trigger(beforeReplaceEvent, [contents, options])
container.html(contents)
container.trigger('pjax:end', [null, options])
} else {
pjax(options)
}
// Force reflow/relayout before the browser tries to restore the
// scroll position.
container[0].offsetHeight // eslint-disable-line no-unused-expressions
} else {
locationReplace(location.href)
}
}
initialPop = false
}
// Fallback version of main pjax function for browsers that don't
// support pushState.
//
// Returns nothing since it retriggers a hard form submission.
function fallbackPjax(options) {
var url = $.isFunction(options.url) ? options.url() : options.url,
method = options.type ? options.type.toUpperCase() : 'GET'
var form = $('<form>', {
method: method === 'GET' ? 'GET' : 'POST',
action: url,
style: 'display:none'
})
if (method !== 'GET' && method !== 'POST') {
form.append($('<input>', {
type: 'hidden',
name: '_method',
value: method.toLowerCase()
}))
}
var data = options.data
if (typeof data === 'string') {
$.each(data.split('&'), function(index, value) {
var pair = value.split('=')
form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
})
} else if ($.isArray(data)) {
$.each(data, function(index, value) {
form.append($('<input>', {type: 'hidden', name: value.name, value: value.value}))
})
} else if (typeof data === 'object') {
var key
for (key in data)
form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
}
$(document.body).append(form)
form.submit()
}
// Internal: Abort an XmlHttpRequest if it hasn't been completed,
// also removing its event handlers.
function abortXHR(xhr) {
if ( xhr && xhr.readyState < 4) {
xhr.onreadystatechange = $.noop
xhr.abort()
}
}
// Internal: Generate unique id for state object.
//
// Use a timestamp instead of a counter since ids should still be
// unique across page loads.
//
// Returns Number.
function uniqueId() {
return (new Date).getTime()
}
function cloneContents(container) {
var cloned = container.clone()
// Unmark script tags as already being eval'd so they can get executed again
// when restored from cache. HAXX: Uses jQuery internal method.
cloned.find('script').each(function(){
if (!this.src) $._data(this, 'globalEval', false)
})
return cloned.contents()
}
// Internal: Strip internal query params from parsed URL.
//
// Returns sanitized url.href String.
function stripInternalParams(url) {
url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '').replace(/^&/, '')
return url.href.replace(/\?($|#)/, '$1')
}
// Internal: Parse URL components and returns a Locationish object.
//
// url - String URL
//
// Returns HTMLAnchorElement that acts like Location.
function parseURL(url) {
var a = document.createElement('a')
a.href = url
return a
}
// Internal: Return the `href` component of given URL object with the hash
// portion removed.
//
// location - Location or HTMLAnchorElement
//
// Returns String
function stripHash(location) {
return location.href.replace(/#.*/, '')
}
// Internal: Build options Object for arguments.
//
// For convenience the first parameter can be either the container or
// the options object.
//
// Examples
//
// optionsFor('#container')
// // => {container: '#container'}
//
// optionsFor('#container', {push: true})
// // => {container: '#container', push: true}
//
// optionsFor({container: '#container', push: true})
// // => {container: '#container', push: true}
//
// Returns options Object.
function optionsFor(container, options) {
if (container && options) {
options = $.extend({}, options)
options.container = container
return options
} else if ($.isPlainObject(container)) {
return container
} else {
return {container: container}
}
}
// Internal: Filter and find all elements matching the selector.
//
// Where $.fn.find only matches descendants, findAll will test all the
// top level elements in the jQuery object as well.
//
// elems - jQuery object of Elements
// selector - String selector to match
//
// Returns a jQuery object.
function findAll(elems, selector) {
return elems.filter(selector).add(elems.find(selector))
}
function parseHTML(html) {
return $.parseHTML(html, document, true)
}
// Internal: Extracts container and metadata from response.
//
// 1. Extracts X-PJAX-URL header if set
// 2. Extracts inline <title> tags
// 3. Builds response Element and extracts fragment if set
//
// data - String response data
// xhr - XHR response
// options - pjax options Object
//
// Returns an Object with url, title, and contents keys.
function extractContainer(data, xhr, options) {
var obj = {}, fullDocument = /<html/i.test(data)
// Prefer X-PJAX-URL header if it was set, otherwise fallback to
// using the original requested url.
var serverUrl = xhr.getResponseHeader('X-PJAX-URL')
obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl
var $head, $body
// Attempt to parse response html into elements
if (fullDocument) {
$body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
var head = data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)
$head = head != null ? $(parseHTML(head[0])) : $body
} else {
$head = $body = $(parseHTML(data))
}
// If response data is empty, return fast
if ($body.length === 0)
return obj
// If there's a <title> tag in the header, use it as
// the page's title.
obj.title = findAll($head, 'title').last().text()
if (options.fragment) {
var $fragment = $body
// If they specified a fragment, look for it in the response
// and pull it out.
if (options.fragment !== 'body') {
$fragment = findAll($fragment, options.fragment).first()
}
if ($fragment.length) {
obj.contents = options.fragment === 'body' ? $fragment : $fragment.contents()
// If there's no title, look for data-title and title attributes
// on the fragment
if (!obj.title)
obj.title = $fragment.attr('title') || $fragment.data('title')
}
} else if (!fullDocument) {
obj.contents = $body
}
// Clean up any <title> tags
if (obj.contents) {
// Remove any parent title elements
obj.contents = obj.contents.not(function() { return $(this).is('title') })
// Then scrub any titles from their descendants
obj.contents.find('title').remove()
// Gather all script[src] elements
obj.scripts = findAll(obj.contents, 'script[src]').remove()
obj.contents = obj.contents.not(obj.scripts)
}
// Trim any whitespace off the title
if (obj.title) obj.title = $.trim(obj.title)
return obj
}
// Load an execute scripts using standard script request.
//
// Avoids jQuery's traditional $.getScript which does a XHR request and
// globalEval.
//
// scripts - jQuery object of script Elements
//
// Returns nothing.
function executeScriptTags(scripts) {
if (!scripts) return
var existingScripts = $('script[src]')
scripts.each(function() {
var src = this.src
var matchedScripts = existingScripts.filter(function() {
return this.src === src
})
if (matchedScripts.length) return
var script = document.createElement('script')
var type = $(this).attr('type')
if (type) script.type = type
script.src = $(this).attr('src')
document.head.appendChild(script)
})
}
// Internal: History DOM caching class.
var cacheMapping = {}
var cacheForwardStack = []
var cacheBackStack = []
// Push previous state id and container contents into the history
// cache. Should be called in conjunction with `pushState` to save the
// previous container contents.
//
// id - State ID Number
// value - DOM Element to cache
//
// Returns nothing.
function cachePush(id, value) {
cacheMapping[id] = value
cacheBackStack.push(id)
// Remove all entries in forward history stack after pushing a new page.
trimCacheStack(cacheForwardStack, 0)
// Trim back history stack to max cache length.
trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)
}
// Shifts cache from directional history cache. Should be
// called on `popstate` with the previous state id and container
// contents.
//
// direction - "forward" or "back" String
// id - State ID Number
// value - DOM Element to cache
//
// Returns nothing.
function cachePop(direction, id, value) {
var pushStack, popStack
cacheMapping[id] = value
if (direction === 'forward') {
pushStack = cacheBackStack
popStack = cacheForwardStack
} else {
pushStack = cacheForwardStack
popStack = cacheBackStack
}
pushStack.push(id)
id = popStack.pop()
if (id) delete cacheMapping[id]
// Trim whichever stack we just pushed to to max cache length.
trimCacheStack(pushStack, pjax.defaults.maxCacheLength)
}
// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no
// longer than the specified length, deleting cached DOM elements as necessary.
//
// stack - Array of state IDs
// length - Maximum length to trim to
//
// Returns nothing.
function trimCacheStack(stack, length) {
while (stack.length > length)
delete cacheMapping[stack.shift()]
}
// Public: Find version identifier for the initial page load.
//
// Returns String version or undefined.
function findVersion() {
return $('meta').filter(function() {
var name = $(this).attr('http-equiv')
return name && name.toUpperCase() === 'X-PJAX-VERSION'
}).attr('content')
}
// Install pjax functions on $.pjax to enable pushState behavior.
//
// Does nothing if already enabled.
//
// Examples
//
// $.pjax.enable()
//
// Returns nothing.
function enable() {
$.fn.pjax = fnPjax
$.pjax = pjax
$.pjax.enable = $.noop
$.pjax.disable = disable
$.pjax.click = handleClick
$.pjax.submit = handleSubmit
$.pjax.reload = pjaxReload
$.pjax.defaults = {
timeout: 650,
push: true,
replace: false,
type: 'GET',
dataType: 'html',
scrollTo: 0,
maxCacheLength: 20,
version: findVersion
}
$(window).on('popstate.pjax', onPjaxPopstate)
}
// Disable pushState behavior.
//
// This is the case when a browser doesn't support pushState. It is
// sometimes useful to disable pushState for debugging on a modern
// browser.
//
// Examples
//
// $.pjax.disable()
//
// Returns nothing.
function disable() {
$.fn.pjax = function() { return this }
$.pjax = fallbackPjax
$.pjax.enable = enable
$.pjax.disable = $.noop
$.pjax.click = $.noop
$.pjax.submit = $.noop
$.pjax.reload = function() { window.location.reload() }
$(window).off('popstate.pjax', onPjaxPopstate)
}
// Add the state property to jQuery's event object so we can use it in
// $(window).bind('popstate')
if ($.event.props && $.inArray('state', $.event.props) < 0) {
$.event.props.push('state')
} else if (!('state' in $.Event.prototype)) {
$.event.addProp('state')
}
// Is pjax supported by this browser?
$.support.pjax =
window.history && window.history.pushState && window.history.replaceState &&
// pushState isn't reliable on iOS until 5.
!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/)
if ($.support.pjax) {
enable()
} else {
disable()
}
})(jQuery)

View File

@ -0,0 +1,778 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// Constants.
const ID_REBOOT_BUTTON = "reboot_button";
const ID_FIRMWARE_TAB_UPLOAD = "firmware_tab_upload";
const ID_FIRMWARE_TAB_UPLOAD_HEADER = "firmware_tab_upload_header";
const ID_SELECT_FIRMWARE_BUTTON = "select_firmware_button";
const ID_UPDATE_FIRMWARE_BUTTON = "update_firmware_button";
const ID_UPDATE_FIRMWARE_FILE = "firmware_file";
const ID_UPDATE_FIRMWARE_FILE_LABEL = "firmware_file_label";
const ID_UPDATE_FIRMWARE_PROGRESS = "update_firmware_progress";
const ID_UPDATE_FIRMWARE_PROGRESS_BAR = "update_firmware_progress_bar";
const ID_UPDATE_FIRMWARE_PROGRESS_MESSAGE = "update_firmware_progress_message";
const ID_UPDATE_FIRMWARE_PROGRESS_TITLE = "update_firmware_progress_title";
const ID_UPDATE_RUNNING = "update_running";
const CLASS_FIRMWARE_TAB = "firmware-tab";
const CLASS_FIRMWARE_TAB_HEADER = "firmware-tab-header";
const CLASS_FIRMWARE_TAB_HEADER_ACTIVE = "firmware-tab-header-active";
const CLASS_MANAGEMENT_BUTTON_DISABLED = "management-button-disabled";
const CLASS_PROGRESS_BAR_ERROR = "update-firmware-progress-bar-error";
const CLASS_PROGRESS_BAR_INFO = "update-firmware-progress-bar-info";
const CLASS_PROGRESS_BAR_SUCCESS = "update-firmware-progress-bar-success";
const TITLE_CONFIRM_FIRMWARE_UPDATE = "Confirm firmware update";
const TITLE_CONFIRM_REBOOT = "Confirm reboot";
const TITLE_DEVICE_REBOOTING = "Device Rebooting";
const TITLE_FIRMWARE_UPDATE_ERROR = "Firmware update failed!";
const TITLE_FIRMWARE_UPDATE_IN_PROGRESS = "Firmware update in progress...";
const TITLE_FIRMWARE_UPDATE_SUCCESS = "Firmware update succeeded!";
const MESSAGE_CHECKING_FIRMWARE_UPDATE_STATUS = "Checking firmware update...";
const MESSAGE_CONFIRM_FIRMWARE_UPDATE = "This action will update the device firmware. Do you want to continue?";
const MESSAGE_CONFIRM_REBOOT = "This action will reboot the device and connection will be lost. Do you want to continue?";
const MESSAGE_DEVICE_REBOOTING = "The device is rebooting. Please wait...";
const MESSAGE_LOADING_INFORMATION = "Loading device information...";
const MESSAGE_LOADING_FILES = "Loading files...";
const MESSAGE_NO_FILE_SELECTED = "No file selected";
const MESSAGE_SENDING_FIRMWARE_UPDATE_REQUEST = "Sending firmware update request...";
const MESSAGE_SENDING_REBOOT = "Sending reboot request...";
const MESSAGE_SENDING_UPLOAD_REQUEST = "Sending firmware upload request...";
const MESSAGE_UPLOAD_COMPLETE = "Firmware file upload complete";
const MESSAGE_UPDATING_FIRMWARE = "Updating firmware...";
const MESSAGE_UPLOADING_FIRMWARE = "Uploading firmware file...";
const UPDATE_ERROR = "error";
const UPDATE_INFO = "info";
const UPDATE_SUCCESS = "success";
const FIRMWARE_UPDATE_CHECK_INTERVAL = 10000;
// Variables.
var readingManagementInfo = false;
var managementInfoRead = false;
var deviceRebooting = false;
var updatingFirmware = false;
var firmwareUpdateTimer = null;
var uploadFirmwareAjaxRequest = null;
var fwStorageDir = "/home/root/";
// Initializes the management page.
function initializeManagementPage() {
// Sanity checks.
if (!isManagementShowing() || managementInfoRead)
return;
// Read management information.
readDeviceInfoManagement();
}
// Gets the information of the device.
function readDeviceInfoManagement() {
// Execute only in the management page.
if (!isManagementShowing() || readingManagementInfo)
return;
// Unset device rebooting variable.
deviceRebooting = false;
// Flag reading variable.
readingManagementInfo = true;
// Hide the info popup.
showInfoPopup(false);
// Hide the firmware progress.
showFirmwareUpdateProgress(false);
// Show the loading popup.
showLoadingPopup(true, MESSAGE_LOADING_INFORMATION);
// Send request to retrieve device information.
$.post(
"http://" + getServerAddress() + "/ajax/get_device_info",
function(data) {
readingManagementInfo = false;
// Process only in the management page.
if (!isManagementShowing())
return;
// Hide the loading panel.
showLoadingPopup(false);
// Process device information answer.
processDeviceInfoManagementResponse(data);
}
).fail(function(response) {
// Flag reading variable.
readingManagementInfo = false;
// Process only in the management page.
if (!isManagementShowing())
return;
// Hide the loading panel.
showLoadingPopup(false);
// Process error.
processAjaxErrorResponse(response);
});
}
// Processes the response of the device info request.
function processDeviceInfoManagementResponse(response) {
// Check if there was any error in the request.
if (!checkErrorResponse(response, false)) {
// Fill device info.
fillDeviceInfo(response);
fwStorageDir = response[ID_FW_STORE_PATH];
// Flag device info read.
managementInfoRead = true;
// Check if there is a firmware update running.
checkFirmwareUpdateRunning();
}
}
// Fills device information.
function fillDeviceInfo(deviceData) {
// Set the device type.
updateFieldValue(ID_DEVICE_NAME, deviceData[ID_DEVICE_TYPE].toUpperCase());
// Set DEY version.
updateFieldValue(ID_DEY_VERSION, deviceData[ID_DEY_VERSION]);
// Set Kernel version.
updateFieldValue(ID_KERNEL_VERSION, deviceData[ID_KERNEL_VERSION]);
// Set U-Boot version.
updateFieldValue(ID_UBOOT_VERSION, deviceData[ID_UBOOT_VERSION]);
}
// Asks the user to confirm the reboot action.
function askReboot() {
showConfirmDialog(TITLE_CONFIRM_REBOOT, MESSAGE_CONFIRM_REBOOT,
function() {
// Execute the reboot.
rebootDevice();
},
function() {
// Do nothing.
}
);
}
// Reboots the device.
function rebootDevice() {
// Hide the info popup.
showInfoPopup(false);
// Show the loading popup.
showLoadingPopup(true, MESSAGE_SENDING_REBOOT);
// Send request to reboot the device.
$.post(
"http://" + getServerAddress() + "/ajax/reboot_device",
function(data) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Hide the loading panel.
showLoadingPopup(false);
// Process reboot device answer.
processRebootDeviceResponse(data);
}
).fail(function(response) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Hide the loading panel.
showLoadingPopup(false);
// Process error.
processAjaxErrorResponse(response);
});
}
function onConnectivity(cb) {
$.get("http://" + getServerAddress() + "/ping", function() {
cb();
}).fail(function() {
onConnectivity(cb);
});
}
function showRebootInfo() {
// Show info dialog.
showInfoPopup(true, TITLE_DEVICE_REBOOTING, "Waiting for connectivity after reboot <span class=\"dots\"></span>");
deviceRebooting = true;
managementInfoRead = false;
prevDeviceConnectionStatus = false;
var dotsInterval = setInterval(function() {
var dots = $("#info_popup .dots");
dots.text(dots.text() === "..." ? "" : dots.text() + ".");
}, 2000);
setTimeout(function() {
onConnectivity(function() {
clearInterval(dotsInterval);
showInfoPopup(false);
showPopup(ID_LOADING_WRAPPER, "rebooted_dialog", true);
});
}, 2000);
}
// Processes the response of the reboot device request.
function processRebootDeviceResponse(response) {
// Check if there was any error in the request.
if (!checkErrorResponse(response, false))
showRebootInfo();
}
// Opens the firmware file browser.
function openFirmwareBrowser() {
if (is_local_access())
openFileSystem(showButtons=false, filters=".swu");
else
document.getElementById(ID_UPDATE_FIRMWARE_FILE).click();
}
// Reads the device status.
function firmwareFileChanged(fileName="") {
// Execute only in the management page.
if (!isManagementShowing())
return;
closeFileSystem();
// Initialize variables.
var firmwareFileElement = document.getElementById(ID_UPDATE_FIRMWARE_FILE);
var firmwareFileLabelElement = document.getElementById(ID_UPDATE_FIRMWARE_FILE_LABEL);
// Hide progress bar.
showFirmwareUpdateProgress(false);
if (fileName == "" && firmwareFileElement.files.length == 0) {
// No file selected.
firmwareFileLabelElement.innerHTML = MESSAGE_NO_FILE_SELECTED;
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, false);
return;
}
var firmwareFile = "";
// Build file path.
if (is_local_access()) {
firmwareFile = currentDirectory + fileName;
// Hide the loading status.
showFileSystemLoading(false);
} else {
firmwareFile = firmwareFileElement.files[0].name;
}
// Update firmware file name.
firmwareFileLabelElement.innerHTML = firmwareFile;
// Enable button.
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, true);
}
// Asks the user to confirm the firmware update action.
function askUpdateFirmware() {
showConfirmDialog(TITLE_CONFIRM_FIRMWARE_UPDATE, MESSAGE_CONFIRM_FIRMWARE_UPDATE,
function() {
// Sanity checks.
var activeTab = getActiveFirmwareUpdateTab();
if (activeTab == null)
return;
// Flag updating variable.
updatingFirmware = true;
// Hide the info popup.
showInfoPopup(false);
// Hide the loading popup.
showLoadingPopup(false);
// Disable firmware update button.
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, false);
// Show progress bar.
showFirmwareUpdateProgress(true);
// Disable management page controls.
enableManagementPageControls(false);
// Check active tab.
if (activeTab == ID_FIRMWARE_TAB_UPLOAD) {
if (!is_local_access())
// Upload firmware.
uploadFirmwareFile();
else
updateFirmware(document.getElementById(ID_UPDATE_FIRMWARE_FILE_LABEL).innerHTML);
}
},
function() {
// Do nothing.
}
);
}
// Attempts to upload the given firmware file.
function uploadFirmwareFile() {
// Initialize variables.
var firmwareFileElement = document.getElementById(ID_UPDATE_FIRMWARE_FILE);
var firmwareFile = firmwareFileElement.files[0];
// Update upload status.
setFirmwareUpdateProgressInfo(0, MESSAGE_UPLOADING_FIRMWARE);
// Prepare data.
var formData = new FormData();
formData.append("path", fwStorageDir + firmwareFile.name);
formData.append("file", firmwareFile);
formData.append("overwrite", true);
// Send request.
$.ajax({
type: 'POST',
url: "http://" + getServerAddress() + "/ajax/fs_upload_file",
data: formData,
cache: false,
async: true,
processData: false,
contentType: false,
enctype: 'multipart/form-data',
success: function(response) {
// Reset request variable.
uploadFirmwareAjaxRequest = null;
// Process only in the management page.
if (!isManagementShowing())
return;
// Process answer.
processUploadFirmwareFileResponse(response);
},
error: function(response) {
// Reset request variable.
uploadFirmwareAjaxRequest = null;
// Process only in the management page.
if (!isManagementShowing())
return;
// Process error.
error = processAjaxErrorResponse(response);
// Update upload status.
setFirmwareUpdateProgressError(error);
// Flag updating variable.
updatingFirmware = false;
// Enable the management page controls.
enableManagementPageControls(true);
}
});
}
// Processes the upload firmware file response.
function processUploadFirmwareFileResponse(response) {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
error = getErrorFromResponse(response);
// Update upload status.
setFirmwareUpdateProgressError(error);
// Flag updating variable.
updatingFirmware = false;
// Enable the management page controls.
enableManagementPageControls(true);
} else {
// Update upload status.
setFirmwareUpdateProgressInfo(100, MESSAGE_UPLOAD_COMPLETE);
// Build file path.
var firmwareFileElement = document.getElementById(ID_UPDATE_FIRMWARE_FILE);
var firmwareFile = firmwareFileElement.files[0];
// Send the update request.
updateFirmware(fwStorageDir + firmwareFile.name);
}
}
// Updates the firmware of the device.
function updateFirmware(filePath) {
// Update status.
setFirmwareUpdateProgressInfo(0, MESSAGE_SENDING_UPLOAD_REQUEST);
// Send request to update the firmware.
$.post(
"http://" + getServerAddress() + "/ajax/update_firmware",
JSON.stringify({
"file": filePath
}),
function(data) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Process update firmware answer.
processUpdateFirmwareResponse(data);
}
).fail(function(response) {
// Flag updating variable.
updatingFirmware = false;
// Process only in the management page.
if (!isManagementShowing())
return;
// Process error.
error = processAjaxErrorResponse(response);
// Update upload status.
setFirmwareUpdateProgressError(error);
// Enable the management page controls.
enableManagementPageControls(true);
});
}
// Processes the response of the update firmware request.
function processUpdateFirmwareResponse(response) {
// Check if there was any error in the request.
if (checkErrorResponse(response, false)) {
error = getErrorFromResponse(response);
// Update upload status.
setFirmwareUpdateProgressError(error);
// Flag updating variable.
updatingFirmware = false;
// Enable the page controls.
enableManagementPageControls(true);
} else {
// Update progress status.
setFirmwareUpdateProgressInfo(100, MESSAGE_SENDING_FIRMWARE_UPDATE_REQUEST);
// Start timer to check firmware update status periodically.
startFirmwareUpdateTimer();
// Check first firmware update status in 2 seconds.
window.setTimeout(function () {
checkFirmwareUpdateStatus();
}, 2000);
}
}
// Starts a timer to check the firmware update status.
function startFirmwareUpdateTimer() {
// Sanity checks
if (!isManagementShowing() || firmwareUpdateTimer != null)
return;
// Start timer to check firmware update status.
firmwareUpdateTimer = setInterval(checkFirmwareUpdateStatus, FIRMWARE_UPDATE_CHECK_INTERVAL);
}
// Stops the timer to check the firmware update status.
function stopFirmwareUpdateTimer() {
// Stop timer.
if (firmwareUpdateTimer != null && firmwareUpdateTimer != "undefined") {
clearInterval(firmwareUpdateTimer);
firmwareUpdateTimer = null;
}
}
// Checks the firmware update status.
function checkFirmwareUpdateStatus() {
// Sanity checks
if (!isManagementShowing()) {
// Stop timer.
stopFirmwareUpdateTimer();
return;
}
// Send request to check firmware update status.
$.post(
"http://" + getServerAddress() + "/ajax/check_firmware_update_status",
function(data) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Process check firmware update status answer.
processCheckFirmwareUpdateStatusResponse(data);
}
).fail(function(response) {
// Process only in the management page.
if (!isManagementShowing())
return;
$.get("http://" + getServerAddress() + "/ping", function() {
// Process error.
processAjaxErrorResponse(response);
}).fail(function() {
if (!deviceRebooting)
showRebootInfo();
});
});
}
// Processes the response of the check firmware update status request.
function processCheckFirmwareUpdateStatusResponse(response) {
// Check if there was any error in the request.
if (!checkErrorResponse(response, false)) {
// Check if the firmware update is running.
if (response[ID_STATUS] == VALUE_ACTIVE) {
// Check the firmware update progress.
checkFirmwareUpdateProgress();
} else if (response[ID_STATUS] == VALUE_FAILED || response[ID_STATUS] == VALUE_SUCCESSFUL || response[ID_STATUS] == VALUE_CANCELED) {
// Stop timer.
stopFirmwareUpdateTimer();
// Flag the update variable.
updatingFirmware = false;
// Enable page controls.
enableManagementPageControls(true);
// Update the firmware update progress.
if (response[ID_STATUS] == VALUE_FAILED || response[ID_STATUS] == VALUE_CANCELED)
setFirmwareUpdateProgressError(ERROR_TITLE + ": " + response[ID_MESSAGE]);
else {
// Reset read info variable so info is read again after device reboots.
managementInfoRead = false;
// Set update as successful.
setFirmwareUpdateProgressSuccess(response[ID_MESSAGE]);
showRebootInfo();
}
}
}
}
// Checks if there is a firmware update running.
function checkFirmwareUpdateRunning() {
// Sanity checks
if (!isManagementShowing())
return;
// Hide the info popup.
showInfoPopup(false);
// Show the loading popup.
showLoadingPopup(true, MESSAGE_CHECKING_FIRMWARE_UPDATE_STATUS);
// Send request to check firmware update running.
$.post(
"http://" + getServerAddress() + "/ajax/check_firmware_update_running",
function(data) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Hide the loading popup.
showLoadingPopup(false);
// Process check firmware update status answer.
processCheckFirmwareUpdateRunningResponse(data);
}
).fail(function(response) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Hide the loading popup.
showLoadingPopup(false);
// Process error.
processAjaxErrorResponse(response);
});
}
// Processes the response of the check firmware update running request.
function processCheckFirmwareUpdateRunningResponse(response) {
// Check if the firmware update is running.
if (response[ID_UPDATE_RUNNING] == true) {
// Flag the update variable.
updatingFirmware = true;
// Disable page controls.
enableManagementPageControls(false);
// Show firmware update progress.
showFirmwareUpdateProgress(true);
// Update the firmware update progress.
setFirmwareUpdateProgressInfo(0, "");
// Check the firmware update progress.
checkFirmwareUpdateProgress();
// Subscribe timer.
startFirmwareUpdateTimer();
}
}
// Checks the firmware update progress.
function checkFirmwareUpdateProgress() {
// Sanity checks
if (!isManagementShowing())
return;
// Hide the info popup.
showInfoPopup(false);
// Hide the loading popup.
showLoadingPopup(false);
// Send request to check firmware update progress.
$.post(
"http://" + getServerAddress() + "/ajax/check_firmware_update_progress",
function(data) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Process check firmware update progress answer.
processCheckFirmwareUpdateProgressResponse(data);
}
).fail(function(response) {
// Process only in the management page.
if (!isManagementShowing())
return;
// Process error.
processAjaxErrorResponse(response);
});
}
// Processes the response of the firmware update progress.
function processCheckFirmwareUpdateProgressResponse(response) {
// Check if there was any error in the request.
if (!checkErrorResponse(response, false)) {
// Update the firmware update progress.
setFirmwareUpdateProgressInfo(response[ID_PROGRESS], response[ID_MESSAGE]);
}
}
// Enables/disables the management page controls.
function enableManagementPageControls(enable) {
// Reboot button.
enableManagementButton(ID_REBOOT_BUTTON, enable);
// Update firmware button.
var activeTab = getActiveFirmwareUpdateTab();
if (activeTab == ID_FIRMWARE_TAB_UPLOAD) {
var firmwareFileElement = document.getElementById(ID_UPDATE_FIRMWARE_FILE);
if (firmwareFileElement.files.length == 0)
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, false);
else
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, enable);
}
// Tabs.
var tabUploadElement = document.getElementById(ID_FIRMWARE_TAB_UPLOAD);
var tabUploadHeaderElement = document.getElementById(ID_FIRMWARE_TAB_UPLOAD_HEADER);
if (enable) {
tabUploadElement.classList.remove((CLASS_DISABLED_DIV));
tabUploadHeaderElement.classList.remove((CLASS_DISABLED_DIV));
} else {
tabUploadElement.classList.add((CLASS_DISABLED_DIV));
tabUploadHeaderElement.classList.add((CLASS_DISABLED_DIV));
}
}
// Enables/disables the given button ID
function enableManagementButton(buttonID, enable) {
// Initialize variables.
var buttonElement = document.getElementById(buttonID);
if (buttonElement != null) {
if (enable) {
if (buttonElement.classList.contains(CLASS_MANAGEMENT_BUTTON_DISABLED))
buttonElement.classList.remove(CLASS_MANAGEMENT_BUTTON_DISABLED);
} else
buttonElement.classList.add(CLASS_MANAGEMENT_BUTTON_DISABLED);
}
}
// Returns the active firmware update tab.
function getActiveFirmwareUpdateTab() {
// Initialize variables.
var tabUploadHeaderElement = document.getElementById(ID_FIRMWARE_TAB_UPLOAD_HEADER);
// Check the active tab.
if (tabUploadHeaderElement.classList.contains(CLASS_FIRMWARE_TAB_HEADER_ACTIVE))
return ID_FIRMWARE_TAB_UPLOAD;
else
return null;
}
// Returns whether the device is rebooting or not.
function isDeviceRebooting() {
return deviceRebooting;
}
// Returns whether firmware update is running or not.
function isFirmwareUpdateRunning() {
return updatingFirmware;
}
// Shows the given firmware tab
function showFirmwareTab(tabID) {
// Initialize variables.
var tabElement = document.getElementById(tabID);
var tabHeaderElement = document.getElementById(tabID + "_header");
if (tabElement != null && tabHeaderElement != null) {
// Deselect all tab headers.
var tabHeaders = document.getElementsByClassName(CLASS_FIRMWARE_TAB_HEADER);
for (var i = 0; i < tabHeaders.length; i++) {
var tabHeader = tabHeaders[i];
if (tabHeader.classList.contains(CLASS_FIRMWARE_TAB_HEADER_ACTIVE))
tabHeader.classList.remove(CLASS_FIRMWARE_TAB_HEADER_ACTIVE);
}
// Hide all the tabs.
var tabs = document.getElementsByClassName(CLASS_FIRMWARE_TAB);
for (var i = 0; i < tabs.length; i++) {
var tab = tabs[i];
tab.style.display = "none";
}
// Show the selected tab.
tabHeaderElement.classList.add(CLASS_FIRMWARE_TAB_HEADER_ACTIVE);
tabElement.style.display = "block";
// Disable firmware update button.
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, false);
// Hide firmware update progress.
showFirmwareUpdateProgress(false);
// Perform additional actions on each tab.
switch(tabID) {
case ID_FIRMWARE_TAB_UPLOAD:
// Check if there is a file in the file input.
var firmwareFileElement = document.getElementById(ID_UPDATE_FIRMWARE_FILE);
if (firmwareFileElement.files.length > 0) {
// Enable firmware update button.
enableManagementButton(ID_UPDATE_FIRMWARE_BUTTON, true);
}
break;
}
}
}
// Shows/hides the firmware update progress section.
function showFirmwareUpdateProgress(visible) {
// Initialize variables.
var firmwareUpdateProgressElement = document.getElementById(ID_UPDATE_FIRMWARE_PROGRESS);
if (firmwareUpdateProgressElement != null) {
if (visible)
firmwareUpdateProgressElement.style.display = "block";
else
firmwareUpdateProgressElement.style.display = "none";
}
}
// Sets the firmware update progress.
function setFirmwareUpdateProgressInfo(progress, message=null) {
updateFirmwareUpdateProgress(UPDATE_INFO, progress, TITLE_FIRMWARE_UPDATE_IN_PROGRESS, message);
}
// Sets the firmware update progress error.
function setFirmwareUpdateProgressError(message=null) {
updateFirmwareUpdateProgress(UPDATE_ERROR, 100, TITLE_FIRMWARE_UPDATE_ERROR, message);
}
// Sets the firmware update progress success.
function setFirmwareUpdateProgressSuccess(message=null) {
updateFirmwareUpdateProgress(UPDATE_SUCCESS, 100, TITLE_FIRMWARE_UPDATE_SUCCESS, message);
}
// Updates the firmware update progress.
function updateFirmwareUpdateProgress(status, progress, title=null, message=null) {
// Initialize variables.
var firmwareUpdateProgressElement = document.getElementById(ID_UPDATE_FIRMWARE_PROGRESS);
if (firmwareUpdateProgressElement != null) {
// Update the progress bar.
var progressBarElement = document.getElementById(ID_UPDATE_FIRMWARE_PROGRESS_BAR);
if (progressBarElement != null) {
// Update the progress bar status type.
if (progressBarElement.classList.contains(CLASS_PROGRESS_BAR_INFO))
progressBarElement.classList.remove(CLASS_PROGRESS_BAR_INFO);
if (progressBarElement.classList.contains(CLASS_PROGRESS_BAR_ERROR))
progressBarElement.classList.remove(CLASS_PROGRESS_BAR_ERROR);
if (progressBarElement.classList.contains(CLASS_PROGRESS_BAR_SUCCESS))
progressBarElement.classList.remove(CLASS_PROGRESS_BAR_SUCCESS);
switch (status) {
case UPDATE_INFO:
progressBarElement.classList.add(CLASS_PROGRESS_BAR_INFO);
break;
case UPDATE_ERROR:
progressBarElement.classList.add(CLASS_PROGRESS_BAR_ERROR);
break;
case UPDATE_SUCCESS:
progressBarElement.classList.add(CLASS_PROGRESS_BAR_SUCCESS);
break;
}
// Update the progress bar percent.
if (progress != "?") {
progressBarElement.style.width = progress + "%";
progressBarElement.innerHTML = progress + "%";
} else {
let html = progressBarElement.innerHTML;
if (html.startsWith("."))
progressBarElement.innerHTML = html + ".";
else
progressBarElement.innerHTML = ".";
}
}
// Update the progress title.
var progressTitleElement = document.getElementById(ID_UPDATE_FIRMWARE_PROGRESS_TITLE);
if (progressTitleElement != null) {
if (title != null)
progressTitleElement.innerHTML = title;
else
progressTitleElement.innerHTML = "";
}
// Update the progress message.
var progressMessageElement = document.getElementById(ID_UPDATE_FIRMWARE_PROGRESS_MESSAGE);
if (progressMessageElement != null) {
if (message != null)
progressMessageElement.innerHTML = message;
else
progressMessageElement.innerHTML = "";
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// Constants.
// Variables.
var readingMultimediaInfo = false;
var multimediaInfoRead = false;
// Initializes the multimedia page.
function initializeMultimediaPage() {
// Sanity checks.
if (!isMultimediaShowing() || multimediaInfoRead)
return;
// Read multimedia information.
readDeviceInfoMultimedia();
}
// Gets the information of the device.
function readDeviceInfoMultimedia() {
// Execute only in the multimedia page.
if (!isMultimediaShowing() || readingMultimediaInfo)
return;
// Flag reading variable.
readingMultimediaInfo = true;
// Hide the info popup.
showInfoPopup(false);
// Show the loading popup.
showLoadingPopup(true, MESSAGE_LOADING_INFORMATION);
// Send request to retrieve device information.
$.post(
"http://" + getServerAddress() + "/ajax/get_device_info",
function(data) {
readingMultimediaInfo = false;
// Process only in the management page.
if (!isMultimediaShowing())
return;
// Hide the loading panel.
showLoadingPopup(false);
// Process device information answer.
processDeviceInfoMultimediaResponse(data);
}
).fail(function(response) {
// Flag reading variable.
readingMultimediaInfo = false;
// Process only in the management page.
if (!isMultimediaShowing())
return;
// Hide the loading panel.
showLoadingPopup(false);
// Process error.
processAjaxErrorResponse(response);
});
}
// Processes the response of the device info request.
function processDeviceInfoMultimediaResponse(response) {
// Check if there was any error in the request.
if (!checkErrorResponse(response, false)) {
// Set the device type.
updateFieldValue(ID_DEVICE_NAME, response[ID_DEVICE_TYPE].toUpperCase());
// Flag device info read.
multimediatInfoRead = true;
}
}

View File

@ -0,0 +1,97 @@
/*
* Copyright 2022, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// Hide submenus
$("#body-row .collapse").collapse("hide");
// Collapse/Expand icon.
$("#collapse-icon").addClass("fa-angle-double-left");
// Select click.
$("#sections > a").click(function() {
selectSection($(this));
});
// Collapse click.
$("[data-toggle=sidebar-collapse]").click(function() {
sidebarCollapse();
});
$(".element-grayed").click(function(){return false;});
// Selects the given item in the sidebar.
function selectSection(selectedItem) {
// Remove decorations of previously selected element.
$("#sections .selected").removeClass(CLASS_SELECTED);
// Decorate the selected element.
selectedItem.toggleClass(CLASS_SELECTED);
}
// Collapses the sidebar to the left.
function sidebarCollapse() {
$(".menu-collapsed").toggleClass("d-none");
$(".sidebar-submenu").toggleClass("d-none");
$(".submenu-icon").toggleClass("d-none");
// Add/Remove right margin.
$(".digi-menu-icon").toggleClass("mr-3 mr-0");
$("#sidebar-container").toggleClass("sidebar-expanded sidebar-collapsed");
// Treating d-flex/d-none on separators with title.
var separatorTitle = $(".sidebar-separator-title");
if (separatorTitle.hasClass("d-flex"))
separatorTitle.removeClass("d-flex");
else
separatorTitle.addClass("d-flex");
// Collapse/Expand icon.
$("#collapse-icon").toggleClass("fa-angle-double-left fa-angle-double-right");
// Make the cards the same height. Wait some time so size is
// calculated after the content of the cards expands or collapses.
window.setTimeout(function () {
$(".adjust-card-height .card").matchHeight();
}, 100);
if (isDashboardShowing()) {
let refreshPanelsInterval = window.setInterval(adjustImageSize, 10);
window.setTimeout(function () {
window.clearInterval(refreshPanelsInterval);
}, 300);
}
}
// Sets the selected section.
function setSelectedSection(element=null) {
// First, unselect all the sections.
$("#sections li").each(function(i, n) {
n.children[0].classList.remove(CLASS_SELECTED);
});
// Select the corresponding section.
if (element != null) {
element.classList.add(CLASS_SELECTED);
} else {
$("#sections li").each(function(i, n) {
if (window.location.pathname == n.children[0].pathname) {
n.children[0].classList.add(CLASS_SELECTED);
return false;
}
});
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2020, Digi International Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
const SEPARATOR = "@@@"
var currentTime;
var timer;
function updateTime() {
currentTime += 1;
postMessage(new Date(1000 * currentTime).toISOString().substr(11, 8));
}
onmessage = function (event) {
var parts = event.data.split(SEPARATOR);
currentTime = parseInt(parts[0]);
var factor = parseInt(parts[1]);
setInterval(updateTime, 1000 / factor);
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long