All the functionality of the Brain4it servers is exposed through a simple HTTP REST API. This allows third-party applications developed with other programming languages to interact remotely with a brain to read and write data, invoke a function or manage its modules.
The data format that this API accepts by default is BPL (Brain4it Programming Language), but the POST method also supports JSON and XML formats.
The modules of a Brain4it server are usually protected with an access key.
This access key is set with a special variable named access-key
in the global scope of the module.
At server level there is also a general access key defined in a configuration file, that allows to perform any operation on any of its modules.
To invoke a method of the REST API, will be necessary, in most cases, to provide the access key of the module or the server through the Access-Key property in the HTTP header:
PUT /geopos/elements/car23/coordinates HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423 Content-Type: text/plain; charset=utf-8 Content-Length: 11 (23.8 89.9)
In production environments it is strongly recommended to configure the server for accepting http secure connections (https:) to avoid compromising the access key.
When multi-tenant mode is enabled the URL format for all operations also includes the tenant name: http://<host>:<port>/<base_path>/<tenant>/<module>/<module_path>
When the HTTP url points to the modules root (that is module and module_path are not specified), the GET method returns a BPL list describing all the modules that are contained in the server. In this case, no access key is required.
Example:
http://localhost:9999GET / HTTP/1.1 Host: localhost:9999
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:95 Content-Type:text/plain;charset=UTF-8 Date:Sat, 04 Nov 2017 19:35:56 GMT Server-Time: 1509820536367 Server:Brain4it (("air1" ("icon" => "air" "description" => "Air conditioner 1")) "biometric" "lights" "main")
The returned list may contain for each module:
The descriptive properties of a module are hold in the special
variable module-metadata
of the module.
When the HTTP url references a module, the GET method will return the data associated to the module_path.
The access key of the module or the server is required
for this operation except when module_path is
module-metadata
.
Example:
http://localhost:9999/geopos/car23/coordinatesGET /geopos/elements/car23/coordinates HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:11 Content-Type:text/plain;charset=UTF-8 Date:Sat, 04 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it (23.8 89.9)
If module_path is omitted, all module data (the global scope) will be returned as a BPL list.
A error will be returned if module or module_path are invalid.
The creation of a new module in the server, can be done through a HTTP PUT request indicating the module name to create in the url. The module_path and the HTTP body must be empty. The server access key is required in this case.
Example:
http://localhost:9999/facilityPUT /facility HTTP/1.1 Host: localhost:9999 Access-Key: 553454422234345345 Content-Length:0
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:26 Content-Type:text/plain;charset=UTF-8 Date:Sat, 04 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it "Module facility created."
If the operation is successful, the server will return a string indicating that the module was created.
A error will be returned if already exists a module with the same name.
Module data can be changed with a HTTP PUT request indicating in the url the module and the module_path of the data to update. The HTTP body must contain data (can not be 0 length) in BPL format. The access key of the module or the server is required in this case.
Example:
http://localhost:9999/facility/space012/infoPUT /facility/space012/info HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423 Content-Length:52 Content-Type:text/plain;charset=UTF-8 ("description" => "Mayor's room" "surface" => 21.2)
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:4 Content-Type:text/plain;charset=UTF-8 Date:Sun, 05 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it null
The server returns the previous data associated with the given module_path.
If module_path is omitted, all module data (the global scope) will be replaced by the given HTTP body.
A error will be returned if module or module_path are invalid.
A server module can be destroyed through a HTTP DELETE request indicating in the url the module to destroy. The module_path must not be specified. This operation requires the access key of the module or the server.
Example:
http://localhost:9999/facilityDELETE /facility HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:29 Content-Type:text/plain;charset=UTF-8 Date:Sun, 05 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it "Module facility destroyed."
If the operation is successful, the server will return a string indicating that the module was destroyed.
Module data can be deleted through a HTTP DELETE request indicating in the url the module and module_path of the data to delete. The access key of the module or the server is required in this case.
Example:
http://localhost:9999/facility/space012/infoDELETE /facility/space012/info HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:52 Content-Type:text/plain;charset=UTF-8 Date:Sun, 05 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it ("description" => "Mayor's room" "surface" => 21.2)
The server returns the data that was associated with the given module_path.
A BPL expression (or code frament) can be evaluated through a HTTP POST request passing that expression in the HTTP body and providing in the url the module in which to do the evaluation. The module_path must not be specified. This operation requires the access key of the module or the server.
Example:
http://localhost:9999/facilityPOST /facility HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423 Content-Length:22 Content-Type:text/plain;charset=UTF-8 (set counter (+ 2 3))
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:1 Content-Type:text/plain;charset=UTF-8 Date:Sun, 05 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it 5
The server returns the result of evaluating the given code or expression.
Exterior functions are user defined functions specially designed to be
invoked from external applications through the REST API.
These functions are easily recognizable because their name always
starts with the at symbol (@). They take two parameters:
context
and body
.
Example:
(set @sum-data
(function (context body)
(eval (append (list +) (parse body "json")))
)
)
An exterior function can be invoked with a HTTP POST request specifying in the url the module (module) and the name (module_path) of the function.
The HTTP body may contain the data to be passed to the exterior function
as the body
argument. That body can be expressed in
BPL, JSON or XML formats in accordance with the Content-Type header property.
When the Content-Type is text/plain body
will be converted to a BPL object. In the other cases, body
will be passed to the function
as a string.
The context
argument is a BPL list that contains the following information:
remote-address
: the client IP addressremote-port
: the client IP portrequest-headers
: a BPL named list containing the request headers. Header names are
lowercase.
When the request comes from a dashboard, this list will contain the property session-id
whose value is an identifier to track the user session.
response-headers
: a BPL named list to set the response headers. Header names must be
lowercase. By default, this list is null
.The result of the function will be sent to the external invoking application.
The format in which that result will be sent is determined by the property content-type
of response-headers
. By default, the result will be encoded as a BPL object.
It is not required to provide the access key when invoking exterior functions. That does not always means that exterior functions are unprotected because they may implement other security strategies.
Example:
http://localhost:9999/facility/@sum-dataPOST /facility/@sum-data HTTP/1.1 Host: localhost:9999 Access-Key: 82769323097141012423 Content-Type: application/json Content-Length: 10 [8, 5, 3]
HTTP/1.1 200 OK Access-Control-Allow-Origin:* Access-Control-Expose-Headers: server-time Content-Length:5 Content-Type:text/plain;charset=UTF-8 Date:Sat, 04 Nov 2017 19:35:36 GMT Server-Time: 1509820536367 Server:Brain4it 16
The server will return the result of evaluating the exterior function.
The widgets of a dashboard need to call the exterior functions of a module to show information to the user. These functions could be invoked doing HTTP requests to the server at a certain frequency (polling), but when the function values vary very often, this method has many drawbacks.
That's why the Brain4it servers offer a more efficient way to monitor the value returned by exterior functions based on a technique similiar to streaming: the HTTP connection will remain open and whenever the value returned by a function changes, the server will send that value to the client through the connection using the standard HTTP chunked transfer encoding.
Exterior functions can be monitored doing a HTTP POST request specifying in the url the module where they are defined and providing in the HTTP body the BPL list that contains the names of the exterior functions to watch.
A special HTTP header property called Monitor must be specified to inform that this is a monitoring request. The value of this header property is the interval, in milliseconds, at which the server will evaluate the given exterior functions. When this value is 0, the server will only evaluate a function if it receives a change notification for that function. (See the module-notify function for more details).
It is not required to provide the access key for this operation.
Example:
http://localhost:9999/facilityPOST /facility HTTP/1.1 Host: localhost:9999 Monitor: 1000 Content-Type:text/plain; charset=utf-8 Content-Length:34 ("@get-photo" "@display" "@light-level")
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Date:Sat, 04 Nov 2017 19:39:56 GMT Server: Brain4it Transfer-Encoding: chunked 27 "1d01e78e-212e-4fe7-bb1d-d28312c4645e" 21 ("@get-value" "A" 1535183881242) 23 ("@light-level" 423 1509820797274) 22 ("@display" "OPEN" 1509820796556) 1 23 ("@light-level" 420 1509820799234) 1
The first chunk sent by the server is the monitoring session identifier, a quoted string that will be used later in an unwatch request to finish the monitoring session.
The data chunks that follows are BPL lists with three elements: the function name, the new value returned by the function and the server time (in milliseconds) when that value was sent.
All chunks are ended by a LF (line feed) character followed by a CR+LF that mandates the chuncked protocol.
The server will continue sending data until the client close the connection or an unwatch request is received.
When none of the monitored functions change for a period greater than 30 seconds (monitorPingTime server parameter) a LF (line feed) character is sent (as a ping message) to check if the connection has been closed.
An application that has an active monitoring session can inform the server that it is no longer interested in receiving data with an unwatch request. These requests are identical to watch requests but instead of a list of exterior functions, its body must contain the monitoring session identifier obtained in the previous watch request.
POST /facility HTTP/1.1 Host: localhost:9999 Monitor: 1000 Content-Type:text/plain; charset=utf-8 Content-Length:39 "1d01e78e-212e-4fe7-bb1d-d28312c4645e"
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Date:Sat, 04 Nov 2017 19:39:59 GMT Server: Brain4it Content-Type:text/plain; charset=utf-8 Content-Length:11 "unwatched"