blob: 3649f2eac2e7d6d7716f4eb2e6e1817c7446d972 [file] [log] [blame]
James Feistbc896df2018-11-26 16:28:17 -08001/*
2// Copyright (c) 2018 Intel Corporation
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
17#include "ExitAirTempSensor.hpp"
18
19#include "Utils.hpp"
20#include "VariantVisitors.hpp"
21
22#include <math.h>
23
24#include <boost/algorithm/string/predicate.hpp>
25#include <boost/algorithm/string/replace.hpp>
26#include <chrono>
27#include <iostream>
28#include <limits>
29#include <numeric>
30#include <sdbusplus/asio/connection.hpp>
31#include <sdbusplus/asio/object_server.hpp>
32#include <vector>
33
34constexpr const float altitudeFactor = 1.14;
35constexpr const char* exitAirIface =
36 "xyz.openbmc_project.Configuration.ExitAirTempSensor";
37constexpr const char* cfmIface = "xyz.openbmc_project.Configuration.CFMSensor";
38
39// todo: this *might* need to be configurable
40constexpr const char* inletTemperatureSensor = "temperature/Front_Panel_Temp";
James Feistbc896df2018-11-26 16:28:17 -080041
42static constexpr bool DEBUG = false;
43
James Feistb2eb3f52018-12-04 16:17:50 -080044static constexpr double cfmMaxReading = 255;
45static constexpr double cfmMinReading = 0;
46
47static void setupSensorMatch(
48 std::vector<sdbusplus::bus::match::match>& matches,
49 sdbusplus::bus::bus& connection, const std::string& type,
50 std::function<void(const double&, sdbusplus::message::message&)>&& callback)
51{
52
53 std::function<void(sdbusplus::message::message & message)> eventHandler =
54 [callback{std::move(callback)}](sdbusplus::message::message& message) {
55 std::string objectName;
James Feist3eb82622019-02-08 13:10:22 -080056 boost::container::flat_map<std::string,
57 std::variant<double, int64_t>>
James Feistb2eb3f52018-12-04 16:17:50 -080058 values;
59 message.read(objectName, values);
60 auto findValue = values.find("Value");
61 if (findValue == values.end())
62 {
63 return;
64 }
James Feist3eb82622019-02-08 13:10:22 -080065 double value =
66 std::visit(VariantToDoubleVisitor(), findValue->second);
James Feist9566bfa2019-01-29 15:31:23 -080067 if (std::isnan(value))
68 {
69 return;
70 }
71
James Feistb2eb3f52018-12-04 16:17:50 -080072 callback(value, message);
73 };
74 matches.emplace_back(connection,
75 "type='signal',"
76 "member='PropertiesChanged',interface='org."
77 "freedesktop.DBus.Properties',path_"
78 "namespace='/xyz/openbmc_project/sensors/" +
79 std::string(type) +
80 "',arg0='xyz.openbmc_project.Sensor.Value'",
81 std::move(eventHandler));
82}
83
James Feistb2eb3f52018-12-04 16:17:50 -080084CFMSensor::CFMSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
85 const std::string& sensorName,
86 const std::string& sensorConfiguration,
87 sdbusplus::asio::object_server& objectServer,
88 std::vector<thresholds::Threshold>&& thresholds,
89 std::shared_ptr<ExitAirTempSensor>& parent) :
90 Sensor(boost::replace_all_copy(sensorName, " ", "_"),
91 "" /* todo: remove arg from base*/, std::move(thresholds),
92 sensorConfiguration, "xyz.openbmc_project.Configuration.ExitAirTemp",
93 cfmMaxReading, cfmMinReading),
James Feist9566bfa2019-01-29 15:31:23 -080094 dbusConnection(conn), parent(parent), objServer(objectServer)
James Feistb2eb3f52018-12-04 16:17:50 -080095{
96 sensorInterface =
97 objectServer.add_interface("/xyz/openbmc_project/sensors/cfm/" + name,
98 "xyz.openbmc_project.Sensor.Value");
99
100 if (thresholds::hasWarningInterface(thresholds))
101 {
102 thresholdInterfaceWarning = objectServer.add_interface(
103 "/xyz/openbmc_project/sensors/cfm/" + name,
104 "xyz.openbmc_project.Sensor.Threshold.Warning");
105 }
106 if (thresholds::hasCriticalInterface(thresholds))
107 {
108 thresholdInterfaceCritical = objectServer.add_interface(
109 "/xyz/openbmc_project/sensors/cfm/" + name,
110 "xyz.openbmc_project.Sensor.Threshold.Critical");
111 }
112 setInitialProperties(conn);
113 setupSensorMatch(
114 matches, *dbusConnection, "fan_tach",
115 std::move(
116 [this](const double& value, sdbusplus::message::message& message) {
117 tachReadings[message.get_path()] = value;
118 if (tachRanges.find(message.get_path()) == tachRanges.end())
119 {
120 // calls update reading after updating ranges
121 addTachRanges(message.get_sender(), message.get_path());
122 }
123 else
124 {
125 updateReading();
126 }
127 }));
128}
129
James Feist9566bfa2019-01-29 15:31:23 -0800130CFMSensor::~CFMSensor()
131{
132 objServer.remove_interface(thresholdInterfaceWarning);
133 objServer.remove_interface(thresholdInterfaceCritical);
134 objServer.remove_interface(sensorInterface);
135}
136
James Feistb2eb3f52018-12-04 16:17:50 -0800137void CFMSensor::addTachRanges(const std::string& serviceName,
138 const std::string& path)
139{
140 dbusConnection->async_method_call(
141 [this, path](const boost::system::error_code ec,
142 const boost::container::flat_map<std::string,
143 BasicVariantType>& data) {
144 if (ec)
145 {
146 std::cerr << "Error getting properties from " << path << "\n";
James Feist1ccdb5e2019-01-24 09:44:01 -0800147 return;
James Feistb2eb3f52018-12-04 16:17:50 -0800148 }
149
150 double max = loadVariant<double>(data, "MaxValue");
151 double min = loadVariant<double>(data, "MinValue");
152 tachRanges[path] = std::make_pair(min, max);
153 updateReading();
154 },
155 serviceName, path, "org.freedesktop.DBus.Properties", "GetAll",
156 "xyz.openbmc_project.Sensor.Value");
157}
158
159void CFMSensor::checkThresholds(void)
160{
161 thresholds::checkThresholds(this);
162}
163
164void CFMSensor::updateReading(void)
165{
166 double val = 0.0;
167 if (calculate(val))
168 {
169 if (value != val && parent)
170 {
171 parent->updateReading();
172 }
173 updateValue(val);
174 }
175 else
176 {
177 updateValue(std::numeric_limits<double>::quiet_NaN());
178 }
179}
180
181bool CFMSensor::calculate(double& value)
182{
183 double totalCFM = 0;
184 for (const std::string& tachName : tachs)
185 {
James Feist9566bfa2019-01-29 15:31:23 -0800186
James Feistb2eb3f52018-12-04 16:17:50 -0800187 auto findReading = std::find_if(
188 tachReadings.begin(), tachReadings.end(), [&](const auto& item) {
189 return boost::ends_with(item.first, tachName);
190 });
191 auto findRange = std::find_if(
192 tachRanges.begin(), tachRanges.end(), [&](const auto& item) {
193 return boost::ends_with(item.first, tachName);
194 });
195 if (findReading == tachReadings.end())
196 {
James Feista96329f2019-01-24 10:08:27 -0800197 if (DEBUG)
198 {
199 std::cerr << "Can't find " << tachName << "in readings\n";
200 }
James Feist9566bfa2019-01-29 15:31:23 -0800201 continue; // haven't gotten a reading
James Feistb2eb3f52018-12-04 16:17:50 -0800202 }
203
204 if (findRange == tachRanges.end())
205 {
James Feist523828e2019-03-04 14:38:37 -0800206 std::cerr << "Can't find " << tachName << " in ranges\n";
James Feistb2eb3f52018-12-04 16:17:50 -0800207 return false; // haven't gotten a max / min
208 }
209
210 // avoid divide by 0
211 if (findRange->second.second == 0)
212 {
213 std::cerr << "Tach Max Set to 0 " << tachName << "\n";
214 return false;
215 }
216
217 double rpm = findReading->second;
218
219 // for now assume the min for a fan is always 0, divide by max to get
220 // percent and mult by 100
221 rpm /= findRange->second.second;
222 rpm *= 100;
223
224 if constexpr (DEBUG)
225 {
226 std::cout << "Tach " << tachName << "at " << rpm << "\n";
227 }
228
229 // Do a linear interpolation to get Ci
230 // Ci = C1 + (C2 - C1)/(RPM2 - RPM1) * (TACHi - TACH1)
231
232 double ci = 0;
233 if (rpm == 0)
234 {
235 ci = 0;
236 }
237 else if (rpm < tachMinPercent)
238 {
239 ci = c1;
240 }
241 else if (rpm > tachMaxPercent)
242 {
243 ci = c2;
244 }
245 else
246 {
247 ci = c1 + (((c2 - c1) * (rpm - tachMinPercent)) /
248 (tachMaxPercent - tachMinPercent));
249 }
250
251 // Now calculate the CFM for this tach
252 // CFMi = Ci * Qmaxi * TACHi
253 totalCFM += ci * maxCFM * rpm;
254 }
255
256 // divide by 100 since rpm is in percent
257 value = totalCFM / 100;
James Feist9566bfa2019-01-29 15:31:23 -0800258 return true;
James Feistb2eb3f52018-12-04 16:17:50 -0800259}
260
261static constexpr double exitAirMaxReading = 127;
262static constexpr double exitAirMinReading = -128;
James Feistbc896df2018-11-26 16:28:17 -0800263ExitAirTempSensor::ExitAirTempSensor(
264 std::shared_ptr<sdbusplus::asio::connection>& conn,
James Feistb2eb3f52018-12-04 16:17:50 -0800265 const std::string& sensorName, const std::string& sensorConfiguration,
James Feistbc896df2018-11-26 16:28:17 -0800266 sdbusplus::asio::object_server& objectServer,
267 std::vector<thresholds::Threshold>&& thresholds) :
James Feistb2eb3f52018-12-04 16:17:50 -0800268 Sensor(boost::replace_all_copy(sensorName, " ", "_"),
269 "" /* todo: remove arg from base*/, std::move(thresholds),
270 sensorConfiguration, "xyz.openbmc_project.Configuration.ExitAirTemp",
271 exitAirMaxReading, exitAirMinReading),
James Feist523828e2019-03-04 14:38:37 -0800272 dbusConnection(conn), objServer(objectServer)
James Feistbc896df2018-11-26 16:28:17 -0800273{
274 sensorInterface = objectServer.add_interface(
275 "/xyz/openbmc_project/sensors/temperature/" + name,
276 "xyz.openbmc_project.Sensor.Value");
277
278 if (thresholds::hasWarningInterface(thresholds))
279 {
280 thresholdInterfaceWarning = objectServer.add_interface(
281 "/xyz/openbmc_project/sensors/temperature/" + name,
282 "xyz.openbmc_project.Sensor.Threshold.Warning");
283 }
284 if (thresholds::hasCriticalInterface(thresholds))
285 {
286 thresholdInterfaceCritical = objectServer.add_interface(
287 "/xyz/openbmc_project/sensors/temperature/" + name,
288 "xyz.openbmc_project.Sensor.Threshold.Critical");
289 }
290 setInitialProperties(conn);
291 setupMatches();
James Feist71d31b22019-01-02 16:57:54 -0800292 setupPowerMatch(conn);
James Feistbc896df2018-11-26 16:28:17 -0800293}
294
295ExitAirTempSensor::~ExitAirTempSensor()
296{
James Feist523828e2019-03-04 14:38:37 -0800297 objServer.remove_interface(thresholdInterfaceWarning);
298 objServer.remove_interface(thresholdInterfaceCritical);
299 objServer.remove_interface(sensorInterface);
James Feistbc896df2018-11-26 16:28:17 -0800300}
301
302void ExitAirTempSensor::setupMatches(void)
303{
304
James Feistb2eb3f52018-12-04 16:17:50 -0800305 constexpr const std::array<const char*, 2> matchTypes = {
306 "power", inletTemperatureSensor};
James Feistbc896df2018-11-26 16:28:17 -0800307
James Feistb2eb3f52018-12-04 16:17:50 -0800308 for (const std::string& type : matchTypes)
James Feistbc896df2018-11-26 16:28:17 -0800309 {
James Feistb2eb3f52018-12-04 16:17:50 -0800310 setupSensorMatch(matches, *dbusConnection, type,
311 [this, type](const double& value,
312 sdbusplus::message::message& message) {
313 if (type == "power")
314 {
315 powerReadings[message.get_path()] = value;
316 }
317 else if (type == inletTemperatureSensor)
318 {
319 inletTemp = value;
320 }
321 updateReading();
322 });
James Feistbc896df2018-11-26 16:28:17 -0800323 }
James Feist9566bfa2019-01-29 15:31:23 -0800324 dbusConnection->async_method_call(
325 [this](boost::system::error_code ec,
326 const std::variant<double>& value) {
327 if (ec)
328 {
329 // sensor not ready yet
330 return;
331 }
332
James Feist3eb82622019-02-08 13:10:22 -0800333 inletTemp = std::visit(VariantToDoubleVisitor(), value);
James Feist9566bfa2019-01-29 15:31:23 -0800334 },
335 "xyz.openbmc_project.HwmonTempSensor",
336 std::string("/xyz/openbmc_project/sensors/") + inletTemperatureSensor,
337 "org.freedesktop.DBus.Properties", "Get",
338 "xyz.openbmc_project.Sensor.Value", "Value");
James Feistbc896df2018-11-26 16:28:17 -0800339}
340
341void ExitAirTempSensor::updateReading(void)
342{
343
344 double val = 0.0;
345 if (calculate(val))
346 {
James Feist18af4232019-03-13 11:14:00 -0700347 val = std::floor(val + 0.5);
James Feistbc896df2018-11-26 16:28:17 -0800348 updateValue(val);
349 }
350 else
351 {
352 updateValue(std::numeric_limits<double>::quiet_NaN());
353 }
354}
355
James Feistb2eb3f52018-12-04 16:17:50 -0800356double ExitAirTempSensor::getTotalCFM(void)
James Feistbc896df2018-11-26 16:28:17 -0800357{
James Feistb2eb3f52018-12-04 16:17:50 -0800358 double sum = 0;
359 for (auto& sensor : cfmSensors)
James Feistbc896df2018-11-26 16:28:17 -0800360 {
James Feistb2eb3f52018-12-04 16:17:50 -0800361 double reading = 0;
362 if (!sensor->calculate(reading))
James Feistbc896df2018-11-26 16:28:17 -0800363 {
James Feistbc896df2018-11-26 16:28:17 -0800364 return -1;
365 }
James Feistb2eb3f52018-12-04 16:17:50 -0800366 sum += reading;
James Feistbc896df2018-11-26 16:28:17 -0800367 }
James Feistb2eb3f52018-12-04 16:17:50 -0800368
369 return sum;
James Feistbc896df2018-11-26 16:28:17 -0800370}
371
372bool ExitAirTempSensor::calculate(double& val)
373{
374 static bool firstRead = false;
375 double cfm = getTotalCFM();
376 if (cfm <= 0)
377 {
378 std::cerr << "Error getting cfm\n";
379 return false;
380 }
381
382 // if there is an error getting inlet temp, return error
383 if (std::isnan(inletTemp))
384 {
385 std::cerr << "Cannot get inlet temp\n";
386 val = 0;
387 return false;
388 }
389
390 // if fans are off, just make the exit temp equal to inlet
James Feist71d31b22019-01-02 16:57:54 -0800391 if (!isPowerOn())
James Feistbc896df2018-11-26 16:28:17 -0800392 {
393 val = inletTemp;
394 return true;
395 }
396
397 double totalPower = 0;
398 for (const auto& reading : powerReadings)
399 {
400 if (std::isnan(reading.second))
401 {
402 continue;
403 }
404 totalPower += reading.second;
405 }
406
407 // Calculate power correction factor
408 // Ci = CL + (CH - CL)/(QMax - QMin) * (CFM - QMin)
409 float powerFactor = 0.0;
410 if (cfm <= qMin)
411 {
412 powerFactor = powerFactorMin;
413 }
414 else if (cfm >= qMax)
415 {
416 powerFactor = powerFactorMax;
417 }
418 else
419 {
420 powerFactor = powerFactorMin + ((powerFactorMax - powerFactorMin) /
421 (qMax - qMin) * (cfm - qMin));
422 }
423
424 totalPower *= powerFactor;
425 totalPower += pOffset;
426
427 if (totalPower == 0)
428 {
429 std::cerr << "total power 0\n";
430 val = 0;
431 return false;
432 }
433
434 if constexpr (DEBUG)
435 {
436 std::cout << "Power Factor " << powerFactor << "\n";
437 std::cout << "Inlet Temp " << inletTemp << "\n";
438 std::cout << "Total Power" << totalPower << "\n";
439 }
440
441 // Calculate the exit air temp
442 // Texit = Tfp + (1.76 * TotalPower / CFM * Faltitude)
443 double reading = 1.76 * totalPower * altitudeFactor;
444 reading /= cfm;
445 reading += inletTemp;
446
447 if constexpr (DEBUG)
448 {
449 std::cout << "Reading 1: " << reading << "\n";
450 }
451
452 // Now perform the exponential average
453 // Calculate alpha based on SDR values and CFM
454 // Ai = As + (Af - As)/(QMax - QMin) * (CFM - QMin)
455
456 double alpha = 0.0;
457 if (cfm < qMin)
458 {
459 alpha = alphaS;
460 }
461 else if (cfm >= qMax)
462 {
463 alpha = alphaF;
464 }
465 else
466 {
467 alpha = alphaS + ((alphaF - alphaS) * (cfm - qMin) / (qMax - qMin));
468 }
469
470 auto time = std::chrono::system_clock::now();
471 if (!firstRead)
472 {
473 firstRead = true;
474 lastTime = time;
475 lastReading = reading;
476 }
477 double alphaDT =
478 std::chrono::duration_cast<std::chrono::seconds>(time - lastTime)
479 .count() *
480 alpha;
481
482 // cap at 1.0 or the below fails
483 if (alphaDT > 1.0)
484 {
485 alphaDT = 1.0;
486 }
487
488 if constexpr (DEBUG)
489 {
490 std::cout << "AlphaDT: " << alphaDT << "\n";
491 }
492
493 reading = ((reading * alphaDT) + (lastReading * (1.0 - alphaDT)));
494
495 if constexpr (DEBUG)
496 {
497 std::cout << "Reading 2: " << reading << "\n";
498 }
499
500 val = reading;
501 lastReading = reading;
502 lastTime = time;
503 return true;
504}
505
506void ExitAirTempSensor::checkThresholds(void)
507{
508 thresholds::checkThresholds(this);
509}
510
James Feistbc896df2018-11-26 16:28:17 -0800511static void loadVariantPathArray(
512 const boost::container::flat_map<std::string, BasicVariantType>& data,
513 const std::string& key, std::vector<std::string>& resp)
514{
515 auto it = data.find(key);
516 if (it == data.end())
517 {
518 std::cerr << "Configuration missing " << key << "\n";
519 throw std::invalid_argument("Key Missing");
520 }
521 BasicVariantType copy = it->second;
James Feist3eb82622019-02-08 13:10:22 -0800522 std::vector<std::string> config = std::get<std::vector<std::string>>(copy);
James Feistbc896df2018-11-26 16:28:17 -0800523 for (auto& str : config)
524 {
525 boost::replace_all(str, " ", "_");
526 }
527 resp = std::move(config);
528}
529
530void createSensor(sdbusplus::asio::object_server& objectServer,
James Feistb2eb3f52018-12-04 16:17:50 -0800531 std::shared_ptr<ExitAirTempSensor>& exitAirSensor,
James Feistbc896df2018-11-26 16:28:17 -0800532 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
533{
534 if (!dbusConnection)
535 {
536 std::cerr << "Connection not created\n";
537 return;
538 }
539 dbusConnection->async_method_call(
540 [&](boost::system::error_code ec, const ManagedObjectType& resp) {
541 if (ec)
542 {
543 std::cerr << "Error contacting entity manager\n";
544 return;
545 }
James Feistb2eb3f52018-12-04 16:17:50 -0800546 std::vector<std::unique_ptr<CFMSensor>> cfmSensors;
James Feistbc896df2018-11-26 16:28:17 -0800547 for (const auto& pathPair : resp)
548 {
549 for (const auto& entry : pathPair.second)
550 {
551 if (entry.first == exitAirIface)
552 {
James Feistbc896df2018-11-26 16:28:17 -0800553 // thresholds should be under the same path
554 std::vector<thresholds::Threshold> sensorThresholds;
555 parseThresholdsFromConfig(pathPair.second,
556 sensorThresholds);
James Feistbc896df2018-11-26 16:28:17 -0800557
James Feist523828e2019-03-04 14:38:37 -0800558 std::string name =
559 loadVariant<std::string>(entry.second, "Name");
560 exitAirSensor = std::make_shared<ExitAirTempSensor>(
561 dbusConnection, name, pathPair.first.str,
562 objectServer, std::move(sensorThresholds));
James Feistb2eb3f52018-12-04 16:17:50 -0800563 exitAirSensor->powerFactorMin =
564 loadVariant<double>(entry.second, "PowerFactorMin");
565 exitAirSensor->powerFactorMax =
566 loadVariant<double>(entry.second, "PowerFactorMax");
567 exitAirSensor->qMin =
568 loadVariant<double>(entry.second, "QMin");
569 exitAirSensor->qMax =
570 loadVariant<double>(entry.second, "QMax");
571 exitAirSensor->alphaS =
572 loadVariant<double>(entry.second, "AlphaS");
573 exitAirSensor->alphaF =
574 loadVariant<double>(entry.second, "AlphaF");
James Feistbc896df2018-11-26 16:28:17 -0800575 }
576 else if (entry.first == cfmIface)
577
578 {
James Feistb2eb3f52018-12-04 16:17:50 -0800579 // thresholds should be under the same path
580 std::vector<thresholds::Threshold> sensorThresholds;
581 parseThresholdsFromConfig(pathPair.second,
582 sensorThresholds);
583 std::string name =
584 loadVariant<std::string>(entry.second, "Name");
585 auto sensor = std::make_unique<CFMSensor>(
586 dbusConnection, name, pathPair.first.str,
587 objectServer, std::move(sensorThresholds),
588 exitAirSensor);
589 loadVariantPathArray(entry.second, "Tachs",
590 sensor->tachs);
591 sensor->maxCFM =
592 loadVariant<double>(entry.second, "MaxCFM");
James Feistbc896df2018-11-26 16:28:17 -0800593
594 // change these into percent upon getting the data
James Feistb2eb3f52018-12-04 16:17:50 -0800595 sensor->c1 =
596 loadVariant<double>(entry.second, "C1") / 100;
597 sensor->c2 =
598 loadVariant<double>(entry.second, "C2") / 100;
599 sensor->tachMinPercent =
600 loadVariant<double>(entry.second,
601 "TachMinPercent") /
James Feistbc896df2018-11-26 16:28:17 -0800602 100;
James Feistb2eb3f52018-12-04 16:17:50 -0800603 sensor->tachMaxPercent =
604 loadVariant<double>(entry.second,
605 "TachMaxPercent") /
James Feistbc896df2018-11-26 16:28:17 -0800606 100;
607
James Feistb2eb3f52018-12-04 16:17:50 -0800608 cfmSensors.emplace_back(std::move(sensor));
James Feistbc896df2018-11-26 16:28:17 -0800609 }
610 }
611 }
James Feistb2eb3f52018-12-04 16:17:50 -0800612 if (exitAirSensor)
James Feistbc896df2018-11-26 16:28:17 -0800613 {
James Feistb2eb3f52018-12-04 16:17:50 -0800614 exitAirSensor->cfmSensors = std::move(cfmSensors);
James Feistbc896df2018-11-26 16:28:17 -0800615
James Feistb2eb3f52018-12-04 16:17:50 -0800616 // todo: when power sensors are done delete this fake
617 // reading
618 exitAirSensor->powerReadings["foo"] = 144.0;
James Feistbc896df2018-11-26 16:28:17 -0800619
James Feistb2eb3f52018-12-04 16:17:50 -0800620 exitAirSensor->updateReading();
James Feistbc896df2018-11-26 16:28:17 -0800621 }
622 },
623 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
624 "GetManagedObjects");
625}
626
627int main(int argc, char** argv)
628{
629
630 boost::asio::io_service io;
631 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
632 systemBus->request_name("xyz.openbmc_project.ExitAirTempSensor");
633 sdbusplus::asio::object_server objectServer(systemBus);
634 std::shared_ptr<ExitAirTempSensor> sensor =
635 nullptr; // wait until we find the config
636 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
637
638 io.post([&]() { createSensor(objectServer, sensor, systemBus); });
639
640 boost::asio::deadline_timer configTimer(io);
641
642 std::function<void(sdbusplus::message::message&)> eventHandler =
643 [&](sdbusplus::message::message& message) {
644 configTimer.expires_from_now(boost::posix_time::seconds(1));
645 // create a timer because normally multiple properties change
646 configTimer.async_wait([&](const boost::system::error_code& ec) {
647 if (ec == boost::asio::error::operation_aborted)
648 {
649 return; // we're being canceled
650 }
651 createSensor(objectServer, sensor, systemBus);
652 if (!sensor)
653 {
654 std::cout << "Configuration not detected\n";
655 }
656 });
657 };
658 constexpr const std::array<const char*, 2> monitorIfaces = {exitAirIface,
659 cfmIface};
660 for (const char* type : monitorIfaces)
661 {
662 auto match = std::make_unique<sdbusplus::bus::match::match>(
663 static_cast<sdbusplus::bus::bus&>(*systemBus),
664 "type='signal',member='PropertiesChanged',path_namespace='" +
665 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
666 eventHandler);
667 matches.emplace_back(std::move(match));
668 }
669
670 io.run();
671}