@@ -28,6 +28,8 @@ use axum::response::IntoResponse;
28
28
use axum:: routing:: MethodFilter ;
29
29
use axum:: { BoxError , Router } ;
30
30
use net_literals:: addr;
31
+ use std:: collections:: BTreeMap ;
32
+ use std:: fmt:: Write ;
31
33
use std:: future:: Future ;
32
34
use std:: net:: SocketAddr ;
33
35
use std:: pin:: Pin ;
@@ -216,6 +218,7 @@ impl Server {
216
218
self . bind ( ) . await ?. start ( ) . await
217
219
}
218
220
221
+ #[ allow( clippy:: too_many_lines) ]
219
222
fn into_router ( self ) -> Router {
220
223
let devices = Arc :: new ( self . devices ) ;
221
224
let server_info = Arc :: new ( self . info ) ;
@@ -248,6 +251,68 @@ impl Server {
248
251
} )
249
252
} ) ,
250
253
)
254
+ . route ( "/setup" , {
255
+ let this = Arc :: clone ( & devices) ;
256
+
257
+ axum:: routing:: get ( || async move {
258
+ let mut grouped_devices = BTreeMap :: new ( ) ;
259
+ for ( device, number) in this. iter_all ( ) {
260
+ let device = device. to_configured_device ( number) ;
261
+
262
+ grouped_devices
263
+ . entry ( device. ty )
264
+ . or_insert_with ( Vec :: new)
265
+ . push ( ( number, device. name ) ) ;
266
+ }
267
+
268
+ let mut devices_html = String :: new ( ) ;
269
+
270
+ for ( device_type, devices) in grouped_devices {
271
+ writeln ! ( devices_html, "<figure>" ) . unwrap ( ) ;
272
+ writeln ! ( devices_html, "<figcaption>{}</figcaption>" , match device_type {
273
+ #[ cfg( feature = "camera" ) ]
274
+ DeviceType :: Camera => "Cameras" ,
275
+ #[ cfg( feature = "dome" ) ]
276
+ DeviceType :: Dome => "Domes" ,
277
+ #[ cfg( feature = "filterwheel" ) ]
278
+ DeviceType :: FilterWheel => "Filter wheels" ,
279
+ #[ cfg( feature = "focuser" ) ]
280
+ DeviceType :: Focuser => "Focusers" ,
281
+ #[ cfg( feature = "observingconditions" ) ]
282
+ DeviceType :: ObservingConditions => "Weather stations" ,
283
+ #[ cfg( feature = "rotator" ) ]
284
+ DeviceType :: Rotator => "Rotators" ,
285
+ #[ cfg( feature = "safetymonitor" ) ]
286
+ DeviceType :: SafetyMonitor => "Safety monitors" ,
287
+ #[ cfg( feature = "switch" ) ]
288
+ DeviceType :: Switch => "Switches" ,
289
+ #[ cfg( feature = "telescope" ) ]
290
+ DeviceType :: Telescope => "Telescopes" ,
291
+ #[ cfg( feature = "covercalibrator" ) ]
292
+ DeviceType :: CoverCalibrator => "Cover calibrators" ,
293
+ } ) . unwrap ( ) ;
294
+ writeln ! ( devices_html, "<ul>" ) . unwrap ( ) ;
295
+ for ( device_index, device_name) in devices {
296
+ writeln ! (
297
+ devices_html,
298
+ r#"<li><a href="/api/v1/{group_path}/{device_index}/setup">{device_name}</a></li>"# ,
299
+ group_path = DevicePath ( device_type) ,
300
+ ) . unwrap ( ) ;
301
+ }
302
+ writeln ! ( devices_html, "</ul>" ) . unwrap ( ) ;
303
+ writeln ! ( devices_html, "</figure>" ) . unwrap ( ) ;
304
+ }
305
+
306
+ axum:: response:: Html ( include_str ! ( "setup_template.html" ) . replace (
307
+ "<!-- devices_html -->" ,
308
+ if devices_html. is_empty ( ) {
309
+ "<p>No devices are registered on this server.</p>"
310
+ } else {
311
+ & devices_html
312
+ } ,
313
+ ) )
314
+ } )
315
+ } )
251
316
. route (
252
317
"/api/v1/:device_type/:device_number/:action" ,
253
318
axum:: routing:: on (
0 commit comments