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

Slave从站(server服务器)端编程

CS104(TCP / IP)服务器配置和设置

要配置和设置IEC 60870-5-104服务器/从属服务器,需要CS104_Slave数据类型的实例。

CS104_Slave slave = CS104_Slave_create(100,100);

创建服务器实例后,可以对其进行配置

CS104服务器模式

服务器提供了三种有关冗余连接支持和事件队列处理的模式:

默认模式(CS104_MODE_SINGLE_REDUNDANCY_GROUP)仅允许单个活动客户端连接。活动客户端连接是发送ASDU(应用程序数据单元)的连接。所有其他连接只是不发送应用程序层数据的备用连接。事件只有一个队列。当没有客户端连接或没有连接处于活动状态时,也会存储事件。

第二种模式(CS104_MODE_CONNECTION_IS_REDUNDANCY_GROUP)允许多个活动客户端连接。每个连接都有其自己的事件队列。关闭客户端连接后,事件队列将被删除。当多个客户端必须访问应用程序数据时,可以使用此模式。此模式易于使用。但是此模式的缺点是,当没有客户端连接时事件会丢失。

第三种模式(CS104_MODE_MULTIPLE_REDUNDANCY_GROUPS)允许多个活动客户端连接,同时保留未连接任何客户端时的事件。在这种模式下,可以将客户端分配给特定的冗余组。分配基于客户端的IP地址。冗余组可以有多个同时连接,但是这些连接中只有一个可以处于活动状态。激活的连接数受冗余组数的限制。每个冗余组都有一个专用的事件队列。

可以使用CS104_Slave_setServerMode函数设置服务器模式:

CS104_Slave_setServerMode(从站,CS104_MODE_MULTIPLE_REDUNDANCY_GROUPS);

 

CS104:定义多个冗余组

仅当使用服务器模式CS104_MODE_MULTIPLE_REDUNDANCY_GROUPS时,才需要显式创建冗余组。您可以将多个IP地址分配给冗余组。然后,来自这些IP地址之一的传入连接将自动分配给该特定的冗余组。

当冗余组没有分配的IP地址时,它将用作“全部捕获”组。这意味着所有未分配给其他组之一的传入连接都将落入该组。

示例如何定义多重冗余组
 
CS104_Slave_setServerMode(slave, CS104_MODE_MULTIPLE_REDUNDANCY_GROUPS);

CS104_RedundancyGroup redGroup1 = CS104_RedundancyGroup_create("red-group-1");
CS104_RedundancyGroup_addAllowedClient(redGroup1, "192.168.2.9");

CS104_RedundancyGroup redGroup2 = CS104_RedundancyGroup_create("red-group-2");
CS104_RedundancyGroup_addAllowedClient(redGroup2, "192.168.2.223");
CS104_RedundancyGroup_addAllowedClient(redGroup2, "192.168.2.222");

CS104_RedundancyGroup redGroup3 = CS104_RedundancyGroup_create("catch-all");

CS104_Slave_addRedundancyGroup(slave, redGroup1);
CS104_Slave_addRedundancyGroup(slave, redGroup2);
CS104_Slave_addRedundancyGroup(slave, redGroup3);

 

CS101(串行)slave从站配置和设置

与主侧相似,CS101从侧也可以配置为两种链路层模式之一(平衡不平衡)。CS101从站由CS101_SLave对象表示。

一个前CS101_Slave对象可以创建的SerialPort是必需的对象。所述的SerialPort对象表示串行接口和它的配置。

SerialPort port = SerialPort_create(serialPort, 9600, 8, 'E', 1);

CS101_Slave_create函数需要创建的SerialPort对象:

CS101_Slave slave = CS101_Slave_create(port,NULL,NULL,IEC60870_LINK_LAYER_UNBALANCED);

此功能具有以下签名:

CS101_Slave
CS101_Slave_create(SerialPort serialPort, LinkLayerParameters llParameters, CS101_AppLayerParameters alParameters, IEC60870_LinkLayerMode linkLayerMode)

可选地,可以指定链路层参数和应用程序层参数。如果应使用默认值,则可以跳过这些参数(设置为NULL)。最后一个参数指定使用平衡还是不平衡模式。

对于串行从站,还需要设置一个链路层地址:

CS101_Slave_setLinkLayerAddress(slave,1);

 

 

设置回调处理函数 callback handler functions

在启动或运行服务器之前,建议设置回调函数以处理从属事件。可以使用以下回调处理程序类型(有关功能签名的详细信息,请参阅API参考手册)。其中一些仅可用于CS 104服务器,而某些仅可用于CS101从服务器。

表2.从站侧回调处理程序类型Slave side callback handler types
回调类型事件第101章第104章

CS101_InterrogationHandler

询问请求

+

+

CS101_CounterInterrogationHandler

反询问请求

+

+

CS101_ReadHandler

读取单个信息对象的请求

+

+

CS101_ClockSynchronizationHandler

收到时钟同步消息

+

+

CS101_ResetProcessHandler

收到重置流程请求

+

+

CS101_DelayAcquisitionHandler

收到延迟获取请求

+

--

CS101_ASDUHandler

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

+

+

CS101_ResetCUHandler

收到类型为复位CU(通信单元)的链路层消息

+

--

CS104_ConnectionRequestHandler

一个新的TCP / IP客户端尝试连接

--

+

 

/* set the callback handler for the clock synchronization command */
CS101_Slave_setClockSyncHandler(slave, clockSyncHandler, NULL);

/* set the callback handler for the interrogation command */
CS101_Slave_setInterrogationHandler(slave, interrogationHandler, NULL);

/* set handler for other message types */
CS101_Slave_setASDUHandler(slave, asduHandler, NULL);

/* set handler for reset CU (reset communication unit) message */
CS101_Slave_setResetCUHandler(slave, resetCUHandler, (void*) slave);

 

CS104启动/停止服务器

配置服务器后,可以使用CS104_Slave_start函数启动它。此函数启动一个新的后台线程,该线程正在侦听传入的客户端连接。

CS104_Slave_start(slave);

要停用IEC 60870-5-104服务,可以使用CS104_Slave_stop功能停止服务器。

CS104_Slave_stop(slave);

 

自动或定期发送消息

为了在server/slave  服务器/从站上 自动或定期地进行消息传输,用户必须分配代表单个ASDU的CS101_ASDU对象,将信息对象添加到ASDU,最后将ASDU放入传输队列中。传输队列是FIFO(先进先出)列表。如果队列已满,则最早的消息将被删除,并由新添加的消息代替。仅当存在活动的客户端连接或有效的链路层连接时,才发送消息。否则,消息将保留在队列中,直到激活连接为止。

CS 104:在CS 104从站中,队列大小由CS104_Slave_create函数的maxLowPrioQueueSize参数确定。如果将maxLowPrioQueueSize参数设置为零,则队列将始终具有CONFIG_SLAVE_MESSAGE_QUEUE_SIZE定义的大小。第二个参数maxHighPrioQueueSize确定高优先级数据队列的大小。放入此队列的消息会绕过低优先级队列的消息。高优先级队列用于库回调处理程序中的请求响应。

要发送自发或定期消息,必须执行以下步骤:

 

  1. 创建一个新的CS101_ASDU实例(使用CS101_COT_PERIODIC定期数据和CS101_COT_SPONTANEOUS自发数据)

    CS101_ASDU newAsdu = CS101_ASDU_create(alParameters,false,CS101_COT_PERIODIC,0,1,false,false);
  2. 创建一个包含要发送数据的新信息对象实例

    InformationObject io =(InformationObject)MeasuredValueScaled_create(NULL,110,scaledValue,IEC60870_QUALITY_GOOD);
  3. 将新的信息对象添加到ASDU

    CS101_ASDU_addInformationObject(newAsdu,io);
  4. 释放信息对象内存

    InformationObject_destroy(io);
  5. 将ASDU放入2类数据队列中进行传输

    CS101_Slave_enqueueUserDataClass2(slave,newAsdu);
  6. 释放ASDU内存

    CS101_ASDU_destroy(newAsdu);

注意:对于CS 104,您必须在步骤5中使用CS104_Slave_enqueueASDU函数:

CS104_Slave_enqueueASDU(slave,newAsdu);

处理查询请求

在服务器端,您应该使用InterrogationHandler回调函数来处理Interrogation请求。根据QOI(询问限定符)的值,您可以返回不同的信息对象。对于一个简单的系统,仅处理 总查询 请求就足够了(QOI = 20)。QOI值21-36用于询问组(1-16)。由从属实施者将信息对象分配给询问组。

根据规范,服务器必须用ACT_CON响应响应来自客户端的ACTIVATION请求,然后是ASDU,其中ASDU包含代表站质询或COT的信息对象,其中CS101_COT_INTERROGATED_BY_STATION代表相应的质询组(例如,质询组1的CS101_COT_INTERROGATED_BY_GROUP_1)。发送完所有信息对象后,服务器必须发送初始查询命令消息,其中COT = CS101_COT_ACTIVATION_TERMINATION,以指示查询数据的传输已完成。

示例如何实现询问处理程序
 
static bool
interrogationHandler(void* parameter, IMasterConnection connection, CS101_ASDU asdu, uint8_t qoi)
{
    if (qoi == 20) { /* only handle station interrogation */

        CS101_AppLayerParameters alParams = IMasterConnection_getApplicationLayerParameters(connection);

        IMasterConnection_sendACT_CON(connection, asdu, false);

        CS101_ASDU newAsdu = CS101_ASDU_create(alParams, false, CS101_COT_INTERROGATED_BY_STATION,
                0, 1, false, false);

        InformationObject io = (InformationObject) MeasuredValueScaled_create(NULL, 100, -1, IEC60870_QUALITY_GOOD);

        CS101_ASDU_addInformationObject(newAsdu, io);

        CS101_ASDU_addInformationObject(newAsdu, (InformationObject)
            MeasuredValueScaled_create((MeasuredValueScaled) io, 101, 23, IEC60870_QUALITY_GOOD));

        CS101_ASDU_addInformationObject(newAsdu, (InformationObject)
            MeasuredValueScaled_create((MeasuredValueScaled) io, 102, 2300, IEC60870_QUALITY_GOOD));

        InformationObject_destroy(io);

        IMasterConnection_sendASDU(connection, newAsdu);

        CS101_ASDU_destroy(newAsdu);

        IMasterConnection_sendACT_TERM(connection, asdu);
    }
    else {
        IMasterConnection_sendACT_CON(connection, asdu, true);
    }

    return true;
}
在询问处理程序内部,可以使用IMasterConnection接口将询问的数据发送回客户端/主机。在查询处理程序内部创建的 CS101_ASDUInformationObject实例由用户负责,并且在之前动态分配它们之前,必须使用适当的功能( CS101_ASDU_destroyInformationObject_destroy)来释放它们。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值