Refactor HomeView to use energyStore for energy data Refactor HomeView

to use energyStore for energy data
This commit is contained in:
rafaeldpsilva
2025-10-01 12:57:09 +01:00
parent 6ee4801071
commit cb659c93bb
5 changed files with 90 additions and 41 deletions

View File

@@ -1,10 +1,12 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref, computed } from 'vue' import { ref, computed, reactive, watch } from 'vue'
import { useWebSocketStore } from './websocket' import { useWebSocketStore } from './websocket'
import { useSensorStore } from './sensor' import { useSensorStore } from './sensor'
import { useRoomStore } from './room' import { useRoomStore } from './room'
import { useAnalyticsStore } from './analytics' import { useAnalyticsStore } from './analytics'
const MAX_HISTORY_POINTS = 100
/** /**
* Energy Store - Simplified to only track energy consumption metrics * Energy Store - Simplified to only track energy consumption metrics
* For sensor data: use useSensorStore() * For sensor data: use useSensorStore()
@@ -20,34 +22,66 @@ export const useEnergyStore = defineStore('energy', () => {
const analyticsStore = useAnalyticsStore() const analyticsStore = useAnalyticsStore()
// Energy-specific state // Energy-specific state
const currentConsumption = ref(0) // Current energy consumption in kWh const currentConsumption = ref<number>(0) // Current energy consumption in kWh
const averageConsumption = ref(0) // Average energy consumption in kWh const averageConsumption = ref<number>(0) // Average energy consumption in kWh
// Computed: Current energy value from WebSocket // Track aggregated energy over time
const currentEnergyValue = computed(() => { const energyHistory = reactive<number[]>([])
return websocketStore.latestMessage?.energy?.value || 0 const energyTimestamps = reactive<string[]>([])
// Computed: Current total energy value - sum of all sensor readings
const currentEnergyValue = computed<number>(() => {
// Sum energy values from all sensors' latest readings
let totalEnergy: number = 0
const readings = Array.from(sensorStore.latestReadings.values())
readings.forEach((reading) => {
if (reading.energy?.value) {
totalEnergy += reading.energy.value
}
}) })
// Computed: Average energy usage from time series return totalEnergy
const averageEnergyUsage = computed(() => {
const data = websocketStore.timeSeriesData.datasets[0].data
if (data.length === 0) return 0
const sum = data.reduce((acc, val) => acc + val, 0)
return sum / data.length
}) })
// Computed: Average energy usage from history
const averageEnergyUsage = computed<number>(() => {
if (energyHistory.length === 0) return 0
const sum: number = energyHistory.reduce((acc: number, val: number) => acc + val, 0)
return sum / energyHistory.length
})
// Watch for changes in sensor readings and update history
watch(
() => sensorStore.latestReadings.size,
() => {
const currentTotal: number = currentEnergyValue.value
const timestamp: string = new Date().toLocaleTimeString()
// Add to history
energyHistory.push(currentTotal)
energyTimestamps.push(timestamp)
// Keep only the latest MAX_HISTORY_POINTS
if (energyHistory.length > MAX_HISTORY_POINTS) {
energyHistory.shift()
energyTimestamps.shift()
}
}
)
// Update current consumption (called from components or watchers) // Update current consumption (called from components or watchers)
function updateCurrentConsumption(value: number) { function updateCurrentConsumption(value: number): void {
currentConsumption.value = value currentConsumption.value = value
} }
// Update average consumption (called from components or watchers) // Update average consumption (called from components or watchers)
function updateAverageConsumption(value: number) { function updateAverageConsumption(value: number): void {
averageConsumption.value = value averageConsumption.value = value
} }
// Initialize data from APIs (convenience function for AnalyticsView) // Initialize data from APIs (convenience function for AnalyticsView)
async function initializeFromApi() { async function initializeFromApi(): Promise<void> {
await Promise.allSettled([ await Promise.allSettled([
roomStore.loadRoomsFromAPI(), roomStore.loadRoomsFromAPI(),
sensorStore.fetchApiSensors(), sensorStore.fetchApiSensors(),
@@ -62,6 +96,8 @@ export const useEnergyStore = defineStore('energy', () => {
averageConsumption, averageConsumption,
currentEnergyValue, currentEnergyValue,
averageEnergyUsage, averageEnergyUsage,
energyHistory,
energyTimestamps,
// Energy-specific actions // Energy-specific actions
updateCurrentConsumption, updateCurrentConsumption,

View File

@@ -30,11 +30,11 @@ export const useRoomStore = defineStore('room', () => {
const apiRooms = ref<ApiRoomInfo[]>([]) const apiRooms = ref<ApiRoomInfo[]>([])
const roomsLoading = ref<boolean>(false) const roomsLoading = ref<boolean>(false)
const roomsLoaded = ref<boolean>(false) const roomsLoaded = ref<boolean>(false)
const apiLoading = ref(false) const apiLoading = ref<boolean>(false)
const apiError = ref<string | null>(null) const apiError = ref<string | null>(null)
// Actions // Actions
function updateRoomData(data: SensorReading) { function updateRoomData(data: SensorReading): void {
const sensorStore = useSensorStore() const sensorStore = useSensorStore()
// Validate data structure and provide fallbacks // Validate data structure and provide fallbacks
@@ -169,7 +169,14 @@ export const useRoomStore = defineStore('room', () => {
return true return true
} }
function getRoomStats(roomName: string) { function getRoomStats(roomName: string): {
sensorCount: number
sensorTypes: string[]
hasMetrics: boolean
energyConsumption: number
co2Level: number
lastUpdated: number | null
} {
const sensorStore = useSensorStore() const sensorStore = useSensorStore()
const sensorsInRoom = sensorStore.getSensorsByRoom(roomName) const sensorsInRoom = sensorStore.getSensorsByRoom(roomName)
const roomMetrics = roomsData.get(roomName) const roomMetrics = roomsData.get(roomName)
@@ -184,7 +191,15 @@ export const useRoomStore = defineStore('room', () => {
} }
} }
function getAllRoomsWithStats() { function getAllRoomsWithStats(): Array<{
name: string
sensorCount: number
sensorTypes: string[]
hasMetrics: boolean
energyConsumption: number
co2Level: number
lastUpdated: number | null
}> {
return availableRooms.value.map((room) => ({ return availableRooms.value.map((room) => ({
name: room, name: room,
...getRoomStats(room), ...getRoomStats(room),

View File

@@ -14,8 +14,8 @@ export const useSensorStore = defineStore('sensor', () => {
const latestReadings = reactive<Map<string, SensorReading>>(new Map()) const latestReadings = reactive<Map<string, SensorReading>>(new Map())
const sensorsData = reactive<Map<string, any>>(new Map()) // Legacy support const sensorsData = reactive<Map<string, any>>(new Map()) // Legacy support
const recentlyUpdatedSensors = reactive<Set<string>>(new Set()) // Track recently updated sensors const recentlyUpdatedSensors = reactive<Set<string>>(new Set()) // Track recently updated sensors
const totalReadings = ref(0) // Total number of readings across all sensors const totalReadings = ref<number>(0) // Total number of readings across all sensors
const apiLoading = ref(false) const apiLoading = ref<boolean>(false)
const apiError = ref<string | null>(null) const apiError = ref<string | null>(null)
// Computed properties // Computed properties
@@ -23,12 +23,12 @@ export const useSensorStore = defineStore('sensor', () => {
const activeSensors = computed(() => { const activeSensors = computed(() => {
return Array.from(sensorDevices.values()).filter( return Array.from(sensorDevices.values()).filter(
sensor => sensor.status === 'active' || sensor.status === 'online' (sensor) => sensor.status === 'active' || sensor.status === 'online',
).length ).length
}) })
// Actions // Actions
function updateSensorRoom(sensorId: string, newRoom: string) { function updateSensorRoom(sensorId: string, newRoom: string): void {
const sensor = sensorDevices.get(sensorId) const sensor = sensorDevices.get(sensorId)
if (sensor) { if (sensor) {
sensor.room = newRoom sensor.room = newRoom
@@ -36,14 +36,14 @@ export const useSensorStore = defineStore('sensor', () => {
} }
} }
async function executeSensorAction(sensorId: string, actionId: string) { async function executeSensorAction(sensorId: string, actionId: string): Promise<boolean> {
const sensor = sensorDevices.get(sensorId) const sensor = sensorDevices.get(sensorId)
if (!sensor) return false if (!sensor) return false
const action = sensor.capabilities.actions.find((a) => a.id === actionId) const action = sensor.capabilities.actions.find((a) => a.id === actionId)
if (!action) return false if (!action) return false
return new Promise((resolve) => { return new Promise<boolean>((resolve) => {
setTimeout(() => { setTimeout(() => {
console.log(`Action ${action.name} executed successfully on ${sensor.name}`) console.log(`Action ${action.name} executed successfully on ${sensor.name}`)
resolve(true) resolve(true)
@@ -59,11 +59,11 @@ export const useSensorStore = defineStore('sensor', () => {
return Array.from(sensorDevices.values()).filter((sensor) => sensor.type === type) return Array.from(sensorDevices.values()).filter((sensor) => sensor.type === type)
} }
function updateEnergySensors(data: Sensor) { function updateEnergySensors(data: SensorReading): void {
console.log(data) console.log(data)
} }
function updateLatestReading(reading: SensorReading) { function updateLatestReading(reading: SensorReading): void {
latestReadings.set(reading.sensor_id, reading) latestReadings.set(reading.sensor_id, reading)
// Increment total readings count // Increment total readings count
@@ -191,12 +191,12 @@ export const useSensorStore = defineStore('sensor', () => {
console.log(result) console.log(result)
// Check if result has a sensors property (common API pattern) // Check if result has a sensors property (common API pattern)
if (result.sensors && Array.isArray(result.sensors)) { if (result.sensors && Array.isArray(result.sensors)) {
let totalReadingsCount = 0 let totalReadingsCount: number = 0
result.sensors.forEach((sensor) => { result.sensors.forEach((sensor) => {
const sensorKey = sensor._id || sensor.sensor_id const sensorKey: string = sensor._id || sensor.sensor_id
const sensorType = sensor.sensor_type || sensor.type const sensorType: string = sensor.sensor_type || sensor.type
const sensorName = sensor.name || '' const sensorName: string = sensor.name || ''
// Accumulate total readings // Accumulate total readings
if (sensor.total_readings) { if (sensor.total_readings) {

View File

@@ -24,7 +24,7 @@ interface SensorReading {
} }
export const useWebSocketStore = defineStore('websocket', () => { export const useWebSocketStore = defineStore('websocket', () => {
const isConnected = ref(false) const isConnected = ref<boolean>(false)
const latestMessage = ref<SensorReading | null>(null) const latestMessage = ref<SensorReading | null>(null)
const timeSeriesData = reactive<{ const timeSeriesData = reactive<{
labels: string[] labels: string[]
@@ -37,7 +37,7 @@ export const useWebSocketStore = defineStore('websocket', () => {
let socket: WebSocket | null = null let socket: WebSocket | null = null
const newDataBuffer: SensorReading[] = [] const newDataBuffer: SensorReading[] = []
function connect(url: string) { function connect(url: string): void {
if (isConnected.value && socket) { if (isConnected.value && socket) {
console.log('Already connected.') console.log('Already connected.')
return return
@@ -109,13 +109,13 @@ export const useWebSocketStore = defineStore('websocket', () => {
}, 500) }, 500)
} }
function disconnect() { function disconnect(): void {
if (socket) { if (socket) {
socket.close() socket.close()
} }
} }
function processIncomingData(data: SensorReading) { function processIncomingData(data: SensorReading): void {
// Skip non-data messages // Skip non-data messages
if ('type' in data && (data.type === 'connection_established' || data.type === 'proxy_info')) { if ('type' in data && (data.type === 'connection_established' || data.type === 'proxy_info')) {
return return

View File

@@ -26,7 +26,7 @@
title="Real-time Energy" title="Real-time Energy"
:content="currentEnergyValue" :content="currentEnergyValue"
details="kWh" details="kWh"
:trend-data="websocketStore.timeSeriesData.datasets[0].data.slice(-8)" :trend-data="energyStore.energyHistory.slice(-8)"
trend-direction="neutral" trend-direction="neutral"
/> />
<GraphMetricCard <GraphMetricCard
@@ -74,15 +74,13 @@ const energyStore = useEnergyStore()
const websocketStore = useWebSocketStore() const websocketStore = useWebSocketStore()
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
// Use energy store for aggregated values across all sensors
const currentEnergyValue = computed(() => { const currentEnergyValue = computed(() => {
return websocketStore.latestMessage?.energy?.value.toFixed(2) || '0.00' return energyStore.currentEnergyValue.toFixed(2)
}) })
const averageEnergyUsage = computed(() => { const averageEnergyUsage = computed(() => {
const data = websocketStore.timeSeriesData.datasets[0].data return energyStore.averageEnergyUsage.toFixed(2)
if (data.length === 0) return '0.00'
const sum = data.reduce((acc, val) => acc + val, 0)
return (sum / data.length).toFixed(2)
}) })
onMounted(() => { onMounted(() => {