DUECA/DUSIME
|
Webserver providing access to DUECA channels. More...
#include <WebSocketsServer.hxx>
Public Member Functions | |
WebSocketsServer (Entity *e, const char *part, const PrioritySpec &ts) | |
Constructor. | |
bool | complete () final |
Continued construction. | |
template<typename S > | |
bool | _complete (S &server) |
Helper function, templated with the server type. | |
void | codeData (std::ostream &s, const DCOReader &r) const final |
Code the data in the reader object. | |
void | codeEmpty (std::ostream &s) const final |
Code the data in the reader object. | |
void | codeEntryInfo (std::ostream &s, const std::string &w_dataname, unsigned w_entryid, const std::string &r_dataname, unsigned r_entryid) const final |
Code the type information in the reader object. | |
~WebSocketsServer () | |
Destructor. | |
Public Member Functions inherited from dueca::websock::WebSocketsServerBase | |
WebSocketsServerBase (Entity *e, const char *part, const PrioritySpec &ts, const char *classname, unsigned char marker) | |
Constructor. | |
template<typename S > | |
bool | _complete_http (S &server) |
Helper function, templated with the server type. | |
virtual | ~WebSocketsServerBase () |
Destructor. | |
bool | setTimeSpec (const TimeSpec &ts) |
Specify a time specification for the simulation activity. | |
bool | checkTiming (const vector< int > &i) |
Request check on the timing. | |
bool | setCurrentData (const std::vector< std::string > &i) |
Define a URL for reading latest data. | |
bool | setFollowData (const std::vector< std::string > &i) |
Define a URL for following all data in a channel entry. | |
bool | setChannelInfo (const std::vector< std::string > &i) |
Define a URL for tracking changes in a channel. | |
bool | setWriterSetup (const std::vector< std::string > &i) |
Define a URL for writing to a channel. | |
bool | setPresetWriterSetup (const std::vector< std::string > &i) |
Define a URL for writing to a channel. | |
bool | setWriteReadSetup (const std::vector< std::string > &i) |
Two-way communication set-up. | |
bool | setCertFiles (const std::vector< std::string > &i) |
Set SLL certificates; will convert to use SSL. | |
bool | addMimeType (const std::vector< std::string > &i) |
Add a mime type. | |
bool | isPrepared () final |
indicate that everything is ready. | |
void | startModule (const TimeSpec &time) final |
start responsiveness to input data. | |
void | stopModule (const TimeSpec &time) final |
stop responsiveness to input data. | |
void | doTransfer (const TimeSpec &ts) |
the method that implements the main calculation. | |
unsigned char | getMarker () const |
sending marker, binary or string | |
Public Member Functions inherited from dueca::Module | |
virtual | ~Module () |
Destructor. | |
virtual bool | isInitialPrepared () |
To check whether the module is prepared to be prepared. | |
ObjectType | getObjectType () const |
The object type within DUECA. | |
virtual void | initialStartModule (const TimeSpec &time) |
Initial start opportunity. | |
virtual void | finalStopModule (const TimeSpec &time) |
Final stop command. | |
const Entity * | getMyEntity () |
Return a pointer to the entity to which this module belongs. | |
const ModuleState & | getState () |
Return the module state. | |
Public Member Functions inherited from dueca::NamedObject | |
const std::string | getEntity () const |
Returns the "entity" part of the name. | |
const std::string | getClass () const |
Returns the "class" part of the name. | |
const std::string | getPart () const |
Returns the sub-entity or "part" part of the name. | |
const NameSet & | getNameSet () const |
This returns the complete name set. | |
const GlobalId & | getId () const |
This returns the id. | |
Static Public Attributes | |
static const char *const | classname |
Name of the module. | |
Additional Inherited Members | |
Static Public Member Functions inherited from dueca::websock::WebSocketsServerBase | |
static const ParameterTable * | getMyParameterTable () |
Return the parameter table. | |
Protected Member Functions inherited from dueca::Module | |
Module (const Entity *e, const char *m_class, const char *part) | |
Constructor. | |
virtual void | setSafetyStop () |
Put a brake on this module's activities. | |
Protected Member Functions inherited from dueca::NamedObject | |
NamedObject (const GlobalId &id) | |
Reserve for AssociateObject. | |
NamedObject (const NameSet &ns) | |
Normal constructor, protected, because it has no use to create a NamedObject by itself. | |
virtual | ~NamedObject () |
Destructor. | |
Protected Attributes inherited from dueca::websock::WebSocketsServerBase | |
unsigned char | marker |
Marker token for the websocket send calls. | |
boost::scoped_ptr< WsServer > | server |
Server, uncoded. | |
boost::scoped_ptr< WssServer > | sserver |
Server, coded. | |
boost::scoped_ptr< HttpServer > | http_server |
Http server, uncoded. | |
boost::scoped_ptr< HttpsServer > | https_server |
Http Server, coded. | |
std::string | server_crt |
Certificate for ssl use, if certificate and key are configured, the ssl version is used. | |
std::string | server_key |
Associated key. | |
std::shared_ptr< boost::asio::io_context > | runcontext |
IO context to perform a run. | |
unsigned | port |
Port to be used. | |
unsigned | http_port |
Port for http server. | |
std::string | document_root |
Folder with files for http server. | |
std::map< std::string, std::string > | mimemap |
Mime types map. | |
bool | aggressive_reconnect |
Flag to indicate aggressive reconnection to preset entries. | |
bool | immediate_start |
Immediate start, do not wait on DUECA's commands. | |
bool | auto_started |
Start flag for immediate_start. | |
StateGuard | thelock |
Access lock for shared data. | |
PrioritySpec | read_prio |
Priority for reading. | |
TimeSpec | time_spec |
Timing specification. | |
bool | extended |
If true, use the extended, non-official JSON specification. | |
singleread_t | readsingles |
Mapping connecting URL details to an object that reads a specific channel entry. | |
singleread_t | autosingles |
Mapping connecting URL details to an object that reads a specific channel entry. | |
singlereadmap_t | singlereadsmapped |
Mapping connection id to SingleEntryRead objects. | |
followread_t | followers |
Mapping connecting URL details to an object that reads and follows the data in a specific channel entry. | |
followread_t | autofollowers |
Mapping connecting URL details to an object that reads and follows the data in a specific channel entry. | |
monitormap_t | monitors |
map from URL to monitors | |
writeables_t | writersetup |
map from URL to writer setup | |
presetwrites_t | presetwriters |
map with preconfigured writeables; these have the channel token created | |
writers_t | writers |
map from connection pointers to the actual writers | |
writereadables_t | writereadsetup |
map from URL to write/read combination setup | |
writersreaders_t | writersreaders |
map with active write/read combinations | |
Protected Attributes inherited from dueca::Module | |
ModuleState | state |
Flag to remember whether we are stopped due to some error with hardware device manipulation. | |
Webserver providing access to DUECA channels.
There are two possible variants for this server, "web-sockets-server", which communicates with JSON-coded messages, and "web-sockets-server-msgpack", which uses msgpack (binary) messages for communication.
This server can define a number of URL's:
URL | Description |
---|---|
/configuration | After opening the configuration URL, the client receives a message with all possible configured URL's, in the sections "current", "read", "info", "write" and "write-and-read".
|
/current/name?entry=.. | From a channel labeled "name", reads the current/latest data from the entry given. To get fresh data, write an empty message on the socket (will be discarded). Returns an object with a member "tick", indicating the time tick and single set of data defined in a member "data". If omitted from the URL, the entry id is assumed to be 0. The entry may have been explicitly configured from the start script, and thus its information was provided in the /configuration URL, or it was added by a channelwatcher, and information was provided in an /info/... url (see later). |
/read/name?entry=.. | From a channel labeled "name", and given entry, open a following read token. Receives all data as it comes in. Data push is provided by the DUECA side. For each new set of data, this returns an array with objects containing time tick and set of data defined. The read entries were either specifically configured (from /configuration), or they are available from information obtained through an info URL. |
/info/name |
Initiate information gathering for a specific channel. The watching capability (and thereby the url) must have been configured beforehand. For each entry in the channel, this returns an object with the following elements; 'dataclass', for the class of object, 'entry', giving the entry number, 'typeinfo', with an array of type information (see below). |
/write/name | Open a write entry for a channel. The data type may be specified in the start script of the module. The first message must be a json object with the member 'label'. Optionally, if this has a member 'ctiming' equal to true, the JSON or msgpack client provides the timing. If this object has a member 'event' equal to false, a stream channel is created; in that case ctiming must be true. If the datatype has not been configured beforehand, this needs to be supplied in the first message. Optionally a /write/name entry can have been created as preset. In that case, the write token is created at startup of the server, and writing will be immediately available. The write token and channel entry will also persist after a connection is lost, and then a new connection can assume the write entry and continue. |
/write-and-read/name | This uses a single bi-directional websocket connection for writing a single entry and reading a corresponding entry in another channel. Information on the data types is provided after completion of the connection. This needs a DUECA module that acts as a server, monitors the channel that is written to from the websocket connection, and creates a matching entry in the reply channel. The first message from the client must contain a member "dataclass", indicating the DCO type the client wishes to write. An entry in the configured channel is created with this dataclass. After the server has created a corresponding entry in the reply channel, (having the exact same label), a websocket message is sent back, defining the read and write entry numbers, dataclass and type information. After this, messages can be written, to which the server module should provide replies. |
Type information on the members of a dataclass, as returned by the channelinfo URL has the following structure:
key | Description |
---|---|
name | Name of the object's member |
type | Type / data class of the object (c++ name) |
size (optional) | For fixed size arrays, the size will be given |
array (optional) | For array/list types, this value will be True |
typeinfo (optional) | If the member is a nested DCO type, the typeinfo will be recursively presented in an array |
map (optional) | If the member is a mapped type (e.g. stl map), this value will be true |
keytype (optional) | If the member is a mapped type (e.g. stl map), this will contain the type / class of the used key |
The instructions to create an module of this class from the script are:
dueca.Module('web-sockets-server', <part name; string>, <PrioritySpec>).param( set_timing = <TimeSpec>, # Supply a time specification to define the update rate of the main activity check_timing = <array of integers>, # Supply three integer parameters to specify a check on the timing of # the main activity: warning limit (in us), critical limit (in us), and # the number of loops to test before sending a report (optional, dflt=2000) current = <array of strings>, # Set up a URL for simply reading the latest data from a single entry # in a channel. Specify the URL name, channel name, dataclass, and # optionally (in a string) the entry number. Data is returned whenever # requested by (an empty) message # This results in a URL /current/name?entry=... # The returned objects objects have members "tick" for timing and # "data" with the DCO object encoded in JSON or msgpack read_timing = <TimeSpec>, # Set the read timing for read data. TimeSpec(0,0) disables this # again, and will read at the rate the data was sent to the channel. extended = <boolean>, # Use the extended (sloppy) JSON, with NaN, Infinite and -Infinite. # Ensure any external clients understand this format. read = <array of strings>, # Set up a URL for tracking all data from a single entry in a channel. # Specify the URL name, channel name, dataclass, and optionally (in a # string) the entry number. Data is pushed to the client, if specified # before, the rate given by "read-timing" is used for readingThis results in a URL /read/name?entry=... # info = <array of strings>, # Set up a URL for obtaining information about channel entries. # Specify the URL name and channel name. Any discovered entries will # be available in the /current or /read URL'sConfiguring this results in a URL /info/name # Information will be provided upon completion of the websocket. write = <array of strings>, # Set up URL for writing to a channel. Specify URL name, channel name # and optionally the dataclass to be written. Any connects will first # need to send a JSON object with information for the written entry: # - "dataclass" <string>, needed if not specified in the arguments # - "label" <string>, mandatory # - "ctiming" <bool>, optional for event, mandatory for stream, # indicates that writer will supply timing # - "event", <bool>, optional, default true, event writing # - "stream", <bool>, optional, indicate stream channel # - "bulk", <bool>, optional, send data in bulk priority # - "diffpack", <bool>, optional, use differential pack for sending # For stream channels, timing information *must* be supplied. Subsequent # messages carry "tick" (if timing supplied, single int for event, # two int's for stream), and "data" for the data struct. # This results in a URL /write/name, each connection creates an entry write_preset = <array of strings>, # Set up URL for writing to a channel. Specify URL name, channel name, # data class and a label for the channel entry. Optional keywords # - "ctiming" <bool>, optional for event, mandatory for stream, # indicates that writer will supply timing # - "event", <bool>, optional, default true, event writing # - "stream", <bool>, optional, indicate stream channel # - "bulk", <bool>, optional, send data in bulk priority # - "diffpack", <bool>, optional, use differential pack for sending # The first JSON message carries the "timing", "event" / "stream" # information, this must match the information specified here. This # creates a single persistent channel entry, only one client can # connect to this entry and write to it. After a disconnect, a new # connection can be made. This results in a URL /write/name. aggressive_reconnect = <boolean>, # Normally a preset entry is only reconnected after the connection with # the previous client has been closed. Setting this variable to true # makes reconnection more aggressive; old connections are closed and # a new connection is always made. immediate_start = <boolean>, # Start as soon as possible, i.e., when watched channels are valid # This is normally only needed for specific debugging purposes. write_and_read = <array of strings>, # Set up a URL connecting a reading and writing channel set. Specify # URL name, channel name for writing, channel name for reading, # optionally, add "bulk" for bulk sending mode and "diffpack" for # differential packing. # The communication is event-based, the first message from the client # should have a JSON struct with information on the written dataclass # ( { "dataclass": ... } ). The first received message will have # information on both dataclasses and channel connections: # ( { "write": { "dataclass": ..., "entry": ##, "typeinfo": {...}}, # ( "read": { "dataclass": ..., "entry": ##, "typeinfo": {...}} # The DUECA module servicing this connection will need to create matching # entries to any write created by a connection, using the same label as # generated by the socket server. # This results in a URL /write-and-read/name, each connection creates a # pair of entries, for completion you need a DUECA module monitoring the # written channel and submitting an entry in the reading channel with a # label matching the written entry port = <uint32_t>, # Server port to be used, default is 8001. http_port = <uint32_t>, # If selected by setting a path, http server port, default is 8000. document_root = <string>, # Location of static files to serve over http; if not supplied, no # http server is created. # certfiles = <array of strings>, # Certificate files for SSL, specify a .crt and a .key file. If these # are supplied, wss sockets will be used instead of ws add_mimetype = <array of strings>, # Add a mime type for an extension, specify the extension (with '.') # and the mime type string ) '''Description: JSON/msgpack server providing access to selected channels and channel entries with websockets.'''
For the configuration of the server, the following options are available.
Manually setting up a /current URL. This specifies a channel entry from a specific channel. Meaningful only for channels with stream data (otherwise you might miss events if reading is not fast enough).
Manually setting up a /read URL. Useful for following events and for obtaining all data written in a channel, e.g. for plotting.
Setting up a /info URL. This can be read to follow changes, and to obtain (initially) the configuration of a channel. With the data one can choose to either open read URL's or current URL's; with an info URL configured, the corresponding read or current URL become available, given that the entries are created.
Setting up a /write URL. The /write URL links the endpoint to the channel name. The first message to such a write URL needs the selection of dataclass, label, and timing control (timing supplied by the websockets side, or added by DUECA on basis of actual time).
Setting up a /write URL with preset/pre-defined entry. In this case, the channel is opened immediately, and a single entry is entered in the channel. This mode is useful if you want the channel entry to be present for the rest of the simulation. If for some reason the websockets connection is broken, a new connection will take its place.
To provide static datafiles (e.g., to start off your javascript program), the module may be configured to act as a very simple web server as well, serving files from a single folder. To get better compatibility with browsers, also configure the mime types for these files.
dueca::websock::WebSocketsServer< Encoder, Decoder >::WebSocketsServer | ( | Entity * | e, |
const char * | part, | ||
const PrioritySpec & | ts ) |
Constructor.
Is normally called from scheme/the creation script.
|
finalvirtual |
Continued construction.
This is called after all script parameters have been read and filled in, according to the parameter table. Your running environment, e.g. for OpenGL drawing, is also prepared. Any lengty initialisations (like reading the 4 GB of wind tables) should be done here. Return false if something in the parameters is wrong (by the way, it would help if you printed what!) May be deleted.
Reimplemented from dueca::Module.
|
finalvirtual |
Code the data in the reader object.
Implements dueca::websock::WebSocketsServerBase.
|
finalvirtual |
Code the data in the reader object.
Implements dueca::websock::WebSocketsServerBase.
|
finalvirtual |
Code the type information in the reader object.
Implements dueca::websock::WebSocketsServerBase.