init
This commit is contained in:
225
example.jsonc
Normal file
225
example.jsonc
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
{
|
||||||
|
"version": 1, // version of the protocol, major number only
|
||||||
|
"msg_type": "telemetry", // telemetry only for now
|
||||||
|
// optional, defaults to "descriptive"
|
||||||
|
//
|
||||||
|
// for strict mode, no `metadata` in fields is allowed
|
||||||
|
// all fields must be well defined in separate documentation (e.g. JSON schema)
|
||||||
|
//
|
||||||
|
// for descriptive mode, everything should self contained (like unit, sample interval, etc.)
|
||||||
|
"mode": "descriptive",
|
||||||
|
"dev_id": "148413b4-c352-49a9-9c48-9d15276a99e7", // uuid-v4, unique for each device
|
||||||
|
"dev_type": "device_type_name",
|
||||||
|
// "dev_type field supports:
|
||||||
|
// string: designated by a unique string
|
||||||
|
// {"type_id": "148413b4-c352-49a9-9c48-9d15276a99e7"} // uuid-v4, unique for each device type
|
||||||
|
// {"type_name": "device_type_name"} // unique string, same as the string above
|
||||||
|
"timestamp": 1715145600, // UNIX timestamp in seconds
|
||||||
|
// timestamp fields supports:
|
||||||
|
// number: UNIX timestamp in seconds (default)
|
||||||
|
// {"unix_ns": 1715145600000000000}
|
||||||
|
// {"unix_us": 1715145600000000}
|
||||||
|
// {"unix_ms": 1715145600000}
|
||||||
|
// {"unix_s": 1715145600} // same as the number above
|
||||||
|
// {"iso8601": "2025-01-01T00:00:00Z"}
|
||||||
|
"fields": [
|
||||||
|
// note the name of the field must be unique in the array
|
||||||
|
// discrete fields
|
||||||
|
{
|
||||||
|
// `id` MUST be unique in the `fields` array
|
||||||
|
// should be ASCII string, no whitespace, no special characters, only underscore is allowed
|
||||||
|
"id": "field_1",
|
||||||
|
"value": "field_value", // string, number, boolean or enum value
|
||||||
|
// field specific metadata
|
||||||
|
"metadata": {
|
||||||
|
// required
|
||||||
|
// primitive types are
|
||||||
|
//
|
||||||
|
// type Primitive = number | string | boolean | enum
|
||||||
|
// where `enum` is new type alias of number with well defined values
|
||||||
|
// type DataType = Primitive |
|
||||||
|
// [Primitive] | // array
|
||||||
|
// {v: [Primitive], t: [Timestamp]} // irregular
|
||||||
|
//
|
||||||
|
// - `null` is not allowed
|
||||||
|
// - nesting (array of array or irregular of array) is not allowed
|
||||||
|
"data_type": "string",
|
||||||
|
// optional
|
||||||
|
// timestamp of the time of sampling
|
||||||
|
// which might differ from the timestamp of uplink message
|
||||||
|
// if not provided, the timestamp of uplink message is used
|
||||||
|
"timestamp": 1715145600,
|
||||||
|
// optional
|
||||||
|
// recommended to use UCUM (unified code for units of measure)
|
||||||
|
// but arbitrary string is supported
|
||||||
|
"unit": "unit_name",
|
||||||
|
// optional
|
||||||
|
// confidence of sampling, 0-1, 1 means 100% confidence
|
||||||
|
"confidence": 0.95,
|
||||||
|
// optional
|
||||||
|
// user defined fields (arbitrary key-value pairs)
|
||||||
|
"user": {
|
||||||
|
"user_defined_field_1": "user_defined_value_1",
|
||||||
|
"user_defined_field_2": "user_defined_value_2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// batch fields, for continuous data
|
||||||
|
{
|
||||||
|
"id": "field_2", // unique string
|
||||||
|
"value": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
], // array of numbers, strings, booleans or enum values
|
||||||
|
"metadata": {
|
||||||
|
// required
|
||||||
|
// "array<number>", "array<string>", "array<boolean>", or "array<enum:identifier>"
|
||||||
|
// no nesting is allowed
|
||||||
|
"data_type": "array<number>",
|
||||||
|
"timestamp": 1715145600, // timestamp of the time of sampling
|
||||||
|
"sample_interval": 0.5, // sample interval in seconds, 0.5 means 2 samples per second
|
||||||
|
// sample_interval fields also supports:
|
||||||
|
// {"ms": 0, "s": 0, "m": 0, "h": 0, "d": 0, "w": 0}
|
||||||
|
// the total sample interval is the sum of each field's sample interval in each unit
|
||||||
|
// optional
|
||||||
|
// recommended to use UCUM (unified code for units of measure)
|
||||||
|
// but arbitrary string is supported
|
||||||
|
"unit": "unit_name",
|
||||||
|
// optional
|
||||||
|
// array of confidence, or single scalar confidence
|
||||||
|
// confidence of each sample, 0-1, 1 means 100% confidence
|
||||||
|
// if it's array, its length must be same as the length of the value array
|
||||||
|
"confidence": [
|
||||||
|
0.95,
|
||||||
|
0.95,
|
||||||
|
0.95
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// batch fields, with enum
|
||||||
|
{
|
||||||
|
"id": "air_quality",
|
||||||
|
// interpreted as:
|
||||||
|
// good, good, moderate, good, unhealthy, very_unhealthy, hazardous
|
||||||
|
// for each hour past from `timestamp`, the value is sampled
|
||||||
|
"value": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
// refer to global enum definitions in `root.metadata.enums`
|
||||||
|
"data_type": "array<enum:air_quality>",
|
||||||
|
"timestamp": 1715145600,
|
||||||
|
// indicate sample interval in 1 hour
|
||||||
|
"sample_interval": {
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// irregular batch fields, with inline enum
|
||||||
|
{
|
||||||
|
"id": "water_quality",
|
||||||
|
// the length of v and t must be the same
|
||||||
|
"value": {
|
||||||
|
"v": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
// any legal timestamp format is supported
|
||||||
|
"t": [
|
||||||
|
1715145600,
|
||||||
|
1715145600,
|
||||||
|
1715145600,
|
||||||
|
1715145600,
|
||||||
|
1715145600,
|
||||||
|
1715145600
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
// refer to local enum definitions in current `metadata.enum`
|
||||||
|
"data_type": "irregular<enum:this>",
|
||||||
|
"enum": {
|
||||||
|
"good": 1,
|
||||||
|
"moderate": 2,
|
||||||
|
"bad": 3
|
||||||
|
},
|
||||||
|
"timestamp": 1715145600
|
||||||
|
// `sample_interval` would be ignored for irregular field
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// an example of sensor with invalid reading
|
||||||
|
{
|
||||||
|
"id": "temperature",
|
||||||
|
"value": 0,
|
||||||
|
"metadata": {
|
||||||
|
// optional
|
||||||
|
// any UTF-8 string is allowed
|
||||||
|
// data consumer would decide whether or how to display this label
|
||||||
|
"label": "温度",
|
||||||
|
"data_type": "number",
|
||||||
|
// required when error occurs, SHOULD NOT appear in non-error cases
|
||||||
|
// defaults to 0 for non-error cases
|
||||||
|
//
|
||||||
|
// well-defined error codes are in separate documentation
|
||||||
|
"error_code": 1001,
|
||||||
|
// optional
|
||||||
|
// a custom error message
|
||||||
|
"error_msg": "sensor disconnected",
|
||||||
|
"confidence": 0,
|
||||||
|
"unit": "Cel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// message level metadata
|
||||||
|
"metadata": {
|
||||||
|
// optional
|
||||||
|
// global enum definitions
|
||||||
|
"enums": [
|
||||||
|
{
|
||||||
|
// unique string in enums array
|
||||||
|
"id": "air_quality",
|
||||||
|
"value": {
|
||||||
|
"good": 1,
|
||||||
|
"moderate": 2,
|
||||||
|
"unhealthy": 3,
|
||||||
|
"very_unhealthy": 4,
|
||||||
|
"hazardous": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// optional
|
||||||
|
"location": {
|
||||||
|
"coordinates": [
|
||||||
|
24.123456,
|
||||||
|
120.123456
|
||||||
|
], // latitude and longitude in degrees
|
||||||
|
// optional, defaults to "gcj02"
|
||||||
|
"coordinate_system": "wgs84", // "wgs84", "gcj02", "bd09"
|
||||||
|
// optional
|
||||||
|
"accuracy": 10, // accuracy in meters
|
||||||
|
// optional
|
||||||
|
"altitude": 100 // altitude in meters
|
||||||
|
},
|
||||||
|
// optional
|
||||||
|
// battery in percentage, 0-100
|
||||||
|
"battery": 99,
|
||||||
|
// optional,
|
||||||
|
// for each sample, increase by 1
|
||||||
|
// defaults to uint32 cyclic counter
|
||||||
|
"seq": 12345,
|
||||||
|
"user": {
|
||||||
|
"user_defined_global_field_1": "user_defined_global_value_1",
|
||||||
|
"user_defined_global_field_2": "user_defined_global_value_2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
338
schema.json
Normal file
338
schema.json
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://example.com/telemetry.schema.json",
|
||||||
|
"title": "Telemetry Message",
|
||||||
|
"description": "Schema describing a telemetry message exchanged by devices.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"version": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"description": "Protocol semantic version (integer)."
|
||||||
|
},
|
||||||
|
"msg_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"telemetry"
|
||||||
|
],
|
||||||
|
"description": "Currently only the literal string 'telemetry' is supported."
|
||||||
|
},
|
||||||
|
"dev_id": {
|
||||||
|
"$ref": "#/$defs/uuid"
|
||||||
|
},
|
||||||
|
"dev_type": {
|
||||||
|
"description": "Device type identifier (string or one-of helper objects).",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"type_id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"type_id": {
|
||||||
|
"$ref": "#/$defs/uuid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"type_name"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"type_name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"$ref": "#/$defs/timestamp"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Array of discrete or batch field objects.",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/discrete_field"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/batch_field"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enum": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/enum_definition"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"$ref": "#/$defs/location"
|
||||||
|
},
|
||||||
|
"battery": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 100,
|
||||||
|
"description": "Battery percentage (0-100)."
|
||||||
|
},
|
||||||
|
"sqe": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 4294967295,
|
||||||
|
"description": "Sample sequence counter (uint32)."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"msg_type",
|
||||||
|
"dev_id",
|
||||||
|
"dev_type",
|
||||||
|
"timestamp",
|
||||||
|
"fields"
|
||||||
|
],
|
||||||
|
"$defs": {
|
||||||
|
"uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
|
||||||
|
"description": "UUID v4 string."
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"description": "UNIX epoch (seconds) or an object with a single alternative timestamp representation.",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
"maxProperties": 1,
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"unix_ns": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"unix_us": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"unix_ms": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"unix_s": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"iso8601": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sample_interval": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"description": "Interval in seconds."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"ms": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"m": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"h": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"d": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"w": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"confidence": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"discrete_field": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"data_type",
|
||||||
|
"value",
|
||||||
|
"timestamp"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"data_type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"$ref": "#/$defs/timestamp"
|
||||||
|
},
|
||||||
|
"unit": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"confidence": {
|
||||||
|
"$ref": "#/$defs/confidence"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"batch_field": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"array_type",
|
||||||
|
"value",
|
||||||
|
"timestamp"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"array_type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"$ref": "#/$defs/timestamp"
|
||||||
|
},
|
||||||
|
"sample_interval": {
|
||||||
|
"$ref": "#/$defs/sample_interval"
|
||||||
|
},
|
||||||
|
"unit": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"confidence": {
|
||||||
|
"$ref": "#/$defs/confidence"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enum_definition": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"identifier",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"identifier": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"coordinates"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"coordinates": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 2,
|
||||||
|
"maxItems": 2,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": -90,
|
||||||
|
"maximum": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"minimum": -180,
|
||||||
|
"maximum": 180
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"coordinate_system": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"wgs84",
|
||||||
|
"gcj02",
|
||||||
|
"bd09"
|
||||||
|
],
|
||||||
|
"default": "gcj02"
|
||||||
|
},
|
||||||
|
"accuracy": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"altitude": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user