queclink-parser 1.3.20

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/src/index.js ADDED
@@ -0,0 +1,316 @@
1
+ 'use strict'
2
+
3
+ const utils = require('./utils.js')
4
+ const gv200 = require('./gv200.js')
5
+ const gv300 = require('./gv300.js')
6
+ const gv300w = require('./gv300w.js')
7
+ const gv75w = require('./gv75w.js')
8
+ const gmt100 = require('./gmt100.js')
9
+ const gv55 = require('./gv55.js')
10
+ const gl300 = require('./gl300.js')
11
+ const gv500 = require('./gv500.js')
12
+ const gv800w = require('./gv800w.js')
13
+ const gv600w = require('./gv600w.js')
14
+ const gl50 = require('./gl50.js')
15
+ const gv50p = require('./gv50p.js')
16
+
17
+ /*
18
+ Checks if raw comes from a Queclink device
19
+ */
20
+ const isQueclink = raw => {
21
+ if (
22
+ utils.patterns.message.test(raw.toString()) ||
23
+ utils.patterns.ack.test(raw.toString()) ||
24
+ utils.patterns.buffer.test(raw.toString())
25
+ ) {
26
+ return true
27
+ }
28
+ return false
29
+ }
30
+
31
+ /*
32
+ Checks if raw is a heartbeat message
33
+ */
34
+ const isHeartBeat = raw => {
35
+ if (utils.patterns.heartbeat.test(raw.toString())) {
36
+ return true
37
+ }
38
+ return false
39
+ }
40
+
41
+ /*
42
+ Gets the ACK command to Hearbeat message
43
+ */
44
+ const getAckHeartBeat = (protocolVersion, count) => {
45
+ return `+SACK:GTHBD,${protocolVersion},${count}$`
46
+ }
47
+
48
+ /*
49
+ Returns the ACK for the given data
50
+ */
51
+ const getAck = serial => {
52
+ let count = utils.nHexDigit(utils.dec2hex(serial), 4).toUpperCase()
53
+ return `+SACK:${count}$`
54
+ }
55
+
56
+ /*
57
+ Returns the reboot command
58
+ */
59
+ const getRebootCommand = (password, serial) => {
60
+ password = password || '000000'
61
+ serial = serial || '0000'
62
+ return `AT+GTRTO=${password},3,,,,,,${serial}$`
63
+ }
64
+
65
+ /*
66
+ Returns the imei
67
+ */
68
+ const getImei = raw => {
69
+ let imei = null
70
+ raw = raw.toString()
71
+ const isValid =
72
+ Object.keys(utils.patterns)
73
+ .map(x => utils.patterns[x].test(raw))
74
+ .find(x => x === true) || false
75
+ if (isValid) {
76
+ const parsedData = raw.split(',')
77
+ imei = parsedData[2]
78
+ }
79
+ return imei ? imei.toString() : null
80
+ }
81
+
82
+ /*
83
+ Parses the raw data
84
+ */
85
+ const parse = (raw, options) => {
86
+ let result = { type: 'UNKNOWN', raw: raw.toString() }
87
+ options = options || {}
88
+ if (
89
+ utils.patterns.message.test(raw.toString()) ||
90
+ utils.patterns.ack.test(raw.toString()) ||
91
+ utils.patterns.buffer.test(raw.toString())
92
+ ) {
93
+ const device = utils.getDevice(raw.toString())
94
+ if (
95
+ utils.patterns.ack.test(raw.toString()) &&
96
+ !utils.patterns.heartbeat.test(raw.toString())
97
+ ) {
98
+ result = getAckCommand(raw.toString(), options.lang)
99
+ } else if (device === 'GV300W') {
100
+ result = gv300w.parse(raw.toString())
101
+ } else if (device === 'GV75W') {
102
+ result = gv75w.parse(raw.toString())
103
+ } else if (device === 'GV300') {
104
+ result = gv300.parse(raw.toString())
105
+ } else if (device === 'GV200') {
106
+ result = gv200.parse(raw.toString())
107
+ } else if (device === 'GV500') {
108
+ result = gv500.parse(raw.toString())
109
+ } else if (device === 'GV55') {
110
+ result = gv55.parse(raw.toString())
111
+ } else if (device === 'GMT100') {
112
+ result = gmt100.parse(raw.toString())
113
+ } else if (device === 'GL300' || device === 'GL300W') {
114
+ result = gl300.parse(raw.toString())
115
+ } else if (device === 'GV800W') {
116
+ result = gv800w.parse(raw.toString())
117
+ } else if (device === 'GV600W') {
118
+ result = gv600w.parse(raw.toString())
119
+ } else if (device === 'GL50' || device === 'GL50B') {
120
+ result = gl50.parse(raw.toString())
121
+ } else if (device === 'GV50P') {
122
+ result = gv50p.parse(raw.toString())
123
+ }
124
+ }
125
+ return result
126
+ }
127
+
128
+ /*
129
+ Returns the ack command
130
+ */
131
+ const getAckCommand = (raw, lang) => {
132
+ const messages = utils.langs[lang] || utils.langs['es']
133
+ const rawData = raw.substr(0, raw.length - 1)
134
+ const parsedData = rawData.split(',')
135
+ const command = parsedData[0].split(':')
136
+
137
+ let data = {
138
+ manufacturer: 'queclink',
139
+ device: 'Queclink-COMMAND-OK',
140
+ type: 'ok',
141
+ serial:
142
+ parsedData[parsedData.length - 3] !== ''
143
+ ? parseInt(utils.hex2dec(parsedData[parsedData.length - 3]), 10)
144
+ : null,
145
+ counter: parseInt(utils.hex2dec(parsedData[parsedData.length - 1]), 10)
146
+ }
147
+ if (command[1] === 'GTSPD') {
148
+ data.command = 'SETOVERSPEEDALARM'
149
+ } else if (command[1] === 'GTOUT') {
150
+ data.command = 'SETIOSWITCH'
151
+ } else if (command[1] === 'GTRTO') {
152
+ if (parsedData[4] === 'RESET') {
153
+ data.command = 'CLEARBUF'
154
+ } else if (parsedData[4] === 'REBOOT') {
155
+ data.command = 'REBOOT'
156
+ } else if (parsedData[4] === 'RTL') {
157
+ data.command = 'REQUESTCURRENTPOSITION'
158
+ }
159
+ } else if (command[1] === 'GTJBS') {
160
+ data.command = 'ANTIJAMMER'
161
+ }
162
+ data.message = messages[data.command] || messages.default
163
+ return data
164
+ }
165
+
166
+ /*
167
+ Parses the Websocket command into Queclink Command
168
+ */
169
+ const parseCommand = data => {
170
+ let command = ''
171
+ const password = data.password || '000000'
172
+ const serial = data.serial || 0
173
+ const serialId = utils.nHexDigit(utils.dec2hex(serial), 4)
174
+
175
+ let state,
176
+ digit,
177
+ port,
178
+ maxSpeed,
179
+ interval,
180
+ validity,
181
+ mode,
182
+ prevOutputs,
183
+ prevDurations,
184
+ prevToggles
185
+
186
+ // Digital Outputs
187
+ if (/^[1-4]{1}_(on|off)$/.test(data.instruction)) {
188
+ /*
189
+ AT+GTOUT=gv800w,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,F,0,0,0,0,0,FFFF$
190
+ AT+GTOUT=gv800w,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,0426$
191
+ */
192
+ let _data = data.instruction.split('_')
193
+ port = parseInt(_data[0], 10)
194
+ state = _data[1]
195
+ prevOutputs = data.previousOutput || {
196
+ '1': false,
197
+ '2': false,
198
+ '3': false,
199
+ '4': false,
200
+ '5': false
201
+ }
202
+ prevDurations = data.previousDuration || {
203
+ '1': 0,
204
+ '2': 0,
205
+ '3': 0,
206
+ '4': 0,
207
+ '5': 0
208
+ }
209
+ prevToggles = data.previousToggle || {
210
+ '1': 0,
211
+ '2': 0,
212
+ '3': 0,
213
+ '4': 0,
214
+ '5': 0
215
+ }
216
+ const outputs = Object.keys(prevOutputs).map(
217
+ key => (prevOutputs[key] === true ? 1 : 0)
218
+ )
219
+ outputs[0] = !outputs[0] ? 0 : outputs[0]
220
+ outputs[1] = !outputs[1] ? 0 : outputs[1]
221
+ outputs[2] = !outputs[2] ? 0 : outputs[2]
222
+ outputs[3] = !outputs[3] ? 0 : outputs[3]
223
+ outputs[4] = !outputs[4] ? 0 : outputs[4]
224
+ digit = state === 'on' ? 1 : 0
225
+ outputs[port - 1] = digit
226
+ const do1 = `${outputs[0]},${prevDurations['1']},${prevToggles['1']}`
227
+ const do2 = `${outputs[1]},${prevDurations['2']},${prevToggles['2']}`
228
+ const do3 = `${outputs[2]},${prevDurations['3']},${prevToggles['3']}`
229
+ const do4 = `${outputs[3]},${prevDurations['4']},${prevToggles['4']}`
230
+ const do5 = `${outputs[4]},${prevDurations['5']},${prevToggles['5']}`
231
+ const longOperation = data.longOperation || false ? '1' : '0'
232
+ const dosReport = data.dosReport || false ? '1' : '0'
233
+ if (data.device_serie === 'GV') {
234
+ command = `AT+GTOUT=${password},${do1},${do2},${do3},${do4},${longOperation},${dosReport},,,${serialId}$`
235
+ } else if (data.device_serie === 'GMT') {
236
+ command = `AT+GTOUT=${password},${do1},${do2},,,,,,,,${serialId}$`
237
+ } else if (data.device_serie === 'GV800') {
238
+ command = `AT+GTOUT=${password},${do1},${do2},${do3},${do4},${do5},${longOperation},${dosReport},0,0,0,0,${serialId}$`
239
+ } else {
240
+ command = `AT+GTOUT=${password},${do1},${do2},${do3},${do4},${longOperation},${dosReport},,,${serialId}$`
241
+ }
242
+ } else if (data.instruction === 'clear_mem') {
243
+ if (data.device_serie === 'GV') {
244
+ command = `AT+GTRTO=${password},4,BUF,,,,,${serialId}$`
245
+ } else if (data.device_serie === 'GMT') {
246
+ command = `AT+GTRTO=${password},D,,,,,,${serialId}$`
247
+ } else {
248
+ command = `AT+GTRTO=${password},4,BUF,,,,,${serialId}$`
249
+ }
250
+ } else if (/^set_speed_(on|off)(E)?$/.test(data.instruction)) {
251
+ maxSpeed = data.speed || 100
252
+ state = data.instruction.split('_')[2]
253
+ validity = data.times || 10
254
+ interval = data.interval || 300
255
+ mode = /on(E)?/.test(state) ? 4 : 0
256
+ if (data.device_serie === 'GMT' || password === 'gv55') {
257
+ mode = /on(E)?/.test(state) ? 3 : 0
258
+ }
259
+ command = `AT+GTSPD=${password},${mode},0,${maxSpeed},${validity},${interval},0,0,0,0,,,,,,,,,,,,${serialId}$`
260
+ } else if (data.instruction === 'Custom') {
261
+ command = data.command
262
+ } else if (/^reboot$/.test(data.instruction)) {
263
+ command = `AT+GTRTO=${password},3,,,,,,${serialId}$`
264
+ } else if (data.instruction === 'set_driver') {
265
+ const mode = data.mode || 1
266
+ const count = data.count || 1
267
+ const ids = data.driverID
268
+ const reportMode = data.reportMode || 1
269
+ command = `AT+GTIDA=${password},${mode},1,${count},${ids},30,${reportMode},,,,,1,0,0,0,,,,,${serialId}$`
270
+ } else if (data.instruction === 'jamming_detection_configuration') {
271
+ // Jammer configuration
272
+ mode = data.mode || '2' // Modes: 1:JDS, 2:JDR, 0:Disabled
273
+ command = `AT+GTJDC=${password},${mode},25,,5,10,10,,0,0,0,0,,${serialId}$`
274
+ } else if (data.instruction === 'jamming_behavior_settings') {
275
+ mode = data.mode || '1' // Modes: 0:Disable, 1:Enable
276
+ maxSpeed = data.speed || '30'
277
+ command = `AT+GTJBS=${password},${mode},,10,10,60,30,3600,1,${maxSpeed},120,,,,${serialId}$`
278
+ } else if (data.instruction === 'jamming_gps_configuration') {
279
+ mode = data.mode || '1' // Modes: 0:Disable, 1:Enable
280
+ command = `AT+GTGPJ=${password},${mode},15,3,,,,,0,0,0,0,,${serialId}$`
281
+ } else if (/^temp_alarm_(on|off)(E)?$/.test(data.instruction)) {
282
+ // Temperature Alarm
283
+ let _data = data.instruction.split('_')
284
+ state = _data[2]
285
+ mode = /on(E)?/.test(state) ? 3 : 0
286
+ const alarmId = data.alarmId || 0
287
+ const sensorId = data.sensorId || '0000000000000000'
288
+ const minTemp = data.minTemp || 0
289
+ const maxTemp = data.maxTemp || 0
290
+ command = `AT+GTTMP=${password},${alarmId},${mode},${sensorId},,,${minTemp},${maxTemp},,,2,10,,,0,0,0,0,,,,,${serialId}$`
291
+ } else if (/^copiloto_temp_alarm_(on|off)(E)?$/.test(data.instruction)) {
292
+ // AT+GTDAT=gv300w,2,,>CMD3005,60,18,0,5,-3<,0,,,,FFFF$
293
+ // Temperature Alarm
294
+ const interval = data.interval || 0
295
+ const minTemp1 = data.minTemp1 || 0
296
+ const maxTemp1 = data.maxTemp1 || 0
297
+ const minTemp2 = data.minTemp2 || 0
298
+ const maxTemp2 = data.maxTemp2 || 0
299
+ command = `AT+GTDAT=${password},2,,>CMD3005,${interval},${maxTemp1},${minTemp1},${maxTemp2},${minTemp2}<,0,,,,${serialId}$`
300
+ } else if (data.instruction === 'get_current_position') {
301
+ // Request current position
302
+ command = `AT+GTRTO=${password},1,,,,,,${serialId}$`
303
+ }
304
+ return command
305
+ }
306
+
307
+ module.exports = {
308
+ parse: parse,
309
+ isQueclink: isQueclink,
310
+ isHeartBeat: isHeartBeat,
311
+ getAckHeartBeat: getAckHeartBeat,
312
+ getAck: getAck,
313
+ parseCommand: parseCommand,
314
+ getRebootCommand: getRebootCommand,
315
+ getImei: getImei
316
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "SETOVERSPEEDALARM": "Set over speed alarm",
3
+ "SETIOSWITCH": "Set IO Switch",
4
+ "CLEARBUF": "Clear internal buffer",
5
+ "default": "Last action"
6
+ }
@@ -0,0 +1,150 @@
1
+ {
2
+ "SETOVERSPEEDALARM": "Ajuste de la alarma de exceso de velocidad",
3
+ "SETIOSWITCH": "Cambio de estado en las salidas digitales",
4
+ "CLEARBUF": "Memoria interna vaciada",
5
+ "REBOOT": "Dispositivo Reiniciado",
6
+ "ANTIJAMMER": "Anti-Jammer configurado",
7
+ "REQUESTCURRENTPOSITION": "Solicitud de posición actual",
8
+ "default": "Última acción",
9
+ "GTIDA": {
10
+ "1": "Conductor identificado autorizado",
11
+ "0": "Conductor identificado no autorizado",
12
+ "2": "Término de sesión de conductor identificado."
13
+ },
14
+ "GTFLA": "Combustible reducido en consumption%",
15
+ "GTTMP": {
16
+ "0": "Temperatura fuera de rango ()",
17
+ "1": "Regreso a temperatura dentro de rango ()"
18
+ },
19
+ "GTCAN": "Reporte CAN BUS: data",
20
+ "GTJES": "Resumen de datos OBDII",
21
+ "GTOSM": {
22
+ "0": {
23
+ "0": "RPM dentro del rango permitido",
24
+ "1": "RPM fuera del rango permitido"
25
+ },
26
+ "1": {
27
+ "0": "Velocidad dentro del rango permitido",
28
+ "1": "Velocidad fuera del rango permitido"
29
+ },
30
+ "2": {
31
+ "0": "Temperatura del coolant dentro del rango permitido",
32
+ "1": "Temperatura del coolant fuera del rango permitido"
33
+ },
34
+ "3": {
35
+ "0": "Consumo de combustible dentro del rango permitido",
36
+ "1": "Consumo de combustible fuera del rango permitido"
37
+ },
38
+ "4": {
39
+ "0": "Consumo de combustible dentro del rango permitido",
40
+ "1": "Consumo de combustible fuera del rango permitido"
41
+ },
42
+ "5": {
43
+ "0": "MIL dentro del rango permitido",
44
+ "1": "MIL fuera del rango permitido"
45
+ },
46
+ "6": {
47
+ "0": "Acelerador dentro del rango permitido",
48
+ "1": "Acelerador fuera del rango permitido"
49
+ },
50
+ "7": {
51
+ "0": "Carga del motor dentro del rango permitido",
52
+ "1": "Carga del motor fuera del rango permitido"
53
+ },
54
+ "8": {
55
+ "0": "Nivel de combustible dentro del rango permitido",
56
+ "1": "Nive de combustible bajo"
57
+ }
58
+ },
59
+ "GTOPN": "OBDII Conectado",
60
+ "GTOPF": "OBDII Desconectado",
61
+ "GTGSS": {
62
+ "1": "Señal GPS recuperada",
63
+ "0": "Sin señal GPS"
64
+ },
65
+ "GTPDP": "Conexión GPRS establecida",
66
+ "GTSTT": "Movimiento de dispositivo detectado",
67
+ "GTHBD": "Conexión viva",
68
+ "GTRMD": {
69
+ "1": "Roaming activado",
70
+ "0": "Roaming desactivado"
71
+ },
72
+ "GTNMR": {
73
+ "1": "Dispositivo en movimiento",
74
+ "0": "Dispositivo detenido"
75
+ },
76
+ "GTSTP": "Partida de vehículo finalizada",
77
+ "GTLSP": "Partida de vehículo finalizada",
78
+ "GTSTR": "Partida de vehículo iniciada",
79
+ "GTANT": {
80
+ "0": "Antena GPS conectada",
81
+ "1": "Antena GPS desconectada"
82
+ },
83
+ "GTAIS": {
84
+ "2": "Botón SOS presionado"
85
+ },
86
+ "GTMAI": {
87
+ "2": "Botón SOS presionado"
88
+ },
89
+ "GTEPS": "Batería de Fuente de Poder Baja",
90
+ "GTJDR": "Vehículo Jammeado",
91
+ "GTJDS": {
92
+ "1": "Cese de Jammer",
93
+ "2": "Vehículo Jammeado"
94
+ },
95
+ "GTGPJ": {
96
+ "0": "GPS Jammer Desconocido",
97
+ "1": "GPS Jammer insignificante",
98
+ "2": "Advertencia de Jammer GPS",
99
+ "3": "Vehículo Jammeado (GPS)"
100
+ },
101
+ "GTIDF": "Vehículo fuera de Ralenti",
102
+ "GTIDN": "Vehículo en Ralenti",
103
+ "GTBPL": "Batería baja",
104
+ "GTSTC": "Se dejo de cargar batería",
105
+ "GTBTC": "Cargando batería",
106
+ "GTEPF": "Desconectado de la fuente de poder",
107
+ "GTMPF": "Desconectado de la fuente de poder",
108
+ "GTMPN": "Conectado a la fuente de poder",
109
+ "GTEMP": "Conectado a la fuente de poder",
110
+ "GTPFA": "Dispositivo Apagado",
111
+ "GTPNA": "Dispositivo Encendido",
112
+ "GTIGN": "Entrada digital 1 activada",
113
+ "GTIGF": "Entrada digital 1 desactivada",
114
+ "GTIGL": {
115
+ "1": "Entrada digital 1 activada",
116
+ "0": "Entrada digital 1 desactivada"
117
+ },
118
+ "GTSPD": {
119
+ "0": "Exceso de Velocidad",
120
+ "1": "Retorno a velocidad permitida"
121
+ },
122
+ "GTSOS": "Botón SOS presionado",
123
+ "GTTOW": "Vehículo remolcado",
124
+ "GTDIS": {
125
+ "1": "Entrada digital port activada",
126
+ "0": "Entrada digital port desactivada"
127
+ },
128
+ "GTDOS": {
129
+ "1": "Salida digital port activada",
130
+ "0": "Salida digital port desactivada"
131
+ },
132
+ "GTNMD": {
133
+ "0": "Vehículo en movimiento",
134
+ "1": "Vehículo detenido"
135
+ },
136
+ "GTDAT": "Datos del puerto serial recibidos",
137
+ "GTSOA": "Compartimento tarjeta SIM abierto",
138
+ "GTHBM": {
139
+ "0": "Frenada Brusca",
140
+ "1": "Aceleración Brusca",
141
+ "2": "Giro Brusco",
142
+ "3": "Frenada Brusca Girando",
143
+ "4": "Aceleración Brusca Girando",
144
+ "5": "Comportamiento Brusco Desconocido"
145
+ },
146
+ "GTDOG": "Dispositivo reiniciado por protocolo",
147
+ "GTGSM": "GSM Report",
148
+ "GTCRA": "Posible choque detectado",
149
+ "GTDTT": "Data transparente del puerto serial"
150
+ }