Refactor to decouple energy, room, and sensor stores
- Remove room and sensor logic from energy store - Update components to use useRoomStore and useSensorStore directly - Fix sensor/room ID mismatches and API response handling in room store - Update AIOptimizationView to use useWebSocketStore for connection status - Update SensorManagementView to use useRoomStore and useSensorStore directly
This commit is contained in:
@@ -70,12 +70,12 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useEnergyStore } from '@/stores/energy'
|
import { useRoomStore } from '@/stores/room'
|
||||||
|
|
||||||
const energyStore = useEnergyStore()
|
const roomStore = useRoomStore()
|
||||||
|
|
||||||
const roomsList = computed(() => {
|
const roomsList = computed(() => {
|
||||||
return Array.from(energyStore.roomsData.values()).sort((a, b) =>
|
return Array.from(roomStore.roomsData.values()).sort((a, b) =>
|
||||||
b.co2.current - a.co2.current // Sort by CO2 level descending
|
b.co2.current - a.co2.current // Sort by CO2 level descending
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -86,7 +86,7 @@ const overallCO2 = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const overallStatus = computed(() => {
|
const overallStatus = computed(() => {
|
||||||
return energyStore.getCO2Status(overallCO2.value)
|
return roomStore.getCO2Status(overallCO2.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
const roomsWithGoodAir = computed(() => {
|
const roomsWithGoodAir = computed(() => {
|
||||||
|
|||||||
@@ -165,7 +165,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useEnergyStore } from '@/stores/energy'
|
|
||||||
import { useSensorStore } from '@/stores/sensor'
|
import { useSensorStore } from '@/stores/sensor'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -179,28 +178,25 @@ const emit = defineEmits<{
|
|||||||
executeAction: [sensor: any, action: any]
|
executeAction: [sensor: any, action: any]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const energyStore = useEnergyStore()
|
|
||||||
const sensorStore = useSensorStore()
|
const sensorStore = useSensorStore()
|
||||||
|
|
||||||
const getSensorValues = (sensor: any) => {
|
const getSensorValues = (sensor: any) => {
|
||||||
const values = []
|
const values = []
|
||||||
|
|
||||||
// Get real-time sensor reading from store
|
// Get real-time sensor reading from store
|
||||||
const latestReading = energyStore.latestReadings.get(sensor.id)
|
const latestReading = sensorStore.latestReadings.get(sensor.id) || sensorStore.latestReadings.get(sensor.sensor_id)
|
||||||
console.log(`[Detailed] Getting values for sensor ${sensor.id}, found reading:`, latestReading)
|
console.log(`[Detailed] Getting values for sensor ${sensor.id}, found reading:`, latestReading)
|
||||||
console.log('[Detailed] Available readings:', Array.from(energyStore.latestReadings.keys()))
|
console.log('[Detailed] Available readings:', Array.from(sensorStore.latestReadings.keys()))
|
||||||
console.log(`[Detailed] Sensor capabilities:`, sensor.capabilities?.monitoring)
|
console.log(`[Detailed] Sensor capabilities:`, sensor.capabilities?.monitoring)
|
||||||
|
|
||||||
// Only show energy if the sensor actually monitors energy
|
// Only show energy if the sensor actually monitors energy
|
||||||
if (sensor.capabilities?.monitoring?.includes('energy')) {
|
if (sensor.capabilities?.monitoring?.includes('energy')) {
|
||||||
const energyValue = latestReading?.energy?.value?.toFixed(2) ||
|
const energyValue = latestReading?.energy?.value?.toFixed(2) || '0.00'
|
||||||
energyStore.latestMessage?.value?.toFixed(2) ||
|
|
||||||
'0.00'
|
|
||||||
values.push({
|
values.push({
|
||||||
type: 'energy',
|
type: 'energy',
|
||||||
label: 'Energy Consumption',
|
label: 'Energy Consumption',
|
||||||
value: energyValue,
|
value: energyValue,
|
||||||
unit: latestReading?.energy?.unit || energyStore.latestMessage?.unit || 'kWh'
|
unit: latestReading?.energy?.unit || 'kWh'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,12 +72,12 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useEnergyStore } from '@/stores/energy'
|
import { useRoomStore } from '@/stores/room'
|
||||||
|
|
||||||
const energyStore = useEnergyStore()
|
const roomStore = useRoomStore()
|
||||||
|
|
||||||
const roomsList = computed(() => {
|
const roomsList = computed(() => {
|
||||||
return Array.from(energyStore.roomsData.values()).sort((a, b) =>
|
return Array.from(roomStore.roomsData.values()).sort((a, b) =>
|
||||||
a.room.localeCompare(b.room)
|
a.room.localeCompare(b.room)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -173,9 +173,9 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useEnergyStore } from '@/stores/energy'
|
import { useRoomStore } from '@/stores/room'
|
||||||
|
|
||||||
const energyStore = useEnergyStore()
|
const roomStore = useRoomStore()
|
||||||
|
|
||||||
// Emit events
|
// Emit events
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -191,7 +191,7 @@ const roomToDelete = ref<string | null>(null)
|
|||||||
|
|
||||||
// Computed properties
|
// Computed properties
|
||||||
const roomsWithStats = computed(() => {
|
const roomsWithStats = computed(() => {
|
||||||
return energyStore.getAllRoomsWithStats()
|
return roomStore.getAllRoomsWithStats()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
@@ -215,7 +215,7 @@ const addNewRoom = async () => {
|
|||||||
errorMessage.value = ''
|
errorMessage.value = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const success = energyStore.addRoom(newRoomName.value.trim())
|
const success = roomStore.addRoom(newRoomName.value.trim())
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
newRoomName.value = ''
|
newRoomName.value = ''
|
||||||
@@ -242,7 +242,7 @@ const deleteRoom = async () => {
|
|||||||
isDeleting.value = roomToDelete.value
|
isDeleting.value = roomToDelete.value
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const success = energyStore.removeRoom(roomToDelete.value)
|
const success = roomStore.removeRoom(roomToDelete.value)
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
console.log(`Room "${roomToDelete.value}" deleted successfully`)
|
console.log(`Room "${roomToDelete.value}" deleted successfully`)
|
||||||
@@ -258,7 +258,7 @@ const deleteRoom = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getRoomStats = (roomName: string) => {
|
const getRoomStats = (roomName: string) => {
|
||||||
return energyStore.getRoomStats(roomName)
|
return roomStore.getRoomStats(roomName)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCO2Color = (co2Level: number) => {
|
const getCO2Color = (co2Level: number) => {
|
||||||
|
|||||||
@@ -1,16 +1,52 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
|
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'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Energy Store - Simplified to only track energy consumption metrics
|
||||||
|
* For sensor data: use useSensorStore()
|
||||||
|
* For room data: use useRoomStore()
|
||||||
|
* For WebSocket: use useWebSocketStore()
|
||||||
|
* For analytics: use useAnalyticsStore()
|
||||||
|
*/
|
||||||
export const useEnergyStore = defineStore('energy', () => {
|
export const useEnergyStore = defineStore('energy', () => {
|
||||||
// Get instances of other stores
|
// Get instances of other stores
|
||||||
|
const websocketStore = useWebSocketStore()
|
||||||
const sensorStore = useSensorStore()
|
const sensorStore = useSensorStore()
|
||||||
const roomStore = useRoomStore()
|
const roomStore = useRoomStore()
|
||||||
const analyticsStore = useAnalyticsStore()
|
const analyticsStore = useAnalyticsStore()
|
||||||
|
|
||||||
// Initialize data from APIs
|
// Energy-specific state
|
||||||
|
const currentConsumption = ref(0) // Current energy consumption in kWh
|
||||||
|
const averageConsumption = ref(0) // Average energy consumption in kWh
|
||||||
|
|
||||||
|
// Computed: Current energy value from WebSocket
|
||||||
|
const currentEnergyValue = computed(() => {
|
||||||
|
return websocketStore.latestMessage?.energy?.value || 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// Computed: Average energy usage from time series
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update current consumption (called from components or watchers)
|
||||||
|
function updateCurrentConsumption(value: number) {
|
||||||
|
currentConsumption.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update average consumption (called from components or watchers)
|
||||||
|
function updateAverageConsumption(value: number) {
|
||||||
|
averageConsumption.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize data from APIs (convenience function for AnalyticsView)
|
||||||
async function initializeFromApi() {
|
async function initializeFromApi() {
|
||||||
await Promise.allSettled([
|
await Promise.allSettled([
|
||||||
roomStore.loadRoomsFromAPI(),
|
roomStore.loadRoomsFromAPI(),
|
||||||
@@ -21,59 +57,30 @@ export const useEnergyStore = defineStore('energy', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Sensor state (delegated)
|
// Energy-specific state
|
||||||
sensorsData: computed(() => sensorStore.sensorsData),
|
currentConsumption,
|
||||||
sensorDevices: computed(() => sensorStore.sensorDevices),
|
averageConsumption,
|
||||||
apiSensors: computed(() => Array.from(sensorStore.sensorDevices.values())), // Convert Map to Array
|
currentEnergyValue,
|
||||||
|
averageEnergyUsage,
|
||||||
|
|
||||||
// Room state (delegated)
|
// Energy-specific actions
|
||||||
roomsData: computed(() => roomStore.roomsData),
|
updateCurrentConsumption,
|
||||||
availableRooms: computed(() => roomStore.availableRooms),
|
updateAverageConsumption,
|
||||||
roomsLoading: computed(() => roomStore.roomsLoading),
|
|
||||||
roomsLoaded: computed(() => roomStore.roomsLoaded),
|
// Legacy delegation for AnalyticsView (keep for now to avoid breaking)
|
||||||
|
apiSensors: computed(() => Array.from(sensorStore.sensorDevices.values())),
|
||||||
apiRooms: computed(() => roomStore.apiRooms),
|
apiRooms: computed(() => roomStore.apiRooms),
|
||||||
|
|
||||||
// Analytics state (delegated)
|
|
||||||
analyticsData: computed(() => analyticsStore.analyticsData),
|
analyticsData: computed(() => analyticsStore.analyticsData),
|
||||||
systemStatus: computed(() => analyticsStore.systemStatus),
|
|
||||||
healthStatus: computed(() => analyticsStore.healthStatus),
|
healthStatus: computed(() => analyticsStore.healthStatus),
|
||||||
|
|
||||||
// Combined API loading/error state
|
|
||||||
apiLoading: computed(
|
apiLoading: computed(
|
||||||
() => sensorStore.apiLoading || roomStore.apiLoading || analyticsStore.apiLoading,
|
() => sensorStore.apiLoading || roomStore.apiLoading || analyticsStore.apiLoading,
|
||||||
),
|
),
|
||||||
apiError: computed(() => sensorStore.apiError || roomStore.apiError || analyticsStore.apiError),
|
apiError: computed(() => sensorStore.apiError || roomStore.apiError || analyticsStore.apiError),
|
||||||
|
|
||||||
// Sensor functions (delegated)
|
// Legacy API functions for AnalyticsView
|
||||||
updateSensorRoom: sensorStore.updateSensorRoom,
|
|
||||||
executeSensorAction: sensorStore.executeSensorAction,
|
|
||||||
getSensorsByRoom: sensorStore.getSensorsByRoom,
|
|
||||||
getSensorsByType: sensorStore.getSensorsByType,
|
|
||||||
fetchApiSensors: sensorStore.fetchApiSensors,
|
fetchApiSensors: sensorStore.fetchApiSensors,
|
||||||
fetchApiSensorData: sensorStore.fetchApiSensorData,
|
|
||||||
updateApiSensorMetadata: sensorStore.updateApiSensorMetadata,
|
|
||||||
deleteApiSensor: sensorStore.deleteApiSensor,
|
|
||||||
exportApiData: sensorStore.exportApiData,
|
|
||||||
|
|
||||||
// Room functions (delegated)
|
|
||||||
getCO2Status: roomStore.getCO2Status,
|
|
||||||
loadRoomsFromAPI: roomStore.loadRoomsFromAPI,
|
|
||||||
addRoom: roomStore.addRoom,
|
|
||||||
removeRoom: roomStore.removeRoom,
|
|
||||||
getRoomStats: roomStore.getRoomStats,
|
|
||||||
getAllRoomsWithStats: roomStore.getAllRoomsWithStats,
|
|
||||||
fetchApiRooms: roomStore.fetchApiRooms,
|
fetchApiRooms: roomStore.fetchApiRooms,
|
||||||
fetchApiRoomData: roomStore.fetchApiRoomData,
|
|
||||||
|
|
||||||
// Analytics functions (delegated)
|
|
||||||
fetchAnalyticsSummary: analyticsStore.fetchAnalyticsSummary,
|
fetchAnalyticsSummary: analyticsStore.fetchAnalyticsSummary,
|
||||||
fetchEnergyTrends: analyticsStore.fetchEnergyTrends,
|
|
||||||
fetchRoomComparison: analyticsStore.fetchRoomComparison,
|
|
||||||
fetchSystemEvents: analyticsStore.fetchSystemEvents,
|
|
||||||
fetchSystemStatus: analyticsStore.fetchSystemStatus,
|
|
||||||
fetchHealthStatus: analyticsStore.fetchHealthStatus,
|
|
||||||
|
|
||||||
// Initialize function
|
|
||||||
initializeFromApi,
|
initializeFromApi,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { roomsApi, type RoomInfo as ApiRoomInfo } from '@/services'
|
import { roomsApi, type RoomInfo as ApiRoomInfo, type SensorReading } from '@/services'
|
||||||
import { useSensorStore } from './sensor'
|
import { useSensorStore } from './sensor'
|
||||||
|
|
||||||
interface RoomMetrics {
|
interface RoomMetrics {
|
||||||
@@ -23,24 +23,6 @@ interface RoomMetrics {
|
|||||||
lastUpdated: number
|
lastUpdated: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SensorReading {
|
|
||||||
sensorId: string
|
|
||||||
room: string
|
|
||||||
timestamp: number
|
|
||||||
energy: {
|
|
||||||
value: number
|
|
||||||
unit: string
|
|
||||||
}
|
|
||||||
co2: {
|
|
||||||
value: number
|
|
||||||
unit: string
|
|
||||||
}
|
|
||||||
temperature?: {
|
|
||||||
value: number
|
|
||||||
unit: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useRoomStore = defineStore('room', () => {
|
export const useRoomStore = defineStore('room', () => {
|
||||||
// State
|
// State
|
||||||
const roomsData = reactive<Map<string, RoomMetrics>>(new Map())
|
const roomsData = reactive<Map<string, RoomMetrics>>(new Map())
|
||||||
@@ -70,7 +52,7 @@ export const useRoomStore = defineStore('room', () => {
|
|||||||
if (!roomMetrics) {
|
if (!roomMetrics) {
|
||||||
roomMetrics = {
|
roomMetrics = {
|
||||||
room: data.room,
|
room: data.room,
|
||||||
sensors: [data.sensorId],
|
sensors: [data.sensor_id],
|
||||||
energy: { current: 0, total: 0, average: 0, unit: data.energy?.unit || 'kWh' },
|
energy: { current: 0, total: 0, average: 0, unit: data.energy?.unit || 'kWh' },
|
||||||
co2: { current: 0, average: 0, max: 0, status: 'good', unit: data.co2?.unit || 'ppm' },
|
co2: { current: 0, average: 0, max: 0, status: 'good', unit: data.co2?.unit || 'ppm' },
|
||||||
occupancyEstimate: 'low',
|
occupancyEstimate: 'low',
|
||||||
@@ -80,8 +62,8 @@ export const useRoomStore = defineStore('room', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update room sensors list
|
// Update room sensors list
|
||||||
if (!roomMetrics.sensors.includes(data.sensorId)) {
|
if (!roomMetrics.sensors.includes(data.sensor_id)) {
|
||||||
roomMetrics.sensors.push(data.sensorId)
|
roomMetrics.sensors.push(data.sensor_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recalculate room metrics from all sensors in the room
|
// Recalculate room metrics from all sensors in the room
|
||||||
@@ -173,7 +155,7 @@ export const useRoomStore = defineStore('room', () => {
|
|||||||
// Reassign sensors to empty room
|
// Reassign sensors to empty room
|
||||||
sensorsInRoom.forEach((sensor) => {
|
sensorsInRoom.forEach((sensor) => {
|
||||||
sensor.room = ''
|
sensor.room = ''
|
||||||
sensorStore.sensorDevices.set(sensor.id, { ...sensor })
|
sensorStore.sensorDevices.set(sensor.sensor_id, { ...sensor })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,9 +240,12 @@ export const useRoomStore = defineStore('room', () => {
|
|||||||
async function fetchApiRooms() {
|
async function fetchApiRooms() {
|
||||||
const result = await handleApiCall(() => roomsApi.getRooms())
|
const result = await handleApiCall(() => roomsApi.getRooms())
|
||||||
if (result) {
|
if (result) {
|
||||||
apiRooms.value = result
|
// Handle both response formats: {rooms: [...]} or direct array [...]
|
||||||
|
const roomsArray = Array.isArray(result) ? result : result.rooms || []
|
||||||
|
apiRooms.value = roomsArray
|
||||||
|
|
||||||
// Update available rooms from API data
|
// Update available rooms from API data
|
||||||
const roomNames = result.map((room) => room.room).filter((name) => name)
|
const roomNames = roomsArray.map((room) => room.name || room.room).filter((name) => name)
|
||||||
if (roomNames.length > 0) {
|
if (roomNames.length > 0) {
|
||||||
availableRooms.value = [...new Set([...availableRooms.value, ...roomNames])].sort()
|
availableRooms.value = [...new Set([...availableRooms.value, ...roomNames])].sort()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
<div class="flex items-center gap-2 text-sm text-gray-600">
|
<div class="flex items-center gap-2 text-sm text-gray-600">
|
||||||
<div
|
<div
|
||||||
class="w-3 h-3 rounded-full"
|
class="w-3 h-3 rounded-full"
|
||||||
:class="energyStore.isConnected ? 'bg-green-500' : 'bg-red-500'"
|
:class="websocketStore.isConnected ? 'bg-green-500' : 'bg-red-500'"
|
||||||
></div>
|
></div>
|
||||||
<span>{{ energyStore.isConnected ? 'Connected' : 'Disconnected' }}</span>
|
<span>{{ websocketStore.isConnected ? 'Connected' : 'Disconnected' }}</span>
|
||||||
<span class="mx-2">•</span>
|
<span class="mx-2">•</span>
|
||||||
<span>{{ activeOptimizations.length }} active optimizations</span>
|
<span>{{ activeOptimizations.length }} active optimizations</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -598,10 +598,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useEnergyStore } from '@/stores/energy'
|
import { useWebSocketStore } from '@/stores/websocket'
|
||||||
|
|
||||||
const energyStore = useEnergyStore()
|
const websocketStore = useWebSocketStore()
|
||||||
|
|
||||||
// Modal states
|
// Modal states
|
||||||
const showNewOptimizationModal = ref(false)
|
const showNewOptimizationModal = ref(false)
|
||||||
@@ -725,11 +725,4 @@ const pauseOptimization = (id: number) => {
|
|||||||
// In a real app, this would make an API call
|
// In a real app, this would make an API call
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize connection
|
|
||||||
onMounted(() => {
|
|
||||||
if (!energyStore.isConnected) {
|
|
||||||
energyStore.connect('ws://localhost:8000/ws')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
class="px-4 py-2 border border-gray-200 rounded-lg bg-white flex-1"
|
class="px-4 py-2 border border-gray-200 rounded-lg bg-white flex-1"
|
||||||
>
|
>
|
||||||
<option value="">All Rooms</option>
|
<option value="">All Rooms</option>
|
||||||
<option v-for="room in energyStore.availableRooms" :key="room" :value="room">
|
<option v-for="room in roomStore.availableRooms" :key="room" :value="room">
|
||||||
{{ room }}
|
{{ room }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
v-for="sensor in filteredSensors"
|
v-for="sensor in filteredSensors"
|
||||||
:key="sensor.sensor_id"
|
:key="sensor.sensor_id"
|
||||||
:sensor="sensor"
|
:sensor="sensor"
|
||||||
:available-rooms="energyStore.availableRooms"
|
:available-rooms="roomStore.availableRooms"
|
||||||
:is-executing-action="isExecutingAction"
|
:is-executing-action="isExecutingAction"
|
||||||
@update-room="updateRoom"
|
@update-room="updateRoom"
|
||||||
@execute-action="executeAction"
|
@execute-action="executeAction"
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Loading State -->
|
<!-- Loading State -->
|
||||||
<div v-if="energyStore.apiLoading" class="text-center py-12">
|
<div v-if="sensorStore.apiLoading" class="text-center py-12">
|
||||||
<div
|
<div
|
||||||
class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"
|
class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"
|
||||||
></div>
|
></div>
|
||||||
@@ -163,10 +163,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Error State -->
|
<!-- Error State -->
|
||||||
<div v-else-if="energyStore.apiError" class="text-center py-12">
|
<div v-else-if="sensorStore.apiError" class="text-center py-12">
|
||||||
<div class="text-red-400 text-6xl mb-4">⚠️</div>
|
<div class="text-red-400 text-6xl mb-4">⚠️</div>
|
||||||
<h3 class="text-lg font-medium text-gray-900 mb-2">Error loading sensors</h3>
|
<h3 class="text-lg font-medium text-gray-900 mb-2">Error loading sensors</h3>
|
||||||
<p class="text-gray-600 mb-4">{{ energyStore.apiError }}</p>
|
<p class="text-gray-600 mb-4">{{ sensorStore.apiError }}</p>
|
||||||
<button
|
<button
|
||||||
@click="reloadSensors"
|
@click="reloadSensors"
|
||||||
class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||||
import { useSensorStore } from '@/stores/sensor'
|
import { useSensorStore } from '@/stores/sensor'
|
||||||
import { useEnergyStore } from '@/stores/energy'
|
import { useRoomStore } from '@/stores/room'
|
||||||
import { useWebSocketStore } from '@/stores/websocket'
|
import { useWebSocketStore } from '@/stores/websocket'
|
||||||
import ActionModal from '@/components/modals/ActionModal.vue'
|
import ActionModal from '@/components/modals/ActionModal.vue'
|
||||||
import RoomManagementModal from '@/components/modals/RoomManagementModal.vue'
|
import RoomManagementModal from '@/components/modals/RoomManagementModal.vue'
|
||||||
@@ -207,7 +207,7 @@ import SimpleSensorCard from '@/components/cards/SimpleSensorCard.vue'
|
|||||||
import DetailedSensorCard from '@/components/cards/DetailedSensorCard.vue'
|
import DetailedSensorCard from '@/components/cards/DetailedSensorCard.vue'
|
||||||
|
|
||||||
const sensorStore = useSensorStore()
|
const sensorStore = useSensorStore()
|
||||||
const energyStore = useEnergyStore()
|
const roomStore = useRoomStore()
|
||||||
const websocketStore = useWebSocketStore()
|
const websocketStore = useWebSocketStore()
|
||||||
|
|
||||||
const viewMode = ref<'simple' | 'detailed'>('simple')
|
const viewMode = ref<'simple' | 'detailed'>('simple')
|
||||||
@@ -238,7 +238,7 @@ const filteredSensors = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const updateRoom = (sensorId: string, newRoom: string) => {
|
const updateRoom = (sensorId: string, newRoom: string) => {
|
||||||
energyStore.updateSensorRoom(sensorId, newRoom)
|
sensorStore.updateSensorRoom(sensorId, newRoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
const executeAction = (sensor: any, action: any) => {
|
const executeAction = (sensor: any, action: any) => {
|
||||||
@@ -254,7 +254,7 @@ const executeAction = (sensor: any, action: any) => {
|
|||||||
const handleActionExecute = async (sensorId: string, actionId: string, parameters: any) => {
|
const handleActionExecute = async (sensorId: string, actionId: string, parameters: any) => {
|
||||||
isExecutingAction.value = true
|
isExecutingAction.value = true
|
||||||
try {
|
try {
|
||||||
await energyStore.executeSensorAction(sensorId, actionId, parameters)
|
await sensorStore.executeSensorAction(sensorId, actionId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Action execution failed:', error)
|
console.error('Action execution failed:', error)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -274,11 +274,12 @@ const showSensorDetails = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const reloadSensors = async () => {
|
const reloadSensors = async () => {
|
||||||
await energyStore.fetchApiSensors()
|
await sensorStore.fetchApiSensors()
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await sensorStore.fetchApiSensors()
|
await sensorStore.fetchApiSensors()
|
||||||
|
await roomStore.fetchApiRooms()
|
||||||
|
|
||||||
if (!websocketStore.isConnected) {
|
if (!websocketStore.isConnected) {
|
||||||
websocketStore.connect('ws://localhost:8007/ws')
|
websocketStore.connect('ws://localhost:8007/ws')
|
||||||
@@ -286,6 +287,6 @@ onMounted(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
// energyStore.disconnect()
|
// WebSocket managed globally, no cleanup needed here
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user