blob: 014b8cb6d06bb09a8aa1a06b8b990f3e6f69ec33 [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>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070014
Ed Tanousf8b6e552025-06-27 13:27:50 -070015#include <cstdint>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070016#include <map>
Ed Tanousf8b6e552025-06-27 13:27:50 -070017#include <stdexcept>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070018#include <string>
James Feist1f802f52019-02-08 13:51:43 -080019#include <variant>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070020#include <vector>
21
22namespace pid_control
23{
Patrick Venture863b9242018-03-08 08:29:23 -080024
Patrick Venture863b9242018-03-08 08:29:23 -080025using Property = std::string;
James Feist1f802f52019-02-08 13:51:43 -080026using Value = std::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -080027using PropertyMap = std::map<Property, Value>;
28
Patrick Venture34ddc902018-10-30 11:05:17 -070029using namespace phosphor::logging;
30
Patrick Venture863b9242018-03-08 08:29:23 -080031/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
32 * part of sdbusplus. There is an old version in libmapper.
33 */
Patrick Venture9b936922020-08-10 11:28:39 -070034std::string DbusHelper::getService(const std::string& intf,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070035 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080036{
Patrick Williamsbd63bca2024-08-16 15:21:10 -040037 auto mapper =
38 _bus.new_method_call("xyz.openbmc_project.ObjectMapper",
39 "/xyz/openbmc_project/object_mapper",
40 "xyz.openbmc_project.ObjectMapper", "GetObject");
Patrick Venture863b9242018-03-08 08:29:23 -080041
42 mapper.append(path);
43 mapper.append(std::vector<std::string>({intf}));
44
Patrick Venture863b9242018-03-08 08:29:23 -080045 std::map<std::string, std::vector<std::string>> response;
Patrick Venture34ddc902018-10-30 11:05:17 -070046
47 try
48 {
Patrick Venture8729eb92020-08-10 10:38:44 -070049 auto responseMsg = _bus.call(mapper);
Patrick Venture34ddc902018-10-30 11:05:17 -070050
51 responseMsg.read(response);
52 }
Patrick Williamsb228bc32022-07-22 19:26:56 -050053 catch (const sdbusplus::exception_t& ex)
Patrick Venture34ddc902018-10-30 11:05:17 -070054 {
55 log<level::ERR>("ObjectMapper call failure",
56 entry("WHAT=%s", ex.what()));
57 throw;
58 }
Patrick Venture863b9242018-03-08 08:29:23 -080059
60 if (response.begin() == response.end())
61 {
62 throw std::runtime_error("Unable to find Object: " + path);
63 }
64
65 return response.begin()->first;
66}
67
Patrick Venture9b936922020-08-10 11:28:39 -070068void DbusHelper::getProperties(const std::string& service,
Patrick Venture1df9e872020-10-08 15:35:01 -070069 const std::string& path, SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080070{
Patrick Venture8729eb92020-08-10 10:38:44 -070071 auto pimMsg = _bus.new_method_call(service.c_str(), path.c_str(),
72 propertiesintf, "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080073
74 pimMsg.append(sensorintf);
Patrick Venture863b9242018-03-08 08:29:23 -080075
Patrick Venture7dbc5172018-10-30 12:18:45 -070076 PropertyMap propMap;
77
78 try
Patrick Venture863b9242018-03-08 08:29:23 -080079 {
Patrick Venture8729eb92020-08-10 10:38:44 -070080 auto valueResponseMsg = _bus.call(pimMsg);
Patrick Venture7dbc5172018-10-30 12:18:45 -070081 valueResponseMsg.read(propMap);
82 }
Patrick Williamsb228bc32022-07-22 19:26:56 -050083 catch (const sdbusplus::exception_t& ex)
Patrick Venture7dbc5172018-10-30 12:18:45 -070084 {
85 log<level::ERR>("GetAll Properties Failed",
86 entry("WHAT=%s", ex.what()));
87 throw;
Patrick Venture863b9242018-03-08 08:29:23 -080088 }
89
90 // The PropertyMap returned will look like this because it's always
91 // reading a Sensor.Value interface.
92 // a{sv} 3:
93 // "Value" x 24875
94 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
95 // "Scale" x -3
Patrick Venture863b9242018-03-08 08:29:23 -080096
Patrick Venture0d73b102018-05-09 10:29:42 -070097 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070098 auto findUnit = propMap.find("Unit");
99 if (findUnit != propMap.end())
100 {
James Feist1f802f52019-02-08 13:51:43 -0800101 prop->unit = std::get<std::string>(findUnit->second);
James Feistc065cf12018-07-05 10:23:11 -0700102 }
103 auto findScale = propMap.find("Scale");
James Feist75eb7692019-02-25 12:50:02 -0800104 auto findMax = propMap.find("MaxValue");
105 auto findMin = propMap.find("MinValue");
106
107 prop->min = 0;
108 prop->max = 0;
109 prop->scale = 0;
James Feistc065cf12018-07-05 10:23:11 -0700110 if (findScale != propMap.end())
111 {
James Feist1f802f52019-02-08 13:51:43 -0800112 prop->scale = std::get<int64_t>(findScale->second);
James Feistc065cf12018-07-05 10:23:11 -0700113 }
James Feist75eb7692019-02-25 12:50:02 -0800114 if (findMax != propMap.end())
James Feistc065cf12018-07-05 10:23:11 -0700115 {
James Feist75eb7692019-02-25 12:50:02 -0800116 prop->max = std::visit(VariantToDoubleVisitor(), findMax->second);
117 }
118 if (findMin != propMap.end())
119 {
120 prop->min = std::visit(VariantToDoubleVisitor(), findMin->second);
James Feistc065cf12018-07-05 10:23:11 -0700121 }
122
James Feist1f802f52019-02-08 13:51:43 -0800123 prop->value = std::visit(VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -0800124
Alex.Song8f73ad72021-10-07 00:18:27 +0800125 bool available = true;
126 try
127 {
128 getProperty(service, path, availabilityIntf, "Available", available);
129 }
Patrick Williamsb228bc32022-07-22 19:26:56 -0500130 catch (const sdbusplus::exception_t& ex)
Alex.Song8f73ad72021-10-07 00:18:27 +0800131 {
132 // unsupported Available property, leaving reading at 'True'
133 }
134 prop->available = available;
135
Patrick Venture863b9242018-03-08 08:29:23 -0800136 return;
137}
138
Patrick Venture9b936922020-08-10 11:28:39 -0700139bool DbusHelper::thresholdsAsserted(const std::string& service,
James Feist36b7d8e2018-10-05 15:39:01 -0700140 const std::string& path)
141{
Patrick Venture8729eb92020-08-10 10:38:44 -0700142 auto critical = _bus.new_method_call(service.c_str(), path.c_str(),
143 propertiesintf, "GetAll");
James Feist36b7d8e2018-10-05 15:39:01 -0700144 critical.append(criticalThreshInf);
145 PropertyMap criticalMap;
146
147 try
148 {
Patrick Venture8729eb92020-08-10 10:38:44 -0700149 auto msg = _bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700150 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700151 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500152 catch (const sdbusplus::exception_t&)
James Feist36b7d8e2018-10-05 15:39:01 -0700153 {
154 // do nothing, sensors don't have to expose critical thresholds
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600155#ifndef UNC_FAILSAFE
James Feist36b7d8e2018-10-05 15:39:01 -0700156 return false;
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600157#endif
James Feist36b7d8e2018-10-05 15:39:01 -0700158 }
159
160 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
161 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
162
163 bool asserted = false;
164 if (findCriticalLow != criticalMap.end())
165 {
James Feist1f802f52019-02-08 13:51:43 -0800166 asserted = std::get<bool>(findCriticalLow->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700167 }
168
169 // as we are catching properties changed, a sensor could theoretically jump
170 // from one threshold to the other in one event, so check both thresholds
171 if (!asserted && findCriticalHigh != criticalMap.end())
172 {
James Feist1f802f52019-02-08 13:51:43 -0800173 asserted = std::get<bool>(findCriticalHigh->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700174 }
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600175#ifdef UNC_FAILSAFE
176 if (!asserted)
177 {
178 auto warning = _bus.new_method_call(service.c_str(), path.c_str(),
179 propertiesintf, "GetAll");
180 warning.append(warningThreshInf);
181 PropertyMap warningMap;
182
183 try
184 {
185 auto msg = _bus.call(warning);
186 msg.read(warningMap);
187 }
188 catch (const sdbusplus::exception_t&)
189 {
190 // sensors don't have to expose non-critical thresholds
191 return false;
192 }
193 auto findWarningHigh = warningMap.find("WarningAlarmHigh");
194
195 if (findWarningHigh != warningMap.end())
196 {
197 asserted = std::get<bool>(findWarningHigh->second);
198 }
199 }
200#endif
James Feist36b7d8e2018-10-05 15:39:01 -0700201 return asserted;
202}
203
Patrick Venturea0764872020-08-08 07:48:43 -0700204} // namespace pid_control