当前位置: 首页 > news >正文

在ESP-IDF环境中如何进行多文件中的数据流转-FreeRTOS实时操作系统_流缓存区“xMessageBuffer”

一、建立三个源文件和对应的头文件

建立文件名,如图所示

图 1-1

二、包含相应的头文件

main.h

图 2-1

mess_send.h

mess_rece.h和这个中类似,不明白的大家看我最后面的源码分享

图2-2

三、声明消息缓存区的句柄

大家注意,在main.c中定义的是全局变量图3-1所示

mess_send.c和mess_rece.c则定义的是外部变量,如图3-2所示

图 3-1

图3-2

四、xMessageBufferCreate函数

xMessageBufferCreate:此函数的作用是为句柄创造一个消息缓存区,用来存储在不同任务之间流转的数据,需要在流转任务执行之间进行创建。

configASSERT(xMessageBuffer != NULL);

此函数是用来确认是否创建成功了,是否成功初始化了资源

xMessageBuffer = xMessageBufferCreate(1024);  // 缓冲区大小为100字节
configASSERT(xMessageBuffer != NULL);

图 4-1

五、xMessageBufferSend发送函数

注意图 5-1中所示的方框,这里要用strlen,千万注意,用错了,会有发送错误的可能

图 5-1

官方示例程序:

大家注意看,当发送的信息是数组形式的时候,用的sizeof;发送字符串的时候用的是strlen。大家使用的时候一定要注意区分。

为什么使用不同的方法

  1. 数组
  • 数组的大小是固定的,并且包含了所有元素的总大小。使用 sizeof 可以确保你发送整个数组的内容。
  • 如果数组不是以空字符结尾的,使用 strlen 会得到错误的结果,因为它会一直读取直到遇到第一个空字符,可能会导致越界访问或未定义行为。

     2.字符串

  • 字符串是以空字符 \0 结尾的字符数组。strlen 函数计算的是从字符串开始到第一个空字符之间的字符数,不包括空字符本身。
  • 使用 strlen 可以确保只发送字符串的有效内容,而不包括结尾的空字符。这对于消息缓冲区来说是合理的,因为你通常不需要发送多余的空字符。
void vAFunction( MessageBufferHandle_t xMessageBuffer )
{
size_t xBytesSent;
uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
char *pcStringToSend = "String to send";
const TickType_t x100ms = pdMS_TO_TICKS( 100 );// Send an array to the message buffer, blocking for a maximum of 100ms to// wait for enough space to be available in the message buffer.xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );if( xBytesSent != sizeof( ucArrayToSend ) ){
// The call to xMessageBufferSend() times out before there was enough
// space in the buffer for the data to be written.}// Send the string to the message buffer.  Return immediately if there is// not enough space in the buffer.xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );if( xBytesSent != strlen( pcStringToSend ) ){
// The string could not be added to the message buffer because there was
// not enough free space in the buffer.}
}

我的程序:
 

参数解释

  1. xMessageBuffer:
  • 类型: MessageBufferHandle_t
  • 描述: 这是消息缓冲区的句柄,由 xMessageBufferCreate 创建并返回。你需要传递这个句柄来指定将数据发送到哪个消息缓冲区。

  2.pvTxData:

  • 类型: const void *
  • 描述: 这是一个指向要发送的数据的指针。函数将从这个指针开始复制数据到消息缓冲区中。

  3.xDataLengthBytes:

  • 类型: size_t
  • 描述: 这是要发送的数据的长度(以字节为单位)。函数将尝试将 xDataLengthBytes 字节的数据发送到消息缓冲区。如果消息缓冲区没有足够的空间来容纳这些数据,任务可能会被阻塞,直到有足够的空间。

  4.xTicksToWait:

  • 类型: TickType_t
  • 描述: 这是指定任务在消息缓冲区没有足够空间时等待的最大时间。你可以使用以下几种值:
  • 0: 不等待,立即返回。如果消息缓冲区没有足够的空间,则返回 0。
  • portMAX_DELAY: 无限等待,直到消息缓冲区有足够空间。
  • 其他正值: 指定等待的滴答数(ticks)。例如,pdMS_TO_TICKS(100) 表示等待 100 毫秒。
#include "mess_send.h"const static char *TAG = "mess_send";
extern MessageBufferHandle_t xMessageBuffer;/*  */void mess_send()
{while (1){char *jsondata = "da_di_ji_de_xiao_bai";size_t xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)jsondata, strlen(jsondata) ,0);  // 包括终止符if ( xBytesSent != strlen(jsondata)) {   ESP_LOGE(TAG, "Failed to send message");} else {ESP_LOGI(TAG, "Message sent: %s", jsondata); }vTaskDelay(pdMS_TO_TICKS(1000)); // 适当延时}
}

六、xMessageBufferReceive函数

char received_message [1024];参考我的程序

使用接收缓存区的时候,上来一定要先定义一个接收信息的地方,要不然,你一直接收人家,也不给人家安排地方休息,那不是让人家不得不乱转,那你到时候最后出事了,你就不能怪别人了。

你不仅要安排,你还要安排足够多的空间。

官方示例程序:

void vAFunction( MessageBuffer_t xMessageBuffer )
{
uint8_t ucRxData[ 20 ];
size_t xReceivedBytes;
const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );// Receive the next message from the message buffer.  Wait in the Blocked// state (so not using any CPU processing time) for a maximum of 100ms for// a message to become available.xReceivedBytes = xMessageBufferReceive( xMessageBuffer,( void * ) ucRxData,sizeof( ucRxData ),xBlockTime );if( xReceivedBytes > 0 ){
// A ucRxData contains a message that is xReceivedBytes long.  Process
// the message here....}
}

我的程序:

我的程序比较多,因为我加入了一些调试信息,这样运行后可以清楚的看出错误出在哪里

参数解释:

1.xMessageBuffer:

  • 类型: MessageBufferHandle_t
  • 描述: 这是消息缓冲区的句柄,由 xMessageBufferCreate 创建并返回。你需要传递这个句柄来指定从哪个消息缓冲区接收数据。

2.pvRxData:

  • 类型: void *
  • 描述: 这是一个指向接收数据的缓冲区的指针。函数将从消息缓冲区中读取的数据复制到这个缓冲区中。你需要确保这个缓冲区足够大,以容纳你希望接收的数据。

3.xBufferLengthBytes:

  • 类型: size_t
  • 描述: 这是 pvRxData 缓冲区的大小(以字节为单位)。函数将尝试从消息缓冲区中读取最多 xBufferLengthBytes 字节的数据。如果消息缓冲区中的数据少于 xBufferLengthBytes,则只读取可用的数据量。

4.xTicksToWait:

  • 类型: TickType_t
  • 描述: 这是指定任务在没有数据可接收时等待的最大时间。你可以使用以下几种值:
  • 0: 不等待,立即返回。如果没有数据可接收,则返回 0。
  • portMAX_DELAY: 无限等待,直到有数据可接收。
  • 其他正值: 指定等待的滴答数(ticks)。例如,pdMS_TO_TICKS(100) 表示等待 100 毫秒。
#include "mess_rece.h"
extern MessageBufferHandle_t xMessageBuffer;
const static char *TAG = "mess_rece";void mess_rece()
{while(1){char received_message [1024];const TickType_t xBlockTime = pdMS_TO_TICKS(100);size_t received_size = xMessageBufferReceive(xMessageBuffer, (void*)received_message,sizeof(received_message)-1, xBlockTime);if(received_size >0 ){received_message[received_size] = '\0';  // 添加终止符// 打印接收到的消息ESP_LOGI(TAG, "mess_rece: %s", received_message);// 检查字符串是否有效if (strlen(received_message) != received_size){ESP_LOGE(TAG, "String length mismatch: expected %zu, got %zu", received_size, strlen(received_message));continue;  // 跳过无效的字符串}} else {ESP_LOGW(TAG, "No message received, waiting...");}vTaskDelay(pdMS_TO_TICKS(900));  // 如果没有接收到数据,则等待一段时间后再次尝试}}

七、关于创建任务的一些补充(挺重要的,建议多看)

补充点:为什么创建任务对应的函数内必须有一个while(1)循环

  1. 任务的持续性
    无限循环:while (1) 循环确保任务不会退出。一旦任务函数返回,FreeRTOS 会自动删除该任务并释放其资源。如果任务需要持续运行以执行某些操作(如周期性地发送或接收数据、监控传感器等),则必须使用无限循环。
    避免任务结束:如果任务函数没有无限循环并且直接返回,任务将被删除,导致该任务的功能无法继续执行。
  2. 任务的状态管理
    阻塞和等待:在 while (1) 循环中,任务可以执行一些操作,然后进入阻塞状态(例如通过 vTaskDelay 或其他阻塞 API)。这样可以有效地管理 CPU 资源,避免任务一直占用 CPU 时间。
    事件驱动:任务可以在 while (1) 循环中等待特定的事件(例如消息队列中的消息、信号量等),并在事件发生时进行处理。
  3. 任务调度
    抢占式调度:FreeRTOS 是一个抢占式实时操作系统。当高优先级任务准备好运行时,当前正在运行的低优先级任务会被中断并切换到高优先级任务。因此,任务函数中的 while (1) 循环允许任务在需要时被调度器暂停和恢复。
    时间片轮转:在相同优先级的任务之间,FreeRTOS 可以使用时间片轮转调度。while (1) 循环允许任务在每次时间片结束后重新开始执行。

八、源码分享

main.c

#include "main.h"
MessageBufferHandle_t xMessageBuffer;const static char *TAG = "main";void app_main(void)
{xMessageBuffer = xMessageBufferCreate(1024);  // 缓冲区大小为100字节configASSERT(xMessageBuffer != NULL);// 创建任务xTaskCreate(mess_send,          // 任务函数"mess_sendTask",      // 任务名称4096,               // 任务堆栈大小(以字为单位)NULL,               // 传递给任务函数的参数1,                  // 任务优先级NULL);              // 任务句柄(不需要)xTaskCreate(mess_rece,          // 任务函数"mess_receTask",      // 任务名称4096,               // 任务堆栈大小(以字为单位)NULL,               // 传递给任务函数的参数1,                  // 任务优先级NULL);              // 任务句柄(不需要)// 主任务可以继续执行其他操作while (1) {vTaskDelay(pdMS_TO_TICKS(5000)); // 主任务每 5 秒打印一次ESP_LOGI(TAG, "successful");}
}

main.h

#ifndef __MAIN_H
#define __MAIN_H#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/message_buffer.h"                //使用消息缓存区应该包含的头文件#include "stdio.h"
#include "string.h"#include "mess_rece.h"                              //包含创建的接收和发送的两个文件的头文件
#include "mess_send.h"#endif

mess_send.c

#include "mess_send.h"const static char *TAG = "mess_send";
extern MessageBufferHandle_t xMessageBuffer;/*  */void mess_send()
{while (1){char *jsondata = "da_di_ji_de_xiao_bai";size_t xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)jsondata, strlen(jsondata) ,0);  // 包括终止符if ( xBytesSent != strlen(jsondata)) {   ESP_LOGE(TAG, "Failed to send message");} else {ESP_LOGI(TAG, "Message sent: %s", jsondata); }vTaskDelay(pdMS_TO_TICKS(1000)); // 适当延时}
}

mess_send.h

#ifndef __MESS_SEND_H
#define __MESS_SEND_H#include "main.h"/* 函数声明区 */void mess_send();
#endif

mess_rece.c

#include "mess_rece.h"
extern MessageBufferHandle_t xMessageBuffer;
const static char *TAG = "mess_rece";void mess_rece()
{while(1){char received_message [1024];const TickType_t xBlockTime = pdMS_TO_TICKS(100);size_t received_size = xMessageBufferReceive(xMessageBuffer, (void*)received_message,sizeof(received_message)-1, xBlockTime);if(received_size >0 ){received_message[received_size] = '\0';  // 添加终止符// 打印接收到的消息ESP_LOGI(TAG, "mess_rece: %s", received_message);// 检查字符串是否有效if (strlen(received_message) != received_size){ESP_LOGE(TAG, "String length mismatch: expected %zu, got %zu", received_size, strlen(received_message));continue;  // 跳过无效的字符串}} else {ESP_LOGW(TAG, "No message received, waiting...");}vTaskDelay(pdMS_TO_TICKS(900));  // 如果没有接收到数据,则等待一段时间后再次尝试}}

mess_rece.h

#ifndef __MESS_RECE_H
#define __MESS_RECE_H#include "main.h"void mess_rece();
#endif

相关文章:

在ESP-IDF环境中如何进行多文件中的数据流转-FreeRTOS实时操作系统_流缓存区“xMessageBuffer”

一、建立三个源文件和对应的头文件 建立文件名&#xff0c;如图所示 图 1-1 二、包含相应的头文件 main.h 图 2-1 mess_send.h mess_rece.h和这个中类似,不明白的大家看我最后面的源码分享 图2-2 三、声明消息缓存区的句柄 大家注意&#xff0c;在main.c中定义的是全局变…...

ConcurrentLinkedQueue适合什么样的使用场景?

ConcurrentLinkedQueue 是 Java 中一种无界线程安全的队列&#xff0c;适合多线程环境中的高并发场景。以下是一些它特别适合的使用场景&#xff1a; 1. 高频读操作&#xff0c;低频写操作 ConcurrentLinkedQueue 对于实际应用中读操作相对频繁&#xff0c;写操作较少的场景非…...

C语言 | Leetcode C语言题解之第480题滑动窗口中位数

题目&#xff1a; 题解&#xff1a; struct Heap {int* heap;int heapSize;int realSize;bool (*cmp)(int, int); };void init(struct Heap* obj, int n, bool (*cmp)(int, int)) {obj->heap malloc(sizeof(int) * (n 1));obj->heapSize 0;obj->cmp cmp; }bool c…...

LabVIEW开发如何实现降维打击

在LabVIEW开发中实现“降维打击”可以理解为利用软件优势和高效工具来解决复杂的问题&#xff0c;将多维度、多层次的技术简化为容易操作和管理的单一维度&#xff0c;达到出其不意的效果。以下是几种关键策略&#xff1a; 1. 模块化设计与封装 将复杂系统分解为若干模块&…...

docker 文件目录迁移

文章参考 du -hs /var/lib/docker/ 命令查看磁盘使用情况。 du -hs /var/lib/docker/docker system df命令&#xff0c;类似于Linux上的df命令&#xff0c;用于查看Docker的磁盘使用情况: rootnn0:~$ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 7 2 122.2…...

Markdown 标题

Markdown 标题 Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式化的HTML代码。Markdown 的语法简洁明了,广泛用于撰写文档、博客文章、笔记等。本文将详细介绍 Markdown 的标题语法及其在文档中的应用。 Markdown 标题语法 在…...

【动手学电机驱动】TI InstaSPIN-FOC(5)Lab04 力矩控制

TI InstaSPIN-FOC&#xff08;1&#xff09;电机驱动和控制测试平台 TI InstaSPIN-FOC&#xff08;2&#xff09;Lab01 闪灯实验 TI InstaSPIN-FOC&#xff08;3&#xff09;Lab03a 测量电压电流漂移量 TI InstaSPIN-FOC&#xff08;4&#xff09;Lab02b 电机参数辨识 TI Insta…...

Mysql的CommunicationsException

一、报错内容 com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 1,500,378 milliseconds ago. The last packet sent successfully to the server was 1,500,378 milliseconds ago. is longer than the s…...

C++学习笔记----9、发现继承的技巧(二)---- 重用目的的继承

现在你对继承的基本语法已经比较熟悉了&#xff0c;是时候探索继承是c语言中重要属性的一个主要原因了。继承是一个装备允许你平衡既有代码。本节会举出基于代码重用目的的继承的例子。 1、WeatherPrediction类 假想你有一个任务&#xff0c;写一个程序来发出简单的天气预报&a…...

锐评 Nodejs 设计模式 - 创建与结构型

本系列文章的思想&#xff0c;都融入了 让 Java 再次伟大 这个全新设计的脚手架产品中&#xff0c;欢迎大家使用。 单例模式与模块系统 Node 的单例模式既特殊又简单——凡是从模块中导出的实例天生就是单例。 // database.js function Database(connect, account, password)…...

【RoadRunner】自动驾驶模拟3D场景构建 | 软件简介与视角控制

&#x1f4af; 欢迎光临清流君的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落 &#x1f4af; &#x1f525; 个人主页:【清流君】&#x1f525; &#x1f4da; 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 &#x1f4da; &#x1f31f;始终保持好奇心&…...

15分钟学Go 第4天:Go的基本语法

第4天&#xff1a;基本语法 在这一部分&#xff0c;将讨论Go语言的基本语法&#xff0c;了解其程序结构和基础语句。这将为我们后续的学习打下坚实的基础。 1. Go语言程序结构 Go语言程序的结构相对简单&#xff0c;主要包括&#xff1a; 包声明导入语句函数语句 1.1 包声…...

【Qt】Qt的介绍——Qt的概念、使用Qt Creator新建项目、运行Qt项目、纯代码方式、可视化操作、认识对象模型(对象树)

文章目录 Qt1. Qt的概念2. 使用Qt Creator新建项目3. 运行Qt项目3.1 纯代码方式实现3.2 可视化操作实现 4. 认识对象模型&#xff08;对象树&#xff09; Qt 1. Qt的概念 Qt 是一个跨平台的 C 图形用户界面应用程序开发框架。它是软件开发者提供的用于界面开发的程序框架&#…...

论文笔记:PTR: Prompt Tuning with Rules for Text Classification

Abstract 手动设计大量语言提示麻烦且易出错&#xff0c;而自动生成的提示&#xff0c;在非小样本场景下验证其有效性昂贵且耗时。因此&#xff0c;提示调优以处理多类别分类任务仍然具有挑战。为此&#xff0c;本文提出使用规则进行多类别文本分类提示调优&#xff08;PTR&…...

服务器和中转机协同工作以提高网络安全

服务器和中转机&#xff08;代理服务器&#xff09;可以通过多种方式协同工作来提高网络安全。 常见的协同工作策略&#xff1a; 1. 使用代理服务器作为安全网关 访问控制&#xff1a;代理服务器可以作为网络的入口点&#xff0c;实施访问控制策略&#xff0c;如基于IP地址、…...

Java利用itextpdf实现pdf文件生成

前言 最近公司让写一个数据页面生成pdf的功能&#xff0c;找了一些市面代码感觉都太麻烦&#xff0c;就自己综合性整合了一个便捷的工具类&#xff0c;开发只需简单组装数据直接调用即可快速生成pdf文件。望大家一起学习&#xff01;&#xff01;&#xff01; 代码获取方式&am…...

2010年国赛高教杯数学建模C题输油管的布置解题全过程文档及程序

2010年国赛高教杯数学建模 C题 输油管的布置 某油田计划在铁路线一侧建造两家炼油厂&#xff0c;同时在铁路线上增建一个车站&#xff0c;用来运送成品油。由于这种模式具有一定的普遍性&#xff0c;油田设计院希望建立管线建设费用最省的一般数学模型与方法。   1. 针对两炼…...

datawhale大模型bot应用开发--task3:工作流

目录 一、介绍&#xff1a;Coze工作流 1.1工作流应用场景 1.2什么是工作流 1.3思考环节 二、各个工作流详情 2.1情感分类工作流 2.2 随机数工作流 2.3 必应搜索工作流 2.4 天气查询工作流 三、集合上面五个工作流的总工作流 一、介绍&#xff1a;Coze工作流 1.1工作…...

期货配资系统风控逻辑开发/完整源代码

期货配资系统风控逻辑的开发是确保系统安全、稳定、高效运行的关键环节。以下是对期货配资系统风控逻辑开发的详细分析&#xff1a; 一、风险识别与评估 风险来源分析&#xff1a; 市场风险&#xff1a;期货市场价格波动带来的风险。信用风险&#xff1a;投资者或配资方违约的…...

汽车免拆诊断案例 | 2023款零跑C01纯电车后备厢盖无法电动打开和关闭

故障现象  一辆2023款零跑C01纯电车&#xff0c;累计行驶里程约为2万km&#xff0c;车主进厂反映&#xff0c;后备厢盖无法电动打开和关闭。 故障诊断  接车后试车&#xff0c;操作后备厢盖外侧、驾驶人侧及遥控钥匙上的后备厢盖开启按钮&#xff0c;可以听到后备厢盖解锁的…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...