HSL2.0 - Communication between logic module instances
Content
1.
Introduction
2.
Example

## 1.Introduction

The HSL 2.0 framework offers the possibility that logic blocks can access instances of other blocks.
This enables the communication of logic module instances among each other.
In the framework there are two methods to get an instance:

- get_instance_by_id(instance_id)
- get_instance_from_module_by_id(module_context, instance_id)

Both methods return as result the logic module instance belonging to instance_id (or `None`if the instance_id is invalid). The difference between the two methods is that get_instance_by_id(instance_id) can only access instances from the same module context. The method get_instance_from_module_by_id(module_context, instance_id) also returns an instance from another module context if the corresponding module context is specified.
The instance_id is an ID for the respective instance of a module that is uniquely assigned by the framework at runtime of the HomeServer. It does not match the five-digit module ID (e.g. 19042). The instance_id (also called runtime ID) can be determined via the method _get_module_id() (of the BaseModule). The following example code would return the own instance (i.e. self):

`self.FRAMEWORK.get_instance_by_id(self._get_module_id())`

The runtime ID can easily be exchanged and made known between logic blocks via the wiring of inputs and outputs.

## 2.Example

The following example shows the communication between logic module instances. For this purpose 2 logic modules were designed. These 2 blocks are used to configure 3 loudspeakers (players) in 3 rooms within a household (office).
The demo modules can also be found in the example folder under "`\communication_between_instances`"
Attention
Most of the modules used here contain only dummy code and serve only as illustrative examples. Under no circumstances should they be used productively!

### 2.1.Overview of the configuration in the graphical logic editor

### 2.2.Description of the modules

#### 2.2.1.Household building block

This block contains the specific program code and centrally controls the communication with the (fictitious) SpeakerSystem API. A Household logically bundles all SpeakerSystem devices located in the office.
After initialisation of the logic, the block sends its runtime ID to output 1 and thus makes it known to the player blocks.

#### 2.2.2.Player Device

This component represents one player at a time (PLAY:1, PLAY:3, etc.). In this example, each player is located in a separate room in the office. Each player block (or each instance of the block) receives the runtime ID of the Household block via input 1. This allows it to access the methods of the Household block and does not have to communicate directly with the SpeakerSystem API.

### 2.3.Sequence of communication

In order to show the communication between the modules in detail, the following section refers to the respective places in the source code. For a better overview, each line of code is preceded by the corresponding line in the respective source code of the module. The source code of the Household module can be found in the file 10705_SpeakerSystem Household.py. The source code of the player module can be found in the file 10706_SpeakerSystem Player.py.

#### 2.3.1.After starting the HS

1. Household module determines its runtime ID:

   `20 module_id = self._get_module_id()`

2. Household block sends its runtime ID to the output:

   `21 self._set_output_value(self.PIN_O_SPEAKERSYSTEM_PLAYER, module_id)`

3. Player module retrieves the instance of the Household module with the help of the runtime ID (value) and remembers it:

   `25 self.household_instance = self.FRAMEWORK.get_instance_by_id(value)`

   (This happens once per instance of the player module. So three times in total)
4. Player module registers a callback method (self.on_trackinfo_event) with the Household module. This method is called by the Household module as soon as the currently played song is changed:

   `28 self.household_instance.register_for_trackinfo_update(self._get_input_value(self.PIN_I_DEVICE_ID), self.on_trackinfo_event)`

   (This happens once per instance of the player module. So three times in total)

#### 2.3.2.Player component at runtime

At runtime a value is received at input 3 of the player module

1. The player module calls the method do_play_or_pause(device_id) of the Household module:

   `33 self.household_instance.do_play_or_pause(self._get_input_value(self.PIN_I_DEVICE_ID))`

#### 2.3.3.Household module at runtime

At runtime the Household module receives a change of the currently played song

1. The Household module searches for the corresponding callback using the supplied client ID and executes it (if available):

   `55 if device_id in self.registered_devices.keys(): 56 self.registered_devices[device_id](args["info"])`