This is an experimental implementation of HTTP/1.1 and WebSocket client for OMRON's NX controllers. This HTTP client lacks functionality and is not of sufficient quality. However, it shows that it is possible to implement a practical HTTP client with a user program using Sysmac Studio and the NX controller. The Sysmac project contains several test programs. The HTTP client test program queries Beeceptor's HTTP echo server, and the WebSocket client test program exchanges data via WebSocket.org's WebSocket echo server. For details, please check this article (Japanese).
The HTTP client has the following restrictions.
- Can't use proxy
- Invalid responses can cause tasks to time out
Inquiries using HTTP(S) can be written as follows.
// POST /chat/api/v1 ContentType: application/json
20:
IF NewHttpClientTask(
Context:=iHttpContext,
ClientTask:=iHttpClientTask)
THEN
HttpPost(Context:=iHttpContext,
Url:='https://echo.free.beeceptor.com/chat/api/v1',
KeepAlive:=FALSE,
ClientTask:=iHttpClientTask);
SetHttpHeader(Context:=iHttpContext,
Key:='X-Api-Key',
Value:='xxxxxx');
SetContentStr(
Context:=iHttpContext,
ContentType:='application/json',
Content:='{"channel":"hell","name":"taker","msg":"Have you played Awaria?"}');
iPostTick := 0;
InvokeHttpClientTask(Context:=iHttpContext,
ClientTask:=iHttpClientTask);
Inc(iState);
END_IF;
21:
CASE HttpClientTaskState(Context:=iHttpContext,
ClientTask:=iHttpClientTask) OF
HTTP_CLIENT_TASK_STATE_CLOSED:
iState := iTransState;
HTTP_CLIENT_TASK_STATE_RESPOND:
CASE GetStatusCode(Context:=iHttpContext) OF
200: // OK
iPostRspContentType
:= GetContentType(Context:=iHttpContext);
GetContent(Context:=iHttpContext,
Out:=iRspBinBody,
Head:=0,
Size=>iRspBinBodySize);
iPostRspContent
:= AryToString(In:=iRspBinBody[0],
Size:=iRspBinBodySize);
iState := iTransState;
204: // No Content
iState := iTransState;
ELSE
Inc(iState);
END_CASE;
HTTP_CLIENT_TASK_STATE_REQUESTING:
Inc(iPostTick);
HTTP_CLIENT_TASK_STATE_ERROR:
GetHttpClientError(Context:=iHttpContext,
Error=>iError,
ErrorID=>iErrorID,
ErrorIDEx=>iErrorIDEx);
iState := iState + 7;
END_CASE;
The WebSocket client can be written as follows.
CASE iState OF
0:
RingBuffer_init(Context:=iWriteBufferContext,
Buffer:=iWriteBuffer);
RingBuffer_init(Context:=iReadBufferContext,
Buffer:=iReadBuffer);
WebSocketClientService_init(
Context:=iServiceContext,
Url:='wss://echo.websocket.org/.ws',
TLSSessionName:='TLSSession1',
OptionNoDelay:=TRUE,
SendThreshold:=0);
iService.Enable := TRUE;
Inc(iState);
1:
IF WebSocketClientService_isActive(Context:=iServiceContext) THEN
WebSocketClientService_getStreamContext(
Context:=iServiceContext,
WriteStreamContext=>iWriteStreamContext,
ReadStreamContext=>iReadStreamContext);
Inc(iState);
END_IF;
2:
CASE WebSocketClientService_getState(Context:=iServiceContext) OF
WEBSOCKET_CLIENT_STATE#WCS_ACTIVE:
// Receive messages.
CASE WebSocketStream_on(
Context:=iReadStreamContext,
BufferContext:=iReadBufferContext,
Buffer:=iReadBuffer,
Data:=iRecvPayload,
Head:=iRecvPayloadHead,
Size=>iRecvPayloadSize,
PayloadLength=>iPayloadLength,
Done=>iDoneFrame)
OF
WEBSOCKET_FRAME_TYPE#WFT_TEXT:
iRecvPayloadHead
:= iRecvPayloadHead + iRecvPayloadSize;
IF iDoneFrame THEN
iRecvMessageStr
:= AryToString(In:=iRecvPayload[0],
Size:=iRecvPayloadHead);
iRecvPayloadHead := 0;
END_IF;
END_CASE;
// Send messages.
IF iSend THEN
WebSocketStream_writeText(
Context:=iWriteStreamContext,
BufferContext:=iWriteBufferContext,
Buffer:=iWriteBuffer,
Payload:=CONCAT(DtToString(GetTime()), '$L'));
iSend := FALSE;
END_IF;
// Close the connection.
IF iClose THEN
WebSocketClientService_deactivate(
Context:=iServiceContext,
CloseCode:=1001);
iClose := FALSE;
Inc(iState);
END_IF;
WEBSOCKET_CLIENT_STATE#WCS_DEACTIVATING:
Inc(iState);
END_CASE;
3:
iService.Enable := FALSE;
Inc(iState);
END_CASE;
iService(Context:=iServiceContext,
WriteBufferContext:=iWriteBufferContext,
WriteBuffer:=iWriteBuffer,
ReadBufferContext:=iReadBufferContext,
ReadBuffer:=iReadBuffer);
To use this project, the following environment is required.
Item | Requirement |
---|---|
Controller | NX1 or NX5 |
Sysmac Studio | Latest version recommended |
Network | Internet connection must be possible |
This project was developed using the following environment.
Item | Version |
---|---|
Controller | NX102-9000 Ver 1.64 |
Sysmac Studio | Ver.1.62 |
The HTTP client test program (Test_HttpEcho) queries Beeceptor's HTTP echo server. There may be some restrictions when accessing from a network that is not under your control. If possible, use a test network to ensure there are no constraints.
Set the controller model of this project to match the controller model to be used, and to enable Internet connection and name resolution. At least the gateway and DNS server settings are required.
Set the controller to program mode to prevent unintended operation and to configure secure sockets.
Keep the controller in program mode to prevent the program from running.
Register a TLS session with ID 0
and no client certificate. Do the following while online to the controller.
Paste the following into Watch window.
LIB Test_HttpEcho.iGetRspContent
LIB Test_HttpEcho.iPostRspContent
LIB Test_HttpEcho.iPostFormRspContent
LIB Test_HttpEcho.iPutRspContent
LIB Test_HttpEcho.iPatchRspContent
LIB Test_HttpEcho.iDeleteRspContent
The moment you switch to driving mode, it starts making requests to the server.
If there is a response from the server, the HTTP response will be displayed as shown below.
If an error occurs, there are the following possibilities:
- Incorrect secure socket settings
Check if the ID is0
. - HTTP echo server is down
Ping the HTTP echo server from your device and check the response. - Not connected to the Internet or unable to resolve name
Check the route to the HTTP echo server with tracert.
The WebSocket client test program (Test_WebSocketEcho) sends and receives data via the WebSocket echo server at WebSocket.org. There may be some restrictions when accessing from a network that is not under your control. If possible, use a test network to ensure there are no constraints.
Set the controller model of this project to match the controller model to be used, and to enable Internet connection and name resolution. At least the gateway and DNS server settings are required.
Set the controller to program mode to prevent unintended operation and to configure secure sockets.
Keep the controller in program mode to prevent the program from running.
Register a TLS session with ID 1
and no client certificate.
The moment you switch to driving mode, it starts making requests to the server.
If the program runs correctly, it will eventually receive the string "done\n" and exit.
If an error occurs, there are the following possibilities:
- Incorrect secure socket settings
Check if the ID is1
. - WebSocket echo server is down
Ping the WebSocket echo server from your device and check the response. - Not connected to the Internet or unable to resolve name
Check the route to the WebSocket echo server with tracert.