接口的嵌入式实现

1.3层级建立

建立FB_Machine_HW_LOG使用ITF_Machine_HW_LOG自己的接口;

复制代码
FB_Machine_HW_LOG:


FUNCTION_BLOCK FB_Machine_HW_LOG IMPLEMENTS ITF_Machine_HW_LOG
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
		fbLogger	:	ITF_LoggerToDevLogAdapter	;//建立内部接口

内部:fbLogger : ITF_LoggerToDevLogAdapter ;//建立内部链接接口;

2.2层级的建立

以3层级构建类推:

建立FB_LoggerToDevLogAdapter 使用ITF_LoggerToDevLogAdapter 自己的接口

复制代码
FUNCTION_BLOCK FB_LoggerToDevLogAdapter IMPLEMENTS ITF_LoggerToDevLogAdapter
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
	ipSink				:	ITF_DevLogSink					;// 设备层 Log 下沉,由应用赋值为 FB_DevLogRouter 等
	

......
......
......
......
......
......
......
......
......
......

程序块:

(* 默认注入内部 Router,若未通过 M_SetSink 注入外部 Sink *)
IF NOT bSinkInjected THEN
    ipSink := fbDevLogRouter;
    bSinkInjected := TRUE;
END_IF

内部:ipSink : ITF_DevLogSink ;//建立内部链接接口;

3.1层级的建立

建立FB_DevLogRouter 使用ITF_DevLogSink自己的接口

复制代码
FUNCTION_BLOCK FB_DevLogRouter IMPLEMENTS ITF_DevLogSink
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
	iRingCount			:	UDINT							;// 缓存条数
	sPathWithOpt		:	WSTRING(96)						;// 设备路径 + 可选治具/载具/料盘
	sLineAssembled		:	WSTRING(255)						;// 组装后的单行 log
	fbLogRingBuffer		:	FB_StringRingBuffer				;// 环形缓存
	aRRsLogBuffer		:	ARRAY[1..100] OF WSTRING(255)	;// 缓存存储
	iLatesDisplayNum: DINT;
	
	//===========================================================================//
	itfLogger						:	ITF_Logger							;//日志	

内部: itfLogger : ITF_Logger ;//日志

4.0层级的建立

具体的的实现:

5.最终程序的实现

在最外部程序实现:

复制代码
FUNCTION_BLOCK FB_StationFoldDispensing
VAR_INPUT
......
......
VAR_OUTPUT
	
END_VAR
VAR
...........
...........				
	fbLog										:	FB_Logger										;//设备日志
	fbAoiHwLogAdapter							:	FB_LoggerToDevLogAdapter						;//AOI 模组-设备层日志适配
	fbAoiHwLogRouter							:	FB_DevLogRouter									;//AOI 设备日志下沉到 FB_Logger
	fbMachineHwLog								:	FB_Machine_HW_LOG								;//AOI 模组-硬件监视日志入口
	
	
//=============================================CommFB================================================//
......
......							
END_VAR

......
......
......
			
fbLog()																								;
fbLog.M_SaveFile(
				sFileName						:= 'Logs'											, 
				sRootDirPath					:= 'C:\UserRecord\DispensingStation'				);
				
//Aoi 硬件日志:适配器 Sink 用工站 Router,Router.pLogger 接本站 fbLog(勿用 ADR,接口直接赋实例)																		;
fbAoiHwLogRouter.pLogger							:=	fbLog										;
fbAoiHwLogAdapter.pDevLogSink						:=	fbAoiHwLogRouter							;
fbMachineHwLog.Prop_LoggerToDevLogAdapter				:=	fbAoiHwLogAdapter							;
fbModuleAoi.pMachine_HW_LOG							:=	fbMachineHwLog								;

参考三步法:

1.提供者->2.注入点->3.接收端本地缓存->4.最终调用落点

1.提供者:fbLog()

2.注入点:

fbAoiHwLogRouter.pLogger := fbLog ;

fbAoiHwLogAdapter.pDevLogSink := fbAoiHwLogRouter ;

fbMachineHwLog.Prop_LoggerToDevLogAdapter := fbAoiHwLogAdapter ;

fbModuleAoi.pMachine_HW_LOG := fbMachineHwLog ;

每个里面必须由属性传输出去:依次向下传输:

第一次:0层级给1层级注入:

fbAoiHwLogRouter.pLogger := fbLog ;//FB_Logger-0层级

第二次:1层级给2层级注入:

fbAoiHwLogAdapter.pDevLogSink := fbAoiHwLogRouter ;//FB_DevLogRouter-1层级

第三次:2层级给3层级注入:

fbMachineHwLog.Prop_LoggerToDevLogAdapter := fbAoiHwLogAdapter;//FB_LoggerToDevLogAdapter-2层级

第四次:3层级给最外部注入:

fbModuleAoi.pMachine_HW_LOG := fbMachineHwLog ;//FB_Machine_HW_LOG-3层级

3.接收本地缓存

外部调用:

4.最终落脚点

安全处理:

1) IF ipSink <> 0 THEN ... 是 Adapter 侧的"Sink 是否已注入"

FB_LoggerToDevLogAdapter.M_SubmitDevLog 里:

IF ipSink <> 0 THEN

ipSink.M_WriteDevLog(stLog);

END_IF

  • ipSink 的来源:要么你通过属性 pDevLogSink.Set 注入(ipSink := pDevLogSink;),要么(原设计)FB 本体那段默认注入把它指向内部 Router。
  • 理解:即使你"通常都会 set 属性",代码仍然要防御式写法,避免某个站点/某个时刻没注入就直接调用接口导致崩。

2) IF itfLogger <> 0 THEN ... 是 Router 侧的"最终 Logger 是否已注入"

FB_DevLogRouter.M_WriteDevLog 里:

IF itfLogger <> 0 THEN

itfLogger.M_LoggerWrite(wsToMsg:= sLineAssembled);

END_IF

  • itfLogger 的来源:你在工站里做的 fbAoiHwLogRouter.pLogger := fbLog;(这是 Router 的 pLogger.Set,内部是 itfLogger := pLogger;)。
  • 理解:即使 Adapter 已经把 ipSink 指到 Router 了,如果 Router 没接到底层 fbLog,同样也不能写。

3) 为什么"set 了就一定非 0"仍然要写判断?

因为 PLC 扫描周期里赋值、调用可能被别人改顺序/改条件,或者某些模式下不注入(比如某站点不需要落盘日志)。这两个 <>0 判断就是"链路上每一段都允许缺省为空,但为空就不做事、不报错"。

一句话总结

  • 属性 set 是"你主动接线";
  • IF ipSink <> 0 / IF itfLogger <> 0 是"就算你没接线,也不要崩溃,只是这条日志不输出"。
相关推荐
eEKI DAND2 小时前
Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
java·spring boot·logback
-Da-2 小时前
【ai应用开发日记】通用未注入Bean AI提示词
java·数据库·人工智能·spring boot·sqlserver
黑马源码库miui520862 小时前
JAVA国际版同城上门服务上门送水桶装水配送源码同城上门配送系统源码支持Android+IOS+H5
android·java·ios
xdscode2 小时前
Spring AI 中的 Flux 与 SSE:流式输出完全解析
java·flux·sse·springai·stream流式输出
星梦清河2 小时前
Java并发编程
java·开发语言
SimonKing2 小时前
IntelliJ IDEA AI Assistant 携带OpenCode保姆级安装教程来了
java·后端·程序员
苏三说技术2 小时前
Redis中的10种高级用法,直接起飞!
后端
清汤饺子2 小时前
Spec Kit:让 AI 编程从 Vibe Coding 到 Spec First
前端·javascript·后端
XiYang-DING2 小时前
【Java SE】sealed关键字
java·开发语言·python