pid: zone split out builders

To enable unit-testing, split the builders into their own
object files.

Tested: Ran on quanta-q71l board and it behaved as expected.

Change-Id: I92168ec9ae4946d12328e9c0b94a36bb89d0f718
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/pid/builder.cpp b/pid/builder.cpp
new file mode 100644
index 0000000..45838e7
--- /dev/null
+++ b/pid/builder.cpp
@@ -0,0 +1,133 @@
+/**
+ * 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 "pid/builder.hpp"
+
+#include <iostream>
+#include <memory>
+#include <sdbusplus/bus.hpp>
+#include <unordered_map>
+
+#include "conf.hpp"
+#include "pid/fancontroller.hpp"
+#include "pid/thermalcontroller.hpp"
+
+static constexpr bool deferSignals = true;
+static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone";
+
+static std::string GetControlPath(int64_t zone)
+{
+    return std::string(objectPath) + std::to_string(zone);
+}
+
+std::unordered_map<int64_t, std::unique_ptr<PIDZone>> BuildZones(
+        std::map<int64_t, PIDConf>& zonePids,
+        std::map<int64_t, struct zone>& zoneConfigs,
+        SensorManager& mgr,
+        sdbusplus::bus::bus& modeControlBus)
+{
+    std::unordered_map<int64_t, std::unique_ptr<PIDZone>> zones;
+
+    for (auto& zi : zonePids)
+    {
+        auto zoneId = static_cast<int64_t>(zi.first);
+        /* The above shouldn't be necessary but is, and I am having trouble
+         * locating my notes on why.  If I recall correctly it was casting it
+         * down to a byte in at least some cases causing weird behaviors.
+         */
+
+        auto zoneConf = zoneConfigs.find(zoneId);
+        if (zoneConf == zoneConfigs.end())
+        {
+            /* The Zone doesn't have a configuration, bail. */
+            static constexpr auto err =
+                "Bailing during load, missing Zone Configuration";
+            std::cerr << err << std::endl;
+            throw std::runtime_error(err);
+        }
+
+        PIDConf& PIDConfig = zi.second;
+
+        auto zone = std::make_unique<PIDZone>(
+                        zoneId,
+                        zoneConf->second.minthermalrpm,
+                        zoneConf->second.failsafepercent,
+                        mgr,
+                        modeControlBus,
+                        GetControlPath(zi.first).c_str(),
+                        deferSignals);
+
+        std::cerr << "Zone Id: " << zone->getZoneId() << "\n";
+
+        // For each PID create a Controller and a Sensor.
+        for (auto& pit : PIDConfig)
+        {
+            std::vector<std::string> inputs;
+            std::string name = pit.first;
+            struct controller_info* info = &pit.second;
+
+            std::cerr << "PID name: " << name << "\n";
+
+            /*
+             * TODO(venture): Need to check if input is known to the
+             * SensorManager.
+             */
+            if (info->type == "fan")
+            {
+                for (auto i : info->inputs)
+                {
+                    inputs.push_back(i);
+                    zone->addFanInput(i);
+                }
+
+                auto pid = FanController::CreateFanPid(
+                               zone.get(),
+                               name,
+                               inputs,
+                               info->info);
+                zone->addFanPID(std::move(pid));
+            }
+            else if (info->type == "temp" || info->type == "margin")
+            {
+                for (auto i : info->inputs)
+                {
+                    inputs.push_back(i);
+                    zone->addThermalInput(i);
+                }
+
+                auto pid = ThermalController::CreateThermalPid(
+                               zone.get(),
+                               name,
+                               inputs,
+                               info->setpoint,
+                               info->info);
+                zone->addThermalPID(std::move(pid));
+            }
+
+            std::cerr << "inputs: ";
+            for (auto& i : inputs)
+            {
+                std::cerr << i << ", ";
+            }
+            std::cerr << "\n";
+        }
+
+        zone->emit_object_added();
+        zones[zoneId] = std::move(zone);
+    }
+
+    return zones;
+}