22
33const utils = require ( './utils' ) ;
44const inbound = require ( './inbound' ) ;
5+ const redis = require ( 'redis' ) ;
6+ const Promise = require ( 'bluebird' ) ;
7+
8+ let _client ;
59
610const patterns = {
711 data : / ( 4 d 4 3 4 7 5 0 [ A - F 0 - 9 ] { 132 } ) / gi
812} ;
913
10- const getData = raw => {
11- const bytes = raw . toString ( 'hex' ) . split ( / ( [ A - F 0 - 9 ] { 2 } ) / i) . filter ( x => x !== '' ) ;
12- const seconds = bytes [ 62 ] ;
13- const messageType = utils . parseMessageType ( bytes [ 4 ] ) ;
14- const unitId = utils . parseUnitsId ( bytes . slice ( 5 , 9 ) . join ( '' ) ) ;
15- const communication = utils . parseCommunication ( bytes . slice ( 9 , 11 ) . join ( '' ) ) ;
16- const messageNumerator = utils . parseMessageNumerator ( bytes [ 11 ] ) ;
17- const version = utils . parseVersion ( bytes [ 12 ] , bytes [ 13 ] ) ;
18- const transmissionReason = utils . parseTransmissionReason ( bytes [ 18 ] ) ;
19- const engine = utils . parseEngineStatus ( bytes [ 19 ] ) ;
20- const io = utils . parseIO ( bytes . slice ( 20 , 24 ) . join ( '' ) ) ;
21- const unitsStatusCurrentGsmOperator = utils . parseUnitsStatusCurrentGsmOperator ( bytes [ 15 ] ) ;
22- const currentGsmOperator = utils . parseCurrentGsmOperator ( bytes [ 16 ] ) ;
23- const plmn = utils . parsePlmn ( bytes [ 24 ] , unitsStatusCurrentGsmOperator . currentGsmOperator1stNibble , currentGsmOperator ) ;
24- const analog1 = utils . parseAnalogInput1 ( bytes [ 25 ] ) ;
25- const analog2 = utils . parseAnalogInput2 ( bytes [ 26 ] ) ;
26- const analog3 = utils . parseAnalogInput3 ( bytes [ 27 ] ) ;
27- const analog4 = utils . parseAnalogInput4 ( bytes [ 28 ] ) ;
28- const odometer = utils . parseMileageCounter ( bytes . slice ( 29 , 32 ) . join ( '' ) ) ;
29- const imei = utils . multiPurposeField ( bytes . slice ( 32 , 38 ) . join ( '' ) , bytes [ 40 ] ) ;
30- const gpsTime = utils . parseGpsTime ( bytes . slice ( 38 , 40 ) . join ( '' ) , seconds ) ;
31- const locationStatus = utils . parseLocationStatus ( bytes [ 40 ] ) ;
32- const mode1 = utils . parseMode1 ( bytes [ 41 ] ) ;
33- const mode2 = utils . parseMode2 ( bytes [ 42 ] ) ;
34- const satellites = utils . parseSatellites ( bytes [ 43 ] ) ;
35- const loc = utils . parseLoc ( bytes . slice ( 44 , 48 ) . join ( '' ) , bytes . slice ( 48 , 52 ) . join ( '' ) ) ;
36- const altitude = utils . parseAltitude ( bytes . slice ( 52 , 56 ) . join ( '' ) ) ;
37- const speed = utils . parseSpeed ( bytes . slice ( 56 , 60 ) . join ( '' ) ) ;
38- const direction = utils . parseDirection ( bytes . slice ( 60 , 62 ) . join ( '' ) ) ;
39- const datetime = utils . parseDatetime ( bytes . slice ( 67 , 69 ) . join ( '' ) , bytes [ 66 ] , bytes [ 65 ] , bytes [ 64 ] , bytes [ 63 ] , bytes [ 62 ] ) ;
40- const data = {
41- raw : bytes . join ( '' ) ,
42- unitId : unitId ,
43- imei : imei ,
44- device : 'CelloTrack' ,
45- type : 'data' ,
46- loc : loc ,
47- speed : speed ,
48- datetime : datetime ,
49- gpsTime : gpsTime ,
50- direction : direction ,
51- satellites : satellites ,
52- voltage : {
53- ada : analog1 ,
54- adb : analog2 ,
55- adc : analog3 ,
56- add : analog4
57- } ,
58- altitude : altitude ,
59- status : {
60- engine : engine === 1 ,
61- unlockInactive : io . unlockInactive ,
62- panicInactive : io . panicInactive ,
63- drivingStatus : io . drivingStatus ,
64- shockInactive : io . shockInactive ,
65- doorInactive : io . doorInactive ,
66- ignitionPortStatus : io . ignitionPortStatus ,
67- accelerometerStatus : io . accelerometerStatus ,
68- lock : io . lock ,
69- noHibernation : communication . noHibernation ,
70- momentarySpeed : communication . momentarySpeed ,
71- privateMode : communication . privateMode ,
72- firmwareSubversion : communication . firmwareSubversion ,
73- canOriginatedOdometer : communication . canOriginatedOdometer ,
74- canOriginatedSpeed : communication . canOriginatedSpeed ,
75- dataType33_38 : communication . dataType33_38 ,
76- messageSource : communication . messageSource ,
77- garminConnected : communication . garminConnected ,
78- garminEnable : communication . garminEnable ,
79- messageInitiative : communication . messageInitiative ,
80- locationStatus : locationStatus ,
81- charge : io . charge ,
82- standardImmobilizer : io . standardImmobilizer ,
83- globalOutput : io . globalOutput ,
84- ledOut : io . ledOut ,
85- gpsPower : io . gpsPower ,
86- gradualStop : io . gradualStop ,
87- siren : io . siren
88- } ,
89- version : version ,
90- transmissionReason : transmissionReason ,
91- odometer : odometer ,
92- gpsModes : {
93- '1' : mode1 ,
94- '2' : mode2
95- } ,
96- plmn : plmn ,
97- sn : messageNumerator ,
98- messageType : messageType
99- } ;
100- return data ;
101- } ;
102-
10314const parse = raw => {
104- const rawString = raw . toString ( 'hex' ) ;
105- let result = { type : 'UNKNOWN' , raw : rawString } ;
106- if ( patterns . data . test ( rawString ) ) {
107- result = rawString . split ( patterns . data ) . filter ( x => patterns . data . test ( x ) ) . map ( getData ) ;
108- if ( result . length === 1 ) result = result [ 0 ] ;
109- }
110- return result ;
15+ return new Promise ( ( resolve , reject ) => {
16+ const rawString = raw . toString ( 'hex' ) ;
17+ if ( ! patterns . data . test ( rawString ) ) resolve ( { type : 'UNKNOWN' , raw : rawString } ) ;
18+ const results = rawString . split ( patterns . data ) . filter ( x => patterns . data . test ( x ) ) . map ( utils . getData ) ;
19+ if ( ! _client ) {
20+ if ( results . length === 1 ) resolve ( results [ 0 ] ) ;
21+ resolve ( results ) ;
22+ }
23+ _client . getAsync ( `incompleteData:${ results [ 0 ] . unitId } ` ) . then ( reply => {
24+ const incompleteData = rawString . split ( patterns . data ) . filter ( x => ! patterns . data . test ( x ) && x !== '' ) ;
25+ if ( incompleteData . length > 0 ) {
26+ if ( reply ) {
27+ let previousData = '' ;
28+ if ( / ^ 4 d 4 3 4 7 5 0 / . test ( reply ) ) {
29+ previousData = new Buffer ( `${ reply } ${ incompleteData [ 0 ] } ` , 'hex' ) ;
30+ } else if ( / ^ 4 d 4 3 4 7 5 0 / . test ( incompleteData [ 0 ] ) ) {
31+ previousData = new Buffer ( `${ incompleteData [ 0 ] } ${ reply } ` , 'hex' ) ;
32+ }
33+ if ( patterns . data . test ( previousData . toString ( 'hex' ) ) ) {
34+ results . unshift ( utils . getData ( previousData ) ) ;
35+ }
36+ } else {
37+ _client . set ( `incompleteData:${ results [ 0 ] . unitId } ` , incompleteData [ 0 ] ) ;
38+ }
39+ }
40+ if ( results . length === 1 ) resolve ( results [ 0 ] ) ;
41+ resolve ( results ) ;
42+ } ) . catch ( reject ) ;
43+ } ) ;
11144} ;
11245
11346const isCello = raw => {
@@ -118,15 +51,21 @@ const isCello = raw => {
11851 return result ;
11952} ;
12053
121- const getImei = raw => {
122- const bytes = raw . toString ( 'hex' ) . split ( / ( [ A - F 0 - 9 ] { 2 } ) / i) . filter ( x => x !== '' ) ;
123- return utils . multiPurposeField ( bytes . slice ( 32 , 38 ) . join ( '' ) , bytes [ 40 ] ) ;
54+ const setClient = options => {
55+ options = options || { } ;
56+ if ( options . client ) {
57+ _client = options . client ;
58+ } else {
59+ _client = redis . createClient ( options ) ;
60+ }
61+ Promise . promisifyAll ( Object . getPrototypeOf ( _client ) ) ;
12462} ;
12563
12664module . exports = {
12765 parse : parse ,
12866 patterns : patterns ,
12967 isCello : isCello ,
130- getImei : getImei ,
131- ack : inbound . ack
68+ getImei : utils . getImei ,
69+ ack : inbound . ack ,
70+ setClient : setClient
13271} ;
0 commit comments