|
- use anyhow::{Context, Result};
- use serde::{Serialize, Deserialize};
- use serde_json;
- use std::io::{self, Read};
- use std::time::Duration;
- use serialport;
- use actix_web::{web, App, HttpServer, HttpResponse};
- use actix_cors::Cors;
- use std::fs;
- use std::path::PathBuf;
- use std::sync::Mutex;
- use once_cell::sync::Lazy;
-
- #[derive(Serialize, Deserialize)]
- struct WeightData {
- weight: String,
- timestamp: u64,
- is_read: bool,
- }
-
- #[derive(Serialize, Deserialize)]
- struct Config {
- scale_type: String,
- serial_port: String,
- baud_rate: u32,
- }
-
- // 读取配置文件
- fn read_config() -> Result<Config> {
- let config_str = fs::read_to_string("config.json")?;
- let config: Config = serde_json::from_str(&config_str)?;
- Ok(config)
- }
-
- // 使用全局静态变量来存储重量数据
- static WEIGHT_DATA: Lazy<Mutex<WeightData>> = Lazy::new(|| {
- Mutex::new(WeightData {
- weight: "0".to_string(),
- timestamp: 0,
- is_read: false,
- })
- });
-
- // 获取MAC地址的HTTP处理函数
- async fn get_mac() -> HttpResponse {
- let response = serde_json::json!({
- "mac": "00:11:22:33:44:55" // 这里替换为实际的MAC地址获取逻辑
- });
- HttpResponse::Ok().json(response)
- }
-
- // 获取秤类型的HTTP处理函数
- async fn get_scale() -> HttpResponse {
- let config = match read_config() {
- Ok(config) => config,
- Err(_) => return HttpResponse::InternalServerError().finish(),
- };
-
- let response = serde_json::json!({
- "scale_type": config.scale_type
- });
- HttpResponse::Ok().json(response)
- }
-
- // 获取重量数据的HTTP处理函数
- async fn get_weight() -> HttpResponse {
- let mut weight_data = WEIGHT_DATA.lock().unwrap();
- if weight_data.is_read {
- // 如果数据已读,返回 null
- HttpResponse::Ok().json(serde_json::json!({"weight": null}))
- } else {
- // 标记为已读并返回数据
- weight_data.is_read = true;
- HttpResponse::Ok().json(&*weight_data)
- }
- }
-
- // 串口数据处理函数
- async fn run_serial() -> Result<()> {
- // 读取配置文件
- let config = read_config()?;
-
- // 打开配置的串口
- println!("正在尝试打开串口 {}...", config.serial_port);
- let mut port = serialport::new(&config.serial_port, config.baud_rate)
- .timeout(Duration::from_millis(1000))
- .open()
- .with_context(|| format!("无法打开串口 {}", config.serial_port))?;
-
- println!("串口打开成功");
-
- let mut buf = [0u8; 1024];
- let mut accumulated_data = String::new();
-
- loop {
- match port.read(&mut buf) {
- Ok(bytes_read) if bytes_read > 0 => {
- // 将读取的数据转换为字符串并添加到累积的数据中
- if let Ok(data) = String::from_utf8(buf[..bytes_read].to_vec()) {
- accumulated_data.push_str(&data);
-
- // 检查是否有完整的行
- if accumulated_data.contains('\n') {
- // 处理所有完整的行
- for line in accumulated_data.lines() {
- let trimmed_data = line.trim();
-
- if !trimmed_data.is_empty() {
- println!("收到串口数据: {}", trimmed_data);
-
- // 更新内存中的数据(直接覆盖)
- let mut weight_data = WEIGHT_DATA.lock().unwrap();
- weight_data.weight = trimmed_data.to_string();
- weight_data.timestamp = std::time::SystemTime::now()
- .duration_since(std::time::UNIX_EPOCH)
- .unwrap()
- .as_secs();
- weight_data.is_read = false; // 新数据未读
- }
- }
-
- // 清除已处理的数据
- accumulated_data.clear();
- }
- }
- }
- Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {
- // 超时是正常的,继续尝试读取
- continue;
- }
- Err(e) => {
- eprintln!("串口读取错误: {}", e);
- return Err(e.into());
- }
- _ => {}
- }
- }
- }
-
- #[actix_web::main]
- async fn main() -> Result<()> {
- println!("程序启动...");
-
- // 启动HTTP服务器
- println!("正在启动HTTP服务器...");
-
- // 创建HTTP服务器
- let server = HttpServer::new(|| {
- // 配置CORS
- let cors = Cors::default()
- .allow_any_origin() // 允许所有来源
- .allow_any_method() // 允许所有HTTP方法
- .allow_any_header() // 允许所有请求头
- .max_age(3600); // 设置预检请求的缓存时间(秒)
-
- App::new()
- .wrap(cors) // 添加CORS中间件
- .route("/mac", web::get().to(get_mac))
- .route("/scale", web::get().to(get_scale))
- .route("/weight", web::get().to(get_weight))
- })
- .bind(("0.0.0.0", 8080))?
- .run();
-
- println!("HTTP服务器已启动,监听在 http://127.0.0.1:8080");
-
- // 在新线程中运行串口服务
- let _serial_handle = tokio::spawn(async {
- if let Err(e) = run_serial().await {
- eprintln!("串口服务错误: {}", e);
- }
- });
-
- // 等待HTTP服务器结束
- server.await?;
-
- Ok(())
- }
|