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