Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
armanruet opened this issue Sep 3, 2024 · 2 comments
Open

Comments

@armanruet
Copy link

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?

@stefandreyer
Copy link
Owner

Hi,

please do call the publisher each cycle.

Then send of Publish reacts on rising edge, so for each send try this have to go true and then back false. For checking if send is done, please use the output done: set send to true --> wait for done --> send to false call the publish at least one time and then set send to true again...

any more questions?

BR Stefan

@armanruet
Copy link
Author

Is it possible to give an example!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants