首页/新闻资讯/正文详情

IronOS Pinecil V2 BLE 蓝牙接口开发指南:三大 GATT 服务、UUID 规范与源码实现解析

发布时间:2026/9/25 11:07:11 来源:云帆数科 栏目:资讯中心
IronOS Pinecil V2 BLE 蓝牙接口开发指南:三大 GATT 服务、UUID 规范与源码实现解析
嵌入式固件硬件开发智能硬件【免费下载链接】IronOSOpen Source Soldering Iron firmware项目地址https://gitcode.com/gh_mirrors/ir/IronOS点击查看免费下载本文基于 IronOS 仓库的 Documentation/Bluetooth.md 编写系统讲解 Pinecil V2 焊台固件的 BLEBluetooth Low EnergyGATT 接口三个服务的 UUID 布局与数据编码、Live/Settings/Bulk 各特征的完整读取方式、保存与重置端点的写入协议、三档 BLE 模式Off/On/Read-only的语义与源码级拦截实现。读完后你可以直接为焊台开发一个监控或控制集成如烟雾净化器联动、温度遥测面板并理解 IronOS 固件内部对应的注册、回调与广播代码做到协议与实现双向对照。适用设备与 BLE 使能机制BLE 硬件支持目前仅存在于Pinecil V2。从源码结构看该能力由 BSP 层编译开关控制只有 Pinecilv2 的板级配置定义了#define BLE_ENABLED见 configuration.h其他 BSP 目录TS100、MHP30、Pinecil V1 等没有此宏系统启动完成 RTOS 初始化后postRTOSInit()会检查BluetoothLE设置项非 0 即调用ble_stack_start()启动 BLE 协议栈postRTOS.cpp。协议栈初始化本身很简单初始化 8KB EM 内存模式、BLE 控制器与 HCI host然后bt_enable(bt_enable_cb)ble.c。BLE 行为由Advanced 菜单中的BluetoothLE设置项控制该设置项在SettingsOptions枚举中固定为索引37Settings.h默认 0、取值范围 0–2settings.yaml。三种模式的语义为值模式行为0Off完全关闭不广播、不连接1On完全访问所有特征可读写、设置可改可存2Read-only广播并接受连接所有特征可读但一切写操作被拒绝Read-only 模式模式 2的定位很明确允许烟雾净化器等监控工具读取实时温度却阻止远端修改温度、设置或触发保存/重置。其实现位于所有设置写回调的最前端——当BluetoothLE 2时直接返回BT_ATT_ERR_WRITE_NOT_PERMITTED见 ble_handlers.cpp。同时文档强调BLE 模式只能从设备本地菜单修改本地菜单项定义见 settingsGUI.cpp远端无法解锁自己。一个容易忽略的实现细节在本地菜单中把 BLE 从 Off 切到非 Off或反向后保存设置固件会主动reboot()使协议栈状态生效Settings.cpp 中的checkBLERebootNeeded。在 On 与 Read-only 之间切换则不需要重启。菜单显示逻辑上0 显示不可用图标1 显示 On2 显示 Read-onlysettingsGUI.cpp。广播、设备发现与轮询要求Pinecil 系列设备在 BLE 上广播的名称形如Pinecil-XXXXXXXX。源码中该名称并非随机生成而是由设备 ID 上下 32 位异或后以 8 位十六进制拼接// source/Core/BSP/Pinecilv2/ble_peripheral.c uint32_t scratch getDeviceID() 0xFFFFFFFF; scratch ^ (getDeviceID() 32) 0xFFFFFFFF; int nameLen snprintf(nameBuffer, 16, Pinecil-%08X, (int)scratch);广播advertisement数据包含标志位与完整设备名扫描响应数据则携带Bulk 服务的 128-bit UUID用于过滤ble_peripheral.c。因此文档给出的第一条集成建议是尽量按 UUID9eae1000-9d0d-48c5-AA55-33e27f9bc533过滤设备而不是按设备名——该 UUID 在扫描响应中是协议级承诺设备名则可能随命名规则变化。另外两点与轮询/吞吐直接相关的实现事实通知Notification/Indication当前未完整实现。从 GATT 属性表看三个服务的全部特征仅注册了BT_GATT_CHRC_READ属性ble_peripheral.c没有BT_GATT_CHRC_NOTIFY所以客户端必须轮询读数。文档也明确说明这一点提示后续版本才会补充通知支持——集成代码不要把等推送作为唯一手段应保留轮询路径。连接建立后固件会执行数据长度扩展bt_le_set_data_len251 字节窗口并发起 MTU 交换ble_peripheral.c。这意味着连接态下单次读 Bulk 端点可以一次带回完整数据配合下文 Bulk 服务可显著减少轮询次数。断开连接后自动恢复广播ble_peripheral.c。除非另有说明所有数据以小端Little-Endian编码收发。GATT 服务总览BLE 接口共暴露三个 GATT 服务定义见 ble_characteristics.h服务服务 UUID用途Lived85ef000-168e-4a71-AA55-33e27f9bc533每个实时读数一个特征逐项轮询Bulk9eae1000-9d0d-48c5-AA55-33e27f9bc533变长数据整块实时数据、固件版本、序列号等Settingsf6d80000-5a10-4eba-AA55-33e27f9bc533设置项读写固定 16 位 保存/重置端点Live 服务14 个实时读数特征Live 服务的 UUID 前缀为d85ef0每个特征对应一个读数特征编号即 UUID 末四位d85ef001–d85ef00e。所有读数统一编码为无符号 32 位整数。按编号顺序为#特征UUID 尾部源码取数逻辑ble_handlers.cpp单位/含义1实时温度d85ef001TipThermoModel::getTipInC()℃整数2设定温度d85ef002getSettingValue(SolderingTemp)℃3DC 输入电压d85ef003getInputVoltageX10(...)0.1 Vx10 定点4手柄温度d85ef004getHandleTemperature(0)℃5功率级别d85ef005X10WattsToPWM(x10WattHistory.average())PWM 占空比换算值6电源来源d85ef006getPowerSrc()枚举见下7烙铁头电阻d85ef007getTipResistanceX10()0.1 Ωx10 定点8运行时长d85ef008xTaskGetTickCount() / TICKS_100MS0.1 s十分之一秒9最后运动时刻d85ef009lastMovementTime / TICKS_100MS0.1 s自启动起10可设定最高温d85ef00ATipThermoModel::getTipMaxInC()℃11烙铁头原始读数d85ef00BconvertTipRawADCTouV(...)μV 原始电压12霍尔传感器d85ef00Cabs(getRawHallEffect())强度绝对值int16 取绝对后装进 u3213运行模式d85ef00D(uint32_t)currentOperatingModeOperatingMode枚举值14估算功率d85ef00Ex10WattHistory.average()0.1 Wx10 定点几个需要特别注意的编码约定x10 定点法输入电压、烙铁头电阻、估算功率都乘以 10 取整传输解析时除以 10 即可时间单位是 0.1 秒TICKS_100MS不是秒电源来源枚举由 getPowerSrc() 产生0DC 电源、1QC非 PD 快充、2PD 已协商且 VBUS 已接通、3PD 已协商VBUS 未检测文档提醒部分读数含义不直观可参考设备 Debug 菜单中对应项的标注来理解每个值的实际物理意义。Settings 服务编号即设置、固定 16 位读写Settings 服务把设备的全部设置暴露为固定编号特征UUID 格式为f6d7ZZZZ-5a10-4eba-AA55-33e27f9bc533其中ZZZZ为十六进制的设置编号与 Settings.h 中SettingsOptions枚举的索引一一对应例如BluetoothLE是 37即特征f6d70025-...。所有设置值都以固定无符号 16 位整数读取和写入。哪些设置可通过 BLE 访问从特征表定义看ble_characteristics.h 及 ble_peripheral.c当前固件暴露的设置编号为0–38 以及 53、54。这不是随意的读回调对超出SettingsOptionsLength的编号统一返回0xFFFF作为未知哨兵值ble_handlers.cpp。这直接对应文档给集成者的第 4、5 条建议编号与设置的对应关系是固定的但固件版本演进可能新增你尚不认识的编号——客户端必须能容忍读到一个未知编号的设置而不崩溃但不要把这些未知设置直接展示给用户静默保留即可。写入设置的生效方式与 OLED 副作用写入路径ble_handlers.cpp要求载荷恰好 2 字节len 2随后调用setSettingValue()立即生效于运行时状态。值得注意的是三个会同步硬件 UI 的特殊分支写入的设置固件即时副作用OLEDInversionOLED::setInverseDisplay()反转显示OLEDBrightnessOLED::setBrightness()调整亮度OrientationModeOLED::setRotation()按最低位旋转屏幕也就是说远端改这些设置时本地 OLED 会立刻跟着变这既是所见即所得的验证手段也是调试集成是否写对的快速通道。Settings save保存端点向f6d7FFFF-5a10-4eba-AA55-33e27f9bc533写入0x0001触发saveSettings()把当前设置落到内部 Flashble_handlers.cpp。文档明确建议不要每次改动都保存应提供保存按钮或超时批量保存——原因是要减少内部 Flash 的写周期Flash 擦写寿命有限。固件侧的saveSettings()采用 memcmp 判重只有内存中的设置与 Flash 页内容不同才真正执行擦写Settings.cpp但远端高频写0x0001仍会不断制造新差异。Settings reset重置端点向f6d7FFFE-5a10-4eba-AA55-33e27f9bc533写入0x0001触发resetSettings()立即把所有设置恢复为出厂默认值ble_handlers.cpp。客户端 UI 上建议对这一操作加确认提示因为它不可撤销且即时生效。Bulk 服务整块遥测与设备身份信息Bulk 服务9eae1000-9d0d-48c5-AA55-33e27f9bc533承载变长数据实现见 ble_char_read_bulk_value_callback#特征UUID 尾部数据1Live data9eae1001Live 服务全部 14 项读数打包成一个二进制块2Accelerometer Name9eae1002尚未实现源码中为 TODO读返回 0 字节3Build ID9eae1003固件版本字符串BUILD_VERSION4Device Serial Number9eae100464 位设备序列号5Device Unique ID9eae100532 位工厂烧录的唯一 IDLive data一次读取代替 14 次9eae1001返回的块是 14 个 u32 按 Live 服务相同顺序排列的小端数组共 56 字节// ble_handlers.cpp 中 bulkData 数组的顺序与 Live 服务编号一一对应 uint32_t bulkData[] { 当前温度, 设定温度, 输入电压x10, 手柄温度x10, 功率(PWM), 电源来源, 铁头电阻x10, 运行时长(0.1s), 最后运动(0.1s), 最高温, 铁头原始电压(μV), 霍尔强度, 运行模式, 估算功率x10 };回调实现了带offset的分片拷贝客户端可以按 MTU 分块读取ble_handlers.cpp。文档给出的取舍建议是要展示大量数据时优先读 Bulk1 次读 ≈ 14 次单特征读只更新其中一两项时直接读 Live 服务对应特征反而更省。两者可以都试按实际数据量选择。Build ID / 序列号 / 唯一 ID 的工程含义Build ID9eae1003返回BUILD_VERSION字符串去掉了末尾\0。文档强调集成方必须读取并解码固件版本——一旦 BLE 协议格式演进客户端需要靠版本号选择解码策略Device Serial Number9eae100464 位整数取自getDeviceID()即芯片 EF 中的 Chip IDBSP.cpp在 Pinecil V2 上等效于 MAC 地址绝大多数设备可直接当唯一标识用Device Unique ID9eae1005Pinecil V2 专有是工厂烧录的 32 位随机 IDEF_Ctrl_Get_Key_Slot_w1()BSP.cpp官方在线真伪校验工具依赖该 ID 查库验证。集成实践清单来自官方文档把文档中Using the BLE Interface一节整理为可执行清单供新集成逐项核对过滤设备优先按 UUID9eae1000-9d0d-48c5-AA55-33e27f9bc533过滤而不是设备名首次连接后自检确认三个预期服务Lived85ef000-...、Settingsf6d80000-...、Bulk9eae1000-...都存在缺失即提示用户选错了设备数据读取策略大量展示数据 → 轮询 Bulk 的9eae1001只刷新少数项 → 读 Live 单特征容忍未知设置编号编号↔设置映射固定但新固件可能引入新编号读取逻辑必须兼容隐藏未知设置内部保留即可不要渲染给用户读取并解码 Build ID协议可能随版本修订客户端按版本协商解码方式持续关注 IronOS 仓库的发布动态未来版本可能调整 BLE 细节或新增设置项。关键源码文件索引文件内容ble_characteristics.h三个服务与全部特征的 128-bit UUID 定义协议事实来源ble_peripheral.cGATT 属性表注册、广播参数、设备名生成、连接后数据长度/MTU 处理ble_handlers.cpp各特征读写回调、Read-only 拦截、保存/重置、电源来源枚举ble.cble_stack_start()BLE 控制器与 Host 协议栈初始化postRTOS.cpp按BluetoothLE设置决定是否启动 BLE 栈Settings.h / settings.yaml设置项枚举编号与BluetoothLE0–2取值范围Settings.cppsaveSettings()/resetSettings()语义与 BLE 模式切换重启逻辑BSP.cppgetDeviceID()Chip ID/MAC与getDeviceValidation()工厂烧录 ID适用前提与限制以上所有协议细节以当前仓库版本为准仅适用于 Pinecil V2BL702 平台BLE_ENABLED开启通知机制尚未实现客户端必须以轮询为前提设计设置编号暴露范围0–38、53、54会随固件版本演进集成方应依赖第 4、6 条清单项做前向兼容。赞分享嵌入式固件硬件开发智能硬件【免费下载链接】IronOSOpen Source Soldering Iron firmware项目地址https://gitcode.com/gh_mirrors/ir/IronOS点击查看免费下载相关推荐ESP IoT Solution 蓝牙人体成分服务BLE BCS开发指南从 GATT 服务实现到指示上报实战ESP IoT Solution 蓝牙人体成分服务BLE BCS开发指南从 GATT 服务实现到指示上报实战 本文基于 esp iot solution物联网嵌入式驱动开发硬件开发esp-iot-solution 的 BLE-MIDI Profile 组件在 ESP32 上实现蓝牙 MIDI 收发与 GATT 服务esp iot solution 的 BLE MIDI Profile 组件在 ESP32 上实现蓝牙 MIDI 收发与 GATT 服务 导读 ble_mid物联网嵌入式驱动开发硬件开发esp-iot-solution 蓝牙心率服务BLE Heart Rate Service开发指南从 GATT 服务注册到心率通知实现esp iot solution 蓝牙心率服务BLE Heart Rate Service开发指南从 GATT 服务注册到心率通知实现 导读 本文围绕 e物联网嵌入式驱动开发硬件开发上一篇革命性突破AI驱动的Verilog代码生成技术如何重塑硬件设计工作流下一篇Minecraft服务器性能优化的三大挑战与Spark解决方案从卡顿诊断到性能调优创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

cuDF 字符串复制(strings_copy)API 完全指南:repeat_strings 重复字符串操作详解
cuDF 字符串复制(strings_copy)API 完全指南:repeat_strings 重复字符串操作详解

数据分析数据工程机器学习 【免费下载链接】cudf cuDF - GPU DataFrame Library 项目地址: https://gitcode.com/gh_mirrors/cu/cudf 点击查看 免费下载 导读 本文聚焦 cuDF C(libcudf)字符串模块中的 Copying(字符串复制&… · 2026/9/25 11:07:11

DeskcommCRM深度拆解:用沟通驱动客户关系管理的实战指南
DeskcommCRM深度拆解:用沟通驱动客户关系管理的实战指南

做客户管理系统最怕什么?不是功能不够多,而是功能太多了,销售不愿意用,最后沦为一个昂贵的Excel仓库。我见过太多团队砸钱上Salesforce或者自研系统,结果一线压根不买账,数据不录、跟进不写、客户资料散落在… · 2026/9/25 11:07:11

从Excel到通讯型CRM:客户支持体系全渠道落地的实践与避坑指南
从Excel到通讯型CRM:客户支持体系全渠道落地的实践与避坑指南

我是在去年底把团队的客户支持体系从"微信群 两张Excel表 一个旧CRM"硬生生迁移到 DeskcommCRM 的。折腾了三个多月,踩了无数坑,但也确实把客服从天天当人肉交换机、天天翻聊天记录找上下文的泥潭里捞了出来。这篇不写厂商宣传稿&#xff0c… · 2026/9/25 11:07:05

Photoshop改尺寸不糊指南:图像大小、画布大小、裁剪与导出全解析
Photoshop改尺寸不糊指南:图像大小、画布大小、裁剪与导出全解析

在修图这件事上,尺寸调整看似是最基础的操作,但我见过太多人栽在这一步。有人把手机拍的40003000照片直接拖进电商详情页模板,结果主体糊成一团;有人为了发朋友圈把图缩到800像素宽,回头想打印时发现原图已经覆盖保存&… · 2026/9/25 11:38:56

微信PC多开防撤回技术原理深度解析
微信PC多开防撤回技术原理深度解析

1. 这个“多开防撤回版”到底是什么东西?先说清楚它不是什么最近在各种技术论坛、软件分享站和群文件里,频繁刷到“微信最新PC版 v4.1.15.09 多开防撤回版”这类标题。很多人第一反应是:终于能像QQ一样开多个微信窗口了?还能看到别… · 2026/9/25 11:38:56

Kali Linux WiFi渗透实战:从监听模式到握手包破解
Kali Linux WiFi渗透实战:从监听模式到握手包破解

说到 Kali,很多新手的第一个反应就是“这系统挺牛,好像能搞 WiFi 密码”。我在网络安全这条路上走了差不多十年,工具越用越多,但每次带新人入门,我都会先把这句话说清楚:Kali 本身只是一把工具,… · 2026/9/25 11:38:56

sinon sandbox.stub() 完全指南:非函数属性 Stubbing 与自动恢复
sinon sandbox.stub() 完全指南:非函数属性 Stubbing 与自动恢复

测试开发工具 【免费下载链接】sinon Test spies, stubs and mocks for JavaScript. 项目地址: https://gitcode.com/gh_mirrors/si/sinon 点击查看 免费下载 本文围绕 Sinon 沙箱(Sandbox)API 中的 sandbox.stub() 方法展开,讲解… · 2026/9/25 11:38:49

客户管理系统落地实践:桌面端CRM设计、自动化与数据安全
客户管理系统落地实践:桌面端CRM设计、自动化与数据安全

做了这么多年的客户管理系统落地,我一直觉得CRM这个品类被不少团队走偏了:不是功能堆得越多越好,而是真正贴合一线人员的工作习惯和信息流转方式才能用起来。DeskcommCRM是我前几年主导设计并落地的一套桌面端客户关系管理系统,英… · 2026/9/25 11:38:49

一篇论文能“真”到什么程度?云智变AI功能验证清单一份“看起来很对”的论文,到底缺了什么
一篇论文能“真”到什么程度?云智变AI功能验证清单一份“看起来很对”的论文,到底缺了什么

先抛一个问题。 把一篇AI生成的论文和一篇人类学者写的论文放在一起,让有经验的审稿人来判断,通常不出三段就能分辨。不是因为语言水平——现在的大模型写出来的学术句式,流畅度早就超过大部分研究生。区分它们的是另一个东西: … · 2026/9/25 11:38:31

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码