gui_pb/drawing/
over_the_air.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use eframe::egui;
use eframe::egui::{Color32, RichText, Ui};
use std::time::Duration;

use crate::App;
use core_pb::messages::ota::{OverTheAirStep, OverTheAirStepCompletion};
use core_pb::messages::{GuiToServerMessage, NetworkStatus};
use core_pb::threaded_websocket::TextOrT;

pub fn draw_over_the_air(app: &mut App, ui: &mut Ui) {
    let name = app.ui_settings.selected_robot;

    ui.label(format!("Upload code to: {name}"));

    if app.server_status.robots[name as usize].connection != NetworkStatus::Connected {
        ui.label(
            RichText::new(format!(
                "{} {name} is not connected",
                egui_phosphor::regular::WARNING
            ))
            .color(Color32::YELLOW),
        );
    }

    ui.separator();

    let current_status = app.server_status.robots[name as usize].ota_current;
    ui.horizontal(|ui| {
        let start_enabled = current_status == OverTheAirStep::GuiRequest
            || current_status == OverTheAirStep::Failed
            || current_status == OverTheAirStep::Finished;
        ui.add_enabled(start_enabled, |ui: &mut Ui| {
            let button = ui.button("Start");
            if button.clicked() {
                app.network
                    .0
                    .send(TextOrT::T(GuiToServerMessage::StartOtaFirmwareUpdate(name)));
            }
            button
        });
        ui.add_enabled(
            current_status == OverTheAirStep::GuiConfirmation
                || current_status == OverTheAirStep::FinalGuiConfirmation,
            |ui: &mut Ui| {
                let button = ui.button("Confirm");
                if button.clicked() {
                    app.network
                        .0
                        .send(TextOrT::T(GuiToServerMessage::ConfirmFirmwareUpdate(name)));
                }
                button
            },
        );
        ui.add_enabled(!start_enabled, |ui: &mut Ui| {
            let button = ui.button("Cancel");
            if button.clicked() {
                app.network
                    .0
                    .send(TextOrT::T(GuiToServerMessage::CancelOtaFirmwareUpdate(
                        name,
                    )));
            }
            button
        });
        if ui.button("Clear").clicked() {
            app.network
                .0
                .send(TextOrT::T(GuiToServerMessage::ClearFirmwareUpdateHistory(
                    name,
                )));
        }
    });

    ui.separator();

    let mut steps = app.server_status.robots[name as usize]
        .ota_completed
        .clone();
    let curr = app.server_status.robots[name as usize].ota_current;
    if steps.last().map(|x| x.step != curr).unwrap_or(true) {
        steps.push(OverTheAirStepCompletion {
            step: curr,
            since_beginning: Duration::from_secs(0),
            success: if curr == OverTheAirStep::Finished {
                Some(true)
            } else if curr == OverTheAirStep::Failed {
                Some(false)
            } else {
                None
            },
        });
    }

    egui::Grid::new("ota_grid").show(ui, |ui| {
        for OverTheAirStepCompletion { step, success, .. } in steps {
            let color = match (step, success) {
                (_, Some(true)) => Color32::GREEN,
                (_, Some(false)) => Color32::RED,
                (_, None) => Color32::YELLOW,
            };
            if success.is_none()
                && step != OverTheAirStep::GuiRequest
                && step != OverTheAirStep::GuiConfirmation
                && step != OverTheAirStep::FinalGuiConfirmation
            {
                ui.spinner();
            } else {
                ui.label(
                    RichText::new(match (step, success) {
                        (_, Some(true)) => egui_phosphor::regular::CHECK,
                        (_, Some(false)) => egui_phosphor::regular::X,
                        (_, None) => egui_phosphor::regular::WARNING,
                    })
                    .color(color),
                );
            }
            ui.label(step.message());
            ui.end_row();

            if success == Some(false) || step == OverTheAirStep::Finished {
                break;
            }
        }
    });
}