Commit c68ca5e98eadb5d11eb907940b53d466ef0bd1c2

Authored by Alain Klotz
2 parents eb3a0070 787f04a2
Exists in dev

Merge branch 'dev' of https://gitlab.irap.omp.eu/pyros-irap/pyros into dev

.gitignore
... ... @@ -58,13 +58,6 @@ old/
58 58  
59 59 out.*
60 60  
61   -OLD/*
62   -*_OLD*
63   -*_ORIG*
64   -*.ORIG
65   -TMP/*
66   -
67   -client.log
68 61  
69 62 docker/*.env
70 63  
... ... @@ -102,5 +95,18 @@ TOKEN
102 95 *.modif.*
103 96 *.moi
104 97 *.moi.*
  98 +*.me.*
  99 +*.me
  100 +*.me?
  101 +*.old
  102 +*.OLD
  103 +OLD/*
  104 +*_OLD*
  105 +*_ORIG*
  106 +*.ORIG
  107 +*.ORIG?
  108 +TMP/*
  109 +___*
  110 +client.log
105 111  
106 112 #privatedev/plugin/agent/triton/triton/CATALOGUES
... ...
Dockerfile
... ... @@ -68,7 +68,7 @@ RUN cd /usr/bin && ln -s python3 python
68 68 #RUN apt-get install -y python3-pip
69 69 RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
70 70 #RUN pip3 install --upgrade pip
71   -RUN python3.10 -m pip install --upgrade pip
  71 +RUN python3 -m pip install --upgrade pip
72 72  
73 73  
74 74  
... ... @@ -155,11 +155,11 @@ CMD ["x11vnc", "-create", "-forever"]
155 155  
156 156  
157 157  
158   -
159   -
160 158 # Get IRAP self signed certificate
161 159 RUN echo | openssl s_client -connect gitlab.irap.omp.eu:443 -servername gitlab.irap.omp.eu 2>/dev/null | openssl x509 > /etc/ssl/certs/gitlab.irap.omp.eu.crt
162 160  
  161 +
  162 +
163 163 #################################
164 164 # PyROS user (better than root) #
165 165 #################################
... ... @@ -178,8 +178,6 @@ USER pyros_user
178 178 # TODO: pourquoi numpy ??? A virer ?
179 179 #RUN pip install --user numpy
180 180  
181   -
182   -
183 181 # Copy local host machine files to image
184 182 COPY --chown=pyros_user:pyros_user . .
185 183 # Copy some aliases
... ... @@ -190,9 +188,12 @@ RUN cp .bash_aliases ..
190 188 # Adding local/bin to path to avoid pip warning
191 189 ENV PATH "$PATH:/home/pyros_user/.local/bin"
192 190  
  191 +
193 192 # Installing click on the image to prevent error on the first execution of the installation script
194   -RUN python3.10 -m pip install --user click
195   -RUN python3.10 -m pip install --user setuptools==58
  193 +RUN python3 -m pip install --user click
  194 +
  195 +RUN python3 -m pip install --user setuptools==58
  196 +
196 197 # (EP 23/3/2022) Installing pip-tools for the management of all the requirements*.txt files (python dependencies packages)
197 198 # NB :
198 199 # - pip-tools generates a smarter and smaller requirements.txt file than the traditional "pip freeze"
... ... @@ -200,14 +201,14 @@ RUN python3.10 -m pip install --user setuptools==58
200 201 # - Unfortunatly, it is difficult to use with several requirements*.txt files as it is the case for this software : pyros + sphinx + guitastro...
201 202 # - So we cannot yet use it completely and still have to use the traditional "pip install -r" anyway ...
202 203 # - But we can at least use it to generate all the requirements*.txt files in a far better format
203   -RUN python3.10 -m pip install --user pip-tools
  204 +RUN python3 -m pip install --user pip-tools
204 205  
205 206 # Installing packages required for Guitastro
206 207 RUN pip-compile ./vendor/guitastro/install/requirements.in
207   -RUN python3.10 -m pip install --user -r ./vendor/guitastro/install/requirements.txt
  208 +RUN python3 -m pip install --user -r ./vendor/guitastro/install/requirements.txt
208 209 # Maybe unnecessary because same requirements as for pyros requirements_dev (?)
209 210 #RUN pip install --user -r ./vendor/guitastro/install/requirements_dev.txt
210 211  
211 212 # Installing packages required for PyROS
212   -RUN python3.10 -m pip install --user -r ./install/requirements.txt
213   -RUN python3.10 -m pip install --user -r ./install/requirements_dev.txt
  213 +RUN python3 -m pip install --user -r ./install/requirements.txt
  214 +RUN python3 -m pip install --user -r ./install/requirements_dev.txt
... ...
config/pyros_observatory/general/schemas/schema_observatory-2.0.yml
... ... @@ -135,6 +135,20 @@ schema;schema_FN_CONTEXTS:
135 135 type: map
136 136 required: False
137 137 mapping:
  138 + pyros_skd:
  139 + type: map
  140 + required: False
  141 + mapping:
  142 + root_dir:
  143 + type: str
  144 + description:
  145 + type: str
  146 + extension:
  147 + type: str
  148 + naming:
  149 + type: str
  150 + pathnaming:
  151 + type: str
138 152 cal_L0:
139 153 type: map
140 154 required: False
... ...
docker/PYROS_DOCKER_INSTALL
1 1 #!/usr/bin/env bash
2 2  
3 3 # if no container is running
4   -if ! [ $(docker ps | grep 'pyros' | wc -l) -eq 4 ]
5   -then
  4 +if ! [ $(docker ps | grep 'pyros' | wc -l) -eq 4 ] ; then
6 5 echo "pyros-db or pyros weren't running, starting them..."
7 6 ./PYROS_DOCKER_START.bat
8 7 fi
9 8  
10 9 # while db container isn't ready to execute queries, wait 5 seconds
11   -if ! docker inspect pyros-db --format='{{.State.Health.Status}}' | grep -q 'healthy'
12   -then
  10 +#if ! docker inspect pyros-db --format='{{.State.Health.Status}}' | grep -q 'healthy' ; then
  11 +#fi
  12 +while ! docker inspect pyros-db --format='{{.State.Health.Status}}' | grep -q 'healthy' ; do
13 13 echo "db service isn't ready yet, waiting until it's ready..."
14   -fi
15   -while ! docker inspect pyros-db --format='{{.State.Health.Status}}' | grep -q 'healthy'
16   -do
17 14 sleep 5
18 15 heal_status=$(docker inspect pyros-db --format='{{.State.Health.Status}}')
19 16 echo "Current status : $heal_status"
20 17 done
21 18  
22   -# db container is ready to execture queries, we can start the installation
  19 +# db container is ready to execture queries
  20 +# We can now start the installation
23 21 docker-compose exec pyros python3 pyros.py install
24 22  
... ...
docker/PYROS_DOCKER_RUN_WEBSERVER_ONLY
1 1 #!/usr/bin/env bash
2 2  
3 3 #if no container is running
4   -if ! [ $(docker ps | grep 'pyros' | wc -l) -eq 4 ]
5   -then
  4 +if ! [ $(docker ps | grep 'pyros' | wc -l) -eq 4 ] ; then
6 5 echo "pyros-db or pyros weren't running, starting them..."
7 6 ./PYROS_DOCKER_START.bat
8 7 fi
9   -docker-compose exec pyros python3 pyros.py -d start webserver $@
  8 +
  9 +docker compose exec pyros python3 pyros.py -d start webserver $@
  10 +#docker-compose exec pyros python3 pyros.py -d start webserver $@
  11 +#docker compose exec pyros python3 pyros.py -d start -o tnc -fg webserver $@
10 12 #docker exec -it pyros python3 pyros.py start webserver $@
11 13 #docker exec -it pyros python3 pyros.py -d start -o tnc webserver $@
... ...
docker/docker-compose.yml
1 1 version: "3.9"
2 2  
3 3 services:
  4 +
  5 + #######################
  6 + # MYSQL - DBMS
  7 + #######################
4 8 db:
5 9 # if we're using mysql >= 8, some of sql queries aren't valid anymore, like for creating and grant an user at the same time
6 10 # This is fixed in pyros.py
  11 + container_name: pyros-db
7 12 image: mysql:8.0.28
8   - command: --default-authentication-plugin=mysql_native_password
9 13 restart: always
  14 + command: --default-authentication-plugin=mysql_native_password
  15 + environment:
  16 + # note : as db is an image of mysql, this root password will be set on the first installation on the image, if the value is changed, it will not be updated in the database
  17 + - "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-root}"
  18 + - VNC_NO_PASSWORD=1
  19 + env_file:
  20 + - .env
  21 + volumes:
  22 + - db:/var/lib/mysql/
10 23 deploy:
11 24 restart_policy:
12 25 condition: on-failure
... ... @@ -15,29 +28,26 @@ services:
15 28 limits:
16 29 cpus: '0.5'
17 30 memory: 1GB
18   - #pids: 1
19   - container_name: pyros-db
20   - environment:
21   - # note : as db is an image of mysql, this root password will be set on the first installation on the image, if the value is changed, it will not be updated in the database
22   - - "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-root}"
23   - - VNC_NO_PASSWORD=1
24   - volumes:
25   - - db:/var/lib/mysql/
  31 + #pids: 1
26 32 # create network to allow images to communicate with other images within the same network
27 33 # networks:
28 34 # pyros-network:
29 35 # ipv4_address: 172.19.0.2
30   -
31 36 healthcheck:
32 37 test: ["CMD", 'mysqladmin', 'ping', '-h', 'db', '-u', 'root', '-p$$MYSQL_ROOT_PASSWORD' ]
33 38 timeout: 10s
34 39 interval: 5s
35 40 retries: 20
36 41  
  42 + ######################################################
  43 + # REDIS - in memory communication bus (for websockets)
  44 + ######################################################
37 45 redis:
38 46 container_name: pyros-redis
39 47 image: redis:latest
40 48 restart: always
  49 + ports:
  50 + - "6379:6379"
41 51 deploy:
42 52 restart_policy:
43 53 condition: on-failure
... ... @@ -46,9 +56,7 @@ services:
46 56 limits:
47 57 cpus: '1'
48 58 memory: 1GB
49   - #pids: 1
50   - ports:
51   - - "6379:6379"
  59 + #pids: 1
52 60 healthcheck:
53 61 test: ["CMD", "redis-cli","ping"]
54 62 timeout: 10s
... ... @@ -58,22 +66,19 @@ services:
58 66 # pyros-network:
59 67 # ipv4_address: 172.19.0.5
60 68  
61   - # Service image of python, that lets users interact with python scripts such as pyros.
  69 + ######################################################
  70 + # PYROS (main image : docker_pyros) => defined in Dockerfile
  71 + # Ubuntu OS with Python3 and PyROS requirements installed
  72 + # PyROS will later be installed on this image with "pyros.py install" (PYROS_DOCKER_INSTALL)
  73 + ######################################################
62 74 pyros:
  75 + container_name: pyros
  76 + restart: always
63 77 #read_only: true
64 78 # app/pyros is equivalent to your PYROS_SOFT/PYROS/ directory
65 79 # Change "pyros" to whatever you want for the PYROS/ dir name (if you do not want "PYROS")
66 80 working_dir:
67 81 /home/pyros_user/app/pyros
68   - deploy:
69   - restart_policy:
70   - condition: on-failure
71   - max_attempts: 5
72   - resources:
73   - limits:
74   - cpus: '1'
75   - memory: 8GB
76   - #pids: 1
77 82 # path to the Dockerfile of this image
78 83 environment:
79 84 # environment variables only for Docker
... ... @@ -93,7 +98,6 @@ services:
93 98 uid: ${CURRENT_UID}
94 99 context: ..
95 100 #filename: Dockerfile
96   - container_name: pyros
97 101 hostname: ${COMPUTER_HOSTNAME}
98 102 # tty is the -t option in docker exec
99 103 tty: true
... ... @@ -112,28 +116,47 @@ services:
112 116 links:
113 117 - db
114 118 - redis
  119 + deploy:
  120 + restart_policy:
  121 + condition: on-failure
  122 + max_attempts: 5
  123 + resources:
  124 + limits:
  125 + cpus: '1'
  126 + memory: 8GB
  127 + #pids: 1
115 128 # create network to allow images to communicate with other images within the same network
116 129 # networks:
117 130 # pyros-network:
118 131 # ipv4_address: 172.19.0.3
119 132 #ipv4_address: "${IP_PYROS_USER}"
120   - restart: always
121 133 healthcheck:
122 134 test: ["CMD", "python3","-V"]
123 135 timeout: 10s
124 136 interval: 5s
125 137 retries: 20
126 138  
127   -
  139 + ######################################################
  140 + # PHPMYADMIN (to interact manually with mysql db)
  141 + # (dev only)
  142 + ######################################################
128 143 phpmyadmin:
129   - image: phpmyadmin/phpmyadmin
130 144 container_name: pyros-pma
  145 + image: phpmyadmin/phpmyadmin
  146 + restart: always
131 147 links:
132 148 - db
133 149 environment:
134 150 PMA_HOST: db
135 151 PMA_PORT: 3306
136 152 PMA_ARBITRARY: 1
  153 + env_file:
  154 + - .env
  155 + # networks:
  156 + # pyros-network:
  157 + # ipv4_address: 172.19.0.4
  158 + ports:
  159 + - "${PHPMYADMIN_PORT:-8081}:80"
137 160 deploy:
138 161 restart_policy:
139 162 condition: on-failure
... ... @@ -143,15 +166,6 @@ services:
143 166 cpus: '1'
144 167 memory: 1GB
145 168 #pids: 1
146   -
147   - env_file:
148   - - .env
149   - restart: always
150   - # networks:
151   - # pyros-network:
152   - # ipv4_address: 172.19.0.4
153   - ports:
154   - - "${PHPMYADMIN_PORT:-8081}:80"
155 169 healthcheck:
156 170 test: ["CMD", 'mysqladmin', 'ping', '-h', 'db', '-u', 'root', '-p$$MYSQL_ROOT_PASSWORD' ]
157 171 timeout: 10s
... ... @@ -159,12 +173,16 @@ services:
159 173 retries: 20
160 174  
161 175  
162   -
163   -# declaring volumes
  176 +######################################################
  177 +# Declaring volumes
  178 +######################################################
164 179 volumes:
165 180 db:
166 181 driver: local
167   -# declaring networks
  182 +
  183 +######################################################
  184 +# Declaring networks
  185 +######################################################
168 186 # networks:
169 187 # pyros-network:
170 188 # #bridge is the default network driver
... ...
pyros.py
... ... @@ -174,7 +174,7 @@ SQL_USER = ""
174 174 SQL_PSWD = ""
175 175 MYSQL_EXE_PATH = ""
176 176  
177   -ENV_PATH = "docker/variables.env"
  177 +ENV_PATH = "docker/.env"
178 178 ENV_SAMPLE_PATH = "docker/.env-sample"
179 179  
180 180  
... ... @@ -476,7 +476,7 @@ def shell():
476 476 os.environ["PATH_TO_OBSCONF_FOLDER"] = os.path.join(os.path.abspath(
477 477 PYROS_DJANGO_BASE_DIR), "../../../config/pyros_observatory/pyros_observatory_default/")
478 478 os.environ["PATH_TO_OBSCONF_FILE"] = os.path.join(os.path.abspath(
479   - PYROS_DJANGO_BASE_DIR), os.environ["PATH_TO_OBSCONF_FOLDER"] + "observatory_default.yml")
  479 + PYROS_DJANGO_BASE_DIR), os.environ["PATH_TO_OBSCONF_FOLDER"] + "observatory.yml")
480 480 print("Execution commande shell")
481 481 print("NAME IS", __name__)
482 482 print()
... ... @@ -579,7 +579,7 @@ def install_or_update(UPDATE: bool = False, with_packages: bool = True, with_dat
579 579 os.environ["PATH_TO_OBSCONF_FOLDER"] = os.path.join(os.path.abspath(
580 580 PYROS_DJANGO_BASE_DIR), "../../../config/pyros_observatory/pyros_observatory_default/")
581 581 os.environ["PATH_TO_OBSCONF_FILE"] = os.path.join(os.path.abspath(
582   - PYROS_DJANGO_BASE_DIR), os.environ["PATH_TO_OBSCONF_FOLDER"] + "observatory_default.yml")
  582 + PYROS_DJANGO_BASE_DIR), os.environ["PATH_TO_OBSCONF_FOLDER"] + "observatory.yml")
583 583 ACTION = "UPDATING" if UPDATE else "INSTALLING"
584 584  
585 585 # if WITH_DOCKER: with_database = True
... ... @@ -1681,6 +1681,7 @@ def install_observatory(observatory):
1681 1681 cloned_repo = Repo.clone_from(
1682 1682 f"https://gitlab.irap.omp.eu/pyros-irap/pyros_observatory_{observatory}.git", os.path.join(pyros_observatory_path, f"pyros_observatory_{observatory}"))
1683 1683 print("Cloned successfully: ", cloned_repo.__class__ is Repo)
  1684 + print(f"The observatory {observatory} has been installed in {os.path.join(pyros_observatory_path, f'pyros_observatory_{observatory}')}")
1684 1685 except GitError:
1685 1686 if not os.path.exists(os.path.join(pyros_observatory_path, f"pyros_observatory_{observatory}")):
1686 1687 print("No repository found. PyROS will create a copy of an default observatory that you can modify.")
... ...
src/core/pyros_django/majordome/doc/AgentMajordome_object_diag.pu deleted
... ... @@ -1,220 +0,0 @@
1   -
2   -@startuml
3   -
4   -!include <tupadr3/common>
5   -!include <tupadr3/font-awesome/server>
6   -
7   -
8   -
9   -/'
10   -UML class Diagram : can be displayed with PlantUML (plugin for Eclipse or for PyCharm)
11   -
12   -PlantUML:
13   -- How to install : https://projects.irap.omp.eu/projects/pyros/wiki/Project_Development#PlantUML
14   -- Eclipse plugin : http://plantuml.com/eclipse
15   -- class diagrams : http://plantuml.com/class-diagram
16   -- sequence diagrams : http://plantuml.com/sequence-diagram
17   -- state diagrams : http://plantuml.com/state-diagram
18   -- Use Case diagrams : http://plantuml.com/use-case-diagram
19   -- OLD Activity diagrams : http://plantuml.com/activity-diagram-legacy
20   -- NEW Activity diagrams : http://plantuml.com/activity-diagram-beta
21   -- Pre-processing (include...) : http://plantuml.com/preprocessing
22   -- GANTT diagrams : http://plantuml.com/gantt-diagram
23   -- REAL WORLD EXAMPLES !!! : https://real-world-plantuml.com/
24   -- For Python:
25   - - https://github.com/SamuelMarks/python-plantuml
26   - - https://pythonhosted.org/plantuml/
27   -
28   -UML diagrams theory : https://www.ibm.com/developerworks/rational/library/content/RationalEdge/sep04/bell/index.html
29   -'/
30   -
31   -title
32   -__**PyROS class diagram (AgentMajordome example)**__
33   -'<size:10><i>Version 16-10-2019</i></size>'
34   -
35   -end title
36   -
37   -
38   -
39   -/' Allow to mix object/class diagram with other symbols like a "server" symbol '/
40   -allowmixing
41   -
42   -FA_SERVER(sbig_device,SBIG detector) #Red
43   -FA_SERVER(gemini_device,Gemini telescope) #Red
44   -
45   -
46   -
47   -/' ======= AgentMajordome & AgentDevices ======= '/
48   -
49   -class AgentMajordome <<Singleton>> #yellow
50   -AgentMajordome -u-|> Agent
51   -AgentDevice -u-|> Agent
52   -
53   -/' Aliases to AgentDevices '/
54   -object AD_Telescope1
55   -object AD_FilterSelector1
56   -object AD_Shutter1
57   -object AD_Sensor1
58   -object AD_Shutter2
59   -
60   -/' Use l,r,u,d for left, right, up, or down row alignement '/
61   -AgentMajordome -d-> AD_Telescope1 : sends cmd to
62   -AgentMajordome -d-> AD_FilterSelector1 : sends cmd to
63   -AgentMajordome -d-> AD_Shutter1 : sends cmd to
64   -AgentMajordome -d-> AD_Sensor1 : sends cmd to
65   -AgentMajordome -d-> AD_Shutter2 : sends cmd to
66   -
67   -
68   -class DeviceController {
69   - ip, port
70   - channel: ClientChannel
71   - protocol: Protocol # abstract
72   - gen2nat_cmds: Gen2NatCmds # abstract
73   -}
74   -
75   -class DC_Mount {
76   - gen2nat_cmds: Gen2NatCmds # abstract
77   -}
78   -class DC_DetectorShutter {
79   - gen2nat_cmds: Gen2NatCmds # abstract
80   -}
81   -class DC_DetectorSensor {
82   - gen2nat_cmds: Gen2NatCmds # abstract
83   -}
84   -class DC_FilterSelector {
85   - gen2nat_cmds: Gen2NatCmds # abstract
86   -}
87   -
88   -
89   -
90   -
91   -/' ======= CHANNELS ======= '/
92   -
93   -DeviceController "1" o-r- "0..1" DeviceSimulator
94   -
95   -DeviceController o-d- ClientChannel
96   -class ClientChannelSerial #lightred
97   -class ClientChannelSocket #lightred
98   -class ClientChannelUSB #lightred
99   -ClientChannel <|-- ClientChannelSerial
100   -ClientChannel <|-- ClientChannelSocket
101   -ClientChannel <|-- ClientChannelUSB
102   -
103   -
104   -/' ======= GEMINI controllers (& sim) ======= '/
105   -
106   -class AgentDeviceGemini #lightblue
107   -AgentDeviceGemini -u--|> AgentDevice
108   -
109   -/' Components (only 1) '/
110   -AD_Telescope1 -d-> AgentDeviceGemini :alias of
111   -
112   -/'DC_Mount o-left- DS_Mount'/
113   -
114   -/'AgentDeviceGemini ---> DC_Gemini :use'/
115   -AgentDeviceGemini "1" o--- "1" DC_Gemini :use
116   -
117   -/' Controllers '/
118   -class DC_Gemini {
119   - (client)
120   - protocol: Protocol # gemini
121   - gen2nat_cmds: Gen2NatCmds # gemini
122   -}
123   -class DC_Gemini <<Singleton>> #lightblue
124   -DC_Gemini <.l> gemini_device : channel/\nsocket
125   -DC_Gemini ---|> DeviceController
126   -DC_Gemini "*" o-- "1" DC_Mount
127   -DC_Mount --|> DeviceController
128   -
129   -/' Simulators '/
130   -class DS_Gemini {
131   - (server)
132   - protocol: Protocol # gemini
133   - gen2nat_cmds: Gen2NatCmds # gemini
134   -}
135   -class DS_Gemini #lightblue
136   -DS_Gemini ---|> DeviceSimulator
137   -DC_Gemini "1" o- "1" DS_Gemini
138   -
139   -
140   -
141   -/' ======= SBIG controllers (& sim) ======= '/
142   -
143   -class AgentDeviceSBIG <<Singleton>> #lightgreen
144   -AgentDeviceSBIG -u--|> AgentDevice
145   -
146   -/' Components (3) '/
147   -AD_FilterSelector1 --> AgentDeviceSBIG :alias of
148   -AD_Shutter1 --> AgentDeviceSBIG :alias of
149   -AD_Sensor1 --> AgentDeviceSBIG :alias of
150   -
151   -AgentDeviceSBIG "1" o-d-> "1" DC_SBIG :use
152   -DC_SBIG "1" o- "1" DS_SBIG
153   -
154   -/' Controllers '/
155   -
156   -class DC_SBIG {
157   - (client)
158   - protocol: Protocol # sbig
159   - gen2nat_cmds: Gen2NatCmds # sbig
160   -}
161   -class DC_SBIG <<Singleton>> #lightgreen
162   -
163   -DC_SBIG <.r> sbig_device : channel/\nsocket
164   -DC_SBIG ---|> DeviceController
165   -DC_SBIG "*" o-down- "0..1" DC_DetectorSensor
166   -DC_SBIG "*" o-down- "0..1" DC_DetectorShutter
167   -DC_SBIG "*" o-down- "0..1" DC_FilterSelector
168   -
169   -DC_DetectorSensor --|> DeviceController
170   -DC_DetectorShutter --|> DeviceController
171   -DC_FilterSelector --|> DeviceController
172   -
173   -/' Simulators '/
174   -class DS_SBIG {
175   - (server)
176   - protocol: Protocol # sbig
177   - gen2nat_cmds: Gen2NatCmds # sbig
178   -}
179   -class DS_SBIG #lightgreen
180   -DS_SBIG ---|> DeviceSimulator
181   -
182   -
183   -/' ======= NOTES ======= '/
184   -
185   -skinparam noteFontSize 9
186   -
187   -note left of DeviceController
188   -Device <b>client</b> (pyros <b>generic commands</b> only):
189   -- Defines (or receives) its own protocol
190   - and "generic to native" commands dictionary (gen2nat_cmds)
191   -- Translates an agent <b>generic</b> command to a native command,
192   - and sends it to device (or DS)
193   -- Receives device's native answer, translates it to <b>generic</b>
194   - and returns it back to agent
195   -(//every DC can include a **DS of the same name**//)
196   - end note
197   -
198   -note bottom of DeviceSimulator
199   -Device placeholder <b>server</b> (<b>native commands</b> only):
200   -- Receives <b>native</b> commands from client
201   -- Returns (simulated) <b>native</b> answer to client
202   -(uses protocol and gen2nat_cmds given by its associated DC)
203   -(//abstract DS receive only generic commands and return generic answers//)
204   - end note
205   -
206   -
207   -
208   -/' ======= LEGEND ======= '/
209   -
210   -skinparam legendFontSize 9
211   -
212   -legend left
213   -<i>Version 06-11-2019</i>
214   -AD = <b>Agent Device</b> ; DC = <b>Device Controller</b> ; DS = <b>Device Simulator</b>
215   -Colors: <b>(light) yellow</b> : abstract classes ; <b>red</b> : real devices ; <b>blue</b> : Gemini concrete classes ; <b>green</b> : SBIG concrete classes
216   -endlegend
217   -'(E. Pallier)
218   -
219   -
220   -@enduml