ContentHub
20250818-MQTT-JSON_String-EN.mp4
109 views
View transcript
Hello, in this WAGO tutorial, we'll demonstrate how to subscribe to a JSON string as an MQTT client in CODESYS 3.5, analyse the data, and assign values from the string to variables. In this tutorial, we'll use the same setup as the WAGO Load Management video, where we show how to send data to an MQTT broker. Additionally, we'll be using a PFC 200 to receive and evaluate the provided data with CODESYS 3.5. Our aim is to capture the first digital input on the CC100 and display it, for instance, in a visualisation. First, let's take a look at what arrives at the broker. We'll use the software tool MQTT Explorer for this purpose. Once connected to the broker, the main topic WALM is listed, and upon expanding it, we find the subtopic cm vars, which could potentially contain the 8 digital inputs of the CC100. When 24V is applied to the first digital input, the value on the broker changes from 0 to 1. We've located our topic and will copy the string to represent it more graphically and understandably. For this, the Jason Crack homepage is recommended. Here, we insert our string, and the structure is displayed. One point immediately noticeable is that we need to consider the analysis. The value VAL is present here at the top and again in each of the 8 inputs – more on this later. So, we've successfully sent data to the MQTT broker, analysed the string, and identified where the relevant data is located within the structure. Now, we're writing a programme in CODESYS 3.5 to retrieve and evaluate the data. The CODESYS programme illustrated is also available as an example programme and can be downloaded via a link, facilitating adaptation for personal projects. To avoid reinventing the wheel when using MQTT in CODESYS 3.5, we utilize the CODESYS 3.5 library: CODESYS IIOT Libraries SL. While initially requiring a licence, this licence is included with a WAGO Controller from Firmware 24. We install the library using the CODESYS 3.5 installer. Our project here is created in the CODESYS 3.5 Service Pack 21 Patch 1 version, as our PFC200 runs on Firmware 29. By clicking "Change," the Add-ons window opens, where we search for IIOT, install it, and then open Codesys 3.5. We've established a new standard project, found the PFC200, and scanned the K-Bus. In CODESYS 3.5, from the IIOT library, we need to load three libraries into our project: the MQTT Client SL library, Jason Utilities SL, and Web Client SL. With these preparations complete, we begin a new programme to manage the connection to the broker. First, we add the Function Block MQTT Client from the MQTT library. All the inputs and outputs of the Function Block are displayed, and we assign and declare variables accordingly. We start by declaring the function block. With xEnable, the MQTT connection is activated, followed by some variables for status display. In this example, we use the unencrypted MQTT Port eighteen eightythree for uiPort, meaning TLS encryption is not used and set to FALSE. The Keep Alive Telegram is set at 5 seconds; following a disconnection, reconnection is attempted twice at 5-second intervals before the block times out and needs restarting via Enable. If xWillRetain is TRUE, missed Telegrams during connection loss are buffered and sent once communication resumes. With Clean Session TRUE, a new session initiates with each connection; FALSE continues an existing session. We don't use username and password for this example. The Client ID must be unique, as multiple clients cannot log onto the broker with the same ID. If no Client ID is assigned, one is generated automatically, but assigning one simplifies client identification. We could specify a ping interval followed by TLS or certificate settings. With TimeOut, we determine when a failed connection attempt errors out with xError. Next, choose TCP or Web Socket connection and specify the MQTT version. Connection Properties are relevant only for MQTT 5. The Hostname is the IP address of the broker, followed by communication status feedback. We've created the xConnect to Broker as a global variable as further programmes require it. Initially, we set a timer, restarting communication automatically following a disconnection. The TON activates if xError is TRUE or x-Enable doesn't become TRUE. Time is set at 15 seconds. We use a state machine with CASE OF: init, activ, and error. Starting with initialization, the init Case, if Enable isn’t TRUE, we set it to TRUE and move to the Activ step. We check the broker connection; if it's not TRUE, we proceed to Error. When successfully initialized, we remain in Activ until xError is TRUE, then move to Error. In Error case, Enable resets to FALSE, and the timer starts. After 15 seconds, the timer resets, the Error counter increases, and we return to initialization, repeating the process. The broker connection established, we proceed with data retrieval using another state machine and an enumeration. We begin with the initialization step, fetch data, assign the data to variables, and handle errors. We start a new programme requiring two blocks: 'MQTT'-Subscribe from the 'MQTT'-library and Jason Byte Array Reader from the Jason library. The 'MQTT'-Subscriber block retrieves broker data. Initially, again some status messages and the Enable bit. The eSubscribeQoS indicates the MQTT connection's Quality of Service. Given the publisher sends to the broker with a QoS 1, a QoS 1 is advisable for reception too. Next is the Telegram content. pbPayload points to memory where the JSON string stores. We assign a String-Variable of size 2048, specifying memory size to avoid Buffer Overflow. We use no filter, and 'Subscribe Properties' are only needed for 'MQTT' 5. Time Out specifies, in microseconds, a response time to a subscription request. The broker connection is already established in 'MQTT' Client, which we reference here. We specify the 'MQTT' Topic. Referencing 'MQTT' Explorer, multiple main topics from different clients with subtopics are listed. We focus only on WALM's, cm_vars topic. Currently, the string structure WALM, device info, cm_vars is recognisable... for more complex strings, Jason Crack aids greatly. Furthermore, the Function Block requires a W-String containing UTF-16. Since MQTT-provided strings are UTF-8, needing conversion to Wide String. The MQTT Client library offers a converter for which we declare variables: 'WS-Topic Filter' and 'S-Topic'. We set conversion in the programme window - The S-Topic variable receives the topic structure. We then declare several variables for block outputs, first for error messages, receipt confirmation, data packet size, active subscriptions, recent REAL topic resolution, and lastly received properties. We receive the desired JSON string, filtering down to the topic 'cm vars.' Next, we dissect the string, assigning values to variables using the JSON Array Reader Function Block. The input Execute begins this process. On rising edge, it triggers actions, resetting outputs on falling edge. Status displays follow. PW-Data points to our data string, again needing conversion to UTF-16. Unfortunately, the simple converter used for topics isn't suitable here due to its 256-character limit. Beyond this, cut-offs occur without notification. However, the WebClient library includes the function Convert UTF8 to UTF16 for this instance, enacted later in the "Fetch" step though established now. Ignore Value isn't necessary; it skips error messages. Keep Asynchronous Mode TRUE, allowing instruction execution beyond a single cycle. Jason Data indicates needed Jason string information – here we'll later keyword search the string. We receive an error output and a BOOL indicating if at least one string exceeded its maximum size. The Jason evaluation block is now complete, allowing us to continue with steps. Recall, we aim for three or four steps if incorporating Error: data retrieval and assignment. We employ an enumeration CASE OF eGetJsonData, commencing with the initialization step. When broker connection establishes and no errors exist, x-Enable starts the previously defined Get WALM Data block, advancing to Fetch. Otherwise, with x Error TRUE or x Enable not getting TRUE, Error proceeds. The first step concludes. In the second "Fetch," data is retrieved. The If statement follows: upon message readiness, xReceived changes from FALSE to TRUE. We convert the data string using the Web Client library's function, starting the reed operation. And we jump to 'Assign', provided that no Error occurs. In Assign, the filtered Jason Array evaluates, assigning provided values to variables. First halt the data reading. Extract the timestamp using the Jason library's Find First Value By Key method to locate a value for the "tst" keyword. The keyword is 'tst'. Start index is 1; store value in json Element Data TST. Create a string from this. We now possess the timestamp in Unix format: seconds from first January 1970 0 o'clock, converting to date and time for reading. Addressing core data, reviewing the string reveals "vars" first, followed by digital input listing. This makes "vars" the data evaluation starting point. Using the 'Find First Element by Key' method, "vars" searches, saving in Json Element Data. Post locating 'vars', search for all 'val' keyed elements from that position and store them into the Array: atypResultArray. iMax specifies maximum result storage. With CC100’s 8 digital inputs, iMax equals 8 as a constant. udiResultSize reveals found "val"-element tally. Addresses and sizes are now available for Jason data retrieval. In Jason, each digital input comprises 5 Topics: name, expression, value, mode, t-dur. Assign theoretically unknown quantities of values to these topics. Three integer variables set, followed by nested FOR loops: the outer loop (j) addresses the 5 terms, the inner loop (k) finds JSON string values for each term. In kind of a table stores found values with elements from [j] and [k]. Now the values need to transfer into a structured format. So we create the structure WALM Data with the 5 Topics. The array begins with name, declared as a String and we search for String Value; Expression is an Integer, thus Value LI. The problem with the third term: 'value', is that the Jason string uses the keyword ‘Val’ once at the beginning and then again in each entry. The required value element is the one that occurs once more than in “i”. So add one, and the required value will be found. Follow usual process for the other two topics. The loop pair iterates until all identified values assign. Values now ordered within 'WALM Data'; Clear the JSON String. Without this, newly added strings would pile, expanding 'ojsonData' indefinitely. Afterwards, jump back to fetch and awaiting the next string. Finaly we need an error handling and we can test the application. Upon activating the first CC100 digital input to TRUE, the corresponding bit in the Codesys programme's WALMData array becomes TRUE. Map this to an output or present it in a visualisation as we do here. As shown, processing a JSON string can be simple and brief, as with the timestamp, or require substantial effort, tips, and knowledge for desired outcomes — varying by JSON structure and required topics. Of course, as always in programming, there are other ways, methods or libraries to evaluate the data. This example is just one of many possibilities. Feel free to write to us and tell us which method you prefer. And that concludes the tutorial on demonstrating how to fetch and evaluate MQTT-provided data in CODESYS 3.5 as a subscriber. Please leave us a thumbs up if the video was helpful, subscribe to the channel, and contact the WAGO Support Centre if you have any questions.