fleetmap-reports 1.0.856 → 1.0.858
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/lang/frFR.json +1 -0
- package/package.json +2 -1
- package/src/location-report.js +7 -7
- package/src/speeding-report.js +72 -1
- package/src/tests/speeding.test.js +4 -4
package/lang/frFR.json
CHANGED
|
@@ -169,6 +169,7 @@
|
|
|
169
169
|
"digital_ports1": "Ports numériques 1",
|
|
170
170
|
"digital_ports2": "Portes numériques 2",
|
|
171
171
|
"temperature": "Température",
|
|
172
|
+
"temperature2": "Température 2",
|
|
172
173
|
"select_vehicles": "sélectionner des véhicules",
|
|
173
174
|
"select_vehicles_placeholder": "Véhicules",
|
|
174
175
|
"select_geofences": "sélectionner les balises",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fleetmap-reports",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.858",
|
|
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/location-report.js
CHANGED
|
@@ -203,6 +203,7 @@ async function exportLocationReportToPDF (userData, reportData) {
|
|
|
203
203
|
|
|
204
204
|
if (userData.includeTemperature) {
|
|
205
205
|
headers.push(translations.report.temperature)
|
|
206
|
+
headers.push(translations.report.temperature2 || 'Temperature 2')
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
if (positionsData) {
|
|
@@ -254,7 +255,8 @@ async function exportLocationReportToPDF (userData, reportData) {
|
|
|
254
255
|
]
|
|
255
256
|
|
|
256
257
|
if (userData.includeTemperature) {
|
|
257
|
-
temp.push(getTempValue(a))
|
|
258
|
+
temp.push(getTempValue(a, 'temp1'))
|
|
259
|
+
temp.push(getTempValue(a, 'temp2'))
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
if (userData.includeDigitalPorts) {
|
|
@@ -300,11 +302,8 @@ async function exportLocationReportToPDF (userData, reportData) {
|
|
|
300
302
|
}
|
|
301
303
|
}
|
|
302
304
|
|
|
303
|
-
function getTempValue (row) {
|
|
304
|
-
return (row.attributes &&
|
|
305
|
-
(row.attributes.temp1 !== 175 && row.attributes.temp1) ||
|
|
306
|
-
(row.attributes.temp2 !== 175 && row.attributes.temp2)
|
|
307
|
-
)) || ''
|
|
305
|
+
function getTempValue (row, sensor) {
|
|
306
|
+
return (row.attributes[sensor] !== 175 && row.attributes[sensor]) || ''
|
|
308
307
|
}
|
|
309
308
|
|
|
310
309
|
function getDigitalPort1Label (row, translations, dAttributes) {
|
|
@@ -397,7 +396,8 @@ function exportLocationReportToExcel (userData, reportData) {
|
|
|
397
396
|
speed: Math.round(a.speed * 1.85200),
|
|
398
397
|
ignition: a.attributes.ignition ? translations.report.ignitionOn : translations.report.ignitionOff,
|
|
399
398
|
driver: userData.byDriver ? d.driver.name : getDriverName(a.attributes.driverUniqueId, a.fixTime, userData),
|
|
400
|
-
temperature: getTempValue(a),
|
|
399
|
+
temperature: getTempValue(a, 'temp1'),
|
|
400
|
+
temperature2: getTempValue(a, 'temp2'),
|
|
401
401
|
digitalport1: getDigitalPortValue(a, 1, translations, d.device.attributes),
|
|
402
402
|
digitalport2: getDigitalPortValue(a, 2, translations, d.device.attributes),
|
|
403
403
|
latitude: a.latitude,
|
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
|