Broadcast - Krystian-L-Lis/Stage GitHub Wiki
#Guide #Broadcast
This module implements the Publisher-Subscriber pattern, allowing components to communicate via signals and receivers. Publishers emit events without needing to know which components receive them.
Warning: Code examples illustrate typical usage and may omit some syntactic details for clarity.
In line with PLC best practices, the framework avoids dynamic memory allocation. Instead, it uses pre-allocated arrays to store signal-receiver connections. If these limits are exceeded, the system will trigger a NewDebug
message.
-
Param.RECEIVER_CAP
: Max number of signal-receiver pairings. -
Param.SIGNAL_CAP
: Max number of signals.
Note: For instructions on modifying library parameters, refer to Beckhoff Infosys.
Warning: This framework uses 1-based indexing. Ensure all parameters and queries are set accordingly to avoid errors or unexpected behaviour.
Signals and receivers are declared within an Entity
scope, making them publicly accessible and simplifying the pairing process. A typical declaration might look like this:
_entity: EntityStart;
_someSignal: Signal;
_someReceiver: Receiver;
_entityEnd: EntityEnd;
Both Signal
and Receiver
include an internal Tag
function block used to attach contextual information to events. Since these components are browsable, the tag is often useful for dynamic identification of individual signals and receivers during runtime, so that others can discover them if needed.
By default, a Receiver
is a callable block that invokes its own Call
method when triggered, which supports an inheritance-style approach where you extend the Receiver
and override Call
. Alternatively, you can assign an external I_Callable
implementation to the Callable
property, allowing the default Receiver
provided by the framework to be used as-is.
VAR
_someCallable: SomeCallableFb;
END_VAR
_someReceiver: Receiver := (Callable := _someCallable);
Pairing is done using the Pair
method provided by the I_Signal
interface, which links a signal to a receiver so that the receiver is notified when the signal is emitted. The Unpair
method removes that link. Both methods return a Result
value, which can indicate failure if, for example, the pair already exists or the internal pairing table is full. A single shared table is used for all signal-receiver pairs to simplify composition and resource tracking.
IF IsOk(_someSignal.Pair(_someReceiver)) THEN
// Receiver paired
END_IF
IF IsOk(_someSignal.Unpair(_someReceiver)) THEN
// Receiver paired
END_IF
A signal can be paired with multiple receivers, and a receiver can listen to multiple signals, allowing for both one-to-many and many-to-many event communication across the system.
Signal emission is performed using the Emit method. By default, this sends the signal’s internal Tag
as the argument, allowing receivers to identify which signal triggered the call. For example, a simple emission looks like this:
_someSignal.Emit();
Alternatively, any function block implementing the I_Arg
interface can be passed to Emit
, allowing custom data to be sent with the signal. This enables communication of rich context or typed payloads at runtime:
VAR
boolArg: BoolArg(TRUE);
END_VAR
_someSignal.Emit(boolArg);
_someSignal.Emit(boolArg.OpSet(FALSE));
Inside the receiver’s Call
method, the I_Arg
input can be cast to a specific type as needed. For example, to extract a boolean value from a signal:
VAR_INPUT
iArg: I_Arg;
END_VAR
VAR
iBoolArg: I_BoolArg;
bBoolValue: BOOL;
END_VAR
IF IsOk(IArgToIBoolArg(iArg, iBoolArg)) THEN
bBoolValue := iBoolArg.Get;
END_IF
To prevent recursion and infinite loops, a signal cannot emit again while it is already in the process of emitting. If such a re-entrant call is attempted, such as when a receiver tries to re-emit the same signal, it will fail:
IF IsErr(_someSignal.Emit()) THEN
// Emission blocked because the signal is already active
END_IF
Finally, you can emit to a specific receiver without pairing using the EmitTo
method. This works even if the receiver is not currently paired with the signal:
_someSignal.Unpair(_someReceiver);
_someSignal.EmitTo(_someReceiver); // Receiver will still be called
< Previous | Home | Next >