D-Bus Sensors Guide

Configure and use dbus-sensors for hardware monitoring.

Table of Contents

  1. Overview
  2. Sensor Daemons
  3. Configuration & Setup
    1. Build-Time Configuration (Yocto)
    2. Meson Build Options
    3. Runtime Enable/Disable
    4. Sensor Custom Properties
    5. Hysteresis Configuration
  4. D-Bus Sensor Interface
    1. Threshold Interfaces
  5. ADC Sensors
    1. Device Tree Configuration
    2. Entity Manager Configuration
    3. Key Properties
  6. Hwmon Temperature Sensors
    1. Entity Manager Configuration
    2. Supported Sensor Types
  7. PSU Sensors
    1. Entity Manager Configuration
    2. Exposed Sensors
  8. Virtual/External Sensors
    1. Entity Manager Configuration
    2. Setting Values via D-Bus
  9. SMBPBI Sensors
  10. Cable Monitoring
  11. IPMB Sensors
    1. SDR Auto-Discovery (IpmbSDRDevice)
  12. MCU Temperature and NVMe Sensors
    1. MCU Temperature (mcutempsensor)
    2. NVMe (nvmesensor)
  13. Threshold Configuration
    1. Threshold Levels
    2. Direction
    3. Example with All Thresholds
  14. Reading Sensors
    1. Via D-Bus
    2. Via Redfish
  15. Troubleshooting
    1. Sensor not appearing
    2. Incorrect readings
    3. Threshold alarms not triggering
  16. Deep Dive
    1. Sensor Reading Pipeline
    2. Threshold Detection Algorithm
    3. Entity Manager Integration Flow
    4. ADC Scaling and Voltage Dividers
    5. Power State Filtering
    6. Source Code Reference
  17. Examples
  18. References

Overview

dbus-sensors is a collection of sensor daemons that expose hardware sensor data via D-Bus. Each daemon handles a specific sensor type and integrates with Entity Manager for configuration.

---
title: dbus-sensors Architecture
---
flowchart TB
    subgraph sensors["Sensor Daemons"]
        direction LR
        adc["ADCSensor<br/>(ADC inputs)"]
        hwmon["HwmonTempSensor<br/>(I2C temps)"]
        psu["PSUSensor<br/>(PMBus PSU)"]
    end

    sensors --> dbus["D-Bus<br/>xyz.openbmc_project.Sensor.Value"]
    dbus <--> em["Entity Manager<br/>(JSON Configuration)"]
    em --> kernel["Linux Kernel<br/>/sys/class/hwmon, /sys/bus/iio"]
ASCII-art version (for comparison)
┌────────────────────────────────────────────────────────────────┐
│                      dbus-sensors Architecture                 │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  ┌────────────────┐  ┌────────────────┐  ┌────────────────┐    │
│  │  ADCSensor     │  │ HwmonTempSensor│  │  PSUSensor     │    │
│  │  (ADC inputs)  │  │  (I2C temps)   │  │  (PMBus PSU)   │    │
│  └───────┬────────┘  └───────┬────────┘  └───────┬────────┘    │
│          │                   │                   │             │
│  ┌───────┴───────────────────┴───────────────────┴───────┐     │
│  │                     D-Bus                             │     │
│  │          xyz.openbmc_project.Sensor.Value             │     │
│  └───────────────────────────┬───────────────────────────┘     │
│                              │                                 │
│  ┌───────────────────────────┴───────────────────────────┐     │
│  │                   Entity Manager                      │     │
│  │              (JSON Configuration)                     │     │
│  └───────────────────────────────────────────────────────┘     │
│                              │                                 │
│  ┌───────────────────────────┴───────────────────────────┐     │
│  │                   Linux Kernel                        │     │
│  │          /sys/class/hwmon, /sys/bus/iio               │     │
│  └───────────────────────────────────────────────────────┘     │
└────────────────────────────────────────────────────────────────┘

Sensor Daemons

Daemon Sensor Types Data Source
adcsensor ADC voltage inputs IIO subsystem
hwmontempsensor I2C temperature sensors hwmon sysfs
psusensor PSU voltage, current, power PMBus hwmon
fansensor Fan tachometers, PWM hwmon sysfs
intrusionsensor Chassis intrusion GPIO
ipmbsensor IPMB sensors IPMB interface
mcutempsensor MCU temperature I2C
nvmesensor NVMe temperature NVMe-MI
externalsensor Virtual sensors D-Bus input

Configuration & Setup

Build-Time Configuration (Yocto)

Enable or disable specific sensor daemons in your machine configuration:

# In your machine .conf or image recipe

# Include all sensor daemons (default)
IMAGE_INSTALL:append = " dbus-sensors"

# Or include specific sensor daemons only
IMAGE_INSTALL:append = " \
    adcsensor \
    hwmontempsensor \
    fansensor \
    psusensor \
"

# Exclude specific daemons
RDEPENDS:${PN}:remove:pn-dbus-sensors = "intrusionsensor ipmbsensor"

Meson Build Options

When building dbus-sensors from source:

# View all options
meson configure build

# Common options
meson setup build \
    -Dadc=enabled \
    -Dhwmon-temp=enabled \
    -Dfan=enabled \
    -Dpsu=enabled \
    -Dintrusion=disabled \
    -Dipmb=disabled \
    -Dnvme=enabled \
    -Dexternal=enabled
Option Default Description
adc enabled ADC voltage sensors
hwmon-temp enabled I2C temperature sensors
fan enabled Fan tachometer sensors
psu enabled PMBus PSU sensors
intrusion enabled Chassis intrusion sensor
ipmb enabled IPMB sensors
nvme enabled NVMe temperature sensors
external enabled External/virtual sensors
mcu-temp enabled MCU temperature sensor

Runtime Enable/Disable

Control sensor daemons at runtime via systemd:

# Disable a sensor daemon
systemctl disable xyz.openbmc_project.adcsensor
systemctl stop xyz.openbmc_project.adcsensor

# Enable a sensor daemon
systemctl enable xyz.openbmc_project.hwmontempsensor
systemctl start xyz.openbmc_project.hwmontempsensor

# Check status
systemctl status xyz.openbmc_project.fansensor

# List all sensor services
systemctl list-units | grep sensor

Sensor Custom Properties

Sensors support additional configuration properties in Entity Manager:

{
    "Exposes": [
        {
            "Name": "CPU Temp",
            "Type": "TMP75",
            "Bus": 1,
            "Address": "0x48",

            "PowerState": "On",
            "ReadState": "On",
            "PollRate": 1.0,
            "Offset": 0.0,
            "ScaleFactor": 1.0,
            "Label": "CPU Core Temperature",
            "MaxValue": 125,
            "MinValue": -40,

            "Thresholds": [...]
        }
    ]
}
Property Type Description
PowerState string When to poll: On, BiosPost, Always
ReadState string Alternate power state control
PollRate float Polling interval in seconds (default: 1.0)
Offset float Value offset adjustment
ScaleFactor float Multiplier for raw value
Label string Human-readable label
MaxValue float Maximum expected value
MinValue float Minimum expected value

Hysteresis Configuration

Configure threshold hysteresis to prevent alarm flapping:

{
    "Thresholds": [
        {
            "Direction": "greater than",
            "Name": "upper critical",
            "Severity": 1,
            "Value": 95,
            "Hysteresis": 2.0
        }
    ]
}

The alarm clears when value drops below Value - Hysteresis (93°C in this example).


D-Bus Sensor Interface

All sensors implement xyz.openbmc_project.Sensor.Value:

# Introspect a sensor
busctl introspect xyz.openbmc_project.ADCSensor \
    /xyz/openbmc_project/sensors/voltage/P12V

# Properties:
#   Value          - Current sensor reading (double)
#   MaxValue       - Maximum possible value
#   MinValue       - Minimum possible value
#   Unit           - Measurement unit

Threshold Interfaces

Sensors can have warning and critical thresholds:

xyz.openbmc_project.Sensor.Threshold.Warning
  - WarningHigh
  - WarningLow
  - WarningAlarmHigh
  - WarningAlarmLow

xyz.openbmc_project.Sensor.Threshold.Critical
  - CriticalHigh
  - CriticalLow
  - CriticalAlarmHigh
  - CriticalAlarmLow

ADC Sensors

ADC sensors read analog voltage inputs via the Linux IIO subsystem.

Device Tree Configuration

// In your device tree
&adc {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_adc0_default
                 &pinctrl_adc1_default>;
};

Entity Manager Configuration

{
    "Exposes": [
        {
            "Index": 0,
            "Name": "P12V",
            "ScaleFactor": 4.0,
            "Type": "ADC"
        },
        {
            "Index": 1,
            "Name": "P3V3",
            "ScaleFactor": 1.0,
            "Type": "ADC",
            "Thresholds": [
                {
                    "Direction": "greater than",
                    "Name": "upper critical",
                    "Severity": 1,
                    "Value": 3.6
                },
                {
                    "Direction": "less than",
                    "Name": "lower critical",
                    "Severity": 1,
                    "Value": 3.0
                }
            ]
        }
    ],
    "Name": "MyBoard",
    "Type": "Board"
}

Key Properties

Property Description
Index ADC channel number (matches hwmon inX_input)
Name Sensor name on D-Bus
ScaleFactor Voltage divider ratio
PowerState When to read (On, BiosPost, Always)
Thresholds Warning/critical levels

Hwmon Temperature Sensors

For I2C temperature sensors (TMP75, LM75, etc.).

Entity Manager Configuration

{
    "Exposes": [
        {
            "Address": "0x48",
            "Bus": 1,
            "Name": "CPU Temp",
            "Type": "TMP75"
        },
        {
            "Address": "0x49",
            "Bus": 1,
            "Name": "Inlet Temp",
            "Type": "TMP75",
            "Thresholds": [
                {
                    "Direction": "greater than",
                    "Name": "upper critical",
                    "Severity": 1,
                    "Value": 45
                }
            ]
        }
    ],
    "Name": "TempSensors",
    "Probe": "TRUE",
    "Type": "Board"
}

Supported Sensor Types

Type Chip Common Uses
TMP75 TI TMP75 Ambient temperature
TMP421 TI TMP421 Remote diode sensing
TMP112 TI TMP112 Low power temp
LM75A NXP LM75A General purpose
EMC1413 Microchip Multi-channel

PSU Sensors

For PMBus power supplies.

Entity Manager Configuration

{
    "Exposes": [
        {
            "Address": "0x58",
            "Bus": 3,
            "Name": "PSU1",
            "Type": "pmbus"
        }
    ],
    "Name": "PowerSupply",
    "Probe": "TRUE",
    "Type": "Board"
}

Exposed Sensors

PSU sensor daemon automatically exposes:

  • Input/output voltage
  • Input/output current
  • Input/output power
  • Temperature
  • Fan speed
  • Status flags

Virtual/External Sensors

For calculated values or sensors from external sources.

Entity Manager Configuration

{
    "Exposes": [
        {
            "Name": "Total Power",
            "Type": "ExternalSensor",
            "Units": "Watts",
            "MinValue": 0,
            "MaxValue": 2000
        }
    ],
    "Name": "VirtualSensors",
    "Type": "Board"
}

Setting Values via D-Bus

# External sensors can be written to
busctl set-property xyz.openbmc_project.ExternalSensor \
    /xyz/openbmc_project/sensors/power/Total_Power \
    xyz.openbmc_project.Sensor.Value Value d 450.5

The externalsensor daemon can enforce staleness on a writable sensor. Add a Timeout (in seconds) to the Entity Manager entry: if no new value is written within that window, the daemon’s reaper (updateReaper) invalidates the sensor and publishes NaN on Value, so a stalled producer surfaces as “unavailable” instead of a stuck last-known reading. A Timeout of 0 (or an omitted key) makes the sensor non-perishable — it keeps its last written value indefinitely.

{
    "Name": "Total Power",
    "Type": "ExternalSensor",
    "Units": "Watts",
    "Timeout": 5,
    "MinValue": 0,
    "MaxValue": 2000
}

SMBPBI Sensors

The smbpbi daemon (service xyz.openbmc_project.SMBPBI) reads telemetry from a management controller — typically an NVIDIA HMC/GPU — that exposes an SMBus Post-Box Interface (SMBPBI) “virtual EEPROM” over I2C. Each Entity Manager entry of type SmbpbiVirtualEeprom maps a byte offset in that virtual EEPROM to one D-Bus sensor.

{
    "Exposes": [
        {
            "Name": "GPU0 Temp",
            "Type": "SmbpbiVirtualEeprom",
            "Bus": 3,
            "Address": "0x4f",
            "ReadOffset": 0,
            "Units": "DegreesC",
            "ValueType": "UINT64",
            "PollRate": 1.0,
            "MinValue": 0,
            "MaxValue": 128
        }
    ],
    "Name": "GPU Board",
    "Type": "Board"
}

The daemon issues a raw I2C_RDWR transfer to read the block at ReadOffset, then decodes it according to Units: convert2Temp for DegreesC, convert2Power for Watts, plus direct handling for Joules (energy) and Volts (voltage). The Units value picks both the decode routine and the D-Bus object path (/xyz/openbmc_project/sensors/{temperature,power,energy,voltage}/…).

When the management controller has not yet published a value, the SMBPBI block reads back as all 0xFF. The daemon treats that as “no data” and publishes NaN rather than a bogus reading, so a consumer can tell a genuine zero from an absent one.


Cable Monitoring

The cable-monitor daemon (service xyz.openbmc_project.cablemonitor) tracks whether the cables a platform expects are actually present and raises Redfish events when one is plugged or unplugged. Unlike the register-reading sensor daemons, it does not touch hardware — it watches the inventory on D-Bus and compares it against a configured expected list.

The expected cables come from a JSON file at /var/lib/cablemonitor/cable-config.json with a ConnectedCables array of cable names:

{
    "ConnectedCables": [
        "PCIe_Cable_0",
        "PCIe_Cable_1"
    ]
}

At runtime the daemon subscribes to inventory objects that implement xyz.openbmc_project.Inventory.Item.Cable (published by Entity Manager) and reacts to their InterfacesAdded / InterfacesRemoved signals; it also watches the config file with inotify so an updated list is picked up without a restart. When an expected cable’s inventory object appears it logs a CableConnected event, and when one disappears it logs CableDisconnected (both in the xyz.openbmc_project.State.Cable namespace, routed through phosphor-logging to the Redfish event log).

# Watch cable connect/disconnect events
journalctl -u xyz.openbmc_project.cablemonitor -f

IPMB Sensors

The ipmbsensor daemon (service xyz.openbmc_project.IpmbSensor) reads sensors that live behind an IPMB (Intelligent Platform Management Bus) satellite controller — a BMC, ME (management engine), or voltage-regulator bridge — instead of on a local I2C bus. It does not talk to the bus directly; it sends IPMI requests through the org.openbmc.Ipmb D-Bus service (/xyz/openbmc_project/Ipmi/Channel/Ipmb, sendRequest method), which an IPMB transport daemon relays onto the wire.

Each Entity Manager entry of type IpmbSensor names a bridge Class and a SensorType:

{
    "Exposes": [
        {
            "Name": "MB Temp",
            "Type": "IpmbSensor",
            "Class": "METemp",
            "SensorType": "temperature",
            "Address": "0x2e",
            "Bus": 0,
            "HostSMbusIndex": 3,
            "PollRate": 1.0
        }
    ],
    "Name": "IPMB Board",
    "Type": "Board"
}
Field Purpose
Class Bridge/reading protocol: METemp/MESensor, PxeBridgeTemp, IRBridgeTemp, HSCBridge, MpsBridgeTemp, SMPro
SensorType Reading subtype: temperature (default), voltage, power, current, utilization
Address IPMB device (satellite) address
HostSMbusIndex SMBus index passed in bridged VR commands

SDR Auto-Discovery (IpmbSDRDevice)

Beyond the statically declared sensors above, the daemon can enumerate a satellite’s sensors automatically by reading its SDR (Sensor Data Record) repository. The IpmbSDRDevice class walks the repository — Get SDR Repository Info, Reserve SDR Repository, then repeated Get SDR — and for every Type-01 (Full Sensor Record) entry it parses the sensor name, unit, conversion factors, and thresholds, then creates a matching D-Bus sensor. This lets a platform pick up all of a satellite BMC’s sensors without listing each one in Entity Manager.


MCU Temperature and NVMe Sensors

MCU Temperature (mcutempsensor)

The mcutempsensor daemon (service xyz.openbmc_project.MCUTempSensor) reads a temperature value from a microcontroller register over I2C. The Entity Manager entry (type MCUTempSensor) gives the Bus, Address, and the register offset in Reg; the daemon opens /dev/i2c-<Bus> and issues an SMBus read-word at that register.

{
    "Exposes": [
        {
            "Name": "MCU Temp",
            "Type": "MCUTempSensor",
            "Class": "MCUTempSensor",
            "Bus": 5,
            "Address": "0x50",
            "Reg": 4
        }
    ],
    "Name": "MCU Board",
    "Type": "Board"
}

NVMe (nvmesensor)

The nvmesensor daemon (service xyz.openbmc_project.NVMeSensor, config type NVME1000) reads drive temperature over NVMe-MI using the Basic Management Command on the drive’s SMBus/I2C interface. Drives usually sit behind an I2C mux, so the daemon derives the root bus from the mux device’s /mux_device symlink and shares one context per root bus. Each basic-management query runs on a dedicated worker thread so a slow or unresponsive drive cannot stall the daemon’s main event loop.


Threshold Configuration

Threshold Levels

Severity Meaning
0 Warning
1 Critical

Direction

Direction Meaning
greater than Alarm when value > threshold
less than Alarm when value < threshold

Example with All Thresholds

{
    "Thresholds": [
        {
            "Direction": "greater than",
            "Name": "upper critical",
            "Severity": 1,
            "Value": 90
        },
        {
            "Direction": "greater than",
            "Name": "upper warning",
            "Severity": 0,
            "Value": 80
        },
        {
            "Direction": "less than",
            "Name": "lower warning",
            "Severity": 0,
            "Value": 10
        },
        {
            "Direction": "less than",
            "Name": "lower critical",
            "Severity": 1,
            "Value": 5
        }
    ]
}

Reading Sensors

Via D-Bus

# List all sensors
busctl tree xyz.openbmc_project.ADCSensor
busctl tree xyz.openbmc_project.HwmonTempSensor

# Read sensor value
busctl get-property xyz.openbmc_project.HwmonTempSensor \
    /xyz/openbmc_project/sensors/temperature/CPU_Temp \
    xyz.openbmc_project.Sensor.Value Value

# Check threshold status
busctl get-property xyz.openbmc_project.HwmonTempSensor \
    /xyz/openbmc_project/sensors/temperature/CPU_Temp \
    xyz.openbmc_project.Sensor.Threshold.Critical CriticalAlarmHigh

Via Redfish

curl -k -u root:0penBmc \
    https://localhost/redfish/v1/Chassis/chassis/Sensors

curl -k -u root:0penBmc \
    https://localhost/redfish/v1/Chassis/chassis/Sensors/CPU_Temp

Troubleshooting

Sensor not appearing

# Check Entity Manager found the device
journalctl -u xyz.openbmc_project.EntityManager | grep -i <sensor-name>

# Check hwmon sysfs exists
ls /sys/class/hwmon/

# Check sensor daemon logs
journalctl -u xyz.openbmc_project.adcsensor -f
journalctl -u xyz.openbmc_project.hwmontempsensor -f

Incorrect readings

# Verify raw hwmon value
cat /sys/class/hwmon/hwmon*/temp1_input

# Check scale factor in Entity Manager config
# Value on D-Bus = raw_value * ScaleFactor

# For ADC, verify voltage divider calculation

Threshold alarms not triggering

# Check threshold configuration
busctl introspect xyz.openbmc_project.HwmonTempSensor \
    /xyz/openbmc_project/sensors/temperature/<name> | grep -i threshold

# Verify SEL logger is running
systemctl status xyz.openbmc_project.sel-logger

Deep Dive

Advanced implementation details for sensor developers.

Sensor Reading Pipeline

Each sensor daemon follows a common pattern for reading and publishing sensor values:

┌─────────────────────────────────────────────────────────────────────────┐
│                    Sensor Reading Pipeline                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   1. HARDWARE LAYER                                                     │
│   ┌──────────────────────────────────────────────────────────────────┐  │
│   │  I2C Device → Kernel Driver → sysfs/hwmon                        │  │
│   │  Example: TMP75 at 0x48 → tmp75 driver → /sys/class/hwmon/hwmonN │  │
│   └──────────────────────────────────────────────────────────────────┘  │
│                                   │                                     │
│                                   ▼                                     │
│   2. SENSOR DAEMON (e.g., hwmontempsensor)                              │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │  a. Entity Manager signals new Configuration object             │   │
│   │  b. Daemon matches Type (e.g., "TMP75") to its supported types  │   │
│   │  c. Daemon locates hwmon sysfs path for bus/address             │   │
│   │  d. Creates Sensor object with D-Bus interface                  │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                   │                                     │
│                                   ▼                                     │
│   3. POLLING LOOP                                                       │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │  while (running) {                                              │   │
│   │      raw_value = read("/sys/class/hwmon/hwmonN/temp1_input");   │   │
│   │      scaled_value = raw_value / 1000.0 * scaleFactor;           │   │
│   │      if (value_changed) {                                       │   │
│   │          update_dbus_property("Value", scaled_value);           │   │
│   │          check_thresholds(scaled_value);                        │   │
│   │      }                                                          │   │
│   │      sleep(pollInterval);  // typically 1 second                │   │
│   │  }                                                              │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                   │                                     │
│                                   ▼                                     │
│   4. D-BUS PUBLICATION                                                  │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │  Service: xyz.openbmc_project.HwmonTempSensor                   │   │
│   │  Path: /xyz/openbmc_project/sensors/temperature/CPU_Temp        │   │
│   │  Interface: xyz.openbmc_project.Sensor.Value                    │   │
│   │      Property: Value = 45.5 (double)                            │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Source reference: HwmonTempSensor.cpp

Threshold Detection Algorithm

Thresholds use hysteresis to prevent rapid alarm toggling:

┌────────────────────────────────────────────────────────────────────────┐
│                    Threshold Hysteresis                                │
├────────────────────────────────────────────────────────────────────────┤
│                                                                        │
│   Temperature (°C)                                                     │
│        │                                                               │
│    95 ─┼─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ Upper Critical                       │
│        │                                                               │
│    90 ─┼─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ Upper Critical Hysteresis (95-5)     │
│        │                                                               │
│    85 ─┼─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ Upper Warning                        │
│        │              ╭───╮                                            │
│    80 ─┼─ ─ ─ ─ ─ ─ ─╱─ ─ ╲─ ─ ─ ─ Upper Warning Hysteresis (85-5)     │
│        │            ╱       ╲       (clear alarm below this)           │
│    75 ─┼───────────╱         ╲──────                                   │
│        │          ╱           ╲                                        │
│    70 ─┼─────────╱             ╲                                       │
│        │                                                               │
│        └────────────────────────────────────────────────────▶ Time     │
│                                                                        │
│   Alarm Logic:                                                         │
│   ├── SET alarm when: value >= threshold                               │
│   ├── CLEAR alarm when: value < (threshold - hysteresis)               │
│   └── Default hysteresis: 1.0 (configurable per threshold)             │
│                                                                        │
│   Code pattern (Thresholds.cpp):                                       │
│   if (!alarm && value >= threshold) {                                  │
│       alarm = true;                                                    │
│       log_event("threshold crossed");                                  │
│   } else if (alarm && value < (threshold - hysteresis)) {              │
│       alarm = false;                                                   │
│       log_event("threshold cleared");                                  │
│   }                                                                    │
│                                                                        │
└────────────────────────────────────────────────────────────────────────┘

Source reference: Thresholds.cpp

Entity Manager Integration Flow

┌─────────────────────────────────────────────────────────────────────────┐
│                    Sensor Discovery Flow                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   1. Entity Manager loads JSON configuration                            │
│      ┌─────────────────────────────────────────────────────────────┐    │
│      │ { "Name": "CPU_Temp", "Type": "TMP75", "Bus": 1, ... }      │    │
│      └─────────────────────────────────────────────────────────────┘    │
│                                   │                                     │
│                                   ▼                                     │
│   2. Entity Manager creates D-Bus Configuration object                  │
│      Path: /xyz/openbmc_project/inventory/.../CPU_Temp                  │
│      Interface: xyz.openbmc_project.Configuration.TMP75                 │
│                                   │                                     │
│                                   ▼                                     │
│   3. HwmonTempSensor receives InterfacesAdded signal                    │
│      ┌─────────────────────────────────────────────────────────────┐    │
│      │ match = "type='signal',interface='ObjectManager',"          │    │
│      │         "member='InterfacesAdded'"                          │    │
│      └─────────────────────────────────────────────────────────────┘    │
│                                   │                                     │
│                                   ▼                                     │
│   4. Daemon checks if Type matches its supported types                  │
│      ┌──────────────────────────────────────────────────────────────┐   │
│      │ supportedTypes = {"TMP75", "TMP112", "LM75", "EMC1403", ...} │   │
│      │ if (config.Type in supportedTypes) { createSensor(); }       │   │
│      └──────────────────────────────────────────────────────────────┘   │
│                                   │                                     │
│                                   ▼                                     │
│   5. Daemon locates hwmon sysfs path                                    │
│      ┌─────────────────────────────────────────────────────────────┐    │
│      │ Scan /sys/class/hwmon/hwmon*/device/                        │    │
│      │ Match i2c-{bus}-00{address} to configuration                │    │
│      │ e.g., i2c-1-0048 for Bus=1, Address=0x48                    │    │
│      └─────────────────────────────────────────────────────────────┘    │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

ADC Scaling and Voltage Dividers

┌─────────────────────────────────────────────────────────────────────────┐
│                    ADC Voltage Calculation                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   Hardware Voltage Divider:                                             │
│                                                                         │
│       Vin ──────┬──────                                                 │
│                 │                                                       │
│                ┌┴┐ R1                                                   │
│                │ │ (e.g., 10kΩ)                                         │
│                └┬┘                                                      │
│                 ├──────────▶ ADC Input                                  │
│                ┌┴┐ R2                                                   │
│                │ │ (e.g., 3.3kΩ)                                        │
│                └┬┘                                                      │
│                 │                                                       │
│       GND ──────┴──────                                                 │
│                                                                         │
│   Voltage Divider Formula:                                              │
│   V_adc = V_in × R2 / (R1 + R2)                                         │
│   V_in = V_adc × (R1 + R2) / R2                                         │
│                                                                         │
│   ScaleFactor Calculation:                                              │
│   ScaleFactor = (R1 + R2) / R2                                          │
│   Example: (10k + 3.3k) / 3.3k = 4.03                                   │
│                                                                         │
│   Entity Manager Configuration:                                         │
│   {                                                                     │
│       "Name": "P12V",                                                   │
│       "Type": "ADC",                                                    │
│       "Index": 0,                                                       │
│       "ScaleFactor": 4.03,     ← Voltage divider ratio                  │
│       "PowerState": "On"       ← Only read when host is on              │
│   }                                                                     │
│                                                                         │
│   Raw to Final Conversion:                                              │
│   raw_mv = read("/sys/bus/iio/devices/iio:device0/in_voltage0_raw");    │
│   adc_voltage = raw_mv × reference_voltage / max_raw_value;             │
│   actual_voltage = adc_voltage × ScaleFactor;                           │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Power State Filtering

Sensors can be configured to only read when the host is in a specific power state:

┌─────────────────────────────────────────────────────────────────────────┐
│                    Power State Filtering                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   PowerState Options:                                                   │
│   ┌─────────────┬────────────────────────────────────────────────────┐  │
│   │ Value       │ Sensor reads when...                               │  │
│   ├─────────────┼────────────────────────────────────────────────────┤  │
│   │ "Always"    │ Always (default, standby power sensors)            │  │
│   │ "On"        │ Host is powered on (CPU/memory sensors)            │  │
│   │ "BiosPost"  │ Host is in BIOS POST (initialization sensors)      │  │
│   │ "Chassis"   │ Chassis power is on (12V rail sensors)             │  │
│   └─────────────┴────────────────────────────────────────────────────┘  │
│                                                                         │
│   Implementation:                                                       │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │ // Subscribe to host state changes                              │   │
│   │ match = "type='signal',path='/xyz/openbmc_project/state/host0'" │   │
│   │                                                                 │   │
│   │ // In polling loop                                              │   │
│   │ if (powerState == "On" && hostState != Running) {               │   │
│   │     value = NaN;  // Mark sensor unavailable                    │   │
│   │     return;                                                     │   │
│   │ }                                                               │   │
│   │ value = read_sensor();                                          │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│   When sensor is unavailable (host off), D-Bus Value = NaN              │
│   This prevents false alarms and stale readings                         │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Source Code Reference

Key implementation files in dbus-sensors:

File Description
src/HwmonTempSensor.cpp I2C temperature sensor implementation
src/ADCSensor.cpp ADC voltage sensor implementation
src/Thresholds.cpp Threshold detection and hysteresis
src/Utils.cpp Hwmon path discovery, scaling
src/SensorPaths.cpp D-Bus path construction
include/sensor.hpp Base sensor class interface

Examples

Working examples are available in the examples/sensors directory:

  • sensor_reader.cpp - C++ sensor reading example
  • external-sensor/ - External sensor daemon example
  • virtual-sensor/ - Virtual sensor configuration

References


Tested on: OpenBMC master, QEMU romulus


Back to top

OpenBMC Guide Tutorial is not affiliated with the OpenBMC project. Content is provided for educational purposes.

This site uses Just the Docs, a documentation theme for Jekyll.