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, and this is beyond 6this guide. 7 8For the sake of this very simple example, let's pretend there is a PCIe card 9that exposes an 24c02 eeprom and a tmp441 sensor. The PCIe slots are behind an 10smbus mux on the 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 this guide, but for this 57example 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": "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. 162 163For the card found on bus 18: 164 165``` 166echo "24c02 0x50 > /sys/bus/i2c/devices/i2c-18/new_device" 167echo "tmp441 0x4c > /sys/bus/i2c/devices/i2c-18/new_device" 168``` 169 170Beyond this, it also publishes to dbus a configuration: 171 172``` 173~# busctl tree --no-pager xyz.openbmc_project.EntityManager 174`-/xyz 175 `-/xyz/openbmc_project 176 |-/xyz/openbmc_project/EntityManager 177 `-/xyz/openbmc_project/inventory 178 `-/xyz/openbmc_project/inventory/system 179 `-/xyz/openbmc_project/inventory/system/board 180 |-/xyz/openbmc_project/inventory/system/board/18_Great_Card 181 | |-/xyz/openbmc_project/inventory/system/board/18_Great_Card/18_great_local 182 |-/xyz/openbmc_project/inventory/system/board/19_Great_Card 183 | |-/xyz/openbmc_project/inventory/system/board/19_Great_Card/19_great_local 184 185~# busctl introspect --no-pager xyz.openbmc_project.EntityManager \ 186 /xyz/openbmc_project/inventory/system/board/18_Great_Card/18_great_local 187 188NAME TYPE SIGNATURE RESULT/VALUE FLAGS 189org.freedesktop.DBus.Introspectable interface - - - 190.Introspect method - s - 191org.freedesktop.DBus.Peer interface - - - 192.GetMachineId method - s - 193.Ping method - - - 194org.freedesktop.DBus.Properties interface - - - 195.Get method ss v - 196.GetAll method s a{sv} - 197.Set method ssv - - 198.PropertiesChanged signal sa{sv}as - - 199xyz.openbmc_project.Configuration.TMP441 interface - - - 200.Address property t 76 emits-change 201.Bus property t 18 emits-change 202.Name property s "18 great local" emits-change 203.Name1 property s "18 great ext" emits-change 204.Type property s "TMP441" emits-change 205``` 206 207The dbus-sensors suite of daemons each run searching for a specific type of 208sensor. In this case the hwmon temperature sensor daemon will recognize the 209configuration interface: `xyz.openbmc_project.Configuration.TMP441`. 210 211It will look up the device on i2c and see there is a hwmon instance, and map 212`temp1_input` to `Name` and since there is also `Name1` it'll map `temp2_input`. 213 214``` 215~# busctl tree --no-pager Service xyz.openbmc_project.HwmonTempSensor 216 217root@semitruck:~# busctl tree --no-pager xyz.openbmc_project.HwmonTempSensor 218`-/xyz 219 `-/xyz/openbmc_project 220 `-/xyz/openbmc_project/sensors 221 `-/xyz/openbmc_project/sensors/temperature 222 |-/xyz/openbmc_project/sensors/temperature/18_great_local 223 |-/xyz/openbmc_project/sensors/temperature/18_great_ext 224 |-/xyz/openbmc_project/sensors/temperature/19_great_local 225 |-/xyz/openbmc_project/sensors/temperature/19_great_ext 226 227~# busctl introspect --no-pager xyz.openbmc_project.HwmonTempSensor \ 228 /xyz/openbmc_project/sensors/temperature/18_great_local 229 230NAME TYPE SIGNATURE RESULT/VALUE FLAGS 231org.freedesktop.DBus.Introspectable interface - - - 232.Introspect method - s - 233org.freedesktop.DBus.Peer interface - - - 234.GetMachineId method - s - 235.Ping method - - - 236org.freedesktop.DBus.Properties interface - - - 237.Get method ss v - 238.GetAll method s a{sv} - 239.Set method ssv - - 240.PropertiesChanged signal sa{sv}as - - 241org.openbmc.Associations interface - - - 242.associations property a(sss) 1 "chassis" "all_sensors" "/xyz/openb... emits-change 243xyz.openbmc_project.Sensor.Value interface - - - 244.MaxValue property d 127 emits-change 245.MinValue property d -128 emits-change 246.Value property d 31.938 emits-change writable 247 248``` 249 250There you are! You now have the two sensors from the two card instances on dbus. 251 252This can be more complex, for instance if your card has a mux you can add this, 253will trigger FruDevice to scan those new buses for more devices. 254