下载逻辑完成, ui通知逻辑完成,
This commit is contained in:
parent
b39853af95
commit
7f059c7782
1353
Cargo.lock
generated
1353
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
@ -4,10 +4,18 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced = "0.13.1"
|
iced = {version = "0.13.1", features = ["tokio", "debug"]}
|
||||||
anyhow = "1.0.91"
|
anyhow = "1.0.91"
|
||||||
serde = {version = "1.0.213", features = ["derive"]}
|
serde = {version = "1.0.213", features = ["derive"]}
|
||||||
serde_json = "1.0.132"
|
serde_json = "1.0.132"
|
||||||
|
mysql = "25.0.1"
|
||||||
|
chrono="0.4.38"
|
||||||
|
tokio = { version = "1.42", features = ["full"] }
|
||||||
|
log = "0.4.22"
|
||||||
|
lazy_static = "1.5.0"
|
||||||
|
time = "0.3.37"
|
||||||
|
crossbeam = "0.8"
|
||||||
|
|
||||||
|
|
||||||
[package.metadata.windows]
|
[package.metadata.windows]
|
||||||
link-args=["/SUBSYSTEM:WINDOWS"]
|
link-args=["/SUBSYSTEM:WINDOWS"]
|
||||||
|
249
src/download_wrapper.rs
Normal file
249
src/download_wrapper.rs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
use crate::download_wrapper::DownloadError::JlinkNotFindError;
|
||||||
|
use anyhow::Error;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
pub struct DownloadWrapper {
|
||||||
|
commander_path: PathBuf,
|
||||||
|
bin_path: PathBuf,
|
||||||
|
bootloader_name: String,
|
||||||
|
app_name: String,
|
||||||
|
rail_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum DownloadType {
|
||||||
|
Bootloader,
|
||||||
|
App,
|
||||||
|
Rail,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum DownloadError {
|
||||||
|
JlinkNotFindError,
|
||||||
|
DeviceNotFindError,
|
||||||
|
EraseError,
|
||||||
|
DownloadBootloaderError,
|
||||||
|
DownloadAppError,
|
||||||
|
DownloadRailError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DownloadWrapper {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
commander_path: PathBuf::from(std::env::current_dir().unwrap())
|
||||||
|
.join("commander/Simplicity Commander/commander.exe"),
|
||||||
|
bin_path: PathBuf::from(std::env::current_dir().unwrap()).join("bin/"),
|
||||||
|
bootloader_name: String::from("RAWM00-2-0-0_silicon-wisun_bootloader_D20241008.s37"),
|
||||||
|
app_name: String::from("RAWM00-2-0-0_silicon-wisun_APP-V1_D20240927.s37"),
|
||||||
|
rail_name: String::from("rail_soc_railtest_sisdk.s37"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DownloadWrapper {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_jlink(&self) -> Result<Vec<String>, DownloadError> {
|
||||||
|
let commander_path_str = self.commander_path.to_str().unwrap();
|
||||||
|
let output = Command::new(commander_path_str)
|
||||||
|
.arg("adapter")
|
||||||
|
.arg("list")
|
||||||
|
.output()
|
||||||
|
.expect("Failed to execute command");
|
||||||
|
if output.status.success() {
|
||||||
|
let result_str = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
let result = result_str
|
||||||
|
.split("\r\n")
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
|
let device_index_str: Vec<String> = result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.starts_with("deviceCount"))
|
||||||
|
.map(|&str| str.to_string())
|
||||||
|
.collect();
|
||||||
|
if device_index_str.is_empty()
|
||||||
|
|| device_index_str[0].split("=").collect::<Vec<&str>>()[1] == "0"
|
||||||
|
{
|
||||||
|
Err(JlinkNotFindError)
|
||||||
|
} else {
|
||||||
|
let device_ids = result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.trim().starts_with("serialNumber"))
|
||||||
|
.map(|&str| {
|
||||||
|
let temp = str.to_string();
|
||||||
|
return temp.split("=").collect::<Vec<&str>>()[1].to_string();
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
Ok(device_ids)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(JlinkNotFindError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_device(&self) -> Result<(), DownloadError> {
|
||||||
|
let commander_path_str = self.commander_path.to_str().unwrap();
|
||||||
|
let output = Command::new(commander_path_str)
|
||||||
|
.arg("device")
|
||||||
|
.arg("info")
|
||||||
|
.arg("--device")
|
||||||
|
.arg("Cortex-M4")
|
||||||
|
.output()
|
||||||
|
.expect("Failed to execute command");
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
let result = stdout.split("\r\n").collect::<Vec<&str>>();
|
||||||
|
let error_log = result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.trim().starts_with("ERROR"))
|
||||||
|
.collect::<Vec<&&str>>();
|
||||||
|
if error_log.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(DownloadError::DeviceNotFindError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn erase(&self) -> Result<(), DownloadError> {
|
||||||
|
let commander_path_str = self.commander_path.to_str().unwrap();
|
||||||
|
let output = Command::new(commander_path_str)
|
||||||
|
.arg("device")
|
||||||
|
.arg("masserase")
|
||||||
|
.arg("--device")
|
||||||
|
.arg("Cortex-M4")
|
||||||
|
.output()
|
||||||
|
.expect("Failed to execute command");
|
||||||
|
let result_str = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
let result = result_str
|
||||||
|
.split("\r\n")
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
|
if !result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.trim().starts_with("ERROR"))
|
||||||
|
.collect::<Vec<&&str>>()
|
||||||
|
.is_empty()
|
||||||
|
|| result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.trim().contains("successfully"))
|
||||||
|
.collect::<Vec<&&str>>()
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
Err(DownloadError::EraseError)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn download(&self, download_type: DownloadType) -> Result<(), DownloadError> {
|
||||||
|
let mut binding: PathBuf;
|
||||||
|
match download_type {
|
||||||
|
DownloadType::Bootloader=> {
|
||||||
|
binding = self.bin_path.join(&self.bootloader_name);
|
||||||
|
}
|
||||||
|
DownloadType::App=>{
|
||||||
|
binding = self.bin_path.join(&self.app_name);
|
||||||
|
}
|
||||||
|
DownloadType::Rail=>{
|
||||||
|
binding = self.bin_path.join(&self.rail_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let bin_path = binding.to_str().unwrap();
|
||||||
|
println!("{:?}", bin_path);
|
||||||
|
let commander_path_str = self.commander_path.to_str().unwrap();
|
||||||
|
let output = Command::new(commander_path_str)
|
||||||
|
.arg("flash")
|
||||||
|
.arg(bin_path)
|
||||||
|
.arg("--device")
|
||||||
|
.arg("Cortex-M4")
|
||||||
|
.output()
|
||||||
|
.expect("Failed to execute command");
|
||||||
|
let result_str = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
let result = result_str
|
||||||
|
.split("\r\n")
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
|
println!("{:?}", result);
|
||||||
|
if !result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.trim().starts_with("ERROR"))
|
||||||
|
.collect::<Vec<&&str>>()
|
||||||
|
.is_empty()
|
||||||
|
|| result
|
||||||
|
.iter()
|
||||||
|
.filter(|&&str| str.trim().contains("successfully"))
|
||||||
|
.collect::<Vec<&&str>>()
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
Err(DownloadError::DownloadBootloaderError)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn download_app(&self) -> Result<bool, DownloadError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn download_rail(&self) -> Result<bool, DownloadError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::download_wrapper::DownloadWrapper;
|
||||||
|
use crate::download_wrapper::DownloadType;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_download_wrapper() {
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
println!("{:?}", dw.commander_path);
|
||||||
|
println!("{:?}", dw.bin_path);
|
||||||
|
println!("{:?}", dw.bootloader_name);
|
||||||
|
println!("{:?}", dw.app_name);
|
||||||
|
println!("{:?}", dw.rail_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_check_jlink() {
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
let result = dw.check_jlink();
|
||||||
|
assert_eq!(result.is_ok(), true);
|
||||||
|
println!("ids:{:?}", result.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_check_device() {
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
let result = dw.check_device();
|
||||||
|
assert_eq!(result.is_ok(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_erase_device() {
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
let result = dw.erase();
|
||||||
|
assert_eq!(result.is_ok(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_download_bootloader(){
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
let result = dw.download(DownloadType::Bootloader);
|
||||||
|
assert_eq!(result.is_ok(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_download_app(){
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
let result = dw.download(DownloadType::App);
|
||||||
|
assert_eq!(result.is_ok(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_download_rail(){
|
||||||
|
let dw = DownloadWrapper::new();
|
||||||
|
let result = dw.download(DownloadType::Rail);
|
||||||
|
assert_eq!(result.is_ok(), true);
|
||||||
|
}
|
||||||
|
}
|
269
src/main.rs
269
src/main.rs
@ -1,12 +1,20 @@
|
|||||||
mod download_wrapper;
|
mod download_wrapper;
|
||||||
|
mod mes_service;
|
||||||
|
|
||||||
|
use std::any::Any;
|
||||||
use iced::widget::{button, checkbox, column, container, radio, row, text_editor, text_input};
|
use crossbeam::channel;
|
||||||
use iced::{event, window, Element, Event, Length, Subscription, Task};
|
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 iced::application::Title;
|
||||||
use iced::widget::text_editor::Action::Scroll;
|
use iced::widget::text_editor::Action::Scroll;
|
||||||
use iced::widget::text_editor::Edit;
|
use iced::widget::text_editor::Edit;
|
||||||
|
|
||||||
pub fn main() ->iced::Result {
|
use download_wrapper::DownloadType;
|
||||||
|
use crate::mes_service::MesService;
|
||||||
|
|
||||||
|
pub fn main() -> iced::Result {
|
||||||
iced::application("WisunDownload V0.1", MainWindow::update, MainWindow::view)
|
iced::application("WisunDownload V0.1", MainWindow::update, MainWindow::view)
|
||||||
.subscription(MainWindow::subscription)
|
.subscription(MainWindow::subscription)
|
||||||
.exit_on_close_request(false)
|
.exit_on_close_request(false)
|
||||||
@ -14,29 +22,37 @@ pub fn main() ->iced::Result {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static logs: LazyLock<Arc<Mutex<Vec<String>>>> = LazyLock::new(|| {
|
||||||
|
Arc::new(Mutex::new(Vec::new()))
|
||||||
|
});
|
||||||
|
|
||||||
struct MainWindow {
|
struct MainWindow {
|
||||||
is_online: bool,
|
is_online: bool,
|
||||||
mysql_config: MysqlConfig,
|
mysql_config: MysqlConfig,
|
||||||
selection: Option<DownloadType>,
|
selection: Option<DownloadType>,
|
||||||
label: String,
|
label: String,
|
||||||
log_content: text_editor::Content,
|
log_content: text_editor::Content,
|
||||||
|
sender: Sender<bool>,
|
||||||
|
receiver: crossbeam::channel::Receiver<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MainWindow {
|
impl Default for MainWindow {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self{
|
let (sender, receiver) = crossbeam::channel::unbounded();
|
||||||
is_online: true,
|
Self {
|
||||||
mysql_config: MysqlConfig::default(),
|
is_online: true,
|
||||||
selection: None,
|
mysql_config: MysqlConfig::default(),
|
||||||
label: String::new(),
|
selection: None,
|
||||||
log_content: text_editor::Content::default(),
|
label: String::new(),
|
||||||
|
log_content: text_editor::Content::default(),
|
||||||
}
|
sender,
|
||||||
}
|
receiver
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
struct MysqlConfig{
|
struct MysqlConfig {
|
||||||
ip: String,
|
ip: String,
|
||||||
port: String,
|
port: String,
|
||||||
username: String,
|
username: String,
|
||||||
@ -45,7 +61,7 @@ struct MysqlConfig{
|
|||||||
work_order: String,
|
work_order: String,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message{
|
enum Message {
|
||||||
Start(),
|
Start(),
|
||||||
IpChanged(String),
|
IpChanged(String),
|
||||||
PortChanged(String),
|
PortChanged(String),
|
||||||
@ -59,32 +75,22 @@ enum Message{
|
|||||||
AddLog(String),
|
AddLog(String),
|
||||||
LogContentChanged(text_editor::Action),
|
LogContentChanged(text_editor::Action),
|
||||||
SaveConfig,
|
SaveConfig,
|
||||||
WindowEvent(Event)
|
DownloadEnd(bool),
|
||||||
|
WindowEvent(Event),
|
||||||
|
Tick,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
pub fn add_log<'a>(msg: String) {
|
||||||
enum DownloadType{
|
let time_now = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
|
||||||
BootLoader,
|
let really_msg = format!("{time_now} [Info]: {msg}");
|
||||||
App,
|
logs.lock().unwrap().push(really_msg);
|
||||||
Cal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MainWindow{
|
impl MainWindow {
|
||||||
pub fn add_log(&mut self, msg: String) -> Task<Message>{
|
fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
self.update(Message::AddLog(msg))
|
match message {
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message)-> Task<Message>{
|
|
||||||
match message{
|
|
||||||
Message::Start() => {
|
Message::Start() => {
|
||||||
println!("Start: {:?}", self.mysql_config);
|
self.start(self.sender.clone());
|
||||||
println!("Start: {:?}", self.is_online);
|
|
||||||
println!("Start: {:?}", self.selection);
|
|
||||||
self.add_log(self.label.clone());
|
|
||||||
self.add_log("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string());
|
|
||||||
self.add_log("bbbbbbbbbbbbbbbb".to_string());
|
|
||||||
self.add_log("cccccccccccccccc".to_string());
|
|
||||||
println!("{:?}", self.log_content.text());
|
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::IpChanged(ip) => {
|
Message::IpChanged(ip) => {
|
||||||
@ -95,63 +101,98 @@ impl MainWindow{
|
|||||||
self.mysql_config.port = port;
|
self.mysql_config.port = port;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::UsernameChanged(username)=>{
|
Message::UsernameChanged(username) => {
|
||||||
self.mysql_config.username = username;
|
self.mysql_config.username = username;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::PasswordChanged(password)=>{
|
Message::PasswordChanged(password) => {
|
||||||
self.mysql_config.password = password;
|
self.mysql_config.password = password;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::DatabaseChanged(database)=>{
|
Message::DatabaseChanged(database) => {
|
||||||
self.mysql_config.database = database;
|
self.mysql_config.database = database;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::WorkOrderChanged(work_order)=>{
|
Message::WorkOrderChanged(work_order) => {
|
||||||
self.mysql_config.work_order = work_order;
|
self.mysql_config.work_order = work_order;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::TypeSelected(download_type)=>{
|
Message::TypeSelected(download_type) => {
|
||||||
self.selection = Some(download_type);
|
self.selection = Some(download_type);
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::LabelChanged(label)=>{
|
Message::LabelChanged(label) => {
|
||||||
self.label = label;
|
self.label = label;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::OnlineChecked(is_online)=>{
|
Message::OnlineChecked(is_online) => {
|
||||||
self.is_online = is_online;
|
self.is_online = is_online;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::AddLog(log)=>{
|
Message::AddLog(log) => {
|
||||||
for c in log.chars(){
|
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();
|
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()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::LogContentChanged(action)=>{
|
Message::Tick => {
|
||||||
if action.is_edit(){
|
for log in logs.lock().unwrap().iter() {
|
||||||
return Task::none()
|
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::Enter));
|
||||||
|
let line_size = self.log_content.lines().count();
|
||||||
|
self.log_content.perform(Scroll { lines: line_size as i32 });
|
||||||
}
|
}
|
||||||
self.log_content.perform(action);
|
logs.lock().unwrap().clear();
|
||||||
|
|
||||||
|
match self.receiver.try_recv() {
|
||||||
|
Ok(res) => {
|
||||||
|
self.update(Message::DownloadEnd(res));
|
||||||
|
}
|
||||||
|
Err(channel::TryRecvError::Empty) => {
|
||||||
|
}
|
||||||
|
Err(channel::TryRecvError::Disconnected) => {
|
||||||
|
println!("Disconnected");
|
||||||
|
}
|
||||||
|
};
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::WindowEvent(event) =>{
|
Message::LogContentChanged(action) => {
|
||||||
println!("{:?}", event);
|
match action{
|
||||||
if let Event::Window(window::Event::CloseRequested) = event {
|
Scroll { lines } => {
|
||||||
println!("Request Close");
|
self.log_content.perform(Scroll { lines });
|
||||||
return window::get_latest().and_then(window::close)
|
Task::none()
|
||||||
};
|
}
|
||||||
Task::none()
|
_=>{
|
||||||
}
|
Task::none()
|
||||||
_=>{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::WindowEvent(event) => {
|
||||||
|
//println!("{:?}", event);
|
||||||
|
if let Event::Window(window::Event::CloseRequested) = event {
|
||||||
|
println!("Request Close");
|
||||||
|
return window::get_latest().and_then(window::close);
|
||||||
|
};
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
_ => { Task::none() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<Message>{
|
fn view(&self) -> Element<Message> {
|
||||||
let ip_input = text_input(
|
let ip_input = text_input(
|
||||||
"IP Address",
|
"IP Address",
|
||||||
&self.mysql_config.ip,
|
&self.mysql_config.ip,
|
||||||
@ -162,32 +203,32 @@ impl MainWindow{
|
|||||||
).on_input(Message::PortChanged);
|
).on_input(Message::PortChanged);
|
||||||
let username_input = text_input(
|
let username_input = text_input(
|
||||||
"Username",
|
"Username",
|
||||||
&self.mysql_config.username
|
&self.mysql_config.username,
|
||||||
).on_input(Message::UsernameChanged);
|
).on_input(Message::UsernameChanged);
|
||||||
let password_input = text_input(
|
let password_input = text_input(
|
||||||
"Password",
|
"Password",
|
||||||
&self.mysql_config.password
|
&self.mysql_config.password,
|
||||||
).on_input(Message::PasswordChanged);
|
).on_input(Message::PasswordChanged);
|
||||||
let database_input = text_input(
|
let database_input = text_input(
|
||||||
"Database",
|
"Database",
|
||||||
&self.mysql_config.database
|
&self.mysql_config.database,
|
||||||
).on_input(Message::DatabaseChanged);
|
).on_input(Message::DatabaseChanged);
|
||||||
let work_order_input = text_input(
|
let work_order_input = text_input(
|
||||||
"WorkOrder",
|
"WorkOrder",
|
||||||
&self.mysql_config.work_order
|
&self.mysql_config.work_order,
|
||||||
).on_input(Message::WorkOrderChanged);
|
).on_input(Message::WorkOrderChanged);
|
||||||
let label_input = text_input(
|
let label_input = text_input(
|
||||||
"label",
|
"label",
|
||||||
&self.label
|
&self.label,
|
||||||
).on_input(Message::LabelChanged).on_submit(Message::Start()).width(Length::Fill);
|
).on_input(Message::LabelChanged).on_submit(Message::Start()).width(Length::Fill);
|
||||||
let content = column![
|
let content = column![
|
||||||
row![ip_input, port_input].spacing(5),
|
row![ip_input, port_input].spacing(5),
|
||||||
row![username_input, password_input].spacing(5),
|
row![username_input, password_input].spacing(5),
|
||||||
row![database_input, work_order_input].spacing(5),
|
row![database_input, work_order_input].spacing(5),
|
||||||
row![
|
row![
|
||||||
radio("BootLoader", DownloadType::BootLoader,self.selection,Message::TypeSelected),
|
radio("BootLoader", DownloadType::Bootloader,self.selection,Message::TypeSelected),
|
||||||
radio("App", DownloadType::App,self.selection,Message::TypeSelected),
|
radio("App", DownloadType::App,self.selection,Message::TypeSelected),
|
||||||
radio("Cal", DownloadType::Cal,self.selection,Message::TypeSelected),
|
radio("Cal", DownloadType::Rail,self.selection,Message::TypeSelected),
|
||||||
checkbox("online", self.is_online).on_toggle(Message::OnlineChecked)
|
checkbox("online", self.is_online).on_toggle(Message::OnlineChecked)
|
||||||
].spacing(10),
|
].spacing(10),
|
||||||
row![label_input,button("Start").on_press(Message::Start())].spacing(10),
|
row![label_input,button("Start").on_press(Message::Start())].spacing(10),
|
||||||
@ -199,6 +240,96 @@ impl MainWindow{
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
event::listen().map(Message::WindowEvent)
|
Subscription::batch(vec![
|
||||||
|
event::listen().map(Message::WindowEvent),
|
||||||
|
time::every(time::Duration::from_millis(50))
|
||||||
|
.map(|_| Message::Tick)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(&mut self, sender: Sender<bool>) -> (){
|
||||||
|
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();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let mut download_wrapper = download_wrapper::DownloadWrapper::new();
|
||||||
|
let mut mes_service: MesService;
|
||||||
|
if online {
|
||||||
|
add_log("当前为在线模式, 正在连接数据库".to_string());
|
||||||
|
mes_service = MesService::new(mes_config.ip.clone(), mes_config.port.clone(), mes_config.username.clone(), mes_config.password.clone(), mes_config.database.clone());
|
||||||
|
add_log("连接成功".to_string());
|
||||||
|
add_log("正在过站检测".to_string());
|
||||||
|
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));
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
} else if let Ok(res) = check_result {
|
||||||
|
if !res {
|
||||||
|
add_log("过站检测失败".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("过站检测成功".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_log("正在检查JLink连接".to_string());
|
||||||
|
if let Err(e) = download_wrapper.check_jlink() {
|
||||||
|
add_log("JLink检查失败, 请检查是否安装驱动或连接是否异常".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("JLink检查成功".to_string());
|
||||||
|
add_log("正在检查设备连接".to_string());
|
||||||
|
if let Err(e) = download_wrapper.check_device() {
|
||||||
|
add_log("设备检查失败, 请检查设备是否连接".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("设备检查成功".to_string());
|
||||||
|
match download_type {
|
||||||
|
DownloadType::Bootloader =>{
|
||||||
|
add_log("正在擦除Flash".to_string());
|
||||||
|
if let Err(e) = download_wrapper.erase(){
|
||||||
|
add_log("擦除失败".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("擦除成功".to_string());
|
||||||
|
add_log("正在下载BootLoader".to_string());
|
||||||
|
if let Err(e) = download_wrapper.download(download_type){
|
||||||
|
add_log("下载BootLoader失败".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("下载成功".to_string());
|
||||||
|
}
|
||||||
|
DownloadType::App =>{
|
||||||
|
add_log("正在下载App".to_string());
|
||||||
|
if let Err(e) = download_wrapper.download(download_type){
|
||||||
|
add_log("下载App失败".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("下载成功".to_string());
|
||||||
|
}
|
||||||
|
DownloadType::Rail=>{
|
||||||
|
add_log("正在下载Rail".to_string());
|
||||||
|
if let Err(e) = download_wrapper.download(download_type){
|
||||||
|
add_log("下载Rail失败".to_string());
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
add_log("下载成功".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if online {
|
||||||
|
mes_service = MesService::new(mes_config.ip, mes_config.port, mes_config.username, mes_config.password, mes_config.database);
|
||||||
|
add_log("正在上传数据".to_string());
|
||||||
|
let update_result = mes_service.update_station(mes_config.work_order, label, download_type);
|
||||||
|
if let Err(e) = update_result {
|
||||||
|
add_log(format!("上传失败: {:?}", e));
|
||||||
|
sender.send(false).unwrap();
|
||||||
|
}
|
||||||
|
sender.send(true).unwrap();
|
||||||
|
} else {
|
||||||
|
add_log("当前为离线模式".to_string());
|
||||||
|
sender.send(true).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,12 +2,12 @@ use crate::download_wrapper::DownloadType;
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use mysql::prelude::*;
|
use mysql::prelude::*;
|
||||||
|
|
||||||
struct MesService {
|
pub(crate) struct MesService {
|
||||||
pool: mysql::Pool,
|
pool: mysql::Pool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MesService {
|
impl MesService {
|
||||||
fn new(ip: String, port: String, username: String, password: String, database: String) -> Self {
|
pub fn new(ip: String, port: String, username: String, password: String, database: String) -> Self {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"mysql://{}:{}@{}:{}/{}",
|
"mysql://{}:{}@{}:{}/{}",
|
||||||
username, password, ip, port, database
|
username, password, ip, port, database
|
||||||
@ -16,14 +16,14 @@ impl MesService {
|
|||||||
Self { pool }
|
Self { pool }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_work_orders(&self) -> Result<Vec<String>, Error> {
|
pub fn get_work_orders(&self) -> Result<Vec<String>, Error> {
|
||||||
let mut conn = self.pool.get_conn()?;
|
let mut conn = self.pool.get_conn()?;
|
||||||
let work_orders: Vec<String> =
|
let work_orders: Vec<String> =
|
||||||
conn.query("SELECT `OrderId` FROM wisun_ordertables".to_string())?;
|
conn.query("SELECT `OrderId` FROM wisun_ordertables".to_string())?;
|
||||||
Ok(work_orders)
|
Ok(work_orders)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_station(
|
pub fn check_station(
|
||||||
&self,
|
&self,
|
||||||
work_order: String,
|
work_order: String,
|
||||||
label: String,
|
label: String,
|
||||||
@ -63,7 +63,7 @@ impl MesService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_station(&self, work_order: String, label: String, download_type: DownloadType) -> Result<(), Error> {
|
pub fn update_station(&self, work_order: String, label: String, download_type: DownloadType) -> Result<(), Error> {
|
||||||
match download_type {
|
match download_type {
|
||||||
DownloadType::Bootloader => {
|
DownloadType::Bootloader => {
|
||||||
let mut conn = self.pool.get_conn()?;
|
let mut conn = self.pool.get_conn()?;
|
||||||
|
Loading…
Reference in New Issue
Block a user