GithubHelp home page GithubHelp logo

fbarresi / beckhoffhttpclient Goto Github PK

View Code? Open in Web Editor NEW
60.0 10.0 9.0 363 KB

Unofficial TwinCAT function for HTTP-Client and Json conversion

License: MIT License

C# 100.00%
beckhoff twincat twincat-ads json api rest

beckhoffhttpclient's Introduction

Beckhoff Http Client

Build status Codacy Badge Licence GitHub All Releases

Unofficial TwinCAT function for HTTP requests with json conversion

This open source library allow any beckhoff PLC (Windows CE based PLCs are not supported šŸ˜„ - see this issue) to make API requests with an HTTP/HTTPS client. If you are going to buy the TF6760 | TC3 IoT HTTPS/REST (planned for End 2019, not realized yet - Dec '19) you should first read this page and wonder how open-source software can simplify your life.

Key features

  • NO Licence costs (This software is free also for commercial uses)
  • support HTTP/HTTPS API calls
  • support all API methods (GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH, MERGE, COPY)
  • reads any Json body with complex nested structures (it also works with json lists of object as API response)
  • parse any Json response to plc structure

Prepare your PLC

  • Install the unofficial TwinCAT Function TFU001 on your target system
  • Install the TwinCAT Library to your project

How to use the TwinCAT Library

Reference the BeckhoffHttpClient Library

Download and reference the BeckhoffHttpClient library and import it to your project.

You can now declare and call a Client in your program and start using rest API.

PROGRAM MAIN
VAR
	client : HttpClient;
END_VAR
client(
	Execute:=FALSE , 
	Address:= 'https://dog.ceo/api/breeds/image/random', 
	CallMethod:= 'GET' , 
	Body:= '', 
	ResponseCode:= 'GVL.ResponseCode', 
	Response:= 'GVL.Response',  
	HasError=> , 
	ErrorId=> );

The JSON Attribute

This software can parse and convert normal DUTs (also nested DUTs) into Json object thaks to the power of TwinCAT.JsonExtension. The only things you have to do is to add the JSON attribute to your code like follows and specify if your field has another json-name or can be used with its own name.

TYPE JsonDUT :
STRUCT
	{attribute 'json' := 'message'}
	sMessage : STRING;
	iResponse : INT;
	{attribute 'json' := 'status'}
	sStatus : STRING;
	{attribute 'json' := 'numbers'}
	daNumbers : ARRAY[1..10] OF DINT := [1,2,3,4,5,6,7,8,9,10];
	{attribute 'json'}
	child : ChildDUT;
END_STRUCT
END_TYPE

Use an API header

You can setup an application-wide header using the header.json file placed into C:\TwinCAT\Functions\Unofficial\BeckhoffHttpClient\.

If no header file is provided the application will create an example file header_example.json you can directly rename, edit and use.

Would you like to contribute?

Yes, please!

Try the library and feel free to open an issue or ask for support.

Don't forget to star this project!

Other projects

Check other project you may be interested in:

Credits

Special thanks to JetBrains for supporting this open source project.

beckhoffhttpclient's People

Contributors

dependabot[bot] avatar fbarresi avatar windows97 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

beckhoffhttpclient's Issues

Json Array Isn't Serialized correctly or written to any array in the PLC

This happens because when the response is in the form of a JSON array and starts with "[" it is of type JArray not JObject. I created a conditional to check for this and handle accordingly as well as use the base Response tag path to point to the array in the plc then add the [index] in a loop to iterate through all results and write to the plc. There may be a better way to handle this. Just wanted to raise the issue and a possible soultion.

Use with c++ modules

Has anyone done any use of this library with twincat c++ modules, i.e. calling an Http POST command from a c++ module?
I've been trying to follow along with the twincat documentation, but I feel like I am missing steps.

POST with JSON string not working

Thank you for your work on this awesome library!

Should we be able to pass JSON strings in the Body of a POST request? Am I not using the Client correctly?

  • I get a 200 ResponseCode in the README example.
  • I get a 200 ResponseCode on POST when passing Body a variable path to a valid DUT.
  • I get a 400 ResponseCode on POST when passing Body an empty string (Body := '') because my endpoint validates the request.
  • I get a 200 ResponseCode when using curl with valid JSON data.
  • I do not get a ResponseCode on POST when passing Body a JSON string with valid JSON data.

Failing example with JSON string

MAIN.TcPOU

Client : HttpClient;
Execute : BOOL := TRUE;
HasError : BOOL;
ErrorId : UDINT;
Client(
	Execute := Execute,
	Address := 'https://www.fake-example.com/ExampleController/Post',
	CallMethod := 'POST',
	Body := '{"stringProperty": "string", "dintProperty": 1, "arrayProperty": ["string"]}',
	ResponseCode := 'GVL.ResponseCode', // This is not updated from the default value of 0.
	Response := '',
	HasError => HasError, // No error returned
	ErrorId => ErrorId);

IF Execute THEN
        Execute := FALSE;
END_IF

GVL.TcGVL

{attribute 'qualified_only'}
VAR_GLOBAL
    ResponseCode : INT;
END_VAR

header.json

{
  "Accept": "*/*",
  "Content-Type": "application/json"
}

The .NET/C# endpoint responds to POST with 200 if it receives a valid request body

ExampleController.cs

namespace ExampleProject.API.Controllers;

[ApiController, Route("[controller]/[action]")]
public class ExampleController : ControllerBase
{
  // "/ExampleController/Post"
  [HttpPost]
  [ProducesResponseType(StatusCodes.Status200OK)]
  [ProducesResponseType(StatusCodes.Status400BadRequest)]
  public async Task<IActionResult> Post([FromBody] Request request) => return Ok();
}

Request.cs

namespace ExampleProject.API.Models;

public class Request
{
    // JSON must include this property with a non-empty string value.
    [Required(AllowEmptyStrings = false)]
    public string StringProperty { get; set; } = string.Empty;

    // JSON must include this property with any int value.
    [Required]
    public int DintProperty { get; set; }

    // JSON must include this property with 0 or more strings in an array.
    [Required]
    public IEnumerable<string> ArrayProperty { get; set; } = Enumerable.Empty<string>();
}

Working example with variable path

MAIN.TcPOU

Client : HttpClient;
Execute : BOOL := TRUE;
HasError : BOOL;
ErrorId : UDINT;
Client(
	Execute := Execute,
	Address := 'https://www.fake-example.com/ExampleController/Post',
	CallMethod := 'POST',
	Body := 'GVL.Body',
	ResponseCode := 'GVL.ResponseCode', // This is 200 on success.
	Response := '',
	HasError => HasError,
	ErrorId => ErrorId);

IF Execute THEN
        Execute := FALSE;
END_IF

GVL.TcGVL

{attribute 'qualified_only'}
VAR_GLOBAL
    Body : Body;
    ResponseCode : INT;
END_VAR

Body.TcDUT

TYPE Body :
STRUCT
    {attribute 'json' := 'stringProperty'}
    StringProperty : STRING := 'string';

    {attribute 'json' := 'dintProperty'}
    DintProperty : INT := 1;

    {attribute 'json' := 'arrayProperty'}
    ArrayProperty : ARRAY[0..9] OF STRING := ['string'];
END_STRUCT
END_TYPE

header.json

{
  "Accept": "*/*",
  "Content-Type": "application/json"
}

Why do I care about using a JSON string if the variable path to a DUT is working ok?

In my working example above, the DUT contains a property of type ARRAY[0..9] OF STRING, a static array, but the REST API endpoint takes in a dynamic array of strings, expected to vary with each call. For this use case, it is preferred to send:

{"stringProperty": "string", "dintProperty": 1, "arrayProperty": ["string"]}

instead of what the DUT deserializes to:

{"stringProperty": "string", "dintProperty": 1, "arrayProperty": ["string","","","","","","","","",""]}

Passing a JSON string to the HttpClient Body would be a workaround for all requests with dynamic arrays that do not serialize appropriately.

Hide Console window

Hello! It is me again...

Is there a way to hide permanently the console window that shows up every http command?
I was looking in the TFU code and you could maybe implement a variable to enable or disable the LOG window.

Thanks!

body not valid for post request

I have a post request to Telegram:
Invoke-RestMethod -Uri https://api.telegram.org/botTTT/sendMessage -Method 'POST' -ContentType 'applicatiomn/json' -Body '{"chat_id": "12345", "text": "This is a test from curl", "disable_notification": true}'
The json Object in the PLC is like that:
TYPE Json_Telegram :
STRUCT
{attribute 'json' := 'chat_id'}
chat_id : STRING := '1020187857';
//iResponse : INT;
{attribute 'json' := 'text'}
text : STRING := 'ScreenCut';
END_STRUCT
END_TYPE
I think, the content-type text/json is not ok, but it comes directly from you program.
Any suggestions?

BTW: Great work! This is a very nice and useful application!

Functionality question

Hi
IĀ“m new to Beckhoff but not to automation.
The functionality i want to accomplish is quite simple and searching for the simplest way to do this without buying a license.
I have a INT variable in the PLC that i want to input to a http-address to post a form on a php-page
like this:
http://ipadress-to-remote-server/index.php?submit=1&MaxAmps=xxx
Where the XXX is my INT.

It's a very basic functionality.
Can I use this 'BeckhoffHttpClient' for this?
Or maybe there is a much simpler way to do it?

Different behavior of HttpClient in different twincat projects

@fbarresi Hi again!

Continues from previous issue that was closed .

So it turns out, the library is not functioning on my existing twincat project, the exact same code was copied over from the sample project which had everything working properly, but the client does not make any calls and ResponseCode remains 0 inside Global_Variables. Now that I have the sample project working fine I can confirm TFU001 is installed successfully and the library is referenced properly as well, do you have any idea as to what could be causing this? I have the same set up on both twincat projects.

Thanks so much,

KK

Installation TFU001 on Windows CE

Hi, im trying to use this extension with the JSON extension as well in order to send data to the POWER BI API via a POST, could you explain how is the TFU001 supposed to installed, I'm not really sure how to install the extension.

Thanks

Cannot run: ErrorId 1799

Hello!

First of all thank you for writing an open source alternative HttpClient.

I have a problem running it. When I try to do a GET to a local server I get a: 1799 -> DeviceNotReady error id.

image

Any idea what I am doing wrong?

String variable 'in' too short for the VAR_IN_OUT parameter

Hello!
When I'm trying to compile, I get the following errors in the HttpClient POU:

String variable 'in' too short for the VAR_IN_OUT parameter 'Body' of 'F_STRING'
String variable 'in' too short for the VAR_IN_OUT parameter 'Address' of 'F_STRING'
String variable 'in' too short for the VAR_IN_OUT parameter 'CallMethod' of 'F_STRING'
String variable 'in' too short for the VAR_IN_OUT parameter 'ResponseCode' of 'F_STRING'
String variable 'in' too short for the VAR_IN_OUT parameter 'Response' of 'F_STRING'

Running on a local machine

Im having issues trying to run this on a local machine Win10x64 machine...
Does this have to run on Beckhoff Win 10 IoT machine?
The TFU0001.exe module is located in the right folder, code it pointing to it, but I dont think it is running when executed. Any ideas?

I don't get any response

Hello and Thank you for your work!
I try to accomplish a communication to a CLI from my Beckhoff CX5040 (Win 10). I can send the desired commands, but i dont recive any response.
Maybe i just dont unterstand how the variables "reponse" and "ResponseCode" work proberly, is ther an furhter documentation of your library?
Even if i try to catch the respons from https://dog.ceo/api/breeds/image/random i dont get anything back.
The commands i send work fine, i recive anything of the CLI-side.

My example-Code:

MAIN:
client(
Execute:=bSend ,
Address:= 'https://dog.ceo/api/breeds/image/random',
CallMethod:= 'GET' ,
Body:= '',
ResponseCode:= 'Globale_Spez.iResponseCode',
Response:= 'Globale_Spez.asBody',
HasError=> bError,
ErrorId=> udiErrorId);

bSend := FALSE;

Globale_Spez:
VAR_Global
iResponseCode : INT;
asResponse : JsonRadioStatus;
END_VAR

DUT:
TYPE JsonRadioStatus :
STRUCT
{attribute 'json' := 'message'}
sMessage : STRING;
{attribute 'json' := 'status'}
sStatus : STRING;
END_STRUCT
END_TYPE

What am i missing?

Thanks for your replay!

No response, response and responseCode does not show change after sample program is executed

Hello! I'm looking to utilize this library in one of our Twincat programs, and right now I'm just trying to get started with this library.

I've copied over the code in the readme to test out a simple API call on my local computer (not PLC) , but I'm not getting any responses.
My code is as shown below:

Main:

VAR
	
	bError: BOOL;
	udiErrorId : UDINT;
	client : HttpClient;
END_VAR
client(
	Execute:=FALSE ,
	Address:= 'https://dog.ceo/api/breeds/image/random',
	CallMethod:= 'GET' ,
	Body:= '',
	ResponseCode:= 'Global_Variables.ResponseCode',
	Response:= 'Global_Variables.ResponseBody',
	HasError=> bError,
	ErrorId=> udiErrorId);
Global_Variables (under GVL):`
`VAR_GLOBAL
	ResponseCode: INT;
	ResponseBody : JsonRadioStatus;
END_VAR

After starting the program, the response body and response both do not change as they are expected to. I've also tried out the sample project existing in this repository by cloning it, and the same goes for that project, I'm getting no errors and no responses.

Could you please enlighten me as to what could be possibly causing this? Thank you so much, and thanks so much for the work on this library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    šŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. šŸ“ŠšŸ“ˆšŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ā¤ļø Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.