lib60870-IEC 60870-5-101 / 104 C源代码库用户指南-版本2.3.0 -第四部分

Master (client) 主站(客户端)编程

对于主站编程,可以使用以下抽象数据类型和API:

  • CS101_Master用于CS 101兼容的平衡模式非平衡模式串行连接。

  • CS104_Connection用于符合CS 104的TCP / IP连接。

创建与CS 104服务器的连接

由于IEC 60870-5-104连接基于TCP客户端/服务器连接,因此该连接将由客户端(主设备)建立。服务器(从站或分站)通常被动地等待连接。

通过调用CS104_Connection类型的CS104_Connection_create函数可以轻松创建新连接:

CS104_Connection con = CS104_Connection_create(“ 127.0.0.1”,2404);

这将创建一个准备连接到服务器的新CS104_Connection对象。参数是服务器的主机名或IP地址以及TCP / IP端口(通常为2404)。对于端口参数,您还可以设置-1以使用默认端口。

创建连接对象后,您现在可以简单地调用CS104_Connection_connect函数以连接到服务器:

CS104_Connection_connect(con);

参数con是对上面创建的连接对象的引用。

正确建立连接后,可以使用连接对象发送命令和接收数据。

使用完连接对象后,您必须调用

CS104_Connection_destroy(con);

释放对象分配的所有资源。使用destroy函数后,您不能将任何函数与con引用一起使用!

 

 

准备与一个或多个从站的CS 101连接

CS 101为主/从连接提供两种链路层模式。

平衡模式支持使用专用串行线在单个主机和单个从机之间进行通信。在两端都可以随时自发发送消息的意义上说,此模式是“平衡的”。

非平衡模式支持串行总线上单个主机和多个从机之间的通信。每个从站都通过其唯一的链路层地址来寻址。从站不允许自发发送消息。他们仅在主人的要求下作出回应。主机可以使用广播地址一次寻址多个从机。

配置串口

对于这两种模式,必须先配置和初始化串行端口。以下代码显示了一个示例,说明如何准备要与库一起使用的串行端口:

 SerialPort port = SerialPort_create("/dev/ttsS0", 9600, 8, 'E', 1);

创建和使用新的不平衡主实例

对于平衡和不平衡的通讯模式,必须使用CS101_Master类型。

以下代码使用上面定义的串行端口创建一个新的不平衡主实例。该 CS101_Master_setASDUReceivedHandler 功能提供了收到的ASDU回调处理程序。该 CS101_Master_addSlave 能将创建一个新的从特定状态机来处理与链路层地址1的从属的所有通信。

CS101_Master master = CS101_Master_create(port, NULL, NULL, IEC60870_LINK_LAYER_UNBALANCED);

CS101_Master_setASDUReceivedHandler(master, asduReceivedHandler, NULL);

CS101_Master_addSlave(master, 1);

链路层参数和应用程序层参数是可选参数。如果未设置,则创建并使用参数对象的默认实例。以后也可以修改参数。

在向特定从站发送任何命令或其他请求之前,必须使用CS101_Master_useSlaveAddress函数设置从站地址。

CS101_Master_useSlaveAddress(master,1);
CS101_Master_sendProcessCommand(master,CS101_COT_ACTIVATION,1,sc);

平衡模式

平衡模式的创建方法相同。只是链路层模式参数不同。所述CS101_Master_useSlaveAddress用于设置从机地址。在平衡主控情况下,仅需设置一次,因为仅存在一次

CS101_Master master = CS101_Master_create(port, NULL, NULL, IEC60870_LINK_LAYER_BALANCED);

CS101_Master_useSlaveAddress(master, 3);
CS101_Master_setASDUReceivedHandler(master, asduReceivedHandler, NULL);

设置链路层参数

设置链路层参数是可选步骤。如果未明确设置,则默认参数集将用于新的主实例。可以使用构造函数CS101_Master_create给出参数,也可以稍后对其进行修改。

示例:禁用单个字符ACK的使用
LinkLayerParameters llParams = CS101_Master_getLinkLayerParameters(master); 
llParams-> useSingleCharACK = false ;

从站发送请求并接收响应

通常,应用程序与将应用程序层消息(ASDU)发送到从属设备有关。主端API支持通用和专用功能,以将消息发送到从属端。当发送系统命令或过程命令时,建议使用专用功能,因为它们有助于创建符合标准的ASDU。这些特殊功能将在以下各节中进行说明。它们通常以CS101和CS104的两个变体形式存在。

在一般情况下,可以使用CS101_Master_sendASDUCS104_Connection_sendASDU函数发送任意ASDU 。

为了接收应用程序层消息,应用程序必须实现CS101_ASDUReceivedHandler回调。

在CS101_ASDUReceivedHandler中处理接收到的ASDU的示例
 
static bool
asduReceivedHandler (void* parameter, int address, CS101_ASDU asdu)
{
    printf("RECVD ASDU type: %s(%i) elements: %i\n",
            TypeID_toString(CS101_ASDU_getTypeID(asdu)),
            CS101_ASDU_getTypeID(asdu),
            CS101_ASDU_getNumberOfElements(asdu));

    if (CS101_ASDU_getTypeID(asdu) == M_ME_TE_1) {

        printf("  measured scaled values with CP56Time2a timestamp:\n");

        int i;

        for (i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) {

            MeasuredValueScaledWithCP56Time2a io =
                    (MeasuredValueScaledWithCP56Time2a) CS101_ASDU_getElement(asdu, i);

            printf("    IOA: %i value: %i\n",
                    InformationObject_getObjectAddress((InformationObject) io),
                    MeasuredValueScaled_getValue((MeasuredValueScaled) io)
            );

            MeasuredValueScaledWithCP56Time2a_destroy(io);
        }
    }
    else if (CS101_ASDU_getTypeID(asdu) == M_SP_NA_1) {
        printf("  single point information:\n");

        int i;

        for (i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) {

            SinglePointInformation io =
                    (SinglePointInformation) CS101_ASDU_getElement(asdu, i);

            printf("    IOA: %i value: %i\n",
                    InformationObject_getObjectAddress((InformationObject) io),
                    SinglePointInformation_getValue((SinglePointInformation) io)
            );

            SinglePointInformation_destroy(io);
        }
    }

    return true;
}

此回调处理程序必须与安装CS104_Connection_setASDUReceivedHandlerCS101_Master_setASDUReceivedHandler功能。

CS101_Master_setASDUReceivedHandler(master,asduReceivedHandler,NULL);

所有回调处理程序的函数签名中都有一个通用参考参数,名称为“ parameter”。用户可以使用此参数将特定于应用程序的上下文信息提供给回调处理程序。该参数将通过回调处理程序的安装功能进行设置(例如上中的CS101_Master_setASDUReceivedHandler)。如果不使用此参数,则可以将其设置为NULL

表1.主端回调处理程序类型
回调类型事件第101章第104章

CS101_ASDUReceivedHandler

ASDU已收到但未由其他回调处理程序之一处理

+

+

IEC60870_LinkLayerStateChangedHandler

链路层状态更改事件

+

--

CS104_ConnectionHandler

CS104 APCI事件

--

+

发送阅读请求

IEC 60870文档不建议使用此服务(周期性数据请求或轮询),但这是获取所需数据的简便方法。您只需要知道公用地址(CA)和信息对象地址(IOA)即可创建正确的请求。

CS104_Connection_sendReadCommand(con,1 / * CA * /,2001 / * IOA * /);

该调用是非阻塞的。您必须在CS101_ASDUReceivedHandler回调函数中评估响应。

通常,期望服务器响应仅包含基本数据类型而没有时间戳(即将消息类型用于不包含时间戳的特定数据类型)!

 

 

总召唤

也可以通过一个请求从站请求一组数据项。在主端(客户端)上,您可以简单地使用Connection对象的sendInterrogationCommand函数:

CS104_Connection_sendInterrogationCommand(con,CS101_COT_ACTIVATION,/ * CA * / 1,/ * QOI * / 20);

客户端/主方方法签名如下所示:

bool 
CS104_Connection_sendInterrogationCommand(CS104_Connection self,CS101_CauseOfTransmission cot,int ca,QualifierOfInterrogation qoi)

与其他方法一样,参数ca是公共地址(CA)。参数qoi是“询问符”(QOI)。QOI的值“ 20”(指示“总召唤”)表示它是对所有数据点的请求。QOI的其他值将指示客户端(主机)仅希望接收来自特定询问组的数据。

时钟同步程序

对于时钟同步过程,控制站(主站)向受控站(从站)发送C_CS_NA_1 ACT消息,该消息包含当前有效时间信息作为CP56Time2a输入的时间值。发送了所有排队的带时间标记的PDU后,受控站必须更新其内部时间并以C_CS_NA_1 ACT_CON消息进行响应。

受控站的时钟同步可以用做CS104_Connection_sendClockSyncCommand功能CS104或CS101_Master_sendClockSyncCommand为CS101。

首先,必须创建并初始化CP56Time2a时间戳:

struct sCP56Time2a currentTime; 
CP56Time2a_createFromMsTimestamp(&currentTime,Hal_getTimeInMs()); 
CS104_Connection_sendClockSyncCommand(con,1 / * CA * /,&currentTime);

或在使用动态内存分配和CS 101时:

CP56Time2a currentTime = CP56Time2a_createFromMsTimestamp(NULL,Hal_getTimeInMs()); 
CS101_Master_sendClockSyncCommand(master,1 / * CA * /,currentTime);

注意Hal_getTimeInMs函数是独立于平台的方式,用于获取自1970年1月1日UTC以来的当前时间(以毫秒为单位)。您也可以使用自己的功能来获取时间。

 

命令程序

命令用于设置设置点,参数或触发受控站上的某些动作。

以下命令类型(数据类型可用于命令):

  • C_SC(单点命令)-控制二进制数据(开关...)

  • C_DC(双点指令)-以过渡状态控制二进制数据(移动开关...)

  • S_RC(步进位置命令)-控制步进位置

  • S_SE(设定点命令)-用于控制设定点(标定值,归一化值,浮点值)-也可以用于设定参数,警报极限等。

这些命令类型在带有时间标记(CP56TIme2a)的版本中也可用。

有两种不同的命令过程可用。在直接操作命令的程序和操作前选择命令过程。

要发送用于直接操作命令过程的命令,您必须将ACTIVATION APDU发送到受控站。

将过程命令发送到受控站
  InformationObject sc = (InformationObject)SingleCommand_create(NULL, 5000, true, false, 0);

  CS101_Master_sendProcessCommand(master, CS101_COT_ACTIVATION, 1, sc);

  InformationObject_destroy(sc);

SingleCommand数据类型的构造函数具有以下签名:

  SingleCommand   SingleCommand_create(SingleCommand self, int ioa, bool command, bool selectCommand, int qu);

为了发送直接操作命令,selectCommand参数应该为false。限定词(qu)通常应设置为0。

对于选择操作之前的命令,必须将selectCommand参数设置为true来发送命令,以选择控制输出。在下一步中,必须将selectCommand设置为false的附加命令发送给实际命令执行。

如果命令成功执行,则外站将以ACT_CON响应消息(未设置否定标志)进行回答。万一外站无法执行命令,它还将以ACT_CON响应但设置了负标志来回答。您可以检查是否通过与接收到的CS101_ASDU实例一起使用的CS101_ASDU_isNegative函数设置了此标志。

对于CS 104主设备,可以使用CS104_Master_sendProcessCommandEx函数以相同的方式发送命令。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值