OpenHarmony-6.IPC/RPC组件

  • IPC/RPC组件机制

1.基本概念

  IPC:设备内的进程间通信(Inter-Process Communication)。

  RPC:设备间的进程间通信(Remote Procedure Call)。

  IPC/RPC用于实现跨进程通信,不同的是前者使用Binder驱动,用于设备内的跨进程通信,后者使用软总线驱动,用于跨设备跨进程通信。需要跨进程通信的原因是因为每个进程都有自己独立的资源和内存空间,其他进程不能随意访问不同进程的内存和资源,IPC/RPC便是为了突破这一点。

  Client-Server 软件模型外加 Interface 接口共同组成了 OpenHarmony 诸多子系统的架构,使其系统的稳定性、扩展性以及进程通信能力得到加强。子系统中均可见到 Interface 接口目录、Framework 客户端目录以及 Service 服务端目录,工作重点一般集中在 Service 服务端,如下图所示:
在这里插入图片描述

1.1.实现原理

  IPC和RPC通常采用客户端-服务端(Client-Server)模型,在使用时,请求Client端进程可获取Server端所在进程的代理(Proxy),并通过此代理读写数据来实现进程间的数据通信,更具体的讲,首先客户端会建立一个服务端的代理对象,这个代理对象具备和服务端一样的功能,若想访问服务端中的某一个方法,只需访问代理对象中对应的方法即可,代理对象会将请求发送给服务端;然后服务端处理接受到的请求,处理完之后通过驱动返回处理结果给代理对象;最后代理对象将请求结果进一步返回给客户端。

  如下图所示: 通常,Stub会先注册系统能力(System Ability)到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理Proxy对象,然后使用代理Proxy对象和SA通信。在整个通信过程中,如果使用的是IPC通信,则依赖的是Binder驱动,使用的是RPC通信,则依赖的是软总线驱动。

说明: 以下为IPC与RPC的典型使用场景:

  • IPC典型使用场景在后台服务,应用的后台服务通过IPC机制提供跨进程的服务调用能力。
  • RPC典型使用场景在多端协同,多端协同通过RPC机制提供远端接口调用与数据传递能力。

  IPC通信机制架构图:
在这里插入图片描述

  目录结构:

/foundation/communication/ipc
├── interfaces        # 对外接口存放目录
│   └── innerkits     # 对内部子系统暴露的头文件存放目录
│       ├── ipc_core     # ipc 接口存放目录
│       └── libdbinder   # dbinder 接口存放目录
├── ipc            # ipc 框架代码
│   ├── native     # ipc native 实现存放目录
│       ├── src    # ipc native 源代码存放目录
│       └── test   # ipc native 单元测试用例存放目录
│   └── test       # ipc native 模块测试用例存放目录
├── service        # dbinder 实现存放目录
│   └── dbinder    # dbinder 源代码存放目录

1.2.Binder机制

  Binder机制通常采用客户端-服务器(Client-Server)模型,服务请求方(Client)可获取服务提供方(Server)的代理 (Proxy),并通过此代理读写数据来实现进程间的数据通信。通常,系统能力(SystemAbility)Server侧会先注册到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口(添加,查询,获取,删除等)。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理,然后使用代理和SA通信。

注:SAMgr本身也是IPC的Server端,Client通过SAMgr的代理,调用SAMgr的接口。

  Binder机制架构图:
在这里插入图片描述

2.系统服务管理子系统

  系统服务管理子系统由两部分构成:

  • 系统服务框架组件(safwk):定义了SystemAbility的实现方法,并提供启动、发布等接口实现。
  • 系统服务管理组件(samgr): 提供系统服务注册、查询等功能。

  系统服务管理架构图如下:
在这里插入图片描述
  代码目录:

/foundation/systemabilitymgr
│── safwk               # 组件目录
│  ├── bundle.json      # 组件描述及编译脚本
│  ├── etc              # 配置文件
│  ├── interfaces       # 对外接口目录
│  ├── services         # 框架实现
│  ├── test             # 测试用例
├── samgr
│   ├── bundle.json  # 部件描述及编译文件
│   ├── frameworks   # 框架实现存在目录
│   ├── interfaces   # 接口目录
│   ├── services     # 组件服务端目录
│   ├── test         # 测试代码存放目录
│   ├── utils        # 工具类目录

2.1.系统服务框架组件

  SystemAbility实现一般采用XXX.cfg + saId.xml + libXXX.z.so的方式由init进程解析对应的XXX.cfg文件拉起SystemAbility所依赖的进程。(注:多个系统服务可能跑在同一个进程里。比如AbilityManagerService、BatteryService、WindowManagerService都在foundation进程,MMIService在独立的进程multimodalinput中。)

  SystemAbility类图如下:
在这里插入图片描述
备注:

SystemAbility子类需要重写OnStart()和OnStop()方法,并且在OnStart()方法中调用Publish(sptr systemAbility)方法把系统服务发布出去。

2.2.系统服务实现步骤

  以AbilityManagerService为例说明SystemAbility的实现。

2.2.1.定义IPC对外接口IXXX

  定义该服务对外提供的能力集合函数,统一继承IPC接口类IRemoteBroker;同时声明该IPC对外接口唯一标识符DECLARE_INTERFACE_DESCRIPTOR(XXX);该标识符用于IPC通信的校验等目的。

foundation\ability\ability_runtime\interfaces\inner_api\ability_manager\include\ability_manager_interface.h:69 class IAbilityManager : public OHOS::IRemoteBroker {70 public:71     DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityManager")7273     /**74      * StartAbility with want, send want to ability manager service.75      *76      * @param want, the want of the ability to start.77      * @param userId, Designation User ID.78      * @param requestCode, Ability request code.79      * @return Returns ERR_OK on success, others on failure.80      */81     virtual int StartAbility(82         const Want &want,83         int32_t userId = DEFAULT_INVAL_VALUE,84         int requestCode = DEFAULT_INVAL_VALUE) = 0;8586   ...87 }
  • 定义客户端代码XXXProxy
foundation\ability\ability_runtime\services\abilitymgr\include\ability_manager_proxy.h:30 class AbilityManagerProxy : public IRemoteProxy<IAbilityManager> {31 public:32     explicit AbilityManagerProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IAbilityManager>(impl)33     {}3435     virtual ~AbilityManagerProxy()36     {}3746     virtual int StartAbility(47         const Want &want,48         int32_t userId = DEFAULT_INVAL_VALUE,49         int requestCode = DEFAULT_INVAL_VALUE) override;5051    ...52 }
 foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_proxy.cpp42 int AbilityManagerProxy::StartAbility(const Want &want, int32_t userId, int requestCode)43 {44     int error;45     MessageParcel data;46     MessageParcel reply;47     MessageOption option;4849     if (!WriteInterfaceToken(data)) {50         return INNER_ERR;51     }52     if (!data.WriteParcelable(&want)) {53         HILOG_ERROR("want write failed.");54         return INNER_ERR;55     }5657     if (!data.WriteInt32(userId)) {58         HILOG_ERROR("userId write failed.");59         return INNER_ERR;60     }6162     if (!data.WriteInt32(requestCode)) {63         HILOG_ERROR("requestCode write failed.");64         return INNER_ERR;65     }6667     error = SendRequest(AbilityManagerInterfaceCode::START_ABILITY, data, reply, option);72     return reply.ReadInt32();73 }

  AbilityManagerProxy::StartAbility()实现代码中会调用Remote()->SendRequest(IAbilityManager::START_ABILITY, data, reply, option);把消息码和数据发送给服务端。

-定义服务端代码XXXStub

 foundation\ability\ability_runtime\services\abilitymgr\include\ability_manager_stub.h34 class AbilityManagerStub : public IRemoteStub<IAbilityManager> {35 public:36     AbilityManagerStub();37     ~AbilityManagerStub();38     virtual int OnRemoteRequest(39         uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;4048     virtual int DoAbilityForeground(const sptr<IRemoteObject> &token, uint32_t flag) override;4950  ...51 }
 foundation\ability\ability_runtime\services\abilitymgr\src\ability_manager_stub.cpp:332 int AbilityManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)333 {334     std::u16string abilityDescriptor = AbilityManagerStub::GetDescriptor();335     std::u16string remoteDescriptor = data.ReadInterfaceToken();336     if (abilityDescriptor != remoteDescriptor && extensionDescriptor != remoteDescriptor) {337         HILOG_ERROR("local descriptor is not equal to remote");338         return ERR_INVALID_STATE;339     }340341     auto itFunc = requestFuncMap_.find(code);342     if (itFunc != requestFuncMap_.end()) {343         auto requestFunc = itFunc->second;344         if (requestFunc != nullptr) {345             return (this->*requestFunc)(data, reply);346         }347     }348     HILOG_WARN("default case, need check.");349     return IPCObjectStub::OnRemoteRequest(code, data, reply, option);350 }

  requestFuncMap_[START_ABILITY] = &AbilityManagerStub::StartAbilityInner。消息码START_ABILITY对应的函数为AbilityManagerStub::StartAbilityInner。

 600 int AbilityManagerStub::StartAbilityInner(MessageParcel &data, MessageParcel &reply)601 {602     Want *want = data.ReadParcelable<Want>();603     if (want == nullptr) {604         HILOG_ERROR("want is nullptr");605         return ERR_INVALID_VALUE;606     }607     int32_t userId = data.ReadInt32();608     int requestCode = data.ReadInt32();609     int32_t result = StartAbility(*want, userId, requestCode);610     reply.WriteInt32(result);611     delete want;612     return NO_ERROR;613 }

  StartAbility()的实现在AbilityManagerStub的实现类AbilityManagerService中。

  • SystemAbility的实现类
 foundation\ability\ability_runtime\services\abilitymgr\include\ability_manager_service.h76 class AbilityManagerService : public SystemAbility,77                               public AbilityManagerStub,78                               public AppStateCallback,79                               public std::enable_shared_from_this<AbilityManagerService> {80     DECLARE_DELAYED_SINGLETON(AbilityManagerService)81     DECLEAR_SYSTEM_ABILITY(AbilityManagerService)82 public:83     void OnStart() override;84     void OnStop() override;8586     virtual void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override;8788     virtual void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override;8990     ServiceRunningState QueryServiceState() const;91100     virtual int StartAbility(101         const Want &want, int32_t userId = DEFAULT_INVAL_VALUE, int requestCode = DEFAULT_INVAL_VALUE) override;102    ...103 }

  AbilityManagerService同时继承了SystemAbility和AbilityManagerStub。在重写的SystemAbility的接口函数OnStart()中,调用Publish(instance_)把自己发布出去。

 foundation/ability/ability_runtime/services/abilitymgr/src/ability_manager_service.cpp268 void AbilityManagerService::OnStart()269 {270     if (state_ == ServiceRunningState::STATE_RUNNING) {271         HILOG_INFO("AMS has already started.");272         return;273     }274     HILOG_INFO("AMS starting.");275     if (!Init()) {276         HILOG_ERROR("Failed to init AMS.");277         return;278     }279     state_ = ServiceRunningState::STATE_RUNNING;280     /* Publish service maybe failed, so we need call this function at the last,281      * so it can't affect the TDD test program */282     instance_ = DelayedSingleton<AbilityManagerService>::GetInstance().get();287     bool ret = Publish(instance_);                       292293     SetParameter(BOOTEVENT_A // In namespace OHOS true");294     WatchParameter(BOOTEVENT namespace AAFwk {}   ), AAFwk::ApplicationUtil::AppFwkBootEventCallback, nullptr);295     AddSystemAbilityListener(BACKGROUND_TASK_MANAGER_SERVICE_ID);296     AddSystemAbilityListener(DISTRIBUTED_SCHED_SA_ID);297     AddSystemAbilityListener(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);298     HILOG_INFO("AMS start success.");299 }

注:在实现SystemAbility的时候,必须调用宏REGISTER_SYSTEM_ABILITY_BY_ID或者SystemAbility::MakeAndRegisterAbility()把SystemAbility注册到LocalAbilityManager中。可参考如下代码:
const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(DelayedSingleton::GetInstance().get());

  • SystemAbility配置

  以c++实现的SA必须配置相关SystemAbility的profile配置文件才会完成SA的自动加载注册逻辑,否则没有编写配置文件的SystemAbility不会完成自动加载注册。配置方法如下:
  在子系统的根目录新建一个以sa_profile为名的文件夹,然后在此文件夹中新建两个文件:一个以saId为前缀的xml文件,另外一个为BUILD.gn文件。比如AbilityManagerService,saId为ABILITY_MGR_SERVICE_ID(即180),对应的配置文件为180.xml。内容如下:

foundation/ability/ability_runtime/services/sa_profile/BUILD.gn:
14 import("//build/ohos/sa_profile/sa_profile.gni")1516 ohos_sa_profile("ams_sa_profile") {17   sources = [18     "180.json",19     "182.json",20     "183.json",21     "184.json",22     "501.json",23   ]2425   part_name = "ability_runtime"26 }

描述说明:

  • part_name为相应部件名称;
  • sources表示当前子系统需要配置的SystemAbility列表,可支持配置多个SystemAbility。
  foundation/ability/ability_runtime/services/sa_profile/180.json:1 {2     "process": "foundation",3     "systemability": [4         {5             "name": 180,6             "libpath": "libabilityms.z.so",7             "run-on-create": true,8             "distributed": false,9             "dump_level": 110         }11     ]12 }

描述说明:

  • 进程名字:该SystemAbility要运行的进程空间,此字段是必填选项。即AbilityManagerService跑在foundation进程中。
  • 一个SystemAbility配置文件只能配置一个SystemAbility节点,配置多个会导致编译失败。
  • SystemAbility的name为对应的saId必须与代码中注册的saId保持一致,必配项。
  • libpath为SystemAbility的加载路径,必配项。
  • run-on-create:true表示进程启动后即向samgr组件注册该SystemAbility;false表示按需启动,即在其他模块访问到该SystemAbility时启动,必配项。
  • distributed:true表示该SystemAbility为分布式SystemAbility,支持跨设备访问;false表示只有本地跨进程访问。
  • bootphase:可不设置;可以设置的值有三种:BootStartPhase、CoreStartPhase、OtherStartPhase(默认类型),三种优先级依次降低,在同一个进程中,会优先拉起注册配置BootStartPhase的SystemAbility,然后是配置了CoreStartPhase的SystemAbility,最后是OtherStartPhase;当高优先级的SystemAbility全部启动注册完毕才会启动下一级的SystemAbility的注册启动。
  • dump-level:表示systemdumper支持的level等级,默认配置1。

  以上步骤完成后,全量编译代码后会在out路径下生成一个以进程名为前缀的xml文件(比如foundation.xml),路径为:out\…\system\profile\foundation.xml。该文件整合了所有需要在该进程中运行的SA的saId.xml文件内容。(比如AbilityManagerService,WindowManagerService,PowerManagerService等SA的配置文件都会被集成到foundation.xml中)。

  • Cfg配置文件

  cfg配置文件为linux提供的native进程拉起策略,开机启动阶段由init进程解析cfg文件把目标进程拉起(动态加载的除外)。foundation进程的配置文件在systemabilitymgr子系统中。

 foundation\systemabilitymgr\safwk\etc\profile\foundation.cfg34     "services" : [{35             "name" : "foundation",36             "path" : ["/system/bin/sa_main", "/system/profile/foundation.json"],37             "importance" : -20,38             "uid" : "foundation",39             "permission" : [40                 "ohos.permission.INPUT_MONITORING",41                 "ohos.permission.PERMISSION_USED_STATS",42                 "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER",43                 "ohos.permission.DISTRIBUTED_DATASYNC",44                 "ohos.permission.MICROPHONE",45                 "ohos.permission.WRITE_CALL_LOG",46                 "ohos.permission.READ_CONTACTS",47                 "ohos.permission.READ_DFX_SYSEVENT",48                 "ohos.permission.GRANT_SENSITIVE_PERMISSIONS",49                 "ohos.permission.REVOKE_SENSITIVE_PERMISSIONS",50                 "ohos.permission.MANAGE_SECURE_SETTINGS",51                 "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",52                 "ohos.permission.START_ABILITIES_FROM_BACKGROUND",53                 "ohos.permission.ACCESS_SERVICE_DM",54                 "ohos.permission.STORAGE_MANAGER",55                 "ohos.permission.PROXY_AUTHORIZATION_URI",56                 "ohos.permission.ABILITY_BACKGROUND_COMMUNICATION",57                 "ohos.permission.USE_USER_IDM",58                 "ohos.permission.MANAGE_LOCAL_ACCOUNTS",59                 "ohos.permission.LISTEN_BUNDLE_CHANGE",60                 "ohos.permission.GET_TELEPHONY_STATE",61                 "ohos.permission.SEND_MESSAGES",62                 "ohos.permission.CONNECT_CELLULAR_CALL_SERVICE",63                 "ohos.permission.SET_TELEPHONY_STATE"

refer to

  • https://gitee.com/openharmony/communication_ipc
  • https://blog.csdn.net/procedurecode/article/details/130222081
  • https://gitee.com/openharmony/docs/blob/39467f023bec8cfca8ec2f97b99039b1dbd141e5/zh-cn/application-dev/ipc/ipc-rpc-overview.md
  • https://forums.openharmony.cn/forum.php?mod=viewthread&tid=2980
  • https://www.51cto.com/article/701821.html

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

米思齐图形化编程之ESP32开发指导

在当今充满创意与探索的科技领域&#xff0c;米思齐图形化编程为广大爱好者开启了一扇通往智能硬件控制的便捷之门&#xff0c;尤其是当它与强大的 ESP32相结合时&#xff0c;更是碰撞出无限可能的火花。ESP32作为一款高性能、多功能的微控制器&#xff0c;拥有丰富的外设接口与…

tslib(触摸屏输入设备的轻量级库)的学习、编译及测试记录

目录 tslib的简介tslib的源码和make及make install后得到的文件下载tslib的主要功能tslib的工作原理tslib的核心组成部分tslib的框架和核心函数分析tslib的框架tslib的核心函数ts_setup()的分析(对如何获取设备名和数据处理流程的分析)函数ts_setup()自身的主要代码ts_setup()对…

使用 AI 辅助开发一个开源 IP 信息查询工具:一

本文将分享如何借助当下流行的 AI 工具,一步步完成一个开源项目的开发。 写在前面 在写代码时&#xff0c;总是会遇到一些有趣的机缘巧合。前几天&#xff0c;我在翻看自己之前的开源项目时&#xff0c;又看到了 DDNS 相关的讨论。虽然在 2021 年我写过两篇相对详细的教程&am…

Oracle:数据库的顶尖认证

在信息技术的飞速发展中&#xff0c;Oracle Corporation&#xff08;甲骨文公司&#xff09;以其在数据库领域的卓越成就而闻名遐迩。自1977年成立以来&#xff0c;Oracle已经从一个小型软件公司成长为全球最大的企业级软件公司之一&#xff0c;其产品和技术广泛应用于金融、电…

「配置应用的可见性」功能使用教程

引言 对于「应用可见性」这一概念&#xff0c;可能很多开发者小伙伴还不是很熟悉。简单举一个很典型的场景例子&#xff0c;当你开发的应用需要调起第三方应用时&#xff0c;这里就涉及到应用可见性的问题了&#xff0c;如果不配置相关的应用可见性&#xff0c;则你的应用是无…

flask flask-socketio创建一个网页聊天应用

应用所需环境&#xff1a; python 3.11.11 其他 只需要通过这个命令即可 pip install flask3.1.0 Flask-SocketIO5.4.1 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple 最好是用conda创建一个新的虚拟环境来验证 完整的pip list如下 Package Version ----…

[计算机网络]唐僧的”通关文牒“NAT地址转换

1.NAT&#xff1a;唐僧的通关文牒 在古老的西游记中&#xff0c;唐僧师徒四人历经九九八十一难&#xff0c;终于取得了真经。然而&#xff0c;他们并不是一开始就获得了通关文牒&#xff0c;而是经过了重重考验&#xff0c;最终得到了国王的认可&#xff0c;才顺利通过了各个关…

数据结构经典算法总复习(下卷)

第五章:树和二叉树 先序遍历二叉树的非递归算法。 void PreOrderTraverse(BiTree T, void (*Visit)(TElemType)) {//表示用于查找的函数的指针Stack S; BiTree p T;InitStack(S);//S模拟工作栈while (p || !StackEmpty(S)) {//S为空且下一个结点为空&#xff0c;意味着结束遍…

【Windows版】opencv 和opencv_contrib配置

一、参考资料 &#xff08;四十一&#xff09;CMakeVSopencv/opencv_contrib 环境配置 从源码安装&#xff2f;penCV&#xff0c;使用python windowsvscodeopencv源码安装配置 二、关键步骤 1. opencv与opencv_contrib版本对齐 下载 opencv 下载 opencv_contrib opencv…

2014年IMO第4题

△ A B C \triangle ABC △ABC 中, B C BC BC 上有一点 P P P 满足 ∠ B A P = ∠ A C B \angle BAP=\angle ACB ∠BAP=∠ACB, 还有一点 Q Q Q 满足 ∠ A = Q A C = ∠ A B C \angle A=QAC=\angle ABC ∠A=QAC=∠ABC. 分别延长 A P AP AP, A Q AQ AQ 一倍至 M M M, N …

基于微信小程序的乡村旅游系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实…

拆解一个微型气泵了解工作原理

原因 在焊接电路板时&#xff0c;测试打印后想要拆卸错误的板子上的元件&#xff0c;但每次拆卸过程中吸锡器手动按压到手疼。忽然看见一种小型气泵&#xff0c;不知道能不能做一个电动的吸锡器。 拆卸过程 第一步先把前盖板拆掉&#xff0c;这一步很好办到&#xff0c;就三…

SAP HCM 考勤时间冲突到分 源码分析

导读 时间冲突:SAP实施顾问应该都知道时间约束的概念&#xff0c;时间约束是按照主键作为分隔&#xff0c;其中信息类型有个seqnr的流水号字段&#xff0c;是控制时间约束的主要条件&#xff0c;今天分析的2001信息类型&#xff0c;如果日期相同&#xff0c;请假的开始时间与结…

《庐山派从入门到...》板载按键启动!

《庐山派从入门到...》板载按键启动&#xff01; 《庐山派从入门到...》板载按键启动&#xff01; 视频内容大致如下 我们之前了解了GPIO的输出模式使用方法&#xff0c;并且成功点灯&#xff0c;很明显本篇要来分享的自然是GPIO的输入模式 正好回顾一下之前学的python基础包…

分布式协同 - 分布式事务_TCC解决方案

文章目录 导图Pre流程图2PC VS 3PC VS TCC2PC&#xff08;Two-Phase Commit&#xff0c;二阶段提交&#xff09;3PC&#xff08;Three-Phase Commit&#xff0c;三阶段提交&#xff09;TCC&#xff08;Try-Confirm-Cancel&#xff09;2PC、3PC与TCC的区别2PC、3PC与TCC的联系 导…

新版国标GB28181设备端Android版EasyGBD支持国标GB28181-2022,支持语音对讲,支持位置上报,开源在Github

经过近3个月的迭代开发&#xff0c;新版本的国标GB28181设备端EasyGBD安卓Android版终于在昨天发布到Github了&#xff0c;最新的EasyGBD支持了国标GB28181-2022版&#xff0c;还支持了语音对讲、位置上报、本地录像等功能&#xff0c;比原有GB28181-2016版的EasyGBD更加高效、…

YOLO-World:Real-Time Open-Vocabulary Object Detection

目录 摘要 Abstract YOLO-World 1 模型架构 1.1 Text Encoder 1.2 YOLO Backbone 2 RepVL-PAN 2.1 T-CSPLayer 2.2 I-Pooling Attention 2.3 预测 3 消融实验 3.1 预训练数据 3.2 RepVL-PAN的消融实验 3.3 文本编码器 4 效果展示 4.1 零样本 4.2 根据词汇表检…

MySQL -- 库的相关操作

目录 查看数据库 创建数据库 直接创建&#xff1a; 加约束条件 if not exists 字符集和校对规则 什么是字符集 什么是校对规则 校对规则的主要功能 校对规则的特性 查看指定的数据库使用的字符集和校对规则&#xff1a; 比较是否区分大小写字母差异 显示创建语句 …

【spring-cloud-gateway总结】

文章目录 什么是gateway如何导入gateway依赖路由配置gateway配置断路器导包配置 什么是gateway 在微服务架构中&#xff0c;gateway网关是一个服务&#xff0c;它作为系统的唯一入口点&#xff0c;处理所有的客户端请求&#xff0c;然后将这些请求路由到适当的服务。提供了几个…

mac iterm2 使用 lrzsz

前言 mac os 终端不支持使用 rz sz 上传下载文件&#xff0c;本文提供解决方法。 mac 上安装 brew install lrzsz两个脚本 注意&#xff1a;/usr/local/bin/iterm2-send-zmodem.sh 中的 sz命令路径要和你mac 上 sz 命令路径一致。 /usr/local/bin/iterm2-recv-zmodem.sh 中…