@adventurelabs/scout-core 1.0.91 → 1.0.93
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.
|
@@ -9,149 +9,127 @@ import { getDaysAgoTimestamp } from "../helpers/time";
|
|
|
9
9
|
export function useScoutRealtimeConnectivity(scoutSupabase) {
|
|
10
10
|
const channels = useRef([]);
|
|
11
11
|
const dispatch = useAppDispatch();
|
|
12
|
-
const [
|
|
12
|
+
const [hasInitialized, setHasInitialized] = useState(null);
|
|
13
13
|
const activeHerdId = useSelector((state) => state.scout.active_herd_id);
|
|
14
|
-
const
|
|
14
|
+
const connectivity = useSelector((state) => state.scout.active_herd_gps_trackers_connectivity);
|
|
15
15
|
const herdModules = useSelector((state) => state.scout.herd_modules);
|
|
16
|
-
//
|
|
16
|
+
// Handle connectivity broadcasts
|
|
17
17
|
const handleConnectivityBroadcast = useCallback((payload) => {
|
|
18
|
-
|
|
19
|
-
const event = payload.payload.event;
|
|
20
|
-
const data = payload.payload;
|
|
18
|
+
const { event, payload: data } = payload;
|
|
21
19
|
const connectivityData = data.new || data.old;
|
|
22
|
-
// Only process tracker
|
|
23
|
-
if (!connectivityData || connectivityData.session_id) {
|
|
20
|
+
// Only process GPS tracker data (no session_id)
|
|
21
|
+
if (!connectivityData?.device_id || connectivityData.session_id) {
|
|
24
22
|
return;
|
|
25
23
|
}
|
|
26
24
|
const deviceId = connectivityData.device_id;
|
|
27
|
-
|
|
28
|
-
return;
|
|
29
|
-
const currentConnectivity = {
|
|
30
|
-
...activeHerdGpsTrackersConnectivity,
|
|
31
|
-
};
|
|
32
|
-
console.log("[Connectivity] Current connectivity:", currentConnectivity);
|
|
25
|
+
const updatedConnectivity = { ...connectivity };
|
|
33
26
|
switch (event) {
|
|
34
27
|
case "INSERT":
|
|
35
|
-
if (!
|
|
36
|
-
|
|
28
|
+
if (!updatedConnectivity[deviceId]) {
|
|
29
|
+
updatedConnectivity[deviceId] = [];
|
|
37
30
|
}
|
|
38
|
-
|
|
31
|
+
updatedConnectivity[deviceId].push(connectivityData);
|
|
39
32
|
// Keep only recent 100 entries
|
|
40
|
-
if (
|
|
41
|
-
|
|
33
|
+
if (updatedConnectivity[deviceId].length > 100) {
|
|
34
|
+
updatedConnectivity[deviceId] = updatedConnectivity[deviceId]
|
|
42
35
|
.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
43
36
|
new Date(a.timestamp_start || 0).getTime())
|
|
44
37
|
.slice(0, 100);
|
|
45
38
|
}
|
|
46
39
|
break;
|
|
47
40
|
case "UPDATE":
|
|
48
|
-
if (
|
|
49
|
-
const index =
|
|
41
|
+
if (updatedConnectivity[deviceId]) {
|
|
42
|
+
const index = updatedConnectivity[deviceId].findIndex((c) => c.id === connectivityData.id);
|
|
50
43
|
if (index >= 0) {
|
|
51
|
-
|
|
44
|
+
updatedConnectivity[deviceId][index] = connectivityData;
|
|
52
45
|
}
|
|
53
46
|
}
|
|
54
47
|
break;
|
|
55
48
|
case "DELETE":
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
delete
|
|
49
|
+
if (updatedConnectivity[deviceId]) {
|
|
50
|
+
updatedConnectivity[deviceId] = updatedConnectivity[deviceId].filter((c) => c.id !== connectivityData.id);
|
|
51
|
+
if (updatedConnectivity[deviceId].length === 0) {
|
|
52
|
+
delete updatedConnectivity[deviceId];
|
|
60
53
|
}
|
|
61
54
|
}
|
|
62
55
|
break;
|
|
63
56
|
}
|
|
64
|
-
dispatch(setActiveHerdGpsTrackersConnectivity(
|
|
65
|
-
}, [
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
70
|
-
const createConnectivityChannel = (herdId) => {
|
|
71
|
-
return scoutSupabase
|
|
72
|
-
.channel(`${herdId}-connectivity`, { config: { private: true } })
|
|
73
|
-
.on("broadcast", { event: "*" }, handleConnectivityBroadcast)
|
|
74
|
-
.subscribe((status) => {
|
|
75
|
-
if (status === "SUBSCRIBED") {
|
|
76
|
-
console.log(`[Connectivity] ✅ Connected to herd ${herdId}`);
|
|
77
|
-
}
|
|
78
|
-
else if (status === "CHANNEL_ERROR") {
|
|
79
|
-
console.error(`[Connectivity] ❌ Failed to connect to herd ${herdId}`);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
// Fetch initial connectivity data for GPS trackers
|
|
84
|
-
const fetchInitialConnectivityData = useCallback(async () => {
|
|
85
|
-
if (!activeHerdId || isLoading)
|
|
57
|
+
dispatch(setActiveHerdGpsTrackersConnectivity(updatedConnectivity));
|
|
58
|
+
}, [connectivity, dispatch]);
|
|
59
|
+
// Fetch initial connectivity data
|
|
60
|
+
const fetchInitialData = useCallback(async () => {
|
|
61
|
+
if (!activeHerdId || hasInitialized === activeHerdId)
|
|
86
62
|
return;
|
|
87
|
-
|
|
88
|
-
const activeHerdModule = herdModules.find((hm) => hm.herd.id.toString() ===
|
|
63
|
+
const herdId = activeHerdId; // Type narrowing
|
|
64
|
+
const activeHerdModule = herdModules.find((hm) => hm.herd.id.toString() === herdId);
|
|
89
65
|
if (!activeHerdModule)
|
|
90
66
|
return;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (gpsTrackerDevices.length === 0) {
|
|
96
|
-
console.log("[Connectivity] No GPS trackers found in herd");
|
|
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) {
|
|
70
|
+
setHasInitialized(herdId);
|
|
97
71
|
return;
|
|
98
72
|
}
|
|
99
|
-
|
|
100
|
-
console.log(`[Connectivity] Fetching last day connectivity for ${gpsTrackerDevices.length} GPS trackers`);
|
|
101
|
-
// Calculate timestamp for last 24 hours
|
|
73
|
+
console.log(`[Connectivity] Loading data for ${gpsDevices.length} GPS trackers`);
|
|
102
74
|
const timestampFilter = getDaysAgoTimestamp(1);
|
|
103
75
|
const connectivityData = {};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
connectivityData[device.id] = trackerConnectivity
|
|
117
|
-
.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
118
|
-
new Date(a.timestamp_start || 0).getTime())
|
|
119
|
-
.slice(0, 100);
|
|
120
|
-
console.log(`[Connectivity] Loaded ${connectivityData[device.id]?.length} records for device ${device.id}`);
|
|
121
|
-
}
|
|
76
|
+
await Promise.all(gpsDevices.map(async (device) => {
|
|
77
|
+
if (!device.id)
|
|
78
|
+
return;
|
|
79
|
+
try {
|
|
80
|
+
const response = await server_get_connectivity_by_device_id(device.id, timestampFilter);
|
|
81
|
+
if (response.status === EnumWebResponse.SUCCESS && response.data) {
|
|
82
|
+
const trackerData = response.data.filter((conn) => !conn.session_id);
|
|
83
|
+
if (trackerData.length > 0) {
|
|
84
|
+
connectivityData[device.id] = trackerData
|
|
85
|
+
.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
86
|
+
new Date(a.timestamp_start || 0).getTime())
|
|
87
|
+
.slice(0, 100);
|
|
122
88
|
}
|
|
123
89
|
}
|
|
124
|
-
|
|
125
|
-
console.
|
|
90
|
+
else {
|
|
91
|
+
console.error(`[Connectivity] API error for device ${device.id}:`, response.msg || "Unknown error");
|
|
126
92
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
setIsLoading(false);
|
|
137
|
-
}
|
|
138
|
-
}, [activeHerdId, herdModules, isLoading, dispatch]);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error(`[Connectivity] Failed to fetch data for device ${device.id}:`, error);
|
|
96
|
+
}
|
|
97
|
+
}));
|
|
98
|
+
dispatch(setActiveHerdGpsTrackersConnectivity(connectivityData));
|
|
99
|
+
setHasInitialized(herdId);
|
|
100
|
+
console.log(`[Connectivity] Loaded data for ${Object.keys(connectivityData).length} devices`);
|
|
101
|
+
}, [activeHerdId, herdModules, hasInitialized, dispatch]);
|
|
139
102
|
useEffect(() => {
|
|
140
|
-
if (!scoutSupabase)
|
|
103
|
+
if (!scoutSupabase || !activeHerdId)
|
|
141
104
|
return;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
105
|
+
// Clean up existing channels
|
|
106
|
+
channels.current.forEach((channel) => scoutSupabase.removeChannel(channel));
|
|
107
|
+
channels.current = [];
|
|
108
|
+
// Reset initialization when herd changes
|
|
109
|
+
setHasInitialized(null);
|
|
110
|
+
// Create connectivity channel
|
|
111
|
+
const channel = scoutSupabase
|
|
112
|
+
.channel(`${activeHerdId}-connectivity`, { config: { private: true } })
|
|
113
|
+
.on("broadcast", { event: "*" }, handleConnectivityBroadcast)
|
|
114
|
+
.subscribe((status) => {
|
|
115
|
+
if (status === "SUBSCRIBED") {
|
|
116
|
+
console.log(`[Connectivity] ✅ Connected to herd ${activeHerdId}`);
|
|
117
|
+
}
|
|
118
|
+
else if (status === "CHANNEL_ERROR") {
|
|
119
|
+
console.error(`[Connectivity] ❌ Failed to connect to herd ${activeHerdId}`);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
channels.current.push(channel);
|
|
123
|
+
// Fetch initial data
|
|
124
|
+
fetchInitialData();
|
|
125
|
+
return () => {
|
|
126
|
+
channels.current.forEach((ch) => scoutSupabase.removeChannel(ch));
|
|
127
|
+
channels.current = [];
|
|
128
|
+
};
|
|
151
129
|
}, [
|
|
152
130
|
scoutSupabase,
|
|
153
131
|
activeHerdId,
|
|
154
132
|
handleConnectivityBroadcast,
|
|
155
|
-
|
|
133
|
+
fetchInitialData,
|
|
156
134
|
]);
|
|
157
135
|
}
|
|
@@ -45,8 +45,6 @@ export function useScoutRealtimeDevices(scoutSupabase) {
|
|
|
45
45
|
});
|
|
46
46
|
};
|
|
47
47
|
useEffect(() => {
|
|
48
|
-
if (!scoutSupabase)
|
|
49
|
-
return;
|
|
50
48
|
cleanupChannels();
|
|
51
49
|
// Create devices channel for active herd
|
|
52
50
|
if (activeHerdId) {
|
|
@@ -54,5 +52,5 @@ export function useScoutRealtimeDevices(scoutSupabase) {
|
|
|
54
52
|
channels.current.push(channel);
|
|
55
53
|
}
|
|
56
54
|
return cleanupChannels;
|
|
57
|
-
}, [
|
|
55
|
+
}, [activeHerdId]);
|
|
58
56
|
}
|