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": "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`-/xyz
217  `-/xyz/openbmc_project
218    `-/xyz/openbmc_project/sensors
219      `-/xyz/openbmc_project/sensors/temperature
220        |-/xyz/openbmc_project/sensors/temperature/18_great_local
221        |-/xyz/openbmc_project/sensors/temperature/18_great_ext
222        |-/xyz/openbmc_project/sensors/temperature/19_great_local
223        |-/xyz/openbmc_project/sensors/temperature/19_great_ext
224
225~# busctl introspect --no-pager xyz.openbmc_project.HwmonTempSensor \
226 /xyz/openbmc_project/sensors/temperature/18_great_local
227
228NAME                                TYPE      SIGNATURE RESULT/VALUE                             FLAGS
229org.freedesktop.DBus.Introspectable interface -         -                                        -
230.Introspect                         method    -         s                                        -
231org.freedesktop.DBus.Peer           interface -         -                                        -
232.GetMachineId                       method    -         s                                        -
233.Ping                               method    -         -                                        -
234org.freedesktop.DBus.Properties     interface -         -                                        -
235.Get                                method    ss        v                                        -
236.GetAll                             method    s         a{sv}                                    -
237.Set                                method    ssv       -                                        -
238.PropertiesChanged                  signal    sa{sv}as  -                                        -
239org.openbmc.Associations            interface -         -                                        -
240.associations                       property  a(sss)    1 "chassis" "all_sensors" "/xyz/openb... emits-change
241xyz.openbmc_project.Sensor.Value    interface -         -                                        -
242.MaxValue                           property  d         127                                      emits-change
243.MinValue                           property  d         -128                                     emits-change
244.Value                              property  d         31.938                                   emits-change writable
245
246```
247
248There you are! You now have the two sensors from the two card instances on dbus.
249
250This can be more complex, for instance if your card has a mux you can add it to
251the configuration, which will trigger FruDevice to scan those new buses for
252more devices.
253