Skip to content

Commit fe7f8d8

Browse files
committed
Update chart UI
1 parent 0bf467b commit fe7f8d8

File tree

4 files changed

+75
-27
lines changed

4 files changed

+75
-27
lines changed

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

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
const canvas = document.getElementById('plot');
66
const ctx = canvas.getContext('2d');
7-
const width = canvas.width, height = canvas.height;
87
const maxSamples = 200;
98
const samples = [];
109
let errorContainer;
1110

12-
const recentAnomaliesElement = document.getElementById('recentClassifications'); // Renamed to recentAnomaliesElement but ID is recentClassifications
11+
const recentAnomaliesElement = document.getElementById('recentClassifications');
1312
let anomalies = [];
1413
const MAX_RECENT_ANOMALIES = 5;
1514

@@ -21,29 +20,33 @@ const noAccelerometerDataPlaceholder = document.getElementById('no-accelerometer
2120
function drawPlot() {
2221
if (!hasDataFromBackend) return; // Only draw if we have data
2322

24-
// clear
25-
// ctx.fillStyle = '#fff';
26-
// ctx.fillRect(0,0,width,height);
23+
const currentWidth = canvas.clientWidth;
24+
const currentHeight = canvas.clientHeight;
25+
26+
if (canvas.width !== currentWidth || canvas.height !== currentHeight) {
27+
canvas.width = currentWidth;
28+
canvas.height = currentHeight;
29+
}
2730

2831
// All grid lines (every 0.5) - same size
29-
ctx.strokeStyle = 'rgba(49, 51, 63, 0.6)';
32+
ctx.strokeStyle = '#31333F99';
3033
ctx.lineWidth = 0.5;
3134
ctx.beginPath();
3235
for (let i=0; i<=8; i++){
33-
const y = 10 + i*((height-20)/8);
36+
const y = 10 + i*((currentHeight-20)/8);
3437
ctx.moveTo(40,y);
35-
ctx.lineTo(width,y);
38+
ctx.lineTo(currentWidth,y);
3639
}
3740
ctx.stroke();
3841

3942
// Y-axis labels (-2.0 to 2.0 every 0.5)
40-
ctx.fillStyle = 'rgba(49, 51, 63, 0.6)';
41-
ctx.font = '12px Arial';
43+
ctx.fillStyle = '#666';
44+
ctx.font = '400 14px Arial';
4245
ctx.textAlign = 'right';
4346
ctx.textBaseline = 'middle';
4447

4548
for (let i=0; i<=8; i++) {
46-
const y = 10 + i*((height-20)/8);
49+
const y = 10 + i*((currentHeight-20)/8);
4750
const value = (2.0 - i * 0.5).toFixed(1);
4851
ctx.fillText(value, 35, y);
4952
}
@@ -55,9 +58,9 @@ function drawPlot() {
5558
ctx.beginPath();
5659
for (let i=0;i<samples.length;i++){
5760
const s = samples[i];
58-
const x = 40 + (i/(maxSamples-1))*(width-40);
61+
const x = 40 + (i/(maxSamples-1))*(currentWidth-40);
5962
const v = s[key];
60-
const y = (height/2) - (v * ((height-20)/4));
63+
const y = (currentHeight/2) - (v * ((currentHeight-20)/4));
6164
if (i===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
6265
}
6366
ctx.stroke();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ <h1 class="arduino-text">Vibration Anomaly Detection</h1>
2929
<div class="popover">Live visualization of raw accelerometer data (X, Y, Z axes) from the board's Movement module. Horizontal axis represents time; vertical axis shows acceleration in m/s<sup>2</sup></div>
3030
</div>
3131
<div id="accelerometer-data-display">
32-
<canvas id="plot" width="640" height="200"></canvas>
32+
<canvas id="plot"></canvas>
3333
<div class="legend">
3434
<div class="legend-item">
3535
<div class="legend-color" style="background-color: #0068C9;"></div>

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ body {
163163
flex-direction: column;
164164
}
165165

166+
.right-column {
167+
max-width: 100%;
168+
}
169+
166170
.arduino-text {
167171
font-size: 14px;
168172
}
@@ -450,13 +454,23 @@ body {
450454
border-bottom: 1px solid #DAE3E3;
451455
}
452456
.anomaly-score {
453-
font-weight: bold;
454-
color: #b00020; /* Red color for score */
457+
font-weight: normal;
458+
color: #2C353A;
459+
font-size: 12px;
455460
}
456461
.anomaly-text {
457-
/* Style for 'Anomaly' text if needed */
462+
color: #2C353A;
463+
font-size: 12px;
458464
}
459465
.anomaly-time {
460-
color: #5D6A6B; /* Grey for time */
461-
font-size: 11px;
462-
}
466+
color: #2C353A;
467+
font-size: 12px;
468+
}
469+
#accelerometer-data-display {
470+
margin-top: 20px;
471+
}
472+
473+
#plot {
474+
width: 100%;
475+
height: 250px;
476+
}

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

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# SPDX-License-Identifier: MPL-2.0
44

55
import json
6+
import time
7+
import math
8+
import threading
69
from datetime import datetime
710
from arduino.app_utils import *
811
from arduino.app_bricks.web_ui import WebUI
@@ -12,6 +15,10 @@
1215

1316
ui = WebUI()
1417

18+
# --- Configuration Constant ---
19+
USE_FAKE_DATA = False # Set to True to use simulated data, False to use real sensor data via Bridge RPC
20+
# ------------------------------
21+
1522
vibration_detection = VibrationAnomalyDetection(anomaly_detection_threshold=1.0)
1623

1724
def on_override_th(value: float):
@@ -55,13 +62,37 @@ def record_sensor_movement(x: float, y: float, z: float):
5562
logger.exception(f"record_sensor_movement: Error: {e}")
5663
print(f"record_sensor_movement: Error: {e}")
5764

58-
# Register the Bridge RPC provider so the sketch can call into Python
59-
try:
60-
logger.debug("Registering 'record_sensor_movement' Bridge provider")
61-
Bridge.provide("record_sensor_movement", record_sensor_movement)
62-
logger.debug("'record_sensor_movement' registered successfully")
63-
except RuntimeError:
64-
logger.debug("'record_sensor_movement' already registered")
65+
if USE_FAKE_DATA:
66+
# Faking sensor data for UI testing
67+
def generate_fake_data():
68+
logger.info("Starting fake data generation")
69+
start_time = time.time()
70+
while True:
71+
current_time = time.time() - start_time
72+
# Generate wave patterns for x, y, and z
73+
x = 0.5 * math.sin(2 * math.pi * 0.5 * current_time) # 0.5 Hz frequency
74+
y = 0.3 * math.sin(2 * math.pi * 1.0 * current_time + (math.pi / 2)) # 1.0 Hz frequency, 90-degree phase shift
75+
z = 0.8 * math.cos(2 * math.pi * 0.2 * current_time) # 0.2 Hz frequency, using cosine
76+
77+
# Introduce a sudden anomaly occasionally
78+
if int(current_time) % 20 == 0 and int(current_time) != 0:
79+
x += 0.5 * math.sin(2 * math.pi * 10 * current_time) # high frequency noise
80+
y += 0.5 * math.cos(2 * math.pi * 10 * current_time)
81+
82+
record_sensor_movement(x, y, z)
83+
time.sleep(0.1) # 10 Hz data rate
84+
85+
fake_data_thread = threading.Thread(target=generate_fake_data, daemon=True)
86+
fake_data_thread.start()
87+
else:
88+
# Register the Bridge RPC provider so the sketch can call into Python
89+
try:
90+
logger.debug("Registering 'record_sensor_movement' Bridge provider")
91+
Bridge.provide("record_sensor_movement", record_sensor_movement)
92+
logger.debug("'record_sensor_movement' registered successfully")
93+
except RuntimeError:
94+
logger.debug("'record_sensor_movement' already registered")
95+
6596

6697
# Let the App runtime manage bricks and run the web server
6798
App.run()

0 commit comments

Comments
 (0)