connectcore-demo-example: improve npu demos launch mechanism
- When launching an NPU demo, display a black screen below the loading spin to avoid the transparent window of some demos to display part of the ConnectCore application in the background. - Create a polling mechanism after an NPU demo is launched to check when the demo is closed in order to hide the black screen and the loading spin. Signed-off-by: David Escalona <david.escalona@digi.com>
This commit is contained in:
parent
893bd689c0
commit
46100efac4
|
|
@ -104,6 +104,9 @@ COMMAND_READ_SN = "fw_printenv -n serial#"
|
||||||
|
|
||||||
NPU_DEMOS_FILE = "static/assets/npu_demos.json"
|
NPU_DEMOS_FILE = "static/assets/npu_demos.json"
|
||||||
|
|
||||||
|
PROGRAM_RUN_CHECK_TIMES = 3
|
||||||
|
PROGRAM_RUN_CHECK_INTERVAL = 0.2
|
||||||
|
|
||||||
# Variables.
|
# Variables.
|
||||||
log = logging.getLogger(APP_NAME)
|
log = logging.getLogger(APP_NAME)
|
||||||
last_cpu_work = 0
|
last_cpu_work = 0
|
||||||
|
|
@ -662,11 +665,20 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||||
if script:
|
if script:
|
||||||
# Execute the demo.
|
# Execute the demo.
|
||||||
exec_cmd_nowait(script)
|
exec_cmd_nowait(script)
|
||||||
self.wfile.write("{}".encode(encoding="utf_8"))
|
self.wfile.write(json.dumps({"id": demo_id}).encode(encoding="utf_8"))
|
||||||
else:
|
else:
|
||||||
self.wfile.write(json.dumps({"error": "NPU demo launch script not found."}).encode(encoding="utf_8"))
|
self.wfile.write(json.dumps({"error": "NPU demo launch script not found."}).encode(encoding="utf_8"))
|
||||||
else:
|
else:
|
||||||
self.wfile.write(json.dumps({"error": "NPU demo not found."}).encode(encoding="utf_8"))
|
self.wfile.write(json.dumps({"error": "NPU demo not found."}).encode(encoding="utf_8"))
|
||||||
|
elif re.search("/ajax/is_npu_demo_running", self.path) is not None:
|
||||||
|
# Set the response headers.
|
||||||
|
self._set_headers(200)
|
||||||
|
# Get the JSON data.
|
||||||
|
data = self.rfile.read(int(self.headers["Content-Length"]))
|
||||||
|
# Get the demo ID.
|
||||||
|
demo_id = json.loads(data.decode("utf-8")).get("demo_id", None)
|
||||||
|
# Return whether demo is running or not.
|
||||||
|
self.wfile.write(json.dumps({"id": demo_id, "is_running": is_npu_demo_running(demo_id)}).encode(encoding="utf_8"))
|
||||||
else:
|
else:
|
||||||
# Forbidden.
|
# Forbidden.
|
||||||
self._set_headers(403)
|
self._set_headers(403)
|
||||||
|
|
@ -1896,6 +1908,59 @@ def get_npu_demos_for_platform(platform_name):
|
||||||
return compatible_demos
|
return compatible_demos
|
||||||
|
|
||||||
|
|
||||||
|
def is_npu_demo_running(demo_id):
|
||||||
|
"""
|
||||||
|
Check if the given NPU demo is currently running in the system or not.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
demo_id (str): ID of the demo to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the demo is running, False otherwise.
|
||||||
|
"""
|
||||||
|
demo = get_npu_demo(demo_id)
|
||||||
|
if demo:
|
||||||
|
# Get the demo execution script.
|
||||||
|
script = None
|
||||||
|
platform_id = get_platform_id()
|
||||||
|
for comp_platform in demo.get("compatible_platforms", []):
|
||||||
|
if comp_platform.get("platform", None) == platform_id:
|
||||||
|
script = comp_platform.get("launch_script", None)
|
||||||
|
break
|
||||||
|
if script:
|
||||||
|
return is_program_running(script)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_program_running(program):
|
||||||
|
"""
|
||||||
|
Check if a given program is currently running in the system or not.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
program (str): The program/command to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the program is running, False otherwise.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
for i in range(PROGRAM_RUN_CHECK_TIMES):
|
||||||
|
# Run the 'ps' command and capture the output
|
||||||
|
command = f"ps w | grep -v 'grep' | grep -q '{program}'"
|
||||||
|
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
# Check if the return code is 0 (program is running)
|
||||||
|
if result.returncode == 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Keep checking to discard false negatives.
|
||||||
|
time.sleep(PROGRAM_RUN_CHECK_INTERVAL)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_platform_id():
|
def get_platform_id():
|
||||||
"""
|
"""
|
||||||
Returns the running platform ID.
|
Returns the running platform ID.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ Digi Demo - NPU
|
||||||
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
|
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="black_frame" class="npu-black-frame"></div>
|
||||||
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
<nav id="topBar" class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||||
<div class="nav-container">
|
<div class="nav-container">
|
||||||
<a id="banner-link" class="navbar-brand align-middle" href="index.html">
|
<a id="banner-link" class="navbar-brand align-middle" href="index.html">
|
||||||
|
|
@ -44,7 +45,6 @@ Digi Demo - NPU
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="bg-light" id="body-row">
|
<div class="bg-light" id="body-row">
|
||||||
|
|
||||||
<!-- Sidebar https://www.codeply.com/go/3e0RAjccRO/bootstrap-4-collapsing-sidebar-menu# -->
|
<!-- Sidebar https://www.codeply.com/go/3e0RAjccRO/bootstrap-4-collapsing-sidebar-menu# -->
|
||||||
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block">
|
<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' -->
|
<!-- d-* hides the Sidebar in smaller devices. Its items can be kept on the Navbar 'Menu' -->
|
||||||
|
|
@ -229,8 +229,6 @@ Digi Demo - NPU
|
||||||
setSelectedSection();
|
setSelectedSection();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 997;
|
z-index: 1003;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,7 +372,7 @@ body {
|
||||||
|
|
||||||
/* POPUP */
|
/* POPUP */
|
||||||
.popup {
|
.popup {
|
||||||
z-index: 999;
|
z-index: 1002;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
@ -2418,3 +2418,17 @@ select {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
}
|
}
|
||||||
/* END NETWORK */
|
/* END NETWORK */
|
||||||
|
|
||||||
|
/* NPU BLACK FRAME */
|
||||||
|
.npu-black-frame {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: black;
|
||||||
|
z-index: 1001;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition-duration: 1s;
|
||||||
|
}
|
||||||
|
|
@ -83,6 +83,7 @@ const ID_ID = "id";
|
||||||
const ID_INFO_POPUP = "info_popup";
|
const ID_INFO_POPUP = "info_popup";
|
||||||
const ID_INFO_POPUP_MESSAGE = "info_popup_message";
|
const ID_INFO_POPUP_MESSAGE = "info_popup_message";
|
||||||
const ID_INFO_POPUP_TITLE = "info_popup_title";
|
const ID_INFO_POPUP_TITLE = "info_popup_title";
|
||||||
|
const ID_IS_RUNNING = "is_running";
|
||||||
const ID_KERNEL_VERSION = "kernel_version";
|
const ID_KERNEL_VERSION = "kernel_version";
|
||||||
const ID_LAST_MODIFIED = "last_modified";
|
const ID_LAST_MODIFIED = "last_modified";
|
||||||
const ID_LED = "led";
|
const ID_LED = "led";
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ const TEMPLATE_NO_DEMOS = "<p style='padding-left: 15px;'><i>No demos found</i><
|
||||||
|
|
||||||
const MESSAGE_EXECUTING_NPU_DEMO = "Executing NPU demo...";
|
const MESSAGE_EXECUTING_NPU_DEMO = "Executing NPU demo...";
|
||||||
|
|
||||||
const HIDE_STATUS_TIMEOUT = 10000; // 10 seconds.
|
const CHECK_DEMO_RUNNING_OFFSET = 8000;
|
||||||
|
const CHECK_DEMO_RUNNING_TIME = 200;
|
||||||
|
|
||||||
// Variables.
|
// Variables.
|
||||||
var readingNPUInfo = false;
|
var readingNPUInfo = false;
|
||||||
|
|
@ -155,12 +156,71 @@ function runNPUDemo(npuDemoID) {
|
||||||
function processRunNPUDemoResponse(response) {
|
function processRunNPUDemoResponse(response) {
|
||||||
// Check if there was any error in the request.
|
// Check if there was any error in the request.
|
||||||
checkErrorResponse(response, false);
|
checkErrorResponse(response, false);
|
||||||
// Start timer to hide loading popup.
|
demoID = response[ID_ID];
|
||||||
|
// Start timer to check whether demo is running.
|
||||||
|
blackFrame = document.getElementById('black_frame');
|
||||||
|
blackFrame.style.pointerEvents = 'auto';
|
||||||
|
blackFrame.style.opacity = 1;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Process only in the NPU page.
|
// Process only in the NPU page.
|
||||||
if (!isNPUShowing())
|
if (!isNPUShowing())
|
||||||
return;
|
return;
|
||||||
|
// Show top black bar.
|
||||||
|
isNPUDemoRunning(demoID);
|
||||||
|
}, CHECK_DEMO_RUNNING_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether the given NPU demo is running or not.
|
||||||
|
function isNPUDemoRunning(npuDemoID) {
|
||||||
|
// Send request.
|
||||||
|
$.post(
|
||||||
|
"http://" + getServerAddress() + "/ajax/is_npu_demo_running",
|
||||||
|
JSON.stringify({
|
||||||
|
"demo_id": npuDemoID,
|
||||||
|
}),
|
||||||
|
function(data) {
|
||||||
|
// Process only in the NPU page.
|
||||||
|
if (!isNPUShowing())
|
||||||
|
return;
|
||||||
|
// Process answer.
|
||||||
|
processIsNPUDemoRunningResponse(data);
|
||||||
|
}
|
||||||
|
).fail(function(response) {
|
||||||
|
// Process only in the NPU page.
|
||||||
|
if (!isNPUShowing())
|
||||||
|
return;
|
||||||
|
// Process error.
|
||||||
|
processAjaxErrorResponse(response);
|
||||||
|
// Hide the black frame.
|
||||||
|
blackFrame = document.getElementById('black_frame');
|
||||||
|
blackFrame.style.opacity = 0;
|
||||||
|
blackFrame.style.pointerEvents = 'none';
|
||||||
// Hide the loading panel.
|
// Hide the loading panel.
|
||||||
showLoadingPopup(false);
|
showLoadingPopup(false);
|
||||||
}, HIDE_STATUS_TIMEOUT);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processes the response of the is NPU demo running request.
|
||||||
|
function processIsNPUDemoRunningResponse(response) {
|
||||||
|
// Check if there was any error in the request.
|
||||||
|
checkErrorResponse(response, false);
|
||||||
|
// Check whether demo is running.
|
||||||
|
demoID = response[ID_ID];
|
||||||
|
isRunning = response[ID_IS_RUNNING];
|
||||||
|
if (isRunning) {
|
||||||
|
// Schedule to check again.
|
||||||
|
setTimeout(() => {
|
||||||
|
// Process only in the NPU page.
|
||||||
|
if (!isNPUShowing())
|
||||||
|
return;
|
||||||
|
isNPUDemoRunning(demoID);
|
||||||
|
}, CHECK_DEMO_RUNNING_TIME);
|
||||||
|
} else { // Demo is not running.
|
||||||
|
// Hide the black frame.
|
||||||
|
blackFrame = document.getElementById('black_frame');
|
||||||
|
blackFrame.style.opacity = 0;
|
||||||
|
blackFrame.style.pointerEvents = 'none';
|
||||||
|
// Hide the loading panel.
|
||||||
|
showLoadingPopup(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue