Leosac  0.8.0
Open Source Access Control
LibgpiodModule.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 
20 #include "LibgpiodModule.hpp"
21 #include "LibgpiodConfig.hpp"
22 #include "core/kernel.hpp"
23 #include "tools/log.hpp"
24 #include "tools/timeout.hpp"
25 #include <boost/iterator/transform_iterator.hpp>
26 #include <boost/property_tree/ptree.hpp>
27 #include <memory>
28 #include <zmqpp/context.hpp>
29 #include <zmqpp/message.hpp>
30 
31 
32 using namespace Leosac::Module::Libgpiod;
33 
34 
35 LibgpiodModule::LibgpiodModule(zmqpp::context &ctx,
36  zmqpp::socket *module_manager_pipe,
37  const boost::property_tree::ptree &config,
38  CoreUtilsPtr utils)
39  : BaseModule(ctx, module_manager_pipe, config, utils)
40  , bus_push_(ctx_, zmqpp::socket_type::push)
41  , general_cfg_(nullptr)
42 {
43  bus_push_.connect("inproc://zmq-bus-pull");
44  process_config(config);
45 
46  for (auto gpio : gpios_)
47  {
48  gpio->register_sockets(&reactor_);
49  }
50 }
51 
52 static LibgpiodPin::InterruptMode gpio_interrupt_from_string(const std::string &str)
53 {
54  if (str == "none")
56  else if (str == "both")
58  else if (str == "falling")
60  else if (str == "rising")
62  else
64 }
65 
66 void LibgpiodModule::process_config(const boost::property_tree::ptree &cfg)
67 {
68  boost::property_tree::ptree module_config = cfg.get_child("module_config");
69 
71 
72  for (auto &node : module_config.get_child("gpios"))
73  {
74  boost::property_tree::ptree gpio_cfg = node.second;
75  LibgpiodPin::Direction direction;
76  LibgpiodPin::InterruptMode interrupt_mode;
77  std::string gpio_name;
78  std::string gpio_device;
79  std::string gpio_direction;
80  std::string gpio_interrupt;
81  int gpio_offset;
82  bool gpio_initial_value;
83 
84  gpio_name = gpio_cfg.get_child("name").data();
85  gpio_device = gpio_cfg.get<std::string>("device", "leosac");
86  gpio_offset = std::stoi(gpio_cfg.get_child("offset").data());
87  gpio_direction = gpio_cfg.get_child("direction").data();
88  gpio_interrupt = gpio_cfg.get<std::string>("interrupt_mode", "none");
89  gpio_initial_value = gpio_cfg.get<bool>("value", false);
90 
91  using namespace Colorize;
92  INFO("Creating GPIO " << green(underline(gpio_name)) << ", device "
93  << green(underline(gpio_device)) << " with offset "
94  << green(underline(gpio_offset)) << ". direction = "
95  << green(underline(gpio_direction)));
96 
97  interrupt_mode = gpio_interrupt_from_string(gpio_interrupt);
98 
99  direction = (gpio_direction == "in" ? LibgpiodPin::Direction::In
101  gpios_.push_back(std::make_shared<LibgpiodPin>(ctx_, gpio_name, gpio_device, gpio_offset, direction,
102  interrupt_mode, gpio_initial_value,
103  *this));
104 
105  utils_->config_checker().register_object(gpio_name,
107  }
108 }
109 
111 {
112  for (auto gpio : gpios_)
113  gpio->release();
114 }
115 
116 void LibgpiodModule::publish_on_bus(zmqpp::message &msg)
117 {
118  bus_push_.send(msg);
119 }
120 
122 {
123  assert(general_cfg_ == nullptr);
124  general_cfg_ = std::make_shared<LibgpiodConfig>(config_.get_child("module_config"));
125 }
126 
127 std::shared_ptr<LibgpiodConfig> LibgpiodModule::general_config() const
128 {
129  return general_cfg_;
130 }
131 
133 {
134  while (is_running_)
135  {
136  auto itr_transform =
137  [](std::shared_ptr<const LibgpiodPin> p) -> std::chrono::system_clock::time_point {
138  return p->next_update();
139  };
140 
141  auto timeout = Tools::compute_timeout(
142  boost::make_transform_iterator(gpios_.begin(), itr_transform),
143  boost::make_transform_iterator(gpios_.end(), itr_transform));
144  reactor_.poll(timeout);
145  for (auto gpio_pin : gpios_)
146  {
147  if (gpio_pin->next_update() < std::chrono::system_clock::now())
148  gpio_pin->update();
149  }
150  }
151 }
Leosac::Module::BaseModule
Base class for module implementation.
Definition: BaseModule.hpp:110
Leosac::Tools::compute_timeout
int compute_timeout(InputIterator begin, InputIterator end)
Compute the time until the next timeout from a collection of time point.
Definition: timeout.hpp:39
zmqpp
Definition: CoreUtils.hpp:27
Leosac::Hardware::GPIO::Direction::Out
@ Out
Leosac::Module::Libgpiod::LibgpiodModule::process_general_config
void process_general_config()
General configuration (file paths, etc).
Definition: LibgpiodModule.cpp:121
Leosac::Hardware::DeviceClass::GPIO
@ GPIO
timeout.hpp
INFO
@ INFO
Definition: log.hpp:34
Leosac::Module::Libgpiod::LibgpiodModule::process_config
void process_config(const boost::property_tree::ptree &cfg)
Process the configuration, preparing configured GPIO pin.
Definition: LibgpiodModule.cpp:66
Leosac::Module::Libgpiod::LibgpiodPin::InterruptMode::None
@ None
Leosac::Module::Libgpiod::LibgpiodModule::bus_push_
zmqpp::socket bus_push_
Socket to write the bus.
Definition: LibgpiodModule.hpp:89
Leosac::Colorize::underline
std::string underline(const T &in)
Definition: Colorize.hpp:64
Leosac::Module::Libgpiod::LibgpiodModule::publish_on_bus
void publish_on_bus(zmqpp::message &msg)
Write the message eon the bus.
Definition: LibgpiodModule.cpp:116
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::Libgpiod::LibgpiodPin::InterruptMode::Both
@ Both
Leosac::Module::Libgpiod::LibgpiodModule::general_config
std::shared_ptr< LibgpiodConfig > general_config() const
Retrieve the config object.
Definition: LibgpiodModule.cpp:127
Leosac::Module::BaseModule::reactor_
zmqpp::reactor reactor_
The reactor object we poll() on in the main loop.
Definition: BaseModule.hpp:214
Leosac::Module::Libgpiod::LibgpiodModule::LibgpiodModule
LibgpiodModule(zmqpp::context &ctx, zmqpp::socket *module_manager_pipe, const boost::property_tree::ptree &config, CoreUtilsPtr utils)
Definition: LibgpiodModule.cpp:35
Leosac::Module::BaseModule::utils_
CoreUtilsPtr utils_
Pointer to the core utils, which gives access to scheduler and others.
Definition: BaseModule.hpp:198
Leosac::Hardware::GPIO::Direction
Direction
Definition: GPIO.hpp:44
Leosac::Module::Libgpiod
Namespace for the module that implements GPIO support using the Linux Kernel libgpiod interface.
Definition: LibgpiodConfig.hpp:32
Leosac::Module::Libgpiod::LibgpiodPin::InterruptMode::Falling
@ Falling
Leosac::Colorize::green
std::string green(const T &in)
Definition: Colorize.hpp:82
Leosac::Module::Libgpiod::LibgpiodModule::general_cfg_
std::shared_ptr< LibgpiodConfig > general_cfg_
General configuration for module.
Definition: LibgpiodModule.hpp:99
Leosac::Module::Libgpiod::LibgpiodModule::~LibgpiodModule
~LibgpiodModule()
Definition: LibgpiodModule.cpp:110
Leosac::Module::Libgpiod::LibgpiodModule::run
virtual void run() override
This is the main loop of the module.
Definition: LibgpiodModule.cpp:132
Leosac::Module::BaseModule::is_running_
bool is_running_
Boolean indicating whether the main loop should run or not.
Definition: BaseModule.hpp:203
Leosac::Module::Libgpiod::LibgpiodPin::InterruptMode
InterruptMode
Definition: LibgpiodPin.hpp:47
LibgpiodModule.hpp
Leosac::Module::Libgpiod::LibgpiodModule::gpios_
std::vector< std::shared_ptr< LibgpiodPin > > gpios_
Vector of underlying pin object.
Definition: LibgpiodModule.hpp:94
Leosac::Module::Libgpiod::LibgpiodPin::InterruptMode::Rising
@ Rising
Leosac::Hardware::GPIO::Direction::In
@ In
log.hpp
LibgpiodConfig.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