var mongoose = require('mongoose'); const FLUCTUATION_THRESHOLD = 50 / 1000; const ObjectID = require('mongodb').ObjectID; var Notifs = require('./app_api/models/notifications'); var MongoClient = require('mongodb').MongoClient var f = require('./gpsFunctions'); var crc = require('crc'); var pushNotifs = require('./notify') var Device = require('./app_api/models/device'); var cmdPackets = require('./app_api/models/cmdPackets') var GeoFence = require('./app_api/models/geofence') var Route = require('./app_api/models/trackRoute'); var RouteMap = require('./app_api/models/routeDeviceMap') var Groups = require('./app_api/models/group'); var GPS = require('./app_api/models/gps') //var gpsio = gpsIo var moment = require('moment-timezone'); var Mailer = require('./app_api/controllers/mailer'); var OutgoingIntegrations = require('./outgoingIntegrations'); var GeofenceReports = require('./app_api/models/geofenceReports'); var GPS_x03 = require('./GPS_x03'); //var geoFenceio = geoFenceIo var TCPUTIL = require('./tcpUtil'); var Utilities = require('./app_api/controllers/utilities.controller'); var request = require('request'); var KafkaService = require('./kafka-producer'); var url = 'mongodb://'+Utilities.getConfig().dbUserName+':'+Utilities.getConfig().dbPassUrlEncoded+'@'+Utilities.getConfig().dbDomain+':'+Utilities.getConfig().dbPort+'/IOT?authSource='+Utilities.getConfig().dbAuthSource; var dbOption = { //user : Utilities.getConfig().dbUserName, //pass : Utilities.getConfig().dbPass }; function parseYantraData(raw) { console.log('yantra') try { var rawWOHeadFoot = raw.substring(1); rawWOHeadFoot = rawWOHeadFoot.substring(0, rawWOHeadFoot.length - 1); var rawArray = rawWOHeadFoot.split(','); var latDecimal = rawArray[5] == 'N' ? parseFloat(rawArray[4].substring(0, 2)) + parseFloat((rawArray[4].substring(2, 9) / 60)) : (parseFloat(rawArray[4].substring(0, 2)) + parseFloat((rawArray[4].substring(2, 9) / 60))) * -1; var longDecimal = rawArray[7] == 'E' ? parseFloat(rawArray[6].substring(0, 3)) + parseFloat((rawArray[6].substring(3, 10) / 60)) : (parseFloat(rawArray[6].substring(0, 3)) + parseFloat((rawArray[6].substring(3, 10) / 60))) * -1; /* var ac=rawArray[12].substring(4,6); var ac1 = (parseInt(ac, 16).toString(2)); while (ac1.length < 8) { ac1 = '0' + ac1; } ac1 = ac1.substr(5, 1); var power = rawArray[12].substring(2, 4); var power1 = parseInt(power, 16).toString(2); while (power1.length < 8) { power1 = '0' + power1; } power1 = power1.substr(4, 1); */ return { "imei": rawArray[0], "command": '$', "date": rawArray[2] ? new Date(parseInt('20' + rawArray[2].substring(4, 6)), parseInt(rawArray[2].substring(2, 4) - 1), parseInt(rawArray[2].substring(0, 2)), parseInt(rawArray[3].substring(0, 2)), parseInt(rawArray[3].substring(2, 4)), parseInt(rawArray[3].substring(4, 6)) ) : null, "dateString": rawArray[2], "latDirection": rawArray[5], "longDirection" : rawArray[7], "latDegrees": rawArray[4] + rawArray[5], "longDegrees": rawArray[6] + rawArray[7], "latDecimal": latDecimal, "longDecimal": longDecimal, "insertionTime": new Date(), "raw": raw, "valid": rawArray[1], "speed": (parseFloat(rawArray[8])).toFixed(2), "odo" : parseFloat(rawArray[9]), "timeString": rawArray[3], "heading": rawArray[10], "satellites": rawArray[11], "gsmSignal": rawArray[12], "DIN1": rawArray[14], "DIN2" : rawArray[15], "ignition": rawArray[13], "boxStatus" : rawArray[17], "GPS positioned": rawArray[16], "batteryStatus" : rawArray[18], "geoJSON": { "type": "Point", "coordinates": [ longDecimal, latDecimal ] } } } catch (err) { console.error("exception handled"); console.error(err); } } function parseRawGpsVTX(raw) { var rawArray = raw.split('&'); var latDecimal = rawArray[3].split(',')[3].charAt(rawArray[3].split(',')[3].length-1) == 'N' ?parseFloat(rawArray[3].split(',')[3].substring(0,2)) + parseFloat((rawArray[3].split(',')[3].substring(2, 9) / 60)):(parseFloat(rawArray[3].split(',')[3].substring(0,2)) + parseFloat((rawArray[3].split(',')[3].substring(2, 9) / 60)))* -1; var longDecimal = rawArray[3].split(',')[4].charAt(rawArray[3].split(',')[4].length-1) == 'E' ?parseFloat(rawArray[3].split(',')[4].substring(0,3)) + parseFloat((rawArray[3].split(',')[4].substring(3, 10) / 60)):(parseFloat(rawArray[3].split(',')[4].substring(0,3)) + parseFloat((rawArray[3].split(',')[4].substring(3, 10) / 60))) * -1; return { "imei": rawArray[0].split(',')[1], "command": 'VTX', "date": new Date(parseInt('20' + rawArray[3].split(',')[7].substring(4,6)), parseInt(rawArray[3].split(',')[7].substring(2,4) - 1), parseInt(rawArray[3].split(',')[7].substring(0,2)), parseInt(rawArray[3].split(',')[1].substring(0,2)), parseInt(rawArray[3].split(',')[1].substring(2,4)), parseInt(rawArray[3].split(',')[1].substring(4,6)) ), "dateString": rawArray[3].split(',')[7], "latDegrees": rawArray[3].split(',')[3], "longDegrees":rawArray[3].split(',')[4], "latDecimal": latDecimal, "longDecimal": longDecimal, "insertionTime": new Date(), "raw": raw, "valid": rawArray[3].split(',')[2], "speed": rawArray[3].split(',')[5], "timeString": rawArray[3].split(',')[1], "heading": rawArray[3].split(',')[6], "GPS positioned":((rawArray[6]=='A')?1:0), "ignition":rawArray[3].split(',')[10]=='1'?'0':'1', "geoJSON": { "type": "Point", "coordinates": [longDecimal,latDecimal] } } } function parseRawGpsTs(raw,type) { var raw1=raw.substring(0, raw.length - 2); var rawArray = raw.split(','); if(type=='first') { } else if(type=='rest') { return { "imei": rawArray[1], "command": 'TS', "date": new Date(parseInt('20' + rawArray[5].substring(0,2)), parseInt(rawArray[5].substring(2,4) - 1), parseInt(rawArray[5].substring(4,6)), parseInt(rawArray[5].substring(6,8)), parseInt(rawArray[5].substring(8,10)), parseInt(rawArray[5].substring(10,12)) ), "dateString": rawArray[5].substring(0,6), "latDecimal": Number(rawArray[3]), "longDecimal": Number(rawArray[4]), "insertionTime": new Date(), "raw": raw, "valid": rawArray[6], "speed": rawArray[8], "timeString": rawArray[5].substring(6,12), "heading": rawArray[10], "GPS positioned":((rawArray[6]=='A')?1:0), "ignition":rawArray[27], "gsmSignal":rawArray[7], "power":rawArray[23]=='0'?'1':'0', "satellites":rawArray[11], "batteryStatus":rawArray[48], "gpsTracking":((rawArray[6]=='A')?'1':'0'), "geoJSON": { "type": "Point", "coordinates": [rawArray[4],rawArray[3]] } } } } function parseRawGpsGB(raw,gpsModel) { if(gpsModel == 'GB') { try { var rawArray = raw.split(','); var latstring=rawArray[4].split(':')[1]; var lat=(parseFloat(latstring.substring(0,2))+parseFloat(latstring.substring(2,9)/60)); var longstring=rawArray[5].split(':')[1]; var long=(parseFloat(longstring.substring(0,3))+parseFloat(longstring.substring(3,10)/60)); return { "imei": rawArray[0].split(':')[1], "command": 'GB', "date": rawArray[11] ? new Date(parseInt('20' + rawArray[7].split(':')[1].substring(4,6)), parseInt(rawArray[7].split(':')[1].substring(2,4) - 1), parseInt(rawArray[7].split(':')[1].substring(0,2)), parseInt(rawArray[3].split(':')[1].substring(0,2)), parseInt(rawArray[3].split(':')[1].substring(2,4)), parseInt(rawArray[3].split(':')[1].substring(4,6)) ) : null, "dateString": rawArray[7].split(':')[1], "latDegrees": rawArray[4].split(':')[1], "longDegrees": rawArray[5].split(':')[1], "latDecimal": lat, "longDecimal": long, "insertionTime": new Date(), "raw": raw, "valid": rawArray[10].split(':')[1].charAt(7), "speed": (parseFloat(rawArray[6].split(':')[1]).toFixed(2)), "timeString": rawArray[3].split(':')[1], "heading": rawArray[12].split(':')[1].substring(0, rawArray[12].split(':')[1].length - 2), "GPS positioned":((rawArray[10].split(':')[1].charAt(7)=='A')?1:0), "ignition": rawArray[9].split(':')[1].charAt(0), "ac": rawArray[9].split(':')[1].charAt(3), "sos" : rawArray[9].split(':')[1].charAt(1) == "1" ? true : false, "debug" : rawArray[9].split(':')[1].charAt(4), "batteryStatus": rawArray[1].split(':')[1], "power":rawArray[9].split(':')[1].charAt(5), "gpsTracking":((rawArray[10].split(':')[1].charAt(7)=='A')?'1':'0'), "geoJSON": { "type": "Point", "coordinates": [long, lat] } } } catch (err) { console.error("exception handled"); console.error(err); } } } function parseRawGpsL(raw) { try { var rawArray = raw.split(','); var lat=(parseFloat(rawArray[4].substring(0,2))+parseFloat(rawArray[4].substring(2,9)/60)); var long=(parseFloat(rawArray[6].substring(0,3))+parseFloat(rawArray[6].substring(3,10)/60)); return { "imei": rawArray[0].substring(11), "command": 'L100', "date": new Date (Number(rawArray[2])).toISOString().replace('T',' '), "dateString": new Date(parseInt('20' + str.split(',')[10].substring(4,6)), parseInt(str.split(',')[10].substring(2,4) - 1), parseInt(str.split(',')[10].substring(0,2))), "latDegrees": rawArray[4]+rawArray[5], "longDegrees": rawArray[6]+rawArray[7], "latDecimal": lat, "longDecimal": long, "insertionTime": new Date(), "raw": raw, "valid": rawArray[3], "speed": (parseFloat(Number(rawArray[8])*1.85).toFixed(2)), "timeString": Number(rawArray[2]), "heading": rawArray[9], "ignition":rawArray[14].charAt(1), "geoJSON": { "type": "Point", "coordinates": [long, lat] } } } catch (err) { console.error("exception handled"); console.error(err); } } function parseT8803_data(raw, parsedHead) { data = Buffer.from(data).toString('hex'); var date = new Date( parseInt(data.substr(88, 2), 16) + 2000, parseInt(data.substr(90, 2), 16) - 1, parseInt(data.substr(92, 2), 16), parseInt(data.substr(94, 2), 16), parseInt(data.substr(96, 2), 16), parseInt(data.substr(98, 2), 16) ) var course_status = parseInt(data.substr(128, 4), 16).toString(2); var latitude = Buffer(str.substr(116, 8), 'hex').readFloatBE(0); var longitude = Buffer(str.substr(108, 8), 'hex').readFloatBE(0); var speedHex = str.substr(124, 4); var speed = [speedHex.slice(0, 3), '.', speedHex.slice(3)].join(''); var gpsPositionedData = parseInt(str.substr(48, 2), 16).toString(2); var gpsPositioned = gpsPositionedData.charAt(0) == '0' ? '1' : '0'; var digitalIOData = parseInt(str.substr(62, 4), 16).toString(2); var ignition = digitalIOData.charAt(1) == '1' ? 1 : 0; return { "imei": parseInt(str.substr(14,16)), "command": parsedHead.protocal_id, "date": date, "dateString": str.substr(88, 6), "latDecimal": latitude, "longDecimal": longitude, "insertionTime": new Date(), "raw": raw.toString('hex'), "speed": speed, "timeString": str.substr(94, 6), "heading": course_status, "geoJSON": { "type": "Point", "coordinates": [longitude, latitude ] }, //'MCC': parseInt(str.substr(36, 4), 16), //'MNC': parseInt(str.substr(40, 2), 16), //'LAC': parseInt(str.substr(42, 4), 16), //'CellT ID': parseInt(str.substr(46, 6), 16), //'lbs': str.substr(36, 16), //'real-time gps': course_status.substr(0, 1), 'GPS positioned': course_status.substr(1, 1), 'ignition' : ignition //'satellites': parseInt(str.substr(13, 1), 16) } } function authorizeT8803(device_id, socket) { socket.imei = parseInt(device_id) var loginResponse = '232301000F0001' + device_id; socket.write(new Buffer(loginResponse, 'hex')); } function respond_T8803_heartbeat(device_id, socket) { socket.imei = parseInt(device_id) var heartbeatResponse = '232303000F0001' + device_id; socket.write(new Buffer(heartbeatResponse, 'hex')); } function parseT8803_head(raw, socket) { data = Buffer.from(data).toString('hex') var parts = { 'start': data.substr(0, 4) }; if (parts['start'] == '2323') { parts['length'] = parseInt(data.substr(6, 4), 16); //parts['finish'] = data.substr(6 + parts['length'] * 2, 4); parts['protocal_id'] = data.substr(4, 2); if (parts['protocal_id'] == '01') { parts['device_id'] = data.substr(14, 16); parts.cmd = 'login_request'; parts.action = 'login_request'; } else if (parts['protocal_id'] == '02') { parts['device_id'] = socket.imei || data.substr(14, 16); parts['data'] = data.substr(30); parts.cmd = 'ping'; parts.action = 'ping'; } else if (parts['protocal_id'] == '03') { parts['device_id'] = socket.imei || data.substr(14, 16); parts['data'] = data.substr(30); parts.cmd = 'heartbeat'; parts.action = 'heartbeat'; } else if (parts['protocal_id'] == '04') { parts['device_id'] = socket.imei || ''; parts['data'] = data.substr(8, parts['length'] * 2); parts.cmd = 'alert'; parts.action = 'alert'; } else { parts['device_id'] = socket.imei || ''; parts.cmd = 'noop'; parts.action = 'noop'; } } else { parts['device_id'] = ''; parts.cmd = 'noop'; parts.action = 'noop'; } return parts; } function parseGM06_Head(data, socket) { data = Buffer.from(data).toString('hex') var parts = { 'start': data.substr(0, 4) }; if (parts['start'] == '6767') { parts['protocal_id'] = data.substr(4, 2); parts['length'] = parseInt(data.substr(6, 4), 16); //parts['finish'] = data.substr(6 + parts['length'] * 2, 4); if (parts['protocal_id'] == '01') { parts['device_id'] = data.substr(15, 15); parts.cmd = 'login_request'; parts.action = 'login_request'; } else if (parts['protocal_id'] == '02') { parts['device_id'] = socket.imei || ''; parts['data'] = data.substr(14, parts['length'] * 2); parts.cmd = 'ping'; parts.action = 'ping'; } else if (parts['protocal_id'] == '03') { parts['device_id'] = socket.imei || ''; parts.cmd = 'heartbeat'; parts['data'] = data/* .substr(8, 10) */; parts.action = 'heartbeat'; } else { parts['device_id'] = socket.imei || ''; parts.cmd = 'noop'; parts.action = 'noop'; } } else { parts['device_id'] = ''; parts.cmd = 'noop'; parts.action = 'noop'; } return parts; }; function authorizeGM06(socket, request, raw) { socket.imei = socket.imei || parseInt(request.device_id); console.log('6767010002' + Buffer.from(raw, 'hex').toString('hex').substr(10, 4)); socket.write('6767010002' + Buffer.from(raw, 'hex').toString('hex').substr(10,4), 'hex'); }; function get_GM06_ping_data(msg_parts, raw, socket) { var str = msg_parts.data; var date = new Date( parseInt(str.substr(0, 8), 16) * 1000 ) var latitude = dex_to_degrees(str.substr(8, 8), 0); var longitude = dex_to_degrees(str.substr(16, 8), 0); var gps = parseInt(str.substr(48, 1), 2).toString(); gps = gps.charAt(gps.length-1) return { "imei": socket.imei.toString(), "command": msg_parts.protocal_id, "date": date, "dateString": str.substr(0, 6), "latDecimal": latitude, "longDecimal": longitude, "insertionTime": new Date(), "raw": raw.toString('hex'), "speed": parseInt(str.substr(24, 2), 16).toString(), "timeString": str.substr(6, 6), "heading": parseInt(str.substr(26, 4), 16).toString(), "geoJSON": { "type": "Point", "coordinates": [longitude, latitude ] }, 'GPS positioned': gps } }; function receive_GM06_heartbeat(raw, socket) { socket.write('6767030002' + Buffer.from(raw, 'hex').toString('hex').substr(10,4), 'hex'); }; function parseVT1000(raw) { var gsm1=str.substring(str.length-20); var gsmval=gsm1.substring(6,8); var latstring=raw.substring(31,38)/1000; var lat=(parseFloat(latstring.toString().substring(0,2))+parseFloat(latstring.toString().substring(2,7)/60)); var longstring=raw.substring(38,46)/1000; var long=(parseFloat(longstring.toString().substring(0,2))+parseFloat(longstring.toString().substring(2,7)/60)); var locationStatusBits = parseInt(raw.substr(54, 2), 16).toString(2); while(locationStatusBits.length < 8) { locationStatusBits = "0" + locationStatusBits; } var alarmPacket = raw.substr(62, 8); var alarm1Packet = alarmPacket.substr(0, 2); var alarm1PacketBits = parseInt(alarm1Packet, 16).toString(2); while(alarm1PacketBits.length < 8) { alarm1PacketBits = "0" + alarm1PacketBits; } var io=raw.substring(62,70).charAt(7); return { "imei": raw.substring(10,18), "command": raw.substring(4,6), "date": new Date(parseInt('20' + raw.substring(18, 20)), parseInt(raw.substring(20, 22) - 1), parseInt(raw.substring(22, 24)), parseInt(raw.substring(24, 26)), parseInt(raw.substring(26, 28)), parseInt(raw.substring(28, 30)) ), "dateString": raw.substring(18, 24), //"latDecimal": raw.substring(31,38)/100000, // "longDecimal": raw.substring(38,46)/100000, "latDecimal": lat, "longDecimal": long, "insertionTime": new Date(), "raw": raw, "speed": raw.substring(46,50), "timeString": raw.substring(24,30), "heading": raw.substring(50, 54), "GPS positioned": locationStatusBits.charAt(0), "alarm1PacketBits": alarm1PacketBits, "locationStatusBits" : locationStatusBits, "ignition": alarm1PacketBits.charAt(0) == '1' ? '0' : '1', "power" : alarm1PacketBits.charAt(4) == '1' ? '0' : '1', "gsmSignal":gsmval, "geoJSON": { "type": "Point", "coordinates": [ long, lat ] } } } function fmb_login(hexString, socket) { //disable nagle's algorithm which prevents packets from being sent immediately //socket.setNoDelay(true); var imei_scramble = hexString.substr(4); var imei = ''; for (var i = 0; i < imei_scramble.length; i++){ if (i % 2 != 0) { imei += imei_scramble.charAt(i); } } socket.imei = imei; socket.write(new Buffer('01', 'hex'), function (z) { //console.log('fmb accepted') }); } function parseFmbData(hexString, socket) { var allData = []; var imei = socket.imei; var command = hexString.substr(16, 2); var number_of_data = parseInt(hexString.substr(18, 2), 16) var startIndex = 20; for (var q = 1; q <= number_of_data; q++){ var data = {} data.startIndex = startIndex; data.command = command; data.number_of_data = number_of_data; data.imei = socket.imei; data.date = new Date(parseInt(hexString.substr(startIndex + 0, 16), 16)); data.priority = hexString.substr(startIndex + 16, 2); var longDecimal = parseInt(hexString.substr(startIndex + 18, 8), 16) / 10000000; var latDecimal = parseInt(hexString.substr(startIndex + 26, 8), 16) / 10000000; data.raw = hexString; data.latDecimal = latDecimal; data.longDecimal = longDecimal; data.geoJSON = { "type": "Point", "coordinates": [longDecimal, latDecimal] }; data.insertionTime = new Date(); data.altitude = hexString.substr(startIndex + 34, 4) data.heading = hexString.substr(startIndex + 38, 4); data.satellites = hexString.substr(startIndex + 42, 2); data.speed = parseInt(hexString.substr(startIndex + 44, 4), 16).toString(); data.eventId = parseInt(hexString.substr(startIndex + 48, 2),16); data.numOfIO = parseInt(hexString.substr(startIndex + 50, 2), 16); //1 byte IO var num1ByteIO = parseInt(hexString.substr(startIndex + 52, 2), 16); data.num1ByteIO = num1ByteIO var _1ByteIO = hexString.substr(startIndex + 54, (num1ByteIO + (num1ByteIO * 1)) * 2); data._1ByteIO = _1ByteIO for (var i = 0; i <= num1ByteIO; i++){ var IoElement = _1ByteIO.substr(i * 4, 2); var IoValue = _1ByteIO.substr((i * 4) + 2, 2); //digital in if (parseInt(IoElement, 16) == 1) { data.ignition = parseInt(IoValue, 16).toString(); } //GNSS status if (parseInt(IoElement, 16) == 69) { data['GPS positioned'] = parseInt(IoValue, 16).toString(); } } //2 byte IO var num2ByteIOIndex = startIndex + 54 + ((num1ByteIO + (num1ByteIO * 1)) * 2); data.num2ByteIOIndex = num2ByteIOIndex; var num2ByteIO = parseInt(hexString.substr(num2ByteIOIndex, 2), 16); data.num2ByteIO = num2ByteIO; var _2ByteIO = hexString.substr(num2ByteIOIndex + 2, (num2ByteIO * 6)); data._2ByteIO = _2ByteIO; for (var i = 0; i <= num2ByteIO; i++){ var IoElement = _2ByteIO.substr(i * 6, 2); var IoValue = _2ByteIO.substr((i * 6) + 2, 4); //analog in if (parseInt(IoElement, 16) == 9) { data.fuelVoltage = parseInt(IoValue, 16); } //ext voltage if (parseInt(IoElement, 16) == 66) { data.power = parseInt(IoValue, 16) == 0 ? '0' : '1'; } } //4 byte IO var num4ByteIOIndex = num2ByteIOIndex + ((num2ByteIO * 6/* + (num2ByteIO * 1) */) + 2); data.num4ByteIOIndex = num4ByteIOIndex; var num4ByteIO = parseInt(hexString.substr(num4ByteIOIndex, 2), 16); data.num4ByteIO = num4ByteIO; var _4ByteIO = hexString.substr(num4ByteIOIndex + 2, (num4ByteIO * 10)); startIndex = num4ByteIOIndex + 2 + 2 + (num4ByteIO * 10); data._4ByteIO = _4ByteIO; for (var i = 0; i <= num4ByteIO; i++){ var IoElement = _4ByteIO.substr(i * 10, 2); var IoValue = _4ByteIO.substr((i * 10) + 2, 8); //analog in if (parseInt(IoElement, 16) == 16) { data.odo = parseInt(IoValue, 16) / 1000; } } allData.push(data); } var latest = allData[0]; if (allData.length > 1) { Device.findOne({ Device_ID: latest.imei }, function (err, device) { if(err){ console.error(err); } else if(device) { allData.shift(); for (var z = 0; z < allData.length; z++){ allData[z].group = device.vehicleGroup; allData[z].vehicle = device.vehicle; } GPS.insertMany(allData, { ordered: false }, function (err, docs) { }) } }) } return latest; } function numHex(s) { var a = s.toString(16); if( (a.length % 2) > 0 ){ a = "0" + a; } return a; } function sendFmbAck(socket, number_of_data) { number_of_data_encoded = parseInt(number_of_data).toString(16); while (number_of_data_encoded.length < 8) { number_of_data_encoded = '0' + number_of_data_encoded; } var packet = new Buffer(number_of_data_encoded, 'hex'); socket.write(packet); } function crc16(buf) { var crcTable = [ 0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF, 0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7, 0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E, 0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876, 0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD, 0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5, 0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C, 0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974, 0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB, 0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3, 0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A, 0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72, 0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9, 0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1, 0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738, 0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70, 0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7, 0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF, 0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036, 0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E, 0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5, 0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD, 0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134, 0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C, 0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3, 0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB, 0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232, 0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A, 0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1, 0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9, 0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330, 0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78 ]; crcX = parseInt("FFFF", 16); cr1 = parseInt("FF", 16); cr2 = parseInt("FFFF", 16); i = 0; while (i < buf.length) { str = buf.substring(i, i + 2); str_hex = parseInt(str, 16); j = (crcX ^ str_hex) & cr1; crcX = (crcX >> 8) ^ crcTable[j]; i = i + 2; } crcX = crcX ^ 0xffff; return crcX.toString(16); } function receive_heartbeat(raw, socket) { var data = Buffer.from(raw, 'hex').toString('hex') if (!socket.__count) { socket.__count = 1; } //socket.imei = parseInt(request.device_id) var length = '05'; var protocal_id = '01'; var serial = Buffer.from(raw).toString('hex').substr(18, 4) var str = length + protocal_id + serial; socket.__count++; var crcResult = crc16(str); var buff = new Buffer('7878' + str + crcResult + '0d0a', 'hex'); socket.write(buff); }; function dex_to_degrees(dex, l) { return (parseInt(dex, 16) / 1800000) }; function parseG500OBD_lat_long(l) { } function parseG500OBD_data(data) { data = Buffer.from(data).toString('hex') if (data.substr(14, 4) == '2084') { var date = new Date( parseInt(data.substr(32, 2)) + 2000, parseInt(data.substr(30, 2)) - 1, parseInt(data.substr(28, 2)), parseInt(data.substr(34, 2)), parseInt(data.substr(36, 2)), parseInt(data.substr(38, 2)) ) var latDecimal = parseInt(data.substr(40, 2)) + (parseFloat(data.substr(42, 2) + '.' + data.substr(44, 4)) / 60) var longDecimal = parseInt(data.substr(48, 2)) + (parseFloat(data.substr(50, 2) + '.' + data.substr(52, 4)) / 60) return { "imei": data.substr(2, 12), "command": data.substr(14, 4), "date": date, "dateString": data.substr(28, 6), "latDecimal": latDecimal, "longDecimal": longDecimal, "insertionTime": new Date(), "raw": data, "speed": parseInt(data.substr(58, 2), 16).toString(), "timeString": data.substr(34, 6), "heading": (parseInt(data.substr(60, 2), 16) * 2).toString(), "geoJSON": { "type": "Point", "coordinates": [ longDecimal, latDecimal ] } } } else { return {} } } function hex2ASCII(hexx) { var hex = hexx.toString(); var str = ''; for (var i = 0; (i < hex.length && hex.substr(i, 2) !== '00'); i += 2) str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); return str; } function parse_GT06_stringInfo(parsedHead) { var contentLength = parseInt(parsedHead.data.substr(0, 2), 16); var serverKeyLength = 4; var stringInfo = hex2ASCII(parsedHead.data.substr(2 + (4 * 2), contentLength * 2)); return stringInfo; } function get_GT06_alarm_data(msg_parts, raw, socket) { var str = msg_parts.data; var sos = 0; var date = new Date( parseInt(str.substr(0, 2), 16) + 2000, parseInt(str.substr(2, 2), 16) - 1, parseInt(str.substr(4, 2), 16), parseInt(str.substr(6, 2), 16), parseInt(str.substr(8, 2), 16), parseInt(str.substr(10, 2), 16) ) var course_status = parseInt(str.substr(32, 4), 16).toString(2); var longDir = course_status.substr(2, 1) == '0' ? 'E' : 'W'; var latDir = course_status.substr(3, 1) == '0' ? 'S' : 'N'; //var latitude = latDir == 'N' ? dex_to_degrees(str.substr(14, 8), 0) : dex_to_degrees(str.substr(14, 8), 0)*-1; //var longitude = longDir == 'E' ? dex_to_degrees(str.substr(22, 8), 1) : dex_to_degrees(str.substr(22, 8), 1)*-1; var latitude = latDir == 'N' ? dex_to_degrees(str.substr(14, 8), 0) : dex_to_degrees(str.substr(14, 8), 0); var longitude = longDir == 'E' ? dex_to_degrees(str.substr(22, 8), 1) : dex_to_degrees(str.substr(22, 8), 1); var terminalInfoContentByte = parseInt(str.substr(54, 2), 16).toString(2); while (terminalInfoContentByte.length < 8) { terminalInfoContentByte = '0' + terminalInfoContentByte } //parse alarms var sosAlarm = 0; var powerCutAlarm = 0; var shockAlarm = 0; var alarmBits = terminalInfoContentByte.substr(2, 3); if (alarmBits == '000') { sosAlarm = 0; powerCutAlarm = 0; shockAlarm = 0; } if (alarmBits == '001') { sosAlarm = 0; powerCutAlarm = 0; shockAlarm = 1; } if (alarmBits == '010') { sosAlarm = 0; powerCutAlarm = 1; shockAlarm = 0; } if (alarmBits == '100') { sosAlarm = 1; sos = 1; powerCutAlarm = 0; shockAlarm = 0; } return { "imei": socket.imei.toString(), "command": msg_parts.protocal_id, "date": date, "dateString": str.substr(0, 6), "latDecimal": latitude, "longDecimal": longitude, "insertionTime": new Date(), "raw": raw.toString('hex'), "speed": parseInt(str.substr(30, 2), 16).toString(), "timeString": str.substr(6, 6), "heading": parseInt(course_status.substr(4, 10), 2).toString(), "geoJSON": { "type": "Point", "coordinates": [longitude, latitude ] }, 'MCC': parseInt(str.substr(36, 4), 16), 'MNC': parseInt(str.substr(40, 2), 16), 'LAC': parseInt(str.substr(42, 4), 16), 'CellT ID': parseInt(str.substr(46, 6), 16), 'lbs': str.substr(36, 16), 'real-time gps': course_status.substr(0, 1), 'GPS positioned': course_status.substr(1, 1), 'satellites': parseInt(str.substr(13, 1), 16), "powerCutAlarm": powerCutAlarm, "sosAlarm": sosAlarm, "shockAlarm": shockAlarm, "terminalInfoContentByte": terminalInfoContentByte, "sos" : sos == 1 ? true : false } }; function get_GT06_ping_data(msg_parts, raw, socket) { var str = msg_parts.data; var date = new Date( parseInt(str.substr(0, 2), 16) + 2000, parseInt(str.substr(2, 2), 16) - 1, parseInt(str.substr(4, 2), 16), parseInt(str.substr(6, 2), 16), parseInt(str.substr(8, 2), 16), parseInt(str.substr(10, 2), 16) ) var course_status = parseInt(str.substr(32, 4), 16).toString(2); var longDir = course_status.substr(2, 1) == '0' ? 'E' : 'W'; var latDir = course_status.substr(3, 1) == '0' ? 'S' : 'N'; //var latitude = latDir == 'N' ? dex_to_degrees(str.substr(14, 8), 0) : dex_to_degrees(str.substr(14, 8), 0)*-1; //var longitude = longDir == 'E' ? dex_to_degrees(str.substr(22, 8), 1) : dex_to_degrees(str.substr(22, 8), 1)*-1; var latitude = latDir == 'N' ? dex_to_degrees(str.substr(14, 8), 0) : dex_to_degrees(str.substr(14, 8), 0); var longitude = longDir == 'E' ? dex_to_degrees(str.substr(22, 8), 1) : dex_to_degrees(str.substr(22, 8), 1); var terminalInfoContentByte = parseInt(str.substr(52, 2), 16).toString(2); while (terminalInfoContentByte.length < 8) { terminalInfoContentByte = '0' + terminalInfoContentByte } //parse alarms var sosAlarm = 0; var powerCutAlarm = 0; var shockAlarm = 0; var alarmBits = terminalInfoContentByte.substr(2, 3); if (alarmBits == '000') { sosAlarm = 0; powerCutAlarm = 0; shockAlarm = 0; } if (alarmBits == '001') { sosAlarm = 0; powerCutAlarm = 0; shockAlarm = 1; } if (alarmBits == '010') { sosAlarm = 0; powerCutAlarm = 1; shockAlarm = 0; } if (alarmBits == '100') { sosAlarm = 1; powerCutAlarm = 0; shockAlarm = 0; } return { "imei": socket.imei.toString(), "command": msg_parts.protocal_id, "date": date, "dateString": str.substr(0, 6), "latDecimal": latitude, "longDecimal": longitude, "insertionTime": new Date(), "raw": raw.toString('hex'), "speed": parseInt(str.substr(30, 2), 16).toString(), "timeString": str.substr(6, 6), "heading": parseInt(course_status.substr(4, 10), 2).toString(), "geoJSON": { "type": "Point", "coordinates": [longitude, latitude ] }, 'MCC': parseInt(str.substr(36, 4), 16), 'MNC': parseInt(str.substr(40, 2), 16), 'LAC': parseInt(str.substr(42, 4), 16), 'CellT ID': parseInt(str.substr(46, 6), 16), 'lbs': str.substr(36, 16), 'real-time gps': course_status.substr(0, 1), 'GPS positioned': course_status.substr(1, 1), 'satellites': parseInt(str.substr(13, 1), 16), "powerCutAlarm": powerCutAlarm, "sosAlarm": sosAlarm, "shockAlarm": shockAlarm, "terminalInfoContentByte" : terminalInfoContentByte } }; function gt06_ping_response(socket) { socket.__count++; //socket.write(new Buffer('787805010001d9dc0d0a', 'hex')) } function authorizeGT06(socket, request, raw) { if (!socket.__count) { socket.__count = 1; } socket.imei = socket.imei || parseInt(request.device_id) var length = '05'; var protocal_id = '01'; var serial = Buffer.from(raw).toString('hex').substr(24, 4) var str = length + protocal_id + serial; socket.__count++; var crcResult = crc16(str); var buff = new Buffer('7878' + str + crcResult + '0D0A', 'hex'); socket.write(buff); }; function parseGT06_Head(data, socket) { data = Buffer.from(data).toString('hex') var parts = { 'start': data.substr(0, 4) }; if (parts['start'] == '7878' || parts['start'] == '7979') { parts['length'] = parseInt(data.substr(4, 2), 16); parts['finish'] = data.substr(6 + parts['length'] * 2, 4); parts['protocal_id'] = data.substr(6, 2); if (parts['protocal_id'] == '01') { parts['device_id'] = data.substr(8, 16); parts.cmd = 'login_request'; parts.action = 'login_request'; } else if (parts['protocal_id'] == '12' || parts['protocal_id'] == '19') { parts['device_id'] = socket.imei || ''; parts['data'] = data.substr(8, parts['length'] * 2); parts.cmd = 'ping'; parts.action = 'ping'; } else if (parts['protocal_id'] == '22') { parts['device_id'] = socket.imei || ''; parts['data'] = data.substr(8, parts['length'] * 2); parts.cmd = 'ping'; parts.action = 'ping'; } else if (parts['protocal_id'] == '13' || parts['protocal_id'] == '23') { parts['device_id'] = socket.imei || ''; parts.cmd = 'heartbeat'; parts['data'] = data.substr(8, 10); parts.action = 'heartbeat'; } else if (parts['protocal_id'] == '16' || parts['protocal_id'] == '18') { parts['device_id'] = socket.imei || ''; parts['data'] = data.substr(8, parts['length'] * 2); parts.cmd = 'alert'; parts.action = 'alert'; } else if (parts['protocal_id'] == '15') { parts['device_id'] = socket.imei || ''; parts['data'] = data.substr(8, parts['length'] * 2); parts.cmd = 'stringInfo'; parts.action = 'stringInfo'; } else { parts['device_id'] = socket.imei || ''; parts.cmd = 'noop'; parts.action = 'noop'; } } else if (parts['start'].indexOf('28') == 0) { parts['device_id'] = data.substr(2, 12); parts.cmd = data.substr(14, 4); if (parts.cmd == '2084') { parts.action = 'ping'; } else if (parts.cmd == '1088') { parts.action = 'heartbeat' } else parts.action = 'noop' } else { parts['device_id'] = ''; parts.cmd = 'noop'; parts.action = 'noop'; } return parts; }; function isHex(h) { var re = /[0-9A-Fa-f]{6}/g; re.lastIndex = 0; if (re.test(h)) { return true; } else { return false; } } function change_G900WKMD(socket, device_id) { //device_id = '865205032299264' var hh = new Date().getHours() < 10 ? '0' + new Date().getHours() : new Date().getHours().toString() var mm = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes().toString() var ss = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds().toString() socket.write('*HQ,' + device_id + ',WKMD,' + hh + mm + ss + ',0#') socket.write('*HQ,' + device_id + ',S26,' + hh + mm + ss + ',W#') } /** move to another file */ function parseRawGps(raw, gpsModel) { if (gpsModel == 'TK') { var latDecimal = raw.substring(33, 34) == 'N' ? parseFloat(raw.substring(24, 26)) + parseFloat((raw.substring(26, 33) / 60)) : (parseFloat(raw.substring(24, 26)) + parseFloat((raw.substring(26, 33) / 60))) * -1; var longDecimal = raw.substring(44, 45) == 'E' ? parseFloat(raw.substring(34, 37)) + parseFloat((raw.substring(37, 44) / 60)) : (parseFloat(raw.substring(34, 37)) + parseFloat((raw.substring(37, 44) / 60))) * -1; var io=raw.substr(63,1)?parseInt(raw.substr(63,1)):null; var ac=raw.substr(64,1)?parseInt(raw.substr(64,1)):null; var fuel=((parseInt(raw.substr(67,1), 16)*16*16)+(parseInt(raw.substr(68,1), 16)*16)+(parseInt(raw.substr(69,1), 16)))*10; var ac1=('0000' + parseInt(ac, 16).toString(2)).slice(-4).charAt(3); var sos=('0000' + parseInt(ac, 16).toString(2)).slice(-4).charAt(2); return { "imei": raw.substring(1, 13), "command": raw.substring(13, 17), "date": new Date(parseInt('20' + raw.substring(17, 19)), parseInt(raw.substring(19, 21) - 1), parseInt(raw.substring(21, 23)), parseInt(raw.substring(50, 52)), parseInt(raw.substring(52, 54)), parseInt(raw.substring(54, 56)) ), "dateString": raw.substring(17, 23), "latDegrees": raw.substring(24, 34), "longDegrees": raw.substring(34, 45), "latDecimal": latDecimal, "longDecimal": longDecimal, "insertionTime": new Date(), "raw": raw, "valid": raw.substring(23, 24), "speed": raw.substring(45, 50), "timeString": raw.substring(50, 56), "heading": raw.substring(56, 62), "power": raw.substr(62,1)=='0'?'1':'0', "mileage": raw.substring(71, 80), "ignition": io, "ac":ac1, "sos":sos, "fuelVoltage":fuel, "GPS positioned":((raw.substring(23, 24)=='A')?1:0), "geoJSON": { "type": "Point", "coordinates": [ longDecimal, latDecimal ] } } } if (gpsModel == 'G') { try { var rawArray = raw.split(',') var latDecimal = rawArray[6] == 'N' ? parseFloat(rawArray[5].substring(0, 2)) + parseFloat((rawArray[5].substring(2, 9) / 60)) : (parseFloat(rawArray[5].substring(0, 2)) + parseFloat((rawArray[5].substring(2, 9) / 60))) * -1; var longDecimal = rawArray[8] == 'E' ? parseFloat(rawArray[7].substring(0, 3)) + parseFloat((rawArray[7].substring(3, 10) / 60)) : (parseFloat(rawArray[7].substring(0, 3)) + parseFloat((rawArray[7].substring(3, 10) / 60))) * -1; var ac=rawArray[12].substring(4,6); var ac1 = (parseInt(ac, 16).toString(2)); while (ac1.length < 8) { ac1 = '0' + ac1; } ac1 = ac1.substr(5, 1); var power = rawArray[12].substring(2, 4); var power1 = parseInt(power, 16).toString(2); while (power1.length < 8) { power1 = '0' + power1; } power1 = power1.substr(4, 1); return { "imei": rawArray[1], "command": rawArray[2], "date": rawArray[11] ? new Date(parseInt('20' + rawArray[11].substring(4, 6)), parseInt(rawArray[11].substring(2, 4) - 1), parseInt(rawArray[11].substring(0, 2)), parseInt(rawArray[3].substring(0, 2)), parseInt(rawArray[3].substring(2, 4)), parseInt(rawArray[3].substring(4, 6)) ) : null, "dateString": rawArray[11], "latDegrees": rawArray[5] + rawArray[6], "longDegrees": rawArray[7] + rawArray[8], "latDecimal": latDecimal, "longDecimal": longDecimal, "insertionTime": new Date(), "raw": raw, "valid": rawArray[4], "speed": (parseFloat(rawArray[9]) * 1.60934).toFixed(2), "timeString": rawArray[3], "heading": rawArray[10], "power": power1/* =='0'?'1':'0' */, "mileage": rawArray[12], "ignition":ac1/* =='0'?'1':'0' */, "GPS positioned":((rawArray[4]=='A')?1:0), "geoJSON": { "type": "Point", "coordinates": [ longDecimal, latDecimal ] } } } catch (err) { console.error("exception handled"); console.error(err); } } } function parseMobileTrackerData(raw) { return { imei: raw.imei.toString(), command: "mPing", latDecimal: parseFloat(raw.curLat), longDecimal: parseFloat(raw.curLong), date: new Date(raw.curDateTime), batteryStatus: raw.batteryStatus, raw : JSON.stringify(raw), deviceModel: raw.deviceModel, deviceUUID: raw.deviceUUID, platform: raw.platform, platformVersion: raw.platformVersion, deviceManufacturer: raw.deviceManufacturer, deviceSerialNo: raw.deviceSerialNo, isVirtual: raw.isVertual, insertionTime: new Date(), sos: raw.SOS, speed: raw.speed, mode: raw.mode, accuracy: raw.accuracy, geoJSON: { "type": "Point", "coordinates": [parseFloat(raw.curLong),parseFloat(raw.curLat)] } } } function parseAIS140Head(packet, socket) { packet = packet.toString('utf8'); var msgParts = packet.split(','); var header = {} if (msgParts.length == 10) { header.cmd = 'login_request'; header.packet = packet; header.action = 'login_request'; header['device_id'] = msgParts[3]; socket.imei = msgParts[3]; } if (msgParts.length == 13) { header.cmd = 'heartbeat'; header.packet = packet; header.action = 'heartbeat'; header['device_id'] = msgParts[3]; socket.imei = msgParts[3]; } if (msgParts.length == 17) { header.cmd = 'alertPacket'; header.packet = packet; header.action = 'alertPacket'; header['device_id'] = msgParts[3]; socket.imei = msgParts[3]; } if (msgParts.length >= 52) { header.cmd = 'ping'; header.packet = packet; header.action = 'ping'; header['device_id'] = msgParts[6]; socket.imei = msgParts[6]; } return header; } function parseAIS140Ping(raw) { raw = raw.toString('utf8'); raw = "$Header" + raw.split('$Header')[raw.split('$Header').length -1] var msgParts = raw.split(','); var date = new Date( parseInt(msgParts[9].substr(4, 4)), parseInt(msgParts[9].substr(2, 2)) - 1, parseInt(msgParts[9].substr(0, 2)), parseInt(msgParts[10].substr(0, 2)), parseInt(msgParts[10].substr(2, 2)), parseInt(msgParts[10].substr(4, 2)), ); return { firmwareVersion: msgParts[2], command: msgParts[3], msgID: msgParts[4], packetStatus: msgParts[5], isPastData: msgParts[5] == 'L' ? false : true, imei: msgParts[6], vehicleRegistration: msgParts[7], "GPS positioned": msgParts[8], dateString: msgParts[9], timeString: msgParts[10], date: date, latDecimal: msgParts[11] * (msgParts[12] == 'N'? 1 : -1), longDecimal: msgParts[13] * (msgParts[14] == 'E' ? 1 : -1), speed: msgParts[15], heading: msgParts[16], satellites: msgParts[17], altitude: msgParts[18], ignition: msgParts[22], power: msgParts[23], gsmSignal: msgParts[28], insertionTime : new Date(), raw: raw, sos: msgParts[4] == '10' ? true : null, geoJSON : { "type" : "Point", "coordinates" : [ msgParts[13] * (msgParts[14] == 'E' ? 1 : -1), msgParts[11] * (msgParts[12] == 'N'? 1 : -1) ] } } } function parseAIS140Packets(packets, socket) { var pings = []; var alertPackets = []; var logins = []; var hbts = []; var latestPing; for (var i = 0; i < packets.length; i++){ var parsedHead = parseAIS140Head(packets[i], socket); console.log(parsedHead); if (parsedHead.cmd == 'ping') { pings.push(parseAIS140Ping(packets[i])); } if (parsedHead.cmd == 'login_request') { logins.push(packets[i]); } if (parsedHead.cmd == 'heartbeat') { hbts.push(packets[i]); } if (parsedHead.cmd == 'alertPacket') { alertPackets.push(packets[i]); } } if (pings.length > 0) { for (var i = 0; i < pings.length; i++){ pings[i].processed = false; if (pings[i].msgID == '10') { pings[0].sos == true; } } if (alertPackets.length) { } latestPing = pings.splice(0, 1); GPS.insertMany(pings, function (err, insertedAISPings) { if(err){ console.log(err); } else { //console.log('insertedAISPings', insertedAISPings); } }) } //console.log('latestPing', latestPing); if (latestPing) { latestPing[0].processed = null; return latestPing[0]; } else { return null; } } module.exports.intermediate = function (data) { // console.log(data.data); module.exports.process(data, KafkaService); } module.exports.process = function (data, KafkaService) { try { var raw = data.data var socket = data.socket var parsedData = {} /** * mTracker proto * */ if (!(Buffer.isBuffer(raw))) { //console.log('mobile tracker : ', raw); //socket.setTimeout(5000); if (!raw.imei) return; parsedData = parseMobileTrackerData(raw); //console.log(raw); } else if (raw.toString('utf8').indexOf('$Header') == 0) { //console.log('ais140 : ', raw); var packets = raw.toString('utf8').split('\r\n'); packets.pop(); //console.log("AIS PACKETS :: ", packets); parsedData = parseAIS140Packets(packets, socket); socket.setTimeout(0); //var parsedHead = parseAIS140Head(raw, socket); //console.log(parsedHead); if (parsedData) { //parsedData = parseAIS140ping(raw); //console.log(parsedData); } else { return; } } else if(/* raw.toString("utf8").split('=')[1] */ raw.toString('utf8').indexOf('ApiString') == 0){ //GB101 //console.log('gb101 : ', raw); if (true) { var raw1 = raw.toString("utf8").split('=')[1]; socket.write('+##Received OK'); parsedData = parseRawGpsGB(raw1, 'GB'); } } else if (Buffer.from(raw, 'hex').toString('hex').indexOf('00') == 0) { //fmb protocol //console.log('fmb : ', raw); var hexString = Buffer.from(raw, 'hex').toString('hex'); if (hexString.indexOf('00000000') == 0) { parsedData = parseFmbData(hexString, socket); sendFmbAck(socket, parsedData.number_of_data); } else if(hexString.indexOf('00') == 0){ fmb_login(hexString, socket); //return; } } else if (raw.toString('utf8').indexOf("imei:") != -1) { //console.log('COBAN GPS103/GPS303 : ', raw); /** * COBAN GPS103/GPS303 PROTOCOL */ var gps_x03 = new GPS_x03(raw.toString('utf8'), socket); if (gps_x03.command == 'login') { gps_x03.doLogin(); } if (gps_x03.command == 'tracker') { parsedData = gps_x03.getPingData(); } } else if (raw.toString('utf8').indexOf('(') == 0 && (raw.toString('utf8').lastIndexOf(')') == (raw.toString('utf8').length - 1)) && raw.toString('utf8').indexOf(' ') != 1) { //tk protocol var data = raw.toString('utf8'); var cmd_start = data.indexOf("B"); if(data.substr(cmd_start,4)=='BP05') { socket.write('('+data.substring(1,cmd_start) + 'AP05)'); return; } parsedData = parseRawGps(raw.toString('utf8'), 'TK'); //console.log('TK : ', raw, parsedData.imei); } else if(raw.toString("utf8").indexOf('$$CLIENT_1')==0) { //console.log('$$CLIENT_1 : ', raw); if(raw.toString("utf8").indexOf('Ignition') != -1) { parsedData = parseRawGpsTs(raw.toString('utf8'), 'first'); } else { parsedData = parseRawGpsTs(raw.toString('utf8'), 'rest'); } } else if(raw.toString("utf8").indexOf('Sender')==0) { //console.log('Sender : ', raw); parsedData = parseRawGpsVTX(raw.toString("utf8")); socket.write('Ok'); } //'yantra' protocol else if (raw.toString('utf8').split(',').length >= 3 && raw.toString('utf8').startsWith('$') && raw.toString('utf8').endsWith('#')) { //console.log('Yantra : ', raw); if (raw.toString('utf8').startsWith('$3')) { //alert packet //parsedData = parseYantraAlert(raw.toString('utf8')); } else { //data packet parsedData = parseYantraData(raw.toString('utf8')); console.log(parsedData); socket.destroy(); } } else if (raw.toString('utf8').split(',').length >= 3 ) { //console.log('g900 : ', raw); //g900 protocol if (raw.toString('utf8').split(',').length == 3) { /** * implement authorizeG900 */ cmdPacket = Buffer.from(raw).toString('hex') cmdPackets.create({ cmd: cmdPacket, device_id: cmdPacket.split(',')[1], time: new Date() }, function (err, inserted) { if (err) { console.error(err) return; } else { } }); //change_G900WKMD(socket, raw.toString('utf8').split(',')[1]) return; } /* var hh = new Date().getHours() < 10 ? '0' + new Date().getHours() : new Date().getHours().toString() var mm = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes().toString() var ss = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds().toString() */ if (raw.toString('utf8').split(',').length >= 12) { parsedData = parseRawGps(raw.toString('utf8'), 'G'); } } else if (Buffer.from(raw, 'hex').toString('hex').indexOf('2323') == 0) { //t8803 protocol //console.log('t8803 : ', raw); var parsedHead = parseT8803_head(raw, socket); if (parsedHead.cmd == 'login_request') { authorizeT8803(parsedHead.device_id, socket); return; } if (parsedHead.cmd == 'ping') { parsedData = parseT8803_data(raw); return; } if (parsedHead.cmd == 'heartbeat') { respond_T8803_heartbeat(parsedHead.device_id, socket); return; } } else if (Buffer.from(raw, 'hex').toString('hex').indexOf('2929') == 0) { //VT1000 protocol //console.log('VT1000 : ', raw); if(Buffer.from(raw, 'hex').toString('hex').indexOf('B1')==4) { socket.write('21'); } if(Buffer.from(raw, 'hex').toString('hex').indexOf('80')==4) { parsedData = parseVT1000(Buffer.from(raw, 'hex').toString('hex')); } } else if (Buffer.from(raw, 'hex').toString('hex').indexOf('20') == 0) { //L100 protocol //console.log('L100 : ', raw); parsedData = parseRawGpsL(Buffer.from(raw, 'hex').toString('hex')); } else if (raw.toString('hex').indexOf('24') == 0) { //console.log('24 : ', raw); raw = raw.toString('hex'); var head = raw.substr(0, 2); var imei = raw.substr(2, 10); var date = new Date( parseInt('20' + raw.substr(22, 2)), parseInt(raw.substr(20, 2) - 1), parseInt(raw.substr(18, 2)), parseInt(raw.substr(12, 2)), parseInt(raw.substr(14, 2)), parseInt(raw.substr(16, 2)) ); var latitude = parseInt(raw.substr(24, 2)) + (parseFloat(raw.substr(26,6)) / 600000); var longitude = parseInt(raw.substr(34, 3)) + (parseFloat(raw.substr(37,6)) / 600000);//parseInt(raw.substr(34, 9)) / 1000000;//dex_to_degrees(raw.substr(34, 9), 0) // var speed = parseInt(raw.substr(44, 3)).toString(); var heading = parseInt(raw.substr(47, 3)).toString(); parsedData = { imei: imei, date: date, latDecimal: latitude, longDecimal: longitude, latString: raw.substr(24, 8), longString: raw.substr(34, 9), raw: raw, speed: speed, heading: heading, insertionTime: new Date(), geoJSON: { "type": "Point", "coordinates": [longitude, latitude] } } console.log(parsedData); } else if (Buffer.from(raw, 'hex').toString('hex').indexOf('6767') == 0) { //gm-06 protocol //console.log('gm-06 : ', raw); var parsedHead = parseGM06_Head(raw, socket); if (parsedHead.cmd == 'login_request') { console.log(Buffer.from(raw, 'hex').toString('hex')) authorizeGM06(socket, parsedHead, raw); parsedHead.insertionTime = new Date(); } else if (parsedHead.cmd == 'ping') { parsedData = get_GM06_ping_data(parsedHead, raw, socket); } else if (parsedHead.cmd == 'heartbeat') { receive_GM06_heartbeat(raw, socket) parsedHead.insertionTime = new Date(); /** * parse HEARTBEAT DATA */ var parsed_HBT = JSON.parse(JSON.stringify(parsedHead)) parsed_HBT.device_id = parsed_HBT.device_id.toString(); parsed_HBT.insertionTime = new Date(); var batteryStatus = parseInt(parsedHead.data.substr(1, 1)).toString(); var gsmSignal = parseInt(parsedHead.data.substr(2, 1)); var terminalInfo = parseInt(parsedHead.data.substr(2, 2), 16).toString(2); while (terminalInfo.length < 8) { terminalInfo = '0' + terminalInfo } parsed_HBT.ignitionLock = terminalInfo.substr(2, 1) == '0' ? '1' : '0'; parsed_HBT.gpsTracking = terminalInfo.substr(7, 1); parsed_HBT.alarm = terminalInfo.substr(2, 3); parsed_HBT.power = terminalInfo.substr(0, 1); parsed_HBT.activated = terminalInfo.substr(7, 1); parsed_HBT.ACC = terminalInfo.substr(6, 1); parsed_HBT.batteryStatus = batteryStatus; parsed_HBT.gsmSignal = gsmSignal; if (parsed_HBT.ACC == "") { parsed_HBT.ACC = "0"; } cmdPackets.create(parsed_HBT, function (err, cmdPkt) { if (err) { console.error(err) return; } else { TCPUTIL.setACCNotif(parsed_HBT.device_id, parsed_HBT.ACC, KafkaService) Device.findOne({ "Device_ID": parsed_HBT.device_id }).populate('user').exec(function (err, dev) { if (err) { console.error(err); } else if (dev) { /** * update last cmdPacket with the vehicle mapped against device */ cmdPackets.update({ _id: cmdPkt._id }, { $set: { vehicle: dev.vehicle } }).exec(); //---------------------------------------------------------------------------------- var previousPower = dev.power; var user = dev.user; dev['last_ACC'] = parsed_HBT.ACC; dev['last_ACC_on'] = new Date(); dev['batteryStatus'] = batteryStatus; dev['gsmSignal'] = parsed_HBT.gsmSignal; dev['ignitionLock'] = parsed_HBT.ignitionLock; dev['gpsTracking'] = parsed_HBT.gpsTracking; dev['alarm'] = parsed_HBT.alarm; dev['power'] = parsed_HBT.power; dev['activated'] = parsed_HBT.activated; //dev['user'] = dev.user._id; dev.save(function (err) { if (err) { console.error(err); } else { KafkaService.sendRecord({ namespace: "gpsio", room: parsed_HBT.device_id.toString(), channel: parsed_HBT.device_id.toString() + 'acc', data: [parsed_HBT.ACC, parsed_HBT.device_id.toString(), new Date(), dev] }) /* gpsio.to(parsed_HBT.device_id.toString()).emit(parsed_HBT.device_id.toString() + 'acc', parsed_HBT.ACC, parsed_HBT.device_id.toString(), new Date(), dev) */ TCPUTIL.setDeviceStatus(dev, null); if ((parsed_HBT.power == "0" || parsed_HBT.power == "1") && previousPower != parsed_HBT.power) { //setPowerNotification TCPUTIL.setPowerNotif(dev, parsed_HBT.power, KafkaService, user); } } }) } }) } }); } else if (parsedHead.cmd == 'alarm') { } } else { // console.log('gt-06 : ', raw); //gt-06 protocol var parsedHead = parseGT06_Head(raw, socket); var hasCombinedHBT = false; var indexOfHBT = raw.toString('hex').indexOf('78780a13'); if (indexOfHBT != -1 && indexOfHBT != 0) { /** * parse HEARTBEAT DATA */ //console.log('combined HBT detected for ', parsedHead.device_id) var hbtBuf = Buffer.from(raw.toString('hex').substr(indexOfHBT), 'hex'); //console.log(hbtBuf); var parsed_HBT = parseGT06_Head(hbtBuf, socket); parsed_HBT.device_id = parsed_HBT.device_id.toString(); parsed_HBT.insertionTime = new Date(); var batteryStatus = parseInt(parsed_HBT.data.substr(1, 1)).toString(); var gsmSignal = parseInt(parsed_HBT.data.substr(2, 1)); var terminalInfo = parseInt(parsed_HBT.data.substr(0, 2), 16).toString(2); while (terminalInfo.length < 8) { terminalInfo = '0' + terminalInfo } parsed_HBT.ignitionLock = terminalInfo.substr(0, 1); parsed_HBT.gpsTracking = terminalInfo.substr(1, 1); parsed_HBT.alarm = terminalInfo.substr(2, 3); parsed_HBT.power = terminalInfo.substr(5, 1); parsed_HBT.activated = terminalInfo.substr(7, 1); parsed_HBT.ACC = terminalInfo.substr(6, 1); parsed_HBT.batteryStatus = batteryStatus; parsed_HBT.gsmSignal = gsmSignal; if (parsed_HBT.ACC == "") { parsed_HBT.ACC = "0"; } TCPUTIL.processServerCommandQueue(parsed_HBT.device_id, socket); cmdPackets.create(parsed_HBT, function (err, cmdPkt) { if (err) { console.error(err) return; } else { //console.log('hbt created on dev', cmdPkt._id) TCPUTIL.setACCNotif(parsed_HBT.device_id, parsed_HBT.ACC, KafkaService) Device.findOne({ "Device_ID": parsed_HBT.device_id }).populate('user').exec(function (err, dev) { if (err) { console.error(err); } else if (dev) { /** * update last cmdPacket with the vehicle mapped against device */ cmdPackets.update({ _id: cmdPkt._id }, { $set: { vehicle: dev.vehicle } }).exec(); //---------------------------------------------------------------------------------- var previousPower = dev.power; var user = dev.user; dev['last_ACC'] = parsed_HBT.ACC; dev['last_ACC_on'] = new Date(); dev['batteryStatus'] = batteryStatus; dev['gsmSignal'] = parsed_HBT.gsmSignal; dev['ignitionLock'] = parsed_HBT.ignitionLock; dev['gpsTracking'] = parsed_HBT.gpsTracking; dev['alarm'] = parsed_HBT.alarm; dev['power'] = parsed_HBT.power; dev['activated'] = parsed_HBT.activated; dev['status'] = parsed_HBT.ACC == 1 ? 'IDLING' : 'STOPPED' //dev['user'] = dev.user._id; dev.save(function (err) { if (err) { console.error(err); } else { KafkaService.sendRecord({ namespace: "gpsio", room: parsed_HBT.device_id.toString(), channel: parsed_HBT.device_id.toString() + 'acc', data: [parsed_HBT.ACC, parsed_HBT.device_id.toString(), new Date(), dev] }) /* gpsio.to(parsed_HBT.device_id.toString()).emit(parsed_HBT.device_id.toString() + 'acc', parsed_HBT.ACC, parsed_HBT.device_id.toString(), new Date(), dev) */ TCPUTIL.setDeviceStatus(dev, null); if ((parsed_HBT.power == "0" || parsed_HBT.power == "1") && previousPower != parsed_HBT.power) { //setPowerNotification TCPUTIL.setPowerNotif(dev, parsed_HBT.power, KafkaService, user); } } }) } }) } }); } if (parsedHead.device_id == '') { socket.destroy(); return; } if (parsedHead.start == '7878') { if (parsedHead.device_id == '860016021075051') { console.log(parsedHead); } if (parsedHead.cmd == 'login_request') { authorizeGT06(socket, parsedHead, raw); parsedHead.insertionTime = new Date(); } else if (parsedHead.cmd == 'ping') { gt06_ping_response(socket) parsedData = get_GT06_ping_data(parsedHead, raw, socket); if (parsedData.latDecimal == 0) { console.info('gt06 0,0 from : ' + socket.imei) } } else if (parsedHead.cmd == 'heartbeat') { receive_heartbeat(raw, socket) parsedHead.insertionTime = new Date(); /** * parse HEARTBEAT DATA */ var parsed_HBT = JSON.parse(JSON.stringify(parsedHead)) parsed_HBT.device_id = parsed_HBT.device_id.toString(); parsed_HBT.insertionTime = new Date(); var batteryStatus = parseInt(parsedHead.data.substr(1, 1)).toString(); var gsmSignal = parseInt(parsedHead.data.substr(2, 1)); var terminalInfo = parseInt(parsedHead.data.substr(0, 2), 16).toString(2); while (terminalInfo.length < 8) { terminalInfo = '0' + terminalInfo } parsed_HBT.ignitionLock = terminalInfo.substr(0, 1); parsed_HBT.gpsTracking = terminalInfo.substr(1, 1); parsed_HBT.alarm = terminalInfo.substr(2, 3); parsed_HBT.power = terminalInfo.substr(5, 1); parsed_HBT.activated = terminalInfo.substr(7, 1); parsed_HBT.ACC = terminalInfo.substr(6, 1); parsed_HBT.batteryStatus = batteryStatus; parsed_HBT.gsmSignal = gsmSignal; if (parsed_HBT.ACC == "") { parsed_HBT.ACC = "0"; } TCPUTIL.processServerCommandQueue(parsed_HBT.device_id, socket); cmdPackets.create(parsed_HBT, function (err, cmdPkt) { if (err) { console.error(err) return; } else { TCPUTIL.setACCNotif(parsed_HBT.device_id, parsed_HBT.ACC, KafkaService) Device.findOne({ "Device_ID": parsed_HBT.device_id }).populate('user').exec(function (err, dev) { if (err) { console.error(err); } else if (dev) { /** * update last cmdPacket with the vehicle mapped against device */ cmdPackets.update({ _id: cmdPkt._id }, { $set: { vehicle: dev.vehicle } }).exec(); //---------------------------------------------------------------------------------- var previousPower = dev.power; var user = dev.user; dev['last_ACC'] = parsed_HBT.ACC; dev['last_ACC_on'] = new Date(); dev['batteryStatus'] = batteryStatus; dev['gsmSignal'] = parsed_HBT.gsmSignal; dev['ignitionLock'] = parsed_HBT.ignitionLock; dev['gpsTracking'] = parsed_HBT.gpsTracking; dev['alarm'] = parsed_HBT.alarm; dev['power'] = parsed_HBT.power; dev['activated'] = parsed_HBT.activated; dev['status'] = parsed_HBT.ACC == 1 ? 'IDLING' : 'STOPPED' //dev['user'] = dev.user._id; dev.save(function (err) { if (err) { console.error(err); } else { KafkaService.sendRecord({ namespace: "gpsio", room: parsed_HBT.device_id.toString(), channel: parsed_HBT.device_id.toString() + 'acc', data: [parsed_HBT.ACC, parsed_HBT.device_id.toString(), new Date(), dev] }) /* gpsio.to(parsed_HBT.device_id.toString()).emit(parsed_HBT.device_id.toString() + 'acc', parsed_HBT.ACC, parsed_HBT.device_id.toString(), new Date(), dev) */ TCPUTIL.setDeviceStatus(dev, null); if ((parsed_HBT.power == "0" || parsed_HBT.power == "1") && previousPower != parsed_HBT.power) { //setPowerNotification TCPUTIL.setPowerNotif(dev, parsed_HBT.power, KafkaService, user); } } }) } }) } }); } else if (parsedHead.cmd == 'alert') { parsedData = get_GT06_alarm_data(parsedHead, raw, socket); } else if (parsedHead.cmd == 'stringInfo') { console.log(parsedHead); console.log(socket.imei, socket.serverCommand) var parsedStringInfo = parse_GT06_stringInfo(parsedHead); TCPUTIL.setDCQResponse(parsedStringInfo, socket.imei); return; } } else if (parsedHead.start.indexOf('28') != -1 || parsedHead.start.indexOf('24') != -1) { console.log(parsedHead) parsedData = parseG500OBD_data(raw) } else { console.info("UNKNOWN PROTOCOL DETECTED") } } if (parsedData && parsedData.command == 'BP00') { socket.write(parsedData.imei + 'AP01HSO') } /** * identify if server commands are queued to be sent for this imei */ if(parsedData){ TCPUTIL.processServerCommandQueue(parsedData.imei, socket); } if (parsedData && parsedData.imei && (parsedData.command == 'BR00' || parsedData.command == 'V1' || parsedData.command == '12' || parsedData.command == '22' || parsedData.command == '19' || parsedData.command == '2084' || parsedData.command == '08' || parsedData.command == 'GB' || parsedData.command == 'L100' || parsedData.command == '80' || parsedData.command == 'TS' || parsedData.command == 'VTX' || parsedData.command == 'mPing' || parsedData.command == 'tracker' || parsedData.command == '$' || parsedData.command == '$3' || parsedData.command == '02' || parsedData.command == '16' || !parsedData.command || parsedData.command == 'NR' || parsedData.command == 'EA' || parsedData.command == 'TA' || parsedData.command == 'HP' || parsedData.command == 'IN' || parsedData.command == 'IF' || parsedData.command == 'BD' || parsedData.command == 'BR' || parsedData.command == 'BL' )) { GPS .aggregate([ { $match: { "imei": parsedData.imei , isPastData: {$ne : true} } }, // { $sort: { "insertionTime": -1 } }, { $limit: 1 }, { $lookup: { from: "devInfo", localField: "imei", foreignField: "Device_ID", as: "lookedUpDevice" } }, { $unwind: "$lookedUpDevice" }, { $lookup: { from: "client_master", localField: "lookedUpDevice.user", foreignField: "_id", as: "lookedUpUser" } }, { $lookup: { from: "trackroutes", localField: "lookedUpDevice.currentRoute", foreignField: "_id", as: "lookedUpCurrentRoute" } }, { $unwind: { path: "$lookedUpCurrentRoute", preserveNullAndEmptyArrays: true } }, { $lookup: { from: "routeDeviceMap", localField: "lookedUpDevice.currentTrip", foreignField: "_id", as: "lookedUpCurrentTrip" } }, { $unwind: { path: "$lookedUpCurrentTrip", preserveNullAndEmptyArrays: true } }, { $lookup: { from: "vehicletypes", localField: "lookedUpDevice.vehicleType", foreignField: "_id", as: "lookedUpVehicleType" } }, { $unwind: { path: "$lookedUpVehicleType", preserveNullAndEmptyArrays: true } } ]).allowDiskUse(true) .exec(function (err, x) { if (err) { console.error(err); return; } var dataForRoadAPI = ''; if (true) { var displacement = 0; if (x.length > 0) { displacement = TCPUTIL.getDistanceFromLatLonInKm( x[0].latDecimal, x[0].longDecimal, parsedData.latDecimal, parsedData.longDecimal ) } if ((parsedData.latDecimal == 0 || parsedData.longDecimal == 0) && x[0]) { TCPUTIL.setDeviceStatus(x[0].lookedUpDevice, 'nofix'); } if (/*x[0] && displacement > 0.40 && (new Date() - new Date(x[0].insertionTime) < 15000) && parsedData.imei != '868728030654476' && parsedData.imei != '2020202020'*/ false) { //do nothing console.log("Too much displacement in short time for " + parsedData.imei); } else if (/*new Date(parsedData.insertionTime) - new Date(parsedData.date) > (5 * 60 * 1000) && (parsedData.command == 'BR00' || parsedData.command == '22') && parsedData.imei != '123456789012345' && parsedData.command != "08"*/ false) { //do nothing console.log("Insertion time - date > 5 mins " + parsedData.imei); } else if (x[0] && new Date() - new Date(parsedData.date) < (-1 * 365 * 24 * 60 * 60 * 1000) && parsedData.imei != '123456789012345' && parsedData.command != "08") { //do nothing console.log("Device from future " + parsedData.imei); } else { if (x[0] && x[0].lookedUpDevice.last_device_time && new Date(parsedData.date) - new Date(x[0].lookedUpDevice.last_device_time) < 1 && parsedData.imei != '123456789012345') { //do nothing if(parsedData.isPastData == null) parsedData.isPastData = true; if (x[0] && new Date(parsedData.date) - new Date(x[0].date) < 1 && parsedData.imei != '123456789012345') { //console.log("Chronology not maintained by device " + parsedData.imei); } } if ( x[0] && displacement < FLUCTUATION_THRESHOLD && parsedData.command != 'mPing' && ((parsedData.speed == 0 && x.length > 0 && x[0].speed == 0) || (x[0].lookedUpDevice && x[0].lookedUpDevice.ignitionSource != 'MOVEMENT' && x[0].lookedUpDevice.last_ACC == 0 && parsedData.speed <10 && x.length > 0 && x[0].speed < 10)) ) { //recalculate displacement on interpolated fields parsedData.isFluctuation = true; /** * if displacement from last location < FLUCTUATION_THRESHOLD * and speed == 0 * then update the last ping data with current time */ //("MITIGATING FLUCTUATION") } if(parsedData.command == 'mPing'){ if(parsedData.accuracy > 27){ parsedData.isFluctuation = true; } } if (parsedData.insertionTime != 'Invalid Date' && parsedData.latDecimal != 0 && parsedData.longDecimal != 0 && typeof parsedData.latDecimal == "number" && typeof parsedData.longDecimal == "number" && parsedData.speed != "NaN" && !isNaN(parseFloat(parsedData.latDecimal)) && !isNaN(parseFloat(parsedData.longDecimal))) { if (x[0]) { parsedData.vehicle = ObjectID(x[0].lookedUpDevice.vehicle); //get distance on interpolated points, if interpolation was returned by google api var interpolatedDistance = 0; var previousLat; var previousLong; if (x[0].interpolated && x[0].interpolated.length > 0) { previousLat = x[0].interpolated[x[0].interpolated.length - 1].location.latitude previousLong = x[0].interpolated[x[0].interpolated.length - 1].location.longitude } else { previousLat = x[0].latDecimal previousLong = x[0].longDecimal } if (parsedData.interpolated && parsedData.interpolated.length > 1) { interpolatedDistance += TCPUTIL.getDistanceFromLatLonInKm( previousLat, previousLong, parsedData.interpolated[0].location.latitude, parsedData.interpolated[0].location.longitude ) for (var m = 0; m < parsedData.interpolated.length - 1; m++) { interpolatedDistance += TCPUTIL.getDistanceFromLatLonInKm( parsedData.interpolated[m].location.latitude, parsedData.interpolated[m].location.longitude, parsedData.interpolated[m + 1].location.latitude, parsedData.interpolated[m + 1].location.longitude ) } } else { interpolatedDistance = TCPUTIL.getDistanceFromLatLonInKm( previousLat, previousLong, parsedData.latDecimal, parsedData.longDecimal ) } /* parsedData.distanceFromPrevious = interpolatedDistance; parsedData.odo = x[0].lookedUpDevice.total_odo + parsedData.distanceFromPrevious; */ if (parsedData.odo != null) { parsedData.distanceFromPrevious = parsedData.odo - (x[0].lookedUpDevice.total_odo || 0); interpolatedDistance = parsedData.distanceFromPrevious; } else { parsedData.distanceFromPrevious = interpolatedDistance; parsedData.odo = x[0].lookedUpDevice.total_odo + parsedData.distanceFromPrevious; } } if (parsedData.fuelVoltage && x[0] && parsedData.ignition == '1') { if (!(x[0].lookedUpDevice.last_ACC == 1 && (new Date() - new Date(x[0].lookedUpDevice.last_ACC_on) > 3 * 60 * 1000))) { parsedData.currentFuel = x[0].lookedUpDevice.currentFuel; } else if (x[0].lookedUpDevice.vehicleType !== null) { if (x[0].lookedUpVehicleType) { var currentFuel = TCPUTIL.getCurrentFuel(x[0].lookedUpVehicleType, parsedData.fuelVoltage); if (currentFuel[1] > x[0].lookedUpVehicleType.tank_size) { parsedData.currentFuel = x[0].lookedUpVehicleType.tank_size } else if (currentFuel[1] < 0) { parsedData.currentFuel = 0; } else { parsedData.currentFuel = currentFuel[1]; } } } } else if (parsedData.fuelVoltage && x[0] && parsedData.ignition == '0') { parsedData.currentFuel = x[0].lookedUpDevice.currentFuel; } //if speed is less than 1, ignore if (parseFloat(parsedData.speed) < 1) { parsedData.speed = "0"; } parsedData.speed = parsedData.speed ? parsedData.speed.toString().split('.')[0] : null; if (x[0] && x[0].lookedUpDevice) { parsedData.group = x[0].lookedUpDevice.vehicleGroup; parsedData.vehicle = ObjectID(x[0].lookedUpDevice.vehicle); } MongoClient.connect(url, dbOption, function (err, db) { if (err) { console.error(err) return; } db.collection('gpstracker').insertOne(parsedData, function (err, inserted) { if (err) { console.error(err) console.error('Could not saved gps ping to db') db.close() } else { db.close() if (x[0]) { if (parsedData.isPastData == true) { if (parsedData.sos == true) { TCPUTIL.setSOSNotif(x[0], parsedData, KafkaService); } return; } if (parsedData.isFluctuation && parsedData.command == 'mPing') { return; } KafkaService.sendRecord({ namespace: "gpsio", room: parsedData.imei, channel: parsedData.imei, data: [parsedData, 'ping', x[0].lookedUpDevice] }) //gpsio.to(parsedData.imei).emit(parsedData.imei, parsedData, 'ping', x[0].lookedUpDevice); TCPUTIL.setMaxSpeed(parsedData, x[0].lookedUpDevice, x[0].lookedUpUser[0], new Date()); //TCPUTIL.routeTracking(x[0].lookedUpDevice.Device_ID, parsedData.longDecimal, parsedData.latDecimal, null, x[0], KafkaService); //poi tracking TCPUTIL.poiTracking(x[0], null, parsedData.longDecimal, parsedData.latDecimal, KafkaService); var start = null; var end = null; if (parsedData.sos == true) { TCPUTIL.setSOSNotif(x[0], parsedData, KafkaService); } if (parsedData.ignition != null && parsedData.ignition !== undefined) { if (parsedData.command == 'BR00') { //tk103 var data = parsedData.raw; start = "28"; end = "29"; var cmd_start = data.indexOf("B"); var dataval = data.substring(cmd_start + 4, data.length - 1); } if (parsedData.command == 'V1') { //tk103 var data = parsedData.raw; start = "*HQ"; end = "#"; var dataval = data; } if (parsedData.command == '08') { //fmbXXX var data = parsedData.raw; start = "00000000"; var cmd_start = data.indexOf("00000000"); var dataval = data.substring(cmd_start + 4, data.length - 1); } if (parsedData.command == 'GB') { //fmbXXX var data = parsedData.raw; start = "{"; end = "}" //var cmd_start = data.indexOf("00000000"); //var dataval=data.substring(cmd_start+4,data.length-1); var dataval = ''; } if (parsedData.command == 'L100') { //fmbXXX var data = parsedData.raw; start = "20"; end = "02"; var startcmd = data.indexOf('$GPRMC'); var dataval = data.substring(startcmd); //var dataval=data.substring(cmd_start+4,data.length-1); } if (parsedData.command == '80') { //fmbXXX var data = parsedData.raw; start = "2929"; end = "0d"; var dataval = data.substring(10, 90); } if (parsedData.command == 'TS') { //fmbXXX var data = parsedData.raw; start = "$$"; end = "0a"; var dataval = data.substring(0, data.length - 2) } if (parsedData.command == 'VTX') { var data = parsedData.raw; start = "Sender"; end = "PKTEND"; var dataval = data.substring(7, data.length - 7); } if (parsedData.command == 'tracker') { var data = parsedData.raw; start = "imei:"; end = ";"; var dataval = data; } if (parsedData.command == 'NR' || parsedData.command == 'IF' || parsedData.command == 'EA') { var data = parsedData.raw; start = "$Header"; end = "*"; var dataval = data; } TCPUTIL.insertIgnition(parsedData, start, end, dataval, KafkaService); } // at line 804, write method to be called from TCPUTIL// if (parsedData.fuelVoltage && parsedData.currentFuel != null) { TCPUTIL.checkFuelFill(x[0], parsedData, x[0].lookedUpVehicleType.tank_size, KafkaService) } // if (parsedData.sos == true) { TCPUTIL.sosAlert(x[0].lookedUpDevice, x[0].lookedUpUser[0], parsedData); } var today_odo = 0 var distFromLastStop = 0 if (parsedData.isFluctuation) { interpolatedDistance = 0 today_odo = (x[0].lookedUpDevice.today_odo || 0) distFromLastStop = (x[0].lookedUpDevice.distFromLastStop || 0) } else { today_odo = interpolatedDistance + (x[0].lookedUpDevice.today_odo || 0) distFromLastStop = interpolatedDistance + (x[0].lookedUpDevice.distFromLastStop || 0) } var incObj = { "total_odo": interpolatedDistance }; var today_start_location = !x[0].lookedUpDevice.today_start_location ? { lat: parsedData.latDecimal, long: parsedData.longDecimal } : x[0].lookedUpDevice.today_start_location; //increment today_running / today_stopped if (x[0].lookedUpDevice.last_ACC == 1) { var today_running = new Date().getTime() - new Date(x[0].insertionTime).getTime(); incObj['today_running'] = today_running; } else { var today_stopped = new Date().getTime() - new Date(x[0].insertionTime).getTime(); incObj['today_stopped'] = today_stopped; } var parsedSpeed = parseInt(parsedData.speed); if (parsedData.ignition == 1 || (typeof parsedData.ignition === 'undefined' && x[0].lookedUpDevice.last_ACC == '1')) { if (0 <= parsedSpeed && parsedSpeed < 20) { incObj['speedChart.0-20'] = 1 } else if (20 <= parsedSpeed && parsedSpeed < 40) { incObj['speedChart.20-40'] = 1 } else if (40 <= parsedSpeed && parsedSpeed < 60) { incObj['speedChart.40-60'] = 1 } else if (60 <= parsedSpeed && parsedSpeed < 80) { incObj['speedChart.60-80'] = 1 } else if (80 <= parsedSpeed && parsedSpeed < 100) { incObj['speedChart.80-100'] = 1 } else if (100 <= parsedSpeed) { incObj['speedChart.>100'] = 1 } } Device.update( { "Device_ID": parsedData.imei }, { $set: { "last_loc.type": "Point", "last_loc.coordinates": [parsedData.longDecimal, parsedData.latDecimal], "sec_last_location.lat": x[0].lookedUpDevice.last_location ? x[0].lookedUpDevice.last_location.lat : null, "sec_last_location.long": x[0].lookedUpDevice.last_location ? x[0].lookedUpDevice.last_location.long : null, "sec_last_speed": x[0].lookedUpDevice.last_speed, "last_location.lat": parsedData.latDecimal, "last_location.long": parsedData.longDecimal, "last_ping_on": new Date(), "last_device_time" : new Date(parsedData.date), "last_speed": parsedData.speed, "currentFuel": parsedData.currentFuel != null ? parsedData.currentFuel : null, "currentFuelVoltage": parsedData.fuelVoltage ? parsedData.fuelVoltage : null, "satellites": parsedData.satellites ? parsedData.satellites : null, "gpsTracking": parsedData['GPS positioned'] ? parsedData['GPS positioned'] : "0", "today_odo": today_odo, "heading": parsedData.heading, "distFromLastStop": distFromLastStop, "power": (parsedData.power == "1" || parsedData.power == "0") ? parsedData.power : x[0].lookedUpDevice.power, "ac": parsedData.ac, "today_start_location" : today_start_location }, $inc: incObj }, function (err, numAffected) { if (err) { console.error(err); } if (!err) { Device.find({ "Device_ID": parsedData.imei }).populate('user').exec(function (err, devices) { if (err) { console.error(err); } else { if (devices[0].integrationId) { OutgoingIntegrations.deliver(devices[0], inserted.ops[0]); } KafkaService.sendRecord({ namespace: 'gpsio', room: devices[0].Device_ID, channel: devices[0].Device_ID.toString() + 'acc', data: [devices[0].last_ACC, devices[0].Device_ID.toString(), new Date(), devices[0]] }) //gpsio.to(devices[0].Device_ID).emit(devices[0].Device_ID.toString() + 'acc', devices[0].last_ACC, devices[0].Device_ID.toString(), new Date(), devices[0]) if ((parsedData.power == "0" || parsedData.power == "1") && x[0].lookedUpDevice.power != parsedData.power) { TCPUTIL.setPowerNotif(x[0].lookedUpDevice, parsedData.power, KafkaService, devices[0].user); } } }) TCPUTIL.setDeviceStatus(x[0].lookedUpDevice, null); if (x[0].lookedUpCurrentTrip) { RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $inc: { "distanceTravelled": interpolatedDistance } }).exec(); } } }); } else { var status = 'OUT OF REACH'; if (parsedData.ignition != null) { if(parsedData.ignition == 1){ if (parsedData.speed > 1) { status = 'RUNNING' } else { status = 'IDLING' } } if (parsedData.ignition == 0) { status = 'STOPPED' } } else{ status = 'STOPPED' } Device.update( { "Device_ID": parsedData.imei }, { $set: { "last_loc.type": "Point", "last_loc.coordinates": [parsedData.longDecimal, parsedData.latDecimal], //"sec_last_location.lat": x[0].lookedUpDevice.last_location ? x[0].lookedUpDevice.last_location.lat : null, //"sec_last_location.long": x[0].lookedUpDevice.last_location ? x[0].lookedUpDevice.last_location.long : null, //"sec_last_speed": x[0].lookedUpDevice.last_speed, "last_location.lat": parsedData.latDecimal, "last_location.long": parsedData.longDecimal, "last_ping_on": new Date(), "last_device_time" : new Date(parsedData.date), "last_speed": parsedData.speed, "status": status, "status_updated_at" : new Date(), //"currentFuel": parsedData.currentFuel != null ? parsedData.currentFuel : null, //"currentFuelVoltage": parsedData.fuelVoltage ? parsedData.fuelVoltage : null, "satellites": parsedData.satellites ? parsedData.satellites : null, "gpsTracking": parsedData['GPS positioned'] ? parsedData['GPS positioned'] : "0", //"today_odo": today_odo, "heading": parsedData.heading, //"distFromLastStop": distFromLastStop, "power": parsedData.power, "ac": parsedData.ac } } ).exec(); } } }) }); } else { if ((parsedData.latDecimal == 0 || parsedData.longDecimal == 0) && x[0]) { TCPUTIL.setDeviceStatus(x[0].lookedUpDevice, 'nofix'); Device.update( { "Device_ID": parsedData.imei }, { $set: { "last_loc.type": "Point", "last_loc.coordinates": [0, 0], "sec_last_location.lat": x[0].lookedUpDevice.last_location ? x[0].lookedUpDevice.last_location.lat : null, "sec_last_location.long": x[0].lookedUpDevice.last_location ? x[0].lookedUpDevice.last_location.long : null, "sec_last_speed": x[0].lookedUpDevice.last_speed, "last_location.lat": 0, "last_location.long": 0, "last_ping_on": new Date(), "last_device_time" : new Date(parsedData.date), "last_speed": parsedData.speed, "currentFuel": parsedData.currentFuel ? parsedData.currentFuel : null, "currentFuelVoltage": parsedData.fuelVoltage ? parsedData.fuelVoltage : null, "satellites": parsedData.satellites ? parsedData.satellites : null, } }).exec(); console.log("0,0 from : " + parsedData.imei); } } //}) /** SPEED LIMIT ALERTS */ if (x[0] && parsedData.latDecimal != 0 && typeof parsedData.latDecimal == "number" && typeof parsedData.longDecimal == "number" && !isNaN(parseFloat(parsedData.latDecimal)) && !isNaN(parseFloat(parsedData.longDecimal))) { if (parseFloat(parsedData.speed) >= x[0].lookedUpDevice.SpeedLimit && x[0].lookedUpDevice.SpeedAlert) { if (x[0].lookedUpDevice.overspeeding == true) { return; } TCPUTIL.sbTracking(null, x[0], 'os', parsedData.latDecimal, parsedData.longDecimal, null, null, parsedData.speed, KafkaService); Notifs.create({ "device": x[0].lookedUpDevice.Device_ID, "vehicle": x[0].lookedUpDevice.vehicle, "dealer": x[0].lookedUpDevice.created_by, "user": x[0].lookedUpUser[0]._id, "type": "overspeed", "priority" : 3, "group" : x[0].lookedUpDevice.vehicleGroup, "trip" : x[0].lookedUpDevice.currentTrip, "overSpeed" : parseFloat(parsedData.speed), "lat" : parsedData.latDecimal, "long" : parsedData.longDecimal, "vehicleName" : x[0].lookedUpDevice.Device_Name, "item": { "_type": "Speed Alert", "sentence": x[0].lookedUpDevice.Device_Name + " exceeded the speed limit of " + x[0].lookedUpDevice.SpeedLimit + ". Travelling at " + parseInt(parsedData.speed) + " kmph."} }, function (err, result) { if (err) { console.error(err) } else { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { overspeeding: true }, $inc: {today_overspeeds : 1} }).exec(); pushNotifs.notify(x[0].lookedUpUser[0], result); KafkaService.sendRecord({ namespace: 'notifIO', room: null, channel : x[0].lookedUpUser[0]._id, data : [result]}) //notifIO.emit(x[0].lookedUpUser[0]._id, result) Utilities.setAddress(result.lat,result.long,result._id,"address","notifications"); } }) } else if (parseFloat(parsedData.speed) < x[0].lookedUpDevice.SpeedLimit) { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { overspeeding: false } }).exec(); } } /**GEO FENCE ALERTS */ if (x[0] && parsedData.latDecimal != 0 && typeof parsedData.latDecimal == "number" && typeof parsedData.longDecimal == "number" && !isNaN(parseFloat(parsedData.latDecimal)) && !isNaN(parseFloat(parsedData.longDecimal))) { GeoFence.find( { geofence: { $geoIntersects: { $geometry: parsedData.geoJSON } }, uid: {$in : [x[0].lookedUpDevice.user, x[0].lookedUpDevice.created_by]}, status: true } ).exec(function (err, geoWithins) { if (err) { console.error(err); return; } if (geoWithins.length > 0) { /**if a location is found to be inside, determine if the previous location was inside or outside */ var geoWithin = geoWithins[0]; //update geofence model [field : devicesWithin] GeoFence.update( { _id: geoWithin._id }, { $addToSet: { devicesWithin: x[0].lookedUpDevice._id } }, function (err, inserted) { if (err) { console.error(err); } } ) GeoFence .find( { _id: geoWithin._id, geofence: { $geoIntersects: { $geometry: x[0].geoJSON } //uid : x[0].lookedUpDevice.user, //status: true } }) .exec(function (err, previousGeo) { if (err) { console.error(err) return } if (previousGeo.length > 0) { /** both ultimate and penultimate locations are inside. nothing's changed. */ } else { var tripId = null; if (x[0].lookedUpCurrentTrip) { tripId = x[0].lookedUpCurrentTrip._id; } //check if this geoFence is assigned as loading site for vehicle's current trip if (x[0].lookedUpCurrentTrip && x[0].lookedUpCurrentTrip.startSite.toString() == geoWithin._id.toString()) { tripId = x[0].lookedUpCurrentTrip._id; //vehicle entering start site if (x[0].lookedUpCurrentTrip.tripType == 2) { //two way trip if (x[0].lookedUpCurrentTrip.endSiteExitAt && x[0].lookedUpCurrentTrip.startSiteExitAt) { // Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "UNASSIGNED", currentTrip : null, tripPTA : null, tripETA : null, loadingDeparture : null, unloadingDeparture : null } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "COMPLETED", startSiteReEnterAt: new Date(), tripPTA : null, tripETA : null } }).exec() TCPUTIL.sbTracking(null,x[0],'tripEnd', parsedData.latDecimal, parsedData.longDecimal,null,null,null,KafkaService) TCPUTIL.setTravelDelay('reverseTransitComplete', x[0].lookedUpCurrentTrip, new Date(), x[0].lookedUpDevice); if (x[0].lookedUpUser[0].tripGeneration == 'scheduled') { // createScheduledTrip /* TCPUTIL.setScheduledTrip(x[0].lookedUpDevice); */ } else if (x[0].lookedUpUser[0].tripGeneration == 'auto') { //change the vehicle's group to geo fence group if it is not the same //cancel current trip and create a new trip with the information available var d = new Date(); var newId = mongoose.Types.ObjectId(); tripId = newId; var newRouteMap = { "_id" : newId, "device" : x[0].lookedUpDevice._id, "user" : x[0].lookedUpUser[0]._id, "device_name": x[0].lookedUpDevice.Device_Name, "group" : x[0].lookedUpDevice.vehicleGroup, "driver" : x[0].lookedUpCurrentTrip ? x[0].lookedUpCurrentTrip.driver : null, "startSite" : geoWithin._id, "createdOn": d, "startSiteEnterAt" : d, "status" : "LOADING", "poi" : [], "tripType" : 2, "radius" : 500, "generated" : "auto" } RouteMap.create(newRouteMap, function (err, newTrip) { if (err) { console.error(err); return; } else { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "LOADING", vehicleGroup: geoWithin.vehicleGroup, currentTrip: newTrip._id, tripPTA : null, tripETA : null, loadingDeparture : null, unloadingDeparture : null } }).exec(); if (x[0].lookedUpCurrentTrip) { //RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "COMPLETED", startSiteReEnterAt: new Date(), tripPTA : null, tripETA : null } }).exec() //TCPUTIL.sbTracking(null,x[0],'tripEnd', parsedData.latDecimal, parsedData.longDecimal,null,null,null,sbNotifIO) } Groups.update({ _id: geoWithin.vehicleGroup }, { $addToSet: { devices: x[0].lookedUpDevice._id } }).exec() Groups.update({ _id: x[0].lookedUpDevice.vehicleGroup }, { $pull: { devices: x[0].lookedUpDevice._id } }).exec(); } }) } } else { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "LOADING" } }).exec() RouteMap.update({_id : x[0].lookedUpCurrentTrip._id}, {$set : {status : "LOADING", startSiteEnterAt : new Date()}}).exec() } } if (x[0].lookedUpCurrentTrip.tripType == 1) { //one way trip; set status to LOADING if (!x[0].lookedUpCurrentTrip.startSiteEnterAt){ Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "LOADING" } }).exec() RouteMap.update({_id : x[0].lookedUpCurrentTrip._id}, {$set : {status : "LOADING", startSiteEnterAt : new Date()}}).exec() } else if (geoWithin.type == 'Loading' && x[0].lookedUpUser[0].tripGeneration == 'auto') { //change the vehicle's group to geo fence group if it is not the same //cancel current trip and create a new trip with the information available var d = new Date(); var newId = mongoose.Types.ObjectId(); tripId = newId; var newRouteMap = { "_id" : newId, "device" : x[0].lookedUpDevice._id, "user" : x[0].lookedUpUser[0]._id, "device_name" : x[0].lookedUpDevice.Device_Name, "driver" : x[0].lookedUpCurrentTrip ? x[0].lookedUpCurrentTrip.driver : null, "startSite": geoWithin._id, "group" : x[0].lookedUpDevice.vehicleGroup, "createdOn": d, "startSiteEnterAt" : d, "status" : "LOADING", "poi" : [], "tripType" : 2, "radius" : 500, "generated" : "auto" } RouteMap.create(newRouteMap, function (err, newTrip) { if (err) { console.error(err); return; } else { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "LOADING", vehicleGroup: geoWithin.vehicleGroup, currentTrip: newTrip._id, tripPTA : null, tripETA : null, loadingDeparture : null, unloadingDeparture : null } }).exec(); if (x[0].lookedUpCurrentTrip) { RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "COMPLETED", cancelledAt: new Date(), tripPTA: null, tripETA: null }, $push: { deviations: {"type": "newLoading","time" : new Date()}} }).exec() } Groups.update({ _id: geoWithin.vehicleGroup }, { $addToSet: { devices: x[0].lookedUpDevice._id } }).exec() Groups.update({ _id: x[0].lookedUpDevice.vehicleGroup }, { $pull: { devices: x[0].lookedUpDevice._id } }).exec(); } }) } } if (x[0].lookedUpCurrentTrip.tripType == 0 && !x[0].lookedUpCurrentTrip.startSiteEnterAt) { //round trip; set status to LOADING Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "LOADING" } }).exec() RouteMap.update({_id : x[0].lookedUpCurrentTrip._id}, {$set : {status : "LOADING", startSiteEnterAt : new Date()}}).exec() } } else if (geoWithin.type == 'Loading' && x[0].lookedUpUser[0].tripGeneration == 'auto') { //change the vehicle's group to geo fence group if it is not the same //cancel current trip and create a new trip with the information available var d = new Date(); var newId = mongoose.Types.ObjectId(); tripId = newId; var newRouteMap = { "_id" : newId, "device" : x[0].lookedUpDevice._id, "user" : x[0].lookedUpUser[0]._id, "device_name" : x[0].lookedUpDevice.Device_Name, "driver" : x[0].lookedUpCurrentTrip ? x[0].lookedUpCurrentTrip.driver : null, "startSite": geoWithin._id, "group" : x[0].lookedUpDevice.vehicleGroup, "createdOn": d, "startSiteEnterAt" : d, "status" : "LOADING", "poi" : [], "tripType" : 2, "radius" : 500, "generated" : "auto" } RouteMap.create(newRouteMap, function (err, newTrip) { if (err) { console.error(err); return; } else { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "LOADING", vehicleGroup: geoWithin.vehicleGroup, currentTrip: newTrip._id, tripPTA : null, tripETA : null, loadingDeparture : null, unloadingDeparture : null } }).exec(); if (x[0].lookedUpCurrentTrip) { RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "COMPLETED", cancelledAt: new Date(), tripPTA : null, tripETA : null }, $push: { deviations: {"type": "newLoading","time" : new Date()}} }).exec() } Groups.update({ _id: geoWithin.vehicleGroup }, { $addToSet: { devices: x[0].lookedUpDevice._id } }).exec() Groups.update({ _id: x[0].lookedUpDevice.vehicleGroup }, { $pull: { devices: x[0].lookedUpDevice._id } }).exec(); } }) } //check if this geoFence is assigned as unloading site for vehicle's current trip if (x[0].lookedUpCurrentTrip && x[0].lookedUpCurrentTrip.endSite && x[0].lookedUpCurrentTrip.endSite.toString() == geoWithin._id.toString()) { tripId = x[0].lookedUpCurrentTrip._id; //vehicle entering end site if (x[0].lookedUpCurrentTrip.tripType == 2) { //two way trip if (!x[0].lookedUpCurrentTrip.endSiteEnterAt) { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "UNLOADING", tripPTA : null, tripETA : null } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "UNLOADING", endSiteEnterAt: new Date(), tripPTA: null, tripETA: null } }).exec() TCPUTIL.setTravelDelay('transitComplete', x[0].lookedUpCurrentTrip, new Date(), x[0].lookedUpDevice); } } if (x[0].lookedUpCurrentTrip.tripType == 1) { //one way trip; set status to LOADING Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "UNLOADING", tripPTA : null, tripETA : null } }).exec() RouteMap.update({_id : x[0].lookedUpCurrentTrip._id}, {$set : {status : "UNLOADING", endSiteEnterAt : new Date(), tripPTA : null, tripETA : null}}).exec() TCPUTIL.setTravelDelay('transitComplete', x[0].lookedUpCurrentTrip, new Date(), x[0].lookedUpDevice); } if (x[0].lookedUpCurrentTrip.tripType == 0 && x[0].lookedUpCurrentTrip.startSiteExitAt) { //one way trip; set status to COMPLETED Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "UNASSIGNED", currentTrip : null, tripPTA : null, tripETA : null, loadingDeparture : null, unloadingDeparture : null } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "COMPLETED", endSiteEnterAt: new Date(), tripPTA : null, tripETA : null } }).exec() TCPUTIL.sbTracking(null,x[0],'tripEnd', parsedData.latDecimal, parsedData.longDecimal,null,null,null,KafkaService) if (x[0].lookedUpUser[0].tripGeneration == 'scheduled') { // createScheduledTrip /* TCPUTIL.setScheduledTrip(x[0].lookedUpDevice); */ } } } else if (x[0].lookedUpCurrentTrip && geoWithin.type == 'Unloading') { if (geoWithin.vehicleGroup.toString() == x[0].lookedUpDevice.vehicleGroup.toString()) { tripId = x[0].lookedUpCurrentTrip._id; Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "UNLOADING", tripPTA : null, tripETA : null } }).exec() RouteMap.update({_id : x[0].lookedUpCurrentTrip._id}, {$set : {status : "UNLOADING", endSite: geoWithin._id, endSiteEnterAt : new Date(), tripPTA : null, tripETA : null}}).exec() TCPUTIL.setTravelDelay('transitComplete', x[0].lookedUpCurrentTrip, new Date(), x[0].lookedUpDevice); } } /**socket emit event for this 'imei' ENTERING geoFence 'geoWithin.name' */ if (geoWithin.entering == true) { Notifs.create({ "device": x[0].lookedUpDevice.Device_ID, "dealer": x[0].lookedUpDevice.created_by, "vehicle" : x[0].lookedUpDevice.vehicle, "user": x[0].lookedUpUser[0]._id, "type": "Geo-Fence", "org":x[0].lookedUpDevice.org, "priority" : 1, "group" : x[0].lookedUpDevice.vehicleGroup, "direction": "In", "trip" : tripId, "geoid" : geoWithin._id, "lat" : parsedData.latDecimal, "long" : parsedData.longDecimal, "vehicleName" : x[0].lookedUpDevice.Device_Name, "item": { "_type": "Geo-Fence Alert", "sentence": x[0].lookedUpDevice.Device_Name + " entered " + geoWithin.geoname } }, function (err, result) { if (err) { console.error(err) } else { GeofenceReports.create({ vehicle: x[0].lookedUpDevice.vehicle, device: x[0].lookedUpDevice._id, geofence: geoWithin._id, group : x[0].lookedUpDevice.vehicleGroup, org:x[0].lookedUpDevice.org, user: x[0].lookedUpUser[0]._id, arrivalTime: new Date() }, function (err, report) { if (err) { console.error(err); return; } //Utilities.setAddress(report.lat, report.long,report._id, "address", "geofenceReports") }) pushNotifs.notify(x[0].lookedUpUser[0], result); KafkaService.sendRecord({ namespace: 'notifIO', room: null, channel: x[0].lookedUpUser[0]._id, data: [result] }); //notifIO.emit(x[0].lookedUpUser[0]._id, result) Utilities.setAddress(result.lat,result.long,result._id,"address","notifications"); } }) } } }) } else { /**if a location is not found inside any geoFence, determine if the previous location was inside or outside ANY of the geoFences for that device */ //update geofence model [field : devicesWithin] GeoFence.update( {}, { $pull: { devicesWithin: x[0].lookedUpDevice._id } }, {multi : true}, function (err, inserted) { if(err){ console.error(err); } } ) GeoFence .find( { geofence: { $geoIntersects: { $geometry: x[0].geoJSON } }, uid: {$in : [x[0].lookedUpDevice.user, x[0].lookedUpDevice.created_by]}, status: true }) .populate('vehicleGroup') .exec(function (err, previousGeos) { if (err) { console.error(err) return } if (previousGeos.length > 0) { var tripId = null; if (x[0].lookedUpCurrentTrip) { tripId = x[0].lookedUpCurrentTrip._id; } //check if this geoFence is assigned as loading site for vehicle's current trip if (x[0].lookedUpCurrentTrip && x[0].lookedUpCurrentTrip.startSite.toString() == previousGeos[0]._id.toString()) { var now = new Date(); //vehicle exiting start site if (x[0].lookedUpCurrentTrip.tripType == 2) { //two way trip Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "TRANSIT", loadingDeparture : now } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "TRANSIT", startSiteExitAt: now } }).exec() TCPUTIL.sbTracking(null, x[0], 'tripStart', parsedData.latDecimal, parsedData.longDecimal, null, null, null, KafkaService); } if (x[0].lookedUpCurrentTrip.tripType == 1) { //one way trip; set status to LOADING Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "TRANSIT", loadingDeparture : now } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "TRANSIT", startSiteExitAt: now } }).exec() TCPUTIL.sbTracking(null, x[0], 'tripStart', parsedData.latDecimal, parsedData.longDecimal, null, null, null, KafkaService); } if (x[0].lookedUpCurrentTrip.tripType == 0) { //round trip; set status to Transit Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "TRANSIT", loadingDeparture : now } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "TRANSIT", startSiteExitAt: now } }).exec() TCPUTIL.sbTracking(null, x[0], 'tripStart', parsedData.latDecimal, parsedData.longDecimal, null, null, null, KafkaService); } if (x[0].lookedUpCurrentTrip.startSiteEnterAt) { TCPUTIL.setTimeAtSite(x[0].lookedUpCurrentTrip.startSiteEnterAt, now , x[0].lookedUpCurrentTrip._id, 'Loading'); } } //check if this geoFence is assigned as unloading site for vehicle's current trip if (x[0].lookedUpCurrentTrip && x[0].lookedUpCurrentTrip.endSite && x[0].lookedUpCurrentTrip.endSite.toString() == previousGeos[0]._id.toString()) { var now = new Date(); //vehicle exiting end site if (x[0].lookedUpCurrentTrip.tripType == 2) { //two way trip if (!x[0].lookedUpCurrentTrip.endSiteExitAt) { Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "TRANSIT-Return", unloadingDeparture : now } }).exec() RouteMap.update({_id : x[0].lookedUpCurrentTrip._id}, {$set : {status : "TRANSIT-Return", lastPOIIndex : null, endSiteExitAt : now}}).exec() } } if (x[0].lookedUpCurrentTrip.tripType == 1 && x[0].lookedUpCurrentTrip.status != "COMPLETED") { //one way trip; set status to LOADING Device.update({ _id: x[0].lookedUpDevice._id }, { $set: { currentTripStatus: "UNASSIGNED", currentTrip : null, tripPTA : null, tripETA : null, loadingDeparture : null, unloadingDeparture : null } }).exec() RouteMap.update({ _id: x[0].lookedUpCurrentTrip._id }, { $set: { status: "COMPLETED", endSiteExitAt: now, tripPTA : null, tripETA : null } }).exec() TCPUTIL.sbTracking(null, x[0], 'tripEnd', parsedData.latDecimal, parsedData.longDecimal, null, null, null, KafkaService); if (x[0].lookedUpUser[0].tripGeneration == 'scheduled') { // createScheduledTrip /* TCPUTIL.setScheduledTrip(x[0].lookedUpDevice); */ } } if (x[0].lookedUpCurrentTrip.endSiteEnterAt) { TCPUTIL.setTimeAtSite(x[0].lookedUpCurrentTrip.endSiteEnterAt, now, x[0].lookedUpCurrentTrip._id, 'Unloading'); } } /** socket emit event for this 'imei' EXITING all geoFences 'previousGeos[i].name'. */ for (var i = 0; i < 1; i++) { if (previousGeos[i].exiting == true) { var prevGeo = previousGeos[0]; Notifs.create({ "device": x[0].lookedUpDevice.Device_ID, "vehicle": x[0].lookedUpDevice.vehicle, "dealer": x[0].lookedUpDevice.created_by, "user": x[0].lookedUpUser[0]._id, "group" : x[0].lookedUpDevice.vehicleGroup, "type": "Geo-Fence", "priority" : 1, "direction": "Out", "trip" : tripId, "geoid" : previousGeos[0]._id, "lat" : parsedData.latDecimal, "long" : parsedData.longDecimal, "vehicleName" : x[0].lookedUpDevice.Device_Name, "item": { "_type": "Geo-Fence Alert", "sentence": x[0].lookedUpDevice.Device_Name + " exited " + previousGeos[0].geoname } }, function (err, result) { if (err) { console.error(err) } else { GeofenceReports.findOneAndUpdate( { device: x[0].lookedUpDevice._id, geofence: previousGeos[0]._id, departureTime: { $exists: false }, vehicle: x[0].lookedUpDevice.vehicle, user : x[0].lookedUpUser[0]._id }, { $set: { group : x[0].lookedUpDevice.vehicleGroup, departureTime: new Date(), vehicle: x[0].lookedUpDevice.vehicle, device: x[0].lookedUpDevice._id, geofence: previousGeos[0]._id, user : x[0].lookedUpUser[0]._id } }, { sort: { "_id": -1 }, new: true, upsert: true }, function (err, latest) { if (err) { console.error(err); return; } }) pushNotifs.notify(x[0].lookedUpUser[0], result); KafkaService.sendRecord({namespace : 'notifIO', room : null, channel : x[0].lookedUpUser[0]._id, data : [result]}) //notifIO.emit(x[0].lookedUpUser[0]._id, result) Utilities.setAddress(result.lat, result.long, result._id, "address", "notifications"); if (prevGeo.vehicleGroup) { var emails = prevGeo.vehicleGroup.contact_email; if (emails.length < 1) { return; } Notifs.findOne({ "device": x[0].lookedUpDevice.Device_ID, "type": "Geo-Fence", "direction": "In", "timestamp": { $lt: result.timestamp }, "geoid" : prevGeo._id }, {}, { sort: { 'timestamp' : -1 } }, function (err, lastInNotif) { if (err) { console.error(err); return; } if (lastInNotif) { if (!x[0].lookedUpUser[0]) { return; } var mailOptions = { from: Utilities.getConfig().mailUser, // sender address to: emails, // list of receivers //cc: emails.length > 1 ? emails.shift() : null, subject: Utilities.getConfig().orgName+"- GeoFence Activity", // Subject line moment(m.report_lastdate.overspeed).tz(m.timezone).format("YYYY-MM-DDTHH:mm"); html:'
Geo-Fence Vehicle In Time Out Time
'+prevGeo.geoname+' '+x[0].lookedUpDevice.Device_Name+' '+moment(lastInNotif.timestamp).tz(x[0].lookedUpUser[0].timezone).format("YYYY-MM-DD HH:mm")+' '+moment(result.timestamp).tz(x[0].lookedUpUser[0].timezone).format("YYYY-MM-DD HH:mm")+'
' } if(emails.length > 0){ Mailer.sendMail(mailOptions); } } }) } } }) } } } else { /**both ultimate and penultimate locations are inside. nothing's changed. */ } }) } }) } } } }); } } catch (error) { console.error(error); } }