Skip to content

Commit

Permalink
feat(parser): Add messages to parse responses. Modularize all compone…
Browse files Browse the repository at this point in the history
…nts.
  • Loading branch information
lgaticaq committed Sep 6, 2016
1 parent 874f4ba commit e064d60
Show file tree
Hide file tree
Showing 17 changed files with 2,031 additions and 1,333 deletions.
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![dependency Status](https://img.shields.io/david/lgaticaq/tz-parser.svg?style=flat-square)](https://david-dm.org/lgaticaq/tz-parser#info=dependencies)
[![devDependency Status](https://img.shields.io/david/dev/lgaticaq/tz-parser.svg?style=flat-square)](https://david-dm.org/lgaticaq/tz-parser#info=devDependencies)

> Parse raw data from TZ-AVL devices
> Parse raw data from TZ-AVL devices (AVL-05, AVL-08, AVL-201)
## Installation

Expand All @@ -20,34 +20,38 @@ npm i -S tz-parser

[Try on Tonic](https://tonicdev.com/npm/tz-parser)
```js
import tz from 'tz-parser'
const tz = require('tz-parser');

const raw = new Buffer('$$B6869444005480041|91$GPRMC,194329.000,A,3321.6735,S,07030.7640,W,0.00,0.00,090216,,,A*6C|02.1|01.3|01.7|000000000000|20160209194326|13981188|00000000|32D3A03F|0000|0.6376|0100|7B20\r\n');
const raw = new Buffer('$$B6869444005480041|AA$GPRMC,194329.000,A,3321.6735,S,07030.7640,W,0.00,0.00,090216,,,A*6C|02.1|01.3|01.7|000000000000|20160209194326|13981188|00000000|32D3A03F|0000|0.6376|0100|995F\r\n');
const data = tz.parse(raw);
/*{
raw: '$$B6869444005480041|91$GPRMC,194329.000,A,3321.6735,S,07030.7640,W,0.00,0.00,090216,,,A*6C|02.1|01.3|01.7|000000000000|20160209194326|13981188|00000000|32D3A03F|0000|0.6376|0100|7B20\r\n',
device: 'TZ-AVL05',
raw: '$$B6869444005480041|AA$GPRMC,194329.000,A,3321.6735,S,07030.7640,W,0.00,0.00,090216,,,A*6C|02.1|01.3|01.7|000000000000|20160209194326|13981188|00000000|32D3A03F|0000|0.6376|0100|995F\r\n',
device: 'tz',
model: 'TZ-AVL05',
type: 'data',
imei: '869444005480041',
alarm: { type: 'Sleep', status: true },
loc: { type: 'Point', coordinates: [ -70.51273333, -33.361225 ] },
gpsStatus: true,
alarm: {type: 'Gps'},
loc: {
type: 'Point',
coordinates: [-70.51273333333333, -33.361225]
},
speed: 0,
gpsStatus: true,
track: '0.00',
magneticVariation: null,
gpsMode: 'Autonomous'
gpsMode: 'Autonomous',
pdop: 2.1,
hdop: 1.3,
vdop: 1.7,
status: {
raw: '000000000000',
sos: false,
input: { '1': false, '2': false, '3': false, '4': false, '5': false },
output: { '1': false, '2': false },
input: {'1': false, '2': false, '3': false, '4': false, '5': false},
output: {'1': false, '2': false},
charge: true
},
datetime: Tue Feb 09 2016 19:43:26 GMT+0000 (UTC),
voltage: { battery: 3.98, inputCharge: 11.88, ada: 0, adb: 0 },
datetime: 2016-02-09T19:43:26.000Z,
voltage: {battery: 3.98, inputCharge: 11.88, ada: 0, adb: 0},
lac: 13011,
cid: 41023,
temperature: 0,
Expand Down
58 changes: 58 additions & 0 deletions src/avl05.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';

const moment = require('moment');
const nmea = require('node-nmea');
const patterns = require('./patterns');
const utils = require('./utils');

module.exports = raw => {
const match = patterns.avl05.exec(raw.toString());
const gprmcData = nmea.parse(match[4]);
const data = {
raw: match[0],
device: 'tz',
model: 'TZ-AVL05',
type: 'data',
imei: match[2],
alarm: utils.getAlarm(match[3]),
loc: gprmcData.loc ? gprmcData.loc.geojson : null,
speed: gprmcData.speed ? gprmcData.speed.kmh : null,
gpsStatus: gprmcData.gps,
track: gprmcData.track,
magneticVariation: gprmcData.magneticVariation,
gpsMode: gprmcData.mode,
pdop: parseFloat(match[17]),
hdop: parseFloat(match[18]),
vdop: parseFloat(match[19]),
status: {
raw: match.slice(20, 32).join(''),
sos: match[20] === '1',
input: {
'1': match[24] === '1',
'2': match[25] === '1',
'3': match[26] === '1',
'4': match[27] === '1',
'5': match[21] === '1'
},
output: {
'1': match[28] === '1',
'2': match[29] === '1'
},
charge: match[33] === '1'
},
datetime: moment(`${match[32]}+00:00`, 'YYYYMMDDHHmmssZZ').toDate(),
voltage: {
battery: parseInt(match[34], 10) / 100,
inputCharge: parseInt(match[35], 10) / 100,
ada: parseInt(match[36], 10) / 100,
adb: parseInt(match[37], 10) / 100
},
lac: parseInt(match[38], 16),
cid: parseInt(match[39], 16),
temperature: parseFloat(match[40]) / 10,
odometer: parseFloat(match[41]),
serialId: parseInt(match[42], 10),
valid: utils.isValid(match[0], parseInt(match[1], 16), parseInt(match[43], 16))
};
return data;
};
61 changes: 61 additions & 0 deletions src/avl08.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict';

const moment = require('moment');
const nmea = require('node-nmea');
const patterns = require('./patterns');
const utils = require('./utils');

module.exports = raw => {
const match = patterns.avl08.exec(raw.toString());
const gprmcData = nmea.parse(match[4]);
const data = {
raw: match[0],
device: 'tz',
model: 'TZ-AVL08',
type: 'data',
imei: match[2],
alarm: utils.getAlarm(match[3]),
loc: gprmcData.loc ? gprmcData.loc.geojson : null,
speed: gprmcData.speed ? gprmcData.speed.kmh : null,
gpsStatus: gprmcData.gps,
track: gprmcData.track,
magneticVariation: gprmcData.magneticVariation,
gpsMode: gprmcData.mode,
pdop: parseFloat(match[17]),
hdop: parseFloat(match[18]),
vdop: parseFloat(match[19]),
status: {
raw: match.slice(20, 32).join(''),
sos: match[20] === '1',
input: {
'1': match[24] === '1',
'2': match[25] === '1',
'3': match[26] === '1',
'4': match[27] === '1',
'5': match[21] === '1'
},
output: {
'1': match[28] === '1',
'2': match[29] === '1',
'3': match[30] === '1',
'4': match[31] === '1'
},
charge: match[33] === '1'
},
datetime: moment(`${match[32]}+00:00`, 'YYYYMMDDHHmmssZZ').toDate(),
voltage: {
battery: parseInt(match[34], 10) / 100,
inputCharge: parseInt(match[35], 10) / 100,
ada: parseInt(match[36], 10) / 100,
adb: parseInt(match[37], 10) / 100
},
lac: parseInt(match[38], 16),
cid: parseInt(match[39], 16),
temperature: parseFloat(match[40]) / 10,
odometer: parseFloat(match[41]),
serialId: parseInt(match[42], 10),
rfidNumber: match[43] || null,
valid: utils.isValid(match[0], parseInt(match[1], 16), parseInt(match[44], 16))
};
return data;
};
52 changes: 52 additions & 0 deletions src/avl201.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use strict';

const moment = require('moment');
const nmea = require('node-nmea');
const patterns = require('./patterns');
const utils = require('./utils');

module.exports = raw => {
const match = patterns.avl201.exec(raw.toString());
const gprmcData = nmea.parse(match[4]);
const data = {
raw: match[0],
device: 'tz',
model: 'TZ-AVL201',
type: 'data',
imei: match[2],
alarm: utils.getAlarm(match[3]),
loc: gprmcData.loc ? gprmcData.loc.geojson : null,
speed: gprmcData.speed ? gprmcData.speed.kmh : null,
gpsStatus: gprmcData.gps,
track: gprmcData.track,
magneticVariation: gprmcData.magneticVariation,
gpsMode: gprmcData.mode,
pdop: parseFloat(match[17]),
hdop: parseFloat(match[18]),
vdop: parseFloat(match[19]),
status: {
raw: match.slice(20, 32).join(''),
input: {
'1': match[22] === '1',
'2': match[23] === '1',
'3': match[20] === '1'
},
output: {
'1': match[30] === '1'
},
charge: match[33] === '1'
},
datetime: moment(`${match[32]}+00:00`, 'YYYYMMDDHHmmssZZ').toDate(),
voltage: {
battery: parseInt(match[34], 10) / 100,
inputCharge: parseInt(match[35], 10) / 100
},
lac: parseInt(match[36], 16),
cid: parseInt(match[37], 16),
temperature: parseFloat(match[38]) / 10,
odometer: parseFloat(match[39]),
serialId: parseInt(match[40], 10),
valid: utils.isValid(match[0], parseInt(match[1], 16), parseInt(match[41], 16))
};
return data;
};
146 changes: 146 additions & 0 deletions src/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
'use strict';

const parseSetUserPassword = data => {
return `*${data.password},001,${data.newPassword}#`;
};

const parseSetIoSwitch = data => {
const _data = data.instruction.split('_');
const ports = {'1': 'A', '2': 'B', '3': 'C', '4': 'D'};
return `*${data.password},025,${ports[_data[0]]},${_data[1] === 'on' ? 1 : 0}#`;
};

const parseSetSysSwitch = data => {
const state = data.instruction.split('_')[1];
return `*${data.password},016,${state === 'on' ? 1 : 0}#`;
};

const parseClearbuf = data => {
return `*${data.password},500#`;
};

const parseSetGprsInterval = data => {
return `*${data.password},018,${data.interval},${data.times || 999}#`;
};

const parseSetPhoneSmsForSos = data => {
const state = data.instruction.split('_')[0];
return `*${data.password},003,0,${state === 'set' ? 1 : 0},00569${data.number},00569${data.number}#`;
};

const parseSetOverSpeedAlarm = data => {
const speed = data.speed || 100;
const state = data.instruction.split('_')[2];
const times = data.times || 10;
const interval = data.interval || 60;
const digit = /on(E)?/.test(state) ? 1 : 0;
return `*${data.password},005,${digit},${speed},${times},${interval}#`;
};

const parseSetpictureinterval = data => {
const interval = data.interval || 5;
const times = data.times || 1;
return `*${data.password},200,${interval},${times}#`;
};

const parseGetpicture = data => {
return `*${data.password},210#`;
};

const parseSetiopicture = data => {
const triggers = {on: 1, off: 2, both: 3};
const trigger = triggers[data.trigger || 'both'];
const number = data.number || 1;
return `*${data.password},201,${data.port},${trigger},${number}#`;
};

const parseCustom = data => {
return data.command;
};

const parseSetdataflash = data => {
const state = data.instruction.split('_')[2];
const digit = state === 'on' ? 1 : 0;
return `*${data.password},601,${digit}#`;
};

const parseSetTrembleSwitch = data => {
return `*${data.password},021,${data.sleep ? 1 : 0},${data.tremble ? 1 : 0}#`;
};

const parseSetTrembleToSleep = data => {
return `*${data.password},044,${data.time}#`;
};

const parseSetTrembleToWakeup = data => {
return `*${data.password},043,${data.time}#`;
};

const parseRboot = data => {
return `*${data.password},991#`;
};

const parseSetExtend2 = data => {
const a = data.a ? 1 : 0;
const b = data.b ? 1 : 0;
const c = data.c ? 1 : 0;
const d = data.d ? 1 : 0;
const e = data.e ? 1 : 0;
const f = data.f ? 1 : 0;
const g = data.g ? 1 : 0;
const h = data.h ? 1 : 0;
return `*${data.password},118,${a}${b}${c}${d}${e}${f}${g}${h}#`;
};

const parseSetHeartbeatSwitch = data => {
const state = data.instruction.split('_')[2];
const digit = state === 'on' ? 1 : 0;
return `*${data.password},040,${digit}#`;
};

const parseSetHeartbeatInterval = data => {
return `*${data.password},041,${data.times}#`;
};

const parseSetidle = data => {
const state = data.instruction.split('_')[2];
const digit = state === 'on' ? 1 : 0;
return `*${data.password},404,${digit},${data.times}#`;
};

const parseCommand = data => {
let command = null;
data.password = data.password || '000000';
const parsers = [
{pattern: /^set_password$/, parser: parseSetUserPassword},
{pattern: /^[1-4]{1}_(on|off)$/, parser: parseSetIoSwitch},
{pattern: /^gprs_(on|off)$/, parser: parseSetSysSwitch},
{pattern: /^clear_mem$/, parser: parseClearbuf},
{pattern: /^set_interval_gprs$/, parser: parseSetGprsInterval},
{pattern: /^(set|setoff)_sos_number(E)?$/, parser: parseSetPhoneSmsForSos},
{pattern: /^set_speed_(on|off)(E)?$/, parser: parseSetOverSpeedAlarm},
{pattern: /^picture$/, parser: parseSetpictureinterval},
{pattern: /^take_picture$/, parser: parseGetpicture},
{pattern: /^configure_io_picture$/, parser: parseSetiopicture},
{pattern: /^Custom$/, parser: parseCustom},
{pattern: /^set_memory_(on|off)$/, parser: parseSetdataflash},
{pattern: /^set_tremble$/, parser: parseSetTrembleSwitch},
{pattern: /^set_into_sleep$/, parser: parseSetTrembleToSleep},
{pattern: /^set_wake_up$/, parser: parseSetTrembleToWakeup},
{pattern: /^reboot$/, parser: parseRboot},
{pattern: /^set_extend$/, parser: parseSetExtend2},
{pattern: /^set_heartbeat_(on|off)$/, parser: parseSetHeartbeatSwitch},
{pattern: /^set_interval_heartbeat$/, parser: parseSetHeartbeatInterval},
{pattern: /^set_idling_(on|off)$/, parser: parseSetidle}
];
const parser = parsers.find(x => x.pattern.test(data.instruction));
if (parser) {
command = parser.parser(data);
}

return command;
};

module.exports = {
parseCommand: parseCommand
};
8 changes: 8 additions & 0 deletions src/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

const patterns = require('./patterns');

module.exports = data => {
const match = patterns.receiveErr.exec(data.toString());
return {device: 'tz', type: 'error', command: match[0]};
};

0 comments on commit e064d60

Please sign in to comment.