I've implemented a HTTP web client for requesting info from public online services.
As test I'm able to connect to the webserver of a local LAN device and retrieve its webpage by sending a HTTP GET header, works fine.
Then I tried to connect to a public weather service on apixu.com by setting up a TCP connection to its webserver on 94.237.49.36 port 80.
But on the public service the code times-out after hanging in the "connecting" state for 5 seconds and never gets connected.
Is there a route or firewall rule that I need to set?
DNS settings ?
Gateway allows your PLC to ask for a unknown IP, but not for a name.
If you use a url with a name (ex: google.com) then it needs to be resolved by a DNS server.
Use your ISP DNS one or google's one (primary 8.8.8.8, secondary 8.8.4.4)
Http should correctly passthrough your ISP router.
Maybe you need a proxy configuration ?
Check it from a computer accessing internet on the same router.
Last but not least, start by issuing a ping (from your plc) to check if the service is available.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thnx for your reply.
No I connect to the IP directly and setup the HOST name in the HTTP header.
So, I don't need the DNS.
I am able to connect to the IP from a computer using Putty (Raw TCP) and when I send the content of the HTTP header I DO get the response form the webserver.
This does not work form the controller, while when I connect to a local webserver it does work.
I just can;t connect to a public IP-address.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Oke well I found the bug. The HTTP protocol is very strict and needs multiple CR+LF characters.
So, for the people who need an HTTP header for simple GET requests.
You may split up the url into document and arguments, but I didn't need that.
FUNCTION_BLOCKHttpHeaderVAR_INPUT
  URL      : STRING[255]   :='/data.xml?arg1=1&arg2=John';Â
  HOST      : STRING[255]  :='subdomain.domain.org'; END_VARVAR_OUTPUT
  HttpReq    : ARRAY[1..255] OFBYTE; //Might be changed to a pointer to write to
  HttpReqSize   : UDINT       :=0;      //Size of data in HttpReq    END_VARVAR Â
  sHttpReq  : STRING[255];END_VARStrToLowerA(ADR(URL));    //convert to lowercase charactersStrToLowerA(ADR(HOST));    //convert to lowercase characters
Â
sHttpReq :=Standard.CONCAT('GET ', URL);sHttpReq :=Standard.CONCAT(sHttpReq , ' HTTP/1.1$0D$0A');sHttpReq :=Standard.CONCAT(sHttpReq , 'Host: ');sHttpReq :=Standard.CONCAT(sHttpReq , HOST);sHttpReq :=Standard.CONCAT(sHttpReq , '$0D$0A'); //first CR+LNsHttpReq :=Standard.CONCAT(sHttpReq , '$0D$0A'); //second CR+LF (indicates end of feed)HttpReqSize :=DINT_TO_UINT(StrLenA(ADR(sHttpReq)));HttpReq   :=String_TO_ArrayOfByte(sHttpReq, TRUE);
Just open a TCP connection to the servers IP where it's hosted at port 80, TCP_send the HttpReq and TCP_read back data (may take some time for the server to respond >500ms).
You may read twice, because the server will first send the 400 OK header, followed by the requested data/page/file/...
The Server will shutdown the connection when it's finished (and you know all data has been transferred).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Dear reader,
I've implemented a HTTP web client for requesting info from public online services.
As test I'm able to connect to the webserver of a local LAN device and retrieve its webpage by sending a HTTP GET header, works fine.
Then I tried to connect to a public weather service on apixu.com by setting up a TCP connection to its webserver on 94.237.49.36 port 80.
But on the public service the code times-out after hanging in the "connecting" state for 5 seconds and never gets connected.
Is there a route or firewall rule that I need to set?
The M251 controller interface is configured correctly :
IP : 192.168.2.5
Subn : 255.255.255.0
Gateway: 192.168.2.254 (ISP modem)
Controller : M251
Somachine : 4.1 SP2 (codesys 3.5.3)
TCP lib used: TcpUdpCommunication (Schneider electric)
Best regards,
DNS settings ?
Gateway allows your PLC to ask for a unknown IP, but not for a name.
If you use a url with a name (ex: google.com) then it needs to be resolved by a DNS server.
Use your ISP DNS one or google's one (primary 8.8.8.8, secondary 8.8.4.4)
Http should correctly passthrough your ISP router.
Maybe you need a proxy configuration ?
Check it from a computer accessing internet on the same router.
Last but not least, start by issuing a ping (from your plc) to check if the service is available.
Hi,
Thnx for your reply.
No I connect to the IP directly and setup the HOST name in the HTTP header.
So, I don't need the DNS.
I am able to connect to the IP from a computer using Putty (Raw TCP) and when I send the content of the HTTP header I DO get the response form the webserver.
This does not work form the controller, while when I connect to a local webserver it does work.
I just can;t connect to a public IP-address.
Could you detail this ? (I'm not familliar with HTTP)
Hi,
Oke well I found the bug. The HTTP protocol is very strict and needs multiple CR+LF characters.
So, for the people who need an HTTP header for simple GET requests.
You may split up the url into document and arguments, but I didn't need that.
Just open a TCP connection to the servers IP where it's hosted at port 80, TCP_send the HttpReq and TCP_read back data (may take some time for the server to respond >500ms).
You may read twice, because the server will first send the 400 OK header, followed by the requested data/page/file/...
The Server will shutdown the connection when it's finished (and you know all data has been transferred).