state of the mqtt
This commit is contained in:
11
src/App.vue
11
src/App.vue
@@ -178,16 +178,19 @@ onMounted(() => {
|
|||||||
// Example: Sync with OS theme only if no theme saved (requires store modification)
|
// Example: Sync with OS theme only if no theme saved (requires store modification)
|
||||||
// syncWithOsThemeIfNeeded();
|
// syncWithOsThemeIfNeeded();
|
||||||
|
|
||||||
// *** Auto-connect MQTT if URL is stored and not already connected/connecting ***
|
// Auto-connect MQTT only if URL is stored AND user desires connection
|
||||||
const storedBrokerUrl = store.getters.mqttBrokerUrl;
|
const storedBrokerUrl = store.getters.mqttBrokerUrl;
|
||||||
|
const connectDesired = store.getters.mqttConnectDesired; // Get the flag
|
||||||
|
|
||||||
if (storedBrokerUrl &&
|
if (storedBrokerUrl &&
|
||||||
|
connectDesired && // Check the flag
|
||||||
MqttService.connectionStatus.value !== 'connected' &&
|
MqttService.connectionStatus.value !== 'connected' &&
|
||||||
MqttService.connectionStatus.value !== 'connecting') {
|
MqttService.connectionStatus.value !== 'connecting') {
|
||||||
console.log("App.vue: Auto-connecting to stored MQTT broker:", storedBrokerUrl);
|
console.log("App.vue: Auto-connecting to stored MQTT broker (user desired):", storedBrokerUrl);
|
||||||
MqttService.connect(storedBrokerUrl);
|
MqttService.connect(storedBrokerUrl);
|
||||||
|
} else if (storedBrokerUrl && !connectDesired) {
|
||||||
|
console.log("App.vue: MQTT Broker URL is stored, but user previously disconnected. Not auto-connecting.");
|
||||||
}
|
}
|
||||||
// *** End Auto-connect MQTT ***
|
|
||||||
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error("App.vue: Error during store.dispatch('loadState'):", error);
|
console.error("App.vue: Error during store.dispatch('loadState'):", error);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -114,15 +114,33 @@ const connect = async (brokerUrl = 'ws://localhost:9001') => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const disconnect = () => { /* ... existing disconnect logic ... */
|
const disconnect = () => {
|
||||||
if (client.value && typeof client.value.end === 'function') {
|
if (client.value) {
|
||||||
console.log('MQTT: Disconnecting...');
|
console.log('MQTT: Disconnecting/Stopping connection attempt...');
|
||||||
|
// Set status immediately to give user feedback, 'close' event will confirm
|
||||||
|
// but if it was 'connecting', it might not emit 'close' if it never truly connected.
|
||||||
|
const wasConnecting = connectionStatus.value === 'connecting';
|
||||||
|
|
||||||
|
client.value.end(true, () => { // true forces close and stops reconnect attempts
|
||||||
|
console.log('MQTT: client.end() callback executed.');
|
||||||
|
// The 'close' event listener on the client should handle final cleanup
|
||||||
|
// like setting client.value = null and connectionStatus.value = 'disconnected'.
|
||||||
|
// If it was just 'connecting' and never connected, 'close' might not fire reliably.
|
||||||
|
if (wasConnecting && connectionStatus.value !== 'disconnected') {
|
||||||
connectionStatus.value = 'disconnected';
|
connectionStatus.value = 'disconnected';
|
||||||
client.value.end(true, () => {
|
client.value = null; // Ensure cleanup if 'close' doesn't fire from 'connecting' state
|
||||||
console.log('MQTT: Disconnected callback triggered.');
|
}
|
||||||
});
|
});
|
||||||
} else {
|
// If it was 'connecting', we might want to immediately reflect disconnected state
|
||||||
|
// as 'end(true)' stops further attempts.
|
||||||
|
if (wasConnecting) {
|
||||||
connectionStatus.value = 'disconnected';
|
connectionStatus.value = 'disconnected';
|
||||||
|
// Note: client.value will be fully nulled on the 'close' event or after end() callback.
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log('MQTT: No active client to disconnect.');
|
||||||
|
connectionStatus.value = 'disconnected'; // Ensure status is correct
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const initialState = {
|
|||||||
globalMqttStopPause: null, // New
|
globalMqttStopPause: null, // New
|
||||||
globalMqttRunAll: null, // New
|
globalMqttRunAll: null, // New
|
||||||
mqttBrokerUrl: 'ws://localhost:9001', // Default, user can change
|
mqttBrokerUrl: 'ws://localhost:9001', // Default, user can change
|
||||||
|
mqttConnectDesired: false,
|
||||||
currentPlayerIndex: 0,
|
currentPlayerIndex: 0,
|
||||||
gameMode: 'normal',
|
gameMode: 'normal',
|
||||||
isMuted: false,
|
isMuted: false,
|
||||||
@@ -80,6 +81,7 @@ export default createStore({
|
|||||||
globalMqttStopPause: persistedState.globalMqttStopPause || initialState.globalMqttStopPause,
|
globalMqttStopPause: persistedState.globalMqttStopPause || initialState.globalMqttStopPause,
|
||||||
globalMqttRunAll: persistedState.globalMqttRunAll || initialState.globalMqttRunAll,
|
globalMqttRunAll: persistedState.globalMqttRunAll || initialState.globalMqttRunAll,
|
||||||
mqttBrokerUrl: persistedState.mqttBrokerUrl || initialState.mqttBrokerUrl,
|
mqttBrokerUrl: persistedState.mqttBrokerUrl || initialState.mqttBrokerUrl,
|
||||||
|
mqttConnectDesired: persistedState.hasOwnProperty('mqttConnectDesired') ? persistedState.mqttConnectDesired : initialState.mqttConnectDesired,
|
||||||
gameRunning: false, // Always start non-running
|
gameRunning: false, // Always start non-running
|
||||||
currentPlayerIndex: persistedState.currentPlayerIndex !== undefined && persistedState.currentPlayerIndex < playersToUse.length ? persistedState.currentPlayerIndex : 0,
|
currentPlayerIndex: persistedState.currentPlayerIndex !== undefined && persistedState.currentPlayerIndex < playersToUse.length ? persistedState.currentPlayerIndex : 0,
|
||||||
};
|
};
|
||||||
@@ -113,6 +115,10 @@ export default createStore({
|
|||||||
},
|
},
|
||||||
SET_MQTT_BROKER_URL(state, url) {
|
SET_MQTT_BROKER_URL(state, url) {
|
||||||
state.mqttBrokerUrl = url;
|
state.mqttBrokerUrl = url;
|
||||||
|
state.mqttConnectDesired = true;
|
||||||
|
},
|
||||||
|
SET_MQTT_CONNECT_DESIRED(state, desired) {
|
||||||
|
state.mqttConnectDesired = desired;
|
||||||
},
|
},
|
||||||
SET_GLOBAL_MQTT_STOP_PAUSE(state, char) {
|
SET_GLOBAL_MQTT_STOP_PAUSE(state, char) {
|
||||||
state.globalMqttStopPause = char;
|
state.globalMqttStopPause = char;
|
||||||
@@ -251,9 +257,10 @@ export default createStore({
|
|||||||
})),
|
})),
|
||||||
globalHotkeyStopPause: state.globalHotkeyStopPause,
|
globalHotkeyStopPause: state.globalHotkeyStopPause,
|
||||||
globalHotkeyRunAll: state.globalHotkeyRunAll,
|
globalHotkeyRunAll: state.globalHotkeyRunAll,
|
||||||
globalMqttStopPause: state.globalMqttStopPause, // Save
|
globalMqttStopPause: state.globalMqttStopPause,
|
||||||
globalMqttRunAll: state.globalMqttRunAll, // Save
|
globalMqttRunAll: state.globalMqttRunAll,
|
||||||
mqttBrokerUrl: state.mqttBrokerUrl, // Save
|
mqttBrokerUrl: state.mqttBrokerUrl,
|
||||||
|
mqttConnectDesired: state.mqttConnectDesired,
|
||||||
currentPlayerIndex: state.currentPlayerIndex,
|
currentPlayerIndex: state.currentPlayerIndex,
|
||||||
gameMode: state.gameMode,
|
gameMode: state.gameMode,
|
||||||
isMuted: state.isMuted,
|
isMuted: state.isMuted,
|
||||||
@@ -268,6 +275,10 @@ export default createStore({
|
|||||||
commit('SET_MQTT_BROKER_URL', url);
|
commit('SET_MQTT_BROKER_URL', url);
|
||||||
dispatch('saveState');
|
dispatch('saveState');
|
||||||
},
|
},
|
||||||
|
setMqttConnectDesired({ commit, dispatch }, desired) {
|
||||||
|
commit('SET_MQTT_CONNECT_DESIRED', desired);
|
||||||
|
dispatch('saveState');
|
||||||
|
},
|
||||||
setGlobalMqttStopPause({ commit, dispatch }, char) {
|
setGlobalMqttStopPause({ commit, dispatch }, char) {
|
||||||
commit('SET_GLOBAL_MQTT_STOP_PAUSE', char);
|
commit('SET_GLOBAL_MQTT_STOP_PAUSE', char);
|
||||||
dispatch('saveState');
|
dispatch('saveState');
|
||||||
@@ -333,6 +344,7 @@ export default createStore({
|
|||||||
commit('SET_GLOBAL_HOTKEY_STOP_PAUSE', freshInitialState.globalHotkeyStopPause);
|
commit('SET_GLOBAL_HOTKEY_STOP_PAUSE', freshInitialState.globalHotkeyStopPause);
|
||||||
commit('SET_GLOBAL_HOTKEY_RUN_ALL', freshInitialState.globalHotkeyRunAll);
|
commit('SET_GLOBAL_HOTKEY_RUN_ALL', freshInitialState.globalHotkeyRunAll);
|
||||||
commit('SET_MQTT_BROKER_URL', freshInitialState.mqttBrokerUrl); // Reset
|
commit('SET_MQTT_BROKER_URL', freshInitialState.mqttBrokerUrl); // Reset
|
||||||
|
commit('SET_MQTT_CONNECT_DESIRED', freshInitialState.mqttConnectDesired); // Reset
|
||||||
commit('SET_GLOBAL_MQTT_STOP_PAUSE', freshInitialState.globalMqttStopPause); // Reset
|
commit('SET_GLOBAL_MQTT_STOP_PAUSE', freshInitialState.globalMqttStopPause); // Reset
|
||||||
commit('SET_GLOBAL_MQTT_RUN_ALL', freshInitialState.globalMqttRunAll); // Reset
|
commit('SET_GLOBAL_MQTT_RUN_ALL', freshInitialState.globalMqttRunAll); // Reset
|
||||||
|
|
||||||
@@ -486,6 +498,7 @@ export default createStore({
|
|||||||
globalHotkeyStopPause: state => state.globalHotkeyStopPause,
|
globalHotkeyStopPause: state => state.globalHotkeyStopPause,
|
||||||
globalHotkeyRunAll: state => state.globalHotkeyRunAll,
|
globalHotkeyRunAll: state => state.globalHotkeyRunAll,
|
||||||
mqttBrokerUrl: state => state.mqttBrokerUrl,
|
mqttBrokerUrl: state => state.mqttBrokerUrl,
|
||||||
|
mqttConnectDesired: state => state.mqttConnectDesired,
|
||||||
globalMqttStopPause: state => state.globalMqttStopPause,
|
globalMqttStopPause: state => state.globalMqttStopPause,
|
||||||
globalMqttRunAll: state => state.globalMqttRunAll,
|
globalMqttRunAll: state => state.globalMqttRunAll,
|
||||||
totalPlayers: state => state.players.length,
|
totalPlayers: state => state.players.length,
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
<h1 class="text-4xl font-bold text-blue-600 dark:text-blue-400">Nexus Timer Setup</h1>
|
<h1 class="text-4xl font-bold text-blue-600 dark:text-blue-400">Nexus Timer Setup</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Player Management -->
|
<!-- Player Management (no changes) -->
|
||||||
<section class="w-full max-w-3xl bg-white dark:bg-gray-700 p-6 rounded-lg shadow-md mb-6">
|
<section class="w-full max-w-3xl bg-white dark:bg-gray-700 p-6 rounded-lg shadow-md mb-6">
|
||||||
|
<!-- ... Player list ... -->
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<h2 class="text-2xl font-semibold">Players ({{ players.length }})</h2>
|
<h2 class="text-2xl font-semibold">Players ({{ players.length }})</h2>
|
||||||
<button @click="openAddPlayerModal" class="btn btn-primary" :disabled="players.length >= 99">
|
<button @click="openAddPlayerModal" class="btn btn-primary" :disabled="players.length >= 99">
|
||||||
@@ -52,22 +53,40 @@
|
|||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<label for="mqttBrokerUrl" class="block text-sm font-medium text-gray-700 dark:text-gray-300">MQTT Broker URL</label>
|
<label for="mqttBrokerUrl" class="block text-sm font-medium text-gray-700 dark:text-gray-300">MQTT Broker URL</label>
|
||||||
<div class="mt-1 flex rounded-md shadow-sm">
|
<div class="mt-1 flex rounded-md shadow-sm">
|
||||||
<input type="text" id="mqttBrokerUrl" v-model="localMqttBrokerUrl" placeholder="ws://localhost:9001" class="input-base flex-1 rounded-none rounded-l-md" :disabled="mqttConnectionStatus === 'connected' || mqttConnectionStatus === 'connecting'">
|
<input
|
||||||
<button @click="toggleMqttConnection"
|
type="text"
|
||||||
:class="['btn inline-flex items-center px-3 rounded-l-none rounded-r-md border border-l-0',
|
id="mqttBrokerUrl"
|
||||||
mqttConnectionStatus === 'connected' ? 'bg-green-500 hover:bg-green-600 border-green-600' :
|
v-model="localMqttBrokerUrl"
|
||||||
mqttConnectionStatus === 'connecting' ? 'bg-yellow-500 border-yellow-600 cursor-not-allowed' :
|
placeholder="ws://broker.example.com:9001"
|
||||||
mqttConnectionStatus === 'error' ? 'bg-red-500 hover:bg-red-600 border-red-600' :
|
class="input-base flex-1 rounded-none rounded-l-md"
|
||||||
'btn-secondary border-gray-300 dark:border-gray-500']"
|
:disabled="mqttConnectionStatus === 'connected' || mqttConnectionStatus === 'connecting'"
|
||||||
:disabled="mqttConnectionStatus === 'connecting'">
|
>
|
||||||
{{ mqttConnectionStatus === 'connected' ? 'Disconnect' : (mqttConnectionStatus === 'connecting' ? 'Connecting...' : 'Connect') }}
|
<button
|
||||||
|
@click="toggleMqttConnection"
|
||||||
|
:class="['btn inline-flex items-center px-4 rounded-l-none rounded-r-md border border-l-0 text-white',
|
||||||
|
mqttConnectionStatus === 'connected' ? 'bg-red-500 hover:bg-red-600 border-red-600' :
|
||||||
|
mqttConnectionStatus === 'connecting' ? 'bg-yellow-500 hover:bg-yellow-600 border-yellow-600 !text-black' : // Stop button is yellow
|
||||||
|
'btn-primary border-blue-500']"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
mqttConnectionStatus === 'connected' ? 'Disconnect' :
|
||||||
|
(mqttConnectionStatus === 'connecting' ? 'Stop' : 'Connect')
|
||||||
|
}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="mqttError" class="text-xs text-red-500 mt-1">{{ mqttError }}</p>
|
<p v-if="mqttError" class="text-xs text-red-500 mt-1">{{ mqttError }}</p>
|
||||||
<p v-else-if="mqttConnectionStatus === 'connected'" class="text-xs text-green-500 mt-1">Connected to {{ store.getters.mqttBrokerUrl }}. Subscribed to '{{ MqttService.MQTT_TOPIC_GAME }}'.</p>
|
<p v-else-if="mqttConnectionStatus === 'connected'" class="text-xs text-green-500 mt-1">
|
||||||
<p v-else-if="mqttConnectionStatus === 'disconnected' && !mqttError" class="text-xs text-gray-500 mt-1">Not connected to MQTT broker.</p>
|
Connected to {{ store.getters.mqttBrokerUrl }}. Subscribed to '{{ MqttService.MQTT_TOPIC_GAME }}'.
|
||||||
|
</p>
|
||||||
|
<p v-else-if="mqttConnectionStatus === 'connecting'" class="text-xs text-yellow-600 mt-1">
|
||||||
|
Connecting to {{ localMqttBrokerUrl }}... (Click "Stop" to cancel)
|
||||||
|
</p>
|
||||||
|
<p v-else-if="mqttConnectionStatus === 'disconnected'" class="text-xs text-gray-500 mt-1">
|
||||||
|
Not connected.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Global Triggers (no changes to this section) -->
|
||||||
<div>
|
<div>
|
||||||
<p class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Global "Stop/Pause All" Trigger:</p>
|
<p class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Global "Stop/Pause All" Trigger:</p>
|
||||||
<div class="flex items-center justify-between space-x-4 mb-3">
|
<div class="flex items-center justify-between space-x-4 mb-3">
|
||||||
@@ -87,7 +106,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Global "Run All Timers" Trigger:</p>
|
<p class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Global "Run All Timers" Trigger:</p>
|
||||||
<div class="flex items-center justify-between space-x-4 mb-6">
|
<div class="flex items-center justify-between space-x-4 mb-6">
|
||||||
@@ -141,6 +159,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.trigger-clear-btn {
|
||||||
|
@apply text-xs text-blue-500 hover:underline ml-2 px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onUnmounted } from 'vue';
|
import { ref, computed, watch, onUnmounted } from 'vue';
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
@@ -255,9 +279,8 @@ const handleGlobalHotkeyCaptured = (key) => {
|
|||||||
isCapturingGlobalHotkey.value = false;
|
isCapturingGlobalHotkey.value = false;
|
||||||
const actionType = currentGlobalActionType.value;
|
const actionType = currentGlobalActionType.value;
|
||||||
if (!actionType || key.length !== 1) { currentGlobalActionType.value = null; return; }
|
if (!actionType || key.length !== 1) { currentGlobalActionType.value = null; return; }
|
||||||
|
|
||||||
let conflictMessage = '';
|
let conflictMessage = '';
|
||||||
if (store.state.players.some(p => p.hotkey === key)) { // Only check player hotkeys
|
if (store.state.players.some(p => p.hotkey === key)) {
|
||||||
conflictMessage = `Hotkey "${key.toUpperCase()}" is already used by a player.`;
|
conflictMessage = `Hotkey "${key.toUpperCase()}" is already used by a player.`;
|
||||||
}
|
}
|
||||||
else if (actionType === 'stopPause' && store.state.globalHotkeyRunAll === key) {
|
else if (actionType === 'stopPause' && store.state.globalHotkeyRunAll === key) {
|
||||||
@@ -265,9 +288,7 @@ const handleGlobalHotkeyCaptured = (key) => {
|
|||||||
} else if (actionType === 'runAll' && store.state.globalHotkeyStopPause === key) {
|
} else if (actionType === 'runAll' && store.state.globalHotkeyStopPause === key) {
|
||||||
conflictMessage = `Hotkey "${key.toUpperCase()}" is already the Global Stop/Pause All Hotkey.`;
|
conflictMessage = `Hotkey "${key.toUpperCase()}" is already the Global Stop/Pause All Hotkey.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conflictMessage) { alert(conflictMessage); currentGlobalActionType.value = null; return; }
|
if (conflictMessage) { alert(conflictMessage); currentGlobalActionType.value = null; return; }
|
||||||
|
|
||||||
if (actionType === 'stopPause') store.dispatch('setGlobalHotkeyStopPause', key);
|
if (actionType === 'stopPause') store.dispatch('setGlobalHotkeyStopPause', key);
|
||||||
else if (actionType === 'runAll') store.dispatch('setGlobalHotkeyRunAll', key);
|
else if (actionType === 'runAll') store.dispatch('setGlobalHotkeyRunAll', key);
|
||||||
currentGlobalActionType.value = null;
|
currentGlobalActionType.value = null;
|
||||||
@@ -296,9 +317,8 @@ const handleGlobalMqttCharCapturedDirect = (charKey) => {
|
|||||||
isCapturingGlobalMqttChar.value = false;
|
isCapturingGlobalMqttChar.value = false;
|
||||||
const actionType = currentGlobalActionType.value;
|
const actionType = currentGlobalActionType.value;
|
||||||
if (!actionType || charKey.length !== 1) { currentGlobalActionType.value = null; return; }
|
if (!actionType || charKey.length !== 1) { currentGlobalActionType.value = null; return; }
|
||||||
|
|
||||||
let conflictMessage = '';
|
let conflictMessage = '';
|
||||||
if (store.state.players.some(p => p.mqttChar === charKey)) { // Only check player MQTT chars
|
if (store.state.players.some(p => p.mqttChar === charKey)) {
|
||||||
conflictMessage = `MQTT Char "${charKey.toUpperCase()}" is already used by a player.`;
|
conflictMessage = `MQTT Char "${charKey.toUpperCase()}" is already used by a player.`;
|
||||||
}
|
}
|
||||||
else if (actionType === 'stopPause' && store.state.globalMqttRunAll === charKey) {
|
else if (actionType === 'stopPause' && store.state.globalMqttRunAll === charKey) {
|
||||||
@@ -306,26 +326,38 @@ const handleGlobalMqttCharCapturedDirect = (charKey) => {
|
|||||||
} else if (actionType === 'runAll' && store.state.globalMqttStopPause === charKey) {
|
} else if (actionType === 'runAll' && store.state.globalMqttStopPause === charKey) {
|
||||||
conflictMessage = `MQTT Char "${charKey.toUpperCase()}" is already the Global Stop/Pause All MQTT Char.`;
|
conflictMessage = `MQTT Char "${charKey.toUpperCase()}" is already the Global Stop/Pause All MQTT Char.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conflictMessage) { alert(conflictMessage); currentGlobalActionType.value = null; return; }
|
if (conflictMessage) { alert(conflictMessage); currentGlobalActionType.value = null; return; }
|
||||||
|
|
||||||
if (actionType === 'stopPause') store.dispatch('setGlobalMqttStopPause', charKey);
|
if (actionType === 'stopPause') store.dispatch('setGlobalMqttStopPause', charKey);
|
||||||
else if (actionType === 'runAll') store.dispatch('setGlobalMqttRunAll', charKey);
|
else if (actionType === 'runAll') store.dispatch('setGlobalMqttRunAll', charKey);
|
||||||
currentGlobalActionType.value = null;
|
currentGlobalActionType.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleMqttConnection = async () => {
|
const toggleMqttConnection = async () => {
|
||||||
if (MqttService.connectionStatus.value === 'connected') {
|
if (MqttService.connectionStatus.value === 'connected' || MqttService.connectionStatus.value === 'connecting') {
|
||||||
MqttService.disconnect();
|
MqttService.disconnect();
|
||||||
} else {
|
// User explicitly disconnected or stopped connecting
|
||||||
|
await store.dispatch('setMqttConnectDesired', false);
|
||||||
|
} else { // Status is 'disconnected' or 'error'
|
||||||
if (!localMqttBrokerUrl.value.trim()) {
|
if (!localMqttBrokerUrl.value.trim()) {
|
||||||
alert("Please enter MQTT Broker URL.");
|
alert("Please enter MQTT Broker URL (e.g., ws://host:port).");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const url = new URL(localMqttBrokerUrl.value);
|
||||||
|
if(!url.protocol.startsWith('ws')) {
|
||||||
|
throw new Error("URL must start with ws:// or wss://");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert(`Invalid MQTT Broker URL: ${e.message}. Please use format ws://host:port or wss://host:port.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Saving URL also sets mqttConnectDesired to true in the store
|
||||||
await store.dispatch('setMqttBrokerUrl', localMqttBrokerUrl.value);
|
await store.dispatch('setMqttBrokerUrl', localMqttBrokerUrl.value);
|
||||||
|
// await store.dispatch('setMqttConnectDesired', true); // This is now handled by setMqttBrokerUrl action
|
||||||
MqttService.connect(localMqttBrokerUrl.value);
|
MqttService.connect(localMqttBrokerUrl.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (MqttService.isCapturingMqttChar.value) {
|
if (MqttService.isCapturingMqttChar.value) {
|
||||||
MqttService.stopMqttCharCapture();
|
MqttService.stopMqttCharCapture();
|
||||||
|
|||||||
@@ -6,29 +6,21 @@ import { resolve } from 'path';
|
|||||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||||
const appVersion = packageJson.version;
|
const appVersion = packageJson.version;
|
||||||
|
|
||||||
|
// Get current date (this will be the server's local time where the build runs)
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const dateTimeFormat = new Intl.DateTimeFormat('sk-SK', {
|
|
||||||
|
// Options for date formatting, targeting CET/CEST
|
||||||
|
const dateTimeFormatOptionsCEST = {
|
||||||
year: 'numeric', month: '2-digit', day: '2-digit',
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
||||||
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
||||||
hour12: false
|
hour12: false, // Use 24-hour format
|
||||||
});
|
timeZone: 'Europe/Bratislava' // Or 'Europe/Prague', 'Europe/Berlin', etc. (any major CET/CEST city)
|
||||||
|
// This will automatically handle Daylight Saving Time (CEST vs CET)
|
||||||
|
};
|
||||||
|
|
||||||
const parts = dateTimeFormat.formatToParts(now);
|
// Generate build time string using a specific time zone that observes CET/CEST
|
||||||
let day = '', month = '', year = '', hour = '', minute = '', second = '';
|
const appBuildTime = now.toLocaleString('sk-SK', dateTimeFormatOptionsCEST) + " CEST/CET"; // Add timezone indicator for clarity
|
||||||
|
|
||||||
parts.forEach(part => {
|
|
||||||
switch (part.type) {
|
|
||||||
case 'day': day = part.value; break;
|
|
||||||
case 'month': month = part.value; break;
|
|
||||||
case 'year': year = part.value; break;
|
|
||||||
case 'hour': hour = part.value; break;
|
|
||||||
case 'minute': minute = part.value; break;
|
|
||||||
case 'second': second = part.value; break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assemble the date part without unwanted spaces
|
|
||||||
const appBuildTime = `${day}.${month}.${year} ${hour}:${minute}:${second}`;
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
|
|||||||
Reference in New Issue
Block a user