fleetmap-reports 1.0.650 → 1.0.652
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.
- package/package.json +1 -1
- package/src/tests/index.test.js +4 -1
- package/src/util/device.js +0 -1
- package/src/zone-report.js +49 -82
package/package.json
CHANGED
package/src/tests/index.test.js
CHANGED
|
@@ -354,15 +354,18 @@ describe('Test_Reports', function () {
|
|
|
354
354
|
const userData = await report.getUserData()
|
|
355
355
|
const data = await report.zoneReport(new Date(2022, 3, 25, 0, 0, 0, 0),
|
|
356
356
|
new Date(2022, 3, 28, 23, 59, 59, 0),
|
|
357
|
-
userData)
|
|
357
|
+
{ ...userData, devices: userData.devices.filter(d => d.id === 22326) })
|
|
358
358
|
|
|
359
359
|
assert.equal(data.length, 1)
|
|
360
360
|
const device = data[0].devices.find(d => d.device.id === 22326)
|
|
361
361
|
assert.equal(device.geofences.length, 19)
|
|
362
|
+
console.log(device.geofences[0])
|
|
362
363
|
assert.equal(device.geofences[0].inTime.fixTime, '2022-04-25T23:47:58.000+0000')
|
|
363
364
|
assert.equal(device.geofences[0].outTime.fixTime, '2022-04-26T07:47:35.000+0000')
|
|
364
365
|
assert.equal(device.geofences[0].totalTime, '28777')
|
|
365
366
|
assert.equal(device.geofences[0].geofenceName, 'Casa João')
|
|
367
|
+
assert.equal(device.geofences[0].distanceIn, 0.38569639521207727)
|
|
368
|
+
// expect(device.geofences[0].distanceOut).toBeGreaterThan(0)
|
|
366
369
|
}, 990000)
|
|
367
370
|
// eslint-disable-next-line no-undef
|
|
368
371
|
it('Zone Report With Stops', async () => {
|
package/src/util/device.js
CHANGED
|
@@ -2,7 +2,6 @@ function devicesToProcess (userData) {
|
|
|
2
2
|
const groupIds = userData.groups.map(g => g.id)
|
|
3
3
|
const devices = userData.byGroup ? userData.devices.filter(d => !groupIds.includes(d.groupId)) : userData.devices
|
|
4
4
|
devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
|
5
|
-
|
|
6
5
|
console.log('LOADING_MESSAGE:' + devices.map(d => d.name).join(', '))
|
|
7
6
|
return devices
|
|
8
7
|
}
|
package/src/zone-report.js
CHANGED
|
@@ -27,12 +27,10 @@ async function createZoneReport (from, to, userData, traccar) {
|
|
|
27
27
|
const url = `https://${process.env.SERVER_HOST}/reports/zone-report`
|
|
28
28
|
return axios.post(url, { from, to, userData }, { withCredentials: true }).then(d => d.data)
|
|
29
29
|
}
|
|
30
|
-
console.log('Create ZoneReport')
|
|
31
30
|
const reportData = []
|
|
32
31
|
const types = ['geofenceEnter', 'geofenceExit']
|
|
33
32
|
|
|
34
33
|
if (userData.byGroup) {
|
|
35
|
-
console.log('ByGroup')
|
|
36
34
|
for (const g of userData.groups) {
|
|
37
35
|
const devices = userData.devices.filter(d => d.groupId === g.id)
|
|
38
36
|
console.log(g.name + ' devices:' + devices.length)
|
|
@@ -42,12 +40,9 @@ async function createZoneReport (from, to, userData, traccar) {
|
|
|
42
40
|
group: g,
|
|
43
41
|
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
44
42
|
}
|
|
45
|
-
console.log('LOADING_MESSAGE:' + 'Eventos...')
|
|
46
43
|
const response = await traccar.reports.reportsEventsGet(from, to, null, [g.id], types)
|
|
47
44
|
const data = response.data
|
|
48
45
|
|
|
49
|
-
console.log('Geofence Enter/Exit Alerts:' + data.length)
|
|
50
|
-
|
|
51
46
|
devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
|
52
47
|
|
|
53
48
|
if (data.length > 0) {
|
|
@@ -74,9 +69,7 @@ async function createZoneReport (from, to, userData, traccar) {
|
|
|
74
69
|
deviceCount, devices.length, sliceSize, deviceChunk, undefined)
|
|
75
70
|
|
|
76
71
|
const route = filterPositions(data.route)
|
|
77
|
-
|
|
78
72
|
const alerts = getInAndOutEvents(slice, route, userData)
|
|
79
|
-
console.log('Geofence Enter/Exit Alerts:' + alerts.length)
|
|
80
73
|
|
|
81
74
|
if (alerts.length) {
|
|
82
75
|
allData.devices.push(...await processDevices(from, to, devices, userData, { alerts, route }))
|
|
@@ -89,7 +82,7 @@ async function createZoneReport (from, to, userData, traccar) {
|
|
|
89
82
|
return reportData
|
|
90
83
|
}
|
|
91
84
|
|
|
92
|
-
function getNextIn(outDate, alerts, geofenceId, deviceRoute) {
|
|
85
|
+
function getNextIn (outDate, alerts, geofenceId, deviceRoute) {
|
|
93
86
|
return alerts
|
|
94
87
|
.filter(a => a.type === 'geofenceEnter' && a.geofenceId === geofenceId)
|
|
95
88
|
.find(a => new Date(a.position.fixTime).getTime() > outDate) ||
|
|
@@ -115,39 +108,37 @@ async function processDevices (from, to, devices, userData, data) {
|
|
|
115
108
|
zoneInData[a.geofenceId] = a
|
|
116
109
|
} else if (a.type === 'geofenceExit') {
|
|
117
110
|
const geofence = userData.geofences.find(g => g.id === a.geofenceId)
|
|
111
|
+
if (!geofence) { return }
|
|
112
|
+
const outDate = new Date(a.position.fixTime).getTime()
|
|
113
|
+
const routeAfterOut = deviceRoute.filter(p =>
|
|
114
|
+
new Date(p.fixTime).getTime() >= outDate &&
|
|
115
|
+
new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, a.geofenceId, deviceRoute)
|
|
116
|
+
)
|
|
118
117
|
if (zoneInData[a.geofenceId]) {
|
|
119
118
|
const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
|
|
120
119
|
const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
|
|
121
|
-
const outDate = new Date(a.position.fixTime).getTime()
|
|
122
120
|
const routeIn = deviceRoute.filter(p =>
|
|
123
121
|
new Date(p.fixTime).getTime() >= inDate &&
|
|
124
122
|
new Date(p.fixTime).getTime() < outDate
|
|
125
123
|
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
distanceOut: calculateDistance(routeAfterOut),
|
|
137
|
-
geofenceName: geofence.name,
|
|
138
|
-
stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
|
|
139
|
-
driverName: zoneInData[a.geofenceId].position.driverName
|
|
140
|
-
})
|
|
141
|
-
}
|
|
124
|
+
zoneInOutData.push({
|
|
125
|
+
inTime: zoneInData[a.geofenceId].position,
|
|
126
|
+
outTime: a.position,
|
|
127
|
+
totalTime: totalInTime,
|
|
128
|
+
distanceIn: calculateDistance(routeIn),
|
|
129
|
+
distanceOut: calculateDistance(routeAfterOut),
|
|
130
|
+
geofenceName: geofence.name,
|
|
131
|
+
stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
|
|
132
|
+
driverName: zoneInData[a.geofenceId].position.driverName
|
|
133
|
+
})
|
|
142
134
|
zoneInData[a.geofenceId] = null
|
|
143
135
|
} else {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
136
|
+
zoneInOutData.push({
|
|
137
|
+
outTime: a.position,
|
|
138
|
+
geofenceName: geofence.name,
|
|
139
|
+
driverName: '',
|
|
140
|
+
distanceOut: calculateDistance(routeAfterOut)
|
|
141
|
+
})
|
|
151
142
|
}
|
|
152
143
|
}
|
|
153
144
|
}
|
|
@@ -182,66 +173,42 @@ async function processDevices (from, to, devices, userData, data) {
|
|
|
182
173
|
return devicesResult
|
|
183
174
|
}
|
|
184
175
|
|
|
176
|
+
function checkGeofenceEnter (p1, p2, g) {
|
|
177
|
+
switch (g.geometry.type) {
|
|
178
|
+
case 'Polygon':
|
|
179
|
+
return !booleanPointInPolygon.default(p1, g) && booleanPointInPolygon.default(p2, g)
|
|
180
|
+
case 'Point':
|
|
181
|
+
return distance.default(p1, g, { units: 'meters' }) >= g.properties.distance &&
|
|
182
|
+
distance.default(p2, g, { units: 'meters' }) < g.properties.distance
|
|
183
|
+
case 'LineString':
|
|
184
|
+
return pointToLineDistance.default(p1, g, { units: 'meters' }) > (g.properties.geofence.attributes.polylineDistance || 25) &&
|
|
185
|
+
pointToLineDistance.default(p2, g, { units: 'meters' }) <= (g.properties.geofence.attributes.polylineDistance || 25)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function checkGeofenceExit (p1, p2, g) {
|
|
190
|
+
return checkGeofenceEnter(p2, p1, g)
|
|
191
|
+
}
|
|
192
|
+
|
|
185
193
|
function getInAndOutEvents (devices, route, userData) {
|
|
186
194
|
const events = []
|
|
187
195
|
devices.forEach(d => {
|
|
188
196
|
const deviceRoute = route.filter(p => p.deviceId === d.id)
|
|
189
|
-
|
|
190
197
|
const routePoints = deviceRoute.sort(sortPositions).map(p => convertPositionToFeature(p))
|
|
191
198
|
const geofencesFeatures = userData.geofences.map(g => convertToFeature(g))
|
|
192
199
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
if (!entryMap.includes(g)) {
|
|
202
|
-
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
203
|
-
entryMap.push(g)
|
|
204
|
-
}
|
|
205
|
-
} else {
|
|
206
|
-
if (entryMap.includes(g)) {
|
|
207
|
-
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
208
|
-
const index = entryMap.indexOf(g)
|
|
209
|
-
entryMap.splice(index, 1)
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (g.geometry.type === 'Point') {
|
|
214
|
-
if (distance.default(p, g, { units: 'meters' }) < g.properties.distance) {
|
|
215
|
-
if (!entryMap.includes(g)) {
|
|
216
|
-
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
217
|
-
entryMap.push(g)
|
|
218
|
-
}
|
|
219
|
-
} else {
|
|
220
|
-
if (entryMap.includes(g)) {
|
|
221
|
-
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
222
|
-
const index = entryMap.indexOf(g)
|
|
223
|
-
entryMap.splice(index, 1)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (g.geometry.type === 'LineString') {
|
|
228
|
-
if (pointToLineDistance.default(p, g, { units: 'meters' }) < (g.properties.geofence.attributes.polylineDistance || 25)) {
|
|
229
|
-
if (!entryMap.includes(g)) {
|
|
230
|
-
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
231
|
-
entryMap.push(g)
|
|
232
|
-
}
|
|
233
|
-
} else {
|
|
234
|
-
if (entryMap.includes(g)) {
|
|
235
|
-
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
236
|
-
const index = entryMap.indexOf(g)
|
|
237
|
-
entryMap.splice(index, 1)
|
|
238
|
-
}
|
|
239
|
-
}
|
|
200
|
+
routePoints.filter(p => p.properties.position.valid).forEach((p, i, array) => {
|
|
201
|
+
if (!i) { return }
|
|
202
|
+
const previous = array[i - 1]
|
|
203
|
+
for (const g of geofencesFeatures) {
|
|
204
|
+
if (checkGeofenceEnter(previous, p, g)) {
|
|
205
|
+
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
206
|
+
} else if (checkGeofenceExit(previous, p, g)) {
|
|
207
|
+
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
240
208
|
}
|
|
241
|
-
}
|
|
209
|
+
}
|
|
242
210
|
})
|
|
243
211
|
})
|
|
244
|
-
|
|
245
212
|
return events
|
|
246
213
|
}
|
|
247
214
|
|