1d1491724SPatrick Venture /**
2d1491724SPatrick Venture  * Copyright 2019 Google Inc.
3d1491724SPatrick Venture  *
4d1491724SPatrick Venture  * Licensed under the Apache License, Version 2.0 (the "License");
5d1491724SPatrick Venture  * you may not use this file except in compliance with the License.
6d1491724SPatrick Venture  * You may obtain a copy of the License at
7d1491724SPatrick Venture  *
8d1491724SPatrick Venture  *     http://www.apache.org/licenses/LICENSE-2.0
9d1491724SPatrick Venture  *
10d1491724SPatrick Venture  * Unless required by applicable law or agreed to in writing, software
11d1491724SPatrick Venture  * distributed under the License is distributed on an "AS IS" BASIS,
12d1491724SPatrick Venture  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d1491724SPatrick Venture  * See the License for the specific language governing permissions and
14d1491724SPatrick Venture  * limitations under the License.
15d1491724SPatrick Venture  */
16d1491724SPatrick Venture 
17d1491724SPatrick Venture #include "pid/buildjson.hpp"
18d1491724SPatrick Venture 
19d1491724SPatrick Venture #include "conf.hpp"
20d1491724SPatrick Venture 
21d1491724SPatrick Venture #include <map>
22d1491724SPatrick Venture #include <nlohmann/json.hpp>
23d1491724SPatrick Venture #include <tuple>
24d1491724SPatrick Venture 
25d1491724SPatrick Venture using json = nlohmann::json;
26d1491724SPatrick Venture 
27f81f2886SJames Feist namespace conf
28f81f2886SJames Feist {
29f81f2886SJames Feist void from_json(const json& j, conf::ControllerInfo& c)
30d1491724SPatrick Venture {
31d1491724SPatrick Venture     j.at("type").get_to(c.type);
32d1491724SPatrick Venture     j.at("inputs").get_to(c.inputs);
33d1491724SPatrick Venture     j.at("setpoint").get_to(c.setpoint);
34d1491724SPatrick Venture 
35d1491724SPatrick Venture     /* TODO: We need to handle parsing other PID controller configurations.
36d1491724SPatrick Venture      * We can do that by checking for different keys and making the decision
37d1491724SPatrick Venture      * accordingly.
38d1491724SPatrick Venture      */
39d1491724SPatrick Venture     auto p = j.at("pid");
40*375f7098SHank Liou 
41*375f7098SHank Liou     auto positiveHysteresis = p.find("positiveHysteresis");
42*375f7098SHank Liou     auto negativeHysteresis = p.find("negativeHysteresis");
43*375f7098SHank Liou     auto positiveHysteresisValue = 0.0;
44*375f7098SHank Liou     auto negativeHysteresisValue = 0.0;
45*375f7098SHank Liou     if (positiveHysteresis != p.end())
46*375f7098SHank Liou     {
47*375f7098SHank Liou         p.at("positiveHysteresis").get_to(positiveHysteresisValue);
48*375f7098SHank Liou     }
49*375f7098SHank Liou     if (negativeHysteresis != p.end())
50*375f7098SHank Liou     {
51*375f7098SHank Liou         p.at("negativeHysteresis").get_to(negativeHysteresisValue);
52*375f7098SHank Liou     }
53*375f7098SHank Liou 
54*375f7098SHank Liou     if (c.type != "stepwise")
55*375f7098SHank Liou     {
56d1491724SPatrick Venture         p.at("samplePeriod").get_to(c.pidInfo.ts);
57d1491724SPatrick Venture         p.at("proportionalCoeff").get_to(c.pidInfo.proportionalCoeff);
58d1491724SPatrick Venture         p.at("integralCoeff").get_to(c.pidInfo.integralCoeff);
59903b0427SPatrick Venture         p.at("feedFwdOffsetCoeff").get_to(c.pidInfo.feedFwdOffset);
60d1491724SPatrick Venture         p.at("feedFwdGainCoeff").get_to(c.pidInfo.feedFwdGain);
61d1491724SPatrick Venture         p.at("integralLimit_min").get_to(c.pidInfo.integralLimit.min);
62d1491724SPatrick Venture         p.at("integralLimit_max").get_to(c.pidInfo.integralLimit.max);
63d1491724SPatrick Venture         p.at("outLim_min").get_to(c.pidInfo.outLim.min);
64d1491724SPatrick Venture         p.at("outLim_max").get_to(c.pidInfo.outLim.max);
65d1491724SPatrick Venture         p.at("slewNeg").get_to(c.pidInfo.slewNeg);
66d1491724SPatrick Venture         p.at("slewPos").get_to(c.pidInfo.slewPos);
67d1491724SPatrick Venture 
68*375f7098SHank Liou         c.pidInfo.positiveHysteresis = positiveHysteresisValue;
69*375f7098SHank Liou         c.pidInfo.negativeHysteresis = negativeHysteresisValue;
70d1491724SPatrick Venture     }
71d1491724SPatrick Venture     else
72d1491724SPatrick Venture     {
73*375f7098SHank Liou         p.at("samplePeriod").get_to(c.stepwiseInfo.ts);
74*375f7098SHank Liou         p.at("isCeiling").get_to(c.stepwiseInfo.isCeiling);
75*375f7098SHank Liou 
76*375f7098SHank Liou         for (size_t i = 0; i < ec::maxStepwisePoints; i++)
77*375f7098SHank Liou         {
78*375f7098SHank Liou             c.stepwiseInfo.reading[i] =
79*375f7098SHank Liou                 std::numeric_limits<double>::quiet_NaN();
80*375f7098SHank Liou             c.stepwiseInfo.output[i] = std::numeric_limits<double>::quiet_NaN();
81d1491724SPatrick Venture         }
82d1491724SPatrick Venture 
83*375f7098SHank Liou         auto reading = p.find("reading");
84*375f7098SHank Liou         if (reading != p.end())
85d1491724SPatrick Venture         {
86*375f7098SHank Liou             auto r = p.at("reading");
87*375f7098SHank Liou             for (size_t i = 0; i < ec::maxStepwisePoints; i++)
88*375f7098SHank Liou             {
89*375f7098SHank Liou                 auto n = r.find(std::to_string(i));
90*375f7098SHank Liou                 if (n != r.end())
91*375f7098SHank Liou                 {
92*375f7098SHank Liou                     r.at(std::to_string(i)).get_to(c.stepwiseInfo.reading[i]);
93d1491724SPatrick Venture                 }
94*375f7098SHank Liou             }
95*375f7098SHank Liou         }
96*375f7098SHank Liou 
97*375f7098SHank Liou         auto output = p.find("output");
98*375f7098SHank Liou         if (output != p.end())
99d1491724SPatrick Venture         {
100*375f7098SHank Liou             auto o = p.at("output");
101*375f7098SHank Liou             for (size_t i = 0; i < ec::maxStepwisePoints; i++)
102*375f7098SHank Liou             {
103*375f7098SHank Liou                 auto n = o.find(std::to_string(i));
104*375f7098SHank Liou                 if (n != o.end())
105*375f7098SHank Liou                 {
106*375f7098SHank Liou                     o.at(std::to_string(i)).get_to(c.stepwiseInfo.output[i]);
107*375f7098SHank Liou                 }
108*375f7098SHank Liou             }
109*375f7098SHank Liou         }
110*375f7098SHank Liou 
111*375f7098SHank Liou         c.stepwiseInfo.positiveHysteresis = positiveHysteresisValue;
112*375f7098SHank Liou         c.stepwiseInfo.negativeHysteresis = negativeHysteresisValue;
113d1491724SPatrick Venture     }
114d1491724SPatrick Venture }
115f81f2886SJames Feist } // namespace conf
116d1491724SPatrick Venture 
117f81f2886SJames Feist std::pair<std::map<int64_t, conf::PIDConf>,
118f81f2886SJames Feist           std::map<int64_t, struct conf::ZoneConfig>>
119d1491724SPatrick Venture     buildPIDsFromJson(const json& data)
120d1491724SPatrick Venture {
121d1491724SPatrick Venture     // zone -> pids
122f81f2886SJames Feist     std::map<int64_t, conf::PIDConf> pidConfig;
123d1491724SPatrick Venture     // zone -> configs
124f81f2886SJames Feist     std::map<int64_t, struct conf::ZoneConfig> zoneConfig;
125d1491724SPatrick Venture 
126d1491724SPatrick Venture     /* TODO: if zones is empty, that's invalid. */
127d1491724SPatrick Venture     auto zones = data["zones"];
128d1491724SPatrick Venture     for (const auto& zone : zones)
129d1491724SPatrick Venture     {
130d1491724SPatrick Venture         int64_t id;
131f81f2886SJames Feist         conf::PIDConf thisZone;
132f81f2886SJames Feist         struct conf::ZoneConfig thisZoneConfig;
133d1491724SPatrick Venture 
134d1491724SPatrick Venture         /* TODO: using at() throws a specific exception we can catch */
135d1491724SPatrick Venture         id = zone["id"];
1363484bedaSJames Feist         thisZoneConfig.minThermalOutput = zone["minThermalOutput"];
137d1491724SPatrick Venture         thisZoneConfig.failsafePercent = zone["failsafePercent"];
138d1491724SPatrick Venture 
139d1491724SPatrick Venture         auto pids = zone["pids"];
140d1491724SPatrick Venture         for (const auto& pid : pids)
141d1491724SPatrick Venture         {
142d1491724SPatrick Venture             auto name = pid["name"];
143f81f2886SJames Feist             auto item = pid.get<conf::ControllerInfo>();
144d1491724SPatrick Venture 
145d1491724SPatrick Venture             thisZone[name] = item;
146d1491724SPatrick Venture         }
147d1491724SPatrick Venture 
148d1491724SPatrick Venture         pidConfig[id] = thisZone;
149d1491724SPatrick Venture         zoneConfig[id] = thisZoneConfig;
150d1491724SPatrick Venture     }
151d1491724SPatrick Venture 
152d1491724SPatrick Venture     return std::make_pair(pidConfig, zoneConfig);
153d1491724SPatrick Venture }
154