fleetmap-reports 2.0.316 → 2.0.318

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": "2.0.316",
3
+ "version": "2.0.318",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -12,7 +12,7 @@ function Reports (config, axios) {
12
12
  }
13
13
  this.getUserData = async () => {
14
14
  return {
15
- user: await this.traccar.session.sessionGet(process.env.TOKEN).then(d => d.data),
15
+ user: await this.traccar.session.sessionGet().then(d => d.data),
16
16
  devices: await this.traccar.devices.devicesGet().then(d => d.data),
17
17
  groups: await this.traccar.groups.groupsGet().then(d => d.data),
18
18
  drivers: await this.traccar.drivers.driversGet().then(d => d.data),
@@ -10,60 +10,13 @@ const { headerFromUser, addTable } = require('./util/pdfDocument')
10
10
  const { getStyle } = require('./reportStyle')
11
11
  const { getUserPartner } = require('fleetmap-partners')
12
12
 
13
- function minimumDuration (status, userData) {
14
- if (status) {
15
- return (userData.minimumMinutesOn * 60 * 1000)
16
- }
17
-
18
- return (userData.minimumMinutesOff * 60 * 1000)
19
- }
20
-
21
- function addSensorPeriod (statusPeriodBySensor, s, currentStatus, d, duration, currentPosition, previousPosition) {
22
- statusPeriodBySensor[s.sensor].push({
23
- startTime: currentStatus[s.sensor].startTime,
24
- endTime: previousPosition.fixTime,
25
- endAddress: previousPosition.address,
26
- value: currentStatus[s.sensor].value,
27
- valueDescription: currentStatus[s.sensor].value ? d.attributes[s.sensor + 'on'] : d.attributes[s.sensor + 'off'],
28
- name: s.name,
29
- duration
30
- })
31
- currentStatus[s.sensor] = { value: currentPosition.attributes[s.id], startTime: currentPosition.fixTime }
32
- }
33
-
34
13
  function processDevices (from, to, devices, data, userData) {
35
14
  const result = []
36
15
 
37
16
  for (const d of devices) {
38
- const positions = data.route.filter(t => t.deviceId === d.id)
39
-
40
- const statusPeriodBySensor = {}
41
- const currentStatus = {}
42
- positions.forEach((p, index) => {
43
- userData.sensors.forEach(s => {
44
- if (!statusPeriodBySensor[s.sensor]) {
45
- statusPeriodBySensor[s.sensor] = []
46
- }
47
- if (currentStatus[s.sensor] !== undefined) {
48
- if (currentStatus[s.sensor].value !== p.attributes[s.id]) {
49
- const duration = new Date(positions[index - 1].fixTime).getTime() - new Date(currentStatus[s.sensor].startTime).getTime()
50
- if ((duration >= minimumDuration(currentStatus[s.sensor].value, userData)) || statusPeriodBySensor[s.sensor].length === 0) {
51
- addSensorPeriod(statusPeriodBySensor, s, currentStatus, d, duration, p, positions[index - 1])
52
- } else {
53
- const element = statusPeriodBySensor[s.sensor].pop()
54
- currentStatus[s.sensor] = { value: p.attributes[s.id], startTime: element.startTime }
55
- }
56
- } else {
57
- const distanceBetweenPositions = new Date(p.fixTime).getTime() - new Date(positions[index - 1].fixTime).getTime()
58
- if (distanceBetweenPositions > 30 * 60 * 1000 && currentStatus[s.sensor].value === true) {
59
- currentStatus[s.sensor] = { value: p.attributes[s.id], startTime: p.fixTime }
60
- }
61
- }
62
- } else {
63
- currentStatus[s.sensor] = { value: p.attributes[s.id], startTime: p.fixTime }
64
- }
65
- })
66
- })
17
+ const positions = data.route.filter(t => t.deviceId === d.id).filter(t => t.attributes.motion)
18
+
19
+ const statusPeriodBySensor = computeSensorPeriods(positions, userData.sensors, d, userData)
67
20
 
68
21
  const rows = Object.values(statusPeriodBySensor).flat()
69
22
  rows.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime())
@@ -92,6 +45,129 @@ function processDevices (from, to, devices, data, userData) {
92
45
  return result
93
46
  }
94
47
 
48
+ function computeSensorPeriods (positions, sensors, d, userData) {
49
+ if (!positions || positions.length === 0) return {}
50
+
51
+ const result = {}
52
+ const minOn = (userData.minimumMinutesOn || 0) * 60 * 1000
53
+ const minOff = (userData.minimumMinutesOff || 0) * 60 * 1000
54
+ const maxDistanceBetweenPositions = 20 * 60 * 1000
55
+
56
+ const minThreshold = (value) => (value ? minOn : minOff)
57
+
58
+ function pushPeriod (sensorKey, s, value, startTime, endTime, endPos) {
59
+ const duration = endTime - startTime
60
+ const period = {
61
+ value,
62
+ startTime,
63
+ endTime,
64
+ duration,
65
+ name: s.name,
66
+ endAddress: endPos.address,
67
+ valueDescription: value
68
+ ? d.attributes[s.sensor + 'on']
69
+ : d.attributes[s.sensor + 'off']
70
+ }
71
+ console.debug(period)
72
+ result[sensorKey].push(period)
73
+ }
74
+
75
+ for (const s of sensors) result[s.sensor] = []
76
+
77
+ // Track current period per sensor
78
+ const current = {}
79
+ const firstPos = positions[0]
80
+ for (const s of sensors) {
81
+ current[s.sensor] = {
82
+ value: firstPos.attributes[s.id],
83
+ startTime: new Date(firstPos.fixTime)
84
+ }
85
+ }
86
+
87
+ for (let i = 1; i < positions.length; i++) {
88
+ const prevPos = positions[i - 1]
89
+ const currPos = positions[i]
90
+ const changeTime = new Date(currPos.fixTime)
91
+
92
+ for (const s of sensors) {
93
+ const key = s.sensor
94
+ const prevValue = current[key].value
95
+ const newValue = currPos.attributes[s.id]
96
+
97
+ if (prevValue === newValue) continue
98
+
99
+ const oldStartTime = current[key].startTime
100
+ const prevEndTime = changeTime
101
+ const duration = prevEndTime - oldStartTime
102
+ const threshold = minThreshold(prevValue)
103
+ let newPeriodStartTime = changeTime
104
+
105
+ // Check distance between positions
106
+ if (prevValue === false && newValue === true && maxDistanceBetweenPositions > 0) {
107
+ const nextPos = positions[i + 1]
108
+ if (nextPos && nextPos.attributes && nextPos.attributes[s.id] === true) {
109
+ const nextTime = new Date(nextPos.fixTime)
110
+ if (nextTime - oldStartTime > maxDistanceBetweenPositions) {
111
+ newPeriodStartTime = nextTime
112
+ }
113
+ }
114
+ }
115
+
116
+ if (duration >= threshold) {
117
+ pushPeriod(key, s, prevValue, oldStartTime, prevEndTime, prevPos)
118
+ } else {
119
+ // merging logic for previous ignored period
120
+ const list = result[key]
121
+ if (list.length > 0) {
122
+ const last = list[list.length - 1]
123
+ if (last.value === newValue) {
124
+ list.pop()
125
+ newPeriodStartTime = new Date(last.startTime)
126
+ }
127
+ }
128
+ }
129
+
130
+ current[key] = {
131
+ value: newValue,
132
+ startTime: newPeriodStartTime
133
+ }
134
+ }
135
+ }
136
+
137
+ // Close final periods
138
+ const lastPos = positions[positions.length - 1]
139
+ const lastTime = new Date(lastPos.fixTime)
140
+
141
+ for (const s of sensors) {
142
+ const key = s.sensor
143
+ const st = current[key]
144
+ const startTime = st.startTime
145
+ const endTime = lastTime
146
+ const value = st.value
147
+ const duration = endTime - startTime
148
+ const threshold = minThreshold(value)
149
+
150
+ if (duration >= threshold) {
151
+ pushPeriod(key, s, value, startTime, endTime, lastPos)
152
+ } else {
153
+ // try to merge tiny final period into previous pushed period if same value
154
+ const list = result[key]
155
+ if (list.length > 0 && list[list.length - 1].value === value) {
156
+ const last = list[list.length - 1]
157
+ last.endTime = endTime
158
+ last.duration = last.endTime - last.startTime
159
+ last.endAddress = lastPos.address
160
+ last.valueDescription = value
161
+ ? d.attributes[s.sensor + 'on']
162
+ : d.attributes[s.sensor + 'off']
163
+ }
164
+ // otherwise drop final tiny period
165
+ }
166
+ }
167
+
168
+ return result
169
+ }
170
+
95
171
  async function create (from, to, userData, traccar) {
96
172
  const devices = devicesToProcess(userData)
97
173
  const sliced = automaticReports.sliceArray(devices, 5)
package/src/util/route.js CHANGED
@@ -51,7 +51,10 @@ function cleanPosition (p) {
51
51
  deviceId: p.deviceId,
52
52
  speed: p.speed,
53
53
  valid: p.valid,
54
- attributes: { driverUniqueId: p.attributes.driverUniqueId }
54
+ attributes: {
55
+ ignition: p.attributes.ignition,
56
+ driverUniqueId: p.attributes.driverUniqueId
57
+ }
55
58
  }
56
59
  }
57
60
 
@@ -150,6 +150,7 @@ async function createZoneReport (from, to, userData, traccar) {
150
150
 
151
151
  async function processDevices (from, to, devices, userData, data) {
152
152
  const devicesResult = []
153
+ console.log('processDevices', from, to, devices.length)
153
154
  for (const d of devices) {
154
155
  const alerts = data.alerts.filter(t => t && t.deviceId === d.id)
155
156
  const deviceRoute = data.route.filter(p => p.deviceId === d.id)