122 lines
3.4 KiB
C++
122 lines
3.4 KiB
C++
#include "mqtt_config.hpp"
|
|
|
|
MQTTConfig g_mqtt_config;
|
|
|
|
MQTTConfig MQTTConfig::load_from_file(const std::string &filepath)
|
|
{
|
|
MQTTConfig cfg;
|
|
|
|
std::ifstream ifs(filepath);
|
|
if (!ifs)
|
|
{
|
|
LOG_ERROR("[Config] Failed to open config file: " + filepath);
|
|
throw std::runtime_error("Failed to open config file: " + filepath);
|
|
}
|
|
|
|
nlohmann::json j;
|
|
ifs >> j;
|
|
|
|
cfg.device_id = j["device_id"];
|
|
cfg.vin = j["vin"];
|
|
cfg.server_ip = j["server_ip"];
|
|
cfg.server_port = j["server_port"];
|
|
cfg.client_id = j["client_id"];
|
|
cfg.username = j["username"];
|
|
cfg.password = j["password"];
|
|
cfg.qos = j["qos"];
|
|
cfg.keep_alive = j["keep_alive"];
|
|
cfg.clean_session = j["clean_session"];
|
|
|
|
const std::string &id = cfg.device_id;
|
|
cfg.topics.uplink_1 = j["topics"]["uplink_1"].get<std::string>() + id;
|
|
cfg.topics.uplink_2 = j["topics"]["uplink_2"].get<std::string>() + id;
|
|
cfg.topics.downlink = j["topics"]["downlink"].get<std::string>() + id;
|
|
|
|
cfg.ports.config_port = j["ports"]["config_port"];
|
|
cfg.ports.uplink_1_port = j["ports"]["uplink_1_port"];
|
|
cfg.ports.uplink_2_port = j["ports"]["uplink_2_port"];
|
|
cfg.ports.downlink_port = j["ports"]["downlink_port"];
|
|
|
|
LOG_INFO("[Config] Loaded config from " + filepath);
|
|
LOG_INFO(" - MQTT Server: " + cfg.server_ip + ":" + std::to_string(cfg.server_port));
|
|
LOG_INFO(" - Client ID: " + cfg.client_id);
|
|
LOG_INFO(" - Topics: " + cfg.topics.uplink_1 + ", " + cfg.topics.uplink_2 + ", " + cfg.topics.downlink);
|
|
|
|
return cfg;
|
|
}
|
|
|
|
bool MQTTConfig::update_mqtt_config(const ordered_json &new_values,
|
|
const std::string &filepath)
|
|
{
|
|
std::ifstream ifs(filepath);
|
|
if (!ifs.is_open())
|
|
{
|
|
LOG_ERROR("[ConfigEdit] Failed to open config file: " + filepath);
|
|
return false;
|
|
}
|
|
|
|
ordered_json j;
|
|
try
|
|
{
|
|
ifs >> j;
|
|
ifs.close();
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
LOG_ERROR(std::string("[ConfigEdit] JSON parse error: ") + e.what());
|
|
return false;
|
|
}
|
|
|
|
for (auto it = new_values.begin(); it != new_values.end(); ++it)
|
|
{
|
|
const std::string &key = it.key();
|
|
const auto &val = it.value();
|
|
|
|
if (j.contains(key))
|
|
{
|
|
LOG_INFO("[ConfigEdit] Updating key: " + key + " -> " + val.dump());
|
|
j[key] = val;
|
|
}
|
|
else
|
|
{
|
|
LOG_WARN("[ConfigEdit] Warning: key '" + key + "' not found in config, ignored.");
|
|
}
|
|
}
|
|
|
|
std::ofstream ofs(filepath);
|
|
if (!ofs.is_open())
|
|
{
|
|
LOG_ERROR("[ConfigEdit] Failed to write updated config file: " + filepath);
|
|
return false;
|
|
}
|
|
|
|
ofs << j.dump(4);
|
|
ofs.close();
|
|
return true;
|
|
}
|
|
|
|
std::string get_executable_dir()
|
|
{
|
|
char result[PATH_MAX] = {0};
|
|
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
|
|
if (count == -1)
|
|
{
|
|
throw std::runtime_error("Failed to read /proc/self/exe");
|
|
}
|
|
|
|
std::string full_path(result, count);
|
|
auto pos = full_path.find_last_of('/');
|
|
if (pos == std::string::npos)
|
|
{
|
|
throw std::runtime_error("Failed to find executable directory");
|
|
}
|
|
return full_path.substr(0, pos);
|
|
}
|
|
|
|
std::string get_executable_dir_file_path(const std::string &filename)
|
|
{
|
|
std::string dir = get_executable_dir();
|
|
if (dir.back() != '/')
|
|
dir += '/';
|
|
return dir + filename;
|
|
} |