stefandreyer / CODESYS-MQTT

MQTT client library for CODESYS, supporting all QoS
MIT License
110 stars 25 forks source link

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

Open armanruet opened 3 weeks ago

armanruet commented 3 weeks ago

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 commented 1 week ago

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 commented 21 hours ago

Is it possible to give an example!!