万字技术指南STM32F103C8T6 + ESP8266-01 连接 OneNet 平台 MQTT/HTTP
此博客为一份详细的指南,涵盖 STM32F103C8T6 通过 ESP8266-01 连接 OneNet 平台,并使用 MQTT/HTTP 进行数据通信的完整流程。这份文档包括:
- OneNet 平台的介绍与功能概览
- 在 OneNet 上创建和配置设备的方法
- STM32CubeIDE 的开发环境搭建
- ESP8266 AT 指令解析及如何连接 OneNet
- STM32 通过 MQTT 向 OneNet 发送/接收数据的详细实现
- 使用 OneNet API 进行 HTTP 交互的方式
- 从设备到云端再到 App 的完整示例代码及解析
本指南详细讲解如何使用 STM32F103C8T6 微控制器通过 ESP8266-01 WiFi 模块接入中国移动 OneNet 物联网平台,并通过 MQTT 和 HTTP 协议实现数据通信的完整流程。内容涵盖 OneNet 平台简介、设备创建配置、硬件与开发环境准备、ESP8266 AT 指令联网流程、STM32 通过 MQTT 发送/接收数据、移动 App 通过 HTTP 获取数据,以及从设备到云端再到手机 App 的综合示例演示。文中包含详细的步骤、代码示例、配置方法和常见问题解答,帮助读者从零开始完成项目集成。
1. OneNet 物联网平台简介与功能概览
OneNet 平台概述: OneNet 是中国移动提供的物联网开放平台,属于 PaaS(Platform as a Service)层服务。在物联网架构中,OneNet 扮演连接设备终端和上层应用的桥梁角色,为设备侧提供可靠的接入手段,为应用开发者提供丰富的 API 和数据管理能力。开发者可以通过 OneNet 对设备进行在线管理、数据存储分析、命令下发和应用构建。OneNet 支持海量设备的高并发接入,提供 99.9% 的服务可用性保障,同时通过分布式架构和多重机制确保数据安全存储与传输。借助 OneNet,企业和个人开发者能够快速搭建物联网应用,实现设备数据上云和远程监控控制等功能。
主要功能特点: OneNet 平台支持多种主流物联网协议,包括 MQTT、HTTP、LwM2M(NB-IoT)、EDP(设备协议)、TCP 透传、ModBus、JT/T808 等等。这意味着各种类型的终端设备都可以选择合适的协议与平台通信。在资源模型上,OneNet 采用“用户 -> 产品 -> 设备 -> 数据流”的组织架构:每个用户账户下可创建多个产品,每个产品下可添加多个设备,并为每台设备定义数据流、触发器、应用等资源。平台提供数据存储(数据流/数据点)、命令下发、触发器(满足条件自动动作)、应用托管等完整的 IoT 功能。此外,OneNet 通过可视化界面和开放 API,使开发者既能在网页端监控管理设备,也能通过 RESTful API 或 SDK 将平台能力集成到自己开发的 App、服务器中。
MQTT 与 HTTP 在 OneNet 中的应用: MQTT 和 HTTP 是 OneNet 平台最常用的两种设备接入和数据交互方式。MQTT(Message Queuing Telemetry Transport)是一种轻量级发布/订阅模型的消息协议,适合资源受限设备和不稳定网络环境,在 IoT 领域广泛使用。在 OneNet 中,MQTT 通常用于设备实时上线、上传传感数据、接收平台指令等场景。设备通过 MQTT 与 OneNet 的消息Broker保持长连接,采用主题 (Topic) 订阅/发布机制交换数据。OneNet 支持 MQTT 3.1.1 标准协议,并针对设备数据上传和命令下发定义了一系列系统主题格式,使物模型数据的上报和下发更加规范。例如,OneNet 平台允许设备发布传感数据到 $sys/{产品ID}/{设备名称}/thing/property/post 主题,并从 $sys/{产品ID}/{设备名称}/thing/property/set 主题接收下发的属性控制指令。同时,OneNet 也允许设备自由创建和订阅自定义主题,以便实现设备间的消息交互(同一产品内不同设备可订阅彼此发布的主题消息)。相比之下,HTTP 则是一种请求/响应式通信协议,更适合应用服务器或移动App和平台进行交互。OneNet 提供完整的 RESTful 风格 API,允许第三方应用通过 HTTP(S) 请求查询设备数据、下发命令、管理设备等。比如,应用可以通过 HTTP GET 请求获取某设备最新的数据点,或通过 HTTP POST 请求调用 OneNet API 向设备发送命令。由于 HTTP 通信不需要保持长连接,通常设备本身不使用 HTTP 实时上线(除非设备无法使用MQTT而周期性通过HTTP上报数据点),但应用层(如手机App、Web后台)会通过 HTTP API 来获取云端已存储的数据或触发控制操作。
简而言之,OneNet 提供了 MQTT 和 HTTP 两种互补的通信方式:设备侧倾向于使用 MQTT 保持长连接进行实时数据传输和指令接收,而应用侧多通过 HTTP API 实现数据查询和控制下发。在本项目中,我们将利用这两者的配合:STM32+ESP8266 设备以 MQTT 协议将传感数据上传到 OneNet,同时我们的手机 App 则通过 OneNet 的 HTTP API 获取设备数据,实现从传感器到云端再到用户界面的闭环。
2. OneNet 平台上的设备创建与配置
在将设备连入 OneNet 之前,需要先在平台上进行账户注册、产品和设备的创建,并获取相关的身份认证信息(如设备ID和APIKey)。以下是具体步骤:
2.1 注册 OneNet 开发者账户: 打开 OneNet 官方网站 open.iot.10086.cn 并完成账户注册流程。注册时需要提供手机号进行验证。注册成功后,使用账号登录 OneNet,进入平台“开发者中心”。OneNet 平台分为老版和新版界面,当前版本通常需要先点击首页右上角的“控制台”,再选择“前往Studio”进入新版开发者中心 (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)。开发者中心是管理产品和设备的主要界面。
2.2 创建产品: 在开发者中心内,找到“产品管理”或直接点击“添加产品”。根据提示填写产品名称、描述等基本信息。设备接入协议选项非常重要,这里请选择“公开协议产品”并指定MQTT协议(如果你的设备走MQTT)或 HTTP 协议(如果设备打算通过HTTP直连)。对于本项目,我们选择 MQTT 协议,因为设备通过 ESP8266 使用 MQTT 上报数据。此外,联网方式可根据设备使用的网络类型选择(如 WiFi、蜂窝等,影响统计信息,不妨选择 Wi-Fi)。产品创建后,系统会分配一个全局唯一的产品ID。进入产品详情页面,能看到“产品概况”,其中包含“产品ID”等关键信息。请记录下产品ID,后续设备连接和 API 调用都需要它。
2.3 创建设备: 在产品的管理页面下,找到“设备管理”并点击“添加设备”。填写设备名称(例如“STM32_Sensor01”)和设备描述等。每个设备会被分配一个设备ID(一般是纯数字)以及初始鉴权信息。在 OneNet 新版 Studio 平台中,设备鉴权有两种方式:一种是设备有设备秘钥(Device APIKey),另一种是每次连接时使用动态 Token。如果平台生成了设备APIKey(通常在设备详情的鉴权信息中可以查看),建议将它记录下来。有些新版界面可能没有直接显示设备APIKey,而是需要用户使用 OneNet 的 Token 生成工具计算一个 Token 来作为密码(后文详细说明)。**注意:**产品ID、设备ID、设备名称、设备APIKey/鉴权信息都是后续设备 MQTT 连接和 HTTP API 访问所需的重要参数,一定要保存好。在OneNet上,每个设备也可以选择不同接入协议,如果是在 MQTT 协议的产品下添加设备,则默认该设备使用 MQTT 协议接入;如果在 HTTP 产品下,则设备通过HTTP上报数据等。
2.4 设备接入方式介绍: OneNet 支持多协议,最常用的还是 MQTT 和 HTTP。对于MQTT接入,前面已经提到设备连接时需要用到三元组:设备ID(作为客户端ID)、产品ID(作为用户名)、鉴权信息(作为密码)。设备连上 OneNet MQTT Broker 成功后,即可通过发布/订阅主题与平台通信(平台不需要预先创建Topic,除系统主题外皆可动态使用,这简化了开发)。而对于HTTP接入,设备可以通过HTTP请求将数据点上传至 OneNet 的REST API(例如通过POST发送JSON数据),通常需要在HTTP请求的Header中包含API-Key用于鉴权 (轻松使用中移物联网平台Onenet,MQTT协议快速接入实验 - ThingsKit)。HTTP方式也可以用于定期上报数据或让不适合长连接的设备与平台交互。在本项目中,我们主要采用 MQTT 连接实时上传数据,HTTP 则用于应用侧读取数据。但了解HTTP接入也有助于理解OneNet API,例如通过HTTP可以方便地测试数据上传和下发。后续章节会详细介绍通过HTTP API 获取设备数据并在App中显示的过程。
小贴士:如果是首次使用 OneNet 平台,建议先在 OneNet 后台熟悉各项操作:浏览产品概况查看产品ID、在设备列表查看设备ID、在设备详情页查看**鉴权信息(设备秘钥或Token)**等。一旦产品和设备设置完成,并确认这些信息,才能进入下一步的硬件配置和编码。
3. 硬件环境与开发环境准备
在软件配置妥当后,我们需要准备硬件环境(STM32F103C8T6 开发板和 ESP8266-01 模块的连接)以及开发调试所需的软件工具。
3.1 STM32F103C8T6 硬件介绍
STM32F103C8T6 是 STM32F1系列中非常经典的一款 MCU,基于 ARM Cortex-M3 内核,主频 72MHz,拥有64KB Flash和20KB SRAM,以及丰富的片上外设(USART、SPI、I2C、ADC、TIM 等)。由于其性价比高、资源适中,被广泛用于入门开发板(如“蓝色小板” BluePill)。本项目中,我们选用 STM32F103C8T6 作为主控,负责采集传感器数据(例如温湿度)、通过串口与 ESP8266 通信,并处理来自云端的控制指令。请确保您的 STM32 开发板已烧录了合适的 Bootloader 或固件,或者通过 SWD 接口连接了调试器(如 ST-Link),以便我们后续下载程序进行调试。
引脚资源回顾: STM32F103C8T6 有多个通用异步收发器 UART/USART。其中 USART1(PA9 TX, PA10 RX)和 USART2(PA2 TX, PA3 RX)经常用于与外部模块通信或打印日志。由于我们的 ESP8266-01 使用串口通信,需要占用STM32的一个 USART 接口。USART1通常连接ST-Link的虚拟串口用于调试打印,因此我们可选择USART2与 ESP8266 通信(当然,用 USART1 给 ESP8266 通信、USART2 用于调试也行,这取决于具体开发板的引出和需求)。无论选择哪个串口,需要确保STM32能以 ESP8266 默认的波特率通信(ESP8266 默认波特率多为 115200bps,某些版本也可能是9600bps,可通过AT指令配置)。另外,STM32需提供3.3V电源给ESP8266模块,且两个器件共地。
3.2 ESP8266-01 硬件介绍及接线方式
ESP8266-01 模块简介: ESP8266-01(简称 ESP-01)是基于乐鑫 ESP8266 芯片的最小系统WiFi模块。它体积小巧(约 25mm x 14mm),板上有 8 个引脚,包含ESP8266所需的最小Flash存储和天线。ESP-01 自带完整的 TCP/IP 协议栈,可以通过 AT 指令集由外部主控(如 STM32)进行控制,实现 WiFi 联网和数据通信。ESP8266-01 的优点是价格便宜、功耗适中,并且通过 UART 串口即可控制,非常适合作为 MCU 的 WiFi 扩展模块。在默认的 AT 固件下,ESP8266-01 可以执行各种网络操作指令,如连接路由器 (AT+CWJAP)、启动TCP连接(AT+CIPSTART)等。通过升级到最新的 MQTT AT 固件,它甚至直接支持 MQTT 客户端的内置指令,如连接 MQTT 服务器、发布/订阅消息等。本项目将利用 ESP8266-01 以 AT 指令模式连接到 WiFi,并通过 MQTT AT 指令连接 OneNet 平台。
ESP8266-01 引脚定义: ESP-01 有 8 个引脚,典型分布和功能如下 (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客):
- VCC:3.3V 电源输入(切勿使用5V,否则会烧毁模块)。
- GND:电源地。
- TXD:UART 串口数据发送端 (模块发送数据给STM32,接STM32 RX 引脚) (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。
- RXD:UART 串口数据接收端 (模块接收数据,从STM32 TX 引脚获取) (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。
- CH_PD(或 EN):芯片使能引脚,**必须接高电平(3.3V)**使模块工作 (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客) (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。拉低该引脚会让芯片休眠/禁用。
- RST:复位引脚,低电平有效。可以接STM32一个GPIO用于软件复位,或简单地接高电平通过手动断电复位 (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。
- GPIO0:引导引脚0。悬空或拉高= 正常运行模式;拉低= 串口下载模式 (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。平时要确保 GPIO0 不被误拉低,否则模块会进入固件下载模式无法正常运行。通常上电时 GPIO0 接高(内部有上拉可悬空)。
- GPIO2:引导引脚2。需拉高运行(上电时禁止为低) (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。一般直接悬空即可(内部上拉)。
ESP8266-01 与 STM32 连接: 按照上面的引脚功能,连接方式如下 (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客):
- 将 ESP8266-01 的 VCC 引脚接 3.3V 电源。确保电源能提供足够电流(建议至少500mA裕量),因为 ESP8266 WiFi 发射时瞬时电流可达数百毫安。使用稳压的 3.3V 且在模块VCC和GND间加旁路电容以稳定供电。
- GND 接地:连接 ESP8266-01 和 STM32 开发板的地线,保证两者参考电平一致。
- ESP-01 TX 接 STM32 的 RX 引脚(例如 STM32 PA3 若用USART2作为接收) (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。
- ESP-01 RX 接 STM32 的 TX 引脚(例如 STM32 PA2 若用USART2发送) (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。请注意 ESP8266 RX 引脚默认3.3V逻辑,STM32F103也是3.3V GPIO,因此可以直接相连。如果主控是5V逻辑,则需要电平转换。STM32F103C8T6 在3.3V下运行,无需电平转换。
- CH_PD/EN 引脚接 3.3V(可与 VCC 短接)。这个引脚必须为高,等效于使能芯片 (ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客)。可以通过 10k 上拉电阻上拉到3.3V。如果希望STM32控制使能,也可接STM32一个GPIO,但通常直接上拉更简单。
- GPIO0 引脚保持悬空或上拉(默认就有上拉)。若您的模块未集成上拉,可用电阻上拉到3.3V。除非要刷固件,否则无需专门连接STM32引脚。
- GPIO2 引脚一般悬空(内部有上拉即可满足正常启动要求)。
- RST 引脚可以暂时悬空或通过上拉电阻拉高。如果需要STM32复位模块,可以将其接到STM32一个GPIO(通过低脉冲复位)。简化起见也可不接,由需要时断电重启模块代替。
连接后,请仔细检查线路:特别是电源和地要可靠连接,串口交叉连接(TX对RX),CH_PD确实为高电平。一个常见的错误是忘记给 CH_PD 上电,导致模块没有响应;或者串口接反。正确连线后,给模块上电,ESP8266 蓝色指示灯会在上电或复位时闪烁一下(ESP-01 上通常有一个蓝色LED连接在UART TX上,每次串口发送数据会闪烁)。如果有 USB 转TTL 模块,可在PC上通过串口工具接ESP8266测试 AT 指令响应,以确认模块工作正常。
3.3 STM32CubeIDE 的安装及配置
开发环境选择: STM32F103 的开发可以使用多种IDE,例如 Keil MDK、IAR、PlatformIO 等。本指南采用 ST 官方的免费开发环境 STM32CubeIDE,它集成了 STM32CubeMX 图形配置和 Eclipse/CDT 编译调试功能,适合构建 HAL 库或 LL 库项目。如果尚未安装,请从 ST 官方网站下载安装 STM32CubeIDE,安装过程中选择相应的包支持 STM32F1 系列。
启动新工程: 打开 STM32CubeIDE,选择 File -> New STM32 Project。在 Target Selector 中搜索 STM32F103C8(或选择相应开发板型号),然后 Next。输入项目名称,如 "STM32_OneNet_Demo",选择使用 CubeMX 初始化。CubeIDE 将创建包含 CMSIS 和 HAL 库的基本工程。接下来会自动打开 CubeMX 配置界面。
3.4 使用 STM32CubeMX 配置 STM32 外设(USART、GPIO 等)
在 CubeMX 图形配置中,我们需要启用并配置以下外设:用于与 ESP8266 通信的 USART、一些 GPIO(可能用作ESP8266 RST控制或板上LED)、如果连接传感器还需要相应接口(如I2C/SPI等),以及调试所需配置。
USART 配置: 找到用于连接 ESP8266 的串口。例如我们选用 USART2:在 CubeMX 的 Pinout & Configuration 中,展开 Connectivity -> USART2,将其模式设置为 Asynchronous。CubeMX 会自动将 PA2/PA3 配置为 USART2 TX/RX。然后在 USART2 参数中,将 Baud Rate 设置为 115200(与 ESP8266 AT默认波特率匹配 (STM32与物联网01-ESP8266基本操作 - 博客园)),数据位8,无奇偶校验,1个停止位,硬件流控 None。开启 **USART2 的中断(NVIC Settings)**以便后续用中断接收数据,或者使用 DMA 接收(可选)。如果打算通过另一个串口打印调试信息,可以同时开启 USART1 并将其TX引脚映射到SWO或者PA9,引出给ST-Link虚拟串口。但简化起见本指南主要描述 USART2 用于WiFi通信。
GPIO 配置: 将用于控制 ESP8266 的 RST 引脚配置为推挽输出(如果需要)。例如我们可用 PB0 连到 ESP8266 RST,那么在 CubeMX 中将 PB0 设置为 GPIO_Output,初始状态设置为高(不复位)。另外,可以配置板载 LED(如 PC13)为输出用于指示状态。
时钟与其他配置: 确保启用了外部高速晶振HSE(如使用外部8MHz晶振的板子),设置系统时钟 72MHz,以获得准确的USART波特率。如果使用内部晶振,需要校准以确保串口通信可靠。开启需要用的定时器(用于延时或心跳)、I2C/SPI/ADC(用于传感器)等。本项目例如使用定时器中断做一个1秒的计时,或者使用 SysTick 实现简单延时函数。
配置完成后,点击 Generate Code。CubeIDE 将根据CubeMX配置生成初始化代码,包括 MX_USART2_Init()、MX_GPIO_Init() 等函数。至此,STM32 外设配置就绪,我们可以编写代码控制USART收发 AT指令来驱动 ESP8266。
开发环境准备小结: 我们现在拥有:STM32F103 硬件连接好 ESP8266-01,并在CubeIDE项目中初始化好了串口和必要引脚。接下来需要考虑 ESP8266 的固件和AT指令用法,然后编写 STM32 程序通过串口发送AT指令,驱动 ESP8266 完成 WiFi联网和 MQTT 连接 OneNet 的流程。
4. ESP8266(AT 模式)连接 OneNet 的基本流程
ESP8266 模块将作为 WiFi调制解调器,通过 AT 指令集由 STM32 来控制。我们首先要确保 ESP8266-01 上烧录了合适的 AT 固件版本,且支持 MQTT 功能。目前常见的方案有:
- 使用乐鑫官方 AT 固件(例如 ESP-AT),版本要求支持 MQTT AT 指令。如果您的模块固件版本较旧(AT+GMR可查看版本号),可能不直接支持 MQTT,需要更新到新版本。
- 或使用第三方定制的 MQTT AT 固件(如安信可提供的 MQTT 版AT固件)。更新固件需要将 ESP8266 IO0 拉低进入下载模式,通过 USB 转串口烧录。考虑到步骤复杂,本指南假设已获得支持 MQTT指令的ESP8266 AT固件。
OneNet 平台允许使用标准 MQTT 协议,我们可以直接利用 ESP8266 的 MQTT AT命令集来连接 OneNet,无需在 STM32 上编写MQTT协议栈。这大大简化了工作。下面分步骤介绍 ESP8266 AT 指令实现从联网到 MQTT 连接的流程。
4.1 常用 AT 指令简介
ESP8266 AT 指令是一系列以“AT”开头的文本命令,用于配置 WiFi模块参数和控制网络操作。以下是我们将用到的一些指令及其功能:
AT:测试AT连通性。发送AT\r\n模块应返回OK,用于验证串口通信是否正常。AT+RST:重启模块。模块会复位并重新上电自检。AT+GMR:查询固件版本号,用于确认固件支持情况。AT+CWMODE:设置 WiFi 工作模式。AT+CWMODE=1将模块设为 Station模式(STA),即作为客户端连接路由器。AT+CWJAP="SSID","PWD":加入WiFi网络。参数为 WiFi 热点的 SSID 和密码。执行成功后模块会连接到指定路由器并获取IP。AT+CIPSTA?:查询模块当前的 IP 地址(可选,确认联网成功)。AT+MQTTUSERCFG=<...>:配置 MQTT 客户端参数。这个是 MQTT 扩展指令,格式较复杂,详见后文。AT+MQTTCONN=<...>:建立 MQTT 连接,指定服务器地址和端口等。AT+MQTTSUB=<...>:订阅 MQTT 主题。AT+MQTTPUB=<...>:发布 MQTT 消息。AT+MQTTPUBRAW=<...>:发布 MQTT 原始消息(需先指定长度,再发送数据)。AT+MQTTCLEAN:断开 MQTT 连接(视固件支持情况)。
其中,AT+MQTTUSERCFG、AT+MQTTCONN、AT+MQTTSUB、AT+MQTTPUB 等属于新版固件中增加的 MQTT 命令集。若输入这些命令提示未知,说明固件不支持MQTT,需要升级固件。
4.2 ESP8266 连接 WiFi 并接入 OneNet
步骤1:模块上电自检 – 给ESP8266上电后,等待1~2秒它完成自检。STM32 向ESP8266串口发送一次AT\r\n,若返回OK则表示串口通信正常。如果无响应,可尝试发送AT+RST\r\n复位模块,或检查串口接线/波特率。
步骤2:设置 WiFi 模式 – 发送AT+CWMODE=1\r\n,将ESP8266切换到 STA(Station)模式。默认有些固件可能已是1,但确认一下最好。期望收到OK回应。若返回ERROR可能是指令格式错误或模块不支持,请检查指令拼写和换行符。
步骤3:连接到路由器 – 发送 AT+CWJAP="你的WiFi名称","WiFi密码"\r\n。此命令执行时间相对较长(数秒),模块会尝试加入指定AP。成功时返回WIFI CONNECTED和WIFI GOT IP消息以及最终的OK (STM32使用esp8266的AT指令连接mqtt服务器,以Thing Cloud为例(标准库和HAL库)_stm32 mqtt at指令-CSDN博客)。若返回FAIL,请检查SSID/密码是否正确,或模块距离路由器过远信号不好。成功获取IP后,可以用AT+CIFSR或AT+CWJAP?验证IP地址。至此,ESP8266 已连接互联网。
步骤4(可选):时间/NTP 配置 – OneNet MQTT可能要求时间戳(一般不需要此步,但部分物模型功能可能涉及时间)。示例中有使用 AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com"\r\n 设置NTP (STM32使用esp8266的AT指令连接mqtt服务器,以Thing Cloud为例(标准库和HAL库)_stm32 mqtt at指令-CSDN博客)。这步可选,仅确保模块时间同步,对MQTT连接OneNet不是必须。
步骤5:解析 OneNet MQTT 连接参数 – 在发起 MQTT 连接前,我们需要准备好 OneNet 的服务器地址、端口以及客户端身份参数。根据 OneNet MQTT 接入规范,我们总结出如下参数:
- 服务器地址:OneNet MQTT Broker 的域名或IP。官方文档显示 OneNet 公共云 MQTT 接入地址可以使用
183.230.40.39(这是OneNet华北主站IP)和端口 6002。也可以使用域名mqtt.heclouds.com或mqtts.heclouds.com。据近期实践,OneNet 新平台也开放了标准端口1883 供非TLS连接。例如域名mqtt.heclouds.com:1883也指向 OneNet MQTT 服务 (oneNet之MQTT按键控制LED 原创 - Csdn博客)。本指南选择传统地址 183.230.40.39:6002(非加密),对应 MQTT 3.1 协议。 - 客户端ID:即设备ID。在 OneNet 平台设备列表中可找到,例如创建设备时给出的数字ID(假设为
"123456789")。 - 用户名:即产品ID。可在产品概况页面查看,如
"98765"。 - 密码:即鉴权信息。OneNet 支持直接使用 设备APIKey 作为 MQTT 密码 (oneNet之MQTT按键控制LED_在检测mqtt用以执行其它按键-CSDN博客) (oneNet之MQTT按键控制LED_在检测mqtt用以执行其它按键-CSDN博客)。例如设备的APIKey(16或24位字符串,如
"aFKcWTrm6VJfgfF1pQqW2=NWDck="(oneNet之MQTT按键控制LED_在检测mqtt用以执行其它按键-CSDN博客))。新版OneNet也允许使用通过产品ID、设备名和设备秘钥计算的 Token 值作为密码。计算 Token 一般需要时间戳和签名,这里为了简便,我们直接使用 设备APIKey,假定平台允许。注意,如果你的 OneNet 产品是新物模型类型,设备可能没有独立APIKey,需要通过 OneNet 提供的 Token 生成工具计算一个 token 字符串,再用作 MQTT 密码 (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客) (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)。生成token的规则通常是:token = version=2018-10-31&res=products/<产品ID>/devices/<设备名称>&et=<过期时间>&method=md5&sign=<签名>(ESP8266/01s AT指令连接OneNET MQTT篇上报和下发数据_onenet mqtt 命令下发-CSDN博客)。签名是把上述信息和产品MasterKey一起MD5生成的字符串。这较复杂,如非必要可使用设备APIKey简单连接。
搞清上述参数后,我们组装 MQTT 用户配置命令。ESP8266 MQTT AT指令 AT+MQTTUSERCFG 用于设置这些参数,其格式为:
AT+MQTTUSERCFG=<链接ID>,<生存周期>,<客户端ID>,<用户名>,<密码>,<KEEPTIME>,<cleansession>,<LWTTOPIC>
各字段含义:
- 链接ID:0(ESP8266可以维护多个MQTT连接,0表示第一个)。
- 生存周期:1(MQTT版本,0=3.1, 1=3.1.1)。
- ClientID:设备ID字符串。
- Username:产品ID字符串。
- Password:鉴权信息字符串(设备APIKey或生成的Token)。
- KEEPTIME:心跳时间(单位s),OneNet默认可用无关紧要值如0表示默认60s。
- cleansession:0或1,设置会话清理,一般设0保持会话,设1表示每次连接不保留会话。
- LWTTOPIC:遗嘱消息主题,可留空
""无遗嘱。
例如,假设设备ID为123456789,产品ID为98765,设备APIKey为abc123XYZ...,则命令为:
AT+MQTTUSERCFG=0,1,"123456789","98765","abc123XYZ...",0,0,""
发送该命令,模块应返回OK表示参数接受成功 (STM32使用esp8266的AT指令连接mqtt服务器,以Thing Cloud为例(标准库和HAL库)_stm32 mqtt at指令-CSDN博客)。如果返回错误,请检查参数格式,特别是引号、逗号是否正确。
步骤6:建立 MQTT 连接 – 接下来发送 AT+MQTTCONN=0,"183.230.40.39",6002,1\r\n。其中参数依次为:链接ID=0,服务器地址,端口号,最后的1表示clean session(这里设1或者0需跟前面的 cleansession 保持一致,否则可能出错)。注意 OneNet MQTT 非TLS,用 6002 端口;如用1883端口将域名改为mqtt.heclouds.com相应调整。建立连接后,ESP8266会尝试和OneNet进行MQTT握手。成功的话,会收到 OK 和一个 MQTT 状态指示,比如:+MQTTCONNECTED:0。如果连接失败,常见错误代码包括:
ERROR直接报错:检查域名/IP是否可达,端口是否正确。+MQTTCONNECTED: -1或+MQTTCONNECTED:4等:这些是MQTT Connect 报文被服务端拒绝的返回码。例如4表示登录被拒绝(可能用户名/密码错误)。请核对产品ID/设备ID/APIKey是否正确对应,或Token是否过期。+CME ERROR: Recv timeout:表示在超时时间内没收到响应,可能网络问题或参数有误。
当 OneNet 平台收到正确的 ClientID(设备ID)、Username(产品ID)和Password(APIKey/token)后,会建立 MQTT 连接,OneNet 后台设备列表应该能看到该设备上线。成功连接后,我们就可以进行 MQTT 数据收发了。
4.3 OneNet MQTT 通信主题格式解析
OneNet 平台的数据交互通过 MQTT 主题(Topic)完成。OneNet 有一些系统主题专门用于物模型设备的数据上下行,为统一格式,通常以 $sys/{产品ID}/{设备名称}/thing/ 开头。例如:
- 上报设备属性(数据点)使用主题:
$sys/{产品ID}/{设备名称}/thing/property/post。设备向该主题发布属性值的JSON数据。 - 平台下发写属性命令使用主题:
$sys/{产品ID}/{设备名称}/thing/property/set。设备需订阅该主题来接收指令。 - 属性上报回复主题:
$sys/{产品ID}/{设备名称}/thing/property/post/reply,平台每次收到设备上报数据会反馈结果,设备可选择订阅此主题确认数据是否成功被平台接收。 - 属性设置回复主题:
$sys/{产品ID}/{设备名称}/thing/property/set_reply,当设备执行完平台下发的属性设置指令后,需向该主题回复执行结果(如成功或错误)以通知平台。
这些主题含有产品ID和设备名称,是OneNet新版物模型统一的路径。如果你的产品在OneNet上创建了物模型(数据流模板)并定义了属性,建议使用上述系统主题来上传和下发数据,平台将自动解析 JSON 格式数据点并存储到对应的属性中。如果没有用物模型,OneNet 也支持另一种数据流透传方式:设备可以向主题 $dp 发布数据点(Data Point)消息 (10.2. MQTT协议:2上传数据点到OneNET平台 — mPython掌控 2.2.0 documentation)。$dp 是 OneNet 定义的特殊主题,用于简化数据上报,它要求发布的消息为特定格式:前3字节指示JSON数据长度和类型,后面跟实际JSON内容 (10.2. MQTT协议:2上传数据点到OneNET平台 — mPython掌控 2.2.0 documentation)。例如 micropython 客户端通过 c.publish("$dp", pubdata(message)) 上报数据点 (10.2. MQTT协议:2上传数据点到OneNET平台 — mPython掌控 2.2.0 documentation)。但考虑到 $dp 较旧且需要自己构造报文头,我们更推荐使用物模型主题直接发 JSON 字符串,这也便于与OneNet Studio中的设备属性对应。
本项目主题规划: 假设我们定义了两个属性数据流:温度(temp)和湿度(humi)。我们将在设备端通过 $sys/{产品ID}/{设备名称}/thing/property/post 发布属性数据,JSON格式如:{"id":"123","params":{"temp":{"value":23.5},"humi":{"value":60}}}。平台处理后,可在OneNet设备详情看到 temp和humi的数据点各自更新。为了接收平台对上报的响应,我们可以订阅 $sys/{产品ID}/{设备名称}/thing/property/post/reply(但其实OneNet当前对post上报一般不需要特殊确认,error=0说明成功)。更重要的是,为了让手机App通过平台控制设备(比如打开设备上的LED),平台会通过 property/set 下发命令,因此设备需要订阅 $sys/{产品ID}/{设备名称}/thing/property/set 主题。一旦收到此主题消息,STM32 就触发对应的控制,并回复执行结果到 set_reply 主题。
4.4 配置 ESP8266 订阅 OneNet 主题
在 MQTT 连接建立后,ESP8266 可以通过 AT 命令订阅所需主题。使用指令格式:
AT+MQTTSUB=<链接ID>,"<主题>",<QoS>
其中 QoS 为服务质量等级,0最多送一次,1至少送一次。OneNet 支持 QoS0 和 QoS1,这里用 QoS0 足矣。
订阅设备下行主题: STM32应发送:
AT+MQTTSUB=0,"$sys/{产品ID}/{设备名称}/thing/property/set",0\r\n
这样当 OneNet 平台有对该设备的控制指令下发时,ESP8266会收到,并通过串口通知STM32。ESP8266 固件在收到订阅的消息时,会通过一种 URC 非命令的格式输出,比如:
+MQTTSUBRECV:0,"$sys/pid/devName/thing/property/set","{...json...}"
具体格式视固件有所不同,可能还带消息长度等信息。但一般包含链接ID、主题、以及消息内容。STM32 程序需解析出消息内容中的 JSON,然后根据指令执行相应动作(如打开LED或改变阈值等)。
(可选)订阅上报回复主题: 若希望确认每次数据上报平台是否成功,可订阅 $sys/{产品ID}/{设备名称}/thing/property/post/reply。平台在收到属性上报后会返回类似:{"id":"123","code":0,"msg":"success"},表示id为123的请求成功(code=0)。ESP8266 收到后STM32可读取+MQTTSUBRECV并判断 code 是否为0,非0可重试上报。订阅指令同理:
AT+MQTTSUB=0,"$sys/{产品ID}/{设备名称}/thing/property/post/reply",0\r\n
回复 OK 则订阅成功。
ESP8266 可以一次订阅多个主题,顺序发送多条 AT+MQTTSUB 命令即可。OneNet 支持动态创建主题,订阅不存在的主题也会成功(只要格式合法),这点和其他云(如阿里IoT)需要预定义Topic不同。所以无须在OneNet平台额外配置这些主题。
注意: 每条 AT 命令都应有相应 OK/ERROR 来指示执行结果。我们在 STM32 程序中通常会发送命令后等待特定应答字符串。例如,发送 MQTTSUB 后等待 "OK" 确认。如果一直等不到(超时),应考虑重发或判定失败。合理的延时和重试机制可以提高连接成功率。
4.5 综合:ESP8266 连接过程命令序列
将上面所有配置串联起来,ESP8266 从上电到订阅完成的大致 AT 指令序列如下(带简要注释):
AT→ 模块应答OK(测试通信)AT+RST→OK(重启模块)- (模块重启后会输出一些启动信息,等待1~2秒继续)
AT+CWMODE=1→OK(设置为Station模式)AT+CWJAP="SSID","PWD"→WIFI CONNECTEDWIFI GOT IP...OK(连接WiFi,联网成功)AT+MQTTUSERCFG=0,1,"<DeviceID>","<ProductID>","<APIKey/token>",0,0,""→OK(配置MQTT参数) (STM32使用esp8266的AT指令连接mqtt服务器,以Thing Cloud为例(标准库和HAL库)_stm32 mqtt at指令-CSDN博客)AT+MQTTCONN=0,"183.230.40.39",6002,1→ 若成功:OK和可能的+MQTTCONNECTED:0AT+MQTTSUB=0,"$sys/<pid>/<dev>/thing/property/post/reply",0→OK(订阅上报回复主题,可选)AT+MQTTSUB=0,"$sys/<pid>/<dev>/thing/property/set",0→OK(订阅平台下行控制主题)
到此,设备已做好与 OneNet 云通信的准备。接下来,STM32 就可以根据应用需要发布数据或者接收指令进行处理了。
5. STM32 通过 MQTT 向 OneNet 发送/接收数据
这一部分我们关注 STM32 程序如何控制 ESP8266 完成 MQTT 数据通信。核心是通过串口发送上节的 AT 指令序列,实现设备数据上报(Publish)和云端命令下发接收(Subscribe)。
5.1 STM32 串口通信控制 ESP8266
USART 通信实现: 在 STM32 中,我们可以使用 HAL 库提供的 HAL_UART_Transmit() 和 HAL_UART_Receive() 函数与 ESP8266 通信,也可以使用中断或 DMA 提高效率。典型地,我们会实现一个函数 ESP8266_SendCmd(const char* cmd, const char* ack, uint32_t timeout) 用于发送 AT 命令并等待某个应答关键字。例如,伪代码:
uint8_t rxBuf[128];
uint8_t ESP8266_SendCmd(const char* cmd, const char* ack, uint32_t timeout) {HAL_UART_Transmit(&huart2, (uint8_t*)cmd, strlen(cmd), 1000);// 清空接收缓冲memset(rxBuf, 0, sizeof(rxBuf));// 等待接收,循环直到发现 ack 或超时uint32_t t0 = HAL_GetTick();uint8_t found = 0;while(HAL_GetTick() - t0 < timeout) {// 假设我们使用中断将数据搬到rxBuf并随时检查if(strstr((char*)rxBuf, ack) != NULL) {found = 1;break;}if(strstr((char*)rxBuf, "ERROR") != NULL) {break;}}return found;
}
上面使用 strstr 查找应答。为此,我们需要在UART接收中断中持续填充 rxBuf 缓冲区。可以开USART接收空闲中断,把每次接收到的新字节追加到 rxBuf 末尾。为了简单,也可以采用 HAL_UART_Receive polling 方式读字符,边读边检查字符串,但效率略低。在实际代码中,还要考虑Buffer溢出以及必要时清除旧应答。
AT 指令发送顺序: STM32上电后,按4.2节流程逐条调用 ESP8266_SendCmd 发送。比如:
ESP8266_SendCmd("AT\r\n", "OK", 500);
ESP8266_SendCmd("AT+RST\r\n", "ready", 2000); // 等待重启后的 "ready" 字样
ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK", 500);
ESP8266_SendCmd("AT+CWJAP=\"MyWiFi\",\"password\"\r\n", "GOT IP", 10000);
sprintf(cmdBuf, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n", deviceID, productID, apiKey);
ESP8266_SendCmd(cmdBuf, "OK", 1000);
sprintf(cmdBuf, "AT+MQTTCONN=0,\"183.230.40.39\",6002,1\r\n");
ESP8266_SendCmd(cmdBuf, "OK", 5000);
ESP8266_SendCmd("AT+MQTTSUB=0,\"$sys/xxx/yyy/thing/property/set\",0\r\n", "OK", 1000);
如上所示,在每一步等待适当的应答。其中连接WiFi可能耗时较长,要给出足够 timeout(10秒甚至更长),而MQTT 连接也需要几秒完成 TLS 握手/认证等(OneNet非TLS会快些)。确保每一步都判断结果,若失败可以重试或进入错误处理(比如重新初始化ESP8266)。
常见错误处理:
- 如果
AT测试不通,可能是串口问题,可重发几次AT或者直接指示错误闪LED。 AT+CWJAP返回FAIL,可尝试再次发送或让用户检查WiFi凭据。AT+MQTTCONN若返回错误,需要检查鉴权。OneNet常见是用户名密码不对导致 Connect 报文返回 4 (Connection Refused: bad user/pass)。这种情况下,可打印调试信息 (比如将 ESP8266 返回的整个字符串通过调试串口输出) 来分析。- 整个流程若卡在某一步超过重试次数,可考虑重启模块(
AT+RST)重来。
经过上述步骤,假设 STM32 最终在MQTT连接和订阅主题上都收到 OK,我们就进入正常通信阶段了。
5.2 发布 MQTT 数据(设备上传)
构造发布命令: 发布属性数据使用 AT+MQTTPUB 或 AT+MQTTPUBRAW。区别是:MQTTPUB 可以直接附带消息字符串,但需要对消息内的特殊字符转义,而且长度有限制;MQTTPUBRAW 则分两步发送,可避开转义问题。我们用普通 AT+MQTTPUB 简化流程。
格式:
AT+MQTTPUB=0,"<主题>","<消息>",<QoS>,<retain>\r\n
其中 QoS=0, retain=0 即可(OneNet 暂无保留消息需求)。
例如上传温湿度:
主题 $sys/pid/dev/thing/property/post,消息内容:{"id":"123","params":{"temp":{"value":23.5},"humi":{"value":60}}}
则命令为:
sprintf(cmdBuf, "AT+MQTTPUB=0,\"$sys/%s/%s/thing/property/post\",\"{\\\"id\\\":\\\"123\\\",\\\"params\\\":{\\\"temp\\\":{\\\"value\\\":%.1f},\\\"humi\\\":{\\\"value\\\":%.1f}}}\",0,0\r\n", productID, deviceName, temperature, humidity);
ESP8266_SendCmd(cmdBuf, "OK", 1000);
注意在C字符串中双引号和反斜杠需要转义(如 \" 和 \\\")。上例用了 %.1f 代入浮点温湿度值并保留1位小数。id 字段可用来匹配应答,这里随意给"123"即可,每次上报可增1或使用时间戳字符串。
发送该命令,如果ESP8266返回 OK,表示消息已发出。OneNet 平台会将数据解析写入设备属性data流。如果我们之前订阅了 post/reply 主题,那么ESP8266稍后会输出一行,例如:
+MQTTSUBRECV:0,"$sys/pid/dev/thing/property/post/reply","{"id":"123","code":0,"msg":"success"}"
STM32 程序在 UART 接收数据中检测到有 +MQTTSUBRECV 字样,就可以进一步解析出主题和内容。可以通过寻找引号来截取主题字符串,再根据主题决定处理方式。如果是 post/reply,解析 JSON 看 code是否为0。如果为0则表示平台接受数据成功;非0表示失败,此时可选择重发该数据或者上报错误状态。一般 code 非0的情况很少出现,除非 JSON 格式不符合物模型定义、数据类型错误等。
循环发布数据: 实际应用中,STM32 会周期性采集传感器数据然后发布。例如每隔 10秒发送一次温湿度。可以使用定时中断或RTOS任务来调用发布函数。确保不要发太频繁以免淹没网络,一般 OneNet 对MQTT上报频率没有苛刻限制,但合理的间隔有助于功耗和流量。
发布调试: 在开发时可以借助 OneNet 平台的“设备调试”功能或 MQTT.fx 等客户端来观察数据是否到云端。OneNet Studio 提供“数据流”或“设备详情”页面,可以看到属性的最新值和历史曲线,验证我们的发布确实成功。
5.3 订阅主题消息处理(设备下行)
STM32 需要处理 ESP8266 通过串口反馈的订阅消息,即当平台有命令下发时,ESP8266 会打印类似 +MQTTSUBRECV: 的信息。我们需要在 UART 接收回调中寻找这个标志并提取其中的 JSON 命令。
示例: 平台通过 HTTP API 或控制台调用下发命令,OneNet 会向主题 $sys/pid/dev/thing/property/set 发送消息。例如让设备LED开关,OneNet 定义了属性 "LED" 为布尔或数值,那么下发 JSON 可能是:{"id":"4","params":{"LED":{"value":1}}}。ESP8266收到,会输出:
+MQTTSUBRECV:0,"$sys/pid/dev/thing/property/set","{"id":"4","params":{"LED":{"value":1}}}"
STM32 程序需解析 params 内的内容。可以采用和发布相同的 cJSON 库(如果使用嵌入式JSON解析库的话)或者简单字符串查找方法。例如,查找 "LED":{"value": 子串,取其后紧跟的数字。或者更通用地,把整个 JSON 文本提取出来,然后用 JSON parser 获取键值。由于OneNet物模型下发格式就是这个 "params":{...},我们可以硬编码寻找目标属性。
执行命令并回复: 一旦提取出 LED 要设置为1,我们就在 STM32 控制相应GPIO点亮 LED。然后需要回复平台,告知命令已执行。回复主题 $sys/pid/dev/thing/property/set_reply,内容一般包含同样的 id 以及 code 表示结果。OneNet 希望收到 code 200 表示设备已成功执行,或其他错误码。示例如ESP8266命令:
AT+MQTTPUB=0,"$sys/pid/dev/thing/property/set_reply","{"id":"4","code":200,"msg":"success"}",0,0
来回应 id=4 的指令执行成功。在 AT 指令里,双引号要转义,同发布类似:
sprintf(cmdBuf, "AT+MQTTPUB=0,\"$sys/%s/%s/thing/property/set_reply\",\"{\\\"id\\\":\\\"%s\\\",\\\"code\\\":200,\\\"msg\\\":\\\"success\\\"}\",0,0\r\n",productID, deviceName, cmdIdString);
ESP8266_SendCmd(cmdBuf, "OK", 1000);
其中 cmdIdString 是收到命令 JSON 里的 id(例如 "4"),需要原样放回。发送完成后,OneNet 运维页面“API调试”处将显示 code:0 表示平台收到了设备的确认。若不回复或回复不正确,平台可能视为设备未执行命令,会显示超时。
总结设备下行处理:
- STM32监听串口数据,捕获
+MQTTSUBRECV行。 - 判断主题是 property/set 还是别的。可通过在该行字符串中搜索
"thing/property/set"来确定。如果以后还有别的订阅主题,也类似判断。 - 提取 JSON 字符串。因为包含引号,我们可以找到第一个出现的
{和最后一个}括号的位置,截取之间的字符串作为 JSON。 - 根据具体的物模型字段解析需要控制的项和值。对简单项目,也可以通过
strstr寻找属性名然后取其后value值。 - 执行相应动作(如控制硬件)。
- 构造 set_reply 消息发送确认。
整个过程应尽量迅速完成,避免下一条UART数据覆盖尚未处理的数据。可以考虑把 JSON 放到任务中处理,以免阻塞UART中断。不过对于一般速度的消息和STM32F1性能,这样处理是足够的。
6. App 与 OneNet 平台的数据交互(HTTP)
在设备通过 MQTT 将数据上传云端后,我们希望手机 App 或其他上层应用能够获取这些数据并展示,同时也能够通过 App 控制设备(本例中如远程开关LED等)。OneNet 平台提供了丰富的 HTTP API 来满足这些需求。开发者可以通过 HTTP 请求查询设备状态、读取数据流、触发命令下发等。下面介绍 OneNet HTTP API 的基础用法,并以使用 Postman 测试为例,演示如何从云端获取设备数据。
6.1 OneNet 提供的 HTTP API 介绍
OneNet 的 HTTP API 遵循 RESTful 风格,对外统一以 api.heclouds.com 域名提供服务。不同的资源(设备、数据流、数据点、命令等)都有各自的 URL 路径。新版本的 OneNet 也提供了 open.iot.10086.cn 下更严格鉴权的接口(需要使用 Token),但为了简单起见,这里介绍经典的基于 API-Key 的接口,因为操作方便易测且足够满足大部分应用。
常用 API 概览:
- 获取设备信息:
GET http://api.heclouds.com/devices/<设备ID> - 获取数据流信息:
GET http://api.heclouds.com/devices/<设备ID>/datastreams/<数据流ID> - 获取数据点:
GET http://api.heclouds.com/devices/<设备ID>/datapoints?datastream_id=<数据流ID>&limit=<n>(APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客)
例如获取最新1条数据点,可用limit=1。 - 批量获取多个数据流的数据点:
GET http://api.heclouds.com/devices/<设备ID>/datapoints?datastream_id=temp,humi&limit=1(多个流用逗号隔开)。 - 下发命令到设备:
POST http://api.heclouds.com/cmds?device_id=<设备ID>,在HTTP Body中写入命令内容(但OneNet的命令接口与MQTT互通需要设备实现特定逻辑,使用Topic更直接,后文详述)。 - 直接向设备的 MQTT 主题发送消息:OneNet 有相应 API,可通过HTTP发布一条消息到某设备的某主题。如果设备订阅了该主题,就能收到。此接口在OneNet称为HTTP透传或发布主题消息。调用方式如:
POST http://api.heclouds.com/mqtt?topic=<TopicName>&device_id=<设备ID>
Body中是消息内容文本 (Python Onenet 实现指南 - 51CTO博客)。这种方式本质上等价于服务器端代替我们去发布MQTT消息。
上述 API 调用均需要鉴权。鉴权通过在请求 Header 中加入 api-key 字段实现。api-key可以使用产品的 Master APIKey(具有该产品下所有设备操作权限),或者使用某台设备的 APIKey(只对该设备的数据有权限)。出于安全考虑,App 端通常不直接用Master Key,而是用设备的APIKey来获取该设备的数据。如果只读数据也可以给APIKey配置只读权限。我们的应用只是查看数据和发命令给自己的设备,用设备APIKey即可。
6.2 通过 HTTP 获取设备数据
使用 Postman 测试 GET 请求: 首先在 OneNet 开发者中心找到我们设备的 设备ID 和设备APIKey(或产品APIKey)。假设设备ID为123456789,数据流ID为temp。我们想获取最新的温度值。可以构造 HTTP GET 请求:
GET http://api.heclouds.com/devices/123456789/datapoints?datastream_id=temp&limit=1
Header:api-key: <设备APIKey>
使用 Postman 或浏览器插件发出请求。如果成功,OneNet会返回一个 JSON 数据。例如:
{"errno": 0,"data": {"count": 1,"datastreams": [{"id": "temp","datapoints": [{"at": "2025-03-10 06:30:00","value": 23.5}]}]},"error": "succ"
}
这里 "errno":0 表示无错误,"data" 下包含我们请求的数据点。count是本次返回的数据点数,datastreams数组列出了请求的各数据流以及数据点列表。可以看到最新数据点的时间戳和值 (APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客) (APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客)。App 可以解析此 JSON 提取所需数值。
如果想获取多个数据流的值(如温度和湿度一起),可以把 datastream_id 设为两个ID组合,或者干脆不指定 datastream_id 让其返回设备下所有数据流的最近点。返回格式会有多个 datastreams 条目,要根据 id 匹配。
注意: OneNet 平台在设备通过物模型上报属性后,会把每个属性映射为一个独立的数据流,其 ID 一般就是属性名。因此用以上接口获取属性值是可行的。例如属性 "humi" 也能通过 datastream_id=humi 查询。同理,也可以通过 OneNet Studio 提供的新接口获取设备的影子信息,但那需要 token 方式,不在本次讨论。
解析返回数据: 在 App 端,我们可以使用 JSON 库解析。例如在Android应用中,可以用 org.json 或 Gson 等库将返回字符串解析成对象 (APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客)。在解析后,就能得到温度值 23.5(数字类型)。我们可以将其显示在 App 界面的文本框中。
周期获取 vs 推送: 由于我们这里使用 HTTP,是一种轮询获取机制。App 需要隔一定时间就发送 GET 请求刷新数据,才能近乎实时显示最新值。可以每隔5秒或10秒请求一次,根据应用需求和流量权衡。如果不想频繁轮询,OneNet 也提供推送机制(通过TCP长连接或MQTT方式),但移动App一般用HTTP轮询简单可靠。
示例:使用 Python 获取数据: 除了 Postman,我们也可以用简单的 Python 脚本测试 API。例如:
import requests
device_id = "123456789"
api_key = "abcdef...你的设备APIKey"
url = f"http://api.heclouds.com/devices/{device_id}/datapoints?datastream_id=temp&limit=1"
headers = {"api-key": api_key}
res = requests.get(url, headers=headers)
data = res.json()
print(data)
这段Python代码发送 GET 请求到 OneNet 数据点 API,获取 JSON 数据并打印 (Python Onenet 实现指南 - 51CTO博客) (Python Onenet 实现指南 - 51CTO博客)。若配置正确,会输出类似上面的 JSON。你可以在 PC 上用这个方法测试设备数据获取是否正常,然后再把逻辑移植到App。
6.3 通过 HTTP 控制设备(命令下发)
App 不仅读取数据,还需能够控制设备。例如用户在手机上按下“打开LED”按钮,我们希望通过 OneNet 让设备收到这个指令。实现方式有两种:
方法A:调用 OneNet 命令下发 API – OneNet 提供专门的命令通道API,即前述的 POST /cmds?device_id=<id> 接口。使用这个接口需要在HTTP body中写命令内容,该内容会通过OneNet内部下发到设备。传统OneNet设备(如使用EDP协议)能直接收到这个命令。但对于MQTT设备,OneNet后台其实会将命令转为 MQTT 消息发送到设备。所以方法A本质也要落到某个主题消息。具体来说,当我们调用/cmds接口发送一条命令字符串,OneNet 平台会将此字符串封装为 MQTT 消息,发送到设备的系统命令主题,即 $sys/{productID}/{deviceName}/cmd/request 等主题(老版OneNet MQTT的做法)。但新版本物模型设备未必使用这个路径,因此方法A适用于不使用自定义Topic的场景。
方法B:直接通过Topic API发送 – 如前面提到的 MQTT HTTP透传接口,可以在HTTP请求中指定发往设备的哪个Topic,这样更灵活。因为我们的设备已经订阅了 $sys/pid/dev/thing/property/set 主题,最自然的是让App通过HTTP直接发布一条消息到此主题。OneNet 有相应文档说明此用法 (Python Onenet 实现指南 - 51CTO博客)。
考虑我们已经采用物模型主题,那使用方法B更直接:App 调用HTTP接口,OneNet立刻把内容推给设备,无需定义其他命令通道。示例:我们希望设置 LED=1,可发送:
POST http://api.heclouds.com/mqtt?topic=$sys/<pid>/<dev>/thing/property/set&device_id=123456789
Header:api-key: <MasterAPIKey或设备APIKey>
Body (application/json):{"id":"app1","params":{"LED":{"value":1}}}
其中 device_id 参数确保消息发往特定设备,topic 参数指定主题。Body 就是设备 set 主题所需的 JSON 格式。我们可以用 Postman 发这个请求尝试。OneNet 返回的响应如果 errno:0 则表示消息已发送 (APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客)。此时在设备端,ESP8266 会收到与平台UI下发命令相同的内容,通过 UART 通知STM32。STM32 执行后再MQTTPUB回复,平台将转发回复给HTTP调用方(App)。但是HTTP接口是否能直接拿到回复需要查询结果,因为HTTP是短连接并不能等回复。
更简单的做法是,App 下发命令后,可以隔几秒重新 GET 一次设备数据,看看对应状态改变没有。例如,App发送 LED=1 后,设备会执行点亮LED,同时也可以选择上报 LED 状态改变(比如作为一个数据流)。然后App轮询看到 LED状态流已变为1,则表示命令生效。这样就不需要App等待同步响应。
小结: HTTP API 非常强大也相对直观。一般流程是:设备->OneNet (MQTT) 实时上报数据;App->OneNet (HTTP) 请求读取数据,App->OneNet (HTTP) 发送控制、OneNet->设备 (MQTT) 转发控制。OneNet充当了中介,让设备和应用解耦。开发者要关注API使用是否正确,参数是否匹配。此外注意 APIKey 的保密和有效期。MasterKey权限很高,应妥善保存或在服务器端使用,不要放在App内。如果必须在App内调用,可以创建设备级APIKey(OneNet控制台的APIKey管理可添加,只赋予特定资源权限)来代替 MasterKey。
使用 HTTP API 的调试技巧: 善用 Postman 之类工具构造HTTP请求,并查看返回结果。OneNet官方文档详细列出了各接口的URL和返回格式 (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)。当遇到问题时,检查HTTP状态码和返回的 errno、error信息。例如 errno=10可能是api-key无效,errno=6可能是设备未找到等。使用正确的 Content-Type(application/json)和 Header 是必要的,否则OneNet会报输入格式错误。
7. 综合示例:从设备到云端再到手机 App 的完整流程
这一节我们以一个具体的应用场景串起前面的所有环节:使用 STM32F103C8T6 定期采集环境温湿度,通过 ESP8266 MQTT 上传至 OneNet;OneNet 云端存储数据并提供查询;用户使用手机App通过HTTP获取实时温湿度并显示。同时,用户可在App上按下按钮控制远端STM32点亮或熄灭一个指示LED,通过 OneNet 平台的指令下发实现。
7.1 设备端(STM32 + ESP8266)过程
-
系统初始化: STM32上电后,初始化 USART、GPIO、传感器接口等。重置ESP8266并配置好WiFi连接和MQTT连接 OneNet(按第4章和第5章流程)。假设成功上线后,STM32订阅了属性设置主题以及上报回复主题。
-
采集传感数据: STM32 通过连接的传感器(如 DHT11 温湿度传感器)获取环境温度和湿度。DHT11 通常用单总线协议,可通过定时GPIO读取,本例略去实现细节,只假定我们得到两个变量
float temperature和float humidity。初始读取可能得到温度25.0℃,湿度60%。 -
上传数据: STM32 将上述值封装 JSON,通过
AT+MQTTPUB发布至 OneNet。发布内容:{"id": "1", "params": { "temp": { "value": 25.0 }, "humi": { "value": 60.0 } } }OneNet 收到后会回应一个确认到
$sys/.../post/reply,ESP8266 收到打印,STM32读取到"code":0,表示上报成功。此时在 OneNet 平台,这台设备的 temp 数据流和 humi 数据流各新增了一个数据点 25.0 和 60.0。 -
周期运行: STM32 设置一个定时,比如每隔10秒执行一次温湿度采集并上报。这样设备会持续地将环境数据发送到云端,云端形成时间序列数据。在等待间隔时,STM32也保持监听ESP8266串口以捕获可能的下行指令。
-
接收控制命令: 当用户在App上按下“打开LED”时,会触发云端下发。具体过程见后文App侧。此时 OneNet 平台会向
$sys/pid/dev/thing/property/set发送:{"id": "100", "params": { "LED": { "value": 1 } } }ESP8266输出:
+MQTTSUBRECV:0,"$sys/pid/dev/thing/property/set","{"id":"100","params":{"LED":{"value":1}}}"STM32 UART收到后,解析出 LED value = 1。它随即设置连接在 PB1(举例)的LED GPIO 输出高点亮 LED。然后构造回复 JSON:
{"id": "100", "code": 200, "msg": "success"}并通过
AT+MQTTPUB发送到$sys/pid/dev/thing/property/set_reply主题。OneNet 平台接收到回复,确认设备已执行命令。 -
状态上报(可选): STM32 也可以选择在执行命令后,将LED的新状态通过属性上报机制通知平台。例如再发布一次属性:
{"id":"2","params":{ "LED": { "value": 1 } } }这样平台上也有 LED 状态的数据流更新。这在需要记录设备状态的应用中很有用。不过若只是瞬时动作也可以不必每次都上报。
-
等待其他指令或定期上报: LED 打开后,设备继续每10秒上报温湿度。假如一段时间后,用户在App点击“关闭LED”,流程类似以上,再将 LED value=0 下发,设备熄灭LED并回复。
设备端的整个逻辑可以用伪代码描述如下:
while(1) {if(time_to_sample) {read_temperature_humidity(&temp, &humi);send_mqtt_property_post(temp, humi);reset_timer();}if(uart_received_flag) {parse_uart_buffer();if(received_topic == PROPERTY_SET) {if(cmd.LED.value == 1) {HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);} else {HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);}send_mqtt_set_reply(cmd.id, 200);}clear_uart_flag();}// ... (other tasks)
}
7.2 云端平台过程
- 当设备上线并订阅主题后,OneNet 将设备标记为“在线”,设备管理列表中可见在线状态。随后每次设备发布数据点,OneNet 平台都会验证数据格式并存储。如果数据对应物模型属性,则在设备详情的属性标签页显示最新值和历史趋势图。开发者中心也可以通过数据浏览API调试看到原始JSON。
- 平台接收到
thing/property/post上报,返回 result code=0。如有订阅post/reply的设备则收得到。 - 平台在设备属性发生变化时,可触发触发器或推送(这里没深入)。
- 当 App 或用户通过平台下发控制时,平台将指令推送至设备的 MQTT 连接。在OneNet Studio界面,如果使用“在线调试”的“设置设备属性”功能填写 LED=1,也会以相同机制发送命令。App 通过HTTP接口发送时,平台收到HTTP请求,立即在后台把消息转发到设备 MQTT连接上的property/set主题。
- 平台等待设备在超时时间内(比如默认3秒)回应 set_reply。如果收到 code=200,则在平台UI上显示执行成功;若超时未收到,平台可认为设备可能未在线或未执行,这时UI/接口会给出相应反馈(如设备无响应)。
- 平台将 LED 属性新值存储更新。所以App再查询 LED 状态就会看到value=1。
7.3 移动 App 端过程
- 初始化: 用户打开手机App(假设已经实现好UI界面,包括显示温湿度的文本和一个LED开关按钮)。App 内可能写死或从用户配置得到设备ID和 APIKey。
- 获取最新数据: App 启动时调用 OneNet HTTP GET 接口获取温湿度。拿到返回 JSON 后解析出value,例如温度25.0、湿度60.0,更新界面显示“25.0°C, 60%”。App 可以每隔 10秒自动刷新一次,以跟踪变化 (APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客) (APP通过http获取OneNet数据与命令下发〖应用层〗_onenet下发内容-CSDN博客)。
- 控制操作: 当用户点击LED开关(比如一个toggle按钮从OFF滑到ON),App捕捉到事件,构造HTTP请求:
并发送。OneNet返回一个 HTTP响应 JSON:POST http://api.heclouds.com/mqtt?topic=$sys/pid/dev/thing/property/set&device_id=123456789 Header: api-key: <APIKey> Body: {"id":"app1","params":{"LED":{"value":1}}}
表示平台已将消息发出 (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)(注意,这不代表设备执行成功,只是发送成功)。{ "errno": 0, "data": {}, "error": "succ" } - 等待结果: 为了确认设备是否真的打开LED,App 可以在发送几秒后再次 GET 设备属性或者设备LED状态数据流。由于我们的设备在执行后可能上报LED状态(如果实现了),那么大约1-2秒后,OneNet 平台的 LED 数据流就更新为1,App 下一次拉取会得到 LED value=1,于是可以在UI上将LED状态显示为“已打开”。如果应用需要即时反馈,也可以在按下按钮后,暂时假定成功改变UI状态,但最好在一定时间后核实。
- 用户观察: App 上看到温湿度在定时刷新,比如逐渐温度变化。用户再次操作LED按钮关闭LED,App发送value=0,下发OneNet。设备执行后LED熄灭。下次App拉数据发现LED状态变0,于是同步UI。
整个流程打通后,我们实现了一个完整的IoT应用:STM32采集环境数据上云 -> 云端存储并提供查询 -> 移动端获取数据显示 -> 移动端发送控制指令 -> 设备执行并反馈,闭环完成。
7.4 常见问题与解答
问1: 为什么 STM32 一直无法连上 OneNet MQTT,AT+MQTTCONN 收到 ERROR 或一直超时?
答: 可能原因很多:
- 检查产品ID、设备ID、APIKey 是否对应正确 (连接onenet云mqtt报文_183.230.40.96-CSDN博客)。尤其别把设备ID和产品ID弄混。设备ID一般是纯数字,产品ID可能是数字或长度较短字符串。
- 如果使用 Token 作为密码,要确保 Token 正确生成且未过期 (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)。Token 的 et(过期时间)默认可能很短或需要自行设定较长时间。
- 端口和服务器地址要匹配。如果用183.230.40.39,端口必须6002;用mqtt.heclouds.com则建议端口1883。若固件不支持域名,可以用IP。
- MQTTUSERCFG 的 cleansession 参数要与 MQTTCONN 的 clean session 保持一致,否则会连不上。有的固件实现要求这个匹配(例如都用1)。
- 检查 ESP8266 是否早先有保持的连接没有断开。可以在尝试前
AT+MQTTCLEAN=0断开旧连接(若支持),或干脆复位模块再连。 - 确认你的 OneNet 产品的接入协议确实是 MQTT,设备也在MQTT列表里。如果产品是HTTP类型,用MQTT连接可能会被拒绝协议不匹配。
问2: ESP8266 AT 指令总是返回 weird symbols 或 ERROR?
答: 如果收到乱码,可能是波特率不对。ESP8266 默认波特率常为115200;确认 STM32 USART 初始化也设为115200 (STM32与物联网01-ESP8266基本操作 - 博客园)。若还是乱码,可以尝试降低ESP8266的波特率来匹配STM32,比如先用串口调试工具连ESP8266发送 AT+UART=9600,8,1,0,0 将其改为9600, 然后STM32也配置9600通信。
如果返回ERROR多出现在发送长命令时,可能是命令格式有误或串口数据丢失。要确保字符串没有拼写错误且包含必要的引号和逗号。此外检查ESP8266接收缓冲是否足够处理长命令(如MQTTPUBRAW发送时注意分两步)。另外,先发的指令没结束响应又发下一个也会引发 ERROR,因此必须串行等待上条命令OK后再发下一条。可以在指令间加入适当延时 (STM32使用esp8266的AT指令连接mqtt服务器,以Thing Cloud为例(标准库和HAL库)_stm32 mqtt at指令-CSDN博客)。
问3: 数据上报成功了,但在 OneNet 平台看不到曲线或数据?
答: 首先,用 OneNet 开发者中心的“设备调试”或API调试工具查看设备是否有数据。如果 MQTT 连接和上报都OK,检查 JSON 格式和数据类型:OneNet 区分数据类型(数值、字符串等),如果物模型里属性定义为数值,你上传的 JSON value必须是数值而非字符串,否则平台可能拒绝入库。另一个可能原因:OneNet Studio需要你先为产品添加**数据流模板(物模型)**才能在可视化中看到图表。如果没定义过数据流,OneNet老平台会自动根据首次上报创建数据流,但新Studio里尽管数据收到了,也许不会显示曲线,除非在物模型里注册该属性。建议提前在产品的“数据流模板”里添加 temp 和 humi 属性。
如果以上都检查过还是无数据,考虑设备APIKey权限。若用Master APIKey上传HTTP数据,要在请求Header带对的 key (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)。对于 MQTT 上报,只要连上成功一般不会有权限问题。可尝试用 MQTT.fx 工具模拟上传看平台表现,以分辨问题出在设备端还是平台端。
问4: HTTP 获取数据时返回 {"errno":10, "error":"key invalid"} 或类似错误?
答: errno=10表示 APIKey 无效或没有权限。请检查HTTP请求Header中的 api-key 是否正确(注意不要拼成 apikey 或 Api-Key,必须全小写中间有连字符) (轻松使用中移物联网平台Onenet,MQTT协议快速接入实验 - ThingsKit)。并确认使用的Key对应设备。若设备ID与APIKey不匹配,也会无权限(比如用A设备的APIKey去查B设备的数据)。可以在 OneNet 控制台的设备管理中点设备详情,看右上角是否可以获取该设备的APIKey,或者使用产品的 Master APIKey尝试。如果Master Key也提示无效,可能是key填错或已失效(OneNet某些操作需要先激活产品)。
另外,如果你的HTTP请求用了 https://open.iot.10086.cn/studio/http 之类的新域名,则不能用APIKey,要改用Token鉴权 (最新版Onenet云平台HTTP协议接入上传数据_onenet物联网postman软件-CSDN博客)。建议使用api.heclouds.com方便。
问5: 移动App能否直接用MQTT而不是HTTP?
答: 当然可以。App 其实也能作为 MQTT 客户端连接 OneNet Broker(用手机流量/WiFi),只要提供正确的产品ID/设备ID/APIKey。但通常手机App不被视为OneNet的“设备”,而是一种应用。如果App以设备身份MQTT接入,会占用一个设备ID,而且OneNet没有针对应用的MQTT通道,只能让App也作为同产品下的“另一设备”加入。这带来管理和安全的复杂度,不如调用HTTP API方便。因此常见实践是:设备用MQTT,App用HTTP。不过OneNet也允许第三方服务器通过MQTT订阅设备数据实现实时推送功能,如果需要,可以研究 OneNet 提供的应用MQTT接口或者结合使用OneNet的MQTT桥接能力。对于本案例,HTTP 足矣,实时性要求不高且实现简单。
问6: STM32 处理 MQTT 下行消息时有时解析不完整,可能丢字符,怎么办?
答: 这可能因为 UART 接收缓冲过小或处理不及时。如果命令JSON较长,而STM32没有用中断/DMAdma持续接收,很可能丢失部分数据。建议开启UART空闲中断,将每次接收的数据放入循环缓冲,然后解析一整帧。也可考虑降低ESP8266的UART发送速度或拆分消息。因为ESP8266收到MQTT消息后,一次性通过串口吐出,对于72MHz MCU还是能处理的,只是要确保接收中断优先级高且处理快。可以简单做法:利用 '\n' 换行判断一条消息结束,然后处理。OneNet的MQTTURC一般一条消息就是一行。
问7: 能否在 OneNet 平台直接让设备把数据转发到我自己的服务器?
答: OneNet 提供数据转发和HTTP触发器等功能,可以配置当设备上传数据或事件发生时,平台自动向你的业务服务器发送HTTP POST通知。这属于OneNet更高级的应用功能。对于初学者,先实现基本的云存储和查询较好。如果将来要大规模部署设备,并在自己服务器汇总处理数据,可考虑使用 OneNet OpenAPI 拉取数据,或配置触发器使OneNet推送数据到指定URL。详细可以查阅OneNet开放平台文档中的“数据转发”和“触发器”章节。
至此,我们完整地介绍了 STM32F103C8T6 + ESP8266-01 连接 OneNet 平台并通过 MQTT/HTTP 进行数据通信的流程。从 OneNet 平台准备、硬件连接、固件指令、到STM32代码逻辑、再到应用层接口都进行了说明和示例。希望通过本指南,读者能够搭建起自己的物联网小系统,实现设备数据上云和远程控制。OneNet 平台功能丰富,在掌握上述基础后,可以进一步探索如:数据触发报警、设备分享、更多传感类型接入、以及结合微信小程序等扩展,实现更加完善的物联网应用。
相关文章:
万字技术指南STM32F103C8T6 + ESP8266-01 连接 OneNet 平台 MQTT/HTTP
此博客为一份详细的指南,涵盖 STM32F103C8T6 通过 ESP8266-01 连接 OneNet 平台,并使用 MQTT/HTTP 进行数据通信的完整流程。这份文档包括: OneNet 平台的介绍与功能概览在 OneNet 上创建和配置设备的方法STM32CubeIDE 的开发环境搭建ESP826…...
MWC 2025 | 紫光展锐联合移远通信推出全面支持R16特性的5G模组RG620UA-EU
2025年世界移动通信大会(MWC 2025)期间,紫光展锐联合移远通信,正式发布了全面支持5G R16特性的模组RG620UA-EU,以强大的灵活性和便捷性赋能产业。 展锐芯加持,关键性能优异 RG620UA-EU模组基于紫光展锐V62…...
PyCharm 接入 DeepSeek、OpenAI、Gemini、Mistral等大模型完整版教程(通用)!
PyCharm 接入 DeepSeek、OpenAI、Gemini、Mistral等大模型完整版教程(通用)! 当我们成功接入大模型时,可以选中任意代码区域进行解答,共分为三个区域,分别是选中区域、提问区域以及回答区域,我…...
小智智能体语言大模型硬件软件开发
硬件可以参考ESP32-AI语音助手 - 立创开源硬件平台 单片机使用esp32s3,可以直接替换,但是引脚IO有变化,而且esp32s3 io35 36 37不能用,所以得飞一条线,原先接在io35的飞到io4上。如果不飞线的话系统一直重启 软件使用…...
网络tcp协议设置,网络tcp协议设置不了
网络TCP协议的设置通常涉及到多个方面,包括IP地址、子网掩码、默认网关、DNS服务器等参数的配置,以及TCP/IP协议栈本身的配置。如果遇到网络TCP协议设置不了的问题,可能是由多种原因导致的。以下是一些可能的原因及解决方法: 一、…...
配置Hadoop集群
Hadoop的运行模式 本地运行:在一台单机上运行,没有分布式文件系统,直接读写本地操作系统的文件系统。特点:不对配置文件进行修改,Hadoop 不会启动 伪分布式:也是在一台单机上运行,但用不同的 …...
模型微调-基于LLaMA-Factory进行微调的一个简单案例
模型微调-基于LLaMA-Factory进行微调的一个简单案例 1. 租用云计算资源2. 拉取 LLaMa-Factory3. 安装依赖环境4. 启动 LLaMa-Factory 界面5. 从 Huggingface 下载模型6. 模型验证7. 模型微调 1. 租用云计算资源 以下示例基于 AutoDL 云计算资源。 在云计算平台选择可用的云计…...
设置重定向不缓存
response.setHeader(“Cache-Control”, “no-cache, no-store, must-revalidate”); response.setHeader(“Pragma”, “no-cache”);response.setHeader(“Expires”, “0”);response.sendRedirect(newURL); response.setContentType(“text/html;charsetUTF-8”); PrintWr…...
java-算法基础优化
一、ACM风格输入输出(高效,替换原有的输入输出流) 1.推荐原因:(内存托管) 对于原本的Scanner读取流,只能根据行来读取数据,而BufferredReader读取信息可以直接读取整个文件…...
⚡ 回声谷即时通讯系统
基于SpringBootVue3的实时通信解决方案 🌟 核心特性 #mermaid-svg-uxEwEcjlUVI6Tjjf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-uxEwEcjlUVI6Tjjf .error-icon{fill:#552222;}#mermaid-svg-uxEwEcjl…...
《 PyQt5》—— 创建 Python GUI(图形用户界面)
文章目录 PyQt5安装基本概念进行配置配置QtDesigner配置PyUIC配置Pyrcc 使用PyQt5使用如何使用ui文件 PyQt5 PyQt5 是一个用于创建 Python GUI(图形用户界面)应用程序的强大工具包,它是 Qt 应用程序框架的 Python 绑定。Qt 是一个跨平台的 C…...
Python图形编程之EasyGUI: indexbox的用法
目录<<上一章:ynbox用法详解 下一章:boolbox用法详解 >> # 1 Python图形编程之EasyGUI: indexbox的用法 1.1 基本用法 indexbox提供用户一个选择不同选项的功能,不同的选项由按钮来表示,提供类似功能的还有choicebox…...
vue+dhtmlx-gantt 实现甘特图-快速入门【甘特图】
文章目录 一、前言二、使用说明2.1 引入依赖2.2 引入组件2.3 引入dhtmlx-gantt2.4 甘特图数据配置2.5 初始化配置 三、代码示例3.1 Vue2完整示例3.2 Vue3 完整示例 四、效果图 一、前言 dhtmlxGantt 是一款功能强大的甘特图组件,支持 Vue 3 集成。它提供了丰富的功…...
游戏引擎学习第147天
仓库:https://gitee.com/mrxiao_com/2d_game_3 上一集回顾 具体来说,我们通过隐式计算来解决问题,而不是像数字微分分析器那样逐步增加数据。我们已经涵盖了这个部分,并计划继续处理音量问题。不过,实际上我们现在不需要继续处理…...
Python自动点击器开发教程 - 支持键盘连按和鼠标连点
Python自动点击器开发教程 - 支持键盘连按和鼠标连点 这里写目录标题 Python自动点击器开发教程 - 支持键盘连按和鼠标连点项目介绍开发环境安装依赖核心代码解析1. 键盘模拟实现2. 鼠标点击实现 开发要点使用说明注意事项优化建议打包发布项目源码开发心得参考资料成品工具 项…...
C++ 链表List使用与实现:拷贝交换与高效迭代器细致讲解
目录 list的使用: 构造与赋值 元素访问 修改操作 容量查询 链表特有操作 拼接(Splice) C11 新增方法 注意: stl_list的模拟实现: 一、链表节点设计的艺术 1.1 结构体 vs 类的选择 二、迭代器实现的精髓 2…...
Manus联创澄清:我们并未使用MCP技术
摘要 近日,Manus联创针对外界关于其产品可能涉及“沙盒越狱”的疑问进行了正式回应。公司明确表示并未使用Anthropic的MCP(模型上下文协议)技术,并强调MCP是一个旨在标准化应用程序与大型语言模型(LLM)之间…...
ACE学习2——write transaction
用于处理缓存行的数据更新到主内存(main memory)的操作。 以下是用于更新主内存的几种事务类型: WriteBack: WriteBack事务用于将cache中的dirty态的cacheline写回主存,以释放cache中的cacheline,用于存…...
c++ 返回引用
在C中,返回引用是一种常见的做法,特别是在需要返回大型对象时,以避免不必要的复制,从而提高程序的效率。返回引用通常有两种情况:返回局部变量的引用和返回成员变量的引用。下面分别讨论这两种情况以及如何安全地实现它…...
Docker篇
1.docker环境搭建: 1.1软件仓库的配置rhel9: #cd/etc/yum.repos.d #vim docker.repo [docker] namedocker-ce baseurlhttps://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable gpgcheck0 1.2安装docker并且启动服务 yum install -y dock…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
