Broadcast - Krystian-L-Lis/Stage GitHub Wiki

#Guide #Broadcast

Overview

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.

Memory Model

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.

Quick Start

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 >

⚠️ **GitHub.com Fallback** ⚠️