rtu: implement modbus sensor read
Read the modbus device config from the Entity Manager configuration and
create the sensor interfaces for related sensor register config.
Tested:
Added new Unit test named test_sensors -
```
> meson test -t 10 -C builddir/ --print-errorlogs --wrapper="valgrind --error-exitcode=1" test_sensors
ninja: Entering directory `/host/repos/Modbus/phosphor-modbus/builddir'
[2/2] Linking target tests/test_sensors
1/1 test_sensors OK 13.98s
Ok: 1
Fail: 0
```
Tested on Qemu using Mock Modbus Device -
```
root@ventura:~# busctl tree xyz.openbmc_project.ModbusRTU
└─ /xyz
└─ /xyz/openbmc_project
├─ /xyz/openbmc_project/inventory_source
│ ├─ /xyz/openbmc_project/inventory_source/Heat_Exchanger_12_DevTTYUSB0
│ ├─ /xyz/openbmc_project/inventory_source/Heat_Exchanger_12_DevTTYUSB1
│ ├─ /xyz/openbmc_project/inventory_source/Reservoir_Pumping_Unit_12_DevTTYUSB0
│ └─ /xyz/openbmc_project/inventory_source/Reservoir_Pumping_Unit_12_DevTTYUSB1
└─ /xyz/openbmc_project/sensors
└─ /xyz/openbmc_project/sensors/temperature
├─ /xyz/openbmc_project/sensors/temperature/Reservoir_Pumping_Unit_12_DevTTYUSB0_RPU_Coolant_Inlet_Temp_C
├─ /xyz/openbmc_project/sensors/temperature/Reservoir_Pumping_Unit_12_DevTTYUSB0_RPU_Coolant_Outlet_Temp_C
├─ /xyz/openbmc_project/sensors/temperature/Reservoir_Pumping_Unit_12_DevTTYUSB1_RPU_Coolant_Inlet_Temp_C
└─ /xyz/openbmc_project/sensors/temperature/Reservoir_Pumping_Unit_12_DevTTYUSB1_RPU_Coolant_Outlet_Temp_C
busctl introspect xyz.openbmc_project.ModbusRTU /xyz/openbmc_project/sensors/temperature/Reservoir_Pumping_Unit_12_DevTTYUSB1_RPU_Coolant_Outlet_Temp_C
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.Sensor.Value interface - - -
.MaxValue property d nan emits-change writable
.MinValue property d nan emits-change writable
.Unit property s "xyz.openbmc_project.Sensor.Value.Unit.… emits-change writable
.Value property d 1670.6 emits-change writable
```
Change-Id: I1368e8df5999b5cee9ac19d185ee110a9ecc3021
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/rtu/device_manager.cpp b/rtu/device_manager.cpp
index 6d2fbd6..804f6eb 100644
--- a/rtu/device_manager.cpp
+++ b/rtu/device_manager.cpp
@@ -1,5 +1,6 @@
#include "device_manager.hpp"
+#include "device/device_factory.hpp"
#include "port/port_factory.hpp"
#include <phosphor-logging/lg2.hpp>
@@ -14,6 +15,7 @@
using ModbusRTUDetectIntf =
sdbusplus::client::xyz::openbmc_project::configuration::ModbusRTUDetect<>;
+using DeviceFactoryIntf = phosphor::modbus::rtu::device::DeviceFactory;
static entity_manager::interface_list_t getInterfaces()
{
@@ -22,8 +24,13 @@
auto portInterfaces = PortIntf::PortFactory::getInterfaces();
interfaces.insert(interfaces.end(), portInterfaces.begin(),
portInterfaces.end());
+
interfaces.emplace_back(ModbusRTUDetectIntf::interface);
+ auto deviceInterfaces = DeviceFactoryIntf::getInterfaces();
+ interfaces.insert(interfaces.end(), deviceInterfaces.begin(),
+ deviceInterfaces.end());
+
return interfaces;
}
@@ -54,48 +61,106 @@
if (std::find(portInterfaces.begin(), portInterfaces.end(),
interfaceName) != portInterfaces.end())
{
- auto config = co_await PortIntf::PortFactory::getConfig(
- ctx, objectPath, interfaceName);
- if (!config)
- {
- error("Failed to get Port config for {PATH}", "PATH", objectPath);
- co_return;
- }
-
- try
- {
- ports[config->name] = PortIntf::PortFactory::create(ctx, *config);
- }
- catch (const std::exception& e)
- {
- error("Failed to create Port for {PATH} with {ERROR}", "PATH",
- objectPath, "ERROR", e);
- co_return;
- }
+ co_return co_await processPortAdded(objectPath, interfaceName);
}
- else if (interfaceName == ModbusRTUDetectIntf::interface)
+
+ if (interfaceName == ModbusRTUDetectIntf::interface)
{
- auto res = co_await InventoryIntf::config::getConfig(ctx, objectPath);
- if (!res)
+ co_return co_await processInventoryAdded(objectPath);
+ }
+
+ auto deviceInterfaces = DeviceFactoryIntf::getInterfaces();
+ if (std::find(deviceInterfaces.begin(), deviceInterfaces.end(),
+ interfaceName) != deviceInterfaces.end())
+ {
+ co_return co_await processDeviceAdded(objectPath, interfaceName);
+ }
+}
+
+auto DeviceManager::processPortAdded(
+ const sdbusplus::message::object_path& objectPath,
+ const std::string& interfaceName) -> sdbusplus::async::task<>
+{
+ auto config = co_await PortIntf::PortFactory::getConfig(
+ ctx, objectPath, interfaceName);
+ if (!config)
+ {
+ error("Failed to get Port config for {PATH}", "PATH", objectPath);
+ co_return;
+ }
+
+ try
+ {
+ ports[config->name] = PortIntf::PortFactory::create(ctx, *config);
+ }
+ catch (const std::exception& e)
+ {
+ error("Failed to create Port for {PATH} with {ERROR}", "PATH",
+ objectPath, "ERROR", e);
+ co_return;
+ }
+}
+
+auto DeviceManager::processInventoryAdded(
+ const sdbusplus::message::object_path& objectPath)
+ -> sdbusplus::async::task<>
+{
+ auto res = co_await InventoryIntf::config::getConfig(ctx, objectPath);
+ if (!res)
+ {
+ error("Failed to get Inventory Device config for {PATH}", "PATH",
+ objectPath);
+ co_return;
+ }
+ auto config = res.value();
+ try
+ {
+ auto inventoryDevice =
+ std::make_unique<InventoryIntf::Device>(ctx, config, ports);
+ ctx.spawn(inventoryDevice->probePorts());
+ inventoryDevices[config.name] = std::move(inventoryDevice);
+ }
+ catch (const std::exception& e)
+ {
+ error("Failed to create Inventory Device for {PATH} with {ERROR}",
+ "PATH", objectPath, "ERROR", e);
+ co_return;
+ }
+}
+
+auto DeviceManager::processDeviceAdded(
+ const sdbusplus::message::object_path& objectPath,
+ const std::string& interfaceName) -> sdbusplus::async::task<>
+{
+ auto res =
+ co_await DeviceFactoryIntf::getConfig(ctx, objectPath, interfaceName);
+ if (!res)
+ {
+ error("Failed to get Device config for {PATH}", "PATH", objectPath);
+ co_return;
+ }
+ auto config = res.value();
+
+ try
+ {
+ auto serialPort = ports.find(config.portName);
+ if (serialPort == ports.end())
{
error("Failed to get Inventory Device config for {PATH}", "PATH",
objectPath);
co_return;
}
- auto config = res.value();
- try
- {
- auto inventoryDevice =
- std::make_unique<InventoryIntf::Device>(ctx, config, ports);
- ctx.spawn(inventoryDevice->probePorts());
- inventoryDevices[config.name] = std::move(inventoryDevice);
- }
- catch (const std::exception& e)
- {
- error("Failed to create Inventory Device for {PATH} with {ERROR}",
- "PATH", objectPath, "ERROR", e);
- co_return;
- }
+
+ auto device =
+ DeviceFactoryIntf::create(ctx, config, *(serialPort->second));
+ ctx.spawn(device->readSensorRegisters());
+ devices[config.name] = std::move(device);
+ }
+ catch (const std::exception& e)
+ {
+ error("Failed to create Device for {PATH} with {ERROR}", "PATH",
+ objectPath, "ERROR", e);
+ co_return;
}
}