blob: b29d0d65ed1fa95f0fe886b9f582ff1eaa02e41f [file] [log] [blame]
Patrick Ventureaadb30d2020-08-10 09:17:11 -07001/**
2 * Copyright 2017 Google Inc.
3 *
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
Pete O_o765a6d82025-07-23 21:44:14 -070017#include "config.h"
18
Patrick Ventureaadb30d2020-08-10 09:17:11 -070019#include "dbushelper.hpp"
20
21#include "dbushelper_interface.hpp"
22#include "dbusutil.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070023
Patrick Venturea83a3ec2020-08-04 09:52:05 -070024#include <phosphor-logging/log.hpp>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070025#include <sdbusplus/bus.hpp>
Ed Tanousf8b6e552025-06-27 13:27:50 -070026#include <sdbusplus/exception.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070027
Ed Tanousf8b6e552025-06-27 13:27:50 -070028#include <cstdint>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070029#include <map>
Ed Tanousf8b6e552025-06-27 13:27:50 -070030#include <stdexcept>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070031#include <string>
James Feist1f802f52019-02-08 13:51:43 -080032#include <variant>
Patrick Ventureaadb30d2020-08-10 09:17:11 -070033#include <vector>
34
35namespace pid_control
36{
Patrick Venture863b9242018-03-08 08:29:23 -080037
Patrick Venture863b9242018-03-08 08:29:23 -080038using Property = std::string;
James Feist1f802f52019-02-08 13:51:43 -080039using Value = std::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -080040using PropertyMap = std::map<Property, Value>;
41
Patrick Venture34ddc902018-10-30 11:05:17 -070042using namespace phosphor::logging;
43
Patrick Venture863b9242018-03-08 08:29:23 -080044/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
45 * part of sdbusplus. There is an old version in libmapper.
46 */
Patrick Venture9b936922020-08-10 11:28:39 -070047std::string DbusHelper::getService(const std::string& intf,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070048 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080049{
Patrick Williamsbd63bca2024-08-16 15:21:10 -040050 auto mapper =
51 _bus.new_method_call("xyz.openbmc_project.ObjectMapper",
52 "/xyz/openbmc_project/object_mapper",
53 "xyz.openbmc_project.ObjectMapper", "GetObject");
Patrick Venture863b9242018-03-08 08:29:23 -080054
55 mapper.append(path);
56 mapper.append(std::vector<std::string>({intf}));
57
Patrick Venture863b9242018-03-08 08:29:23 -080058 std::map<std::string, std::vector<std::string>> response;
Patrick Venture34ddc902018-10-30 11:05:17 -070059
60 try
61 {
Patrick Venture8729eb92020-08-10 10:38:44 -070062 auto responseMsg = _bus.call(mapper);
Patrick Venture34ddc902018-10-30 11:05:17 -070063
64 responseMsg.read(response);
65 }
Patrick Williamsb228bc32022-07-22 19:26:56 -050066 catch (const sdbusplus::exception_t& ex)
Patrick Venture34ddc902018-10-30 11:05:17 -070067 {
68 log<level::ERR>("ObjectMapper call failure",
69 entry("WHAT=%s", ex.what()));
70 throw;
71 }
Patrick Venture863b9242018-03-08 08:29:23 -080072
73 if (response.begin() == response.end())
74 {
75 throw std::runtime_error("Unable to find Object: " + path);
76 }
77
78 return response.begin()->first;
79}
80
Patrick Venture9b936922020-08-10 11:28:39 -070081void DbusHelper::getProperties(const std::string& service,
Patrick Venture1df9e872020-10-08 15:35:01 -070082 const std::string& path, SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080083{
Patrick Venture8729eb92020-08-10 10:38:44 -070084 auto pimMsg = _bus.new_method_call(service.c_str(), path.c_str(),
85 propertiesintf, "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080086
87 pimMsg.append(sensorintf);
Patrick Venture863b9242018-03-08 08:29:23 -080088
Patrick Venture7dbc5172018-10-30 12:18:45 -070089 PropertyMap propMap;
90
91 try
Patrick Venture863b9242018-03-08 08:29:23 -080092 {
Patrick Venture8729eb92020-08-10 10:38:44 -070093 auto valueResponseMsg = _bus.call(pimMsg);
Patrick Venture7dbc5172018-10-30 12:18:45 -070094 valueResponseMsg.read(propMap);
95 }
Patrick Williamsb228bc32022-07-22 19:26:56 -050096 catch (const sdbusplus::exception_t& ex)
Patrick Venture7dbc5172018-10-30 12:18:45 -070097 {
98 log<level::ERR>("GetAll Properties Failed",
99 entry("WHAT=%s", ex.what()));
100 throw;
Patrick Venture863b9242018-03-08 08:29:23 -0800101 }
102
103 // The PropertyMap returned will look like this because it's always
104 // reading a Sensor.Value interface.
105 // a{sv} 3:
106 // "Value" x 24875
107 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
108 // "Scale" x -3
Patrick Venture863b9242018-03-08 08:29:23 -0800109
Patrick Venture0d73b102018-05-09 10:29:42 -0700110 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -0700111 auto findUnit = propMap.find("Unit");
112 if (findUnit != propMap.end())
113 {
James Feist1f802f52019-02-08 13:51:43 -0800114 prop->unit = std::get<std::string>(findUnit->second);
James Feistc065cf12018-07-05 10:23:11 -0700115 }
116 auto findScale = propMap.find("Scale");
James Feist75eb7692019-02-25 12:50:02 -0800117 auto findMax = propMap.find("MaxValue");
118 auto findMin = propMap.find("MinValue");
119
120 prop->min = 0;
121 prop->max = 0;
122 prop->scale = 0;
James Feistc065cf12018-07-05 10:23:11 -0700123 if (findScale != propMap.end())
124 {
James Feist1f802f52019-02-08 13:51:43 -0800125 prop->scale = std::get<int64_t>(findScale->second);
James Feistc065cf12018-07-05 10:23:11 -0700126 }
James Feist75eb7692019-02-25 12:50:02 -0800127 if (findMax != propMap.end())
James Feistc065cf12018-07-05 10:23:11 -0700128 {
James Feist75eb7692019-02-25 12:50:02 -0800129 prop->max = std::visit(VariantToDoubleVisitor(), findMax->second);
130 }
131 if (findMin != propMap.end())
132 {
133 prop->min = std::visit(VariantToDoubleVisitor(), findMin->second);
James Feistc065cf12018-07-05 10:23:11 -0700134 }
135
James Feist1f802f52019-02-08 13:51:43 -0800136 prop->value = std::visit(VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -0800137
Alex.Song8f73ad72021-10-07 00:18:27 +0800138 bool available = true;
139 try
140 {
141 getProperty(service, path, availabilityIntf, "Available", available);
142 }
Patrick Williamsb228bc32022-07-22 19:26:56 -0500143 catch (const sdbusplus::exception_t& ex)
Alex.Song8f73ad72021-10-07 00:18:27 +0800144 {
145 // unsupported Available property, leaving reading at 'True'
146 }
147 prop->available = available;
148
Patrick Venture863b9242018-03-08 08:29:23 -0800149 return;
150}
151
Patrick Venture9b936922020-08-10 11:28:39 -0700152bool DbusHelper::thresholdsAsserted(const std::string& service,
James Feist36b7d8e2018-10-05 15:39:01 -0700153 const std::string& path)
154{
Patrick Venture8729eb92020-08-10 10:38:44 -0700155 auto critical = _bus.new_method_call(service.c_str(), path.c_str(),
156 propertiesintf, "GetAll");
James Feist36b7d8e2018-10-05 15:39:01 -0700157 critical.append(criticalThreshInf);
158 PropertyMap criticalMap;
159
160 try
161 {
Patrick Venture8729eb92020-08-10 10:38:44 -0700162 auto msg = _bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700163 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700164 }
Patrick Williams0001ee02021-10-06 14:44:22 -0500165 catch (const sdbusplus::exception_t&)
James Feist36b7d8e2018-10-05 15:39:01 -0700166 {
167 // do nothing, sensors don't have to expose critical thresholds
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600168#ifndef UNC_FAILSAFE
James Feist36b7d8e2018-10-05 15:39:01 -0700169 return false;
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600170#endif
James Feist36b7d8e2018-10-05 15:39:01 -0700171 }
172
173 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
174 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
175
176 bool asserted = false;
177 if (findCriticalLow != criticalMap.end())
178 {
James Feist1f802f52019-02-08 13:51:43 -0800179 asserted = std::get<bool>(findCriticalLow->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700180 }
181
182 // as we are catching properties changed, a sensor could theoretically jump
183 // from one threshold to the other in one event, so check both thresholds
184 if (!asserted && findCriticalHigh != criticalMap.end())
185 {
James Feist1f802f52019-02-08 13:51:43 -0800186 asserted = std::get<bool>(findCriticalHigh->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700187 }
Jonico Eustaquioaf97d8e2024-01-02 14:35:07 -0600188#ifdef UNC_FAILSAFE
189 if (!asserted)
190 {
191 auto warning = _bus.new_method_call(service.c_str(), path.c_str(),
192 propertiesintf, "GetAll");
193 warning.append(warningThreshInf);
194 PropertyMap warningMap;
195
196 try
197 {
198 auto msg = _bus.call(warning);
199 msg.read(warningMap);
200 }
201 catch (const sdbusplus::exception_t&)
202 {
203 // sensors don't have to expose non-critical thresholds
204 return false;
205 }
206 auto findWarningHigh = warningMap.find("WarningAlarmHigh");
207
208 if (findWarningHigh != warningMap.end())
209 {
210 asserted = std::get<bool>(findWarningHigh->second);
211 }
212 }
213#endif
James Feist36b7d8e2018-10-05 15:39:01 -0700214 return asserted;
215}
216
Patrick Venturea0764872020-08-08 07:48:43 -0700217} // namespace pid_control