この記事ではTF6701 Iot Communication(MQTT) Functionを使用しMQTT Clientを実装しBrokerのTopicをSubscribe します。
Reference Link
Function Blocks
いつも通り、Tutorialで使われてるもののみ説明します。
FB_IotMqttClient.Subscribe
このMethodはBrokerにTopicをSubscribeし、複数のTopicでもSupportします。
VAR_INPUT
Name | Type | Description |
sTopic | STRING | SubscribeするTopic |
eQoS | TcIotMqttQos | Quality of Service |
Return value
Name | Type | Description |
Subscribe | BOOL | True=Callは成功. |
FB_IotMqttMessage
このFunction BlockはMQTT Messageのqueue FB(FB_IotMqttMessageQueue)のパラメータです。そしてMQTT BrokerからきたMessageは収集され貯まっています。
Binary Fomratや文字列は使用可能で、PLC単体の最大MQTT MessageはHardwareに左右されるが、基本は2,3MB以内に収まってください。
MQTT Messageの最大SizeはcMaxSizeOfMqttMessage という変数から調整できます。
最後に、MQTT のTopicなどは基本UTF-8 Formatです。
CompareTopic
Brokerから受信されたMessageのTopicと比較します。True=Topicは一致すること。
VAR_INPUT
Name | Type | Description |
sTopic | STRING | 比較するTopic |
GetTopic
VAR_INPUT
Name | Type | Description |
pTopic | POINTER TO STRING | topic buffer Pointer |
nTopicSize | UINT | topic buffer の最大Size (bytes) |
GetPayload
BrokerからもらったMessageのPaylaodを取るMethodです。
VAR_INPUT
Name | Type | Description |
pPayload | PVOID | Payloadの保存先のPointer |
nPayloadSize | UDINT | Payloadの保存先の最大Size(bytes) |
bSetNullTermination | BOOL | If the payload type requires zero termination (string), this can beimplemented during the copy process |
FB_IotMqttMessageQueue
こちらのFunction BlockでMQTT メッセージのQueueを実装し、基本的にはFIFO-つまりFirst in First outです。
MQTTメッセージ Queueは最大Default1000まで貯めることができます。Message最大Sizeは100kBで、そのかたまりは1000kbがMaxです。
(それらはパラメータで調整できます。)
Dequeue
True=MQTT MessageをQueryから取り出し成功の意味、つまり新しいメッセージがQuery内で貯まったりし>そのMessage取り出し成功の意味です。
1回TrueになるとQueueの貯まり数も当然1つ減ります。
VAR_INPUT
Name | Type | Description |
fbMessage | REFERENCE TO FB_IotMqttMess | FB_IotMqttMessageのInstanceそのまま |
nPayloadSize | UDINT | buffer size (bytes) の最大Size |
bSetNullTermination | BOOL | If the payload type requires zero termination (string), this can beimplemented during the copy process |
ResetQueue
Queueで貯まったMQTT Messageを削除することです。
Configration
こちらが今回の構成になります。MQTT PublihserはPythonから実装し、SubscriberはTwinCATのTF6701にします。BrokerがRaspberry-pi3で立ち上げます。
Setup a Broker
Raspberry pi使うとき便利な参考Link:
Raspberry pi/UbuntuからBrokerをBuildする記事:
もしBrokerから接続拒否されたら:
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.
テストするには、まずBrokerを起動し、次はPublisherのScriptを起動します。
TwinCAT側見ると、1秒毎にデータが更新されたとわかります。
Source Code
以下のLinkからSource Codeをダウンロードできます。
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT%20Project_MQTT_Client_Sub.zip