blob: 501d9cd4e0f345bac17faf2100baec8ad765e318 [file] [log] [blame]
Vijay Khemkaabcc94f2020-08-11 15:27:44 -07001#include "virtualSensor.hpp"
2
3#include "config.hpp"
4
5#include <phosphor-logging/log.hpp>
6#include <sdeventplus/event.hpp>
7
8#include <fstream>
9#include <iostream>
10
11static constexpr bool DEBUG = false;
12static constexpr auto busName = "xyz.openbmc_project.VirtualSensor";
13static constexpr auto sensorDbusPath = "/xyz/openbmc_project/sensors/";
14static constexpr uint8_t defaultHighThreshold = 100;
15static constexpr uint8_t defaultLowThreshold = 0;
16
17using namespace phosphor::logging;
18
19namespace phosphor
20{
21namespace virtualSensor
22{
23
24void printParams(const VirtualSensor::ParamMap& paramMap)
25{
26 for (const auto& p : paramMap)
27 {
28 const auto& p1 = p.first;
29 const auto& p2 = p.second;
30 auto val = p2->getParamValue();
31 std::cout << p1 << " = " << val << "\n";
32 }
33}
34
35double SensorParam::getParamValue()
36{
37 switch (paramType)
38 {
39 case constParam:
40 return value;
41 break;
Vijay Khemka7452a862020-08-11 16:01:23 -070042 case dbusParam:
43 return dbusSensor->getSensorValue();
44 break;
Vijay Khemkaabcc94f2020-08-11 15:27:44 -070045 default:
46 throw std::invalid_argument("param type not supported");
47 }
48}
49
50void VirtualSensor::initVirtualSensor(const Json& sensorConfig)
51{
52
53 static const Json empty{};
54
55 /* Get threshold values if defined in config */
56 auto threshold = sensorConfig.value("Threshold", empty);
57 if (!threshold.empty())
58 {
59 sensorThreshold.criticalHigh =
60 threshold.value("CriticalHigh", defaultHighThreshold);
61 sensorThreshold.criticalLow =
62 threshold.value("CriticalLow", defaultLowThreshold);
63 sensorThreshold.warningHigh =
64 threshold.value("WarningHigh", defaultHighThreshold);
65 sensorThreshold.warningLow =
66 threshold.value("WarningLow", defaultLowThreshold);
67 }
68
69 /* Set threshold value to dbus */
70 setSensorThreshold();
71
72 /* Get expression string */
73 exprStr = sensorConfig.value("Expression", "");
74
75 /* Get all the parameter listed in configuration */
76 auto params = sensorConfig.value("Params", empty);
77
78 /* Check for constant parameter */
79 const auto& consParams = params.value("ConstParam", empty);
80 if (!consParams.empty())
81 {
82 for (auto& j : consParams)
83 {
84 if (j.find("ParamName") != j.end())
85 {
86 auto paramPtr = std::make_unique<SensorParam>(j["Value"]);
87 paramMap.emplace(j["ParamName"], std::move(paramPtr));
88 }
89 else
90 {
91 /* Invalid configuration */
92 throw std::invalid_argument(
93 "ParamName not found in configuration");
94 }
95 }
96 }
97
Vijay Khemka7452a862020-08-11 16:01:23 -070098 /* Check for dbus parameter */
99 auto dbusParams = params.value("DbusParam", empty);
100 if (!dbusParams.empty())
101 {
102 for (auto& j : dbusParams)
103 {
104 /* Get parameter dbus sensor descriptor */
105 auto desc = j.value("Desc", empty);
106 if ((!desc.empty()) && (j.find("ParamName") != j.end()))
107 {
108 std::string sensorType = desc.value("SensorType", "");
109 std::string name = desc.value("Name", "");
110
111 if (!sensorType.empty() && !name.empty())
112 {
113 std::string objPath(sensorDbusPath);
114 objPath += sensorType + "/" + name;
115
116 auto paramPtr = std::make_unique<SensorParam>(bus, objPath);
117 paramMap.emplace(j["ParamName"], std::move(paramPtr));
118 }
119 }
120 }
121 }
Vijay Khemkaabcc94f2020-08-11 15:27:44 -0700122
123 /* Print all parameters for debug purpose only */
124 if (DEBUG)
125 printParams(paramMap);
126}
127
128void VirtualSensor::setSensorValue(double value)
129{
130 ValueIface::value(value);
131}
132
133void VirtualSensor::setSensorThreshold()
134{
135 CriticalInterface::criticalHigh(sensorThreshold.criticalHigh);
136 CriticalInterface::criticalLow(sensorThreshold.criticalLow);
137 WarningInterface::warningHigh(sensorThreshold.warningHigh);
138 WarningInterface::warningLow(sensorThreshold.warningLow);
139}
140
141/* TBD */
142void VirtualSensor::updateVirtualSensor()
143{}
144
145/** @brief Parsing Virtual Sensor config JSON file */
146Json VirtualSensors::parseConfigFile(const std::string configFile)
147{
148 std::ifstream jsonFile(configFile);
149 if (!jsonFile.is_open())
150 {
151 log<level::ERR>("config JSON file not found",
152 entry("FILENAME = %s", configFile.c_str()));
153 throw std::exception{};
154 }
155
156 auto data = Json::parse(jsonFile, nullptr, false);
157 if (data.is_discarded())
158 {
159 log<level::ERR>("config readings JSON parser failure",
160 entry("FILENAME = %s", configFile.c_str()));
161 throw std::exception{};
162 }
163
164 return data;
165}
166
167void VirtualSensors::createVirtualSensors()
168{
169 static const Json empty{};
170
171 auto data = parseConfigFile(VIRTUAL_SENSOR_CONFIG_FILE);
172 // print values
173 if (DEBUG)
174 std::cout << "Config json data:\n" << data << "\n\n";
175
176 /* Get virtual sensors config data */
177 for (const auto& j : data)
178 {
179 auto desc = j.value("Desc", empty);
180 if (!desc.empty())
181 {
182 std::string sensorType = desc.value("SensorType", "");
183 std::string name = desc.value("Name", "");
184
185 if (!name.empty() && !sensorType.empty())
186 {
187 std::string objPath(sensorDbusPath);
188 objPath += sensorType + "/" + name;
189
190 auto virtualSensorPtr =
191 std::make_unique<VirtualSensor>(bus, objPath.c_str(), j);
192 virtualSensorsMap.emplace(name, std::move(virtualSensorPtr));
193
194 log<level::INFO>("Added a new virtual sensor",
195 entry("NAME = %s", name.c_str()));
196 }
197 else
198 {
199 log<level::ERR>("Sensor type or name not found in config file");
200 }
201 }
202 else
203 {
204 log<level::ERR>(
205 "Descriptor for new virtual sensor not found in config file");
206 }
207 }
208}
209
210} // namespace virtualSensor
211} // namespace phosphor
212
213/**
214 * @brief Main
215 */
216int main()
217{
218
219 // Get a default event loop
220 auto event = sdeventplus::Event::get_default();
221
222 // Get a handle to system dbus
223 auto bus = sdbusplus::bus::new_default();
224
225 // Create an virtual sensors object
226 phosphor::virtualSensor::VirtualSensors virtualSensors(bus);
227
228 // Request service bus name
229 bus.request_name(busName);
230
231 // Attach the bus to sd_event to service user requests
232 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
233 event.loop();
234
235 return 0;
236}