fleetmap-reports 1.0.856 → 1.0.857
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 +2 -1
- package/src/speeding-report.js +72 -1
- package/src/tests/speeding.test.js +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fleetmap-reports",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.857",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"@turf/point-to-line-distance": "^6.5.0",
|
|
17
17
|
"axios": "^0.22.0",
|
|
18
18
|
"axios-cookiejar-support": "^1.0.1",
|
|
19
|
+
"country-reverse-geocoding": "^0.2.2",
|
|
19
20
|
"docx": "^7.3.0",
|
|
20
21
|
"file-saver": "^2.0.5",
|
|
21
22
|
"fleetmap-partners": "^1.0.126",
|
package/src/speeding-report.js
CHANGED
|
@@ -15,6 +15,7 @@ const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
|
|
|
15
15
|
const automaticReports = require('./automaticReports')
|
|
16
16
|
const { default: axios } = require('axios')
|
|
17
17
|
const { getDriverName, getDriverData } = require('./util/driver')
|
|
18
|
+
const crg = require('country-reverse-geocoding').country_reverse_geocoding()
|
|
18
19
|
|
|
19
20
|
const fileName = 'SpeedingReport'
|
|
20
21
|
const eventTypes = ['deviceOverspeed']
|
|
@@ -136,7 +137,7 @@ async function getEvents (traccarInstance, from, to, devices, userData, deviceCo
|
|
|
136
137
|
|
|
137
138
|
const events = []
|
|
138
139
|
if (userData.roadSpeedLimits) {
|
|
139
|
-
const hereResults = await
|
|
140
|
+
const hereResults = await getRoadSpeedLimits(devices, routes, userData.maxSpeedThreshold, userData.minimumIdleMinutes)
|
|
140
141
|
console.log('got', hereResults.length, 'from here')
|
|
141
142
|
events.push(...hereResults)
|
|
142
143
|
} else if (!userData.useVehicleSpeedLimit && userData.customSpeed) {
|
|
@@ -298,6 +299,76 @@ async function getCustomSpeedLimitEvents (devices, routes, customSpeed) {
|
|
|
298
299
|
return events
|
|
299
300
|
}
|
|
300
301
|
|
|
302
|
+
async function getRoadSpeedLimits(devices, routes, threshold, minimumMinutes = 0) {
|
|
303
|
+
const position = routes[0]
|
|
304
|
+
const country = crg.get_country(position.latitude, position.longitude)
|
|
305
|
+
const config = {
|
|
306
|
+
CHL: getOSMSpeedingEvents
|
|
307
|
+
}
|
|
308
|
+
const method = config[country && country.code] || getHereEvents
|
|
309
|
+
return method(devices, routes, threshold, minimumMinutes)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async function getOSMSpeedingEvents(devices, routes, threshold, minimumMinutes = 0) {
|
|
313
|
+
const chunk = 1000
|
|
314
|
+
const events = []
|
|
315
|
+
for (const d of devices) {
|
|
316
|
+
const route = routes.filter(r => r.deviceId === d.id)
|
|
317
|
+
const results = []
|
|
318
|
+
for (let i = 0; i < route.length; i += chunk) {
|
|
319
|
+
const apiKey = process.env.geoapifyKey
|
|
320
|
+
const slice = route.slice(i, i + chunk)
|
|
321
|
+
const { features } = await axios.post(`https://api.geoapify.com/v1/mapmatching?apiKey=${apiKey}`, {
|
|
322
|
+
mode: 'drive',
|
|
323
|
+
waypoints: slice.map(p => ({
|
|
324
|
+
timestamp: p.fixTime,
|
|
325
|
+
bearing: p.bearing,
|
|
326
|
+
location: [p.longitude, p.latitude]
|
|
327
|
+
}))
|
|
328
|
+
}).then(r => r.data)
|
|
329
|
+
|
|
330
|
+
const { properties } = features[0]
|
|
331
|
+
for (const wp of properties.waypoints) {
|
|
332
|
+
const leg = properties.legs[wp.leg_index]
|
|
333
|
+
if (!leg) {
|
|
334
|
+
console.log('ignoring legs (count):', properties.legs.count, wp.leg_index)
|
|
335
|
+
continue
|
|
336
|
+
}
|
|
337
|
+
const step = leg.steps[wp.step_index]
|
|
338
|
+
const position = route[wp.original_index + i]
|
|
339
|
+
if (!step) {
|
|
340
|
+
console.log('ignoring', wp.step_index, wp.leg_index, properties.legs[0].steps[wp.step_index], properties.legs[0].steps.length)
|
|
341
|
+
continue
|
|
342
|
+
}
|
|
343
|
+
if (wp.match_type !== 'unmatched' && step.speed_limit < position.speed * 1.852) {
|
|
344
|
+
results.push({ ...wp, ...step, ...position })
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const reduced = results.reduce((acc, cur, idx, src) => {
|
|
349
|
+
cur.overSpeeding = cur.speed * 1.852 > cur.speed_limit + (threshold || 0)
|
|
350
|
+
const last = acc.length && acc.slice(-1)[0]
|
|
351
|
+
if (cur.overSpeeding && last && src[idx - 1].overSpeeding && last.speed_limit === cur.speed_limit) {
|
|
352
|
+
last.eventTime = new Date(cur.fixTime) - new Date(last.fixTime)
|
|
353
|
+
last.attributes.maxSpeed = Math.max(last.attributes.maxSpeed, cur.speed)
|
|
354
|
+
last.distance = distance.default(point([cur.longitude, cur.latitude]), point([last.longitude, last.latitude]))
|
|
355
|
+
} else if (cur.overSpeeding) {
|
|
356
|
+
cur.positionId = cur && cur.id
|
|
357
|
+
cur.roadSpeedLimit = cur.speed_limit
|
|
358
|
+
cur.deviceId = d.id
|
|
359
|
+
cur.attributes = { speedLimit: cur.speed_limit, speed: cur.speed, maxSpeed: cur.speed }
|
|
360
|
+
cur.eventTime = 0
|
|
361
|
+
cur.distance = 0
|
|
362
|
+
cur.position = {...cur}
|
|
363
|
+
acc.push(cur)
|
|
364
|
+
}
|
|
365
|
+
return acc
|
|
366
|
+
}, [])
|
|
367
|
+
events.push(...reduced)
|
|
368
|
+
}
|
|
369
|
+
return events.filter(e => e.eventTime >= minimumMinutes * 60 * 1000)
|
|
370
|
+
}
|
|
371
|
+
|
|
301
372
|
async function getHereEvents (devices, routes, threshold, minimumMinutes = 0) {
|
|
302
373
|
try {
|
|
303
374
|
console.log('PROCESS_HERE_EVENTS', process.env.PROCESS_HERE_EVENTS)
|
|
@@ -3,11 +3,11 @@ const assert = require('assert')
|
|
|
3
3
|
|
|
4
4
|
async function getSpeedingReport (report, userData) {
|
|
5
5
|
const data = await report.speedingReport(
|
|
6
|
-
new Date(Date.UTC(
|
|
7
|
-
new Date(Date.UTC(
|
|
6
|
+
new Date(Date.UTC(2023, 9, 4, 0, 0, 0, 0)),
|
|
7
|
+
new Date(Date.UTC(2023, 9, 4, 23, 59, 59, 0)),
|
|
8
8
|
userData)
|
|
9
9
|
|
|
10
|
-
const device = data[0].devices
|
|
10
|
+
const device = data[0].devices[0]
|
|
11
11
|
const totalDistance = device && device.alerts.reduce((a, b) => a + b.distance, 0)
|
|
12
12
|
const totalEventTime = device && device.alerts.reduce((a, b) => a + b.eventTime, 0)
|
|
13
13
|
return { device, totalDistance, totalEventTime }
|
|
@@ -20,7 +20,7 @@ describe('speeding tests', function () {
|
|
|
20
20
|
const userData = await report.getUserData()
|
|
21
21
|
userData.roadSpeedLimits = true
|
|
22
22
|
const { device } = await getSpeedingReport(report, userData)
|
|
23
|
-
assert.equal(device.alerts.length,
|
|
23
|
+
assert.equal(device.alerts.length, 9) // Total Alerts
|
|
24
24
|
console.log(device.alerts)
|
|
25
25
|
|
|
26
26
|
userData.minimumIdleMinutes = 1
|