- 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
646 lines
26 KiB
C++
646 lines
26 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright Pionix GmbH and Contributors to EVerest
|
|
|
|
#include <exception>
|
|
|
|
#include <everest/logging.hpp>
|
|
|
|
#include <utils/config/storage.hpp>
|
|
#include <utils/config/types.hpp>
|
|
#include <utils/config_service.hpp>
|
|
#include <utils/conversions.hpp>
|
|
|
|
namespace Everest {
|
|
namespace config {
|
|
|
|
bool ModuleIdType::operator<(const ModuleIdType& rhs) const {
|
|
return (this->module_id < rhs.module_id ||
|
|
(this->module_id == rhs.module_id && this->module_type < rhs.module_type));
|
|
}
|
|
|
|
enum class AccessMethod {
|
|
Read,
|
|
Write
|
|
};
|
|
|
|
namespace {
|
|
bool access_allowed(const everest::config::Access& access, const std::string& origin, const std::string& target,
|
|
AccessMethod method) {
|
|
if (origin == target) {
|
|
// a module can always read and write its own config
|
|
return true;
|
|
}
|
|
if (not access.config.has_value()) {
|
|
return false;
|
|
}
|
|
const auto& config_access = access.config.value();
|
|
const auto& config_access_modules_it = config_access.modules.find(target);
|
|
switch (method) {
|
|
case AccessMethod::Read:
|
|
if (config_access.allow_global_read) {
|
|
return true;
|
|
}
|
|
if (config_access_modules_it != config_access.modules.end()) {
|
|
if (config_access_modules_it->second.allow_read) {
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case AccessMethod::Write:
|
|
if (config_access.allow_global_write) {
|
|
return true;
|
|
}
|
|
if (config_access_modules_it != config_access.modules.end()) {
|
|
if (config_access_modules_it->second.allow_write) {
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
nlohmann::json get_module_config(const std::string& module_id, const ManagerConfig& config) {
|
|
const auto& module_configurations = config.get_module_configurations();
|
|
return get_serialized_module_config(module_id, module_configurations);
|
|
}
|
|
|
|
everest::config::ModuleConfigurationParameters
|
|
update_mutability(const everest::config::ModuleConfigurationParameters& configuration_parameters,
|
|
bool allow_set_read_only = false) {
|
|
if (not allow_set_read_only) {
|
|
return configuration_parameters;
|
|
}
|
|
everest::config::ModuleConfigurationParameters updated_configuration_parameters = configuration_parameters;
|
|
for (auto& [impl_id, config_params] : updated_configuration_parameters) {
|
|
for (auto& config_param : config_params) {
|
|
auto& mutability = config_param.characteristics.mutability;
|
|
if (mutability == everest::config::Mutability::ReadOnly) {
|
|
config_param.characteristics.mutability = everest::config::Mutability::ReadWrite;
|
|
}
|
|
}
|
|
}
|
|
return updated_configuration_parameters;
|
|
}
|
|
|
|
GetResponse handle_get_module_config(const std::string& origin, const ManagerConfig& config) {
|
|
GetResponse get_response;
|
|
get_response.type = GetType::Module;
|
|
get_response.data = get_module_config(origin, config);
|
|
return get_response;
|
|
}
|
|
|
|
Response handle_get_config_value(const GetRequest& get_request, const std::string& origin, ManagerConfig& config) {
|
|
Response response;
|
|
response.type = Type::Get;
|
|
GetResponse get_response;
|
|
get_response.type = GetType::Value;
|
|
|
|
if (not get_request.identifier.has_value()) {
|
|
response.status = ResponseStatus::Error; // no identifier is always an error in this case
|
|
response.status_info = "No identifier provided";
|
|
} else {
|
|
const auto identifier = get_request.identifier.value();
|
|
const auto& module_configs = config.get_module_configurations();
|
|
const everest::config::Access access = module_configs.at(origin).access;
|
|
if (not access_allowed(access, origin, identifier.module_id, AccessMethod::Read)) {
|
|
response.status = ResponseStatus::AccessDenied;
|
|
response.status_info =
|
|
fmt::format("Access to config item denied: {} cannot access {}", origin, identifier.module_id);
|
|
} else {
|
|
const auto get_config_value_response = config.get_config_value(identifier);
|
|
if (get_config_value_response.status == everest::config::GetSetResponseStatus::OK) {
|
|
if (get_config_value_response.configuration_parameter.has_value()) {
|
|
get_response.data = get_config_value_response.configuration_parameter.value();
|
|
response.status = ResponseStatus::Ok;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
response.response = get_response;
|
|
return response;
|
|
}
|
|
|
|
GetResponse handle_get_all_configs(const std::string& origin, const ManagerConfig& config) {
|
|
// FIXME: we might run into size limits when the config is really large, split this up in the
|
|
// future!
|
|
GetResponse get_response;
|
|
get_response.type = GetType::All;
|
|
json all_configs = json::object();
|
|
const auto& module_configs = config.get_module_configurations();
|
|
everest::config::Access access = module_configs.at(origin).access;
|
|
for (const auto& [module_id, module_name] : config.get_module_names()) {
|
|
if (not access_allowed(access, origin, module_id, AccessMethod::Read)) {
|
|
// request.origin has no access to module_id.config
|
|
continue;
|
|
}
|
|
auto allow_set_read_only = false;
|
|
if (access.config.has_value()) {
|
|
const auto config_access = access.config.value();
|
|
allow_set_read_only = config_access.allow_set_read_only;
|
|
|
|
if (not allow_set_read_only) {
|
|
// check if allow_set_read_only is set for specific modules
|
|
const auto module_config_access_it = config_access.modules.find(module_id);
|
|
if (module_config_access_it != config_access.modules.end()) {
|
|
allow_set_read_only = module_config_access_it->second.allow_set_read_only;
|
|
}
|
|
}
|
|
}
|
|
|
|
all_configs[module_id] =
|
|
update_mutability(module_configs.at(module_id).configuration_parameters, allow_set_read_only);
|
|
}
|
|
get_response.data = all_configs;
|
|
return get_response;
|
|
}
|
|
|
|
GetResponse handle_get_all_mappings(const std::string& origin, const ManagerConfig& config) {
|
|
GetResponse get_response;
|
|
get_response.type = GetType::AllMappings;
|
|
json all_mappings = json::object();
|
|
const auto& module_configs = config.get_module_configurations();
|
|
const everest::config::Access access = module_configs.at(origin).access;
|
|
for (const auto& [module_id, module_name] : config.get_module_names()) {
|
|
if (not access_allowed(access, origin, module_id, AccessMethod::Read)) {
|
|
// request.origin has no access to module_id.mappings
|
|
continue;
|
|
}
|
|
all_mappings[module_id] = module_configs.at(module_id).mapping;
|
|
}
|
|
|
|
get_response.data = all_mappings;
|
|
return get_response;
|
|
}
|
|
|
|
Response handle_set_request(const SetRequest& set_request, const std::string& origin, ManagerConfig& config) {
|
|
Response response;
|
|
response.type = Type::Set;
|
|
SetResponse set_response;
|
|
set_response.status = SetResponseStatus::Rejected;
|
|
|
|
const auto& module_configs = config.get_module_configurations();
|
|
const everest::config::Access access = module_configs.at(origin).access;
|
|
if (not access_allowed(access, origin, set_request.identifier.module_id, AccessMethod::Write)) {
|
|
set_response.status = SetResponseStatus::Rejected;
|
|
response.status = ResponseStatus::AccessDenied;
|
|
response.status_info =
|
|
fmt::format("Access to config item denied: {} cannot access {}", origin, set_request.identifier.module_id);
|
|
} else {
|
|
// TODO: explicit input validation
|
|
const auto& target_module_config = module_configs.at(set_request.identifier.module_id);
|
|
everest::config::SetConfigStatus status = everest::config::SetConfigStatus::Rejected;
|
|
const auto impl_id = set_request.identifier.module_implementation_id.value_or(MODULE_IMPLEMENTATION_ID);
|
|
for (const auto& config_entry : target_module_config.configuration_parameters.at(impl_id)) {
|
|
if (config_entry.name == set_request.identifier.configuration_parameter_name) {
|
|
try {
|
|
const auto value = parse_config_value(config_entry.characteristics.datatype, set_request.value);
|
|
status = config.set_config_value(set_request.identifier, value);
|
|
response.status = ResponseStatus::Ok;
|
|
} catch (const std::exception& e) {
|
|
response.status = ResponseStatus::Error;
|
|
response.status_info = fmt::format("Could not set config entry {} of module {}: {}",
|
|
set_request.identifier.configuration_parameter_name,
|
|
set_request.identifier.module_id, e.what());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
set_response.status = conversions::set_config_status_to_set_response_status(status);
|
|
}
|
|
response.response = set_response;
|
|
return response;
|
|
}
|
|
} // namespace
|
|
|
|
ConfigServiceClient::ConfigServiceClient(std::shared_ptr<MQTTAbstraction> mqtt_abstraction,
|
|
const std::string& module_id,
|
|
const std::map<std::string, std::string, std::less<>>& module_names) :
|
|
mqtt_abstraction(mqtt_abstraction), origin(module_id), module_names(module_names) {
|
|
}
|
|
|
|
std::map<ModuleIdType, everest::config::ModuleConfigurationParameters> ConfigServiceClient::get_module_configs() {
|
|
Request get_request;
|
|
get_request.type = Type::Get;
|
|
get_request.request = GetRequest{GetType::All};
|
|
get_request.origin = this->origin;
|
|
|
|
MQTTRequest mqtt_request;
|
|
mqtt_request.response_topic =
|
|
fmt::format("{}modules/{}/response", mqtt_abstraction->get_everest_prefix(), get_request.origin);
|
|
mqtt_request.request_topic = fmt::format("{}config/request", mqtt_abstraction->get_everest_prefix());
|
|
mqtt_request.request_data = json(get_request).dump();
|
|
|
|
try {
|
|
Response response = mqtt_abstraction->get(mqtt_request, mqtt_get_config_retries);
|
|
if (response.status != ResponseStatus::Ok) {
|
|
EVLOG_error << "Could not get module configs via MQTT";
|
|
return {};
|
|
}
|
|
|
|
GetResponse get_response = std::get<GetResponse>(response.response);
|
|
|
|
std::map<ModuleIdType, everest::config::ModuleConfigurationParameters> module_configs;
|
|
for (const auto& [module_id, config_maps] : get_response.data.items()) {
|
|
ModuleIdType module_id_type;
|
|
module_id_type.module_id = module_id;
|
|
module_id_type.module_type = module_names.at(module_id);
|
|
module_configs[module_id_type] = config_maps;
|
|
}
|
|
|
|
return module_configs;
|
|
} catch (const std::exception& e) {
|
|
EVLOG_error << "Could not get module configs via MQTT: " << e.what();
|
|
return {};
|
|
}
|
|
}
|
|
|
|
std::map<std::string, ModuleTierMappings> ConfigServiceClient::get_mappings() {
|
|
Request get_request;
|
|
get_request.type = Type::Get;
|
|
get_request.request = GetRequest{GetType::AllMappings};
|
|
get_request.origin = this->origin;
|
|
|
|
MQTTRequest mqtt_request;
|
|
mqtt_request.response_topic =
|
|
fmt::format("{}modules/{}/response", mqtt_abstraction->get_everest_prefix(), get_request.origin);
|
|
mqtt_request.request_topic = fmt::format("{}config/request", mqtt_abstraction->get_everest_prefix());
|
|
mqtt_request.request_data = json(get_request).dump();
|
|
|
|
try {
|
|
Response response = mqtt_abstraction->get(mqtt_request, mqtt_get_config_retries);
|
|
if (response.status != ResponseStatus::Ok) {
|
|
EVLOG_error << "Could not get mappings configs via MQTT";
|
|
return {};
|
|
}
|
|
|
|
GetResponse get_response = std::get<GetResponse>(response.response);
|
|
|
|
std::map<std::string, ModuleTierMappings> mappings;
|
|
for (const auto& [module_id, mapping] : get_response.data.items()) {
|
|
mappings[module_id] = everest::config::parse_mapping(mapping);
|
|
}
|
|
|
|
return mappings;
|
|
} catch (const std::exception& e) {
|
|
EVLOG_error << "Could not get mappings configs via MQTT: " << e.what();
|
|
return {};
|
|
}
|
|
}
|
|
|
|
SetConfigResult
|
|
ConfigServiceClient::set_config_value(const everest::config::ConfigurationParameterIdentifier& identifier,
|
|
const std::string& value) {
|
|
SetConfigResult result;
|
|
Request request;
|
|
request.type = Type::Set;
|
|
request.origin = this->origin;
|
|
SetRequest set_request;
|
|
set_request.identifier = identifier;
|
|
set_request.value = value;
|
|
request.request = set_request;
|
|
|
|
try {
|
|
MQTTRequest mqtt_request;
|
|
mqtt_request.response_topic =
|
|
fmt::format("{}modules/{}/response", mqtt_abstraction->get_everest_prefix(), request.origin);
|
|
mqtt_request.request_topic = fmt::format("{}config/request", mqtt_abstraction->get_everest_prefix());
|
|
mqtt_request.request_data = json(request).dump();
|
|
|
|
const Response response = mqtt_abstraction->get(mqtt_request, mqtt_get_config_retries);
|
|
result.status = response.status;
|
|
result.status_info = response.status_info;
|
|
if (response.status == ResponseStatus::Ok) {
|
|
if (response.type.has_value() and response.type.value() == Type::Set) {
|
|
const SetResponse set_response = std::get<SetResponse>(response.response);
|
|
result.set_status = conversions::set_response_status_to_set_config_status(set_response.status);
|
|
}
|
|
}
|
|
return result;
|
|
} catch (const std::exception& e) {
|
|
EVLOG_info << "Could not set config value: " << identifier.module_id << ": "
|
|
<< identifier.module_implementation_id.value_or(MODULE_IMPLEMENTATION_ID) << ": "
|
|
<< identifier.configuration_parameter_name << ": " << e.what();
|
|
result.status = ResponseStatus::Error;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
GetConfigResult
|
|
ConfigServiceClient::get_config_value(const everest::config::ConfigurationParameterIdentifier& identifier) {
|
|
GetConfigResult result;
|
|
Request request;
|
|
request.type = Type::Get;
|
|
request.origin = this->origin;
|
|
GetRequest get_request;
|
|
get_request.type = GetType::Value;
|
|
get_request.identifier = identifier;
|
|
request.request = get_request;
|
|
|
|
try {
|
|
MQTTRequest mqtt_request;
|
|
mqtt_request.response_topic =
|
|
fmt::format("{}modules/{}/response", mqtt_abstraction->get_everest_prefix(), request.origin);
|
|
mqtt_request.request_topic = fmt::format("{}config/request", mqtt_abstraction->get_everest_prefix());
|
|
mqtt_request.request_data = json(request).dump();
|
|
const Response response = mqtt_abstraction->get(mqtt_request, mqtt_get_config_retries);
|
|
result.status = response.status;
|
|
result.status_info = response.status_info;
|
|
if (response.status == ResponseStatus::Ok) {
|
|
if (response.type.has_value() and response.type.value() == Type::Get) {
|
|
const GetResponse get_response = std::get<GetResponse>(response.response);
|
|
result.configuration_parameter = get_response.data;
|
|
}
|
|
}
|
|
} catch (const std::exception& e) {
|
|
EVLOG_info << "Could not get config value: " << identifier.module_id << ": "
|
|
<< identifier.module_implementation_id.value_or(MODULE_IMPLEMENTATION_ID) << ": "
|
|
<< identifier.configuration_parameter_name << ": " << e.what();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
ConfigService::ConfigService(MQTTAbstraction& mqtt_abstraction, std::shared_ptr<ManagerConfig> config) :
|
|
mqtt_abstraction(mqtt_abstraction), config(config) {
|
|
|
|
// TODO: thread-safe?
|
|
|
|
const Handler global_config_request_handler = [&mqtt_abstraction, config](const std::string& /*topic*/,
|
|
const nlohmann::json& data) {
|
|
Response response;
|
|
response.status = ResponseStatus::Error;
|
|
try {
|
|
Request request = data;
|
|
response.type = request.type;
|
|
const auto response_topic =
|
|
fmt::format("{}modules/{}/response", mqtt_abstraction.get_everest_prefix(), request.origin);
|
|
|
|
if (request.type == Type::Get) {
|
|
const GetRequest get_request = std::get<GetRequest>(request.request);
|
|
if (get_request.type == GetType::Module) {
|
|
response.response = handle_get_module_config(request.origin, *config);
|
|
response.status = ResponseStatus::Ok;
|
|
} else if (get_request.type == GetType::Value) {
|
|
response = handle_get_config_value(get_request, request.origin, *config);
|
|
} else if (get_request.type == GetType::All) {
|
|
response.response = handle_get_all_configs(request.origin, *config);
|
|
response.status = ResponseStatus::Ok;
|
|
} else if (get_request.type == GetType::AllMappings) {
|
|
response.response = handle_get_all_mappings(request.origin, *config);
|
|
response.status = ResponseStatus::Ok;
|
|
}
|
|
} else if (request.type == Type::Set) {
|
|
response = handle_set_request(std::get<SetRequest>(request.request), request.origin, *config);
|
|
}
|
|
|
|
MqttMessagePayload payload{MqttMessageType::GetConfigResponse, response};
|
|
mqtt_abstraction.publish(response_topic, payload, QOS::QOS2);
|
|
|
|
} catch (const std::exception& e) {
|
|
EVLOG_error << "Exception during handling of request: " << e.what();
|
|
} catch (...) {
|
|
EVLOG_error << "Could not parse request: " << data.dump();
|
|
}
|
|
};
|
|
|
|
const std::string global_config_request_topic =
|
|
fmt::format("{}config/request", mqtt_abstraction.get_everest_prefix());
|
|
this->get_config_token = std::make_shared<TypedHandler>(HandlerType::GetConfig,
|
|
std::make_shared<Handler>(global_config_request_handler));
|
|
mqtt_abstraction.register_handler(global_config_request_topic, this->get_config_token, QOS::QOS2);
|
|
}
|
|
|
|
namespace conversions {
|
|
std::string type_to_string(Type type) {
|
|
switch (type) {
|
|
case Type::Get:
|
|
return "Get";
|
|
case Type::Set:
|
|
return "Set";
|
|
case Type::Unknown:
|
|
return "Unknown";
|
|
}
|
|
throw std::out_of_range("Could not convert Type to string");
|
|
}
|
|
|
|
Type string_to_type(const std::string& type) {
|
|
if (type == "Get") {
|
|
return Type::Get;
|
|
} else if (type == "Set") {
|
|
return Type::Set;
|
|
} else if (type == "Unknown") {
|
|
return Type::Unknown;
|
|
}
|
|
throw std::out_of_range("Could not convert " + type + " to Type");
|
|
}
|
|
|
|
std::string get_type_to_string(GetType type) {
|
|
switch (type) {
|
|
case GetType::All:
|
|
return "All";
|
|
case GetType::Module:
|
|
return "Module";
|
|
case GetType::Value:
|
|
return "Value";
|
|
case GetType::AllMappings:
|
|
return "AllMappings";
|
|
case GetType::Unknown:
|
|
return "Unknown";
|
|
}
|
|
throw std::out_of_range("Could not convert GetType to string");
|
|
}
|
|
|
|
GetType string_to_get_type(const std::string& type) {
|
|
if (type == "All") {
|
|
return GetType::All;
|
|
} else if (type == "Module") {
|
|
return GetType::Module;
|
|
} else if (type == "Value") {
|
|
return GetType::Value;
|
|
} else if (type == "AllMappings") {
|
|
return GetType::AllMappings;
|
|
} else if (type == "Unknown") {
|
|
return GetType::Unknown;
|
|
}
|
|
throw std::out_of_range("Could not convert " + type + " to GetType");
|
|
}
|
|
|
|
std::string response_status_to_string(ResponseStatus status) {
|
|
switch (status) {
|
|
case ResponseStatus::Ok:
|
|
return "Ok";
|
|
case ResponseStatus::Error:
|
|
return "Error";
|
|
case ResponseStatus::AccessDenied:
|
|
return "AccessDenied";
|
|
}
|
|
throw std::out_of_range("Could not convert ResponseStatus to string");
|
|
}
|
|
|
|
ResponseStatus string_to_response_status(const std::string& status) {
|
|
if (status == "Ok") {
|
|
return ResponseStatus::Ok;
|
|
} else if (status == "Error") {
|
|
return ResponseStatus::Error;
|
|
} else if (status == "AccessDenied") {
|
|
return ResponseStatus::AccessDenied;
|
|
}
|
|
throw std::out_of_range("Could not convert " + status + " to ResponseStatus");
|
|
}
|
|
|
|
std::string set_response_status_to_string(SetResponseStatus status) {
|
|
switch (status) {
|
|
case SetResponseStatus::Accepted:
|
|
return "Accepted";
|
|
case SetResponseStatus::Rejected:
|
|
return "Rejected";
|
|
case SetResponseStatus::RebootRequired:
|
|
return "RebootRequired";
|
|
}
|
|
throw std::out_of_range("Could not convert SetResponseStatus to string");
|
|
}
|
|
|
|
SetResponseStatus string_to_set_response_status(const std::string& status) {
|
|
if (status == "Accepted") {
|
|
return SetResponseStatus::Accepted;
|
|
} else if (status == "Rejected") {
|
|
return SetResponseStatus::Rejected;
|
|
} else if (status == "RebootRequired") {
|
|
return SetResponseStatus::RebootRequired;
|
|
}
|
|
throw std::out_of_range("Could not convert " + status + " to SetResponseStatus");
|
|
}
|
|
|
|
everest::config::SetConfigStatus set_response_status_to_set_config_status(SetResponseStatus status) {
|
|
switch (status) {
|
|
case SetResponseStatus::Accepted:
|
|
return everest::config::SetConfigStatus::Accepted;
|
|
case SetResponseStatus::Rejected:
|
|
return everest::config::SetConfigStatus::Rejected;
|
|
case SetResponseStatus::RebootRequired:
|
|
return everest::config::SetConfigStatus::RebootRequired;
|
|
}
|
|
throw std::out_of_range("Could not convert SetResponseStatus to SetConfigStatus");
|
|
}
|
|
|
|
SetResponseStatus set_config_status_to_set_response_status(everest::config::SetConfigStatus status) {
|
|
switch (status) {
|
|
case everest::config::SetConfigStatus::Accepted:
|
|
return SetResponseStatus::Accepted;
|
|
case everest::config::SetConfigStatus::Rejected:
|
|
return SetResponseStatus::Rejected;
|
|
case everest::config::SetConfigStatus::RebootRequired:
|
|
return SetResponseStatus::RebootRequired;
|
|
}
|
|
throw std::out_of_range("Could not convert SetConfigStatus to SetResponseStatus");
|
|
}
|
|
} // namespace conversions
|
|
|
|
std::ostream& operator<<(std::ostream& os, const GetType& t) {
|
|
os << conversions::get_type_to_string(t);
|
|
return os;
|
|
}
|
|
|
|
void to_json(nlohmann::json& j, const GetRequest& r) {
|
|
j = {{"type", conversions::get_type_to_string(r.type)}};
|
|
if (r.identifier.has_value()) {
|
|
j["identifier"] = r.identifier.value();
|
|
}
|
|
}
|
|
|
|
void from_json(const nlohmann::json& j, GetRequest& r) {
|
|
r.type = conversions::string_to_get_type(j.at("type"));
|
|
if (j.contains("identifier")) {
|
|
r.identifier = j.at("identifier");
|
|
}
|
|
}
|
|
|
|
void to_json(nlohmann::json& j, const SetRequest& r) {
|
|
j = {{"value", r.value}};
|
|
j["identifier"] = nlohmann::json(r.identifier);
|
|
}
|
|
|
|
void from_json(const nlohmann::json& j, SetRequest& r) {
|
|
r.identifier = j.at("identifier");
|
|
r.value = j.at("value");
|
|
}
|
|
|
|
void to_json(nlohmann::json& j, const GetResponse& r) {
|
|
j = {{"type", conversions::get_type_to_string(r.type)}, {"data", r.data}};
|
|
}
|
|
|
|
void from_json(const nlohmann::json& j, GetResponse& r) {
|
|
r.type = conversions::string_to_get_type(j.at("type"));
|
|
r.data = j.at("data");
|
|
}
|
|
|
|
void to_json(nlohmann::json& j, const SetResponse& r) {
|
|
j = {{"status", conversions::set_response_status_to_string(r.status)}};
|
|
}
|
|
|
|
void from_json(const nlohmann::json& j, SetResponse& r) {
|
|
r.status = conversions::string_to_set_response_status(j.at("status"));
|
|
}
|
|
|
|
void to_json(nlohmann::json& j, const Request& r) {
|
|
j = {{"type", conversions::type_to_string(r.type)}, {"origin", r.origin}};
|
|
j["request"] = Everest::variant_to_json(r.request);
|
|
}
|
|
|
|
void from_json(const nlohmann::json& j, Request& r) {
|
|
r.type = conversions::string_to_type(j.at("type"));
|
|
if (r.type == Type::Get) {
|
|
r.request = j.at("request").get<GetRequest>();
|
|
} else if (r.type == Type::Set) {
|
|
r.request = j.at("request").get<SetRequest>();
|
|
}
|
|
r.origin = j.at("origin");
|
|
}
|
|
|
|
void to_json(nlohmann::json& j, const Response& r) {
|
|
j = {{"status", conversions::response_status_to_string(r.status)}, {"status_info", r.status_info}};
|
|
if (r.type.has_value()) {
|
|
j["type"] = conversions::type_to_string(r.type.value());
|
|
}
|
|
j["response"] = Everest::variant_to_json(r.response);
|
|
}
|
|
|
|
void from_json(const nlohmann::json& j, Response& r) {
|
|
r.status = conversions::string_to_response_status(j.at("status"));
|
|
r.status_info = j.at("status_info");
|
|
if (j.contains("type")) {
|
|
Type type = conversions::string_to_type(j.at("type"));
|
|
r.type = type;
|
|
|
|
if (type == Type::Get) {
|
|
r.response = j.at("response").get<GetResponse>();
|
|
} else if (type == Type::Set) {
|
|
r.response = j.at("response").get<SetResponse>();
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace config
|
|
} // namespace Everest
|
|
|
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
|
void adl_serializer<everest::config::ConfigurationParameterIdentifier>::to_json(
|
|
nlohmann::json& j, const everest::config::ConfigurationParameterIdentifier& c) {
|
|
j = {{"module_id", c.module_id}, {"configuration_parameter_name", c.configuration_parameter_name}};
|
|
if (c.module_implementation_id.has_value()) {
|
|
j["module_implementation_id"] = c.module_implementation_id.value();
|
|
}
|
|
}
|
|
|
|
void adl_serializer<everest::config::ConfigurationParameterIdentifier>::from_json(
|
|
const nlohmann::json& j, everest::config::ConfigurationParameterIdentifier& c) {
|
|
c.module_id = j.at("module_id");
|
|
c.configuration_parameter_name = j.at("configuration_parameter_name");
|
|
if (j.contains("module_implementation_id")) {
|
|
c.module_implementation_id = j.at("module_implementation_id");
|
|
}
|
|
}
|
|
NLOHMANN_JSON_NAMESPACE_END
|