Sockets¶
Data-stream interface¶
A simple method to export data through the network. The MORSE sockets
middleware will create one socket for each component. The service
simulation.list_streams
returns the list of available data streams, and the
service simulation.get_stream_port(<stream name>)
returns the port number
associated to this stream.
Data is shared as JSON object, encoded in utf-8 strings. As such, when
exchanging data with a particular component using this middleware, it is
necessary to create a similar data structure to the local_data
dictionary
in the component.
For example, when using telnet to connect to a
waypoint actuator, you need to send a message
like the following:
$ telnet localhost 60000
{"x":3.0, "y":5.0, "z":0.0, "tolerance":0.5, "speed":2.0}
The socket data-stream interface is implemented in morse.middleware.socket_datastream
.
Note
The port numbers used for the socket datastream interface start at 60000.
Configuration specificities¶
When configuring a component to export its data through socket, you can
specify the wished port
where you want the socket listens on. Note that it
is only an “hint”, in some case, it is not possible to satisfy all the
constraints.
foo.add_stream('socket', port = 60005)
Moreover, it is possible to enable some time synchronisation mechanism using the following parameters:
- time_sync: Optional: Enable or disable the time synchronisation mechanism. The default value is False
- sync_port: Optional: It is the port where the simulator waits for the signal of synchronisation. The default value is 6000.
To enable time synchronisation using the custom port 12000, you should do:
env.configure_stream_manager('socket', time_sync = True, sync_port = 12000)
If the time synchronisation mechanism is enabled and once someone is connected to the synchronisation port, the simulator will wait for a message (any string of length < 2048) at each turn of the simulation. Once the client disconnects, the simulator is free again to run at “normal” speed.
Service interface¶
Requests to components or MORSE itself can be sent through the socket interface.
The (ASCII) protocol is simple. Either:
id component service [parameters]
or:
id special
id
is a freely chosen request id. It is mainly useful to identify answers from asynchronous services.component
is the name of the component you want to invoke the service on.
Note
Services that control the whole simulator belong to the special component simulation
.
service
: the name of the request to invoke.parameters
(can be omitted if the request takes no argument): request arguments in JSON format. Arguments must be enclosed in a list (i.e., inside brackets).special
: a special command, used to manipulate already existing requests. Currently, the only special command iscancel
(to abort a running service)
MORSE answer follows this model:
id status [result]
id
the same id the client used to send the request,status
: one of themorse.core.status
constantsresult
: a JSON-serialized result, if any.
Example:
$ telnet localhost 4000
Connected to localhost.
> req1 Human move [1.0, 2.0]
req1 OK
Note
The socket service interface listen by default on port 4000. If this port is busy, MORSE will try to connect to the next 10 ports {4001-4010} before giving up.
Note
Why 4000?? That’s a good question! A free beer for the first one who finds out.
The socket service interface is implemented in morse.middleware.socket_request_manager
.
Files¶
- Python (data-stream):
$MORSE_ROOT/src/morse/middleware/socket_datastream.py
- Python (services):
$MORSE_ROOT/src/morse/middleware/socket_request_manager.py