diff --git a/package-lock.json b/package-lock.json
index a0078a9..fe497d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,9 +13,11 @@
"@vue-leaflet/vue-leaflet": "^0.10.1",
"axios": "^1.2.1",
"leaflet": "^1.9.4",
+ "leaflet-contextmenu": "^1.4.0",
"leaflet-extra-markers": "^2.0.1",
"leaflet-geosearch": "^4.2.2",
"leaflet-routing-machine": "^3.2.12",
+ "openrouteservice-js": "^0.4.1",
"pinia": "^3.0.4",
"quasar": "^2.16.0",
"socket.io-client": "^4.8.3",
@@ -26,6 +28,7 @@
"@eslint/js": "^9.14.0",
"@quasar/app-vite": "^2.1.0",
"@types/leaflet": "^1.9.21",
+ "@types/leaflet-contextmenu": "^1.4.4",
"@types/node": "^20.5.9",
"@vue/eslint-config-prettier": "^10.1.0",
"@vue/eslint-config-typescript": "^14.4.0",
@@ -2097,11 +2100,20 @@
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz",
"integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==",
"devOptional": true,
- "license": "MIT",
"dependencies": {
"@types/geojson": "*"
}
},
+ "node_modules/@types/leaflet-contextmenu": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/@types/leaflet-contextmenu/-/leaflet-contextmenu-1.4.4.tgz",
+ "integrity": "sha512-3BcUZceTEHDOu2kD6Is5cQB5z/DIVMPZoN/o5yXGrH0Y4CfWuSpP1Sm6ZHdBMQ+nVtEQXZnIV/GOE4ZEGX39HQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/leaflet": "^1.9"
+ }
+ },
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
@@ -5748,6 +5760,11 @@
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
"license": "BSD-2-Clause"
},
+ "node_modules/leaflet-contextmenu": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/leaflet-contextmenu/-/leaflet-contextmenu-1.4.0.tgz",
+ "integrity": "sha512-BXASCmJ5bLkuJGDCpWmvGqhZi5AzeOY0IbQalfkgBcMAMfAOFSvD4y0gIQxF/XzEyLkjXaRiUpibVj4+Cf3tUA=="
+ },
"node_modules/leaflet-extra-markers": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/leaflet-extra-markers/-/leaflet-extra-markers-2.0.1.tgz",
@@ -6301,6 +6318,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/openrouteservice-js": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/openrouteservice-js/-/openrouteservice-js-0.4.1.tgz",
+ "integrity": "sha512-Oeb/KgzaYXEtafSHB40KfZvHFfTSPhtt0/oEf0jv5o5Ljw3//+C63CFxbknOqDBrOkYLLQMMCjJGa54rUOBtLg=="
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
diff --git a/package.json b/package.json
index 814627e..4217d43 100644
--- a/package.json
+++ b/package.json
@@ -19,9 +19,11 @@
"@vue-leaflet/vue-leaflet": "^0.10.1",
"axios": "^1.2.1",
"leaflet": "^1.9.4",
+ "leaflet-contextmenu": "^1.4.0",
"leaflet-extra-markers": "^2.0.1",
"leaflet-geosearch": "^4.2.2",
"leaflet-routing-machine": "^3.2.12",
+ "openrouteservice-js": "^0.4.1",
"pinia": "^3.0.4",
"quasar": "^2.16.0",
"socket.io-client": "^4.8.3",
@@ -32,6 +34,7 @@
"@eslint/js": "^9.14.0",
"@quasar/app-vite": "^2.1.0",
"@types/leaflet": "^1.9.21",
+ "@types/leaflet-contextmenu": "^1.4.4",
"@types/node": "^20.5.9",
"@vue/eslint-config-prettier": "^10.1.0",
"@vue/eslint-config-typescript": "^14.4.0",
diff --git a/quasar.config.ts b/quasar.config.ts
index 424e67f..c77270e 100644
--- a/quasar.config.ts
+++ b/quasar.config.ts
@@ -70,14 +70,30 @@ export default defineConfig((/* ctx */) => {
extendViteConf() {
return {
+ build: {
+ rollupOptions: {
+ output: {
+ manualChunks(id) {
+ if (id.includes('node_modules/leaflet')) return 'vendor-leaflet-core';
+ if (id.includes('leaflet-routing-machine')) return 'vendor-leaflet-routing';
+ if (id.includes('leaflet-geosearch')) return 'vendor-leaflet-geosearch';
+ if (id.includes('leaflet-extra-markers')) return 'vendor-leaflet-markers';
+ if (id.includes('openrouteservice-js')) return 'vendor-openrouteservice';
+ if (id.includes('socket.io-client')) return 'vendor-socketio';
+ if (id.includes('node_modules/quasar')) return 'vendor-quasar';
+ if (id.includes('node_modules/vue') || id.includes('node_modules/pinia')) {
+ return 'vendor-vue-core';
+ }
+ return undefined;
+ },
+ },
+ },
+ },
server: {
hmr: {
-// overlay: false,
+ // overlay: false,
},
- allowedHosts: [
- 'localhost',
- 'strixx.famor.org'
- ],
+ allowedHosts: ['localhost', 'strixx.famor.org', 'simloc.strixx.intrepidnet.org'],
},
};
},
@@ -102,7 +118,7 @@ export default defineConfig((/* ctx */) => {
devServer: {
// https: true,
open: false, // opens browser window automatically
- // public: 'http://strixx.famor.org:9000',
+ // public: 'https://simloc.strixx.intrepidnet.org',
proxy: {
// proxy all requests starting with /api to jsonplaceholder
'/api': {
@@ -118,9 +134,27 @@ export default defineConfig((/* ctx */) => {
changeOrigin: true,
// rewrite: (path) => path.replace(/^\/socket.io/, ''),
},
+ '/osm': {
+ target: 'https://nominatim.openstreetmap.org',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/osm/, ''),
+ headers: {
+ Referer: 'https://nominatim.openstreetmap.org/',
+ 'User-Agent': 'map-sim-location/0.0.1 (iam@williambr.uno)',
+ },
+ },
+ '/ors': {
+// target: 'https://router.project-osrm.org',
+ target: 'http://localhost:8080',
+ changeOrigin: true,
+// rewrite: (path) => path.replace(/^\/osrm/, ''),
+// headers: {
+// Referer: 'https://router.project-osrm.org/',
+// 'User-Agent': 'map-sim-location/0.0.1 (iam@williambr.uno)',
+// },
+ },
},
},
-
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#framework
framework: {
config: {
diff --git a/src/boot/axios.ts b/src/boot/axios.ts
index a2b7d07..a36b1c5 100644
--- a/src/boot/axios.ts
+++ b/src/boot/axios.ts
@@ -5,16 +5,19 @@ declare module 'vue' {
interface ComponentCustomProperties {
$axios: AxiosInstance;
$api: AxiosInstance;
+ $osm: AxiosInstance;
}
}
const api = axios.create({ baseURL: '/api' });
+const osm = axios.create({ baseURL: '/osm' });
export default defineBoot(({ app }) => {
app.config.globalProperties.$axios = axios
app.config.globalProperties.$api = api
+ app.config.globalProperties.$osm = osm
})
-export { axios, api };
+export { axios, api, osm };
diff --git a/src/components/ConfirmCommandDiaglog.vue b/src/components/ConfirmCommandDiaglog.vue
index c24639c..607cbae 100644
--- a/src/components/ConfirmCommandDiaglog.vue
+++ b/src/components/ConfirmCommandDiaglog.vue
@@ -18,7 +18,7 @@
@@ -339,4 +500,8 @@ onMounted(() => {
.q-item.q-router-link--active, .q-item--active
background-color: $accent
color: $primary
+
+.leafletDrawer
+ background-color: $dark
+ color: $dark
diff --git a/src/components/LocationMark.vue b/src/components/LocationMark.vue
index 416a869..a19215b 100644
--- a/src/components/LocationMark.vue
+++ b/src/components/LocationMark.vue
@@ -4,7 +4,7 @@ import { useSocketioStore } from 'stores/socketio';
import { computed, onMounted, onUnmounted, ref } from 'vue';
const socketStore = useSocketioStore();
-const { currentLocation, locationQueueOrder } = storeToRefs(socketStore);
+const { currentLocation, locationQueueOrder, simulationRunning } = storeToRefs(socketStore);
const props = defineProps({
address: {
@@ -43,6 +43,10 @@ const props = defineProps({
type: String,
required: true,
},
+ isLast: {
+ type: Boolean,
+ default: false,
+ },
});
// Define custom events that this component can emit
@@ -100,6 +104,16 @@ const calculateDeltaT = computed(() => {
return delta;
});
+const secondsToTime = computed(() => {
+ const seconds = props.delay;
+ const hours = Math.floor(seconds / 3600);
+ const minutes = Math.floor((seconds % 3600) / 60);
+ const remainingSeconds = seconds % 60;
+ return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds
+ .toString()
+ .padStart(2, '0')}`;
+});
+
const humanReadableDateTime = (iso: string) => {
return new Date(iso).toLocaleDateString('en-US', {
// year: 'numeric',
@@ -181,6 +195,24 @@ function formatAddress(input: string): string {
return `${streetNumber} ${streetName}, ${city}, ${state} ${zip}`;
}
+const markerIndex = computed(() => {
+ const currentIndex = currentLocation.value
+ ? locationQueueOrder.value.indexOf(currentLocation.value.loc_id)
+ : 0;
+ const locationIndex = locationQueueOrder.value.indexOf(props.loc_id);
+ return props.active ? '*' : (locationIndex - currentIndex).toString();
+});
+
+const itemClass = computed(() => {
+ const currentIndex = currentLocation.value
+ ? locationQueueOrder.value.indexOf(currentLocation.value.loc_id)
+ : 0;
+ const locationIndex = locationQueueOrder.value.indexOf(props.loc_id);
+ if (locationIndex - currentIndex > 0) return 'future';
+ else if (locationIndex - currentIndex < 0) return 'past';
+ else return 'active';
+});
+
onMounted(() => {
const update = () => {
currentTime.value = new Date();
@@ -195,32 +227,35 @@ onUnmounted(() => {
-
+
{{ formatAddress(address) }}
{{ latitude }}, {{ longitude }}
-
+
start: {{ humanReadableDateTime(start) }}
-
+
end: {{ humanReadableDateTime(end) }}
-
+
{{ calculateDeltaT }}
+ delay: {{ secondsToTime }} seconds
- {{
- active ? '*' : locationQueueOrder.indexOf(loc_id)
- }}
+ {{ markerIndex }}
+
-
+
diff --git a/src/components/MenuBar.vue b/src/components/MenuBar.vue
index 231ea5e..4d54ad2 100644
--- a/src/components/MenuBar.vue
+++ b/src/components/MenuBar.vue
@@ -1,6 +1,6 @@
+
diff --git a/src/components/SimulationCommands.ts b/src/components/SimulationCommands.ts
index 272c56b..cb0ff5c 100644
--- a/src/components/SimulationCommands.ts
+++ b/src/components/SimulationCommands.ts
@@ -1 +1 @@
-import { socket } from 'boot/socketio';
+export {};
diff --git a/src/components/SocketTest.vue b/src/components/SocketTest.vue
index 5fd3ced..dc4dc6a 100644
--- a/src/components/SocketTest.vue
+++ b/src/components/SocketTest.vue
@@ -4,6 +4,7 @@ import { useQuasar } from 'quasar';
import { computed, ref, watch } from 'vue';
import { useSocketioStore } from 'stores/socketio';
import { storeToRefs } from 'pinia';
+import type { ClientToServerEvents } from 'components/models';
const socketioStore = useSocketioStore();
const $q = useQuasar();
@@ -30,18 +31,17 @@ function sendMessage() {
function handleEmit() {
const event = sockEvent.value;
const jsonArgs = eventArgs.value;
- socket.emit(event, jsonArgs, (resp) => {
- console.log('Server Reponse: ' + resp);
+ socket.emit(event as keyof ClientToServerEvents, jsonArgs, (resp: unknown) => {
+ console.log('Server Reponse: ' + String(resp));
});
sockEvent.value = '';
eventArgs.value = '';
-};
+}
watch(
messageList,
(newVal: string[], oldVal: string[]) => {
- let newMsg: string;
- newMsg = newVal[newVal.length - 1];
+ const newMsg = newVal[newVal.length - 1] ?? '';
console.log('New message received: ', newMsg);
console.log('Past List', oldVal);
$q.notify(newMsg);
diff --git a/src/components/StatusBar.vue b/src/components/StatusBar.vue
index 058c1c7..a5abd52 100644
--- a/src/components/StatusBar.vue
+++ b/src/components/StatusBar.vue
@@ -9,8 +9,6 @@ const {
tunnelConnected,
simulationRunning,
icloudMonitor,
- currentLocation,
- nextLocation,
} = storeToRefs(socketioStore);
function statusDevColor(state: string | boolean): string {
if (typeof state === 'boolean') {
@@ -56,7 +54,7 @@ function statusDevColor(state: string | boolean): string {
void;
}
-interface SimulationStatus {
+export interface SimulationStatus {
+ loc_id: string;
status: boolean;
- data: {
- latitude: number;
- longitude: number;
- start: string;
- end?: string;
- next_move?: number;
- };
+ latitude: number;
+ longitude: number;
+ start: string;
+ end?: string;
+ next_move?: number;
}
export interface StatusUpdate {
@@ -256,3 +255,36 @@ export interface NextLocation {
}
+
+export interface NominatimReverseResponse {
+ place_id: number
+ licence: string
+ osm_type: string
+ osm_id: number
+ lat: string
+ lon: string
+ class: string
+ type: string
+ place_rank: number
+ importance: number
+ addresstype: string
+ name: string
+ display_name: string
+ address: NominatimAddress
+ boundingbox: string[]
+}
+
+export interface NominatimAddress {
+ house_number: string;
+ road: string;
+ village?: string;
+ city? : string;
+ county: string;
+ state: string;
+ 'ISO3166-2-lvl4': string;
+ postcode: string;
+ country: string;
+ country_code: string;
+}
+
+
diff --git a/src/composables/useMarkerContextMenu.ts b/src/composables/useMarkerContextMenu.ts
new file mode 100644
index 0000000..3e37b84
--- /dev/null
+++ b/src/composables/useMarkerContextMenu.ts
@@ -0,0 +1,45 @@
+import { ref, type Ref } from 'vue';
+import * as LeafLet from 'leaflet';
+import type { LeafletMouseEvent } from 'leaflet';
+
+type RouteSet = {
+ start?: LeafLet.LatLng | null | undefined;
+ end?: LeafLet.LatLng | null | undefined;
+};
+
+type RouteSetLike = {
+ start?: unknown;
+ end?: unknown;
+ [key: string]: unknown;
+};
+
+export function useMarkerContextMenu(routeSet: Ref, updateRoute: () => void) {
+ const clickedLatLng = ref(null);
+
+ const handleMarkerClick = (event: LeafletMouseEvent) => {
+ console.log('marker clicked', event);
+ clickedLatLng.value = event.latlng;
+ LeafLet.DomEvent.stopPropagation(event.originalEvent);
+ };
+
+ const setStartRoute = () => {
+ if (!clickedLatLng.value) return;
+ (routeSet.value as RouteSet).start = clickedLatLng.value;
+ console.log('setStartRoute: ', routeSet.value.start);
+ };
+
+ const setEndRoute = () => {
+ if (!clickedLatLng.value) return;
+ (routeSet.value as RouteSet).end = clickedLatLng.value;
+ console.log('setEndRoute: ', routeSet.value.end);
+ updateRoute();
+ console.log('updating Route');
+ };
+
+ return {
+ clickedLatLng,
+ handleMarkerClick,
+ setStartRoute,
+ setEndRoute,
+ };
+}
diff --git a/src/composables/useRoutingEvents.ts b/src/composables/useRoutingEvents.ts
new file mode 100644
index 0000000..a8b2ec4
--- /dev/null
+++ b/src/composables/useRoutingEvents.ts
@@ -0,0 +1,54 @@
+import { useLeafletStore } from 'stores/leaflet';
+import { storeToRefs } from 'pinia';
+
+const leafletStore = useLeafletStore();
+const { routeSegments } = storeToRefs(leafletStore);
+
+
+type RouteSummary = {
+ totalDistance: number;
+ totalTime: number;
+};
+
+type RouteWaypoint = {
+ latLng: {
+ lat: number;
+ lng: number;
+ };
+};
+
+type RouteResult = {
+ summary?: RouteSummary;
+ segments?: RouteSummary[];
+ inputWaypoints?: RouteWaypoint[];
+};
+
+export function useRoutingEvents() {
+ const handleRoutesFound = (event: { routes?: RouteResult[] }) => {
+ const route = event.routes?.[0];
+ console.log('routesfound event:', event);
+ if (!route) {
+ return;
+ }
+
+ if (route.summary) {
+ console.log('Route summary:', route.summary);
+ }
+
+ if (route.segments?.length) {
+ const segmentSummary = route.segments.map((segment, index) => ({
+ fromWaypoint: index,
+ toWaypoint: index + 1,
+ distanceMeters: segment.totalDistance,
+ timeSeconds: segment.totalTime,
+ toCoordinates: route.inputWaypoints?.[index + 1]?.latLng ?? null,
+ }));
+ routeSegments.value = segmentSummary;
+ console.log('Waypoint segment summary:', segmentSummary);
+ }
+ };
+
+ return {
+ handleRoutesFound,
+ };
+}
diff --git a/src/constants/controls.ts b/src/constants/controls.ts
index 77caabd..db67bed 100644
--- a/src/constants/controls.ts
+++ b/src/constants/controls.ts
@@ -1,5 +1,3 @@
-import type { CtrlAttrs } from 'components/models';
-
export const controls = {
simulation: {
start: {
@@ -59,7 +57,7 @@ export const controls = {
icon: 'restart_alt',
cnfrm: true,
delay: 5,
- }
+ },
},
icloudmonitor: {
start: {
@@ -77,6 +75,6 @@ export const controls = {
icon: 'stop',
cnfrm: false,
delay: 0,
- }
- }
+ },
+ },
};
diff --git a/src/functions/reverseGeocode.ts b/src/functions/reverseGeocode.ts
new file mode 100644
index 0000000..73d25d5
--- /dev/null
+++ b/src/functions/reverseGeocode.ts
@@ -0,0 +1,47 @@
+// services/nominatimService.ts
+import { osm } from 'boot/axios';
+
+// TypeScript Interface for Reverse Geocoding Response
+export interface NominatimResponse {
+ place_id: number;
+ display_name: string;
+ address: {
+ road?: string;
+ city?: string;
+ country?: string;
+ [key: string]: unknown;
+ };
+ lat: string;
+ lon: string;
+}
+
+const API_URL = '/reverse';
+
+// Simple debounce to respect 1s limit
+let lastRequestTime = 0;
+
+export const reverseGeocodeRateLimited = async (lat: number, lon: number): Promise => {
+ const now = Date.now();
+ const timeSinceLast = now - lastRequestTime;
+
+ // Wait if less than 1000ms has passed
+ if (timeSinceLast < 1000) {
+ await new Promise((resolve) => setTimeout(resolve, 1000 - timeSinceLast));
+ }
+
+ const response = await osm.get(API_URL, {
+ params: {
+ lat,
+ lon,
+ format: 'jsonv2',
+ addressdetails: 1,
+ },
+ headers: {
+ // It is mandatory to set a descriptive User-Agent
+ 'User-Agent': 'Vue3App/1.0 (your-email@example.com)',
+ },
+ });
+
+ lastRequestTime = Date.now();
+ return response.data;
+};
diff --git a/src/functions/routingControl.ts b/src/functions/routingControl.ts
index 5211671..41ac942 100644
--- a/src/functions/routingControl.ts
+++ b/src/functions/routingControl.ts
@@ -1,48 +1,46 @@
import { Utilities } from '@vue-leaflet/vue-leaflet';
-import type L from 'leaflet';
-import type { IRouter, IGeocoder, LineOptions } from 'leaflet-routing-machine';
+import type { PropType } from 'vue';
+import type { IRouter, LineOptions } from 'leaflet-routing-machine';
-// ---- Props typing ----
export interface RoutingControlProps {
- waypoints: L.Routing.Waypoint[];
- router?: IRouter;
- plan?: L.Routing.Plan;
+ waypoints: unknown[];
+ router?: IRouter | undefined;
+ plan?: unknown;
fitSelectedRoutes?: string | boolean;
- lineOptions?: LineOptions;
- routeLine?: (route: any) => L.Layer;
+ lineOptions?: LineOptions | undefined;
+ routeLine?: ((route: unknown) => unknown) | undefined;
autoRoute?: boolean;
routeWhileDragging?: boolean;
routeDragInterval?: number;
waypointMode?: string;
useZoomParameter?: boolean;
showAlternatives?: boolean;
- altLineOptions?: LineOptions;
+ altLineOptions?: LineOptions | undefined;
}
-// ---- Vue-compatible prop definition ----
export const routingControlProps = {
waypoints: {
- type: Array as () => L.Routing.Waypoint[],
+ type: Array as PropType,
default: () => [],
},
router: {
- type: Object as () => IRouter | undefined,
+ type: Object as PropType,
default: undefined,
},
plan: {
- type: Object as () => L.Routing.Plan | undefined,
+ type: Object as PropType,
default: undefined,
},
fitSelectedRoutes: {
- type: [String, Boolean] as unknown as () => string | boolean,
+ type: [String, Boolean] as PropType,
default: 'smart',
},
lineOptions: {
- type: Object as () => LineOptions | undefined,
+ type: Object as PropType,
default: undefined,
},
routeLine: {
- type: Function as unknown as () => ((route: any) => L.Layer) | undefined,
+ type: Function as PropType<((route: unknown) => unknown) | undefined>,
default: undefined,
},
autoRoute: {
@@ -70,17 +68,13 @@ export const routingControlProps = {
default: false,
},
altLineOptions: {
- type: Object as () => LineOptions | undefined,
+ type: Object as PropType,
default: undefined,
},
};
-// ---- Setup function ----
export const setupRoutingControl = (props: RoutingControlProps) => {
- const options = Utilities.propsToLeafletOptions(
- props,
- routingControlProps,
- ) as L.Routing.RoutingControlOptions;
+ const options = Utilities.propsToLeafletOptions(props, routingControlProps);
return {
options,
diff --git a/src/functions/serviceURL.ts b/src/functions/serviceURL.ts
new file mode 100644
index 0000000..052982b
--- /dev/null
+++ b/src/functions/serviceURL.ts
@@ -0,0 +1,11 @@
+import { openrouteserviceV2 } from 'components/L.Routing.OpenRouteServiceV2';
+
+export const customRouter = openrouteserviceV2({
+ profile: 'driving-car',
+ geometry_simplify: true,
+ host: '/ors',
+});
+
+//export const customRouter = L.Routing.osrmv1({
+// serviceUrl: '/osrm/route/v1', // Replace with your URL
+//});
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index e263030..283c98e 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -6,6 +6,7 @@
+
@@ -51,6 +53,7 @@ import StatusBar from 'components/StatusBar.vue';
const socketioStore = useSocketioStore();
const drawer = ref(false);
+/*
const route = useRoute();
const menuList = [
@@ -110,6 +113,7 @@ const menuList = [
route: 'ErrorNotFound',
},
];
+*/
onMounted(() => {
socketioStore.bindEvents();
socketioStore.connect();
diff --git a/src/stores/leaflet.ts b/src/stores/leaflet.ts
index 52b0abe..2024301 100644
--- a/src/stores/leaflet.ts
+++ b/src/stores/leaflet.ts
@@ -1,11 +1,42 @@
import { defineStore, acceptHMRUpdate } from 'pinia';
import { favorites } from 'constants/favorites'
+interface RoutesSet {
+ [key: string]: RouteSet
+}
+
+interface LatLng {
+ lat: number | null | undefined;
+ lng: number | null | undefined;
+}
+
+interface routeSegments {
+ fromWaypoint: number;
+ toWaypoint: number;
+ distanceMeters: number;
+ timeSeconds: number;
+ toCoordinates: LatLng | null | undefined;
+}
+
+
+interface RouteSet {
+ start: [number, number] | [null, null] | [undefined, undefined] | null | undefined;
+ end: [number, number] | [null, null] | [undefined, undefined] | null | undefined;
+ wayPoints?: [number, number][] | [null, null] | [undefined, undefined] | null | undefined;
+}
+
interface State {
- zoom: number
- center: [number, number] | [null, null] | null
- markerLatLng: [number, number] | [null, null] | null
- qLocDrawer: boolean
+ zoom: number;
+ center: [number, number] | [null, null] | null;
+ markerLatLng: [number, number] | [null, null] | null;
+ qLocDrawer: boolean;
+ routeSet: {
+ start: LatLng | null | undefined;
+ end: LatLng | null | undefined;
+ wayPoints?: LatLng[] | null | undefined;
+ };
+ routesSet: RoutesSet[] | null;
+ routeSegments?: routeSegments[] | null;
}
export const useLeafletStore = defineStore('leaflet', {
@@ -15,6 +46,15 @@ export const useLeafletStore = defineStore('leaflet', {
center: [favorites.home.coords.lat, favorites.home.coords.lng],
markerLatLng: null,
qLocDrawer: false,
+ routeSet:
+ {
+ start: { lat: null, lng: null },
+ end: { lat: null, lng: null},
+ wayPoints: null,
+ },
+ routesSet: null,
+ routeSegments: null,
+
}
},
actions: {
diff --git a/src/stores/socketio.ts b/src/stores/socketio.ts
index 0e238c8..ca7cfb0 100644
--- a/src/stores/socketio.ts
+++ b/src/stores/socketio.ts
@@ -11,6 +11,7 @@ import type {
StatusUpdate,
FindMyUpdate,
iCloudMonitorResponse,
+ SimulationStatus,
} from 'components/models';
@@ -110,6 +111,20 @@ export const useSocketioStore = defineStore('socketio', {
this.findMyUpdate = data;
});
+ 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,
+ next_move: data.next_move,
+ };
+ this.locationQueueData[data.loc_id]['start'] = data.start;
+ });
+
socket.on('icloud_2fa_request', (callback) => {
if (debugLog) {
console.log('iCloud 2FA Request');
@@ -328,6 +343,24 @@ export const useSocketioStore = defineStore('socketio', {
},
);
break;
+ case 'test-mode':
+ socket.emit(
+ 'simulation_control',
+ { command: 'test-mode' },
+ (response: SimulationControlResponse) => {
+ if (response.status === 'error') {
+ throw new Error(response.message);
+ } else {
+ this.simulationState = response.status;
+ if (debugLog) {
+ console.log(response.message, response);
+ }
+ return response.message;
+ }
+ },
+ );
+ break;
+
case 'pause':
if (this.simulationState !== 'RUNNING') {
throw new Error('Simulation is not running');
@@ -368,9 +401,6 @@ export const useSocketioStore = defineStore('socketio', {
if (this.simulationQueueLength == 0) {
throw new Error('Simulation queue is empty');
}
- if (this.simulationState == 'STOPPED ' || !this.simulationRunning) {
- throw new Error('Simulation is not running');
- }
socket.emit('simulation_control', { command: 'clear' }, (response) => {
if (response.status == 'error') {
throw new Error(response.message);
@@ -417,15 +447,6 @@ export const useSocketioStore = defineStore('socketio', {
if (debugLog) {
console.log('response from simulate_control_add: ', response);
}
- const locMrk = {
- [response.loc_id]: {
- loc_id: response.loc_id,
- latitude: response.latitude,
- longitude: response.longitude,
- delay: response.delay,
- start_time: response.start_time,
- },
- };
return response.message;
}
},
diff --git a/src/types/leaflet-esm.d.ts b/src/types/leaflet-esm.d.ts
new file mode 100644
index 0000000..0bd4a27
--- /dev/null
+++ b/src/types/leaflet-esm.d.ts
@@ -0,0 +1 @@
+declare module 'leaflet/dist/leaflet-src.esm';
diff --git a/src/types/leaflet-routing-machine.d.ts b/src/types/leaflet-routing-machine.d.ts
index 75c90a6..18a28f2 100644
--- a/src/types/leaflet-routing-machine.d.ts
+++ b/src/types/leaflet-routing-machine.d.ts
@@ -1,12 +1,12 @@
-declare module "leaflet-routing-machine" {
- import * as L from "leaflet";
+declare module 'leaflet-routing-machine' {
+ import type * as L from 'leaflet';
- export interface IRouter {}
- export interface IGeocoder {}
- export interface LineOptions extends L.PolylineOptions {}
+ export type IRouter = Record;
+ export type IGeocoder = Record;
+ export type LineOptions = L.PolylineOptions;
export namespace Routing {
- function control(options: any): any;
+ function control(options: Record): Record;
class Plan {}
}
diff --git a/src/types/openrouteservice-js.d.ts b/src/types/openrouteservice-js.d.ts
new file mode 100644
index 0000000..32135af
--- /dev/null
+++ b/src/types/openrouteservice-js.d.ts
@@ -0,0 +1 @@
+declare module 'openrouteservice-js';