Skip to content

Continuous publication on Broker after receiving a message from it #70

@armanruet

Description

@armanruet

Hi Stefan

As a beginner with Codesys and MQTT, I have found your repository extremely helpful in understanding and implementing MQTT communication in my PLC project. I have successfully set up some logic with my devices and controller, but I'm facing a challenge in making the system work continuously based on incoming MQTT messages.
My goal is to have the PLC execute a specific logic sequence whenever it receives a message on a predefined topic from the MQTT broker. This logic should then publish the corresponding steps continuously in a loop until a new message is received, triggering a different logic sequence.
Currently, I can only manage to run the system once and publish the results, but I want the PLC to execute the logic immediately after receiving a message from the broker and keep publishing the logic steps in a loop until a new message arrives. I followed the following Function blocks:

//Function Block

FUNCTION_BLOCK FirstPublish
//VAR
VAR
	publisher_1:MQTT.MQTTPublish;
	publisher_2:MQTT.MQTTPublish;
	publisher_3:MQTT.MQTTPublish;
	doPublish: BOOL:=True ;
	init: BOOL;
	//Sinit: BOOL;
	sendPayload_1:STRING :='PsTL: 1';
	sendPayload_2:STRING :='PsTL: 2';
	sendPayload_3:STRING :='PsTL: 3';
END_VAR


IF PLC_PRG.sPayload = 1 THEN
    init := TRUE;
    publisher_1.SetMqttInOut(MQTT_IN_OUT := PLC_PRG.MQTT_IN_OUT);
ELSIF PLC_PRG.sPayload = 2 THEN
    init := TRUE;
    publisher_2.SetMqttInOut(MQTT_IN_OUT := PLC_PRG.MQTT_IN_OUT);
ELSIF PLC_PRG.sPayload = 3 THEN
    init := TRUE;
    publisher_3.SetMqttInOut(MQTT_IN_OUT := PLC_PRG.MQTT_IN_OUT);
	init := FALSE;
END_IF;


publisher_1(
	Topic:= ADR('Test/PsTL_1'),  PayloadString:= ADR(sendPayload_1),  PublishAsString:= TRUE,  QoSIn:= MQTT.QoS.ExactlyOnce, 
	MRetain:= FALSE, send:= doPublish);

publisher_2(
	Topic:= ADR('Test/PsTL_2'), PayloadString:= ADR(sendPayload_2), PublishAsString:= TRUE, QoSIn:= MQTT.QoS.ExactlyOnce, 
                MRetain:= FALSE,  send:= doPublish);
	
publisher_3(
	Topic:= ADR('Test/PsTL_3'), PayloadString:= ADR(sendPayload_3), PublishAsString:= TRUE, QoSIn:= MQTT.QoS.ExactlyOnce, 
	MRetain:= FALSE, send:= doPublish);

FUNCTION_BLOCK FirstSubscription
//VAR
VAR
	collector:MQTT.CallbackCollector;
	SUB1:MQTT.MQTTSubscribe;
	init: BOOL;
	receiver:MQTT.ReceiveString;
	fPayload : INT ; 
END_VAR

IF NOT init THEN
	init := TRUE;
	SUB1.SetMqttInOut(MQTT_IN_OUT:= PLC_PRG.MQTT_IN_OUT);
	collector.put(instance:= receiver);
	receiver.initAsFindTopic(compString:= ADR('Test/PsTL_1'), returnHit:= TRUE);	
END_IF

fpayload := STRING_TO_INT(receiver.MQTTReceived);

SUB1(
	Subscribe:= TRUE,  Topic:= ADR('Test/PsTL_1'), QoSSubscribe:= MQTT.QoS.ExactlyOnce, ExpectingString:= TRUE, 
	Callback:= collector);

In PLC_PRG I did this logic for publishing

//After getting message from Broker
IF FirstSubscription.fPayload = 1 THEN
	lastTouchedSensor := 0; // Initialize last touched sensor
// Initialize values and colors at the start of the program
END_IF

IF In THEN
    IF lastTouchedSensor = 0 OR lastTouchedSensor = 1 THEN
        lastTouchedSensor := 1; // Update last touched sensor
	FirstPublish();
    END_IF
END_IF
	
IF In2 THEN
     IF lastTouchedSensor = 1 THEN
		FirstPublish();
    END_IF
END_IF

IF In3 THEN
     IF lastTouchedSensor = 2 THEN
		FirstPublish();
    END_IF
END_IF

Can you please help me in which way I can run this process continuously?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions