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/gmt100.js ADDED
@@ -0,0 +1,486 @@
1
+ 'use strict'
2
+ const utils = require('./utils.js')
3
+
4
+ /*
5
+ Parses messages data from GMT100 devices
6
+ */
7
+ const parse = raw => {
8
+ raw = raw.substr(0, raw.length - 1)
9
+
10
+ const parsedData = raw.split(',')
11
+ const command = parsedData[0].split(':')
12
+
13
+ let history = false
14
+ if (utils.patterns.buffer.test(command[0])) {
15
+ history = true
16
+ }
17
+
18
+ let data = {
19
+ raw: `${raw.toString()}$`,
20
+ manufacturer: 'queclink',
21
+ device: 'Queclink-GMT100',
22
+ type: 'data',
23
+ imei: parsedData[2],
24
+ protocolVersion: utils.getProtocolVersion(parsedData[1]),
25
+ temperature: null,
26
+ history: history,
27
+ sentTime: utils.parseDate(parsedData[parsedData.length - 2]),
28
+ serialId: parseInt(parsedData[parsedData.length - 1], 16),
29
+ hourmeter: null
30
+ }
31
+
32
+ // GPS
33
+ if (command[1] === 'GTFRI') {
34
+ data = Object.assign(data, {
35
+ alarm: utils.getAlarm(command[1], null),
36
+ loc: {
37
+ type: 'Point',
38
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
39
+ },
40
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
41
+ gpsStatus: utils.checkGps(
42
+ parseFloat(parsedData[11]),
43
+ parseFloat(parsedData[12])
44
+ ),
45
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
46
+ status: {
47
+ // parsedData[24]
48
+ raw: parsedData[24] + parsedData[25],
49
+ sos: false,
50
+ input: {
51
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[24]), 2)[1] === '1',
52
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[24]), 2)[0] === '1'
53
+ },
54
+ output: {
55
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[25]), 2)[1] === '1',
56
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[25]), 2)[0] === '1'
57
+ },
58
+ charge: parseFloat(parsedData[4]) > 5
59
+ },
60
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
61
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
62
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
63
+ voltage: {
64
+ battery: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null, // percentage
65
+ inputCharge:
66
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
67
+ ada: parsedData[21] !== '' ? parseFloat(parsedData[21]) / 1000 : null
68
+ },
69
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
70
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
71
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
72
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
73
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null
74
+ })
75
+ } else if (command[1] === 'GTHBD') {
76
+ // Heartbeat. It must response an ACK command
77
+ data = Object.assign(data, {
78
+ alarm: utils.getAlarm(command[1], null)
79
+ })
80
+ } else if (command[1] === 'GTINF') {
81
+ // General Info Report
82
+ data = Object.assign(data, {
83
+ alarm: utils.getAlarm(command[1], null),
84
+ state: utils.states[parsedData[4]],
85
+ gsmInfo: {
86
+ SIM_ICC: parsedData[5],
87
+ RSSI_dBm: parsedData[6],
88
+ RSSI_quality:
89
+ parsedData[7] !== ''
90
+ ? 100 * parseInt(parseFloat(parsedData[7]) / 7, 10)
91
+ : null // Percentage
92
+ },
93
+ backupBattery: {
94
+ using: parsedData[10] === '1',
95
+ voltage: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
96
+ charging: parsedData[12] === '1'
97
+ },
98
+ externalGPSAntenna: parsedData[15] === '0',
99
+ status: {
100
+ // parsedData[24]
101
+ raw: parsedData[18] + parsedData[19],
102
+ sos: false,
103
+ input: {
104
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[20]), 2)[1] === '1',
105
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[20]), 2)[0] === '1'
106
+ },
107
+ output: {
108
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[21]), 2)[1] === '1',
109
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[21]), 2)[0] === '1'
110
+ },
111
+ charge: parsedData[8] === '1'
112
+ },
113
+ voltage: {
114
+ battery:
115
+ parsedData[11] !== ''
116
+ ? parseInt(100 * (parseFloat(parsedData[11]) / 4.5), 10)
117
+ : null, // percentage
118
+ inputCharge:
119
+ parsedData[9] !== '' ? parseFloat(parsedData[9]) / 1000 : null,
120
+ ada: parsedData[18] !== '' ? parseFloat(parsedData[18]) / 1000 : null
121
+ },
122
+ lastFixUTCTime:
123
+ parsedData[16] !== '' ? utils.parseDate(parsedData[16]) : null,
124
+ timezoneOffset: parsedData[22]
125
+ })
126
+ } else if (
127
+ command[1] === 'GTTOW' ||
128
+ command[1] === 'GTDIS' ||
129
+ command[1] === 'GTIOB' ||
130
+ command[1] === 'GTSPD' ||
131
+ command[1] === 'GTSOS' ||
132
+ command[1] === 'GTRTL' ||
133
+ command[1] === 'GTDOG' ||
134
+ command[1] === 'GTIGL' ||
135
+ command[1] === 'GTHBM'
136
+ ) {
137
+ // Common Alarms
138
+ data = Object.assign(data, {
139
+ alarm: utils.getAlarm(command[1], parsedData[5], 'GMT100'),
140
+ loc: {
141
+ type: 'Point',
142
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
143
+ },
144
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
145
+ gpsStatus: utils.checkGps(
146
+ parseFloat(parsedData[11]),
147
+ parseFloat(parsedData[12])
148
+ ),
149
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
150
+ status: null,
151
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
152
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
153
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
154
+ voltage: {
155
+ battery: null,
156
+ inputCharge: null,
157
+ ada: null
158
+ },
159
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
160
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
161
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
162
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
163
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null
164
+ })
165
+ } else if (command[1] === 'GTEPS') {
166
+ // External low battery
167
+ data = Object.assign(data, {
168
+ alarm: utils.getAlarm(command[1], parsedData[5]),
169
+ loc: {
170
+ type: 'Point',
171
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
172
+ },
173
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
174
+ gpsStatus: utils.checkGps(
175
+ parseFloat(parsedData[11]),
176
+ parseFloat(parsedData[12])
177
+ ),
178
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
179
+ status: null,
180
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
181
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
182
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
183
+ voltage: {
184
+ battery: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null, // percentage
185
+ inputCharge:
186
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
187
+ ada: parsedData[21] !== '' ? parseFloat(parsedData[21]) / 1000 : null
188
+ },
189
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
190
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
191
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
192
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
193
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null
194
+ })
195
+ } else if (command[1] === 'GTAIS') {
196
+ // Low voltage from analog input
197
+ data = Object.assign(data, {
198
+ alarm: utils.getAlarm(command[1], parsedData[5]),
199
+ loc: {
200
+ type: 'Point',
201
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
202
+ },
203
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
204
+ gpsStatus: utils.checkGps(
205
+ parseFloat(parsedData[11]),
206
+ parseFloat(parsedData[12])
207
+ ),
208
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
209
+ status: null,
210
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
211
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
212
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
213
+ voltage: {
214
+ battery: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null, // percentage
215
+ inputCharge:
216
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
217
+ ada: parsedData[21] !== '' ? parseFloat(parsedData[21]) / 1000 : null
218
+ },
219
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
220
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
221
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
222
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
223
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null
224
+ })
225
+ } else if (
226
+ command[1] === 'GTPNA' ||
227
+ command[1] === 'GTPFA' ||
228
+ command[1] === 'GTPDP'
229
+ ) {
230
+ // Event report (It uses the last GPS data and MCC info)
231
+ data = Object.assign(data, {
232
+ alarm: utils.getAlarm(command[1], null),
233
+ loc: null,
234
+ speed: null,
235
+ gpsStatus: null,
236
+ hdop: null,
237
+ status: null,
238
+ azimuth: null,
239
+ altitude: null,
240
+ datetime: parsedData[4] !== '' ? utils.parseDate(parsedData[4]) : null,
241
+ voltage: {
242
+ battery: null,
243
+ inputCharge: null,
244
+ ada: null
245
+ },
246
+ mcc: null,
247
+ mnc: null,
248
+ lac: null,
249
+ cid: null,
250
+ odometer: null
251
+ })
252
+ } else if (
253
+ command[1] === 'GTMPN' ||
254
+ command[1] === 'GTMPF' ||
255
+ command[1] === 'GTCRA' ||
256
+ command[1] === 'GTJDR' ||
257
+ command[1] === 'GTSOA'
258
+ ) {
259
+ data = Object.assign(data, {
260
+ alarm: utils.getAlarm(command[1], null),
261
+ loc: {
262
+ type: 'Point',
263
+ coordinates: [parseFloat(parsedData[8]), parseFloat(parsedData[9])]
264
+ },
265
+ speed: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
266
+ gpsStatus: utils.checkGps(
267
+ parseFloat(parsedData[8]),
268
+ parseFloat(parsedData[9])
269
+ ),
270
+ hdop: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
271
+ status: null,
272
+ azimuth: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
273
+ altitude: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
274
+ datetime: parsedData[10] !== '' ? utils.parseDate(parsedData[10]) : null,
275
+ voltage: {
276
+ battery: null,
277
+ inputCharge: null,
278
+ ada: null
279
+ },
280
+ mcc: parsedData[11] !== '' ? parseInt(parsedData[11], 10) : null,
281
+ mnc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
282
+ lac: parsedData[13] !== '' ? parseInt(parsedData[13], 16) : null,
283
+ cid: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
284
+ odometer: null
285
+ })
286
+ } else if (
287
+ command[1] === 'GTJDS' ||
288
+ command[1] === 'GTANT' ||
289
+ command[1] === 'GTRMD' ||
290
+ command[1] === 'GTNMD'
291
+ ) {
292
+ data = Object.assign(data, {
293
+ alarm: utils.getAlarm(command[1], parsedData[4]),
294
+ loc: {
295
+ type: 'Point',
296
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
297
+ },
298
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
299
+ gpsStatus: utils.checkGps(
300
+ parseFloat(parsedData[9]),
301
+ parseFloat(parsedData[10])
302
+ ),
303
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
304
+ status: null,
305
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
306
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
307
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
308
+ voltage: {
309
+ battery: null,
310
+ inputCharge: null,
311
+ ada: null
312
+ },
313
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
314
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
315
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
316
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
317
+ odometer: null
318
+ })
319
+ } else if (command[1] === 'GTBPL') {
320
+ data = Object.assign(data, {
321
+ alarm: utils.getAlarm(command[1], null),
322
+ loc: {
323
+ type: 'Point',
324
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
325
+ },
326
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
327
+ gpsStatus: utils.checkGps(
328
+ parseFloat(parsedData[9]),
329
+ parseFloat(parsedData[10])
330
+ ),
331
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
332
+ status: null,
333
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
334
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
335
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
336
+ voltage: {
337
+ battery: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
338
+ inputCharge: null,
339
+ ada: null
340
+ },
341
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
342
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
343
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
344
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
345
+ odometer: null
346
+ })
347
+ } else if (command[1] === 'GTIGN' || command[1] === 'GTIGF') {
348
+ data = Object.assign(data, {
349
+ alarm: utils.getAlarm(command[1], parsedData[4]),
350
+ loc: {
351
+ type: 'Point',
352
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
353
+ },
354
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
355
+ gpsStatus: utils.checkGps(
356
+ parseFloat(parsedData[9]),
357
+ parseFloat(parsedData[10])
358
+ ),
359
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
360
+ status: null,
361
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
362
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
363
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
364
+ voltage: {
365
+ battery: null,
366
+ inputCharge: null,
367
+ ada: null
368
+ },
369
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
370
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
371
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
372
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
373
+ odometer: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null
374
+ })
375
+ } else if (command[1] === 'GTIDN' || command[1] === 'GTIDF') {
376
+ data = Object.assign(data, {
377
+ alarm: utils.getAlarm(command[1], parsedData[5]),
378
+ loc: {
379
+ type: 'Point',
380
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
381
+ },
382
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
383
+ gpsStatus: utils.checkGps(
384
+ parseFloat(parsedData[10]),
385
+ parseFloat(parsedData[11])
386
+ ),
387
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
388
+ status: null,
389
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
390
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
391
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
392
+ voltage: {
393
+ battery: null,
394
+ inputCharge: null,
395
+ ada: null
396
+ },
397
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
398
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
399
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
400
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
401
+ odometer: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null
402
+ })
403
+ } else if (
404
+ command[1] === 'GTSTR' ||
405
+ command[1] === 'GTSTP' ||
406
+ command[1] === 'GTLSP'
407
+ ) {
408
+ data = Object.assign(data, {
409
+ alarm: utils.getAlarm(command[1], null),
410
+ loc: {
411
+ type: 'Point',
412
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
413
+ },
414
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
415
+ gpsStatus: utils.checkGps(
416
+ parseFloat(parsedData[10]),
417
+ parseFloat(parsedData[11])
418
+ ),
419
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
420
+ status: null,
421
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
422
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
423
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
424
+ voltage: {
425
+ battery: null,
426
+ inputCharge: null,
427
+ ada: null
428
+ },
429
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
430
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
431
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
432
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
433
+ odometer: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null
434
+ })
435
+ } else if (command[1] === 'GTSTT') {
436
+ // Motion State Changed
437
+ data = Object.assign(data, {
438
+ alarm: utils.getAlarm(command[1], null),
439
+ loc: {
440
+ type: 'Point',
441
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
442
+ },
443
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
444
+ gpsStatus: utils.checkGps(
445
+ parseFloat(parsedData[9]),
446
+ parseFloat(parsedData[10])
447
+ ),
448
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
449
+ status: null,
450
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
451
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
452
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
453
+ voltage: {
454
+ battery: null,
455
+ inputCharge: null,
456
+ ada: null
457
+ },
458
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
459
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
460
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
461
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
462
+ odometer: null,
463
+ hourmeter: null
464
+ })
465
+ } else {
466
+ data = Object.assign(data, {
467
+ alarm: utils.getAlarm(command[1], null)
468
+ })
469
+ }
470
+ // Check gps data
471
+ if (data.loc !== null && typeof data.loc !== 'undefined') {
472
+ if (
473
+ data.loc.coordinates[0] === 0 ||
474
+ isNaN(data.loc.coordinates[0]) ||
475
+ data.loc.coordinates[1] === 0 ||
476
+ isNaN(data.loc.coordinates[1])
477
+ ) {
478
+ data.loc = null
479
+ }
480
+ }
481
+ return data
482
+ }
483
+
484
+ module.exports = {
485
+ parse: parse
486
+ }