/** * Copyright 2017 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "dbuspassive.hpp" #include "dbus/util.hpp" #include #include #include #include #include #include #include std::unique_ptr DbusPassive::createDbusPassive( sdbusplus::bus::bus& bus, const std::string& type, const std::string& id, DbusHelperInterface* helper) { if (helper == nullptr) { return nullptr; } if (!validType(type)) { return nullptr; } /* Need to get the scale and initial value */ auto tempBus = sdbusplus::bus::new_system(); /* service == busname */ std::string path = getSensorPath(type, id); struct SensorProperties settings; bool failed; try { std::string service = helper->getService(tempBus, sensorintf, path); helper->getProperties(tempBus, service, path, &settings); failed = helper->thresholdsAsserted(tempBus, service, path); } catch (const std::exception& e) { return nullptr; } return std::make_unique(bus, type, id, helper, settings, failed); } DbusPassive::DbusPassive(sdbusplus::bus::bus& bus, const std::string& type, const std::string& id, DbusHelperInterface* helper, const struct SensorProperties& settings, bool failed) : ReadInterface(), _bus(bus), _signal(bus, getMatch(type, id).c_str(), dbusHandleSignal, this), _id(id), _helper(helper), _failed(failed) { _scale = settings.scale; _value = settings.value * pow(10, _scale); _updated = std::chrono::high_resolution_clock::now(); } ReadReturn DbusPassive::read(void) { std::lock_guard guard(_lock); struct ReadReturn r = {_value, _updated}; return r; } void DbusPassive::setValue(double value) { std::lock_guard guard(_lock); _value = value; _updated = std::chrono::high_resolution_clock::now(); } bool DbusPassive::getFailed(void) const { return _failed; } void DbusPassive::setFailed(bool value) { _failed = value; } int64_t DbusPassive::getScale(void) { return _scale; } std::string DbusPassive::getID(void) { return _id; } int handleSensorValue(sdbusplus::message::message& msg, DbusPassive* owner) { std::string msgSensor; std::map> msgData; msg.read(msgSensor, msgData); if (msgSensor == "xyz.openbmc_project.Sensor.Value") { auto valPropMap = msgData.find("Value"); if (valPropMap != msgData.end()) { double value = std::visit(VariantToDoubleVisitor(), valPropMap->second); value *= std::pow(10, owner->getScale()); owner->setValue(value); } } else if (msgSensor == "xyz.openbmc_project.Sensor.Threshold.Critical") { auto criticalAlarmLow = msgData.find("CriticalAlarmLow"); auto criticalAlarmHigh = msgData.find("CriticalAlarmHigh"); if (criticalAlarmHigh == msgData.end() && criticalAlarmLow == msgData.end()) { return 0; } bool asserted = false; if (criticalAlarmLow != msgData.end()) { asserted = std::get(criticalAlarmLow->second); } // checking both as in theory you could de-assert one threshold and // assert the other at the same moment if (!asserted && criticalAlarmHigh != msgData.end()) { asserted = std::get(criticalAlarmHigh->second); } owner->setFailed(asserted); } return 0; } int dbusHandleSignal(sd_bus_message* msg, void* usrData, sd_bus_error* err) { auto sdbpMsg = sdbusplus::message::message(msg); DbusPassive* obj = static_cast(usrData); return handleSensorValue(sdbpMsg, obj); }