x
This commit is contained in:
132
READMD.md
132
READMD.md
@ -12,12 +12,12 @@ WHTP 消息由根级字段与 `fields` 数组两部分组成。根级字段描
|
|||||||
| msg_type | 是 | string | 消息类别,目前仅 `"telemetry"` |
|
| msg_type | 是 | string | 消息类别,目前仅 `"telemetry"` |
|
||||||
| mode | 否 | string | 工作模式,`"descriptive"`(默认)或 `"strict"` |
|
| mode | 否 | string | 工作模式,`"descriptive"`(默认)或 `"strict"` |
|
||||||
| dev_id | 是 | string | 设备唯一标识(UUID v4) |
|
| dev_id | 是 | string | 设备唯一标识(UUID v4) |
|
||||||
| dev_type | 否 | string / object | 设备型号标识 |
|
| dev_type | 是 | string / object | 设备型号标识 |
|
||||||
| timestamp | 是 | Timestamp | 消息生成时刻 |
|
| timestamp | 是 | Timestamp | 消息生成时刻 |
|
||||||
| fields | 是 | Field[] | 采集字段数组 |
|
| fields | 是 | Field[] | 采集字段数组 |
|
||||||
| metadata | 否 | object | 消息级元数据 |
|
| metadata | 否 | object | 消息级元数据 |
|
||||||
|
|
||||||
## 消息字段
|
## 根级字段
|
||||||
|
|
||||||
### Version (`version`)
|
### Version (`version`)
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ WHTP 消息由根级字段与 `fields` 数组两部分组成。根级字段描
|
|||||||
type DeviceType = string | { type_id: string } | { type_name: string }
|
type DeviceType = string | { type_id: string } | { type_name: string }
|
||||||
```
|
```
|
||||||
|
|
||||||
可选。用于标识设备类别或型号。支持三种写法:
|
必选。用于标识设备类别或型号。支持三种写法:
|
||||||
|
|
||||||
1. **字符串**:例如 `"device_type_name"`;与 `{ "type_name": string }` 等价
|
1. **字符串**:例如 `"device_type_name"`;与 `{ "type_name": string }` 等价
|
||||||
2. **对象** `{ "type_id": UUID }`;UUID 为设备型号的唯一标识, 由平台分配
|
2. **对象** `{ "type_id": UUID }`;UUID 为设备型号的唯一标识, 由平台分配
|
||||||
@ -64,12 +64,27 @@ type Timestamp =
|
|||||||
| { iso8601: string } // e.g. "2025-01-01T00:00:00Z"
|
| { iso8601: string } // e.g. "2025-01-01T00:00:00Z"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
所有时间字段(如顶层 `timestamp`、field 级 `timestamp`、irregular `timestamp[]`)应采用以下格式之一:
|
||||||
|
|
||||||
|
- `number`:默认解释为 UNIX 秒(UTC)
|
||||||
|
- `object`:显式指定格式,支持以下键:
|
||||||
|
- `unix_s` → UNIX 秒
|
||||||
|
- `unix_ms` → UNIX 毫秒
|
||||||
|
- `unix_us` → UNIX 微秒
|
||||||
|
- `unix_ns` → UNIX 纳秒
|
||||||
|
- `iso8601` → ISO8601 标准格式(推荐 UTC,Z 结尾)
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> `"timestamp": "2025-01-01T00:00:00Z"` 为非法, 应使用 `"timestamp": { "iso8601": "2025-01-01T00:00:00Z" }` 或 `"timestamp": 1715145600`
|
||||||
|
|
||||||
### field 字段 (`fields`)
|
### field 字段 (`fields`)
|
||||||
|
|
||||||
必填。`Field` 对象数组,数组中每个元素代表一个测量项,其 `id` 在同一条消息内必须唯一。关于 `Field` 对象的定义详见后文 "field 字段" 章节。
|
必填。`Field` 对象数组,数组中每个元素代表一个测量项,其 `id` 在同一条消息内必须唯一。关于 `Field` 对象的定义详见后文 "field 字段" 章节。
|
||||||
|
|
||||||
### 消息元数据 (`metadata`)
|
### 消息元数据 (`metadata`)
|
||||||
|
|
||||||
|
`user` 字段之外的 `metadata` 字段为已定义 (well-defined) 字段, 其定义见下文
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface MessageMetadata {
|
interface MessageMetadata {
|
||||||
enums?: EnumDefinition[];
|
enums?: EnumDefinition[];
|
||||||
@ -82,7 +97,7 @@ interface MessageMetadata {
|
|||||||
|
|
||||||
#### 全局枚举 (`enums`)
|
#### 全局枚举 (`enums`)
|
||||||
|
|
||||||
可选。全局枚举定义表,用于在字段 `metadata.data_type` 中以 `enum:<id>` 形式引用。
|
可选。全局枚举定义表,用于在字段 `fields[*].metadata.data_type` 中以 `enum:<id>` 形式引用。
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
type EnumDefinition = { id: string; value: Record<string, number> };
|
type EnumDefinition = { id: string; value: Record<string, number> };
|
||||||
@ -126,7 +141,7 @@ type EnumDefinition = { id: string; value: Record<string, number> };
|
|||||||
|
|
||||||
可选。任意键值对,为数据生产方保留的自定义信息区:
|
可选。任意键值对,为数据生产方保留的自定义信息区:
|
||||||
|
|
||||||
## field 字段
|
## 消息描述字段 (fields)
|
||||||
|
|
||||||
### 标识符 (`id`)
|
### 标识符 (`id`)
|
||||||
|
|
||||||
@ -156,31 +171,19 @@ type EnumDefinition = { id: string; value: Record<string, number> };
|
|||||||
|
|
||||||
### 元数据 (`metadata`)
|
### 元数据 (`metadata`)
|
||||||
|
|
||||||
|
field 级字段元数据, 用于描述 `value` 的类型, 采样间隔, 单位, 标签, 置信度, 错误码, 错误信息, 内联枚举, 用户自定义信息等
|
||||||
|
|
||||||
#### 数据类型 (`data_type`)
|
#### 数据类型 (`data_type`)
|
||||||
|
|
||||||
##### 枚举类型 (`enums`)
|
必填。字符串。用于描述 `value` 的类型。
|
||||||
|
|
||||||
```haskell
|
|
||||||
newtype Enum = number
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 原始型別 (`primitive`)
|
|
||||||
|
|
||||||
```haskell
|
|
||||||
type PrimitiveType = string | number | boolean
|
|
||||||
|
|
||||||
type ScalarType = string | number | boolean | Enum
|
|
||||||
type ArrayType T = T[] -- array<T>
|
|
||||||
type IrregularType T = { v: T[], t: Timestamp[] } -- irregular<T>
|
|
||||||
|
|
||||||
|
```typescript
|
||||||
type DataType =
|
type DataType =
|
||||||
| ScalarType
|
| ScalarType
|
||||||
| ArrayType ScalarType
|
| ArrayType ScalarType
|
||||||
| IrregularType ScalarType
|
| IrregularType ScalarType
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 总结
|
|
||||||
|
|
||||||
所有合法的 `data_type` 如下:
|
所有合法的 `data_type` 如下:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@ -205,9 +208,74 @@ type DataType =
|
|||||||
- `null` 和 `undefined` 是非法的
|
- `null` 和 `undefined` 是非法的
|
||||||
- 嵌套是非法的
|
- 嵌套是非法的
|
||||||
|
|
||||||
|
下面分别介绍各个类型
|
||||||
|
|
||||||
|
##### 原始型別 (`primitive`)
|
||||||
|
|
||||||
|
协议中的 **原始型别(primitive)** 直接对应于 JSON 支持的基本数据类型。所有字段的最基本取值都必须属于原始型别。
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
type PrimitiveType = string | number | boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
- `string`:任意长度的 UTF-8 文本字符串
|
||||||
|
- `number`:IEEE-754 双精度浮点数
|
||||||
|
- `boolean`:布尔值,仅允许 true 或 false(不支持 0/1 或字符串)
|
||||||
|
|
||||||
|
##### 枚举类型 (`enums`)
|
||||||
|
|
||||||
|
在本协议中,枚举类型本质上是一种特殊的 number 类型。其取值必须限定在一组预先定义的枚举值中。枚举的具体定义可以来源于:
|
||||||
|
|
||||||
|
- 全局定义:`metadata.enums`(适用于多个字段复用的场景)
|
||||||
|
- 字段内联定义:`fields[*].metadata.enum`(只对当前字段有效)
|
||||||
|
|
||||||
|
每个枚举值都必须对应唯一的数值(number)。在类型系统中,枚举类型可以视为带有标签约束的 number:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
newtype Enum = number
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 标量类型 (`scalar`)
|
||||||
|
|
||||||
|
标量类型为 `string | number | boolean | Enum` 的统称, 其定义见上文
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
type ScalarType = PrimitiveType | Enum
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 等间隔数组类型 (`array`)
|
||||||
|
|
||||||
|
本协议中的数组类型在 `field` 中的含义为 **等采样率** 的数组, 其定义为:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
type ArrayType T = T[] -- array<T>
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 非等间隔数组类型 (`irregular`)
|
||||||
|
|
||||||
|
本协议中的非等间隔数组类型在 `field` 中的含义为 **非等采样率** 或 **采样率未知** 的数组, 其定义为:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
type IrregularType T = { v: T[], t: Timestamp[] } -- irregular<T>
|
||||||
|
```
|
||||||
|
|
||||||
|
`t` 数组必须与 `v` 数组长度相同, 且 `t` 数组中的时间戳必须严格递增, 否则会被视为非法数据
|
||||||
|
|
||||||
|
等间隔数组与非等间隔数组统称为批量 (batch) 数据
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
type BatchType T = ArrayType T | IrregularType T
|
||||||
|
```
|
||||||
|
|
||||||
|
#### field 时间戳 (`timestamp`)
|
||||||
|
|
||||||
|
可选。若不存在则取 `root.timestamp` 的值; 表示该字段 **采样时刻** 的时间戳, 其类型为 `Timestamp`
|
||||||
|
|
||||||
#### 标签 (`label`)
|
#### 标签 (`label`)
|
||||||
|
|
||||||
可选。字段展示名,UTF-8 字符串,便于人机界面直观呈现。
|
可选。字段展示名,UTF-8 字符串,便于人机界面直观呈现。实际是否使用/如何使用由数据消费方决定。
|
||||||
|
|
||||||
示例:`"label": "温度"`
|
示例:`"label": "温度"`
|
||||||
|
|
||||||
@ -246,7 +314,17 @@ type DataType =
|
|||||||
type Confidence = number | number[]
|
type Confidence = number | number[]
|
||||||
```
|
```
|
||||||
|
|
||||||
数组形式 (`number[]`) 仅对数组 (等间隔/非等间隔) 有意义, 表示每个采样点的置信度, 其长度应与采样点数量相同; 若不指定, 则默认为 1
|
置信度用于表征 value 数据的可靠性,其取值类型可为单个数值(`number`)或数值数组(`number[]`),具体规则如下:
|
||||||
|
|
||||||
|
- 当 confidence 为单个数值时,表示该字段所有采样点共用相同的置信度。此形式适用于任意类型的 value(包括单点和批量数据)。
|
||||||
|
- 当 confidence 为数值数组时,表示每个采样点各自的置信度。此形式仅适用于批量数据(即 value 为数组或不等间隔序列);此时 confidence 数组长度必须与采样点数量严格一致。
|
||||||
|
|
||||||
|
置信度的取值范围为 0 至 1,其中 0 表示完全不可信,1 表示完全可信(100%)。
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> - 对于单值(scalar)数据,不应填写数组形式的置信度,若填写则无意义,解析器将会忽略
|
||||||
|
> - 对于批量数据,既可填写单一置信度(所有采样点共享),也可填写置信度数组(每个采样点单独指定)
|
||||||
|
> - 如未指定 confidence 字段,则默认所有采样点的置信度为 1
|
||||||
|
|
||||||
#### 采样间隔 (`sample_interval`)
|
#### 采样间隔 (`sample_interval`)
|
||||||
|
|
||||||
@ -303,23 +381,25 @@ type Timestamp =
|
|||||||
| { unix_ns: number }
|
| { unix_ns: number }
|
||||||
| { iso8601: string };
|
| { iso8601: string };
|
||||||
|
|
||||||
|
|
||||||
// 采样间隔
|
// 采样间隔
|
||||||
type SampleInterval = number | { ms?: number; s?: number; m?: number; h?: number; d?: number; w?: number };
|
type SampleInterval = number | { ms?: number; s?: number; m?: number; h?: number; d?: number; w?: number };
|
||||||
|
|
||||||
// 枚举定义
|
// 枚举定义
|
||||||
type EnumDefinition = { id: string; value: Record<string, number> };
|
type InlineEnum = Record<string, number>
|
||||||
|
type EnumDefinition = { id: string; value: InlineEnum };
|
||||||
|
|
||||||
// Field 元数据
|
// Field 元数据
|
||||||
interface FieldMetadata {
|
interface FieldMetadata {
|
||||||
data_type: string;
|
data_type: string;
|
||||||
timestamp?: Timestamp;
|
timestamp?: Timestamp;
|
||||||
sample_interval?: SampleInterval;
|
sample_interval?: SampleInterval; // valid only when data_type is array<T>
|
||||||
unit?: string;
|
unit?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
confidence?: number | number[];
|
confidence?: number | number[];
|
||||||
error_code?: number;
|
error_code?: number;
|
||||||
error_msg?: string;
|
error_msg?: string;
|
||||||
enum?: Record<string, number>; // inline enum when data_type === "enum:this"
|
enum?: InlineEnum; // inline enum when data_type === "enum:this"
|
||||||
user?: Record<string, any>;
|
user?: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user