Added command responses success/failure to web UI

This commit is contained in:
Jono Targett 2026-03-17 22:12:53 +10:30
parent a3c9d053aa
commit 58de012af6
4 changed files with 60 additions and 5 deletions

View File

@ -11,6 +11,8 @@ import CommandsWidget from "./components/dashboard/CommandsWidget.vue";
</script>
<template>
<Toast position="bottom-right" />
<div class="layout-container">
<AppTopbar />
<div class="layout-grid">

View File

@ -6,10 +6,15 @@ import Accordion from 'primevue/accordion';
import AccordionPanel from 'primevue/accordionpanel';
import AccordionHeader from 'primevue/accordionheader';
import AccordionContent from 'primevue/accordioncontent';
import Dialog from 'primevue/dialog'
import { JsonForms } from "@jsonforms/vue";
import { primeVueRenderers } from 'jsonforms-primevue'
import { useToast } from 'primevue/usetoast'
const toast = useToast()
const renderers = Object.freeze([
...primeVueRenderers,
// here you can add custom renderers
@ -24,6 +29,7 @@ const mqtt2 = new MQTTService()
const filters = ref({})
const commands = ref([])
const commandMap = reactive({})
const commandByResponseId = reactive({})
function rebuildList() {
commands.value = Object.values(commandMap)
@ -35,7 +41,8 @@ function updateCommand(device, name, field, value) {
name,
description: "No description provided.",
schema: {},
input: {}
input: {},
response: null
}
}
@ -44,12 +51,27 @@ function updateCommand(device, name, field, value) {
}
function sendCommand(cmd) {
cmd.responseId = null
cmd.response = {}
const topic = `device/${props.deviceId}/command/${cmd.name}`
var payload = JSON.stringify(cmd.input, null, 2)
mqtt2.publish(topic, payload || '{}')
var responseId = generateId()
commandByResponseId[responseId] = cmd
mqtt2.publish(topic, payload || '{}', {
qos: 1,
properties: {
responseTopic: `client/${mqtt2.clientId}/responses`,
correlationData: new TextEncoder().encode(responseId)
}
})
}
import Dialog from 'primevue/dialog'
function generateId() {
return Math.random().toString(16).substr(2, 8)
}
const schemaDialog = reactive({
visible: false,
@ -86,6 +108,26 @@ onMounted(() => {
}
})
mqtt2.subscribe(`client/${mqtt2.clientId}/responses`, (payload, topic) => {
let response = JSON.parse(payload)
const responseId = response.correlation
const cmd = commandByResponseId[responseId]
if (cmd) {
cmd.response = response
toast.add({
severity: response.success ? 'success' : 'error',
summary: cmd.name,
detail: response.message !== 'None' ? response.message : (response.success ? 'Success' : 'Failed'),
life: 4000
})
delete commandByResponseId[responseId]
}
})
})
const jsonFormsConfig = {
@ -146,6 +188,13 @@ const jsonFormsConfig = {
<!-- Right: Buttons -->
<div class="button-container">
<Button
v-if="cmd.response"
:icon="cmd.response.success ? 'pi pi-check' : 'pi pi-times'"
class="p-button-rounded p-button-text"
:class="cmd.response.success ? 'p-button-success' : 'p-button-danger'"
v-tooltip="cmd.response.message !== 'None' ? cmd.response.message : null"
/>
<Button
icon="pi pi-question-circle"
class="p-mb-2"

View File

@ -5,6 +5,8 @@ import PrimeVue from "primevue/config";
import App from "./App.vue";
import Aura from "@primeuix/themes/aura";
import ToastService from 'primevue/toastservice'
const app = createApp(App);
app.use(PrimeVue, {
@ -16,4 +18,6 @@ app.use(PrimeVue, {
},
});
app.use(ToastService)
app.mount("#app");

View File

@ -3,7 +3,7 @@ import mqtt from 'mqtt'
export default class MQTTService {
constructor(brokerUrl = 'ws://127.0.0.1:8083/mqtt', clientId = null) {
this.clientId = clientId || 'vue-client-' + Math.random().toString(16).substr(2, 8)
this.client = mqtt.connect(brokerUrl, { clientId: this.clientId })
this.client = mqtt.connect(brokerUrl, { clientId: this.clientId, protocolVersion: 5})
this.subscriptions = [] // array of {topic, callback}
this.client.on('connect', () => console.log('Connected to MQTT broker'))