Hello and in this tutorial I will show you how to implement a MQTT Client to subscribe to the topics by TwinCAT TF6701.
Reference Link:
Function Blocks
Here the function blocks that are used will be explained.
FB_IotMqttClient.Subscribe
This method is used by the client to Subscribe a topic to the broker that it wants to receive.Multiple topics are supported also.
VAR_INPUT
Name | Type | Description |
sTopic | STRING | Topic of the MQTT message |
eQoS | TcIotMqttQos | Quality of Service |
Return value
Name | Type | Description |
Subscribe | BOOL | True=Call was successful. |
FB_IotMqttMessage
Its function block is used with the message queue(FB_IotMqttMessageQueue, i will explain it in the next session), and the MQTT incoming messages are collected by the message queue.
Binary Information or string are sent in here, the maximum size of an MQTT message in PLC, is dependent on the hardware and should be less than few MB.
We can adjust the max mqtt message size by changing the cMaxSizeOfMqttMessage parameter,and default=100kb.
Finally, UTF-8 format is used and it is a common type for MQTT just like JSON.
CompareTopic
A method to compare the topic received from Broker,Ture=Topic is identical .
VAR_INPUT
Name | Type | Description |
sTopic | STRING | Topic that would like to compare |
GetTopic
VAR_INPUT
Name | Type | Description |
pTopic | POINTER TO STRING | topic buffer |
nTopicSize | UINT | maximum size of topic buffer in bytes |
GetPayload
A method to get the message that received from the broker.
VAR_INPUT
Name | Type | Description |
pPayload | PVOID | The memory address for the buffer into which the payload is to becopied is specified here |
nPayloadSize | UDINT | The maximum available buffer size (in bytes) is specified here. |
bSetNullTermination | BOOL | If the payload type requires zero termination (string), this can beimplemented during the copy process |
FB_IotMqttMessageQueue
A Function Block offers a message queue for MQTT messages, which can be used with the block FB_IotMqttClient.It operates by FIFO – first in first out.
The max size of the MQTT message queue in default is 1000, and the by default the maximum size of a message is limited to 100 kB, the size of the MQTT message queue is limited to 1000 kB
Dequeue
The method returns the return value TRUE if the removal of an MQTT message from the queue was
successful. The number of MQTT messages currently in the queue (nQueuedMessages property) is reduced
by one through the removal of a message.
VAR_INPUT
Name | Type | Description |
fbMessage | REFERENCE TO FB_IotMqttMess | For the message itself the reference is transferred to an instance of type FB_IotMqttMessage |
nPayloadSize | UDINT | The maximum available buffer size (in bytes) is specified here. |
bSetNullTermination | BOOL | If the payload type requires zero termination (string), this can beimplemented during the copy process |
ResetQueue
all accumulated MQTT messages are deleted from the queue when this method is called.
Configration
Here is the configuration in this tutorial. The publisher is implemented by the python library, and the Subscriber is done by TF6701.Broker is built in Raspberry-pi3.
Setup a Broker
Some Useful Link while using Raspberry
Here is the tutorial to build a broker in the raspberry pi/ubuntu.
If the connection is refused:
Python MQTT Client Implementation
Code
Python Publicher
import paho.mqtt.client as mqtt import time def on_connect(client,userdata,flag,rc): print(‘Connected with result code ‘+str(rc)) client.subscribe(‘RoboDK/Station/s1/Lamp/Red’) def on_disconnect(client,userdata,rc): if rc !=0: print(‘Something Wrong..’) def on_publish(client,userdata,mid): print(‘publish: {0}’.format(mid)) BROCKER_URL=’192.168.1.50′ BROCKET_PORT=1883 client=mqtt.Client() client.on_connect=on_connect client.on_disconnect=on_disconnect client.on_publish=on_publish client.connect(BROCKER_URL,BROCKET_PORT,60) count=0 while count<1000: ret=client.publish(‘RoboDK/Station/s1/Lamp/Yellow’,str(count)) ret=client.publish(‘RoboDK/Station/s1/Lamp/Red’,str(count+200)) ret=client.publish(‘RoboDK/Station/s1/Lamp/Green’,str(count+100)) count=count+1 time.sleep(1) client.disconnect() |
TwinCAT
VAR
PROGRAM MAIN VAR MQTTClient:FB_IotMqttClient; payload:STRING(255); payload_r,payload_y,payload_g:STRING(20); fbMessageQueue : FB_IotMqttMessageQueue; fbMessage : FB_IotMqttMessage; sTopic :STRING; bSetNullTermination :BOOL; bScbscrible:BOOL; sTopicReceived:STRING(255); Value_r,Value_g,Value_y:DINT; END_VAR |
PROGRAM
MQTTClient.sHostName:=’192.168.1.50′; MQTTClient.nKeepAlive:=60; MQTTClient.ipMessageQueue:=fbMessageQueue; MQTTClient.Execute(bConnect:=TRUE); IF MQTTClient.bConnected THEN IF NOT bScbscrible THEN MQTTClient.Subscribe( sTopic:=sTopic ,eQoS:=0 ); bScbscrible:=TRUE; END_IF END_IF sTopic:=’RoboDK/Station/s1/#’; IF fbMessageQueue.nQueuedMessages > 0 THEN IF fbMessageQueue.Dequeue(fbMessage:=fbMessage) THEN fbMessage.GetTopic(pTopic:=ADR(sTopicReceived), nTopicSize:=SIZEOF(sTopicReceived)); IF fbMessage.CompareTopic(sTopic:=’RoboDK/Station/s1/Lamp/Red’) THEN payload_r:=’ ‘; fbMessage.GetPayload(pPayload:=ADR(payload_r), nPayloadSize:=SIZEOF(payload_r), bSetNullTermination:=FALSE); ELSIF fbMessage.CompareTopic(sTopic:=’RoboDK/Station/s1/Lamp/Yellow’) THEN payload_y:=’ ‘; fbMessage.GetPayload(pPayload:=ADR(payload_y), nPayloadSize:=SIZEOF(payload_y), bSetNullTermination:=FALSE); ELSIF fbMessage.CompareTopic(sTopic:=’RoboDK/Station/s1/Lamp/Green’) THEN payload_g:=’ ‘; fbMessage.GetPayload(pPayload:=ADR(payload_g), nPayloadSize:=SIZEOF(payload_g), bSetNullTermination:=FALSE); END_IF END_IF END_IF Value_r:=STRING_TO_DINT(payload_r); Value_g:=STRING_TO_DINT(payload_g); Value_y:=STRING_TO_DINT(payload_y); |
Result
Startup the Broker and run the publisher first.
And then we know the values inside TwinCAT are updated.
Source Code
Please download the source code from this link:
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT%20Project_MQTT_Client_Sub.zip