# sensor 传感器管理

**sensor** 主要用于承接iBMC的传感器管理

---

1. 功能简介
2. 关键特性
3. 对外接口
4. 传感器配置

---

## 1 功能简介

传感器主要用于监测如CPU、内存、硬盘、风扇、电源、卡等部件的信息，如部件在位、温度、电压、风扇转速等信息。并相应记录IPMI SEL以及通过传感器健康状态进行表征。 <br>
以此达到监管部件的**运行状态**及**健康状况**的目的。


## 2 关键特性

### 2.1 门限型传感器

门限传感器 又叫做 连续性传感器，表征传感器的值是连续变化的（对比了解：数学中的连续值/曲线），如：温度，电压，功耗，转速等。通过门限传感器可描述性资源表征传感器的运行状态和健康状况。

关联类：`ThresholdSensor`


#### 2.1.1 门限型传感器可描述资源
门限传感器可描述资源均使用`ThresholdSensorDisplay`类来进行表示，该类不需要CSR配置，由sensor 组件进行解析和完成上资源树。

|属性名称|属性类型|属性说明|
|--|--|--|
|Status|string|传感器当前状态：<br>Enabled：传感器使能<br>Disabled：传感器禁用<br>InTest：传感器测试中<br>Starting：传感器更新中|
|Health|string|传感器健康状态：<br>Critical：紧急<br>Major：严重<br>Minor：一般<br>OK：正常|
|AssertStatus|uint16|传感器SEL事件状态，如0x0080<br>bit[0:5]依次对应6种门限事件状态，每个bit的两种读值状态：<br>1：Assert<br>0：Deassert|
|ReadingDisplay|string|传感器读值可读描述，精度3位有效数字|
|UnitDisplay|string|传感器单位可读描述|
|UpperNonrecoverableDisplay|string|传感器**紧急**门限上限可读描述，精度3位有效数字|
|UpperCriticalDisplay|string|传感器**严重**门限上限可读描述，精度3位有效数字|
|UpperNoncriticalDisplay|string|传感器**一般**门限上限可读描述，精度3位有效数字|
|LowerNonrecoverableDisplay|string|传感器**紧急**门限下限可读描述，精度3位有效数字|
|LowerNoncriticalDisplay|string|传感器**严重**门限下限可读描述，精度3位有效数字|
|LowerCriticalDisplay|string|传感器**一般**门限下限可读描述，精度3位有效数字|
|PositiveHysteresisDisplay|string|传感器**正向**迟滞量可读描述，精度3位有效数字|
|NegativeHysteresisDisplay|string|传感器**负向**迟滞量可读描述，精度3位有效数字|

### 2.2 离散型传感器
离散传感器，表征传感器的值是离散的（对比了解：数学中的离散值/曲线），如：运行状态，隔离值等。通过离散型传感器可描述性资源表征传感器的运行状态和健康状况。

关联类：`DiscreteSensor`

#### 2.2.1 离散型传感器可描述资源
离散型传感器可描述资源均使用`DiscreteSensorDisplay`类来进行表示，该类不需要CSR配置，由sensor组件进行解析和完成上资源树。

|属性名称|属性类型|属性说明|
|--|--|--|
|Status|string|传感器当前状态：<br>Enabled：传感器使能<br>Disabled：传感器禁用<br>InTest：传感器测试中<br>Starting：传感器更新中|
|Health|string|传感器健康状态：<br>Critical：紧急<br>Major：严重<br>Minor：一般<br>OK：正常|
|AssertStatus|uint16|传感器SEL事件状态，16进制的数，如0x8000<br>bit[0:14]依次对应15种离散事件状态，每个bit的两种读值状态：<br>1：Assert<br>0：Deassert|

### 2.3 IPMI SEL

#### 2.3.1 连续型传感器触发事件
连续传感器的事件生成条件即：读值与门限值比较后是否满足了产生或恢复事件的条件。会依次比较读值与6个门限值是否满足产生与恢复条件。<br>

检查是否满足事件生成条件流程如下：

```mermaid
graph LR
    A[检查是否触发sel事件] --> 1B[触发sel事件发生];
    1B --> 1C{1. AssertMask是否置位};
    1C --> |是|1D{2. 读值是否超出门限值范围}
    1D --> |是|1E{3. 是否已经产生了事件}
    1E --> |否|F{填充sel信息并记录事件数据库，更新传感器健康信息}
    A[检查是否触发sel事件] --> 2B[触发sel事件恢复];
    2B --> 2C{1. DeassertMask是否置位};
    2C --> |是|2D{2. 读值是否恢复到门限范围内}
    2D --> |是|2E{3. 是否已经产生了事件未恢复}
    2E --> |是|F[填充sel信息并记录事件数据库，更新传感器健康信息]
```

#### 2.3.2 离散型传感器触发事件
离散传感器的事件生成条件即关联的**离散事件**的方向是否发生改变，然后查看是否满足产生与恢复条件。<br>

|监听方式|数据组成|
|----|----|
|组合监听|Property：`event_dir | event_data3 | event_data2 | event_data1`|
|独立监听|本对象属性：EventDir、EventData1、EventData2、EventData3|
|----|----|
|事件翻转|Conversion属性低4位为翻转位，翻转该事件的方向<br>`Conversion & 0x0F == 1`：`assert => deassert` 或 `deassert => assert`|

检查是否满足事件生成条件流程如下：

```mermaid
graph LR
    A[检查是否触发sel事件] --> 1B[触发sel事件产生]
    1B --> 1C{1. AssertMask是否置位}
    1C --> |是|1D{2. 是否已产生相同事件}
    1D --> |否|1E{3. 是否为数字离散，即互斥事件}
    1E --> |是|1F[删除已产生的事件]
    1F --> G[填充sel信息并记录事件数据库，更新传感器健康信息]
    A[检查是否触发sel事件] --> 2B[触发sel事件恢复]
    2B --> 2C{1. 是否产生了事件未恢复}
    2C --> |是|G[填充sel信息并记录事件数据库，更新传感器健康信息]
```


## 3 对外接口

### 3.1 资源树接口
- Sensors

    - Path: `/bmc/kepler/Chassis/:ChassisId/Sensors` 

    - Interface: `bmc.kepler.Chassis.Sensors`

        | 方法  | 描述  |
        | :------------: | :------------: |
        | GetThresholdSensorList | 获取连续传感器列表 |
        | GetDiscreteSensorList | 获取离散传感器列表 |
        | GetSensorList | 获取所有传感器列表 |
        | MockSensor | 模拟传感器 |
        | SetSensorStatus | 设置传感器使能 |
        | ExportSel | 导出传感器事件 |
        | GetSel | 获取传感器事件 |

#### 3.1.1 获取连续传感器列表 GetThresholdSensorList

**输入：**

- 无

**输出：**

- `ThresholdSensorList`: 连续传感器列表

**列表中的基本信息如下：**

- `SensorNumber`: 传感器编号
- `SensorName`: 传感器名称
- `SensorIdentifier`：传感器标识
- `SensorUnit`: 传感器单位，具体的描述单位，比如RPM
- `SensorStatus`: 传感器状态
- `SensorReading`: 传感器读数，经过单位转换之后
- `LowerThresholdFatal`: 传感器紧急事件下限
- `LowerThresholdCritical`: 传感器严重事件下限
- `LowerThresholdNonCritical`: 传感器一般事件下限
- `UpperThresholdNonCritical`: 传感器紧急事件上限
- `UpperThresholdCritical`: 传感器严重事件上限
- `UpperThresholdFatal`: 传感器一般事件上限
- `PosHysteresis`: 传感器正向迟滞量
- `NegHysteresis`: 传感器负向迟滞量
- `SensorType`: 传感器类型
- `Status`: 传感器使能状态
- `Health`: 传感器健康状态
- `SystemId`: 传感器归属host的编号



#### 3.1.2 获取离散传感器列表 GetDiscreteSensorList

**输入：**

- 无

**输出：**

- `DiscreteSensorList`: 离散传感器列表

**列表中的基本信息如下：**

- `SensorNumber`: 传感器编号
- `SensorName`: 传感器名称
- `SensorIdentifier`：传感器标识
- `SensorStatus`: 传感器状态
- `SystemId`: 传感器归属host的编号


#### 3.1.3 获取所有传感器列表 GetSensorList

**输入：**

- 无

**输出：**

- `SensorList`: 传感器列表

**列表中的基本信息如下：**

- `SensorNumber`: 传感器编号
- `SensorName`: 传感器名称
- `SensorUnit`: 传感器单位，具体的描述单位，比如RPM
- `SensorStatus`: 传感器状态
- `SensorReading`: 传感器读数，经过单位转换之后
- `LowerFatal`: 传感器紧急事件下限
- `LowerCritical`: 传感器严重事件下限
- `LowerNonCritical`: 传感器一般事件下限
- `UpperNonCritical`: 传感器紧急事件上限
- `UpperCritical`: 传感器严重事件上限
- `UpperFatal`: 传感器一般事件上限
- `PosHysteresis`: 传感器正向迟滞量
- `NegHysteresis`: 传感器负向迟滞量
- `SensorType`: 传感器类型
- `BaseUnit`: 单位(数字描述)
- `ReadingType`: 读值类型
- `SystemId`: 传感器归属host的编号



#### 3.1.4 模拟传感器 MockSensor

**输入：**


- `Enabled`:使能模拟：1 = 开启模拟; 0 = 关闭模拟
- `SensorName`:传感器名称
- `Value`:传感器读数，`stop` 表示停止模拟

**输出：**

- 无


#### 3.1.5 设置传感器使能 SetSensorStatus

**输入：**


- `SensorName`:传感器名称
- `Status`:使能状态：enabled; disabled

**输出：**

- 无



#### 3.1.6  导出传感器事件 ExportSel

**输入：**


- `Path`:导出sel的路径

**输出：**

- `TaskId`: 任务标识


#### 3.1.7  获取传感器事件 GetSel

**输入：**


- `StartId`:查询事件的起始编号，大于等于1。超过总条数会返回空表
- `Count`:查询事件的数量，大于等于0。超过总条数会返回所有事件

**输出：**

- `Total`: 获取传感器事件的总条数
- `SelList`: 传感器事件列表

**列表中的基本信息如下：**

- `RecordId`: 传感器事件编号
- `Timestamp`: 传感器事件时间戳
- `Level`: 传感器事件等级
- `SensorName`: 传感器名称
- `SensorType`: 传感器类型
- `Status`: 传感器事件状态
- `Description`: 传感器事件描述

### 3.2 IPMI接口
- 具体参数参考本组件配置文件ipmi.json

| 方法  | 描述  |
|--|--|
| SetSensorEventReceiver | 设置传感器事件接收器 |
| GetSensorEventReceiver | 获取传感器事件接收器 |
| ReportSensorEvent | 传感器事件消息 |
| GetPEFCapabilities | 获取PEF能力 |
| SetPEFPostponeTimer | 设置PEF延迟定时器 |
| SetPEFParameters | 设置PEF参数 |
| GetPEFParameters | 获取PEF参数 |
| SetPEFLastEventId | 设置PEF最新事件ID |
| GetPEFLastEventId | 获取PEF最新事件ID |
| GetDeviceSDRInfo | 获取设备SDR信息 |
| GetDeviceSDR | 获取设备SDR |
| ReserveDeviceSDR | 预留设备SDR存储库 |
| GetSensorFactors | 获取传感器读数计算系数 |
| SetSensorHysteresis | 设定传感器迟滞 |
| GetSensorHysteresis | 获取传感器迟滞 |
| SetSensorThreshold | 设置传感器阈值 |
| GetSensorThreshold | 获取传感器阈值 |
| SetSensorEventEnable | 设置传感器事件启用状态 |
| GetSensorEventEnable | 获取传感器事件启用状态 |
| RearmSensorEvent | 重新布置传感器事件 |
| GetSensorEventStatus | 获取传感器事件状态 |
| GetSensorReading | 获取传感器读数 |
| GetSensorType | 获取传感器类型 |
| GetSDRRepoInfo | 获取SDR存储库信息 |
| GetSDRRepoAllocInfo | 获取SDR存储库分配信息 |
| GetSDRReserveId | 获取SDR预约ID |
| GetSDR | 获取SDR |
| AddPartialSDR | 添加部分SDR |
| AddSDR | 添加一条SDR |
| ClearSDR | 清除SDR |
| EnterSDRRepoUpdate | 进入SDR存储库更新模式 |
| ExitSDRRepoUpdate | 退出SDR存储库更新模式 |
| RunSDRInitAgent | 运行SDR初始化代理 |
| GetSelInfo | 获取SEL信息 |
| GetSelAllocInfo | 获取SEL分配信息 |
| GetSelReserveId | 获取SEL预约ID |
| GetSelEntry | 获取SEL条目 |
| AddSelEntry | 添加SEL条目 |
| ClearSel | 清除SEL |
| OEMGetSystemSel | 查询系统健康事件(BMC内部使用) |
| OEMGetSystemSel2 | 查询系统健康事件(dft) |
| SetBMCEnables | 设置BMC全局启用 |
| GetBMCEnables | 获取BMC全局启用 |
| GetDeviceLocatorRecordId | 获取设备定位器记录ID |



## 4 配置介绍
传感器配置需要一定程度上参照 [IPMI标准规范协议](https://www.intel.cn/content/www/cn/zh/products/docs/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html)

### 4.1 实体资源配置

传感器实体资源，表征当前的传感器依赖或者所属的硬件的实体描述，该实体的**在位状态**或者**上下电状态**会影响当前传感器的值以及状态，还有对应传感器事件IPMI SEL的生成状态。

#### 4.1.1 配置属性
|属性名称|属性类型|属性说明|
|--|--|--|
|Id|uint8|传感器对应的实体标识 <br>具体参照 *Table 43-, Entity ID Codes(P550)*|
|Instance|uint8|传感器对应的实体实例标识，通常以`0x60`开始配置 <br>具体参照 *Section 39.1 System- and Device-relatice Entity Instance Values(P492)*|
|Slot|uint8|实体所在的槽位，默认`0xFF`。如果槽位不是默认，则会根据槽位生成唯一的Instance|
|Name|string  |实体的名称|
|Presence|uint8|实体的在位状态，需要关联对应的在位信号来源 <br>若不存在部件动态拔插，则配置为`1`|
|PowerState|uint8|实体的上下电状态，需要关联对应的上下电信号来源 <br>若与上下电状态无关，则配置为`1`|

#### 4.1.2 配置关键点

1. `Entity Id`严格按照**IPMI规范**中的表格进行配置
2. `Entity Instance`保证同一`Entity Id`下唯一

### 4.2 连续型传感器配置

连续型传感器，表征传感器的值是连续变化的，如：温度，电压，功耗，转速等。

#### 4.2.1 配置属性

以下属性配置原则皆参照 *Section 43.1 SDR Type 01h, Full Sensor Record(P521)*

|属性名称|属性类型|属性说明|
|--|--|--|
|OwnerId|uint8|传感器的归属Id <br>BMC - `0x20`|
|OwnerLun|uint8|传感器的归属Lun <br>owner为系统软件 - `0x00`|
|EntityId|uint8|传感器对应实体标识，关联传感器对应的`Entity.Id`|
|EntityInstance|uint8|传感器对应实体实例，关联传感器对应的`Entity.Instance`|
|Initialization|uint8|传感器初始化选项，门限传感器 - `0x7F`|
|Capabilities|uint8|传感器能力 <br>|
|SensorType|uint8|传感器类型 <br>具体参照 *Table 42-, Sensor Type Codes(P505)*|
|ReadingType|uint8|传感器读值类型，门限传感器 - `0x01` <br>具体参照 *Table 42-, Event/Reading Type Code Ranges(P503)*|
|SensorName|string  |传感器名称|
|AssertMask|uint16|传感器事件产生掩码，决定是否能产生事件|
|DeassertMask|uint16|传感器事件恢复掩码，决定是否能恢复事件|
|ReadingMask|uint16|传感器读值掩码，决定是否能对外显示门限|
|Unit|uint8|传感器单位|
|BaseUnit|uint8|传感器基准单位 <br>具体参照 *Table 43-, Sensor Unit Type Codes(P554)*|
|ModifierUnit|uint8|传感器单位描述符 <br>具体参照 *Table 43-, Sensor Unit Type Codes(P554)*|
|Linearization|uint8|传感器线性计算方程<br>计算表达式参照 *Section 36.3 Sensor Reading Conversion Formula*|
|M|uint8|按需配置，默认配置为`1`，传感器计算表达式M参数低8bit|
|MT|uint8|按需配置，传感器计算表达式M参数高2bit和容差|
|B|uint8|按需配置，传感器计算表达式B参数低8bit|
|BA|uint8|按需配置，传感器计算表达式B参数高2bit和准确率低6bit|
|Accuracy|uint8|按需配置，传感器准确率高6bit和传感器方向|
|RBExp|uint8|按需配置，传感器计算表达式R/B参数，R即表达式中的K2，B即表达式中的K1，各4bit|
|Analog|uint8|传感器模拟特性标志，通常配置为`1`|
|NominalReading|uint8|传感器名义读值，当前无实际含义，在数据格式范围内即可|
|NormalMaximum|uint8|传感器正常最大读值，当前无实际含义，配`0`或不配都可|
|NormalMinimum|uint8|传感器正常最小读值，配`0`或不配都可|
|MaximumReading|uint8|传感器实际最大读值，与数据格式有关 <br>若为无符号数，配置为`255` <br>若为有符号数，配置为`127`|
|MinimumReading|uint8|传感器实际最小读值，与数据格式有关 <br>若为无符号数，配置为`0` <br>若为有符号数，配置为`128`|
|UpperNonrecoverable|uint8|按需配置，传感器紧急事件上限|
|UpperCritical|uint8|按需配置，传感器严重事件上限|
|UpperNoncritical|uint8|按需配置，传感器一般事件上限|
|LowerNonrecoverable|uint8|按需配置，传感器紧急事件下限|
|LowerCritical|uint8|按需配置，传感器严重事件下限|
|LowerNonCritical|uint8|按需配置，传感器一般事件下限|
|PositiveHysteresis|uint8|按需配置，传感器上升事件恢复迟滞量|
|NegativeHysteresis|uint8|按需配置，传感器下降事件恢复迟滞量|
|Reading|uint8|传感器原始读值，引用传感器的数据源（如Scanner）读值同步|
|ReadingStatus|uint8|传感器读值状态，引用传感器的数据源（如Scanner）读值状态同步|

#### 4.2.2 配置关键点

1. 传感器类型`SensorType`严格按照**IPMI规范**中的表格配置
2. 三个`Mask`属性要与配置的门限匹配，若配置了某个门限，`Mask`相应bit需要置位
3. 注意当前`Reading`（也即原始值），数据源的范围不可超过`255`，若不满足则需要通过表达式进行一定程度的缩放，并通过传感器的表达公式进行还原

### 4.3 离散型传感器配置

离散型传感器，表征传感器的值是离散的，如：上下电状态、在位状态、运行状态等。

#### 4.3.1 配置属性

以下属性配置原则皆参照 *Section 43.2 SDR Type 02h, Compact Sensor Record(P521)*

|属性名称|属性类型|属性说明|
|--|--|--|
|OwnerId|uint8|传感器的归属Id <br>BMC - `0x20`|
|OwnerLun|uint8|传感器的归属Lun <br>owner为系统软件 - `0x00`|
|EntityId|uint8|传感器对应实体标识，关联传感器对应的`Entity.Id`|
|EntityInstance|uint8|传感器对应实体实例，关联传感器对应的`Entity.Instance`|
|Initialization|uint8|传感器初始化选项，离散传感器 - `0x63`|
|Capabilities|uint8|传感器能力|
|SensorType|uint8|传感器类型 <br>具体参照 *Table 42-, Sensor Type Codes(P505)*|
|ReadingType|uint8|传感器读值类型 <br>具体参照 *Table 42-, Event/Reading Type Code Ranges(P503)*|
|SensorName|string  |传感器名称|
|AssertMask|uint16|传感器事件产生掩码，决定是否能产生事件|
|DeassertMask|uint16|传感器事件恢复掩码，决定是否能恢复事件|
|DiscreteMask|uint16|传感器离散值掩码|
|Unit|uint8|传感器单位 <br>离散传感器 - `0xC0`|
|BaseUnit|uint8|传感器基准单位 <br>离散传感器 - `0`|
|ModifierUnit|uint8|传感器单位描述符 <br>离散传感器 - `0`|
|DiscreteType|uint8|传感器离散类型，具体类型参照 *Table 42-, Sensor Type Codes(P505)*<br>普通离散：`0`<br>数字离散：`1`|
|RecordSharing|uint16|传感器记录共享、离散参考方向，配置为`1`|
|PositiveHysteresis|uint8|传感器上升事件恢复迟滞量，离散传感器通常无应用场景，无需配置|
|NegativeHysteresis|uint8|传感器下降事件恢复迟滞量，离散传感器通常无应用场景，无需配置|
|Reading|uint16|传感器原始值，离散传感器无实际意义，无需配置|

#### 4.3.2 配置关键点

1. 传感器类型`SensorType`严格按照**IPMI规范**中的表格配置
2. 离散传感器的读值类型`ReadingType`分为两种：`02h~0Ch`、`6Fh`，需要根据离散事件的配置场景相应配置该属性
3. 离散传感器的配置与挂载的离散事件相关，注意三个`Mask`的配置需要与离散事件配置匹配

### 4.4 离散事件配置

离散事件，是针对**离散传感器**需要承载和触发的事件源，每个离散传感器最多可以监听**15**个离散事件。

#### 4.4.1 配置属性

|属性名称|属性类型|属性说明|
|--|--|--|
|Property|uint32|离散事件监听的属性，应用场景为监听方式是**组合监听** <br>共4字节，从高到低分别表示'event_dir, event_data3, event_data2, event_data1'，数据含义参照本对象对应属性的解释|
|ListenType|uint8|离散事件监听方式：<br>0：组合监听，表征SEL的三个数据和方向均来自于Property属性<br>1：独立监听，表征SEL的三个数据和方向来自于本对象属性|
|EventData1|uint8|应用场景为监听方式是**独立监听** <br>离散事件产生的数据1，数据含义参照 *29.7 Event Data Field Formats* <br>其中低4bit表示事件的偏移，配置参照 *Table 42-, Generic Event/Reading Type Codes*或*Table 42-, Sensor Type Codes*的`Offset`列|
|EventData2|uint8|应用场景为监听方式是**独立监听** <br>离散事件产生的数据2，数据含义参照 *29.7 Event Data Field Formats* <br>应用需求参照 *Table 42-, Generic Event/Reading Type Codes* 或 *Table 42-, Sensor Type Codes*中的描述，若无应用需求，配置为默认值`255`|
|EventData3|uint8|应用场景为监听方式是**独立监听** <br>离散事件产生的数据3，数据含义参照 *29.7 Event Data Field Formats* <br>应用需求参照 *Table 42-, Generic Event/Reading Type Codes* 或 *Table 42-, Sensor Type Codes*中的描述，若无应用需求，配置为默认值`255`|
|EventDir|uint8|离散事件监听的属性，应用场景为监听方式是**独立监听** <br>离散事件产生的方向：<br>0：恢复<br>非0：产生|
|Conversion|uint8|离散事件翻转标识，高4bit用于组合监听时event_data1的掩码，低4bit用来表征是否翻转事件方向：<br>1：翻转；<br>非1：不翻转|
|SensorObject|string  |离散事件关联的离散传感器，当IPMI SEL产生或者恢复时体现在当前传感器的健康状态以及SEL上|

#### 4.4.2 配置关键点
1. 监听方式无固定要求，可以根据场景任意选择。若选择组合监听，需要保证`Property`属性按要求进行配置，保证各个字节的数据皆按照含义正确配置；若选择独立监听，需要保证三个EventData数据及EventDir属性按照含义正确配置。
2. 离散事件实则是遵循**IPMI规范**定义的，因此需要严格参照**IPMI规范**中的描述和定义进行配置
