warning system
This commit is contained in:
parent
5e029ff99c
commit
0c5c7bcb5f
10 changed files with 1074 additions and 54 deletions
|
@ -1,36 +1,209 @@
|
|||
import { NextResponse } from 'next/server';
|
||||
import { SensorConfig } from '@/types/sensor';
|
||||
|
||||
// Sensor configuration that matches the API route
|
||||
const SENSOR_CONFIG = [
|
||||
// Head area
|
||||
{ id: "head-1", x: 45, y: 15, zone: "head", label: "Head Left", pin: 2 },
|
||||
{ id: "head-2", x: 55, y: 15, zone: "head", label: "Head Right", pin: 3 },
|
||||
const SENSOR_CONFIG: SensorConfig[] = [
|
||||
// Head area - Higher thresholds due to critical nature, faster escalation
|
||||
{
|
||||
id: "head-1",
|
||||
x: 45,
|
||||
y: 15,
|
||||
zone: "head",
|
||||
label: "Head Left",
|
||||
pin: 2,
|
||||
warningThreshold: 3000,
|
||||
alarmThreshold: 3500,
|
||||
warningDelayMs: 30000, // 30 seconds - fast escalation for head
|
||||
baseNoise: 200
|
||||
},
|
||||
{
|
||||
id: "head-2",
|
||||
x: 55,
|
||||
y: 15,
|
||||
zone: "head",
|
||||
label: "Head Right",
|
||||
pin: 3,
|
||||
warningThreshold: 3000,
|
||||
alarmThreshold: 3500,
|
||||
warningDelayMs: 30000, // 30 seconds
|
||||
baseNoise: 150
|
||||
},
|
||||
|
||||
// Shoulder area
|
||||
{ id: "shoulder-1", x: 35, y: 25, zone: "shoulders", label: "Left Shoulder", pin: 4 },
|
||||
{ id: "shoulder-2", x: 65, y: 25, zone: "shoulders", label: "Right Shoulder", pin: 5 },
|
||||
// Shoulder area - Moderate thresholds, medium escalation time
|
||||
{
|
||||
id: "shoulder-1",
|
||||
x: 35,
|
||||
y: 25,
|
||||
zone: "shoulders",
|
||||
label: "Left Shoulder",
|
||||
pin: 4,
|
||||
warningThreshold: 2800,
|
||||
alarmThreshold: 3200,
|
||||
warningDelayMs: 45000, // 45 seconds
|
||||
baseNoise: 250
|
||||
},
|
||||
{
|
||||
id: "shoulder-2",
|
||||
x: 65,
|
||||
y: 25,
|
||||
zone: "shoulders",
|
||||
label: "Right Shoulder",
|
||||
pin: 5,
|
||||
warningThreshold: 2800,
|
||||
alarmThreshold: 3200,
|
||||
warningDelayMs: 45000, // 45 seconds
|
||||
baseNoise: 220
|
||||
},
|
||||
|
||||
// Upper back
|
||||
{ id: "back-1", x: 40, y: 35, zone: "back", label: "Upper Back Left", pin: 6 },
|
||||
{ id: "back-2", x: 50, y: 35, zone: "back", label: "Upper Back Center", pin: 7 },
|
||||
{ id: "back-3", x: 60, y: 35, zone: "back", label: "Upper Back Right", pin: 8 },
|
||||
// Upper back - Moderate thresholds, 1 minute escalation
|
||||
{
|
||||
id: "back-1",
|
||||
x: 40,
|
||||
y: 35,
|
||||
zone: "back",
|
||||
label: "Upper Back Left",
|
||||
pin: 6,
|
||||
warningThreshold: 2500,
|
||||
alarmThreshold: 3000,
|
||||
warningDelayMs: 60000, // 1 minute
|
||||
baseNoise: 300
|
||||
},
|
||||
{
|
||||
id: "back-2",
|
||||
x: 50,
|
||||
y: 35,
|
||||
zone: "back",
|
||||
label: "Upper Back Center",
|
||||
pin: 7,
|
||||
warningThreshold: 2500,
|
||||
alarmThreshold: 3000,
|
||||
warningDelayMs: 60000, // 1 minute
|
||||
baseNoise: 350
|
||||
},
|
||||
{
|
||||
id: "back-3",
|
||||
x: 60,
|
||||
y: 35,
|
||||
zone: "back",
|
||||
label: "Upper Back Right",
|
||||
pin: 8,
|
||||
warningThreshold: 2500,
|
||||
alarmThreshold: 3000,
|
||||
warningDelayMs: 60000, // 1 minute
|
||||
baseNoise: 280
|
||||
},
|
||||
|
||||
// Lower back/Hip area
|
||||
{ id: "hip-1", x: 35, y: 50, zone: "hips", label: "Left Hip", pin: 9 },
|
||||
{ id: "hip-2", x: 50, y: 50, zone: "hips", label: "Lower Back", pin: 10 },
|
||||
{ id: "hip-3", x: 65, y: 50, zone: "hips", label: "Right Hip", pin: 11 },
|
||||
// Lower back/Hip area - Lower thresholds, 90 second escalation
|
||||
{
|
||||
id: "hip-1",
|
||||
x: 35,
|
||||
y: 50,
|
||||
zone: "hips",
|
||||
label: "Left Hip",
|
||||
pin: 9,
|
||||
warningThreshold: 2200,
|
||||
alarmThreshold: 2800,
|
||||
warningDelayMs: 90000, // 90 seconds
|
||||
baseNoise: 400
|
||||
},
|
||||
{
|
||||
id: "hip-2",
|
||||
x: 50,
|
||||
y: 50,
|
||||
zone: "hips",
|
||||
label: "Lower Back",
|
||||
pin: 10,
|
||||
warningThreshold: 2200,
|
||||
alarmThreshold: 2800,
|
||||
warningDelayMs: 90000, // 90 seconds
|
||||
baseNoise: 450
|
||||
},
|
||||
{
|
||||
id: "hip-3",
|
||||
x: 65,
|
||||
y: 50,
|
||||
zone: "hips",
|
||||
label: "Right Hip",
|
||||
pin: 11,
|
||||
warningThreshold: 2200,
|
||||
alarmThreshold: 2800,
|
||||
warningDelayMs: 90000, // 90 seconds
|
||||
baseNoise: 380
|
||||
},
|
||||
|
||||
// Thigh area
|
||||
{ id: "thigh-1", x: 40, y: 65, zone: "legs", label: "Left Thigh", pin: 12 },
|
||||
{ id: "thigh-2", x: 60, y: 65, zone: "legs", label: "Right Thigh", pin: 13 },
|
||||
// Thigh area - Lower thresholds, 2 minute escalation
|
||||
{
|
||||
id: "thigh-1",
|
||||
x: 40,
|
||||
y: 65,
|
||||
zone: "legs",
|
||||
label: "Left Thigh",
|
||||
pin: 12,
|
||||
warningThreshold: 2000,
|
||||
alarmThreshold: 2500,
|
||||
warningDelayMs: 120000, // 2 minutes
|
||||
baseNoise: 320
|
||||
},
|
||||
{
|
||||
id: "thigh-2",
|
||||
x: 60,
|
||||
y: 65,
|
||||
zone: "legs",
|
||||
label: "Right Thigh",
|
||||
pin: 13,
|
||||
warningThreshold: 2000,
|
||||
alarmThreshold: 2500,
|
||||
warningDelayMs: 120000, // 2 minutes
|
||||
baseNoise: 300
|
||||
},
|
||||
|
||||
// Calf area (mock data)
|
||||
{ id: "calf-1", x: 40, y: 75, zone: "legs", label: "Left Calf" },
|
||||
{ id: "calf-2", x: 60, y: 75, zone: "legs", label: "Right Calf" },
|
||||
// Calf area (mock data) - Lower thresholds, 2.5 minute escalation
|
||||
{
|
||||
id: "calf-1",
|
||||
x: 40,
|
||||
y: 75,
|
||||
zone: "legs",
|
||||
label: "Left Calf",
|
||||
warningThreshold: 1800,
|
||||
alarmThreshold: 2200,
|
||||
warningDelayMs: 150000, // 2.5 minutes
|
||||
baseNoise: 200
|
||||
},
|
||||
{
|
||||
id: "calf-2",
|
||||
x: 60,
|
||||
y: 75,
|
||||
zone: "legs",
|
||||
label: "Right Calf",
|
||||
warningThreshold: 1800,
|
||||
alarmThreshold: 2200,
|
||||
warningDelayMs: 150000, // 2.5 minutes
|
||||
baseNoise: 220
|
||||
},
|
||||
|
||||
// Feet (mock data)
|
||||
{ id: "feet-1", x: 45, y: 85, zone: "feet", label: "Left Foot" },
|
||||
{ id: "feet-2", x: 55, y: 85, zone: "feet", label: "Right Foot" },
|
||||
// Feet (mock data) - Lowest thresholds, 3 minute escalation
|
||||
{
|
||||
id: "feet-1",
|
||||
x: 45,
|
||||
y: 85,
|
||||
zone: "feet",
|
||||
label: "Left Foot",
|
||||
warningThreshold: 1500,
|
||||
alarmThreshold: 1800,
|
||||
warningDelayMs: 180000, // 3 minutes
|
||||
baseNoise: 150
|
||||
},
|
||||
{
|
||||
id: "feet-2",
|
||||
x: 55,
|
||||
y: 85,
|
||||
zone: "feet",
|
||||
label: "Right Foot",
|
||||
warningThreshold: 1500,
|
||||
alarmThreshold: 1800,
|
||||
warningDelayMs: 180000, // 3 minutes
|
||||
baseNoise: 160
|
||||
},
|
||||
];
|
||||
|
||||
export async function GET() {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { BedHardware, PinState, PinChange } from '@/services/BedHardware';
|
||||
import { SensorDataStorage, SensorDataPoint } from '@/services/SensorDataStorage';
|
||||
import { SensorConfig } from '@/types/sensor';
|
||||
|
||||
// Complete sensor configuration with positions, pin mappings, and thresholds
|
||||
const SENSOR_CONFIG = [
|
||||
const SENSOR_CONFIG: SensorConfig[] = [
|
||||
// Head area
|
||||
{ id: "head-1", x: 45, y: 15, zone: "head", label: "Head Left", pin: 2, baseNoise: 200, warningThreshold: 3000, alarmThreshold: 3500, warningDelayMs: 30000 },
|
||||
{ id: "head-2", x: 55, y: 15, zone: "head", label: "Head Right", pin: 3, baseNoise: 150, warningThreshold: 3000, alarmThreshold: 3500, warningDelayMs: 30000 },
|
||||
|
@ -235,6 +236,25 @@ function updateMockSensorData() {
|
|||
const currentSensor = sensorData[sensor.id];
|
||||
const variation = (Math.random() - 0.5) * 200; // Larger variation for analog values
|
||||
const newValue = Math.max(0, Math.min(4095, currentSensor.value + variation));
|
||||
const timestamp = Date.now();
|
||||
|
||||
// Determine status based on thresholds
|
||||
let status = 'normal';
|
||||
let warningStartTime = currentSensor.warningStartTime;
|
||||
|
||||
if (newValue >= sensor.alarmThreshold) {
|
||||
status = 'alarm';
|
||||
warningStartTime = undefined; // Clear warning timer for immediate alarm
|
||||
} else if (newValue >= sensor.warningThreshold) {
|
||||
status = 'warning';
|
||||
if (!warningStartTime) {
|
||||
warningStartTime = timestamp; // Start warning timer
|
||||
} else if (timestamp - warningStartTime >= sensor.warningDelayMs) {
|
||||
status = 'alarm'; // Escalate to alarm after delay
|
||||
}
|
||||
} else {
|
||||
warningStartTime = undefined; // Clear warning timer
|
||||
}
|
||||
|
||||
sensorData[sensor.id] = {
|
||||
...currentSensor,
|
||||
|
@ -248,8 +268,8 @@ function updateMockSensorData() {
|
|||
value: newValue,
|
||||
}
|
||||
],
|
||||
status: newValue >= sensor.alarmThreshold ? 'alarm' :
|
||||
newValue >= sensor.warningThreshold ? 'warning' : 'normal'
|
||||
status,
|
||||
warningStartTime
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
60
app/api/sensors/zones/route.ts
Normal file
60
app/api/sensors/zones/route.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { NextResponse } from 'next/server';
|
||||
import { ZONE_CONFIGS, validateSensorConfig } from '@/utils/sensorConfig';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
zones: ZONE_CONFIGS,
|
||||
description: 'Available sensor zones with default threshold configurations',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Zone config API error:', error);
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Failed to get zone configurations',
|
||||
zones: {},
|
||||
timestamp: new Date().toISOString()
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const sensorConfigs = await request.json();
|
||||
|
||||
if (!Array.isArray(sensorConfigs)) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Expected array of sensor configurations'
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
const validationResults = sensorConfigs.map(config => ({
|
||||
sensorId: config.id,
|
||||
...validateSensorConfig(config)
|
||||
}));
|
||||
|
||||
const hasErrors = validationResults.some(result => !result.isValid);
|
||||
|
||||
return NextResponse.json({
|
||||
success: !hasErrors,
|
||||
validationResults,
|
||||
summary: {
|
||||
total: sensorConfigs.length,
|
||||
valid: validationResults.filter(r => r.isValid).length,
|
||||
withWarnings: validationResults.filter(r => r.warnings.length > 0).length,
|
||||
withErrors: validationResults.filter(r => !r.isValid).length
|
||||
},
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Sensor validation API error:', error);
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Failed to validate sensor configurations'
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue