# Server - developer documentation

## File tree

```
./graphs
    /setup_info_examples/       <-- Contains some examples out of the nicos/se_main measurement, field setup_info (these examples are not full setup_info value, they correspond to the value "content" in the _extract_variables method in the file influxdb.py)
chart_config.py                 <-- Contains the ChartConfig class that represent a chart configuration (chart section out of generic.ini or <instrument>.ini)
circularlog.py                  <-- Allows to log messages to some log files, with a maximum length of 80 messages
colors.py                       <-- Allows color assignement to the available variables taken from InfluxDB
influxdb.py                     <-- Contains all InfluxDB related code
influxgraph.py                  <-- Implements the different routes when InfluxDB is used for the history
seagraph.py                     <-- Implements some classes and functions used in the SeaGraph class
seaweb.py                       <-- Main file (see seaweb.py section)
tcp_lineserver.py               <-- Holds the necessary code for the communication (TCP) the for right part
```

## seaweb.py

This file is the main one for the server.

### Serving the application

The Python module gevent is used to serve the different routes.

Routes are managed with the Flask Python module. All routes are indicated with `@app.route` and refer to one function. Multiple routes can refer to the same Python function, as it is the case for the API and some files. The routes serve :
- Files, as response to an URI or any files refered in some HTML code, or for the /export route : all functions that return `general_file` or `send_file`
- API functions (called on clients) : the `reply` function that returns `application/json` content
- Other : 
    - the `/update` route which is assigned to a generator for the SSE connection
    - the `/circular` route which logs the buffered messages and return the string "log"
    - the `/clients` route which returns HTML with information about connected clients

### Instrument

When the the server is started, a global variable `instrument` is assigned in the `if __name__ == "__main__"` condition, holding an `Instrument` instance (derived depending on the type of instrument) which contains a list of the corresponding client types that are connected to the server. The derived `Instrument` classes need to override the method `newClient` in order to specify which type of client needs to be added when a new client is connecting. These derived classes can implement other methods that might be required when a client needs special information about the current instrument.

The possible instrument types are the following :
- `sea` (OBSOLETE) : creates an instance of `SeaInstrument`, which registers `SeaClient`. This uses SEA for both history and control.
- `influxsea` : creates an instance of `SeaInfluxInstrument`, which registers `SeaInfluxClient`. This uses SEA for the control and Influx for the history.
- `influx` : creates an instance of `InfluxInstrument`, which registers `InfluxClient`. This uses Influx for the history, and does not have control part.
- `dummy` (NOT TESTED IN RECENT DEVELOPMENTS, PROBABLY OBSOLETE) : creates an instance of `DummyInstrument`, which registers `DummyClient`. This uses SEA for the history, and does not have control part.
- `secop` (NOT TESTED IN RECENT DEVELOPMENTS) : creates an instance of `SecopInstrument`, which registers `SecopClient`. This uses directly TCP to communicate for the control part.

The previously indicated behavior for the instruments are defined in the corresponding client class.

In any cases, the server needs an instrument name in order to run, which is given by the key `instrument` in the arguments passed to run this file.

### Clients

A client is a class representing a client connection to the server. It also implements some methods that are called in response to client requests.

As explained before, the instrument is responsible for creating and keeping track of connected clients in memory. In order for a client to connect, it first requests for the /update route (which will stay open), that creates an instance of the right client type (depending on the implementation of `newClient`) on the instrument, which assigns it an id. This is intended for the SSE connection, but also help to find the right client instance with which the server needs to call the methods. Then, each time a client makes a request, it will have to send its previously given id.

As explained, each client implements some methods that will be called to client requests. These methods are identified by their name which have the format : `w_<route>`. All these methods return Python dictionnaries that can be converted to JSON response, except for the `w_export` method that returns bytes. These methods can be found directly in the definition of the client, or by inheritance from `SeaGraph`, `SeaParams`, `InfluxGraph` and/or `InfluxParams`. These four last classes were made to be able to factorize some code between the classes `SeaClient`, `SeaInfluxClient` and `InfluxClient`.

Each client defines a `poll` function that allows the loop in the `generator` function to get the messages from it.