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:
David Escalona 2024-09-19 16:45:32 +02:00
parent 893bd689c0
commit 46100efac4
5 changed files with 147 additions and 9 deletions

View File

@ -104,6 +104,9 @@ COMMAND_READ_SN = "fw_printenv -n serial#"
NPU_DEMOS_FILE = "static/assets/npu_demos.json"
PROGRAM_RUN_CHECK_TIMES = 3
PROGRAM_RUN_CHECK_INTERVAL = 0.2
# Variables.
log = logging.getLogger(APP_NAME)
last_cpu_work = 0
@ -662,11 +665,20 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
if script:
# Execute the demo.
exec_cmd_nowait(script)
self.wfile.write("{}".encode(encoding="utf_8"))
self.wfile.write(json.dumps({"id": demo_id}).encode(encoding="utf_8"))
else:
self.wfile.write(json.dumps({"error": "NPU demo launch script not found."}).encode(encoding="utf_8"))
else:
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:
# Forbidden.
self._set_headers(403)
@ -1896,6 +1908,59 @@ def get_npu_demos_for_platform(platform_name):
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():
"""
Returns the running platform ID.

View File

@ -26,6 +26,7 @@ Digi Demo - NPU
<script type="text/javascript" src="./static/js/toastr.min.js"></script>
</head>
<body>
<div id="black_frame" class="npu-black-frame"></div>
<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="index.html">
@ -44,7 +45,6 @@ Digi Demo - NPU
</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' -->
@ -229,8 +229,6 @@ Digi Demo - NPU
setSelectedSection();
});
</script>
</body>
</html>

View File

@ -351,7 +351,7 @@ body {
width: 100%;
height: 100%;
position: relative;
z-index: 997;
z-index: 1003;
text-align: center;
}
@ -372,7 +372,7 @@ body {
/* POPUP */
.popup {
z-index: 999;
z-index: 1002;
position: fixed;
transform: translate(-50%, -50%);
background-color: white;
@ -2418,3 +2418,17 @@ select {
font-size: 1.25em;
}
/* 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;
}

View File

@ -83,6 +83,7 @@ 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_IS_RUNNING = "is_running";
const ID_KERNEL_VERSION = "kernel_version";
const ID_LAST_MODIFIED = "last_modified";
const ID_LED = "led";

View File

@ -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 HIDE_STATUS_TIMEOUT = 10000; // 10 seconds.
const CHECK_DEMO_RUNNING_OFFSET = 8000;
const CHECK_DEMO_RUNNING_TIME = 200;
// Variables.
var readingNPUInfo = false;
@ -155,12 +156,71 @@ function runNPUDemo(npuDemoID) {
function processRunNPUDemoResponse(response) {
// Check if there was any error in the request.
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(() => {
// Process only in the NPU page.
if (!isNPUShowing())
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.
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);
}
}