Files
STM32F4-Base/IEC60870-Slave/.build/command-comments/IEC104_Command.h.before
T
STF cd42b4d61d
CI / L0 静态门禁 (pre-commit) (push) Failing after 2m51s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 18s
添加遥控业务代码
2026-10-30 20:03:19 -07:00

203 lines
10 KiB
Plaintext
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.
/*
* IEC104遥控:单命令45、双命令46,COT=6激活、COT=8撤销。
* 每个Slave至多一个实例,每实例至多一个未释放事务;其他业务仍独立推进。
* 静态存储、串行事件循环;仅Accept显式调用一次应用动作,不保存回调。
* 返回信息由Submit_Return_Info沿原连接提交,确认/返回信息/终止保持顺序。
*/
#ifndef IEC104_COMMAND_H
#define IEC104_COMMAND_H
#include "IEC104_Slave.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct IEC104_Command IEC104_Command_t;
/* 供无副作用的类型常量使用;45..51映射bit0..6,58..64映射bit7..13。
* 范围外为0,不作非法移位。第一版Create只接受45、46两位。 */
#define IEC104_COMMAND_TYPE_BIT(type) ((uint16_t)( \
((type) >= 45U && (type) <= 51U) ? (1U << ((type) - 45U)) : \
(((type) >= 58U && (type) <= 64U) ? (1U << ((type) - 51U)) : 0U)))
/* 期限以Net单调时钟计算,等于边界即到期;0仅禁用时长限制,等待阶段遇到时钟倒退仍终结。 */
typedef struct {
uint16_t type_mask; /* 默认45|46,不能为空,不接受本版不支持的位。 */
uint16_t select_required_mask; /* 默认45|46,必须是type_mask子集;清除对应位允许直接执行。 */
uint32_t select_timeout_ms; /* 选择保持,默认30000,不得为0。 */
uint32_t decision_timeout_ms; /* 工作事件生成至Accept/Reject,默认15000;0禁用。 */
uint32_t execute_timeout_ms; /* 动作STARTED至Report_Result,默认60000;0禁用。 */
bool send_act_term; /* 成功后发ACT_TERM,默认true。 */
bool act_term_on_failure; /* 默认false;true且send_act_term时失败也发COT=10、P/N=0。 */
} IEC104_CommandConfig_t;
/* 纯值请求。state编码为单命令0/1、双命令1/2;具体操作含义由应用点表定义。
* accepted_ms为Handle_Event受理时刻,不是报文在网络上的实际到达时刻。 */
typedef struct {
uint64_t generation, receive_serial;
uint64_t station_id;
uint16_t common_address;
uint8_t originator_address, type_id;
uint32_t ioa;
bool is_select, selected;
uint8_t state, qualifier;
uint64_t accepted_ms;
} IEC104_CommandRequest_t;
typedef enum {
IEC104_COMMAND_SELECT = 1,
IEC104_COMMAND_EXECUTE,
IEC104_COMMAND_FINISHED
} IEC104_CommandEventType_t;
typedef enum {
IEC104_COMMAND_FINISH_NONE = 0,
IEC104_COMMAND_FINISH_COMPLETED,
IEC104_COMMAND_FINISH_EXECUTION_FAILED,
IEC104_COMMAND_FINISH_REJECTED,
IEC104_COMMAND_FINISH_ACTION_FAILED,
IEC104_COMMAND_FINISH_MISMATCH,
IEC104_COMMAND_FINISH_DEACTIVATED,
IEC104_COMMAND_FINISH_SELECT_TIMEOUT,
IEC104_COMMAND_FINISH_DECISION_TIMEOUT,
IEC104_COMMAND_FINISH_EXECUTE_TIMEOUT,
IEC104_COMMAND_FINISH_CANCELLED,
IEC104_COMMAND_FINISH_STOPPED,
IEC104_COMMAND_FINISH_DISCONNECTED,
IEC104_COMMAND_FINISH_CONNECTION_CHANGED,
IEC104_COMMAND_FINISH_SEND_ERROR,
IEC104_COMMAND_FINISH_SERVICE_ERROR
} IEC104_CommandFinishReason_t;
/* 事件是可保存的纯值,应答须原样传回;调用方不能用修改request改变实际执行内容。
* 任何工作事件曾被取走的事务,恰好交付一次FINISHED;后者无需应答。
* 应用跨循环持有站点/context或异步动作时,应在首个工作事件时自行Acquire,
* FINISHED清理且物理输出确已结束后Release,不能等读到FINISHED后才申请引用。 */
typedef struct {
IEC104_CommandEventType_t type;
uint64_t instance_id, transaction_id, event_serial;
IEC104_CommandRequest_t request;
IEC104_CommandFinishReason_t reason;
bool select_effect, execute_effect;
} IEC104_CommandEvent_t;
typedef enum {
IEC104_COMMAND_ACTION_NOT_STARTED = 0, /* 必须保证没有任何副作用。 */
IEC104_COMMAND_ACTION_STARTED, /* 选择生效或输出启动;输出结果另行报告。 */
IEC104_COMMAND_ACTION_FAILED /* 未报告启动成功,但可能已留下副作用。 */
} IEC104_CommandActionResult_t;
/* 须短时返回;request只在本次调用有效,不得保存指针、推进Slave或发布上报。
* 回调期间仅可Get_Status/Get_Transaction;其他修改入口拒绝重入。 */
typedef IEC104_CommandActionResult_t (*IEC104_CommandAction_t)(void *context,
const IEC104_CommandRequest_t *request);
typedef enum {
IEC104_COMMAND_RESULT_SUCCEEDED = 1,
IEC104_COMMAND_RESULT_FAILED
} IEC104_CommandResult_t;
typedef enum {
IEC104_COMMAND_REJECT_NEGATIVE = 1,
IEC104_COMMAND_REJECT_UNKNOWN_IOA
} IEC104_CommandRejectCause_t;
typedef enum {
IEC104_COMMAND_EVENT_ERROR = -1,
IEC104_COMMAND_EVENT_IGNORED = 0,
IEC104_COMMAND_EVENT_HANDLED = 1
} IEC104_CommandEventResult_t;
typedef enum {
IEC104_COMMAND_NEXT_ERROR = -1,
IEC104_COMMAND_NEXT_EMPTY = 0,
IEC104_COMMAND_NEXT_READY = 1
} IEC104_CommandNextResult_t;
typedef enum {
IEC104_COMMAND_REPLY_STALE = -2,
IEC104_COMMAND_REPLY_ERROR = -1,
IEC104_COMMAND_REPLY_WAIT = 0,
IEC104_COMMAND_REPLY_OK = 1
} IEC104_CommandReplyResult_t;
typedef enum {
IEC104_COMMAND_PHASE_SELECT_WAIT = 1,
IEC104_COMMAND_PHASE_SELECTED,
IEC104_COMMAND_PHASE_EXECUTE_WAIT,
IEC104_COMMAND_PHASE_EXECUTING,
IEC104_COMMAND_PHASE_ENDED
} IEC104_CommandPhase_t;
typedef struct {
bool active; /* 尚未ENDED;不是当前连接是否可操作的保证。 */
IEC104_CommandPhase_t phase;
bool confirm_submitted; /* 当前工作请求的确认已交给发送层,不表示写完或ACK。 */
bool result_reported, completed, term_submitted;
} IEC104_CommandTransactionInfo_t;
/* 累计计数从Create起维护;查询不改变阶段、不做超时转换。
* busy包括待消费FINISHED和未交接的事务应答,不包含独立短应答。
* need_process不因发送WAIT持续置true;每轮网络推进后仍须Process重试。 */
typedef struct {
uint64_t generation;
bool active, events_pending, need_process, timer_active;
bool busy;
uint32_t timeout_remaining_ms;
unsigned pending_replies, pending_events;
unsigned long accepted, selected, executed, completed, execution_failed, action_failed;
unsigned long submitted, negative_submitted, return_info_submitted, waits;
unsigned long rejected, app_rejected, busy_rejected, overloads, dropped_requests, cancelled;
unsigned long deactivated, mismatches, select_timeouts, decision_timeouts, execute_timeouts;
unsigned long clock_errors;
} IEC104_CommandStatus_t;
void IEC104_Command_Config_Default(IEC104_CommandConfig_t *config);
/* config按值复制,必须非NULL;slave寿命覆盖实例。创建早于消费Slave通知。
* 池容量IEC104_COMMAND_CAPACITY默认等于TCP服务容量;独立应答容量
* IEC104_COMMAND_REPLY_CAPACITY默认4。配置/归属非法、重复绑定或池耗尽返回NULL。 */
IEC104_Command_t *IEC104_Command_Create(IEC104_Slave_t *slave, const IEC104_CommandConfig_t *config);
/* 事务槽、未读事件和全部独立应答槽均空才成功;不隐式Cancel/Close。 */
bool IEC104_Command_Destroy(IEC104_Command_t *self);
/* 结束事务并保留欠应用的FINISHED;清空未提交应答,保持会话激活,不回滚动作。
* 回调中/无效句柄无操作。ENDED事务保持首次终结原因,不重复产生FINISHED。 */
void IEC104_Command_Cancel(IEC104_Command_t *self);
/* 按Slave FIFO分派全部连接/启停通知;通知消费不受后续WAIT_EVENTS阻挡。
* 仅45/46 I帧接手;非法请求可否定或丢新计数,HANDLED不表示已应答。 */
IEC104_CommandEventResult_t IEC104_Command_Handle_Event(IEC104_Command_t *self,
const IEC104_SlaveEvent_t *event);
/* 有界处理期限和全局FIFO队首;不调用应用。true包含等待或已终结,false为服务/参数错误。 */
bool IEC104_Command_Process(IEC104_Command_t *self);
/* READY才修改event。工作事件先检查会话/期限;已有FINISHED可在离线时读取。
* 最后FINISHED读取可能释放事务站点引用;应用自己的引用仍需自行归还。 */
IEC104_CommandNextResult_t IEC104_Command_NextEvent(IEC104_Command_t *self,
IEC104_CommandEvent_t *event);
/* OK仅表示工作事件已消费,动作最多执行一次,不表示动作成功或确认已交接。
* SELECT的action可为NULL,选择生效但select_effect=false;EXECUTE必须提供action。
* WAIT未消费,STALE不得重试,ERROR为参数/重入错误且未调用动作。 */
IEC104_CommandReplyResult_t IEC104_Command_Accept(IEC104_Command_t *self,
const IEC104_CommandEvent_t *event, IEC104_CommandAction_t action, void *context);
IEC104_CommandReplyResult_t IEC104_Command_Reject(IEC104_Command_t *self,
const IEC104_CommandEvent_t *event, IEC104_CommandRejectCause_t cause);
/* 以下三个仅接受启动成功的原EXECUTE事件。结果报告一次后冻结;重复报告ERROR。
* Report_Result可早于ACT_CON交接,OK即停止执行期限。 */
IEC104_CommandReplyResult_t IEC104_Command_Report_Result(IEC104_Command_t *self,
const IEC104_CommandEvent_t *event, IEC104_CommandResult_t result);
/* 监视类型1..21/30..40,COT=11或3,P/N=0,TEST/CA与命令一致;完整校验对象。
* 模块有更早待交应答、确认未交接、网络背压或未读通知时WAIT,不缓存ASDU、也不占排序位置。
* OK固定帧序,不可重交;Complete后仍待收尾时ERROR,事务已结束则STALE。
* 发送错误终结事务,不可重试旧ASDU。 */
IEC104_CommandReplyResult_t IEC104_Command_Submit_Return_Info(IEC104_Command_t *self,
const IEC104_CommandEvent_t *event, const IEC60870_Asdu_t *asdu);
/* 结果须已报告;OK立即关闭返回阶段、冻结终止策略,Process负责后续发送。
* 仍待收尾时重复调用ERROR,事务已结束则STALE;WAIT未消费。
* 失败配置发TERM时P/N=0表示流程结束,不能据此认定设备成功。 */
IEC104_CommandReplyResult_t IEC104_Command_Complete(IEC104_Command_t *self,
const IEC104_CommandEvent_t *event);
/* 可查询仍保留事务的任一已交付事件;ENDED返回active=false。
* 槽已回收/事件不属于事务时false且不改info,不保留历史事务。 */
bool IEC104_Command_Get_Transaction(const IEC104_Command_t *self,
const IEC104_CommandEvent_t *event, IEC104_CommandTransactionInfo_t *info);
bool IEC104_Command_Get_Status(const IEC104_Command_t *self, IEC104_CommandStatus_t *status);
#ifdef __cplusplus
}
#endif
#endif /* IEC104_COMMAND_H */