修改日志
This commit is contained in:
@@ -2,6 +2,77 @@ use rand::Rng;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// ===================== 日志模块 =====================
|
||||
/// 日志文件(Mutex 确保线程安全写入)
|
||||
static LOG_FILE: std::sync::Mutex<Option<std::fs::File>> = std::sync::Mutex::new(None);
|
||||
|
||||
/// 初始化日志文件(以追加方式打开)
|
||||
fn init_log_file() {
|
||||
let mut guard = LOG_FILE.lock().unwrap();
|
||||
if guard.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let exe_path = match std::env::current_exe() {
|
||||
Ok(p) => p,
|
||||
Err(_) => return,
|
||||
};
|
||||
let log_dir = match exe_path.parent() {
|
||||
Some(d) => d,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let log_name = format!("Updater_{}.log", chrono::Local::now().format("%Y%m%d"));
|
||||
let log_path = log_dir.join(log_name);
|
||||
|
||||
match std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&log_path)
|
||||
{
|
||||
Ok(file) => {
|
||||
eprintln!("[日志] 日志文件: {:?}", log_path);
|
||||
*guard = Some(file);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[日志] 无法打开日志文件: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 日志宏:同时输出到控制台和文件
|
||||
macro_rules! log_print {
|
||||
($($arg:tt)*) => {{
|
||||
let msg = format!($($arg)*);
|
||||
print!("{}\n", msg);
|
||||
std::io::stdout().flush().ok();
|
||||
if LOG_FILE.lock().unwrap().is_none() {
|
||||
init_log_file();
|
||||
}
|
||||
if let Some(ref mut file) = *LOG_FILE.lock().unwrap() {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(file, "{}", msg);
|
||||
let _ = file.flush();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// 错误日志宏:同时输出到控制台stderr和文件(始终记录)
|
||||
macro_rules! log_eprintln {
|
||||
($($arg:tt)*) => {{
|
||||
let msg = format!($($arg)*);
|
||||
eprintln!("{}", msg);
|
||||
if LOG_FILE.lock().unwrap().is_none() {
|
||||
init_log_file();
|
||||
}
|
||||
if let Some(ref mut file) = *LOG_FILE.lock().unwrap() {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(file, "{}", msg);
|
||||
let _ = file.flush();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
// ===================== 更新阶段枚举 =====================
|
||||
/// 更新流程的三个阶段
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -412,7 +483,7 @@ fn schedule_bootloader_launch(
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e);
|
||||
log_eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e);
|
||||
// 启动失败也发送断连信号
|
||||
if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() {
|
||||
let _ = tx.send(());
|
||||
@@ -436,7 +507,7 @@ fn schedule_bootloader_launch(
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e);
|
||||
log_eprintln!("{} [错误] 启动 BootLoader.exe 失败: {}", ts, e);
|
||||
if let Some(tx) = shutdown_tx_arc.lock().unwrap().take() {
|
||||
let _ = tx.send(());
|
||||
}
|
||||
@@ -447,28 +518,24 @@ fn schedule_bootloader_launch(
|
||||
}
|
||||
|
||||
/// 发送 GetFileMd5 请求
|
||||
fn request_file_md5(sender: &cube_lib::websocket::MessageSender, filename: &str, bytes: u64, debug: bool) {
|
||||
fn request_file_md5(sender: &cube_lib::websocket::MessageSender, filename: &str, bytes: u64) {
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#,
|
||||
filename, bytes
|
||||
);
|
||||
if debug {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} 发送消息:{}", ts, msg_str);
|
||||
}
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
|
||||
/// 发送文件下载请求(断点续传)
|
||||
fn request_download(sender: &cube_lib::websocket::MessageSender, filename: &str, offset: u64, debug: bool) {
|
||||
fn request_download(sender: &cube_lib::websocket::MessageSender, filename: &str, offset: u64) {
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#,
|
||||
filename, offset
|
||||
);
|
||||
if debug {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} 发送消息:{}", ts, msg_str);
|
||||
}
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
|
||||
@@ -666,7 +733,7 @@ fn get_app_tmp_file_size(app_name: &str, relative_path: &str) -> u64 {
|
||||
}
|
||||
|
||||
/// 获取其他应用的本地版本号(通过 PowerShell 读取 PE 版本)
|
||||
fn get_local_app_version(app_name: &str, relative_path: &str, _debug: bool) -> String {
|
||||
fn get_local_app_version(app_name: &str, relative_path: &str) -> String {
|
||||
// 应用主 exe 一般在相对路径的顶级,如 app.exe 或 bin/app.exe
|
||||
// 取第一段目录名或文件名作为 exe 查找起点
|
||||
let file_path = get_updater_data_dir()
|
||||
@@ -720,16 +787,14 @@ fn request_file_md5_for_app(
|
||||
app_name: &str,
|
||||
relative_path: &str,
|
||||
offset: u64,
|
||||
debug: bool,
|
||||
) {
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"GetFileMd5","Data":{{"filename":"{}","bytes":{}}}}}"#,
|
||||
relative_path, offset
|
||||
);
|
||||
if debug {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} [应用] {} 请求 md5 (offset {}): {}", ts, app_name, offset, relative_path);
|
||||
}
|
||||
log_print!("{} [应用] {} 请求 md5 (offset {}): {}", ts, app_name, offset, relative_path);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
|
||||
@@ -738,16 +803,14 @@ fn request_download_for_app(
|
||||
sender: &cube_lib::websocket::MessageSender,
|
||||
relative_path: &str,
|
||||
offset: u64,
|
||||
debug: bool,
|
||||
) {
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"DownloadFile","Data":{{"filename":"{}","offset":{}}}}}"#,
|
||||
relative_path, offset
|
||||
);
|
||||
if debug {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} [应用] 请求下载: {} (offset {})", ts, relative_path, offset);
|
||||
}
|
||||
log_print!("{} [应用] 请求下载: {} (offset {})", ts, relative_path, offset);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
|
||||
@@ -1072,16 +1135,14 @@ fn get_app_candidates(debug: bool) -> Vec<String> {
|
||||
|
||||
/// 递归扫描升级目录,返回 (relative_path, full_path) 列表
|
||||
/// 跳过 .tmp 文件(如果存在同名非 tmp 文件的话)
|
||||
fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> {
|
||||
fn scan_upgrade_dir(app_name: &str) -> Vec<(String, PathBuf)> {
|
||||
let upgrade_base = get_updater_data_dir()
|
||||
.join("Updater")
|
||||
.join("UpGrade")
|
||||
.join(app_name);
|
||||
|
||||
if !upgrade_base.exists() {
|
||||
if debug {
|
||||
println!("[应用] {} 升级目录不存在: {:?}", app_name, upgrade_base);
|
||||
}
|
||||
log_print!("[应用] {} 升级目录不存在: {:?}", app_name, upgrade_base);
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
@@ -1107,9 +1168,7 @@ fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> {
|
||||
let non_tmp = rel_str.trim_end_matches(".tmp");
|
||||
let non_tmp_path = upgrade_base.join(non_tmp);
|
||||
if non_tmp_path.exists() {
|
||||
if debug {
|
||||
println!("[应用] 跳过 tmp(同名文件已存在): {} -> {}", rel_str, non_tmp);
|
||||
}
|
||||
log_print!("[应用] 跳过 tmp(同名文件已存在): {} -> {}", rel_str, non_tmp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1121,11 +1180,9 @@ fn scan_upgrade_dir(app_name: &str, debug: bool) -> Vec<(String, PathBuf)> {
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
println!("[应用] {} 升级文件列表 ({} 个):", app_name, files.len());
|
||||
log_print!("[应用] {} 升级文件列表 ({} 个):", app_name, files.len());
|
||||
for (rel, _) in &files {
|
||||
println!("[应用] - {}", rel);
|
||||
}
|
||||
log_print!("[应用] - {}", rel);
|
||||
}
|
||||
|
||||
files
|
||||
@@ -1145,7 +1202,7 @@ fn make_shutdown_channel() -> (
|
||||
|
||||
|
||||
/// 运行 Updater(使用 CubeLib 内置的自动重连)
|
||||
/// 返回本次运行是否执行了更新(下载了文件)
|
||||
/// 返回本次运行是否更新了 Updater 自身(只有 Updater 更新了才需要退出重启)
|
||||
async fn run_updater(debug_mode: bool) -> bool {
|
||||
// 创建本次运行的上下文
|
||||
let ctx = Arc::new(UpdateContext::default());
|
||||
@@ -1223,16 +1280,15 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
let update_check_done_clone2 = update_check_done_clone.clone();
|
||||
client.on_message(move |msg_type, data, sender| {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
if debug_msg {
|
||||
// 收到消息日志:data 是完整 parsed 对象,取其中的 Data 字段打印
|
||||
|
||||
// 收到消息日志(始终记录)
|
||||
let actual_data = data.get("Data").unwrap_or(&serde_json::Value::Null);
|
||||
let data_str = serde_json::to_string(actual_data).unwrap_or_else(|_| "{}".to_string());
|
||||
println!("{} 收到消息:{{\"Type\":{},\"Data\":{}}}",
|
||||
log_print!("{} 收到消息:{{\"Type\":{},\"Data\":{}}}",
|
||||
ts,
|
||||
serde_json::to_string(&msg_type).unwrap_or_default(),
|
||||
data_str
|
||||
);
|
||||
}
|
||||
|
||||
// 收到 welcome 后,根据当前阶段发送 GetFileVer
|
||||
if msg_type == "welcome" {
|
||||
@@ -1243,14 +1299,12 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
match current_phase {
|
||||
UpdatePhase::BootLoader => {
|
||||
// 阶段1:只请求 BootLoader.exe
|
||||
println!("{} [阶段1] 检查 BootLoader...", ts);
|
||||
log_print!("{} [阶段1] 检查 BootLoader...", ts);
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["BootLoader.exe"]}}}}"#,
|
||||
device_number
|
||||
);
|
||||
if debug_msg {
|
||||
println!("{} 发送消息:{}", ts, msg_str);
|
||||
}
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
_ => {
|
||||
@@ -1274,40 +1328,42 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
let local_version = get_local_file_version("BootLoader.exe");
|
||||
let tmp_size = get_tmp_file_size("BootLoader.exe");
|
||||
|
||||
println!("{} [版本] BootLoader.exe: 服务端={}, 本地={}", ts, server_version, local_version);
|
||||
log_print!("{} [版本] BootLoader.exe: 服务端={}, 本地={}", ts, server_version, local_version);
|
||||
|
||||
let need_update = local_version == "0.0.0" || version_less_than(&local_version, server_version);
|
||||
if need_update {
|
||||
if tmp_size > 0 {
|
||||
println!("{} [续传] BootLoader.exe 发现未完成下载,请求 hash 校验...", ts);
|
||||
request_file_md5(&sender, "BootLoader.exe", tmp_size, debug_msg);
|
||||
log_print!("{} [续传] BootLoader.exe 发现未完成下载,请求 hash 校验...", ts);
|
||||
request_file_md5(&sender, "BootLoader.exe", tmp_size);
|
||||
} else {
|
||||
println!("{} [升级] BootLoader.exe 需要更新,开始下载...", ts);
|
||||
request_download(&sender, "BootLoader.exe", 0, debug_msg);
|
||||
log_print!("{} [升级] BootLoader.exe 需要更新,开始下载...", ts);
|
||||
request_download(&sender, "BootLoader.exe", 0);
|
||||
}
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
} else {
|
||||
println!("{} [版本] BootLoader.exe 版本已是最新", ts);
|
||||
log_print!("{} [版本] BootLoader.exe 版本已是最新", ts);
|
||||
// 推进到阶段2
|
||||
let next_phase = UpdatePhase::Updater;
|
||||
*ctx_clone.current_phase.lock().unwrap() = next_phase;
|
||||
println!("{} [阶段2] 检查 Updater...", ts);
|
||||
log_print!("{} [阶段2] 检查 Updater...", ts);
|
||||
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#,
|
||||
device_number
|
||||
);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
} else {
|
||||
// BootLoader 不在响应中,推进到阶段2
|
||||
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Updater;
|
||||
println!("{} [阶段2] 检查 Updater...", ts);
|
||||
log_print!("{} [阶段2] 检查 Updater...", ts);
|
||||
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#,
|
||||
device_number
|
||||
);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
}
|
||||
@@ -1322,25 +1378,25 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
// 保存 Updater.exe 的服务端版本号
|
||||
*ctx_clone.server_updater_version.lock().unwrap() = Some(server_version.to_string());
|
||||
|
||||
println!("{} [版本] Updater.exe: 服务端={}, 本地={}", ts, server_version, local_version);
|
||||
log_print!("{} [版本] Updater.exe: 服务端={}, 本地={}", ts, server_version, local_version);
|
||||
|
||||
let need_update = local_version == "0.0.0" || version_less_than(&local_version, server_version);
|
||||
if need_update {
|
||||
if tmp_size > 0 {
|
||||
println!("{} [续传] Updater.exe 发现未完成下载,请求 hash 校验...", ts);
|
||||
request_file_md5(&sender, "Updater.exe", tmp_size, debug_msg);
|
||||
log_print!("{} [续传] Updater.exe 发现未完成下载,请求 hash 校验...", ts);
|
||||
request_file_md5(&sender, "Updater.exe", tmp_size);
|
||||
} else {
|
||||
println!("{} [升级] Updater.exe 需要更新,开始下载...", ts);
|
||||
request_download(&sender, "Updater.exe", 0, debug_msg);
|
||||
log_print!("{} [升级] Updater.exe 需要更新,开始下载...", ts);
|
||||
request_download(&sender, "Updater.exe", 0);
|
||||
}
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
} else {
|
||||
println!("{} [版本] Updater.exe 版本已是最新", ts);
|
||||
log_print!("{} [版本] Updater.exe 版本已是最新", ts);
|
||||
// 检查是否有旧的 Updater.new.exe
|
||||
if has_updater_new_exe() {
|
||||
let updater_new_path = get_updater_data_dir().join("Updater.new.exe");
|
||||
let _ = fs::remove_file(&updater_new_path);
|
||||
println!("{} [清理] 删除旧的 Updater.new.exe", ts);
|
||||
log_print!("{} [清理] 删除旧的 Updater.new.exe", ts);
|
||||
}
|
||||
|
||||
// 推进到阶段3
|
||||
@@ -1348,7 +1404,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
if candidates.is_empty() {
|
||||
// 没有候选应用,所有阶段完成
|
||||
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Complete;
|
||||
println!("{} [阶段3] 没有候选应用,所有阶段完成", ts);
|
||||
log_print!("{} [阶段3] 没有候选应用,所有阶段完成", ts);
|
||||
update_check_done_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
// 发送断连信号
|
||||
if let Some(tx) = shutdown_tx_arc_clone.lock().unwrap().take() {
|
||||
@@ -1356,7 +1412,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
}
|
||||
} else {
|
||||
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Apps;
|
||||
println!("{} [阶段3] 检查应用: {:?}", ts, candidates);
|
||||
log_print!("{} [阶段3] 检查应用: {:?}", ts, candidates);
|
||||
|
||||
// 构建应用版本查询
|
||||
let mut file_list = Vec::new();
|
||||
@@ -1368,6 +1424,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":{}}}}}"#,
|
||||
device_number, file_list_json
|
||||
);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
}
|
||||
@@ -1394,6 +1451,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":{}}}}}"#,
|
||||
device_number, file_list_json
|
||||
);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
}
|
||||
}
|
||||
@@ -1408,9 +1466,9 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
let exe_name = format!("{}.exe", app_name);
|
||||
if let Some(server_ver) = file_versions.get(&exe_name) {
|
||||
let server_version = server_ver.as_str().unwrap_or("0.0.0");
|
||||
let local_version = get_local_app_version(app_name, &exe_name, debug_msg);
|
||||
let local_version = get_local_app_version(app_name, &exe_name);
|
||||
|
||||
println!("{} [应用] {}: 服务端={}, 本地={}", ts, app_name, server_version, local_version);
|
||||
log_print!("{} [应用] {}: 服务端={}, 本地={}", ts, app_name, server_version, local_version);
|
||||
|
||||
if local_version == "0.0.0" || version_less_than(&local_version, server_version) {
|
||||
apps_to_update.push(app_name.clone());
|
||||
@@ -1421,18 +1479,18 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
// 处理需要更新的应用
|
||||
let mut has_downloads = false;
|
||||
for app_name in &apps_to_update {
|
||||
let upgrade_files = scan_upgrade_dir(app_name, debug_msg);
|
||||
let upgrade_files = scan_upgrade_dir(app_name);
|
||||
if upgrade_files.is_empty() {
|
||||
println!("{} [应用] {} 没有升级文件,跳过", ts, app_name);
|
||||
log_print!("{} [应用] {} 没有升级文件,跳过", ts, app_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (rel_path, _) in upgrade_files {
|
||||
let tmp_size = get_app_tmp_file_size(app_name, &rel_path);
|
||||
if tmp_size > 0 {
|
||||
request_file_md5_for_app(&sender, app_name, &rel_path, tmp_size, debug_msg);
|
||||
request_file_md5_for_app(&sender, app_name, &rel_path, tmp_size);
|
||||
} else {
|
||||
request_download_for_app(&sender, &rel_path, 0, debug_msg);
|
||||
request_download_for_app(&sender, &rel_path, 0);
|
||||
}
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
has_downloads = true;
|
||||
@@ -1491,15 +1549,14 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
let tmp_filename = format!("{}.tmp", filename);
|
||||
let local_md5 = compute_file_hash_in_dir(app_name, &tmp_filename, bytes, debug_msg);
|
||||
|
||||
if debug_msg {
|
||||
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
if let Some(ref lm) = local_md5 {
|
||||
println!("{} [应用] {} md5: 本地={}, 服务端={}", ts, filename, lm, server_md5);
|
||||
}
|
||||
log_print!("{} [应用] {} md5: 本地={}, 服务端={}", ts, filename, lm, server_md5);
|
||||
}
|
||||
|
||||
if local_md5.as_deref() == Some(server_md5) {
|
||||
request_download_for_app(&sender, filename, bytes, debug_msg);
|
||||
request_download_for_app(&sender, filename, bytes);
|
||||
} else {
|
||||
let tmp_path = get_updater_data_dir()
|
||||
.join("Updater")
|
||||
@@ -1507,7 +1564,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
.join(app_name)
|
||||
.join(&tmp_filename);
|
||||
let _ = fs::remove_file(&tmp_path);
|
||||
request_download_for_app(&sender, filename, 0, debug_msg);
|
||||
request_download_for_app(&sender, filename, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1539,20 +1596,16 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
// 比较 md5
|
||||
if local_md5.as_deref() == Some(server_md5) {
|
||||
// md5 相同,从 offset bytes 处续传
|
||||
if debug_msg {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} [续传] {} md5匹配,从 {} 字节处续传", ts, filename, bytes);
|
||||
}
|
||||
request_download(&sender, filename, bytes, debug_msg);
|
||||
log_print!("{} [续传] {} md5匹配,从 {} 字节处续传", ts, filename, bytes);
|
||||
request_download(&sender, filename, bytes);
|
||||
} else {
|
||||
// md5 不同,删除临时文件,重新下载
|
||||
if debug_msg {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} [续传] {} md5不匹配,重新下载", ts, filename);
|
||||
}
|
||||
log_print!("{} [续传] {} md5不匹配,重新下载", ts, filename);
|
||||
let tmp_path = get_updater_data_dir().join(&tmp_filename);
|
||||
let _ = fs::remove_file(&tmp_path);
|
||||
request_download(&sender, filename, 0, debug_msg);
|
||||
request_download(&sender, filename, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1639,26 +1692,31 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
// ========== BootLoader/Updater 的 DownloadComplete 处理 ==========
|
||||
let completed = handle_download_complete(&ctx_clone, data_obj, debug_msg);
|
||||
if let Some(ref completed_file) = completed {
|
||||
// BootLoader.exe 下载完成
|
||||
// BootLoader.exe 下载完成,推进到阶段2检查 Updater 版本
|
||||
if completed_file == "BootLoader.exe" {
|
||||
if !bootloader_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
bootloader_downloaded_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
if debug_msg {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} [升级] BootLoader.exe 下载完成,开始下载 Updater.exe...", ts);
|
||||
log_print!("{} [升级] BootLoader.exe 下载完成,推进到阶段2检查 Updater...", ts);
|
||||
}
|
||||
// 开始下载 Updater.exe
|
||||
request_download(&sender, "Updater.exe", 0, debug_msg);
|
||||
// 推进到阶段2,由阶段2决定是否需要下载 Updater
|
||||
*ctx_clone.current_phase.lock().unwrap() = UpdatePhase::Updater;
|
||||
let msg = format!(
|
||||
r#"{{"Type":"GetFileVer","Data":{{"DeviceNumber":"{}","file_list":["Updater.exe"]}}}}"#,
|
||||
device_number
|
||||
);
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
log_print!("{} 发送消息:{}", ts, msg);
|
||||
sender.send(msg);
|
||||
}
|
||||
}
|
||||
// Updater.new.exe 下载完成
|
||||
else if completed_file == "Updater.new.exe" {
|
||||
if !updater_downloaded_clone2.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
updater_downloaded_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
if debug_msg {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
println!("{} [升级] Updater.new.exe 下载完成(DownloadComplete),准备启动 BootLoader...", ts);
|
||||
}
|
||||
log_print!("{} [升级] Updater.new.exe 下载完成(DownloadComplete),准备启动 BootLoader...", ts);
|
||||
schedule_bootloader_launch(debug_msg, shutdown_tx_arc.clone());
|
||||
}
|
||||
}
|
||||
@@ -1679,7 +1737,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
|
||||
// 设置错误回调
|
||||
client.on_error(|error| {
|
||||
eprintln!("[错误] WebSocket: {}", error);
|
||||
log_eprintln!("[错误] WebSocket: {}", error);
|
||||
});
|
||||
|
||||
// 设置首次连接回调
|
||||
@@ -1763,8 +1821,8 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
println!("Updater 本次运行结束");
|
||||
}
|
||||
|
||||
// 返回是否执行了更新(下载了文件)
|
||||
update_performed.load(std::sync::atomic::Ordering::SeqCst)
|
||||
// 返回 Updater 是否被更新(只有 Updater 更新了才需要退出重启)
|
||||
updater_downloaded.load(std::sync::atomic::Ordering::SeqCst)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@@ -1799,11 +1857,11 @@ async fn main() {
|
||||
// 主循环:常驻运行,定期检查更新
|
||||
loop {
|
||||
// 运行一次 Updater(连接、检查、下载)
|
||||
let update_performed = run_updater(config.debug_mode).await;
|
||||
let updater_updated = run_updater(config.debug_mode).await;
|
||||
|
||||
if update_performed {
|
||||
if updater_updated {
|
||||
if config.debug_mode {
|
||||
println!("Updater 执行了更新,即将退出(等待 BootLoader 重启)");
|
||||
println!("Updater 自身已更新,即将退出(等待 BootLoader 重启)");
|
||||
}
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user