MQTTSuite
Loading...
Searching...
No Matches
ConfigApplication.cpp
Go to the documentation of this file.
1/*
2 * MQTTSuite - A lightweight MQTT Integration System
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2022, 2023, 2024, 2025, 2026
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20/*
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
43
44#include "MqttMapper.h"
45
46#ifndef DOXYGEN_SHOULD_SKIP_THIS
47
48#include "log/Logger.h"
49
50#include <exception>
51#include <fstream>
52#include <iterator>
53#include <map>
54#include <stdexcept>
55//
56#include <nlohmann/json_fwd.hpp>
57
58#endif
59
60namespace mqtt::lib {
61
62 template <typename ConcretConfigApplication>
63 ConfigApplication::ConfigApplication(utils::SubCommand* parent, ConcretConfigApplication* concretConfigApplication)
64 : utils::SubCommand(parent, concretConfigApplication, "Applications")
65 , mqttMapper(std::make_shared<MqttMapper>())
66 , mappingFileOpt( //
67 addOptionFunction( //
68 "--mqtt-mapping-file",
69 [this](const std::string& mappFilename) {
70 try {
71 loadMapping(mappFilename);
72 } catch (std::runtime_error& e) {
73 this->mapFilename.clear();
74
75 throw CLI::ValidationError(getName(),
76 std::string("Activating mapping description in '" + mappFilename +
77 "' failed\n"
78 "What: " +
79 e.what()));
80 }
81 },
82 "MQTT mapping file (json format) for integration",
83 "filename",
84 !CLI::ExistingDirectory))
85 , sessionStoreOpt( //
86 addOption( //
87 "--mqtt-session-store",
88 "Path to file for the persistent session store",
89 "filename",
90 !CLI::ExistingDirectory)) {
91 }
92
94
95 ConfigApplication& ConfigApplication::setSessionStore(const std::string& sessionStore) {
96 setDefaultValue(sessionStoreOpt, sessionStore);
97
98 return *this;
99 }
100
101 std::string ConfigApplication::getSessionStore() const {
102 return sessionStoreOpt->as<std::string>();
103 }
104
105 const std::shared_ptr<MqttMapper> ConfigApplication::getMqttMapper() const {
106 return mqttMapper;
107 }
108
109 bool ConfigApplication::setMappingFile(const std::string& mapFilename) {
110 setDefaultValue(mappingFileOpt, mapFilename);
111
112 return loadMapping(mapFilename);
113 }
114
116 return mapFilename;
117 }
118
119 bool ConfigApplication::setMapping(const std::string& mapping) const {
120 return mqttMapper->setMapping(nlohmann::json::parse(mapping));
121 }
122
123 std::string ConfigApplication::getMapping(int indent) const {
124 return mqttMapper->getMapping().dump(indent);
125 }
126
128 bool success = false;
129
130 std::ofstream mapFile(mapFilename, std::ios::trunc);
131 if (mapFile.is_open()) {
132 try {
133 mapFile << getMapping();
134
135 success = true;
136
137 VLOG(1) << "Write mapping file seccess";
138 } catch (const std::exception& e) {
139 VLOG(1) << "Write mapping file failed: " << e.what();
140 }
141
142 mapFile.close();
143 } else {
144 VLOG(1) << "Cannot open mapping file for writing: " << mapFilename;
145 }
146
147 return success;
148 }
149
150 bool ConfigApplication::loadMapping(const std::string mapFilename) {
151 VLOG(1) << "Mapping file: " << mapFilename;
152
153 this->mapFilename = mapFilename;
154
155 bool mustReconnect = true;
156
157 if (!mapFilename.empty()) {
158 std::ifstream mapFile(mapFilename);
159
160 if (mapFile.is_open()) {
161 try {
162 mustReconnect = setMapping({std::istreambuf_iterator<char>(mapFile), std::istreambuf_iterator<char>()});
163
164 mapFile.close();
165
166 VLOG(1) << "Load mapping file success";
167 } catch (const std::exception& e) {
168 mapFile.close();
169
170 throw std::runtime_error("Loading mapping description from '" + mapFilename +
171 "' failed\n"
172 "What: " +
173 e.what());
174 }
175
176 } else {
177 VLOG(1) << "Mapping file '" + mapFilename +
178 "' not found. Please provide a valid mapping file with the option --mqtt-mapping-file";
179 }
180 }
181
182 return mustReconnect;
183 }
184
185 ConfigMqttBroker::ConfigMqttBroker(utils::SubCommand* parent)
186 : ConfigApplication(parent, this)
187 , htmlRootOpt( //
188 addOption( //
189 "--html-root",
190 "HTML root directory",
191 "directory",
192 CLI::ExistingDirectory)) {
193 required(htmlRootOpt);
194 }
195
197
198 ConfigMqttBroker& ConfigMqttBroker::setHtmlRoot(const std::string& htmlRoot) {
199 setDefaultValue(htmlRootOpt, htmlRoot);
200 required(htmlRootOpt, false);
201
202 return *this;
203 }
204
206 std::string htmlRoot;
207
208 return htmlRootOpt->as<std::string>();
209 }
210
211 ConfigMqttIntegrator::ConfigMqttIntegrator(utils::SubCommand* parent)
212 : ConfigApplication(parent, this) {
213 }
214
216
217} // namespace mqtt::lib
std::string getMapping(int indent=2) const
bool loadMapping(const std::string mapFilename)
std::string getMappingFilename() const
bool setMapping(const std::string &mapping) const
const std::shared_ptr< MqttMapper > getMqttMapper() const
bool setMappingFile(const std::string &mapFilename)
ConfigApplication & setSessionStore(const std::string &sessionStore)
ConfigApplication(utils::SubCommand *parent, ConcretConfigApplicationT *concretConfigApplication)
std::shared_ptr< MqttMapper > mqttMapper
ConfigMqttBroker & setHtmlRoot(const std::string &htmlRoot)
ConfigMqttBroker(utils::SubCommand *parent)
ConfigMqttIntegrator(utils::SubCommand *parent)
bool setMapping(nlohmann::json mappingJson)
const nlohmann::json & getMapping() const