general dashboard
This commit is contained in:
165
src/stores/energy.ts
Normal file
165
src/stores/energy.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
const MAX_DATA_POINTS = 100 // Keep the last 100 data points for the chart
|
||||
|
||||
interface SensorReading {
|
||||
sensorId: string
|
||||
room: string
|
||||
timestamp: number
|
||||
energy: {
|
||||
value: number
|
||||
unit: string
|
||||
}
|
||||
co2: {
|
||||
value: number
|
||||
unit: string
|
||||
}
|
||||
temperature?: {
|
||||
value: number
|
||||
unit: string
|
||||
}
|
||||
}
|
||||
|
||||
interface RoomMetrics {
|
||||
room: string
|
||||
sensors: string[]
|
||||
energy: {
|
||||
current: number
|
||||
total: number
|
||||
average: number
|
||||
unit: string
|
||||
}
|
||||
co2: {
|
||||
current: number
|
||||
average: number
|
||||
max: number
|
||||
status: 'good' | 'moderate' | 'poor' | 'critical'
|
||||
unit: string
|
||||
}
|
||||
occupancyEstimate: 'low' | 'medium' | 'high'
|
||||
lastUpdated: number
|
||||
}
|
||||
|
||||
interface LegacyEnergyData {
|
||||
sensorId: string
|
||||
timestamp: number
|
||||
value: number
|
||||
unit: string
|
||||
}
|
||||
|
||||
export const useEnergyStore = defineStore('energy', () => {
|
||||
// State
|
||||
const isConnected = ref(false)
|
||||
const latestMessage = ref<LegacyEnergyData | null>(null)
|
||||
const timeSeriesData = reactive<{
|
||||
labels: string[]
|
||||
datasets: { data: number[] }[]
|
||||
}>({
|
||||
labels: [],
|
||||
datasets: [{ data: [] }],
|
||||
})
|
||||
|
||||
const sensorsData = reactive<Map<string, any>>(new Map()) // Legacy support
|
||||
const roomsData = reactive<Map<string, RoomMetrics>>(new Map())
|
||||
const latestReadings = reactive<Map<string, SensorReading>>(new Map())
|
||||
|
||||
let socket: WebSocket | null = null
|
||||
const newDataBuffer: (LegacyEnergyData | SensorReading)[] = []
|
||||
|
||||
// Actions
|
||||
function connect(url: string) {
|
||||
if (isConnected.value) {
|
||||
console.log('Already connected.')
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`Connecting to WebSocket at ${url}`)
|
||||
socket = new WebSocket(url)
|
||||
|
||||
socket.onopen = () => {
|
||||
console.log('WebSocket connection established.')
|
||||
isConnected.value = true
|
||||
}
|
||||
|
||||
socket.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
newDataBuffer.push(data)
|
||||
} catch (error) {
|
||||
console.error('Error parsing incoming data:', error)
|
||||
}
|
||||
}
|
||||
|
||||
socket.onclose = () => {
|
||||
console.log('WebSocket connection closed.')
|
||||
isConnected.value = false
|
||||
socket = null
|
||||
}
|
||||
|
||||
socket.onerror = (error) => {
|
||||
console.error('WebSocket error:', error)
|
||||
isConnected.value = false
|
||||
socket = null
|
||||
}
|
||||
|
||||
// Process the buffer at intervals
|
||||
setInterval(() => {
|
||||
if (newDataBuffer.length > 0) {
|
||||
const data = newDataBuffer.shift() // Get the oldest data point
|
||||
if (data) {
|
||||
latestMessage.value = data
|
||||
|
||||
// Update sensor-specific data
|
||||
updateSensorData(data)
|
||||
|
||||
// Update time series for chart (aggregate all sensors)
|
||||
const newLabel = new Date(data.timestamp * 1000).toLocaleTimeString()
|
||||
timeSeriesData.labels.push(newLabel)
|
||||
timeSeriesData.datasets[0].data.push(data.value)
|
||||
|
||||
if (timeSeriesData.labels.length > MAX_DATA_POINTS) {
|
||||
timeSeriesData.labels.shift()
|
||||
timeSeriesData.datasets[0].data.shift()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 500) // Process every 500ms
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (socket) {
|
||||
socket.close()
|
||||
}
|
||||
}
|
||||
|
||||
function updateSensorData(data: EnergyData) {
|
||||
const existingSensor = sensorsData.get(data.sensorId)
|
||||
|
||||
if (existingSensor) {
|
||||
// Update existing sensor
|
||||
const newTotal = existingSensor.totalConsumption + data.value
|
||||
const dataPoints = Math.floor((data.timestamp - existingSensor.lastUpdated) / 60) + 1 // Rough estimate
|
||||
|
||||
sensorsData.set(data.sensorId, {
|
||||
...existingSensor,
|
||||
latestValue: data.value,
|
||||
totalConsumption: newTotal,
|
||||
averageConsumption: newTotal / dataPoints,
|
||||
lastUpdated: data.timestamp
|
||||
})
|
||||
} else {
|
||||
// Create new sensor entry
|
||||
sensorsData.set(data.sensorId, {
|
||||
sensorId: data.sensorId,
|
||||
latestValue: data.value,
|
||||
totalConsumption: data.value,
|
||||
averageConsumption: data.value,
|
||||
lastUpdated: data.timestamp,
|
||||
unit: data.unit
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return { isConnected, latestMessage, timeSeriesData, sensorsData, connect, disconnect }
|
||||
})
|
||||
Reference in New Issue
Block a user