/* 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_wifi_setup.h>
#include <gui_string_dialog.h>
#include <string.h>
GuiWifiSetup::GuiWifiSetup(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);
mNetworkListCtrl = new wxListCtrl(this, ID_LISTBOX_NETWORK, wxDefaultPosition, FromDIP(wxSize(300, 420)), wxLC_SINGLE_SEL | wxLC_LIST | wxLC_VRULES);
main_sizer->Add(new wxStaticText(this, wxID_ANY, wxT("Wireless Network List")), 0, wxBOTTOM | wxEXPAND, BORDER_SIZE);
main_sizer->Add(mNetworkListCtrl, 1, wxEXPAND | wxALL, 0);
main_sizer->SetSizeHints(this);
Centre();
mPowermon.setOnWifiScanReportCallback([this](const Powermon::WifiScanResult* result)
{
if (result)
{
Powermon::WifiScanResult report = *result;
wxQueueEvent(this, new GuiEvent([this, report](const GuiEvent &event)
{
if (std::find(mNetworkList.begin(), mNetworkList.end(), report) == mNetworkList.end())
{
mNetworkList.push_back(report);
char name[33];
memset(name, 0, sizeof(name));
if (report.ssid_length)
{
memcpy(name, report.ssid, report.ssid_length);
char* ptr = name;
for(uint32_t i = 0; i < report.ssid_length; i++)
{
if (isprint(*ptr) == false)
*ptr = '-';
ptr++;
}
}
else
{
strcpy(name, "<unknown>");
}
mNetworkListCtrl->InsertItem(mNetworkListCtrl->GetItemCount(), wxString(name, wxConvUTF8));
mNetworkListCtrl->Refresh();
}
}));
}
});
mTimer = new wxTimer(this, ID_TIMER);
mTimer->Start(1000);
UpdateInfo();
mPowermon.requestStartWifiScan([this](Powermon::ResponseCode status)
{
});
}
GuiWifiSetup::~GuiWifiSetup()
{
}
void GuiWifiSetup::OnClose(wxCloseEvent &event)
{
mPowermon.setOnWifiScanReportCallback([this](const Powermon::WifiScanResult* result){});
mTimer->Stop();
EndModal(wxID_CANCEL);
}
void GuiWifiSetup::OnGuiEvent(GuiEvent &event)
{
event.process();
}
void GuiWifiSetup::OnTimerEvent(wxTimerEvent &event)
{
UpdateInfo();
}
void GuiWifiSetup::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 GuiWifiSetup::OnListNetworkActivated(wxListEvent &event)
{
const int32_t selected = mNetworkListCtrl->GetNextItem(-1, wxLIST_NEXT_BELOW, wxLIST_STATE_SELECTED);
if (selected >= 0)
{
Powermon::WifiScanResult &scan = mNetworkList[selected];
Powermon::WifiNetwork network;
network.ssid_length = scan.ssid_length;
memcpy(network.ssid, scan.ssid, sizeof(network.ssid));
network.flags = Powermon::WifiNetwork::SecurityMode::OPEN;
if (scan.security.wpa2)
network.flags = Powermon::WifiNetwork::SecurityMode::WPA2_PSK;
else if (scan.security.wpa)
network.flags = Powermon::WifiNetwork::SecurityMode::WPA2_WPA1_PSK;
else if (scan.security.wep)
network.flags = Powermon::WifiNetwork::SecurityMode::WEP;
debug_printf("\r\nSelected: %.*s", scan.ssid_length, scan.ssid);
if (network.flags)
{
GuiEnterString dialog(this, wxID_ANY, wxT("Enter password for network"), true, false);
dialog.setMaxStringLength(64);
dialog.setStringLabel(wxT("Network Password"));
if (dialog.ShowModal() != wxID_OK)
return;
network.pass_length = dialog.getString().size();
memcpy(network.pass, dialog.getString().mb_str(), network.pass_length);
debug_printf("\r\nPass: %.*s", network.pass_length, network.pass);
}
mPowermon.requestWifiConfigure(network, [this](Powermon::ResponseCode status)
{
debug_printf("\r\nSET WIFI Status: %X %X", status);
GuiEvent* event = new GuiEvent([this, status](GuiEvent &event)
{
if (status == Powermon::RSP_SUCCESS)
{
}
else
{
}
});
wxQueueEvent(this, event);
});
}
}
BEGIN_EVENT_TABLE(GuiWifiSetup, wxDialog)
EVT_CLOSE(GuiWifiSetup::OnClose)
EVT_LIST_ITEM_ACTIVATED(ID_LISTBOX_NETWORK, GuiWifiSetup::OnListNetworkActivated)
GUI_EVT(GuiWifiSetup::OnGuiEvent)
EVT_TIMER(ID_TIMER, GuiWifiSetup::OnTimerEvent)
END_EVENT_TABLE()