1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
pub mod config;

use std::sync::Arc;

use axum::{
    extract::{Json, State},
    http::StatusCode,
    routing::{get, post},
};
use tracing::{debug, info, instrument};

use crate::config::ServerConfiguration;
use pixy_core::validation::parse_configs;
use pixy_core::{Gateway, SensorGateway, SensorMessage};

pub async fn run_server_with(server_configs: ServerConfiguration) {
    let pixy_configs = parse_configs(&server_configs.config_file).unwrap();

    let gateway: Arc<dyn Gateway> = Arc::new(SensorGateway::from(pixy_configs));

    let app = axum::Router::new()
        .route("/data", post(handler))
        .route("/healthz", get(|| async { StatusCode::OK }))
        .with_state(gateway);

    let app = if server_configs.enable_echo {
        app.route("/echo", post(echo))
    } else {
        app
    };

    let bind_address = format!("0.0.0.0:{}", server_configs.port);

    println!(
        r#"
     ___                     ___                 
    /  /\      ___          /__/|          ___   
   /  /::\    /  /\        |  |:|         /__/|  
  /  /:/\:\  /  /:/        |  |:|        |  |:|  
 /  /:/~/:/ /__/::\      __|__|:|        |  |:|  
/__/:/ /:/  \__\/\:\__  /__/::::\____  __|__|:|  
\  \:\/:/      \  \:\/\    ~\~~\::::/ /__/::::\  
 \  \::/        \__\::/     |~~|:|~~     ~\~~\:\ 
  \  \:\        /__/:/      |  |:|         \  \:\
   \  \:\       \__\/       |  |:|          \__\/
    \__\/                   |__|/                
    "#
    );

    info!("Starting server on {}", &bind_address);
    axum::Server::bind(&bind_address.as_str().parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

#[instrument]
async fn handler(
    State(gateway): State<Arc<dyn Gateway>>,
    Json(reading): Json<SensorMessage>,
) -> StatusCode {
    debug!("Received reading: {:?}", &reading);

    tokio::spawn(async move {
        gateway.handle_reading(reading).await;
    });

    StatusCode::ACCEPTED
}

#[instrument]
async fn echo(data: String) -> String {
    info!("Received data: {:?}", &data);
    data
}