This article uses pfc-kbus-api to collect the state of the IO modules installed on the PFC200 Controller without PLC RUNTIME and update each Channel on the output module via MQTT.
Let’s Start!
Reference Link
http://soup01.com/en/category/docker_en/
pfc-kbus-api
pfc-kbus-api is an open source project that enables the reading and writing of IO data of WAGO PFC controllers via the MQTT protocol, whereby controller states and IO values can be cycled at a rate specified in the configuration file.
https://github.com/jessejamescox/pfc-kbus-api
The following is an example of data received by pfc-kbus-api:
{ “state”: { “reported”: { “node_id”: “PFC200”, “timestamp”: 1649356003, “switch_state”: “RUN”, “module_count”: 6, “modules”: { “module1”: { “pn”: 36865, “position”: 1, “type”: “DI”, “input_channel_count”: 2, “output_channel_count”: 0, “process_data”: { “inputs”: { “channel1”: { “value”: true, “label”: “myFirstLabeledChan” }, “channel2”: { “value”: false, “label”: “m1_input2” } } } } } } } } |
The following is an example of data sent by pfc-kbus-api:
{ “state”: { “desired”: { “modules”: { “module2”: { “process_data”: { “outputs”: { “channel1”: { “value”: false } } } } } } } } |
Setup
Login as root
Login to Root with the following Username and Password: wago is the Default Password, so you need to change the Password of Root after the first Login.
username: root password:wago |
Check docker installation
Check the status of your Docker installation with the following command.
docker info docker ps docker images |
Get prebuild pfc-kbus-api image
The next step is to acquire the pfc-kbus-api image that we are going to use.
docker pull jessejamescox/pfc-kbus-api |
Environemnt Setup
Download the Setup shell script from Github.
https://github.com/jessejamescox/pfc-kbus-api
Transfer the File to the PFC Controller using FTP client software and modify the permissions ,so that the File can be executed.
root@PFC200V3-44BD59:~ chmod +x setup_environment.sh |
Then execute the Script.
root@PFC200V3-44BD59:~ ./setup_environment.sh Terminate Codesys3…done swith runtime to none…done stopping codesys3 webserver…done |
kbus-api MQTT Configure
Change connection parameters for kbbus-api and MQTT Broker.
root@PFC200V3-44BD59:~ nano /home/docker/volumes/kbusapidata/_data/kbus-api.cfg |
This is the actual Configuration. Some important parameters are explained in this tutorial.
# The main configuration file for the Kbus <> MQTT # client service. Please configure all points. # The hostname or some unique identifier to the # MQTT broker. This will default to hostname. # If AWS shadaow compatibility is enabled, this will # be used as your thing name from the IoT Core # ** if blank, the controller hostname will be used *** node_id = “PFC200”; # Set the communication type. Enable the publish cyclic # in this state all messages are published to status topic # to publish the kbus on a set cycle. # DO NOT CHANGE – for future use publish_cyclic = true; # publish cycle in milliseconds. default is 100ms # performance with cloud broker may be unstable with # faster cycle speed publish_interval = 100; # The broker network address, this can be localhost # or an external device address mqtt_endpoint = “192.168.5.188”; # Mqtt broker port. The beta version only supports # non-TLS encrypted connections and no SSL config mqtt_port = 1883; # Use username and password for secure broker connections support_userpasswd = false; mqtt_username = “johnDoe”; mqtt_password = “myPassword”; # Maximum number of retries before the program exits # setting this to a negative number will loop infinitely max_retries = -1; # Setting this to true enables the TLS capabiltiy from # the client only. TLS is not currently supported by the # local broker. When enabled, you must have cert, key, # and rootCA paths mapped below support_tls = false; # direct path to your certificate #cert_path = “/etc/ssl/certs/mycert.pem.crt”; # direct path to your private key #key_path = “/etc/ssl/certs/mykey.pem.key”; # direct path to your rootCA certificate #rootca_path = “/etc/ssl/certs/root.ca.pem”; # setting this true formats the mqtt topics and payload # to comply with the AWS IoT Thing Shadow formatting support_aws_shadow = false; #TOPICS # subscribe topic for kbus events. publish to this topic # to command kbus outputs. Unless formatted to AWS Thing # Shadow, the topic will be prefixed with the Node ID. event_sub_topic = “/controller/kbus/event/outputs”; # publish topic for kbus events. subscribe to this topic # for messages on input change-of-state. Unless formatted # AWS Thing Shadow, the topic will be prefixed with the # Node ID. status_pub_topic = “/controller/status”; # setting this creates a deadband with analog input signals # which for now is the decimal value threshold you must # exceed to trigger an update to publish. See README for # instructions on how to set individual deadband for each channel default_analog_deadband = 10; |
The Nodeid here is actually the prefix of the Topic. The rules are in the form node_id/your_topic.
node_id = “PFC200”; |
This sets the period at which Message is published. (100ms)
publish_interval = 100; |
If Login is required when connecting to the Broker, please configure the Username and Password.
support_userpasswd = false; mqtt_username = “johnDoe”; mqtt_password = “myPassword”; |
Topic name is used to subscribe the output command from Broker to WAGO PFC200.
As explained earlier ,the topic is a combination of Nodeid with a prefix. The rules are node_id/your_topic.
So the actual Topic is
PFC200/controller/kbus/event/outputs.
event_sub_topic = “/controller/kbus/event/outputs”; |
This is the Topic name to be Public to the Broker from WAGO PFC 200, which is a combination of Nodeid with a prefix, as explained earlier. The rule is in the form node_id/your_topic .
So the actual Topic is,
PFC200/controller/status.
status_pub_topic = “/controller/status”; |
RUN
Start the Container.
docker run -d –init \ –restart unless-stopped –privileged \ –network=host \ -v kbusapidata:/etc/kbus-api \ -v /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket \ jessejamescox/pfc-kbus-api |
Test Broker
Installation
In this case, the MQTT Broker is used in my MAC.
brew
install the brew tools.
/bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)” |
Broker
Install the MQTT Broker.
brew install mosquitto |
setup
Change the configuration of the MQTT Broker.
Chris-no-MacBook-Pro:~ chrischung$ nano /usr/local/etc/mosquitto/mosquitto.conf |
Enable max_keepalive 0 to match MQTT v3.1.1 and V3.1.
# For MQTT v3.1.1 and v3.1 clients, there is no mechanism to tell the client # what keepalive value they should use. If an MQTT v3.1.1 or v3.1 client # specifies a keepalive time greater than max_keepalive they will be sent a # CONNACK message with the “identifier rejected” reason code, and disconnected. # max_keepalive 0 |
set allow_anonymous to true to allow other clients to connect without Username.
allow_anonymous true # allow_zero_length_clientid # auto_id_prefix # password_file # plugin # plugin_opt_* # psk_file |
The Port of the MQTT Broker is set to 1883.
# listener port-number [ip address/host name/unix socket path] listener 1883 |
RUN
Start the Broker.
Chris-no-MacBook-Pro:~ chrischung$ /usr/local/sbin/mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf -p 1883 |
Result
Done!A connection has been received from the Wago PFC200 Controller.
1682559080: New connection from 192.168.5.58:46058 on port 1883. 1682559080: New client connected from 192.168.5.58:46058 as PFC200 (p2, c1, k0). |
Sub
Open another Terminal and check the subscription data to PFC200/controller/status Topic.
Chris-no-MacBook-Pro:~ chrischung$ mosquitto_sub -h 192.168.5.188 -t PFC200/controller/status |
From Wireshark, we can see that MQTT Packets are flowing from 192.168.5.58 (WAGO PFC200) to 192.168.5.188 (my PC).
The current value of each Channel can be checked.
Here is the terminal output and we can check the status of each channel.
{ “state”: { “reported”: { “node_id”: “PFC200”, “timestamp”: 1682559258, “switch_state”: “RUN”, “module_count”: 4, “modules”: { “module1”: { “pn”: 34817, “position”: 1, “type”: “DI”, “input_channel_count”: 8, “output_channel_count”: 0, “process_data”: { “inputs”: { “channel1”: { “value”: true, “label”: “m1_input1” }, “channel2”: { “value”: false, “label”: “m1_input2” }, “channel3”: { “value”: false, “label”: “m1_input3” }, “channel4”: { “value”: false, “label”: “m1_input4” }, “channel5”: { “value”: false, “label”: “m1_input5” }, “channel6”: { “value”: false, “label”: “m1_input6” }, “channel7”: { “value”: false, “label”: “m1_input7” }, “channel8”: { “value”: false, “label”: “m1_input8” } } } }, “module2”: { “pn”: 34818, “position”: 2, “type”: “DO”, “input_channel_count”: 0, “output_channel_count”: 8, “process_data”: { “outputs”: { “channel1”: { “value”: false, “label”: “m2_output1” }, “channel2”: { “value”: false, “label”: “m2_output2” }, “channel3”: { “value”: false, “label”: “m2_output3” }, “channel4”: { “value”: false, “label”: “m2_output4” }, “channel5”: { “value”: false, “label”: “m2_output5” }, “channel6”: { “value”: false, “label”: “m2_output6” }, “channel7”: { “value”: false, “label”: “m2_output7” }, “channel8”: { “value”: false, “label”: “m2_output8” } } } }, “module3”: { “pn”: 597, “position”: 3, “type”: “AO”, “input_channel_count”: 0, “output_channel_count”: 8, “process_data”: { “outputs”: { “channel1”: { “value”: 0, “label”: “m3_output1” }, “channel2”: { “value”: 0, “label”: “m3_output2” }, “channel3”: { “value”: 0, “label”: “m3_output3” }, “channel4”: { “value”: 0, “label”: “m3_output4” }, “channel5”: { “value”: 0, “label”: “m3_output5” }, “channel6”: { “value”: 0, “label”: “m3_output6” }, “channel7”: { “value”: 0, “label”: “m3_output7” }, “channel8”: { “value”: 0, “label”: “m3_output8” } } } }, “module4”: { “pn”: 471, “position”: 4, “type”: “DX”, “input_channel_count”: 64, “output_channel_count”: 0, “process_data”: { “outputs”: { }, “inputs”: { “channel1”: { “value”: false, “label”: “m4_input1” }, “channel2”: { “value”: false, “label”: “m4_input2” }, “channel3”: { “value”: false, “label”: “m4_input3” }, “channel4”: { “value”: false, “label”: “m4_input4” }, “channel5”: { “value”: false, “label”: “m4_input5” }, “channel6”: { “value”: false, “label”: “m4_input6” }, “channel7”: { “value”: false, “label”: “m4_input7” }, “channel8”: { “value”: false, “label”: “m4_input8” }, “channel9”: { “value”: false, “label”: “m4_input9” }, “channel10”: { “value”: false, “label”: “m4_input10” }, “channel11”: { “value”: false, “label”: “m4_input11” }, “channel12”: { “value”: false, “label”: “m4_input12” }, “channel13”: { “value”: false, “label”: “m4_input13” }, “channel14”: { “value”: false, “label”: “m4_input14” }, “channel15”: { “value”: false, “label”: “m4_input15” }, “channel16”: { “value”: false, “label”: “m4_input16” }, “channel17”: { “value”: false, “label”: “m4_input17” }, “channel18”: { “value”: false, “label”: “m4_input18” }, “channel19”: { “value”: false, “label”: “m4_input19” }, “channel20”: { “value”: false, “label”: “m4_input20” }, “channel21”: { “value”: false, “label”: “m4_input21” }, “channel22”: { “value”: false, “label”: “m4_input22” }, “channel23”: { “value”: false, “label”: “m4_input23” }, “channel24”: { “value”: false, “label”: “m4_input24” }, “channel25”: { “value”: false, “label”: “m4_input25” }, “channel26”: { “value”: false, “label”: “m4_input26” }, “channel27”: { “value”: false, “label”: “m4_input27” }, “channel28”: { “value”: false, “label”: “m4_input28” }, “channel29”: { “value”: false, “label”: “m4_input29” }, “channel30”: { “value”: false, “label”: “m4_input30” }, “channel31”: { “value”: false, “label”: “m4_input31” }, “channel32”: { “value”: false, “label”: “m4_input32” }, “channel33”: { “value”: false, “label”: “m4_input33” }, “channel34”: { “value”: false, “label”: “m4_input34” }, “channel35”: { “value”: false, “label”: “m4_input35” }, “channel36”: { “value”: false, “label”: “m4_input36” }, “channel37”: { “value”: false, “label”: “m4_input37” }, “channel38”: { “value”: false, “label”: “m4_input38” }, “channel39”: { “value”: false, “label”: “m4_input39” }, “channel40”: { “value”: false, “label”: “m4_input40” }, “channel41”: { “value”: false, “label”: “m4_input41” }, “channel42”: { “value”: false, “label”: “m4_input42” }, “channel43”: { “value”: false, “label”: “m4_input43” }, “channel44”: { “value”: false, “label”: “m4_input44” }, “channel45”: { “value”: false, “label”: “m4_input45” }, “channel46”: { “value”: false, “label”: “m4_input46” }, “channel47”: { “value”: false, “label”: “m4_input47” }, “channel48”: { “value”: false, “label”: “m4_input48” }, “channel49”: { “value”: false, “label”: “m4_input49” }, “channel50”: { “value”: false, “label”: “m4_input50” }, “channel51”: { “value”: false, “label”: “m4_input51” }, “channel52”: { “value”: false, “label”: “m4_input52” }, “channel53”: { “value”: false, “label”: “m4_input53” }, “channel54”: { “value”: false, “label”: “m4_input54” }, “channel55”: { “value”: false, “label”: “m4_input55” }, “channel56”: { “value”: false, “label”: “m4_input56” }, “channel57”: { “value”: false, “label”: “m4_input57” }, “channel58”: { “value”: false, “label”: “m4_input58” }, “channel59”: { “value”: false, “label”: “m4_input59” }, “channel60”: { “value”: false, “label”: “m4_input60” }, “channel61”: { “value”: false, “label”: “m4_input61” }, “channel62”: { “value”: false, “label”: “m4_input62” }, “channel63”: { “value”: false, “label”: “m4_input63” }, “channel64”: { “value”: false, “label”: “m4_input64” } } } } } } } } |
Pub
Let’s open another Terminal and try to update the output of WAGO PFC200’s output module.
Chris-no-MacBook-Pro:~ chrischung$ mosquitto_pub –h 192.168.5.188 -t PFC200/controller/kbus/event/outputs –m {‘”state”: {“desired”: {“modules”: {“module2”: {“process_data”: {“outputs”: {“channel4”: {“value”: true}}}}}}}’} |
From Wireshark, we can see that MQTT Packets are flowing from 192.168.5.188 (WAGO PFC200) to 192.168.5.58 (my PC), and the PFC200 second output module, Channel 4, is True.
Startup IO
Wago.PFC200 Startup IO With out PLC Runtime
Flashing Output
Wago.PFC 200 Flashing output without PLC Runtime
Error-Invalid arguments provided.
max_keepalive=0 to solve it。
1682557698: New client connected from 192.168.5.58:45916 as PFC200 (p2, c1, k0). 1682557698: Bad socket read/write on client PFC200: Invalid arguments provided. |
Error-Starting in local only Mode
allow_anonymous true listener 1883 |
https://stackoverflow.com/questions/65278648/mosquitto-starting-in-local-only-mode