// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include #include #include #include #include #include #include #include #include namespace settings { Settings::Settings(sys::Service *app, const std::string &dbAgentName) : dbAgentName(dbAgentName) { this->app = std::shared_ptr(app, [](sys::Service *) {}); /// with deleter that doesn't delete. this->app->busChannels.push_back(sys::BusChannels::ServiceDBNotifications); sys::Bus::Add(std::static_pointer_cast(this->app)); registerHandlers(); } Settings::~Settings() { LOG_DEBUG("Settings::~Settings on %s", app->GetName().c_str()); sys::Bus::Remove(std::static_pointer_cast(app)); } void Settings::sendMsg(std::shared_ptr &&msg) { sys::Bus::SendUnicast(std::move(msg), dbAgentName, app.get()); } void Settings::registerHandlers() { using std::placeholders::_1; using std::placeholders::_2; LOG_DEBUG("Settings::registerHandlers for %s", app->GetName().c_str()); app->connect(settings::Messages::VariableChanged(), std::bind(&Settings::handleVariableChanged, this, _1)); app->connect(settings::Messages::CurrentProfileChanged(), std::bind(&Settings::handleCurrentProfileChanged, this, _1)); app->connect(settings::Messages::CurrentModeChanged(), std::bind(&Settings::handleCurrentModeChanged, this, _1)); app->connect(settings::Messages::ProfileListResponse(), std::bind(&Settings::handleProfileListResponse, this, _1)); app->connect(settings::Messages::ModeListResponse(), std::bind(&Settings::handleModeListResponse, this, _1)); } auto Settings::handleVariableChanged(sys::Message *req) -> sys::MessagePointer { LOG_DEBUG("handleVariableChanged"); if (auto msg = dynamic_cast(req)) { auto key = msg->getPath().variable; auto val = msg->getValue(); LOG_DEBUG("handleVariableChanged: (k=v): (%s=%s)", key.c_str(), val.value_or("").c_str()); ValueCb::iterator it_cb = cbValues.find(key); if (cbValues.end() != it_cb) { auto [cb, cbWithName] = it_cb->second; if (nullptr != cb && nullptr != cbWithName) { // in case of two callbacks there is a need to duplicate the value auto value = std::move(val.value_or("")); cb(std::string{value}); cbWithName(key, std::move(value)); } else if (nullptr != cb) { cb(std::move(val.value_or(""))); } else { cbWithName(key, std::move(val.value_or(""))); } } } return std::make_shared(); } auto Settings::handleCurrentProfileChanged(sys::Message *req) -> sys::MessagePointer { LOG_DEBUG("handleCurrentProfileChanged"); if (auto msg = dynamic_cast(req)) { auto profile = msg->getProfileName(); LOG_DEBUG("handleCurrentProfileChanged: %s", profile.c_str()); cbProfile(profile); } return std::make_shared(); } auto Settings::handleCurrentModeChanged(sys::Message *req) -> sys::MessagePointer { LOG_DEBUG("handleCurrentModeChanged"); if (auto msg = dynamic_cast(req)) { auto mode = msg->getProfileName(); LOG_DEBUG("handleCurrentModeChanged: %s", mode.c_str()); cbMode(mode); } return std::make_shared(); } auto Settings::handleProfileListResponse(sys::Message *req) -> sys::MessagePointer { LOG_DEBUG("handleProfileListResponse"); if (auto msg = dynamic_cast(req)) { auto profiles = msg->getValue(); LOG_DEBUG("handleProfileListResponse: %zu elements", profiles.size()); cbAllProfiles(profiles); } return std::make_shared(); } auto Settings::handleModeListResponse(sys::Message *req) -> sys::MessagePointer { LOG_DEBUG("handleModeListResponse"); if (auto msg = dynamic_cast(req)) { auto modes = msg->getValue(); LOG_DEBUG("handleModeListResponse: %zu elements", modes.size()); cbAllModes(modes); } return std::make_shared(); } void Settings::registerValueChange(const std::string &variableName, ValueChangedCallback cb) { ValueCb::iterator it_cb = cbValues.find(variableName); if (cbValues.end() != it_cb && nullptr != it_cb->second.first) { LOG_INFO("Callback function on value change (%s) already exists, rewriting", variableName.c_str()); } cbValues[variableName].first = cb; EntryPath path; path.variable = variableName; path.service = app->GetName(); auto msg = std::make_shared(path); sendMsg(std::move(msg)); } void Settings::registerValueChange(const std::string &variableName, ValueChangedCallbackWithName cb) { auto it_cb = cbValues.find(variableName); if (cbValues.end() != it_cb && nullptr != it_cb->second.second) { LOG_INFO("Callback function on value change (%s) already exists, rewriting", variableName.c_str()); } cbValues[variableName].second = cb; EntryPath path; path.variable = variableName; path.service = app->GetName(); auto msg = std::make_shared(path); sendMsg(std::move(msg)); } void Settings::unregisterValueChange(const std::string &variableName) { ValueCb::iterator it_cb = cbValues.find(variableName); if (cbValues.end() == it_cb) { LOG_INFO("Callback function on value change (%s) does not exist", variableName.c_str()); } else { cbValues.erase(it_cb); } EntryPath path; path.variable = variableName; path.service = app->GetName(); auto msg = std::make_shared(path); sendMsg(std::move(msg)); } void Settings::setValue(const std::string &variableName, const std::string &variableValue) { EntryPath path; path.variable = variableName; path.service = app->GetName(); auto msg = std::make_shared(path, variableValue); sendMsg(std::move(msg)); } void Settings::getAllProfiles(OnAllProfilesRetrievedCallback cb) { if (nullptr == cbAllProfiles) { sendMsg(std::make_shared()); } cbAllProfiles = cb; } void Settings::setCurrentProfile(const std::string &profile) { sendMsg(std::make_shared(profile)); } void Settings::addProfile(const std::string &profile) { sendMsg(std::make_shared(profile)); } void Settings::registerProfileChange(ProfileChangedCallback cb) { if (nullptr != cbProfile) { LOG_DEBUG("Profile change callback already exists, overwritting"); } else { sendMsg(std::make_shared()); } cbProfile = cb; } void Settings::unregisterProfileChange() { cbProfile = nullptr; sendMsg(std::make_shared()); } void Settings::getAllModes(OnAllModesRetrievedCallback cb) { if (nullptr == cbAllModes) { sendMsg(std::make_shared()); } cbAllModes = cb; } void Settings::setCurrentMode(const std::string &mode) { sendMsg(std::make_shared(mode)); } void Settings::addMode(const std::string &mode) { sendMsg(std::make_shared(mode)); } void Settings::registerModeChange(ModeChangedCallback cb) { if (nullptr != cbMode) { LOG_DEBUG("ModeChange callback allready set overwriting"); } else { sendMsg(std::make_shared()); } cbMode = cb; } void Settings::unregisterModeChange() { cbMode = nullptr; sendMsg(std::make_shared()); } } // namespace settings