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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.856",
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",
@@ -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 getHereEvents(devices, routes, userData.maxSpeedThreshold, userData.minimumIdleMinutes)
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(2022, 1, 17, 0, 0, 0, 0)),
7
- new Date(Date.UTC(2022, 1, 17, 23, 59, 59, 0)),
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.find(d => d.device.id === 22326)
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, 104) // Total Alerts
23
+ assert.equal(device.alerts.length, 9) // Total Alerts
24
24
  console.log(device.alerts)
25
25
 
26
26
  userData.minimumIdleMinutes = 1