blob: 30c1172b567b5f408bcde51620971fb6796155e9 [file] [log] [blame]
Matthew Barthfd05d642019-11-14 15:01:57 -06001/**
2 * Copyright © 2019 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 <string>
Matthew Barth0961fae2019-11-15 09:00:27 -060017#include <filesystem>
18#include <fstream>
19#include <nlohmann/json.hpp>
20#include <phosphor-logging/log.hpp>
Matthew Barthfd05d642019-11-14 15:01:57 -060021
22#include "json_config.hpp"
Matthew Barthe7566632019-11-18 16:13:04 -060023#include "tach.hpp"
24#include "gpio.hpp"
Matthew Barthfd05d642019-11-14 15:01:57 -060025
26namespace phosphor
27{
28namespace fan
29{
30namespace presence
31{
32
Matthew Barth0961fae2019-11-15 09:00:27 -060033using json = nlohmann::json;
34namespace fs = std::filesystem;
35using namespace phosphor::logging;
36
Matthew Barthfd05d642019-11-14 15:01:57 -060037policies JsonConfig::_policies;
Matthew Barthe7566632019-11-18 16:13:04 -060038const std::map<std::string, methodHandler> JsonConfig::_methods =
39{
40 {"tach", method::getTach},
41 {"gpio", method::getGpio}
42};
Matthew Barthfd05d642019-11-14 15:01:57 -060043
44JsonConfig::JsonConfig(const std::string& jsonFile)
45{
Matthew Barth0961fae2019-11-15 09:00:27 -060046 fs::path confFile{jsonFile};
47 std::ifstream file;
48 json jsonConf;
Matthew Barthfd05d642019-11-14 15:01:57 -060049
Matthew Barth0961fae2019-11-15 09:00:27 -060050 if (fs::exists(confFile))
51 {
52 file.open(confFile);
53 try
54 {
55 jsonConf = json::parse(file);
56 }
57 catch (std::exception& e)
58 {
59 log<level::ERR>("Failed to parse JSON config file",
60 entry("JSON_FILE=%s", jsonFile.c_str()),
61 entry("JSON_ERROR=%s", e.what()));
62 throw std::runtime_error("Failed to parse JSON config file");
63 }
64 }
65 else
66 {
67 log<level::ERR>("Unable to open JSON config file",
68 entry("JSON_FILE=%s", jsonFile.c_str()));
69 throw std::runtime_error("Unable to open JSON config file");
70 }
Matthew Barth4a94dec2019-11-15 10:40:47 -060071
72 process(jsonConf);
Matthew Barthfd05d642019-11-14 15:01:57 -060073}
74
75const policies& JsonConfig::get()
76{
77 return _policies;
78}
79
Matthew Barth4a94dec2019-11-15 10:40:47 -060080void JsonConfig::process(const json& jsonConf)
81{
82 for (auto& member : jsonConf)
83 {
Matthew Barthe7566632019-11-18 16:13:04 -060084 if (!member.contains("name") || !member.contains("path") ||
85 !member.contains("methods"))
Matthew Barth4a94dec2019-11-15 10:40:47 -060086 {
87 log<level::ERR>(
88 "Missing required fan presence properties",
Matthew Barthe7566632019-11-18 16:13:04 -060089 entry("REQUIRED_PROPERTIES=%s", "{name, path, methods}"));
Matthew Barth4a94dec2019-11-15 10:40:47 -060090 throw std::runtime_error(
91 "Missing required fan presence properties");
92 }
93 // Create a fan object
94 _fans.emplace_back(std::make_tuple(member["name"], member["path"]));
Matthew Barthe7566632019-11-18 16:13:04 -060095
96 // Loop thru the configured methods of presence detection
97 for (auto& method : member["methods"].items())
98 {
99 if (!method.value().contains("type"))
100 {
101 log<level::ERR>(
102 "Missing required fan presence method type",
103 entry("FAN_NAME=%s",
104 member["name"].get<std::string>().c_str()));
105 throw std::runtime_error(
106 "Missing required fan presence method type");
107 }
108 // The method type of fan presence detection
109 // (Must have a supported function within the method namespace)
110 auto type = method.value()["type"].get<std::string>();
111 std::transform(type.begin(), type.end(), type.begin(), tolower);
112 auto func = _methods.find(type);
113 if (func != _methods.end())
114 {
115 // Call function for method type
116 auto sensor = func->second((_fans.size() - 1), method.value());
117 if (sensor)
118 {
119 _sensors.emplace_back(std::move(sensor));
120 }
121 }
122 else
123 {
124 log<level::ERR>("Invalid fan presence method type",
125 entry("FAN_NAME=%s",
126 member["name"].get<std::string>().c_str()),
127 entry("METHOD_TYPE=%s", type.c_str()));
128 throw std::runtime_error("Invalid fan presence method type");
129 }
130 }
Matthew Barth4a94dec2019-11-15 10:40:47 -0600131 }
132}
133
Matthew Barthe7566632019-11-18 16:13:04 -0600134/**
135 * Methods of fan presence detection function definitions
136 */
137namespace method
138{
139 // Get a constructed presence sensor for fan presence detection by tach
140 std::unique_ptr<PresenceSensor> getTach(size_t fanIndex, const json& method)
141 {
142 return nullptr;
143 }
144
145 // Get a constructed presence sensor for fan presence detection by gpio
146 std::unique_ptr<PresenceSensor> getGpio(size_t fanIndex, const json& method)
147 {
148 return nullptr;
149 }
150
151} // namespace method
152
Matthew Barthfd05d642019-11-14 15:01:57 -0600153} // namespace presence
154} // namespace fan
155} // namespace phosphor