1# My First Sensors 2 3This document is meant to bring you from nothing to using Entity-Manager with 4Dbus-Sensors to populate a plug-in card's sensor values on dbus. Once the sensor 5values are on dbus, they can be read via IPMI or Redfish (doing so is beyond 6the scope of this guide). 7 8For the sake of this example, let's pretend there is a PCIe card that exposes 9an 24c02 eeprom and a tmp441 sensor. The PCIe slots are behind an smbus mux on 10the motherboard and are in a device-tree such as this: 11 12``` 13aliases { 14 i2c16 = &i2c_pe0; 15 i2c17 = &i2c_pe1; 16 i2c18 = &i2c_pe2; 17 i2c19 = &i2c_pe3; 18}; 19 20... 21 22&i2c1 { 23 status = "okay"; 24 i2c-switch@71 { 25 compatible = "nxp,pca9546"; 26 reg = <0x71>; 27 #address-cells = <1>; 28 #size-cells = <0>; 29 i2c-mux-idle-disconnect; 30 31 i2c_pe0: i2c@0 { 32 #address-cells = <1>; 33 #size-cells = <0>; 34 reg = <0>; 35 }; 36 i2c_pe1: i2c@1 { 37 #address-cells = <1>; 38 #size-cells = <0>; 39 reg = <1>; 40 }; 41 i2c_pe2: i2c@2 { 42 #address-cells = <1>; 43 #size-cells = <0>; 44 reg = <2>; 45 }; 46 i2c_pe3: i2c@3 { 47 #address-cells = <1>; 48 #size-cells = <0>; 49 reg = <3>; 50 }; 51 }; 52}; 53``` 54 55The first daemon of interest that will run is the FruDevice portion of 56Entity-Manager. The exact layout of a FRU is beyond the scope of this guide, 57but assume the PCIe card's eeprom holds the following information: 58 59``` 60Product: 61 MANUFACTURER "Awesome" 62 PART_NUMBER "12345" 63 PRODUCT_NAME "Super Great" 64 SERIAL_NUMBER "12312490840" 65``` 66 67The FruDevice daemon will walk all i2c buses and attempt to find FRU contents at 68responsive smbus addresses. When if finds a FRU it will parse the contents and 69publish them to dbus keying off the most prominent name field. In this case, it 70found two of the cards. One at bus 18 and the other at 19. 71 72The dbus tree for this will look like: ``` 73 74``` 75~# busctl tree --no-pager xyz.openbmc_project.FruDevice 76`-/xyz 77 `-/xyz/openbmc_project 78 `-/xyz/openbmc_project/FruDevice 79 |-/xyz/openbmc_project/FruDevice/Super_Great 80 |-/xyz/openbmc_project/FruDevice/Super_Great_0 81``` 82 83The dbus path for each instance is unimportant beyond needing to be unique. 84Digging into one of these FRUs we see: 85 86``` 87~# busctl introspect --no-pager xyz.openbmc_project.FruDevice \ 88 /xyz/openbmc_project/FruDevice/Super_Great 89 90NAME TYPE SIGNATURE RESULT/VALUE FLAGS 91org.freedesktop.DBus.Introspectable interface - - - 92.Introspect method - s - 93org.freedesktop.DBus.Peer interface - - - 94.GetMachineId method - s - 95.Ping method - - - 96org.freedesktop.DBus.Properties interface - - - 97.Get method ss v - 98.GetAll method s a{sv} - 99.Set method ssv - - 100.PropertiesChanged signal sa{sv}as - - 101xyz.openbmc_project.FruDevice interface - - - 102.ADDRESS property u 80 emits-change 103.BUS property u 18 emits-change 104.Common_Format_Version property s "1" emits-change 105.PRODUCT_ASSET_TAG property s "--" emits-change 106.PRODUCT_FRU_VERSION_ID property s "??????" emits-change 107.PRODUCT_LANGUAGE_CODE property s "0" emits-change 108.PRODUCT_MANUFACTURER property s "Awesome" emits-change 109.PRODUCT_PART_NUMBER property s "12345" emits-change 110.PRODUCT_PRODUCT_NAME property s "Super Great" emits-change 111.PRODUCT_SERIAL_NUMBER property s "12312490840" emits-change 112.PRODUCT_VERSION property s "0A" emits-change 113``` 114 115Ok, now you can find the cards, but what about the temperature sensors on each 116of them? Entity-Manager provides a very powerful mechanism for querying various 117information, but our goal is simple. If we find the card, we want to add the 118device to the system and tell dbus-sensors that there is a hwmon temperature 119sensor available. 120 121We start with a simple hardware profile. We know that if the card's bus is 122identified we know the address of the temperature sensor is 0x4c. 123 124``` 125{ 126 "Exposes": [ 127 { 128 "Address": "$address", 129 "Bus": "$bus", 130 "Name": "$bus great eeprom", 131 "Type": "EEPROM_24C02" 132 }, 133 { 134 "Address": "0x4c", 135 "Bus": "$bus", 136 "Name": "$bus great local", 137 "Name1": "$bus great ext", 138 "Type": "TMP441" 139 } 140 ], 141 "Name": "$bus Great Card", 142 "Probe": "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'Super Great'})", 143 "Type": "Board" 144} 145``` 146 147There's a lot going on in the above hardware profile, and they can become 148considerably more complex. Firstly, let's start with the `Probe` field. This is 149a way of defining under what circumstances this hardware profile is applied. In 150this case, we want the hardware profile to be applied when a Fru is found with 151the field `PRODUCT_PRODUCT_NAME` holding the value `Super Great`. In our system, 152this will match twice. When the probe has matched the information from that 153device is then swapped into the hardware profile via the templated variables, 154such as `$bus` or `$address`. We then shift our focus to the `Exposes` field. 155This lists the entities that are added when this hardware profile is loaded. The 156field is optional and there is a wide variety of entities that can be added this 157way. 158 159In our example we only care about the eeprom and the temperature sensor. The 160`Type` field is checked against a device export map and if it matches a known 161device, it'll attempt to install the device. Be noticed that dbus only allows an 162interface name as an dot delimited string with each truncated substring starting 163with alphabets(a-z, A-Z). So the Type is intensionally renamed as EEPROM_24C02. 164It is safe to do so since Entity manager types are not required to be 1:1 with 165Linux types. 166 167For the card found on bus 18: 168 169``` 170echo "24c02 0x50 > /sys/bus/i2c/devices/i2c-18/new_device" 171echo "tmp441 0x4c > /sys/bus/i2c/devices/i2c-18/new_device" 172``` 173 174Beyond this, it also publishes to dbus a configuration: 175 176``` 177~# busctl tree --no-pager xyz.openbmc_project.EntityManager 178`-/xyz 179 `-/xyz/openbmc_project 180 |-/xyz/openbmc_project/EntityManager 181 `-/xyz/openbmc_project/inventory 182 `-/xyz/openbmc_project/inventory/system 183 `-/xyz/openbmc_project/inventory/system/board 184 |-/xyz/openbmc_project/inventory/system/board/18_Great_Card 185 | |-/xyz/openbmc_project/inventory/system/board/18_Great_Card/18_great_local 186 |-/xyz/openbmc_project/inventory/system/board/19_Great_Card 187 | |-/xyz/openbmc_project/inventory/system/board/19_Great_Card/19_great_local 188 189~# busctl introspect --no-pager xyz.openbmc_project.EntityManager \ 190 /xyz/openbmc_project/inventory/system/board/18_Great_Card/18_great_local 191 192NAME TYPE SIGNATURE RESULT/VALUE FLAGS 193org.freedesktop.DBus.Introspectable interface - - - 194.Introspect method - s - 195org.freedesktop.DBus.Peer interface - - - 196.GetMachineId method - s - 197.Ping method - - - 198org.freedesktop.DBus.Properties interface - - - 199.Get method ss v - 200.GetAll method s a{sv} - 201.Set method ssv - - 202.PropertiesChanged signal sa{sv}as - - 203xyz.openbmc_project.Configuration.TMP441 interface - - - 204.Address property t 76 emits-change 205.Bus property t 18 emits-change 206.Name property s "18 great local" emits-change 207.Name1 property s "18 great ext" emits-change 208.Type property s "TMP441" emits-change 209``` 210 211The dbus-sensors suite of daemons each run searching for a specific type of 212sensor. In this case the hwmon temperature sensor daemon will recognize the 213configuration interface: `xyz.openbmc_project.Configuration.TMP441`. 214 215It will look up the device on i2c and see there is a hwmon instance, and map 216`temp1_input` to `Name` and since there is also `Name1` it'll map `temp2_input`. 217 218``` 219~# busctl tree --no-pager Service xyz.openbmc_project.HwmonTempSensor 220`-/xyz 221 `-/xyz/openbmc_project 222 `-/xyz/openbmc_project/sensors 223 `-/xyz/openbmc_project/sensors/temperature 224 |-/xyz/openbmc_project/sensors/temperature/18_great_local 225 |-/xyz/openbmc_project/sensors/temperature/18_great_ext 226 |-/xyz/openbmc_project/sensors/temperature/19_great_local 227 |-/xyz/openbmc_project/sensors/temperature/19_great_ext 228 229~# busctl introspect --no-pager xyz.openbmc_project.HwmonTempSensor \ 230 /xyz/openbmc_project/sensors/temperature/18_great_local 231 232NAME TYPE SIGNATURE RESULT/VALUE FLAGS 233org.freedesktop.DBus.Introspectable interface - - - 234.Introspect method - s - 235org.freedesktop.DBus.Peer interface - - - 236.GetMachineId method - s - 237.Ping method - - - 238org.freedesktop.DBus.Properties interface - - - 239.Get method ss v - 240.GetAll method s a{sv} - 241.Set method ssv - - 242.PropertiesChanged signal sa{sv}as - - 243org.openbmc.Associations interface - - - 244.associations property a(sss) 1 "chassis" "all_sensors" "/xyz/openb... emits-change 245xyz.openbmc_project.Sensor.Value interface - - - 246.MaxValue property d 127 emits-change 247.MinValue property d -128 emits-change 248.Value property d 31.938 emits-change writable 249 250``` 251 252There you are! You now have the two sensors from the two card instances on dbus. 253 254This can be more complex, for instance if your card has a mux you can add it to 255the configuration, which will trigger FruDevice to scan those new buses for 256more devices. 257