130 lines
4.0 KiB
JavaScript
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
|
|
} |