blob: 4a692cbfb8730d54b9f8fba6a0d48dae463fc065 [file] [log] [blame]
Alexander Hansen46a755f2025-10-27 16:31:08 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2017 Google Inc
Patrick Ventureaadb30d2020-08-10 09:17:11 -07003
Pete O_o765a6d82025-07-23 21:44:14 -07004#include "config.h"
5
Patrick Ventureaadb30d2020-08-10 09:17:11 -07006#include "dbushelper.hpp"
7
8#include "dbushelper_interface.hpp"
9#include "dbusutil.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070010
Patrick Venturea83a3ec2020-08-04 09:52:05 -070011#include <phosphor-logging/log.hpp>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070012#include <sdbusplus/bus.hpp>
Ed Tanousf8b6e552025-06-27 13:27:50 -070013#include <sdbusplus/exception.hpp>
Alexander Hansen1ec3d132025-10-27 17:19:50 +010014#include <xyz/openbmc_project/ObjectMapper/common.hpp>
Alexander Hansendae4a3a2025-11-11 17:12:01 +010015#include <xyz/openbmc_project/Sensor/Value/client.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070016
Ed Tanousf8b6e552025-06-27 13:27:50 -070017#include <cstdint>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070018#include <map>
Ed Tanousf8b6e552025-06-27 13:27:50 -070019#include <stdexcept>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070020#include <string>
James Feist1f802f52019-02-08 13:51:43 -080021#include <variant>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070022#include <vector>
23
Alexander Hansen1ec3d132025-10-27 17:19:50 +010024using ObjectMapper = sdbusplus::common::xyz::openbmc_project::ObjectMapper;
Alexander Hansendae4a3a2025-11-11 17:12:01 +010025using SensorValue = sdbusplus::common::xyz::openbmc_project::sensor::Value;
Alexander Hansen1ec3d132025-10-27 17:19:50 +010026
Patrick Ventureaadb30d2020-08-10 09:17:11 -070027namespace pid_control
28{
Patrick Venture863b9242018-03-08 08:29:23 -080029
Patrick Venture863b9242018-03-08 08:29:23 -080030using Property = std::string;
James Feist1f802f52019-02-08 13:51:43 -080031using Value = std::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -080032using PropertyMap = std::map<Property, Value>;
33
Patrick Venture34ddc902018-10-30 11:05:17 -070034using namespace phosphor::logging;
35
Patrick Venture863b9242018-03-08 08:29:23 -080036/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
37 * part of sdbusplus. There is an old version in libmapper.
38 */
Patrick Venture9b936922020-08-10 11:28:39 -070039std::string DbusHelper::getService(const std::string& intf,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070040 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080041{
Alexander Hansen1ec3d132025-10-27 17:19:50 +010042 auto mapper = _bus.new_method_call(
43 ObjectMapper::default_service, ObjectMapper::instance_path,
44 ObjectMapper::interface, ObjectMapper::method_names::get_object);
Patrick Venture863b9242018-03-08 08:29:23 -080045
46 mapper.append(path);
47 mapper.append(std::vector<std::string>({intf}));
48
Patrick Venture863b9242018-03-08 08:29:23 -080049 std::map<std::string, std::vector<std::string>> response;
Patrick Venture34ddc902018-10-30 11:05:17 -070050
51 try
52 {
Patrick Venture8729eb92020-08-10 10:38:44 -070053 auto responseMsg = _bus.call(mapper);
Patrick Venture34ddc902018-10-30 11:05:17 -070054
55 responseMsg.read(response);
56 }
Patrick Williamsb228bc32022-07-22 19:26:56 -050057 catch (const sdbusplus::exception_t& ex)
Patrick Venture34ddc902018-10-30 11:05:17 -070058 {
59 log<level::ERR>("ObjectMapper call failure",
60 entry("WHAT=%s", ex.what()));
61 throw;
62 }
Patrick Venture863b9242018-03-08 08:29:23 -080063
64 if (response.begin() == response.end())
65 {
66 throw std::runtime_error("Unable to find Object: " + path);
67 }
68
69 return response.begin()->first;
70}
71
Patrick Venture9b936922020-08-10 11:28:39 -070072void DbusHelper::getProperties(const std::string& service,
Patrick Venture1df9e872020-10-08 15:35:01 -070073 const std::string& path, SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080074{
Patrick Venture8729eb92020-08-10 10:38:44 -070075 auto pimMsg = _bus.new_method_call(service.c_str(), path.c_str(),
76 propertiesintf, "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080077
Alexander Hansendae4a3a2025-11-11 17:12:01 +010078 pimMsg.append(SensorValue::interface);
Patrick Venture863b9242018-03-08 08:29:23 -080079
Patrick Venture7dbc5172018-10-30 12:18:45 -070080 PropertyMap propMap;
81
82 try
Patrick Venture863b9242018-03-08 08:29:23 -080083 {
Patrick Venture8729eb92020-08-10 10:38:44 -070084 auto valueResponseMsg = _bus.call(pimMsg);
Patrick Venture7dbc5172018-10-30 12:18:45 -070085 valueResponseMsg.read(propMap);
86 }
Patrick Williamsb228bc32022-07-22 19:26:56 -050087 catch (const sdbusplus::exception_t& ex)
Patrick Venture7dbc5172018-10-30 12:18:45 -070088 {
89 log<level::ERR>("GetAll Properties Failed",
90 entry("WHAT=%s", ex.what()));
91 throw;
Patrick Venture863b9242018-03-08 08:29:23 -080092 }
93
94 // The PropertyMap returned will look like this because it's always
95 // reading a Sensor.Value interface.
96 // a{sv} 3:
97 // "Value" x 24875
98 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
99 // "Scale" x -3
Patrick Venture863b9242018-03-08 08:29:23 -0800100
Patrick Venture0d73b102018-05-09 10:29:42 -0700101 // If no error was set, the values should all be there.
Alexander Hansendae4a3a2025-11-11 17:12:01 +0100102 auto findUnit = propMap.find(SensorValue::property_names::unit);
James Feistc065cf12018-07-05 10:23:11 -0700103 if (findUnit != propMap.end())
104 {
James Feist1f802f52019-02-08 13:51:43 -0800105 prop->unit = std::get<std::string>(findUnit->second);
James Feistc065cf12018-07-05 10:23:11 -0700106 }
Alexander Hansendae4a3a2025-11-11 17:12:01 +0100107 // TODO: in PDI there is no such 'Scale' property on the Sensor.Value
108 // interface
James Feistc065cf12018-07-05 10:23:11 -0700109 auto findScale = propMap.find("Scale");
Alexander Hansendae4a3a2025-11-11 17:12:01 +0100110 auto findMax = propMap.find(SensorValue::property_names::max_value);
111 auto findMin = propMap.find(SensorValue::property_names::min_value);
James Feist75eb7692019-02-25 12:50:02 -0800112
113 prop->min = 0;
114 prop->max = 0;
115 prop->scale = 0;
James Feistc065cf12018-07-05 10:23:11 -0700116 if (findScale != propMap.end())
117 {
James Feist1f802f52019-02-08 13:51:43 -0800118 prop->scale = std::get<int64_t>(findScale->second);
James Feistc065cf12018-07-05 10:23:11 -0700119 }
James Feist75eb7692019-02-25 12:50:02 -0800120 if (findMax != propMap.end())
James Feistc065cf12018-07-05 10:23:11 -0700121 {
James Feist75eb7692019-02-25 12:50:02 -0800122 prop->max = std::visit(VariantToDoubleVisitor(), findMax->second);
123 }
124 if (findMin != propMap.end())
125 {
126 prop->min = std::visit(VariantToDoubleVisitor(), findMin->second);
James Feistc065cf12018-07-05 10:23:11 -0700127 }
128
Alexander Hansendae4a3a2025-11-11 17:12:01 +0100129 prop->value = std::visit(VariantToDoubleVisitor(),
130 propMap[SensorValue::property_names::value]);
Patrick Venture863b9242018-03-08 08:29:23 -0800131
Alex.Song8f73ad72021-10-07 00:18:27 +0800132 bool available = true;
133 try
134 {
135 getProperty(service, path, availabilityIntf, "Available", available);
136 }
Patrick Williamsb228bc32022-07-22 19:26:56 -0500137 catch (const sdbusplus::exception_t& ex)
Alex.Song8f73ad72021-10-07 00:18:27 +0800138 {
139 // unsupported Available property, leaving reading at 'True'
140 }
141 prop->available = available;
142
Patrick Venture863b9242018-03-08 08:29:23 -0800143 return;
144}
145
Patrick Venture9b936922020-08-10 11:28:39 -0700146bool DbusHelper::thresholdsAsserted(const std::string& service,
James Feist36b7d8e2018-10-05 15:39:01 -0700147 const std::string& path)
148{
Patrick Venture8729eb92020-08-10 10:38:44 -0700149 auto critical = _bus.new_method_call(service.c_str(), path.c_str(),
150 propertiesintf, "GetAll");
James Feist36b7d8e2018-10-05 15:39:01 -0700151 critical.append(criticalThreshInf);
152 PropertyMap criticalMap;
153
154 try
155 {
Patrick Venture8729eb92020-08-10 10:38:44 -0700156 auto msg = _bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700157 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700158 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500159 catch (const sdbusplus::exception_t&)
James Feist36b7d8e2018-10-05 15:39:01 -0700160 {
161 // do nothing, sensors don't have to expose critical thresholds
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600162#ifndef UNC_FAILSAFE
James Feist36b7d8e2018-10-05 15:39:01 -0700163 return false;
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600164#endif
James Feist36b7d8e2018-10-05 15:39:01 -0700165 }
166
167 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
168 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
169
170 bool asserted = false;
171 if (findCriticalLow != criticalMap.end())
172 {
James Feist1f802f52019-02-08 13:51:43 -0800173 asserted = std::get<bool>(findCriticalLow->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700174 }
175
176 // as we are catching properties changed, a sensor could theoretically jump
177 // from one threshold to the other in one event, so check both thresholds
178 if (!asserted && findCriticalHigh != criticalMap.end())
179 {
James Feist1f802f52019-02-08 13:51:43 -0800180 asserted = std::get<bool>(findCriticalHigh->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700181 }
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600182#ifdef UNC_FAILSAFE
183 if (!asserted)
184 {
185 auto warning = _bus.new_method_call(service.c_str(), path.c_str(),
186 propertiesintf, "GetAll");
187 warning.append(warningThreshInf);
188 PropertyMap warningMap;
189
190 try
191 {
192 auto msg = _bus.call(warning);
193 msg.read(warningMap);
194 }
195 catch (const sdbusplus::exception_t&)
196 {
197 // sensors don't have to expose non-critical thresholds
198 return false;
199 }
200 auto findWarningHigh = warningMap.find("WarningAlarmHigh");
201
202 if (findWarningHigh != warningMap.end())
203 {
204 asserted = std::get<bool>(findWarningHigh->second);
205 }
206 }
207#endif
James Feist36b7d8e2018-10-05 15:39:01 -0700208 return asserted;
209}
210
Patrick Venturea0764872020-08-08 07:48:43 -0700211} // namespace pid_control