bootloader与app下载合并, 保存原始日志与ui日志

This commit is contained in:
JIe
2024-12-11 11:40:05 +08:00
parent fd87bf7fce
commit 85939e7fc4
3 changed files with 302 additions and 275 deletions

View File

@@ -1,19 +1,20 @@
mod download_wrapper;
mod mes_service;
use std::any::Any;
use std::fs;
use crate::mes_service::MesService;
use crossbeam::channel;
use std::sync::{Arc, Mutex, LazyLock};
use crossbeam::channel::Sender;
use iced::widget::{button, checkbox, column, container, radio, row, text_editor, text_input};
use iced::{event, window, Element, Event, Length, Subscription, Task, time};
use download_wrapper::DownloadType;
use iced::application::Title;
use iced::widget::text_editor::Action::Scroll;
use iced::widget::text_editor::Edit;
use iced::widget::{button, checkbox, column, container, radio, row, text_editor, text_input};
use iced::{event, time, window, Element, Event, Length, Subscription, Task};
use serde_json::Map;
use download_wrapper::DownloadType;
use crate::mes_service::MesService;
use std::any::Any;
use std::fs;
use std::sync::{Arc, LazyLock, Mutex};
use std::io::Write;
pub fn main() -> iced::Result {
iced::application("WisunDownload V0.1", MainWindow::update, MainWindow::view)
@@ -23,9 +24,7 @@ pub fn main() -> iced::Result {
.run()
}
static logs: LazyLock<Arc<Mutex<Vec<String>>>> = LazyLock::new(|| {
Arc::new(Mutex::new(Vec::new()))
});
static logs: LazyLock<Arc<Mutex<Vec<String>>>> = LazyLock::new(|| Arc::new(Mutex::new(Vec::new())));
struct MainWindow {
is_online: bool,
@@ -39,7 +38,7 @@ struct MainWindow {
impl Default for MainWindow {
fn default() -> Self {
let (sender, receiver) =channel::unbounded();
let (sender, receiver) = channel::unbounded();
Self {
is_online: true,
mysql_config: MysqlConfig::default(),
@@ -47,7 +46,7 @@ impl Default for MainWindow {
label: String::new(),
log_content: text_editor::Content::default(),
sender,
receiver
receiver,
}
}
}
@@ -76,8 +75,9 @@ enum Message {
AddLog(String),
LogContentChanged(text_editor::Action),
SaveConfig,
DownloadEnd(bool),
DownloadEnd((String,bool)),
WindowEvent(Event),
ClearLog,
Tick,
}
@@ -130,65 +130,66 @@ impl MainWindow {
self.is_online = is_online;
Task::none()
}
Message::ClearLog =>{
self.log_content.perform(text_editor::Action::SelectAll);
self.log_content.perform(text_editor::Action::Edit(Edit::Delete));
Task::none()
}
Message::AddLog(log) => {
for c in log.chars() {
self.log_content.perform(text_editor::Action::Edit(Edit::Insert(c)))
self.log_content
.perform(text_editor::Action::Edit(Edit::Insert(c)))
}
self.log_content.perform(text_editor::Action::Edit(Edit::Enter));
self.log_content
.perform(text_editor::Action::Edit(Edit::Enter));
let line_size = self.log_content.lines().count();
self.log_content.perform(Scroll { lines: line_size as i32 });
self.log_content.perform(Scroll {
lines: line_size as i32,
});
Task::none()
}
Message::Tick => {
for log in logs.lock().unwrap().iter() {
for c in log.chars() {
self.log_content.perform(text_editor::Action::Edit(Edit::Insert(c)))
self.log_content
.perform(text_editor::Action::Edit(Edit::Insert(c)))
}
self.log_content.perform(text_editor::Action::Edit(Edit::Enter));
self.log_content
.perform(text_editor::Action::Edit(Edit::Enter));
let line_size = self.log_content.lines().count();
self.log_content.perform(Scroll { lines: line_size as i32 });
self.log_content.perform(Scroll {
lines: line_size as i32,
});
}
logs.lock().unwrap().clear();
match self.receiver.try_recv() {
Ok(event) => {
match event{
Message::DownloadEnd(res)=>{
if res{
add_log("下载成功 By Ui Thread".to_string());
}else{
add_log("下载失败 By Ui Thread".to_string());
}
}
_=>{
}
Ok(event) => match event {
Message::DownloadEnd((label, res)) => {
let _ = self.update(Message::DownloadEnd((label, res)));
}
}
Err(channel::TryRecvError::Empty) => {
}
_ => {}
},
Err(channel::TryRecvError::Empty) => {}
Err(channel::TryRecvError::Disconnected) => {
println!("Disconnected");
}
};
Task::none()
}
Message::LogContentChanged(action) => {
match action{
Scroll { lines } => {
self.log_content.perform(Scroll { lines });
Task::none()
}
_=>{
Task::none()
}
Message::LogContentChanged(action) => match action {
Scroll { lines } => {
self.log_content.perform(Scroll { lines });
Task::none()
}
}
Message::DownloadEnd(res)=>{
if res{
add_log("下载成功 By Ui Thread".to_string());
}else{
add_log("下载失败 By Ui Thread".to_string());
_ => Task::none(),
},
Message::DownloadEnd((label,res)) => {
if !fs::exists("./uilog"){
fs::create_dir("./uilog").expect("Cant Create UiLog Folder");
}
let mut file = fs::OpenOptions::new().create(true).append(true).open(format!("./uilog/{label}.txt")).unwrap();
writeln!(file, "{:?}",self.log_content.text().clone()).unwrap();
Task::none()
}
Message::WindowEvent(event) => {
@@ -205,52 +206,52 @@ impl MainWindow {
};
Task::none()
}
_ => { Task::none() }
_ => Task::none(),
}
}
fn view(&self) -> Element<Message> {
let ip_input = text_input(
"IP Address",
&self.mysql_config.ip,
).on_input(Message::IpChanged);
let port_input = text_input(
"Port",
&self.mysql_config.port,
).on_input(Message::PortChanged);
let username_input = text_input(
"Username",
&self.mysql_config.username,
).on_input(Message::UsernameChanged);
let password_input = text_input(
"Password",
&self.mysql_config.password,
).on_input(Message::PasswordChanged);
let database_input = text_input(
"Database",
&self.mysql_config.database,
).on_input(Message::DatabaseChanged);
let work_order_input = text_input(
"WorkOrder",
&self.mysql_config.work_order,
).on_input(Message::WorkOrderChanged);
let label_input = text_input(
"label",
&self.label,
).on_input(Message::LabelChanged).on_submit(Message::Start()).width(Length::Fill);
let ip_input = text_input("IP Address", &self.mysql_config.ip).on_input(Message::IpChanged);
let port_input = text_input("Port", &self.mysql_config.port).on_input(Message::PortChanged);
let username_input =
text_input("Username", &self.mysql_config.username).on_input(Message::UsernameChanged);
let password_input =
text_input("Password", &self.mysql_config.password).on_input(Message::PasswordChanged);
let database_input =
text_input("Database", &self.mysql_config.database).on_input(Message::DatabaseChanged);
let work_order_input = text_input("WorkOrder", &self.mysql_config.work_order)
.on_input(Message::WorkOrderChanged);
let label_input = text_input("label", &self.label)
.on_input(Message::LabelChanged)
.on_submit(Message::Start())
.width(Length::Fill);
let content = column![
row![ip_input, port_input].spacing(5),
row![username_input, password_input].spacing(5),
row![database_input, work_order_input].spacing(5),
row![
radio("BootLoader", DownloadType::Bootloader,self.selection,Message::TypeSelected),
radio("App", DownloadType::App,self.selection,Message::TypeSelected),
radio("Cal", DownloadType::Rail,self.selection,Message::TypeSelected),
radio(
"App",
DownloadType::App,
self.selection,
Message::TypeSelected
),
radio(
"Cal",
DownloadType::Rail,
self.selection,
Message::TypeSelected
),
checkbox("online", self.is_online).on_toggle(Message::OnlineChecked)
].spacing(10),
row![label_input,button("Start").on_press(Message::Start())].spacing(10),
text_editor(&self.log_content).on_action(Message::LogContentChanged).height(Length::Fill)
].spacing(10).padding(5);
]
.spacing(10),
row![label_input, button("Start").on_press(Message::Start())].spacing(10),
text_editor(&self.log_content)
.on_action(Message::LogContentChanged)
.height(Length::Fill)
]
.spacing(10)
.padding(5);
let container = container(content).padding(20);
container.into()
@@ -259,44 +260,54 @@ impl MainWindow {
fn subscription(&self) -> Subscription<Message> {
Subscription::batch(vec![
event::listen().map(Message::WindowEvent),
time::every(time::Duration::from_millis(50))
.map(|_| Message::Tick)
time::every(time::Duration::from_millis(50)).map(|_| Message::Tick),
])
}
fn start(&mut self, sender: Sender<Message>) -> (){
fn start(&mut self, sender: Sender<Message>) -> () {
let mes_config = self.mysql_config.clone();
let label = self.label.clone();
let download_type: DownloadType = self.selection.unwrap();
let online = self.is_online.clone();
if label == ""{
if label == "" {
add_log("请输入Label".to_string());
return;
}
std::thread::spawn(move || {
let mut download_wrapper = download_wrapper::DownloadWrapper::new();
let mut mes_service: MesService;
sender.send(Message::ClearLog).unwrap();
if online {
add_log("当前为在线模式, 正在连接数据库".to_string());
match MesService::new(mes_config.ip.clone(), mes_config.port.clone(), mes_config.username.clone(), mes_config.password.clone(), mes_config.database.clone()){
match MesService::new(
mes_config.ip.clone(),
mes_config.port.clone(),
mes_config.username.clone(),
mes_config.password.clone(),
mes_config.database.clone(),
) {
Ok(service) => mes_service = service,
Err(e) =>{
Err(e) => {
add_log(format!("连接数据库失败: {:?}", e.to_string()));
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
}
add_log("连接成功".to_string());
add_log("正在过站检测".to_string());
let check_result = mes_service.check_station(mes_config.work_order.clone(), label.clone(), download_type);
let check_result = mes_service.check_station(
mes_config.work_order.clone(),
label.clone(),
download_type,
);
if let Err(res) = check_result {
add_log(format!("过站检测失败: {:?}", res.to_string()));
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
} else if let Ok(res) = check_result {
if !res {
add_log("过站检测失败".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("过站检测成功".to_string());
@@ -305,98 +316,119 @@ impl MainWindow {
add_log("正在检查JLink连接".to_string());
if let Err(e) = download_wrapper.check_jlink() {
add_log("JLink检查失败, 请检查是否安装驱动或连接是否异常".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("JLink检查成功".to_string());
add_log("正在检查设备连接".to_string());
if let Err(e) = download_wrapper.check_device() {
add_log("设备检查失败, 请检查设备是否连接".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("设备检查成功".to_string());
match download_type {
DownloadType::Bootloader =>{
DownloadType::Bootloader => {}
DownloadType::App => {
add_log("正在擦除Flash".to_string());
if let Err(e) = download_wrapper.erase(){
if let Err(e) = download_wrapper.erase(Some(label.clone())) {
add_log("擦除失败".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("擦除成功".to_string());
add_log("正在下载BootLoader".to_string());
if let Err(e) = download_wrapper.download(download_type){
if let Err(e) = download_wrapper.download(DownloadType::Bootloader,Some(label.clone())) {
add_log("下载BootLoader失败".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("下载成功".to_string());
}
DownloadType::App =>{
add_log("下载BootLoader成功".to_string());
add_log("正在下载App".to_string());
if let Err(e) = download_wrapper.download(download_type){
if let Err(e) = download_wrapper.download(download_type, Some(label.clone())) {
add_log("下载App失败".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("下载成功".to_string());
add_log("下载App成功".to_string());
}
DownloadType::Rail=>{
DownloadType::Rail => {
add_log("正在下载Rail".to_string());
if let Err(e) = download_wrapper.download(download_type){
if let Err(e) = download_wrapper.download(download_type, Some(label.clone())) {
add_log("下载Rail失败".to_string());
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
add_log("下载成功".to_string());
add_log("下载Rail成功".to_string());
}
}
return if online {
match MesService::new(mes_config.ip.clone(), mes_config.port.clone(), mes_config.username.clone(), mes_config.password.clone(), mes_config.database.clone()){
match MesService::new(
mes_config.ip.clone(),
mes_config.port.clone(),
mes_config.username.clone(),
mes_config.password.clone(),
mes_config.database.clone(),
) {
Ok(service) => mes_service = service,
Err(e) =>{
Err(e) => {
add_log(format!("连接数据库失败: {:?}", e.to_string()));
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
} add_log("正在上传数据".to_string());
let update_result = mes_service.update_station(mes_config.work_order, label, download_type);
}
add_log("正在上传数据".to_string());
let update_result =
mes_service.update_station(mes_config.work_order, label.clone(), download_type);
if let Err(e) = update_result {
add_log(format!("上传失败: {:?}", e.to_string()));
sender.send(Message::DownloadEnd(false)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
sender.send(Message::DownloadEnd(true)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
} else {
add_log("当前为离线模式".to_string());
sender.send(Message::DownloadEnd(true)).unwrap();
sender.send(Message::DownloadEnd((label, false))).unwrap();
return;
}
};
});
}
fn save_config(&mut self){
fn save_config(&mut self) {
let mut config = Map::new();
config.insert("ip".to_string(), self.mysql_config.ip.clone().into());
config.insert("port".to_string(), self.mysql_config.port.clone().into());
config.insert("username".to_string(), self.mysql_config.username.clone().into());
config.insert("password".to_string(), self.mysql_config.password.clone().into());
config.insert("database".to_string(), self.mysql_config.database.clone().into());
config.insert("work_order".to_string(), self.mysql_config.work_order.clone().into());
config.insert(
"username".to_string(),
self.mysql_config.username.clone().into(),
);
config.insert(
"password".to_string(),
self.mysql_config.password.clone().into(),
);
config.insert(
"database".to_string(),
self.mysql_config.database.clone().into(),
);
config.insert(
"work_order".to_string(),
self.mysql_config.work_order.clone().into(),
);
config.insert("is_online".to_string(), self.is_online.clone().into());
config.insert("selection".to_string(), self.selection.unwrap().to_string().into());
config.insert(
"selection".to_string(),
self.selection.unwrap().to_string().into(),
);
let config_str = serde_json::to_string(&config).unwrap();
fs::write("config.json", config_str).unwrap();
fs::write("./config.json", config_str).unwrap();
}
fn read_config(&mut self){
if !fs::exists("config.json").unwrap(){
fn read_config(&mut self) {
if !fs::exists("./config.json"){
return;
}
let config_str = fs::read_to_string("config.json").unwrap();
let config_str = fs::read_to_string("./config.json").unwrap();
let config: Map<String, serde_json::Value> = serde_json::from_str(&config_str).unwrap();
self.mysql_config.ip = config["ip"].as_str().unwrap().to_string();
self.mysql_config.port = config["port"].as_str().unwrap().to_string();
@@ -405,24 +437,19 @@ impl MainWindow {
self.mysql_config.database = config["database"].as_str().unwrap().to_string();
self.mysql_config.work_order = config["work_order"].as_str().unwrap().to_string();
self.is_online = config["is_online"].as_bool().unwrap();
match config["selection"].as_str().unwrap(){
"BootLoader"=>{
match config["selection"].as_str().unwrap() {
"BootLoader" => {
self.selection = Some(DownloadType::Bootloader);
}
"App"=>{
"App" => {
self.selection = Some(DownloadType::App);
}
"Rail"=>{
"Rail" => {
self.selection = Some(DownloadType::Rail);
}
_=>{
_ => {
self.selection = None;
}
}
}
fn save_ui_log(&mut self){
todo!()
}
}
}