iot/docs/host-mqtt-jiaohu.md
2023-06-14 19:41:32 +08:00

9.3 KiB
Raw Blame History

交互流程数据格式说明

主题说明

system/upstream qos = 1

用于主机注册到平台

host/upstream/$uuid qos = 1

用于主机向平台汇报数据

host/downstream/$uuid qos = 2

用于平台向主机下发所有的指令信息

需要注意的点

1. 主机的uuid是采用主动发现的机制因此host主机在启动时需要先subscribe主题: host/downstream/${uuid}

register主机注册会话

  1. 请求: 设备端向主题system/upstream发送注册信息
{
	"method": "register",
    "params": {
      "uuid": "$uuid",
      "os_version": "系统版本",
    }
}
  1. 响应: host/downstream/$uuid

t = 0

  {
  "code": 0 | 1, // 0表示失败1表示成功
  // 内容 
  "m": "$bytes"
}

create_session主机注册会话

register的时候设备端向主题host/upstream/${uuid}发送注册信息由于topic里面已经携带了主机标识因此body里面不需要$uuid, 该信息格式如下:

{
	"method": "create_session",
    "params": {
      "pub_key": "该客户端自己生成的公钥"
    }
}

其中,pub_key表示客户端自身的公钥该公钥用于与服务端交换aes密钥。

需要注意,这里的交互逻辑有变更(topic: host/downstream/$uuid)

  1. 当主机未激活时,返回: #{<<"a">> => false, <<"aes">> => <<"">>},
  2. 当主机已经激活时,返回: #{<<"a">> => true, <<"aes">> => Aes}
  3. 当主机超过一定的时间没有收到任何返回的时候需要重试执行create_session操作

t = 10

{
	"a": true/false, // 表示是授权还是拒绝授权
	"aes": "", // 如果a字段为true表示服务端允许授权该aes为一个加密字符串以后的通信服务端和设备端都使用该aes密钥进行加解密。
}

主机授权消息格式

t = 8


// 数据采用之前协商的aes加密

{
  "auth": true/false, // true表示授权此时aes的值不为空false表示取消授权
  "aes": "",
  "reply": {
    "topic": "", // 主机端操作成功后需要回写的topic名称
    "assoc": "" // 关联的信息,回写的时候需要带上
  }
}

// 回写的消息格式, 其中topic为: reply.topic的值

{
  "code": 0 | 1, // 0表示操作失败1表示成功
  message: "",
  assoc: "下发给你值"
}

数据上传结构

设备端在采集到数据之后会向topic为host/upstream/$uuid发送消息,消息格式如下:

{
	"methods": "data",
	"params": "$bytes"
}

其中params代表具体的采集信息,这部分数据通过与服务端交互商量的: base64:encode(aes加密),加密之前是一个列表,列表里面的数据格式如下:

[
	{
		"service_name": "从该设备端的哪个服务采集的数据",
		"node_name": "节点名称", insert到influxdb的时候就是表名
		"at": int, 精确到毫秒
		// 该微服务采集的数据是一个包含map的列表类型map的内容可以由微服务自己指定
		// 目前一般的格式是"metric-name": $value样式的数据
		"fields": [
			{
				"name1": "test"
				"name2": 124,
				"name3": false,
				"device_id": $uuid 非设备产生的device_id为空
			}
		],
		// 微服务自身可以生成tag用于微服务指定自己的一些性质目前使用得不多以后可以扩展
		// 是一个map[string]string类型的数据
		"tags": {
			"tag1": "value1",
			"tag2", "value2"
		}
		// todo 在insert数据到influxdb的时候需要增加service_name + host_uuid
	}
]

命令下发结构

命令下发,用于服务端或者其他的系统,通过调用接口,向设备端发送消息,设备端会监听host/downstream/$uuid的消息。 服务端在发送之前应先用该客户端的aes密钥进行加密将加密之后的二进制数据发送到该topic。 TODO 命令下发是需要增加当前的时间戳host主机用来协调任务的一致性

加密前的消息结构如下: // 消息类型,目前支持四种消息类型: // 1代表参数下发就是向该设备端的微服务发送消息,该消息会辗转发送给微服务进行处理比如设置modbus微服务的波特率等消息 // 2代表采集向下发比如设置某个设备短上的modbus微服务采集某个地址的数据 // 3代表下发微服务文件。 // 4代表下发数据流图这个指令用于设置设备端上各个微服务之间的逐句流转。

占用数据项的第一个字节

"t": 1|2|3|4,

{	
	// 针对不同的命令类型,这个字段里的`to`和`m`数据有所不同,具体在下面的小节描述
    // 任务id服务端在下发数据的时候需要生成一个唯一的uuid
    // 用于标识一个任务
    "t_id": "任务id",
    // 表示发给哪个微服务,这里是服务的标识,即服务名称
    "to":  "",
    // 命令执行的超时时间,单位为秒
    "t": 10,
    // 实际内容
    "m": "$bytes",
}

下面介绍几种下发类型:

参数下发的结构

对于参数下发下发内容中的m为一个map[string]interface{}结构,用于向某个微服务发送参数,具体参数内容由微服务的参数配置提供。

采集项下发的结构

采集项下发时下发内容中的m为一个[]map[string]interface{}结构的列表,每一个条目是一个采集项内容,具体采集向内容由微服务的采集项配置提供。

微服务下发的结构

在微服务下发中,to字段会被忽略可以填写空字符串而m字段为json化之后的数据json化之前结构如下

{
	"f": "微服务名",
	"v": "微服务版本"
	"k": "微服务下载的token"
	"md5": "微服务的md5值用于验证下载完整性"
	// ms表示是微服务config表示配置文件self表示efka的新版本
	"t": "ms|config|self"
	// o代表oldversion老版本如果t为ms且o不为空字符串
	// 则表示要升级微服务版本,老版本的内容会被删除和替换。
	"o": "old-version"
}

ping结构

ping结构会上传到topic为"host/upstream/$uuid", 结构体由msgpack格式编码, ping结构每隔20秒发送一次, 其中params的数据格式为: base64:encode(aes("加密"))

{
	"method": "ping",
    "params": {
        // 硬件信息目前有剩余内存剩余磁盘和cpu负载
        // 剩余内存单位为mb
      
        "memory": {
          "total": 1024, // 内存数mb
          "used": "$int" // 剩余内存数
        },
        "disk": {
          "total": 1024, //  硬盘容量GB
          "used": "$int" // 剩余硬盘内容GB
        },
      
        "cpu_load":  $float, // 浮点数
        "cpu_temperature": $float // 稳定信息
        "cpu_core": $int,
      
        "boot_time": 2000, // 启动时间
        "efka_version": "1.0.0", // 客户端版本
        "kernel_arch": "arm64", // 客户端硬件架构
        "province": "", // 所在省
        "city": "", // 所在市
        "adcode": 100, // 所在城市的编号
        "ips": [
          "ip地址1",
          "ip地址2"
        ],
        // 接口信息
        "interfaces": [
          {
            "status": 0|1, "接口状态0离线1在线"
            "name": "接口名称",
            "desc": "接口描述",
          } 
        ]
    }
}

命令下发步骤上报结构

在任务下发之后设备端会根据命令到哪个环节进行步骤上报上报的消息写入到topic为host/upstream/$uuid,上报结构如下:

{
	"method": "feedback_step",
	"params": {
        "task_id": "任务的task id",
        // sc为step code具体地
        //  0代表该任务开始了服务端创建该任务之后是这个代码
        //  1代表任务被分发了服务端向nats(mqtt)发送消息之后,是这个代码
        //  2代表任务被设备端接收到了
        //  3代表该任务已经被发送给微服务进行处理了
        //  4代表该任务已经被微服务收到了微服务正在处理
        //  5代表任务已经完成微服务已经处理完成。
        "code": $int
    }
}

有了这个步骤,最后任务超时等情况,就可以知道任务卡在哪里。

命令下发结果上报结构

任务在微服务处理完成之后,设备端会向服务端反馈任务执行的结果。该结果会写入host/upstream/$uuid,上报的结构如下:

{
	"method": "feedback_result",
	"params": {
      "task_id": "任务id",
      // unix nano类型
      "time": $int,
      // 返回的结果码0代表成功其他代表出错
      "code": $int,
      "reason": "任务执行的结果",
      "error": "错误消息当c为非0时这个字段会表示出错消息",
      // 返回任务类型1表示任务是微服务下发0代表是命令下发
      "type": 0 | 1,
    } 
}

inform结构

inform用于客户端主动通知服务端本地事情的发生比如自身的某个微服务下线了就会发送一个inform信息给服务端。 topic: host/upstream/$uuid

inform信息会发送给``, 结构如下:

{
    "method": "inform", 
    "params": {
      "at": $int64,
      // 微服务信息
      "services": [{
        "name": "微服务名称",
        "version": "微服务版本",
        "version_copy": "微服务副本",
        // 微服务是否在线0表示离线1表示在线
        "status": 0|1
      }]
    }
}