1 /**
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 #include <chrono>
17 #include <cmath>
18 #include <memory>
19 #include <mutex>
20 #include <sdbusplus/bus.hpp>
21 #include <string>
22 
23 #include "dbuspassive.hpp"
24 #include "dbus/util.hpp"
25 
26 std::unique_ptr<ReadInterface> DbusPassive::CreateDbusPassive(
27     sdbusplus::bus::bus& bus, const std::string& type,
28     const std::string& id, DbusHelperInterface *helper)
29 {
30     if (helper == nullptr)
31     {
32         return nullptr;
33     }
34     if (!ValidType(type))
35     {
36         return nullptr;
37     }
38 
39     return std::make_unique<DbusPassive>(bus, type, id, helper);
40 }
41 
42 DbusPassive::DbusPassive(
43     sdbusplus::bus::bus& bus,
44     const std::string& type,
45     const std::string& id,
46     DbusHelperInterface *helper)
47     : ReadInterface(),
48       _bus(bus),
49       _signal(bus, GetMatch(type, id).c_str(), DbusHandleSignal, this),
50       _id(id),
51       _helper(helper)
52 {
53     /* Need to get the scale and initial value */
54     auto tempBus = sdbusplus::bus::new_default();
55     /* service == busname */
56     std::string path = GetSensorPath(type, id);
57     std::string service = _helper->GetService(tempBus, sensorintf, path);
58 
59     struct SensorProperties settings;
60     _helper->GetProperties(tempBus, service, path, &settings);
61 
62     _scale = settings.scale;
63     _value = settings.value * pow(10, _scale);
64     _updated = std::chrono::high_resolution_clock::now();
65 }
66 
67 ReadReturn DbusPassive::read(void)
68 {
69     std::lock_guard<std::mutex> guard(_lock);
70 
71     struct ReadReturn r = {
72         _value,
73         _updated
74     };
75 
76     return r;
77 }
78 
79 void DbusPassive::setValue(double value)
80 {
81     std::lock_guard<std::mutex> guard(_lock);
82 
83     _value = value;
84     _updated = std::chrono::high_resolution_clock::now();
85 }
86 
87 int64_t DbusPassive::getScale(void)
88 {
89     return _scale;
90 }
91 
92 std::string DbusPassive::getId(void)
93 {
94     return _id;
95 }
96 
97 int HandleSensorValue(sdbusplus::message::message& msg, DbusPassive* owner)
98 {
99     std::string msgSensor;
100     std::map<std::string, sdbusplus::message::variant<int64_t>> msgData;
101 
102     msg.read(msgSensor, msgData);
103 
104     if (msgSensor == "xyz.openbmc_project.Sensor.Value")
105     {
106         auto valPropMap = msgData.find("Value");
107         if (valPropMap != msgData.end())
108         {
109             int64_t rawValue = sdbusplus::message::variant_ns::get<int64_t>(
110                 valPropMap->second);
111 
112             double value = rawValue * std::pow(10, owner->getScale());
113 
114             owner->setValue(value);
115         }
116     }
117 
118     return 0;
119 }
120 
121 int DbusHandleSignal(sd_bus_message* msg, void* usrData, sd_bus_error* err)
122 {
123     auto sdbpMsg = sdbusplus::message::message(msg);
124     DbusPassive* obj = static_cast<DbusPassive*>(usrData);
125 
126     return HandleSensorValue(sdbpMsg, obj);
127 }
128