ping_viewer_next/server/protocols/v1/
rest.rs1use crate::device::manager::{ManagerActorHandler, UuidWrapper};
2use crate::server::protocols::v1::errors::Error;
3use actix_web::Responder;
4use mime_guess::from_path;
5use paperclip::actix::{
6 api_v2_operation, get, post,
7 web::{self, HttpResponse, Json},
8 Apiv2Schema,
9};
10use serde::{Deserialize, Serialize};
11use serde_json::json;
12use uuid::Uuid;
13
14#[cfg(not(feature = "embed-frontend"))]
15#[derive(rust_embed::RustEmbed)]
16#[folder = "src/server/protocols/v1/frontend"]
17struct Asset;
18
19#[cfg(feature = "embed-frontend")]
20#[derive(rust_embed::RustEmbed)]
21#[folder = "ping-viewer-next-frontend/dist"]
22struct Asset;
23
24fn handle_embedded_file(path: &str) -> HttpResponse {
25 match Asset::get(path) {
26 Some(content) => HttpResponse::Ok()
27 .content_type(from_path(path).first_or_octet_stream().as_ref())
28 .body(content.data.into_owned()),
29 None => HttpResponse::NotFound().body("404 Not Found"),
30 }
31}
32
33#[api_v2_operation(skip)]
34#[get("/")]
35async fn index() -> impl Responder {
36 handle_embedded_file("index.html")
37}
38
39#[api_v2_operation(skip)]
40#[get("/{file_path:.*}")]
41async fn index_files(file_path: web::Path<String>) -> impl Responder {
42 handle_embedded_file(&file_path)
43}
44
45#[api_v2_operation]
47#[get("register_service")]
48async fn server_metadata() -> Result<Json<ServerMetadata>, Error> {
49 let package = ServerMetadata::default();
50 Ok(Json(package))
51}
52
53pub fn register_services(cfg: &mut web::ServiceConfig) {
54 cfg.service(index)
55 .service(post_request)
56 .service(device_manager_get)
57 .service(device_manager_post)
58 .service(post_create)
59 .service(device_manager_device_get)
60 .service(device_manager_device_ping1d_get)
61 .service(device_manager_device_ping360_get)
62 .service(device_manager_device_common_get)
63 .service(index_files);
64}
65
66async fn send_request_and_broadcast(
67 manager_handler: &web::Data<ManagerActorHandler>,
68 request: crate::device::manager::Request,
69) -> Result<Json<crate::device::manager::Answer>, Error> {
70 let answer = manager_handler.send(request).await?;
71 crate::server::protocols::v1::websocket::send_to_websockets(json!(answer), None);
72 Ok(Json(answer))
73}
74
75#[api_v2_operation(tags("Device Manager"))]
76#[post("device_manager/request")]
77async fn post_request(
78 manager_handler: web::Data<ManagerActorHandler>,
79 json: web::Json<crate::device::manager::Request>,
80) -> Result<Json<crate::device::manager::Answer>, Error> {
81 let request = json.into_inner();
82
83 send_request_and_broadcast(&manager_handler, request).await
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize, Apiv2Schema)]
87pub enum DeviceManagerGetOptionsV1 {
88 AutoCreate,
89 List,
90 Search,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize, Apiv2Schema)]
94pub enum DeviceManagerPostOptionsV1 {
95 Delete,
96 Info,
97 EnableContinuousMode,
98 DisableContinuousMode,
99}
100
101#[api_v2_operation(tags("Device Manager"))]
102#[get("device_manager/{selection}")]
103async fn device_manager_get(
104 manager_handler: web::Data<ManagerActorHandler>,
105 selection: web::Path<DeviceManagerGetOptionsV1>,
106) -> Result<Json<crate::device::manager::Answer>, Error> {
107 let request = match selection.into_inner() {
108 DeviceManagerGetOptionsV1::AutoCreate => crate::device::manager::Request::AutoCreate,
109 DeviceManagerGetOptionsV1::List => crate::device::manager::Request::List,
110 DeviceManagerGetOptionsV1::Search => crate::device::manager::Request::Search,
111 };
112
113 send_request_and_broadcast(&manager_handler, request).await
114}
115
116#[api_v2_operation(tags("Device Manager"))]
117#[post("device_manager/create")]
118async fn post_create(
119 manager_handler: web::Data<ManagerActorHandler>,
120 info: web::Json<crate::device::manager::CreateStruct>,
121) -> Result<Json<crate::device::manager::Answer>, Error> {
122 let create_struct = info.into_inner();
123
124 let request = crate::device::manager::Request::Create(create_struct);
125
126 send_request_and_broadcast(&manager_handler, request).await
127}
128
129#[api_v2_operation(tags("Device Manager : Device"))]
130#[post("device_manager/{device}/{selection}")]
131async fn device_manager_post(
132 manager_handler: web::Data<ManagerActorHandler>,
133 info: web::Path<(Uuid, DeviceManagerPostOptionsV1)>,
134) -> Result<Json<crate::device::manager::Answer>, Error> {
135 let info = info.into_inner();
136 let uuid = info.0;
137 let request = info.1;
138
139 let request = match request {
140 DeviceManagerPostOptionsV1::Delete => {
141 crate::device::manager::Request::Delete(UuidWrapper { uuid })
142 }
143 DeviceManagerPostOptionsV1::Info => {
144 crate::device::manager::Request::Info(UuidWrapper { uuid })
145 }
146 DeviceManagerPostOptionsV1::EnableContinuousMode => {
147 crate::device::manager::Request::EnableContinuousMode(UuidWrapper { uuid })
148 }
149 DeviceManagerPostOptionsV1::DisableContinuousMode => {
150 crate::device::manager::Request::DisableContinuousMode(UuidWrapper { uuid })
151 }
152 };
153
154 send_request_and_broadcast(&manager_handler, request).await
155}
156
157#[api_v2_operation(tags("Device Manager : Device"))]
158#[get("device_manager/{device}/{request}")]
159async fn device_manager_device_get(
160 manager_handler: web::Data<ManagerActorHandler>,
161 info: web::Path<(Uuid, crate::device::devices::PingRequest)>,
162) -> Result<Json<crate::device::manager::Answer>, Error> {
163 let info = info.into_inner();
164 let uuid = info.0;
165 let request = info.1;
166
167 let request =
168 crate::device::manager::Request::Ping(crate::device::manager::DeviceRequestStruct {
169 uuid,
170 device_request: request,
171 });
172
173 send_request_and_broadcast(&manager_handler, request).await
174}
175
176#[api_v2_operation(tags("Device Manager : Device"))]
177#[get("device_manager/{device}/ping1d/{request}")]
178async fn device_manager_device_ping1d_get(
179 manager_handler: web::Data<ManagerActorHandler>,
180 info: web::Path<(Uuid, crate::device::devices::Ping1DRequest)>,
181) -> Result<Json<crate::device::manager::Answer>, Error> {
182 let info = info.into_inner();
183 let uuid = info.0;
184 let request = info.1;
185
186 let request = crate::device::devices::PingRequest::Ping1D(request);
187
188 let request =
189 crate::device::manager::Request::Ping(crate::device::manager::DeviceRequestStruct {
190 uuid,
191 device_request: request,
192 });
193
194 send_request_and_broadcast(&manager_handler, request).await
195}
196
197#[api_v2_operation(tags("Device Manager : Device"))]
198#[get("device_manager/{device}/ping360/{request}")]
199async fn device_manager_device_ping360_get(
200 manager_handler: web::Data<ManagerActorHandler>,
201 info: web::Path<(Uuid, crate::device::devices::Ping360Request)>,
202) -> Result<Json<crate::device::manager::Answer>, Error> {
203 let info = info.into_inner();
204 let uuid = info.0;
205 let request = info.1;
206
207 let request = crate::device::devices::PingRequest::Ping360(request);
208
209 let request =
210 crate::device::manager::Request::Ping(crate::device::manager::DeviceRequestStruct {
211 uuid,
212 device_request: request,
213 });
214
215 send_request_and_broadcast(&manager_handler, request).await
216}
217
218#[api_v2_operation(tags("Device Manager : Device"))]
219#[get("device_manager/{device}/common/{request}")]
220async fn device_manager_device_common_get(
221 manager_handler: web::Data<ManagerActorHandler>,
222 info: web::Path<(Uuid, crate::device::devices::PingCommonRequest)>,
223) -> Result<Json<crate::device::manager::Answer>, Error> {
224 let info = info.into_inner();
225 let uuid = info.0;
226 let request = info.1;
227
228 let request = crate::device::devices::PingRequest::Common(request);
229
230 let request =
231 crate::device::manager::Request::Ping(crate::device::manager::DeviceRequestStruct {
232 uuid,
233 device_request: request,
234 });
235
236 send_request_and_broadcast(&manager_handler, request).await
237}
238
239#[derive(Debug, Serialize, Deserialize, Apiv2Schema)]
240pub struct ServerMetadata {
241 pub name: &'static str,
242 pub description: &'static str,
243 pub icon: &'static str,
244 pub company: &'static str,
245 pub version: &'static str,
246 pub new_page: bool,
247 pub webpage: &'static str,
248 pub api: &'static str,
249}
250
251impl Default for ServerMetadata {
252 fn default() -> Self {
253 Self {
254 name: "Ping Viewer Next",
255 description: "A ping protocol extension for expose devices to web.",
256 icon: "mdi-compass-outline",
257 company: "BlueRobotics",
258 version: "0.0.0",
259 new_page: false,
260 webpage: "https://github.com/RaulTrombin/navigator-assistant",
261 api: "/docs",
262 }
263 }
264}