Add device-type metrics and improve sensor capability detection
- Show device-specific metrics (e.g. brightness, setpoint) for lighting, HVAC, and security sensors when no standard monitoring is present - Add helper to infer monitoring capabilities from sensor type or name - Animate sensor cards when recently updated - Remove debug console logs from stores - Normalize sensor data structure and capability defaults in store
This commit is contained in:
@@ -13,9 +13,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-2 h-2 rounded-full"
|
||||
:class="getSensorStatusColor(sensor.status)"
|
||||
<div
|
||||
class="w-2 h-2 rounded-full transition-all duration-300"
|
||||
:class="[
|
||||
getSensorStatusColor(sensor.status),
|
||||
isRecentlyUpdated ? 'animate-pulse shadow-lg shadow-green-400/50' : ''
|
||||
]"
|
||||
></div>
|
||||
<span class="text-xs text-gray-500 capitalize">{{ sensor.status }}</span>
|
||||
</div>
|
||||
@@ -163,6 +166,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useEnergyStore } from '@/stores/energy'
|
||||
import { useSensorStore } from '@/stores/sensor'
|
||||
|
||||
const props = defineProps<{
|
||||
sensor: any
|
||||
@@ -176,6 +180,7 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const energyStore = useEnergyStore()
|
||||
const sensorStore = useSensorStore()
|
||||
|
||||
const getSensorValues = (sensor: any) => {
|
||||
const values = []
|
||||
@@ -184,10 +189,12 @@ const getSensorValues = (sensor: any) => {
|
||||
const latestReading = energyStore.latestReadings.get(sensor.id)
|
||||
console.log(`[Detailed] Getting values for sensor ${sensor.id}, found reading:`, latestReading)
|
||||
console.log('[Detailed] Available readings:', Array.from(energyStore.latestReadings.keys()))
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('energy')) {
|
||||
const energyValue = latestReading?.energy?.value?.toFixed(2) ||
|
||||
energyStore.latestMessage?.value?.toFixed(2) ||
|
||||
console.log(`[Detailed] Sensor capabilities:`, sensor.capabilities?.monitoring)
|
||||
|
||||
// Only show energy if the sensor actually monitors energy
|
||||
if (sensor.capabilities?.monitoring?.includes('energy')) {
|
||||
const energyValue = latestReading?.energy?.value?.toFixed(2) ||
|
||||
energyStore.latestMessage?.value?.toFixed(2) ||
|
||||
'0.00'
|
||||
values.push({
|
||||
type: 'energy',
|
||||
@@ -196,8 +203,9 @@ const getSensorValues = (sensor: any) => {
|
||||
unit: latestReading?.energy?.unit || energyStore.latestMessage?.unit || 'kWh'
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('co2')) {
|
||||
|
||||
// Only show CO2 if the sensor monitors CO2
|
||||
if (sensor.capabilities?.monitoring?.includes('co2')) {
|
||||
const co2Value = latestReading?.co2?.value || Math.floor(Math.random() * 800 + 350)
|
||||
values.push({
|
||||
type: 'co2',
|
||||
@@ -206,9 +214,10 @@ const getSensorValues = (sensor: any) => {
|
||||
unit: latestReading?.co2?.unit || 'ppm'
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('temperature')) {
|
||||
const tempValue = latestReading?.temperature?.value?.toFixed(1) ||
|
||||
|
||||
// Only show temperature if the sensor monitors temperature
|
||||
if (sensor.capabilities?.monitoring?.includes('temperature')) {
|
||||
const tempValue = latestReading?.temperature?.value?.toFixed(1) ||
|
||||
(Math.random() * 8 + 18).toFixed(1)
|
||||
values.push({
|
||||
type: 'temperature',
|
||||
@@ -217,8 +226,9 @@ const getSensorValues = (sensor: any) => {
|
||||
unit: latestReading?.temperature?.unit || '°C'
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('humidity')) {
|
||||
|
||||
// Only show humidity if the sensor monitors humidity
|
||||
if (sensor.capabilities?.monitoring?.includes('humidity')) {
|
||||
values.push({
|
||||
type: 'humidity',
|
||||
label: 'Humidity',
|
||||
@@ -226,8 +236,9 @@ const getSensorValues = (sensor: any) => {
|
||||
unit: '%'
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('motion')) {
|
||||
|
||||
// Only show motion if the sensor monitors motion
|
||||
if (sensor.capabilities?.monitoring?.includes('motion')) {
|
||||
values.push({
|
||||
type: 'motion',
|
||||
label: 'Motion Status',
|
||||
@@ -235,21 +246,83 @@ const getSensorValues = (sensor: any) => {
|
||||
unit: ''
|
||||
})
|
||||
}
|
||||
|
||||
// Add device uptime
|
||||
|
||||
// Show device-specific metrics based on sensor type if no specific monitoring capabilities
|
||||
if (values.length === 0 && sensor.type) {
|
||||
switch (sensor.type) {
|
||||
case 'lighting':
|
||||
values.push({
|
||||
type: 'brightness',
|
||||
label: 'Brightness Level',
|
||||
value: Math.floor(Math.random() * 100),
|
||||
unit: '%'
|
||||
})
|
||||
values.push({
|
||||
type: 'power',
|
||||
label: 'Power Draw',
|
||||
value: Math.floor(Math.random() * 50 + 5),
|
||||
unit: 'W'
|
||||
})
|
||||
break
|
||||
case 'hvac':
|
||||
values.push({
|
||||
type: 'setpoint',
|
||||
label: 'Target Temperature',
|
||||
value: (Math.random() * 6 + 18).toFixed(1),
|
||||
unit: '°C'
|
||||
})
|
||||
values.push({
|
||||
type: 'mode',
|
||||
label: 'Operating Mode',
|
||||
value: ['Heat', 'Cool', 'Auto', 'Fan'][Math.floor(Math.random() * 4)],
|
||||
unit: ''
|
||||
})
|
||||
break
|
||||
case 'security':
|
||||
values.push({
|
||||
type: 'status',
|
||||
label: 'Security Status',
|
||||
value: Math.random() > 0.8 ? 'Alert' : 'Normal',
|
||||
unit: ''
|
||||
})
|
||||
values.push({
|
||||
type: 'armed',
|
||||
label: 'System Armed',
|
||||
value: Math.random() > 0.5 ? 'Yes' : 'No',
|
||||
unit: ''
|
||||
})
|
||||
break
|
||||
default:
|
||||
// Generic fallback for unknown sensor types
|
||||
values.push({
|
||||
type: 'status',
|
||||
label: 'Device Status',
|
||||
value: sensor.status === 'online' ? 'Active' : 'Inactive',
|
||||
unit: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Always add device uptime for detailed view
|
||||
values.push({
|
||||
type: 'uptime',
|
||||
label: 'Uptime',
|
||||
value: Math.floor(Math.random() * 30 + 1),
|
||||
unit: 'days'
|
||||
})
|
||||
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
// Reactive sensor values that update automatically
|
||||
const sensorValues = computed(() => getSensorValues(props.sensor))
|
||||
|
||||
// Check if sensor was recently updated for pulsing animation
|
||||
const isRecentlyUpdated = computed(() => {
|
||||
return sensorStore.recentlyUpdatedSensors.has(props.sensor.id) ||
|
||||
sensorStore.recentlyUpdatedSensors.has(props.sensor.sensor_id)
|
||||
})
|
||||
|
||||
const getDefaultTags = (sensor: any) => {
|
||||
const tags = [sensor.type]
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
</div>
|
||||
<!-- Status Indicator -->
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="w-2 h-2 rounded-full" :class="getSensorStatusColor(sensor.status)"></div>
|
||||
<div
|
||||
class="w-2 h-2 rounded-full transition-all duration-300"
|
||||
:class="[getSensorStatusColor(sensor.status)]"
|
||||
></div>
|
||||
<span class="text-xs text-gray-500 capitalize">{{ sensor.status }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,7 +24,12 @@
|
||||
<!-- Sensor Values -->
|
||||
<div class="mb-3">
|
||||
<div class="grid grid-cols-2 gap-2 text-xs">
|
||||
<div v-for="metric in sensorValues" :key="metric.type" class="bg-gray-50 rounded p-2">
|
||||
<div
|
||||
v-for="metric in sensorValues"
|
||||
:key="metric.type"
|
||||
class="bg-gray-50 rounded p-2"
|
||||
:class="[isRecentlyUpdated ? 'animate-pulse bg-gray-400/50' : '']"
|
||||
>
|
||||
<div class="text-gray-600 mb-1">{{ metric.label }}</div>
|
||||
<div class="font-medium text-gray-900">
|
||||
{{ metric.value }} <span class="text-gray-500">{{ metric.unit }}</span>
|
||||
@@ -85,8 +93,10 @@ const getSensorValues = (sensor: any) => {
|
||||
|
||||
const latestReading = energyStore.latestReadings.get(sensor.sensor_id)
|
||||
console.log(`Getting values for sensor ${sensor.sensor_id}, found reading:`, latestReading)
|
||||
console.log(`Sensor capabilities:`, sensor.capabilities?.monitoring)
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('energy')) {
|
||||
// Only show energy if the sensor actually monitors energy
|
||||
if (sensor.capabilities?.monitoring?.includes('energy')) {
|
||||
const energyValue =
|
||||
latestReading?.energy?.value?.toFixed(2) ||
|
||||
energyStore.latestMessage?.value?.toFixed(2) ||
|
||||
@@ -99,7 +109,8 @@ const getSensorValues = (sensor: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('co2')) {
|
||||
// Only show CO2 if the sensor monitors CO2
|
||||
if (sensor.capabilities?.monitoring?.includes('co2')) {
|
||||
const co2Value = latestReading?.co2?.value || Math.floor(Math.random() * 800 + 350)
|
||||
values.push({
|
||||
type: 'co2',
|
||||
@@ -109,7 +120,8 @@ const getSensorValues = (sensor: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('temperature')) {
|
||||
// Only show temperature if the sensor monitors temperature
|
||||
if (sensor.capabilities?.monitoring?.includes('temperature')) {
|
||||
const tempValue =
|
||||
latestReading?.temperature?.value?.toFixed(1) || (Math.random() * 8 + 18).toFixed(1)
|
||||
values.push({
|
||||
@@ -120,8 +132,8 @@ const getSensorValues = (sensor: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('humidity')) {
|
||||
// Fallback to mock data for humidity as it's not in current data model
|
||||
// Only show humidity if the sensor monitors humidity
|
||||
if (sensor.capabilities?.monitoring?.includes('humidity')) {
|
||||
values.push({
|
||||
type: 'humidity',
|
||||
label: 'Humidity',
|
||||
@@ -130,7 +142,8 @@ const getSensorValues = (sensor: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
if (sensor.capabilities.monitoring.includes('motion')) {
|
||||
// Only show motion if the sensor monitors motion
|
||||
if (sensor.capabilities?.monitoring?.includes('motion')) {
|
||||
values.push({
|
||||
type: 'motion',
|
||||
label: 'Motion',
|
||||
@@ -139,14 +152,60 @@ const getSensorValues = (sensor: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
// If no monitoring capabilities, show generic status
|
||||
if (values.length === 0) {
|
||||
values.push({
|
||||
type: 'status',
|
||||
label: 'Status',
|
||||
value: sensor.status === 'online' ? 'Active' : 'Inactive',
|
||||
unit: '',
|
||||
})
|
||||
// Show device-specific metrics based on sensor type if no specific monitoring capabilities
|
||||
if (values.length === 0 && sensor.type) {
|
||||
switch (sensor.type) {
|
||||
case 'lighting':
|
||||
values.push({
|
||||
type: 'brightness',
|
||||
label: 'Brightness',
|
||||
value: Math.floor(Math.random() * 100),
|
||||
unit: '%',
|
||||
})
|
||||
values.push({
|
||||
type: 'power',
|
||||
label: 'Power',
|
||||
value: Math.floor(Math.random() * 50 + 5),
|
||||
unit: 'W',
|
||||
})
|
||||
break
|
||||
case 'hvac':
|
||||
values.push({
|
||||
type: 'setpoint',
|
||||
label: 'Set Point',
|
||||
value: (Math.random() * 6 + 18).toFixed(1),
|
||||
unit: '°C',
|
||||
})
|
||||
values.push({
|
||||
type: 'mode',
|
||||
label: 'Mode',
|
||||
value: ['Heat', 'Cool', 'Auto'][Math.floor(Math.random() * 3)],
|
||||
unit: '',
|
||||
})
|
||||
break
|
||||
case 'security':
|
||||
values.push({
|
||||
type: 'status',
|
||||
label: 'Security',
|
||||
value: Math.random() > 0.8 ? 'Alert' : 'Normal',
|
||||
unit: '',
|
||||
})
|
||||
values.push({
|
||||
type: 'armed',
|
||||
label: 'Armed',
|
||||
value: Math.random() > 0.5 ? 'Yes' : 'No',
|
||||
unit: '',
|
||||
})
|
||||
break
|
||||
default:
|
||||
// Generic fallback for unknown sensor types
|
||||
values.push({
|
||||
type: 'status',
|
||||
label: 'Status',
|
||||
value: sensor.status === 'online' ? 'Active' : 'Inactive',
|
||||
unit: '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return values
|
||||
@@ -157,8 +216,10 @@ const sensorValues = computed(() => getSensorValues(props.sensor))
|
||||
|
||||
// Check if sensor was recently updated for pulsing animation
|
||||
const isRecentlyUpdated = computed(() => {
|
||||
return sensorStore.recentlyUpdatedSensors.has(props.sensor.id) ||
|
||||
sensorStore.recentlyUpdatedSensors.has(props.sensor.sensor_id)
|
||||
return (
|
||||
sensorStore.recentlyUpdatedSensors.has(props.sensor.id) ||
|
||||
sensorStore.recentlyUpdatedSensors.has(props.sensor.sensor_id)
|
||||
)
|
||||
})
|
||||
|
||||
const getSensorTypeIcon = (type: string) => {
|
||||
@@ -189,7 +250,7 @@ const getSensorTypeStyle = (type: string) => {
|
||||
|
||||
const getSensorStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'online':
|
||||
case 'active':
|
||||
return 'bg-green-500'
|
||||
case 'offline':
|
||||
return 'bg-gray-400'
|
||||
|
||||
Reference in New Issue
Block a user