1*** Settings ***
2Documentation  Validate IPMI sensor IDs using Redfish.
3
4Resource          ../lib/ipmi_client.robot
5Resource          ../lib/openbmc_ffdc.robot
6Resource          ../lib/boot_utils.robot
7Library           ../lib/ipmi_utils.py
8Variables         ../data/ipmi_raw_cmd_table.py
9
10Test Setup        Redfish.Login
11Test Teardown     Run Keywords  FFDC On Test Case Fail  AND
12...  Redfish.Logout
13
14
15*** Variables ***
16${allowed_temp_diff}    ${2}
17${allowed_power_diff}   ${10}
18
19
20*** Test Cases ***
21
22Verify IPMI Temperature Readings using Redfish
23    [Documentation]  Verify temperatures from IPMI sensor reading command using Redfish.
24    [Tags]  Verify_IPMI_Temperature_Readings_using_Redfish
25    [Template]  Get Temperature Reading And Verify In Redfish
26
27    # command_type  sensor_id  member_id
28    IPMI            PCIE       PCIE
29    IPMI            Ambient    Ambient
30
31
32Verify DCMI Temperature Readings using Redfish
33    [Documentation]  Verify temperatures from DCMI sensor reading command using Redfish.
34    [Tags]  Verify_DCMI_Temperature_Readings_using_Redfish
35    [Template]  Get Temperature Reading And Verify In Redfish
36
37    # command_type  sensor_id  member_id
38    DCMI            PCIE       PCIE
39    DCMI            Ambient    Ambient
40
41
42Test Ambient Temperature Via IPMI
43    [Documentation]  Test ambient temperature via IPMI and verify using Redfish.
44    [Tags]  Test_Ambient_Temperature_Via_IPMI
45
46    # Example of IPMI dcmi get_temp_reading output:
47    #        Entity ID                       Entity Instance    Temp. Readings
48    # Inlet air temperature(40h)                      1               +22 C
49    # Inlet air temperature(40h)                      2               +23 C
50    # Inlet air temperature(40h)                      3               +22 C
51    # CPU temperature sensors(41h)                    0               +0 C
52    # Baseboard temperature sensors(42h)              1               +26 C
53    # Baseboard temperature sensors(42h)              2               +27 C
54
55    ${temp_reading}=  Run IPMI Standard Command  dcmi get_temp_reading -N 10
56    Should Contain  ${temp_reading}  Inlet air temperature
57    ...  msg="Unable to get inlet temperature via DCMI".
58
59    ${ambient_temp_line}=
60    ...  Get Lines Containing String  ${temp_reading}
61    ...  Inlet air temperature  case-insensitive
62
63    ${ambient_temp_line}=  Split To Lines  ${ambient_temp_line}
64    ${ipmi_temp_list}=  Create List
65    FOR  ${line}  IN  @{ambient_temp_line}
66        ${ambient_temp_ipmi}=  Set Variable  ${line.split('+')[1].strip(' C')}
67        Append To List  ${ipmi_temp_list}  ${ambient_temp_ipmi}
68    END
69    ${list_length}=  Get Length  ${ipmi_temp_list}
70
71    # Getting temperature readings from Redfish.
72    ${ambient_temp_redfish}=  Get Temperature Reading From Redfish  Ambient
73    ${ambient_temp_redfish}=  Get Dictionary Values  ${ambient_temp_redfish}  sort_keys=True
74    FOR  ${index}  IN RANGE  ${list_length}
75        ${ipmi_redfish_temp_diff}=
76        ...  Evaluate  abs(${ambient_temp_redfish[${index}]} - ${ipmi_temp_list[${index}]})
77
78        Should Be True  ${ipmi_redfish_temp_diff} <= ${allowed_temp_diff}
79        ...  msg=Ambient temperature above allowed threshold ${allowed_temp_diff}.
80    END
81
82
83Test Power Reading Via IPMI With Host Off
84    [Documentation]  Verify power reading via IPMI with host in off state
85    [Tags]  Test_Power_Reading_Via_IPMI_With_Host_Off
86
87    Redfish Power Off  stack_mode=skip
88
89    ${ipmi_reading}=  Get IPMI Power Reading
90
91    Should Be Equal  ${ipmi_reading['instantaneous_power_reading']}  0
92    ...  msg=Power reading not zero when power is off.
93
94
95Test Power Reading Via IPMI With Host Booted
96    [Documentation]  Test power reading via IPMI with host in booted state and
97    ...  verify using Redfish.
98    [Tags]  Test_Power_Reading_Via_IPMI_With_Host_Booted
99
100    IPMI Power On  stack_mode=skip
101
102    Wait Until Keyword Succeeds  2 min  30 sec  Verify Power Reading Using IPMI And Redfish
103
104
105Test Baseboard Temperature Via IPMI
106    [Documentation]  Test baseboard temperature via IPMI and verify using Redfish.
107    [Tags]  Test_Baseboard_Temperature_Via_IPMI
108
109    # Example of IPMI dcmi get_temp_reading output:
110    #        Entity ID                       Entity Instance    Temp. Readings
111    # Inlet air temperature(40h)                      1               +22 C
112    # Inlet air temperature(40h)                      2               +23 C
113    # Inlet air temperature(40h)                      3               +22 C
114    # CPU temperature sensors(41h)                    0               +0 C
115    # Baseboard temperature sensors(42h)              1               +26 C
116    # Baseboard temperature sensors(42h)              2               +27 C
117
118    ${temp_reading}=  Run IPMI Standard Command  dcmi get_temp_reading -N 10
119    Should Contain  ${temp_reading}  Baseboard temperature sensors
120    ...  msg="Unable to get baseboard temperature via DCMI".
121    ${baseboard_temp_lines}=
122    ...  Get Lines Containing String  ${temp_reading}
123    ...  Baseboard temperature  case-insensitive=True
124    ${lines}=  Split To Lines  ${baseboard_temp_lines}
125
126    ${ipmi_temp_list}=  Create List
127    FOR  ${line}  IN  @{lines}
128        ${baseboard_temp_ipmi}=  Set Variable  ${line.split('+')[1].strip(' C')}
129        Append To List  ${ipmi_temp_list}  ${baseboard_temp_ipmi}
130    END
131    ${list_length}=  Get Length  ${ipmi_temp_list}
132
133    # Getting temperature readings from Redfish.
134    ${baseboard_temp_redfish}=  Get Temperature Reading From Redfish  PCIE
135    ${baseboard_temp_redfish}=  Get Dictionary Values  ${baseboard_temp_redfish}  sort_keys=True
136
137    FOR  ${index}  IN RANGE  ${list_length}
138        ${baseboard_temp_diff}=  Evaluate  abs(${baseboard_temp_redfish[${index}]} - ${ipmi_temp_list[${index}]})
139        Should Be True
140        ...  ${baseboard_temp_diff} <= ${allowed_temp_diff}
141        ...  msg=Baseboard temperature above allowed threshold ${allowed_temp_diff}.
142    END
143
144Test Power Reading Via IPMI Raw Command
145    [Documentation]  Test power reading via IPMI raw command and verify
146    ...  using Redfish.
147    [Tags]  Test_Power_Reading_Via_IPMI_Raw_Command
148
149    IPMI Power On  stack_mode=skip
150
151    Wait Until Keyword Succeeds  2 min  30 sec  Verify Power Reading Via Raw Command
152
153
154Verify CPU Present
155    [Documentation]  Verify the IPMI sensor for CPU present using Redfish.
156    [Tags]  Verify_CPU_Present
157    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
158
159    # component  state
160    cpu          Enabled
161
162
163Verify CPU Not Present
164    [Documentation]  Verify the IPMI sensor for CPU not present using Redfish.
165    [Tags]  Verify_CPU_Not_Present
166    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
167
168    # component  state
169    cpu          Absent
170
171
172Verify GPU Present
173    [Documentation]  Verify the IPMI sensor for GPU present using Redfish.
174    [Tags]  Verify_GPU_Present
175    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
176
177    # sensor_id  component
178    0xC5         gv100card0
179
180
181Verify GPU Not Present
182    [Documentation]  Verify the IPMI sensor for GPU not present using Redfish.
183    [Tags]  Verify_GPU_Not_Present
184    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
185
186    # sensor_id  component
187    0xC5         gv100card0
188
189
190Test Sensor Threshold Via IPMI
191    [Documentation]  Test sensor threshold via IPMI and verify using Redfish.
192    [Tags]  Test_Sensor_Threshold_Via_IPMI
193    [Template]  Verify Power Supply Sensor Threshold
194
195    # threshold_id             component
196    Upper Non-Critical         UpperThresholdNonCritical
197    Upper Critical             UpperThresholdCritical
198    Lower Non-Critical         LowerThresholdNonCritical
199    Lower Critical             LowerThresholdCritical
200
201
202*** Keywords ***
203
204Get Temperature Reading And Verify In Redfish
205    [Documentation]  Get IPMI or DCMI sensor reading and verify in Redfish.
206    [Arguments]  ${command_type}  ${sensor_id}  ${member_id}
207
208    # Description of argument(s):
209    # command_type  Type of command used to get sensor data (eg. IPMI, DCMI).
210    # sensor_id     Sensor id used to get reading in IPMI or DCMI.
211    # member_id     Member id of sensor data in Redfish.
212
213    ${ipmi_value}=  Run Keyword If  '${command_type}' == 'IPMI'  Get IPMI Sensor Reading  ${sensor_id}
214    ...  ELSE  Get DCMI Sensor Reading  ${sensor_id}
215
216    ${redfish_value}=  Get Temperature Reading From Redfish  ${member_id}
217
218    ${keys}=  Get Dictionary Keys  ${ipmi_value}
219    FOR  ${index}  IN  @{keys}
220        ${value_diff}=  Evaluate  abs(${redfish_value["${index}"]} - ${ipmi_value["${index}"]})
221        Should Be True  ${value_diff} <= ${allowed_temp_diff}
222    END
223
224
225
226Get IPMI Sensor Reading
227    [Documentation]  Get IPMI sensor readings as a dictionary.
228    [Arguments]  ${sensor_id}
229
230    # Description of argument(s):
231    # sensor_id     Sensor id used to get reading in IPMI.
232
233    ${sensor_list}=  Get Available Sensors  ${sensor_id}
234    ${sensor_value_dict}=  Create Dictionary
235
236    FOR  ${ids}  IN  @{sensor_list}
237        ${data}=  Run IPMI Standard Command  sensor reading ${ids}
238
239        # Example reading:
240        # PCIE_0_Temp      | 5Ch | ok  | 41.1 | 27 degrees C
241
242        ${sensor_key}=  Set Variable  ${data.split('| ')[0].strip()}
243        ${sensor_value}=  Set Variable  ${data.split('| ')[1].strip()}
244        Set To Dictionary  ${sensor_value_dict}  ${sensor_key}  ${sensor_value}
245    END
246
247    [Return]  ${sensor_value_dict}
248
249
250Get DCMI Sensor Reading
251    [Documentation]  Get DCMI sensor readings as a dictionary.
252    [Arguments]  ${sensor_id}
253
254    # Description of argument(s):
255    # sensor_id     Sensor id used to get reading in DCMI.
256
257    ${data}=  Run IPMI Standard Command  dcmi sensors
258    ${sensor_data}=  Get Lines Containing String  ${data}  ${sensor_id}  case_insensitive
259    ${sensor_lines}=  Split To Lines  ${sensor_data}
260
261    # Example reading:
262    # Record ID 0x005c: PCIE_0_Temp      | 27 degrees C      | ok
263
264    ${sensor_value_dict}=  Create Dictionary
265
266    FOR  ${line}  IN  @{sensor_lines}
267        ${sensor}=  Set Variable  ${line.split(' | ')}
268        ${sensor_key}=  Set Variable  ${sensor[0].split(':')[1].strip()}
269        ${sensor_value}=  Set Variable  ${sensor[1].split()[0].strip()}
270        ${contains}=  Evaluate  """disabled""" in "${sensor_value}"
271
272        Run Keyword IF  "${contains}" != """True"""
273        ...  Set To Dictionary  ${sensor_value_dict}  ${sensor_key}  ${sensor_value}
274    END
275
276    [Return]  ${sensor_value_dict}
277
278
279Get Temperature Reading From Redfish
280    [Documentation]  Get temperature reading from Redfish.
281    [Arguments]  ${member_id}
282
283    # Description of argument(s):
284    # member_id    Member id of temperature.
285
286    @{thermal_uri}=  redfish_utils.Get Member List  /redfish/v1/Chassis/
287    @{redfish_readings}=  redfish_utils.Get Attribute  ${thermal_uri[0]}/${THERMAL_METRICS}  TemperatureReadingsCelsius
288
289    # Example of Baseboard temperature via Redfish
290
291    # "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/ThermalMetrics",
292    # "@odata.type": "#ThermalMetrics.v1_0_0.ThermalMetrics",
293    # "Id": "ThermalMetrics",
294    # "Name": "Chassis Thermal Metrics",
295    # "TemperatureReadingsCelsius": [
296    # {
297    # "@odata.id": "/redfish/v1/Chassis/chassis/Sensors/PCIE_0_Temp",
298    # "DataSourceUri": "/redfish/v1/Chassis/chassis/Sensors/PCIE_0_Temp",
299    # "DeviceName": "PCIE_0_Temp",
300    # "Reading": 23.75
301    # },
302
303    ${redfish_value_dict}=  Create Dictionary
304    FOR  ${data}  IN  @{redfish_readings}
305        ${contains}=  Evaluate  "${member_id}" in """${data}[DeviceName]"""
306        ${reading}=  Set Variable  ${data}[Reading]
307        Run Keyword IF  "${contains}" == "True"
308        ...  Set To Dictionary  ${redfish_value_dict}  ${data}[DeviceName]  ${reading}
309    END
310
311    [Return]  ${redfish_value_dict}
312
313
314Verify Power Reading Using IPMI And Redfish
315    [Documentation]  Verify power reading using IPMI and Redfish.
316
317    # Example of power reading command output via IPMI.
318    # Instantaneous power reading:                   235 Watts
319    # Minimum during sampling period:                235 Watts
320    # Maximum during sampling period:                235 Watts
321    # Average power reading over sample period:      235 Watts
322    # IPMI timestamp:                                Thu Jan  1 00:00:00 1970
323    # Sampling period:                               00000000 Seconds.
324    # Power reading state is:                        deactivated
325
326    ${ipmi_reading}=  Get IPMI Power Reading
327
328    ${power_uri_list}=  redfish_utils.Get Members URI  /redfish/v1/Chassis/  PowerControl
329    Log List  ${power_uri_list}
330
331    # Power entries could be seen across different redfish path, remove the URI
332    # where the attribute is non-existent.
333    # Example:
334    #     ['/redfish/v1/Chassis/chassis/Power',
335    #      '/redfish/v1/Chassis/motherboard/Power']
336    FOR  ${idx}  IN  @{power_uri_list}
337        ${power}=  redfish_utils.Get Attribute  ${idx}  PowerControl
338        Log Dictionary  ${power[0]}
339
340        # Ensure the path does have the attribute else set to EMPTY as default to skip.
341        ${value}=  Get Variable Value  ${power[0]['PowerConsumedWatts']}  ${EMPTY}
342        Run Keyword If  "${value}" == "${EMPTY}"
343        ...  Remove Values From List  ${power_uri_list}  ${idx}
344
345        # Check the next available element in the list.
346        Continue For Loop If  "${value}" == "${EMPTY}"
347
348        ${ipmi_redfish_power_diff}=
349        ...  Evaluate  abs(${${power[0]['PowerConsumedWatts']}} - ${ipmi_reading['instantaneous_power_reading']})
350        Should Be True  ${ipmi_redfish_power_diff} <= ${allowed_power_diff}
351        ...  msg=Power reading above allowed threshold ${allowed_power_diff}.
352    END
353
354    # Double check, the validation has at least one valid path.
355    Should Not Be Empty  ${power_uri_list}
356    ...  msg=Should contain at least one element in the list.
357
358
359Verify Power Reading Via Raw Command
360    [Documentation]  Get dcmi power reading via IPMI raw command.
361
362    ${ipmi_raw_output}=  Run IPMI Standard Command
363    ...  raw ${IPMI_RAW_CMD['power_reading']['Get'][0]}
364
365    ${power_reading_ipmi}=  Set Variable  ${ipmi_raw_output.split()[1]}
366    ${power_reading_ipmi}=
367    ...  Convert To Integer  0x${power_reading_ipmi}
368
369    #  Example of power reading via Redfish
370    #  "@odata.id": "/redfish/v1/Chassis/chassis/Power#/PowerControl/0",
371    #  "@odata.type": "#Power.v1_0_0.PowerControl",
372    #  "MemberId": "0",
373    #  "Name": "Chassis Power Control",
374    #  "PowerConsumedWatts": 145.0,
375
376    ${power}=  Redfish.Get Properties  /redfish/v1/Chassis/${CHASSIS_ID}/Power
377    ${redfish_reading}=  Set Variable  ${power['PowerControl'][0]['PowerConsumedWatts']}
378
379    ${ipmi_redfish_power_diff}=
380    ...  Evaluate  abs(${redfish_reading} - ${power_reading_ipmi})
381
382    Should Be True  ${ipmi_redfish_power_diff} <= ${allowed_power_diff}
383    ...  msg=Power reading above allowed threshold ${allowed_power_diff}.
384
385
386Set Present Bit Via IPMI and Verify Using Redfish
387    [Documentation]  Set present bit of sensor via IPMI and verify using Redfish.
388    [Arguments]  ${component}  ${status}
389
390    # Description of argument(s):
391    # component    The Redfish component of IPMI sensor.
392    # status  Status of the bit to be set(e.g. Absent, Present).
393
394    ${sensor_list}=  Get Available Sensors  ${component}
395    ${sensor_name}=  Set Variable  ${sensor_list[0]}
396    ${sensor_id}=  Get Sensor Id For Sensor  ${sensor_name}
397
398     Run Keyword If  '${status}' == 'Absent'
399     ...  Run IPMI Command
400     ...  0x04 0x30 ${sensor_id} 0xa9 0x00 0x00 0x00 0x80 0x00 0x00 0x20 0x00
401     ...  ELSE IF  '${status}' == 'Enabled'
402     ...  Run IPMI Command
403     ...  0x04 0x30 ${sensor_id} 0xa9 0x00 0x80 0x00 0x00 0x00 0x00 0x20 0x00
404
405     # Redfish cpu components have "-" instead of "_" (e.g.: dcm0-cpu0).
406     ${cpu_name}=  Replace String  ${sensor_name}  _  -
407     ${sensor_properties}=  Redfish.Get Properties  /redfish/v1/Systems/system/Processors/${cpu_name}
408
409     #  Example of CPU state via Redfish
410
411     # "ProcessorType": "CPU",
412     # "SerialNumber": "YA1936422499",
413     # "Socket": "",
414     # "SparePartNumber": "F210110",
415     # "Status": {
416     # "Health": "OK",
417     # "State": "Absent"
418     # }
419
420     Should Be True  '${sensor_properties['Status']['State']}' == '${status}'
421
422
423Verify Power Supply Sensor Threshold
424    [Documentation]  Get power supply sensor threshold value via IPMI and verify using Redfish.
425    [Arguments]  ${ipmi_threshold_id}  ${redfish_threshold_id}
426
427    # Description of argument(s):
428    # ipmi_threshold_id       The sensor threshold component of IPMI sensor.
429    # redfish_threshold_id    The sensor threshold component of Redfish sensor.
430
431
432    #  Example of ipmi sensor output
433    # Locating sensor record...
434    # Sensor ID              : ps0_input_voltag (0xf7)
435    # Entity ID             : 10.19
436    # Sensor Type (Threshold)  : Voltage
437    # Sensor Reading        : 208 (+/- 0) Volts
438    # Status                : ok
439    # Lower Non-Recoverable : na
440    # Lower Critical        : 180.000
441    # Lower Non-Critical    : 200.000
442    # Upper Non-Critical    : 290.000
443    # Upper Critical        : 300.000
444    # Upper Non-Recoverable : na
445    # Positive Hysteresis   : Unspecified
446    # Negative Hysteresis   : Unspecified
447
448
449    ${ipmi_sensor_output}=  Run External IPMI Standard Command  sensor get ps0_input_voltag
450    ${ipmi_threshold_output}=  Get Lines Containing String  ${ipmi_sensor_output}  ${ipmi_threshold_id}
451    ${ipmi_threshold_reading}=  Fetch From Right  ${ipmi_threshold_output}  :${SPACE}
452
453    ${ipmi_threshold_reading}=  Set Variable If  '${ipmi_threshold_reading}' == 'na'
454    ...  ${0}  ${ipmi_threshold_reading}
455
456    #  Example of redfish sensor output
457    # "@odata.id": "/redfish/v1/Chassis/chassis/Power#/Voltages/0",
458    # "@odata.type": "#Power.v1_0_0.Voltage",
459    # "LowerThresholdCritical": 180.0,
460    # "LowerThresholdNonCritical": 200.0,
461    # "MaxReadingRange": 0.0,
462    # "MemberId": "ps0_input_voltage",
463    # "MinReadingRange": 0.0,
464    # "Name": "ps0 input voltage",
465    # "ReadingVolts": 209.5,
466    # "Status": {
467    # "Health": "OK",
468    # "State": "Enabled"
469    # },
470    # "UpperThresholdCritical": 300.0,
471    # "UpperThresholdNonCritical": 290.0
472
473    @{redfish_readings}=  Redfish.Get Attribute  /redfish/v1/Chassis/${CHASSIS_ID}/Power  Voltages
474    FOR  ${data}  IN  @{redfish_readings}
475        Run keyword if  '${data}[MemberId]' == 'ps0_input_voltage'
476        ...  Should Be Equal As Numbers  ${data['${redfish_threshold_id}']}  ${ipmi_threshold_reading}
477    END
478
479
480Get Available Sensors
481    [Documentation]  Get all the available sensors for the required component.
482    ...  Returns a list of available sensors.
483    [Arguments]  ${sensor_component}
484
485    # Description of argument(s):
486    # sensor_component     sensor component name.(e.g.:cpu)
487
488    ${resp}=  Run IPMI Standard Command  sdr elist
489    ${sensor_list}=  Create List
490    ${sensors}=  Get Lines Containing String  ${resp}  ${sensor_component}  case-insensitive
491    ${sensors}=  Split To Lines  ${sensors}
492
493    # Example of IPMI sdr elist command.
494
495    # dcm0_cpu0        | 41h | ok  |  3.1 | Presence detected
496    # dcm0_cpu1        | 42h | ok  |  3.2 | Presence detected, Disabled
497    # dcm1_cpu0        | 43h | ok  |  3.3 | Presence detected
498    # dcm1_cpu1        | 44h | ok  |  3.4 | Presence detected, Disabled
499    # dcm2_cpu0        | 45h | ns  |  3.5 | Disabled
500    # dcm2_cpu1        | 46h | ns  |  3.6 | Disabled
501    # dcm3_cpu0        | 47h | ns  |  3.7 | Disabled
502    # dcm3_cpu1        | 48h | ns  |  3.8 | Disabled
503
504    FOR  ${line}  IN  @{sensors}
505        ${sensor_name}=  Set Variable  ${line.split('|')[0].strip()}
506
507        # Adding sensors to the list whose presence is detected.
508        ${contains}=  Evaluate  "Presence detected" in "${line}" or "ok" in "${line}"
509        Run Keyword IF  "${contains}" == "True"
510        ...  Append To List  ${sensor_list}  ${sensor_name}
511    END
512
513    # Example of output for ${sensor_list}
514    # ['dcm0_cpu0', 'dcm0_cpu1', 'dcm1_cpu0', 'dcm1_cpu1']
515
516    [RETURN]  ${sensor_list}
517
518
519Get Sensor Id For Sensor
520    [Documentation]  Returns the sensor ID value for the given sensor.
521    [Arguments]  ${sensor_name}
522
523    # Description of argument(s):
524    # sensor_name     Name of sensor whose ID is required(e.g.: dcm0_cpu0, dcm0_cpu1 etc).
525
526    ${get_resp}=  Run IPMI Standard Command  sensor get ${sensor_name}
527
528    # Example of sensor get command.
529
530    # Locating sensor record...
531    # Sensor ID              : dcm0_cpu0 (0x41)
532    # Entity ID             : 3.1
533    # Sensor Type (Discrete): Processor
534    # States Asserted       : Processor
535    #                  [Presence detected]
536
537    ${line}=  Get Lines Containing String  ${get_resp}  Sensor ID
538    ${sensor_id}=  Set Variable  ${line[-5:-1]}
539
540    # Example of output for ${sensor_id} is 0x41.
541
542    [RETURN]  ${sensor_id}
543
544