diff --git a/src/boot/axios.ts b/src/boot/axios.ts index 311c4e2..a14d14e 100644 --- a/src/boot/axios.ts +++ b/src/boot/axios.ts @@ -3,10 +3,9 @@ import axios from 'axios'; const host = window.location.hostname; const port = 8100; -const baseURL = `http://${host}:${port}`; const api = axios.create({ - baseURL: baseURL, + baseURL: `http://${host}:${port}`, timeout: 30000, headers: { 'Content-Type': 'application/json', diff --git a/src/boot/websocket.ts b/src/boot/websocket.ts index a4ee6c8..41b53e4 100644 --- a/src/boot/websocket.ts +++ b/src/boot/websocket.ts @@ -4,11 +4,8 @@ import { initWebSocket } from '../vueLib/services/websocket'; export default boot(({ app }) => { const $q = app.config.globalProperties.$q as QVueGlobals; - const host = window.location.hostname; - const port = 8100; - const randomId = Math.floor(Math.random() * 10001); // random number from 0 to 10000 - const ws = initWebSocket(`ws://${host}:${port}/ws?id=q${randomId}`, $q); + const ws = initWebSocket(window.location.hostname, 8100, $q); app.config.globalProperties.$socket = ws; ws.connect(); diff --git a/src/components/dialog/OkDialog.vue b/src/components/dialog/OkDialog.vue index 78c6cbc..3ae1d50 100644 --- a/src/components/dialog/OkDialog.vue +++ b/src/components/dialog/OkDialog.vue @@ -66,18 +66,14 @@ const internalShowDialog = ref(props.showDialog); watch( () => props.showDialog, (newValue) => { - console.log('watch showDialog', newValue); internalShowDialog.value = newValue; }, ); watch(internalShowDialog, (newValue) => { - console.log('watch internalShowDialog', newValue); emit('update:showDialog', newValue); if (!newValue) { - console.log('emit cancel'); emit('cancel'); } else { - console.log('emit confirmed'); emit('confirmed'); } }); diff --git a/src/vueLib/dbm/DataTable.vue b/src/vueLib/dbm/DataTable.vue index 630a5be..fa64b61 100644 --- a/src/vueLib/dbm/DataTable.vue +++ b/src/vueLib/dbm/DataTable.vue @@ -17,7 +17,7 @@
@@ -26,8 +26,8 @@
Read Write Access
- Read - Write + Read + Write
{{ props.buttonOkLabel @@ -45,7 +45,7 @@ + + diff --git a/src/vueLib/dbm/dialog/RenameDatapoint.vue b/src/vueLib/dbm/dialog/RenameDatapoint.vue index 074cb5f..df4dbac 100644 --- a/src/vueLib/dbm/dialog/RenameDatapoint.vue +++ b/src/vueLib/dbm/dialog/RenameDatapoint.vue @@ -10,7 +10,7 @@ + + diff --git a/src/vueLib/dbm/dialog/UpdateValueDialog.vue b/src/vueLib/dbm/dialog/UpdateValueDialog.vue index 93afab2..9d7be23 100644 --- a/src/vueLib/dbm/dialog/UpdateValueDialog.vue +++ b/src/vueLib/dbm/dialog/UpdateValueDialog.vue @@ -6,7 +6,7 @@ :class="'text-' + props.labelColor" >{{ props.dialogLabel ? props.dialogLabel : localDialogLabel }} - + - - +
+
+
current value
+
+ +
+
+
+
new value
+
+ +
+
+
{{ props.text @@ -63,15 +68,16 @@ import type { Subscribe } from '../../models/Subscribe'; import type { Ref } from 'vue'; import { setValues } from '../../services/websocket'; import { useNotify } from '../../general/useNotify'; -import type { QTableProps } from 'quasar'; -import type { Driver } from '../../models/Drivers'; import { catchError } from 'src/vueLib/models/error'; const { NotifyResponse } = useNotify(); const Dialog = ref(); +const localDialogLabel = ref(''); const writeValue = ref(); const onlyRead = ref(false); const writeType = ref<'text' | 'number'>('text'); +const datapoint = ref(); +const inputValue = ref(datapoint?.value); const props = defineProps({ buttonOkLabel: { @@ -100,33 +106,14 @@ const props = defineProps({ }, }); -const datapoint = ref(); -const inputValue = ref(datapoint?.value); -const localDialogLabel = ref(''); -const drivers = ref([]); -const columns = [ - { name: 'type', label: 'Driver Name', field: 'type', align: 'left' }, - { name: 'bus', label: 'Bus Name', field: 'bus', align: 'center' }, - { name: 'address', label: 'Address', field: 'address', align: 'center' }, -] as QTableProps['columns']; - -const open = (sub: Ref, type?: string) => { +const open = (sub: Ref) => { datapoint.value = sub.value; if (datapoint.value.rights == 'R') onlyRead.value = true; - drivers.value = []; - switch (type) { - case 'driver': - localDialogLabel.value = 'Update Drivers'; - if (sub.value.drivers) drivers.value = Object.values(sub.value.drivers); - writeValue.value = sub.value.drivers; - break; - default: - localDialogLabel.value = 'Update Value'; - if (sub.value.type === 'STR') writeType.value = 'text'; - else if (sub.value.type === 'BIT') writeType.value = 'text'; - else writeType.value = 'number'; - writeValue.value = sub.value.value; - } + localDialogLabel.value = 'Update Value'; + if (sub.value.type === 'STR') writeType.value = 'text'; + else writeType.value = 'number'; + writeValue.value = sub.value.value; + Dialog.value?.open(); }; @@ -156,4 +143,8 @@ defineExpose({ open }); .outercard { border-radius: 10px; } +.readonly-toggle { + pointer-events: none; + opacity: 0.7; +} diff --git a/src/vueLib/models/Bus.ts b/src/vueLib/models/Bus.ts new file mode 100644 index 0000000..6137835 --- /dev/null +++ b/src/vueLib/models/Bus.ts @@ -0,0 +1,7 @@ +import type { Topic } from './Topic'; + +export interface Bus { + name: string; + address?: number[]; + topic?: Topic; +} diff --git a/src/vueLib/models/Drivers.ts b/src/vueLib/models/Drivers.ts index 1ff5552..02cde2b 100644 --- a/src/vueLib/models/Drivers.ts +++ b/src/vueLib/models/Drivers.ts @@ -1,5 +1,9 @@ +import type { Bus } from './Bus'; export interface Driver { type: string; - addess: number; - value: number; + buses?: Bus[]; } + +export const driverDefault = { + type: '', +}; diff --git a/src/vueLib/models/Publish.ts b/src/vueLib/models/Publish.ts index 657060c..62ab86a 100644 --- a/src/vueLib/models/Publish.ts +++ b/src/vueLib/models/Publish.ts @@ -1,14 +1,21 @@ +import type { Driver } from './Drivers'; export type Publish = { event: string; uuid: string; path: string; type: string; + drivers?: Record; value: string | number | boolean | null; hasChild: boolean; }; export type Pubs = Publish[]; -import { updateSubscriptionValue, removeRawSubscriptions } from './Subscriptions'; +import { + updateSubscriptionValue, + removeRawSubscriptions, + addRawSubscription, + removeRawSubscription, +} from './Subscriptions'; import { buildTree, buildTreeWithRawSubs, removeNodes } from '../dbm/dbmTree'; import type { RawSubs, RawSubscribe } from '../models/Subscribe'; import { ref } from 'vue'; @@ -33,6 +40,11 @@ export function publishToSubscriptions(pubs: Pubs) { rawSubs.value.push(pub as RawSubscribe); break; } + if (pub.drivers) { + removeRawSubscription(pub as RawSubscribe); + addRawSubscription(pub as RawSubscribe); + UpdateTable(); + } updateSubscriptionValue(pub.uuid, pub.value); }); diff --git a/src/vueLib/models/Request.ts b/src/vueLib/models/Request.ts index c713a0a..a09e79c 100644 --- a/src/vueLib/models/Request.ts +++ b/src/vueLib/models/Request.ts @@ -1,3 +1,4 @@ +import type { Driver } from './Drivers'; import type { Gets } from './Get'; import type { Sets } from './Set'; import type { Subs } from './Subscribe'; @@ -61,10 +62,11 @@ export async function rawSetsRequest(sets: Sets): Promise { export async function setRequest( path: string, - type: string, - value: string | number | boolean, + type?: string, + value?: string | number | boolean, rights?: string, uuid?: string, + driver?: Driver, rename?: boolean, ): Promise { const payload = { @@ -73,6 +75,7 @@ export async function setRequest( value: value, rights: rights, uuid: uuid, + driver: driver, rename: rename, }; @@ -99,14 +102,18 @@ export async function setsRequest(sets: Sets): Promise { } } -export async function deleteRequest(uuid?: string, path?: string, rename?: boolean): Promise { +export async function deleteRequest( + uuid?: string, + path?: string, + driver?: Driver, + rename?: boolean, +): Promise { let payload = {}; if (uuid) { - payload = { uuid: uuid, rename: rename }; + payload = { uuid: uuid, driver: driver, rename: rename }; } else if (path) { - payload = { path: path }; + payload = { path: path, driver: driver }; } - const resp = await api.delete('/json_data', { data: { set: [payload], diff --git a/src/vueLib/models/Subscribe.ts b/src/vueLib/models/Subscribe.ts index cf53b11..b28d6c7 100644 --- a/src/vueLib/models/Subscribe.ts +++ b/src/vueLib/models/Subscribe.ts @@ -20,6 +20,7 @@ export type RawSubscribe = { path?: string; depth?: number; value?: string | number | boolean | null; + drivers?: Record; rights?: string; hasChild?: boolean; }; diff --git a/src/vueLib/models/Topic.ts b/src/vueLib/models/Topic.ts new file mode 100644 index 0000000..b5f6d0b --- /dev/null +++ b/src/vueLib/models/Topic.ts @@ -0,0 +1,4 @@ +export interface Topic { + subscribe: string[]; + publish: string[]; +} diff --git a/src/vueLib/models/driverTable.ts b/src/vueLib/models/driverTable.ts new file mode 100644 index 0000000..de73d77 --- /dev/null +++ b/src/vueLib/models/driverTable.ts @@ -0,0 +1,83 @@ +import { reactive, ref } from 'vue'; +import type { QTableColumn } from 'quasar'; +import type { Subscribe } from './Subscribe'; + +export type DriverTableRow = { + type: string; + bus: string; + address?: number | undefined; + subscribe?: string; + publish?: string; +}; + +const driverTable = reactive([]); +const columns = ref([]); +const baseColumns: QTableColumn[] = [ + { name: 'type', label: 'Driver Name', field: 'type', align: 'left' }, + { name: 'bus', label: 'Bus Name', field: 'bus', align: 'center' }, + { name: 'address', label: 'Address', field: 'address', align: 'center' }, + { name: 'settings', label: '', field: 'settings', align: 'center' }, +]; + +export function updateDriverTable(sub: Subscribe) { + driverTable.length = 0; + let hasSubs = false; + let hasPubs = false; + + if (sub.drivers) + Object.entries(sub.drivers).forEach(([driverName, driverData]) => { + driverData.buses?.forEach((bus) => { + hasSubs = bus.topic?.subscribe !== undefined || hasSubs; + hasPubs = bus.topic?.publish !== undefined || hasPubs; + + const subscribeList = bus.topic?.subscribe ?? []; + const publishList = bus.topic?.publish ?? []; + + const addresses = bus.address?.length ? bus.address : [undefined]; + + addresses.forEach((addr) => { + driverTable.push({ + type: driverName, + bus: bus.name, + address: addr, + subscribe: subscribeList.join(', '), + publish: publishList.join(', '), + }); + }); + }); + }); + reloadColumns(hasSubs, hasPubs); +} +export function useDriverTable() { + function emptyTable() { + driverTable.length = 0; + } + + return { + driverTable, + emptyTable, + columns, + }; +} + +function reloadColumns(hasSubs: boolean, hasPubs: boolean) { + columns.value = [...baseColumns]; + const settingsIndex = columns?.value.findIndex((col) => col.name === 'settings'); + + if (hasSubs) { + columns.value?.splice(settingsIndex ?? -1, 0, { + name: 'subscribe', + label: 'subscribe', + field: 'subscribe', + align: 'left', + }); + } + if (hasPubs) { + columns.value?.splice(settingsIndex ?? -1, 0, { + name: 'publish', + label: 'publish', + field: 'publish', + align: 'left', + }); + } +} diff --git a/src/vueLib/services/websocket.ts b/src/vueLib/services/websocket.ts index f69ca6c..699019c 100644 --- a/src/vueLib/services/websocket.ts +++ b/src/vueLib/services/websocket.ts @@ -12,9 +12,11 @@ export let socket: WebSocket | null = null; const isConnected = ref(false); -export function initWebSocket(url: string, $q?: QVueGlobals) { +export function initWebSocket(host: string, port: number = 8100, $q?: QVueGlobals) { + const randomId = Math.floor(Math.random() * 10001); // random number from 0 to 10000 + const connect = () => { - socket = new WebSocket(url); + socket = new WebSocket(`ws://${host}:${port}/ws?id=q${randomId}`); socket.onopen = () => { console.log('WebSocket connected');