我一直致力于使用 Node.JS、mongoDB 和 mongoose framwork 创建地理围栏和警报系统。
我有一辆带有传感器的车辆,它会不断发送其行驶经过的坐标。 现在,我需要检查该车辆是否进入了我之前创建的地理围栏。
如果车辆进入围栏,我需要向系统管理员发送警报。
但是我很困惑如何使用车辆本身提供的坐标和围栏的坐标来检查车辆是否进入围栏。
下面是我迄今为止使用过的代码。
Geofences.js 模型
const mongoose = require('mongoose');
const FenceSchema = mongoose.Schema({
fenceId : {type: String, unique: true, required: false},
fenceName : {type: String, required: true},
geoData : {type: Object, required: false},
description : {type: String, required: false},
status : {type: Boolean, required: false, default: true}
},{
versionKey: false,
timestamps: true
});
FenceSchema.index({ "geoData": "2dsphere" });
module.exports = mongoose.model("geofences", FenceSchema);
FenceAlerts.js 的示例数据
{
"_id" : ObjectId("5ef9b89334b4f12f74dd60a1"),
"fenceName" : "Ram Nagar",
"description" : "Should alert the admin when anyone enters or leaves through Ram Nagar",
"geoData" : {
"coordinates" : [
[
[
78.4521996974945,
17.4258916749477
],
[
78.4533584117889,
17.4262294770614
],
[
78.4534442424774,
17.4267617700325
],
[
78.4533584117889,
17.4273657159469
],
[
78.4528541564941,
17.4279389508985
],
[
78.4519529342651,
17.4280822593551
],
[
78.4514486789703,
17.4277854059987
],
[
78.4511590003967,
17.4269357885517
],
[
78.451384305954,
17.4262806591452
],
[
78.4521996974945,
17.4258916749477
]
]
],
"type" : "Polygon"
}
}
FenceAlerts.js 模型
const mongoose = require('mongoose');
const AlertSchema = mongoose.Schema({
deviceId : {type: mongoose.Schema.Types.ObjectId, ref: 'templates.devices', required: true},
fenceId : {type: mongoose.Schema.Types.ObjectId, ref: 'geofences', required: true},
status : {type: Boolean, required: true, default: true},
alertRule : {type: String, required: true},
notifyType : {type: String, enum: ['WARNING','DANGER','EMERGENCY'], defualt: "WARNING"}
},{
versionKey: false,
timestamps: true
});
module.exports = mongoose.model("fenceAlerts", AlertSchema);
FenceAlerts.js 的示例数据
{
"_id" : ObjectId("5efb0082260fca32e8b08bfe"),
"deviceId" : ObjectId("5ef9f8ffc667822e84ecec9e"), //DeviceName: "VEH-1"
"fenceId" : ObjectId("5ef9b89334b4f12f74dd60a1"),
"alertRule" : "Incoming",
"status" : true,
"notifyType" : "EMERGENCY"
}
车辆发送的坐标
{
"_id" : ObjectId("5efb3bcd829b9310c83091de"),
"latitude" : 40.25,
"longitude" : 20.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T13:19:09.989Z")
},
{
"_id" : ObjectId("5efb3bf5fc418a182c76d520"),
"latitude" : 42.25,
"longitude" : 21.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T13:19:49.045Z")
},
{
"_id" : ObjectId("5efb3dd028b6e533a071707e"),
"latitude" : 52.25,
"longitude" : 31.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T13:27:44.200Z")
},
{
"_id" : ObjectId("5efb3e06a78a9538b4c5b8a8"),
"latitude" : 22.25,
"longitude" : 15.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T13:28:38.431Z")
},
{
"_id" : ObjectId("5efb3e4b3e598f386cf88357"),
"latitude" : 20.25,
"longitude" : 18.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T13:29:47.391Z")
},
{
"_id" : ObjectId("5efb46267a00ce41fc466bbe"),
"latitude" : 80.25,
"longitude" : 18.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T14:03:18.579Z")
},
{
"_id" : ObjectId("5efb4670ceeab33c48973d86"),
"latitude" : 90.25,
"longitude" : 48.69,
"deviceId" : "VEH-1",
"entryDayTime" : ISODate("2020-06-30T14:04:32.951Z")
}
我一直在使用RabbitMQ和MQTT来持续传输数据。因此,随着车辆发送的每个有效负载,我需要检查车辆是否在围栏内。
但实际问题是,如何比较设备位置和栅栏坐标?
我见过
$geoWithin
但无法理解如何在我的案例中实施。无论如何,是否可以比较它们并返回类似“车辆进入围栏”和“车辆离开围栏”的字符串?
在研究类似需求的解决方案时看到这篇文章。所以,这不是一个完整的答案,而是一系列调查。
如上所述,有一个查询 $geoWithin。因此,当车辆位于地理围栏内时,该条件为真。
从 true 到 false 的变化,以及显然从 false 到 true 的变化,可以用来跟踪退出或进入。需要开发查询语法。