基于PESdk和EasyModbus实现录波控制逻辑和数据传输

news2024/11/29 6:32:06

文章目录

    • 0. 概要
    • 1. 录波功能简介
      • 1.1 功能框架
      • 1.2 录波控制逻辑
      • 1.3 手动录波数据传输流程
      • 1.4 故障录波传输流程
    • 2 C语言应用程序接口(API)
      • 2.1 EasyModbus接口
      • 2.2 PESdk
    • 3 录波功能的实现
      • 3.1 功能码定义
        • 3.1.1 公共功能码
        • 3.1.2 用户自定义功能码
        • 3.1.3 保留功能码
      • 3.2 录波功能寄存器定义
        • 3.2.1 公共寄存器
        • 3.2.2 手动录波寄存器
        • 3.2.3 故障录波寄存器
      • 3.3 示例代码
        • 3.3.1 Modbus初始化和回调函数
        • 3.3.2 录波器初始化和回调函数
        • 3.3.3. 录波器API调用和数据填充
    • 4 录波数据展示

0. 概要

本文介绍C语言库PESdk和EasyModbus在没有文件系统的嵌入式设备上实现手动录波、故障录波数据存储的功能,配合上位机软件DeMate进行录波数据的传输、展示,将录波数据保存到Comtrade文件中。

PESdk是可用于电力电子设备控制开发的C语言库,对一些比较通用的功能进行抽象和开发,手动录波、故障录波是其中的一部分功能。EasyModbus支持RTU和TCP/IP,实现了Modbus协议的公共功能码,扩展了功能码对录波数据和工控数据寄存器进行隔离,扩大可用于录波数据存储的寄存器地址空间。PESdk和EasyModbus不依赖于具体的硬件或操作系统

1. 录波功能简介

1.1 功能框架

整个系统和录波相关的功能架构如下图。
功能框架
DeMate是上位机,运行于Windows操作系统,DSP或ARM是下位机,EasyModbu和PESdk向上提供通信和录波的基础功能。

  • DeMate
    配置手动录波通道、数据收发、波形展示、故障录波文件的保存和加载,响应用户手动录波指令,配置下位机手动录波通道,启动录波并自动读取录波数据,自动读取故障录波数据;
  • 应用程序
    串口设备的初始化、数据转发、填充录波数据;
  • EasyModbus
    接收Modbus RTU数据帧,读写寄存器,响应上位机的请示;
  • PESdk
    录波初始化,录波控制逻辑;

1.2 录波控制逻辑

启动手动录波器时,从数据缓存首地址开始向后填充数据,数据填满时置完成标志位,等待上位机来读数据。

  • 手动录波控制逻辑
    故障录波器在系统启动的时候就开始缓存数据,故障发生时记录当前时刻的数据缓存位置,继续缓存由寄存器PostFault指定的数据个数后停止录波,等待上位机读取数据。如果读取数据之前系统故障消除,则故障录波器自动启动,之前的缓存将会被新数据覆盖。
    手动录波流程
    故障录波器在系统启动的时候就开始缓存数据,故障发生时记录当前时刻的数据缓存位置,继续缓存由寄存器PostFault指定的数据个数后停止录波,等待上位机读取数据。如果读取数据之前系统故障消除,则故障录波器自动启动,之前的缓存将会被新数据覆盖。
    故障录波流程图

1.3 手动录波数据传输流程

手动录波由用户发起,DeMate按照协议和流程给下位机发送手动录波指令、录波通道对应的modbus点表地址,经过一定的延时后读取录波器状态位,决定是否要发起读取数据的流程,数据读取完毕后以曲线的形式向用户展示,用户可以将录波数据保存到本地的Comtrade文件中。
手动录波时序图

1.4 故障录波传输流程

在正常运行的情况下,PESdk的故障录波控制逻辑在应用程序的回调函数中循环刷新故障数据缓存,当应用程序检测到故障时,PESdk自动计算停止录波的时刻,以满足存储故障前、后数据点数的要求。
故障录波数据缓存示意图
假设在t8时刻发生了故障,在t10时刻停止录波,上位机从t4开始读取数据,读取数据完成后需要做数据移位处理,才能从t1~t10依次保存或展示数据。

上位机在后台线程中不间断地读取寄存器状态,当录波标志位置位时自动发起读故障的流程,读故障录波数据的时序图如下。
故障录波时序图

2 C语言应用程序接口(API)

EasyModbus和PESdk提供一系列API,支持数据的传输和录波控制逻辑的实现。
和录波相关的API

2.1 EasyModbus接口

接口描述
modbus_rtu_init初始化一个modbus结构体变量,指定数据接收完成、校验失败、发送数据的回调,等。
modbus_rtu_push接收modbus数据,内部做了帧长度合法性校验,接收完成后进入回调函数进行处理
modbus_rtu_reset应用程序处理完modbus数据帧后复位结构体的相关变量,准备接收下一帧
modbus_rtu_response从机的响应处理,在内部进行数据的拷贝和组包,如果在modbus_rtu_init中指定了发送数据的回调函数,则自己调用回调函数进行发送
mbtable_get_item_value从Modbus点表中读取数据项的值
mbtable_set_item_value设置Modbus点表某个数据项的值,内部有数据超上、下限的校验
mbtable_get_item_index获取数据项在Modbus点表中的下标
mbtable_reset_item_to_default设置Modbus点表中某个数据项为默认值
mbtable_reset_all_to_default设置Modbus点表中所有数据项为默认值

2.2 PESdk

接口描述
recorder_get_profile读录波寄存器
recorder_set_profile写录波寄存器
recorder_reset_fault复位故障录波相关寄存器
recorder_reset_manual复位手动录波相关寄存器
recorder_fault_record故障录波入口
recorder_manual_record手动录波入口

3 录波功能的实现

3.1 功能码定义

Modbus功能码占用一个字节,取值范围是 1~127(即 0x01~0x7F)。同时,使用功能码+0x80 表示异常状态,即129~255 代表异常码。功能码可分为位操作和字操作两类,位操作的最小单位为1位(bit),字操作的最小单位为两个字节。
在 Modbus 标准协议中,一共规定了三类Modbus功能码:公共功能码、用户自定义功能码和保留功能码。

3.1.1 公共功能码

公共功能码有如下特点:(1)被明确定义的功能码;(2)保证唯一性;(3)由 Modbus 协会确认,并提供公开的文档;(4)可进行一致性测试;(5)包括协议定义的功能码和保留将来使用的功能码。
常用的部分公共功能码见下表。

代码名称地址位/字操作数量
0x01读线圈状态00001~09999单个/多个
0x02读离散输入状态10001~19999单个/多个
0x03读保持寄存器40001~49999单个/多个
0x04读输入寄存器30001~39999单个/多个
0x05写单个线圈00001~09999单个
0x06写单个保持寄存器40001~49999单个
0x0F写多个线圈00001~09999多个
0x10写多个保持寄存器40001~49999多个
3.1.2 用户自定义功能码

Modbus有两个用户自定义功能码区域,分别是 65~72 和 100~110,用于录波的扩展功能码如下表。

代码名称地址位/字操作数量
0x41读录波设置0x0000~0x0068多个
0x42写录波设置0x0000~0x0068多个
0x43读保持寄存器0x0000~0xFFFF多个
0x44读输入寄存器0x0000~0xFFFF多个

上表中的寄存器地址有重叠的部分,由上层应用程序通过功能码进行隔离,并不会冲突。

3.1.3 保留功能码

保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。

3.2 录波功能寄存器定义

3.2.1 公共寄存器
名称地址字节R/W描述
SampleInterval0x00002RO采样点间隔(us)
SerialNum0x0000~0x000816RO序列号,占16个字节,不足的补0
Version0x0009~0x000E12RO版本号
ChannelCount0x000F2RO低8位:最大的手动录波通道数;高8位:最大的故障录波通道数
PostFault0x00102RO故障发生后继续缓存的数据个数
RSV0x0011~0x00136RO预留
3.2.2 手动录波寄存器
名称地址字节R/W描述
Start0x00142RO启动录波控制,可由上位机触发或故障自动触发启动录波
Ready0x00152RO录波就绪状态,0-录波未完成1-录波完成
TimeStamp0x0016~0x00198RO时间戳
ValidChannel0x001A2RO实际使用的录波通道数
DataCount0x001B2RO每个通道的数据个数
DataAddr_0~DataAddr_150x001C~0x002B32RW录波通道对应的数据的寄存器地址,对应于用公共功能码读写的寄存器地址,默认最多支持16个通道,应用程序可根据存储空间的大小确定使用的通道数
RSV0x002C~0x002F8RO预留
3.2.3 故障录波寄存器
名称地址字节R/W描述
Start0x00302RO启动录波控制,可由上位机触发或故障自动触发启动录波
Ready0x00312RO录波就绪状态,0-录波未完成1-录波完成
TimeStamp0x0032~0x00358RO时间戳
ValidChannel0x00362RO实际使用的录波通道数
DataCount0x00372RO每个通道的数据个数
DataAddr_0~DataAddr_150x0038~0x005764RW录波通道对应的数据的寄存器地址,对应于用公共功能码读写的寄存器地址,默认最多支持32个通道,应用程序可根据存储空间的大小确定使用的通道数
Additional Information0x0058~0x006732RO故障录波的附加信息,由上层应用定义
FaultPoint0x00682RO故障时的数据下标

3.3 示例代码

3.3.1 Modbus初始化和回调函数
// 需要包含两个头文件
#include "pesdk.h"
#include "modbusrtu.h"

// 初始化Modbus数据点表
const struct modbus_table_item_t mb_table_items[] =
{
	// {寄存器地址,指向实际的变量指针,{最小值,最大值,默认值},格式}
    {RW_ITEM_START + 0, &mydevice.command.start_pwm, {0, 1, 1}, TDF_U16_RW},
    {RW_ITEM_START + 1, &mydevice.command.reset, {0, 1, 2}, TDF_U16_RW},
    {RW_ITEM_START + 2, &mydevice.command.save_param, {0, 1, 3}, TDF_U16_RW},
    {RW_ITEM_START + 3, &mydevice.command.load_default_param, {0, 1, 0}, TDF_U16_RW},

    {RO_ITEM_START + 0, &mydevice.data.rms.ugrid.a, {0, 10000, 0}, TDF_FLT_RO},
    {RO_ITEM_START + 2, &mydevice.data.rms.ugrid.b, {0, 10000, 0}, TDF_FLT_RO},
    {RO_ITEM_START + 4, &mydevice.data.rms.ugrid.c, {0, 10000, 0}, TDF_FLT_RO},

    {RO_ITEM_START + 6, &mydevice.data.rms.ugridline.ab, {0, 1, 0}, TDF_FLT_RO},
    {RO_ITEM_START + 8, &mydevice.data.rms.ugridline.bc, {0, 1, 0}, TDF_FLT_RO},
    {RO_ITEM_START + 10, &mydevice.data.rms.ugridline.ca, {0, 1, 0}, TDF_FLT_RO},
    ...
};
void init_system(void)
{
    // ...
    // modbus rtu结构体变量,ID,本机地址,客户端,接收完成回调,错误回调,发送数据回调
    modbus_rtu_init(&mbhost, 0, 0x01, MODBUS_INST_TYPE_CLIENT, modbus_frame_recv, modbus_frame_error, &write_scia_bytes);
    // ...
    recorder_init();
    // ...
}

// 接收数据帧完成的回调
void modbus_frame_recv(struct modbus_rtu_inst_t *inst, char  *data, int len)
{
    switch(MODBUS_RTU_REG_CMD(inst))
    {
    case MODBUS_CMD_RD_REGS:       // 0x03功能码
        modbus_resp_cmd03(inst);
        break;
    case MODBUS_CMD_WR_MULT_REGS:  // 0x10功能码
        modbus_resp_cmd10(inst);
        break;
    case MODBUS_CMD_RD_RECORD_PROFILE: // 读录波寄存器
        modbus_resp_read_record_profile(inst);
        break;
    case MODBUS_CMD_WR_RECORD_PROFILE: // 写录波寄存器
        modbus_resp_write_record_profile(inst);
        break;
    case MODBUS_CMD_RD_FAULT_RECORD_DATA: // 读故障录皮数据
        modbus_resp_read_record_data(inst, &fault_record_buff[0][0]);
        break;
    case MODBUS_CMD_RD_MANUAL_RECORD_DATA: // 读手动录波数据
        modbus_resp_read_record_data(inst, &manual_record_buff[0][0]);
        break;
    default:
        break;
    }
    modbus_rtu_reset(inst); // 复位相关变量,准备接收新数据
    return;
}

// 接收错误数据帧的回调
void modbus_frame_error(struct modbus_rtu_inst_t *inst)
{
    if(inst->frame_handler == NULL)
    {
        return;
    }
    inst->frame_handler(inst, inst->data, inst->framelen);
    return;
}

// 串口接收回调
void serial_data_handler(char data)
{
    modbus_rtu_push(&mbhost, &data, 1); // 接收modbus rtu数据
}
3.3.2 录波器初始化和回调函数

主要完成录波器信息寄存器、录波通道对应的数据指针的初始化,故障录波通道一般固定,而手动录波通道可通过上位机配置。


void recorder_init(void)
{
    memset(&recorder_info, 0, sizeof(recorder_info_t));
    memset(&manual_recorder, 0, sizeof(struct record_manual_t));
    memset(&fault_recorder, 0, sizeof(struct record_fault_t));S

    memcpy(&recorder_info.serial, deviceserial, sizeof(deviceserial) > RECORDER_MAX_SERIAL_LEN?RECORDER_MAX_SERIAL_LEN:sizeof(deviceserial));
    recorder_info.sample_interval = 1000000/(RATE_GRID_FREQ*SAMPLE_PER_CYCLE);
    recorder_info.version[0] = VERSION_MAJOR;
    recorder_info.version[1] = VERSION_MINOR;
    recorder_info.version[2] = VERSION_REV;
    recorder_info.version[3] = VERSION_BUILD;
    recorder_info.postfault = RECORDER_POST_FAULT_COUNT;

    manual_recorder.common.start = 0;                       // 不启动录波
    manual_recorder.common.ready = 0;                       // 录波完成状态位清零
    manual_recorder.common.timestamp = 0;                   // 时间戳清零
    manual_recorder.common.datacount = RECORDER_BUFF_LEN;   // 每个手动录波通道的数据长度
    manual_recorder.common.validchannel = sizeof(manual_record_buff)/(sizeof(float)*RECORDER_BUFF_LEN);  // 实际起用的故障录波通道数
    for(int i = 0; i < RECORDER_MAX_MANUAL_CHANNEL_COUNT; i++)
    {
        manual_recorder.regaddr[i] = 3 + RO_ITEM_START + 2*i;   // 初始化手动录波数据地址
    }
    manual_recorder.buff = manual_record_buff;              // 手动录波数据的缓存
    manual_recorder.push_data_callback = record_manual;     // 填充录波数据的回调

    fault_recorder.common.start = 0;                        // 不启动录波
    fault_recorder.common.ready = 0;                        // 录波完成状态位清零
    fault_recorder.common.timestamp = 0;                    // 时间戳清零
    fault_recorder.common.datacount = RECORDER_BUFF_LEN;    // 每个故障录波通道的数据长度
    fault_recorder.common.validchannel = sizeof(fault_record_buff)/(sizeof(float)*RECORDER_BUFF_LEN);   // 实际起用的故障录波通道数
    for(int i = 0; i < RECORDER_MAX_FAULT_CHANNEL_COUNT; i++)
    {
        fault_recorder.regaddr[i] = 3 + RO_ITEM_START + 2*i;    // 初始化故障录波数据地址
    }
    fault_recorder.buff = fault_record_buff;                // 故障录波数据的缓存
    fault_recorder.push_data_callback = record_fault;       // 填充录波数据的回调
    return;
}
3.3.3. 录波器API调用和数据填充

在PWM或定时器中断中调用PESdk的录波API,PESdk内部做录波逻辑控制,在应用程序的回调函数中填充录波数据。

// 计算ADC数据
void calc_data(void)
{
    // ...
#ifdef TEST_RECORDER // 生成模拟数据
    static int index = 0;
    mydevice.data.inst.ugridline.ab = 100*sin(2*index*PI/SAMPLE_PER_CYCLE);
    mydevice.data.inst.ugridline.bc = 100*sin(2*index*PI/SAMPLE_PER_CYCLE - 2.0*PI/3.0) + 110;
    mydevice.data.inst.ugridline.ca = 100*sin(2*index*PI/SAMPLE_PER_CYCLE + 2.0*PI/3.0) + 220;
    index++;
    if(index >= SAMPLE_PER_CYCLE)
    {
        index = 0;
    }
#endif
    // ...
}

// 填充故障数据的回调
void record_fault(struct record_fault_t *recorder)
{
	struct modbus_table_item_t *pitem = mbtable_get_item_by_addr(recorder->regaddr[0]);
	memcpy(&fault_record_buff[0][recoder->index], pitem->pointer, pitem->format.bits.regcount << 1)
	pitem = mbtable_get_item_by_addr(recorder->regaddr[1]);
	memcpy(&fault_record_buff[1][recoder->index], pitem->pointer, pitem->format.bits.regcount << 1)
	pitem = mbtable_get_item_by_addr(recorder->regaddr[2]);
	memcpy(&fault_record_buff[2][recoder->index], pitem->pointer, pitem->format.bits.regcount << 1)
	// ...
    // 填充一个异常数据
    if(postfaultcounter == RECORDER_POST_FAULT_COUNT)
    {
        fault_record_buff[0][recorder->index] = 11;
        fault_record_buff[1][recorder->index] = 12;
        fault_record_buff[2][recorder->index] = 13;
    }
}

// 填充手动录波数据的回调
void record_manual(struct record_manual_t *recoder)
{
	struct modbus_table_item_t *pitem = mbtable_get_item_by_addr(recorder->regaddr[0]);
	memcpy(&manual_record_buff[0][recoder->index], pitem->pointer, pitem->format.bits.regcount << 1)
	pitem = mbtable_get_item_by_addr(recorder->regaddr[1]);
	memcpy(&manual_record_buff[1][recoder->index], pitem->pointer, pitem->format.bits.regcount << 1)
	pitem = mbtable_get_item_by_addr(recorder->regaddr[2]);
	memcpy(&manual_record_buff[2][recoder->index], pitem->pointer, pitem->format.bits.regcount << 1)
	// ...
}

// 读ADC数据
void read_adc(void)
{
    mydevice.data.raw.ugrid.ab = (int16)(AdcRegs.ADCRESULT0 >> 4);
    mydevice.data.raw.ugrid.bc = (int16)(AdcRegs.ADCRESULT1 >> 4);
    mydevice.data.raw.ugrid.ca = (int16)(AdcRegs.ADCRESULT2 >> 4);
    ...
}

// 有PWM中断中调用录波器
__interrupt void epwm_isr(void)
{
    // 启动ADC...
    // ...
    read_adc();    // 读ADC数据
    calc_data();   // 计算模拟量 
    // ...
#ifdef TEST_RECORDER
    // 调用PESdk的录波API,sysfault为故障标志位
    recorder_fault_record(&fault_recorder, recorder_info.postfault, sysfault);
    recorder_manual_record(&manual_recorder);
#endif
}

4 录波数据展示

在示例代码中模拟发生了一个故障,在故障数据填充回调函数中写入一个异常数据,DeMate读到数据后做数据对齐,将数据保存为Comtrade文件,向用户展示了正确的故障录波数据。
故障数据展示
后续继续升级PESdk,增加传输存储在flash中的故障录波文件列表和数据、固件升级等功能。

原文发表于个人公众号:E路臻品,欢迎关注

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

维修服务预约小程序的效果如何

生活服务中维修项目绝对是需求量很高的&#xff0c;如常见的保洁、管道疏通、数码维修、安装、便民服务等&#xff0c;可以说每天都有生意&#xff0c;而对相关维修店企业来说&#xff0c;如何获得更多生意很重要。 接下来让我们看看通过【雨科】平台制作维修服务预约小程序能…

XX棋牌架设指南

一、环境要求&#xff1a; 1.服务器要求&#xff1a;WINDOWS2008或更高版本。 2.数据库要求&#xff1a;MS SQL SERVER 2008 R2或更高版本。 3.服务器需要安装IIS。 二、游戏部署步骤&#xff1a; 1.解压文件至服务器数据盘&#xff0c;此处以D盘为例进行说明。 2. 目录说…

树结构及其算法-用链表来实现二叉树

目录 树结构及其算法-用链表来实现二叉树 C代码 树结构及其算法-用链表来实现二叉树 以链表实现二叉树就是使用链表来存储二叉树&#xff0c;也就是运用动态分配内存和指针的方式来建立二叉树。 使用链表来表示二叉树的好处是节点的增加与删除操作相当容易&#xff0c;缺点…

MATLAB野外观测站生态气象数据处理分析实践应用

1.基于MATLAB语言 2.以实践案例为主&#xff0c;提供所有代码 3.原理与操作结合 4.布置作业&#xff0c;答疑与拓展 示意图&#xff1a; 以野外观测站高频时序生态气象数据为例&#xff0c;基于MATLAB开展上机操作&#xff1a; 1.不同生态气象要素文件的数据读写与批处理实现 …

Ubuntu18.04系统镜像制作

安装使用systemback # 添加源 sudo add-apt-repository --remove ppa:nemh/systemback sudo add-apt-repository "deb http://ppa.launchpad.net/nemh/systemback/ubuntu xenial main"# 下载 sudo apt update sudo apt install systemback打开systemback,点击创建li…

加州大学提出 PromptAgent 帮忙我们高效的使用 ChatGPT

本心、输入输出、结果 文章目录 加州大学提出 PromptAgent 帮忙我们高效的使用 ChatGPT前言加州大学团队提出了可以自动优化 Prompt 的框架 —— PromptAgentPromptAgent 原理论文 实例介绍PromptAgent 框架设计PromptAgent 的策略优化过过程PromptAgent 的结果是否具备普适性弘…

[Docker]四.Docker部署nodejs项目,部署Mysql,部署Redis,部署Mongodb

一.部署nodejs项目,映射端口,挂载数据卷 可以到https://hub.docker.com/去搜索node镜像,然后下载,也可以直接通过docker pull node下载镜像,然后用这个node镜像启动容器node,这样系统就集成了node服务了,在这里挂载www/node目录到容器中,并指定端口映射,运行nodejs程序,安装npm…

【Tricks】PC端微信输入时,文本出现右对齐情况怎么恢复

应该是摁到某个快捷键&#xff0c;于是光标就变成如下图所示的样子&#xff1a; 如果再输入字符&#xff0c;则字符就会变成下图所示的样子&#xff08;对齐输入框右侧&#xff09;&#xff1a; 解决办法&#xff1a;ctrl J 解决办法&#xff1a;ctrl J 解决办法&#xff1…

transformers-AutoClass

https://huggingface.co/docs/transformers/main/en/autoclass_tutorialhttps://huggingface.co/docs/transformers/main/en/autoclass_tutorialAutoClass可以自动推断和加载给定checkpoint的正确架构。 对于文本&#xff0c;使用Tokenizer将文本转换为token序列&#xff0c;创…

MTSC2023|深圳大会,你关心的技术话题都在这里

MTSC中国互联网测试开发大会 (Make Tester Super Cool&#xff0c; 简称MTSC&#xff09; 是由国内知名的测试技术社区TesterHome发起的软件测试行业技术会议&#xff0c;大会以“软件质量保障体系和测试研发技术交流”为主要目的&#xff0c;旨在为行业搭建一个深入探讨和交流…

【Linux】Nginx安装使用负载均衡及动静分离(前后端项目部署),前端项目打包

一、Nginx导言 1、引言 Nginx 是一款高性能的 Web 服务器和反向代理服务器&#xff0c;也可以充当负载均衡器、HTTP 缓存和安全防护设备。它的特点是内存占用小、稳定性高、并发性强、易于扩展&#xff0c;因此在互联网领域得到了广泛的使用。 总结出以下三点: 负载均衡&#x…

作物模型--土壤数据制备过程

作物模型–土壤数据制备过程 首先打开FAO网站 下载下面这两个 Arcgis打开.bil文件 .mdb文件在access中转成.xls格式 Arcgis中对.bil文件定义投影

进口跨境商城源码的技术要点和优化策略

随着全球电子商务的快速发展&#xff0c;进口跨境商城已成为一种新型的商业模式。为了满足消费者日益增长的需求&#xff0c;提高商城的运营效率和用户体验&#xff0c;对进口跨境商城源码进行技术优化显得尤为重要。本文将探讨进口跨境商城源码的技术要点和优化策略。 一、背景…

Prometheus+Node_exporter+Grafana实现监控主机

PrometheusNode_exporterGrafana实现监控主机 如果没有安装相关的配置&#xff0c;首先要进行安装配置&#xff0c;环境是基于Linux&#xff0c;虚拟机的相关环境配置在文末给出&#xff0c;现在先讲解PrometheusNode_exporterGrafana的安装和使用。 一.Prometheus安装 虽然…

后端设计PG liberty的作用和增量式生成

Liberty&#xff08;俗称LIB和DB&#xff09;&#xff0c;是后端设计中重要的库逻辑描述文件&#xff0c;这里边包含了除过physical&#xff08;当然也有一点点涉及&#xff09;以外所有的信息&#xff0c;对整个后端设计实现有非常大的作用。借此机会&#xff0c;一起LIB做一个…

半导体精密划片机在行业中适合切割哪些材料?

在高端精密切割划片领域中&#xff0c;半导体材料需要根据其特性和用途进行选择。划片机适用于多种材料&#xff0c;包括硅片、石英、氧化铝、氧化铁、砷化镓、铌酸锂、蓝宝石和玻璃等。这些材料在半导体行业被广泛使用&#xff0c;包括在集成电路、半导体芯片、QFN、发光二极管…

【R统计】各式各样的插补法解决数据缺失的问题!

&#x1f482; 个人信息&#xff1a;酷在前行&#x1f44d; 版权: 博文由【酷在前行】原创、需要转载请联系博主&#x1f440; 如果博文对您有帮助&#xff0c;欢迎点赞、关注、收藏 订阅专栏&#x1f516; 本文收录于【R统计】&#xff0c;该专栏主要介绍R语言实现统计分析的…

创新方案|2023如何用5种新形式重塑疫后实体门店体验

在电商盛行的当下&#xff0c;线上购物已成为新零售的重要组成部分&#xff0c;实体零售业正处于两难境地。一方面&#xff0c;实体零售是绝对有必要的&#xff1a;美国约 85% 的销售额来自实体商店。 另一方面&#xff0c;尽管增长放缓&#xff0c;但电商收入占销售总额的比例…

【蓝桥杯 第十届省赛Java B组】真题训练(A - H)H待更新

目录 A、组队 - 看图一眼出答案 B、不同子串 - 字符串模拟 set去重 C、数列求值 - 模拟取余 D、数的分解 - 三重暴力 E、迷宫 - bfs 判断路径 F、特别数的和 - 弱智模拟 G、外卖店优先级 - map 暴力&#xff08;90%通过率&#xff09; H、人物相关性分析 - A、组队 -…

Ant Design Vue Table 表格内容高度自适应+固定表头踩坑

前言 对于非专业前端开发者来使用 Ant Design UI 组件来开发企业级后台管理系统来说是非常不错的选择&#xff0c;但这并不意味着我们能够用好这个框架&#xff0c;因为 UI 交互上和有许多细节上的问题对于非专业前端来说并不容易解决&#xff0c;最近在使用 Table 组件时就遇…