A C++ microservices framework which purpose is to simplify development of applications. How would one ask, the framework offers an API which simplifies communication between processes and runtime configuration storage.
Important this repository both contains the library API of the framework along with already made use cases(executables) like:
- IPC ruler
- tfcctl (nice utility to test with)
- Ethercat master
- MQTT-bridge
- Operation mode (start, stop, emergency, fault, etc.)
- etc.
The IPC ruler distinguishes from every other executable, as it is needed to use the communication layer. So this is the one daemon that you would need to start to make your process run.
We have many dependencies on other open source software stacks. The main being boost asio, zeromq, sdbus, json(glaze). These components will be referred to multiple times, so you might need to look up their documentation.
The communication layer uses simple predefined message format. The following message format are currently supported:
enum struct filter_e : std::uint8_t {
_bool = 1,
_int64_t = 2,
_uint64_t = 3,
_double_t = 4,
_string = 5,
_json = 6,
};
It is worth to mention that json values are passed as string through the communication channel.
What makes this communication layer unique is the simplicity to connect those channels, you are able to change connections during runtime, without restarting any process.
The terminology used in the communication layer is signals
for owner of information and slot
for connecting to signal
.
And on top of that this mechanism works like one-to-many pattern.
To gain greater depth of understanding please refer to the IPC docs.
#include <boost/asio.hpp>
#include <tfc/ipc.hpp>
using asio = boost::asio;
struct my_application {
asio::io_context& ctx;
tfc::ipc::bool_signal{ ctx, "name_of_signal", "optional description of signal" };
tfc::ipc::bool_slot{ ctx, "name_of_slot", "optional description of slot", [](bool new_value){} };
};
Each individual part of a software can own a config instance object.
The config is stored into a json file located default in /etc/tfc/
but can be overwritten with the environment variable CONFIGURATION_DIRECTORY
.
Currently, you would declare your struct for example and its according projection to json with glaze. For example:
#include <chrono>
#include <glaze/glaze.hpp>
#include <units/isq/si/si.h>
#include <tfc/confman/observable.hpp>
struct storage {
std::chrono::milliseconds drop_time{};
units::quantity<units::isq::si::dim_speed, units::isq::si::metre_per_second, int32_t> target_speed{};
tfc::confman::observable<int> state{};
struct glaze {
static constexpr auto value{ glz::object("drop_time", &storage::drop_time, "drop time description ...",
"target_speed", &storage::target_speed, "target speed description ...",
"state", &storage::state, "state description ...") };
static constexpr auto name{ "name of this storage struct" };
};
};
This struct would be wrapped with our confman class.
#include <boost/asio.hpp>
#include <fmt/chrono.hpp>
#include <tfc/confman.hpp>
using asio = boost::asio;
struct my_application {
my_application(asio::io_context& ctx) : ctx{ ctx } {
config->state.observe([](int new_value, int old_value){
// here you can get a callback whenever this one variable is changed
});
}
asio::io_context& ctx;
tfc::confman::config<storage> config{ ctx, "unique config key to this process" };
void using_config() {
fmt::print("drop time is {}", config->drop_time);
}
};
There are currently two ways of changing the config, one being through a dbus
API and the second being changing the file directly.
Disclaimer the naming scheme can change in the future.
The interface name is for example com.skaginn3x.config.etc.tfc.operation_mode.def.state_machine
which owns a dbus property of type
struct of two strings,
{
string,
string
}
The first string is the config in json format, the second string is the json schema of the configuration. To change the config you can write to the property and the process will update its config file.
There exist many dbus frontends like D-Feet which can help with understanding any dbus related API.
User can change the file on the system and the process will get notification via inotify
.
Todo
Everything will be built on CMake and using features from 3.23+ version.
Copyright 2023 Skaginn 3X ehf