ggserver
Version:
GeoGate is an opensource GPS tracking server framework
254 lines (214 loc) • 9.7 kB
JavaScript
/*
* Copyright 2014 Fulup Ar Foll.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var MongoClient = require('mongodb').MongoClient; https://github.com/mongodb/node-mongodb-native
var util = require("util");
var Debug = require("../lib/_Debug");
MONGO_RECONNECT_TIMER=10*1000; // 10s timeout in between two MONGO reconnects
// ConnectDB is done on at creation time
function CreateConnection (backend) {
backend.Debug (4, "MongoDB creating connection [%s]", backend.uid);
MongoClient.connect(backend.uid, function (err, db) {
if (err) {
backend.Debug (0, "Fail to connect to MongoDB: %s err=[%s]", backend.uid, err)
} else {
backend.Debug (4, "Connected to MongoDB: %s", backend.uid)
backend.base = db;
}
});
}
// Create MongoDB Backend object
function BackendStorage (gateway, opts){
// prepare ourself to make debug possible
this.debug =opts.debug;
this.gateway=gateway;
this.opts=
{ hostname : opts.mongodb.hostname || "localhost"
, username : opts.mongodb.username
, password : opts.mongodb.password
, basename : opts.mongodb.basename || opts.mongo.username
, port : opts.mongodb.port || 27017
};
this.uid ="mongodb://" + this.opts.username + ':' + this.opts.password + "@" + this.opts.hostname +':'+ this.opts.port + "/" + this.opts.basename;
// create initial connection handler to database
CreateConnection (this);
}
// Import debug method
BackendStorage.prototype.Debug = Debug;
// Mongo is schema less and does not requiere to pre-create collections
BackendStorage.prototype.CheckTablesExits = function () {
var self = this;
self.Debug (3,"Check and Create collections if needed");
function ResponseCB (err, collection) {
self.Debug (1,"*** ResponseCB err=%j collection=%j", err, collection);
}
this.base.collection('ALL_Devices', {w:1}).createIndex({devid:1}, {unique: true, w:1}, ResponseCB);
};
// Typically would create an entry inside device database table
BackendStorage.prototype.CreateDev = function (devid, data) {
this.Debug (3,"Create entry in DB for device:%s data=%j", devid, data);
var self=this;
var gateway=this.gateway;
function DeviceCB (err, doc) {
self.Debug (6, 'Device Insert devid=%s doc=%j err=%j', devid, doc, err);
if (err !== null) {
gateway.event.emit ("notice", "ERROR-CREATDEVICE", "MongoDB", devid, err);
}
};
this.base.collection('T_' + devid,{w:1}).createIndex({date:1}, {w:1}, DeviceCB);
this.base.collection('A_' + devid,{w:1}).createIndex({date:1}, {w:1}, DeviceCB);
this.base.collection('O_' + devid,{w:1}).createIndex({date:1}, {w:1}, DeviceCB);
var article = {
devid : devid.toString()
,devname : data.devname
,callsign : data.callsign
,model : data.model
,collection: { track: 'T_' + devid, alarm: 'A_' + devid, obd: 'O_' + devid }
};
this.base.collection("ALL_Devices").insert (article, {w:1}, DeviceCB);
};
// Typically would create an entry inside device database table
BackendStorage.prototype.RemoveDev = function (devid) {
this.Debug (3,"Device Remove devid:%s", devid);
var gateway=this.gateway;
var self=this;
function ResponseCB (err, doc) {
self.Debug (6, 'Removing device doc=%j err=%j', doc, err);
if (err !== null) {
gateway.event.emit ("notice", "ERROR-REMOVEDEV", "remove MongoDB", devid, err);
}
}
this.base.collection("ALL_Devices").remove({devid:devid}, ResponseCB);
this.base.collection("T"+devid).drop(ResponseCB);
this.base.collection("A"+devid).drop(ResponseCB);
this.base.collection("O"+devid).drop(ResponseCB);
};
// Query are done asynchronously and function will return before result is knowned
BackendStorage.prototype.LoginDev = function (device) {
var self= this;
self.Debug (6,"Authenticate device:%s devid=%s", device.uid, device.devid);
function ResponseCB (err, responses) {
if (err) {
self.Debug (0, "MongoDB Find Err=%s", err);
return;
}
if (responses.length === 0) {
self.Debug(1, "Device %s not authenticated", device.devid);
} else {
var response = responses[0];
self.Debug(4, "Device %s authenticated Response=%j", device.devid, response);
device.name = response.name; // friendly name extracted from database
device.logged = true; // marked tracker as known from database
device.mogodevid = response._id; // this is MongoDB unique ID and not tracker's DEVID
device.mogotrack = self.base.collection(response.collection.track);
device.mogoobd = self.base.collection(response.collection.obd);
device.mogoalarm = self.base.collection(response.collection.alarm);
}
};
// connection to mongo is asynchronous we may reach a login before database is open
if (this.base !== undefined)
this.base.collection("ALL_Devices").find({devid: device.devid.toString()}).limit(1).toArray(ResponseCB);
};
// Query are done asynchronously and function will return before result is known
BackendStorage.prototype.LogoutDev = function (device) {
this.Debug(4, "Logout Device:%s", device.uid);
// change device status to logout
device.logged = false;
};
BackendStorage.prototype.TempryLoggin = function (device) {
this.Debug(6, "TempryLogin Device:%s", device.uid);
this.event.emit("dev-tmp", device);
};
BackendStorage.prototype.IgnorePosDev = function (device) {
this.Debug(6, "IgnoreDev Device:%s", device.uid);
this.event.emit("dev-ign", device);
};
// Query are done asynchronously and function will return before result is known
BackendStorage.prototype.UpdatePosDev = function (device) {
var self= this;
this.Debug (6,"Update Position device:%s devid=%s", device.uid, device.devid);
function ResponseCB (err, response) {
if (err !== null) {
self.Debug(0, 'Hoops MongoDB device=%s error=%j', device.devid, err);
return;
}
status = JSON.parse (response);
if (!status.ok) {
self.Debug(1, 'ERROR-TRACK insert devid=%s failed err=%j response=%j', device.devid, err, status);
} else {
self.Debug(6, "UPDATE-TRACK insert devid=%s MongoDB response=%j", device.devid, response);
}
}
// launch insertion of new position asynchronously
device.mogotrack.insert (device.stamp, {w:1}, ResponseCB);
};
// Query are done asynchronously and function will return before result is known
BackendStorage.prototype.UpdateObdDev = function (device) {
var self= this;
this.Debug (6,"Update OBD device:%s devid=%s", device.uid, device.devid);
function ResponseCB (err, response) {
if (err != null) {
self.Debug(0, 'Hoops MongoDB device=%s error=%j', device.devid, err);
return;
}
status = JSON.parse (response);
if (!status.ok) {
self.Debug(1, 'ERROR-UPDATE insert devid=%s failed err=%j response=%j', device.devid, err, status);
} else {
self.Debug(6, "UPDATE-OK insert devid=%s MongoDB response=%j", device.devid, response);
}
}
// launch insertion of new position asynchronously
device.mogoobd.insert (device.stamp, {w:1}, ResponseCB);
};
// Query are done asynchronously and function will return before result is known
BackendStorage.prototype.UpdateAlarmDev = function (device) {
var self= this;
this.Debug (6,"Update OBD device:%s devid=%s", device.uid, device.devid);
function ResponseCB (err, response) {
if (err != null) {
self.Debug(0, 'Hoops MongoDB device=%s error=%j', device.devid, err);
return;
}
status = JSON.parse (response);
if (!status.ok) {
self.Debug(1, 'ERROR-UPDATE insert devid=%s failed err=%j response=%j', device.devid, err, status);
} else {
self.Debug(6, "UPDATE-OK insert devid=%s MongoDB response=%j", device.devid, response);
}
}
// launch insertion of new position asynchronously
device.mogoalarm.insert (device.stamp, {w:1}, ResponseCB);
};
// Write last X positions on Telnet/Console
BackendStorage.prototype.LookupDev = function (callback, devid, limit) {
var self=this;
function ResponseCB (err, responses) {
self.Debug(6, 'LookupDev device doc=%j err=%j', responses, err);
if (err) {
self.Debug(0, "MongoDB Find Err=%s", err);
return;
}
if (responses.length === 0) {
self.Debug(1, "Device %s no positions avaliable", devid);
} else {
// send back DB position to application callback
callback(responses);
}
}
this.base.collection('T_'+ devid).find({}).limit(limit).sort({$natural: -1}).toArray(ResponseCB);
};
// export the class
module.exports = BackendStorage; // http://openmymind.net/2012/2/3/Node-Require-and-Exports/