Skip to content

Commit d62f63e

Browse files
committed
UI update
1 parent 1272842 commit d62f63e

File tree

4 files changed

+79
-43
lines changed

4 files changed

+79
-43
lines changed

examples/vibration-anomaly-detection/assets/app.js

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ document.addEventListener('DOMContentLoaded', () => {
9393
initSocketIO();
9494
renderAccelerometerData(); // Initial render for accelerometer
9595
renderAnomalies(); // Initial render for anomalies
96-
updateFeedback(false); // Initial feedback state
96+
updateFeedback(null); // Initial feedback state
9797
initializeConfidenceSlider(); // Initialize the confidence slider
9898

9999
// Popover logic
@@ -139,25 +139,25 @@ function handleConfidenceInputChange() {
139139
const confidenceInput = document.getElementById('confidenceInput');
140140
const confidenceSlider = document.getElementById('confidenceSlider');
141141

142-
let value = parseFloat(confidenceInput.value);
142+
let value = parseInt(confidenceInput.value, 10);
143143

144-
if (isNaN(value)) value = 0.5;
145-
if (value < 0) value = 0;
146-
if (value > 1) value = 1;
144+
if (isNaN(value)) value = 5;
145+
if (value < 1) value = 1;
146+
if (value > 10) value = 10;
147147

148148
confidenceSlider.value = value;
149149
updateConfidenceDisplay();
150150
}
151151

152152
function validateConfidenceInput() {
153153
const confidenceInput = document.getElementById('confidenceInput');
154-
let value = parseFloat(confidenceInput.value);
154+
let value = parseInt(confidenceInput.value, 10);
155155

156-
if (isNaN(value)) value = 0.5;
157-
if (value < 0) value = 0;
158-
if (value > 1) value = 1;
156+
if (isNaN(value)) value = 5;
157+
if (value < 1) value = 1;
158+
if (value > 10) value = 10;
159159

160-
confidenceInput.value = value.toFixed(2);
160+
confidenceInput.value = value.toFixed(0);
161161

162162
handleConfidenceInputChange();
163163
}
@@ -169,10 +169,10 @@ function updateConfidenceDisplay() {
169169
const sliderProgress = document.getElementById('sliderProgress');
170170

171171
const value = parseFloat(confidenceSlider.value);
172-
socket.emit('override_th', value); // Send confidence to backend
172+
socket.emit('override_th', value / 10); // Send scaled confidence to backend (0.1 to 1.0)
173173
const percentage = (value - confidenceSlider.min) / (confidenceSlider.max - confidenceSlider.min) * 100;
174174

175-
const displayValue = value.toFixed(2);
175+
const displayValue = value.toFixed(0);
176176
confidenceValueDisplay.textContent = displayValue;
177177

178178
if (document.activeElement !== confidenceInput) {
@@ -187,8 +187,8 @@ function resetConfidence() {
187187
const confidenceSlider = document.getElementById('confidenceSlider');
188188
const confidenceInput = document.getElementById('confidenceInput');
189189

190-
confidenceSlider.value = '0.5';
191-
confidenceInput.value = '0.50';
190+
confidenceSlider.value = '5';
191+
confidenceInput.value = '5';
192192
updateConfidenceDisplay();
193193
}
194194

@@ -200,7 +200,13 @@ function initSocketIO() {
200200
}
201201
printAnomalies(message);
202202
renderAnomalies();
203-
updateFeedback(true);
203+
try {
204+
const parsedAnomaly = JSON.parse(message);
205+
updateFeedback(parsedAnomaly.score); // Pass the anomaly score
206+
} catch (e) {
207+
console.error("Failed to parse anomaly message for feedback:", message, e);
208+
updateFeedback(null); // Fallback to no anomaly feedback
209+
}
204210
});
205211

206212
socket.on('sample', (s) => {
@@ -225,7 +231,7 @@ function initSocketIO() {
225231

226232
// ... (existing printAnomalies and renderAnomalies functions)
227233

228-
function updateFeedback(hasAnomaly) {
234+
function updateFeedback(anomalyScore = null) {
229235
clearTimeout(feedbackTimeout); // Clear any existing timeout
230236

231237
if (!hasDataFromBackend) {
@@ -238,21 +244,20 @@ function updateFeedback(hasAnomaly) {
238244
return;
239245
}
240246

241-
if (hasAnomaly) {
247+
if (anomalyScore !== null) { // Anomaly detected
242248
feedbackContentWrapper.innerHTML = `
243249
<div class="feedback-content">
244-
<img src="./img/good.svg" alt="Anomaly Detected">
245-
<p class="feedback-text">Anomaly Detected!</p>
250+
<img src="./img/bad.svg" alt="Anomaly Detected">
251+
<p class="feedback-text">Anomaly detected: ${anomalyScore.toFixed(2)}</p>
246252
</div>
247253
`;
248-
// Reset to "No anomalies" state after 3 seconds
249254
feedbackTimeout = setTimeout(() => {
250-
updateFeedback(false);
255+
updateFeedback(null); // Reset after 3 seconds
251256
}, 3000);
252-
} else {
257+
} else { // No anomaly or reset
253258
feedbackContentWrapper.innerHTML = `
254259
<div class="feedback-content">
255-
<img src="./img/bad.svg" alt="No Anomalies">
260+
<img src="./img/good.svg" alt="No Anomalies">
256261
<p class="feedback-text">No anomalies</p>
257262
</div>
258263
`;
@@ -285,25 +290,22 @@ function renderAnomalies() {
285290
return; // Skip empty anomaly objects
286291
}
287292

288-
const row = document.createElement('div');
289-
row.className = 'anomaly-container'; // Using a new class for styling
293+
const listItem = document.createElement('li');
294+
listItem.className = 'anomaly-list-item';
290295

291-
const cellContainer = document.createElement('span');
292-
cellContainer.className = 'anomaly-cell-container';
296+
const score = parsedAnomaly.score.toFixed(1);
297+
const date = new Date(parsedAnomaly.timestamp);
293298

294-
const scoreText = document.createElement('span');
295-
scoreText.className = 'anomaly-content';
296-
const value = parsedAnomaly.score; // Assuming 'score' is a property
297-
scoreText.innerHTML = `Anomaly Score: ${value.toFixed(2)}`;
299+
const timeString = date.toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
300+
const dateString = date.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }).replace(/ /g, ' ');
298301

299-
const timeText = document.createElement('span');
300-
timeText.className = 'anomaly-content-time';
301-
timeText.textContent = new Date(parsedAnomaly.timestamp).toLocaleString('it-IT').replace(',', ' -'); // Assuming 'timestamp' property
302+
listItem.innerHTML = `
303+
<span class="anomaly-score">${score}</span>
304+
<span class="anomaly-text">Anomaly</span>
305+
<span class="anomaly-time">${timeString} - ${dateString}</span>
306+
`;
302307

303-
cellContainer.appendChild(scoreText);
304-
cellContainer.appendChild(timeText);
305-
row.appendChild(cellContainer);
306-
recentAnomaliesElement.appendChild(row);
308+
recentAnomaliesElement.appendChild(listItem);
307309

308310
} catch (e) {
309311
console.error("Failed to parse anomaly data:", anomaly, e);

examples/vibration-anomaly-detection/assets/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,18 @@ <h1 class="arduino-text">Vibration Anomaly Detection</h1>
5858
Scores above your threshold are flagged as an anomaly.</div>
5959
</div>
6060
<button id="confidenceResetButton" class="btn-tertiary">
61-
<input type="number" id="confidenceInput" class="confidence-input" min="0" max="1" step="0.05" value="0.50">
61+
<input type="number" id="confidenceInput" class="confidence-input" min="1" max="10" step="1" value="5">
6262
<img src="img/reset.svg" alt="Reset" class="reset-icon">
6363
</button>
6464
</div>
6565
<div class="slider-box">
66-
<span class="confidence-limits">0</span>
66+
<span class="confidence-limits">1</span>
6767
<div class="slider-container">
6868
<div class="slider-progress" id="sliderProgress"></div>
69-
<div class="confidence-value-display" id="confidenceValueDisplay">0.5</div>
70-
<input type="range" id="confidenceSlider" min="0" max="1" step="0.01" value="0.5">
69+
<div class="confidence-value-display" id="confidenceValueDisplay">5</div>
70+
<input type="range" id="confidenceSlider" min="1" max="10" step="1" value="5">
7171
</div>
72-
<span class="confidence-limits">1</span>
72+
<span class="confidence-limits">10</span>
7373
</div>
7474
</div>
7575
</div>

examples/vibration-anomaly-detection/assets/style.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,4 +440,23 @@ body {
440440

441441
.btn-tertiary:hover .reset-icon {
442442
opacity: 1;
443+
}
444+
445+
.anomaly-list-item {
446+
display: flex;
447+
justify-content: space-between;
448+
align-items: center;
449+
padding: 16px 0;
450+
border-bottom: 1px solid #DAE3E3;
451+
}
452+
.anomaly-score {
453+
font-weight: bold;
454+
color: #b00020; /* Red color for score */
455+
}
456+
.anomaly-text {
457+
/* Style for 'Anomaly' text if needed */
458+
}
459+
.anomaly-time {
460+
color: #5D6A6B; /* Grey for time */
461+
font-size: 11px;
443462
}

examples/vibration-anomaly-detection/python/main.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#
33
# SPDX-License-Identifier: MPL-2.0
44

5+
import json
6+
from datetime import datetime
57
from arduino.app_utils import *
68
from arduino.app_bricks.web_ui import WebUI
79
from arduino.app_bricks.vibration_anomaly_detection import VibrationAnomalyDetection
@@ -12,6 +14,11 @@
1214

1315
vibration_detection = VibrationAnomalyDetection(anomaly_detection_threshold=1.0)
1416

17+
@ui.on('override_th')
18+
def on_override_th(value: float):
19+
logger.info(f"Setting new anomaly threshold: {value}")
20+
vibration_detection.anomaly_detection_threshold = value
21+
1522
def get_fan_status(anomaly_detected: bool):
1623
return {
1724
"anomaly": anomaly_detected,
@@ -22,6 +29,11 @@ def get_fan_status(anomaly_detected: bool):
2229
# Register action to take after successful detection
2330
def on_detected_anomaly(anomaly_score: float, classification: dict):
2431
print(f"Detected anomaly. Score: {anomaly_score}")
32+
anomaly_payload = {
33+
"score": anomaly_score,
34+
"timestamp": datetime.now().isoformat()
35+
}
36+
ui.send_message('anomaly_detected', json.dumps(anomaly_payload))
2537
ui.send_message('fan_status_update', get_fan_status(True))
2638

2739
vibration_detection.on_anomaly(on_detected_anomaly)
@@ -34,6 +46,9 @@ def record_sensor_movement(x: float, y: float, z: float):
3446
y_ms2 = y * 9.81
3547
z_ms2 = z * 9.81
3648

49+
# Forward raw data to UI for plotting
50+
ui.send_message('sample', {'x': x_ms2, 'y': y_ms2, 'z': z_ms2})
51+
3752
# Forward samples to the vibration_detection brick
3853
vibration_detection.accumulate_samples((x_ms2, y_ms2, z_ms2))
3954

0 commit comments

Comments
 (0)