EPICS asyn连接测试例程

news2024/11/15 14:02:09

1) 用makeBaseApp.pl新建一个EPICS IOC的目录结构:

root@orangepi5:/usr/local/EPICS/program/testConnect# ls
configure  iocBoot  Makefile  testConnectApp

2) 编辑configure目录下的RELEASE文件,定义asyn模块所在的路径:

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

3) 进入testConnectApp目录下的src目录,编写用于连接测试的c++源程序myConnect.cpp:

此程序运行时,每个1秒,向网络输出一个"Hello World"字符串并且从网络回读一个字符串。

/* myConnect derived from asynPortDriver to test Connect */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "epicsThread.h"
#include "epicsString.h"
#include "iocsh.h"
#include "asynPortDriver.h"
#include "asynOctetSyncIO.h"
#include "epicsExport.h"

static const char * driverName = "myConnect";

#define POLLER_PERIOD 1
#define MAX_RESPONSE_LEN 256

class myConnect : public asynPortDriver {
public:
        myConnect(const char * portName, const char * IPPortName, const char * outputString);
        void pollerTask(void);

private:
        asynUser * pasynUserIPPort_; // asynUser to connect to this driver
        const char * outputString_; // used for storing the input string
};


static void pollerTask(void * drvPvt);

myConnect::myConnect(const char * portName, const char * IPPortName, const char * outputString)
        : asynPortDriver(portName, 1, asynOctetMask, 0, ASYN_CANBLOCK, 1, 0, 0)
{
        asynStatus status;
        const char * functionName = "myConnect";

        // copy the input string, and point to the copy
        outputString_ = epicsStrDup(outputString);
        // connect to the driver and get the asynUser
        // parameters:1) char *port, 2)int addr,  3)asynUser **ppasynUser, 4) const char *drvInfo
        status = pasynOctetSyncIO->connect(IPPortName, 0, &pasynUserIPPort_, NULL);

        if (status)
        {
                printf("%s:%s:pasynOctetSyncIO->connect failure, status = %d\n", driverName, functionName, status);
                return;
        }

        // if NULL, create epicsThread failed
        status = (asynStatus)(epicsThreadCreate("myConnectTask", epicsThreadPriorityMedium,
                        epicsThreadGetStackSize(epicsThreadStackMedium),
                        (EPICSTHREADFUNC)::pollerTask, this) == NULL);

        if (status){
                printf("%s:%s: epicsThreadCreate failure, status: %d\n", driverName, functionName, status);
                return;
        }
}

static void pollerTask(void * drvPvt)
{
        myConnect * pPvt = (myConnect *)drvPvt;

        pPvt->pollerTask();
}

void myConnect::pollerTask(void)
{
        asynStatus status;
        char response[MAX_RESPONSE_LEN];
        size_t numWrite, numRead;
        int isConnected;
        int eomReason;
        static const char * functionName = "pollerTask";

        while (1){
                lock();
                status = pasynManager->isConnected(pasynUserIPPort_, &isConnected);

                if (status){
                        // pasynUserSelf used to connect to ourselves for asynTrace, it defined in asynPortDriver
                        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: error calling pasynManager->isConnected, status=%d, error=%s\n",
                                        driverName, functionName, status, pasynUserIPPort_->errorMessage);
                }

                asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: isConnected = %d\n",
                                driverName, functionName, isConnected);

                status = pasynOctetSyncIO->writeRead(pasynUserIPPort_, outputString_, strlen(outputString_),
                                response, sizeof(response), 1.0, &numWrite, &numRead, &eomReason);

                if (status){
                        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: error calling pasynOctetSyncIO->writeRead, status=%d, error=%s\n",
                                        driverName, functionName, status, pasynUserIPPort_->errorMessage);
                }
                else{
                        asynPrint(pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s:%s: numWrite=%ld, wrote:%s, numRead=%ld, response=%s\n",
                                        driverName, functionName, (long)numWrite, outputString_, (long)numRead, response);
                }
                unlock();
                epicsThreadSleep(POLLER_PERIOD);
        }

}

extern "C"{
int myConnectConfigure(const char * portName, const char * IPPortName, const char * outputString)
{
        new myConnect(portName, IPPortName, outputString);
        return asynSuccess;
}

/*  EPICS iocsh shell commands */
static const iocshArg initArg0 = {"portName", iocshArgString};
static const iocshArg initArg1 = {"IPPortName", iocshArgString};
static const iocshArg initArg2 = {"output string", iocshArgString};
static const iocshArg * const initArgs[]  = {&initArg0, &initArg1, &initArg2};
static const iocshFuncDef initFuncDef = {"myConnectConfigure", 3, initArgs};
static void initCallFunc(const iocshArgBuf * args)
{
        myConnectConfigure(args[0].sval, args[1].sval, args[2].sval);
}

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

epicsExportRegistrar(myConnectRegister);
}

4)编写3)步骤中编写源程序对应的支持文件myConnect.dbd:

registrar(myConnectRegister)

5)编写与3)和4)相同路径下的Makefile文件,添加以下内容:

...
# support dbd file
testConnect_DBD += asyn.dbd
testConnect_DBD += drvAsynIPPort.dbd
testConnect_DBD += myConnect.dbd


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

# source files to be compiled
testConnect_SRCS += myConnect.cpp

...

6) 回到顶层目录,执行make,进行编译。

7)进入IOC启动目录,编辑启动文件st.cmd:

#!../../bin/linux-aarch64/testConnect

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

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/testConnect.dbd"
testConnect_registerRecordDeviceDriver pdbbase


# This is a real IP address that will connect
drvAsynIPPortConfigure("IPPort", "192.168.3.208:9999", 0, 0, 1);
myConnectConfigure("MYPORT", "IPPort", "Hello World")
#asynSetTraceMask("PORT1",0,9)
asynSetTraceIOMask("MYPORT",0,0x2)

dbLoadRecords("$(ASYN)/db/asynRecord.db","P=testConnect:,R=asyn1,PORT=MYPORT,ADDR=0,OMAX=80,IMAX=80")


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

8) 编写一个python tcp服务程序,用于对测试以上连接程序:

此程序运行时,监听网络,接收一个套接字连接后建立TCP连接,从连接套接字读取字符串,并且在这个字符串前加上Hello后,重新发送给连接套接字。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import socket
import threading
import time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.bind(('0.0.0.0', 9999))

s.listen(5)
print('Waiting for connection...')

def tcplink(sock, addr):
    print('Accept new connection from %s:%s...' %addr)
    sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        print(data)
        time.sleep(0.2)
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('Connection from %s:%s closed.' %addr)


while True:
    sock, addr = s.accept()
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()

9)启动以上python程序,等待连接:

orangepi@orangepizero2:~/python$ ./tcpserver.py
Waiting for connection...

10) 启动IOC程序:

root@orangepi5:/usr/local/EPICS/program/testConnect/iocBoot/ioctestConnect# ../../bin/linux-aarch64/testConnect st.cmd
#!../../bin/linux-aarch64/testConnect
< envPaths
epicsEnvSet("IOC","ioctestConnect")
epicsEnvSet("TOP","/usr/local/EPICS/program/testConnect")
epicsEnvSet("SUPPORT","/usr/local/EPICS/synApps/support")
epicsEnvSet("ASYN","/usr/local/EPICS/synApps/support/asyn")
epicsEnvSet("EPICS_BASE","/usr/local/EPICS/base")
cd "/usr/local/EPICS/program/testConnect"
## Register all support components
dbLoadDatabase "dbd/testConnect.dbd"
testConnect_registerRecordDeviceDriver pdbbase
# This is a real IP address that will connect
drvAsynIPPortConfigure("IPPort", "192.168.3.208:9999", 0, 0, 1);
myConnectConfigure("MYPORT", "IPPort", "Hello World")
#asynSetTraceMask("PORT1",0,9)
asynSetTraceIOMask("MYPORT",0,0x2)
dbLoadRecords("/usr/local/EPICS/synApps/support/asyn/db/asynRecord.db","P=testConnect:,R=asyn1,PORT=MYPORT,ADDR=0,OMAX=80,IMAX=80")
cd "/usr/local/EPICS/program/testConnect/iocBoot/ioctestConnect"
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.7
## Rev. 2023-05-26T09:07+0000
## Rev. Date build date/time:
############################################################################
iocRun: All initialization complete
## Start any sequence programs
#seq sncxxx,"user=orangepi"
epics> dbl
testConnect:asyn1
epics>

11) 观察python tcp服务程序的输出,不断接收到"Hello World"

orangepi@orangepizero2:~/python$ ./tcpserver.py
Waiting for connection...
Accept new connection from 192.168.3.191:59798...
b'Hello World'
b'Hello World'
b'Hello World'
b'Hello World'
b'Hello World'
b'Hello World'
...

13) 启动asynRecord.adl界面:

medm -x -macro "P=testConnect:,R=asyn1"  asynRecord.adl &

 启动traceIODriver选项,可以观察到服务器发送给这个连接测试程序的应答字符串:

epics> 2023/08/24 11:13:15.131 myConnect:pollerTask: isConnected = 1
2023/08/24 11:13:15.334 myConnect:pollerTask: numWrite=11, wrote:Hello World, numRead=19, response=Hello, Hello World!
2023/08/24 11:13:16.335 myConnect:pollerTask: isConnected = 1
2023/08/24 11:13:16.537 myConnect:pollerTask: numWrite=11, wrote:Hello World, numRead=19, response=Hello, Hello World!
2023/08/24 11:13:17.538 myConnect:pollerTask: isConnected = 1
2023/08/24 11:13:17.741 myConnect:pollerTask: numWrite=11, wrote:Hello World, numRead=19, response=Hello, Hello World!
...

启动traceError选项后,断开IOC所在主机的网络后,可以观察到IOC的报错信息:

2023/08/24 11:15:33.378 myConnect:pollerTask: error calling pasynOctetSyncIO->writeRead, status=1, error=192.168.3.208:9999 timeout: Resource temporarily unavailable
2023/08/24 11:15:35.380 myConnect:pollerTask: error calling pasynOctetSyncIO->writeRead, status=1, error=192.168.3.208:9999 timeout: Resource temporarily unavailable
...

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

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

相关文章

Java“牵手”1688拍立淘接口数据,图片搜索1688商品,图片识别商品接口,1688API申请指南

1688商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取1688商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问1688商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

【Java 动态数据统计图】动态数据统计思路案例(动态,排序,动态数组(重点推荐))七(129)

需求&#xff1a;前端根据后端的返回数据&#xff1a;画统计图&#xff1b; 说明&#xff1a; 1.X轴为地域&#xff0c;Y轴为地域出现的次数&#xff1b; 2. 动态展示&#xff08;有地域展示&#xff0c;没有不展示&#xff0c;且高低排序&#xff09; Demo案例&#xff1a; …

使用卷积操作实现因子分解机

本文将介绍如何使用卷积操作实现因子分解机器。卷积网络因其局部性和权值共享的归纳偏差而在计算机视觉领域获得了广泛的成功和应用。卷积网络可以用来捕获形状的堆叠分类特征(B, num_cat, embedding_size)和形状的堆叠特征(B, num_features, embedding_size)之间的特征交互。 …

【C++】C++11的新特性(上)

引入 C11作为C标准的一个重要版本&#xff0c;引入了许多令人振奋的新特性&#xff0c;极大地丰富了这门编程语言的功能和表达能力。本章将为您介绍C11的一些主要变化和改进&#xff0c;为接下来的章节铺垫。 文章目录 引入 一、列表初始化 1、1 {} 初始化 1、2 std::initiali…

问道管理:macd参数改良设置?

MACD目标是一种广泛应用的技能剖析目标&#xff0c;其特色在于能够同时反映趋势和动量改变。可是&#xff0c;很多买卖者感到困惑的是&#xff0c;怎么设置MACD的参数才能更好地指导买卖。 1. MACD目标参数解析 MACD目标是依据两个移动平均线的穿插来判别商场的趋势与动量改变…

解压jar包并导入库环境

背景 因为各种历史原因&#xff0c;当初的maven依赖环境已下载不了了&#xff0c;所以需要从生产环境的jar包里&#xff0c;获取库环境来本地运行。 但是网上很多方法都是用mvn install命令&#xff0c;一个个jar包导入的&#xff0c;不符合我的需求&#xff08;需要导入280多…

Linux 虚拟机同步时间crontab以及crond详解

目录 一 Linux 虚拟机同步时间设置 1. 检查是否安装cron服务&#xff08;即时间同步器&#xff09; 2. 下载时间同步器 3. 编辑crontab 内容 4. 同步更新电脑网络时间 5.设置 reload 6. 查看 crond 状态 二 crond 详解 1. 启动/关闭cron服务 2. crontab命令格式 3. …

VK1616是LED显示控制驱动电路/LED驱动IC、数显驱动芯片、数码管驱动芯片

产品品牌&#xff1a;永嘉微电/VINKA 产品型号&#xff1a;VK1616 封装形式&#xff1a;SOP16 产品年份&#xff1a;新年份 概述&#xff1a;VK1616是一种数码管或点阵LED驱动控制专用芯片&#xff0c;内部集成有3线串行接口、数据锁存器、LED 驱动等电路。SEG脚接LED阳极&a…

mysql存储过程之遍历设置表中某些字段值

缘起 ​ mysql数据库中有用到分表&#xff0c;大概300张表&#xff0c;都是以geo_data_xxxxxx来命名&#xff0c;之前测试过程中&#xff0c;有给300张表中的一个字段设置过值&#xff0c;但是想重新生成一遍数据。那么后面是做了一个数据清洗&#xff0c;给300张表is_turnout…

Prometheus监控(三)架构

文章目录 Prometheus架构图Prometheus生态圈组件Prometheus Serverclient librariesPushgatewayexporterAlartmanager Prometheus架构理解存储计算层采集层应用层 Prometheus架构图 Prometheus生态圈组件 Prometheus Server 主服务器&#xff0c;负责收集和存储时间序列数据 …

SAP_ABAP_BDC录屏案例

SAP ABAP顾问能力模型梳理_企业数字化建设者的博客-CSDN博客SAP Abap顾问能力模型https://blog.csdn.net/java_zhong1990/article/details/132469977 一、实施步骤 1.1 SHDB --> 新建记录-->输入录制的tcode :BP,-->执行录屏操作-->录制结果封装成函数 1.2 SHDB …

大数据到底是好是坏?_光点科技

近年来&#xff0c;随着科技的不断发展和互联网的普及&#xff0c;大数据已经成为一个备受关注的话题。它带来了许多机遇和挑战&#xff0c;引发了人们对于其是好是坏的争议。大数据究竟是一把双刃剑&#xff0c;需要我们从多个角度来审视。 大数据的好处无疑是显而易见的。首先…

GNU make系列之写Makefile文件(1)

一.欢迎来到我的酒馆 在本章节介绍如何写Makefile文件。 目录 一.欢迎来到我的酒馆二.Makefile包含了什么三.引入其它的Makefile文件四.MAKEFILES变量 二.Makefile包含了什么 2.1 Makefile包含了5种类型&#xff1a;显式的规则&#xff0c;隐式的规则&#xff0c;变量的定义&am…

There is already ‘xxxController‘ bean method的解决方法

报这个错的原因是因为你controller里的RequestMapping中的路径有重复&#xff01;

嵌入式linux设备网口带宽-测试方法

iperf是一个基于Client/Server的网络性能测试工具&#xff0c;可以测试TCP、UDP和SCTP带宽质量&#xff0c;能够提供网络吞吐率信息&#xff0c;以及震动、丢包率&#xff0c;最大段和最大传输单元大小等统计信息&#xff0c;帮助我们测试网络性能&#xff0c;定位网络瓶颈。其…

keil5 报错no target connected

场景&#xff1a;用ST_Link V2 在 keil5 中下载stm32程序 原因&#xff1a;线路连接错误 正确连接 注意&#xff1a;江科大stm32和stlink的接线&#xff0c;一定要对齐&#xff0c;我买的一个不是按照顺序接线的&#xff0c;需要仔细查看

Arduino程序设计(五)按键中断+按键状态检测

按键中断按键状态检测 前言一、按键中断1、中断的基本概念2、外部中断3、示例代码4、按键中断实验 二、按键状态检测1、按键单击、双击和长按的工作原理2、按键状态检测实验 参考资料 前言 本文主要介绍两种按键检测实验&#xff0c;分别是&#xff1a;1、外部中断实现按键控制…

SQL-DQL

-----分组查询----- 1.语法&#xff1a; SELECT 字段列表 FROM 表名 [WHERE 条件 ] GROUP BY 分组字段名 [HAVING 分组后过滤条件]&#xff1b; 2.where与having区别 》执行时机不同&#xff1a;where是分组之前进行过滤&#xff0c;不满足where条件&#xff0c;不参与分组&…

docker常见面试问题详解

在面试的时候&#xff0c;面试官常常会问一些问题&#xff1a; docker是什么&#xff0c;能做什么&#xff1f;docker和虚拟机的区别是什么呢&#xff1f;docker是用什么做隔离的&#xff1f;docke的网络类型&#xff1f;docker数据之间是如何通信的&#xff1f;docker的数据保…

阿里云申请免费SSL证书的两种验证方式及配置服务器Tomcat升级HTTPS协议

通用教程&#xff0c;其他服务商的免费 SSL 证书也差不多是这个流程。&#xff08;至少腾讯云的操作步骤和本文是一致&#xff0c;嘻嘻&#xff01;&#xff09; 申请 SSL 证书 首先在阿里云上创建并申请 SSL 证书&#xff0c;之后选择 DNS 验证的方式&#xff0c;一种是手动配…