mirror of
https://github.com/FoggedLens/deflock.git
synced 2026-02-12 15:02:45 +00:00
a little hacky but it works
This commit is contained in:
@@ -16,5 +16,9 @@ val PekkoHttpVersion = "1.0.1"
|
||||
libraryDependencies ++= Seq(
|
||||
"org.apache.pekko" %% "pekko-actor-typed" % PekkoVersion,
|
||||
"org.apache.pekko" %% "pekko-stream" % PekkoVersion,
|
||||
"org.apache.pekko" %% "pekko-http" % PekkoHttpVersion
|
||||
"org.apache.pekko" %% "pekko-http" % PekkoHttpVersion,
|
||||
"io.circe" %% "circe-core" % "0.14.7",
|
||||
"io.circe" %% "circe-generic" % "0.14.9",
|
||||
"io.circe" %% "circe-parser" % "0.14.9",
|
||||
"org.apache.pekko" %% "pekko-http-cors" % PekkoHttpVersion
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.deflock.shotgun
|
||||
|
||||
import org.apache.pekko
|
||||
import org.apache.pekko.http.scaladsl.model.headers.{HttpOrigin, HttpOriginRange, `Access-Control-Allow-Origin`}
|
||||
import pekko.actor.typed.ActorSystem
|
||||
import pekko.actor.typed.scaladsl.Behaviors
|
||||
import pekko.http.scaladsl.Http
|
||||
@@ -17,16 +18,32 @@ object ShotgunServer {
|
||||
implicit val system: ActorSystem[Any] = ActorSystem(Behaviors.empty, "my-system")
|
||||
implicit val executionContext: ExecutionContextExecutor = system.executionContext
|
||||
|
||||
val route =
|
||||
path("oauth2" / "callback") {
|
||||
get {
|
||||
parameters(Symbol("code").?) { (code) =>
|
||||
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to Pekko HTTP</h1><p><b>Code: " + code.getOrElse("None") + "</b></p>"))
|
||||
val routes = {
|
||||
concat {
|
||||
path("oauth2" / "callback") {
|
||||
get {
|
||||
parameters(Symbol("code").?) { (code) =>
|
||||
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to Pekko HTTP</h1><p><b>Code: " + code.getOrElse("None") + "</b></p>"))
|
||||
}
|
||||
}
|
||||
}
|
||||
path("alpr") {
|
||||
get {
|
||||
parameters("minLat".as[Double], "minLng".as[Double], "maxLat".as[Double], "maxLng".as[Double]) { (minLat, minLng, maxLat, maxLng) =>
|
||||
val client = new services.OverpassClient() // TODO: make this global
|
||||
val bBox = services.BoundingBox(minLat, minLng, maxLat, maxLng)
|
||||
onSuccess(client.getALPRs(bBox)) { json =>
|
||||
respondWithHeader(`Access-Control-Allow-Origin`.*) {
|
||||
complete(HttpEntity(ContentTypes.`application/json`, json.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bindingFuture = Http().newServerAt("localhost", 8080).bind(route)
|
||||
val bindingFuture = Http().newServerAt("localhost", 8080).bind(routes)
|
||||
|
||||
println(s"Server now online. Please navigate to http://localhost:8080\nPress RETURN to stop...")
|
||||
StdIn.readLine() // let it run until user presses return
|
||||
|
||||
38
shotgun/src/main/scala/services/OverpassClient.scala
Normal file
38
shotgun/src/main/scala/services/OverpassClient.scala
Normal file
@@ -0,0 +1,38 @@
|
||||
package services
|
||||
|
||||
import org.apache.pekko
|
||||
import pekko.actor.typed.ActorSystem
|
||||
import pekko.actor.typed.scaladsl.Behaviors
|
||||
import pekko.http.scaladsl.Http
|
||||
import pekko.http.scaladsl.model._
|
||||
import pekko.http.scaladsl.unmarshalling.Unmarshal
|
||||
import io.circe._
|
||||
import io.circe.parser._
|
||||
import org.apache.pekko.http.scaladsl.client.RequestBuilding._
|
||||
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.concurrent.{ExecutionContextExecutor, Future}
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
case class BoundingBox(minLat: Double, minLng: Double, maxLat: Double, maxLng: Double)
|
||||
|
||||
class OverpassClient(implicit val system: ActorSystem[_], implicit val executionContext: ExecutionContextExecutor) {
|
||||
val baseUrl = "https://overpass-api.de/api/interpreter"
|
||||
|
||||
def getALPRs(bBox: BoundingBox): Future[Json] = {
|
||||
val query = s"""[out:json][bbox:${bBox.minLat},${bBox.minLng},${bBox.maxLat},${bBox.maxLng}];node["man_made"="surveillance"]["surveillance:type"="ALPR"];out body;>;out skel qt;"""
|
||||
val formData = FormData("data" -> query).toEntity
|
||||
val request = HttpRequest(
|
||||
method = HttpMethods.POST,
|
||||
uri = baseUrl,
|
||||
entity = formData
|
||||
)
|
||||
|
||||
Http().singleRequest(request).flatMap { response =>
|
||||
response.entity.toStrict(5.seconds).flatMap { entity =>
|
||||
Unmarshal(entity).to[String].map(parse(_).getOrElse(Json.Null))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
152
webapp/package-lock.json
generated
152
webapp/package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "deflock",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"vue": "^3.4.29",
|
||||
"vue-router": "^4.3.3",
|
||||
"vuetify": "^3.7.2"
|
||||
@@ -882,6 +883,21 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.7",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
|
||||
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -897,6 +913,17 @@
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/computeds": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz",
|
||||
@@ -928,6 +955,14 @@
|
||||
"integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
@@ -982,6 +1017,38 @@
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -1043,6 +1110,25 @@
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
@@ -1174,6 +1260,11 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/read-package-json-fast": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
|
||||
@@ -1967,6 +2058,21 @@
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.7.7",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
|
||||
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -1982,6 +2088,14 @@
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"computeds": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz",
|
||||
@@ -2010,6 +2124,11 @@
|
||||
"integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
|
||||
"dev": true
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
},
|
||||
"entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
@@ -2051,6 +2170,21 @@
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -2096,6 +2230,19 @@
|
||||
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
@@ -2170,6 +2317,11 @@
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"read-package-json-fast": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"type-check": "vue-tsc --build --force"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"vue": "^3.4.29",
|
||||
"vue-router": "^4.3.3",
|
||||
"vuetify": "^3.7.2"
|
||||
|
||||
26
webapp/src/services/apiService.ts
Normal file
26
webapp/src/services/apiService.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import axios from "axios";
|
||||
|
||||
export interface BoundingBox {
|
||||
minLat: number;
|
||||
maxLat: number;
|
||||
minLng: number;
|
||||
maxLng: number;
|
||||
}
|
||||
|
||||
const apiService = axios.create({
|
||||
baseURL: "http://localhost:8080",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
export const getALPRs = async (boundingBox: BoundingBox) => {
|
||||
const queryParams = new URLSearchParams({
|
||||
minLat: boundingBox.minLat.toString(),
|
||||
maxLat: boundingBox.maxLat.toString(),
|
||||
minLng: boundingBox.minLng.toString(),
|
||||
maxLng: boundingBox.maxLng.toString(),
|
||||
});
|
||||
const response = await apiService.get(`/alpr?${queryParams.toString()}`);
|
||||
return response.data;
|
||||
}
|
||||
@@ -1,12 +1,26 @@
|
||||
<template>
|
||||
<div class="map-container">
|
||||
<!-- use-global-leaflet=false is a workaround for a bug in current version of vue-leaflet -->
|
||||
<l-map v-if="center" ref="map" v-model:zoom="zoom" :center="center" :use-global-leaflet="false">
|
||||
<l-map
|
||||
v-if="center"
|
||||
ref="map"
|
||||
v-model:zoom="zoom"
|
||||
v-model:center="center"
|
||||
:use-global-leaflet="false"
|
||||
@update:bounds="updateBounds"
|
||||
@ready="mapLoaded"
|
||||
>
|
||||
<l-tile-layer
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
layer-type="base"
|
||||
name="OpenStreetMap"
|
||||
></l-tile-layer>
|
||||
<l-marker
|
||||
@click="console.log('marker clicked')"
|
||||
v-for="alpr in alprsInView"
|
||||
:key="alpr.id"
|
||||
:lat-lng="[alpr.lat, alpr.lon]"
|
||||
><l-popup>This is an ALPR! Fuck it!</l-popup></l-marker>
|
||||
</l-map>
|
||||
<div v-else>
|
||||
loading...
|
||||
@@ -16,12 +30,58 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { LMap, LTileLayer, LMarker } from '@vue-leaflet/vue-leaflet';
|
||||
import { LMap, LTileLayer, LMarker, LPopup } from '@vue-leaflet/vue-leaflet';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { Ref } from 'vue';
|
||||
import type { BoundingBox } from '@/services/apiService';
|
||||
import { getALPRs } from '@/services/apiService';
|
||||
|
||||
const zoom: Ref<number> = ref(12);
|
||||
const center: Ref<[number, number]|null> = ref(null);
|
||||
const center: Ref<any|null> = ref(null);
|
||||
const bounds: Ref<BoundingBox|null> = ref(null);
|
||||
const router = useRouter();
|
||||
|
||||
const alprsInView = ref([
|
||||
{
|
||||
"type": "node",
|
||||
"id": 12187369976,
|
||||
"lat": 34.6616103,
|
||||
"lon": -86.4870137,
|
||||
"tags": {
|
||||
"brand": "Flock Safety",
|
||||
"brand:wikidata": "Q108485435",
|
||||
"camera:mount": "pole",
|
||||
"camera:type": "fixed",
|
||||
"direction": "335",
|
||||
"man_made": "surveillance",
|
||||
"operator": "Flock Safety",
|
||||
"operator:wikidata": "Q108485435",
|
||||
"surveillance": "traffic",
|
||||
"surveillance:type": "ALPR",
|
||||
"surveillance:zone": "traffic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"id": 12187369977,
|
||||
"lat": 34.6615727,
|
||||
"lon": -86.4881948,
|
||||
"tags": {
|
||||
"brand": "Flock Safety",
|
||||
"brand:wikidata": "Q108485435",
|
||||
"camera:mount": "pole",
|
||||
"camera:type": "fixed",
|
||||
"direction": "295",
|
||||
"man_made": "surveillance",
|
||||
"operator": "Flock Safety",
|
||||
"operator:wikidata": "Q108485435",
|
||||
"surveillance": "traffic",
|
||||
"surveillance:type": "ALPR",
|
||||
"surveillance:zone": "traffic"
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
function getUserLocation(): Promise<[number, number]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -44,10 +104,73 @@ function getUserLocation(): Promise<[number, number]> {
|
||||
});
|
||||
};
|
||||
|
||||
function mapLoaded(map: any) {
|
||||
updateBounds(map.getBounds());
|
||||
}
|
||||
|
||||
function updateBounds(newBounds: any) {
|
||||
bounds.value = {
|
||||
minLat: newBounds.getSouth(),
|
||||
maxLat: newBounds.getNorth(),
|
||||
minLng: newBounds.getWest(),
|
||||
maxLng: newBounds.getEast(),
|
||||
};
|
||||
|
||||
updateMarkers();
|
||||
|
||||
if (center.value) {
|
||||
updateURL();
|
||||
}
|
||||
}
|
||||
|
||||
function updateURL() {
|
||||
if (!center.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
router.replace({
|
||||
hash: `#map=${zoom.value}/${center.value.lat.toFixed(6)}/${center.value.lng.toFixed(6)}`
|
||||
});
|
||||
}
|
||||
|
||||
function updateMarkers() {
|
||||
// Fetch ALPRs in the current view
|
||||
if (!bounds.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (zoom.value < 12) {
|
||||
console.log('zoomed out too far');
|
||||
return;
|
||||
}
|
||||
|
||||
// getALPRs(bounds.value)
|
||||
// .then((alprs: any) => {
|
||||
// alprsInView.value = alprs.elements;
|
||||
// });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const hash = router.currentRoute.value.hash;
|
||||
if (hash) {
|
||||
const parts = hash.split('/');
|
||||
console.log('parts', parts);
|
||||
if (parts.length === 3 && parts[0].startsWith('#map')) {
|
||||
const zoomLevelString = parts[0].replace('#map=', '');
|
||||
zoom.value = parseInt(zoomLevelString, 10);
|
||||
center.value = {
|
||||
lat: parseFloat(parts[1]),
|
||||
lng: parseFloat(parts[2]),
|
||||
};
|
||||
console.log('center', center.value);
|
||||
console.log('zoom', zoom.value);
|
||||
}
|
||||
}
|
||||
|
||||
getUserLocation()
|
||||
.then(location => {
|
||||
center.value = location;
|
||||
if (!hash)
|
||||
center.value = { lat: location[0], lng: location[1] };
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user