拓扑关系如何管理?

在设备对接涂鸦云端时,部分子设备需通过网关中转接入。要实现此功能,子设备和网关需建立拓扑关系。本文介绍了建立拓扑关系的三种方式,详细说明了网关设备侧管理拓扑关系的协议内容,包括绑定、删除子设备,建立、删除、查询拓扑关系及通知拓扑变更等交互流程。

在设备对接涂鸦的云端过程中,一部分设备由于自身资源或硬件配置,无法直接连接云端。而是需要通过网关进行中转,由网关代理实现和云端进行数据交互,间接实现设备接入云端。这样的设备也称为子设备。

要想实现网关代理子设备接入云端,子设备和网关需要先建立关联关系,也称为 拓扑关系

方式对比

建立拓扑关系有三种方式,您可以根据实际情况,选择其中一种,并且注意不要混用。

名称适用场景接口特点
动态发现
  • 无法事先获取子设备信息,无法提前在云端注册子设备和烧录注册信息。
  • 网关能发现子设备,动态向云端注册子设备并建立拓扑。
网关绑定子设备全自动
网关建立拓扑
  • 事先获取子设备信息,并在云端注册子设备。
  • 拿到子设备注册信息后,烧录到子设备或者网关里面。
  • 网关发现子设备,调用云端接口建立拓扑关系。
建立拓扑关系半自动
平台管理
  • 事先获取子设备信息,并在云端注册子设备。
  • 在云端上建立拓扑关系。
建立拓扑关系全手动

本文主要介绍用于网关设备侧管理拓扑关系的协议内容,并详细说明每个协议。

网关绑定子设备(动态发现)

网关动态发现子设备,请求云端注册子设备并建立拓扑关系,云端返回请求结果。这对应方式对比章节的 动态发现 方式。

交互流程

拓扑关系管理

设备发送消息

设备检测到子设备连接,主动向云端发送绑定子设备消息。

topic: tylink/${deviceId}/device/sub/bind

{
    "msgId":"45lkj355123****",
    "time":1626197189600,
    "version":"1.0",
	"data":[
      {
        "productId":"a123b456****",
        "clientId":"123455asdf****"
      },
      {
        "productId":"a123b457****",
        "clientId":"453455asdf****"
      }
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起子设备绑定的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
dataArray子设备参数列表多个子设备绑定参数,子设备数量不超过 100 个。
data[].productIdString子设备的产品 ID需要绑定在子设备的产品 ID。
data[].clientIdString设备端唯一 ID此处主要用于子设备硬件的唯一标识,可以是设备的 MAC、SN 等,至少保证产品下唯一,将显示在 设备管理 > 注册 ID 字段。

设备接收消息

设备订阅接收绑定子设备消息回复。

topic: tylink/${deviceId}/device/sub/bind_response

{
    "msgId":"45lkj3551234****",
    "time":1626197189640,
    "version":"1.0",
    "code":0,
	"data":[
      {
        "productId":"a123b456****",
        "clientId":"123455****",
        "deviceId":"6c828cba434ff40c07****"
      },
      {
        "productId":"a123b457****",
        "clientId":"123456****",
        "deviceId":"6c828cba434ff40c07****"
      }
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起子设备绑定的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
codeNumber响应状态码
  • 0 代表成功,默认值。
  • 非 0 代表失败。
dataArray子设备绑定结果列表-
data[].productIdString产品 ID子设备的产品 ID。
data[].clientIdString子设备硬件的唯一表示 ID子设备的唯一标识,需保证产品下唯一。
data[].deviceIdString云端分配的唯一设备 ID同一个 clientId、同一个网关设备 ID,多次绑定只会生成同一个设备 ID,否则会重新生成一个新的设备 ID。

状态码说明

状态码说明
0默认状态,代表成功。
1001服务异常。
1002请求参数校验不合法。
1004设备不存在。
2401产品不存在。
2402网关绑定了多个设备组。
2403拓扑信息存在,子设备信息不存在。
2404授权码数量不足, 获取授权码失败。
2405获取网关设备组异常。
2406子设备重新注册时,必须先解绑。
2410同一个网关绑定子设备的数量,不能超过 2000 个。

网关删除子设备

网关通过动态发现注册的子设备,可支持网关请求云端删除对应的子设备。云端接收到该请求后,会校验并删除该子设备,同时删除网关和子设备的拓扑关系。由于是设备端发起的删除操作,针对已绑定家庭或资产的子设备,支持网关直接删除子设备。

交互流程

拓扑关系管理

设备发送消息

Topic:tylink/${deviceId}/device/sub/delete

消息内容

{
    "msgId":"45lkj355123****",
    "time":1626197189600,
    "version":"1.0",
	"data":[
      "devId123455as****",
      "devId123456ty****"
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起删除子设备的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
dataArray待删除的子设备 ID 列表子设备 ID 列表,设备数量不超过 10。

设备接收消息

Topic:tylink/${deviceId}/device/sub/delete_response

消息内容

{
    "msgId":"45lkj355123****",
    "time":1626197189640,
    "version":"1.0",
  	"code":0,
	"data":[
      "devId123455as****",
      "devId123456ty****"
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起删除拓扑关系的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
codeNumber响应状态码0 代表成功,非 0 代表失败,默认 0
dataArray被删除的子设备 ID 列表。/

状态码说明

状态码说明
0默认状态,代表成功。
1001服务异常。
1004设备记录不存在。
2407子设备列表为空。
2408子设备数量超限。

建立拓扑关系

对于已经在云端注册的子设备,拿到子设备注册信息后烧录到子设备。网关运行后动态发现子设备,请求云端建立拓扑关系,云端返回请求结果。这对应方式对比章节中的 网关建立拓扑 方式。

交互流程

拓扑关系管理

设备发送消息

topic:tylink/${deviceId}/device/topo/add

{
    "msgId":"45lkj355123****",
    "time":1626197189600,
    "version":"1.0",
	"data":[
      {
        "productId":"a123b456****",
        "deviceId":"123455asdf****",
        "sign":"adstewq35324ds****",
        "signMethod":"HmacSHA256",
        "timestamp":"16067836521"
      },
      {
        "productId":"a123b457****",
        "deviceId":"123456****",
        "sign":"adstewq35324ds****",
        "signMethod":"HmacSHA256",
        "timestamp":"16067836521"
      }
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起建立拓扑关系的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
dataArray子设备参数列表多个子设备拓扑参数, 子设备数量不能超过 100 个。
data[].productIdString子设备的产品 ID-
data[].deviceIdString子设备的设备 ID注册设备时,获取的设备 ID,云端分配的唯一 ID。
data[].signMethodString签名算法签名算法, 当前仅支持 HmacSHA256。
data[].timestampString时间戳签名时间戳,10 位秒级或 13 位毫秒级。
data[].signString签名使用 signMethod 对内容进行签名。例如,HmacSHA256(content, deviceSecret)content 的内容如:productId= a123b456****|deviceId=123455asdf****|timestamp=${签名时间戳}deviceSecret 为 涂鸦 IoT 开发平台 设备管理中展示的 DeviceSecret 字段。

设备接收消息

topic:tylink/${deviceId}/device/topo/add_response

{
    "msgId":"45lkj355123****",
    "time":1626197189640,
    "version":"1.0",
  	"code":0,
	"data":[
      {
        "productId":"a123b456****",
        "deviceId":"6c828cba434ff40c07****"
      },
      {
        "productId":"a123b457****",
        "deviceId":"6c828cba434ff40c07****"
      }
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起建立拓扑关系的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
codeNumber响应状态码
  • 0 代表成功,默认值。
  • 非 0 代表失败。
dataArray建立拓扑关系成功的结果列表。-
data[].productIdString子设备的产品 ID。-
data[].deviceIdString子设备的设备 ID。-

状态码说明

状态码说明
0默认状态,代表成功。
1001服务异常。
1004设备记录不存在。
2407子设备列表为空。
2408子设备数量超限。
2409签名验证失败。
2410同一个网关绑定子设备的数量,不能超过 2000 个。

删除拓扑关系

网关请求云端删除与指定子设备的拓扑关系,云端返回请求结果。该请求不会删除子设备。删除拓扑关系后,子设备还能和该网关或其它网关再次建立拓扑关系。

交互流程

拓扑关系管理

设备发送消息

topic:tylink/${deviceId}/device/topo/delete

{
    "msgId":"45lkj355123****",
    "time":1626197189600,
    "version":"1.0",
	"data":[
      "devId123455as****",
      "devId123456ty****"
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起删除拓扑关系的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
dataArray待删除的子设备 ID 列表子设备 ID 列表, 设备数量不超过 100 个。

设备接收消息

topic:tylink/${deviceId}/device/topo/delete_response

{
    "msgId":"45lkj355123****",
    "time":1626197189640,
    "version":"1.0",
  	"code":0,
	"data":[
      "devId123455as****",
      "devId123456ty****"
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起删除拓扑关系的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
codeNumber响应状态码
  • 0 代表成功,默认值。
  • 非 0 代表失败。
dataArray被删除的子设备 ID 列表-

状态码说明

状态码说明
0默认状态,代表成功。
1001服务异常。
1004设备记录不存在。
2407子设备列表为空。
2408子设备数量超限。

查询拓扑关系

网关请求云端查询拓扑关系,云端返回请求结果。

交互流程

拓扑关系管理

设备发送消息

topic:tylink/${deviceId}/device/topo/get

{
    "msgId":"45lkj355123****",
    "time":1626197189600,
    "version":"1.0",
	"data":{
      "startId": 0,
      "pageSize": 20, 
      "devIds":[
        "devId123455as****",
        "devId123456ty****"
      ]
    }
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起查询拓扑关系的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
codeNumber响应状态码
  • 0 代表成功,默认值。
  • 非 0 代表失败。
data.startIndexIdNumber本次查询子设备列表起始值默认为 0,从第一条开始查询。如果查询第二页, 则该值为第一页查询结果最后一条记录的索引 ID。第三页及以后,以此类推。
data.pageSizeNumber每次查询的设备数量默认及最大查询数量均为 100 个。
data.devIdsArray本次查询子设备 ID 列表子设备 ID 列表,设备数量不超过 100 个。

设备接收消息

topic:tylink/${deviceId}/device/topo/get_response

{
    "msgId":"45lkj355123****",
    "time":1626197189640,
    "version":"1.0",
  	"code":0,
	"data":[
      {
        "productId":"a123b456****",
        "deviceId":"6c828cba434ff40c074***",
        "indexId": 1
      },
      {
        "productId":"a123b457****",
        "deviceId":"6c828cba434ff40c074***",
        "indexId": 2
      }
    ]
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID发起拓扑关系查询的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,上报和订阅消息通过该值建立应答关系。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
codeNumber响应状态码
  • 0 代表成功,默认值。
  • 非 0 代表失败。
dataArray子设备列表-
data[].productIdString子设备的产品 ID-
data[].deviceIdString子设备的设备 ID-
data[].indexIdNumber索引 ID每页最后一条记录的索引 ID,作为下一页查询的 startIndexId

状态码说明

状态码说明
0默认状态,代表成功。
1001服务异常。
1004设备不存在。
2408子设备数量超限。

通知拓扑关系变更

云端变更拓扑关系,如往拓扑关系中新增子设备,或把子设备从拓扑关系中删除,发送消息通知网关。

交互流程

拓扑关系管理

设备接收消息

topic:tylink/${deviceId}/device/topo/change

{
    "msgId":"45lkj355123****",
    "time":1626197189600,
	"data":{
      "addDevIds":[
           "devId123asdf****",
           "devId456tyiy****"
        ],
       "delDevIds":[
           "devId789****",
           "devIdyiy****"
        ]
    }
}

参数说明

参数类型说明必选备注
${deviceId}String设备 ID拓扑关系发生变更的网关设备 ID。
versionString协议版本默认 1.0,当前仅支持 1.0。
msgIdString消息 ID总长度不超过 32 位的字符,消息的唯一 ID。
timeNumber消息时间戳消息发送时的 Unix 时间戳,10 位秒级或 13 位毫秒级。
dataobject业务数据-
data.addDevIdsArray新增的子设备 ID 列表子设备数量不超过 100 个。
data.delDevIdsArray删除的子设备 ID 列表子设备数量不超过 100 个。
<think>我们正在讨论如何在QGIS中创建自定义的拓扑关系连线。根据用户之前的问题,他们希望以地图为背景展示总部-分公司-站端的拓扑结构。现在用户具体询问如何创建自定义的拓扑关系连线。 关键点:自定义拓扑关系连线意味着用户需要根据特定的规则(例如,总部连接分公司,分公司连接站点)来绘制线要素,这些线要素将表示节点之间的逻辑关系。 步骤: 1. 准备节点数据(点图层):总部、分公司、站点。 2. 创建一个线图层来表示连接关系。 3. 在编辑模式下绘制连接线,或者通过编程方式生成连接线(例如,根据节点之间的关联表)。 方法一:手动绘制(适合少量连线) - 创建新的线图层(例如,Shapefile线图层)。 - 添加字段来存储连接关系(如:起点ID、终点ID、关系类型等)。 - 启用编辑模式,使用捕捉工具(参考引用[2])来精确连接点要素。 - 绘制每条连接线(总部到分公司,分公司到站点)。 方法二:通过关联表自动生成连线(适合大量数据) - 准备一个关联表(CSV或数据库表),包含三列:起点ID、终点ID、关系类型(如“总部-分公司”、“分公司-站点”)。 - 使用点图层的坐标关联表,通过QGIS的“点集连线”工具(Points to Path)或“几何生成器”来创建连线。 详细步骤(方法二): 1. 确保每个点图层都有一个唯一标识符(ID)字段。 2. 创建关联表(例如,relations.csv): start_id, end_id, relation_type 1, 10, "总部-分公司" 2, 20, "分公司-站点" 3. 将关联表导入QGIS(作为非空间表)。 4. 使用“虚拟层”或“连接”工具将关联表与点图层连接,以获取起点终点的坐标。 5. 使用“几何生成器”或“处理工具箱”中的“点集连线”工具生成线。 具体操作(使用虚拟层): - 菜单:图层 -> 添加/编辑虚拟图层... - 输入查询语句,例如: SELECT r.relation_type, make_line(start_point.geometry, end_point.geometry) AS geometry FROM relations AS r JOIN 总部 AS start_point ON r.start_id = start_point.id JOIN 分公司 AS end_point ON r.end_id = end_point.id WHERE r.relation_type = '总部-分公司' UNION ALL SELECT r.relation_type, make_line(start_point.geometry, end_point.geometry) AS geometry FROM relations AS r JOIN 分公司 AS start_point ON r.start_id = start_point.id JOIN 站点 AS end_point ON r.end_id = end_point.id WHERE r.relation_type = '分公司-站点' - 这样会生成一个虚拟的线图层,然后可以将其导出为永久图层(如Shapefile)。 方法三:使用“点集连线”工具(Processing Toolbox) - 需要将关联表与点图层连接,生成一个包含起点终点坐标的点图层(每个点出现两次,一次作为起点,一次作为终点,并标记角色)。 - 然后使用“点集连线”工具,按连接关系分组,顺序字段设置为连接顺序(通常为12,表示起点终点)。 注意:在绘制连线时,使用捕捉功能(引用[2])可以确保线精确连接到点。在编辑线图层时,确保启用捕捉,并设置合适的捕捉容差(如10像素),这样在绘制线时,鼠标靠近点就会自动吸附。 样式设置:生成连线后,可以根据“关系类型”字段设置不同的样式(如颜色、线型)。 相关问题: 1. 如何将拓扑结构导出为Web交互式地图? 2. QGIS中如何实现动态拓扑关系(实时更新连接状态)? 3. 能否用QGIS分析总部到站点的最短路径? 4. 如何批量导入地理坐标数据创建拓扑节点? 5. 如何优化拓扑连线的显示效果(如添加箭头)? 现在,根据这些思路,编写回答。</think>### 在QGIS中创建自定义拓扑关系连线的详细步骤 #### 1. **准备数据** - **点图层**:创建包含拓扑节点的矢量点图层(如总部、分公司、站点) - 每个点需包含唯一ID类型字段(如`node_id`, `node_type`) - **关联表**:创建CSV或Excel文件定义连接关系: ```csv start_id,end_id,relation_type HQ001,BranchA,管理 BranchA,SiteX,支持 ``` #### 2. **创建拓扑连线图层** ##### 方法一:手动绘制(适合少量连线) 1. 创建新线图层:`图层菜单 > 创建图层 > 新建Shapefile图层` - 几何类型:线 - 添加字段:`start_id`, `end_id`, `relation_type` 2. 启用编辑模式:右键图层 → 切换编辑 3. **启用捕捉工具**: ![捕捉工具栏](https://qgis.org/static/docs/images/toolbars/snapping_toolbar.png) - 设置捕捉容差(推荐10-15像素)[^2] - 勾选目标图层(总部/分公司/站点点图层) 4. 绘制连线: - 使用`添加线要素`工具 - 起点捕捉到源节点 → 终点捕捉到目标节点 - 属性窗口填写连接关系字段 ##### 方法二:自动生成(适合批量连线) 1. 导入关联表:`图层菜单 > 添加图层 > 添加文本数据层` 2. 使用虚拟层生成连线: ```sql SELECT r.relation_type, make_line(hq.geometry, branch.geometry) AS geometry FROM relations r JOIN headquarters hq ON r.start_id = hq.node_id JOIN branches branch ON r.end_id = branch.node_id ``` - 执行路径:`数据库菜单 > DB管理器 > 虚拟图层`[^1] #### 3. **设置拓扑样式** - **按关系类型差异化显示**: 1. 线图层属性 → 符号化 → 分类 2. 值字段选择`relation_type` 3. 为不同关系设置样式: - 管理关系:红色实线(宽度1.5mm) - 支持关系:蓝色虚线(宽度1.0mm) - **添加流向箭头**: ```mermaid graph LR 符号系统 --> 线符号图层 --> 添加箭头标记 ``` 1. 符号选择`箭头` 2. 设置箭头位置:`在线终点` 3. 调整箭头大小(推荐3-5mm) #### 4. **拓扑验证与优化** - **检查连接准确性**: - 使用`拓扑检查器`:`矢量菜单 > 拓扑检查器` - 添加规则:`线要素必须连接点要素` - **动态更新**: - 启用`自动捕捉`:捕捉工具栏 → 启用拓扑编辑 - 移动节点时连线自动跟随[^2] #### 5. **高级应用:基于规则生成** ```python # 使用PyQGIS自动生成连接线(示例) for hq in headquarters.getFeatures(): for branch in branches.getFeatures(): if hq['region'] == branch['region']: # 自定义连接规则 line = QgsFeature(lines_layer.fields()) line.setGeometry(QgsGeometry.fromPolyline([ hq.geometry().asPoint(), branch.geometry().asPoint() ])) lines_layer.addFeature(line) ``` - 执行路径:`Python控制台 > 编辑器` > **关键提示**: > - 捕捉容差设置直接影响连接精度,需根据地图比例调整[^2] > - 复杂拓扑建议使用`PostGIS`数据库存储关系数据[^1] > - 批量操作优先选择`处理工具箱`中的`点集连线`工具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IoT砖家涂拉拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值