This repository was archived by the owner on Dec 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy patheverest.hpp
More file actions
280 lines (231 loc) · 10.7 KB
/
everest.hpp
File metadata and controls
280 lines (231 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef FRAMEWORK_EVEREST_HPP
#define FRAMEWORK_EVEREST_HPP
#include <chrono>
#include <functional>
#include <future>
#include <map>
#include <set>
#include <thread>
#include <variant>
#include <everest/exceptions.hpp>
#include <utils/config.hpp>
#include <utils/error.hpp>
#include <utils/mqtt_abstraction.hpp>
#include <utils/types.hpp>
namespace Everest {
///
/// \brief A structure that contains a command definition for a cmd of a module
///
struct cmd {
std::string impl_id; ///< The implementation id of the command
std::string cmd_name; ///< The name of the command
Command cmd; ///< The callback function
Arguments arg_types; ///< The argument types
ReturnType return_type; ///< The return type
};
using TelemetryEntry = std::variant<std::string, const char*, bool, int32_t, uint32_t, int64_t, uint64_t, double>;
using TelemetryMap = std::map<std::string, TelemetryEntry>;
using UnsubscribeToken = std::function<void()>;
namespace error {
struct ErrorDatabaseMap;
struct ErrorManagerImpl;
struct ErrorManagerReq;
struct ErrorManagerReqGlobal;
struct ErrorStateMonitor;
struct ErrorFactory;
} // namespace error
///
/// \brief Contains the EVerest framework that provides convenience functionality for implementing EVerest modules
///
class Everest {
public:
Everest(std::string module_id, const Config& config, bool validate_data_with_schema,
std::shared_ptr<MQTTAbstraction> mqtt_abstraction, const std::string& telemetry_prefix,
bool telemetry_enabled);
// forbid copy assignment and copy construction
// NOTE (aw): move assignment and construction are also not supported because we're creating explicit references to
// our instance due to callback registration
Everest(Everest const&) = delete;
void operator=(Everest const&) = delete;
nlohmann::json get_cmd_definition(const std::string& module_id, const std::string& impl_id,
const std::string& cmd_name, bool is_call);
nlohmann::json get_cmd_definition(const std::string& module_id, const std::string& impl_id,
const std::string& cmd_name);
///
/// \brief Allows a module to indicate that it provides the given command \p cmd
///
void provide_cmd(const std::string& impl_id, const std::string& cmd_name, const JsonCommand& handler);
void provide_cmd(const cmd& cmd);
///
/// \brief Provides functionality for calling commands of other modules. The module is identified by the given \p
/// req, the command by the given command name \p cmd_name and the needed arguments by \p args
///
nlohmann::json call_cmd(const Requirement& req, const std::string& cmd_name, json args);
///
/// \brief Publishes a variable of the given \p impl_id, names \p var_name with the given \p value
///
void publish_var(const std::string& impl_id, const std::string& var_name, nlohmann::json value);
///
/// \brief Subscribes to a variable of another module identified by the given \p req and variable name \p
/// var_name. The given \p callback is called when a new value becomes available
///
void subscribe_var(const Requirement& req, const std::string& var_name, const JsonCallback& callback);
///
/// \brief Return the error manager for the given \p impl_id
///
std::shared_ptr<error::ErrorManagerImpl> get_error_manager_impl(const std::string& impl_id);
///
/// \brief Return the error state monitor for the given \p impl_id
///
std::shared_ptr<error::ErrorStateMonitor> get_error_state_monitor_impl(const std::string& impl_id);
///
/// \brief Return the error factory for the given \p impl_id
///
std::shared_ptr<error::ErrorFactory> get_error_factory(const std::string& impl_id);
///
/// \brief Return the error manager for the given \p req
///
std::shared_ptr<error::ErrorManagerReq> get_error_manager_req(const Requirement& req);
///
/// \brief Return the error state monitor for the given \p req
std::shared_ptr<error::ErrorStateMonitor> get_error_state_monitor_req(const Requirement& req);
///
/// \brief Return the global error manager, if not enabled nullptr
std::shared_ptr<error::ErrorManagerReqGlobal> get_global_error_manager() const;
///
/// \brief Return the global state monitor, if not enabled nullptr
std::shared_ptr<error::ErrorStateMonitor> get_global_error_state_monitor() const;
///
/// \brief publishes the given \p data on the given \p topic
///
void external_mqtt_publish(const std::string& topic, const std::string& data);
///
/// \brief Allows a module to indicate that it provides a external mqtt \p handler at the given \p topic
///
UnsubscribeToken provide_external_mqtt_handler(const std::string& topic, const StringHandler& handler);
///
/// \brief Allows a module to indicate that it provides a external mqtt \p handler at the given \p topic
///
UnsubscribeToken provide_external_mqtt_handler(const std::string& topic, const StringPairHandler& handler);
///
/// \brief publishes the given telemetry \p data on the given \p topic
///
void telemetry_publish(const std::string& topic, const std::string& data);
///
/// \brief publishes the given telemetry \p telemetry on a topic constructed from \p category \p subcategory and \p
/// type
///
void telemetry_publish(const std::string& category, const std::string& subcategory, const std::string& type,
const TelemetryMap& telemetry);
/// \returns true if telemetry is enabled
bool is_telemetry_enabled();
///
/// \returns the 3 tier model mappings for this module
///
std::optional<ModuleTierMappings> get_3_tier_model_mapping();
///
/// \brief Chccks if all commands of a module that are listed in its manifest are available
///
void check_code();
///
/// \brief Calls the connect method of the MQTTAbstraction to connect to the MQTT broker
///
bool connect();
///
/// \brief Calls the disconnect method of the MQTTAbstraction to disconnect from the MQTT broker
///
void disconnect();
///
/// \brief Initiates spawning the MQTT main loop thread
///
void spawn_main_loop_thread();
///
/// \brief Wait for main loop thread to end
///
void wait_for_main_loop_end();
///
/// \brief Ready Handler for local readyness (e.g. this module is now ready)
///
void signal_ready();
///
/// \brief registers a callback \p handler that is called when the global ready signal is received via mqtt
///
void register_on_ready_handler(const std::function<void()>& handler);
private:
std::shared_ptr<MQTTAbstraction> mqtt_abstraction;
Config config;
std::string module_id;
std::map<std::string, std::shared_ptr<error::ErrorManagerImpl>> impl_error_managers; // one per implementation
std::map<std::string, std::shared_ptr<error::ErrorStateMonitor>>
impl_error_state_monitors; // one per implementation
std::map<std::string, std::shared_ptr<error::ErrorFactory>> error_factories; // one per implementation
std::map<Requirement, std::shared_ptr<error::ErrorManagerReq>> req_error_managers; // one per requirement
std::map<Requirement, std::shared_ptr<error::ErrorStateMonitor>> req_error_state_monitors; // one per requirement
std::shared_ptr<error::ErrorManagerReqGlobal> global_error_manager; // nullptr if not enabled in manifest
std::shared_ptr<error::ErrorStateMonitor> global_error_state_monitor; // nullptr if not enabled in manifest
std::map<std::string, std::set<std::string>> registered_cmds;
bool ready_received;
std::chrono::seconds remote_cmd_res_timeout;
bool validate_data_with_schema;
std::unique_ptr<std::function<void()>> on_ready;
std::thread heartbeat_thread;
std::string module_name;
std::shared_future<void> main_loop_end{};
nlohmann::json module_manifest;
nlohmann::json module_classes;
std::string mqtt_everest_prefix;
std::string mqtt_external_prefix;
std::string telemetry_prefix;
std::optional<TelemetryConfig> telemetry_config;
bool telemetry_enabled;
std::optional<ModuleTierMappings> module_tier_mappings;
void handle_ready(const nlohmann::json& data);
void heartbeat();
void publish_metadata();
static std::string check_args(const Arguments& func_args, nlohmann::json manifest_args);
static bool check_arg(ArgumentType arg_types, nlohmann::json manifest_arg);
///
/// \brief Publishes the given \p error as a cleared error
///
void publish_cleared_error(const std::string& impl_id, const error::Error& error);
///
/// \brief Publishes the given \p error as a raised error
///
void publish_raised_error(const std::string& impl_id, const error::Error& error);
///
/// \brief Subscribes to an error of another module indentified by the given \p req and error type
/// \p error_type. The given \p callback is called when a new error is raised and \p clear_callback is called when
/// an error is cleared
///
void subscribe_error(const Requirement& req, const error::ErrorType& error_type,
const error::ErrorCallback& callback, const error::ErrorCallback& clear_callback);
///
/// \brief Subscribes globally to all errors of all modules. The given \p callback is called when a new error is
/// raised. The given \p clear_callback is called when an error is cleared
///
void subscribe_global_all_errors(const error::ErrorCallback& callback, const error::ErrorCallback& clear_callback);
///
/// \brief Check that external MQTT is configured - raises exception on error
///
void check_external_mqtt();
///
/// \brief Check that external MQTT is configured - raises exception on error
/// \returns the full external MQTT topic
///
std::string check_external_mqtt(const std::string& topic);
///
/// \brief Create external MQTT with an unsubscribe token
/// \returns the unsubscribe token
///
UnsubscribeToken create_external_handler(const std::string& topic, const std::string& external_topic,
const StringPairHandler& handler);
};
///
/// \returns the 3 tier model mapping from a \p module_tier_mapping for the given \p impl_id
///
std::optional<Mapping> get_impl_mapping(std::optional<ModuleTierMappings> module_tier_mappings,
const std::string& impl_id);
} // namespace Everest
#endif // FRAMEWORK_EVEREST_HPP