blob: 66e48a885e8755342606f2fc414518513c361052 [file] [log] [blame]
Brad Bishope55ef3d2016-12-19 09:12:40 -05001/**
2 * Copyright © 2016 IBM 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#include <iostream>
17#include <memory>
Brad Bishop9c7b6e02016-12-19 12:43:36 -050018#include <cstring>
19#include <cstdlib>
20#include <chrono>
Brad Bishop74aa4dd2017-01-06 09:50:31 -050021#include <algorithm>
Brad Bishope55ef3d2016-12-19 09:12:40 -050022#include "sensorset.hpp"
Brad Bishope55ef3d2016-12-19 09:12:40 -050023#include "hwmon.hpp"
24#include "sysfs.hpp"
Brad Bishopd499ca62016-12-19 09:24:50 -050025#include "mainloop.hpp"
Brad Bishope55ef3d2016-12-19 09:12:40 -050026
Brad Bishop9c7b6e02016-12-19 12:43:36 -050027using namespace std::literals::chrono_literals;
28
Brad Bishop74aa4dd2017-01-06 09:50:31 -050029static constexpr auto typeAttrMap =
30{
31 // 1 - hwmon class
32 // 2 - unit
33 // 3 - sysfs scaling factor
34 std::make_tuple(
35 hwmon::type::ctemp,
36 ValueInterface::Unit::DegreesC,
37 -3),
38 std::make_tuple(
39 hwmon::type::cfan,
40 ValueInterface::Unit::RPMS,
41 0),
42 std::make_tuple(
43 hwmon::type::cvolt,
44 ValueInterface::Unit::Volts,
45 -3),
46};
47
48auto getHwmonType(decltype(typeAttrMap)::const_reference attrs)
49{
50 return std::get<0>(attrs);
51}
52
53auto getUnit(decltype(typeAttrMap)::const_reference attrs)
54{
55 return std::get<1>(attrs);
56}
57
58auto getScale(decltype(typeAttrMap)::const_reference attrs)
59{
60 return std::get<2>(attrs);
61}
62
Brad Bishopb9e2b072016-12-19 13:47:10 -050063MainLoop::MainLoop(
Brad Bishop9c7b6e02016-12-19 12:43:36 -050064 sdbusplus::bus::bus&& bus,
Brad Bishopb9e2b072016-12-19 13:47:10 -050065 const std::string& path,
66 const char* prefix,
67 const char* root)
Brad Bishop9c7b6e02016-12-19 12:43:36 -050068 : _bus(std::move(bus)),
69 _manager(sdbusplus::server::manager::manager(_bus, root)),
70 _shutdown(false),
Brad Bishopb9e2b072016-12-19 13:47:10 -050071 _path(path),
72 _prefix(prefix),
Brad Bishop3c344d32017-01-05 11:48:39 -050073 _root(root),
74 state()
Brad Bishopd499ca62016-12-19 09:24:50 -050075{
Brad Bishop9c7b6e02016-12-19 12:43:36 -050076 if (_path.back() == '/')
77 {
78 _path.pop_back();
79 }
Brad Bishopd499ca62016-12-19 09:24:50 -050080}
81
82void MainLoop::shutdown() noexcept
83{
84 _shutdown = true;
85}
86
87void MainLoop::run()
Brad Bishope55ef3d2016-12-19 09:12:40 -050088{
89 // Check sysfs for available sensors.
Brad Bishopd499ca62016-12-19 09:24:50 -050090 auto sensors = std::make_unique<SensorSet>(_path);
Brad Bishope55ef3d2016-12-19 09:12:40 -050091
Brad Bishop75b4ab82017-01-06 09:33:50 -050092 for (auto& i : *sensors)
93 {
Brad Bishop73831cd2017-01-06 09:37:22 -050094 // Ignore inputs without a label.
95 std::string envKey = "LABEL_" + i.first.first + i.first.second;
96 std::string label;
97
98 auto env = getenv(envKey.c_str());
99
100 if (env)
101 {
102 label.assign(env);
103 }
104
105 if (label.empty())
106 {
107 continue;
108 }
109
Brad Bishop47378502017-01-06 09:47:41 -0500110 // Get the initial value for the value interface.
111 auto sysfsPath = make_sysfs_path(
112 _path,
113 i.first.first,
114 i.first.second,
115 hwmon::entry::input);
116 int val = 0;
117 read_sysfs(sysfsPath, val);
118
Brad Bishop075f7a22017-01-06 09:45:08 -0500119 Object o;
120 std::string objectPath{_root};
121
122 objectPath.append("/");
123 objectPath.append(i.first.first);
124 objectPath.append("/");
125 objectPath.append(label);
126
127 auto iface = std::make_shared<ValueObject>(_bus, objectPath.c_str());
Brad Bishop47378502017-01-06 09:47:41 -0500128 iface->value(val);
Brad Bishop74aa4dd2017-01-06 09:50:31 -0500129
130 const auto& attrs = std::find_if(
131 typeAttrMap.begin(),
132 typeAttrMap.end(),
133 [&](const auto & e)
134 {
135 return i.first.first == getHwmonType(e);
136 });
137 if (attrs != typeAttrMap.end())
138 {
139 iface->unit(getUnit(*attrs));
140 iface->scale(getScale(*attrs));
141 }
142
Brad Bishop075f7a22017-01-06 09:45:08 -0500143 o.emplace(InterfaceType::VALUE, iface);
144
145 auto value = std::make_tuple(
146 std::move(i.second),
147 std::move(label),
148 std::move(o));
Brad Bishop73831cd2017-01-06 09:37:22 -0500149
Brad Bishop75b4ab82017-01-06 09:33:50 -0500150 state[std::move(i.first)] = std::move(value);
151 }
152
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500153 {
154 struct Free
155 {
156 void operator()(char* ptr) const
157 {
158 free(ptr);
159 }
160 };
161
162 auto copy = std::unique_ptr<char, Free>(strdup(_path.c_str()));
163 auto busname = std::string(_prefix) + '.' + basename(copy.get());
164 _bus.request_name(busname.c_str());
165 }
166
Brad Bishope55ef3d2016-12-19 09:12:40 -0500167 // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
168 // ensure the objects all exist?
169
170 // Polling loop.
Brad Bishopd499ca62016-12-19 09:24:50 -0500171 while (!_shutdown)
Brad Bishope55ef3d2016-12-19 09:12:40 -0500172 {
173 // Iterate through all the sensors.
Brad Bishop75b4ab82017-01-06 09:33:50 -0500174 for (auto& i : state)
Brad Bishope55ef3d2016-12-19 09:12:40 -0500175 {
Brad Bishop75b4ab82017-01-06 09:33:50 -0500176 auto& attrs = std::get<0>(i.second);
177 if (attrs.find(hwmon::entry::input) != attrs.end())
Brad Bishope55ef3d2016-12-19 09:12:40 -0500178 {
179 // Read value from sensor.
180 int value = 0;
Brad Bishopd499ca62016-12-19 09:24:50 -0500181 read_sysfs(make_sysfs_path(_path,
Brad Bishope55ef3d2016-12-19 09:12:40 -0500182 i.first.first, i.first.second,
183 hwmon::entry::input),
184 value);
185
Brad Bishopdddb7152017-01-06 09:54:23 -0500186 auto& obj = std::get<Object>(i.second);
187 auto iface = obj.find(InterfaceType::VALUE);
188
189 if (iface != obj.end())
190 {
191 auto realIface = std::experimental::any_cast<std::shared_ptr<ValueObject>>
192 (iface->second);
193 realIface->value(value);
194 }
Brad Bishope55ef3d2016-12-19 09:12:40 -0500195 }
196 }
197
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500198 // Respond to DBus
199 _bus.process_discard();
200
Brad Bishope55ef3d2016-12-19 09:12:40 -0500201 // Sleep until next interval.
202 // TODO: Issue#5 - Make this configurable.
203 // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
Brad Bishop9c7b6e02016-12-19 12:43:36 -0500204 _bus.wait((1000000us).count());
Brad Bishope55ef3d2016-12-19 09:12:40 -0500205
206 // TODO: Issue#7 - Should probably periodically check the SensorSet
207 // for new entries.
208 }
Brad Bishope55ef3d2016-12-19 09:12:40 -0500209}
210
211// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4