Leosac  0.8.0
Open Source Access Control
MqttModule.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2022 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
21 #include "core/Scheduler.hpp"
22 #include "core/kernel.hpp"
23 #include "hardware/HardwareFwd.hpp"
26 #include "modules/mqtt/MqttConfig_odb.h"
27 #include "tools/log.hpp"
28 #include <boost/property_tree/ptree.hpp>
29 #include <memory>
30 #include <zmqpp/context.hpp>
31 #include <zmqpp/message.hpp>
32 
33 using namespace Leosac::Hardware;
34 using namespace Leosac::Module::Mqtt;
35 
36 MqttModule::MqttModule(zmqpp::context &ctx, zmqpp::socket *pipe,
37  boost::property_tree::ptree const &cfg,
38  CoreUtilsPtr utils)
39  : BaseModule(ctx, pipe, cfg, utils)
40 {
42 
43  for (auto &server : servers_)
44  {
45  server.register_sockets(&reactor_);
46  }
47 }
48 
50 {
51 }
52 
54 {
55  boost::property_tree::ptree module_config = config_.get_child("module_config");
56 
57  if (module_config.get<bool>("use_database", false))
58  {
60  }
61  else
62  {
63  load_xml_config(module_config);
64  }
65 
66  // Now we process the configuration object.
67  for (const auto &server_config : mqtt_config_->servers())
68  {
69  using namespace Colorize;
70  INFO("Creating Mqtt Server: "
71  << green(underline(server_config->name()))
72  << "\n\t Host: " << green(underline(server_config->host()))
73  << "\n\t Port: " << green(underline(server_config->port()))
74  << "\n\t Ssl: " << green(underline(server_config->ssl()))
75  << "\n\t Username: " << green(underline(server_config->username())));
76 
77  MqttExternalServer server(ctx_, server_config, mqtt_config_->topics());
78  utils_->config_checker().register_object(server.name(),
80  servers_.push_back(std::move(server));
81  }
82 }
83 
85 {
86  for (auto &server : servers_)
87  {
88  server.connect();
89  }
91  for (auto &server : servers_)
92  {
93  server.disconnect();
94  }
95 }
96 
98 {
99  using namespace odb;
100  using namespace odb::core;
101  auto db = utils_->database();
102 
103  // First we load or update database schema if needed.
104  schema_version v = db->schema_version("module_mqtt");
105  schema_version cv(schema_catalog::current_version(*db, "module_mqtt"));
106  if (v == 0)
107  {
108  transaction t(db->begin());
109  INFO("Attempt to create module_mqtt SQL schema.");
110  schema_catalog::create_schema(*db, "module_mqtt");
111  t.commit();
112  }
113  else if (v < cv)
114  {
115  INFO("Mqtt Module performing database migration. Going from version "
116  << v << " to version " << cv);
117  transaction t(db->begin());
118  schema_catalog::migrate(*db, cv, "module_mqtt");
119  t.commit();
120  }
121 
122  // Create empty configuration object...
123  mqtt_config_ = std::make_unique<MqttConfig>();
124 
125  // ... then loads servers from database.
126  odb::transaction t(utils_->database()->begin());
127  odb::result<MqttServerConfig> sresult(
128  utils_->database()->query<MqttServerConfig>());
129  for (const auto &server : sresult)
130  {
131  MqttServerConfigPtr server_ptr =
132  db->load<MqttServerConfig>(server.id());
133  ASSERT_LOG(server_ptr, "Loading from database/cache failed");
134  if (server_ptr->enabled())
135  mqtt_config_->add_server(server_ptr);
136  }
137  t.commit();
138 
139  // ... and topics
140  odb::transaction t2(utils_->database()->begin());
141  odb::result<MqttExternalMessage> tresult(
142  utils_->database()->query<MqttExternalMessage>());
143  for (const auto &topic : tresult)
144  {
145  std::shared_ptr<MqttExternalMessage> topic_ptr =
146  db->load<MqttExternalMessage>(topic.id());
147  ASSERT_LOG(topic_ptr == nullptr, "Loading from database/cache failed");
148  if (topic_ptr->enabled())
149  mqtt_config_->add_topic(topic_ptr);
150  }
151  t2.commit();
152  INFO("Mqtt module using SQL database for configuration.");
153 }
154 
156  const boost::property_tree::ptree &module_config)
157 {
158  mqtt_config_ = std::make_unique<MqttConfig>();
159  for (auto &node : module_config.get_child("servers"))
160  {
161  auto server_config = std::make_shared<MqttServerConfig>();
162  boost::property_tree::ptree xml_server_cfg = node.second;
163 
164  server_config->name(xml_server_cfg.get_child("name").data());
165  server_config->host(xml_server_cfg.get<std::string>("host", "localhost"));
166  server_config->port(xml_server_cfg.get<uint16_t>("port", 1883));
167  server_config->client_id_ = xml_server_cfg.get<std::string>("client_id", "leosac");
168  server_config->subscribe_prefix_ = xml_server_cfg.get<std::string>("subscribe_prefix", "homeassistant/");
169  server_config->publish_prefix_ = xml_server_cfg.get<std::string>("publish_prefix", "leosac/");
170  server_config->username_ = xml_server_cfg.get<std::string>("username", "");
171  server_config->password_ = xml_server_cfg.get<std::string>("password", "");
172  server_config->ssl_ = xml_server_cfg.get<bool>("ssl", false);
173  server_config->ssl_ca_certs_ = xml_server_cfg.get<std::string>("ssl_ca_certs", "");
174  server_config->ssl_client_certfile_ = xml_server_cfg.get<std::string>("ssl_client_certfile", "");
175  server_config->ssl_client_keyfile_ = xml_server_cfg.get<std::string>("ssl_client_keyfile", "");
176  server_config->ssl_insecure_ = xml_server_cfg.get<bool>("ssl_insecure", false);
177 
178  mqtt_config_->add_server(server_config);
179  }
180 
181  for (const auto &node : module_config.get_child("topics"))
182  {
183  auto topic_config = std::make_shared<MqttExternalMessage>();
184  boost::property_tree::ptree xml_topic_cfg = node.second;
185 
186  std::string direction;
187  std::string virtualtype;
188 
189  topic_config->name(xml_topic_cfg.get_child("name").data());
190  topic_config->subject(xml_topic_cfg.get_child("subject").data());
191  direction = xml_topic_cfg.get_child("direction").data();
193  virtualtype = xml_topic_cfg.get_child("virtualtype").data();
194  if (virtualtype == "rfidreader")
195  {
196  topic_config->virtualtype(Leosac::Hardware::DeviceClass::RFID_READER);
197  }
198  else if (virtualtype == "led")
199  {
200  topic_config->virtualtype(Leosac::Hardware::DeviceClass::LED);
201  }
202  else if (virtualtype == "buzzer")
203  {
204  topic_config->virtualtype(Leosac::Hardware::DeviceClass::BUZZER);
205  }
206  else
207  {
208  topic_config->virtualtype(Leosac::Hardware::DeviceClass::GPIO);
209  }
210  topic_config->payload(xml_topic_cfg.get<std::string>("payload", ""));
211 
212  mqtt_config_->add_topic(topic_config);
213  }
214 }
Leosac::Module::Mqtt::MqttModule::load_xml_config
void load_xml_config(const boost::property_tree::ptree &module_config)
Load the module configuration from the XML configuration object.
Definition: MqttModule.cpp:155
Leosac::Hardware::DeviceClass::RFID_READER
@ RFID_READER
Leosac::Module::Mqtt::MqttServerConfig
An instance of this class represents the configuration of one Mqtt server.
Definition: MqttConfig.hpp:44
Leosac::Module::BaseModule
Base class for module implementation.
Definition: BaseModule.hpp:110
MqttModule.hpp
ExternalMessage.hpp
Leosac::Module::Mqtt::MqttModule::run
virtual void run() override
This is the main loop of the module.
Definition: MqttModule.cpp:84
ASSERT_LOG
#define ASSERT_LOG(cond, msg)
Definition: log.hpp:190
Leosac::Hardware::DeviceClass::GPIO
@ GPIO
Leosac::Hardware::ExternalMessage::Direction::Publish
@ Publish
INFO
@ INFO
Definition: log.hpp:34
Leosac::Hardware::DeviceClass::BUZZER
@ BUZZER
odb
Provide ODB magic to be able to store an Leosac::Audit::EventType (FlagSet) object.
Definition: AuditEventMaskODB.hpp:31
Scheduler.hpp
Leosac::Colorize::underline
std::string underline(const T &in)
Definition: Colorize.hpp:64
Leosac::Hardware::ExternalMessage::Direction::Subscribe
@ Subscribe
Leosac::Module::Mqtt::MqttExternalServer
Implementation class, for use by the Mqtt module only.
Definition: MqttExternalServer.hpp:38
kernel.hpp
Leosac::Module::BaseModule::config_
boost::property_tree::ptree config_
The configuration tree passed to the start_module function.
Definition: BaseModule.hpp:193
Leosac::Module::Mqtt::MqttModule::servers_
std::vector< MqttExternalServer > servers_
Vector of mqtt connections managed by this module.
Definition: MqttModule.hpp:75
Leosac::Module::BaseModule::reactor_
zmqpp::reactor reactor_
The reactor object we poll() on in the main loop.
Definition: BaseModule.hpp:214
Leosac::Module::BaseModule::utils_
CoreUtilsPtr utils_
Pointer to the core utils, which gives access to scheduler and others.
Definition: BaseModule.hpp:198
Leosac::Module::Mqtt::MqttExternalMessage
Definition: MqttConfig.hpp:125
Leosac::Hardware::DeviceClass::EXTERNAL_SERVER
@ EXTERNAL_SERVER
Leosac::Module::Mqtt::MqttExternalServer::name
const std::string & name() const
Definition: MqttExternalServer.cpp:344
Leosac::Module::Mqtt::MqttModule::load_db_config
void load_db_config()
Load the module configuration from the database.
Definition: MqttModule.cpp:97
Leosac::Colorize::green
std::string green(const T &in)
Definition: Colorize.hpp:82
HardwareFwd.hpp
HardwareService.hpp
Leosac::Module::BaseModule::run
virtual void run()
This is the main loop of the module.
Definition: BaseModule.cpp:48
Leosac::Hardware::Device::enabled
bool enabled() const
Definition: Device.cpp:75
Leosac::Module::Mqtt::MqttModule::process_config
void process_config()
Create Mqtt server instances based on configuration.
Definition: MqttModule.cpp:53
Leosac::Module::Mqtt
Provide support for Mqtt.
Definition: MqttConfig.cpp:28
Leosac::Module::Mqtt::MqttServerConfigPtr
std::shared_ptr< MqttServerConfig > MqttServerConfigPtr
Definition: MqttFwd.hpp:31
log.hpp
Leosac::Module::BaseModule::ctx_
zmqpp::context & ctx_
A reference to the ZeroMQ context in case you need it to create additional socket.
Definition: BaseModule.hpp:183
Leosac::CoreUtilsPtr
std::shared_ptr< CoreUtils > CoreUtilsPtr
Definition: LeosacFwd.hpp:35
Leosac::Hardware
Provides facade classes to hardware device implementation.
Definition: Buzzer.cpp:25
Leosac::Hardware::DeviceClass::LED
@ LED
Leosac::Module::Mqtt::MqttModule::mqtt_config_
std::unique_ptr< MqttConfig > mqtt_config_
Configuration object for the module.
Definition: MqttModule.hpp:80
Leosac::Module::Mqtt::MqttModule::~MqttModule
~MqttModule() override
Definition: MqttModule.cpp:49