fleetmap-reports 1.0.679 → 1.0.681
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/partnerReports/afriquia.js +13 -3
- package/src/util/geofence.js +14 -0
- package/src/zone-report.js +78 -82
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const traccar = require('../util/traccar')
|
|
2
2
|
const { getIdleEvents } = require('../util/route')
|
|
3
|
-
const {
|
|
3
|
+
const { getNearestPOIs, checkGeofenceIn } = require('../util/geofence')
|
|
4
|
+
const { convertToFeature, convertPositionToFeature } = require('../util/utils')
|
|
4
5
|
|
|
5
6
|
function calculateLastStopTime (stopTime, to, time) {
|
|
6
7
|
return stopTime + (to.getTime() - new Date(time).getTime())
|
|
@@ -16,10 +17,12 @@ async function createActivityReport (from, to, userData, traccarInstance) {
|
|
|
16
17
|
|
|
17
18
|
const notAuthGeofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, Number(process.env.AFRIQUIA_NOT_AUTH_GROUP_ID), undefined, undefined).then(r => r.data)).map(g => g.id)
|
|
18
19
|
unauthorizedGeofences.push(...(userData.geofences.filter(g => notAuthGeofenceIds.includes(g.id))))
|
|
20
|
+
const unauthorizedGeofencesFeatures = unauthorizedGeofences.map(g => convertToFeature(g))
|
|
19
21
|
console.log('unauthorizedGeofences', unauthorizedGeofences)
|
|
20
22
|
|
|
21
23
|
const authGeofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, Number(process.env.AFRIQUIA_AUTH_GROUP_ID), undefined, undefined).then(r => r.data)).map(g => g.id)
|
|
22
24
|
authorizedGeofences.push(...(userData.geofences.filter(g => authGeofenceIds.includes(g.id))))
|
|
25
|
+
const authorizedGeofencesFeatures = authorizedGeofences.map(g => convertToFeature(g))
|
|
23
26
|
console.log('authorizedGeofences', authorizedGeofences)
|
|
24
27
|
|
|
25
28
|
const allInOne = await traccar.getAllInOne(traccarInstance, from, to, userData.devices, true, true, true, false)
|
|
@@ -37,12 +40,19 @@ async function createActivityReport (from, to, userData, traccarInstance) {
|
|
|
37
40
|
let authorizedStopsTime = 0
|
|
38
41
|
|
|
39
42
|
stops.forEach(s => {
|
|
40
|
-
const
|
|
43
|
+
const point = convertPositionToFeature({ latitude: s.latitude, longitude: s.longitude })
|
|
44
|
+
const unauthorized = unauthorizedGeofencesFeatures.find(g => {
|
|
45
|
+
const geofenceFeature = unauthorizedGeofencesFeatures.find(gF => gF.properties.geofence.id === g.id)
|
|
46
|
+
return checkGeofenceIn(point, geofenceFeature)
|
|
47
|
+
})
|
|
41
48
|
|
|
42
49
|
if (unauthorized) {
|
|
43
50
|
unauthorizedStops = unauthorizedStops + 1
|
|
44
51
|
} else {
|
|
45
|
-
const authorized = authorizedGeofences.find(g =>
|
|
52
|
+
const authorized = authorizedGeofences.find(g => {
|
|
53
|
+
const geofenceFeature = authorizedGeofencesFeatures.find(gF => gF.properties.geofence.id === g.id)
|
|
54
|
+
return checkGeofenceIn(point, geofenceFeature)
|
|
55
|
+
})
|
|
46
56
|
|
|
47
57
|
if (authorized) {
|
|
48
58
|
authorizedStops = authorizedStops + 1
|
package/src/util/geofence.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const turf = require('@turf/helpers')
|
|
2
2
|
const inside = require('@turf/boolean-point-in-polygon')
|
|
3
3
|
const { coordsDistance } = require('./utils')
|
|
4
|
+
const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
|
|
5
|
+
const distance = require('@turf/distance')
|
|
6
|
+
const pointToLineDistance = require('@turf/point-to-line-distance')
|
|
4
7
|
|
|
5
8
|
exports.insideGeofence = function insideGeofence (position, geofence) {
|
|
6
9
|
const coords = geofence.area.slice(9, geofence.area.length - 2).split(',')
|
|
@@ -32,3 +35,14 @@ exports.loadGroupsData = async function loadGroupsData (userData, traccarInstanc
|
|
|
32
35
|
g.geofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, g.id, undefined, undefined).then(r => r.data)).map(g => g.id)
|
|
33
36
|
}
|
|
34
37
|
}
|
|
38
|
+
|
|
39
|
+
exports.checkGeofenceIn = function checkGeofenceIn (p, g) {
|
|
40
|
+
switch (g.geometry.type) {
|
|
41
|
+
case 'Polygon':
|
|
42
|
+
return booleanPointInPolygon.default(p, g)
|
|
43
|
+
case 'Point':
|
|
44
|
+
return distance.default(p, g, { units: 'meters' }) >= g.properties.distance
|
|
45
|
+
case 'LineString':
|
|
46
|
+
return pointToLineDistance.default(p, g, { units: 'meters' }) > (g.properties.geofence.attributes.polylineDistance || 25)
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/zone-report.js
CHANGED
|
@@ -11,12 +11,10 @@ const { headerFromUser, addTable } = require('./util/pdfDocument')
|
|
|
11
11
|
const { getStyle } = require('./reportStyle')
|
|
12
12
|
const { getUserPartner } = require('fleetmap-partners')
|
|
13
13
|
const { devicesToProcess } = require('./util/device')
|
|
14
|
-
const pointToLineDistance = require('@turf/point-to-line-distance')
|
|
15
|
-
const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
|
|
16
|
-
const distance = require('@turf/distance')
|
|
17
14
|
const axios = require('axios')
|
|
18
15
|
const { processServerSide } = require('./util')
|
|
19
16
|
const { filterPositions } = require('./util/route')
|
|
17
|
+
const { checkGeofenceIn } = require('./util/geofence')
|
|
20
18
|
const sliceSize = 100
|
|
21
19
|
const deviceChunk = 5
|
|
22
20
|
const fileName = 'ZoneReport'
|
|
@@ -97,91 +95,91 @@ async function processDevices (from, to, devices, userData, data) {
|
|
|
97
95
|
|
|
98
96
|
const zoneInOutData = analyseAlerts(alerts, deviceRoute, userData, from, to).filter(d => !userData.onlyWithStop || d.stopped)
|
|
99
97
|
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
const dates = getDates(from, to)
|
|
98
|
+
if (userData.groupByDay) {
|
|
99
|
+
const dates = getDates(from, to)
|
|
103
100
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
const geofencesData = []
|
|
102
|
+
for (const geofence of userData.geofences) {
|
|
103
|
+
const filteredByGeofence = zoneInOutData.filter(d => d.geofenceId === geofence.id)
|
|
107
104
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
const dataByDay = []
|
|
106
|
+
for (const date of dates) {
|
|
107
|
+
const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
|
|
108
|
+
const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
|
|
112
109
|
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
const dayRoute = deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay)
|
|
111
|
+
const zoneInOutDayData = filteredByGeofence.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < toByDay)) &&
|
|
115
112
|
(!z.outTime || (new Date(z.outTime.fixTime) > fromByDay)))
|
|
116
113
|
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
|
|
115
|
+
const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
|
|
119
116
|
|
|
120
|
-
|
|
117
|
+
let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
|
|
121
118
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
|
|
120
|
+
let distanceOut = 0
|
|
121
|
+
if (zoneInOutDayData.length) {
|
|
122
|
+
distanceOut = zoneInOutDayData.reduce((a, b) => a + (b.distanceOut || 0), 0) - zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut
|
|
123
|
+
} else {
|
|
124
|
+
distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
|
|
125
|
+
}
|
|
129
126
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
if (zoneInOutDayData.length) {
|
|
128
|
+
// Check if the first entry starts only on the day before
|
|
129
|
+
if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
|
|
130
|
+
const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
|
|
131
|
+
timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
|
|
132
|
+
const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
|
|
136
133
|
new Date(p.fixTime) < fromByDay)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
distanceIn = distanceIn - calculateDistance(routeDayBefore)
|
|
135
|
+
} else {
|
|
136
|
+
// Add distanceOut before the first entry
|
|
137
|
+
const routeOut = deviceRoute.filter(p =>
|
|
138
|
+
new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
|
|
142
139
|
new Date(p.fixTime).getTime() >= fromByDay.getTime()
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
140
|
+
)
|
|
141
|
+
distanceOut = distanceOut + calculateDistance(routeOut)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check if the last entry ends only on the next day
|
|
145
|
+
if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
|
|
146
|
+
const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
|
|
147
|
+
timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
|
|
148
|
+
const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
|
|
149
|
+
distanceIn = distanceIn - calculateDistance(routeDayAfter)
|
|
150
|
+
} else {
|
|
151
|
+
const routeOut = deviceRoute.filter(p =>
|
|
152
|
+
new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
|
|
156
153
|
new Date(p.fixTime) < toByDay.getTime())
|
|
157
|
-
|
|
158
|
-
}
|
|
154
|
+
distanceOut = distanceOut + calculateDistance(routeOut)
|
|
159
155
|
}
|
|
160
|
-
dataByDay.push({
|
|
161
|
-
date,
|
|
162
|
-
firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
|
|
163
|
-
lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
|
|
164
|
-
distanceIn: distanceIn > 0 ? distanceIn : 0,
|
|
165
|
-
distanceOut,
|
|
166
|
-
totalInTime: timeIn,
|
|
167
|
-
totalOutTime: (24 * 60 * 60 * 1000) - timeIn
|
|
168
|
-
})
|
|
169
156
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
157
|
+
dataByDay.push({
|
|
158
|
+
date,
|
|
159
|
+
firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
|
|
160
|
+
lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
|
|
161
|
+
distanceIn: distanceIn > 0 ? distanceIn : 0,
|
|
162
|
+
distanceOut,
|
|
163
|
+
totalInTime: timeIn,
|
|
164
|
+
totalOutTime: (24 * 60 * 60 * 1000) - timeIn
|
|
174
165
|
})
|
|
175
166
|
}
|
|
176
167
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
to,
|
|
181
|
-
groupByDay: true,
|
|
182
|
-
geofences: geofencesData
|
|
168
|
+
geofencesData.push({
|
|
169
|
+
geofenceName: geofence.name,
|
|
170
|
+
days: dataByDay
|
|
183
171
|
})
|
|
184
|
-
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
devicesResult.push({
|
|
175
|
+
device: d,
|
|
176
|
+
from,
|
|
177
|
+
to,
|
|
178
|
+
groupByDay: true,
|
|
179
|
+
geofences: geofencesData
|
|
180
|
+
})
|
|
181
|
+
} else {
|
|
182
|
+
if (zoneInOutData.length > 0) {
|
|
185
183
|
devicesResult.push({
|
|
186
184
|
device: d,
|
|
187
185
|
from,
|
|
@@ -281,6 +279,15 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
|
|
|
281
279
|
}
|
|
282
280
|
}
|
|
283
281
|
|
|
282
|
+
if (!zoneInOutData.length && userData.groupByDay) {
|
|
283
|
+
const geofenceIn = alerts.find(a => a.type === 'geofenceIn')
|
|
284
|
+
zoneInOutData.push({
|
|
285
|
+
distanceIn: geofenceIn ? calculateDistance(deviceRoute) : 0,
|
|
286
|
+
distanceOut: !geofenceIn ? calculateDistance(deviceRoute) : 0,
|
|
287
|
+
totalTime: to.getTime() - from.getTime()
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
|
|
284
291
|
return zoneInOutData
|
|
285
292
|
}
|
|
286
293
|
|
|
@@ -292,17 +299,6 @@ function checkGeofenceExit (p1, p2, g) {
|
|
|
292
299
|
return checkGeofenceEnter(p2, p1, g)
|
|
293
300
|
}
|
|
294
301
|
|
|
295
|
-
function checkGeofenceIn (p, g) {
|
|
296
|
-
switch (g.geometry.type) {
|
|
297
|
-
case 'Polygon':
|
|
298
|
-
return booleanPointInPolygon.default(p, g)
|
|
299
|
-
case 'Point':
|
|
300
|
-
return distance.default(p, g, { units: 'meters' }) >= g.properties.distance
|
|
301
|
-
case 'LineString':
|
|
302
|
-
return pointToLineDistance.default(p, g, { units: 'meters' }) > (g.properties.geofence.attributes.polylineDistance || 25)
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
302
|
function getInAndOutEvents (devices, route, userData) {
|
|
307
303
|
const events = []
|
|
308
304
|
devices.forEach(d => {
|