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 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