This commit is contained in:
rafaeldpsilva
2025-12-19 23:54:43 +00:00
parent a94e1b06b2
commit 37ccef2f12
5 changed files with 23 additions and 23 deletions

View File

@@ -37,15 +37,15 @@
<input <input
v-model.number="numericValue" v-model.number="numericValue"
type="range" type="range"
:min="action.parameters.min" :min="action.parameters?.min"
:max="action.parameters.max" :max="action.parameters?.max"
:step="action.parameters.step" :step="action.parameters?.step"
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer slider" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer slider"
/> />
<div class="flex justify-between text-sm text-gray-600"> <div class="flex justify-between text-sm text-gray-600">
<span>{{ action.parameters.min }}</span> <span>{{ action.parameters?.min }}</span>
<span class="font-medium">{{ numericValue }}{{ getUnit() }}</span> <span class="font-medium">{{ numericValue }}{{ getUnit() }}</span>
<span>{{ action.parameters.max }}</span> <span>{{ action.parameters?.max }}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -157,9 +157,9 @@ watch(
(action) => { (action) => {
if (action) { if (action) {
if (action.parameters?.min !== undefined) { if (action.parameters?.min !== undefined) {
numericValue.value = action.parameters.min numericValue.value = action.parameters?.min ?? 0
} }
if (action.parameters?.options?.length > 0) { if (action.parameters?.options && action.parameters.options.length > 0) {
selectedOption.value = action.parameters.options[0] selectedOption.value = action.parameters.options[0]
} }
toggleValue.value = false toggleValue.value = false

View File

@@ -379,14 +379,14 @@ class ApiClient {
return await response.json() return await response.json()
} }
async post<T>(endpoint: string, data?: Record<string, unknown> | unknown[]): Promise<T> { async post<T>(endpoint: string, data?: unknown): Promise<T> {
return this.request<T>(endpoint, { return this.request<T>(endpoint, {
method: 'POST', method: 'POST',
body: data ? JSON.stringify(data) : undefined, body: data ? JSON.stringify(data) : undefined,
}) })
} }
async put<T>(endpoint: string, data?: Record<string, unknown> | unknown[]): Promise<T> { async put<T>(endpoint: string, data?: unknown): Promise<T> {
return this.request<T>(endpoint, { return this.request<T>(endpoint, {
method: 'PUT', method: 'PUT',
body: data ? JSON.stringify(data) : undefined, body: data ? JSON.stringify(data) : undefined,

View File

@@ -5,15 +5,15 @@ import { useRoomStore } from './room'
const MAX_DATA_POINTS = 100 const MAX_DATA_POINTS = 100
interface SensorReading { interface WebSocketReading {
sensorId: string sensorId: string
room: string room: string
timestamp: number timestamp: number
energy: { energy?: {
value: number value: number
unit: string unit: string
} }
co2: { co2?: {
value: number value: number
unit: string unit: string
} }
@@ -25,7 +25,7 @@ interface SensorReading {
export const useWebSocketStore = defineStore('websocket', () => { export const useWebSocketStore = defineStore('websocket', () => {
const isConnected = ref<boolean>(false) const isConnected = ref<boolean>(false)
const latestMessage = ref<SensorReading | null>(null) const latestMessage = ref<WebSocketReading | null>(null)
const timeSeriesData = reactive<{ const timeSeriesData = reactive<{
labels: string[] labels: string[]
datasets: { data: number[] }[] datasets: { data: number[] }[]
@@ -35,7 +35,7 @@ export const useWebSocketStore = defineStore('websocket', () => {
}) })
let socket: WebSocket | null = null let socket: WebSocket | null = null
const newDataBuffer: SensorReading[] = [] const newDataBuffer: WebSocketReading[] = []
function connect(url: string): void { function connect(url: string): void {
if (isConnected.value && socket) { if (isConnected.value && socket) {
@@ -115,9 +115,9 @@ export const useWebSocketStore = defineStore('websocket', () => {
} }
} }
function processIncomingData(data: SensorReading): void { function processIncomingData(data: WebSocketReading): 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 as any).type === 'connection_established' || (data as any).type === 'proxy_info') {
return return
} }
@@ -125,21 +125,21 @@ export const useWebSocketStore = defineStore('websocket', () => {
const roomStore = useRoomStore() const roomStore = useRoomStore()
// Update individual sensor readings first // Update individual sensor readings first
sensorStore.updateLatestReading(data) sensorStore.updateLatestReading(data as any)
// Update room data if we have room information (accepts partial readings) // Update room data if we have room information (accepts partial readings)
if (data.room) { if (data.room) {
if (data.energy) { if (data.energy) {
sensorStore.updateEnergySensors(data) sensorStore.updateEnergySensors(data as any)
} }
roomStore.updateRoomData(data) roomStore.updateRoomData(data as any)
} }
// Update time series for chart if energy data is available // Update time series for chart if energy data is available
if (data.energy) { if (data.energy) {
const newLabel = new Date(data.timestamp * 1000).toLocaleTimeString() const newLabel = new Date(data.timestamp * 1000).toLocaleTimeString()
timeSeriesData.labels.push(newLabel) timeSeriesData.labels.push(newLabel)
timeSeriesData.datasets[0].data.push(data.energy?.value) timeSeriesData.datasets[0].data.push(data.energy.value)
} }
} }

View File

@@ -222,11 +222,11 @@
<div v-else class="space-y-3"> <div v-else class="space-y-3">
<div <div
v-for="room in apiRooms" v-for="room in apiRooms"
:key="room.name || room.room" :key="room.room"
class="p-3 bg-gray-50 rounded-lg" class="p-3 bg-gray-50 rounded-lg"
> >
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<p class="font-medium text-gray-900">{{ room.name || room.room }}</p> <p class="font-medium text-gray-900">{{ room.room }}</p>
<span class="text-sm text-gray-500">{{ room.sensor_count }} sensors</span> <span class="text-sm text-gray-500">{{ room.sensor_count }} sensors</span>
</div> </div>
<div class="text-xs text-gray-600 space-y-1"> <div class="text-xs text-gray-600 space-y-1">

View File

@@ -184,7 +184,7 @@
<!-- Action Modal --> <!-- Action Modal -->
<ActionModal <ActionModal
v-if="showActionModal" v-if="showActionModal && selectedSensor && selectedAction"
:sensor="selectedSensor" :sensor="selectedSensor"
:action="selectedAction" :action="selectedAction"
@execute="handleActionExecute" @execute="handleActionExecute"