Add SensorPurpose for total_power sensor

Change will allow users to find the total system/chassis power sensor by
querying the SensorPurpose for TotalPower.
The total_power chassis association is being removed, since the
SensorPurpose will be used in its place.

Tested on Rainier.

'''
$ busctl call xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/object_mapper xyz.openbmc_project.ObjectMapper GetSubTree sias "/" 0 1 "xyz.openbmc_project.Sensor.Purpose"

a{sa{sas}} 1 "/xyz/openbmc_project/sensors/power/total_power" 1 "org.open_power.OCC.Control" 6 "org.freedesktop.DBus.Introspectable" "org.freedesktop.DBus.Peer" "org.freedesktop.DBus.Properties" "xyz.openbmc_project.Sensor.Purpose" "xyz.openbmc_project.Sensor.Value" "xyz.openbmc_project.State.Decorator.OperationalStatus"

$ busctl -l introspect org.open_power.OCC.Control /xyz/openbmc_project/sensors/power/total_power

NAME                                                  TYPE      SIGNATURE RESULT/VALUE                                                                                                                                      FLAGS
org.freedesktop.DBus.Introspectable                   interface -         -                                                                                                                                                 -
.Introspect                                           method    -         s                                                                                                                                                 -
org.freedesktop.DBus.Peer                             interface -         -                                                                                                                                                 -
.GetMachineId                                         method    -         s                                                                                                                                                 -
.Ping                                                 method    -         -                                                                                                                                                 -
org.freedesktop.DBus.Properties                       interface -         -                                                                                                                                                 -
.Get                                                  method    ss        v                                                                                                                                                 -
.GetAll                                               method    s         a{sv}                                                                                                                                             -
.Set                                                  method    ssv       -                                                                                                                                                 -
.PropertiesChanged                                    signal    sa{sv}as  -                                                                                                                                                 -
xyz.openbmc_project.Association.Definitions           interface -         -                                                                                                                                                 -
.Associations                                         property  a(sss)    1 "chassis" "all_sensors" "/xyz/openbmc_project/inventory/system/chassis" emits-change writable
B
xyz.openbmc_project.Sensor.Purpose                    interface -         -                                                                                                                                                 -
.Purpose                                              property  as        1 "xyz.openbmc_project.Sensor.Purpose.SensorPurpose.TotalPower"                                                                                   emits-change
xyz.openbmc_project.Sensor.Value                      interface -         -                                                                                                                                                 -
.MaxValue                                             property  d         inf                                                                                                                                               emits-change writable
.MinValue                                             property  d         -inf                                                                                                                                              emits-change writable
.Unit                                                 property  s         "xyz.openbmc_project.Sensor.Value.Unit.Watts"                                                                                                     emits-change writable
.Value                                                property  d         419                                                                                                                                               emits-change writable
xyz.openbmc_project.State.Decorator.OperationalStatus interface -         -                                                                                                                                                 -
.Functional                                           property  b         true                                                                                                                                              emits-change writable
'''

Change-Id: I414c01e81cbb965d9ab68bafa06565d997abbe0f
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/occ_dbus.cpp b/occ_dbus.cpp
index e018246..f68aa2a 100644
--- a/occ_dbus.cpp
+++ b/occ_dbus.cpp
@@ -242,6 +242,38 @@
     dvfsTemps[path]->value(value);
 }
 
+bool OccDBusSensors::setPurpose(const std::string& path,
+                                const std::string& value)
+{
+    if (path.empty())
+    {
+        return false;
+    }
+
+    if (!purposes.contains(path))
+    {
+        purposes.emplace(
+            path, std::make_unique<PurposeIntf>(utils::getBus(), path.c_str()));
+        try
+        {
+            std::set<sdbusplus::common::xyz::openbmc_project::sensor::Purpose::
+                         SensorPurpose>
+                pSet{sdbusplus::common::xyz::openbmc_project::sensor::Purpose::
+                         convertSensorPurposeFromString(value)};
+            purposes.at(path)->purpose(pSet);
+        }
+        catch (const std::exception& e)
+        {
+            lg2::error(
+                "set SensorPurpose propety failed for {PATH}: error={ERR}",
+                "PATH", path, "ERR", e.what());
+            return false;
+        }
+    }
+
+    return true;
+}
+
 } // namespace dbus
 } // namespace occ
 } // namespace open_power
diff --git a/occ_dbus.hpp b/occ_dbus.hpp
index 595cf5f..1446a45 100644
--- a/occ_dbus.hpp
+++ b/occ_dbus.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
+#include <xyz/openbmc_project/Sensor/Purpose/server.hpp>
 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
 #include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp>
 
@@ -18,6 +19,8 @@
 using OperationalStatusIntf =
     sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::State::
                                     Decorator::server::OperationalStatus>;
+using PurposeIntf = sdbusplus::server::object_t<
+    sdbusplus::xyz::openbmc_project::Sensor::server::Purpose>;
 
 // Note: Not using object<> so the PropertiesVariant ctor is available.
 using AssociationIntf =
@@ -159,8 +162,18 @@
      */
     bool hasDvfsTemp(const std::string& path) const;
 
+    /** @brief Set the purpose of the Sensor
+     *
+     *  @param[in] path  - The object path
+     *  @param[in] value - The value of the Purpose property
+     *
+     *  @return true or false
+     */
+    bool setPurpose(const std::string& path, const std::string& value);
+
   private:
     std::map<ObjectPath, std::unique_ptr<SensorIntf>> sensors;
+    std::map<ObjectPath, std::unique_ptr<PurposeIntf>> purposes;
 
     std::map<ObjectPath, std::unique_ptr<OperationalStatusIntf>>
         operationalStatus;
diff --git a/occ_manager.cpp b/occ_manager.cpp
index df8ff0c..6b0282c 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -1260,12 +1260,13 @@
 
         if (existingSensors.find(sensorPath) == existingSensors.end())
         {
-            std::vector<int> occs;
             std::vector<std::string> fTypeList = {"all_sensors"};
             if (iter->second == "total_power")
             {
-                // Total system power has its own chassis association
-                fTypeList.push_back("total_power");
+                // Set sensor purpose as TotalPower
+                dbus::OccDBusSensors::getOccDBus().setPurpose(
+                    sensorPath,
+                    "xyz.openbmc_project.Sensor.Purpose.SensorPurpose.TotalPower");
             }
             dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
                 sensorPath, fTypeList);