• EPICS -- 测试asynDriver和设备支持的示例1-- 连接测试


    这个应用程序可以用于测试连接管理。它用drvAsynIPPort连接一个设备并且在一个后台线程中周期地写入此设备。取决于是否连接了设备,将打印出错消息。可以通过循环上电或者断开网线连接或断开这个设备来测试这种行为。

    以下是建立并且测试这个程序的完整过程:

    1) 建立IOC应用程序框架

    1. [blctrl@main-machine exer]$ mkdir exer41
    2. [blctrl@main-machine exer]$ cd exer41
    3. [blctrl@main-machine exer41]$ makeBaseApp.pl -t ioc testAsynDriver
    4. [blctrl@main-machine exer41]$ makeBaseApp.pl -i -t ioc testAsynDriver
    5. Using target architecture linux-x86_64 (only one available)
    6. The following applications are available:
    7. testAsynDriver
    8. What application should the IOC(s) boot?
    9. The default uses the IOC's name, even if not listed above.
    10. Application name?
    11. [blctrl@main-machine exer41]$ ls
    12. configure iocBoot Makefile testAsynDriverApp

    2) 编辑configure/RELEASE目录,添加以下内容:

    1. SUPPORT=/usr/local/EPICS/synApps/support
    2. ASYN=$(SUPPORT)/asyn
    3. IPAC=$(SUPPORT)/ipac

    3) 进入testAsynDriverApp/src目录中,创建一个名testConnect.cpp为的c++源文件:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. class testConnect : public asynPortDriver {
    11. public:
    12. // 构造函数
    13. testConnect(const char * portName, const char * IPPortName, const char * outputString);
    14. void pollerTask(void);
    15. private:
    16. asynUser * pasynUserIPPort_;
    17. const char * outputString_;
    18. };
    19. static const char * driverName = "testConnect";
    20. // 定义程序轮询时间
    21. #define POLLER_PERIOD 1
    22. // 定义响应的最大长度
    23. #define MAX_RESPONSE_LEN 256
    24. //定义静态函数,只能被从这个文件中调用
    25. static void pollerTask(void * drvPvt);
    26. testConnect::testConnect(const char * portName, const char * IPPortName, const char * outputString)
    27. : asynPortDriver(portName,
    28. 1, /*maxAddr*/
    29. asynOctetMask, /*接口掩码*/
    30. 0, /*中断掩码*/
    31. ASYN_CANBLOCK, /*asynFlag.这个驱动程序阻塞,并且它不是多设备*/
    32. 1,/*自动连接*/
    33. 0,/*默认优先级y*/
    34. 0)/*默认栈大小*/
    35. {
    36. asynStatus status;
    37. const char * functionName = "testConnect";
    38. // 开辟空间,存储传入字符串
    39. outputString_ = epicsStrDup(outputString);
    40. /*
    41. * asynStatus (*connect)(const char *port, int addr,
    42. * asynUser **ppasynUser, const char *drvInfo);
    43. * 传入端口名称,传出一个asynUser指针
    44. * */
    45. status = pasynOctetSyncIO->connect(IPPortName, 0, &pasynUserIPPort_,NULL);
    46. if (status) //连接失败
    47. {
    48. printf("%s:%s: pasynOctetSyncIO->connect failure, status=%d\n", driverName, functionName, status);
    49. return;
    50. }
    51. /* 创建在后台运行的线程 */
    52. status = (asynStatus)(epicsThreadCreate("testConnectTask",
    53. epicsThreadPriorityMedium,
    54. epicsThreadGetStackSize(epicsThreadStackMedium),
    55. (EPICSTHREADFUNC)::pollerTask,
    56. this) == NULL);
    57. if (status){
    58. printf("%s:%s: epicsThreadCreate failed, status=%d\n", driverName, functionName, status);
    59. return;
    60. }
    61. printf("Start new Thread testConnectTask successfully!\n\n");
    62. }
    63. static void pollerTask(void * drvPvt)
    64. {
    65. testConnect * pPvt = (testConnect *)drvPvt;
    66. pPvt->pollerTask();
    67. }
    68. /* 轮询任务作为一个单独线程运行 */
    69. void testConnect::pollerTask(void)
    70. {
    71. asynStatus status;
    72. char response[MAX_RESPONSE_LEN] = "";
    73. size_t numWrite, numRead;
    74. int isConnected;
    75. int eomReason;
    76. static const char * functionName = "pollerTask";
    77. /* 一直循环 */
    78. while(1){
    79. // 父类的公有成员函数
    80. lock();
    81. /* 根据端口或设备是否连接,isConnect被设置0或1 */
    82. status = pasynManager->isConnected(pasynUserIPPort_, &isConnected);
    83. if (status){
    84. //父类的保护成员变量
    85. asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
    86. "%s:%s: error calling pasyManager->isConnected, status=%d, error=%s\n",
    87. driverName, functionName, status, pasynUserIPPort_->errorMessage);
    88. }
    89. asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER,
    90. "%s:%s: isConnected = %d\n", driverName, functionName, isConnected);
    91. /*
    92. * asynStatus (*writeRead)(asynUser *pasynUser, const char *write_buffer, size_t write_buffer_len,
    93. * char *read_buffer, size_t read_buffer_len, double timeout,size_t *nbytesOut, size_t *nbytesIn, int *eomReason);
    94. * */
    95. status = pasynOctetSyncIO->writeRead(pasynUserIPPort_, outputString_, strlen(outputString_),
    96. response, sizeof(response),
    97. 1.0, &numWrite, &numRead, &eomReason);
    98. if (status){
    99. asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
    100. "%s:%s: error calling pasynOctetSyncIO->writeRead,status=%d, error=%s\n",
    101. driverName, functionName, status, pasynUserIPPort_->errorMessage);
    102. }
    103. else{
    104. printf("From Server: %s\n", response);
    105. asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER,
    106. "%s:%s: numWrite=%ld, wrote:%s, numRead=%ld, response=%s\n",
    107. driverName, functionName, (long)numWrite,outputString_,(long)numRead, response);
    108. }
    109. unlock();
    110. epicsThreadSleep(POLLER_PERIOD);
    111. }
    112. }
    113. extern "C" {
    114. int testConnectConfigure(const char * portName, const char * IPPortName, const char * outputString)
    115. {
    116. new testConnect(portName, IPPortName, outputString);
    117. return(asynSuccess);
    118. }
    119. /* EPICS iocsh shell command */
    120. static const iocshArg initArg0 = {"portName", iocshArgString};
    121. static const iocshArg initArg1 = {"IPPortName", iocshArgString};
    122. static const iocshArg initArg2 = {"output string", iocshArgString};
    123. static const iocshArg * const initArgs[] = {&initArg0, &initArg1, &initArg2};
    124. static const iocshFuncDef initFuncDef = {"testConnectConfigure",3, initArgs};
    125. static void initCallFunc(const iocshArgBuf * args)
    126. {
    127. testConnectConfigure(args[0].sval,args[1].sval, args[2].sval);
    128. }
    129. void testConnectRegister(void)
    130. {
    131. iocshRegister(&initFuncDef, initCallFunc);
    132. }
    133. epicsExportRegistrar(testConnectRegister);
    134. }

    4) 在与第(3)步相同路径下,创建一个名为testConnectSupport.dbd的文件,在此文件中添加以下一行:

    registrar("testConnectRegister")

    5) 编译 在第(3)步相同路径下的Makefile文件,内容如下:

    1. TOP=../..
    2. include $(TOP)/configure/CONFIG
    3. #----------------------------------------
    4. # ADD MACRO DEFINITIONS AFTER THIS LINE
    5. #=============================
    6. LIBRARY_IOC += testAsynDriverSupport
    7. # Compile and add code to the support library
    8. LIB_SRCS += testConnect.cpp
    9. LIB_LIBS += asyn
    10. LIB_LIBS += $(EPICS_BASE_IOC_LIBS)
    11. #
    12. #=============================
    13. # Build the IOC application
    14. PROD_IOC = testAsynDriver
    15. # testAsynDriver.dbd will be created and installed
    16. DBD += testAsynDriver.dbd
    17. # testAsynDriver.dbd will be made up from these files:
    18. testAsynDriver_DBD += base.dbd
    19. testAsynDriver_DBD += testConnectSupport.dbd
    20. # Include dbd files from all support applications:
    21. testAsynDriver_DBD += asyn.dbd
    22. testAsynDriver_DBD += drvAsynIPPort.dbd
    23. testAsynDriver_DBD += testConnectSupport.dbd
    24. # Add all the support libraries needed by this IOC
    25. testAsynDriver_LIBS += asyn
    26. testAsynDriver_LIBS += testAsynDriverSupport
    27. # testAsynDriver_registerRecordDeviceDriver.cpp derives from testAsynDriver.dbd
    28. testAsynDriver_SRCS += testAsynDriver_registerRecordDeviceDriver.cpp
    29. # Build the main IOC entry point on workstation OSs.
    30. testAsynDriver_SRCS_DEFAULT += testAsynDriverMain.cpp
    31. testAsynDriver_SRCS_vxWorks += -nil-
    32. # Add support from base/src/vxWorks if needed
    33. #testAsynDriver_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
    34. # Finally link to the EPICS Base libraries
    35. testAsynDriver_LIBS += $(EPICS_BASE_IOC_LIBS)
    36. #===========================
    37. include $(TOP)/configure/RULES
    38. #----------------------------------------
    39. # ADD RULES AFTER THIS LINE

    6) 切换倒这个IOC的顶层目录中执行make进行编译。

    7)切换到iocBoot/ioctestAsynDriver/目录下,编辑启动文件st.cmd,内容如下:

    1. #!../../bin/linux-x86_64/testAsynDriver
    2. #- You may have to change testAsynDriver to something else
    3. #- everywhere it appears in this file
    4. < envPaths
    5. cd "${TOP}"
    6. ## Register all support components
    7. dbLoadDatabase "dbd/testAsynDriver.dbd"
    8. testAsynDriver_registerRecordDeviceDriver pdbbase
    9. ## Load record instances
    10. #dbLoadRecords("db/xxx.db","user=blctrl")
    11. drvAsynIPPortConfigure("IPPort", "127.0.0.1:6666", 0, 0, 1);
    12. testConnectConfigure("PORT1", "IPPort", "Hello EPICS ")
    13. cd "${TOP}/iocBoot/${IOC}"
    14. iocInit

    8) 用python编写一个服务器程序server.py,对以上IOC程序进行测试:

    1. #!/usr/bin/python3
    2. import socket
    3. serverIP = "127.0.0.1"
    4. serverPort = 6666
    5. class Tcp_Server(object):
    6. def __init__(self, ip, port):
    7. self.server_ip = ip
    8. self.server_port = port
    9. self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    10. self.server.bind((self.server_ip, self.server_port))
    11. self.server.listen(10)
    12. while True:
    13. while True:
    14. sock, ip_port = self.server.accept()
    15. if sock is not None:
    16. print('New Client: %s' % str(ip_port))
    17. break
    18. while True:
    19. print("start receive!")
    20. data = sock.recv(1024)
    21. print("Client: %s" % data)
    22. sock.send(data)
    23. if len(data) == 0:
    24. sock.close()
    25. break
    26. def server_close(self):
    27. self.server.close()
    28. def main():
    29. Tcp_Server(serverIP, serverPort)
    30. if __name__ == "__main__":
    31. main()

    9) 启动服务程序和IOC应用程序:

    IOC应用程序终端:

    1. [blctrl@main-machine ioctestAsynDriver]$ ../../bin/linux-x86_64/testAsynDriver st.cmd
    2. #!../../bin/linux-x86_64/testAsynDriver
    3. < envPaths
    4. epicsEnvSet("IOC","ioctestAsynDriver")
    5. epicsEnvSet("TOP","/home/blctrl/exer/exer41")
    6. epicsEnvSet("SUPPORT","/usr/local/EPICS/synApps/support")
    7. epicsEnvSet("ASYN","/usr/local/EPICS/synApps/support/asyn")
    8. epicsEnvSet("IPAC","/usr/local/EPICS/synApps/support/ipac")
    9. epicsEnvSet("EPICS_BASE","/usr/local/EPICS/base")
    10. cd "/home/blctrl/exer/exer41"
    11. ## Register all support components
    12. dbLoadDatabase "dbd/testAsynDriver.dbd"
    13. testAsynDriver_registerRecordDeviceDriver pdbbase
    14. ## Load record instances
    15. #dbLoadRecords("db/xxx.db","user=blctrl")
    16. drvAsynIPPortConfigure("IPPort", "127.0.0.1:6666", 0, 0, 1);
    17. testConnectConfigure("PORT1", "IPPort", "Hello EPICS")
    18. cd "/home/blctrl/exer/exer41/iocBoot/ioctestAsynDriver"
    19. iocInit
    20. Starting iocInit
    21. ############################################################################
    22. ## EPICS R7.0.3.1
    23. ## EPICS Base built Sep 8 2022
    24. ############################################################################
    25. From Server: Hello EPICS
    26. iocRun: All initialization complete
    27. ## Start any sequence programs
    28. #seq sncxxx,"user=blctrl"
    29. epics> From Server: Hello EPICS
    30. From Server: Hello EPICS
    31. From Server: Hello EPICS
    32. From Server: Hello EPICS
    33. From Server: Hello EPICS
    34. From Server: Hello EPICS
    35. From Server: Hello EPICS
    36. From Server: Hello EPICS
    37. From Server: Hello EPICS
    38. From Server: Hello EPICS
    39. From Server: Hello EPICS
    40. From Server: Hello EPICS
    41. From Server: Hello EPICS
    42. From Server: Hello EPICS
    43. From Server: Hello EPICS

    服务程序的终端:

    1. [blctrl@main-machine python_server]$ ./server.py
    2. New Client: ('127.0.0.1', 50312)
    3. start receive!
    4. Client: b'Hello EPICS'
    5. start receive!
    6. Client: b'Hello EPICS'
    7. start receive!
    8. Client: b'Hello EPICS'
    9. start receive!
    10. Client: b'Hello EPICS'
    11. start receive!
    12. Client: b'Hello EPICS'
    13. start receive!
    14. Client: b'Hello EPICS'
    15. start receive!
    16. Client: b'Hello EPICS'
    17. start receive!
    18. Client: b'Hello EPICS'
    19. start receive!
    20. Client: b'Hello EPICS'
  • 相关阅读:
    小白学爬虫:通过关键词搜索1688商品列表数据接口|1688商品列表数据接口|1688商品列表数据采集|1688API接口
    SpringBoot知识点复习
    SVD奇异值分解
    【echarts】19、echarts+vue2 - 折线图柱状图
    导数...
    OKR之剑(理念篇)02—— OKR布道之旅
    shell中的文件、变量、字符串判断表达式及$等特殊字符
    【计算机视觉】图像分割与特征提取——基于Roberts、Prewitt、Sobel算子的图像分割实验
    Golang开发--Goroutine的使用
    javascirpt封装xhr上传多张图片,以及解决formdata后端只接受一张图片问题,用原型链来封装减少资源浪费和提高性能
  • 原文地址:https://blog.csdn.net/yuyuyuliang00/article/details/128150585