低功耗蓝牙ble开发(三)——bluez5接口及glib相关函数开发说明

在 D-Bus 编程中,代理对象(proxy object)是一个方便的抽象,用于简化与远程 D-Bus 服务的交互。代理对象代表远程 D-Bus 服务的某个对象,使得你可以像调用本地对象的方法一样调用远程对象的方法、获取属性以及监听信号。虽然使用代理对象并不是必须的,但它极大地简化了 D-Bus 编程,特别是对于复杂的 D-Bus 接口。

代理对象的作用

  1. 方法调用简化: 代理对象提供了调用远程方法的简单接口,你可以直接调用代理对象的方法,而不需要手动构建和解析 D-Bus 消息。
  2. 属性访问简化: 代理对象允许你直接访问远程对象的属性,而不需要手动处理 D-Bus 的 GetSet 请求。
  3. 信号处理简化: 代理对象可以自动处理从远程对象发出的信号,简化信号监听和处理过程。
  4. 错误处理: 代理对象提供一致的错误处理机制,使得处理 D-Bus 方法调用和属性访问中的错误更加方便。

6、bluez提供的基于dbus的api

BlueZ 是 Linux 下的官方蓝牙协议栈,提供了丰富的 D-Bus 接口来管理蓝牙设备。BlueZ 中的主要接口和方法涉及设备发现、配对、连接以及管理 GATT 服务和特征。以下是 BlueZ 中的关键接口、方法及其之间的关系的详细说明。

(1)主要接口
  1. org.bluez.Adapter1
    • 描述:表示蓝牙适配器,负责设备发现和管理。
    • 常用方法:
      • StartDiscovery:开始扫描周围的蓝牙设备。
      • StopDiscovery:停止扫描。
      • RemoveDevice:移除已配对的设备。
    • 常用属性:
      • Address:适配器的地址。
      • Name:适配器的名称。
      • Powered:适配器的电源状态。
  2. org.bluez.Device1
    • 描述:表示蓝牙设备,可以配对和连接。
    • 常用方法:
      • Connect:连接到设备。
      • Disconnect:断开连接。
      • Pair:配对设备。
      • CancelPairing:取消配对过程。
    • 常用属性:
      • Address:设备的地址。
      • Name:设备的名称。
      • Paired:配对状态。
      • Connected:连接状态。
  3. org.bluez.GattService1
    • 描述:表示 GATT 服务。
    • 常用属性:
      • UUID:服务的 UUID。
      • Primary:是否为主服务。
      • Device:所属设备。
  4. org.bluez.GattCharacteristic1
    • 描述:表示 GATT 特征。
    • 常用方法:
      • ReadValue:读取特征值。
      • WriteValue:写入特征值。
      • StartNotify:开始通知。
      • StopNotify:停止通知。
    • 常用属性:
      • UUID:特征的 UUID。
      • Service:所属服务。
      • Value:当前特征值。
  5. org.bluez.GattDescriptor1
    • 描述:表示 GATT 描述符。
    • 常用方法:
      • ReadValue:读取描述符值。
      • WriteValue:写入描述符值。
    • 常用属性:
      • UUID:描述符的 UUID。
      • Characteristic:所属特征。
      • Value:当前描述符值。
  6. org.freedesktop.DBus.ObjectManager
    • 描述:用于管理和监控 D-Bus 对象,通常用于获取所有对象及其接口和属性。
    • 常用方法:
      • GetManagedObjects:获取所有受管理的对象及其接口和属性。
    • 常用信号:
      • InterfacesAdded:当新对象添加时发出信号。
      • InterfacesRemoved:当对象接口移除时发出信号。
(2)方法之间的关系和流程

以下是使用 BlueZ 进行 BLE 设备发现、连接和操作的常见流程:

  1. 启动设备发现
    • 调用 org.bluez.Adapter1.StartDiscovery 开始扫描设备。
    • 订阅 org.freedesktop.DBus.ObjectManager.InterfacesAdded 信号,获取新发现的设备。
  2. 配对设备
    • InterfacesAdded 信号回调中,检查是否是目标设备。
    • 调用 org.bluez.Device1.Pair 进行配对。
  3. 连接设备
    • 配对成功后,调用 org.bluez.Device1.Connect 连接到设备。
  4. 发现服务和特征
    • 连接成功后,调用 org.freedesktop.DBus.ObjectManager.GetManagedObjects 获取设备的所有服务和特征。
    • 遍历返回的对象,找到 org.bluez.GattService1org.bluez.GattCharacteristic1
  5. 操作特征
    • 使用 org.bluez.GattCharacteristic1.ReadValue 读取特征值。
    • 使用 org.bluez.GattCharacteristic1.WriteValue 写入特征值。
    • 使用 org.bluez.GattCharacteristic1.StartNotify 订阅通知。

7、main_loop和dbus

“main_loop” 和 “dbus” 是两个在 Linux 环境下开发桌面应用和系统服务时经常会遇到的概念。

(1)Main Loop (主循环)

主循环是事件驱动编程的核心概念,广泛应用于图形用户界面(GUI)和其他需要持续处理事件的应用中。它的主要作用是不断地检查和处理事件,如用户输入、网络数据、定时器等。

在一个典型的主循环中,应用程序会做以下工作:

  1. 检查是否有任何事件发生(如鼠标点击、键盘输入)。
  2. 处理这些事件并执行相应的回调函数。
  3. 如果没有事件发生,则应用程序通常会等待(通常是阻塞操作),直到有事件需要处理。

在 Linux 环境下,许多 GUI 库如 GTK 和 Qt 都实现了自己的主循环。例如,GTK 使用 GMainLoop 进行事件处理。

(2)D-Bus (Desktop Bus)

D-Bus 是一个消息总线系统,用于在同一台机器上运行的多个程序之间进行通信。它的设计初衷是提供一个简单的方式,允许应用程序相互通信并协调工作。

D-Bus 有两个主要的总线:

  1. 系统总线:用于系统服务与应用程序之间的通信,例如网络管理器、音量控制等系统服务。
  2. 会话总线:用于同一用户会话中的应用程序之间的通信,例如桌面环境的组件。

D-Bus 的通信模型基于消息传递,包括方法调用、信号和属性。应用程序可以通过 D-Bus 接口来调用其他应用程序的方法、接收信号或查询/设置属性。

(3)Main Loop 和 D-Bus 的结合

在实际开发中,D-Bus 通常需要集成到应用程序的主循环中,以便处理来自 D-Bus 的消息。这种集成通常通过库来实现,例如:

  • GLib(用于 GTK 应用):GLib 提供了对 D-Bus 的支持,可以将 D-Bus 消息处理集成到 GMainLoop 中。
  • QtDBus(用于 Qt 应用):QtDBus 提供了对 D-Bus 的支持,可以将 D-Bus 消息处理集成到 Qt 的事件循环中。

例如,在一个使用 GLib 的应用程序中,您可以这样使用 D-Bus:

#include <glib.h>
#include <gio/gio.h>

int main(int argc, char *argv[]) {
    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
    GDBusConnection *connection;
    GError *error = NULL;

    connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
    if (error != NULL) {
        g_printerr("Error connecting to D-Bus: %s\n", error->message);
        g_error_free(error);
        return 1;
    }

    // 设置 D-Bus 信号处理等

    g_main_loop_run(loop);

    // 清理资源
    g_main_loop_unref(loop);
    g_object_unref(connection);

    return 0;
}

在这个示例中,g_main_loop_run 会启动主循环,g_bus_get_sync 用于连接到会话总线,之后可以设置 D-Bus 信号处理等操作。

总之,main loop 和 D-Bus 在 Linux 环境下的桌面应用开发中是两个非常重要的组件,前者负责事件处理循环,后者提供了进程间通信机制。通过将 D-Bus 集成到主循环中,可以让应用程序更高效地处理系统事件和进程间通信。

8、GVariant格式

GVariant 是 GLib 库中的一种数据类型,用于在 D-Bus 上表示和传输复杂的数据结构。格式字符串 (a{oa{sa{sv}}}) 描述了 GVariant 的一种复合结构,常用于表示对象树及其属性。这种格式在 BlueZ 和其他使用 D-Bus 的应用中非常常见,尤其是在实现 org.freedesktop.DBus.ObjectManager 接口时。

结构说明

  • ( ... ):表示一个元组。
  • a{ ... }:表示一个键值对的数组(字典)。
  • o:表示一个对象路径(D-Bus 中的对象路径以 / 开头的字符串)。
  • a{ ... }:嵌套的键值对数组。
  • s:表示一个字符串。
  • a{ ... }:再次嵌套的键值对数组。
  • v:表示一个变体(可以是任意类型)。

解释 (a{oa{sa{sv}}})

  • 最外层的括号 () 表示这是一个元组。
  • a{oa{sa{sv}}} 描述了元组中的一个元素,这是一个数组,每个元素是一个键值对,其中键是对象路径(o),值是另一个字典(a{sa{sv}})。
  • a{sa{sv}} 描述了对象路径对应的值,这是一个字典,其中键是接口名称(s),值是属性字典(a{sv})。
  • a{sv} 描述了属性字典,其中键是属性名称(s),值是属性值(v,表示变体类型)。

bluez和dbus的开发中,很多该格式的操作,glib库中提供了很多该格式的函数方法,具体情况具体分析使用。

(1)具体示例

假设我们有如下的 GVariant 数据表示一个蓝牙设备和其服务:

(
  {
    "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX" : {  // 设备对象路径
      "org.bluez.Device1" : {  // 接口
        "Address" : <"XX:XX:XX:XX:XX:XX">,  // 属性
        "Name" : <"DeviceName">
      }
    },
    "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0001" : {  // 服务对象路径
      "org.bluez.GattService1" : {  // 接口
        "UUID" : <"00001800-0000-1000-8000-00805f9b34fb">,  // 属性
        "Primary" : <true>
      }
    }
  }
)
(2)解析示例
void parse_managed_objects(GVariant *result) {
    GVariantIter *iter;
    gchar *object_path;
    GVariant *interfaces;

    // 解析结果
    g_variant_get(result, "(a{oa{sa{sv}}})", &iter);

    // 遍历每个对象路径
    while (g_variant_iter_next(iter, "{oa{sa{sv}}}", &object_path, &interfaces)) {
        g_print("Object Path: %s\n", object_path);

        GVariantIter *iface_iter;
        gchar *interface;
        GVariant *props;

        // 解析接口
        g_variant_get(interfaces, "a{sa{sv}}", &iface_iter);
        while (g_variant_iter_next(iface_iter, "{sa{sv}}", &interface, &props)) {
            g_print("  Interface: %s\n", interface);

            GVariantIter *prop_iter;
            gchar *prop_name;
            GVariant *prop_value;

            // 解析属性
            g_variant_get(props, "a{sv}", &prop_iter);
            while (g_variant_iter_next(prop_iter, "{sv}", &prop_name, &prop_value)) {
                gchar *value_str = g_variant_print(prop_value, TRUE);
                g_print("    %s: %s\n", prop_name, value_str);
                g_free(value_str);
                g_variant_unref(prop_value);
                g_free(prop_name);
            }
            g_variant_iter_free(prop_iter);
            g_variant_unref(props);
            g_free(interface);
        }
        g_variant_iter_free(iface_iter);
        g_variant_unref(interfaces);
        g_free(object_path);
    }
    g_variant_iter_free(iter);
}

9、Dbus接口

org.freedesktop.DBus.ObjectManagerorg.freedesktop.DBus.Properties 是两个不同的 D-Bus 接口,分别用于管理对象和处理属性。它们在 BlueZ(Linux 上的 Bluetooth 栈)以及其他基于 D-Bus 的系统中广泛使用。以下是它们的详细介绍。

(1)org.freedesktop.DBus.ObjectManager

org.freedesktop.DBus.ObjectManager 接口用于管理对象树,主要用于枚举和监视对象的生命周期变化。它有两个主要方法:

  1. GetManagedObjects

    • 描述:返回对象路径和它们对应的接口和属性。

    • 方法签名a{oa{sa{sv}}}

    • 示例代码:

      GVariant *result = g_dbus_connection_call_sync(
          connection,
          "org.bluez",
          "/",
          "org.freedesktop.DBus.ObjectManager",
          "GetManagedObjects",
          NULL,
          G_VARIANT_TYPE("(a{oa{sa{sv}}})"),
          G_DBUS_CALL_FLAGS_NONE,
          -1,
          NULL,
          &error
      );
      
      if (error != NULL) {
          g_printerr("Error getting managed objects: %s\n", error->message);
          g_error_free(error);
          return;
      }
      

信号

  1. InterfacesAdded
    • 描述:在新对象添加到对象树时发出信号。
    • 信号签名(oa{sa{sv}})
  2. InterfacesRemoved
    • 描述:在对象从对象树中移除时发出信号。
    • 信号签名(oas)
(2)org.freedesktop.DBus.Properties

org.freedesktop.DBus.Properties 接口用于获取和设置对象属性,并监听属性变化。它有几个主要方法和一个信号:

方法

  1. Get

    • 描述:获取对象的特定属性值。

    • 方法签名(ss) -> (v)

    • 示例代码:

      GVariant *result = g_dbus_connection_call_sync(
          connection,
          "org.bluez",
          object_path,
          "org.freedesktop.DBus.Properties",
          "Get",
          g_variant_new("(ss)", interface_name, property_name),
          G_VARIANT_TYPE("(v)"),
          G_DBUS_CALL_FLAGS_NONE,
          -1,
          NULL,
          &error
      );
      
      if (error != NULL) {
          g_printerr("Error getting property: %s\n", error->message);
          g_error_free(error);
          return;
      }
      
      GVariant *property_value = g_variant_get_child_value(result, 0);
      // 处理属性值
      g_variant_unref(property_value);
      g_variant_unref(result);
      
  2. Set

    • 描述:设置对象的特定属性值。
    • 方法签名(ssv) -> ()
  3. GetAll

    • 描述:获取对象的所有属性值。
    • 方法签名(s) -> (a{sv})

信号

  1. PropertiesChanged
    • 描述:当对象的属性发生变化时发出信号。
    • 信号签名(sa{sv}as)
(3)信号签名

上述中的信号签名可以理解为调用方法的输入参数类型(箭头后面的表示输出参数类型)

(ss) -> (v) 是 D-Bus 方法调用的签名格式,描述了方法的输入参数和返回值类型。这种签名在 org.freedesktop.DBus.Properties 接口的 Get 方法中非常常见。

签名解释

  • (ss):表示方法的输入参数是两个字符串。
  • ->:表示从输入参数到返回值的转换。
  • (v):表示方法的返回值是一个变体类型。

具体来说,这个签名表示一个方法,它接收两个字符串参数并返回一个变体。

org.freedesktop.DBus.Properties.Get 方法

这个签名用于 org.freedesktop.DBus.Properties 接口中的 Get 方法,该方法用于获取某个对象属性的值。

  • 方法名称Get
  • 输入参数:
    • s:接口名称
    • s:属性名称
  • 返回值:
    • v:属性值

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

示例:WPF中使用DecodePixelHeight和DecodePixelWidth优化Image性能

一、目的&#xff1a;在使用Image控件时&#xff0c;如果图片太大或者图片数量过多时加载出来的程序内存会非常的大&#xff0c;但一般图片多时我们只要预览缩略图就可以&#xff0c;查看时再显示原图&#xff0c;这个时候需要通过通过设置BitmapImage的DecodePixelHeight和Dec…

在微信公众号上怎么添加预定房间功能

在这个快节奏的现代社会&#xff0c;人们对于便捷与高效的需求日益增加。特别是在旅行或出差时&#xff0c;能够快速、方便地预订一间舒适的房间&#xff0c;无疑是每个人心中的小确幸。今天&#xff0c;我们为您带来了一项革命性的服务——微信公众号上的房间预定功能&#xf…

如何修改倍福CX7000PLC IP地址

我们可以通过登录网页修改PLC的IP地址,这个需要我们知道PLC的初始IP地址 1、浏览器直接输入PLC 的IP地址 2、点击修改按钮(就是那个旋转) 修改IP地址前DHCP要先disable关闭 。 3、DHCP关闭 4、点击保存 5、在CAT3里搜索 在SYSTEM双击,之后点击搜索,具体过程可以参考下…

Pikachu靶场--RCE

exec"ping" 输入IP地址查看页面反应 可以在IP地址的后面拼接我们想要执行的命令 127.0.0.1 & ipconfig 127.0.0.1 && type C:\Windows\win.ini 127.0.0.1 | systeminfo 127.0.0.1 && net user 命令连接符 &命令1和命令2正…

【C++】认识STL

【C】认识STL STL的概念STL的版本STL的六大组件STL的三个境界STL的缺陷 STL的概念 SLT(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个保罗数据结构与算法的软件框架。 STL的版本 原…

Cesium加载Mapbox自定义地图

Cesium 加载影像地图&#xff0c;一般都是天地图&#xff0c;高德地图&#xff0c;必应地图&#xff0c;谷歌地图等。 如果真实项目中想要自定义地图的风格样式&#xff0c;为了配合相应的页面UI风格&#xff0c;这些公共免费的影像地图就满足不了需求。 但是MapBox可以支持自…

物联网网关和飞鸟物联平台如何助力其实现智能化升级,提升生产效率-天拓四方

随着工业4.0时代的到来&#xff0c;物联网技术逐渐成为推动工业转型升级的关键力量。物联网网关作为连接工业设备与网络的核心枢纽&#xff0c;在工业自动化、数据收集与分析等方面发挥着越来越重要的作用。本案例将围绕一家知名制造企业&#xff0c;展示物联网网关和飞鸟物联平…

​一个高清影像下载插件

数据是GIS的血液&#xff01; 虽然我们在水经微图&#xff08;简称“微图”&#xff09;中可以下载各种各样丰富的地图数据&#xff0c;但相信大家对数据的追求是无止境的。 我们现在就来分享一下&#xff0c;如何在QGIS中下载高清卫星影像的方法。 如果你需要最新版本的QGI…

专业纸箱厂:品质之选

在繁忙的工业园区&#xff0c;我们的纸箱厂以其卓越的品质和高效的生产能力脱颖而出。我们深谙纸箱制造的精髓&#xff0c;不断推陈出新&#xff0c;将传统工艺与现代科技完美结合。我们的纸箱不仅坚固耐用&#xff0c;而且设计独特&#xff0c;能够满足各种包装需求。 田东美达…

《天软行业全景画像定期报告》(2024-06)

最新《天软行业全景画像定期报告》&#xff08;2024-06&#xff09;内容概要如下&#xff1a; 家用电器、环保、机械设备行业的拥挤度较高&#xff0c;实际投资交易应注意&#xff1b;有色金属、通信、家用电器行业动量较强&#xff0c;房地产、综合、建筑装饰行业动量较弱&…

BatchNormalization和Layer Normalization解析

Batch Normalization 是google团队2015年提出的&#xff0c;能够加速网络的收敛并提升准确率 1.Batch Normalization原理 图像预处理过程中通常会对图像进行标准化处理&#xff0c;能够加速网络的收敛&#xff0c;如下图所示&#xff0c;对于Conv1来说输入的就是满足某一分布…

Dart 弱引用进阶

前言 村里的老人说&#xff1a;“真正的强者&#xff0c;都是扮猪吃老虎。” 日常开发中经常需要用到弱引用&#xff0c;Dart 语言里也有提供弱引用的接口 WeakReference&#xff0c;我们可以基于它开发更强大的复杂结构。 在前面的文章中&#xff0c;我们用到了一个以弱引用…

无需配置MySQL,Navicat也有在线版了?

前言 随着互联网技术的飞速发展&#xff0c;远程办公和在线协作成为了新的趋势。为了满足这一需求&#xff0c;TitanIDE模板市场近日上线了Navicat模板&#xff0c;使得数据库管理变得更加便捷、高效。现在&#xff0c;用户只需在浏览器打开TitanIDE&#xff0c;即可轻松使用N…

2024年上网行为审计软件排名,推荐这五款上网行为管理软件

上网行为审计软件是企业IT管理中不可或缺的一部分&#xff0c;它们旨在帮助组织监控、管理、审计员工的互联网使用情况&#xff0c;确保网络资源的合理利用&#xff0c;提高工作效率&#xff0c;同时维护企业信息安全。下面将介绍几款市场上知名的上网行为审计软件&#xff0c;…

通用大模型VS垂直大模型 难兄难弟?

在互联网&#x1f30f;背景下的快速发展与人工智能AI的崛起是21世纪科技进步的重要标志&#x1f3c5;&#xff0c; 近年来&#xff0c;随着计算能力的显著提升&#x1f680;、海量数据的积累以及算法创新&#xff0c;尤其是深度学习技术的突破&#xff0c;人工智能领域迎来了…

Windows 与 Java 环境下的 Redis 利用分析

1 前言 在最近的一次攻防演练中&#xff0c;遇到了两个未授权访问的 Redis 实例。起初以为可以直接利用&#xff0c;但后来发现竟然是Windows Java (Tomcat)。因为网上没有看到相关的利用文章&#xff0c;所以在经过摸索&#xff0c;成功解决之后决定简单写一写。 本文介绍了…

树莓派pico入坑笔记,快捷键键盘制作

使用usb_hid功能制作快捷键小键盘&#xff0c;定义了6个键&#xff0c;分别是 ctrlz ctrlv ctrlc ctrla ctrlw ctrln 对应引脚 board.GP4, board.GP8, board.GP13 board.GP28, board.GP20, board.GP17 需要用到的库&#xff0c;记得复制进单片机存储里面 然后是main主程…

【leetcode刷题】面试经典150题 88.合并两个有序数组

leetcode刷题 面试经典150 88. 合并两个有序数组 难度&#xff1a;简单 文章目录 一、题目内容二、自己实现代码2.1 实现思路2.2 实现代码2.3 结果分析 三、 官方解法3.1 直接合并后排序3.1.1 算法实现3.1.2 代码实现3.1.3 代码分析 3.2 双指针3.2.1 算法实现3.2.2 代码实现3.2…

列表(list)(Python)

文章目录 一、定义二、列表常用操作 一、定义 list ["张三", "李四", "王五", "赵六"]二、列表常用操作 分类关键字/函数/方法说明增加列表.append(值)在列表末尾追加值列表.insert(索引&#xff0c; 值)在指定位置插入值&#xff…

从11个视角看全球Rust程序员1/4:深度解读JetBrains最新报告

讲动人的故事,写懂人的代码 五个月前,编程界的大佬JetBrains发布了他们的全球开发者年度报告。 小吾从这份报告中找出了下面11个关于全球程序员如何使用Rust的有趣的趋势,让你学习和使用Rust更轻松。 1 这两年有多少程序员在工作中使用了Rust? 2 全球程序员使用Rust有多…