鸿蒙实战开发:【分布式软总线组件】

news2025/1/11 16:54:23

简介

现实中多设备间通信方式多种多样(WIFI、蓝牙等),不同的通信方式使用差异大,导致通信问题多;同时还面临设备间通信链路的融合共享和冲突无法处理等挑战。分布式软总线实现近场设备间统一的分布式通信管理能力,提供不区分链路的设备间发现连接、组网和传输能力,主要功能如下:

  • 发现连接:提供基于Wifi、蓝牙等通信方式的设备发现连接能力。
  • 设备组网:提供统一的设备组网和拓扑管理能力,为数据传输提供已组网设备信息。
  • 数据传输:提供数据传输通道,支持消息、字节、流、文件的数据传输能力。

业务方通过使用分布式软总线提供的API实现设备间的高速通信,不用关心通信细节,进而实现业务平台的高效部署与运行能力。

系统架构


图 1 分布式软总线组件架构图

约束

  • 组网设备需在同一局域网中 或者 距离相近的近场设备间。
  • 组网之前,需先完成设备绑定,绑定流程参见安全子系统中说明。
  • 传输完成数据收发之后,业务要主动关闭会话,释放资源。

说明

使用说明

须知: 使用跨设备通信时,必须添加权限ohos.permission.DISTRIBUTED_DATASYNCohos.permission.DISTRIBUTED_SOFTBUS_CENTER,该权限类型为 dangerous

设备主动发现手机时,手机需打开超级终端的允许被“附近设备”发现开关(设置-超级终端-我的设备-允许被发现-附近设备),才能被设备发现。

1、发现

  • 发布流程
  1. 上层应用需要对外发布自身能力时,调用服务发布接口发布自身能力。

    // 发布回调
    typedef struct {
        /** Callback for publish result */
        void (*OnPublishResult)(int publishId, PublishResult reason);
    } IPublishCb;
    
    // 发布服务
    int32_t PublishLNN(const char *pkgName, const PublishInfo *info, const IPublishCb *cb);
    
  2. 上层应用不再需要对外发布自身能力时,调用StopPublishLNN接口注销服务。

    // 注销服务
    int32_t StopPublishLNN(const char *pkgName, int32_t publishId);
    
  • 发现流程
  1. 上层应用需要发现特定能力设备时,调用发现接口启动发现。

    // 发现回调
    typedef struct {
        /** Callback that is invoked when a device is found */
        void (*OnDeviceFound)(const DeviceInfo *device);
        /** Callback for a subscription result */
        void (*OnDiscoverResult)(int32_t refreshId, RefreshResult reason);
    } IRefreshCallback;
    
    // 发现服务
    int32_t RefreshLNN(const char *pkgName, const SubscribeInfo *info, const IRefreshCallback *cb);
    
  2. 当软总线发现到设备时,通过回调接口通知业务所发现的设备信息。

  3. 上层应用不再需要发现时,调用StopRefreshLNN接口停止设备发现。

    // 停止发现
    int32_t StopRefreshLNN(const char *pkgName, int32_t refreshId);
    

2、组网

  1. 发起组网请求,携带组网连接地址信息,并且提供组网执行结果回调函数。

    // 组网连接地址
    typedef struct {
        ConnectionAddrType type;
        union {
            struct BrAddr {
                char brMac[BT_MAC_LEN];
            } br;
            struct BleAddr {
                char bleMac[BT_MAC_LEN];
                uint8_t udidHash[UDID_HASH_LEN];
            } ble;
            struct IpAddr {
                char ip[IP_STR_MAX_LEN];
                uint16_t port; 
            } ip;
        } info;
        char peerUid[MAX_ACCOUNT_HASH_LEN];
    } ConnectionAddr;
    
    // 组网连接地址类型
    typedef enum {
        CONNECTION_ADDR_WLAN = 0,
        CONNECTION_ADDR_BR,
        CONNECTION_ADDR_BLE,
        CONNECTION_ADDR_ETH,
        CONNECTION_ADDR_MAX
    } ConnectionAddrType;
    
    // 组网请求执行结果回调
    typedef void (*OnJoinLNNResult)(ConnectionAddr *addr, const char *networkId, int32_t retCode);
    
    // 发起组网请求
    int32_t JoinLNN(const char *pkgName, ConnectionAddr *target, OnJoinLNNResult cb);
    
  2. 等待组网结果,JoinLNN()返回成功表示软总线接受了组网请求,组网结果通过回调函数通知业务;组网回调函数中addr参数内容和JoinLNN()的入参互相匹配;retCode如果为0,表示组网成功,此时networkId为有效值,后续传输、退网等接口均需使用该参数;retCode如果不为0,表示组网失败,此时networkId为无效值。

  3. 使用传输相关接口进行数据传输。

  4. 发送退网请求,携带组网成功后返回的networkId,并且提供退网执行结果回调。

    // 退网执行结果回调
    typedef void (*OnLeaveLNNResult)(const char *networkId, int32_t retCode);
    
    // 退网请求
    int32_t LeaveLNN(const char *pkgName, const char *networkId, OnLeaveLNNResult cb);
    
  5. 等待退网完成,OnLeaveLNNResult()的networkId和退网请求接口中的networkId互相匹配;retCode为0表示退网成功,否则退网失败。退网成功后,networkId变为无效值,后续不应该被继续使用。

  6. 使用节点(即设备)注册和注销接口,监听网络中节点状态变化等事件。

    // 事件掩码
    #define EVENT_NODE_STATE_ONLINE 0x1
    #define EVENT_NODE_STATE_OFFLINE 0x02
    #define EVENT_NODE_STATE_INFO_CHANGED 0x04
    #define EVENT_NODE_STATUS_CHANGED 0x08
    #define EVENT_NODE_STATE_MASK 0xF
    
    // 节点信息
    typedef struct {
        char networkId[NETWORK_ID_BUF_LEN];
        char deviceName[DEVICE_NAME_BUF_LEN];
        uint16_t deviceTypeId;
    } NodeBasicInfo;
    
    // 节点状态事件回调
    typedef struct {
        uint32_t events; // 组网事件掩码
        void (*onNodeOnline)(NodeBasicInfo *info);   // 节点上线事件回调
        void (*onNodeOffline)(NodeBasicInfo *info);  // 节点下线事件回调
        void (*onNodeBasicInfoChanged)(NodeBasicInfoType type, NodeBasicInfo *info); // 节点信息变化事件回调
        void (*onNodeStatusChanged)(NodeStatusType type, NodeStatus *status); // 设备运行状态变化事件回调
    } INodeStateCb;
    
    //  注册节点状态事件回调
    int32_t RegNodeDeviceStateCb(const char *pkgName, INodeStateCb *callback);
    
    // 注销节点状态事件回调
    int32_t UnregNodeDeviceStateCb(INodeStateCb *callback);
    

3、传输

  1. 创建Socket。

    typedef struct {
        char *name;                 // 本端Socket名称
        char *peerName;             // 对端Socket名称
        char *peerNetworkId;        // 对端Socket的网络ID
        char *pkgName;              // 调用者包名
        TransDataType dataType;     // 传输的数据类型,需要与发送方法一致
    } SocketInfo;
    
    // 创建Socket
    int32_t Socket(SocketInfo info);
    
  2. 服务端启动监听,客户端进行绑定。

    // Socket回调函数
    typedef struct {
        void (*OnBind)(int32_t socket, PeerSocketInfo info);
        void (*OnShutdown)(int32_t socket, ShutdownReason reason);
        void (*OnBytes)(int32_t socket, const void *data, uint32_t dataLen);
        void (*OnMessage)(int32_t socket, const void *data, uint32_t dataLen);
        void (*OnStream)(int32_t socket, const StreamData *data, const StreamData *ext, const StreamFrameInfo *param);
        void (*OnFile)(int32_t socket, FileEvent *event);
        void (*OnQos)(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount);
    } ISocketListener;
    
    typedef enum {
        QOS_TYPE_MIN_BW,            // 最小带宽
        QOS_TYPE_MAX_LATENCY,       // 最大建链时延
        QOS_TYPE_MIN_LATENCY,       // 最小建链时延
        QOS_TYPE_MAX_WAIT_TIMEOUT,  // 最大超时时间
        QOS_TYPE_MAX_BUFFER,        // 最大缓存
        QOS_TYPE_FIRST_PACKAGE,     // 首包大小
        QOS_TYPE_MAX_IDLE_TIMEOUT,  // 最大空闲时间
        QOS_TYPE_TRANS_RELIABILITY, // 传输可靠性
        QOS_TYPE_BUTT,
    } QosType;
    
    typedef struct {
        QosType qos;
        int32_t value;
    } QosTV;
    
    // 监听Socket,由服务端开启。
    int32_t Listen(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener);
    
    // 绑定Socket,由客户端开启。
    int32_t Bind(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener);
    
  3. 通过Socket向对端设备发送数据。

    // 发送字节数据
    int32_t SendBytes(int32_t socket, const void *data, uint32_t len);
    // 发送消息数据
    int32_t SendMessage(int32_t socket, const void *data, uint32_t len);
    // 发送流数据
    int32_t SendStream(int32_t socket, const StreamData *data, const StreamData *ext, const StreamFrameInfo *param);
    // 发送文件
    int32_t SendFile(int32_t socket, const char *sFileList[], const char *dFileList[], uint32_t fileCnt);
    
  4. 关闭Socket。

    // 关闭Socket
    void Shutdown(int32_t socket);
    

    鸿蒙OpenHarmony知识已更新←前往

7ebde29c85a3faa0ae369e2ea9dd3130.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1519925.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

邮件自动化:简化Workplace中的操作

电子邮件在职场中的使用对于企业和组织的日常活动起着重要的作用。电子邮件不再仅仅是一种通信方式,已经成为现代企业和组织实施日常运营的关键要素。 除了通信,电子邮件对于需求生成、流程工作流、交易审批以及各种其他与业务相关的活动至关重要。在当…

【C++设计模式】策略模式

文章目录 前言一、策略模式是什么?二、策略模式的实现原理三、UML图四、代码实现总结 前言 策略模式是一种行为设计模式,它允许在运行时选择算法的行为。通过将每个算法封装到具有共同接口的独立类中,客户端可以在不改变自身代码的情况下选择…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:RelativeContainer)

相对布局组件,用于复杂场景中元素对齐的布局。 说明: 该组件从API Version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 规则说明 容器内子组件区分水平方向,垂直方向: 水平方向为left&…

ThingsBoard Edge 设备连接

文章目录 一、创建设备1.创建设备配置2.创建设备 二、上传遥测1.MQTTX 工具2.上传遥测 三、属性1.属性类型2.上传客户端属性3.下载共享属性4.订阅共享数据 四、设备告警1.配置告警规则2.清除报警规则3.测试3.1.设备告警3.1.清除告警 五、规则链1.规则管理2.Edge 查看规则链 Thi…

腾讯云对象存储的在Java使用步骤介绍

腾讯云对象存储的在Java使用步骤介绍 创建一个腾讯云的账户 这个自己去创建,然后开通对象存储服务,如下 有了账号就要创建一个对象存储的桶,也就是存储对象的一个容器 如果你想只有自己放存放的就设置 私有读写 ,如果想用网络直…

SpringCloud Stream 消息驱动

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第九篇,即介绍 Stream 消息驱动。 二、消息驱动概念 2.1 消息驱动是什么 官方定义 Spring …

提升用户体验,Xinstall智能判定拉起技术来袭

在移动互联网时代,App推广已经成为各大企业的必争之地。然而,随着市场竞争的加剧,如何提升App的转化效率和用户体验成为了推广者们亟待解决的问题。这时,Xinstall的智能判定拉起技术应运而生,为推广者们带来了新的解决…

Go-知识select

Go-知识select 1. select 的特性1.1 chan读写1.2 返回值1.3 default 2. select 经典使用2.1 永久阻塞2.2 快速检错2.3 限时等待 3. 实现原理3.1 数据结构3.2 实现逻辑3.3 原理总结 4. 总结4.1 大概原理4.2 参数4.3 返回值 一个小活动: https://developer.aliyun.com…

element el-table 表格限制多选个数

本次的功能的要求是: 原本的引入的elment 的表格,去除全选框,版本对比的按钮,需要在选择版本,并且版本个数为2的时候,可点击,进行版本对比操作每次选择版本的时候,目前已有两个选择…

【C语言】—— 指针二 : 初识指针(下)

【C语言】——函数栈帧 一、 c o n s t const const 修饰指针1.1、 c o n s t const const 修饰变量1.2、 c o n s t const const 修饰指针 二、野指针2.1野指针的成因(1)指针未初始化(2)指针越界访问(3)指…

Hardness of Scheme-Switching and Comparison in FHE

参考文献: [AP13] Alperin-Sheriffff, J., Peikert, C.: Practical bootstrapping in quasilinear time. In: Canetti, R., Garay, J.A. (eds.) CRYPTO 2013. LNCS, vol. 8042, pp. 1–20. Springer, Heidelberg (2013). https://doi.org/10.1007/978-3-642-40041-…

微服务初识

1.认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢? 1.1.单体架构 单体架构:将业务的所有功能集中在一个项目中开发,打…

Qt4 设计师自定义控件----写好qmake文件,无需额外拷贝

前言 浏览了很多帖子,看了很多博主的教程,每一个都写的很好,美中不足的是。Qt在每次自定义插件时都需要拷贝,如果能够利用qmake install拷贝功能就很完美了,在其他人使用的时候只要简单的几个步骤就能轻松的用起来&am…

点餐平台网站|基于springboot框架+ Mysql+Java+Tomcat的点餐平台网站设计与实现(可运行源码+数据库+设计文档+部署说明)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能实现 系统功能设计 数据库E-R图设计 lunwen参…

R语言数据挖掘-关联规则挖掘(1)

一、分析目的和数据集描述 要分析的数据是美国一区域的保险费支出的历史数据。保险费用数据表的每列分别为年龄、性别、体重指数、孩子数量、是否吸烟、所在区域、保险收费。 本文的主要目的是分析在年龄、性别、体重指数、孩子数量、是否吸烟、所在区域中这些因素中&#xf…

【PTA】L1-039 古风排版(C++)

题目链接:L1-039 古风排版 - 团体程序设计天梯赛-练习集 (pintia.cn) 目录: 目录: 题目要求: 输入格式: 输出格式: 输入样例: 输出样例: 思路: 代码: 测试结…

【四 (4)数据可视化之 Ploty Express常用图表及代码实现 】

目录 文章导航一、介绍二、安装Plotly Express三、导入Plotly Express四、占比类图表1、饼图2、环形图3、堆叠条形图4、百分比堆叠条形图 五、比较排序类1、条形图2、漏斗图3、面积漏斗图 六、趋势类图表1、折线图2、多图例折线图3、分列折线图4、面积图5、多图例面积图 七、频…

解锁区块链游戏数据解决方案

作者:stellafootprint.network 随着区块链技术的日新月异,游戏行业正迎来一场革命,催生了区块链游戏的崛起。这一变革不仅为用户带来了全新的互动体验,也开辟了全新的盈利渠道。然而,在这一新兴领域,数据的…

程序人生——Java泛型和反射的使用建议

目录 引出泛型和反射建议93:Java的泛型是类型擦除的建议94:不能初始化泛型参数和数组建议95:强制声明泛型的实际类型 建议96:不同的场景使用不同的泛型通配符建议97:警惕泛型是不能协变和逆变的 建议98:建议…

安卓国产百度网盘与国外云盘软件onedrive对比

我更愿意使用国外软件公司的产品,而不是使用国内百度等制作的流氓软件。使用这些国产软件让我不放心,他们占用我的设备大量空间,在我的设备上推送运行各种无用的垃圾功能。瞒着我,做一些我不知道的事情。 百度网盘安装包大小&…