EPICS -- 使用asynPortDriver类编写示一个示例程序

news2024/12/26 22:35:40

本示例展示了如何使用asynPortDriver类编写一个EPICS端口驱动程序的示例。 这个驱动程序参数库中一个有5个参数,分别支持5个EPICS记录。

如下是具体步骤:

1) 用makeBaseApp.pl脚本建立这个IOC应用程序的框架:

[blctrl@main-machine exer42]$ makeBaseApp.pl -t ioc testAsynPortDriver
[blctrl@main-machine exer42]$ makeBaseApp.pl -i -t ioc testAsynPortDriver
Using target architecture linux-x86_64 (only one available)
The following applications are available:
    testAsynPortDriver
What application should the IOC(s) boot?
The default uses the IOC's name, even if not listed above.
Application name?
[blctrl@main-machine exer42]$ ls
configure  iocBoot  Makefile  testAsynPortDriverApp

2)修改configure/RELEASE文件,增加一个SUPPORT和ASYN环境变量,它们分别指向support和asyn模块所在的路径:

SUPPORT=/usr/local/EPICS/synApps/support
ASYN=$(SUPPORT)/asyn

3) 进入到testAsynPortDriverApp/src目录,编写程序头文件以及源文件:

头文件:

#include "asynPortDriver.h"

/*
 * 这些是drvInfo字符串,它们用于标识这些参数。包括标准asyn设备支持的asyn客户端使用它们。
 * */

#define P_RunString             "PROCESS_RUN"           /*asynInt32,    r/w*/
#define P_IntString             "PROCESS_INT"           /*asynInt32,    r/w*/
#define P_FloatString           "PROCESS_FLOAT"         /*asynFloat64,  r/w*/
#define P_IntRandString         "PROCESS_INTRAND"       /*asynInt32,    r/o*/
#define P_FloatRandString       "PROCESS_FLOATRAND"     /*asynFloat64m  r/o*/

/*  
 * 这个类演示了如何使用asynPortDriver基类来大大简化编写一个aysn端口驱动程序的任务
*/
class testAsynPortDriver : public asynPortDriver {//需要继承asynPortDriver
public:
        testAsynPortDriver(const char * portName);
        /* 我们重写从asynPortDriver继承的方法 */
        virtual asynStatus writeInt32(asynUser * pasynUser, epicsInt32 value);
        virtual asynStatus readInt32 (asynUser * pasynUser, epicsInt32 *value);
        virtual asynStatus writeFloat64(asynUser * pasynUser,  epicsFloat64 value);
        virtual asynStatus readFloat64 (asynUser * pasynUser, epicsFloat64 * value);

        /* 此方法是这个类的新方法 */
        void simTask(void);


protected:
        /* 用于pasynUser->reason的值, 并且是对参数库的索引 */
        int P_Run;
        int P_Int;
        int P_FloatRand;
        int P_Float;
        int P_IntRand;

private:
        epicsEventId eventId_;  //用于线程同步的事件

        int getIntRand();         //这个方法,返回一个0-100的随机数
        float getFloatRand();     //这个方法,返回一个0.01-1的随机数
};

C++源文件:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>
#include <time.h>

#include <epicsTypes.h>
#include <epicsTime.h>
#include <epicsThread.h>
#include <epicsString.h>
#include <epicsTimer.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <iocsh.h>

#include "testAsynPortDriver.h"
#include <epicsExport.h>

static const char * driverName = "testAsynPortDriver";
void simTask(void * drvPvt);

/* testAsynPort类的构造函数 */
/* 调用asynPortDriver基类的构造器 */
/* param[in] : 要被创建的asyn驱动程序的名称 */
testAsynPortDriver::testAsynPortDriver(const char *portName)
        :asynPortDriver(portName,
                        1, /* maxAddr */
                        asynInt32Mask | asynFloat64Mask | asynDrvUserMask, /* Interface mask */
                        asynInt32Mask | asynFloat64Mask, /* Interrupt mask */
                        0, /* asynFlags */
                        1, /* AutoConnect  */
                        0, /* Default priority  */
                        0) /* Default stack size  */
{
        asynStatus status;
        int i;
        const char * functionName = "testAsynPortDriver";

        // 创建一个空时间
        eventId_ = epicsEventCreate(epicsEventEmpty);

        //根据参数名称,参数类型,在参数库中创建这个参数,并且返回其在参数库中的索引
        createParam(P_RunString,        asynParamInt32,  &P_Run);
        createParam(P_IntString,        asynParamInt32,  &P_Int);
        createParam(P_FloatString,      asynParamFloat64,&P_Float);
        createParam(P_IntRandString,    asynParamInt32,  &P_IntRand);
        createParam(P_FloatRandString,  asynParamFloat64,&P_FloatRand);

        // 此是调试代码,打印在参数库中的索引
        printf("P_Run:%d,P_Int:%d,P_Float:%d,P_IntRand:%d,P_FloatRand:%d\n", P_Run, P_Int, P_Float, P_IntRand, P_FloatRand);

        // 用索引将参数库中对应的变量初始化。
        setIntegerParam(P_Run, 0);
        setIntegerParam(P_Int, 0);
        setIntegerParam(P_IntRand, 0);
        setDoubleParam(P_Float, 0.0);
        setDoubleParam(P_FloatRand, 0.0);

        // 初始化随机数种子
        srand(time(0));
        /* 创建在后台计算这些随机数的线程 */
        /* Create the thread that computes the random numbers in background */
        status = (asynStatus)(epicsThreadCreate("testAsynPortDriverTask",
                                epicsThreadPriorityMedium,
                                epicsThreadGetStackSize(epicsThreadStackMedium),
                                (EPICSTHREADFUNC)::simTask,
                                this) == NULL);

        // 如果线程创建失败,则打印产生错误的命令,以及驱动名,函数名
        if (status){
                printf("%s:%s: epicsThreadCreate failed\n", driverName, functionName);
                return;
        }

}


// 创建的新线程执行这个函数,此参数是指向testAsynPortDriver类实例的指针
void simTask(void * drvPvt)
{
        testAsynPortDriver * pPvt = (testAsynPortDriver *)drvPvt;

        pPvt->simTask();
}


/* 
 * 以单独线程运行仿真任务。当P_Run参数被设为1时,计算随机数。
 * */
void testAsynPortDriver::simTask(void)
{
        epicsInt32 run, int1, intrand;
        epicsFloat64  float1, floatrand;

        lock();
        
        while(1){

                getIntegerParam(P_Run, &run);
                // 在等待启动命令或者等待更新时,释放锁
                unlock();
                if (run)
                        {//run为1,线程运行,计算随机数,并且设置到参数库中
                                epicsInt32 inum = (epicsInt32)getIntRand();
                                setIntegerParam(P_IntRand, inum);
                                epicsFloat64 fnum = (epicsFloat64)getFloatRand();
                                setDoubleParam(P_FloatRand, fnum);
                                // 带超时时间地进行等待
                                epicsEventWaitWithTimeout(eventId_, 1.0);
                        }
                else //run为0,系统阻塞这个线程运行,直到等待的事件出现
                        (void)epicsEventWait(eventId_);

                lock();
            
                /* 在我们等待时,run可能发生变化,再次读取run */
                getIntegerParam(P_Run, &run);
                /*  如果run为0, 则从返回循环开始处执行 */
                if (!run)
                        continue;
                // 根据索引获取参数值,存入指定位置
                getIntegerParam(P_Int,          &int1);
                getIntegerParam(P_IntRand,      &intrand);
                getDoubleParam(P_Float,         &float1);
                getDoubleParam(P_FloatRand,     &floatrand);
                // 初始为调试代码,查看这些参数值
                printf("int1=%d, intrand=%d, float1=%f,floatrand=%f\n", int1, intrand,float1, floatrand);
                // 更新时间戳
                updateTimeStamp();
                // 对上层进行回调
                callParamCallbacks();
        }
}

asynStatus testAsynPortDriver::writeInt32(asynUser * pasynUser, epicsInt32 value)
{
        int function = pasynUser->reason;
        asynStatus status = asynSuccess;
        const char * paramName;
        const char * functionName = "writeInt32";

        // 调试代码:这个重写的方法被调用了。
        printf("call writeInt32\n");
        /* 在参数库中设置这个参数,此处reason就是参数索引 */
        status = (asynStatus) setIntegerParam(function, value);

      
        /* 根据索引获取参数字符串名称,在调试中可用 */
        getParamName(function, &paramName);

        if (function == P_Run){//如果参数索引对应P_Run,并且传入值为1,表示启动线程
                if (value) epicsEventSignal(eventId_);
        }
        else if (function == P_Int) //如果参数索引对应P_Int,则测试传入的value范围,并且将其写入参数库
        {       if (value > 100)
                        value = 100;
                else if (value < 0)
                        value = 0;
                setIntegerParam(P_Int, value);

        }
        else if (function == P_IntRand)
        {
        }

        // 通知客户端,参数库中参数发生变化了
        status = (asynStatus)callParamCallbacks();
        
        if (status)
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                  "%s:%s: status=%d, function=%d, name=%s, value=%d",
                  driverName, functionName, status, function, paramName, value);
        else
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
              "%s:%s: function=%d, name=%s, value=%d\n",
              driverName, functionName, function, paramName, value);
    return status;
}

asynStatus testAsynPortDriver::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
{
        int function = pasynUser->reason;
        asynStatus status = asynSuccess;
        epicsInt32 run;
        const char * paramName;
        const char * functionName = "writeFloat64";

        printf("call writeFloat64\n");
 
        status = (asynStatus) setDoubleParam(function, value);
       
        getParamName(function, &paramName);

        if (function == P_Float)
        {
                if (value < -1000.0)
                        value = -1000.0;
                else if (value > 1000.0)
                        value = 1000.0;
                setDoubleParam(P_Float, value);

        }
        else if (function == P_FloatRand)
        {
        }
        了
        getIntegerParam(P_Run, &run);
        if (run) epicsEventSignal(eventId_);

        // 通知客户端,参数库中参数发生变化
        status = (asynStatus) callParamCallbacks();

        if (status)
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                  "%s:%s: status=%d, function=%d, name=%s, value=%f",
                        driverName, functionName, status, function, paramName, value);
        else
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
                "%s:%s: function=%d, name=%s, value=%f\n",
                driverName, functionName, function, paramName, value);
        return status;
}


asynStatus testAsynPortDriver::readFloat64(asynUser *pasynUser, epicsFloat64 * value)
{
        int function = pasynUser->reason;
        epicsFloat64 ftemp;
        asynStatus status = asynSuccess;
        epicsTimeStamp timeStamp;
        const char * functionName = "readFloat64";

        printf("call readFloat64\n");

        getTimeStamp(&timeStamp);
        pasynUser->timestamp = timeStamp;
        getDoubleParam(function, &ftemp);

        * value = ftemp;
        printf("value = %f\n", ftemp);


        if (status)
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                          "%s:%s: status=%d, function=%d",
                        driverName, functionName, status, function);
        else
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
                "%s:%s: function=%d\n",
                driverName, functionName, function);
        return status;
}

asynStatus testAsynPortDriver::readInt32(asynUser * pasynUser, epicsInt32 * value)
{
        int function = pasynUser->reason;
        epicsInt32 itemp;
        asynStatus status = asynSuccess;
        epicsTimeStamp timeStamp;
        const char * functionName = "readInt32";


        printf("call readInt32\n");
        getTimeStamp(&timeStamp);
        pasynUser->timestamp = timeStamp;
        getIntegerParam(function, &itemp);

        * value = itemp;
        printf("value = %d\n", itemp);

        if (status)
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
                          "%s:%s: status=%d, function=%d",
                        driverName, functionName, status, function);
        else
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
                        "%s:%s: function=%d\n",
                        driverName, functionName, function);
        return status;
}

int testAsynPortDriver::getIntRand()
{
        int num;

        num = rand() % 100 + 1;
        printf("call getIntRand() = %d\n", num);

        return num;
}

float testAsynPortDriver::getFloatRand()
{
        float num;

        num = this->getIntRand();

        return num / 100.0;
}


// 向EPICS注册端口驱动程序
extern "C" {

int testAsynPortDriverConfigure(const char *portName)
{
    new testAsynPortDriver(portName);
    return(asynSuccess);
}


/* EPICS iocsh shell commands */

static const iocshArg initArg0 = { "portName",iocshArgString};
static const iocshArg * const initArgs[] = {&initArg0,};
static const iocshFuncDef initFuncDef = {"testAsynPortDriverConfigure",1,initArgs};
static void initCallFunc(const iocshArgBuf *args)
{
    testAsynPortDriverConfigure(args[0].sval);
}

void testAsynPortDriverRegister(void)
{
    iocshRegister(&initFuncDef,initCallFunc);
}

epicsExportRegistrar(testAsynPortDriverRegister);
}

添加以下一个testAsynPortDriverSupport.dbd支持文件:

registrar("testAsynPortDriverRegister")

编辑相同目录下的Makefile文件:

TOP=../..

include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
LIBRARY_IOC += testAsynPortDriverSupport

# Compile and add code to the support library
LIB_SRCS += testAsynPortDriver.cpp
LIB_LIBS += asyn
LIB_LIBS += $(EPICS_BASE_IOC_LIBS)
#

#=============================
# Build the IOC application

PROD_IOC = testAsynPortDriver
# testAsynPortDriver.dbd will be created and installed
DBD += testAsynPortDriver.dbd

# testAsynPortDriver.dbd will be made up from these files:
testAsynPortDriver_DBD += base.dbd
testAsynPortDriver_DBD += asyn.dbd
testAsynPortDriver_DBD += testAsynPortDriverSupport.dbd


# Include dbd files from all support applications:
#testAsynPortDriver_DBD += xxx.dbd

# Add all the support libraries needed by this IOC
testAsynPortDriver_LIBS += asyn
testAsynPortDriver_LIBS += testAsynPortDriverSupport

# testAsynPortDriver_registerRecordDeviceDriver.cpp derives from testAsynPortDriver.dbd
testAsynPortDriver_SRCS += testAsynPortDriver_registerRecordDeviceDriver.cpp

# Build the main IOC entry point on workstation OSs.
testAsynPortDriver_SRCS_DEFAULT += testAsynPortDriverMain.cpp
testAsynPortDriver_SRCS_vxWorks += -nil-

# Add support from base/src/vxWorks if needed
#testAsynPortDriver_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary

# Finally link to the EPICS Base libraries
testAsynPortDriver_LIBS += $(EPICS_BASE_IOC_LIBS)

#===========================

include $(TOP)/configure/RULES

4) 进入到 testAsynPortDriverApp/Db/目录,编辑一个名为testAsynPortDriver.db的数据库文件,内容如下:

###################################################################
#  这两个记录控制启动/停止,连接程序参数库中索引为P_RUN的变量         #
###################################################################
record(bo, "$(P)$(R)Run")
{
    field(PINI,  "1")
    field(DTYP, "asynInt32")
    field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_RUN")
    field(ZNAM, "Stop")
    field(ONAM, "Run")
}

record(bi, "$(P)$(R)Run_RBV")
{
    field(PINI, "1")
    field(DTYP, "asynInt32")
    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_RUN")
    field(ZNAM, "Done")
    field(ZSV,  "NO_ALARM")
    field(ONAM, "Running")
    field(OSV,  "MINOR")
    field(SCAN, "I/O Intr")
}


###################################################################
#  这两个记录控制一个浮点数,连接程序参数库中索引为P_Float的参数      #
###################################################################
record(ao, "$(P)$(R)Float")
{
   field(PINI, "1")
   field(DTYP, "asynFloat64")
   field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_FLOAT")
   field(PREC, "3")
}

record(ai, "$(P)$(R)Float_RBV")
{
   field(PINI, "1")
   field(DTYP, "asynFloat64")
   field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_FLOAT")
   field(PREC, "3")
   field(SCAN, "I/O Intr")
}


###################################################################
#  这个记录读取一个浮点数(0-1),连接程序参数库中索引为P_FloatRand的参数#
###################################################################
record(ai, "$(P)$(R)FloatRand_RBV")
{
   field(DTYP, "asynFloat64")
   field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_FLOATRAND")
   field(PREC, "2")
   field(SCAN, "I/O Intr")
}

###################################################################
#  这些记录控制一个整数,连接程序参数库中索引为P_Int的参数           #
###################################################################
record(longin, "$(P)$(R)Int_RBV")
{
    field(PINI, "1")
    field(DTYP, "asynInt32")
    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_INT")
    field(SCAN, "I/O Intr")
}

record(longout, "$(P)$(R)Int")
{
    field(PINI, "1")
    field(DTYP, "asynInt32")
    field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_INT")
}



###################################################################
#  这个记录读取一个随机整数,连接程序参数库中索引为P_IntRand的参数     #
###################################################################
record(longin, "$(P)$(R)IntRand_RBV")
{
    field(PINI, "1")
    field(DTYP, "asynInt32")
    field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROCESS_INTRAND")
    field(SCAN, "I/O Intr")
}

设置相同目录中Makefile文件,向文件中添加以下一行:

DB += testAsynPortDriver.db

5) 返回到这个IOC应用程序的顶层目录,执行make编译。

6) 进入到iocBoot/ioctestAsynPortDriver目录下,编译启动脚本st.cmd,内容如下:

#!../../bin/linux-x86_64/testAsynPortDriver

#- You may have to change testAsynPortDriver to something else
#- everywhere it appears in this file

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/testAsynPortDriver.dbd"
testAsynPortDriver_registerRecordDeviceDriver pdbbase

## Load record instances
testAsynPortDriverConfigure("testAPD")

dbLoadRecords("db/testAsynPortDriver.db","P=BLCTRL:,R=Test:,PORT=testAPD,ADDR=0,TIMEOUT=1")


cd "${TOP}/iocBoot/${IOC}"
iocInit

7)启动这个IOC,用dbl查看,IOC中加载的记录:

[blctrl@main-machine ioctestAsynPortDriver]$ ../../bin/linux-x86_64/testAsynPortDriver st.cmd
#!../../bin/linux-x86_64/testAsynPortDriver
< envPaths
epicsEnvSet("IOC","ioctestAsynPortDriver")
epicsEnvSet("TOP","/home/blctrl/exer/exer42")
epicsEnvSet("SUPPORT","/usr/local/EPICS/synApps/support")
epicsEnvSet("ASYN","/usr/local/EPICS/synApps/support/asyn")
epicsEnvSet("EPICS_BASE","/usr/local/EPICS/base")
cd "/home/blctrl/exer/exer42"
## Register all support components
dbLoadDatabase "dbd/testAsynPortDriver.dbd"
testAsynPortDriver_registerRecordDeviceDriver pdbbase
## Load record instances
testAsynPortDriverConfigure("testAPD")
P_Run:0,P_Int:1,P_Float:2,P_IntRand:3,P_FloatRand:4
dbLoadRecords("db/testAsynPortDriver.db","P=BLCTRL:,R=Test:,PORT=testAPD,ADDR=0,TIMEOUT=1")
cd "/home/blctrl/exer/exer42/iocBoot/ioctestAsynPortDriver"
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.3.1
## EPICS Base built Sep  8 2022
############################################################################
call readInt32
value = 0
call readInt32
value = 0
call readFloat64
value = 0.000000
call writeInt32
call readInt32
value = 0
call writeInt32
call readFloat64
value = 0.000000
call readInt32
value = 0
call readInt32
value = 0
call writeFloat64
iocRun: All initialization complete
## Start any sequence programs
#seq sncxxx,"user=blctrl"
epics> dbl
BLCTRL:Test:Int
BLCTRL:Test:Run_RBV
BLCTRL:Test:Run
BLCTRL:Test:Float_RBV
BLCTRL:Test:FloatRand_RBV
BLCTRL:Test:Int_RBV
BLCTRL:Test:IntRand_RBV
BLCTRL:Test:Float
epics>

8) 用CS Stdio设计一个客户端来查看这个IOC程序中的PV值,并且对这些PV值进行修改,测试这个程序的运行效果:

点击Run后,程序运行,IntRand和FloatRand对应的两个框中数值每秒钟变化一次,点击Stop后,程序运行停止,IntRand和FloatRand对应的两个框中数值不会变化。

 

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

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

相关文章

IDEA中如何实现git的cherry-pick可视化操作?

目录 问题现象&#xff1a; 问题分析&#xff1a; 解决方法&#xff1a; 拓展&#xff1a;如何回退提交记录&#xff1f; 问题现象&#xff1a; 今天在学习了git的cherry-pick功能&#xff0c;于是引出了一个问题&#xff1a; IDEA中如何实现git的cherry-pick可视化操作&am…

【Docker学习教程系列】7-如何将本地的Docker镜像发布到阿里云

在上一篇中&#xff0c;我们使用docker commit 命令&#xff0c;创建了一个带有vim的Ubuntu镜像。那么怎么将这个镜像分享出去呢&#xff1f;本文就来讲解如何将本地的docker镜像发布到阿里云上。 本文主要内容&#xff1a; 1&#xff1a;本地镜像发布到阿里云流程 2&#xf…

Linux网络原理与编程(4)——第十四节 传输层协议

目录 前置知识 再谈端口号 几个函数 netstat telnet UDP报文 UDP协议端格式 UDP首部&#xff1a; UDP的特点 UDP的缓冲区 TCP报文详解 Tcp报头详解 传输层是在应用层的下面一层&#xff0c;我们在讲解传输层协议之前&#xff0c;先来说一说一些前置知识即命令函数等…

看完就会flink基础API

文章目录一、执行环境&#xff08;Execution Environment&#xff09;1、创建执行环境2、执行模式(Execution Mode)3、触发程序执行二、源算子&#xff08;Source&#xff09;1、数据源类准备2、从集合中读取数据3、从文件中读取数据4、从Socket中读取数据5、从Kafka中读取数据…

ISCSLP 2022 Program|希尔贝壳邀您参加第十三届中文口语语言处理国际会议

第十三届中文口语语言处理国际会议将于2022年12月11-14日&#xff08;本周日~下周三&#xff09;正式开启&#xff0c;本次会议中的部分Session将通过语音之家视频号进行线上直播&#xff0c;欢迎大家参加&#xff01; 官网&#xff1a;www.iscslp2022.org 大会简介 中文口语…

ABAP学习笔记之——第十二章:SALV

一、概要 在Net Weaver 2004 平台上集合了利用函数和 GRID 的功能发布的 SALV 包程序 (SALV也称为 New ALV)。SALV 可以像利用函数生成 ALV 的不用创建屏幕就可以调用的全屏式ALV&#xff0c;还可以利用控制器在屏幕的控制器中显示 ALV。利用GRID 的ALV 虽然不能注册成 Batch …

速卖通知识产权规则介绍,如何才能规避侵权的问题?

最近有商家咨询到我&#xff0c;关于速卖通对商品知识产权是怎么评判的&#xff0c;今天就来给大家科普一下平台关于知识产权的规则介绍 速卖通平台严禁用户未经授权发布、销售涉嫌侵犯第三方知识产权的商品或发布涉嫌侵犯第三方知识产权的信息。 若卖家发布涉嫌侵犯第三方知…

从股票市场选择配对的股票:距离计算方法

我们来看看如何定义距离的计算方法。 回想一下&#xff0c;在共同趋势模型中&#xff0c;协整的必要条件是从共同趋势得到的新息序列必须完全相关。APT中的共同因子回报就理解成是从共同趋势得到的新息序列&#xff0c;因此&#xff0c;新息序列之间的相关系数就是共同因子回报…

网关性能大PK,Spring Cloud Gateway让人大失所望

现在的架构基本都是使用微服务的&#xff0c;而网关作为微服务的统一门户在架构模式中用得越来越多&#xff0c;API网关是所有客户端的单一入口点。 API网关模式是微服务体系结构的一个很好的起点&#xff0c;因为它能够将特定的请求路由到我们从整体上分离的不同服务。事实上…

嘿嘿嘿,10个我经常逛的“小网站”,不骗人

反思一下&#xff0c;为什么你会点进来~ 咳咳&#xff0c;步入正题。 工欲善其事必先利其器&#xff0c;你们的收藏夹里收藏了多少“小网站”&#xff1f;今天和大家分享10个我压箱底的效率工具/平台&#xff0c;现在用不上不要紧&#xff0c;赶紧收藏最关键&#xff01; 1.G…

【产品设计】APP常见的6种图片浏览模式

六种是指比较常见的图片浏览模式&#xff0c;是在这四种的基础上加上手势来实现另一种读图方式&#xff0c;这里不绝对说就这么几种&#xff0c;那么就谈谈个人对每种图片浏览模式说说自己在实际使用和工作中的一些理解&#xff0c;以及这些模式在实际设计中&#xff0c;哪一种…

智能聊天机器人––ChatGPT初体验

最近几天&#xff0c;由OpenAI公司发布的ChatGPT聊天机器人火了&#xff0c;小杨也怀着对新鲜事物的好奇&#xff0c;亲自体验了一下这个火爆全网&#xff0c;让人沉迷其中无法自拔的ChatGPT聊天机器人&#xff0c;经过体验&#xff0c;我只想用一个字来表达我的感受&#xff0…

【LeetCode每日一题】——142.环形链表 II

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【题目进阶】九【时间频度】十【代码实现】十一【提交结果】一【题目类别】 链表 二【题目难度】 中等 三【题目编号】 142.环形链表 II 四【题目描述】 …

Java百度地图全套教程(地图找房、轻骑小程序、金运物流等)

课程简介&#xff1a; 本课程基于百度地图技术&#xff0c;将企业项目中地图相关常见应用场景的落地实战&#xff0c;包括有地图找房、轻骑小程序、金运物流等。同时还讲了基于Netty实现高性能的web服务&#xff0c;来处理高并发的问题。 学完本课程能够收获&#xff1a;百度…

支持本地挂载的网盘文件列表工具AList

什么是 Alist&#xff1f; AList 是一个支持多存储的文件列表程序&#xff0c;使用 Gin 框架和 Solidjs 库。可以将常见的 18 种网盘整合在一起&#xff0c;并支持 WebDAV 客户端访问。 之前老苏写过一篇 Alist&#xff0c; 但此 Alist 非彼 Alist&#xff0c;之前的 A 应该是 …

React基础知识(React基本使用、JSX语法、React模块化与组件化)(一)

系列文章目录 文章目录系列文章目录一、React简介1.1 React的特点1.2 React高效的原因二、React基本使用2.1 引入react相关js库2.2 创建虚拟DOM的两种方法2.3 虚拟DOM和真实DOM三、JSX基本使用3.1 jsx使用四、React模块化与组件化4.1 函数式组件4.2 类式组件一、React简介 1.英…

Kafka消费者组消费进度监控

针对Kafka消费者&#xff0c;重要的就是监控消费进度或者是消费的滞后程度&#xff0c;有个专业名词 消费者 Lag 或 Consumer Lag。 滞后程度&#xff08;Consumer Lag&#xff09;是指消费者当前落后生产者的程度。比如Kafka 生产者向某主题成功生产了 100 万条消息&#xff0…

一个.NetCore前后端分离、模块化、插件式的通用框架

今天给大家推荐一个基于.NET 6实现的快速开发平台。采用模块化插件式开发&#xff0c;前后端分离&#xff0c;开箱即用。 项目简介 这是一个开箱即用的快速开发平台&#xff0c;前后端分离架构&#xff0c;支持插件式开发&#xff0c;支持工作流、可视化表单功能。系统基础功…

Qt 快速读写Excel指南

Qt Windows 下快速读写Excel指南 很多人搜如何读写excel都会看到用QAxObject来进行操作&#xff0c;很多人试了之后都会发现一个问题&#xff0c;就是慢&#xff0c;非常缓慢&#xff01;因此很多人得出结论是QAxObject读写excel方法不可取&#xff0c;效率低。 后来我曾试过用…

网络攻击损失不容小觑

据研究数据显示&#xff0c;2022年数据泄露给企业造成的平均损失为435万美元&#xff1b;如果是勒索软件攻击&#xff0c;损失将增加到454万美元。当然这只是估计&#xff0c;在某些国家或地区平均损失更高&#xff0c;比如在美国&#xff0c;损失接近1000万美元。 此外&#x…