【ESP32】ESP-IDF开发 | 低功耗蓝牙开发 | GATT规范和ATT属性协议 + 电池电量服务例程
1. 简介
低功耗蓝牙中最为核心的部分当属 GATT(Generic Attribute Profile),全称通用属性配置文件。而 GATT 又是建立在 ATT 协议(属性协议)的基础之上,为 ATT 协议传输和存储的数据建立了通用操作和框架。GATT 和 ATT 并不针对特定的传输协议,可在经典蓝牙和低功耗蓝牙中使用。不过,它们是必须在低功耗蓝牙中实施的,因为低功耗蓝牙用于发现服务。
GATT 定义了两种角色: 服务器(Server)和客户端(Client)。GATT 服务器存储通过ATT 协议传输的数据,并接受来自 GATT 客户端的 ATT 协议请求、命令和确认。GATT 服务器发送对请求的响应,并在 GATT 服务器发生指定事件时,根据配置向 GATT 客户端异步发送指示和通知。
1.1 ATT协议
低功耗蓝牙里面的数据以属性 (Attribute) 的方式存在,每条属性由四个元素组成——属性句柄(Attribute Handle)、属性类型(Attribute UUID)、属性值(Attribute Value)和属性许可(Attribute Permissions)。
- 属性句柄:可以通俗理解为属性的序号,例如第⼀个属性的句柄是0x0001,第二个属性的句柄是 0x0002,以此类推,最大可以到 0xFFFF;
- 属性类型:每个数据有自己需要代表的意思,例如温度、发射功率、电池等等。这个类型是以UUID的形式来表示的,有16bit和128bit两种长度,蓝牙组织(Bluetooth SIG)负责对常用的一些数据类型进行归类;
- 属性值:这个部分就是数据本身,长度可以是固定的,也可以是可变的;
- 属性许可:每个属性对各自的属性值有相应的访问限制,比如有些属性是可读的、有些是可写的、有些是可读又可写的等等。拥有数据的一方可以通过属性许可,控制本地数据的可读写属性。
1.2 GATT规范
ATT 属性协议规定了在低功耗蓝牙中的最小数据存储单位,而 GATT 规范则定义了如何用特性值和描述符表示一个数据,如何把相似的数据聚合成服务(Service),以及如何发现对端设备拥有哪些服务和数据。
GATT 规范引进了特性(Charateristic)的概念。这是由于在某些时候,一个数据可能并不只是单纯的数值,还会带有一些额外的信息。比如,这个数据的单位、这个数值的名称等等。
一个特性包含特性声明(Characteristic Declaration)、特性数值(Characteristic Value)和描述符(Descriptor)。
- 特性声明:用于告诉对方此声明后面跟的内容为特性数值。
- 特征数值:用于承载特性的真正内容。
- 描述符:对特性进行进⼀步的描述,每个特性可以有多个描述符,也可以没有描述符。
2. 例程
这个例程会建立一个标准的 GATT 和 ATT 通信环境,然后注册一个电池电量服务。使能ESP32作为服务器,启动后不断广播让周围的设备连接自己;然后我们使用手机上的测试APP连接ESP32,并读取电池电量服务中的数据。
2.1 menuconfig
ESP32是默认不使能蓝牙功能的,因此要配置menuconfig来使能。首先,使能蓝牙控制器为仅低功耗蓝牙。
然后,使能协议栈为NimBLE。
保存配置后建议清除原有的CMake缓存,重新配置,不然静态语言检查可能会不生效。
2.2 代码
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
#include <stdbool.h>#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"#include "nvs.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_log.h"#include "host/ble_gap.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "services/bas/ble_svc_bas.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"#define TAG "app"
#define OWN_NAME "ESP32"#define BDASTR "%02X:%02X:%02X:%02X:%02X:%02X"
#define BDA2STR(x) (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5]static uint8_t ble_addr_type;
static TaskHandle_t bas_task_handle;
static uint8_t device_name[] = OWN_NAME;static void ble_advertise(void);
static int ble_gap_event(struct ble_gap_event *event, void *arg);
static void ble_on_reset(int reason);
static void ble_on_sync(void);
static void ble_host_task(void *param);
static void bas_task(void* args);static void ble_advertise(void)
{ int rc;struct ble_hs_adv_fields fields;memset(&fields, 0, sizeof(fields));/* 标志位 */fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;/* 发射功率 */fields.tx_pwr_lvl_is_present = 1;fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;/* 设备名 */fields.name = device_name;fields.name_len = strlen(OWN_NAME);fields.name_is_complete = 1;/* UUID */fields.uuids16 = (ble_uuid16_t[]) {BLE_UUID16_INIT(BLE_SVC_BAS_UUID16)};fields.num_uuids16 = 1;fields.uuids16_is_complete = 1;rc = ble_gap_adv_set_fields(&fields);if (rc != 0) {ESP_LOGE(TAG, "error setting advertisement data; rc=%d", rc);return;}/* 开始广播 */struct ble_gap_adv_params adv_params;memset(&adv_params, 0, sizeof(adv_params));adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;rc = ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL);if (rc != 0) {ESP_LOGE(TAG, "error enabling advertisement, rc=%d", rc);return;}
}static int ble_gap_event(struct ble_gap_event *event, void *arg)
{int rc = 0;switch (event->type) {/* 连接建立事件 */case BLE_GAP_EVENT_LINK_ESTAB:ESP_LOGI(TAG, "connection %s, status=%d",event->connect.status == 0 ? "established" : "failed",event->connect.status);if (event->connect.status != 0) {ble_advertise();} else {xTaskCreate(bas_task, "bas_task", 2048, NULL, 5, &bas_task_handle);}break;/* 连接断开事件 */case BLE_GAP_EVENT_DISCONNECT:ESP_LOGI(TAG, "disconnect, reason=%d", event->disconnect.reason);if (bas_task_handle != NULL) {vTaskDelete(bas_task_handle);}ble_advertise();break;/* 广播完成事件 */case BLE_GAP_EVENT_ADV_COMPLETE:ESP_LOGI(TAG, "advertise complete");ble_advertise();break;/* 订阅事件 */case BLE_GAP_EVENT_SUBSCRIBE:ESP_LOGI(TAG, "subscribe event, cur_notify=%d, val_handle=%d",event->subscribe.cur_notify,event->subscribe.attr_handle);break;/* MTU更新事件 */case BLE_GAP_EVENT_MTU:ESP_LOGI(TAG, "mtu updated, conn_handle=%d mtu=%d",event->mtu.conn_handle,event->mtu.value);break;default:break;}return rc;
}static void ble_on_reset(int reason)
{ESP_LOGE(TAG, "Resetting state; reason=%d", reason);
}static void ble_on_sync(void)
{int ret;/* 获取最佳地址类型 */ret = ble_hs_id_infer_auto(0, &ble_addr_type);if (ret) {ESP_LOGE(TAG, "ble_hs_id_infer_auto failed, err: %d", ret);return;}/* 获取地址 */uint8_t addr_val[6] = {0};ret = ble_hs_id_copy_addr(ble_addr_type, addr_val, NULL);if (ret) {ESP_LOGE(TAG, "ble_hs_id_copy_addr failed, err: %d", ret);return;}ESP_LOGI(TAG, "Device address: " BDASTR, BDA2STR(addr_val));/* 使能广播 */ble_advertise();
}static void ble_host_task(void *param)
{nimble_port_run();nimble_port_freertos_deinit();
}static void bas_task(void* args)
{while (1) {for (uint8_t i = 0; i <= 10; i++) {ble_svc_bas_battery_level_set(i * 10);ESP_LOGI(TAG, "set battery level to %d", i * 10);vTaskDelay(2000 / portTICK_PERIOD_MS);}}
}int app_main()
{/* 初始化NVS */esp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ESP_ERROR_CHECK(nvs_flash_init());}/* 初始化控制器和NimBLE协议栈 */ret = nimble_port_init();if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to init nimble %d ", ret);return -1;}/* 使能电池电量服务 */ble_svc_bas_init();/* 配置主机 */ble_hs_cfg.reset_cb = ble_on_reset;ble_hs_cfg.sync_cb = ble_on_sync;ble_hs_cfg.store_status_cb = ble_store_util_status_rr;/* 使能绑定 */ble_hs_cfg.sm_bonding = 1;ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;ble_hs_cfg.sm_sc = 1;ble_hs_cfg.sm_mitm = 1;/* 设置设备名 */if (ble_svc_gap_device_name_set(OWN_NAME) != 0) {ESP_LOGE(TAG, "set device name failed");return -1;}/* 使能NimBLE协议栈 */nimble_port_freertos_init(ble_host_task);return 0;
}
在上一篇文章中已经介绍了低功耗蓝牙 GAP 协议相关的代码编写,所以下面就不再赘述。
在初始化蓝牙控制器和NimBLE协议栈后,调用 ble_svc_bas_init 函数即可初始化电池电量服务,NimBLE协议栈封装了大部分常用的服务接口,基本上可以即用。
接着配置相关的回调函数,一个是 reset_cb ,这个是在设备复位时会调用,这里就是简单打印一个log;另一个是 sync_cb ,这个是协议栈刚启动和复位时会调用的,这里面首先会调用 ble_hs_id_infer_auto 函数去获取当前设备的最佳地址类型,然后调用 ble_advertise 去使能广播。
使能广播前需要配置一个结构体,定义如下:
struct ble_hs_adv_fields {/*** 0x01 - Flags. */uint8_t flags;/*** 0x02,0x03 - 16-bit service class UUIDs. */const ble_uuid16_t *uuids16;uint8_t num_uuids16;unsigned uuids16_is_complete:1;/*** 0x04,0x05 - 32-bit service class UUIDs. */const ble_uuid32_t *uuids32;uint8_t num_uuids32;unsigned uuids32_is_complete:1;/*** 0x06,0x07 - 128-bit service class UUIDs. */const ble_uuid128_t *uuids128;uint8_t num_uuids128;unsigned uuids128_is_complete:1;/*** 0x08,0x09 - Local name. */const uint8_t *name;uint8_t name_len;unsigned name_is_complete:1;/*** 0x0a - Tx power level. */int8_t tx_pwr_lvl;unsigned tx_pwr_lvl_is_present:1;/*** 0x0d - Slave connection interval range. */const uint8_t *slave_itvl_range;/*** 0x10 - Security Manager TK value */const uint8_t *sm_tk_value;unsigned sm_tk_value_is_present:1;/*** 0x11 - Security Manager OOB flag */uint8_t sm_oob_flag;unsigned sm_oob_flag_is_present:1;/*** 0x14 - 16-bit service soliciation list. */const ble_uuid16_t *sol_uuids16;uint8_t sol_num_uuids16;/*** 0x15 - 128-bit service solicitation UUIDs. */const ble_uuid128_t *sol_uuids128;uint8_t sol_num_uuids128;/*** 0x16 - Service data - 16-bit UUID. */const uint8_t *svc_data_uuid16;uint8_t svc_data_uuid16_len;/*** 0x17 - Public target address. */const uint8_t *public_tgt_addr;uint8_t num_public_tgt_addrs;/*** 0x18 - Random target address. */const uint8_t *random_tgt_addr;uint8_t num_random_tgt_addrs;/*** 0x19 - Appearance. */uint16_t appearance;unsigned appearance_is_present:1;/*** 0x1a - Advertising interval. */uint16_t adv_itvl;unsigned adv_itvl_is_present:1;/*** 0x1b - LE Bluetooth device address */const uint8_t *device_addr;unsigned device_addr_type;unsigned device_addr_is_present:1;/*** 0xF1 - 32-bit service solicitation UUIDs */const ble_uuid32_t *sol_uuids32;uint8_t sol_num_uuids32;/*** 0x1c - LE Role */uint8_t le_role;unsigned le_role_is_present:1;/*** 0x20 - Service data - 32-bit UUID. */const uint8_t *svc_data_uuid32;uint8_t svc_data_uuid32_len;/*** 0x21 - Service data - 128-bit UUID. */const uint8_t *svc_data_uuid128;uint8_t svc_data_uuid128_len;/*** 0x24 - URI. */const uint8_t *uri;uint8_t uri_len;/*** 0xff - Manufacturer specific data. */const uint8_t *mfg_data;uint8_t mfg_data_len;
};
这个结构体非常长,这个例程里面我们只需关注标志位(Flags)、UUID、本地名称(Local Name)和发射功率这几个部分。
标志位目前支持以下几个:
#define BLE_HS_ADV_F_DISC_LTD 0x01 // 限制性发现模式
#define BLE_HS_ADV_F_DISC_GEN 0x02 // 普通发现模式
#define BLE_HS_ADV_F_BREDR_UNSUP 0x04 // 禁用经典蓝牙
UUID是跟使能的服务类型有关的,例程里面的电池电量服务使用的是16bit的UUID,UUID号可以在对应的头文件中找到。
本地名称就是广播时附带的设备名,设置字符串数组和其长度即可。
发射功率一般来说填BLE_HS_ADV_TX_PWR_LVL_AUTO,来让协议栈决定。
配置完结构体后调用 ble_gap_adv_set_fields 写入配置。调用 ble_gap_adv_start 来使能广播;参数一为地址类型;参数二为直接地址,用于定向广播时使用;参数三为广播时长,填BLE_HS_FOREVER表示无限时间;参数四为配置参数,结构体定义如下:
struct ble_gap_adv_params {/** Advertising mode. Can be one of following constants:* - BLE_GAP_CONN_MODE_NON (non-connectable; 3.C.9.3.2).* - BLE_GAP_CONN_MODE_DIR (directed-connectable; 3.C.9.3.3).* - BLE_GAP_CONN_MODE_UND (undirected-connectable; 3.C.9.3.4).*/uint8_t conn_mode;/** Discoverable mode. Can be one of following constants:* - BLE_GAP_DISC_MODE_NON (non-discoverable; 3.C.9.2.2).* - BLE_GAP_DISC_MODE_LTD (limited-discoverable; 3.C.9.2.3).* - BLE_GAP_DISC_MODE_GEN (general-discoverable; 3.C.9.2.4).*/uint8_t disc_mode;/** Minimum advertising interval, if 0 stack use sane defaults */uint16_t itvl_min;/** Maximum advertising interval, if 0 stack use sane defaults */uint16_t itvl_max;/** Advertising channel map , if 0 stack use sane defaults */uint8_t channel_map;/** Advertising Filter policy */uint8_t filter_policy;/** If do High Duty cycle for Directed Advertising */uint8_t high_duty_cycle:1;
};
- conn_mode:连接模式,BLE_GAP_CONN_MODE_NON(不可连接)、BLE_GAP_CONN_MODE_DIR(直接连接)、BLE_GAP_CONN_MODE_UND(非直接连接);
- disc_mode:发现模式,BLE_GAP_DISC_MODE_NON(不可发现)、BLE_GAP_DISC_MODE_LTD(限制性发现)、BLE_GAP_DISC_MODE_GEN(普通发现);
- itvl_min:最小广播间隔,0为协议栈决定;
- itvl_max:最大广播间隔,0为协议栈决定;
- channel_map:通道遮罩,一共有3个通道,填BLE_GAP_ADV_DFLT_CHANNEL_MAP为全开;0为协议栈决定;
- filter_policy:过滤策略;
- high_duty_cycle:高占空比(仅直接广播)。
参数五为回调函数,参数六为回调函数的用户参数。
上面的回调函数是重点,主要处理以下几个GAP事件:
1. 广播完成事件(BLE_GAP_EVENT_ADV_COMPLETE)
当广播程序执行完后触发,理论上我们这里是不会触发的,因为代码里面设置了永不超时的广播。
2. 连接建立事件(BLE_GAP_EVENT_LINK_ESTAB)
当有子节点与广播者建立连接时触发,这里会创建一个电池电量的任务,任务主函数里面就是定时地调用 ble_svc_bas_battery_level_set 来设置电池电量百分比。
3. 连接断开事件(BLE_GAP_EVENT_DISCONNECT)
当有子节点断开连接时触发,这里会删除电池电量任务,并重新使能广播。
4. 订阅事件(BLE_GAP_EVENT_SUBSCRIBE)
当有子节点的订阅状态改变时触发,这里只是打印log。
5. MTU更新事件(BLE_GAP_EVENT_MTU)
当L2CAP协议的某通道MTU长度改变时触发,这里只是打印log。
回到 main 函数,下面继续设置一些安全配对相关的配置。sm_bonding,使能设备绑定功能;sm_our_key_dist,本地键值对遮罩;sm_their_key_dist,远程键值对遮罩;sm_mitm,使能MITM保护协议;sm_sc,使能安全连接。
调用 ble_svc_gap_device_name_set 设置本机的设备名。最后调用 nimble_port_freertos_init 使能NimBLE协议栈。
2.3 运行
下面是部分的运行log。
打开手机的调试上位机,找到我们的ESP32。
连接设备后,可以在“服务”这一栏看到电池电量服务的相关信息。
点击该服务卡片,接收服务的数据,可以看到下面的就会显示ESP32发送过来的服务数据了。
相关文章:

【ESP32】ESP-IDF开发 | 低功耗蓝牙开发 | GATT规范和ATT属性协议 + 电池电量服务例程
1. 简介 低功耗蓝牙中最为核心的部分当属 GATT(Generic Attribute Profile),全称通用属性配置文件。而 GATT 又是建立在 ATT 协议(属性协议)的基础之上,为 ATT 协议传输和存储的数据建立了通用操作和框架。…...

2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题
2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题 (二)A 模块基础设施设置/安全加固(200 分)A-1 任务一登录安全加固(Windows,Linux)A-2 任务二 Nginx 安全策略&…...

【记录】Windows|竖屏怎么调整分辨率使横竖双屏互动鼠标丝滑
本文版本:Windows11,记录一下,我最后调整的比较舒适的分辨率是800*1280。 文章目录 第一步 回到桌面第二步 右键桌面第三步 设置横屏为主显示器第四步 调整分辨率使之符合你的需求第五步 勾选轻松在显示器之间移动光标第六步 拖动屏幕符合物理…...

开源项目实战学习之YOLO11:12.2 ultralytics-models-sam-decoders.py源码分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-decoders.pyblocks.py: 定义模型中的各…...

数据结构*优先级队列(堆)
什么是优先级队列(堆) 优先级队列一般通过堆(Heap)这种数据结构来实现,堆是一种特殊的完全二叉树,其每个节点都满足堆的性质。如下图所示就是一个堆: 堆的存储方式 由于堆是一棵完全二叉树,所以也满足二…...

汽车Wafer连接器:工业设备神经网络的隐形革命者
汽车Wafer连接器正在突破传统车载场景的边界,以毫米级精密结构重构工业设备的连接范式。这款厚度不足3毫米的超薄连接器,在新能源电池模组中承载200A持续电流的同时,仍能保持85℃温升的稳定表现,其每平方厘米高达120针的触点密度&…...

微信小程序:封装表格组件并引用
一、效果 封装表格组件,在父页面中展示表格组件并显示数据 二、表格组件 1、创建页面 创建一个components文件夹,专门用于存储组件的文件夹 创建Table表格组件 2、视图层 (1)表头数据 这里会从父组件中传递表头数据,这里为columns,后续会讲解数据由来 循环表头数组,…...
湖北理元理律师事务所:债务优化中的双维支持实践解析
在债务压力与生活质量失衡的社会议题下,法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式,探索债务优化与生活保障的平衡路径,其方法论或为行业提供实践参考。 法律框架&…...
uniapp在APP上如何使用websocket--详解
UniApp 在 APP 端如何使用 WebSocket以及常见问题 一、WebSocket 基础概念 WebSocket 是一种在单个TCP连接上进行全双工通信的协议,适用于实时数据传输场景(如聊天室、实时游戏、股票行情等)。 与传统HTTP对比 特性WebSocketHTTP连接方式…...
计网| 网际控制报文协议(ICMP)
目录 网际控制报文协议(ICMP) 一、ICMP 基础特性 二、ICMP 报文分类及作用 差错报告报文 询问报文 网际控制报文协议(ICMP) ICMP(Internet Control Message Protocol,网际控制报文协议)是 …...

Conda 完全指南:从环境管理到工具集成
Conda 完全指南:从环境管理到工具集成 在数据科学、机器学习和 Python 开发领域,环境管理一直是令人头疼的问题。不同项目依赖的库版本冲突、Python 解释器版本不兼容等问题频繁出现,而 Conda 的出现彻底解决了这些痛点。作为目前最流行的跨…...

安卓中0dp和match_parent区别
安卓中的 0dp 和 match_parent 的区别? 第一章 前言 有段时间,看到同事在编写代码的时候,写到的是 0dp 有时候自己写代码的时候,编写的是 match_parent 发现有时候效果很类似。 后来通过一个需求案例,才发现两者有着…...
蓝桥杯-不完整的算式
问题描述 小蓝在黑板上写了一个形如 AopBCAopBC 的算式,其中 AA、BB、CC 都是非负整数,opop 是 、-、*、/、-、*、/(整除)四种运算之一。不过 AA、opop、BB、CC 这四部分有一部分被不小心的同学擦掉了。 给出这个不完整的算式&a…...

信贷风控笔记4——贷前策略之额度、定价(面试准备12)
1.贷前模型的策略应用 分类:审批准入(对头尾部区分度要求高):单一规则(找lift>3的分数做规则);二维交叉;拒绝回捞 额度定价(对排序性要求高)&am…...

A级、B级弱电机房数据中心建设运营汇报方案
该方案围绕A 级、B 级弱电机房数据中心建设与运营展开,依据《数据中心设计规范》等标准,施工范围涵盖 10 类机房及配套设施,采用专业化施工团队与物资调配体系,强调标签规范、线缆隐藏等细节管理。运营阶段建立三方协同运维模式,针对三级故障制定30 分钟至 1 小时响应机制…...

Linux中的域名解析服务器
一、DNS(域名系统)详解 1. 核心功能与特点 特性说明核心作用将域名(如 www.example.com)转换为 IP 地址(如 192.168.1.1),实现人类可读地址与机器可读地址的映射。端口与协议- 默认端口&#…...
如何优化Java中十进制字符串转十六进制的性能
在 Java 中优化十进制字符串转十六进制的性能,可以从减少对象创建、避免正则表达式、使用高效数据结构等方面入手。以下是具体的优化方案: 1. 避免字符串分割,直接遍历字符数组 原始方法(频繁创建子字符串)࿱…...

CycleISP: Real Image Restoration via Improved Data Synthesis通过改进数据合成实现真实图像恢复
摘要 大规模数据集的可用性极大释放了深度卷积神经网络(CNN)的潜力。然而,针对单图像去噪问题,获取真实数据集成本高昂且流程繁琐。因此,图像去噪算法主要基于合成数据开发与评估,这些数据通常通过广泛假设的加性高斯白噪声(AWGN)生成。尽管CNN在合成数据集上表现优异…...

Day28 Python打卡训练营
知识点回顾: 1. 类的定义 2. pass占位语句 3. 类的初始化方法 4. 类的普通方法 5. 类的继承:属性的继承、方法的继承 作业 题目1:定义圆(Circle)类 要求: 1. 包含属性:半径 radius。 2. …...
【OpenCV】基本数据类型及常见图像模式
是什么?能做什么?解决什么问题?为什么用它? OpenCV:是一个基于开源发行的跨平台计算机视觉库,实现 一、应用场景: 目标识别:人脸、车辆、车牌...自动驾驶医学影像分析视频内容理解与分析&…...

Linux之Nginx安装及配置原理篇(一)
Nginx安装及配置 前情回顾 首先针对Nginx进程模型,我们回顾一下它的原理机制,我们知道它是通过Master通过fork分发任务节点给予work节点,然后work节点触发了event事件,之后通过一个access_muttex互斥锁,来单线程调用我…...

【Linux网络】NAT和代理服务
NAT 之前我们讨论了,IPv4协议中,IP地址数量不充足的问题。 原始报文途径路由器WAN口时,对报文中的源IP进行替换的过程,叫做NAT。 NAT技术当前解决IP地址不够用的主要手段,是路由器的一个重要功能: NAT能…...

中药药效成分群的合成生物学研究进展-文献精读130
Advances in synthetic biology for producing potent pharmaceutical ingredients of traditional Chinese medicine 中药药效成分群的合成生物学研究进展 摘要 中药是中华民族的文化瑰宝,也是我国在新药创制领域的重要驱动力。许多中药材来源于稀缺物种…...

【消息队列】RabbitMQ基本认识
目录 一、基本概念 1. 生产者(Producer) 2. 消费者(Consumer) 3. 队列(Queue) 4. 交换器(Exchange) 5. 绑定(Binding) 6. 路由键(Routing …...
OCCT知识笔记之OCAF框架详解
OCAF框架在OCCT项目中的构建与使用指南 Open CASCADE Application Framework (OCAF)是Open CASCADE Technology (OCCT)中用于管理CAD数据的核心框架,它提供了一种结构化方式来组织和管理复杂的CAD数据,如装配体、形状、属性(颜色、材料)和元数据等。本文…...
蓝桥杯 16. 外卖店优先级
外卖店优先级 原题目链接 题目描述 “饱了么” 外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有一个优先级,初始时(0 时刻)优先级都为 0。 每经过 1 个时间单位: 如果外卖店没有订单,则优先…...

1T 服务器租用价格解析
服务器作为数据存储与处理的核心设备,对于企业和个人开发者而言至关重要。当涉及到租用 1T 服务器时,价格是大家很为关注的要点。然而,1T 服务器租用一个月的费用并非固定不变,而是受到诸多因素的综合影响。 影响 1T 服务器租用…...

【JavaWeb】Maven(下)
1 依赖管理 1.1 依赖配置 1.1.1 基本配置 依赖:指当前项目运行所需要的jar包。 一个项目中可以引入多个依赖: 例如:在当前工程中,我们需要用到logback来记录日志,此时就可以在maven工程的pom.xml文件中,引…...
java.lang.ArithmeticException
ArithmeticException算术异常类在java.lang包下,继承RuntimeException运行期异常,算术异常类在Java1.0就有,当发生异常算术条件时抛出算术异常类,譬如除数为0的情况,除数除不尽的情况。 一 异常出现场景 1.1 除数为零…...

openEuler24.03 LTS下安装MySQL8.0.42
目录 前提步骤 删除原有mysql及maridb数据库 安装MySQL 启动MySQL 启动查看MySQL状态 设置MySQL开机自启动 查看登录密码 登录MySQL 修改密码及支持远程连接 远程连接MySQL 前提步骤 拥有openEuler24.03 LTS环境,可参考:Vmware下安装openEule…...