xref: /openbmc/phosphor-modbus/rtu/device/base_device.cpp (revision e92aba4516471f5a01d4ab1f93eb9919ec05c21f)
1*e92aba45SJagpal Singh Gill #include "base_device.hpp"
2*e92aba45SJagpal Singh Gill 
3*e92aba45SJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
4*e92aba45SJagpal Singh Gill 
5*e92aba45SJagpal Singh Gill #include <numeric>
6*e92aba45SJagpal Singh Gill 
7*e92aba45SJagpal Singh Gill namespace phosphor::modbus::rtu::device
8*e92aba45SJagpal Singh Gill {
9*e92aba45SJagpal Singh Gill 
10*e92aba45SJagpal Singh Gill PHOSPHOR_LOG2_USING;
11*e92aba45SJagpal Singh Gill 
12*e92aba45SJagpal Singh Gill BaseDevice::BaseDevice(sdbusplus::async::context& ctx,
13*e92aba45SJagpal Singh Gill                        const config::Config& config, PortIntf& serialPort) :
14*e92aba45SJagpal Singh Gill     ctx(ctx), config(config), serialPort(serialPort)
15*e92aba45SJagpal Singh Gill {
16*e92aba45SJagpal Singh Gill     createSensors();
17*e92aba45SJagpal Singh Gill 
18*e92aba45SJagpal Singh Gill     info("Successfully created device {NAME}", "NAME", config.name);
19*e92aba45SJagpal Singh Gill }
20*e92aba45SJagpal Singh Gill 
21*e92aba45SJagpal Singh Gill static auto getObjectPath(const std::string& sensorType,
22*e92aba45SJagpal Singh Gill                           const std::string& sensorName)
23*e92aba45SJagpal Singh Gill     -> sdbusplus::message::object_path
24*e92aba45SJagpal Singh Gill {
25*e92aba45SJagpal Singh Gill     return sdbusplus::message::object_path(
26*e92aba45SJagpal Singh Gill         std::string(SensorValueIntf::namespace_path::value) + "/" + sensorType +
27*e92aba45SJagpal Singh Gill         "/" + sensorName);
28*e92aba45SJagpal Singh Gill }
29*e92aba45SJagpal Singh Gill 
30*e92aba45SJagpal Singh Gill auto BaseDevice::createSensors() -> void
31*e92aba45SJagpal Singh Gill {
32*e92aba45SJagpal Singh Gill     for (const auto& sensorRegister : config.sensorRegisters)
33*e92aba45SJagpal Singh Gill     {
34*e92aba45SJagpal Singh Gill         SensorValueIntf::properties_t initProperties = {
35*e92aba45SJagpal Singh Gill             std::numeric_limits<double>::quiet_NaN(),
36*e92aba45SJagpal Singh Gill             std::numeric_limits<double>::quiet_NaN(),
37*e92aba45SJagpal Singh Gill             std::numeric_limits<double>::quiet_NaN(), sensorRegister.unit};
38*e92aba45SJagpal Singh Gill 
39*e92aba45SJagpal Singh Gill         auto sensorPath = getObjectPath(
40*e92aba45SJagpal Singh Gill             sensorRegister.pathSuffix, config.name + "_" + sensorRegister.name);
41*e92aba45SJagpal Singh Gill 
42*e92aba45SJagpal Singh Gill         auto sensor = std::make_unique<SensorValueIntf>(
43*e92aba45SJagpal Singh Gill             ctx, sensorPath.str.c_str(), initProperties);
44*e92aba45SJagpal Singh Gill 
45*e92aba45SJagpal Singh Gill         sensor->emit_added();
46*e92aba45SJagpal Singh Gill 
47*e92aba45SJagpal Singh Gill         sensors.emplace(sensorRegister.name, std::move(sensor));
48*e92aba45SJagpal Singh Gill     }
49*e92aba45SJagpal Singh Gill 
50*e92aba45SJagpal Singh Gill     return;
51*e92aba45SJagpal Singh Gill }
52*e92aba45SJagpal Singh Gill 
53*e92aba45SJagpal Singh Gill static auto getRawIntegerFromRegister(const std::vector<uint16_t>& reg,
54*e92aba45SJagpal Singh Gill                                       bool sign) -> int64_t
55*e92aba45SJagpal Singh Gill {
56*e92aba45SJagpal Singh Gill     if (reg.empty())
57*e92aba45SJagpal Singh Gill     {
58*e92aba45SJagpal Singh Gill         return 0;
59*e92aba45SJagpal Singh Gill     }
60*e92aba45SJagpal Singh Gill 
61*e92aba45SJagpal Singh Gill     uint64_t accumulator = 0;
62*e92aba45SJagpal Singh Gill     for (auto val : reg)
63*e92aba45SJagpal Singh Gill     {
64*e92aba45SJagpal Singh Gill         accumulator = (accumulator << 16) | val;
65*e92aba45SJagpal Singh Gill     }
66*e92aba45SJagpal Singh Gill 
67*e92aba45SJagpal Singh Gill     int64_t result = 0;
68*e92aba45SJagpal Singh Gill 
69*e92aba45SJagpal Singh Gill     if (sign)
70*e92aba45SJagpal Singh Gill     {
71*e92aba45SJagpal Singh Gill         if (reg.size() == 1)
72*e92aba45SJagpal Singh Gill         {
73*e92aba45SJagpal Singh Gill             result = static_cast<int16_t>(accumulator);
74*e92aba45SJagpal Singh Gill         }
75*e92aba45SJagpal Singh Gill         else if (reg.size() == 2)
76*e92aba45SJagpal Singh Gill         {
77*e92aba45SJagpal Singh Gill             result = static_cast<int32_t>(accumulator);
78*e92aba45SJagpal Singh Gill         }
79*e92aba45SJagpal Singh Gill         else
80*e92aba45SJagpal Singh Gill         {
81*e92aba45SJagpal Singh Gill             result = static_cast<int64_t>(accumulator);
82*e92aba45SJagpal Singh Gill         }
83*e92aba45SJagpal Singh Gill     }
84*e92aba45SJagpal Singh Gill     else
85*e92aba45SJagpal Singh Gill     {
86*e92aba45SJagpal Singh Gill         if (reg.size() == 1)
87*e92aba45SJagpal Singh Gill         {
88*e92aba45SJagpal Singh Gill             result = static_cast<uint16_t>(accumulator);
89*e92aba45SJagpal Singh Gill         }
90*e92aba45SJagpal Singh Gill         else if (reg.size() == 2)
91*e92aba45SJagpal Singh Gill         {
92*e92aba45SJagpal Singh Gill             result = static_cast<uint32_t>(accumulator);
93*e92aba45SJagpal Singh Gill         }
94*e92aba45SJagpal Singh Gill         else
95*e92aba45SJagpal Singh Gill         {
96*e92aba45SJagpal Singh Gill             result = static_cast<int64_t>(accumulator);
97*e92aba45SJagpal Singh Gill         }
98*e92aba45SJagpal Singh Gill     }
99*e92aba45SJagpal Singh Gill 
100*e92aba45SJagpal Singh Gill     return result;
101*e92aba45SJagpal Singh Gill }
102*e92aba45SJagpal Singh Gill 
103*e92aba45SJagpal Singh Gill auto BaseDevice::readSensorRegisters() -> sdbusplus::async::task<void>
104*e92aba45SJagpal Singh Gill {
105*e92aba45SJagpal Singh Gill     while (!ctx.stop_requested())
106*e92aba45SJagpal Singh Gill     {
107*e92aba45SJagpal Singh Gill         for (const auto& sensorRegister : config.sensorRegisters)
108*e92aba45SJagpal Singh Gill         {
109*e92aba45SJagpal Singh Gill             auto sensor = sensors.find(sensorRegister.name);
110*e92aba45SJagpal Singh Gill             if (sensor == sensors.end())
111*e92aba45SJagpal Singh Gill             {
112*e92aba45SJagpal Singh Gill                 error("Sensor not found for {NAME}", "NAME",
113*e92aba45SJagpal Singh Gill                       sensorRegister.name);
114*e92aba45SJagpal Singh Gill                 continue;
115*e92aba45SJagpal Singh Gill             }
116*e92aba45SJagpal Singh Gill 
117*e92aba45SJagpal Singh Gill             if (sensorRegister.size > 4)
118*e92aba45SJagpal Singh Gill             {
119*e92aba45SJagpal Singh Gill                 error("Unsupported size for register {NAME}", "NAME",
120*e92aba45SJagpal Singh Gill                       sensorRegister.name);
121*e92aba45SJagpal Singh Gill                 continue;
122*e92aba45SJagpal Singh Gill             }
123*e92aba45SJagpal Singh Gill 
124*e92aba45SJagpal Singh Gill             auto registers = std::vector<uint16_t>(sensorRegister.size);
125*e92aba45SJagpal Singh Gill             auto ret = co_await serialPort.readHoldingRegisters(
126*e92aba45SJagpal Singh Gill                 config.address, sensorRegister.offset, config.baudRate,
127*e92aba45SJagpal Singh Gill                 config.parity, registers);
128*e92aba45SJagpal Singh Gill             if (!ret)
129*e92aba45SJagpal Singh Gill             {
130*e92aba45SJagpal Singh Gill                 error(
131*e92aba45SJagpal Singh Gill                     "Failed to read holding registers {NAME} for {DEVICE_ADDRESS}",
132*e92aba45SJagpal Singh Gill                     "NAME", sensorRegister.name, "DEVICE_ADDRESS",
133*e92aba45SJagpal Singh Gill                     config.address);
134*e92aba45SJagpal Singh Gill                 continue;
135*e92aba45SJagpal Singh Gill             }
136*e92aba45SJagpal Singh Gill 
137*e92aba45SJagpal Singh Gill             double regVal = static_cast<double>(
138*e92aba45SJagpal Singh Gill                 getRawIntegerFromRegister(registers, sensorRegister.isSigned));
139*e92aba45SJagpal Singh Gill             if (sensorRegister.format == config::SensorFormat::floatingPoint)
140*e92aba45SJagpal Singh Gill             {
141*e92aba45SJagpal Singh Gill                 regVal = sensorRegister.shift +
142*e92aba45SJagpal Singh Gill                          (sensorRegister.scale *
143*e92aba45SJagpal Singh Gill                           (regVal / (1ULL << sensorRegister.precision)));
144*e92aba45SJagpal Singh Gill             }
145*e92aba45SJagpal Singh Gill 
146*e92aba45SJagpal Singh Gill             sensor->second->value(regVal);
147*e92aba45SJagpal Singh Gill         }
148*e92aba45SJagpal Singh Gill 
149*e92aba45SJagpal Singh Gill         constexpr auto pollInterval = 3;
150*e92aba45SJagpal Singh Gill         co_await sdbusplus::async::sleep_for(
151*e92aba45SJagpal Singh Gill             ctx, std::chrono::seconds(pollInterval));
152*e92aba45SJagpal Singh Gill         debug("Polling sensors for {NAME} in {INTERVAL} seconds", "NAME",
153*e92aba45SJagpal Singh Gill               config.name, "INTERVAL", pollInterval);
154*e92aba45SJagpal Singh Gill     }
155*e92aba45SJagpal Singh Gill 
156*e92aba45SJagpal Singh Gill     co_return;
157*e92aba45SJagpal Singh Gill }
158*e92aba45SJagpal Singh Gill 
159*e92aba45SJagpal Singh Gill } // namespace phosphor::modbus::rtu::device
160