event stream
This commit is contained in:
parent
9ebf7b0f0a
commit
a0ec314cac
5 changed files with 120 additions and 25 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1085,6 +1085,7 @@ dependencies = [
|
|||
"rocket_codegen",
|
||||
"rocket_http",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"state",
|
||||
"tempfile",
|
||||
"time",
|
||||
|
|
|
@ -5,8 +5,9 @@ edition = "2021"
|
|||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rocket = "0.5.0"
|
||||
[dependencies.rocket]
|
||||
version = "0.5.0"
|
||||
features = ["json"]
|
||||
|
||||
[dependencies.rocket_dyn_templates]
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -3,5 +3,5 @@ let
|
|||
fenix = import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { };
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = with fenix.latest; [ cargo rustc ];
|
||||
buildInputs = with fenix.latest; [ cargo rustc rustfmt ];
|
||||
}
|
||||
|
|
128
src/main.rs
128
src/main.rs
|
@ -1,11 +1,17 @@
|
|||
#[macro_use] extern crate rocket;
|
||||
use rocket::fs::{FileServer, relative};
|
||||
use rocket::State;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::RwLock,
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
use rocket::{
|
||||
fs::{relative, FileServer},
|
||||
response::stream::{Event, EventStream},
|
||||
serde::Serialize,
|
||||
tokio::{
|
||||
select,
|
||||
time::{self, Duration},
|
||||
},
|
||||
Shutdown, State,
|
||||
};
|
||||
use rocket_dyn_templates::{Template, context};
|
||||
use rocket_dyn_templates::{context, Template};
|
||||
use std::{collections::HashMap, sync::RwLock};
|
||||
|
||||
enum TrackedState {
|
||||
Conscrit {
|
||||
|
@ -19,7 +25,7 @@ enum TrackedState {
|
|||
Vieux {
|
||||
color: u8,
|
||||
invisible: bool,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
struct Tracked {
|
||||
|
@ -28,20 +34,90 @@ struct Tracked {
|
|||
state: TrackedState,
|
||||
}
|
||||
|
||||
fn build_conscrit(name: String) -> Tracked {
|
||||
Tracked {
|
||||
name: name,
|
||||
pos: (0.0, 0.0),
|
||||
state: TrackedState::Conscrit {
|
||||
invisible: false,
|
||||
blurred: false,
|
||||
captured: false,
|
||||
malette: false,
|
||||
invisibility_codes: 0,
|
||||
blur_codes: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn build_vieux(name: String) -> Tracked {
|
||||
Tracked {
|
||||
name: name,
|
||||
pos: (0.0, 0.0),
|
||||
state: TrackedState::Vieux {
|
||||
invisible: true,
|
||||
color: 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Tracking = RwLock<HashMap<String, RwLock<Tracked>>>;
|
||||
|
||||
#[get("/track/conscrit")]
|
||||
fn conscrit() -> Template{
|
||||
Template::render("conscrit", context!{
|
||||
name: "un nom",
|
||||
id: "ID",
|
||||
gpslog: "no"
|
||||
})
|
||||
#[derive(Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
struct TrackedInfo {
|
||||
name: String,
|
||||
pos: (f32, f32),
|
||||
}
|
||||
|
||||
#[get("/track/<id>?<gpslog>")]
|
||||
fn tracked_view(id: &str, gpslog: Option<bool>, tracking: &State<Tracking>) -> Option<Template> {
|
||||
if let Some(tracked) = tracking.read().unwrap().get(&id.to_string()) {
|
||||
Some(Template::render(
|
||||
match tracked.read().unwrap().state {
|
||||
TrackedState::Vieux { .. } => "vieux",
|
||||
TrackedState::Conscrit { .. } => "conscrit",
|
||||
},
|
||||
context! {
|
||||
name: &tracked.read().unwrap().name,
|
||||
id: &id,
|
||||
gpslog: gpslog.unwrap_or(true)
|
||||
},
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/track/<id>/events")]
|
||||
fn tracked_events<'a>(
|
||||
id: &'a str,
|
||||
tracking: &'a State<Tracking>,
|
||||
mut shutdown: Shutdown,
|
||||
) -> Option<EventStream![Event + 'a]> {
|
||||
if tracking.read().unwrap().contains_key(&id.to_string()) {
|
||||
Some(EventStream! {
|
||||
let mut interval = time::interval(Duration::from_secs(5));
|
||||
loop {
|
||||
select!{
|
||||
_ = interval.tick() => {
|
||||
let info = TrackedInfo {
|
||||
name: id.to_string(),
|
||||
pos: tracking.read().unwrap().get(&id.to_string()).unwrap().read().unwrap().pos
|
||||
};
|
||||
yield Event::json(&info).event("coords")
|
||||
},
|
||||
_ = &mut shutdown => break
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[put("/track/<id>?<lat>&<long>")]
|
||||
fn store_pos(id: String, lat: f32, long: f32, tracking: &State<Tracking>){
|
||||
if let Some(tracked) = tracking.read().unwrap().get(&id) {
|
||||
fn store_pos(id: &str, lat: f32, long: f32, tracking: &State<Tracking>) {
|
||||
if let Some(tracked) = tracking.read().unwrap().get(&id.to_string()) {
|
||||
tracked.write().unwrap().pos = (lat, long);
|
||||
}
|
||||
}
|
||||
|
@ -54,10 +130,26 @@ fn index() -> &'static str {
|
|||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
let tracking = HashMap::<String, RwLock<Tracked>>::from([
|
||||
(
|
||||
"team00".to_string(),
|
||||
RwLock::new(build_conscrit("Équipe 0".to_string())),
|
||||
),
|
||||
(
|
||||
"team01".to_string(),
|
||||
RwLock::new(build_conscrit("Équipe 1".to_string())),
|
||||
),
|
||||
(
|
||||
"npc0".to_string(),
|
||||
RwLock::new(build_vieux("PNJ 0".to_string())),
|
||||
),
|
||||
(
|
||||
"npc1".to_string(),
|
||||
RwLock::new(build_vieux("PNJ 1".to_string())),
|
||||
),
|
||||
]);
|
||||
rocket::build()
|
||||
.attach(Template::fairing())
|
||||
.manage(RwLock::new(tracking))
|
||||
.mount("/", routes![index, store_pos, conscrit])
|
||||
.mount("/", routes![index, store_pos, tracked_view, tracked_events])
|
||||
.mount("/", FileServer::from(relative!("static")))
|
||||
}
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
|
||||
crossorigin=""></script>
|
||||
|
||||
<!-- SOCKET.IO INCLUDE -->
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
#map { height: 600px; }
|
||||
#codes {
|
||||
|
@ -27,7 +24,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="/utils.js"></script>
|
||||
<!-- <script type="text/javascript" src="/utils.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div><br/>
|
||||
|
@ -39,6 +36,10 @@
|
|||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
const evtSource = new EventSource("/track/{{id}}/events");
|
||||
evtSource.addEventListener("coords", (event) => {
|
||||
console.log(event);
|
||||
});
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// // SETUP MAP
|
||||
|
||||
|
|
Loading…
Reference in a new issue