Newer
Older
powermon_manager_sw / gui / gui_mult_wifi_setup.cpp
/* Copyright (C) 2020 - 2025, 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_mult_wifi_setup.h>
#include <gui_string_dialog.h>

#include <gui_wifi_add.h>


#include <string.h>


GuiMultipleWifiSetup::GuiMultipleWifiSetup(wxWindow* parent, Powermon &powermon): wxDialog(parent, wxID_ANY, wxT("PowerMon WiFi Setup")), mPowermon(powermon)
{
	const size_t BORDER_SIZE = FromDIP(6);

	wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(main_sizer);

	mNetworkStatic = new wxStaticText(this, wxID_ANY, wxT(""));
	mStatusStatic = new wxStaticText(this, wxID_ANY, wxT(""));

	wxBoxSizer*	h_sizer = new wxBoxSizer(wxHORIZONTAL);	
	h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("WiFi Network: ")), 0, wxALL | wxEXPAND, BORDER_SIZE);
	h_sizer->Add(mNetworkStatic, 0, wxALL | wxEXPAND, BORDER_SIZE);
	main_sizer->Add(h_sizer, 0, wxALL | wxEXPAND, 0);

	h_sizer = new wxBoxSizer(wxHORIZONTAL);
	h_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("WiFi Status: ")), 0, wxALL | wxEXPAND, BORDER_SIZE);
	h_sizer->Add(mStatusStatic, 0, wxALL | wxEXPAND, BORDER_SIZE);
	main_sizer->Add(h_sizer, 0, wxDOWN | wxEXPAND, 20);


	main_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Known WiFi Networks")), 0, wxBOTTOM | wxEXPAND, BORDER_SIZE);
	
	mNetworksListCtrl = new wxListCtrl(this, ID_LISTBOX_NETWORKS, wxDefaultPosition, wxDefaultSize, wxLC_SINGLE_SEL | wxLC_REPORT | wxLC_VRULES);
	main_sizer->Add(mNetworksListCtrl, 0, wxALL | wxEXPAND, 0);

	mNetworksListCtrl->AppendColumn(wxT("Name"), wxLIST_FORMAT_LEFT, FromDIP(120));
	mNetworksListCtrl->AppendColumn(wxT("Properties"), wxLIST_FORMAT_LEFT, FromDIP(300));

	h_sizer = new wxBoxSizer(wxHORIZONTAL);		
	mAddButton = new wxButton(this, ID_BUTTON_ADD, wxT("Add Network"), wxDefaultPosition, FromDIP(wxSize(120, 40)));
	mAddButton->Enable(false);
	h_sizer->Add(mAddButton, 0, wxALL | wxEXPAND, BORDER_SIZE);	
	
	mRemoveButton = new wxButton(this, ID_BUTTON_REMOVE, wxT("Remove Network"), wxDefaultPosition, FromDIP(wxSize(160, 40)));
	mRemoveButton->Enable(false);
	h_sizer->Add(mRemoveButton, 0, wxALL | wxEXPAND, BORDER_SIZE);	
	main_sizer->Add(h_sizer, 0, wxDOWN | wxEXPAND, 20);

	main_sizer->SetSizeHints(this);
	Centre();


	mTimer = new wxTimer(this, ID_TIMER);
	mTimer->Start(500);

	UpdateInfo();
	UpdateNetworkList();
}


GuiMultipleWifiSetup::~GuiMultipleWifiSetup()
{
}


void GuiMultipleWifiSetup::OnClose(wxCloseEvent &event)
{
	mTimer->Stop();
	EndModal(wxID_CANCEL);
}


void GuiMultipleWifiSetup::OnGuiEvent(GuiEvent &event)
{
	event.process();
}


void GuiMultipleWifiSetup::UpdateInfo(void)
{
	mPowermon.requestGetInfo([this](Powermon::ResponseCode status, const Powermon::DeviceInfo &info)
	{
		if (status == Powermon::RSP_SUCCESS)
		{
			debug_printf("\r\nINFO Status: %X", status);
			debug_printf("\r\nSerial: %016lX, Name: %s %X", info.serial, info.name.c_str(), info.flags);

			wxQueueEvent(this, new GuiEvent([this, info](GuiEvent &event)
			{
				char cstr[MAX_WIFI_SSID_SIZE + 1];
				memcpy(cstr, info.ssid, info.ssid_length);
				cstr[info.ssid_length] = 0;
				
				mNetworkStatic->SetLabel(wxString(cstr, wxConvUTF8));

				if (info.isWifiFailed())
				{
					mStatusStatic->SetLabel(wxT("Cannot connect"));
				}
				else if (info.isWifiConnecting())
				{
					mStatusStatic->SetLabel(wxT("Connecting ..."));
				}
				else if (info.isWifiConnected())
				{
					if (info.address)
					{
						wxString str;
						str.Printf(wxT("Connected (%u.%u.%u.%u)"), (info.address >> 0) & 0xFF, 
													(info.address >> 8) & 0xFF, 
													(info.address >> 16) & 0xFF, 
													(info.address >> 24) & 0xFF);
						mStatusStatic->SetLabel(str);
					}
					else
					{
						mStatusStatic->SetLabel(wxT("Connected (obtaining IP ...)"));
					}
				}
				else
				{
					mNetworkStatic->SetLabel(wxT(""));
					mStatusStatic->SetLabel(wxT("Not connected"));
				}

				mNetworkStatic->Refresh();
				mStatusStatic->Refresh();
			}));
		}
	});
}


void GuiMultipleWifiSetup::UpdateNetworkList(void)
{
	mRemoveButton->Enable(false);

	mPowermon.requestGetWifiNetworks([this](Powermon::ResponseCode status, const std::vector<Powermon::WifiNetwork> &networks)
	{
		wxQueueEvent(this, new GuiEvent([this, status, networks](GuiEvent &event)
		{
			if (checkDeviceError(this, status))
			{
				mAddButton->Enable(networks.size() < 5);

				uint32_t index = 0;
				for(const Powermon::WifiNetwork &net: networks)
				{
					std::string ssid(reinterpret_cast<const char*>(net.ssid), net.ssid_length);
					size_t count = mNetworksListCtrl->GetItemCount();

					if (index >= count)
						mNetworksListCtrl->InsertItem(count, wxString(ssid.c_str(), wxConvUTF8));
					else
						mNetworksListCtrl->SetItem(index, 0, wxString(ssid.c_str(), wxConvUTF8));

					wxString str;

					if (net.isPasswordProtected())
						str += wxT("password protected");

					if (!str.IsEmpty())
						str += wxT(", ");

					if (net.isMetered())
						str += wxT("metered");
					else
						str += wxT("non-metered");
						
					if (net.isFailed())
					{
						if (!str.IsEmpty())
							str += wxT(", ");

						str += wxT("FAILED");
					}
						
					mNetworksListCtrl->SetItem(index, 1, str);	
					mNetworksListCtrl->RefreshItem(index);

					index++;
				}

				size_t count = mNetworksListCtrl->GetItemCount();
				while (count > index)
					mNetworksListCtrl->DeleteItem(--count);

				mNetworksListCtrl->SetItemState(-1, 0, wxLIST_STATE_SELECTED);
			}
		}));
	});
}


void GuiMultipleWifiSetup::OnListSelection(wxListEvent &event)
{
	const int32_t selected = mNetworksListCtrl->GetNextItem(-1, wxLIST_NEXT_BELOW, wxLIST_STATE_SELECTED);
	mRemoveButton->Enable(selected >= 0);
}


void GuiMultipleWifiSetup::OnButtonAddClicked(wxCommandEvent &event)
{
	GuiWifiAdd dialog(this, mPowermon);
	dialog.ShowModal();
	UpdateNetworkList();
}


void GuiMultipleWifiSetup::OnButtonRemoveClicked(wxCommandEvent &event)
{
	const int32_t selected = mNetworksListCtrl->GetNextItem(-1, wxLIST_NEXT_BELOW, wxLIST_STATE_SELECTED);
	if (selected >= 0)
	{
		mPowermon.requestRemoveWifiNetwork(selected, [this](Powermon::ResponseCode status)
		{
			debug_printf("\r\nREMOVE WIFI Status: %X", status);

			wxQueueEvent(this, new GuiEvent([this, status](GuiEvent &event)
			{
				if (checkDeviceError(this, status))
					UpdateNetworkList();
			}));
		});
	}
}


void GuiMultipleWifiSetup::OnTimerEvent(wxTimerEvent &event)
{
	UpdateInfo();
}


BEGIN_EVENT_TABLE(GuiMultipleWifiSetup, wxDialog)
EVT_CLOSE(GuiMultipleWifiSetup::OnClose)
EVT_LIST_ITEM_SELECTED(ID_LISTBOX_NETWORKS, GuiMultipleWifiSetup::OnListSelection)
EVT_BUTTON(ID_BUTTON_ADD, GuiMultipleWifiSetup::OnButtonAddClicked)
EVT_BUTTON(ID_BUTTON_REMOVE, GuiMultipleWifiSetup::OnButtonRemoveClicked)
EVT_TIMER(ID_TIMER, GuiMultipleWifiSetup::OnTimerEvent)
GUI_EVT(GuiMultipleWifiSetup::OnGuiEvent)
END_EVENT_TABLE()