Trafic Light Sample - aliconnect/aliconnect.sdk GitHub Wiki
This example is based on a Logic Control for a trafic light conform the Dutch Tunnel Standard LTS of the Dutch Government
Open command prompt. Hit windows
+R
and enter cmd
.
Create project folder sample1
md sample1
cd sample1
Create a package.json
file with npm.
npm init
Install the package aim-server.
npm i aim-server
or create a mklink to your development aim-server folder
mklink /d node_modules c:\aliconnect\node_modules
Create file secret.json
and set following attributes
-
client_secret
: Yourclient_secret
code from the Aliconnect platform. For this example theclient_secret
isea877497-86a1-49f3-a69a-ef4b0287df82
{
"client_secret": "ea877497-86a1-49f3-a69a-ef4b0287df82"
}
- Create file
control1.json
and set following attributes
-
debug
:true
will enable debug message. -
secret
: Filename of secret file. Note that the filenamesecret.json
is read protected through the webserver. -
access_token
: This is anaccess_token
received during the authorization process. This token is used for the sample. Normaly do not enter this code in your config. -
http
: configure the HTTP of the current device.-
port
: For the control application we use port 1341 -
key
: Optional file reference to a SSL certificate (not used within this sample) -
cert
: Optional file reference to a SSL certificate key (not used within this sample) -
ca
: Optional file reference to a SSL certificate (not used within this sample)
-
-
ws
: Websocket configuration with websocket server. This is the websocket server address of the aim message server in a server based network.-
url
: websocket server URL. Can be cloudwss://aliconnect.nl:444
or local aim server f.e. unsecurews://192.168.0.201:81
or securewss://192.168.0.201:444
.
-
{
"debug": true,
"secret": "./secret.json",
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJzaGEyNTYifQ.eyJhdWQiOjF9.98zaT3r4KqJD4phz9RhQE4JffdLO_b2bZ7fOZutizFo",
"http": {
"port": 1341
},
"ws": {
"url": "ws://localhost:1340"
}
}
Create file control1.js
Require the aim-server module
aim = require('aim-server');
Extend the aim module with the API specification conform the Open API Standard 3.0.1.
- api
-
openapi
: OAS version 3.0.1 -
info
: See OAS documentation for more information. -
paths
: See OAS documentation for more information.-
Control(id)/SetState(state)
: Specification of a API url. See OAS documentation for more information.-
POST
: MethodPOST
within theurl
-
operationId
: Name of operation that will be executed with the described parameters extracted from the url.
-
-
-
-
components
: See OAS documentation for more information.-
schemas
: See OAS documentation for more information.-
Control
: Definition of schema Control
-
-
-
aim.extend ({
api: {
"openapi": "3.0.1",
"info": {
"title": "Control",
"description": "Control application",
"contact": {
"email": "[email protected]"
},
"version": "1.0.0"
},
"paths": {
"Control(id)/SetState(state)": {
"POST": {
"tags": [],
"summary": "",
"description": "Set output state",
"operationId": "setControl",
"parameters": [
{ "name": "id", "in": "path", "description": "ID of output", "required": true, "schema": { "type": "integer", "format": "int64" } },
{ "name": "state", "in": "path", "description": "State of output", "required": true, "schema": { "type": "boolean" } }
],
"responses": {
"200": { "description": "Successful operation", "content": {} },
"400": { "description": "Invalid output supplied", "content": {} }
},
"security": [
{ "api_key": [] }
]
}
}
},
"components": {
"schemas": {
"Control": {
"type": "object",
"properties": {
"state": {
"type": "string"
}
}
}
}
}
}
});
The API referense to the operationID
setOutput
. This operation is called with the arguments id
and state
. Now extend the aim platform with the refered operation.
aim.extend ({
operations : {
setControl : function (id, state) {
console.log(`The requested state of control ${id} is set to ${state}`);
setTimeout(function() {
ws.request({url: `Control(${id})`, method: "PATCH", body: { state: state } });
},1000);
return { status: 200 }; // OK
}
}
});
- Create folder
sample1\js
- Create file
sample1\js\hmi.js
. - Create folder
sample1\css
. - Create file
sample1\css\hmi.css
. - Create file
sample1\hmi.html
.
We will use the aim http.request
function. This function is called with the following arguments
- Request parameters as an object containing the following properties
-
url
: url of the request (required) -
method
: method of the request,GET
,POST
,PATCH
orDELETE
(required) -
headers
: headers as object (optional) -
body
: body object send with requestPOST
andPATCH
-
- Callback response function with arguments
-
res
: JSON object response with state f.e.{"state":200}
.
-
setState = function(id,state) {
http.request({ url: `/api/Control(${id})/SetState(${state})`, method: 'POST' }, function(res) {
console.log(`Control state set`);
});
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>HMI</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="node_modules/aim-server/js/lib.js"></script>
<script src="node_modules/aim-server/js/main.js"></script>
<script src="js/hmi.js"></script>
<link rel="stylesheet" href="css/hmi.css" />
</head>
<body>
<h1>HMI</h1>
<button onclick="setState(1,'red');">Request state red</button><br />
<button onclick="setState(1,'yellow');">Request state yellow</button><br />
<button onclick="setState(1,'green');">Request state green</button><br />
<button onclick="setState(1,'white');">Request state off</button><br />
</body>
</html>
node control
http://localhost:1341/hmi
ow click on the button Request state red
and check if command prompt logs The requested state of control 1 is set to red
.
What we see is the followin proces
- The user clicks on the button
- The button onclick event executes the function
setState
with argumentsid
=1
andstate
=red
in the javascriptjs/hmi.js
file - This function executes a HTTP request with
url
=/api/Output(1)/SetState(1)
andmethod
=POST
. - The webserver receives the HTTP request and will lookup the API call in the API configuration. The request url
/api/Output(1)/SetState(1)
is find in deapi/paths
asOutput(id)/SetState(state)
. - The API configuration referce to
operationId
setControl
. - The
operationId
setControl
is found in theaim.operations
code ofcontrol1.js
. It is executed with the configured parametersid
andstate
- This function returns a response
{ status: 200 }
- The response is send back to the HTTP request done by the HMI aplication function
http.request
in thesetControl
function.
We will create a central server
{
"debug": true,
"secret": "./secret.json",
"http": {
"port": 1340
}
}
aim = require('aim-server');
aim.extend ({
api: {
"openapi": "3.0.1",
"info": {
"title": "Server",
"description": "Server application",
"contact": {
"email": "[email protected]"
},
"version": "1.0.0"
},
"paths": {
"Control(id)/SetState(state)": {
"POST": {
"tags": [],
"summary": "",
"description": "Set output state",
"operationId": "setControl",
"parameters": [
{ "name": "id", "in": "path", "description": "ID of output", "required": true, "schema": { "type": "integer", "format": "int64" } },
{ "name": "state", "in": "path", "description": "State of output", "required": true, "schema": { "type": "boolean" } }
],
"responses": {
"200": { "description": "Successful operation", "content": {} },
"400": { "description": "Invalid output supplied", "content": {} }
},
"security": [
{ "api_key": [] }
]
}
}
},
"components": {
"schemas": {
"Output": {
"type": "object",
"properties": {
"state": {
}
}
}
}
}
},
operations : {
setControl : function (id, state) {
console.log(`The requested state ${state} for control ${id} is send`);
wss.request({url: `Control(${id})/SetState(${state})`, method: "POST", body: { state: state } });
return { status: 200 }; // OK
}
}
});
- Create folder
sample1\js
- Create file
sample1\js\hmi.js
. - Create folder
sample1\css
. - Create file
sample1\css\hmi.css
. - Create file
sample1\hmi.html
.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Sample 1</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="node_modules/aim-server/js/lib.js"></script>
<script src="node_modules/aim-server/js/main.js"></script>
<script src="js/gui.js"></script>
<link rel="stylesheet" href="css/gui.css" />
</head>
<body>
<h1>GUI</h1>
<button onclick="setOutput(1,'red');">SetOutput 1 to red</button><br />
<button onclick="setOutput(1,'yellow');">SetOutput 1 to yellow</button><br />
<button onclick="setOutput(1,'green');">SetOutput 1 to green</button><br />
<button onclick="setOutput(1,'white');">SetOutput 1 to off</button><br />
</body>
</html>
setOutput = function(id,state) {
ws.request({ url: `/api/Control(${id})/SetState(${state})`, method: 'POST' }, function(res) {
console.log(`Response Control(${id})/SetState(${state})`,res);
});
}
aim.extend({
config: {
access_token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJzaGEyNTYifQ.eyJhdWQiOjF9.98zaT3r4KqJD4phz9RhQE4JffdLO_b2bZ7fOZutizFo",
ws: {
url: "ws://localhost:1340",
}
},
operations : {
updateValue : function (id, body) {
document.body.style.background = body.state;
return { status: 200 }; // OK
}
},
api: {
paths: {
"Control(id)": {
"PATCH": {
"tags": [],
"summary": "",
"description": "Set output state",
"operationId": "updateValue",
"parameters": [
{ "name": "id", "in": "path", "description": "ID of output", "required": true, "schema": { "type": "integer", "format": "int64" } },
{ "name": "body", "in": "path", "description": "State of output", "required": true }
],
"responses": {
"200": { "description": "Successful operation", "content": {} },
"400": { "description": "Invalid output supplied", "content": {} }
},
"security": [
{ "api_key": [] }
]
}
}
},
}
})
Max van Kampen
CEO, Founder, Alicon, Aliconnect
[email protected]