diff --git a/public/favicon.ico b/public/favicon.ico index ae7bbdb..d86a70a 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/icons/favicon-128x128.png b/public/icons/favicon-128x128.png index 1401176..bcf145e 100644 Binary files a/public/icons/favicon-128x128.png and b/public/icons/favicon-128x128.png differ diff --git a/public/icons/favicon-16x16.png b/public/icons/favicon-16x16.png index 679063a..d50ecd9 100644 Binary files a/public/icons/favicon-16x16.png and b/public/icons/favicon-16x16.png differ diff --git a/public/icons/favicon-32x32.png b/public/icons/favicon-32x32.png index fd1fbc6..5d99a2a 100644 Binary files a/public/icons/favicon-32x32.png and b/public/icons/favicon-32x32.png differ diff --git a/public/icons/favicon-96x96.png b/public/icons/favicon-96x96.png index e93b80a..1873264 100644 Binary files a/public/icons/favicon-96x96.png and b/public/icons/favicon-96x96.png differ diff --git a/quasar.config.ts b/quasar.config.ts index 1b22535..cb0dc58 100644 --- a/quasar.config.ts +++ b/quasar.config.ts @@ -20,15 +20,15 @@ export default defineConfig((/* ctx */) => { // https://github.com/quasarframework/quasar/tree/dev/extras extras: [ // 'ionicons-v4', - // 'mdi-v7', + 'mdi-v7', // 'fontawesome-v6', // 'eva-icons', // 'themify', // 'line-awesome', // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! - 'roboto-font', // optional, you are not bound to it - 'material-icons', // optional, you are not bound to it + // 'roboto-font', // optional, you are not bound to it + // 'material-icons', // optional, you are not bound to it ], // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#build @@ -151,7 +151,8 @@ export default defineConfig((/* ctx */) => { config: { dark: true, }, - iconSet: 'material-icons', // Quasar icon set + // iconSet: 'material-icons', // Quasar icon set + iconSet: 'mdi-v7', // lang: 'en-US', // Quasar language pack // For special cases outside of where the auto-import strategy can have an impact diff --git a/src/assets/mdi-v7-icons.json b/src/assets/mdi-v7-icons.json new file mode 100644 index 0000000..56128ec --- /dev/null +++ b/src/assets/mdi-v7-icons.json @@ -0,0 +1,15 @@ +[ + "mdi-dark", + "mdi-flip-h", + "mdi-flip-v", + "mdi-inactive", + "mdi-light", + "mdi-rotate-135", + "mdi-rotate-180", + "mdi-rotate-225", + "mdi-rotate-270", + "mdi-rotate-315", + "mdi-rotate-45", + "mdi-rotate-90", + "mdi-spin" +] \ No newline at end of file diff --git a/src/assets/simloc_logo.png b/src/assets/simloc_logo.png new file mode 100644 index 0000000..6fe489b Binary files /dev/null and b/src/assets/simloc_logo.png differ diff --git a/src/assets/simloc_logo.svg b/src/assets/simloc_logo.svg new file mode 100644 index 0000000..64be41a --- /dev/null +++ b/src/assets/simloc_logo.svg @@ -0,0 +1,1978 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/simloc_logo2.png b/src/assets/simloc_logo2.png new file mode 100644 index 0000000..4582185 Binary files /dev/null and b/src/assets/simloc_logo2.png differ diff --git a/src/components/EditFavoriteDialog.vue b/src/components/EditFavoriteDialog.vue new file mode 100644 index 0000000..2a0adb0 --- /dev/null +++ b/src/components/EditFavoriteDialog.vue @@ -0,0 +1,218 @@ + + + + diff --git a/src/components/FormattedAddress.vue b/src/components/FormattedAddress.vue index f4dc37e..2f5ae2a 100644 --- a/src/components/FormattedAddress.vue +++ b/src/components/FormattedAddress.vue @@ -1,48 +1,38 @@ + diff --git a/src/components/NestedKnob.vue b/src/components/NestedKnob.vue new file mode 100644 index 0000000..91ff706 --- /dev/null +++ b/src/components/NestedKnob.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/src/components/SetLocationDialog.vue b/src/components/SetLocationDialog.vue index b0ffa82..d5a19a7 100644 --- a/src/components/SetLocationDialog.vue +++ b/src/components/SetLocationDialog.vue @@ -2,15 +2,27 @@ - + Add Location to Queue -
Are you sure you want to set location to:
-
- +
Are you sure you want to set location to:
+
+
+
+ + + +
+ +
+
- - - + +
+ + Favorite + +
+
+ + +
@@ -34,39 +63,83 @@ diff --git a/src/stores/device.ts b/src/stores/device.ts new file mode 100644 index 0000000..953ad8a --- /dev/null +++ b/src/stores/device.ts @@ -0,0 +1,47 @@ +import { defineStore, acceptHMRUpdate } from 'pinia'; +import { socket } from 'boot/socketio'; +import type { DeviceCommands } from 'components/models'; + +import { useSocketStore } from 'stores/socket'; + + + +export const useDeviceStore = defineStore('deviceStore', { + state: () => { + return { + deviceConnected: false as boolean, + }; + }, + getters: {}, + actions: { + digestUpdate(data: boolean) { + this.deviceConnected = data; + }, + deviceControl(command: DeviceCommands, delay: number = 0) { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; + if (debugLog) { + console.log('deviceStore: got command: ', command, ' with delay: ', delay, ' seconds'); + } + socket.emit( + 'device_control', + { command: command, delay: delay }, + (response) => { + console.log(response.command_status, response.command); + if (response.command_status == 'ERROR') { + fnctRtn = { sts: 'error', msg: response.message?.toString() }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + } + }, + ); + return fnctRtn; + } + } +}); + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useDeviceStore, import.meta.hot)); +} diff --git a/src/stores/favorite.ts b/src/stores/favorite.ts new file mode 100644 index 0000000..3bc2382 --- /dev/null +++ b/src/stores/favorite.ts @@ -0,0 +1,124 @@ +import { defineStore, acceptHMRUpdate } from 'pinia'; +import { socket } from 'boot/socketio'; +import { useSocketStore } from 'stores/socket'; +import type { Favorite } from 'components/models'; + +export const useFavoriteStore = defineStore('favoriteStore', { + state: () => { + return { + favorites: [] as Favorite[], + categories: [] as string[], + }; + }, + getters: {}, + actions: { + favoriteControl({ command, favorite }: { command: string; favorite?: Favorite }) { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; + switch (command) { + case 'set': + if (!favorite) { + console.log('Favorite not provided, favdata: %s', favorite); + fnctRtn = { sts: 'error', msg: 'Favorite not provided.' }; + throw new Error('Favorite not provided.'); + } + socket.emit('favorite_control', { command: 'set', favorite: favorite }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.favorites) { + fnctRtn = { sts: 'error', msg: 'No favorites found.' }; + throw new Error(response.message); + } else { + console.log('Favorite added, favdata: %s', favorite); + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.favorites = response.data.favorites; + response.data.favorites.forEach((fav) => { + if (!this.categories.includes(fav.category)) { + this.categories.push(fav.category); + } + }); + } + if (debugLog) { + console.log('response from favorite_control_add: ', response); + } + return response.message; + } + }); + break; + case 'delete': + socket.emit('favorite_control', { command: 'delete', favorite: favorite }, (response) => { + if (response.command_status == 'ERROR') { + fnctRtn = { sts: 'error', msg: response.message }; + throw new Error(response.message); + } else { + if (!response.data?.favorites) { + fnctRtn = { sts: 'error', msg: 'No favorites found.' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.favorites = response.data.favorites; + response.data.favorites.forEach((fav) => { + if (!this.categories.includes(fav.category)) { + this.categories.push(fav.category); + } + }); + } + if (debugLog) { + console.log('response from favorite_control_delete: ', response); + } + return response.message; + } + }); + break; + case 'get': + socket.emit('favorite_control', { command: 'get', favorite: favorite }, (response) => { + if (response.command_status == 'ERROR') { + fnctRtn = { sts: 'error', msg: response.message }; + throw new Error(response.message); + } else { + if (!response.data?.favorites) { + fnctRtn = { sts: 'error', msg: 'No favorites found.' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.favorites = response.data.favorites; + response.data.favorites.forEach((fav) => { + if(!this.categories.includes(fav.category)) { + this.categories.push(fav.category); + } + }) + } + if (debugLog) { + console.log('response from favorite_control_get: ', response); + } + return response.message; + } + }); + break; + default: + fnctRtn = { sts: 'error', msg: 'Invalid command' + command }; + throw new Error('Invalid command' + command); + } + return fnctRtn; + }, + initialize(): void { + this.favoriteControl({ command: 'get' }); + }, + getCategories(): string[] { + this.favoriteControl({ command: 'get' }); + const categories: string[] = []; + this.favorites.forEach((favorite) => { + if (!categories.includes(favorite.category)) { + categories.push(favorite.category); + } + }); + return categories; + }, + }, +}); + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useFavoriteStore, import.meta.hot)); +} diff --git a/src/stores/icloud.ts b/src/stores/icloud.ts new file mode 100644 index 0000000..94f2fda --- /dev/null +++ b/src/stores/icloud.ts @@ -0,0 +1,219 @@ +import { defineStore, acceptHMRUpdate } from 'pinia'; +import { socket } from 'boot/socketio'; +import { useSocketStore } from 'stores/socket'; +import { useQuasar } from 'quasar'; + +import iCloudCodeDialog from 'components/iCloudCodeDialog.vue'; + +import type { FindMyUpdate, icloudData, iCloudMonitorResponse } from 'components/models'; + +const $q = useQuasar(); + + +export const useIcloudStore = defineStore('icloudStore', { + state: () => { + return { + icloudMonitor: false as boolean, + findMyUpdate: null as FindMyUpdate | null | undefined, + consumerQueue: 0 as number | string | boolean, + consumerTask: false as boolean | string, + monitorTask: false as boolean | string, + monitorEnabled: false as boolean, + monitorRunning: false as boolean, + }; + }, + getters: {}, + actions: { + bindEvents() { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + // fmf_update + socket.on('fmf_update', (data: FindMyUpdate): void => { + if (debugLog) { + console.log('event: fmf_update received: ', data); + } + this.findMyUpdate = data; + }); + + // icloud_2fa_request + socket.on('icloud_2fa_request', (callback) => { + if (debugLog) { + console.log('iCloud 2FA Request'); + } + $q.dialog({ + component: iCloudCodeDialog, + }) + .onOk((code: number) => { + if (callback && typeof callback === 'function') { + callback(code); + } + }) + .onCancel(() => { + if (debugLog) { + console.log('Dialog cancelled'); + } + }) + .onDismiss(() => { + if (debugLog) { + console.log('Dialog dismissed'); + } + }); + }); + }, + icloudMonitorControl(command: string) { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; + switch (command) { + case 'start': + if (debugLog) { + console.log('socketStore: got command: icloudMonitor start'); + } + if (this.icloudMonitor) { + fnctRtn = { sts: 'error', msg: 'iCloud Monitor is already running' }; + throw new Error('iCloud Monitor is already running'); + } + if (debugLog) { + console.log('Emitting icloud_monitor_control: start'); + } + socket.emit( + 'icloud_monitor_control', + { command: 'start' }, + (response: iCloudMonitorResponse) => { + fnctRtn.sts = response.command_status; + if (response.command_status == 'ERROR') { + if (response.message) { + if (debugLog) { + console.log(response.message); + } + fnctRtn.msg = response.message; + } else { + fnctRtn.msg = 'Error'; + } + throw new Error(fnctRtn.msg); + } else { + fnctRtn = { sts: 'OK', msg: 'iCloud Monitor: ' + response.command_status }; + this.icloudMonitor = true; + } + }, + ); + break; + case 'stop': + if (debugLog) { + console.log('socketStore: got command: icloudMonitor stop'); + } + if (!this.icloudMonitor) { + fnctRtn = { sts: 'error', msg: 'iCloud Monitor is not running' }; + throw new Error('iCloud Monitor is not running'); + } + if (debugLog) { + console.log('Emitting icloud_monitor_control: stop'); + } + socket.emit( + 'icloud_monitor_control', + { command: 'stop' }, + (response: iCloudMonitorResponse) => { + fnctRtn.sts = response.command_status; + if (response.command_status == 'ERROR') { + if (response.message) { + if (debugLog) { + console.log(response.message); + } + fnctRtn.msg = response.message; + } else { + fnctRtn.msg = 'Error'; + } + throw new Error(fnctRtn.msg); + } else { + fnctRtn = { sts: 'OK', msg: 'iCloud Monitor: ' + response.command_status }; + this.icloudMonitor = false; + } + }, + ); + break; + case 'status': + if (debugLog) { + console.log('socketStore: got command: icloudMonitor status'); + } + socket.emit( + 'icloud_monitor_control', + { command: 'get' }, + (response: iCloudMonitorResponse) => { + fnctRtn.sts = response.command_status; + if (response.command_status == 'error') { + if (response.message) { + if (debugLog) { + console.log(response.message); + } + fnctRtn.msg = response.message; + } else { + fnctRtn.msg = 'Error'; + } + throw new Error(fnctRtn.msg); + } else { + fnctRtn = { + sts: 'OK', + msg: 'iCloud Location Requested', + }; + } + this.icloudMonitor = !!( + response.icloud_monitor_enabled && response.icloud_monitor_running + ); + }, + ); + break; + case 'refresh': + if (debugLog) { + console.log('socketStore: got command: icloudMonitor refresh'); + } + socket.emit( + 'icloud_monitor_control', + { command: 'status' }, + (response: iCloudMonitorResponse) => { + fnctRtn.sts = response.command_status; + if (response.command_status == 'ERROR') { + if (response.message) { + if (debugLog) { + console.log(response.message); + } + fnctRtn.msg = response.message; + } else { + fnctRtn.msg = 'Error'; + } + throw new Error(fnctRtn.msg); + } else { + fnctRtn = { + sts: 'OK', + msg: + 'iCloud Monitor Enabled: ' + + response.icloud_monitor_enabled + + 'iCloud Monitor Running: ' + + response.icloud_monitor_running, + }; + } + this.icloudMonitor = !!( + response.icloud_monitor_enabled && response.icloud_monitor_running + ); + }, + ); + break; + default: + fnctRtn = { sts: 'error', msg: 'Invalid command' }; + throw new Error('Invalid command'); + } + return fnctRtn; + }, + digestUpdate(data: icloudData) { + this.icloudMonitor = data.monitor_running; + this.consumerQueue= data.consumer_queue; + this.consumerTask = data.consumer_task; + this.monitorEnabled = data.monitor_enabled; + this.monitorTask = data.monitor_task; + this.monitorRunning = data.monitor_running; + } + }, +}); + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useIcloudStore, import.meta.hot)); +} diff --git a/src/stores/leaflet.ts b/src/stores/leaflet.ts index a8c9daf..275f4e5 100644 --- a/src/stores/leaflet.ts +++ b/src/stores/leaflet.ts @@ -1,6 +1,12 @@ import { defineStore, acceptHMRUpdate } from 'pinia'; import { favorites } from 'constants/favorites' -import type { RoutesSet, LatLng, routeSegments, routeDirections } from 'components/models'; +import type { + RoutesSet, + LatLng, + routeSegments, + routeDirections, + routeCoordinates, +} from 'components/models'; interface State { zoom: number; @@ -13,8 +19,9 @@ interface State { wayPoints?: LatLng[] | null | undefined; }; routesSet: RoutesSet[] | null; - routeSegments?: routeSegments[] | null; - routeDirections?: routeDirections[] | null; + routeSegments: routeSegments[] | null; + routeDirections: routeDirections[] | null; + routeCoordinates: routeCoordinates[] | null; } export const useLeafletStore = defineStore('leaflet', { @@ -32,6 +39,7 @@ export const useLeafletStore = defineStore('leaflet', { routesSet: [], routeSegments: [], routeDirections: [], + routeCoordinates: [], }; }, actions: { diff --git a/src/stores/simulation.ts b/src/stores/simulation.ts new file mode 100644 index 0000000..6fe4c69 --- /dev/null +++ b/src/stores/simulation.ts @@ -0,0 +1,443 @@ +import { defineStore, acceptHMRUpdate } from 'pinia'; +import { socket } from 'boot/socketio'; +import { useSocketStore } from 'stores/socket'; + +import type { + CurrentLocation, + LocationItemUpdate, + LocationMarkUpdateResponse, + LocationQueue, + NominatimResponse, + QueueData, + SimulationControlResponse, + SimulationStatus, +} from 'components/models'; + + + +export const useSimulationStore = defineStore('simulationStore', { + state: () => { + return { + currentLocation: null as CurrentLocation | null | undefined, + gpsNoise: null as boolean | undefined | null, + locationQueueData: {} as LocationQueue, + locationQueueDeletedItems: [] as string[], + locationQueueOrder: [] as string[], + simulationQueueLength: 0 as number | null | undefined, + simulationRunning: false as boolean | undefined | null, + simulationState: null as string | null | undefined, + testMode: null as boolean | undefined | null, + }; + }, + getters: {}, + actions: { + bindEvents() { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + // simulation_status + socket.on('simulation_status', (data: SimulationStatus): void => { + if (debugLog) { + console.log('event: simulation_status received: ', data); + } + console.log('updating currentLocation', data); + this.currentLocation = { + loc_id: data.loc_id, + latitude: data.latitude, + longitude: data.longitude, + }; + }); + + // queue_data_update + socket.on('queue_data_update', (inData: QueueData): void => { + if (debugLog) { + console.log('QueueUpdate received: ', inData); + } + this.digestQueueUpdate(inData); + }); + // location_item_update + socket.on('location_item_update', (inData: LocationItemUpdate): void => { + console.log('Location item update received, data: ', inData); + this.locationQueueData[inData.loc_id] = inData.data; + }); + }, + simulationControl({ + command, + latitude, + longitude, + loc_id, + delay, + address, + }: { + command: string; + latitude?: number | null | undefined; + longitude?: number | null | undefined; + loc_id?: string | null | undefined; + delay?: number | null | undefined; + address?: NominatimResponse | string | null | undefined; + }) { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; + switch (command) { + case 'start': + if (debugLog) { + console.log('socketStore: got command: start'); + } + if ( + this.simulationRunning || + this.simulationState == 'RUNNING' || + this.simulationState == 'PAUSED' + ) { + fnctRtn = { sts: 'error', msg: 'Simulation is already running' }; + throw new Error('Simulation is already running' + this.simulationState); + } + if (debugLog) { + console.log('Emitting simulation_control: start'); + } + socket.emit( + 'simulation_control', + { command: 'start' }, + (response: SimulationControlResponse) => { + if (response.command_status == 'ERROR') { + fnctRtn = { sts: 'error', msg: response.message?.toString() }; + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_start: ', response); + } + // return response.message; + } + }, + ); + break; + case 'test-mode': + socket.emit( + 'simulation_control', + { command: 'test-mode' }, + (response: SimulationControlResponse) => { + if (response.command_status === 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_test-mode: ', response); + } + return response.message; + } + }, + ); + break; + case 'gps-noise': + socket.emit( + 'simulation_control', + { command: 'gps-noise' }, + (response: SimulationControlResponse) => { + if (response.command_status === 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_gps-noise: ', response); + } + return response.message; + } + }, + ); + break; + case 'pause': + if (this.simulationState !== 'RUNNING') { + throw new Error('Simulation is not running'); + } + socket.emit( + 'simulation_control', + { command: 'pause' }, + (response: SimulationControlResponse) => { + if (response.command_status === 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_pause: ', response); + } + return response.message; + } + }, + ); + break; + case 'resume': + if (this.simulationState !== 'PAUSED') { + throw new Error('Simulation is not paused'); + } + socket.emit('simulation_control', { command: 'resume' }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_resume: ', response); + } + return response.message; + } + }); + break; + case 'clear': + if (this.simulationQueueLength == 0) { + throw new Error('Simulation queue is empty'); + } + socket.emit('simulation_control', { command: 'clear' }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_clear: ', response); + } + return response.message; + } + }); + break; + case 'reset': + if (this.simulationQueueLength == 0) { + throw new Error('Simulation queue is empty'); + } + socket.emit('simulation_control', { command: 'reset' }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_reset: ', response); + } + return response.message; + } + }); + break; + case 'end': + if (this.simulationState == 'ENDED' || !this.simulationRunning) { + throw new Error('Simulation has already ended'); + } + socket.emit('simulation_control', { command: 'end' }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_end: ', response); + } + return response.message; + } + }); + break; + case 'add': + if (!latitude || !longitude) { + throw new Error('latitude or longitude not set'); + } + if (!address) { + address = ''; + } + socket.emit( + 'simulation_control', + { + command: 'add', + latitude: latitude, + longitude: longitude, + delay: delay, + address: address, + }, + (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_add: ', response); + } + return response.message; + } + }, + ); + break; + case 'delete': + if (!loc_id) { + throw new Error('loc_id not set.'); + } + socket.emit('simulation_control', { command: 'delete', loc_id: loc_id }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + if (!response.data?.simulation_queue) { + fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + this.digestQueueUpdate(response.data.simulation_queue); + } + if (debugLog) { + console.log('response from simulate_control_delete: ', response); + } + return response.message; + } + }); + this.updateLocationMark(loc_id, 'status', 'deleted'); + break; + case 'next': + socket.emit('simulation_control', { command: 'next' }, (response) => { + if (response.command_status == 'ERROR') { + throw new Error(response.message); + } else { + this.simulationState = response.data?.simulation_queue?.state; + if (debugLog) { + console.log('response from simulate_control_next: ', response); + } + return response.message; + } + }); + break; + default: + fnctRtn = { sts: 'error', msg: 'Invalid command' }; + throw new Error('Invalid command'); + } + return fnctRtn; + }, + updateLocationMark(loc_id: string, key: string, value: string | number) { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { command_status: string; message: string }; + if (debugLog) { + console.log( + 'socketStore: Update LocationMark request, loc_id: %s, key: %s, new value: %s', + loc_id, + key, + value, + ); + } + if (!this.locationQueueData[loc_id]) { + fnctRtn = { + command_status: 'error', + message: 'Location Id: ' + loc_id + ' is not in the simulation queue', + }; + throw new Error('loc_id ' + loc_id + 'not found'); + } + if (debugLog) { + console.log('Emitting LocationItem Update'); + } + socket.emit( + 'location_item_update', + { loc_id: loc_id, key: key, value: value }, + (response: LocationMarkUpdateResponse) => { + if (response.command_status == 'ERROR') { + fnctRtn = { command_status: 'error', message: response.message?.toString() }; + throw new Error(response.message); + } else { + fnctRtn = { command_status: 'OK', message: response.message?.toString() }; + if (debugLog) { + console.log('response from backend: ', response); + } + this.locationQueueData[loc_id] = response.data; + } + return fnctRtn; + }, + ); + }, + updateLocationQueueOrder(newOrder: string[]) { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { command_status: string; message: string }; + if (debugLog) { + console.log('socketStore: Update Location Queue Order, new order: %s', newOrder); + } + socket.emit('queue_order_update', { newOrder: newOrder }, (response) => { + if (response.command_status == 'ERROR') { + fnctRtn = { command_status: 'error', message: response.message?.toString() }; + throw new Error(response.message); + } else { + fnctRtn = { command_status: 'OK', message: response.message?.toString() }; + if (debugLog) { + console.log('response from queue_order_update: ', response); + } + this.locationQueueOrder = response.data; + } + return fnctRtn; + }); + }, + digestQueueUpdate(data: QueueData): void { + console.log('digesting QueueUpdate: ', data); + this.simulationRunning = data.active; + console.log('Setting SimulationState to %s', data.state); + this.simulationState = data.state; + this.simulationQueueLength = data.order.length; + this.locationQueueData = data.data; + this.locationQueueOrder = data.order; + this.locationQueueDeletedItems = data.deleted_items; + this.testMode = data.test_mode; + this.gpsNoise = data.gps_noise; + }, + digestCurrentLocation(data: CurrentLocation): void { + this.currentLocation = { + loc_id: data.loc_id, + latitude: data.latitude, + longitude: data.longitude, + next_move: data.next_move, + }; + } + }, +}); + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useSimulationStore, import.meta.hot)); +} diff --git a/src/stores/socket.ts b/src/stores/socket.ts new file mode 100644 index 0000000..4aa2eb9 --- /dev/null +++ b/src/stores/socket.ts @@ -0,0 +1,129 @@ +import { defineStore, acceptHMRUpdate } from 'pinia'; +import { socket } from 'boot/socketio'; + +import { useDeviceStore } from 'stores/device'; +import { useIcloudStore } from 'stores/icloud'; +import { useSimulationStore } from 'stores/simulation'; +import { useTunneldStore } from 'stores/tunneld'; + +import type { AppError, ErrorFull, StatusUpdate } from 'components/models'; + + + +export const useSocketStore = defineStore('socketStore', { + state: () => { + return { + sockConnected: false as boolean, + socketID: null as string | null | undefined, + errorList: [] as ErrorFull[], + debugLog: true, + }; + }, + getters: {}, + actions: { + setSockStatus() { + this.sockConnected = socket.connected; + this.socketID = socket.id; + }, + connect() { + if (this.debugLog) { + console.log('Connecting to server...'); + } + socket.connect(); + this.setSockStatus(); + }, + disconnect() { + socket.disconnect(); + this.setSockStatus(); + }, + toggleSock() { + this.setSockStatus(); + if (this.sockConnected) { + socket.disconnect(); + } else { + socket.connect(); + } + this.setSockStatus(); + }, + bindEvents() { + this.setSockStatus(); + + // connect + socket.on('connect', () => { + this.setSockStatus(); + socket.emit('message', 'Hello from client', (e: boolean) => { + if (this.debugLog) { + console.log('Message delivered: ' + e); + } + }); + if (this.debugLog) { + console.log('Connected to server'); + } + }); + + // disconnect + socket.on('disconnect', () => { + this.setSockStatus(); + console.log('Disconnected from server'); + }); + + // error + socket.on('error', (data: ErrorFull) => { + this.setSockStatus(); + const errorFull = { type: data.type, error: data.error }; + this.errorList.push(errorFull); + console.error('Error Received: ', data); + }); + + // app_error + socket.on('app_error', (data: AppError) => { + this.setSockStatus(); + const errorFull = { + type: data.type, + error: data.error, + message: data.message, + data: data.data, + }; + this.errorList.push(errorFull); + console.error('Error Received: ', data); + }); + + // status + socket.on('status', (data: StatusUpdate): void => { + if (this.debugLog) { + console.log('StatusUpdate received: ', data); + } + this.digestUpdate(data); + }); + }, + requestUpdate(): void { + socket.emit('request_update', (response: StatusUpdate) => { + this.digestUpdate(response); + }); + }, + digestUpdate(data: StatusUpdate): void { + const deviceStore = useDeviceStore(); + const icloudStore = useIcloudStore(); + const simulationStore = useSimulationStore(); + const tunneldStore = useTunneldStore(); + if (data.simulation_queue) { + simulationStore.digestQueueUpdate(data.simulation_queue); + } + deviceStore.deviceConnected = !!(data.udid && data.tunnel); + if (data.current_location) { + simulationStore.digestCurrentLocation(data.current_location); + } + tunneldStore.tunnelConnected = !!data.tunnel; + tunneldStore.tunneldWatcher = data.tunnel_watcher_running; + if (data.icloud) { + icloudStore.digestUpdate(data.icloud); + } + icloudStore.findMyUpdate = data.fmf_location; + + }, + }, +}); + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useSocketStore, import.meta.hot)); +} diff --git a/src/stores/socketio.ts b/src/stores/socketio.ts index 87f98fa..e45af7f 100644 --- a/src/stores/socketio.ts +++ b/src/stores/socketio.ts @@ -1,54 +1,24 @@ import { defineStore, acceptHMRUpdate } from 'pinia'; -import { socket } from 'boot/socketio'; -import { useQuasar } from 'quasar'; -import iCloudCodeDialog from 'components/iCloudCodeDialog.vue'; -import type { - CurrentLocation, - NextLocation, - ErrorFull, - LocationQueue, - SimulationControlResponse, - StatusUpdate, - FindMyUpdate, - iCloudMonitorResponse, - SimulationStatus, - LocationMarkUpdateResponse, - LocationItemUpdate, - NominatimResponse, - NominatimRequest, - AppError, - QueueData, -} from 'components/models'; -const $q = useQuasar(); -const debugLog: boolean = true; + + + export const useSocketioStore = defineStore('socketio', { state: () => { return { - sockConnected: false as boolean, - socketID: null as string | null | undefined, - testMode: null as boolean | undefined | null, - gpsNoise: null as boolean | undefined | null, - deviceConnected: false as boolean, - tunnelConnected: false as boolean, - simulationRunning: false as boolean | undefined | null, - simulationState: null as string | null | undefined, - simulationQueueLength: 0 as number | null | undefined, - currentLocation: null as CurrentLocation | null | undefined, - nextLocation: null as NextLocation | null, - messageList: [''] as string[], - errorList: [] as ErrorFull[], - locationQueueData: {} as LocationQueue, - locationQueueOrder: [] as string[], - locationQueueDeletedItems: [] as string[], + + + +// nextLocation: null as NextLocation | null, +// messageList: [''] as string[], + leafletZoom: 10 as number, - icloudMonitor: false as boolean, - findMyUpdate: null as FindMyUpdate | null | undefined, + }; }, getters: { - sockState: (state) => state.sockConnected, +/* sockState: (state) => state.sockConnected, deviceState: (state) => state.deviceConnected, lMarkerLatLng: (state): [number, number] => { if ( @@ -64,687 +34,27 @@ export const useSocketioStore = defineStore('socketio', { return this.lMarkerLatLng; }, lZoom: (state): number => state.leafletZoom, + */ + }, actions: { - setSockStatus() { - this.sockConnected = socket.connected; - this.socketID = socket.id; - }, - bindEvents() { - this.setSockStatus(); - // connect - socket.on('connect', () => { - this.setSockStatus(); - socket.emit('message', 'Hello from client', (e: boolean) => { - if (debugLog) { - console.log('Message delivered: ' + e); - } - }); - if (debugLog) { - console.log('Connected to server'); - } - }); - // disconnect - socket.on('disconnect', () => { - this.setSockStatus(); - console.log('Disconnected from server'); - }); - // message - socket.on('message', (e: string) => { - this.setSockStatus(); - this.messageList.push(e); - if (debugLog) { - console.log('Websock message received!'); - } - }); - // error - socket.on('error', (data: ErrorFull) => { - this.setSockStatus(); - const errorFull = { type: data.type, error: data.error }; - this.errorList.push(errorFull); - console.error('Error Received: ', data); - }); - // app_error - socket.on('app_error', (data: AppError) => { - this.setSockStatus(); - const errorFull = { type: data.type, error: data.error, message: data.message, data: data.data }; - this.errorList.push(errorFull); - console.error('Error Received: ', data); - }); - // status - socket.on('status', (data: StatusUpdate): void => { - if (debugLog) { - console.log('StatusUpdate received: ', data); - } - this.digestUpdate(data); - }); - // fmf_update - socket.on('fmf_update', (data: FindMyUpdate): void => { - if (debugLog) { - console.log('event: fmf_update received: ', data); - } - this.findMyUpdate = data; - }); - // simulation_status - socket.on('simulation_status', (data: SimulationStatus): void => { - if (debugLog) { - console.log('event: simulation_status received: ', data); - } - console.log('updating currentLocation', data); - this.currentLocation = { - loc_id: data.loc_id, - latitude: data.latitude, - longitude: data.longitude - }; - }); - // icloud_2fa_request - socket.on('icloud_2fa_request', (callback) => { - if (debugLog) { - console.log('iCloud 2FA Request'); - } - $q.dialog({ - component: iCloudCodeDialog, - }) - .onOk((code: number) => { - if (callback && typeof callback === 'function') { - callback(code); - } - }) - .onCancel(() => { - if (debugLog) { - console.log('Dialog cancelled'); - } - }) - .onDismiss(() => { - if (debugLog) { - console.log('Dialog dismissed'); - } - }); - }); - // queue_data_update - socket.on('queue_data_update', (inData: QueueData): void => { - if (debugLog) { - console.log('QueueUpdate received: ', inData); - } - this.digestQueueUpdate(inData); - }); - // location_item_update - socket.on('location_item_update', (inData: LocationItemUpdate): void => { - console.log('Location item update received, data: ', inData); - this.locationQueueData[inData.loc_id] = inData.data; - }); - /* - socket.onAny((eventName, ...args) => { - console.log('Event received: ', eventName, ' Args: ', args, ''); - if (serverToClientKnownEvents.includes(eventName)) { - console.log('Known event received: ', eventName, ' Args: ', args, ''); - } else { - console.log( - 'Known events: ', - serverToClientKnownEvents, - ' Received Event: ', - eventName, - ' Args: ', - args, - '', - ); - console.log(`Received UNKNOWN Event: ${eventName}`, args); - } - }); - */ - }, - connect() { - if (debugLog) { - console.log('Connecting to server...'); - } - socket.connect(); - this.setSockStatus(); - }, - disconnect() { - socket.disconnect(); - this.setSockStatus(); - }, - toggleSock() { - this.setSockStatus(); - if (this.sockConnected) { - socket.disconnect(); - } else { - socket.connect(); - } - this.setSockStatus(); - }, - setSimulationRunning(isRunning: boolean, states: string): void { - this.setSockStatus(); - this.simulationState = states; - this.simulationRunning = isRunning; - }, - icloudMonitorControl(command: string) { - let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; - switch (command) { - case 'start': - if (debugLog) { - console.log('socketStore: got command: icloudMonitor start'); - } - if (this.icloudMonitor) { - fnctRtn = { sts: 'error', msg: 'iCloud Monitor is already running' }; - throw new Error('iCloud Monitor is already running'); - } - if (debugLog) { - console.log('Emitting icloud_monitor_control: start'); - } - socket.emit( - 'icloud_monitor_control', - { command: 'start' }, - (response: iCloudMonitorResponse) => { - fnctRtn.sts = response.command_status; - if (response.command_status == 'ERROR') { - if (response.message) { - if (debugLog) { - console.log(response.message); - } - fnctRtn.msg = response.message; - } else { - fnctRtn.msg = 'Error'; - } - throw new Error(fnctRtn.msg); - } else { - fnctRtn = { sts: 'OK', msg: 'iCloud Monitor: ' + response.command_status }; - this.icloudMonitor = true; - } - }, - ); - break; - case 'stop': - if (debugLog) { - console.log('socketStore: got command: icloudMonitor stop'); - } - if (!this.icloudMonitor) { - fnctRtn = { sts: 'error', msg: 'iCloud Monitor is not running' }; - throw new Error('iCloud Monitor is not running'); - } - if (debugLog) { - console.log('Emitting icloud_monitor_control: stop'); - } - socket.emit( - 'icloud_monitor_control', - { command: 'stop' }, - (response: iCloudMonitorResponse) => { - fnctRtn.sts = response.command_status; - if (response.command_status == 'ERROR') { - if (response.message) { - if (debugLog) { - console.log(response.message); - } - fnctRtn.msg = response.message; - } else { - fnctRtn.msg = 'Error'; - } - throw new Error(fnctRtn.msg); - } else { - fnctRtn = { sts: 'OK', msg: 'iCloud Monitor: ' + response.command_status }; - this.icloudMonitor = false; - } - }, - ); - break; - case 'status': - if (debugLog) { - console.log('socketStore: got command: icloudMonitor status'); - } - socket.emit( - 'icloud_monitor_control', - { command: 'get' }, - (response: iCloudMonitorResponse) => { - fnctRtn.sts = response.command_status; - if (response.command_status == 'error') { - if (response.message) { - if (debugLog) { - console.log(response.message); - } - fnctRtn.msg = response.message; - } else { - fnctRtn.msg = 'Error'; - } - throw new Error(fnctRtn.msg); - } else { - fnctRtn = { - sts: 'OK', - msg: 'iCloud Location Requested', - }; - } - this.icloudMonitor = !!( - response.icloud_monitor_enabled && response.icloud_monitor_running - ); - }, - ); - break; - case 'refresh': - if (debugLog) { - console.log('socketStore: got command: icloudMonitor refresh'); - } - socket.emit( - 'icloud_monitor_control', - { command: 'status' }, - (response: iCloudMonitorResponse) => { - fnctRtn.sts = response.command_status; - if (response.command_status == 'ERROR') { - if (response.message) { - if (debugLog) { - console.log(response.message); - } - fnctRtn.msg = response.message; - } else { - fnctRtn.msg = 'Error'; - } - throw new Error(fnctRtn.msg); - } else { - fnctRtn = { - sts: 'OK', - msg: - 'iCloud Monitor Enabled: ' + - response.icloud_monitor_enabled + - 'iCloud Monitor Running: ' + - response.icloud_monitor_running, - }; - } - this.icloudMonitor = !!( - response.icloud_monitor_enabled && response.icloud_monitor_running - ); - }, - ); - break; - default: - fnctRtn = { sts: 'error', msg: 'Invalid command' }; - throw new Error('Invalid command'); - } - return fnctRtn; - }, - simulationControl({ - command, - latitude, - longitude, - loc_id, - delay, - address, - }: { - command: string; - latitude?: number | null | undefined; - longitude?: number | null | undefined; - loc_id?: string | null | undefined; - delay?: number | null | undefined; - address?: string | null | undefined; - }) { - let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; - this.setSockStatus(); - switch (command) { - case 'start': - if (debugLog) { - console.log('socketStore: got command: start'); - } - if ( - this.simulationRunning || - this.simulationState == 'RUNNING' || - this.simulationState == 'PAUSED' - ) { - fnctRtn = { sts: 'error', msg: 'Simulation is already running' }; - throw new Error('Simulation is already running' + this.simulationState); - } - if (debugLog) { - console.log('Emitting simulation_control: start'); - } - socket.emit( - 'simulation_control', - { command: 'start', delay: 0, latitude: null, longitude: null }, - (response: SimulationControlResponse) => { - if (response.command_status == 'ERROR') { - fnctRtn = { sts: 'error', msg: response.message?.toString() }; - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: "Simulation queue data missing"}; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_start: ', response); - } - // return response.message; - } - }, - ); - break; - case 'test-mode': - socket.emit( - 'simulation_control', - { command: 'test-mode' }, - (response: SimulationControlResponse) => { - if (response.command_status === 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_test-mode: ', response); - } - return response.message; - } - }, - ); - break; - case 'gps-noise': - socket.emit( - 'simulation_control', - { command: 'gps-noise' }, - (response: SimulationControlResponse) => { - if (response.command_status === 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_gps-noise: ', response); - } - return response.message; - } - }, - ); - break; - case 'pause': - if (this.simulationState !== 'RUNNING') { - throw new Error('Simulation is not running'); - } - socket.emit( - 'simulation_control', - { command: 'pause' }, - (response: SimulationControlResponse) => { - if (response.command_status === 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_pause: ', response); - } - return response.message; - } - }, - ); - break; - case 'resume': - if (this.simulationState !== 'PAUSED') { - throw new Error('Simulation is not paused'); - } - socket.emit('simulation_control', { command: 'resume' }, (response) => { - if (response.command_status == 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_resume: ', response); - } - return response.message; - } - }); - break; - case 'clear': - if (this.simulationQueueLength == 0) { - throw new Error('Simulation queue is empty'); - } - socket.emit('simulation_control', { command: 'clear' }, (response) => { - if (response.command_status == 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_clear: ', response); - } - return response.message; - } - }); - break; - case 'end': - if (this.simulationState == 'ENDED' || !this.simulationRunning) { - throw new Error('Simulation has already ended'); - } - socket.emit('simulation_control', { command: 'end' }, (response) => { - if (response.command_status == 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_end: ', response); - } - return response.message; - } - }); - break; - case 'add': - if (!latitude || !longitude) { - throw new Error('latitude or longitude not set'); - } - if (!address) { - address = '{latitude}, {longitude}'; - } - socket.emit( - 'simulation_control', - { - command: 'add', - latitude: latitude, - longitude: longitude, - delay: delay, - address: address, - }, - (response) => { - if (response.command_status == 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_add: ', response); - } - return response.message; - } - }, - ); - break; - case 'delete': - if (!loc_id) { - throw new Error('loc_id not set.'); - } - socket.emit('simulation_control', { command: 'delete', loc_id: loc_id }, (response) => { - if (response.command_status == 'ERROR') { - throw new Error(response.message); - } else { - if (!response.data?.simulation_queue) { - fnctRtn = { sts: 'error', msg: 'Simulation queue data missing' }; - throw new Error(response.message); - } else { - fnctRtn = { sts: 'OK', msg: response.message?.toString() }; - this.digestQueueUpdate(response.data.simulation_queue); - } - if (debugLog) { - console.log('response from simulate_control_delete: ', response); - } - return response.message; - } - }); - this.updateLocationMark(loc_id, 'status', 'deleted'); - break; - case 'next': - socket.emit('simulation_control', { command: 'next' }, (response) => { - if (response.command_status == 'ERROR') { - throw new Error(response.message); - } else { - this.simulationState = response.data?.simulation_queue?.state; - if (debugLog) { - console.log('response from simulate_control_next: ', response); - } - return response.message; - } - }); - break; - default: - fnctRtn = { sts: 'error', msg: 'Invalid command' }; - throw new Error('Invalid command'); - } - return fnctRtn; - }, - requestUpdate(): void { - socket.emit('request_update', (response: StatusUpdate) => { - this.digestUpdate(response); - }); - }, - digestQueueUpdate(data: QueueData): void { - console.log("digesting QueueUpdate: ", data) - this.simulationRunning = data.active; - console.log("Setting SimulationState to %s", data.state) - this.simulationState = data.state; - this.simulationQueueLength = data.order.length; - this.locationQueueData = data.data; - this.locationQueueOrder = data.order; - this.locationQueueDeletedItems = data.deleted_items; - this.testMode = data.test_mode; - this.gpsNoise = data.gps_noise; - }, - digestUpdate(data: StatusUpdate): void { - if (data.simulation_queue) { - this.digestQueueUpdate(data.simulation_queue) - } - this.deviceConnected = !!(data.udid && data.tunnel); - this.tunnelConnected = !!data.tunnel; - this.icloudMonitor = data.icloud.monitor_enabled; - this.currentLocation = { - loc_id: data.current_location.loc_id, - latitude: data.current_location.latitude, - longitude: data.current_location.longitude, - next_move: data.next_move, - }; - this.findMyUpdate = data.fmf_location; - }, - setDeviceState(state: boolean) { - this.deviceConnected = state; - }, - revGeoCode(nomRequest: NominatimRequest): Promise { - return new Promise((resolve) => { - socket.emit( - 'reverse_geocode', - { latitude: nomRequest.latitude, longitude: nomRequest.longitude }, - (response) => { - resolve(response); - }, - ); - }); - }, - updateLocationMark(loc_id: string, key: string, value: string | number) { - let fnctRtn: { command_status: string; message: string }; - if (debugLog) { - console.log( - 'socketStore: Update LocationMark request, loc_id: %s, key: %s, new value: %s', - loc_id, - key, - value, - ); - } - if (!this.locationQueueData[loc_id]) { - fnctRtn = { - command_status: 'error', - message: 'Location Id: ' + loc_id + ' is not in the simulation queue', - }; - throw new Error('loc_id ' + loc_id + 'not found'); - } - if (debugLog) { - console.log('Emitting LocationItem Update'); - } - socket.emit( - 'location_item_update', - { loc_id: loc_id, key: key, value: value }, - (response: LocationMarkUpdateResponse) => { - if (response.command_status == 'ERROR') { - fnctRtn = { command_status: 'error', message: response.message?.toString() }; - throw new Error(response.message); - } else { - fnctRtn = { command_status: 'OK', message: response.message?.toString() }; - if (debugLog) { - console.log('response from backend: ', response); - } - this.locationQueueData[loc_id] = response.data; - } - return fnctRtn; - }, - ); - }, - updateLocationQueueOrder(newOrder: string[]) { - let fnctRtn: { command_status: string; message: string }; - if (debugLog) { - console.log('socketStore: Update Location Queue Order, new order: %s', newOrder); - } - socket.emit('queue_order_update', { newOrder: newOrder }, (response) => { - if (response.command_status == 'ERROR') { - fnctRtn = { command_status: 'error', message: response.message?.toString() }; - throw new Error(response.message); - } else { - fnctRtn = { command_status: 'OK', message: response.message?.toString() }; - if (debugLog) { - console.log('response from queue_order_update: ', response); - } - this.locationQueueOrder = response.data; - } - return fnctRtn; - }); - }, + + + + + }, }); diff --git a/src/stores/tunneld.ts b/src/stores/tunneld.ts new file mode 100644 index 0000000..94af540 --- /dev/null +++ b/src/stores/tunneld.ts @@ -0,0 +1,48 @@ +import { defineStore, acceptHMRUpdate } from 'pinia'; +import type { TunneldCommands } from 'components/models'; +import { useSocketStore } from 'stores/socket'; +import { socket } from 'boot/socketio'; + +export const useTunneldStore = defineStore('tunneldStore', { + state: () => { + return { + tunnelConnected: false as boolean, + tunneldWatcher: false as boolean, + }; + }, + getters: {}, + actions: { + digestUpdate(data: boolean) { + this.tunnelConnected = data; + }, + tunneldControl(command: TunneldCommands, udid: string = '') { + const socketStore = useSocketStore(); + const debugLog = socketStore.debugLog; + let fnctRtn: { sts: string; msg?: string | undefined } = { sts: '', msg: '' }; + if (debugLog) { + console.log('tunneldStore: got command: ', command); + } + let args: {command: TunneldCommands, udid?: string} = {command: command}; + if (udid != '') { + args = { command: command, udid: udid }; + } + socket.emit( + 'tunneld_control', args, (response) => { + console.log(response.command_status, response.command); + if (response.command_status == 'ERROR') { + fnctRtn = { sts: 'error', msg: response.message?.toString() }; + throw new Error(response.message); + } else { + fnctRtn = { sts: 'OK', msg: response.message?.toString() }; + } + }, + ); + return fnctRtn; + } + } +}); + + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useTunneldStore, import.meta.hot)); +}