Wi-Fi Hotspot UI
This commit is contained in:
+111
-100
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
// Copyright (c) 2022-2024 Robin Davies
|
||||
//
|
||||
// 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
|
||||
@@ -1132,7 +1132,7 @@ static void PrintHelp()
|
||||
PrettyPrinter pp;
|
||||
pp << "pipedalconfig - Command-line post-install configuration for PiPedal"
|
||||
<< "\n"
|
||||
<< "Copyright (c) 2022 Robin Davies. All rights reserved."
|
||||
<< "Copyright (c) 2022-2024 Robin Davies."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "See https://rerdavies.github.io/pipedal/Documentation.html for "
|
||||
@@ -1157,10 +1157,10 @@ static void PrintHelp()
|
||||
<< "\n"
|
||||
|
||||
<< HangingIndent() << " --install [--port <port#>]\t"
|
||||
<< "Install or re-install services and service accounts."
|
||||
<< "Install or re-install PiPedal services and service accounts."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "The --port option controls which port the web server uses."
|
||||
<< "The --port option controls which TCP/IP port the web server uses."
|
||||
<< "\n\n"
|
||||
|
||||
<< HangingIndent() << " --uninstall\t"
|
||||
@@ -1169,68 +1169,54 @@ static void PrintHelp()
|
||||
<< "\n"
|
||||
|
||||
<< HangingIndent() << " --enable\t"
|
||||
<< "Start the pipedal service at boot time."
|
||||
<< "Start PiPedal services at boot time."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
|
||||
<< HangingIndent() << " --disable\tDo not start the pipedal service at boot time."
|
||||
<< HangingIndent() << " --disable\tDo not start PiPedal services at boot time."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< HangingIndent() << " --start\tStart the pipedal services."
|
||||
<< HangingIndent() << " --start\tStart PiPedal services."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< HangingIndent() << " --stop\tStop the pipedal services."
|
||||
<< HangingIndent() << " --stop\tStop PiPedal services."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< HangingIndent() << " --restart\tRestart the pipedal services."
|
||||
<< HangingIndent() << " --restart\tRestart PiPedal services."
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
|
||||
<< HangingIndent() << " --enable-p2p [<country_code> <ssid> [[<pin>] <channel>] ]\t"
|
||||
<< "Enable the P2P (Wi-Fi Direct) hotspot."
|
||||
<< HangingIndent() << " --enable-hotspot\t <country_code> <ssid> <wep_password> <channel> [<hotspot-option>]"
|
||||
<< "\n\nEnable Wi-Fi hotspot."
|
||||
<< "\n\n"
|
||||
<< "With no additional arguments, the P2P channel is enabled with most-recent settings."
|
||||
<< "PiPedal's Wi-Fi hotspot allows you to connect to your Raspberry Pi when you don't have a Wi-Fi router, for example, when you are "
|
||||
<< "performing away from home. It is most particularly useful when using the PiPedal Android client. Consult PiPedal's online documentation "
|
||||
<< "for guidance on configuring a Wi-Fi hotspot."
|
||||
<< "\n\n"
|
||||
<< "<country_code> is the 2-letter ISO-3166 country code for "
|
||||
"the country you are in. see below for further notes."
|
||||
<< "One of the following hotspot options can be specifed. If no hotspot option is given, the hotspot will always be enabled. "
|
||||
<< "If one of the hotspot options are given, the PiPedal server will turn the hotspot on or off automatically, as conditions change."
|
||||
<< "\n\n"
|
||||
<< "--home-network <wifi-ssid>\n"
|
||||
<< AddIndent(4) << "Hotspot is disabled if the specificed Wi-Fi network is detected.\n"
|
||||
<< AddIndent(-4)
|
||||
<< "--no-ethernet\n"
|
||||
<< AddIndent(4) << "Hotspot is disabled if an ethernet network is connected.\n"
|
||||
<< AddIndent(-4)
|
||||
<< "--no-wifi\n"
|
||||
<< AddIndent(4) << "Hotspot is disabled if a remembered Wi-Fi network is detected.\n"
|
||||
<< AddIndent(-4)
|
||||
<< "\n"
|
||||
<< "Caution: Wi-Fi connections are disabled when the hotspot is activated. If you currently access your Raspberry Pi using "
|
||||
<< "Wi-Fi, choose your hotspot options carefully, to ensure that you can still access your Raspberry Pi."
|
||||
<< "\n\n"
|
||||
<< "<ssid> is the name you see when connecting. "
|
||||
<< "country_code is the 2-letter ISO-3166 country code for "
|
||||
<< "the country you are in. see below for further notes."
|
||||
<< "\n\n"
|
||||
<< "<pin> is an exactly-eight-digit pin number that you must "
|
||||
<< "enter when connecting to the hotspot. If you don't "
|
||||
<< "provide a pin, pipedalconfig will generate and "
|
||||
<< "display a random pin for you. The pin is a "
|
||||
<< "so-called \"label\" pin, which is the same every "
|
||||
<< "time you are asked to enter it (unlike a keypad pin "
|
||||
<< "which changes every time you need to enter it."
|
||||
<< "\n\n"
|
||||
<< "Consider attaching a label to the bottom of your device "
|
||||
<< "so you can can remember the pin if you wan't to connect a new "
|
||||
<< "device to PiPedal. (It's also available on the Settings page of PiPedal, if you have access to PiPedal UI on another device.)"
|
||||
<< "\n\n"
|
||||
<< "For best performance, the channel number should be 1, 6, or 11 (the Wifi Direct \"social\" channels). "
|
||||
<< "Channel number defaults to 1."
|
||||
<< "If the Wi-Fi channel is not specified, a Wi-Fi channel will be automatically selected."
|
||||
<< "\n\n"
|
||||
|
||||
<< HangingIndent() << " --disable-p2p\tDisable Wi-Fi Direct access."
|
||||
<< HangingIndent() << " --disable-hotspot\tDisabled the Wi-Fi hotspot."
|
||||
<< "\n\n"
|
||||
|
||||
<< HangingIndent() << " --list-p2p-channels [<country_code>] \tList valid p2p channels for the current/specified country."
|
||||
<< "\n\n"
|
||||
|
||||
// << HangingIndent() << " --enable-legacy-ap\t <country_code> <ssid> <wep_password> <channel>\tEnable a legacy Wi-Fi access point."
|
||||
// << "\n\n"
|
||||
// << "Enable a legacy Wi-Fi access point. \n\n"
|
||||
// << "country_code is the 2-letter ISO-3166 country code for "
|
||||
// << "the country you are in. see below for further notes."
|
||||
// << "\n\n"
|
||||
// << "See below for an explanation of when you might want to use a legacy Wi-Fi access point instead of Wifi-Direct access."
|
||||
// << "an explanation of when you might want to use a legacy Access Point instead of "
|
||||
// << "a P2P (Wi-Fi Direct) connection. Generally, you should prefer a P2p connection "
|
||||
// << "to an ordinary Hotspot connection."
|
||||
// << "\n\n"
|
||||
|
||||
<< HangingIndent() << " --disable-legacy-ap\tDisabled the legacy Wi-Fi access point."
|
||||
<< HangingIndent() << " --list-wifi-channels [<country_code>] \tList valid Wifi channels for the current/specified country."
|
||||
<< "\n\n"
|
||||
|
||||
<< Indent(0) << "Country codes:"
|
||||
@@ -1244,28 +1230,11 @@ static void PrintHelp()
|
||||
<< "with reduced amplitude and feature sets."
|
||||
<< "\n\n"
|
||||
<< "For the most part, Wi-Fi country codes are taken from the list of ISO 3661 "
|
||||
<< "2-letter country codes; although there are a handful of exceptions for small "
|
||||
<< "2-letter country codes; although there are a handful of exceptions for small "
|
||||
<< "countries and islands. See the Alpha-2 code column of "
|
||||
<< "\n\n"
|
||||
<< Indent(8) << "https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes."
|
||||
<< "\n\n"
|
||||
|
||||
<< Indent(0) << "Legacy Wi-Fi Access Points:"
|
||||
<< "\n\n"
|
||||
<< Indent(4)
|
||||
<< "Some older devices may not be able to connect to PiPedal using Wi-Fi Direct connections. "
|
||||
"Old Apple devices, for example, do not support Wi-Fi Direct. In theory, Wi-Fi Direct should "
|
||||
"allow legacy Wi-Fi devices to connect to a Wi-Fi Direct access points as if it were an "
|
||||
"ordinary Access Point. If this turns out "
|
||||
"not to be the case, you can configure PiPedal to provide a legacy Wi-Fi access point instead. "
|
||||
"\n\n"
|
||||
"Unlike Wi-Fi Direct connections, legacy Access Points will prevent both the connecting device "
|
||||
"and the PiPedal host machine from connecting to the Internet over a simultanous Wi-Fi connection Access "
|
||||
"Point. On a connecting Android device, you won't be able to use the data connection either when a legacy "
|
||||
"Wi-Fi connection is active."
|
||||
"\n\n"
|
||||
"Wi-Fi Direct connections are "
|
||||
"therefore preferrable under almost all circumstances.\n\n";
|
||||
<< "\n\n";
|
||||
}
|
||||
|
||||
static int ListP2PChannels(const std::vector<std::string> &arguments)
|
||||
@@ -1315,7 +1284,7 @@ int main(int argc, char **argv)
|
||||
bool helpError = false;
|
||||
bool stop = false, start = false;
|
||||
bool enable = false, disable = false, restart = false;
|
||||
bool enable_ap = false, disable_ap = false;
|
||||
bool enable_hotspot = false, disable_hotspot = false;
|
||||
bool enable_p2p = false, disable_p2p = false;
|
||||
bool list_p2p_channels = false;
|
||||
bool get_current_port = false;
|
||||
@@ -1324,6 +1293,9 @@ int main(int argc, char **argv)
|
||||
bool excludeShutdownService = false;
|
||||
std::string prefixOption;
|
||||
std::string portOption;
|
||||
std::string homeNetwork;
|
||||
bool noEthernet = false;
|
||||
bool noWifi = false;
|
||||
|
||||
parser.AddOption("--nosudo", &nosudo); // strictly a debugging aid. Run without sudo, until we fail because of permissions.
|
||||
parser.AddOption("--install", &install);
|
||||
@@ -1337,22 +1309,17 @@ int main(int argc, char **argv)
|
||||
parser.AddOption("--help", &help);
|
||||
parser.AddOption("--prefix", &prefixOption);
|
||||
parser.AddOption("--port", &portOption);
|
||||
// parser.AddOption("--enable-legacy-ap", &enable_ap);
|
||||
parser.AddOption("--disable-ap", &disable_ap);
|
||||
parser.AddOption("--enable-p2p", &enable_p2p);
|
||||
parser.AddOption("--disable-p2p", &disable_p2p);
|
||||
parser.AddOption("--list-p2p-channels", &list_p2p_channels);
|
||||
parser.AddOption("--fix-permissions", &fix_permissions);
|
||||
|
||||
parser.AddOption("--get-current-port", &get_current_port); // private. For debug use only.
|
||||
|
||||
parser.AddOption("--excludeShutdownService", &excludeShutdownService); // private (unstable) option used by shutdown service.
|
||||
parser.AddOption("--enable-hotspot", &enable_hotspot);
|
||||
parser.AddOption("--disable-hotspot", &disable_hotspot);
|
||||
parser.AddOption("--home-network",&homeNetwork);
|
||||
parser.AddOption("--no-ethernet",&noEthernet);
|
||||
parser.AddOption("--no-wifi",&noWifi);
|
||||
try
|
||||
{
|
||||
parser.Parse(argc, (const char **)argv);
|
||||
|
||||
int actionCount =
|
||||
help + get_current_port + install + uninstall + stop + start + enable + disable + enable_ap + disable_ap + restart + enable_p2p + disable_p2p + list_p2p_channels + fix_permissions;
|
||||
help + get_current_port + install + uninstall + stop + start + enable + disable + enable_hotspot + disable_hotspot + restart + enable_p2p + disable_p2p + list_p2p_channels + fix_permissions;
|
||||
if (actionCount > 1)
|
||||
{
|
||||
throw std::runtime_error("Please provide only one action.");
|
||||
@@ -1366,7 +1333,7 @@ int main(int argc, char **argv)
|
||||
|
||||
throw std::runtime_error("No action provided.");
|
||||
}
|
||||
if ((!enable_p2p) && (!enable_ap) && (!list_p2p_channels))
|
||||
if ((!enable_p2p) && (!enable_hotspot) && (!list_p2p_channels))
|
||||
{
|
||||
if (parser.Arguments().size() != 0)
|
||||
{
|
||||
@@ -1374,6 +1341,23 @@ int main(int argc, char **argv)
|
||||
helpError = true;
|
||||
}
|
||||
}
|
||||
int hotspotOptionCount =
|
||||
(homeNetwork.length() != 0 ? 1: 0)
|
||||
+ noEthernet
|
||||
+ noWifi;
|
||||
|
||||
if (enable_hotspot)
|
||||
{
|
||||
if (hotspotOptionCount > 1)
|
||||
{
|
||||
throw std::runtime_error("Only one hotspot option at a time can be specified.");
|
||||
}
|
||||
} else {
|
||||
if (hotspotOptionCount > 0)
|
||||
{
|
||||
throw std::runtime_error("Hotspot options only only valid when the --enable-hotspot option has been supplied.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -1383,7 +1367,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (helpError)
|
||||
{
|
||||
cout << "\n";
|
||||
cout << endl;
|
||||
return EXIT_FAILURE; // don't scroll the error off the screen.
|
||||
}
|
||||
|
||||
@@ -1483,21 +1467,23 @@ int main(int argc, char **argv)
|
||||
}
|
||||
else if (enable_p2p)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto argv = parser.Arguments();
|
||||
WifiDirectConfigSettings settings;
|
||||
settings.ParseArguments(argv);
|
||||
settings.valid_ = true;
|
||||
settings.enable_ = true;
|
||||
SetWifiDirectConfig(settings);
|
||||
RestartService(true); // also have to retart web service so that it gets the correct device name.
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
cout << "ERROR: " << e.what() << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
cout << "ERROR: Wi-Fi p2p connections are no longer supported. Use hotspots instead." << endl;
|
||||
return EXIT_FAILURE;
|
||||
// try
|
||||
// {
|
||||
// auto argv = parser.Arguments();
|
||||
// WifiDirectConfigSettings settings;
|
||||
// settings.ParseArguments(argv);
|
||||
// settings.valid_ = true;
|
||||
// settings.enable_ = true;
|
||||
// SetWifiDirectConfig(settings);
|
||||
// RestartService(true); // also have to retart web service so that it gets the correct device name.
|
||||
// }
|
||||
// catch (const std::exception &e)
|
||||
// {
|
||||
// cout << "ERROR: " << e.what() << endl;
|
||||
// return EXIT_FAILURE;
|
||||
// }
|
||||
}
|
||||
else if (disable_p2p)
|
||||
{
|
||||
@@ -1508,20 +1494,45 @@ int main(int argc, char **argv)
|
||||
RestartService(true);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else if (enable_ap)
|
||||
else if (enable_hotspot)
|
||||
{
|
||||
auto argv = parser.Arguments();
|
||||
WifiConfigSettings settings;
|
||||
settings.ParseArguments(argv);
|
||||
|
||||
HotspotAutoStartMode startMode = HotspotAutoStartMode::Always;
|
||||
if (homeNetwork.length() != 0)
|
||||
{
|
||||
startMode = HotspotAutoStartMode::NotAtHome;
|
||||
} else if (noEthernet)
|
||||
{
|
||||
startMode = HotspotAutoStartMode::NoEthernetConnection;
|
||||
} else if (noWifi)
|
||||
{
|
||||
startMode = HotspotAutoStartMode::NoRememberedWifiConections;
|
||||
}
|
||||
|
||||
settings.ParseArguments(argv,startMode,homeNetwork);
|
||||
|
||||
if (settings.hasPassword_)
|
||||
{
|
||||
settings.hasSavedPassword_ = true;
|
||||
}
|
||||
SetWifiConfig(settings);
|
||||
if (silentSysExec(SYSTEMCTL_BIN " restart " PIPEDALD_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Failed to restart the " PIPEDALD_SERVICE " service.");
|
||||
}
|
||||
}
|
||||
else if (disable_ap)
|
||||
else if (disable_hotspot)
|
||||
{
|
||||
WifiConfigSettings settings;
|
||||
settings.valid_ = true;
|
||||
settings.enable_ = false;
|
||||
settings.autoStartMode_ = (uint16_t)HotspotAutoStartMode::Never;
|
||||
SetWifiConfig(settings);
|
||||
if (silentSysExec(SYSTEMCTL_BIN " restart " PIPEDALD_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Failed to restart the " PIPEDALD_SERVICE " service.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
|
||||
+159
-23
@@ -29,6 +29,7 @@
|
||||
#include "ServiceConfiguration.hpp"
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace pipedal;
|
||||
using namespace dbus::networkmanager;
|
||||
@@ -51,6 +52,8 @@ namespace pipedal::impl
|
||||
virtual void Reload() override;
|
||||
virtual void Close() override;
|
||||
|
||||
std::vector<std::string> GetKnownWifiNetworks();
|
||||
|
||||
virtual PostHandle Post(PostCallback&&fn) override;
|
||||
virtual PostHandle PostDelayed(const clock::duration&delay,PostCallback&&fn) override;
|
||||
virtual bool CancelPost(PostHandle handle) override;
|
||||
@@ -97,8 +100,14 @@ namespace pipedal::impl
|
||||
void ReleaseNetworkManager();
|
||||
void OnEthernetStateChanged(uint32_t state);
|
||||
void OnWlanStateChanged(uint32_t state);
|
||||
std::vector<ssid_t> GetAutoConnectSsids();
|
||||
std::vector<ssid_t> GetKnownVisibleAccessPoints();
|
||||
std::vector<AccessPoint::ptr> GetAllAccessPoints();
|
||||
std::vector<ssid_t> GetAllAutoConnectSsids();
|
||||
std::vector<ssid_t> GetKnownVisibleAccessPoints(const std::vector<ssid_t> &allAccessPoints);
|
||||
|
||||
void UpdateKnownNetworks(
|
||||
std::vector<ssid_t> &knownSsids,
|
||||
std::vector<AccessPoint::ptr> &allAccessPoints
|
||||
);
|
||||
|
||||
void FireNetworkChanging();
|
||||
|
||||
@@ -126,9 +135,11 @@ namespace pipedal::impl
|
||||
std::recursive_mutex networkChangingListenerMutex;
|
||||
NetworkChangingListener networkChangingListener;
|
||||
|
||||
std::mutex knownWifiNetworksMutex;
|
||||
std::vector<std::string> knownWifiNetworks;
|
||||
|
||||
bool ethernetConnected = true;
|
||||
bool wlanConnected = true;
|
||||
bool isAutoWlanConnectionVisible = true;
|
||||
|
||||
DBusEventHandle onDeviceAddedHandle = INVALID_DBUS_EVENT_HANDLE;
|
||||
DBusEventHandle onDeviceRemovedHandle = INVALID_DBUS_EVENT_HANDLE;
|
||||
@@ -190,7 +201,7 @@ void HotspotManagerImpl::onInitialize()
|
||||
{
|
||||
wifiConfigSettings.Load();
|
||||
|
||||
if (wifiConfigSettings.valid_ && wifiConfigSettings.enable_)
|
||||
if (wifiConfigSettings.valid_ && wifiConfigSettings.IsEnabled())
|
||||
{
|
||||
onStartMonitoring();
|
||||
}
|
||||
@@ -445,7 +456,7 @@ void HotspotManagerImpl::onReload()
|
||||
// ignore.
|
||||
return;
|
||||
case State::Disabled:
|
||||
if (wifiConfigSettings.valid_ && wifiConfigSettings.enable_)
|
||||
if (wifiConfigSettings.valid_ && wifiConfigSettings.IsEnabled())
|
||||
{
|
||||
onStartMonitoring();
|
||||
}
|
||||
@@ -487,6 +498,8 @@ void HotspotManagerImpl::Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
HotspotManager::ptr HotspotManager::Create()
|
||||
{
|
||||
return std::make_unique<HotspotManagerImpl>();
|
||||
@@ -508,37 +521,134 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static std::string ssidToString(const std::vector<uint8_t> &ssid)
|
||||
|
||||
struct NetworkSortRecord {
|
||||
std::string ssid;
|
||||
bool connected = false;
|
||||
bool knownNetwork = false;
|
||||
bool visibleNetwork = false;
|
||||
uint8_t strength;
|
||||
};
|
||||
void HotspotManagerImpl::UpdateKnownNetworks(
|
||||
std::vector<ssid_t> &knownSsids,
|
||||
std::vector<AccessPoint::ptr> & allAccessPoints
|
||||
)
|
||||
{
|
||||
std::stringstream s;
|
||||
for (auto v: ssid)
|
||||
std::map<std::string,NetworkSortRecord> map;
|
||||
|
||||
for (auto &knownSsid: knownSsids)
|
||||
{
|
||||
if (v == 0) break; // breaks for some arguably legal ssids, but I can live with that.
|
||||
s << (char)v;
|
||||
std::string ssid = ssidToString(knownSsid);
|
||||
if (ssid.length() != 0)
|
||||
{
|
||||
NetworkSortRecord &record = map[ssid];
|
||||
record.ssid = ssid;
|
||||
record.knownNetwork = true;
|
||||
}
|
||||
}
|
||||
return s.str();
|
||||
for (auto&accessPoint: allAccessPoints)
|
||||
{
|
||||
uint8_t strength = accessPoint->Strength();
|
||||
auto vSsid = accessPoint->Ssid();
|
||||
std::string ssid = ssidToString(vSsid);
|
||||
if (ssid.length() != 0)
|
||||
{
|
||||
NetworkSortRecord&record = map[ssid];
|
||||
record.ssid = ssid;
|
||||
record.visibleNetwork = true;
|
||||
record.strength = strength;
|
||||
}
|
||||
}
|
||||
if (this->wlanDevice)
|
||||
{
|
||||
auto activeConnectionPath = this->wlanDevice->ActiveConnection();
|
||||
if (activeConnectionPath.length() > 2) // "/" -> no connection. Be paranoid about "".
|
||||
{
|
||||
auto activeConnection = ActiveConnection::Create(dbusDispatcher,activeConnectionPath);
|
||||
std::string activeSsid = activeConnection->Id();
|
||||
auto it = map.find(activeSsid);
|
||||
if (it != map.end())
|
||||
{
|
||||
it->second.connected = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
std::vector<NetworkSortRecord> records;
|
||||
records.reserve(map.size());
|
||||
for (auto & mapEntry: map)
|
||||
{
|
||||
records.push_back(mapEntry.second);
|
||||
}
|
||||
std::sort(records.begin(),records.end(), [](const NetworkSortRecord&left, const NetworkSortRecord &right)
|
||||
{
|
||||
if (left.connected != right.connected)
|
||||
{
|
||||
return left.connected > right.connected;
|
||||
}
|
||||
if (left.knownNetwork != right.knownNetwork)
|
||||
{
|
||||
return left.knownNetwork > right.knownNetwork;
|
||||
}
|
||||
if (left.visibleNetwork != right.visibleNetwork)
|
||||
{
|
||||
return left.visibleNetwork > right.visibleNetwork;
|
||||
}
|
||||
if (left.strength != right.strength)
|
||||
{
|
||||
return left.strength > right.strength;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (records.size() > 10)
|
||||
{
|
||||
records.resize(10);
|
||||
}
|
||||
std::vector<std::string> result;
|
||||
result.reserve(records.size());
|
||||
for (auto &record: records)
|
||||
{
|
||||
result.push_back(std::move(record.ssid));
|
||||
}
|
||||
{
|
||||
std::lock_guard lock { this->knownWifiNetworksMutex };
|
||||
this->knownWifiNetworks = std::move(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::vector<uint8_t>> HotspotManagerImpl::GetKnownVisibleAccessPoints()
|
||||
|
||||
std::vector<AccessPoint::ptr> HotspotManagerImpl::GetAllAccessPoints() {
|
||||
std::vector<AccessPoint::ptr> accessPoints;
|
||||
|
||||
for (const auto &accessPointPath : wlanWirelessDevice->AccessPoints())
|
||||
{
|
||||
auto accessPoint = AccessPoint::Create(dbusDispatcher, accessPointPath);
|
||||
accessPoints.push_back(std::move(accessPoint));
|
||||
}
|
||||
return accessPoints;
|
||||
|
||||
}
|
||||
std::vector<std::vector<uint8_t>> HotspotManagerImpl::GetKnownVisibleAccessPoints(const std::vector<ssid_t>&allAccessPoints)
|
||||
{
|
||||
std::vector<std::vector<uint8_t>> knownSsids = this->GetAutoConnectSsids();
|
||||
std::vector<std::vector<uint8_t>> knownSsids = this->GetAllAutoConnectSsids();
|
||||
|
||||
std::unordered_set<std::vector<uint8_t>, VectorHash<uint8_t>> index{knownSsids.begin(), knownSsids.end()};
|
||||
|
||||
std::vector<ssid_t> result;
|
||||
for (const auto &accessPointPath : wlanWirelessDevice->AccessPoints())
|
||||
std::vector<AccessPoint::ptr> accessPoints;
|
||||
|
||||
for (const auto &accessPoint : allAccessPoints)
|
||||
{
|
||||
auto accessPoint = AccessPoint::Create(dbusDispatcher, accessPointPath);
|
||||
auto ssid = accessPoint->Ssid();
|
||||
if (index.contains(ssid))
|
||||
if (index.contains(accessPoint))
|
||||
{
|
||||
result.push_back(ssid);
|
||||
result.push_back(accessPoint);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::vector<uint8_t>> HotspotManagerImpl::GetAutoConnectSsids()
|
||||
std::vector<std::vector<uint8_t>> HotspotManagerImpl::GetAllAutoConnectSsids()
|
||||
{
|
||||
auto availableConnections = wlanDevice->AvailableConnections();
|
||||
std::vector<std::vector<uint8_t>> ssids;
|
||||
@@ -599,13 +709,31 @@ void HotspotManagerImpl::onAccessPointChanged()
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::vector<uint8_t>> GetAccessPointSsids(std::vector<AccessPoint::ptr>&accessPoints)
|
||||
{
|
||||
std::vector<std::vector<uint8_t>> result;
|
||||
for (const auto&accessPoint: accessPoints)
|
||||
{
|
||||
try {
|
||||
result.push_back(accessPoint->Ssid());
|
||||
} catch (const std::exception&ignored)
|
||||
{
|
||||
// race to get a disappearing ssid. Ignore the error.
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void HotspotManagerImpl::MaybeStartHotspot()
|
||||
{
|
||||
std::vector<std::vector<uint8_t>> connectableSsids = GetKnownVisibleAccessPoints(); // all the ssids currently visible for which we have credentials.
|
||||
bool wantsHotspot = this->wifiConfigSettings.WantsHotspot(
|
||||
this->ethernetConnected,connectableSsids);
|
||||
std::vector<AccessPoint::ptr> allAccessPoints = GetAllAccessPoints();
|
||||
std::vector<std::vector<uint8_t>> allAccessPointSsids = GetAccessPointSsids(allAccessPoints);
|
||||
std::vector<std::vector<uint8_t>> connectableSsids = GetKnownVisibleAccessPoints(allAccessPointSsids); // all the ssids currently visible for which we have credentials.
|
||||
|
||||
this->UpdateKnownNetworks(connectableSsids,allAccessPoints);
|
||||
|
||||
this->isAutoWlanConnectionVisible = connectableSsids.size() != 0;
|
||||
bool wantsHotspot = this->wifiConfigSettings.WantsHotspot(
|
||||
|
||||
this->ethernetConnected,connectableSsids,allAccessPointSsids);
|
||||
|
||||
if (this->state == State::Monitoring && wantsHotspot)
|
||||
{
|
||||
@@ -849,3 +977,11 @@ void HotspotManagerImpl::FireNetworkChanging() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::string> HotspotManagerImpl::GetKnownWifiNetworks()
|
||||
{
|
||||
std::lock_guard lock(knownWifiNetworksMutex); // pushed off the service thread.
|
||||
return this->knownWifiNetworks;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace pipedal {
|
||||
HotspotManager(HotspotManager&&) = delete;
|
||||
HotspotManager & operator=(const HotspotManager&) = delete;
|
||||
HotspotManager & operator=(const HotspotManager&&) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
HotspotManager() {} // use Create().
|
||||
@@ -47,6 +46,9 @@ namespace pipedal {
|
||||
virtual void Reload() = 0;
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual std::vector<std::string> GetKnownWifiNetworks() = 0;
|
||||
|
||||
|
||||
using NetworkChangingListener = std::function<void(bool ethernetConnected,bool hotspotEnabled)>;
|
||||
|
||||
virtual void SetNetworkChangingListener(NetworkChangingListener &&listener) = 0;
|
||||
|
||||
+16
-1
@@ -91,7 +91,7 @@ PiPedalModel::PiPedalModel()
|
||||
OnNetworkChanging(ethernetConnected,hotspotEnabling);
|
||||
}
|
||||
);
|
||||
hotspotManager->Open();
|
||||
// don't actuall start the hotspotManager until after LV2 is initialized (in order to avoid logging oddities)
|
||||
}
|
||||
|
||||
void PiPedalModel::Close()
|
||||
@@ -2241,6 +2241,11 @@ static bool HasAlsaDevice(const std::vector<AlsaDeviceInfo> devices, const std::
|
||||
return false;
|
||||
}
|
||||
|
||||
void PiPedalModel::StartHotspotMonitoring()
|
||||
{
|
||||
this->hotspotManager->Open();
|
||||
}
|
||||
|
||||
void PiPedalModel::WaitForAudioDeviceToComeOnline()
|
||||
{
|
||||
auto serverSettings = this->GetJackServerSettings();
|
||||
@@ -2324,6 +2329,16 @@ void PiPedalModel::CancelNetworkChangingTimer()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> PiPedalModel::GetKnownWifiNetworks()
|
||||
{
|
||||
if (!this->hotspotManager)
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
return this->hotspotManager->GetKnownWifiNetworks();
|
||||
}
|
||||
|
||||
void PiPedalModel::OnNetworkChanging(bool ethernetConnected,bool hotspotConnected)
|
||||
{
|
||||
CancelNetworkChangingTimer();
|
||||
|
||||
@@ -245,6 +245,8 @@ namespace pipedal
|
||||
networkChangedListener = listener;
|
||||
}
|
||||
|
||||
void StartHotspotMonitoring();
|
||||
|
||||
void WaitForAudioDeviceToComeOnline();
|
||||
|
||||
UpdateStatus GetUpdateStatus();
|
||||
@@ -333,6 +335,7 @@ namespace pipedal
|
||||
|
||||
void SetWifiConfigSettings(const WifiConfigSettings &wifiConfigSettings);
|
||||
WifiConfigSettings GetWifiConfigSettings();
|
||||
std::vector<std::string> GetKnownWifiNetworks();
|
||||
|
||||
void SetWifiDirectConfigSettings(const WifiDirectConfigSettings &wifiConfigSettings);
|
||||
WifiDirectConfigSettings GetWifiDirectConfigSettings();
|
||||
|
||||
@@ -1025,6 +1025,12 @@ public:
|
||||
std::vector<AlsaDeviceInfo> devices = model.GetAlsaDevices();
|
||||
this->Reply(replyTo, "getAlsaDevices", devices);
|
||||
}
|
||||
else if (message == "getKnownWifiNetworks")
|
||||
{
|
||||
std::vector<std::string> channels = this->model.GetKnownWifiNetworks();
|
||||
this->Reply(replyTo, "getWifiChannels", channels);
|
||||
|
||||
}
|
||||
else if (message == "getWifiChannels")
|
||||
{
|
||||
std::string country;
|
||||
|
||||
+4
-1
@@ -458,7 +458,10 @@ void PluginHost::Load(const char *lv2Path)
|
||||
|
||||
for (const std::string &s : messages)
|
||||
{
|
||||
Lv2Log::info("lilv: " + s);
|
||||
if (s.length() != 0)
|
||||
{
|
||||
Lv2Log::info("lilv: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
auto collator = Locale::GetInstance()->GetCollator();
|
||||
|
||||
@@ -63,6 +63,11 @@ namespace pipedal
|
||||
this->indent = indent;
|
||||
return *this;
|
||||
}
|
||||
PrettyPrinter&AddIndent(int64_t indent)
|
||||
{
|
||||
this->indent += indent;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void WriteLine() {
|
||||
lineBuffer.push_back('\n');
|
||||
@@ -246,6 +251,15 @@ namespace pipedal
|
||||
return pp;
|
||||
};
|
||||
}
|
||||
pp_manip AddIndent(int n)
|
||||
{
|
||||
return [n] (PrettyPrinter&pp) ->PrettyPrinter& {
|
||||
pp.AddIndent(n);
|
||||
return pp;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
pp_manip HangingIndent()
|
||||
{
|
||||
return [] (PrettyPrinter&pp) ->PrettyPrinter&{
|
||||
|
||||
+8
-1
@@ -961,12 +961,19 @@ bool Storage::SetWifiConfigSettings(const WifiConfigSettings &wifiConfigSettings
|
||||
{
|
||||
copyToSave.hasPassword_ = previousValue.hasPassword_;
|
||||
copyToSave.password_ = previousValue.hasPassword_;
|
||||
copyToSave.hasSavedPassword_ = previousValue.hasPassword_;
|
||||
} else {
|
||||
if (copyToSave.IsEnabled())
|
||||
{
|
||||
copyToSave.hasSavedPassword_ = copyToSave.hasPassword_;
|
||||
}
|
||||
}
|
||||
bool configChanged = wifiConfigSettings.ConfigurationChanged(previousValue);
|
||||
bool configChanged = copyToSave.ConfigurationChanged(previousValue);
|
||||
copyToSave.Save();
|
||||
this->wifiConfigSettings = copyToSave;
|
||||
this->wifiConfigSettings.hasPassword_ = false;
|
||||
this->wifiConfigSettings.password_ = "";
|
||||
|
||||
return configChanged;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -41,6 +41,7 @@
|
||||
#include "WebServer.hpp"
|
||||
|
||||
#include "Uri.hpp"
|
||||
#include "ss.hpp"
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
|
||||
@@ -1194,7 +1195,7 @@ namespace pipedal
|
||||
}
|
||||
catch (websocketpp::exception const &e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
Lv2Log::error(SS("Web server: " << e.what()));
|
||||
}
|
||||
if (this->signalOnDone != -1)
|
||||
{
|
||||
|
||||
@@ -29,19 +29,25 @@ int main(int argc, char**argv)
|
||||
while (true)
|
||||
{
|
||||
std::string line;
|
||||
std::cout << "e=enable,x=disable,q=quit > " << std::endl;;
|
||||
std::cout << "e=no-etthernet,a=always,n=never,q=quit > " << std::endl;;
|
||||
std::getline(std::cin,line);
|
||||
|
||||
if (line == "e")
|
||||
{
|
||||
settings.Load();
|
||||
settings.enable_ = true;
|
||||
settings.autoStartMode_ = (uint16_t)HotspotAutoStartMode::NoEthernetConnection;
|
||||
settings.Save();
|
||||
hotspotManager->Reload();
|
||||
} else if (line == "x")
|
||||
} else if (line == "a")
|
||||
{
|
||||
settings.Load();
|
||||
settings.enable_ = false;
|
||||
settings.autoStartMode_ = (uint16_t)HotspotAutoStartMode::Always;
|
||||
settings.Save();
|
||||
hotspotManager->Reload();
|
||||
} else if (line == "n")
|
||||
{
|
||||
settings.Load();
|
||||
settings.autoStartMode_ = (uint16_t)HotspotAutoStartMode::Never;
|
||||
settings.Save();
|
||||
hotspotManager->Reload();
|
||||
} else if (line == "q") {
|
||||
@@ -53,9 +59,6 @@ int main(int argc, char**argv)
|
||||
hotspotManager->Close();
|
||||
hotspotManager = nullptr;
|
||||
|
||||
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ int main(int argc, char *argv[])
|
||||
(unsigned long)getpid());
|
||||
}
|
||||
|
||||
model.StartHotspotMonitoring();
|
||||
model.WaitForAudioDeviceToComeOnline();
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user