# 温度

> 冷藏温度与加热温度，由人测得或由传感器上报：三个集合，以及区分它们的是什么。

Source: https://developers.backresto.com/zh/docs/temperatures

温度是一次食品安全检查所围绕的那个测量值，而应用用三种方式记录它。它们看起来
相像，含义却不同，所以在拿其中任何一个去搭东西之前，值得先把这个区分弄对。

| 集合 | 权限范围 | 是谁做的这次测量 |
| --- | --- | --- |
| `temperature-records` | `temperature-records:read` | 一个人，在一台冰箱或冷冻柜上，在某个指定的班次里。 |
| `temperature-readings` | `temperature-readings:read` | 一个[传感器](https://developers.backresto.com/zh/docs/facilities)，自己完成，无人值守。 |
| `cooking-temperature-records` | `cooking-temperature-records:read` | 一个人，在一台加热设备上（烤箱、保温柜）。 |

这三个共用同一个[快照信封](https://developers.backresto.com/zh/docs/collections)：`id`、`deleted`、`capturedAt`、
`receivedAt`、`sequence` 以及其余字段，都摆在下文描述的 `data` 旁边。

## `temperature-records`

在一台冷链设备上做的一次手工查验。每次读数、每台设备、每个班次各一条记录。

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `timestamp` | string, **必填** | 这次读数是什么时候取的，以字符串表示的 Unix 毫秒时间戳。 |
| `value` | number, **必填** | 温度本身。 |
| `unit` | string, **必填** | 我们见过的每一条记录里都是 `CELSIUS`。请读它，而不要想当然。 |
| `shift` | string, **必填** | 它所属的那一班：`MORNING`、`EVENING`。大写。 |
| `equipmentId` | string, **必填** | 被测量的那台[设备](https://developers.backresto.com/zh/docs/facilities)。 |
| `correctiveActions` | string[] | 读数超出范围时做了什么。不需要做什么时为空。 |
| `userId` | string \| null | 取这次读数的那名员工，在应用记下了一个的时候。 |

```json
{
  "id": "48a30f0b-ccc0-4d18-8404-525b16ecaaa6",
  "collection": "temperature-records",
  "deleted": false,
  "capturedAt": "1789772570338",
  "receivedAt": "1789772802108",
  "sequence": "1",
  "data": {
    "timestamp": "1789768800000",
    "value": -14.4,
    "unit": "CELSIUS",
    "shift": "MORNING",
    "equipmentId": "84ce5c13-3237-40d4-901a-cbba59a6406f",
    "userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
  }
}
```

**`value` 是一个读数，不是一个判定。** 这条记录里没有任何东西说它是否可接受：那
取决于[设备](https://developers.backresto.com/zh/docs/facilities)上的 `min` 和 `max`，你得单独去读它们，而且餐厅可以
改动它们。一条在 -14.4 °C 取得的记录，在冰箱里是个问题，在冷冻柜里则很正常。

**`correctiveActions` 是自由文本**，在营业中用这家餐厅的语言打出来。你想数它就
数；但不要拿它建枚举。

## `temperature-readings`

同样的测量，由一个无线探头而不是一个人上报。结构相同，只是少了那两个唯有在有人
参与时才说得通的字段：没有 `shift`，也没有 `userId`。

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `timestamp` | string, **必填** | 传感器上报的时间，以字符串表示的 Unix 毫秒时间戳。 |
| `value` | number, **必填** | 温度。 |
| `unit` | string, **必填** | 同上。 |
| `equipmentId` | string, **必填** | 这个传感器看着的那台设备。 |
| `correctiveActions` | string[] | 事后由人填上，在有人对一次告警采取了行动的时候。 |

这些是按传感器自己的节奏送来的，所以一家忙碌的餐厅产出的这类记录，远多于手工
记录。请按这个量来规划你的轮询，而不是按人头。

是哪个传感器上报的，并不在这条读数上。这个关联在
[`sensors`](https://developers.backresto.com/zh/docs/facilities) 集合里，它的 `sensorEquipmentId` 指回那台设备。
留意这个名字，它不是 `equipmentId`。

## `cooking-temperature-records`

一个人测量的是加热设备，而不是制冷设备。与 `temperature-records` 完全一样，只是
它指向的是[加热设备](https://developers.backresto.com/zh/docs/facilities)。

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `timestamp` | string, **必填** | 这次读数是什么时候取的。 |
| `value` | number, **必填** | 温度。 |
| `unit` | string, **必填** | 同上。 |
| `shift` | string, **必填** | 它所属的那一班。 |
| `cookingEquipmentId` | string, **必填** | 被测量的那台加热设备，**不是** `equipmentId`。 |
| `correctiveActions` | string[] | 对一次超出范围的读数做了什么。 |
| `userId` | string \| null | 是谁取的。 |

字段名是这里唯一一处会绊倒你的差别：一个在这里去读 `equipmentId` 的客户端，悄无
声息地拿到 `undefined`，然后得到一张上面没有任何设备的图表。

## 把三个一起读

一块回答「这台冰箱今天在范围内吗」的看板，需要把 `temperature-records` 和
`temperature-readings` 按 `equipmentId` 合起来，再配上 `equipment` 上的阈值。三次
遍历，在你这边做连接。没有哪个端点会替你做这件事。

有两件事值得从一开始就做进去：

- **报表用 `capturedAt`，同步用 `receivedAt`。** 一台放在冷库里的平板会在找到信号
  时才上传，所以一次 09:00 读数的记录可能 14:00 才到。[信封那一页](https://developers.backresto.com/zh/docs/collections)
  讲了完整的来龙去脉。
- **缺席证明不了什么。** 一条缺失的读数，可能意味着这次查验被跳过了，也可能意味着
  设备还没把它传上来。不要拿这个 API 印出一个完成率，然后把它叫作合规。见
  [那条提醒](https://developers.backresto.com/zh/docs/support)。
