@adventurelabs/scout-core 1.0.96 → 1.0.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useAppDispatch } from "../store/hooks";
|
|
3
3
|
import { useSelector } from "react-redux";
|
|
4
|
-
import { useEffect, useRef, useCallback } from "react";
|
|
4
|
+
import { useEffect, useRef, useCallback, useMemo } from "react";
|
|
5
5
|
import { setActiveHerdGpsTrackersConnectivity } from "../store/scout";
|
|
6
6
|
import { server_get_connectivity_by_device_id } from "../helpers/connectivity";
|
|
7
7
|
import { EnumWebResponse } from "../types/requests";
|
|
@@ -12,6 +12,21 @@ export function useScoutRealtimeConnectivity(scoutSupabase) {
|
|
|
12
12
|
const activeHerdId = useSelector((state) => state.scout.active_herd_id);
|
|
13
13
|
const connectivity = useSelector((state) => state.scout.active_herd_gps_trackers_connectivity);
|
|
14
14
|
const herdModules = useSelector((state) => state.scout.herd_modules);
|
|
15
|
+
// Create stable reference for GPS device IDs to prevent unnecessary refetching
|
|
16
|
+
const gpsDeviceIds = useMemo(() => {
|
|
17
|
+
if (!activeHerdId)
|
|
18
|
+
return "";
|
|
19
|
+
const activeHerdModule = herdModules.find((hm) => hm.herd.id.toString() === activeHerdId);
|
|
20
|
+
if (!activeHerdModule)
|
|
21
|
+
return "";
|
|
22
|
+
const gpsDevices = activeHerdModule.devices.filter((device) => device.device_type &&
|
|
23
|
+
["gps_tracker", "gps_tracker_vehicle", "gps_tracker_person"].includes(device.device_type));
|
|
24
|
+
return gpsDevices
|
|
25
|
+
.map((d) => d.id)
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.sort()
|
|
28
|
+
.join(",");
|
|
29
|
+
}, [activeHerdId, herdModules]);
|
|
15
30
|
// Handle connectivity broadcasts
|
|
16
31
|
const handleConnectivityBroadcast = useCallback((payload) => {
|
|
17
32
|
const { event, payload: data } = payload;
|
|
@@ -25,81 +40,108 @@ export function useScoutRealtimeConnectivity(scoutSupabase) {
|
|
|
25
40
|
switch (data.operation) {
|
|
26
41
|
case "INSERT":
|
|
27
42
|
if (!updatedConnectivity[deviceId]) {
|
|
28
|
-
updatedConnectivity[deviceId] =
|
|
43
|
+
updatedConnectivity[deviceId] = {
|
|
44
|
+
most_recent: connectivityData,
|
|
45
|
+
history: [connectivityData],
|
|
46
|
+
};
|
|
29
47
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
else {
|
|
49
|
+
// Create a copy of the existing historical data
|
|
50
|
+
const newHistory = [
|
|
51
|
+
...updatedConnectivity[deviceId].history,
|
|
52
|
+
connectivityData,
|
|
53
|
+
];
|
|
54
|
+
// Keep only recent 100 entries
|
|
55
|
+
const sortedHistory = newHistory
|
|
34
56
|
.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
35
57
|
new Date(a.timestamp_start || 0).getTime())
|
|
36
58
|
.slice(0, 100);
|
|
59
|
+
updatedConnectivity[deviceId] = {
|
|
60
|
+
most_recent: sortedHistory[0],
|
|
61
|
+
history: sortedHistory,
|
|
62
|
+
};
|
|
37
63
|
}
|
|
38
64
|
break;
|
|
39
65
|
case "UPDATE":
|
|
40
66
|
if (updatedConnectivity[deviceId]) {
|
|
41
|
-
|
|
67
|
+
// Create a copy of the history array before modifying
|
|
68
|
+
const newHistory = [...updatedConnectivity[deviceId].history];
|
|
69
|
+
const index = newHistory.findIndex((c) => c.id === connectivityData.id);
|
|
42
70
|
if (index >= 0) {
|
|
43
|
-
|
|
71
|
+
newHistory[index] = connectivityData;
|
|
72
|
+
// Update most_recent if this was the most recent item
|
|
73
|
+
const sortedHistory = newHistory.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
74
|
+
new Date(a.timestamp_start || 0).getTime());
|
|
75
|
+
updatedConnectivity[deviceId] = {
|
|
76
|
+
most_recent: sortedHistory[0],
|
|
77
|
+
history: sortedHistory,
|
|
78
|
+
};
|
|
44
79
|
}
|
|
45
80
|
}
|
|
46
81
|
break;
|
|
47
82
|
case "DELETE":
|
|
48
83
|
if (updatedConnectivity[deviceId]) {
|
|
49
|
-
|
|
50
|
-
|
|
84
|
+
// Filter creates a new array, so this is safe
|
|
85
|
+
const newHistory = updatedConnectivity[deviceId].history.filter((c) => c.id !== connectivityData.id);
|
|
86
|
+
if (newHistory.length === 0) {
|
|
51
87
|
delete updatedConnectivity[deviceId];
|
|
52
88
|
}
|
|
89
|
+
else {
|
|
90
|
+
const sortedHistory = newHistory.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
91
|
+
new Date(a.timestamp_start || 0).getTime());
|
|
92
|
+
updatedConnectivity[deviceId] = {
|
|
93
|
+
most_recent: sortedHistory[0],
|
|
94
|
+
history: sortedHistory,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
53
97
|
}
|
|
54
98
|
break;
|
|
55
99
|
}
|
|
56
100
|
console.log("[Connectivity] updating tracker connectivity in response to broadcast");
|
|
57
101
|
dispatch(setActiveHerdGpsTrackersConnectivity(updatedConnectivity));
|
|
58
|
-
}, [connectivity]);
|
|
102
|
+
}, [connectivity, dispatch]);
|
|
59
103
|
// Fetch initial connectivity data
|
|
60
104
|
const fetchInitialData = useCallback(async () => {
|
|
61
|
-
if (!
|
|
105
|
+
if (!gpsDeviceIds)
|
|
62
106
|
return;
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
if (!activeHerdModule)
|
|
66
|
-
return;
|
|
67
|
-
const gpsDevices = activeHerdModule.devices.filter((device) => device.device_type &&
|
|
68
|
-
["gps_tracker", "gps_tracker_vehicle", "gps_tracker_person"].includes(device.device_type));
|
|
69
|
-
if (gpsDevices.length === 0) {
|
|
107
|
+
const deviceIds = gpsDeviceIds.split(",").filter(Boolean).map(Number);
|
|
108
|
+
if (deviceIds.length === 0) {
|
|
70
109
|
return;
|
|
71
110
|
}
|
|
72
|
-
console.log(`[Connectivity] Loading data for ${
|
|
111
|
+
console.log(`[Connectivity] Loading data for ${deviceIds.length} GPS trackers`);
|
|
73
112
|
const timestampFilter = getDaysAgoTimestamp(1);
|
|
74
113
|
const connectivityData = {};
|
|
75
|
-
await Promise.all(
|
|
76
|
-
if (!device.id)
|
|
77
|
-
return;
|
|
114
|
+
await Promise.all(deviceIds.map(async (deviceId) => {
|
|
78
115
|
try {
|
|
79
|
-
const response = await server_get_connectivity_by_device_id(
|
|
116
|
+
const response = await server_get_connectivity_by_device_id(deviceId, timestampFilter);
|
|
80
117
|
if (response.status === EnumWebResponse.SUCCESS && response.data) {
|
|
81
118
|
const trackerData = response.data.filter((conn) => !conn.session_id);
|
|
82
119
|
if (trackerData.length > 0) {
|
|
83
|
-
|
|
120
|
+
const sortedData = trackerData
|
|
84
121
|
.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
85
122
|
new Date(a.timestamp_start || 0).getTime())
|
|
86
123
|
.slice(0, 100);
|
|
124
|
+
connectivityData[deviceId] = {
|
|
125
|
+
most_recent: sortedData[0],
|
|
126
|
+
history: sortedData,
|
|
127
|
+
};
|
|
87
128
|
}
|
|
88
129
|
}
|
|
89
130
|
else {
|
|
90
|
-
console.
|
|
131
|
+
console.warn(`[Connectivity] API error for device ${deviceId}:`, response.msg || "Unknown error");
|
|
91
132
|
}
|
|
92
133
|
}
|
|
93
134
|
catch (error) {
|
|
94
|
-
console.
|
|
135
|
+
console.warn(`[Connectivity] Failed to fetch data for device ${deviceId}:`, error);
|
|
95
136
|
}
|
|
96
137
|
}));
|
|
97
138
|
dispatch(setActiveHerdGpsTrackersConnectivity(connectivityData));
|
|
98
139
|
console.log(`[Connectivity] Loaded data for ${Object.keys(connectivityData).length} devices`);
|
|
99
|
-
}, [
|
|
140
|
+
}, [gpsDeviceIds, dispatch]);
|
|
100
141
|
useEffect(() => {
|
|
101
|
-
if (!scoutSupabase ||
|
|
142
|
+
if (!scoutSupabase || gpsDeviceIds === "")
|
|
102
143
|
return;
|
|
144
|
+
console.log(`[Connectivity Hook] Loading data for ${gpsDeviceIds}`);
|
|
103
145
|
// Clean up existing channels
|
|
104
146
|
channels.current.forEach((channel) => scoutSupabase.removeChannel(channel));
|
|
105
147
|
channels.current = [];
|
|
@@ -112,7 +154,7 @@ export function useScoutRealtimeConnectivity(scoutSupabase) {
|
|
|
112
154
|
console.log(`[Connectivity] ✅ Connected to herd ${activeHerdId}`);
|
|
113
155
|
}
|
|
114
156
|
else if (status === "CHANNEL_ERROR") {
|
|
115
|
-
console.
|
|
157
|
+
console.warn(`[Connectivity] 🟡 Failed to connect to herd ${activeHerdId}`);
|
|
116
158
|
}
|
|
117
159
|
});
|
|
118
160
|
channels.current.push(channel);
|
|
@@ -122,5 +164,11 @@ export function useScoutRealtimeConnectivity(scoutSupabase) {
|
|
|
122
164
|
channels.current.forEach((ch) => scoutSupabase.removeChannel(ch));
|
|
123
165
|
channels.current = [];
|
|
124
166
|
};
|
|
125
|
-
}, [
|
|
167
|
+
}, [
|
|
168
|
+
scoutSupabase,
|
|
169
|
+
gpsDeviceIds,
|
|
170
|
+
activeHerdId,
|
|
171
|
+
handleConnectivityBroadcast,
|
|
172
|
+
fetchInitialData,
|
|
173
|
+
]);
|
|
126
174
|
}
|
|
@@ -39,7 +39,7 @@ export function useScoutRealtimeDevices(scoutSupabase) {
|
|
|
39
39
|
console.log(`[Devices] ✅ Connected to herd ${herdId}`);
|
|
40
40
|
}
|
|
41
41
|
else if (status === "CHANNEL_ERROR") {
|
|
42
|
-
console.
|
|
42
|
+
console.warn(`[Devices] 🟡 Failed to connect to herd ${herdId}`);
|
|
43
43
|
}
|
|
44
44
|
});
|
|
45
45
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|