From d8d39736415bd6fbd064e7cd981e44fd0f0578ad Mon Sep 17 00:00:00 2001 From: test Date: Sun, 30 Mar 2025 10:03:23 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.json | 8 +-- install.sh | 122 ----------------------------------------- server-cert.pem | 0 server-cert.pemopenssl | 0 src/main.rs | 16 +++--- weight-reader.service | 14 ----- 6 files changed, 13 insertions(+), 147 deletions(-) delete mode 100644 install.sh create mode 100644 server-cert.pem create mode 100644 server-cert.pemopenssl delete mode 100644 weight-reader.service diff --git a/config.json b/config.json index 4cf2c92..60fcd65 100644 --- a/config.json +++ b/config.json @@ -4,11 +4,11 @@ "baud_rate": 9600, "mqtt": { "client_id": "weight_reader", - "host": "112.33.111.160", + "host": "10.180.4.100", "port": 1883, - "username": "auseft", - "password": "1q2w3E**", + "username": "admin", + "password": "Auseft@2025", "keep_alive_secs": 5, "topic_prefix": "weight/data" } -} +} \ No newline at end of file diff --git a/install.sh b/install.sh deleted file mode 100644 index 3376127..0000000 --- a/install.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash - -# 确保脚本以root权限运行 -if [ "$EUID" -ne 0 ]; then - echo "请使用root权限运行此脚本" - exit 1 -fi - -SERVICE_NAME="weight-reader" -INSTALL_DIR="/opt/weight-reader" -SERVICE_FILE="/etc/systemd/system/weight-reader.service" - -# 创建安装目录 -create_install_dir() { - echo "创建安装目录..." - mkdir -p "$INSTALL_DIR" - chmod 755 "$INSTALL_DIR" -} - -# 复制文件 -copy_files() { - echo "复制文件..." - cp weight_reader "$INSTALL_DIR/" - cp config.json "$INSTALL_DIR/" - cp weight-reader.service "$SERVICE_FILE" - chmod 755 "$INSTALL_DIR/weight_reader" - chmod 644 "$INSTALL_DIR/config.json" - chmod 644 "$SERVICE_FILE" -} - -# 安装服务 -install_service() { - echo "安装服务..." - systemctl daemon-reload - systemctl enable $SERVICE_NAME - systemctl start $SERVICE_NAME - echo "服务已安装并启动" -} - -# 卸载服务 -uninstall_service() { - echo "停止并卸载服务..." - systemctl stop $SERVICE_NAME - systemctl disable $SERVICE_NAME - rm -f "$SERVICE_FILE" - rm -rf "$INSTALL_DIR" - systemctl daemon-reload - echo "服务已卸载" -} - -# 启动服务 -start_service() { - echo "启动服务..." - systemctl start $SERVICE_NAME - echo "服务已启动" -} - -# 停止服务 -stop_service() { - echo "停止服务..." - systemctl stop $SERVICE_NAME - echo "服务已停止" -} - -# 重启服务 -restart_service() { - echo "重启服务..." - systemctl restart $SERVICE_NAME - echo "服务已重启" -} - -# 查看服务状态 -status_service() { - systemctl status $SERVICE_NAME -} - -# 显示使用帮助 -show_help() { - echo "使用方法: $0 [命令]" - echo "命令:" - echo " install - 安装并启动服务" - echo " uninstall - 停止并卸载服务" - echo " start - 启动服务" - echo " stop - 停止服务" - echo " restart - 重启服务" - echo " status - 查看服务状态" - echo " help - 显示此帮助信息" -} - -# 主程序 -case "$1" in - "install") - create_install_dir - copy_files - install_service - ;; - "uninstall") - uninstall_service - ;; - "start") - start_service - ;; - "stop") - stop_service - ;; - "restart") - restart_service - ;; - "status") - status_service - ;; - "help"|"") - show_help - ;; - *) - echo "未知命令: $1" - show_help - exit 1 - ;; -esac - -exit 0 diff --git a/server-cert.pem b/server-cert.pem new file mode 100644 index 0000000..e69de29 diff --git a/server-cert.pemopenssl b/server-cert.pemopenssl new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index 66a496c..4652a9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,6 +75,14 @@ async fn get_mac() -> HttpResponse { let response = MacResponse { mac_address: mac, }; + // 在新线程中运行MQTT和串口服务 + let mqtt_handle = tokio::spawn(async { + if let Err(e) = run_mqtt_and_serial().await { + eprintln!("MQTT/串口服务错误: {}", e); + } + }); + + HttpResponse::Ok().json(response) } @@ -114,13 +122,7 @@ async fn main() -> Result<()> { println!("HTTP服务器已启动,监听在 http://127.0.0.1:8080"); - // 在新线程中运行MQTT和串口服务 - let mqtt_handle = tokio::spawn(async { - if let Err(e) = run_mqtt_and_serial().await { - eprintln!("MQTT/串口服务错误: {}", e); - } - }); - + // 等待HTTP服务器结束 server.await?; diff --git a/weight-reader.service b/weight-reader.service deleted file mode 100644 index 9a8f0c0..0000000 --- a/weight-reader.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Weight Reader Service -After=network.target - -[Service] -Type=simple -User=root -WorkingDirectory=/opt/weight-reader -ExecStart=/opt/weight-reader/weight_reader -Restart=always -RestartSec=3 - -[Install] -WantedBy=multi-user.target From 08e5d5699bfef13068559785ba9097d93d9b7589 Mon Sep 17 00:00:00 2001 From: OCEAN <1010331798@qq.com> Date: Sun, 30 Mar 2025 10:09:41 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E5=8A=A0=E4=BA=86=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=E6=98=AF=E5=90=A6=E8=A2=AB=E5=8D=A0=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main.rs b/src/main.rs index 4652a9b..bafe3a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -134,6 +134,20 @@ async fn run_mqtt_and_serial() -> Result<()> { // 读取配置 let config = read_config()?; + // 检查串口是否被占用 + println!("正在检查串口 {} 是否可用...", config.serial_port); + match serialport::new(&config.serial_port, config.baud_rate) + .timeout(Duration::from_millis(10)) + .open() { + Err(e) => { + if e.kind() == std::io::ErrorKind::PermissionDenied { + eprintln!("串口 {} 已被占用", config.serial_port); + return Ok(()); + } + }, + Ok(_) => {} + } + // 创建 MQTT 客户端 let mut mqttopts = MqttOptions::new( &config.mqtt.client_id, From 9ba428ddba673e0fa233b232a2b76af14d089244 Mon Sep 17 00:00:00 2001 From: test Date: Mon, 31 Mar 2025 08:31:49 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index bafe3a6..eae5e06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,7 +76,7 @@ async fn get_mac() -> HttpResponse { mac_address: mac, }; // 在新线程中运行MQTT和串口服务 - let mqtt_handle = tokio::spawn(async { + let _mqtt_handle = tokio::spawn(async { if let Err(e) = run_mqtt_and_serial().await { eprintln!("MQTT/串口服务错误: {}", e); } @@ -139,11 +139,9 @@ async fn run_mqtt_and_serial() -> Result<()> { match serialport::new(&config.serial_port, config.baud_rate) .timeout(Duration::from_millis(10)) .open() { - Err(e) => { - if e.kind() == std::io::ErrorKind::PermissionDenied { - eprintln!("串口 {} 已被占用", config.serial_port); - return Ok(()); - } + Err(_e) => { + eprintln!("串口 {} 已被占用", config.serial_port); + return Ok(()); }, Ok(_) => {} } From 3d66a87708c41bf781d63ddb367aa9306233626b Mon Sep 17 00:00:00 2001 From: OCEAN <1010331798@qq.com> Date: Tue, 1 Apr 2025 16:41:35 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BC=98=E5=8C=96mqtt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.json | 2 +- src/main.rs | 82 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/config.json b/config.json index 60fcd65..e7b4b47 100644 --- a/config.json +++ b/config.json @@ -8,7 +8,7 @@ "port": 1883, "username": "admin", "password": "Auseft@2025", - "keep_alive_secs": 5, + "keep_alive_secs": 60, "topic_prefix": "weight/data" } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index eae5e06..6253fcd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -146,24 +146,38 @@ async fn run_mqtt_and_serial() -> Result<()> { Ok(_) => {} } - // 创建 MQTT 客户端 - let mut mqttopts = MqttOptions::new( - &config.mqtt.client_id, - &config.mqtt.host, - config.mqtt.port - ); - mqttopts.set_keep_alive(Duration::from_secs(config.mqtt.keep_alive_secs)); - mqttopts.set_credentials(&config.mqtt.username, &config.mqtt.password); - let (mut client, mut connection) = Client::new(mqttopts, 10); - - // 在单独的线程中处理 MQTT 连接 + // 创建MQTT连接函数 + let create_mqtt_client = || -> (Client, rumqttc::Connection) { + let mut mqttopts = MqttOptions::new( + &config.mqtt.client_id, + &config.mqtt.host, + config.mqtt.port + ); + mqttopts.set_keep_alive(Duration::from_secs(60)); // 增加保活时间到60秒 + mqttopts.set_credentials(&config.mqtt.username, &config.mqtt.password); + mqttopts.set_clean_session(true); + Client::new(mqttopts, 10) + }; + + // 初始化MQTT客户端 + let (mut client, mut connection) = create_mqtt_client(); + + // 在单独的线程中处理MQTT连接 + let mqtt_config = config.mqtt.clone(); thread::spawn(move || { - for notification in connection.iter() { - match notification { - Ok(_) => {} - Err(e) => { - eprintln!("MQTT连接错误: {:?}", e); - break; + loop { + for notification in connection.iter() { + match notification { + Ok(_) => {} + Err(e) => { + eprintln!("MQTT连接错误: {:?}, 尝试重新连接...", e); + thread::sleep(Duration::from_secs(5)); // 等待5秒后重试 + // 重新创建连接 + let (new_client, new_connection) = create_mqtt_client(); + client = new_client; + connection = new_connection; + break; + } } } } @@ -187,13 +201,10 @@ async fn run_mqtt_and_serial() -> Result<()> { match port.read(serial_buf.as_mut_slice()) { Ok(t) => { if t > 0 { - // 将新数据添加到累积的字符串中 if let Ok(data) = String::from_utf8(serial_buf[..t].to_vec()) { accumulated_data.push_str(&data); - // 检查是否有完整的数据行(以换行符或回车符结束) if accumulated_data.contains('\n') || accumulated_data.contains('\r') { - // 处理累积的数据 let lines: Vec<&str> = accumulated_data .split(|c| c == '\n' || c == '\r') .filter(|s| !s.is_empty()) @@ -204,7 +215,6 @@ async fn run_mqtt_and_serial() -> Result<()> { if !trimmed_data.is_empty() { println!("收到完整数据: {}", trimmed_data); - // 创建权重数据结构 let weight_data = WeightData { weight: trimmed_data.to_string(), timestamp: std::time::SystemTime::now() @@ -213,31 +223,41 @@ async fn run_mqtt_and_serial() -> Result<()> { .as_secs(), }; - // 序列化数据 let json_data = serde_json::to_string(&weight_data)?; println!("当前JSON数据: {}", json_data); - // 获取MAC地址 let mac_address = get_mac_address(); println!("MAC地址: {}", mac_address); - // 发布到 MQTT,主题中包含MAC地址 - let topic = format!("{}/{}", config.mqtt.topic_prefix, mac_address); - if let Err(e) = client.publish(topic, QoS::AtLeastOnce, false, json_data) { - eprintln!("MQTT发布错误: {:?}", e); - } else { - println!("成功发送数据到MQTT"); + + let topic = format!("{}/{}", mqtt_config.topic_prefix, mac_address); + let mut retry_count = 0; + let max_retries = 3; + + // 添加重试机制 + while retry_count < max_retries { + match client.publish(&topic, QoS::AtLeastOnce, false, json_data.clone()) { + Ok(_) => { + println!("成功发送数据到MQTT"); + break; + } + Err(e) => { + eprintln!("MQTT发布错误 (尝试 {}/{}): {:?}", retry_count + 1, max_retries, e); + retry_count += 1; + if retry_count < max_retries { + thread::sleep(Duration::from_secs(1)); + } + } + } } } } - // 清空累积的数据 accumulated_data.clear(); } } } } Err(ref e) if e.kind() == io::ErrorKind::TimedOut => { - // Timeout is not an error, just continue continue; } Err(e) => { From c2a749df78e5f78ad42f2fefc374d641c881253b Mon Sep 17 00:00:00 2001 From: OCEAN <1010331798@qq.com> Date: Tue, 1 Apr 2025 16:55:04 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6253fcd..b594527 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use serialport; use actix_web::{web, App, HttpServer, HttpResponse}; use actix_cors::Cors; use std::fs; +use std::sync::{Arc, Mutex}; #[derive(Serialize, Deserialize)] struct WeightData { @@ -26,7 +27,7 @@ struct ScaleTypeResponse { scale_type: String, } -#[derive(Deserialize)] +#[derive(Deserialize, Clone)] struct MqttConfig { client_id: String, host: String, @@ -146,24 +147,27 @@ async fn run_mqtt_and_serial() -> Result<()> { Ok(_) => {} } + let mqtt_config = config.mqtt.clone(); + // 创建MQTT连接函数 - let create_mqtt_client = || -> (Client, rumqttc::Connection) { + let create_mqtt_client = move || -> (Client, rumqttc::Connection) { let mut mqttopts = MqttOptions::new( - &config.mqtt.client_id, - &config.mqtt.host, - config.mqtt.port + &mqtt_config.client_id, + &mqtt_config.host, + mqtt_config.port ); mqttopts.set_keep_alive(Duration::from_secs(60)); // 增加保活时间到60秒 - mqttopts.set_credentials(&config.mqtt.username, &config.mqtt.password); + mqttopts.set_credentials(&mqtt_config.username, &mqtt_config.password); mqttopts.set_clean_session(true); Client::new(mqttopts, 10) }; // 初始化MQTT客户端 - let (mut client, mut connection) = create_mqtt_client(); + let (client, mut connection) = create_mqtt_client(); + let client = Arc::new(Mutex::new(client)); + let client_clone = client.clone(); // 在单独的线程中处理MQTT连接 - let mqtt_config = config.mqtt.clone(); thread::spawn(move || { loop { for notification in connection.iter() { @@ -174,7 +178,7 @@ async fn run_mqtt_and_serial() -> Result<()> { thread::sleep(Duration::from_secs(5)); // 等待5秒后重试 // 重新创建连接 let (new_client, new_connection) = create_mqtt_client(); - client = new_client; + *client_clone.lock().unwrap() = new_client; connection = new_connection; break; } @@ -235,7 +239,8 @@ async fn run_mqtt_and_serial() -> Result<()> { // 添加重试机制 while retry_count < max_retries { - match client.publish(&topic, QoS::AtLeastOnce, false, json_data.clone()) { + let mut client_guard = client.lock().unwrap(); + match client_guard.publish(&topic, QoS::AtLeastOnce, false, json_data.clone()) { Ok(_) => { println!("成功发送数据到MQTT"); break;