## FB_OUTPUT_BINARY_MQTT ![MQTT Discovery](https://img.shields.io/badge/MQTT%20Discovery-brightgreen) ### **General** Can be switched using pulses that are high for one clock cycle (for example from `FB_INPUT_PUSHBUTTON_MQTT`), maintains output state through powercycles. ### **Block diagram** INPUT(S) - TOGGLE: when high the output `OUT` gets toggled. input should one be high for one clockcycle. - PRIO_HIGH: when high the output `OUT` is set to high, has priority over the `TOGGLE` and `PRIO_LOW` input. - PRIO_LOW: when high the output `OUT` is set to low, has priority over the `TOGGLE` input. OUTPUT(S) - OUT: output to switch digital output on and off. Can be connected to a relay for example. METHOD(S) - InitMQTT: enables MQTT events on the FB, an overview of the parameters: - `MQTTPublishPrefix`: datatype *POINTER TO STRING*, pointer to the MQTT publish prefix that should be used for publishing any messages/events for this FB. Suffix is automatically set to FB name. - `MQTTSubscribePrefix`: datatype *POINTER TO STRING*, pointer to the MQTT subscribe prefix that should be used for publishing any messages/events to this FB. Suffix is automatically set to FB name. - `pMqttPublishQueue`: datatype *POINTER TO FB_MqttPublishQueue*, pointer to the MQTT queue to publish messages. - `pMqttCallbackCollector`: datatype *SD_MQTT.CallbackCollector*, pointer to the MQTT callback collector, required to register FB for subscriptions on a certain topic. - PublishReceived: callback method called by the callbackcollector when a message is received on the subscribed topic by the callbackcollector. ### **MQTT publish behavior** Requires method call `InitMQTT` to enable MQTT capabilities. | Event | Description | MQTT payload | QoS | Retain flag | Published on startup | |:-------------|:------------------|:------------------|:------------------|:--------------------------|:--------------------------| | **Output changes: OUT** | A change is detected on output `OUT`. | `TRUE/FALSE` | 2 | `TRUE` | yes MQTT publish topic is a concatenation of the publish prefix and the function block name. ### **MQTT subscribe behavior** Requires method call `InitMQTT` to enable MQTT capabilities. Commands are executed by the FB if the topic `MQTTSubscribeTopic` matches the MQTT topic and the payload exists in the table below. | Command | Description | expected payload | Additional notes | |:-------------|:------------------|:------------------|:------------------| | **Change output to high** | Request to change output to high. | `TRUE` | Command executed when `PRIO_HIGH` and `PRIO_LOW` inputs are low. | **Change output to low** | Request to change output to low. | `FALSE` | Command executed when `PRIO_HIGH` and `PRIO_LOW` inputs are low. MQTT subscription topic is a concatenation of the subscribe prefix variable and the function block name. ### **Code example** - variables initiation: ``` MQTTPubSwitchPrefix :STRING(100) := 'Devices/PLC/House/Out/DigitalOutputs/'; MQTTSubSwitchPrefix :STRING(100) := 'Devices/PLC/House/In/DigitalOutputs/'; FB_DO_SW_001 :FB_OUTPUT_BINARY_MQTT; ``` - Init MQTT method call (called once during startup): ``` FB_DO_SW_001.InitMQTT(MQTTPublishPrefix:= ADR(MQTTPubSwitchPrefix), (* pointer to string prefix for the MQTT publish topic *) MQTTSubscribePrefix:= ADR(MQTTSubSwitchPrefix), (* pointer to string prefix for the MQTT subscribe topic *) pMQTTPublishQueue := ADR(MQTTVariables.fbMQTTPublishQueue), (* pointer to MQTTPublishQueue to send a new MQTT event *) pMQTTCallbackCollector := ADR(MQTTVariables.collector_FB_OUTPUT_BINARY_MQTT) (* pointer to CallbackCollector to receive MQTT subscription events *) ); ``` The MQTT publish topic in this code example will be `Devices/PLC/House/Out/DigitalOutputs/FB_DO_SW_001` (MQTTPubSwitchPrefix variable + function block name). The subscription topic will be `Devices/PLC/House/In/DigitalOutputs/FB_DO_SW_001` (MQTTSubSwitchPrefix variable + function block name). - checking for events to switch the digital output (cyclic): ``` FB_DO_SW_001(OUT=> DO_001, (* couple the function block to the physical output *) PRIO_HIGH:= FALSE, (* brings the output high regardless of other input values *) PRIO_LOW:= FALSE (* brings the output low regardless of other input values. NOTE: Priohigh overrules Priolow input *) TOGGLE:= FB_DI_PB_009.SINGLE (* for toggling the output *) ); ``` - integration with `FB_INPUT_PUSHBUTTON_MQTT`: ``` FB_DO_SW_001(OUT=> DO_001, (* couple the function block to the physical output *) PRIO_HIGH:= FALSE, (* brings the output high regardless of other input values *) PRIO_LOW:= FALSE, (* brings the output low regardless of other input values. NOTE: Priohigh overrules Priolow input *) TOGGLE:= FB_DI_PB_001.SINGLE (* for toggling the output *) ); ``` - MQTT discovery (choose one): ``` (* switch entity *) FB_DO_SW_001.InitMqttDiscoveryAsSwitch( Name := 'switch 001', (* The name show in Home Assistant frond-end*) Device := ADR(PLC_DEVICE), (* The device show in Home Assistant *) ); (* light entity *) FB_DO_SW_001.InitMqttDiscoveryAsLight( Name := 'light 001', (* The name show in Home Assistant frond-end*) Device := ADR(PLC_DEVICE), (* The device show in Home Assistant *) ); (* siren entity *) FB_DO_SW_001.InitMqttDiscoveryAsSiren( Name := 'siren 001', (* The name show in Home Assistant frond-end*) Device := ADR(PLC_DEVICE), (* The device show in Home Assistant *) ); (* lock entity *) FB_DO_SW_001.InitMqttDiscoveryAsLock( Name := 'lock 001', (* The name show in Home Assistant frond-end*) Device := ADR(PLC_DEVICE), (* The device show in Home Assistant *) ); (* valve entity *) FB_DO_SW_001.InitMqttDiscoveryAsValve( Name := 'valve 001', (* The name show in Home Assistant frond-end*) Device := ADR(PLC_DEVICE), (* The device show in Home Assistant *) ); ``` By default a 'NO' (Normally Open) contact is assumed for MQTT discovery yet this can be inverted to a 'NC' (Normally Closed) contact by leveraging the 'Invert' parameter: ``` FB_DO_SW_001.InitMqttDiscoveryAsLock( Name := 'lock 001', (* The name show in Home Assistant frond-end*) Device := ADR(PLC_DEVICE), (* The device show in Home Assistant *) Invert := TRUE (* FALSE by default = NO, TRUE = NC *) ); ``` ### **Home Assistant YAML** If [MQTT discovery](../AdditionalFunctionality/MQTT_Discovery.md) is not working for you, you can use the YAML code below in your [MQTT lights](https://www.home-assistant.io/components/light.mqtt/) config: ```YAML mqtt: light: - name: "FB_DO_SW_001" state_topic: "Devices/PLC/House/Out/DigitalOutputs/FB_DO_SW_001" command_topic: "Devices/PLC/House/In/DigitalOutputs/FB_DO_SW_001" payload_on: "TRUE" payload_off: "FALSE" qos: 2 optimistic: false availability_topic: "Devices/PLC/House/availability" payload_available: "online" payload_not_available: "offline" ```