fleetmap-reports 1.0.261 → 1.0.265

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.
@@ -16,109 +16,135 @@ let traccarInstance
16
16
  let userData
17
17
 
18
18
  const fileName = 'SpeedingReport'
19
+ const eventTypes = ['deviceOverspeed']
19
20
 
20
21
  async function createSpeedingReport(from, to, reportUserData, traccar) {
22
+ console.log('Create SpeedingReport')
21
23
  traccarInstance = traccar
22
24
  userData = reportUserData
23
- console.log('createSpeedingReport', from, to, userData, traccar)
24
25
  const reportData = []
25
26
 
26
- if(userData.byDriver){
27
+ if (userData.byDriver) {
28
+ console.log("ByDriver")
27
29
  const allData = await createSpeedingReportByDriver(from, to)
28
30
  reportData.push(allData)
29
31
  }
30
- else if(userData.byGroup){
32
+ else if (userData.byGroup) {
31
33
  console.log("ByGroup")
32
- for (const g of userData.groups) {
33
- const devices = userData.devices.filter(d => d.groupId === g.id)
34
- console.log(g.name + ' devices:' + devices.length)
35
- if(devices.length > 0) {
36
- const groupData = {
37
- devices: [],
38
- group: g,
39
- xpert: devices.filter(d => d.attributes.xpert).length > 0
40
- }
34
+ const allData = await createSpeedingReportByGroup(from, to)
35
+ reportData.push(...allData)
36
+ } else {
37
+ console.log("ByDevice")
38
+ const allData = await createSpeedingReportByDevice(from, to, userData.devices)
39
+ reportData.push(allData)
40
+ }
41
41
 
42
- const eventTypes = ['deviceOverspeed']
43
- const events = await traccar.getEvents(traccarInstance, from, to, devices, eventTypes)
44
- const routes = userData.useVehicleSpeedLimit ? [] : await traccar.getRoute(traccarInstance, from, to, devices)
42
+ return reportData
43
+ }
45
44
 
46
- devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
45
+ async function createSpeedingReportByGroup(from, to){
46
+ const reportData = []
47
+ for (const g of userData.groups) {
48
+ const devices = userData.devices.filter(d => d.groupId === g.id)
49
+ console.log(g.name + ' devices:' + devices.length)
50
+ if(devices.length > 0) {
51
+ const groupData = {
52
+ devices: [],
53
+ group: g,
54
+ xpert: devices.filter(d => d.attributes.xpert).length > 0
55
+ }
47
56
 
48
- if (events.length > 0) {
49
- groupData.devices = await processDevices(from, to, devices, events, routes)
50
- reportData.push(groupData)
51
- }
57
+ const events = await traccar.getEvents(traccarInstance, from, to, devices, eventTypes)
58
+ const routes = await traccar.getRoute(traccarInstance, from, to, devices)
59
+
60
+ devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
61
+
62
+ if (events.length > 0) {
63
+ groupData.devices = await processDevices(from, to, devices, events, routes)
64
+ reportData.push(groupData)
52
65
  }
53
66
  }
54
-
55
- const withoutGroupData = await createSpeedingReportByDevice(from, to)
56
- reportData.push(withoutGroupData)
57
- } else {
58
- const allData = await createSpeedingReportByDevice(from, to)
59
- reportData.push(allData)
60
67
  }
61
68
 
69
+ const groupIds = userData.groups.map(g => g.id)
70
+ const withoutGroupDevices = userData.devices.filter(d => !groupIds.includes(d.groupId))
71
+
72
+ const withoutGroupData = await createSpeedingReportByDevice(from, to, withoutGroupDevices)
73
+ reportData.push(withoutGroupData)
74
+
62
75
  return reportData
63
76
  }
64
77
 
65
- async function createSpeedingReportByDevice(from, to) {
66
- const groupIds = userData.groups.map(g => g.id)
67
- const withoutGroupDevices = userData.byGroup ? userData.devices.filter(d => !groupIds.includes(d.groupId)) : userData.devices
68
-
69
- withoutGroupDevices.sort((a, b) => (a.name > b.name) ? 1 : -1)
78
+ async function createSpeedingReportByDevice(from, to, devices) {
79
+ devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
70
80
 
71
- const eventTypes = ['deviceOverspeed']
72
- const events = await traccar.getEvents(traccarInstance, from, to, withoutGroupDevices, eventTypes)
73
- const routes = userData.useVehicleSpeedLimit ? [] : await traccar.getRoute(traccarInstance, from, to, withoutGroupDevices)
81
+ const routes = await traccar.getRoute(traccarInstance, from, to, devices)
82
+ const events = []
83
+ if(!userData.useVehicleSpeedLimit && userData.customSpeed){
84
+ events.push(...await getCustomSpeedLimitEvents(devices, routes))
85
+ } else {
86
+ events.push(...await traccar.getEvents(traccarInstance, from, to, devices, eventTypes))
87
+ }
74
88
 
75
- const allData = { devices: [] }
89
+ if(userData.roadSpeedLimits){
90
+ events.push(...await getHereEvents(devices, routes))
91
+ }
76
92
 
77
- if(events.length > 0 || userData.roadSpeedLimits) {
78
- allData.devices = await processDevices(from, to, withoutGroupDevices, events, routes)
79
- allData.xpert = withoutGroupDevices.filter(d => d && d.attributes && d.attributes.xpert).length > 0
93
+ if(!events.length) {
94
+ //empty report
95
+ return { devices: [] }
80
96
  }
81
97
 
82
- return allData
98
+ return {
99
+ devices: await processDevices(from, to, devices, events, routes),
100
+ xpert: devices.filter(d => d && d.attributes && d.attributes.xpert).length > 0
101
+ }
83
102
  }
84
103
 
85
104
  async function createSpeedingReportByDriver(from, to) {
86
- const deviceIds = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
87
- console.log('Devices with driver',deviceIds.length)
105
+ const devices = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
106
+ console.log('Devices with driver',devices.length)
107
+
108
+ if(!devices.length) {
109
+ //empty report
110
+ return { drivers: [] }
111
+ }
88
112
 
89
- let eventsData = []
90
- if(deviceIds.length > 0) {
91
- const devices = userData.devices.filter(d => deviceIds.includes(d.id))
92
- eventsData = await traccar.getEvents(traccarInstance, from, to, devices,['deviceOverspeed'])
113
+ const routes = await traccar.getRoute(traccarInstance, from, to, devices)
114
+ const events = []
115
+ if(!userData.useVehicleSpeedLimit && userData.customSpeed){
116
+ events.push(...await getCustomSpeedLimitEvents(devices, routes))
117
+ } else {
118
+ events.push(...await traccar.getEvents(traccarInstance, from, to, devices, eventTypes))
93
119
  }
94
120
 
95
- const allData = {
96
- drivers: []
121
+ if(userData.roadSpeedLimits){
122
+ events.push(...await getHereEvents(devices, routes))
97
123
  }
98
- console.log(eventsData.length)
99
124
 
100
- await getEventsPosition(from , to, userData.devices, eventsData)
101
- allData.drivers = await processDrivers(from, to, eventsData)
102
- console.log(allData.drivers.length)
103
- return allData
125
+ if(!events.length) {
126
+ //empty report
127
+ return { drivers: [] }
128
+ }
129
+
130
+ return {drivers: await processDrivers(from, to, events, routes)}
104
131
  }
105
132
 
106
- async function processDrivers(from, to, data) {
107
- console.log(data)
133
+ async function processDrivers(from, to, events, routes) {
108
134
  const driversResult = []
109
- const alertsWithPosition = data.filter(a => a.position)
110
-
111
- userData.drivers.forEach(d => {
112
- const alerts = alertsWithPosition.filter(e => e.position.attributes.driverUniqueId === d.uniqueId)
113
135
 
114
- if (alerts.length > 0) {
136
+ await findEventsPosition(from, to, userData.devices, events, routes)
115
137
 
138
+ userData.drivers.forEach(d => {
139
+ const driverEvents = events.filter(e => e.position && e.position.attributes.driverUniqueId === d.uniqueId)
140
+ if (driverEvents.length > 0) {
141
+ driverEvents.sort((a, b) => a.positionId - b.positionId)
116
142
  driversResult.push({
117
143
  driver: d,
118
144
  from: from,
119
145
  to: to,
120
- alerts: alerts,
121
- maxSpeed: alerts.reduce((a, b) => {
146
+ alerts: driverEvents,
147
+ maxSpeed: driverEvents.reduce((a, b) => {
122
148
  return a > b.attributes.maxSpeed ? a : b.attributes.maxSpeed
123
149
  }, 0),
124
150
  })
@@ -130,117 +156,38 @@ async function processDrivers(from, to, data) {
130
156
 
131
157
  async function processDevices(from, to, devices, events, routes) {
132
158
  const devicesResult = []
159
+ await findEventsPosition(from, to, devices, events, routes)
133
160
 
134
- if(userData.useVehicleSpeedLimit) {
135
- await getEventsPosition(from, to, devices, events)
136
-
137
- console.log(events)
138
-
139
- for (const d of devices) {
140
- const deviceEvents = events.filter(t => t.deviceId === d.id)
141
-
142
- if (deviceEvents.length > 0) {
143
- const alertsWithPosition = deviceEvents.filter(a => a.position).sort((a, b) => a.positionId - b.positionId)
144
- devicesResult.push({
145
- device: d,
146
- from: from,
147
- to: to,
148
- alerts: alertsWithPosition,
149
- maxSpeed: alertsWithPosition.reduce((a, b) => {
150
- return a > (b && b.attributes && b.attributes.maxSpeed) ? a : (b && b.attributes && b.attributes.maxSpeed)
151
- }, 0),
152
- })
153
- }
154
- }
155
- } else {
156
- for (const d of devices) {
157
- const positions = routes.filter(t => t.deviceId === d.id)
158
- const maxSpeed = userData.customSpeed / 1.85200
159
-
160
- const alerts = []
161
- for(let pIndex = 0; pIndex < positions.length ; pIndex++){
162
- const position = positions[pIndex]
163
- if(position.speed > maxSpeed){
164
- const alert = {
165
- position: position,
166
- attributes: {
167
- speedLimit: maxSpeed,
168
- speed: position.speed
169
- }
170
- }
171
-
172
- pIndex = calculateEventData(positions, pIndex, alert)
173
-
174
- alerts.push(alert)
175
- }
176
- }
177
- if(alerts.length > 0){
178
- devicesResult.push({
179
- device: d,
180
- from: from,
181
- to: to,
182
- alerts: alerts,
183
- maxSpeed: alerts.reduce((a, b) => {
184
- return a > (b && b.attributes && b.attributes.maxSpeed) ? a : (b && b.attributes && b.attributes.maxSpeed)
185
- }, 0),
186
- })
187
- }
161
+ for (const d of devices) {
162
+ const deviceEvents = events.filter(e => e.deviceId === d.id && e.position)
163
+ if (deviceEvents.length > 0) {
164
+ deviceEvents.sort((a, b) => a.positionId - b.positionId)
165
+ devicesResult.push({
166
+ device: d,
167
+ from: from,
168
+ to: to,
169
+ alerts: deviceEvents,
170
+ maxSpeed: deviceEvents.reduce((a, b) => {
171
+ return a > (b && b.attributes && b.attributes.maxSpeed) ? a : (b && b.attributes && b.attributes.maxSpeed)
172
+ }, 0),
173
+ })
188
174
  }
189
175
  }
190
176
 
191
177
  return devicesResult
192
178
  }
193
179
 
194
- async function getEventsPosition(from, to, devices, events){
195
-
196
- const deviceIds = [...new Set(events.map(e => e.deviceId))]
197
- const routeData = await traccar.getRoute(traccarInstance, from, to, deviceIds.map(id => { return { id: id } } ))
198
-
199
- console.log(events)
200
-
180
+ async function findEventsPosition(from, to, devices, events, routes){
201
181
  for (const d of devices) {
202
- let alerts = events.filter(t => t.deviceId === d.id)
203
-
204
- if (alerts.length > 0 || userData.roadSpeedLimits) {
205
- const positions = routeData.filter(p => p.deviceId === d.id)
206
-
207
- if (userData.roadSpeedLimits && positions.length) {
208
- try {
209
- const results = await here.routeMatch(positions)
210
- const hereAlerts = results.map(r => {
211
- const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
212
- return {
213
- ...r,
214
- roadSpeedLimit: r.speedLimit,
215
- deviceId: d.id,
216
- position,
217
- positionId: position && position.id,
218
- attributes: {speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200}
219
- }
220
- })
221
- console.log('hereAlerts', hereAlerts)
222
- const reduced = hereAlerts.reduce((acc, cur, idx, src) => {
223
- if (idx === 1) {
224
- return [cur]
225
- }
226
- if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
227
- return acc.concat(cur)
228
- }
229
- return acc
230
- })
231
- events.push(...reduced)
232
- alerts = events.filter(t => t.deviceId === d.id)
233
- } catch (e) {
234
- console.error(e)
235
- }
236
- }
182
+ let deviceEvents = events.filter(e => e.deviceId === d.id && e.positionId)
183
+ if (deviceEvents.length > 0) {
184
+ deviceEvents.sort((a,b) => a.positionId-b.positionId )
185
+ const positions = routes.filter(p => p.deviceId === d.id)
237
186
 
238
- for (const a of alerts) {
187
+ for (const a of deviceEvents) {
239
188
  let pIndex = positions.findIndex(p => p.id === a.positionId)
240
189
  if (pIndex > 0) {
241
- a.position = positions[pIndex]
242
190
  let geofence = null
243
-
244
191
  if (a.geofenceId) {
245
192
  geofence = userData.geofences.find(g => g.id === a.geofenceId)
246
193
  if (geofence) {
@@ -248,44 +195,87 @@ async function getEventsPosition(from, to, devices, events){
248
195
  }
249
196
  }
250
197
 
251
- let endEventPosition = a.position
252
- let maxSpeed = a.position.speed
253
- let dist = 0
254
- while (pIndex + 1 < positions.length) {
255
- pIndex++
256
-
257
- dist += distance(point([endEventPosition.longitude, endEventPosition.latitude]),
258
- point([positions[pIndex].longitude, positions[pIndex].latitude]))
259
- endEventPosition = positions[pIndex]
260
- if (endEventPosition.speed <= a.attributes.speedLimit || (geofence && isOutsideGeofence(geofence, endEventPosition))) {
261
- a.eventTime = new Date(endEventPosition.fixTime) - new Date(a.position.fixTime)
262
- a.attributes.maxSpeed = maxSpeed
263
- a.distance = dist
264
- break
265
- } else {
266
- if (maxSpeed < endEventPosition.speed) {
267
- maxSpeed = endEventPosition.speed
268
- }
269
- }
270
- }
198
+ if(!a.position) {
199
+ a.position = positions[pIndex]
200
+ pIndex = calculateEventData(positions, pIndex, a, d, geofence)
271
201
 
272
- if (a.position.attributes.driverUniqueId) {
273
- const driver = userData.drivers.find(d => d.uniqueId === a.position.attributes.driverUniqueId)
274
- a.driver = driver && driver.name
202
+ positions.slice(pIndex)
275
203
  }
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
276
209
 
277
- a.deviceName = d.name
210
+ async function getCustomSpeedLimitEvents(devices, routes){
211
+ console.log('calculate custom speed limit events')
212
+ const events = []
213
+ const maxSpeed = userData.customSpeed / 1.85200
278
214
 
279
- positions.slice(pIndex)
215
+ for (const d of devices) {
216
+ const positions = routes.filter(p => p.deviceId === d.id)
217
+ let eventIsActive = false
218
+
219
+ for (const position of positions) {
220
+ if(position.speed > maxSpeed && !eventIsActive){
221
+ const event = {
222
+ positionId: position && position.id,
223
+ deviceId: d.id,
224
+ attributes: {
225
+ speedLimit: maxSpeed,
226
+ speed: position.speed
227
+ }
280
228
  }
229
+ events.push(event)
230
+ eventIsActive = true
231
+ } else if (position.speed <= maxSpeed) {
232
+ eventIsActive = false
281
233
  }
282
234
  }
283
235
  }
236
+
237
+ return events
284
238
  }
285
239
 
286
- function calculateEventData(positions, pIndex, a, geofence){
287
- let endEventPosition = a.position
288
- let maxSpeed = a.position.speed
240
+ async function getHereEvents(devices, routes){
241
+ console.log('calculate custom speed limit events')
242
+ const events = []
243
+ for (const d of devices) {
244
+ const positions = routes.filter(p => p.deviceId === d.id)
245
+ try {
246
+ const results = await here.routeMatch(positions)
247
+ const hereAlerts = results.map(r => {
248
+ const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
249
+ return {
250
+ ...r,
251
+ roadSpeedLimit: r.speedLimit,
252
+ deviceId: d.id,
253
+ position,
254
+ positionId: position && position.id,
255
+ attributes: {speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200}
256
+ }
257
+ })
258
+ console.log('hereAlerts', hereAlerts)
259
+ const reduced = hereAlerts.reduce((acc, cur, idx, src) => {
260
+ if (idx === 1) {
261
+ return [cur]
262
+ }
263
+ if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
264
+ return acc.concat(cur)
265
+ }
266
+ return acc
267
+ })
268
+ events.push(...reduced)
269
+ } catch (e) {
270
+ //console.error(e)
271
+ }
272
+ }
273
+ return events
274
+ }
275
+
276
+ function calculateEventData(positions, pIndex, alert, device, geofence){
277
+ let endEventPosition = alert.position
278
+ let maxSpeed = alert.position.speed
289
279
  let dist = 0
290
280
  while (pIndex + 1 < positions.length) {
291
281
  pIndex++
@@ -293,10 +283,10 @@ function calculateEventData(positions, pIndex, a, geofence){
293
283
  dist += distance(point([endEventPosition.longitude, endEventPosition.latitude]),
294
284
  point([positions[pIndex].longitude, positions[pIndex].latitude]))
295
285
  endEventPosition = positions[pIndex]
296
- if (endEventPosition.speed <= a.attributes.speedLimit || (geofence && isOutsideGeofence(geofence, endEventPosition))) {
297
- a.eventTime = new Date(endEventPosition.fixTime) - new Date(a.position.fixTime)
298
- a.attributes.maxSpeed = maxSpeed
299
- a.distance = dist
286
+ if (endEventPosition.speed <= alert.attributes.speedLimit || (geofence && isOutsideGeofence(geofence, endEventPosition))) {
287
+ alert.eventTime = new Date(endEventPosition.fixTime) - new Date(alert.position.fixTime)
288
+ alert.attributes.maxSpeed = maxSpeed
289
+ alert.distance = dist
300
290
  break
301
291
  } else {
302
292
  if (maxSpeed < endEventPosition.speed) {
@@ -305,6 +295,14 @@ function calculateEventData(positions, pIndex, a, geofence){
305
295
  }
306
296
  }
307
297
 
298
+
299
+ if (alert.position.attributes.driverUniqueId) {
300
+ const driver = userData.drivers.find(d => d.uniqueId === alert.position.attributes.driverUniqueId)
301
+ alert.driver = driver && driver.name
302
+ }
303
+
304
+ alert.deviceName = device.name
305
+
308
306
  return pIndex
309
307
  }
310
308