In this tutorial I will show you how to use beckhoff twincat TF6760 to send a http request to the server and change the json object to the plc variable.
Hope you like this.
System Requirement
installation
There is no additional installation for this function.
Driver: TcIotDrivers.sys(included in TwinCAT3 XAE・XAR)
PLC library: Tc3_IotBase(included in TwinCAT3 XAE)
TF6760 Iot HTTPS/REST
By using TF6760, we can implement the http command (put/get/etc..) and exchange the data between server and client ( twincat) with the Tc3_IotBase library.
HTTP?
Http is a standard protocol to implement the communication between client and server.
The most common case is your web browser.
The request is sent to google.jp if you type in the web address inside the browser.
And this time we will use the REST-Web services.
Please be careful that the commands of each http command are separated.
It means that the server will determine the connection after the data is sent to the client side.
(But there is some options to keep the connection alive)
Methods
Please refer to your server API documentation – because not all commands are supported on the server side.
Status Code
Header and body are replied from the server separated. It is very important to check the status code that returns from the server.
( Did you remember some error codes like 404/501?)
insert the library
Tc3_IotBase
Tc3_JsonXml
Function Block
I will only explain the methods and function blocks that are used in this tutorial.
And there is a very powerful tool in chrome that will help you to find out the parameters/reply from the server.
Please open your tools and right click “Inspect”.
This below screen is shown.
Click the network tab.
The request that was sent from the client (chrome ) to the server is shown and you can check all inside.
FB_IotHttpClient
This function block can implement a connection to the http server.you need to call the executive () method cycling and use another FB_IotHttpRequest function block to send the request to the server.
VAR_INPUT | ||
sHostName | STRING | Default=127.0.0.1, server IP |
nHostPort | UINT | Default=80 , the using port. |
bKeepAlive | BOOL | Default=True, the connection to server will check until client side cut the connection *Not all server had this function |
tConnectionTimeout | TIME | Timeout |
stTLS | ST_IotSocketTls | The configuration that if TLS is used. |
VAR_OUTPUT | ||
bError | STRING | True=error |
hrErrorCode | HRESULT | Error code |
bConfigured | BOOL | True=Block configuration is finished |
bConnected | BOOL | True=connection is established |
Method
Disconnect | ServerのConnectionを切断する |
Execute | Background通信で使われてるメソッドです。そのメソッドは毎周期で呼び出す必要があります。 |
FB_IotHttpRequest
This function block is used to send the request to sever , and while the signal of FB_IotHttpRequest.bBusy is changed from true to false – it means response is received from the server, we can encode and get the field inside the header field with json format.
VAR_INPUT | ||
sContentType | STRING | Request Contect Type Setting |
eCompressionMode | E_IotHttpCompressionMode | compression Mode |
VAR_OUTPUT | ||
bError | BOOL | True=Error |
bBusy | BOOL | True=FB is running |
eErrorId | ETcIotHttpRequestError | Error ID |
nStatusCode | UINT | Status Codes from Server |
nContentSize | UDINT | The size of HTTP Server response |
The sContentType can be checked by the Inspect tools in chrome.
The eCompressionMode can be checked by the Inspect tools in chrome also.
Method
GetContent
A method to get the content from HTTP Response.Please execute this method after the FB_IotHttpRequest.bBusy signal is changed from True to False.
frp | ||
ntSize | UDINT | The size of Read Data size |
bSetNullTermination | BOOL | |
Return | ||
GetContent | BOOL | True=Method is called without error |
GetHeaderField
A method to get the http response header.Please execute this method after the FB_IotHttpRequest.bBusy signal is changed from True to False.
sField | STRING | The Header Field that you want to take |
pValue | PVOID | ReadData memory offset |
nValueSize | UDINT | ReadData memory size |
Return | ||
GetHeaderField | BOOL | True=Method is called without error |
We can also check the header by inspection tools of chrome.
GetJsonDomContent
A method to change the response to a json object.Please execute this method after the FB_IotHttpRequest.bBusy signal is changed from True to False.
fbJson | REFERENCE TO FB_JsonDomParser | |
Return | ||
GetJsonDomContent | SJsonValue | JSON Root Node |
SendRequest
A method to send the request to the http server.
sUri | STRING | HTTP Request |
fbClient | REFERENCE TO FB_IotHttpClient | FB_IotHttpClient FB Instance |
eRequestType | ETcIotHttpRequestType | Http Command |
pContent | PVOID | |
nContentSize | UDINT | |
fbHeader | REFERENCE TO FB_IotHttpHeaderFieldMap | |
Return | ||
SendRequest | BOOL | True=Methodi is called without error |
FB_JsonDomParser
We can use this function block to change the json object to another object.
Method
GetJson
Get the length of the Json object.
If the length of the string is more than 255, null is returned .
v | SJsonValue | Json Obejct |
Return | ||
GetJson | STRING(255) | String that changed from Json |
FindMember
Search and return a specific property inside the json object.
0 is returned if that property is not found.
v | SJsonValue | Json Obejct |
member | STRING | Property |
Return | ||
FindMember | SJsonValue | The member inside that json object |
ParseDocument
A method to change from string to json object.
sJson | STRING | The string that would like to change |
Return | ||
ParseDocument | SJsonValue | Json Object |
MemberBegin
Get the first property from the json object.
This method is used with MethodEnd() and NextMember() to implement the looping.
SJsonValue | Proprety that would like to take | |
Return | ||
MemberBegin | SJsonIterator | The first property inside a json object. |
MemberEnd
Get the last property inside a json object.
This method is used with MemberBegin() and NextMemver() to loop all the property inside the json object.
v | SJsonValue | Proprety that would like to take |
Return | ||
MemberEnd | SJsonIterator | The last property inside a json object |
NextMember
Get the next member inside the json object.
This method is used with MemberBegin() and MemberEnd() to loop all the properties inside the json object.
v | SJsonValue | Proprety that would like to take |
Return | ||
NextMember | SJsonIterator | The next property inside a json object |
GetMemberName
Get the property name of the current json object.
i | SJsonIterator | |
Return | ||
GetMemberName | STRING | The current proptery name |
GetMemberValue
Get the property value of the current json object.
i | SJsonIterator | |
Return | ||
GetMemberValue | STRING | The property value |
TEST API
Now we can try to configure your Test API.
You can find thousands of API testing servers from google.
Get request is used in this tutorial.
Enter this link into your browser.
https://gorest.co.in/public/v1/users
Response is came from the server.
String process is not an easy task of the plc program , and I will choose only the response that is redlined out.
Add a /1666 to the end of the request, the information of user id 1666 is return .
https://gorest.co.in/public/v1/users/1666
Example
Good! Test API is confirmed and we can make the twincat program.we will send the http rest request to that test API server and convert the response into json format, finally take some specific fields inside the content.
_CallRestAPI
This _CallRestAPI POU can create a client to establish a connection to server and send the request, process the response.
VAR
VAR //Client IotHttpClient:FB_IotHttpClient; //Request IotHttpRequest:FB_IotHttpRequest; JsonDomParser:FB_JsonDomParser; R_TRIG :R_TRIG; bSendRequest:BOOL; bGetContentResult :BOOL; sContent:STRING(511); //Json jsonDoc:SJsonValue; jsonVal:SJsonValue; JsonSaxWriter:FB_JsonReadWriteDataType; jsonDocWithSpeicificMember:SJsonValue; jsonCurrentIterator:SJsonIterator; jsonLastIterator :SJsonIterator; sProperty:STRING; jsonLoopValue:SJsonValue; sHeaderValues:STRING; jsonDataWithSpecificMember:STRING(511); sJsonPropertyValue:STRING; //Unitiy nReqCount:UDINT; iState:INT; nVaildCount:INT:=0; bConfigurated:BOOL; iVaildHeaderCount:INT; bReset:BOOL; bError:BOOL; nError:INT; END_VAR |
VAR CONSTANT
VAR CONSTANT ciStepInit :INT:=0; ciStepSendRequest:INT:=10; ciStepGetContent:INT:=20; ciStepError :INT:=8000; ciHTTPSPort :UINT:=443; END_VAR |
Code
//Start to Send the Request R_TRIG( CLK:=bSendRequest ); CASE iState OF ciStepInit: IF NOT IotHttpClient.bConfigured THEN IotHttpClient.nHostPort:=ciHTTPSPort; IotHttpClient.sHostName:=’gorest.co.in’; IotHttpClient.bKeepAlive:=TRUE; IotHttpClient.tConnectionTimeout:=T#10S; IotHttpClient.stTLS.bNoServerCertCheck:=TRUE; nReqCount:=0; nVaildCount:=0; bError:=FALSE; bReset:=FALSE; nError:=DUTE_HTTPRequest_ERRORCode.E_ERR_Noraml; ELSE iState:=ciStepSendRequest; END_IF ciStepSendRequest: IF R_TRIG.Q THEN IF IotHttpRequest.SendRequest( sUri:=’/public/v1/users/62′ ,fbClient:=IotHttpClient ,eRequestType:=ETcIotHttpRequestType.HTTP_GET ,pContent:=0 ,nContentSize:=0 ,fbHeader:=0 ) THEN nReqCount:=nReqCount+1; bSendRequest:=FALSE; iState:=ciStepGetContent; END_IF; END_IF ciStepGetContent: bGetContentResult:=IotHttpRequest.GetContent( pContent:=ADR(sContent) ,nContentSize:=SIZEOF(sContent) ,bSetNullTermination:=TRUE ); IF IotHttpClient.bError THEN iState:=ciStepError; nError:=DUTE_HTTPRequest_ERRORCode.E_ERR_FB_TioHttpRequest; ELSE CASE IotHttpRequest.nStatusCode OF 200..299: //get the Json Dom from Response jsonDoc:=IotHttpRequest.GetJsonDomContent( fbJson:=JsonDomParser ); //get the Header IF IotHttpRequest.GetHeaderField( sField:=’Server’ ,pValue:=ADR(sHeaderValues) ,nValueSize:=SIZEOF(sHeaderValues) ) THEN iVaildHeaderCount:=iVaildHeaderCount+1; END_IF; //get ‘data’ property from JSON DOM jsonDataWithSpecificMember:=JsonDomParser.GetJson( v:=JsonDomParser.FindMember( jsonDoc ,’data’ ) ); //Convert it to Dom again jsonDocWithSpeicificMember:=JsonDomParser.ParseDocument( jsonDataWithSpecificMember ); //While loop + NextMember(),MemberBegin(),MemberEnd jsonCurrentIterator:=JsonDomParser.MemberBegin(jsonDoc); jsonLastIterator:=JsonDomParser.MemberEnd(jsonDoc); WHILE jsonCurrentIterator <> jsonLastIterator DO sProperty:=JsonDomParser.GetMemberName( jsonCurrentIterator ); jsonLoopValue:=JsonDomParser.GetMemberValue( jsonCurrentIterator ); IF sProperty =’email’ THEN JsonDomParser.CopyString( jsonLoopValue ,sJsonPropertyValue ,SIZEOF(sJsonPropertyValue) ); END_IF jsonCurrentIterator:=JsonDomParser.NextMember( jsonCurrentIterator ); END_WHILE iState:=ciStepSendRequest; //if json Dom from Response is 0, somethings error in your program IF jsonDoc <> 0 THEN nVaildCount:=nVaildCount+1; ELSE iState:=ciStepError; nError:=DUTE_HTTPRequest_ERRORCode.E_ERR_JsonDOM_IsZero; END_IF ciStepError: IF bReset THEN iState:=ciStepInit; END_IF END_CASE END_IF; END_CASE IotHttpClient.Execute(); |
MAIN
Just call the POU that created in the previous step
_CallRestAPI(); |
Result
This is the response from the server.
Here is the specific header .
use the while loop to get the value of mail properties.
Finally
Please download the sample code from here.