IEC61499开源项目FORTE部分源码分析

一、IEC 61499简介

IEC 61499 作为工业自动化领域分布式控制系统级建模语言的标准,其第一(体系结构)、二(软件工具要求)、四(兼容文件的规则)部分的第一版于 2005 年正式发布,并在 2012 年发布第一部分的 2.0 版本,主要解决了旧版中诸如功能块执行控制表语法语义存在的歧义等一系列问题。

 图1 分布式应用的功能块连接

设备是多条资源的容器,并提供这些资源与通讯网络、传感器和执行器之间的接口。这些接口提供的服务由支持分布式应用的专用资源中的SIFB完成。通讯网络把各分散设备集成为一个完整的系统。这样,分布在不同物理设备中的功能块形成了一个真正的分布式应用。

分布式指的是上图的某个功能块可以部署到某一个硬件上,多个硬件设备共同实现一个工业流程,红线代表事件流,蓝线代表数据流,各个功能块协同工作,但对于每个功能块到底是在哪里并不关心,61499协议并不对底层的具体实现方式进行定义。

1. 4diac FORTE

Eclipse Foundation 4diac project 是一个支持IEC-61499协议的开源项目,

IDEFORTE、功能块库等部分组成。

 图2. 4diac project

2. 4diac IDE

IDE用于编辑PLC应用逻辑,下发PLC程序到硬件设备或导出PLC为.fboot文件,供PLC运行时使用。

下图是IEC-61499的DEMO,主要功能是一个实现一个opc ua服务器,对外提供10个数据点,10个数据由随机数生成器产生,随机数生成器每50ms更新一次。 demo内容下载链接在文章最后。

图3 IDE编辑IEC61499 demo

3. FORTE编译

下载FORTE源码并编译:

unzip forte_2.0.1.zip
cd forte_2.0.1
mkdir build
cd build
cmake -DFORTE_ARCHITECTURE=Posix -DFORTE_COM_ETH=ON \
-DFORTE_COM_FBDK=ON -DFORTE_COM_LOCAL=ON \
-DFORTE_TESTS=OFF -DFORTE_MODULE_CONVERT=ON \
-DFORTE_MODULE_IEC61131=ON -DFORTE_MODULE_UTILS=ON  ..make –j

运行FORTE:

./forte -c 0.0.0.0:61500 -f server.fboot

-c设置PLC程序监听的地址。

-f指定启动文件,即从IDE中导出的fboot格式PLC程序。

4. server.fboot文件内容

以类似于XML文件的格式,定义PLC程序中用到的功能块和全部的连接信息。

图4 FB_RANDOM功能块到.fboot的转换

Action定义CREATE、WRITE、START、DELETE等操作。

fastWrite;<Request ID="5" Action="CREATE"><FB Name="FB_RANDOM" Type="FB_RANDOM" /></Request>

创建名为FB_RANDOM的功能块,ID为5,Type为FB_RANDOM。

fastWrite;<Request ID="6" Action="WRITE"><Connection Source="0" Destination="FB_RANDOM.SEED" /></Request>

为一个连接写入值,Source是0,Destination是FB_RANDOM.SEED。

fastWrite;<Request ID="12" Action="CREATE"><Connection Source="E_CYCLE.EO" Destination="FB_RANDOM.REQ" /></Request>

创建从E_CYCLE.EO到FB_RANDOM.REQ的连接。

fastWrite;<Request ID="19" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_1" /></Request>

创建从FB_RANDOM.VAL到PUBLISH_10.SD_1的连接。

完整的server.fboot的内容,列在本文最后。

二、PLC功能块到汇编代码的过程

区别于iec61131,比如OpenPLC的实现方式,OpenPLC是将PLC的逻辑变成中间语言的.st文件,再生成.cpp进行编译后生成 elf的可执行程序再进行执行的。

FORTE是将PLC程序导出成类似于XML格式的.fboot文件,在设备上运行的时候,由FORTE进行动态解析建立PLC逻辑。

下面分析.fboot文件在FORTE中的解析和处理流程。此处我们以FB_RANDOM功能块为例进行分析。

1.FB_RANDOM功能块

FB_RANDOM功能块的作用是生成介于0-1之间的float随机数。

 

图2.3 FB_RANDOM的对外接口

FB_RANDOM功能块的对外接口如下所示:

按61499的规范,功能块的左边是输入,右边是输出。

  1. INIT用于接收事件进行初始化。
  2. INITO用于对外输出初始化完毕事件,在INIT结束后发出。
  3. REQ用于接收外部请求事件,请求一次生成一个随机数。
  4. SEED即外部给的随机数种子。
  5. CNF是Execution Confirmation执行确认,REQ请求事件处理完毕后输出执行完毕事件。
  6. VAL是功能块的输出,输出生成的随机数。.fboot文件到具体逻辑的转换

2.FORTE_FB_RANDOM 的功能实现

IDE中的每一个功能块都与对应的cpp实现相关联。

如果要在IDE中自定义新的功能块,必须导出成对应的.cpp和.h文件,并加入到FORTE的源代码的src\modules目录中,重新编译FORTE才能启用此功能块。目前FORTE的这种实现方式添加新的功能块还不是特别方便。

自定义功能块功能支持ST语法或C语法,编写的程序会导出到.cpp文件中。

IEC 61499功能块按功能分为基本功能块、复合功能块、服务接口功能块(通讯功能块和管理功能块)和适配器(插件和插座)。

src\core\funcbloc.h中定义了CFunctionBlock,CFunctionBlock是所有功能块的基类。

继承此类的有4个类:

basicfb.h定义基本功能块类CBasicFB。

cfb.h定义复合功能块类CCompositeFB。

esfb.h定义服务接口功能块类CEventSourceFB。

adapter.h定义接口类CAdapter。

FB_RANDOM功能块对应的cpp类名称为:FORTE_FB_RANDOM,继承自CBasicFB。

class FORTE_FB_RANDOM: public CBasicFB{

3.FB_RANDOM.h

FB_RANDOM类继承了 CBasicFB,第一行DECLARE_FIRMWARE_FB(FORTE_FB_RANDOM)用于定义

宏展开后如下:

定义了一个static 静态函数createFB,用于生成此类的实例。

class FORTE_FB_RANDOM: public CBasicFB{DECLARE_FIRMWARE_FB(FORTE_FB_RANDOM)private:static const CStringDictionary::TStringId scm_anDataInputNames[];static const CStringDictionary::TStringId scm_anDataInputTypeIds[];CIEC_UINT &SEED() {return *static_cast<CIEC_UINT*>(getDI(0));};static const CStringDictionary::TStringId scm_anDataOutputNames[];static const CStringDictionary::TStringId scm_anDataOutputTypeIds[];CIEC_REAL &VAL() {return *static_cast<CIEC_REAL*>(getDO(0));};static const TEventID scm_nEventINITID = 0;static const TEventID scm_nEventREQID = 1;static const TForteInt16 scm_anEIWithIndexes[];static const TDataIOID scm_anEIWith[];static const CStringDictionary::TStringId scm_anEventInputNames[];static const TEventID scm_nEventINITOID = 0;static const TEventID scm_nEventCNFID = 1;static const TForteInt16 scm_anEOWithIndexes[];static const TDataIOID scm_anEOWith[];static const CStringDictionary::TStringId scm_anEventOutputNames[];static const SFBInterfaceSpec scm_stFBInterfaceSpec;FORTE_BASIC_FB_DATA_ARRAY(2, 1, 1, 0, 0);virtual void setInitialValues();void alg_INIT(void);void alg_REQ(void);static const TForteInt16 scm_nStateSTART = 0;static const TForteInt16 scm_nStateREQ = 1;static const TForteInt16 scm_nStateState = 2;void enterStateSTART(void);void enterStateREQ(void);void enterStateState(void);virtual void executeEvent(int pa_nEIID);public:FORTE_FB_RANDOM(CStringDictionary::TStringId pa_nInstanceNameId, CResource *pa_poSrcRes) : CBasicFB(pa_poSrcRes, &scm_stFBInterfaceSpec, pa_nInstanceNameId,0, m_anFBConnData, m_anFBVarsData){};virtual ~FORTE_FB_RANDOM(){};};

4.FB_RANDOM.cpp

 在FB_RANDOM.cpp中是这样实现的:


#include "FB_RANDOM.h"
#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
#include "FB_RANDOM_gen.cpp"
#endif
#include <time.h>
#include <stdlib.h>DEFINE_FIRMWARE_FB(FORTE_FB_RANDOM, g_nStringIdFB_RANDOM)const CStringDictionary::TStringId FORTE_FB_RANDOM::scm_anDataInputNames[] = {g_nStringIdSEED};const CStringDictionary::TStringId FORTE_FB_RANDOM::scm_anDataInputTypeIds[] = {g_nStringIdUINT};const CStringDictionary::TStringId FORTE_FB_RANDOM::scm_anDataOutputNames[] = {g_nStringIdVAL};const CStringDictionary::TStringId FORTE_FB_RANDOM::scm_anDataOutputTypeIds[] = {g_nStringIdREAL};const TForteInt16 FORTE_FB_RANDOM::scm_anEIWithIndexes[] = {0, -1};
const TDataIOID FORTE_FB_RANDOM::scm_anEIWith[] = {0, 255};
const CStringDictionary::TStringId FORTE_FB_RANDOM::scm_anEventInputNames[] = {g_nStringIdINIT, g_nStringIdREQ};const TDataIOID FORTE_FB_RANDOM::scm_anEOWith[] = {0, 255};
const TForteInt16 FORTE_FB_RANDOM::scm_anEOWithIndexes[] = {-1, 0, -1};
const CStringDictionary::TStringId FORTE_FB_RANDOM::scm_anEventOutputNames[] = {g_nStringIdINITO, g_nStringIdCNF};const SFBInterfaceSpec FORTE_FB_RANDOM::scm_stFBInterfaceSpec = {2,  scm_anEventInputNames,  scm_anEIWith,  scm_anEIWithIndexes,2,  scm_anEventOutputNames,  scm_anEOWith, scm_anEOWithIndexes,  1,  scm_anDataInputNames, scm_anDataInputTypeIds,1,  scm_anDataOutputNames, scm_anDataOutputTypeIds,0, 0
};void FORTE_FB_RANDOM::setInitialValues(){SEED().fromString("0");
}void FORTE_FB_RANDOM::alg_INIT(void){
// WARNING - Don't forget to add #include <time.h>if (SEED() == 0) {srand((unsigned int) time(NULL) );} else {srand( SEED() );}
}void FORTE_FB_RANDOM::alg_REQ(void){VAL() = static_cast<TForteFloat>(rand())/static_cast<TForteFloat>(RAND_MAX);
}void FORTE_FB_RANDOM::enterStateSTART(void){m_nECCState = scm_nStateSTART;
}void FORTE_FB_RANDOM::enterStateREQ(void){m_nECCState = scm_nStateREQ;alg_REQ();sendOutputEvent( scm_nEventCNFID);
}void FORTE_FB_RANDOM::enterStateState(void){m_nECCState = scm_nStateState;alg_INIT();sendOutputEvent( scm_nEventINITOID);
}void FORTE_FB_RANDOM::executeEvent(int pa_nEIID){bool bTransitionCleared;do{bTransitionCleared = true;switch(m_nECCState){case scm_nStateSTART:if(scm_nEventREQID == pa_nEIID)enterStateREQ();elseif(scm_nEventINITID == pa_nEIID)enterStateState();elsebTransitionCleared  = false; //no transition clearedbreak;case scm_nStateREQ:if(1)enterStateSTART();elsebTransitionCleared  = false; //no transition clearedbreak;case scm_nStateState:if(1)enterStateSTART();elsebTransitionCleared  = false; //no transition clearedbreak;default:DEVLOG_ERROR("The state is not in the valid range! The state value is: %d. The max value can be: 2.", m_nECCState.operator TForteUInt16 ());m_nECCState = 0; //0 is always the initial statebreak;}pa_nEIID = cg_nInvalidEventID;  // we have to clear the event after the first check in order to ensure correct behavior}while(bTransitionCleared);
}

三、FB_RANDOM 功能块的动态加载

1. .fboot文件解析流程

.fboot文件中定义了PLC程序的功能块及相互的连接。

stdfblib\ita\DEV_MGR.cpp实现对.fboot文件的处理。通过解析.fboot文件建立各个功能块及输入和输出端口之间的连接。

DEV_MGR::parseAndExecuteMGMCommand(char *paDest, char *paCommand)

对.fboot进行文本解析,解析后的需要进行的处理保存在mCommand变量中,再执行executeMGMCommand函数进行相关资源的创建。

forte::core::SManagementCMD mCommand;

executeMGMCommand(mCommand);

在core\resource.cpp中实现资源创建。

可以看到FORTE支持动态创建,即用LUA语言进行动态创建,但暂时在.fboot文件中还没有看到lua的脚本,并且lua脚本可能也是类似的工作机制,并不能实现自定义功能块逻辑。

EMGMResponse CResource::executeMGMCommand(forte::core::SManagementCMD &paCommand){

最终执行到FORTE_FB_RANDOM的构造函数。

FB_RANDOM功能块初始化的调用堆栈如下所示:

#0  FORTE_FB_RANDOM::FORTE_FB_RANDOM (this=0x180, pa_nInstanceNameId=0, pa_poSrcRes=0x555555695119 <operator new(unsigned long)+28>) at /home/plc/forte_2.0.1/src/modules/utils/FB_RANDOM.h:66
#1  0x0000555555722445 in FORTE_FB_RANDOM::createFB (pa_nInstanceNameId=666, pa_poSrcRes=0x7ffff0004b60) at /home/plc/forte_2.0.1/src/modules/utils/FB_RANDOM.h:21
#2  0x00005555556b82cf in CTypeLib::CFBTypeEntry::createFBInstance (this=0x5555557b7020 <FORTE_FB_RANDOM::csm_oFirmwareFBEntry_FORTE_FB_RANDOM>, pa_nInstanceNameId=666, pa_poSrcRes=0x7ffff0004b60)at /home/plc/forte_2.0.1/src/core/./datatypes/../typelib.h:155
#3  0x00005555556b7e86 in CTypeLib::createFB (pa_nInstanceNameId=666, pa_nFBTypeId=666, pa_poRes=0x7ffff0004b60) at /home/plc/forte_2.0.1/src/core/typelib.cpp:118
#4  0x00005555556b33c0 in forte::core::CFBContainer::createFB (this=0x7ffff0004bd8, paNameListIt=..., paTypeName=666, paRes=0x7ffff0004b60) at /home/plc/forte_2.0.1/src/core/fbcontainer.cpp:68
#5  0x00005555556b476e in CResource::executeMGMCommand (this=0x7ffff0004b60, paCommand=...) at /home/plc/forte_2.0.1/src/core/resource.cpp:73
#6  0x00005555556b1418 in CDevice::executeMGMCommand (this=0x5555557cd870, paCommand=...) at /home/plc/forte_2.0.1/src/core/device.cpp:30
#7  0x000055555572a323 in DEV_MGR::parseAndExecuteMGMCommand (this=0x5555557cecc0, paDest=0x7ffff0005814 "fastWrite", paCommand=0x7ffff000581e "<Request ID=\"5") at /home/plc/forte_2.0.1/src/stdfblib/ita/DEV_MGR.cpp:637
#8  0x000055555572a6a3 in DEV_MGR::executeCommand (this=0x5555557cecc0, paDest=0x7ffff0005814 "fastWrite", paCommand=0x7ffff000581e "<Request ID=\"5") at /home/plc/forte_2.0.1/src/stdfblib/ita/DEV_MGR.cpp:696
#9  0x000055555572bad3 in ForteBootFileLoader::loadBootFile (this=0x7ffff724bde0) at /home/plc/forte_2.0.1/src/stdfblib/ita/ForteBootFileLoader.cpp:90
#10 0x0000555555728771 in DEV_MGR::executeEvent (this=0x5555557cecc0, paEIID=0) at /home/plc/forte_2.0.1/src/stdfblib/ita/DEV_MGR.cpp:68
#11 0x00005555556b2881 in CFunctionBlock::receiveInputEvent (this=0x5555557cecc0, paEIID=0, paExecEnv=0x5555557cdf60) at /home/plc/forte_2.0.1/src/core/funcbloc.cpp:314
#12 0x00005555556b8510 in CEventChainExecutionThread::mainRun (this=0x5555557cdf60) at /home/plc/forte_2.0.1/src/core/ecet.cpp:49
#13 0x00005555556b8454 in CEventChainExecutionThread::run (this=0x5555557cdf60) at /home/plc/forte_2.0.1/src/core/ecet.cpp:34
#14 0x0000555555695aa7 in forte::arch::CThreadBase<unsigned long, 0ul, forte::arch::EmptyThreadDeletePolicy>::runThread (paThread=0x5555557cdf60) at /home/plc/forte_2.0.1/src/arch/posix/../threadbase.tpp:69
#15 0x0000555555695324 in CPosixThread::threadFunction (paArguments=0x5555557cdf60) at /home/plc/forte_2.0.1/src/arch/posix/forte_thread.cpp:68
#16 0x00007ffff7f9a609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#17 0x00007ffff7b90293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

2.FB_RANDOM类是如何注册的?

从调用堆栈可以看到,.fboot文件解析后,FORTE根据.fboot文件的内容进行了动态创建功能块,但大家是不是有一个疑问,就是从Cpp语法角度,如何根据字符串创建一个类对象?

就像如下的代码,但下面的代码与FORTE的运行情况还不太一样,FORTE程序并不引用功能块的.h文件,main函数无法拿到FuncA的定义,那功能块又是如何动态创建的呢?

就是说,程序在运行时如何知道有这个类FuncA存在?

Class Base{
};Class FuncA : public Base {FuncA(){printf("FuncA");}
};Class FuncB : public Base {FuncB(){printf("FuncB");}
};int main(){Base* ptr = nullptr;string str="FuncA";if(str== "FuncA")ptr =  new FuncA();else if(str== "FuncB")ptr =  new FuncB();return 0;
}

在FB_RANDOM.cpp中有如下宏定义

DEFINE_FIRMWARE_FB(FORTE_FB_RANDOM, g_nStringIdFB_RANDOM)

 宏展开后是这样的:

定义了一个const CTypeLib::CFBTypeEntry 类型的static变量 , static定义在FB_RANDOM.h中。

FORTE_FB_RANDOM::csm_oFirmwareFBEntry_FORTE_FB_RANDOM(( xxx), xxx,xxx);

CTypeLib::CFBTypeEntry 这个类在初始化的时候,在CFBTypeEntry 构造函数中执行 CTypeLib::addFBType函数,将自己的相关信息(包括id,接口相关函数)加入到静态变量中。

//! The base class for all function block types entries in the type lib.class CFBTypeEntry : public CSpecTypeEntry{public:CFBTypeEntry(CStringDictionary::TStringId pa_nTypeNameId, TFunctionBlockCreateFunc pa_pfuncCreateFB, const SFBInterfaceSpec* paSocketInterfaceSpec);virtual ~CFBTypeEntry(void);virtual CFunctionBlock *createFBInstance(CStringDictionary::TStringId pa_nInstanceNameId, CResource *pa_poSrcRes){return m_pfuncFBCreationFunc( pa_nInstanceNameId, pa_poSrcRes);}private:TFunctionBlockCreateFunc m_pfuncFBCreationFunc;};

CTypeLib::CFBTypeEntry::CFBTypeEntry(
CStringDictionary::TStringId pa_nTypeNameId,TFunctionBlockCreateFunc pa_pfuncCreateFB,const SFBInterfaceSpec* paSocketInterfaceSpec):CSpecTypeEntry(pa_nTypeNameId, paSocketInterfaceSpec),m_pfuncFBCreationFunc(pa_pfuncCreateFB)
{CTypeLib::addFBType(this); //这一行
}void CTypeLib::addFBType(CFBTypeEntry *pa_poFBTypeEntry) 
{if (0 == findType(pa_poFBTypeEntry->getTypeNameId(), m_poFBLibStart)) 
{if(m_poFBLibStart == 0) {m_poFBLibStart = pa_poFBTypeEntry;} else {m_poFBLibEnd->m_poNext = pa_poFBTypeEntry;//pa_poFBTypeEntry加入静态变量m_poFBLibEnd中}m_poFBLibEnd = pa_poFBTypeEntry;}
}CTypeLib::CFBTypeEntry *CTypeLib::m_poFBLibStart = 0;
CTypeLib::CFBTypeEntry *CTypeLib::m_poFBLibEnd = 0;//.h头文件中的定义
class CTypeLib
{static CFBTypeEntry *m_poFBLibStart, *m_poFBLibEnd;//!< pointer to the begin of the firmware fb library list//!<pointer to the end of the firmware fb library list//静态变量的定义
}

在创建此类型的时候,首先执行findType()函数,进行查找,找到指定的TypeNameId,如果找不到,就报错,无法运行此程序。

void CTypeLib::addFBType(CFBTypeEntry *pa_poFBTypeEntry) {if (0 == findType(pa_poFBTypeEntry->getTypeNameId(), m_poFBLibStart)) {if(m_poFBLibStart == 0) {m_poFBLibStart = pa_poFBTypeEntry;} else {m_poFBLibEnd->m_poNext = pa_poFBTypeEntry;}m_poFBLibEnd = pa_poFBTypeEntry;}
}

c程序运行时,并不是从main开始运行,在main()运行前,会有一系列的函数进行一些初始化工作,static静态变量都是在这一时期初始化的。具体可参见下面的链接。

因此,在main函数运行前,会初始化此处的CTypeLib::CFBTypeEntry 类型的变量,将FB_RANDOM类的相关信息添加到m_poFBLibStart 开始的链表中。即可实现在解析.fboot文件时,根据ID查找对应的类。并通过调用对应的createFB()生成对应的对象。

linux编程之main()函数启动过程_gary_ygl的专栏-CSDN博客_linux启动main函数

附件

server.fboot文件内容:

;<Request ID="2" Action="CREATE"><FB Name="fastWrite" Type="EMB_RES" /></Request>
fastWrite;<Request ID="3" Action="CREATE"><FB Name="E_CYCLE" Type="E_CYCLE" /></Request>
fastWrite;<Request ID="4" Action="WRITE"><Connection Source="T#50ms" Destination="E_CYCLE.DT" /></Request>
fastWrite;<Request ID="5" Action="CREATE"><FB Name="FB_RANDOM" Type="FB_RANDOM" /></Request>
fastWrite;<Request ID="6" Action="WRITE"><Connection Source="0" Destination="FB_RANDOM.SEED" /></Request>
fastWrite;<Request ID="7" Action="CREATE"><FB Name="PUBLISH_10" Type="PUBLISH_10" /></Request>
fastWrite;<Request ID="8" Action="WRITE"><Connection Source="1" Destination="PUBLISH_10.QI" /></Request>
fastWrite;<Request ID="9" Action="WRITE"><Connection Source="opc_ua[WRITE;/Objects/folder1/var1;/Objects/folder1/var2;/Objects/folder1/var3;/Objects/folder1/var4;/Objects/folder1/var5;/Objects/folder1/var6;/Objects/folder1/var7;/Objects/folder1/var8;/Objects/folder1/var9;/Objects/folder1/var10]" Destination="PUBLISH_10.ID" /></Request>
fastWrite;<Request ID="10" Action="CREATE"><FB Name="E_DELAY_2" Type="E_DELAY" /></Request>
fastWrite;<Request ID="11" Action="WRITE"><Connection Source="T#2s" Destination="E_DELAY_2.DT" /></Request>
fastWrite;<Request ID="12" Action="CREATE"><Connection Source="E_CYCLE.EO" Destination="FB_RANDOM.REQ" /></Request>
fastWrite;<Request ID="13" Action="CREATE"><Connection Source="START.WARM" Destination="FB_RANDOM.INIT" /></Request>
fastWrite;<Request ID="14" Action="CREATE"><Connection Source="START.COLD" Destination="FB_RANDOM.INIT" /></Request>
fastWrite;<Request ID="15" Action="CREATE"><Connection Source="FB_RANDOM.INITO" Destination="PUBLISH_10.INIT" /></Request>
fastWrite;<Request ID="16" Action="CREATE"><Connection Source="FB_RANDOM.CNF" Destination="PUBLISH_10.REQ" /></Request>
fastWrite;<Request ID="17" Action="CREATE"><Connection Source="PUBLISH_10.INITO" Destination="E_DELAY_2.START" /></Request>
fastWrite;<Request ID="18" Action="CREATE"><Connection Source="E_DELAY_2.EO" Destination="E_CYCLE.START" /></Request>
fastWrite;<Request ID="19" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_1" /></Request>
fastWrite;<Request ID="20" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_2" /></Request>
fastWrite;<Request ID="21" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_3" /></Request>
fastWrite;<Request ID="22" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_4" /></Request>
fastWrite;<Request ID="23" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_5" /></Request>
fastWrite;<Request ID="24" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_6" /></Request>
fastWrite;<Request ID="25" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_7" /></Request>
fastWrite;<Request ID="26" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_8" /></Request>
fastWrite;<Request ID="27" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_9" /></Request>
fastWrite;<Request ID="28" Action="CREATE"><Connection Source="FB_RANDOM.VAL" Destination="PUBLISH_10.SD_10" /></Request>
fastWrite;<Request ID="28" Action="START"/>

所用demo下载

https://download.csdn.net/download/v6543210/80644938

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023搜狐科技峰会结束 白春礼刘韵洁武向平等院士解读科技新格局

雷递网 乐天 5月18日 正值“517世界电信日”&#xff0c;搜狐于北京如期举办“2023搜狐科技峰会”。 走入第五个年头的峰会继续在内容深度和广度上实现新突破&#xff0c;从宇宙文明、天文卫星、人类永生&#xff0c;到核聚变、6G通信、脑机接口&#xff0c;再到通用人工智能时…

安卓版ChatGPT要来了!

千呼万唤始出来&#xff01; OpenAI并没有给出发布的具体日期&#xff0c;官宣中只是提供了一个“预订”&#xff08;预注册&#xff09;入口。 但安卓党们在得知这事后&#xff0c;纷纷搓起了激动的小手&#xff1a; 终于可以换回去用安卓手机了&#xff01; 不过这次OpenAI也…

关于嵌入式开发

写在前面 嵌入式是一个具有深度和广度的概念&#xff0c;设计的知识面非常广阔&#xff0c;如数字、电子、编程语言和通讯网络等。嵌入式开发就是指在嵌入式操作系统下进行开发。对于嵌入式系统的定义&#xff0c;目前一种普遍被认同的定义是&#xff1a;以应用为中心&#xff…

万字长文说清大模型在自动驾驶领域的应用

交流群 | 进“传感器群/滑板底盘群/汽车基础软件群/域控制器群”请扫描文末二维码&#xff0c;添加九章小助手&#xff0c;务必备注交流群名称 真实姓名 公司 职位&#xff08;不备注无法通过好友验证&#xff09; 作者 | 张萌宇 随着ChatGPT的火爆&#xff0c;大模型受到的…

Android开发成功转行车载开发之后,并没有想象中的那么简单,我承认,是我小瞧了它

前言 近几年的Android开发岗位就业环境想必大家也都有所耳闻&#xff0c;许多Android开发工程师都找不到自己满意的工作&#xff0c;于是纷纷另谋出路… 刚好这几年随着Android车载开发的兴起&#xff0c;令人眼睛一亮的是车载开发工程师的工资普遍偏高&#xff0c;这高昂的工…

2023年,Android程序员就业方向是怎样的?

一转眼&#xff0c;2023年一半就要过去了&#xff0c;各位Android程序员的工作还顺利吗&#xff1f; 今年以来各大厂纷纷爆出裁员的新闻&#xff0c;Chat GPT等人工智能工具的爆火也让今年IT行业的就业状况雪上加霜。 不少人觉得近几年的打工人普遍又卷又焦虑&#xff0c;岗位…

如何定义一款好的自动驾驶芯片?

导读 自动驾驶领域&#xff0c;传统处理器的竞争规则正发生急速的变化。 一般来说&#xff0c;人工智能的发展主要取决于两大基本要素&#xff1a;算力和算法。自动驾驶作为目前技术投入较大、商业落地较早、市场前景广阔的人工智能应用&#xff0c;其主控芯片的算力也被业内拿…

星火认知大模型发布,科大讯飞入场科技巨头AI大战?

自从ChatGPT横空出世&#xff0c;一个更美好的世界开始向我们招手。为了推开新时代的大门&#xff0c;几乎所有人工智能厂商都投入了最大的热情逐浪AIGC。 5月6日&#xff0c;科大讯飞召开了“讯飞星火认知大模型”成果发布会。发布会现场&#xff0c;科大讯飞董事长刘庆峰展示…

浪潮之巅 OpenAI有可能是历史上第一个10万亿美元的公司

淘金时代很像 如果你那个时候去加州淘金&#xff0c;一大堆人会死掉&#xff0c;但是卖勺子的人、卖铲子的人永远可以赚钱。所谓的shove and pick business。 大模型是平台型机会。按照我们几天的判断&#xff0c;以模型为先的平台&#xff0c;将比以信息为先的平台体量更大。…

ChatGPT告诉你智能制造

ChatGPT自上线以来&#xff0c;几乎得到了外界的一致好评&#xff0c;上线两个月&#xff0c;获得1亿月活跃用户&#xff0c;成为增长最快的面向消费者的应用。 面对ChatGPT拟人一般的问答能力&#xff0c;很多人认为它代表着AlphaGo之后&#xff0c;人工智能应用的第二次浪潮…

这一次AI应该是真正的已经到来

渐渐感觉这一次AI的变革能真正的突破迷雾&#xff0c;迎来真正的人工智能时代的到来。所以写篇博文学习一下。经过半年的发酵与发展&#xff0c;不得不说AI已经成为了不可逆转的趋势。之所以说这一次AI应该是真正的已经到来&#xff0c;是因为人工智能的发展其实已经经历了几十…

chatgpt赋能python:Python在电气行业中的应用——从数据分析到自动化控制

Python在电气行业中的应用——从数据分析到自动化控制 介绍 Python语言作为一种高级编程语言&#xff0c;越来越受到电气行业的关注。随着互联网、物联网以及大数据时代的到来&#xff0c;电气行业需要将传统的工业控制与现代化的数据分析、智能决策等技术相结合&#xff0c;…

学会提示-AI时代职场必修课

作者&#xff1a;京东 何雨航 “ 上个时代要学会提问&#xff0c;这个时代要学会提示。” 引言 当你在写提数代码时&#xff0c;小张已经完成了数据分析&#xff1b;当你正在整理材料时&#xff0c;小王却在和对象逛环球影城&#xff1b;述职时&#xff0c;你发现小郑的汇报有…

来 Azure 学习 OpenAI 四 - 用 Embedding 赋能 GPT

大家好&#xff0c;我是学生大使 Jambo。在我们前一篇文章中&#xff0c;我们介绍了 OpenAI 模型的调用。今天&#xff0c;我将为大家介绍 Embedding 的使用。 嵌入是什么 嵌入&#xff08;Embedding &#xff09;是一种将高维数据映射到低维空间的方法。嵌入可以将高维数据可…

北信源VRVEIS网管软件测试

本文出自 “李晨光原创技术博客” 博客&#xff0c;谢绝转载&#xff01;

北信源顺利获得信息技术服务标准(ITSS)符合性二级证书

近期&#xff0c;北信源系统集成有限公司顺利通过了中国电子工业标准化技术协会信息技术服务分会的专家评审&#xff0c;成功取得了“信息技术服务标准&#xff08;ITSS&#xff09;符合性二级证书”&#xff0c;具备了为客户提供更专业、标准化、可信赖的IT服务能力&#xff0…

北信源携手天津麒麟共建国产信息安全

【51CTO.com原创稿件】操作系统安全是计算机网络系统安全的基础。在网络环境中&#xff0c;网络系统的安全性依赖于网络中各主机系统的安全性&#xff0c;而主机系统的安全性正是由其操作系统的安全性所决定的&#xff0c;没有安全的操作系统的支持&#xff0c;网络安全也毫无根…

华为鸿蒙生态伙伴峰会,华为鸿蒙生态加速!北信源率先参与其中

华为鸿蒙OS connect伙伴峰会来了! 北信源与金山办公战略合作签约仪式现场 (右一:北信源董事长林皓先生 右二:金山办公CEO章庆元先生) 5月12日,北信源与金山办公战略合作签约仪式在北京国家会议中心成功举行。在主题演讲环节,东莞华为CTO蒋兴发表了以《携手共筑安全领域可信鸿蒙…

成功粉碎北信源监控程序vrvedp_m.exe ,vrvrf_c64.exe,svchost.exe,vrvrf_c.exe

公司安装了北信源的监控软件&#xff0c;用360粉碎了大部分北信源的程序文件&#xff0c;但是有几个程序进程始终开机启动&#xff0c;进程无法杀死&#xff0c;一度成了我的一块心病&#xff01; 后来不知咋的灵光一闪&#xff0c;彻底将其粉碎的毛都不剩&#xff0c;现将成功…

北信源华为鸿蒙概念,A股华为鸿蒙概念板块的股票有哪些

华为作为最近热点的股票&#xff0c;近日又启动鸿蒙高校人才计划&#xff0c;相关的概念股票都炒作了一波&#xff0c;华为鸿蒙概念股票成为热点之一&#xff0c;A股华为鸿蒙概念股票有哪些&#xff0c;目前还有多少的上升空间&#xff0c;我们来了解一下。 A股华为鸿蒙概念板块…