/* Copyright (C) 2020 - 2024, Thornwave Labs Inc * Written by Razvan Turiac <razvan.turiac@thornwave.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the “Software”), to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * Attribution shall be given to Thornwave Labs Inc. and shall be made visible to the final user. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <gui_stats.h> GuiStats::GuiStats(wxWindow *parent, const wxString &title, Powermon &powermon): wxDialog(parent, wxID_ANY, title), mPowermon(powermon) { const size_t BORDER_SIZE = FromDIP(6); mSecondsSinceOnText = new wxStaticText(this, wxID_ANY, wxT("")); mVoltage1MaxText = new wxStaticText(this, wxID_ANY, wxT("")); mVoltage1MinText = new wxStaticText(this, wxID_ANY, wxT("")); mVoltage2MaxText = new wxStaticText(this, wxID_ANY, wxT("")); mVoltage2MinText = new wxStaticText(this, wxID_ANY, wxT("")); mPeakChargeCurrentText = new wxStaticText(this, wxID_ANY, wxT("")); mPeakDischargeCurrentText = new wxStaticText(this, wxID_ANY, wxT("")); mTemperatureMaxText = new wxStaticText(this, wxID_ANY, wxT("")); mTemperatureMinText = new wxStaticText(this, wxID_ANY, wxT("")); mResetButton = new wxButton(this, ID_BUTTON_RESET, wxT("Reset"), wxDefaultPosition, FromDIP(wxSize(110, 40))); mCloseButton = new wxButton(this, wxID_CANCEL, wxT("Close"), wxDefaultPosition, FromDIP(wxSize(110, 40))); //main window sizer wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); SetSizer(main_sizer); wxBoxSizer* h_sizer; h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Time Since Powered On:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mSecondsSinceOnText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Minimum Voltage 1:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mVoltage1MinText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Maximum Voltage 1:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mVoltage1MaxText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Minimum Voltage 2:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mVoltage2MinText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Maximum Voltage 2:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mVoltage2MaxText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Peak Discharge Current:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mPeakDischargeCurrentText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Peak Charge Current:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mPeakChargeCurrentText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Minimum Temperature:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mTemperatureMinText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Maximum Temperature:")), 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); h_sizer->Add(mTemperatureMaxText, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, BORDER_SIZE); h_sizer = new wxBoxSizer(wxHORIZONTAL); h_sizer->Add(mResetButton, 0, wxALIGN_CENTER | wxALL, BORDER_SIZE); h_sizer->Add(mCloseButton, 0, wxALIGN_CENTER | wxALL, BORDER_SIZE); main_sizer->Add(h_sizer, 0, wxALL | wxALIGN_CENTER, BORDER_SIZE); main_sizer->SetSizeHints(this); Centre(); mStatsTimer = new wxTimer(this, ID_STATS_TIMER); } GuiStats::~GuiStats() { delete mStatsTimer; } bool GuiStats::Show(bool show) { if (show) { mStatsTimer->Start(1000); updateStats(); } else { mStatsTimer->Stop(); } return wxDialog::Show(show); } void GuiStats::OnGuiEvent(GuiEvent &event) { event.process(); } void GuiStats::OnButtonResetClicked(wxCommandEvent &event) { wxMessageDialog msg(this, wxT("Reset the power meter statistics ?"), wxT("Confirmation"), wxOK | wxCANCEL | wxICON_QUESTION | wxSTAY_ON_TOP | wxCENTRE); if (msg.ShowModal() == wxID_OK) { mPowermon.requestResetStatistics([this](uint16_t status) { wxQueueEvent(this, new GuiEvent([this, status](const GuiEvent &event) { checkDeviceError(this, status); })); }); } } void GuiStats::OnStatsTimerEvent(wxTimerEvent &event) { updateStats(); } void GuiStats::updateStats(void) { mPowermon.requestGetStatistics([this](uint16_t status, const Powermon::MonitorStatistics &stats) { wxQueueEvent(this, new GuiEvent([this, status, stats](const GuiEvent &event) { if (status == Powermon::RSP_SUCCESS) { wxString str; uint32_t seconds = stats.seconds_since_on; uint32_t days = seconds / (3600 * 24); seconds -= days * 3600 * 24; uint32_t hours = seconds / 3600; seconds -= hours * 3600; uint32_t minutes = seconds / 60; seconds -= minutes * 60; if (days) str.Printf(wxT("%ud %uh %um"), days, hours, minutes); else if (hours) str.Printf(wxT("%uh %um %us"), hours, minutes, seconds); else str.Printf(wxT("%um %us"), minutes, seconds); mSecondsSinceOnText->SetLabel(str); str.Printf(wxT("%6.3f V"), stats.voltage1_min); mVoltage1MinText->SetLabel(str); str.Printf(wxT("%6.3f V"), stats.voltage1_max); mVoltage1MaxText->SetLabel(str); if (!isnan(stats.voltage2_min)) { str.Printf(wxT("%6.3f V"), stats.voltage2_min); mVoltage2MinText->SetLabel(str); } else { mVoltage2MinText->SetLabel(wxT("n/a")); } if (!isnan(stats.voltage2_max)) { str.Printf(wxT("%6.3f V"), stats.voltage2_max); mVoltage2MaxText->SetLabel(str); } else { mVoltage2MaxText->SetLabel(wxT("n/a")); } str.Printf(wxT("%6.2f A"), stats.peak_charge_current); mPeakChargeCurrentText->SetLabel(str); str.Printf(wxT("%6.2f A"), stats.peak_discharge_current); mPeakDischargeCurrentText->SetLabel(str); str.Printf(wxT("%3.0f \u00B0C"), stats.temperature_min); mTemperatureMinText->SetLabel(str); str.Printf(wxT("%3.0f \u00B0C"), stats.temperature_max); mTemperatureMaxText->SetLabel(str); Refresh(); } })); }); } void GuiStats::OnClose(wxCloseEvent &event) { mStatsTimer->Stop(); Hide(); } void GuiStats::OnButtonCloseClicked(wxCommandEvent &event) { Close(); } BEGIN_EVENT_TABLE(GuiStats, wxDialog) EVT_CLOSE(GuiStats::OnClose) GUI_EVT(GuiStats::OnGuiEvent) EVT_BUTTON(wxID_CANCEL, GuiStats::OnButtonCloseClicked) EVT_BUTTON(ID_BUTTON_RESET, GuiStats::OnButtonResetClicked) EVT_TIMER(ID_STATS_TIMER, GuiStats::OnStatsTimerEvent) END_EVENT_TABLE()