/* 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);
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(sizer, 0, wxALL | wxALIGN_CENTER, 20);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
sizer->Add(h_sizer, 0, wxALL | wxALIGN_LEFT, 0);
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);
SetSizer(main_sizer);
main_sizer->SetSizeHints(this);
Fit();
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](Powermon::ResponseCode 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](Powermon::ResponseCode 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();
Fit();
}
}));
});
}
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()