agmission/Development/server/controllers/location.js

130 lines
4.0 KiB
JavaScript

'use strict';
const User = require('../model/user'),
LocCache = require('../model/location_cache'),
ObjectId = require('mongodb').ObjectId,
{ UserTypes } = require('../helpers/constants'),
queueHelper = require('../helpers/job_queue').getInstance(),
utils = require('../helpers/utils'),
geoUtils = require('../helpers/geo_util'),
{ Errors } = require('../helpers/constants'),
{ AppParamError, AppError } = require('../helpers/app_error');
/**
* Find all user and vehicles/users last locations under the same user's applicator (excluding this user)
* @returns last location list of { name, type, coors: [lat, lon], createdAt, updatedAt }
*/
async function nearMe_post(req, res) {
const ops = req.body;
const userId = ObjectId(req.uid);
const isDevice = (req.ut === UserTypes.DEVICE);
const user = await updateUserLoc({ uid: userId, kind: req.ut, coors: ops.coors || null });
const filter = {
$and: [
{
$or: [
{ kind: { $ne: UserTypes.DEVICE }, _id: { $ne: userId } },
{ kind: UserTypes.DEVICE, unitId: { $nin: [null, ''] } }
]
}
]
};
if (isDevice) {
if (user.unitId)
filter.$and[0].$or[1].unitId.$nin.push(user.unitId);
filter.$and.push({ $or: [{ _id: user.parent }, { parent: (user.kind === UserTypes.APP ? userId : user.parent) }] });
} else {
filter.$and.push({ $or: [{ _id: user.parent }, { parent: user.parent }] });
}
const ulocs = await User.aggregate([
{ $match: filter },
{
$project: {
_id: 0,
unitId: {
$cond: {
if: { $ne: ["$kind", "9"] }, then: { $toString: "$_id" }, else: "$unitId"
}
},
name: {
$cond: {
if: { $ne: ["$kind", "9"] }, then: { $arrayElemAt: [{ $split: ["$username", "@"] }, 0] }, else: "$name"
}
},
type: {
$cond: {
if: { $ne: ["$kind", "9"] }, then: "user", else: "ac"
}
}
}
},
{
$lookup: {
from: "location_cache",
localField: "unitId",
foreignField: "unitId",
as: "userLoc"
}
},
{ $unwind: { path: "$userLoc" } },
{
$project: {
name: 1, type: 1,
coors: ["$userLoc.lat", "$userLoc.lon"],
createAt: { $toDate: "$userLoc._id" },
updatedAt: "$userLoc.updatedAt"
}
}
]);
res.json(ulocs);
}
/**
* Update user location, return the user detail if existed
* @param {*} uloc User/Device location detail { uid: .., coors: [lat,lon], kind: userType }
*/
async function updateUserLoc(uloc) {
let userStrId = uloc.uid.toHexString();
const user = await User.findOne({ _id: uloc.uid }, '-password', { lean: true });
if (user) {
// Only log location if type is Device or Aircraft user account thus just update the user's latest location to location cache
if (!utils.isEmptyArray(uloc.coors) && geoUtils.isValidLL(uloc.coors[0], uloc.coors[1])) {
if (user.kind !== UserTypes.DEVICE || (user.kind === UserTypes.DEVICE && !user.unitId)) {
const updateRessult = await LocCache.updateOne({ unitId: userStrId },
{
$currentDate: { 'updatedAt': true, 'gdt': true },
$set: { lat: uloc.coors[0], lon: uloc.coors[1] }
},
{ upsert: true });
// Notify Track server to push the new added position for this user
if (updateRessult && updateRessult.modifiedCount || updateRessult.upsertedCount) {
const pkg = {};
pkg[userStrId] = [{ lat: utils.fixedTo(uloc.coors[0], 7), lon: utils.fixedTo(uloc.coors[1], 7), gdt: new Date() }];
queueHelper.publishLocTask(Buffer.from(JSON.stringify(pkg)));
}
}
}
return user;
}
else AppError.throw(Errors.USER_NOT_FOUND);
}
async function addpos_post(req, res) {
const ops = req.body;
if (!ops.coors) AppParamError.throw();
const uloc = await updateUserLoc({ uid: ObjectId(req.uid), kind: req.ut, coors: ops.coors })
res.json(uloc);
}
module.exports = {
nearMe_post, addpos_post
}