blob: 7e5d4964fb2d6da033005895a69ec6f4da41ed78 [file] [log] [blame]
Matthew Bartha227a162020-08-05 10:51:45 -05001/**
Mike Cappsb2e9a4f2022-06-13 10:15:42 -04002 * Copyright © 2022 IBM Corporation
Matthew Bartha227a162020-08-05 10:51:45 -05003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
Matthew Barthd9cb63b2021-03-24 14:36:49 -050018#include "action.hpp"
Matthew Barth44ab7692021-03-26 11:40:10 -050019#include "event.hpp"
Matthew Barthd9cb63b2021-03-24 14:36:49 -050020#include "group.hpp"
Matthew Barthacd737c2021-03-04 11:04:01 -060021#include "json_config.hpp"
Matthew Barth48f44da2021-05-27 15:43:34 -050022#include "power_state.hpp"
Matthew Barth06764942021-03-04 09:28:40 -060023#include "profile.hpp"
Matthew Barth9403a212021-05-17 09:31:50 -050024#include "sdbusplus.hpp"
Matthew Barthbd52ed02022-02-07 15:15:10 -060025#include "utils/flight_recorder.hpp"
Matthew Barthacd737c2021-03-04 11:04:01 -060026#include "zone.hpp"
Matthew Barth06764942021-03-04 09:28:40 -060027
Matthew Bartha227a162020-08-05 10:51:45 -050028#include <nlohmann/json.hpp>
Anwaar Hadi64b5ac22025-04-04 23:54:53 +000029#include <phosphor-logging/lg2.hpp>
Matthew Bartha227a162020-08-05 10:51:45 -050030#include <sdbusplus/bus.hpp>
Matthew Barth1542fb52021-06-10 14:09:09 -050031#include <sdbusplus/server/manager.hpp>
Matthew Barth06764942021-03-04 09:28:40 -060032#include <sdeventplus/event.hpp>
Matt Spinler2fc0a352021-10-04 15:10:57 -050033#include <sdeventplus/source/event.hpp>
Matthew Barthd9cb63b2021-03-24 14:36:49 -050034#include <sdeventplus/utility/timer.hpp>
35
36#include <chrono>
Patrick Williamsfbf47032023-07-17 12:27:34 -050037#include <format>
Matthew Barthd9cb63b2021-03-24 14:36:49 -050038#include <map>
39#include <memory>
40#include <optional>
41#include <tuple>
42#include <utility>
43#include <vector>
Matthew Bartha227a162020-08-05 10:51:45 -050044
45namespace phosphor::fan::control::json
46{
47
48using json = nlohmann::json;
49
Matthew Barthacd737c2021-03-04 11:04:01 -060050/* Application name to be appended to the path for loading a JSON config file */
51constexpr auto confAppName = "control";
52
Matthew Barthd9cb63b2021-03-24 14:36:49 -050053/* Type of timers supported */
54enum class TimerType
55{
56 oneshot,
57 repeating,
58};
Mike Cappsb2e9a4f2022-06-13 10:15:42 -040059
Matthew Barthd9cb63b2021-03-24 14:36:49 -050060/**
61 * Package of data required when a timer expires
62 * Tuple constructed of:
63 * std::string = Timer package unique identifier
Matthew Barthd9cb63b2021-03-24 14:36:49 -050064 * std::vector<std::unique_ptr<ActionBase>> = List of pointers to actions
65 * that run when the timer expires
Matt Spinlerade0c372021-10-28 16:09:44 -050066 * const std::vector<Group> = List of groups
67 * bool = If groups should be preloaded before actions are run
Matthew Barthd9cb63b2021-03-24 14:36:49 -050068 */
Matthew Barth00f6aa02021-04-09 10:49:47 -050069using TimerPkg =
Matt Spinlerade0c372021-10-28 16:09:44 -050070 std::tuple<std::string, std::vector<std::unique_ptr<ActionBase>>&,
71 const std::vector<Group>&, bool>;
Matthew Barthd9cb63b2021-03-24 14:36:49 -050072/**
73 * Data associated with a running timer that's used when it expires
74 * Pair constructed of:
75 * TimerType = Type of timer to manage expired timer instances
76 * TimerPkg = Package of data required when the timer expires
77 */
78using TimerData = std::pair<TimerType, TimerPkg>;
79/* Dbus event timer */
80using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
81
Matthew Barthebabc042021-05-13 15:38:58 -050082/* Dbus signal object */
83constexpr auto Path = 0;
84constexpr auto Intf = 1;
85constexpr auto Prop = 2;
86using SignalObject = std::tuple<std::string, std::string, std::string>;
87/* Dbus signal actions */
Matt Spinlerd0ba86a2021-11-09 10:09:13 -060088using TriggerActions =
Matthew Barthc3a69082021-11-15 14:32:48 -060089 std::vector<std::reference_wrapper<std::unique_ptr<ActionBase>>>;
Matthew Barthebabc042021-05-13 15:38:58 -050090/**
91 * Signal handler function that handles parsing a signal's message for a
92 * particular signal object and stores the results in the manager
93 */
Patrick Williamscb356d42022-07-22 19:26:53 -050094using SignalHandler =
95 std::function<bool(sdbusplus::message_t&, const SignalObject&, Manager&)>;
Matthew Barthebabc042021-05-13 15:38:58 -050096/**
97 * Package of data required when a signal is received
98 * Tuple constructed of:
99 * SignalHandler = Signal handler function
100 * SignalObject = Dbus signal object
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600101 * TriggerActions = List of actions that are run when the signal is received
Matthew Barthebabc042021-05-13 15:38:58 -0500102 */
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600103using SignalPkg = std::tuple<SignalHandler, SignalObject, TriggerActions>;
Matthew Barthebabc042021-05-13 15:38:58 -0500104/**
105 * Data associated to a subscribed signal
106 * Tuple constructed of:
Matthew Barthc024d782021-11-09 16:15:49 -0600107 * std::unique_ptr<std::vector<SignalPkg>> =
108 * Pointer to list of the signal's packages
Patrick Williams3ea9ec22021-11-19 12:21:08 -0600109 * std::unique_ptr<sdbusplus::bus::match_t> =
Matthew Barthebabc042021-05-13 15:38:58 -0500110 * Pointer to match holding the subscription to a signal
111 */
Matthew Barthc024d782021-11-09 16:15:49 -0600112using SignalData = std::tuple<std::unique_ptr<std::vector<SignalPkg>>,
Patrick Williams3ea9ec22021-11-19 12:21:08 -0600113 std::unique_ptr<sdbusplus::bus::match_t>>;
Matthew Barthebabc042021-05-13 15:38:58 -0500114
Matthew Bartha227a162020-08-05 10:51:45 -0500115/**
Mike Capps1a19ead2021-10-22 09:15:14 -0400116 * Package of data from a D-Bus call to get managed objects
117 * Tuple constructed of:
118 * std::map<Path, // D-Bus Path
119 * std::map<Intf, // D-Bus Interface
120 * std::map<Property, // D-Bus Property
121 * std::variant>>> // Variant value of that property
122 */
123using Path_v = sdbusplus::message::object_path;
124using Intf_v = std::string;
125using Prop_v = std::string;
126using ManagedObjects =
127 std::map<Path_v, std::map<Intf_v, std::map<Prop_v, PropertyVariantType>>>;
128
129/**
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600130 * Actions to run when a parameter trigger runs.
131 */
132using ParamTriggerData = std::vector<
133 std::reference_wrapper<const std::vector<std::unique_ptr<ActionBase>>>>;
134
135/**
Matthew Bartha227a162020-08-05 10:51:45 -0500136 * @class Manager - Represents the fan control manager's configuration
137 *
138 * A fan control manager configuration is optional, therefore the "manager.json"
139 * file is also optional. The manager configuration is used to populate
140 * fan control's manager parameters which are used in how the application
141 * operates, not in how the fans are controlled.
142 *
143 * When no manager configuration exists, the fan control application starts,
144 * processes any configured events and then begins controlling fans according
145 * to those events.
146 */
147class Manager
148{
149 public:
150 Manager() = delete;
151 Manager(const Manager&) = delete;
152 Manager(Manager&&) = delete;
153 Manager& operator=(const Manager&) = delete;
154 Manager& operator=(Manager&&) = delete;
155 ~Manager() = default;
156
157 /**
158 * Constructor
159 * Parses and populates the fan control manager attributes from a json file
160 *
Matthew Barth06764942021-03-04 09:28:40 -0600161 * @param[in] event - sdeventplus event loop
Matthew Bartha227a162020-08-05 10:51:45 -0500162 */
Matt Spinler9b062432023-01-26 14:38:50 -0600163 explicit Manager(const sdeventplus::Event& event);
Matthew Bartha227a162020-08-05 10:51:45 -0500164
165 /**
Matthew Barthe91ac862021-05-25 16:22:17 -0500166 * @brief Callback function to handle receiving a HUP signal to reload the
167 * JSON configurations.
168 */
169 void sighupHandler(sdeventplus::source::Signal&,
170 const struct signalfd_siginfo*);
171
172 /**
Matt Spinler2fc0a352021-10-04 15:10:57 -0500173 * @brief Callback function to handle receiving a USR1 signal to dump
174 * the flight recorder.
175 */
Matt Spinler27f5f4e2022-09-01 14:57:39 -0500176 void dumpDebugData(sdeventplus::source::Signal&,
177 const struct signalfd_siginfo*);
Matt Spinler2fc0a352021-10-04 15:10:57 -0500178
179 /**
Matthew Barthacd737c2021-03-04 11:04:01 -0600180 * @brief Get the active profiles of the system where an empty list
181 * represents that only configuration entries without a profile defined will
182 * be loaded.
183 *
184 * @return - The list of active profiles
185 */
186 static const std::vector<std::string>& getActiveProfiles();
187
188 /**
189 * @brief Load the configuration of a given JSON class object based on the
190 * active profiles
191 *
Matthew Barthacd737c2021-03-04 11:04:01 -0600192 * @param[in] isOptional - JSON configuration file is optional or not
Matthew Barth603ef162021-03-24 15:34:53 -0500193 * @param[in] args - Arguments to be forwarded to each instance of `T`
Matthew Barthe6d1f782021-05-14 12:52:20 -0500194 * (*Note that a sdbusplus bus object is required as the first argument)
Matthew Barthacd737c2021-03-04 11:04:01 -0600195 *
196 * @return Map of configuration entries
197 * Map of configuration keys to their corresponding configuration object
198 */
Matthew Barth603ef162021-03-24 15:34:53 -0500199 template <typename T, typename... Args>
Patrick Williams4fa67aa2025-02-03 14:28:47 -0500200 static std::map<configKey, std::unique_ptr<T>> getConfig(bool isOptional,
201 Args&&... args)
Matthew Barthacd737c2021-03-04 11:04:01 -0600202 {
203 std::map<configKey, std::unique_ptr<T>> config;
204
Mike Capps808d7fe2022-06-13 10:12:16 -0400205 auto confFile = fan::JsonConfig::getConfFile(
206 confAppName, T::confFileName, isOptional);
207
Matthew Barthacd737c2021-03-04 11:04:01 -0600208 if (!confFile.empty())
209 {
Matthew Barthbd52ed02022-02-07 15:15:10 -0600210 FlightRecorder::instance().log(
Patrick Williamsfbf47032023-07-17 12:27:34 -0500211 "main", std::format("Loading configuration from {}",
Matthew Barthbd52ed02022-02-07 15:15:10 -0600212 confFile.string()));
Matthew Barthacd737c2021-03-04 11:04:01 -0600213 for (const auto& entry : fan::JsonConfig::load(confFile))
214 {
215 if (entry.contains("profiles"))
216 {
217 std::vector<std::string> profiles;
218 for (const auto& profile : entry["profiles"])
219 {
220 profiles.emplace_back(
221 profile.template get<std::string>());
222 }
223 // Do not create the object if its profiles are not in the
224 // list of active profiles
Matthew Barth42428052021-03-30 12:50:59 -0500225 if (!profiles.empty() &&
226 !std::any_of(profiles.begin(), profiles.end(),
Matthew Barthacd737c2021-03-04 11:04:01 -0600227 [](const auto& name) {
Patrick Williamsdfddd642024-08-16 15:21:51 -0400228 return std::find(
229 getActiveProfiles().begin(),
230 getActiveProfiles().end(),
231 name) !=
232 getActiveProfiles().end();
233 }))
Matthew Barthacd737c2021-03-04 11:04:01 -0600234 {
235 continue;
236 }
237 }
Patrick Williamsdfddd642024-08-16 15:21:51 -0400238 auto obj =
239 std::make_unique<T>(entry, std::forward<Args>(args)...);
Matthew Barthacd737c2021-03-04 11:04:01 -0600240 config.emplace(
241 std::make_pair(obj->getName(), obj->getProfiles()),
242 std::move(obj));
243 }
Anwaar Hadi64b5ac22025-04-04 23:54:53 +0000244 lg2::info("Configuration({CONF_FILE}) loaded successfully",
245 "CONF_FILE", T::confFileName);
Matthew Barthbd52ed02022-02-07 15:15:10 -0600246 FlightRecorder::instance().log(
Patrick Williamsfbf47032023-07-17 12:27:34 -0500247 "main", std::format("Configuration({}) loaded successfully",
Matthew Barthbd52ed02022-02-07 15:15:10 -0600248 T::confFileName));
Matthew Barthacd737c2021-03-04 11:04:01 -0600249 }
250 return config;
251 }
252
253 /**
Matthew Barth0206c722021-03-30 15:20:05 -0500254 * @brief Check if the given input configuration key matches with another
255 * configuration key that it's to be included in
256 *
257 * @param[in] input - Config key to be included in another config object
258 * @param[in] comp - Config key of the config object to compare with
259 *
260 * @return Whether the configuration object should be included
261 */
262 static bool inConfig(const configKey& input, const configKey& comp);
263
264 /**
Matthew Barth12cb1252021-03-08 16:47:30 -0600265 * @brief Check if the given path and inteface is owned by a dbus service
266 *
267 * @param[in] path - Dbus object path
268 * @param[in] intf - Dbus object interface
269 *
270 * @return - Whether the service has an owner for the given object path and
271 * interface
272 */
273 static bool hasOwner(const std::string& path, const std::string& intf);
274
275 /**
Matthew Barth6d8e2d32022-02-01 16:47:08 -0600276 * @brief Sets the dbus service owner state for all entries in the _servTree
277 * cache and removes associated objects from the _objects cache
278 *
279 * @param[in] serv - Dbus service name
280 * @param[in] hasOwner - Dbus service owner state
281 */
282 void setOwner(const std::string& serv, bool hasOwner);
283
284 /**
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500285 * @brief Sets the dbus service owner state of a given object
286 *
287 * @param[in] path - Dbus object path
288 * @param[in] serv - Dbus service name
289 * @param[in] intf - Dbus object interface
290 * @param[in] isOwned - Dbus service owner state
291 */
292 void setOwner(const std::string& path, const std::string& serv,
293 const std::string& intf, bool isOwned);
294
295 /**
296 * @brief Add a set of services for a path and interface by retrieving all
297 * the path subtrees to the given depth from root for the interface
298 *
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500299 * @param[in] intf - Interface to add services for
300 * @param[in] depth - Depth of tree traversal from root path
301 *
302 * @throws - DBusMethodError
303 * Throws a DBusMethodError when the `getSubTree` method call fails
304 */
Matthew Barth98f6fc12021-04-16 10:48:37 -0500305 static void addServices(const std::string& intf, int32_t depth);
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500306
307 /**
308 * @brief Get the service for a given path and interface from cached
309 * dataset and attempt to add all the services for the given path/interface
310 * when it's not found
311 *
312 * @param[in] path - Path to get service for
313 * @param[in] intf - Interface to get service for
314 *
315 * @return - The now cached service name
316 *
317 * @throws - DBusMethodError
318 * Ripples up a DBusMethodError exception from calling addServices
319 */
320 static const std::string& getService(const std::string& path,
321 const std::string& intf);
322
323 /**
Matthew Barthf41e9472021-05-13 16:38:06 -0500324 * @brief Get all the object paths for a given service and interface from
325 * the cached dataset and try to add all the services for the given
326 * interface when no paths are found and then attempt to get all the object
327 * paths again
328 *
329 * @param[in] serv - Service name to get paths for
330 * @param[in] intf - Interface to get paths for
331 *
332 * @return The cached object paths
333 */
334 std::vector<std::string> getPaths(const std::string& serv,
335 const std::string& intf);
336
337 /**
338 * @brief Add objects to the cached dataset by first using
339 * `getManagedObjects` for the same service providing the given path and
340 * interface or just add the single object of the given path, interface, and
341 * property if that fails.
342 *
343 * @param[in] path - Dbus object's path
344 * @param[in] intf - Dbus object's interface
345 * @param[in] prop - Dbus object's property
346 *
347 * @throws - DBusMethodError
348 * Throws a DBusMethodError when the the service is failed to be found or
349 * when the `getManagedObjects` method call fails
350 */
351 void addObjects(const std::string& path, const std::string& intf,
Matt Spinler9ac325c2022-04-25 14:13:49 -0500352 const std::string& prop)
353 {
354 addObjects(path, intf, prop, std::string{});
355 }
356
357 /**
358 * @copydoc Manager::addObjects()
359 *
360 * If the service is known, then it can be used to add all objects
361 * in that service with the interface passed in to the cache instead of
362 * having to look it up. This is done so objects can still be
363 * added even when the D-Bus path passed in doesn't exist so it
364 * can't be used to get a service name.
365 *
366 * @param[in] path - Dbus object's path
367 * @param[in] intf - Dbus object's interface
368 * @param[in] prop - Dbus object's property
369 * @param[in] serviceName - The service of the path/intf/prop if known
370 */
371 void addObjects(const std::string& path, const std::string& intf,
372 const std::string& prop, const std::string& serviceName);
Matthew Barthf41e9472021-05-13 16:38:06 -0500373
374 /**
375 * @brief Get an object's property value
376 *
377 * @param[in] path - Dbus object's path
378 * @param[in] intf - Dbus object's interface
379 * @param[in] prop - Dbus object's property
380 */
Patrick Williams4fa67aa2025-02-03 14:28:47 -0500381 const std::optional<PropertyVariantType> getProperty(
382 const std::string& path, const std::string& intf,
383 const std::string& prop);
Matthew Barthf41e9472021-05-13 16:38:06 -0500384
385 /**
Matthew Barthbaeeb8f2021-05-13 16:03:54 -0500386 * @brief Set/update an object's property value
387 *
388 * @param[in] path - Dbus object's path
389 * @param[in] intf - Dbus object's interface
390 * @param[in] prop - Dbus object's property
391 * @param[in] value - Dbus object's property value
392 */
393 void setProperty(const std::string& path, const std::string& intf,
Mike Capps1a19ead2021-10-22 09:15:14 -0400394 const std::string& prop, PropertyVariantType value);
Matthew Barthbaeeb8f2021-05-13 16:03:54 -0500395
396 /**
Matthew Barthc2691402021-05-13 16:20:32 -0500397 * @brief Remove an object's interface
398 *
399 * @param[in] path - Dbus object's path
400 * @param[in] intf - Dbus object's interface
401 */
402 inline void removeInterface(const std::string& path,
403 const std::string& intf)
404 {
405 auto itPath = _objects.find(path);
406 if (itPath != std::end(_objects))
407 {
408 _objects[path].erase(intf);
409 }
410 }
411
412 /**
Matthew Barth07fecfc2021-01-29 09:04:43 -0600413 * @brief Get the object's property value as a variant
414 *
415 * @param[in] path - Path of the object containing the property
416 * @param[in] intf - Interface name containing the property
417 * @param[in] prop - Name of property
418 *
419 * @return - The object's property value as a variant
420 */
421 static inline auto getObjValueVariant(const std::string& path,
422 const std::string& intf,
423 const std::string& prop)
424 {
425 return _objects.at(path).at(intf).at(prop);
426 };
427
428 /**
Matthew Barthd9cb63b2021-03-24 14:36:49 -0500429 * @brief Add a dbus timer
430 *
431 * @param[in] type - Type of timer
432 * @param[in] interval - Timer interval in microseconds
433 * @param[in] pkg - Packaged data for when timer expires
434 */
435 void addTimer(const TimerType type,
436 const std::chrono::microseconds interval,
437 std::unique_ptr<TimerPkg> pkg);
438
439 /**
440 * @brief Callback when a timer expires
441 *
442 * @param[in] data - Data to be used when the timer expired
443 */
444 void timerExpired(TimerData& data);
445
446 /**
Matthew Barthebabc042021-05-13 15:38:58 -0500447 * @brief Get the signal data for a given match string
448 *
449 * @param[in] sigMatch - Signal match string
450 *
451 * @return - Reference to the signal data for the given match string
452 */
453 std::vector<SignalData>& getSignal(const std::string& sigMatch)
454 {
455 return _signals[sigMatch];
456 }
457
458 /**
459 * @brief Handle receiving signals
460 *
461 * @param[in] msg - Signal message containing the signal's data
462 * @param[in] pkgs - Signal packages associated to the signal being handled
463 */
Patrick Williamscb356d42022-07-22 19:26:53 -0500464 void handleSignal(sdbusplus::message_t& msg,
Matthew Barthc024d782021-11-09 16:15:49 -0600465 const std::vector<SignalPkg>* pkgs);
Matthew Barthebabc042021-05-13 15:38:58 -0500466
467 /**
Matthew Bartheebde062021-04-14 12:48:52 -0500468 * @brief Get the sdbusplus bus object
469 */
470 inline auto& getBus()
471 {
472 return _bus;
473 }
474
475 /**
Matthew Barth48f44da2021-05-27 15:43:34 -0500476 * @brief Is the power state on
477 *
478 * @return Current power state of the system
479 */
480 inline bool isPowerOn() const
481 {
482 return _powerState->isPowerOn();
483 }
484
Matthew Barth3770a1d2021-06-10 15:09:37 -0500485 /**
486 * @brief Load all the fan control JSON configuration files
487 *
488 * This is where all the fan control JSON configuration files are parsed and
489 * loaded into their associated objects. Anything that needs to be done when
490 * the Manager object is constructed or handling a SIGHUP to reload the
491 * configurations needs to be done here.
492 */
493 void load();
494
Matt Spinlerd76351b2021-08-05 16:23:09 -0500495 /**
496 * @brief Sets a value in the parameter map.
497 *
Matt Spinler72c4af42021-11-29 14:40:17 -0600498 * If it's a std::nullopt, it will be deleted instead.
499 *
Matt Spinlerd76351b2021-08-05 16:23:09 -0500500 * @param[in] name - The parameter name
501 * @param[in] value - The parameter value
502 */
503 static void setParameter(const std::string& name,
Matt Spinler72c4af42021-11-29 14:40:17 -0600504 const std::optional<PropertyVariantType>& value)
Matt Spinlerd76351b2021-08-05 16:23:09 -0500505 {
Matt Spinler72c4af42021-11-29 14:40:17 -0600506 if (value)
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600507 {
Matt Spinler72c4af42021-11-29 14:40:17 -0600508 auto it = _parameters.find(name);
509 auto changed = (it == _parameters.end()) ||
510 ((it != _parameters.end()) && it->second != *value);
511 _parameters[name] = *value;
512
513 if (changed)
514 {
515 runParameterActions(name);
516 }
517 }
518 else
519 {
520 size_t deleted = _parameters.erase(name);
521
522 if (deleted)
523 {
524 runParameterActions(name);
525 }
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600526 }
Matt Spinlerd76351b2021-08-05 16:23:09 -0500527 }
528
529 /**
530 * @brief Returns a value from the parameter map
531 *
532 * @param[in] name - The parameter name
533 *
534 * @return The parameter value, or std::nullopt if not found
535 */
Patrick Williams4fa67aa2025-02-03 14:28:47 -0500536 static std::optional<PropertyVariantType> getParameter(
537 const std::string& name)
Matt Spinlerd76351b2021-08-05 16:23:09 -0500538 {
539 auto it = _parameters.find(name);
540 if (it != _parameters.end())
541 {
542 return it->second;
543 }
544
545 return std::nullopt;
546 }
547
548 /**
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600549 * @brief Runs the actions registered to a parameter
550 * trigger with this name.
551 *
552 * @param[in] name - The parameter name
553 */
554 static void runParameterActions(const std::string& name);
555
556 /**
557 * @brief Adds a parameter trigger
558 *
559 * @param[in] name - The parameter name
560 * @param[in] actions - The actions to run on the trigger
561 */
Patrick Williams4fa67aa2025-02-03 14:28:47 -0500562 static void addParameterTrigger(
563 const std::string& name,
564 std::vector<std::unique_ptr<ActionBase>>& actions);
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600565
Matt Spinler7787def2021-10-14 16:33:16 -0500566 /* The name of the dump file */
567 static const std::string dumpFile;
568
Matthew Bartha227a162020-08-05 10:51:45 -0500569 private:
Mike Capps1a19ead2021-10-22 09:15:14 -0400570 /**
571 * @brief Helper to detect when a property's double contains a NaN
572 * (not-a-number) value.
573 *
574 * @param[in] value - The property to test
575 */
576 static bool PropertyContainsNan(const PropertyVariantType& value)
577 {
578 return (std::holds_alternative<double>(value) &&
579 std::isnan(std::get<double>(value)));
580 }
581
582 /**
583 * @brief Insert managed objects into cache, but filter out properties
Matt Spinlerc2c2db72022-04-07 13:59:37 -0500584 * containing unwanted NaN (not-a-number) values and properties that
585 * are on D-Bus paths that aren't in an existing Group object.
Mike Capps1a19ead2021-10-22 09:15:14 -0400586 *
587 * @param[in] ref - The map of ManagedObjects to insert into cache
588 */
589 void insertFilteredObjects(ManagedObjects& ref);
590
Matthew Barth1542fb52021-06-10 14:09:09 -0500591 /* The sdbusplus bus object to use */
Patrick Williamscb356d42022-07-22 19:26:53 -0500592 sdbusplus::bus_t& _bus;
Matthew Barthacd737c2021-03-04 11:04:01 -0600593
Matthew Barth1542fb52021-06-10 14:09:09 -0500594 /* The sdeventplus even loop to use */
Matthew Barthacd737c2021-03-04 11:04:01 -0600595 sdeventplus::Event _event;
596
Matthew Barth1542fb52021-06-10 14:09:09 -0500597 /* The sdbusplus manager object to set the ObjectManager interface */
Patrick Williamscb356d42022-07-22 19:26:53 -0500598 sdbusplus::server::manager_t _mgr;
Matthew Barth1542fb52021-06-10 14:09:09 -0500599
Matthew Barth3770a1d2021-06-10 15:09:37 -0500600 /* Whether loading the config files is allowed or not */
601 bool _loadAllowed;
602
Matthew Barth48f44da2021-05-27 15:43:34 -0500603 /* The system's power state determination object */
604 std::unique_ptr<PowerState> _powerState;
605
Matthew Barth06764942021-03-04 09:28:40 -0600606 /* List of profiles configured */
Matthew Barthacd737c2021-03-04 11:04:01 -0600607 std::map<configKey, std::unique_ptr<Profile>> _profiles;
Matthew Barth06764942021-03-04 09:28:40 -0600608
609 /* List of active profiles */
Matthew Barthacd737c2021-03-04 11:04:01 -0600610 static std::vector<std::string> _activeProfiles;
611
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500612 /* Subtree map of paths to services of interfaces(with ownership state) */
613 static std::map<
614 std::string,
615 std::map<std::string, std::pair<bool, std::vector<std::string>>>>
Matthew Barth12cb1252021-03-08 16:47:30 -0600616 _servTree;
617
Matthew Barth07fecfc2021-01-29 09:04:43 -0600618 /* Object map of paths to interfaces of properties and their values */
619 static std::map<
620 std::string,
621 std::map<std::string, std::map<std::string, PropertyVariantType>>>
622 _objects;
623
Matthew Barthd9cb63b2021-03-24 14:36:49 -0500624 /* List of timers and their data to be processed when expired */
625 std::vector<std::pair<std::unique_ptr<TimerData>, Timer>> _timers;
626
Matthew Barthebabc042021-05-13 15:38:58 -0500627 /* Map of signal match strings to a list of signal handler data */
628 std::unordered_map<std::string, std::vector<SignalData>> _signals;
629
Matthew Barthacd737c2021-03-04 11:04:01 -0600630 /* List of zones configured */
631 std::map<configKey, std::unique_ptr<Zone>> _zones;
632
Matthew Barth44ab7692021-03-26 11:40:10 -0500633 /* List of events configured */
634 std::map<configKey, std::unique_ptr<Event>> _events;
635
Matthew Barthacd737c2021-03-04 11:04:01 -0600636 /**
Matt Spinlerd76351b2021-08-05 16:23:09 -0500637 * @brief A map of parameter names and values that are something
638 * other than just D-Bus property values that other actions
639 * can set and use.
640 */
641 static std::unordered_map<std::string, PropertyVariantType> _parameters;
642
643 /**
Matt Spinlerd0ba86a2021-11-09 10:09:13 -0600644 * @brief Map of parameter names to the actions to run when their
645 * values change.
646 */
647 static std::unordered_map<std::string, TriggerActions> _parameterTriggers;
648
649 /**
Matthew Barthb2cd93f2021-06-16 16:37:40 -0500650 * @brief Callback for power state changes
651 *
652 * @param[in] powerStateOn - Whether the power state is on or not
653 *
654 * Callback function bound to the PowerState object instance to handle each
655 * time the power state changes.
656 */
657 void powerStateChanged(bool powerStateOn);
658
659 /**
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500660 * @brief Find the service name for a given path and interface from the
661 * cached dataset
662 *
663 * @param[in] path - Path to get service for
664 * @param[in] intf - Interface to get service for
665 *
666 * @return - The cached service name
667 */
668 static const std::string& findService(const std::string& path,
669 const std::string& intf);
670
671 /**
Matthew Barthf41e9472021-05-13 16:38:06 -0500672 * @brief Find all the paths for a given service and interface from the
673 * cached dataset
674 *
675 * @param[in] serv - Service name to get paths for
676 * @param[in] intf - Interface to get paths for
677 *
678 * @return - The cached object paths
679 */
680 std::vector<std::string> findPaths(const std::string& serv,
681 const std::string& intf);
682
683 /**
Matthew Barthacd737c2021-03-04 11:04:01 -0600684 * @brief Parse and set the configured profiles from the profiles JSON file
685 *
686 * Retrieves the optional profiles JSON configuration file, parses it, and
687 * creates a list of configured profiles available to the other
688 * configuration files. These profiles can be used to remove or include
689 * entries within the other configuration files.
690 */
691 void setProfiles();
Matt Spinler2fc0a352021-10-04 15:10:57 -0500692
693 /**
Matt Spinlerb5c21a22021-10-14 16:52:12 -0500694 * @brief Dump the _objects, _servTree, and _parameters maps to JSON
695 *
696 * @param[out] data - The JSON that will be filled in
697 */
698 void dumpCache(json& data);
Matt Spinlerade0c372021-10-28 16:09:44 -0500699
700 /**
Matthew Barth2f359f72022-02-15 10:00:26 -0600701 * @brief Add a list of groups to the cache dataset.
Matt Spinlerade0c372021-10-28 16:09:44 -0500702 *
Matthew Barth2f359f72022-02-15 10:00:26 -0600703 * @param[in] groups - The groups to add
Matt Spinlerade0c372021-10-28 16:09:44 -0500704 */
Matthew Barth2f359f72022-02-15 10:00:26 -0600705 void addGroups(const std::vector<Group>& groups);
Matthew Bartha227a162020-08-05 10:51:45 -0500706};
707
708} // namespace phosphor::fan::control::json