Files
STM32F4-Base/IEC60870-Slave/104/business/IEC104_Interrogation.h
T
STF 7596f3371a
CI / L0 静态门禁 (pre-commit) (push) Failing after 44s
CI / L0.5 主机侧单测 (MSVC) (push) Failing after 42s
补充总召唤的广播地址,电度召唤+时钟同步业务的实现
2026-10-29 03:20:19 -07:00

327 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 104召唤共用引擎:具体种类规则由GeneralInterrogation/CounterInterrogation创建入口提供。
* 总召旧入口Create保持兼容;计数量召唤入口见IEC104_CounterInterrogation.h。
* 借用一个Slave,不创建socket/线程,不保存业务回调;动作入口仅同步借用回调执行一次。
* 所有接口在同一事件循环串行调用,动作回调不得重入引擎。
* 先把Slave通知按FIFO交给Handle_Event,读空后Process,再NextEvent并显式应答。
* 事件来源和会话状态由Slave公共接口校验;本模块维护召唤阶段、业务期限和应用事件。
* 退出顺序:Cancel -> 读完业务FINISHED并清理应用资源 -> Destroy -> Destroy Slave。
*/
#ifndef IEC104_INTERROGATION_H
#define IEC104_INTERROGATION_H
#include "IEC104_Slave.h"
#ifdef __cplusplus
extern "C" {
#endif
/* 不透明静态池句柄,只能由Create取得、Destroy释放,不能自行分配、复制对象或free。
* 销毁成功后停止使用旧句柄;同一实例的全部接口须在所属事件循环中串行调用。 */
typedef struct IEC104_Interrogation IEC104_Interrogation_t;
/* 请求信息随事件按值复制,不暴露可发送的connection。
* 应用据此选择数据源、构造数据头;IOA、分组成员及遍历状态均由应用维护。
* 引擎不登记或冻结IOA列表;总召由应用逐批取当前值,计数量读取由应用固定本轮冻结快照。
* 冻结/复位命令在BEGIN执行应用动作,不进入NEED_DATA。 */
typedef struct {
uint64_t generation, receive_serial; /* 原TCP会话代次、接收I帧标识,供应用关联和诊断。 */
uint64_t station_id; /* 本次选中的注册编号,兼容裸CA模式为0;按编号查找避免同CA替换串站。 */
uint16_t common_address; /* 实际本站地址;广播65535解析为此地址,应用数据批次须使用同一CA。 */
uint8_t originator_address; /* 请求的源发地址OA,应答数据须原样保留。 */
uint8_t qualifier; /* 总召QOI=20..36;计数量RQT=1..5,应用维护分组点表。 */
bool is_test; /* 请求的TEST标志,数据批次须保持一致。 */
uint8_t max_objects_per_asdu; /* 1..127,实际另受249字节容量限制。 */
uint8_t freeze; /* 计数量FRZ:0读取,1冻结,2冻结并复位,3仅复位;总召恒为0。 */
uint8_t data_cause; /* 数据COT:总召等于QOI,计数量总请求37、分组38..41。 */
} IEC104_InterrogationRequest_t;
/* FINISHED通知应用清理本次游标及业务资源;终结原因不等于网络发送回执。
* COMPLETED表示结束帧被发送层接手,不表示写完或收到ACK;读取为ACT_TERM,动作命令为ACT_CON。 */
typedef enum {
IEC104_INTERROGATION_FINISH_NONE = 0, /* 未终结;BEGIN/NEED_DATA事件也使用此值。 */
IEC104_INTERROGATION_FINISH_COMPLETED, /* 读取的全部批次和ACT_TERM,或动作命令的ACT_CON已提交。 */
IEC104_INTERROGATION_FINISH_REJECTED, /* 应用拒绝;否定ACT_CON可能仍在排队。 */
IEC104_INTERROGATION_FINISH_CANCELLED, /* 应用调用本地Cancel放弃任务。 */
IEC104_INTERROGATION_FINISH_STOPPED, /* 收到Slave的停用通知,结束本次数据传输。 */
IEC104_INTERROGATION_FINISH_DISCONNECTED, /* 原TCP会话断开。 */
IEC104_INTERROGATION_FINISH_CONNECTION_CHANGED, /* 连接代次或当前传输状态已不再适用于任务。 */
IEC104_INTERROGATION_FINISH_SOURCE_ERROR, /* 应用通过Fail_Request报告数据源准备/取数失败。 */
IEC104_INTERROGATION_FINISH_SEND_ERROR, /* 提交应答失败且不是可等待的发送容量不足。 */
IEC104_INTERROGATION_FINISH_OVERLOAD, /* 兼容保留;满槽现在拒绝/丢弃新请求,不终结已有任务。 */
IEC104_INTERROGATION_FINISH_INVALID_REQUEST, /* 保留枚举值兼容;畸形新请求不再终结已有总召。 */
IEC104_INTERROGATION_FINISH_SERVICE_ERROR, /* 服务查询、内部状态或构造应答失败。 */
IEC104_INTERROGATION_FINISH_DEACTIVATED, /* 主站COT=8撤销;COT=9可能仍待发送。 */
IEC104_INTERROGATION_FINISH_BEGIN_TIMEOUT, /* BEGIN入队后未在期限内得到应用决定。 */
IEC104_INTERROGATION_FINISH_DATA_TIMEOUT, /* NEED_DATA入队后未在期限内得到应用应答。 */
IEC104_INTERROGATION_FINISH_TOTAL_TIMEOUT /* BEGIN生成至ACT_TERM提交超过执行整体期限。 */
} IEC104_InterrogationFinishReason_t;
typedef enum {
IEC104_INTERROGATION_BEGIN = 1, /* 检查数据源并接受/拒绝;取数游标可延至首个NEED_DATA建立。 */
IEC104_INTERROGATION_NEED_DATA, /* 应用选择本批IOA并读取当前值/品质;暂未就绪时保存事件。 */
IEC104_INTERROGATION_FINISHED /* 清理游标及业务资源,无需应答。 */
} IEC104_InterrogationEventType_t;
/* 纯值事件,无借用指针和自引用,可赋值、排入应用队列、保存到后续循环。
* 字段只读,应答时原样传回;实例/请求/批次标识用于拒绝迟到和重复应答。
* 每个已取出的BEGIN恰好配对一次FINISHED,取消也不丢失终结通知。
* BEGIN尚未取出便取消时移除BEGIN,不产生FINISHED(应用尚未建立资源)。
* 取消移除队列中的NEED_DATA;已取出的旧事件仍可读取,应答返回STALE。 */
typedef struct {
IEC104_InterrogationEventType_t type; /* 决定调用Reply_Begin、提交数据或只清理资源。 */
uint64_t instance_id, request_id; /* 实例及请求身份;必须与事件其他字段一起原样传回。 */
IEC104_InterrogationRequest_t request; /* 原激活请求的元数据,FINISHED仍保留此副本。 */
size_t batch_index, objects_submitted; /* 已被发送层接手的批次/对象数;首个NEED_DATA的批次号为0。 */
IEC104_InterrogationFinishReason_t reason; /* 仅FINISHED有意义。 */
} IEC104_InterrogationEvent_t;
/* 多站广播的调用方存储:每个目标站一项,不保存点值、ASDU或独立发送任务。
* config借用整个数组至Destroy,期间地址稳定、不得读写或与其他实例重叠。
* 模块初始化/清理内部字段,不要求调用方逐项初始化。 */
typedef struct {
IEC104_Station_t *_station; /* 本轮持有的原节点引用,直到整轮终结事件读完才释放。 */
uint64_t _request_id, _started_ms; /* 每站独立的请求身份和BEGIN时刻,切换当前站不丢失。 */
size_t _batch_index, _objects_submitted; /* 已提交进度,不是应用的IOA遍历游标。 */
uint8_t _state, _flags, _reason; /* 协议阶段、事件交付/撤销标志、终结原因,仅库内部使用。 */
} IEC104_InterrogationStationState_t;
/* Create复制此配置;创建后修改调用方对象不会改变已有实例,指向的广播数组仍为借用。
* 接受/取数期限从事件入队开始,包含应用尚未NextEvent读取它的时间。 */
typedef struct {
uint16_t common_address; /* station为NULL时的兼容站地址1..65534;绑定站点时从节点取得CA并忽略此值。 */
uint8_t max_objects_per_asdu; /* 每批1..127个对象,配置无业务函数指针。 */
bool use_station_registry; /* true按请求CA查共用站点表,广播分三阶段;station须NULL,common_address忽略。 */
uint32_t begin_timeout_ms; /* BEGIN入队至Reply_Begin/Fail_Request,默认15000ms。 */
uint32_t data_timeout_ms; /* NEED_DATA至首次有效批次/Complete/Fail,默认15000ms;发送WAIT后的重试不计。 */
uint32_t total_timeout_ms; /* 读取:每站BEGIN至ACT_TERM提交;动作:BEGIN至应用接受。默认0禁用。 */
/* 上述期限是业务策略,独立于104链路t0..t3;每项0表示禁用该项。
* BEGIN尚未生成时不计业务期限;START/CONFIRM超时转为否定ACT_CON并保留连接。
* 动作命令接受后的CONFIRM不再受业务期限约束,避免执行成功后被改发否定;连接期限仍生效。
* 肯定ACT_CON被发送层接手后,DATA/TERMINATE超时关闭原连接,不发送成功ACT_TERM。
* 同一执行任务的总期限与阶段期限同时到点时优先报告总超时。 */
IEC104_Station_t *station; /* 兼容固定站绑定:Create持有至Destroy;删除后不接新请求,已接受任务可完成。 */
IEC104_InterrogationStationState_t *broadcast_states; /* 调用方独占提供的状态数组,寿命覆盖实例。 */
size_t broadcast_capacity; /* 数组项数,即单轮多站广播能接纳的目标数,不是注册站数上限。 */
/* 默认NULL/0。广播涉及多个站时,容量须覆盖请求时的全部注册站,否则整轮否定确认。
* 单站/定向总召不需要数组。容量由应用决定,不限制注册站数;数组含已确认目标及终结记录。 */
} IEC104_InterrogationConfig_t;
/* 输入Slave通知的处理结果;其他类型I帧返回IGNORED,交后续业务处理。 */
typedef enum {
IEC104_INTERROGATION_EVENT_ERROR = -1, /* 参数、复制、关闭连接等处理失败。 */
IEC104_INTERROGATION_EVENT_IGNORED = 0, /* 本模块未接手,可转交其他业务处理器。 */
IEC104_INTERROGATION_EVENT_HANDLED = 1 /* 已处理,含畸形/满槽丢弃;不保证应用接受或已发送响应。 */
} IEC104_InterrogationEventResult_t;
typedef enum {
IEC104_INTERROGATION_NEXT_ERROR = -1, /* 非法句柄或NULL输出。 */
IEC104_INTERROGATION_NEXT_EMPTY = 0, /* 当前无业务事件,不代表总召已经结束。 */
IEC104_INTERROGATION_NEXT_READY = 1 /* 已复制并移除最早事件,输出可独立保存。 */
} IEC104_InterrogationNextResult_t;
/* 显式比较,不能按真假判断。
* OK:交互已消费;Submit_Batch已交发送层并固定顺序,其余应答由Process推进;不表示写完/ACK。
* WAIT:先处理Slave通知并推进网络;Submit_Batch还可能因发送背压WAIT,不缓存本次原文。
* 保留同一事件,批次游标不动,下次重读当前值组包。首次有效批次的发送WAIT结束本批取数计时。
* STALE:实例/请求/批次/类型不匹配、未取出、已应答、已取消或已超时;不要重试旧事件。
* ERROR:参数/批次/服务查询错误,不消费交互,可修正再提交。
* NEED_DATA阶段Fail_Request例外:即使关闭连接失败,仍取消并交付FINISHED,不能重试。 */
typedef enum {
IEC104_INTERROGATION_REPLY_STALE = -2,
IEC104_INTERROGATION_REPLY_ERROR = -1,
IEC104_INTERROGATION_REPLY_WAIT = 0,
IEC104_INTERROGATION_REPLY_OK = 1
} IEC104_InterrogationReplyResult_t;
/* 优先描述唯一未终结总召的诊断阶段;仅有应答时REPLY,无任务时IDLE。
* 阶段由模块推进,应用通过事件交互,不直接修改。 */
typedef enum {
IEC104_INTERROGATION_IDLE, /* 没有协议任务。 */
IEC104_INTERROGATION_REPLY, /* 等待提交单帧确认(含撤销确认)或错误应答。 */
IEC104_INTERROGATION_START, /* 等事件空位生成BEGIN,或等待应用接受/拒绝;两者均占用总召资格。 */
IEC104_INTERROGATION_CONFIRM, /* 应用已接受,等待提交肯定ACT_CON。 */
IEC104_INTERROGATION_DATA, /* 生成NEED_DATA,等待应用取值并尝试直接提交。 */
IEC104_INTERROGATION_TERMINATE, /* 应用声明数据结束,等待提交ACT_TERM。 */
IEC104_INTERROGATION_FINISHING /* 多站广播网络任务已结束,等NextEvent读完各站FINISHED后归还状态区。 */
} IEC104_InterrogationPhase_t;
/* Get_Status返回的独立副本;计数自Create起累计,Cancel和重连不清零。
* active/waiting反映最近已处理的通知/推进结果;events_pending及need_process在查询时计算。 */
typedef struct {
uint64_t generation; /* 已消费的连接代次,断线后0。 */
bool active; /* 已消费ACTIVATED且未停用,不是socket实时状态。 */
bool gi_pending; /* 总召网络流程尚未终结;FINISHING虽为false,读完终结事件前仍拒绝新激活。 */
bool waiting; /* 存在发送、应用或事件空位等待;总召等应用时仍可推进单帧应答。 */
bool application_waiting; /* 等待应用首次有效应答,包含事件尚未取出;发送背压另见data_send_waiting。 */
bool data_send_waiting; /* 有效批次提交曾遇发送WAIT;应用仍持有NEED_DATA,网络推进后重取再试。 */
bool events_pending; /* 当前Slave FIFO未空,须先处理网络通知。 */
bool need_process; /* 有本地工作/到期/会话失效待处理,应立即Process;未读Slave通知优先。 */
bool timer_active; /* 存在启用的业务期限;为false时timeout_remaining_ms无意义。 */
uint32_t timeout_remaining_ms; /* 最近期限距当前单调时钟的毫秒数;0表示应立即Process。 */
unsigned pending_requests, pending_events; /* 任务数含FINISHING;事件数含状态区中待交付的FINISHED,不含预留。 */
IEC104_InterrogationPhase_t phase; /* 当前站阶段;收尾为FINISHING,仅有应答为REPLY,无任务为IDLE。 */
size_t batch_index, objects_submitted; /* 活动总召已提交的批次/对象数;仅有应答时取最早应答保留的进度。 */
unsigned long submitted, gi_submitted; /* 接手ASDU数、完成协议提交的召唤数;动作命令以ACT_CON计。 */
unsigned long waits, cancelled, rejected, overloads;
/* waits统计发送层返回WAIT;cancelled统计取消的协议任务(含单帧应答);
* rejected统计校验拒绝(含无法应答的畸形请求)/总召忙/应用/确认前失败/容量拒绝;
* overloads含任务槽满或广播状态区不足。 */
unsigned long negative_submitted, dropped_requests; /* 已提交否定应答数、无法保存或提交而丢弃的新请求数。 */
unsigned long deactivated, timeouts; /* 成功匹配的主站撤销、执行阶段业务超时次数。 */
IEC104_InterrogationFinishReason_t last_finish_reason; /* 最近合法总召的终结原因,含BEGIN尚未交付的任务。 */
} IEC104_InterrogationStatus_t;
/* 初始化调用方的可写配置:station=NULL、兼容CA=1,broadcast_states=NULL、broadcast_capacity=0,每批最多127个对象,
* 接受/取数期限各15000ms,执行整体期限为0(禁用);NULL无操作。 */
void IEC104_Interrogation_Config_Default(IEC104_InterrogationConfig_t *config);
/* 复制配置,借用Slave;同一Slave的同一种类只能绑定一个实例,在消费Slave通知前创建。
* slave须保持有效直到本实例Destroy;config在返回后可释放或复用。
* station非NULL时校验其属于本Slave并占用节点,本站CA只取节点值;创建失败不泄漏引用。
* use_station_registry开启时按CA选站;广播共用一个任务,依次完成全部确认、各站数据、全部终止。
* 各站独立BEGIN/FINISHED和request_id;多目标广播须有足够broadcast_states,容量不足整轮否定。
* 接收时持有目标节点引用;尚未选入BEGIN便删除的站跳过,已经选中的站持原引用完成。
* 新增/替代节点不加入本轮;已确认站即使尚未取数或被删除,也必须完成或明确终结。
* BEGIN后需跨循环保留context的应用须按station_id查节点并Acquire,FINISHED清理后Release。
* 兼容模式use_station_registry=false保留单CA或固定station行为。
* NULL:参数非法、重复绑定、状态区重叠、池满或实例编号耗尽;无网络操作,无malloc。
* 编译.c可覆盖IEC104_INTERROGATION_CAPACITY(默认为TCP实例容量的两倍)、
* IEC104_INTERROGATION_TASK_CAPACITY(默认4)、IEC104_INTERROGATION_EVENT_CAPACITY
* (默认4,最小2)。任务池容纳至多一个总召及短应答,不是多个总召的等待队列。
* 单目标流程在FIFO预留FINISHED;多目标用每站状态区保留终结记录,NextEvent按空位交付。 */
IEC104_Interrogation_t *IEC104_Interrogation_Create(IEC104_Slave_t *slave,
const IEC104_InterrogationConfig_t *config);
/* 协议任务和业务事件均为空才释放槽,否则false并保持原状态。
* 先Cancel,再NextEvent读完FINISHED并清理应用资源,最后Destroy;成功后句柄失效。 */
bool IEC104_Interrogation_Destroy(IEC104_Interrogation_t *self);
/* 放弃未提交任务;保留已交付BEGIN的FINISHED(CANCELLED),移除未交付工作事件。
* 不撤回已接手帧、不补发ACT_TERM,也不回滚已执行的冻结/复位;非法句柄无操作。 */
void IEC104_Interrogation_Cancel(IEC104_Interrogation_t *self);
/* 按FIFO接收本Slave的每个通知,不消费Slave FIFO,不保存调用方指针。
* 下列QOI和撤销约定针对总召;计数量的RQT/FRZ规则见CounterInterrogation.h。
* 同时使用两个实例时,连接/启停通知交给两边;I帧仅在当前实例IGNORED后转交下一个。
* 总召须SQ=0、一个对象、COT=6或8、P/N=0、CA为本站或65535、IOA=0、QOI=20..36。
* 广播常量为IEC104_CA_BROADCAST;应用事件、确认、数据、否定应答及终止均使用实际本站CA。
* 原输入事件不修改;每次选站设置应答CA,同一站发送及重试沿用该地址。
* 空闲时保存一个COT=6激活并进入START;从保存起至终结,拒绝所有后续激活,不区分QOI。
* 忙或QOI/P/N非法时回否定ACT_CON;保留已有请求的QOI/OA/TEST、工作事件及数据进度。
* 单帧应答在无未读Slave通知、原会话有效且无更早REPLY时尝试立即提交,未接手再保存。
* 多站广播应答先保存一个遍历任务,再由Process逐站提交;无槽时整体丢新请求并计数。
* 满槽时尝试否定确认;无法安全提交/保存则仅丢新请求并累计dropped_requests,不断链。
* 撤销COT=8不受忙拒绝限制,按连接代次、实际站CA、OA、TEST、QOI匹配当前总召;
* 定向撤销停止匹配站,包括已确认但尚未取数/等待终止的站;其他站继续。
* 尚未选入BEGIN的站没有可撤销的活动事务。广播撤销停止整轮,按各活动站CA确认。
* 已完成/已拒绝站不补发撤销确认;无注册站且无匹配事务时,广播请求回复未知CA。
* 为已交付BEGIN保留FINISHED(DEACTIVATED),按单帧应答规则提交肯定COT=9;
* 不匹配/非法QOI或P/N回否定COT=9。
* 撤销无需应用再次批准;应用收到FINISHED后停止采样并释放本次资源。
* 匹配撤销复用原任务槽,并将确认排到单帧应答队尾;满池也不需要额外槽。
* 一组撤销确认尚未提交完时,重叠的新撤销按未匹配拒绝,不覆盖已有确认。
* COT/CA/IOA错误回45/46/47;撤销不撤回发送层已接手的帧,不补发ACT_TERM。
* 尚未生成/交付BEGIN的撤销不产生FINISHED;已有BEGIN交付才通知应用清理。
* 先安全读取Type,非100返回IGNORED;公共视图不可用也返回IGNORED,由公共入口处理。
* Type100仅一个对象且IOA/QOI完整时,SQ=1或多余尾字节回否定7/9(COT/CA/IOA错误优先45/46/47)。
* 此应答规范为10字节、VSQ=1,保留OA/TEST/IOA/QOI;绝不据规范化副本执行激活或撤销。
* 零对象/多对象等无法可靠对应请求的布局错误计入rejected并返回HANDLED,不生成应答。
* 上述请求错误不取消已有总召、不刷新其期限;基础帧错误仍由Receiver/连接层处理。
* STOPDT/断线取消总召及待发短应答并保留终结事件;不替其他业务回答UNKNOWN_TYPE。 */
IEC104_InterrogationEventResult_t IEC104_Interrogation_Handle_Event(
IEC104_Interrogation_t *self, const IEC104_SlaveEvent_t *event);
/* 自动推进当前就绪任务,不等待应用或网络;调用方不需要指定处理步数。
* Slave FIFO未空仅设置events_pending。顺序:START -> BEGIN -> 应用接受 -> ACT_CON ->
* NEED_DATA/提交批次(可重复)-> 应用Complete_Data -> ACT_TERM -> FINISHED。
* 动作命令例外:ACT_CON被发送层接手后直接FINISHED,不生成NEED_DATA或ACT_TERM。
* 多目标广播先完成所有站的BEGIN/ACT_CON,再逐站NEED_DATA,全部数据结束后才逐站ACT_TERM。
* 工作事件只交付一次;应用暂未就绪可保存事件,后续Process不会重复请求。
* 单帧应答保持FIFO,可在总召等待应用/业务事件空位时提交;双方可推进时先应答再总召轮转,
* 继续处理当前就绪任务,直至空闲、所有任务等待应用/事件空位,或发送返回WAIT。
* 每个站的REPLY成功后继续广播或释放任务;不保存后续主站新发来的总召激活。
* 每轮最多推进2倍任务容量步,广播余下站点由need_process提示继续,避免大量站点独占事件循环。
* 应答可穿插总召各批次,本次总召自身ACT_CON/数据/ACT_TERM顺序不变。
* 确认、终止和短应答沿原connection走HIGH,WAIT保留请求;DATA只生成NEED_DATA,
* 由应用Submit_Batch直接提交,OK才增加批次/对象计数,WAIT须重新取值后重试。
* WAIT让出本轮,下轮优先检查单帧应答;已被发送层接手的帧不被后到应答越过。
* 发送ERROR时复核原连接;正常STOP拒绝且通知未读时仅置events_pending并让出,由通知终结为STOPPED。
* 不因此增加waits、重置期限或撤销已接手帧;其他ERROR及FATAL仍按SEND_ERROR处理。
* 使用平台单调时钟检查期限,先处理Slave通知;START/CONFIRM超时转为否定REPLY并继续调度,
* 肯定ACT_CON提交后的DATA/TERMINATE超时关闭原连接;FINISHED保留具体超时原因。
* 执行总期限默认禁用,启用后按每站BEGIN独立开始,含等待其他站完成的时间。
* 已确认站总期限到点即关闭原连接;此前等待事件空位不计期限,应及时读FINISHED。
* 网络推进并读空Slave通知后须Process重试,即使need_process为false;发送WAIT不自行触发空转。
* 数据WAIT还须重试应用持有的NEED_DATA;本函数不会代为重读或重发数据。
* 本地应答/事件消费后重查Get_Status,need_process为true不得休眠;并用剩余期限限制等待时长。
* true本轮正常(可等待/取消/超时);false参数、组包、关闭连接或服务查询失败。 */
bool IEC104_Interrogation_Process(IEC104_Interrogation_t *self);
/* 取最早业务事件;event须为非NULL输出,只有READY写入,EMPTY/ERROR保持输出不变。
* READY后工作事件才允许应答;FINISHED仅用于应用清理,不调用应答接口。
* 多站终结记录超过FIFO容量时,本函数按需补入,连续NextEvent即可读完,无需Process。
* 最后一条FINISHED出队后归还广播状态区和节点引用;应用持有的节点引用仍须自行Release。
* 事件是可保存的纯值副本,本函数无网络操作,也不自动执行应用代码。 */
IEC104_InterrogationNextResult_t IEC104_Interrogation_NextEvent(
IEC104_Interrogation_t *self, IEC104_InterrogationEvent_t *event);
/* 应答已取出的BEGIN。true允许提交ACT_CON;false立即FINISHED(REJECTED),
* 并排队否定ACT_CON;不支持的分组可在这里拒绝。应用按instance_id/request_id管理遍历状态。
* 接受前检查数据源及业务资源;无需登记完整IOA列表或预先采样全部数据。
* event须原样传回;OK表示接受/拒绝决定已消费,实际ACT_CON由后续Process提交。
* 所有应答接口也检查期限,不能通过迟到应答绕过超时;Slave通知未读空时仍优先返回WAIT。
* 计数量FRZ!=0建议使用CounterInterrogation_Execute_Begin,在校验通过后才执行副作用。
* 不要在本函数之前无条件执行冻结/复位:WAIT会重试,STALE也不能撤销已经发生的动作。
* 动作命令接受后停止业务期限,保留确认等待;TEST动作始终拒绝。 */
IEC104_InterrogationReplyResult_t IEC104_Interrogation_Reply_Begin(
IEC104_Interrogation_t *self, const IEC104_InterrogationEvent_t *event, bool accept);
/* 应答已取出的NEED_DATA,验证非空ASDU后当场尝试不排队提交。
* OK表示已复制进发送缓冲并固定发送顺序,当场累计批次/对象数;输入缓冲及参数可立即复用。
* WAIT不接手、不推进游标;应用保存同一事件,网络推进后重新组包,不保留旧编码等待重发。
* 总召可重取当前值;计数量必须保持本轮冻结版本,值、序号、品质及可选时标一起固定。
* 首次有效批次发生发送WAIT后停止本批取数计时;下一NEED_DATA重新计时,显式整体期限仍有效。
* 参数须2/2/3,COT=request.data_cause、P/N=0、CA=本事件目标站地址、OA/TEST与事件相同。
* 广播请求的数据CA也不能使用65535;对象数不超配置。
* 总召接受Type 1/3/5/7/9/11/13/20/21,SQ=0/1均可;计数量读取接受Type 15(SQ=0/1)、37(SQ=0)。
* IOA及分组归属由调用方决定;库校验编码布局,不规定点表或强制固定IOA集合。
* 总召建议每次NEED_DATA读取当前值/品质,整轮不保证同一采样时刻;计数量由应用保证快照一致。
* 点值更新及突发发布、总召取值及本调用须由同一发布流程串行协调,不能迟交旧事件。
* HIGH/NORMAL有待发数据时总召退让;持续事件拥塞可能延后总召。OK后不再重新取值或重复提交。
* 发送ERROR若确认为原连接正常STOP拒绝且有未读通知,返回WAIT并保留事件,先处理DEACTIVATED。
* 此等待不设置data_send_waiting、不停止取数计时;通知处理后旧事件STALE,FINISHED为STOPPED。
* 其他发送ERROR/FATAL取消请求并返回STALE;FATAL可能已发出字节,不允许重试旧批次。
* 非法批次ERROR,保留NEED_DATA供修正,不断线;无法继续则Fail_Request。
* 应用使用Asdu_Create/InformationObject_Create/Add自行构造业务ASDU。 */
IEC104_InterrogationReplyResult_t IEC104_Interrogation_Submit_Batch(
IEC104_Interrogation_t *self, const IEC104_InterrogationEvent_t *event,
const IEC60870_Asdu_t *asdu);
/* 应答已取出的NEED_DATA,声明数据耗尽;不以空ASDU作为结束标记。
* OK后本请求不再取数,可归还其取数游标;多目标广播继续下一站数据,全部结束后才发终止。
* Process提交本站ACT_TERM成功后才交付FINISHED(COMPLETED)。 */
IEC104_InterrogationReplyResult_t IEC104_Interrogation_Complete_Data(
IEC104_Interrogation_t *self, const IEC104_InterrogationEvent_t *event);
/* 应答已取出的BEGIN/NEED_DATA,报告数据源失败,两者均交付FINISHED(SOURCE_ERROR)。
* BEGIN阶段复用原槽保存否定ACT_CON,保留连接和其他任务;OK不表示否定确认已发送,须继续Process。
* NEED_DATA阶段肯定ACT_CON已经提交:关闭原连接并取消任务,不发送成功终止,不影响后来新代次。
* 检查通过后即终结交互;即使NEED_DATA阶段关闭失败返回ERROR,任务仍已取消,不能重试。 */
IEC104_InterrogationReplyResult_t IEC104_Interrogation_Fail_Request(
IEC104_Interrogation_t *self, const IEC104_InterrogationEvent_t *event);
/* 取得独立状态副本,实时查询Slave通知、可推进任务和最近期限;不消费事件或触发I/O/超时。
* need_process表示无需等新网络事件就应尝试推进,不保证发送接手,也不是waiting的反值。
* 生成工作事件有空位、应答接手后可提交下一帧、业务期限到期时置位;Slave通知未读空时不置位。
* 当前帧提交WAIT后停止本地续跑,网络推进后仍须调用Process重试;不能仅凭本标志决定是否处理网络进展。
* data_send_waiting时应用仍须在网络推进后重取并重试保留的NEED_DATA,不能等新事件或need_process置位。
* pending_events非零先消费业务事件;释放空位或完成应答后须重查,不能沿用旧状态休眠。
* timer_active时,调用方等待时长不得超过timeout_remaining_ms;false时不限制等待。
* 返回false为非法句柄/NULL,输出保持不变。 */
bool IEC104_Interrogation_Get_Status(const IEC104_Interrogation_t *self,
IEC104_InterrogationStatus_t *status);
#ifdef __cplusplus
}
#endif
#endif /* IEC104_INTERROGATION_H */