From 4f9fcbe7e03a10b7f72bab9d021e4754ea1552a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Z=C3=ADpek?= Date: Tue, 4 Mar 2025 12:09:15 +0100 Subject: [PATCH 1/6] MQTT sensors implemented, refactoring needed --- client/src/api/sensors.ts | 21 ++- .../sensors/components/SensorFormModal.tsx | 58 +++++++- server/app/mqtt.go | 5 + server/app/server.go | 8 +- .../migrations/1741085898207_sensors_mqtt.sql | 4 + server/integrations/mqtt.go | 32 +++++ server/main.go | 3 + server/models/sensors.go | 12 +- server/routes/sensors.go | 10 +- server/services/mqtt_brokers_service.go | 136 +++++++++++++++++- server/services/sensors_service.go | 44 ++++-- 11 files changed, 305 insertions(+), 28 deletions(-) create mode 100644 server/app/mqtt.go create mode 100644 server/database/migrations/1741085898207_sensors_mqtt.sql diff --git a/client/src/api/sensors.ts b/client/src/api/sensors.ts index 7252e26..9f75bc9 100644 --- a/client/src/api/sensors.ts +++ b/client/src/api/sensors.ts @@ -5,18 +5,33 @@ export type SensorInfo = { name: string authKey: string lastContactAt?: number + type: 'rest' | 'mqtt' + mqttTopic?: string + mqttBrokerId?: number + mqttPath?: string +} + +export type SensorModifiableData = { + name: string + type: 'rest' | 'mqtt' + mqttTopic?: string + mqttBrokerId?: number + mqttPath?: string } export const getSensors = () => request('/api/sensors') -export const createSensor = (name: string) => +export const createSensor = (data: SensorModifiableData) => request('/api/sensors', { method: 'POST', headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ name }), + body: JSON.stringify(data), }) -export const updateSensor = ({ id, ...body }: { id: number; name: string }) => +export const updateSensor = ({ + id, + ...body +}: { id: number } & SensorModifiableData) => request(`/api/sensors/${id}`, { method: 'PUT', headers: { 'content-type': 'application/json' }, diff --git a/client/src/pages/sensors/components/SensorFormModal.tsx b/client/src/pages/sensors/components/SensorFormModal.tsx index e7b90f8..94648bc 100644 --- a/client/src/pages/sensors/components/SensorFormModal.tsx +++ b/client/src/pages/sensors/components/SensorFormModal.tsx @@ -1,7 +1,8 @@ +import { getMQTTBrokers } from '@/api/mqttBrokers' import { createSensor, SensorInfo, updateSensor } from '@/api/sensors' import { Modal } from '@/components/Modal' import { useForm } from '@/utils/hooks/useForm' -import { useMutation, useQueryClient } from 'react-query' +import { useMutation, useQuery, useQueryClient } from 'react-query' type Props = { open: boolean @@ -14,22 +15,36 @@ export const SensorFormModal = ({ open, onClose, sensor }: Props) => { const createMutation = useMutation(createSensor) const updateMutation = useMutation(updateSensor) - const { handleSubmit, register } = useForm({ + const brokers = useQuery(['/mqtt/brokers'], getMQTTBrokers) + + const { handleSubmit, register, watch } = useForm({ defaultValue: () => ({ name: sensor?.name ?? '', + type: sensor?.type ?? 'rest', + mqttBrokerId: sensor?.mqttBrokerId ?? null, + mqttPath: sensor?.mqttPath ?? null, + mqttTopic: sensor?.mqttTopic ?? null, }), onSubmit: async (v) => { if (isLoading) { return } + const data = { + name: v.name, + type: v.type, + mqttBrokerId: v.mqttBrokerId ? +v.mqttBrokerId : undefined, + mqttPath: v.mqttPath ?? undefined, + mqttTopic: v.mqttTopic ?? undefined, + } + if (sensor) { await updateMutation.mutateAsync({ id: sensor.id, - name: v.name, + ...data, }) } else { - await createMutation.mutateAsync(v.name) + await createMutation.mutateAsync(data) } queryClient.invalidateQueries(['/sensors']) @@ -38,6 +53,8 @@ export const SensorFormModal = ({ open, onClose, sensor }: Props) => { }, }) + const type = watch('type') + const isLoading = createMutation.isLoading || updateMutation.isLoading return ( @@ -54,6 +71,39 @@ export const SensorFormModal = ({ open, onClose, sensor }: Props) => { /> +
+ + +
+ + {type === 'mqtt' && ( + <> +
+ + +
+ +
+ + +
+ +
+ + +
+ + )} +