Implemented Pull OTA json

This commit is contained in:
2025-01-04 22:29:43 +00:00
parent f76f248446
commit 9919495346
11 changed files with 194 additions and 35 deletions

View File

@@ -1,9 +1,11 @@
use std::{env, process};
use std::{env, fs, process, str::FromStr};
use crate::schemas::{TelemetryMessageFromDevice, ValueMessageFromDevice};
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use actix_web::{get, post, put, web, App, HttpResponse, HttpServer, Responder};
use database::Database;
use dotenvy::dotenv;
use log::{error, info};
use schemas::{BoardConfig, BoardType, Device, OTAConfiguration};
use sqlx::types::mac_address::MacAddress;
use util::parse_mac_address;
@@ -34,7 +36,11 @@ async fn receive_telemetry(
}
};
match data.db.add_telemetry(&telemetry_message, &mac_converted).await {
match data
.db
.add_telemetry(&telemetry_message, &mac_converted)
.await
{
Ok(_) => HttpResponse::Created(),
Err(e) => {
error!("adding Telemetry message to DB failed \n{}", e);
@@ -105,7 +111,7 @@ async fn get_value(device_id: web::Path<String>, data: web::Data<AppState>) -> i
HttpResponse::Ok().json(messages)
}
#[get("/device/")]
#[get("/device")]
async fn get_devices(data: web::Data<AppState>) -> impl Responder {
info!("GET - devices - Processing");
let devices = match data.db.get_devices().await {
@@ -118,12 +124,54 @@ async fn get_devices(data: web::Data<AppState>) -> impl Responder {
HttpResponse::Ok().json(devices)
}
#[put("/firmware/{product}/{config}/{version}")]
async fn upload_firmware(path: web::Path<(String, String, String)>, body: web::Bytes) -> impl Responder {
let (product, config, version) = path.into_inner();
println!("Uploading firmware version: {}", version);
let fw_folder = format!("./firmware/{product}");
fs::create_dir_all(&fw_folder).unwrap();
let file_path = format!("{fw_folder}/firmware_{config}_{version}.bin");
info!("Saving to {file_path}");
tokio::fs::write(&file_path, &body).await.unwrap();
HttpResponse::Ok().body(format!("Firmware version {} uploaded successfully", version))
}
// TODO this is more or less a placeholder. Firmware upload will be more detailed in the future
#[get("/firmware/{product}")]
async fn get_firmware_json(product: web::Path<String>) -> impl Responder {
let product = product.into_inner();
let mut configs = Vec::new();
if let Ok(entries) = fs::read_dir(format!("./firmware/{product}")) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
println!("File: {:?}", path);
let split_name: Vec<_> = path.file_name().unwrap().to_str().unwrap().split("_").collect();
let version = split_name[2].strip_suffix(".bin").unwrap();
let board_config = BoardConfig::from_str(split_name[1]).unwrap();
let board_type = BoardType::from_str(&product).unwrap();
let cfg = OTAConfiguration{board: board_type, configuration: board_config, version: version.to_string(), url: path.to_str().to_owned().unwrap().to_owned() };
configs.push(cfg);
} else if path.is_dir() {
println!("Directory: {:?}", path);
}
}
} else {
return HttpResponse::InternalServerError().finish()
}
HttpResponse::Ok().json(configs)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
env_logger::init();
info!("Starting");
let db_url = match env::var("DATABASE_URL") {
Ok(url) => url,
Err(e) => {
@@ -139,13 +187,16 @@ async fn main() -> std::io::Result<()> {
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(AppState { db: db.clone() }))
.app_data(web::PayloadConfig::new(256 * 1024 * 1024)) //256MB
.service(receive_telemetry)
.service(get_telemetry)
.service(receive_value)
.service(get_value)
.service(get_devices)
.service(upload_firmware)
.service(get_firmware_json)
})
.bind(("0.0.0.0", 8080))?
.bind(("0.0.0.0", 8484))?
.run()
.await
}