- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
708 lines
25 KiB
C++
708 lines
25 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright Pionix GmbH and Contributors to EVerest
|
|
#include "Setup.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
#include <locale>
|
|
|
|
#include <everest/run_application/run_application.hpp>
|
|
|
|
#include <fmt/core.h>
|
|
|
|
using namespace everest::run_application;
|
|
|
|
namespace module {
|
|
|
|
// set WifiConfigureClass to the class to use for configuring WiFi
|
|
typedef WpaCliSetup WifiConfigureClass;
|
|
|
|
void to_json(json& j, const NetworkDeviceInfo& k) {
|
|
j = json::object({{"interface", k.interface},
|
|
{"wireless", k.wireless},
|
|
{"blocked", k.blocked},
|
|
{"rfkill_id", k.rfkill_id},
|
|
{"ipv4", k.ipv4},
|
|
{"ipv6", k.ipv6},
|
|
{"mac", k.mac},
|
|
{"link_type", k.link_type}});
|
|
}
|
|
|
|
void to_json(json& j, const WifiCredentials& k) {
|
|
j = json::object({{"interface", k.interface}, {"ssid", k.ssid}, {"psk", k.psk}, {"hidden", k.hidden}});
|
|
}
|
|
|
|
void from_json(const json& j, WifiCredentials& k) {
|
|
k.interface = j.at("interface");
|
|
k.ssid = j.at("ssid");
|
|
k.psk = j.at("psk");
|
|
k.hidden = false;
|
|
// optional item
|
|
auto it = j.find("hidden");
|
|
if ((it != j.end() && *it)) {
|
|
k.hidden = true;
|
|
}
|
|
}
|
|
|
|
void to_json(json& j, const InterfaceAndNetworkId& k) {
|
|
j = json::object({{"interface", k.interface}, {"network_id", k.network_id}});
|
|
}
|
|
void from_json(const json& j, InterfaceAndNetworkId& k) {
|
|
k.interface = j.at("interface");
|
|
k.network_id = j.at("network_id");
|
|
}
|
|
|
|
void to_json(json& j, const SupportedSetupFeatures& k) {
|
|
j = json::object(
|
|
{{"setup_wifi", k.setup_wifi}, {"localization", k.localization}, {"setup_simulation", k.setup_simulation}});
|
|
}
|
|
|
|
void to_json(json& j, const ApplicationInfo& k) {
|
|
j = json::object({{"initialized", k.initialized},
|
|
{"mode", k.mode},
|
|
{"default_language", k.default_language},
|
|
{"current_language", k.current_language},
|
|
{"release_metadata_file", k.release_metadata_file}});
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// JSON conversion for WifiConfigureClass types
|
|
static void to_json(json& j, const WifiConfigureClass::WifiNetworkStatus& k) {
|
|
j = json::object({{"interface", k.interface},
|
|
{"network_id", k.network_id},
|
|
{"ssid", k.ssid},
|
|
{"connected", k.connected},
|
|
{"signal_level", k.signal_level}});
|
|
}
|
|
|
|
static void to_json(json& j, const WifiConfigureClass::WifiScan& k) {
|
|
auto flags_array = json::array();
|
|
flags_array = k.flags;
|
|
j = json::object({{"bssid", k.bssid},
|
|
{"ssid", k.ssid},
|
|
{"frequency", k.frequency},
|
|
{"signal_level", k.signal_level},
|
|
{"flags", flags_array}});
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Setup::init() {
|
|
// Set default locale "C" when no locale is set at all
|
|
try {
|
|
std::locale loc("");
|
|
} catch (const std::runtime_error& e) {
|
|
setenv("LC_ALL", "C", 1);
|
|
}
|
|
}
|
|
|
|
void Setup::ready() {
|
|
this->discover_network_thread = std::thread([this]() {
|
|
while (true) {
|
|
if ((this->config.setup_wifi) && (wifi_scan_enabled)) {
|
|
this->discover_network();
|
|
}
|
|
this->publish_hostname();
|
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
}
|
|
});
|
|
|
|
this->publish_application_info_thread = std::thread([this]() {
|
|
while (true) {
|
|
this->publish_supported_features();
|
|
this->publish_application_info();
|
|
this->publish_ap_state();
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
});
|
|
|
|
std::string set_mode_cmd = this->cmd_base + "set_mode";
|
|
this->mqtt.subscribe(set_mode_cmd, [this](const std::string& data) { this->set_mode(data); });
|
|
|
|
std::string set_initialized_cmd = this->cmd_base + "set_initialized";
|
|
this->mqtt.subscribe(set_initialized_cmd, [this](const std::string& data) { this->set_initialized(true); });
|
|
|
|
std::string reset_initialized_cmd = this->cmd_base + "reset_initialized";
|
|
this->mqtt.subscribe(reset_initialized_cmd, [this](const std::string& data) { this->set_initialized(false); });
|
|
|
|
std::string change_default_language_cmd = this->cmd_base + "change_default_language";
|
|
this->mqtt.subscribe(change_default_language_cmd,
|
|
[this](const std::string& data) { this->set_default_language(data); });
|
|
|
|
std::string change_current_language_cmd = this->cmd_base + "change_current_language";
|
|
this->mqtt.subscribe(change_current_language_cmd,
|
|
[this](const std::string& data) { this->set_current_language(data); });
|
|
|
|
std::string get_application_info_cmd = this->cmd_base + "get_application_info";
|
|
this->mqtt.subscribe(get_application_info_cmd,
|
|
[this](const std::string& data) { this->publish_application_info(); });
|
|
|
|
if (this->config.setup_wifi) {
|
|
std::string rfkill_unblock_cmd = this->cmd_base + "rfkill_unblock";
|
|
this->mqtt.subscribe(rfkill_unblock_cmd, [this](const std::string& data) { this->rfkill_unblock(data); });
|
|
|
|
std::string rfkill_block_cmd = this->cmd_base + "rfkill_block";
|
|
this->mqtt.subscribe(rfkill_block_cmd, [this](const std::string& data) { this->rfkill_block(data); });
|
|
|
|
std::string list_configured_networks_cmd = this->cmd_base + "list_configured_networks";
|
|
this->mqtt.subscribe(list_configured_networks_cmd,
|
|
[this](const std::string& data) { this->publish_configured_networks(); });
|
|
|
|
std::string add_network_cmd = this->cmd_base + "add_network";
|
|
this->mqtt.subscribe(add_network_cmd, [this](const std::string& data) {
|
|
WifiCredentials wifi_credentials = json::parse(data);
|
|
WifiConfigureClass wifi;
|
|
this->add_and_enable_network(wifi_credentials.interface, wifi_credentials.ssid, wifi_credentials.psk,
|
|
wifi_credentials.hidden);
|
|
wifi.save_config(wifi_credentials.interface);
|
|
this->publish_configured_networks();
|
|
});
|
|
|
|
std::string enable_network_cmd = this->cmd_base + "enable_network";
|
|
this->mqtt.subscribe(enable_network_cmd, [this](const std::string& data) {
|
|
InterfaceAndNetworkId wifi_details = json::parse(data);
|
|
WifiConfigureClass wifi;
|
|
wifi.enable_network(wifi_details.interface, wifi_details.network_id);
|
|
wifi.save_config(wifi_details.interface);
|
|
this->publish_configured_networks();
|
|
});
|
|
|
|
std::string disable_network_cmd = this->cmd_base + "disable_network";
|
|
this->mqtt.subscribe(disable_network_cmd, [this](const std::string& data) {
|
|
InterfaceAndNetworkId wifi_details = json::parse(data);
|
|
WifiConfigureClass wifi;
|
|
wifi.disable_network(wifi_details.interface, wifi_details.network_id);
|
|
wifi.save_config(wifi_details.interface);
|
|
this->publish_configured_networks();
|
|
});
|
|
|
|
std::string select_network_cmd = this->cmd_base + "select_network";
|
|
this->mqtt.subscribe(select_network_cmd, [this](const std::string& data) {
|
|
InterfaceAndNetworkId wifi_details = json::parse(data);
|
|
WifiConfigureClass wifi;
|
|
wifi.select_network(wifi_details.interface, wifi_details.network_id);
|
|
wifi.save_config(wifi_details.interface);
|
|
this->publish_configured_networks();
|
|
});
|
|
|
|
std::string remove_network_cmd = this->cmd_base + "remove_network";
|
|
this->mqtt.subscribe(remove_network_cmd, [this](const std::string& data) {
|
|
InterfaceAndNetworkId wifi_details = json::parse(data);
|
|
WifiConfigureClass wifi;
|
|
wifi.remove_network(wifi_details.interface, wifi_details.network_id);
|
|
wifi.save_config(wifi_details.interface);
|
|
this->publish_configured_networks();
|
|
});
|
|
|
|
std::string scan_wifi_cmd = this->cmd_base + "scan_wifi";
|
|
this->mqtt.subscribe(scan_wifi_cmd, [this](const std::string& data) { this->discover_network(); });
|
|
|
|
std::string enable_wifi_scanning_cmd = this->cmd_base + "enable_wifi_scanning";
|
|
this->mqtt.subscribe(enable_wifi_scanning_cmd,
|
|
[this](const std::string& data) { this->wifi_scan_enabled = true; });
|
|
|
|
std::string disable_wifi_scanning_cmd = this->cmd_base + "disable_wifi_scanning";
|
|
this->mqtt.subscribe(disable_wifi_scanning_cmd,
|
|
[this](const std::string& data) { this->wifi_scan_enabled = false; });
|
|
|
|
std::string remove_all_networks_cmd = this->cmd_base + "remove_all_networks";
|
|
this->mqtt.subscribe(remove_all_networks_cmd, [this](const std::string& data) {
|
|
this->remove_all_networks();
|
|
this->publish_configured_networks();
|
|
});
|
|
|
|
std::string reboot_cmd = this->cmd_base + "reboot";
|
|
this->mqtt.subscribe(reboot_cmd, [this](const std::string& data) { this->reboot(); });
|
|
|
|
std::string check_online_status_cmd = this->cmd_base + "check_online_status";
|
|
this->mqtt.subscribe(check_online_status_cmd, [this](const std::string& data) { this->check_online_status(); });
|
|
|
|
std::string enable_ap_cmd = this->cmd_base + "enable_ap";
|
|
this->mqtt.subscribe(enable_ap_cmd, [this](const std::string& data) { enable_ap(); });
|
|
|
|
std::string disable_ap_cmd = this->cmd_base + "disable_ap";
|
|
this->mqtt.subscribe(disable_ap_cmd, [this](const std::string& data) { disable_ap(); });
|
|
}
|
|
}
|
|
|
|
void Setup::publish_supported_features() {
|
|
SupportedSetupFeatures supported_setup_features;
|
|
supported_setup_features.setup_wifi = this->config.setup_wifi;
|
|
supported_setup_features.localization = this->config.localization;
|
|
supported_setup_features.setup_simulation = this->config.setup_simulation;
|
|
|
|
std::string supported_setup_features_var = this->var_base + "supported_setup_features";
|
|
|
|
json supported_setup_features_json = supported_setup_features;
|
|
|
|
this->mqtt.publish(supported_setup_features_var, supported_setup_features_json.dump());
|
|
}
|
|
|
|
void Setup::publish_application_info() {
|
|
ApplicationInfo application_info;
|
|
application_info.initialized = this->get_initialized();
|
|
application_info.mode = this->get_mode();
|
|
application_info.default_language = this->get_default_language();
|
|
application_info.current_language = this->get_current_language();
|
|
application_info.release_metadata_file = this->info.paths.etc / this->config.release_metadata_file;
|
|
|
|
std::string application_info_var = this->var_base + "application_info";
|
|
|
|
json application_info_json = application_info;
|
|
|
|
this->mqtt.publish(application_info_var, application_info_json.dump());
|
|
}
|
|
|
|
void Setup::publish_hostname() {
|
|
std::string hostname_var = this->var_base + "hostname";
|
|
|
|
this->mqtt.publish(hostname_var, this->get_hostname());
|
|
}
|
|
|
|
void Setup::publish_ap_state() {
|
|
std::string ap_state_var = this->var_base + "ap_state";
|
|
|
|
auto hostapd_enabled_output = run_application("systemctl", {"is-active", "--quiet", "hostapd"});
|
|
if (hostapd_enabled_output.exit_code == 0) {
|
|
this->ap_state = "enabled";
|
|
} else {
|
|
this->ap_state = "disabled";
|
|
}
|
|
|
|
this->mqtt.publish(ap_state_var, this->ap_state);
|
|
}
|
|
|
|
void Setup::set_default_language(std::string language) {
|
|
this->r_store->call_store("everest_localization_default_language", language);
|
|
}
|
|
|
|
std::string Setup::get_default_language() {
|
|
auto language = this->r_store->call_load("everest_localization_default_language");
|
|
if (!std::holds_alternative<std::string>(language)) {
|
|
return "unknown";
|
|
}
|
|
return std::get<std::string>(language);
|
|
}
|
|
|
|
void Setup::set_current_language(const std::string& language) {
|
|
this->current_language = language;
|
|
}
|
|
|
|
std::string Setup::get_current_language() {
|
|
if (this->current_language.empty()) {
|
|
this->current_language = this->get_default_language();
|
|
}
|
|
|
|
return this->current_language;
|
|
}
|
|
|
|
void Setup::set_mode(std::string mode) {
|
|
this->r_store->call_store("everest_mode", mode);
|
|
}
|
|
|
|
std::string Setup::get_mode() {
|
|
auto mode = this->r_store->call_load("everest_mode");
|
|
if (!std::holds_alternative<std::string>(mode)) {
|
|
return "unknown";
|
|
}
|
|
return std::get<std::string>(mode);
|
|
}
|
|
|
|
void Setup::set_initialized(bool initialized) {
|
|
this->r_store->call_store("everest_initialized", initialized);
|
|
}
|
|
|
|
bool Setup::get_initialized() {
|
|
if (this->config.initialized_by_default) {
|
|
return true;
|
|
}
|
|
auto initialized = this->r_store->call_load("everest_initialized");
|
|
if (!std::holds_alternative<bool>(initialized)) {
|
|
return false;
|
|
}
|
|
return std::get<bool>(initialized);
|
|
}
|
|
|
|
void Setup::discover_network() {
|
|
std::vector<NetworkDeviceInfo> device_info = this->get_network_devices();
|
|
|
|
this->populate_rfkill_status(device_info);
|
|
this->populate_ip_addresses(device_info);
|
|
|
|
std::string network_device_info_var = this->var_base + "network_device_info";
|
|
json device_info_json = json::array();
|
|
device_info_json = device_info;
|
|
this->mqtt.publish(network_device_info_var, device_info_json.dump());
|
|
|
|
auto wifi_info = this->scan_wifi(device_info);
|
|
|
|
std::string wifi_info_var = this->var_base + "wifi_info";
|
|
json wifi_info_json = json::array();
|
|
wifi_info_json = wifi_info;
|
|
this->mqtt.publish(wifi_info_var, wifi_info_json.dump());
|
|
|
|
this->publish_configured_networks();
|
|
}
|
|
|
|
std::string Setup::read_type_file(const fs::path& type_path) {
|
|
if (!fs::exists(type_path)) {
|
|
return "";
|
|
}
|
|
|
|
std::ifstream ifs(type_path.c_str());
|
|
std::string type_file((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
|
// trim newlines
|
|
type_file.erase(std::remove(type_file.begin(), type_file.end(), '\n'), type_file.end());
|
|
|
|
return type_file;
|
|
}
|
|
|
|
std::vector<NetworkDeviceInfo> Setup::get_network_devices() {
|
|
auto sys_net_path = fs::path("/sys/class/net");
|
|
auto sys_virtual_net_path = fs::path("/sys/devices/virtual/net");
|
|
|
|
std::vector<NetworkDeviceInfo> device_info;
|
|
|
|
for (auto&& net_it : fs::directory_iterator(sys_net_path)) {
|
|
auto net_path = net_it.path();
|
|
auto type_path = net_path / "type";
|
|
if (!fs::exists(type_path)) {
|
|
continue;
|
|
}
|
|
|
|
std::string type_file = this->read_type_file(type_path);
|
|
|
|
auto interface = net_path.filename();
|
|
auto virtual_interface = sys_virtual_net_path / interface;
|
|
|
|
// check if type is ethernet:
|
|
if (type_file == "1") {
|
|
if (fs::exists(virtual_interface)) {
|
|
continue;
|
|
}
|
|
|
|
auto device = NetworkDeviceInfo();
|
|
device.interface = interface.string();
|
|
device.link_type = "ether";
|
|
|
|
// check if its wireless or not:
|
|
auto wireless_path = net_path / "wireless";
|
|
if (fs::exists(wireless_path)) {
|
|
device.wireless = true;
|
|
auto phy80211_path = net_path / "phy80211";
|
|
for (auto&& rfkill_it : fs::directory_iterator(phy80211_path)) {
|
|
auto phy_file_path = rfkill_it.path().filename().string();
|
|
std::string rfkill = "rfkill";
|
|
if (phy_file_path.find(rfkill) == 0) {
|
|
phy_file_path.erase(0, rfkill.size());
|
|
device.rfkill_id = phy_file_path;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
device_info.push_back(device);
|
|
} else if (type_file == "65534") {
|
|
if (!fs::exists(virtual_interface)) {
|
|
continue;
|
|
}
|
|
|
|
auto virtual_type_path = virtual_interface / "type";
|
|
|
|
if (!fs::exists(virtual_type_path)) {
|
|
continue;
|
|
}
|
|
|
|
std::string virtual_type_file = this->read_type_file(virtual_type_path);
|
|
if (virtual_type_file == type_file) {
|
|
// assume it's a vpn, but check ip link
|
|
auto ip_output = run_application("ip", {"--json", "-details", "link", "show", interface});
|
|
if (ip_output.exit_code != 0) {
|
|
continue;
|
|
}
|
|
const auto ip_json = json::parse(ip_output.output);
|
|
if (ip_json.size() < 1) {
|
|
continue;
|
|
}
|
|
const auto& entry = ip_json.at(0);
|
|
if (entry.contains("linkinfo") and entry.at("linkinfo").contains("info_kind")) {
|
|
auto device = NetworkDeviceInfo();
|
|
device.interface = interface.string();
|
|
device.link_type = entry.at("linkinfo").at("info_kind");
|
|
device_info.push_back(device);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return device_info;
|
|
}
|
|
|
|
void Setup::populate_rfkill_status(std::vector<NetworkDeviceInfo>& device_info) {
|
|
auto rfkill_output = run_application("rfkill", {"--json"});
|
|
if (rfkill_output.exit_code != 0) {
|
|
return;
|
|
}
|
|
auto rfkill_json = json::parse(rfkill_output.output);
|
|
for (auto rfkill_object : rfkill_json.items()) {
|
|
for (auto rfkill_device : rfkill_object.value()) {
|
|
for (auto& device : device_info) {
|
|
int device_id = rfkill_device.at("id");
|
|
if (!device.rfkill_id.empty() && std::to_string(device_id) == device.rfkill_id) {
|
|
if (rfkill_device.at("soft") == "blocked") {
|
|
device.blocked = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Setup::rfkill_unblock(std::string rfkill_id) {
|
|
auto network_devices = this->get_network_devices();
|
|
this->populate_rfkill_status(network_devices);
|
|
bool found = false;
|
|
for (auto device : network_devices) {
|
|
if (device.rfkill_id == rfkill_id) {
|
|
if (!device.blocked) {
|
|
return true;
|
|
}
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
return false;
|
|
}
|
|
|
|
auto rfkill_output = run_application("rfkill", {"unblock", rfkill_id});
|
|
if (rfkill_output.exit_code != 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Setup::rfkill_block(std::string rfkill_id) {
|
|
auto network_devices = this->get_network_devices();
|
|
this->populate_rfkill_status(network_devices);
|
|
bool found = false;
|
|
for (auto device : network_devices) {
|
|
if (device.rfkill_id == rfkill_id) {
|
|
if (device.blocked) {
|
|
return true;
|
|
}
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
return false;
|
|
}
|
|
|
|
auto rfkill_output = run_application("rfkill", {"block", rfkill_id});
|
|
if (rfkill_output.exit_code != 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Setup::publish_configured_networks() {
|
|
auto network_devices = this->get_network_devices();
|
|
|
|
WpaCliSetup::WifiNetworkStatusList all_wifi_networks;
|
|
|
|
for (auto device : network_devices) {
|
|
if (!device.wireless) {
|
|
continue;
|
|
}
|
|
WifiConfigureClass wifi;
|
|
auto network_list = wifi.list_networks_status(device.interface);
|
|
for (auto& i : network_list) {
|
|
all_wifi_networks.push_back(std::move(i));
|
|
}
|
|
}
|
|
|
|
std::string network_list_var = this->var_base + "configured_networks";
|
|
json configured_networks_json = json::array();
|
|
configured_networks_json = all_wifi_networks;
|
|
this->mqtt.publish(network_list_var, configured_networks_json.dump());
|
|
}
|
|
|
|
bool Setup::add_and_enable_network(const std::string& interface, const std::string& ssid, const std::string& psk,
|
|
bool hidden) {
|
|
WifiConfigureClass wifi;
|
|
|
|
std::string net_if = interface;
|
|
if (net_if.empty()) {
|
|
EVLOG_warning << "Attempting to add a network without an interface, attempting to use the first one";
|
|
auto network_devices = this->get_network_devices();
|
|
for (auto device : network_devices) {
|
|
if (device.wireless) {
|
|
net_if = device.interface;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto network_id = wifi.add_network(net_if);
|
|
bool bResult = network_id != -1;
|
|
bResult = bResult && wifi.set_network(net_if, network_id, ssid, psk, hidden);
|
|
bResult = bResult && wifi.enable_network(net_if, network_id);
|
|
return bResult;
|
|
}
|
|
|
|
bool Setup::remove_all_networks() {
|
|
auto network_devices = this->get_network_devices();
|
|
std::uint32_t remove_fail = 0;
|
|
|
|
for (auto device : network_devices) {
|
|
if (!device.wireless) {
|
|
continue;
|
|
}
|
|
|
|
WifiConfigureClass wifi;
|
|
auto networks = wifi.list_networks(device.interface);
|
|
|
|
for (auto network : networks) {
|
|
if (!wifi.remove_network(device.interface, network.network_id)) {
|
|
remove_fail++;
|
|
}
|
|
}
|
|
|
|
wifi.save_config(device.interface);
|
|
}
|
|
|
|
return remove_fail == 0;
|
|
}
|
|
|
|
bool Setup::reboot() {
|
|
bool success = true;
|
|
auto reboot_output = run_application("systemctl", {"reboot"});
|
|
if (reboot_output.exit_code != 0) {
|
|
success = false;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool Setup::is_online() {
|
|
bool success = true;
|
|
auto reboot_output = run_application("ping", {"-c", "1", this->config.online_check_host});
|
|
if (reboot_output.exit_code != 0) {
|
|
success = false;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
void Setup::check_online_status() {
|
|
std::string online_status_var = this->var_base + "online_status";
|
|
|
|
if (this->is_online()) {
|
|
this->mqtt.publish(online_status_var, "online");
|
|
} else {
|
|
this->mqtt.publish(online_status_var, "offline");
|
|
}
|
|
}
|
|
|
|
void Setup::enable_ap() {
|
|
auto wpa_cli_output = run_application("wpa_cli", {"-i", this->config.ap_interface, "disconnect"});
|
|
if (wpa_cli_output.exit_code != 0) {
|
|
EVLOG_error << "Could not disconnect from wireless LAN";
|
|
}
|
|
auto start_hostapd_output = run_application("systemctl", {"start", "hostapd"});
|
|
if (start_hostapd_output.exit_code != 0) {
|
|
EVLOG_error << "Could not start hostapd";
|
|
}
|
|
auto start_dnsmasq_output = run_application("systemctl", {"start", "dnsmasq"});
|
|
if (start_dnsmasq_output.exit_code != 0) {
|
|
EVLOG_error << "Could not start dnsmasq";
|
|
}
|
|
auto add_static_ip_output =
|
|
run_application("ip", {"addr", "add", this->config.ap_ipv4, "dev", this->config.ap_interface});
|
|
if (add_static_ip_output.exit_code != 0) {
|
|
EVLOG_error << "Could not add static ip to interface " << this->config.ap_interface;
|
|
}
|
|
}
|
|
|
|
void Setup::disable_ap() {
|
|
auto del_static_ip_output =
|
|
run_application("ip", {"addr", "del", this->config.ap_ipv4, "dev", this->config.ap_interface});
|
|
if (del_static_ip_output.exit_code != 0) {
|
|
EVLOG_error << "Could not del static ip " << this->config.ap_ipv4 << " from interface "
|
|
<< this->config.ap_interface;
|
|
}
|
|
auto stop_dnsmasq_output = run_application("systemctl", {"stop", "dnsmasq"});
|
|
if (stop_dnsmasq_output.exit_code != 0) {
|
|
EVLOG_error << "Could not stop dnsmasq";
|
|
}
|
|
auto stop_hostapd_output = run_application("systemctl", {"stop", "hostapd"});
|
|
if (stop_hostapd_output.exit_code != 0) {
|
|
EVLOG_error << "Could not stop hostapd";
|
|
}
|
|
|
|
auto wpa_cli_output = run_application("wpa_cli", {"-i", this->config.ap_interface, "reconnect"});
|
|
if (wpa_cli_output.exit_code != 0) {
|
|
EVLOG_error << "Could not reconnect to wireless LAN";
|
|
}
|
|
}
|
|
|
|
static void add_addr_infos_to_device(const json& addr_infos, NetworkDeviceInfo& device) {
|
|
for (const auto& addr_info : addr_infos) {
|
|
if (addr_info.at("family") == "inet") {
|
|
device.ipv4.push_back(addr_info.at("local"));
|
|
} else if (addr_info.at("family") == "inet6") {
|
|
device.ipv6.push_back(addr_info.at("local"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void Setup::populate_ip_addresses(std::vector<NetworkDeviceInfo>& device_info) {
|
|
auto ip_output = run_application("ip", {"--json", "address", "show"});
|
|
if (ip_output.exit_code != 0) {
|
|
return;
|
|
}
|
|
const auto ip_json = json::parse(ip_output.output);
|
|
for (const auto& ip_object : ip_json) {
|
|
const std::string ifname = ip_object.at("ifname");
|
|
auto device = std::find_if(device_info.begin(), device_info.end(),
|
|
[&ifname](NetworkDeviceInfo& device) { return device.interface == ifname; });
|
|
if (device == device_info.end()) {
|
|
continue;
|
|
}
|
|
if (ip_object.contains("address")) {
|
|
device->mac = ip_object.at("address");
|
|
}
|
|
add_addr_infos_to_device(ip_object.at("addr_info"), *device);
|
|
}
|
|
}
|
|
|
|
WifiConfigureClass::WifiScanList Setup::scan_wifi(const std::vector<NetworkDeviceInfo>& device_info) {
|
|
WifiConfigureClass::WifiScanList wifi_info;
|
|
WifiConfigureClass wifi;
|
|
|
|
for (auto device : device_info) {
|
|
if (!device.wireless) {
|
|
continue;
|
|
}
|
|
|
|
auto dev_list = wifi.scan_wifi(device.interface);
|
|
wifi_info.insert(wifi_info.end(), dev_list.begin(), dev_list.end());
|
|
}
|
|
|
|
return wifi_info;
|
|
}
|
|
|
|
std::string Setup::get_hostname() {
|
|
auto hostname_output = run_application("hostname", {});
|
|
if (hostname_output.exit_code == 0 && hostname_output.split_output.size() > 0) {
|
|
return hostname_output.split_output.at(0);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
} // namespace module
|