diff --git a/.gitignore b/.gitignore index 7f249738c56e97da80aaecaebb99c528eba78d3a..60c6519f7724a7ca08cac3263b595400dba9fdd2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,8 @@ **/.project **/.pydevproject **/.settings/org.eclipse.core.resources.prefs +tangostationcontrol/dist +tangostationcontrol/build +**/.ipynb_checkpoints +**/pending_log_messages.db +**/.eggs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0371a7f7f806a9a6e9ac5c22d8c5562c6880a4eb..f458c94bb5c002a69aac660d28736b4b0aa65f8a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,9 @@ # TODO(Corne): Update this image to use our own registry once building # images is in place. -image: artefact.skao.int/ska-tango-images-tango-itango:9.3.5 +image: artefact.skao.int/ska-tango-images-tango-itango:9.3.7 variables: + GIT_SUBMODULE_STRATEGY: recursive PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" - # The PBR dependency requires a set version, not actually used - # Instead `util/lofar_git.py:get_version()` is used. - PBR_VERSION: "0.1" cache: paths: - .cache/pip @@ -15,21 +13,29 @@ stages: - static-analysis - unit-tests - integration-tests + - packaging newline_at_eof: - stage: linting - before_script: - - pip3 install -r devices/test-requirements.txt - script: - - flake8 --filename *.sh,*.conf,*.md,*.yml --select=W292 --exclude .tox,.egg-info,docker + stage: linting + before_script: + - pip3 install -r tangostationcontrol/test-requirements.txt + script: +# TODO(Corne): Ignore shell files in submodules more cleanly + - flake8 --filename *.sh,*.conf,*.md,*.yml --select=W292 --exclude docker-compose/tango-prometheus-exporter,.tox,.egg-info,docker python_linting: stage: linting + before_script: + - sudo apt-get update + - sudo apt-get install -y git script: - - cd devices + - cd tangostationcontrol - tox -e pep8 bandit: stage: static-analysis + before_script: + - sudo apt-get update + - sudo apt-get install -y git script: - - cd devices + - cd tangostationcontrol - tox -e bandit shellcheck: stage: static-analysis @@ -37,6 +43,7 @@ shellcheck: - sudo apt-get update - sudo apt-get install -y shellcheck script: +# TODO(Corne): Ignore shell files in submodules - shellcheck **/*.sh unit_test: stage: unit-tests @@ -44,29 +51,47 @@ unit_test: - sudo apt-get update - sudo apt-get install -y git script: - - cd devices - - tox --recreate -e py37 -integration_test: + - cd tangostationcontrol + - tox -e py37 +integration_test_docker: stage: integration-tests - allow_failure: true + image: docker:latest tags: - privileged services: - - name: docker:20.10.8-dind + - name: docker:dind variables: DOCKER_TLS_CERTDIR: "/certs" -# Everything below does not work currently, we need a privileged container -# that can run the dind service before_script: - - sudo apt update - - sudo apt install -y docker.io - - export USER=$(id | awk -F'=' '{print $2}' | awk -F'(' '{print $2}' | awk -F')' '{print $1}') - - echo $USER -# - sudo usermod -aG docker $USER - - sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - apk add --update make bash docker-compose + - apk add --update bind-tools + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + script: + - touch /root/.Xauthority +# Hack BASH_SOURCE into sourced files, docker its sh shell won't set this + - export BASH_SOURCE=$(pwd)/bootstrap/etc/lofar20rc.sh +# Hack HOSTNAME env variable into host.docker.internal, set in docker-compose + - export HOSTNAME=host.docker.internal +# - export HOSTNAME=$(hostname -i) +# - export HOSTNAME=$(cat /run/systemd/netif/leases/2 | grep ^ADDRESS= | awk -F'=' '{print $2}') +# source the lofarrc file and mask its non zero exit code + - . bootstrap/etc/lofar20rc.sh || true +# TANGO_HOST must be unset our databaseds will be unreachable + - unset TANGO_HOST +# Allow integration test to execute + - chmod u+x $CI_PROJECT_DIR/sbin/run_integration_test.sh +# Do not remove 'bash' or statement will be ignored by primitive docker shell + - bash $CI_PROJECT_DIR/sbin/run_integration_test.sh +wheel_packaging: + stage: packaging + artifacts: + paths: + - tangostationcontrol/dist/*.whl + before_script: + - sudo apt-get update + - sudo apt-get install -y git + - pip3 install -r tangostationcontrol/test-requirements.txt + - pip3 install -r docker-compose/itango/lofar-requirements.txt script: - - touch /home/$USER/.Xauthority - - source bootstrap/etc/lofar20rc.sh - - export HOSTNAME=$(cat /run/systemd/netif/leases/2 | grep ^ADDRESS= | awk -F'=' '{print $2}') - - echo $HOSTNAME - - sudo $CI_PROJECT_DIR/sbin/run_integration_test.sh + - cd tangostationcontrol + - python setup.py bdist_wheel diff --git a/CDB/LOFAR_ConfigDb.json b/CDB/LOFAR_ConfigDb.json index e903a459ef687aa8ee11164c58cc0c22c43c1347..6886437ce7cf02ee741b5b70f07ebfbf71b08b4d 100644 --- a/CDB/LOFAR_ConfigDb.json +++ b/CDB/LOFAR_ConfigDb.json @@ -1,9 +1,9 @@ { "servers": { - "docker_device": { - "LTS": { + "Docker": { + "STAT": { "Docker": { - "LTS/Docker/1": {} + "STAT/Docker/1": {} } } }, @@ -14,24 +14,24 @@ } } }, - "observation_control": { - "LTS": { + "ObservationControl": { + "STAT": { "ObservationControl": { - "LTS/ObservationControl/1": {} + "STAT/ObservationControl/1": {} } } }, "boot": { - "LTS": { + "STAT": { "Boot": { - "LTS/Boot/1": {} + "STAT/Boot/1": {} } } }, "APSCT": { - "LTS": { + "STAT": { "APSCT": { - "LTS/APSCT/1": { + "STAT/APSCT/1": { "properties": { } } @@ -39,9 +39,9 @@ } }, "APSPU": { - "LTS": { + "STAT": { "APSPU": { - "LTS/APSPU/1": { + "STAT/APSPU/1": { "properties": { } } @@ -49,9 +49,9 @@ } }, "RECV": { - "LTS": { + "STAT": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "attribute_properties": { "Ant_mask_RW": { "archive_period": [ @@ -459,9 +459,9 @@ } }, "random_data": { - "LTS": { + "STAT": { "Random_Data": { - "LTS/random_data/1": { + "STAT/random_data/1": { "properties": { "polled_attr": [ "rnd1", @@ -513,7 +513,7 @@ ] } }, - "LTS/random_data/2": { + "STAT/random_data/2": { "properties": { "polled_attr": [ "rnd1", @@ -563,9 +563,9 @@ } }, "SDP": { - "LTS": { + "STAT": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "attribute_properties": { "SDP_mask_RW": { "event_period": [ @@ -736,9 +736,9 @@ } }, "SST": { - "LTS": { + "STAT": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5001" @@ -770,9 +770,9 @@ } }, "XST": { - "LTS": { + "STAT": { "XST": { - "LTS/XST/1": { + "STAT/XST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5002" @@ -804,9 +804,9 @@ } }, "UNB2": { - "LTS": { + "STAT": { "UNB2": { - "LTS/UNB2/1": { + "STAT/UNB2/1": { "properties": { } } diff --git a/CDB/integration_ConfigDb.json b/CDB/integration_ConfigDb.json index aa67083d5c849d9fb653726f71387d71057923a1..7cfbd82751791d7968315923edfc2ba971480308 100644 --- a/CDB/integration_ConfigDb.json +++ b/CDB/integration_ConfigDb.json @@ -1,9 +1,9 @@ { "servers": { "APSCT": { - "LTS": { + "STAT": { "APSCT": { - "LTS/APSCT/1": { + "STAT/APSCT/1": { "properties": { "OPC_Server_Name": [ "apsct-sim" @@ -20,9 +20,9 @@ } }, "APSPU": { - "LTS": { + "STAT": { "APSPU": { - "LTS/APSPU/1": { + "STAT/APSPU/1": { "properties": { "OPC_Server_Name": [ "apspu-sim" @@ -39,9 +39,9 @@ } }, "RECV": { - "LTS": { + "STAT": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "recv-sim" @@ -58,9 +58,9 @@ } }, "SDP": { - "LTS": { + "STAT": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ "sdptr-sim" @@ -125,9 +125,9 @@ } }, "SST": { - "LTS": { + "STAT": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5001" @@ -204,9 +204,9 @@ } }, "XST": { - "LTS": { + "STAT": { "XST": { - "LTS/XST/1": { + "STAT/XST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5002" @@ -283,9 +283,9 @@ } }, "UNB2": { - "LTS": { + "STAT": { "UNB2": { - "LTS/UNB2/1": { + "STAT/UNB2/1": { "properties": { "OPC_Server_Name": [ "unb2-sim" diff --git a/CDB/jasper_ConfigDb.json b/CDB/jasper_ConfigDb.json index 8455c1859e4a122f38b95be929c81a3af164aede..a156f34ce1e642da3637622439e1cc8f90b7bb4e 100644 --- a/CDB/jasper_ConfigDb.json +++ b/CDB/jasper_ConfigDb.json @@ -8,16 +8,16 @@ } }, "observation_control": { - "LTS": { + "STAT": { "ObservationControl": { - "LTS/ObservationControl/1": {} + "STAT/ObservationControl/1": {} } } }, "RECV": { - "LTS": { + "STAT": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "attribute_properties": { "Ant_mask_RW": { "archive_period": [ @@ -434,9 +434,9 @@ } }, "random_data": { - "LTS": { + "STAT": { "Random_Data": { - "LTS/random_data/1": { + "STAT/random_data/1": { "properties": { "polled_attr": [ "rnd1", @@ -488,7 +488,7 @@ ] } }, - "LTS/random_data/2": { + "STAT/random_data/2": { "properties": { "polled_attr": [ "rnd1", @@ -538,9 +538,9 @@ } }, "SDP": { - "LTS": { + "STAT": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "attribute_properties": { "SDP_mask_RW": { "event_period": [ @@ -720,9 +720,9 @@ } }, "SST": { - "LTS": { + "STAT": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "Statistics_Client_Port": [ "5001" @@ -742,9 +742,9 @@ } }, "UNB2": { - "LTS": { + "STAT": { "UNB2": { - "LTS/UNB2/1": { + "STAT/UNB2/1": { "properties": { "OPC_Server_Name": [ "despi.astron.nl" diff --git a/CDB/stations/DTS_ConfigDb.json b/CDB/stations/DTS_ConfigDb.json index 685a3d62da82e40aa05ea409c20f2475e3472ea5..c5bbf009334e47e2dd0eed89dbddea6889f83933 100644 --- a/CDB/stations/DTS_ConfigDb.json +++ b/CDB/stations/DTS_ConfigDb.json @@ -1,9 +1,9 @@ { "servers": { "APSCT": { - "LTS": { + "STAT": { "APSCT": { - "LTS/APSCT/1": { + "STAT/APSCT/1": { "properties": { "OPC_Server_Name": [ "DESPi3.nfra.nl" @@ -20,9 +20,9 @@ } }, "APSPU": { - "LTS": { + "STAT": { "APSPU": { - "LTS/APSPU/1": { + "STAT/APSPU/1": { "properties": { "OPC_Server_Name": [ "DESPi3.nfra.nl" @@ -39,9 +39,9 @@ } }, "RECV": { - "LTS": { + "STAT": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "DESPi3.nfra.nl" @@ -58,12 +58,12 @@ } }, "SDP": { - "LTS": { + "STAT": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ - "dop36.astron.nl" + "10.99.0.252" ], "OPC_Server_Port": [ "4840" @@ -95,12 +95,12 @@ } }, "SST": { - "LTS": { + "STAT": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "OPC_Server_Name": [ - "dop36.astron.nl" + "10.99.0.252" ], "OPC_Server_Port": [ "4840" @@ -127,22 +127,22 @@ "0c:c4:7a:c0:30:f1" ], "FPGA_sst_offload_hdr_ip_destination_address_RW_default": [ - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1" + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250" ] } } @@ -150,12 +150,12 @@ } }, "XST": { - "LTS": { + "STAT": { "XST": { - "LTS/XST/1": { + "STAT/XST/1": { "properties": { "OPC_Server_Name": [ - "dop36.astron.nl" + "10.99.0.252" ], "OPC_Server_Port": [ "4840" @@ -182,22 +182,22 @@ "0c:c4:7a:c0:30:f1" ], "FPGA_xst_offload_hdr_ip_destination_address_RW_default": [ - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1", - "10.99.0.1" + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250", + "10.99.250.250" ] } } @@ -205,9 +205,9 @@ } }, "UNB2": { - "LTS": { + "STAT": { "UNB2": { - "LTS/UNB2/1": { + "STAT/UNB2/1": { "properties": { "OPC_Server_Name": [ "DESPi3.nfra.nl" diff --git a/CDB/stations/LTS_ConfigDb.json b/CDB/stations/LTS_ConfigDb.json index 672ff0210a9bad8ed6c48db2f648393b8cee0069..7c03ff1434f5e88860d6d174ad7ce952750606b6 100644 --- a/CDB/stations/LTS_ConfigDb.json +++ b/CDB/stations/LTS_ConfigDb.json @@ -1,62 +1,17 @@ { "servers": { - "APSCT": { - "LTS": { - "APSCT": { - "LTS/APSCT/1": { - "properties": { - "OPC_Server_Name": [ - "ltspi.astron.nl" - ], - "OPC_Server_Port": [ - "4842" - ], - "OPC_Time_Out": [ - "5.0" - ], - "OPC_Node_Path_prefix": [ - "PCC" - ] - } - } - } - } - }, - "APSPU": { - "LTS": { - "APSPU": { - "LTS/APSPU/1": { - "properties": { - "OPC_Server_Name": [ - "ltspi.astron.nl" - ], - "OPC_Server_Port": [ - "4842" - ], - "OPC_Time_Out": [ - "5.0" - ], - "OPC_Node_Path_prefix": [ - "PCC" - ] - } - } - } - } - }, "RECV": { - "LTS": { + "STAT": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "ltspi.astron.nl" ], "OPC_Server_Port": [ - "4842" + "4840" ], "OPC_Node_Path_prefix": [ - "PCC" ], "OPC_Time_Out": [ "5.0" @@ -67,12 +22,12 @@ } }, "SDP": { - "LTS": { + "STAT": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ - "dop36.astron.nl" + "dop369.astron.nl" ], "OPC_Server_Port": [ "4840" @@ -104,9 +59,9 @@ } }, "SST": { - "LTS": { + "STAT": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5001" @@ -115,7 +70,7 @@ "5101" ], "OPC_Server_Name": [ - "dop36.astron.nl" + "dop369.astron.nl" ], "OPC_Server_Port": [ "4840" @@ -183,9 +138,9 @@ } }, "XST": { - "LTS": { + "STAT": { "XST": { - "LTS/XST/1": { + "STAT/XST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5002" @@ -194,7 +149,7 @@ "5102" ], "OPC_Server_Name": [ - "dop36.astron.nl" + "dop369.astron.nl" ], "OPC_Server_Port": [ "4840" @@ -260,28 +215,6 @@ } } } - }, - "UNB2": { - "LTS": { - "UNB2": { - "LTS/UNB2/1": { - "properties": { - "OPC_Server_Name": [ - "despi.astron.nl" - ], - "OPC_Server_Port": [ - "4842" - ], - "OPC_Node_Path_prefix": [ - "PCC" - ], - "OPC_Time_Out": [ - "5.0" - ] - } - } - } - } } } } diff --git a/CDB/stations/simulators_configDb.json b/CDB/stations/simulators_ConfigDb.json similarity index 94% rename from CDB/stations/simulators_configDb.json rename to CDB/stations/simulators_ConfigDb.json index 7d246bdd6cbc80b7f0cc3e21110265fdc4bbd81a..df2ffc1c1194282f7cc92cd0e7df1e5eb90b3a58 100644 --- a/CDB/stations/simulators_configDb.json +++ b/CDB/stations/simulators_ConfigDb.json @@ -1,9 +1,9 @@ { "servers": { "APSCT": { - "LTS": { + "STAT": { "APSCT": { - "LTS/APSCT/1": { + "STAT/APSCT/1": { "properties": { "OPC_Server_Name": [ "apsct-sim" @@ -20,15 +20,15 @@ } }, "APSPU": { - "LTS": { + "STAT": { "APSPU": { - "LTS/APSPU/1": { + "STAT/APSPU/1": { "properties": { "OPC_Server_Name": [ "apspu-sim" ], "OPC_Server_Port": [ - "4843" + "4842" ], "OPC_Time_Out": [ "5.0" @@ -39,9 +39,9 @@ } }, "RECV": { - "LTS": { + "STAT": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "recv-sim" @@ -58,9 +58,9 @@ } }, "SDP": { - "LTS": { + "STAT": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ "sdptr-sim" @@ -77,9 +77,9 @@ } }, "SST": { - "LTS": { + "STAT": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "OPC_Server_Name": [ "sdptr-sim" @@ -132,9 +132,9 @@ } }, "XST": { - "LTS": { + "STAT": { "XST": { - "LTS/XST/1": { + "STAT/XST/1": { "properties": { "OPC_Server_Name": [ "sdptr-sim" @@ -187,9 +187,9 @@ } }, "UNB2": { - "LTS": { + "STAT": { "UNB2": { - "LTS/UNB2/1": { + "STAT/UNB2/1": { "properties": { "OPC_Server_Name": [ "unb2-sim" diff --git a/CDB/test_ConfigDb.json b/CDB/test_ConfigDb.json index 7030e2d97166b244c3d3c682d4a975386510ecbc..7f7e69512d0e9475e5d640ba6033ce7819106101 100644 --- a/CDB/test_ConfigDb.json +++ b/CDB/test_ConfigDb.json @@ -3,7 +3,7 @@ "RECV": { "1": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "ltspi.astron.nl" @@ -16,7 +16,7 @@ "SDP": { "1": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ "dop36.astron.nl" @@ -29,7 +29,7 @@ "APSCTL": { "1": { "APSCTL": { - "LTS/APSCTL/1": { + "STAT/APSCTL/1": { "properties": { "OPC_Server_Name": [ "ltspi.astron.nl" @@ -48,7 +48,7 @@ "test_device": { "1": { "test_device": { - "LTS/test_device/1": { + "STAT/test_device/1": { "attribute_properties": { "Ant_mask_RW": { "archive_period": [ diff --git a/CDB/thijs_ConfigDb.json b/CDB/thijs_ConfigDb.json index 5cd6813622bc642a8e2fd4ce1001158da3977dae..6361533704fa01dc373b6c35f608772e89e9bdbc 100644 --- a/CDB/thijs_ConfigDb.json +++ b/CDB/thijs_ConfigDb.json @@ -3,7 +3,7 @@ "RECV": { "1": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "host.docker.internal" @@ -16,7 +16,7 @@ "SDP": { "1": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ "dop36.astron.nl" @@ -35,7 +35,7 @@ "example_device": { "1": { "example_device": { - "LTS/example_device/1": { + "STAT/example_device/1": { "properties": { "OPC_Server_Name": [ "host.docker.internal" @@ -54,7 +54,7 @@ "ini_device": { "1": { "ini_device": { - "LTS/ini_device/1": { + "STAT/ini_device/1": { "properties": { "OPC_Server_Name": [ "host.docker.internal" @@ -73,7 +73,7 @@ "APSCTL": { "1": { "APSCTL": { - "LTS/APSCTL/1": { + "STAT/APSCTL/1": { "properties": { "OPC_Server_Name": [ "ltspi.astron.nl" @@ -92,7 +92,7 @@ "SST": { "1": { "SST": { - "LTS/SST/1": { + "STAT/SST/1": { "properties": { "Statistics_Client_UDP_Port": [ "5001" @@ -117,7 +117,7 @@ "SNMP": { "1": { "SNMP": { - "LTS/SNMP/1": { + "STAT/SNMP/1": { "properties": { "SNMP_community": [ "public" diff --git a/CDB/thomas_ConfigDb.json b/CDB/thomas_ConfigDb.json deleted file mode 100644 index c1d50d969298798a95755fd340c9061f08762310..0000000000000000000000000000000000000000 --- a/CDB/thomas_ConfigDb.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "servers": { - "RECV": { - "LTS": { - "RECV": { - "LTS/RECV/1": { - "properties": { - "OPC_Server_Name": [ - "okeanos" - ] - } - } - } - } - }, - "SDP": { - "LTS": { - "SDP": { - "LTS/SDP/1": { - "properties": { - "OPC_Server_Name": [ - "okeanos" - ] - } - } - } - } - }, - "SST": { - "LTS": { - "SST": { - "LTS/SST/1": { - "properties": { - "OPC_Server_Name": [ - "okeanos" - ] - } - } - } - } - } - } -} diff --git a/CDB/thomas_arm64_ConfigDb.json b/CDB/thomas_arm64_ConfigDb.json deleted file mode 100644 index 0bf870680b8ff66ae6f46851b01870f4dd4f6ee8..0000000000000000000000000000000000000000 --- a/CDB/thomas_arm64_ConfigDb.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "servers": { - "RECV": { - "LTS": { - "RECV": { - "LTS/RECV/1": { - "properties": { - "OPC_Server_Name": [ - "arm2" - ] - } - } - } - } - }, - "SDP": { - "LTS": { - "SDP": { - "LTS/SDP/1": { - "properties": { - "OPC_Server_Name": [ - "okeanos" - ] - } - } - } - } - }, - "SST": { - "LTS": { - "SST": { - "LTS/SST/1": { - "properties": { - "OPC_Server_Name": [ - "okeanos" - ] - } - } - } - } - } - } -} diff --git a/CDB/windows_ConfigDb.json b/CDB/windows_ConfigDb.json index d00826eddf16687cc0329f68f8ae86b0543d7a82..ffc34ee01f505570da387bf6be81ec776f942f60 100644 --- a/CDB/windows_ConfigDb.json +++ b/CDB/windows_ConfigDb.json @@ -3,7 +3,7 @@ "RECV": { "1": { "RECV": { - "LTS/RECV/1": { + "STAT/RECV/1": { "properties": { "OPC_Server_Name": [ "host.docker.internal" @@ -16,7 +16,7 @@ "SDP": { "1": { "SDP": { - "LTS/SDP/1": { + "STAT/SDP/1": { "properties": { "OPC_Server_Name": [ "host.docker.internal" @@ -29,7 +29,7 @@ "ini_device": { "1": { "ini_device": { - "LTS/ini_device/1": { + "STAT/ini_device/1": { "attribute_properties": { "Ant_mask_RW": { "archive_period": [ @@ -55,7 +55,7 @@ "SNMP": { "1": { "SNMP": { - "LTS/SNMP/1": { + "STAT/SNMP/1": { "attribute_properties": { "Ant_mask_RW": { "archive_period": [ @@ -81,7 +81,7 @@ "test_device": { "1": { "test_device": { - "LTS/test_device/1": { + "STAT/test_device/1": { "attribute_properties": { "Ant_mask_RW": { "archive_period": [ diff --git a/bin/dump_ConfigDb.sh b/bin/dump_ConfigDb.sh index 7745c18482000fe2e7a726e27b6fa5eeae57e88e..0dc634c458b76cd5d3c13e2d7dab6e905f66248a 100755 --- a/bin/dump_ConfigDb.sh +++ b/bin/dump_ConfigDb.sh @@ -1,4 +1,4 @@ #!/bin/bash -# writes the JSON dump to stdout -docker exec -it dsconfig python -m dsconfig.dump +# writes the JSON dump to stdout, Do not change -i into -it incompatible with gitlab ci! +docker exec -i "${CONTAINER_NAME_PREFIX}"dsconfig python -m dsconfig. diff --git a/bin/itango_console.sh b/bin/itango_console.sh index fb4c9b8a285adca3211633fb89e6e9e59bd01087..c2474781787257c6ab3ee0656659415f09380b29 100755 --- a/bin/itango_console.sh +++ b/bin/itango_console.sh @@ -1,2 +1,2 @@ #!/bin/bash -exec docker exec -it itango itango3 +exec docker exec -it "${CONTAINER_NAME_PREFIX}"itango itango3 diff --git a/bin/itango_shell.sh b/bin/itango_shell.sh index abab9ef8515fd5ce1a1bf2d6d452a538426a499a..334953de3cca29ff459f6c861637c0859b1da97b 100755 --- a/bin/itango_shell.sh +++ b/bin/itango_shell.sh @@ -1,2 +1,2 @@ #!/bin/bash -exec docker exec -it itango /bin/bash +exec docker exec -it "${CONTAINER_NAME_PREFIX}"itango /bin/bash diff --git a/bin/start-DS.sh b/bin/start-DS.sh deleted file mode 100755 index 83a6eec6dd30f2e496fa03ffc6f7351d8e9a664d..0000000000000000000000000000000000000000 --- a/bin/start-DS.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -function help() -{ - why="${1}" - echo -e "*** Cannot start the Python device server.\\n${why}\\n\\n* The Python file for the device server must be the 1st parameter that is provided.\\n* The instance of this device server must be the 2nd parameter that is provided." - exit -1 -} - -# Check if the mandatory parameters are present: -# ${1}: device server's Python file -# ${2}: instance of the device server's executable in the configDB -case ${#} in - 0) - help "The device server's Python file and the instance are missing." - ;; - 1) - help "The device server's instance is missing." - ;; - *) - deviceServer="${1}" - shift - instance="${1}" - shift - ;; -esac - -# Find the path to the device server's Python file that is -# relative to the /hosthome directory (in Docker the user's -# mounted ${HOME}). -# ATTENTION -# This is assuming that the device server's Python file exists -# on the Docker's host in the user's ${HOME} directory. -runThis=$(basename "${deviceServer}") -runThis=${runThis//.sh/.py} -if [ -f "${runThis}" ]; then - myDir=${PWD} -else - myDir=${PWD}/$(dirname "${deviceServer}") -fi -deviceServerPath=${myDir/${HOME}/\/hosthome} - -# Tango log lines start with a UNIX timestamp. Replace them with the UTC time. -docker exec -it itango python3 "${deviceServerPath}/${runThis}" "${instance}" "${@}" | perl -ne 'use Time::Piece; s/^([0-9]+)/gmtime($1)->strftime("%F %T")/e; print;' diff --git a/bin/start-ds.sh b/bin/start-ds.sh new file mode 100755 index 0000000000000000000000000000000000000000..7b601c4c8f5e24ac56755ad08a1203a6cbba62d2 --- /dev/null +++ b/bin/start-ds.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Serves as entrypoint script for docker containers + +# Check required support file exists +if [[ ! -f "/usr/local/bin/wait-for-it.sh" ]]; then + >&2 echo "/usr/local/bin/wait-for-it.sh file does not exist!" + exit 1 +fi + +# Check required environment variable is set +if [[ ! $TANGO_HOST ]]; then + >&2 echo "TANGO_HOST environment variable unset!" + exit 1 +fi + +# Check if configured for specific version +if [[ $TANGOSTATIONCONTROL ]]; then + # TODO (Corne): Download version from artifacts or pypi. + # Consider exit 2 an UnImplementedError + exit 2 +else + # Install the package, exit 1 if it fails + cd tangostationcontrol || exit 1 + mkdir -p /tmp/tangostationcontrol + python3 setup.py build --build-base /tmp/tangostationcontrol egg_info --egg-base /tmp/tangostationcontrol bdist_wheel --dist-dir /tmp/tangostationcontrol || exit 1 + # shellcheck disable=SC2012 + sudo pip install --force-reinstall "$(ls -Art /tmp/tangostationcontrol/*.whl | tail -n 1)" +fi + +/usr/local/bin/wait-for-it.sh "$TANGO_HOST" --timeout=30 --strict -- "$@" diff --git a/bootstrap/etc/lofar20rc.sh b/bootstrap/etc/lofar20rc.sh index 9a9dd658b56f5d30bb1ff8c5de692bd8fe2164de..6e4a5c9bc8d6a78c1b61cca02159ee01291d3805 100755 --- a/bootstrap/etc/lofar20rc.sh +++ b/bootstrap/etc/lofar20rc.sh @@ -16,6 +16,14 @@ if [ ! -f "${LOFAR20_DIR}/.git/hooks/post-checkout" ]; then alias git="cp ${LOFAR20_DIR}/bin/update_submodules.sh ${LOFAR20_DIR}/.git/hooks/post-checkout; cp ${LOFAR20_DIR}/bin/update_submodules.sh ${LOFAR20_DIR}/.git/hooks/post-merge; unalias git; git" fi +if [ ! -z ${CI_BUILD_ID+x} ]; then + export CONTAINER_NAME_PREFIX=${CI_BUILD_ID}- +elif [ ! -z ${CI_JOB_ID+x} ]; then + export CONTAINER_NAME_PREFIX=${CI_JOB_ID}- +else + unset CONTAINER_NAME_PREFIX +fi + # This needs to be modified for a development environment. # In case you run multiple Docker networks on the same host in parallel, you need to specify a unique # network name for each of them. @@ -26,7 +34,6 @@ export NETWORK_MODE=tangonet # Example: export TANGO_HOST=station-xk25.astron.nl:10000 export TANGO_HOST=$(hostname):10000 - # # NO MODIFICATION BEYOND THIS POINT! # diff --git a/devices/.stestr.conf b/devices/.stestr.conf deleted file mode 100644 index 07147c8697683f270e9388da8b914c20cb8e4c45..0000000000000000000000000000000000000000 --- a/devices/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=${TESTS_DIR:-./test} -top_dir=./ diff --git a/devices/LICENSE.txt b/devices/LICENSE.txt deleted file mode 100644 index c9978b8eee263aebfdd8d0a016e447940682ba8b..0000000000000000000000000000000000000000 --- a/devices/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright 2021 ASTRON Netherlands Institute for Radio Astronomy - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/devices/__init__.py b/devices/__init__.py deleted file mode 100644 index 82b2af0e96f75105253e501e47f8861218132f63..0000000000000000000000000000000000000000 --- a/devices/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from util.lofar_git import get_version - -__version__ = get_version() - diff --git a/devices/common/lofar_git.py b/devices/common/lofar_git.py deleted file mode 100644 index f4f6217280fe612fa2e9a7830c1f026c1e36a815..0000000000000000000000000000000000000000 --- a/devices/common/lofar_git.py +++ /dev/null @@ -1,84 +0,0 @@ -import git # pip3 install gitpython -import os -from functools import lru_cache - -def get_repo(starting_directory: str = os.path.dirname(os.path.abspath(__file__))) -> git.Repo: - """ Try finding the repository by traversing up the tree. - - By default, the repository containing this module is returned. - """ - - directory = starting_directory - - try: - return git.Repo(directory) - except git.InvalidGitRepositoryError: - pass - - # We now have to traverse up the tree - while directory != "/" and os.path.exists(directory): - # Go to parent - directory = os.path.abspath(directory + os.path.sep + "..") - - try: - return git.Repo(directory) - except git.InvalidGitRepositoryError: - pass - - raise git.InvalidGitRepositoryError("Could not find git repository root in {}".format(starting_directory)) - - -@lru_cache(maxsize=None) -def get_version(repo: git.Repo = None) -> str: - """ Return a version string for the current commit. - - There is a practical issue: the repository changes over time, f.e. switching branches with 'git checkout'. We want - to know the version that is running in memory, not the one that is on disk. - - As a work-around, we cache the version information, in that it is at least consistent. It is up to the caller - to request the version early enough. - - The version string is one of: - - <tag> - - <branch> [<commit>] - - In both cases, a "*" prefix indicates this code is not production ready. Code is considered production ready if - it is a tag and there are no local modifications. - - """ - - if repo is None: - repo = get_repo() - - commit = repo.commit() - tags = {tag.commit: tag for tag in repo.tags} - - if commit in tags: - # a tag = production ready - commit_str = "{}".format(tags[commit]) - production_ready = True - elif repo.head.is_detached: - # no active branch - commit_str = "<detached HEAD> [{}]".format(commit) - production_ready = False - else: - # HEAD of a branch - branch = repo.active_branch - commit_str = "{} [{}]".format(branch, commit) - production_ready = False - - if repo.is_dirty(): - production_ready = False - - return "{}{}".format("*" if not production_ready else "", commit_str) - - -# at least cache the current repo version immediately -try: - _ = get_version() -except: - pass - - -if __name__ == "__main__": - print(get_version()) diff --git a/devices/devices/sdp/sdp.py b/devices/devices/sdp/sdp.py deleted file mode 100644 index 6cdfe9a2b2788f1b3466bbdb38a4ca5c83e9780f..0000000000000000000000000000000000000000 --- a/devices/devices/sdp/sdp.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the SDP project -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -""" SDP Device Server for LOFAR2.0 - -""" - -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - -# PyTango imports -from tango.server import run -from tango.server import device_property, attribute -from tango import AttrWriteType -# Additional import - -from clients.attribute_wrapper import attribute_wrapper -from devices.opcua_device import opcua_device - -from common.lofar_logging import device_logging_to_python, log_exceptions - -import numpy - -__all__ = ["SDP", "main"] - -@device_logging_to_python() -class SDP(opcua_device): - # ----------------- - # Device Properties - # ----------------- - - TR_fpga_mask_RW_default = device_property( - dtype='DevVarBooleanArray', - mandatory=False, - default_value=[True] * 16 - ) - - FPGA_processing_enable_RW_default = device_property( - dtype='DevVarBooleanArray', - mandatory=False, - default_value=[True] * 16 - ) - - FPGA_wg_enable_RW_default = device_property( - dtype='DevVarBooleanArray', - mandatory=False, - default_value=[[False] * 12] * 16 - ) - - # If we enable the waveform generator, we want some sane defaults. - - FPGA_wg_amplitude_RW = device_property( - dtype='DevVarDoubleArray', - mandatory=False, - default_value=[[0.1] * 12] * 16 - ) - - FPGA_wg_frequency_RW = device_property( - dtype='DevVarDoubleArray', - mandatory=False, - # Emit a signal on subband 102 - default_value=[[102 * 200e6/1024] * 12] * 16 - ) - - FPGA_wg_phase_RW = device_property( - dtype='DevVarDoubleArray', - mandatory=False, - default_value=[[0.0] * 12] * 16 - ) - - FPGA_sdp_info_station_id_RW_default = device_property( - dtype='DevVarULongArray', - mandatory=False, - default_value=[0] * 16 - ) - - FPGA_subband_weights_RW_default = device_property( - dtype='DevVarULongArray', - mandatory=False, - default_value=[[8192] * 12 * 512] * 16 - ) - - first_default_settings = [ - # set the masks first, as those filter any subsequent settings - 'TR_fpga_mask_RW' - ] - - # ---------- - # Attributes - # ---------- - - FPGA_beamlet_output_enable_R = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_enable_R"], datatype=numpy.bool_, dims=(16,)) - FPGA_beamlet_output_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_beamlet_output_hdr_eth_destination_mac_R = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_hdr_eth_destination_mac_R"], datatype=numpy.str, dims=(16,)) - FPGA_beamlet_output_hdr_eth_destination_mac_RW = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_hdr_eth_destination_mac_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_beamlet_output_hdr_ip_destination_address_R = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_hdr_ip_destination_address_R"], datatype=numpy.str, dims=(16,)) - FPGA_beamlet_output_hdr_ip_destination_address_RW = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_hdr_ip_destination_address_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_beamlet_output_hdr_udp_destination_port_R = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) - FPGA_beamlet_output_hdr_udp_destination_port_RW = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_beamlet_output_scale_R = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_scale_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_beamlet_output_scale_RW = attribute_wrapper(comms_annotation=["2:FPGA_beamlet_output_scale_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_firmware_version_R = attribute_wrapper(comms_annotation=["2:FPGA_firmware_version_R"], datatype=numpy.str, dims=(16,)) - FPGA_global_node_index_R = attribute_wrapper(comms_annotation=["2:FPGA_global_node_index_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_hardware_version_R = attribute_wrapper(comms_annotation=["2:FPGA_hardware_version_R"], datatype=numpy.str, dims=(16,)) - FPGA_processing_enable_R = attribute_wrapper(comms_annotation=["2:FPGA_processing_enable_R"], datatype=numpy.bool_, dims=(16,)) - FPGA_processing_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_scrap_R = attribute_wrapper(comms_annotation=["2:FPGA_scrap_R"], datatype=numpy.int32, dims=(8192,)) - FPGA_scrap_RW = attribute_wrapper(comms_annotation=["2:FPGA_scrap_RW"], datatype=numpy.int32, dims=(8192,), access=AttrWriteType.READ_WRITE) - FPGA_sdp_info_antenna_band_index_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_antenna_band_index_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_block_period_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_block_period_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_f_adc_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_f_adc_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_fsub_type_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_fsub_type_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_nyquist_sampling_zone_index_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_nyquist_sampling_zone_index_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_nyquist_sampling_zone_index_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_nyquist_sampling_zone_index_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sdp_info_observation_id_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_observation_id_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_observation_id_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_observation_id_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sdp_info_station_id_R = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_station_id_R"], datatype=numpy.uint32, dims=(16,)) - FPGA_sdp_info_station_id_RW = attribute_wrapper(comms_annotation=["2:FPGA_sdp_info_station_id_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_subband_weights_R = attribute_wrapper(comms_annotation=["2:FPGA_subband_weights_R"], datatype=numpy.uint32, dims=(12 * 512, 16)) - FPGA_subband_weights_RW = attribute_wrapper(comms_annotation=["2:FPGA_subband_weights_RW"], datatype=numpy.uint32, dims=(12 * 512, 16), access=AttrWriteType.READ_WRITE) - FPGA_temp_R = attribute_wrapper(comms_annotation=["2:FPGA_temp_R"], datatype=numpy.float_, dims=(16,)) - FPGA_weights_R = attribute_wrapper(comms_annotation=["2:FPGA_weights_R"], datatype=numpy.int16, dims=(12 * 488 * 2, 16)) - FPGA_weights_RW = attribute_wrapper(comms_annotation=["2:FPGA_weights_RW"], datatype=numpy.int16, dims=(12 * 488 * 2, 16), access=AttrWriteType.READ_WRITE) - FPGA_wg_amplitude_R = attribute_wrapper(comms_annotation=["2:FPGA_wg_amplitude_R"], datatype=numpy.float_, dims=(12, 16)) - FPGA_wg_amplitude_RW = attribute_wrapper(comms_annotation=["2:FPGA_wg_amplitude_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE) - FPGA_wg_enable_R = attribute_wrapper(comms_annotation=["2:FPGA_wg_enable_R"], datatype=numpy.bool_, dims=(12, 16)) - FPGA_wg_enable_RW = attribute_wrapper(comms_annotation=["2:FPGA_wg_enable_RW"], datatype=numpy.bool_, dims=(12, 16), access=AttrWriteType.READ_WRITE) - FPGA_wg_frequency_R = attribute_wrapper(comms_annotation=["2:FPGA_wg_frequency_R"], datatype=numpy.float_, dims=(12, 16)) - FPGA_wg_frequency_RW = attribute_wrapper(comms_annotation=["2:FPGA_wg_frequency_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE) - FPGA_wg_phase_R = attribute_wrapper(comms_annotation=["2:FPGA_wg_phase_R"], datatype=numpy.float_, dims=(12, 16)) - FPGA_wg_phase_RW = attribute_wrapper(comms_annotation=["2:FPGA_wg_phase_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE) - TR_fpga_mask_R = attribute_wrapper(comms_annotation=["2:TR_fpga_mask_R"], datatype=numpy.bool_, dims=(16,)) - TR_fpga_mask_RW = attribute_wrapper(comms_annotation=["2:TR_fpga_mask_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - TR_fpga_communication_error_R = attribute_wrapper(comms_annotation=["2:TR_fpga_communication_error_R"], datatype=numpy.bool_, dims=(16,)) - TR_sdp_config_first_fpga_nr_R = attribute_wrapper(comms_annotation=["2:TR_sdp_config_first_fpga_nr_R"], datatype=numpy.uint32) - TR_sdp_config_nof_beamsets_R = attribute_wrapper(comms_annotation=["2:TR_sdp_config_nof_beamsets_R"], datatype=numpy.uint32) - TR_sdp_config_nof_fpgas_R = attribute_wrapper(comms_annotation=["2:TR_sdp_config_nof_fpgas_R"], datatype=numpy.uint32) - TR_software_version_R = attribute_wrapper(comms_annotation=["2:TR_software_version_R"], datatype=numpy.str) - TR_start_time_R = attribute_wrapper(comms_annotation=["2:TR_start_time_R"], datatype=numpy.int64) - TR_tod_R = attribute_wrapper(comms_annotation=["2:TR_tod_R"], datatype=numpy.int64, dims=(2,)) - TR_tod_pps_delta_R = attribute_wrapper(comms_annotation=["2:TR_tod_pps_delta_R"], datatype=numpy.double) - - S_pn = 12 # Number of ADC signal inputs per Processing Node (PN) FPGA. - N_pn = 16 # Number of FPGAs per antenna band that is controlled via the SC - SDP interface. - - # OPC-UA MP only points for AIT - FPGA_signal_input_mean_R = attribute_wrapper(comms_annotation=["2:FPGA_signal_input_mean_R"], datatype=numpy.double , dims=(S_pn, N_pn)) - FPGA_signal_input_rms_R = attribute_wrapper(comms_annotation=["2:FPGA_signal_input_rms_R"], datatype=numpy.double, dims=(S_pn, N_pn)) - - FPGA_jesd204b_csr_rbd_count_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_csr_rbd_count_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) - FPGA_jesd204b_csr_dev_syncn_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_csr_dev_syncn_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) - FPGA_jesd204b_rx_err0_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_rx_err0_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) - FPGA_jesd204b_rx_err1_R = attribute_wrapper(comms_annotation=["2:FPGA_jesd204b_rx_err1_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) - - FPGA_bsn_monitor_input_bsn_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_bsn_R"], datatype=numpy.int64, dims=(N_pn,)) - FPGA_bsn_monitor_input_nof_packets_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_nof_packets_R"], datatype=numpy.int32, dims=(N_pn,)) - FPGA_bsn_monitor_input_nof_valid_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_nof_valid_R"], datatype=numpy.int32, dims=(N_pn,)) - FPGA_bsn_monitor_input_nof_err_R = attribute_wrapper(comms_annotation=["2:FPGA_bsn_monitor_input_nof_err_R"], datatype=numpy.int32, dims=(N_pn,)) - - - # -------- - # overloaded functions - # -------- - - # -------- - # Commands - # -------- - -# ---------- -# Run server -# ---------- -def main(args=None, **kwargs): - """Main function of the SDP module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((SDP,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/devices/requirements.txt b/devices/requirements.txt deleted file mode 100644 index 8e11e2f537bf59f3602379c853976696df7524f0..0000000000000000000000000000000000000000 --- a/devices/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -# the order of packages is of significance, because pip processes them in the -# order of appearance. Changing the order has an impact on the overall -# integration process, which may cause wedges in the gate later. - -pbr>=2.0 # Apache-2.0 diff --git a/devices/setup.cfg b/devices/setup.cfg deleted file mode 100644 index 55b29032e6aefc1787179c054b701b7fc51323ac..0000000000000000000000000000000000000000 --- a/devices/setup.cfg +++ /dev/null @@ -1,30 +0,0 @@ -[metadata] -name = TangoStationControl -summary = LOFAR 2.0 Station Control -description_file = - README.md -description_content_type = text/x-rst; charset=UTF-8 -author = ASTRON -home_page = https://astron.nl -project_urls = - Bug Tracker = https://support.astron.nl/jira/projects/L2SS/issues/ - Source Code = https://git.astron.nl/lofar2.0/tango -license = Apache-2 -classifier = - Environment :: Console - License :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - -[files] -package_dir=./ - -[entry_points] -console_scripts = - SDP = SDP:main - RECV = RECV:main diff --git a/devices/setup.py b/devices/setup.py deleted file mode 100644 index 4fa0ce44d0caa9b174fc65a699e63b31e43aee9b..0000000000000000000000000000000000000000 --- a/devices/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -import setuptools - -# Requires: setup.cfg -setuptools.setup(setup_requires=['pbr>=2.0.0'], pbr=True) diff --git a/devices/test/common/test_lofar_git.py b/devices/test/common/test_lofar_git.py deleted file mode 100644 index 52a1c7d876fc2827757f082e0f44a0a64b1ffc78..0000000000000000000000000000000000000000 --- a/devices/test/common/test_lofar_git.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of the LOFAR 2.0 Station Software -# -# -# -# Distributed under the terms of the APACHE license. -# See LICENSE.txt for more info. - -import git -from unittest import mock - -from common import lofar_git - -from test import base - - -class TestLofarGit(base.TestCase): - - def setUp(self): - super(TestLofarGit, self).setUp() - - # Clear the cache as this function of lofar_git uses LRU decorator - # This is a good demonstration of how unit tests in Python can have - # permanent effects, typically fixtures are needed to restore these. - lofar_git.get_version.cache_clear() - - def test_get_version(self): - """Test if attributes of get_repo are correctly used by get_version""" - - with mock.patch.object(lofar_git, 'get_repo') as m_get_repo: - m_commit = mock.Mock() - m_commit.return_value = "123456" - - m_is_dirty = mock.Mock() - m_is_dirty.return_value = True - - m_head = mock.Mock(is_detached=False) - - m_get_repo.return_value = mock.Mock( - active_branch="main", commit=m_commit, tags=[], - is_dirty=m_is_dirty, head=m_head) - - # No need for special string equal in Python - self.assertEqual("*main [123456]", lofar_git.get_version()) - - def test_get_version_tag(self): - """Test if get_version determines production_ready for tagged commit""" - - with mock.patch.object(lofar_git, 'get_repo') as m_get_repo: - m_commit = mock.Mock() - m_commit.return_value = "123456" - - m_is_dirty = mock.Mock() - m_is_dirty.return_value = False - - m_head = mock.Mock(is_detached=False) - - m_tag = mock.Mock(commit="123456") - m_tag.__str__ = mock.Mock(return_value= "version-1.2") - - m_get_repo.return_value = mock.Mock( - active_branch="main", commit=m_commit, - tags=[m_tag], is_dirty=m_is_dirty, head=m_head) - - self.assertEqual("version-1.2", lofar_git.get_version()) - - @mock.patch.object(lofar_git, 'get_repo') - def test_get_version_tag_dirty(self, m_get_repo): - """Test if get_version determines dirty tagged commit""" - - m_commit = mock.Mock() - m_commit.return_value = "123456" - - m_is_dirty = mock.Mock() - m_is_dirty.return_value = False - - m_head = mock.Mock(is_detached=False) - - m_tag = mock.Mock(commit="123456") - m_tag.__str__ = mock.Mock(return_value= "version-1.2") - - # Now m_get_repo is mocked using a decorator - m_get_repo.return_value = mock.Mock( - active_branch="main", commit=m_commit, - tags=[m_tag], is_dirty=m_is_dirty, head=m_head) - - self.assertEqual("version-1.2", lofar_git.get_version()) - - def test_catch_repo_error(self): - """Test if invalid git directories will raise error""" - - with mock.patch.object(lofar_git, 'get_repo') as m_get_repo: - - # Configure lofar_git.get_repo to raise InvalidGitRepositoryError - m_get_repo.side_effect = git.InvalidGitRepositoryError - - # Test that error is raised by get_version - self.assertRaises( - git.InvalidGitRepositoryError, lofar_git.get_version) diff --git a/docker-compose/.env b/docker-compose/.env index 00b12b0fcb55b351ebf9e56b37ae2c1f0fc6f4a9..de1f54725ceedea52e8dd6ded8849327627cf7bf 100644 --- a/docker-compose/.env +++ b/docker-compose/.env @@ -4,12 +4,12 @@ LOCAL_DOCKER_REGISTRY_HOST=git.astron.nl:5000 LOCAL_DOCKER_REGISTRY_USER=lofar2.0/tango TANGO_ARCHIVER_VERSION=2021-05-28 -TANGO_CPP_VERSION=9.3.5 -TANGO_DB_VERSION=10.4.11 -TANGO_DSCONFIG_VERSION=1.5.1 +TANGO_CPP_VERSION=9.3.9 +TANGO_DB_VERSION=10.4.14 +TANGO_DSCONFIG_VERSION=1.5.3 TANGO_HDBPP_VIEWER_VERSION=2021-05-28 TANGO_ITANGO_VERSION=9.3.7 -TANGO_JAVA_VERSION=9.3.4 -TANGO_POGO_VERSION=9.6.32 -TANGO_REST_VERSION=1.14.2 +TANGO_JAVA_VERSION=9.3.6 +TANGO_POGO_VERSION=9.6.34 +TANGO_REST_VERSION=1.14.6 TANGO_STARTER_VERSION=2021-05-28 diff --git a/docker-compose/Makefile b/docker-compose/Makefile index 649e63518d5f1276a2f1fb696d90a2b79fef0f24..d85ff1df88d91db097bdd22b060cfc03b681a04f 100644 --- a/docker-compose/Makefile +++ b/docker-compose/Makefile @@ -13,7 +13,8 @@ ATTACH_COMPOSE_FILE_ARGS := $(foreach yml,$(filter-out tango.yml,$(COMPOSE_FILES # But we allow to overwrite it. NETWORK_MODE ?= tangonet -# Host name through which others can reach our control interfaces +# Host name through which others can reach our control interfaces. +# Needs to be resolvable from the containers and clients. ifneq (,$(wildcard /run/WSL)) # Microsoft Windows Subsystem for Linux HOSTNAME ?= host.docker.internal @@ -21,6 +22,10 @@ else HOSTNAME ?= $(shell hostname -f) endif +# Host name to which to send our container logs. Needs to be resolvable from +# the host. +LOG_HOSTNAME ?= localhost + # If the first make argument is "start" or "stop"... ifeq (start,$(firstword $(MAKECMDGOALS))) SERVICE_TARGET = true @@ -113,6 +118,7 @@ DOCKER_COMPOSE_ARGS := DISPLAY=$(DISPLAY) \ TANGO_HOST=$(TANGO_HOST) \ MYSQL_HOST=$(MYSQL_HOST) \ HOSTNAME=$(HOSTNAME) \ + LOG_HOSTNAME=$(LOG_HOSTNAME) \ NETWORK_MODE=$(NETWORK_MODE) \ XAUTHORITY_MOUNT=$(XAUTHORITY_MOUNT) \ CONTAINER_NAME_PREFIX=$(CONTAINER_NAME_PREFIX) \ @@ -130,7 +136,7 @@ pull: ## pull the images from the Docker hub build: ## rebuild images # docker-compose does not support build dependencies, so manage those here $(DOCKER_COMPOSE_ARGS) docker-compose -f lofar-device-base.yml -f networks.yml build --progress=plain - $(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) build --progress=plain $(SERVICE) + $(DOCKER_COMPOSE_ARGS) docker-compose $(COMPOSE_FILE_ARGS) build --parallel --progress=plain $(SERVICE) build-nocache: ## rebuild images from scratch # docker-compose does not support build dependencies, so manage those here diff --git a/docker-compose/archiver.yml b/docker-compose/archiver.yml index 84dded354d22c97eeccd51ea97d8ff41b909f01e..1a56516c707ba965486432e753e45e24c14cbdc0 100644 --- a/docker-compose/archiver.yml +++ b/docker-compose/archiver.yml @@ -3,7 +3,7 @@ version: '2' services: archiver-maria-db: image: ${LOCAL_DOCKER_REGISTRY_HOST}/${LOCAL_DOCKER_REGISTRY_USER}/mariadb_hdbpp:2021-05-28 - container_name: archiver-maria-db + container_name: ${CONTAINER_NAME_PREFIX}archiver-maria-db networks: - control ports: @@ -17,13 +17,19 @@ services: - MYSQL_USER=tango - MYSQL_PASSWORD=tango - TANGO_HOST=${TANGO_HOST} + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped hdbpp-es: image: ${LOCAL_DOCKER_REGISTRY_HOST}/${LOCAL_DOCKER_REGISTRY_USER}/tango-archiver:2021-05-28 networks: - control - container_name: hdbpp-es + container_name: ${CONTAINER_NAME_PREFIX}hdbpp-es depends_on: - databaseds - dsconfig @@ -36,13 +42,19 @@ services: wait-for-it.sh archiver-maria-db:3306 --timeout=30 --strict -- wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict -- hdbppes-srv 01" + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped hdbpp-cm: image: ${LOCAL_DOCKER_REGISTRY_HOST}/${LOCAL_DOCKER_REGISTRY_USER}/tango-archiver:${TANGO_ARCHIVER_VERSION} networks: - control - container_name: hdbpp-cm + container_name: ${CONTAINER_NAME_PREFIX}hdbpp-cm depends_on: - databaseds - dsconfig @@ -55,10 +67,16 @@ services: wait-for-it.sh archiver-maria-db:3306 --timeout=30 --strict -- wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict -- hdbppcm-srv 01" + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" dsconfig: image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-dsconfig:${TANGO_DSCONFIG_VERSION} - container_name: dsconfig + container_name: ${CONTAINER_NAME_PREFIX}dsconfig networks: - control depends_on: @@ -73,5 +91,11 @@ services: - ..:/opt/lofar/tango:rw - ${HOME}:/hosthome - ../docker/tango/tango-archiver:/tango-archiver + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped diff --git a/docker-compose/device-apsct.yml b/docker-compose/device-apsct.yml index f17919a227a12b9846ba7a272254faaaee4d496a..60f65fc47ed81822242282fc743846221acec2d9 100644 --- a/docker-compose/device-apsct.yml +++ b/docker-compose/device-apsct.yml @@ -26,17 +26,16 @@ services: - control ports: - "5709:5709" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/apsct.py LTS -v -ORBendPoint giop:tcp:0:5709 -ORBendPointPublish giop:tcp:${HOSTNAME}:5709 + - l2ss-apsct Apsct STAT -v -v -ORBendPoint giop:tcp:0:5709 -ORBendPointPublish giop:tcp:${HOSTNAME}:5709 restart: on-failure diff --git a/docker-compose/device-apspu.yml b/docker-compose/device-apspu.yml index 30da5a6c2aba5daef2452f906693c41e7fece330..b694b09518215e293d19e1ff551f4f608e6f818d 100644 --- a/docker-compose/device-apspu.yml +++ b/docker-compose/device-apspu.yml @@ -26,17 +26,16 @@ services: - control ports: - "5710:5710" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/apspu.py LTS -v -ORBendPoint giop:tcp:0:5710 -ORBendPointPublish giop:tcp:${HOSTNAME}:5710 + - l2ss-apspu Apspu STAT -v -ORBendPoint giop:tcp:0:5710 -ORBendPointPublish giop:tcp:${HOSTNAME}:5710 restart: on-failure diff --git a/docker-compose/device-boot.yml b/docker-compose/device-boot.yml index 58a9aa7df81eab368464f4ca69ddab54129b7ace..3db111410fafde9901fd8f91cb40a1c3560e4242 100644 --- a/docker-compose/device-boot.yml +++ b/docker-compose/device-boot.yml @@ -25,17 +25,16 @@ services: - control ports: - "5708:5708" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/boot.py LTS -v -ORBendPoint giop:tcp:0:5708 -ORBendPointPublish giop:tcp:${HOSTNAME}:5708 + - l2ss-boot Boot STAT -v -ORBendPoint giop:tcp:0:5708 -ORBendPointPublish giop:tcp:${HOSTNAME}:5708 restart: unless-stopped diff --git a/docker-compose/device-docker.yml b/docker-compose/device-docker.yml index d9e1e1e35233177ab271db395773538ed8c74ffa..5a2641e9871f163f27ed7a60d872d30d4fe855e1 100644 --- a/docker-compose/device-docker.yml +++ b/docker-compose/device-docker.yml @@ -26,19 +26,18 @@ services: - control ports: - "5705:5705" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw - /var/run/docker.sock:/var/run/docker.sock:rw # we want to control our sibling containers, NOT do docker-in-docker (dind) user: 1000:${DOCKER_GID} # uid 1000 is the default "tango" user environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/docker_device.py LTS -v -ORBendPoint giop:tcp:0:5705 -ORBendPointPublish giop:tcp:${HOSTNAME}:5705 + - l2ss-docker-device Docker STAT -v -ORBendPoint giop:tcp:0:5705 -ORBendPointPublish giop:tcp:${HOSTNAME}:5705 restart: unless-stopped diff --git a/docker-compose/device-observation_control.yml b/docker-compose/device-observation_control.yml index 827a558a10167d29f3e0bd3402f3f84debcd3c23..33fb0d066fd76b8eb4a9c7753266f16d04157726 100644 --- a/docker-compose/device-observation_control.yml +++ b/docker-compose/device-observation_control.yml @@ -25,17 +25,16 @@ services: - control ports: - "5703:5703" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/observation_control.py LTS -v -ORBendPoint giop:tcp:0:5703 -ORBendPointPublish giop:tcp:${HOSTNAME}:5703 + - l2ss-observation-control ObservationControl STAT -v -ORBendPoint giop:tcp:0:5703 -ORBendPointPublish giop:tcp:${HOSTNAME}:5703 restart: unless-stopped diff --git a/docker-compose/device-recv.yml b/docker-compose/device-recv.yml index f3bc3eea12b51b44cacbeb790d0666ced24ae169..a08f566e7b39e095403f00cb5b086420b689d66b 100644 --- a/docker-compose/device-recv.yml +++ b/docker-compose/device-recv.yml @@ -26,17 +26,16 @@ services: - control ports: - "5707:5707" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/recv.py LTS -v -ORBendPoint giop:tcp:0:5707 -ORBendPointPublish giop:tcp:${HOSTNAME}:5707 + - l2ss-receiver RECV STAT -v -ORBendPoint giop:tcp:0:5707 -ORBendPointPublish giop:tcp:${HOSTNAME}:5707 restart: unless-stopped diff --git a/docker-compose/device-sdp.yml b/docker-compose/device-sdp.yml index 8fefa3f355eda485ea757f0859924e317b9245ee..f32c34394475c6a7483cb98cd03def1f62cf9ff0 100644 --- a/docker-compose/device-sdp.yml +++ b/docker-compose/device-sdp.yml @@ -26,17 +26,16 @@ services: - control ports: - "5701:5701" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/sdp/sdp.py LTS -v -ORBendPoint giop:tcp:0:5701 -ORBendPointPublish giop:tcp:${HOSTNAME}:5701 + - l2ss-sdp SDP STAT -v -ORBendPoint giop:tcp:0:5701 -ORBendPointPublish giop:tcp:${HOSTNAME}:5701 restart: unless-stopped diff --git a/docker-compose/device-sst.yml b/docker-compose/device-sst.yml index 7d922a61badf6575d15c6f0a0489a6fac3683367..7464cb01f45e584ab705fe9098e0229a1b762295 100644 --- a/docker-compose/device-sst.yml +++ b/docker-compose/device-sst.yml @@ -29,17 +29,16 @@ services: - "5001:5001/udp" # port to receive SST UDP packets on - "5101:5101/tcp" # port to emit SST TCP packets on - "5702:5702" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/sdp/sst.py LTS -v -ORBendPoint giop:tcp:0:5702 -ORBendPointPublish giop:tcp:${HOSTNAME}:5702 + - l2ss-sst SST STAT -v -ORBendPoint giop:tcp:0:5702 -ORBendPointPublish giop:tcp:${HOSTNAME}:5702 restart: unless-stopped diff --git a/docker-compose/device-unb2.yml b/docker-compose/device-unb2.yml index 6844ee2b6994c11fb53469535925284be42410c0..af1329d21a905f3c150c092529978e17f0c0ee37 100644 --- a/docker-compose/device-unb2.yml +++ b/docker-compose/device-unb2.yml @@ -26,17 +26,16 @@ services: - control ports: - "5704:5704" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/unb2.py LTS -v -ORBendPoint giop:tcp:0:5704 -ORBendPointPublish giop:tcp:${HOSTNAME}:5704 + - l2ss-unb2 UNB2 STAT -v -ORBendPoint giop:tcp:0:5704 -ORBendPointPublish giop:tcp:${HOSTNAME}:5704 restart: unless-stopped diff --git a/docker-compose/device-xst.yml b/docker-compose/device-xst.yml index c634e5d83fc7b28f2b8438ae59dffb7157a03f54..c4ea684fd94e34fcaaa857a5717ca47745eccc72 100644 --- a/docker-compose/device-xst.yml +++ b/docker-compose/device-xst.yml @@ -29,17 +29,16 @@ services: - "5002:5002/udp" # port to receive XST UDP packets on - "5102:5102/tcp" # port to emit XST TCP packets on - "5706:5706" # unique port for this DS + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} + working_dir: /opt/lofar/tango entrypoint: - - /usr/local/bin/wait-for-it.sh - - ${TANGO_HOST} - - --timeout=30 - - --strict - - -- + - bin/start-ds.sh # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/sdp/xst.py LTS -v -ORBendPoint giop:tcp:0:5706 -ORBendPointPublish giop:tcp:${HOSTNAME}:5706 + - l2ss-xst XST STAT -v -ORBendPoint giop:tcp:0:5706 -ORBendPointPublish giop:tcp:${HOSTNAME}:5706 restart: unless-stopped diff --git a/docker-compose/elk.yml b/docker-compose/elk.yml index bf6e22e3de6ea82571acba0ac8e7c69f3eeb2941..67f13baee061a74ebd08320f1e9f2f9f3e72f646 100644 --- a/docker-compose/elk.yml +++ b/docker-compose/elk.yml @@ -34,7 +34,8 @@ services: - "5601:5601" # kibana - "9200:9200" # elasticsearch - "5044:5044" # logstash beats input - - "1514:1514" # logstash syslog input + - "1514:1514/tcp" # logstash syslog input + - "1514:1514/udp" # logstash syslog input - "5959:5959" # logstash tcp json input depends_on: - elk-configure-host diff --git a/docker-compose/elk/logstash/conf.d/20-parse-grafana.conf b/docker-compose/elk/logstash/conf.d/20-parse-grafana.conf new file mode 100644 index 0000000000000000000000000000000000000000..37db44fda67109d7ef8a6beac1193004968a2349 --- /dev/null +++ b/docker-compose/elk/logstash/conf.d/20-parse-grafana.conf @@ -0,0 +1,16 @@ +filter { + if [program] == "grafana" { + kv { } + mutate { + rename => { + "t" => "timestamp" + "lvl" => "level" + "msg" => "message" + } + uppercase => [ "level" ] + } + date { + match => [ "timestamp", "ISO8601" ] + } + } +} diff --git a/docker-compose/elk/logstash/conf.d/21-parse-prometheus.conf b/docker-compose/elk/logstash/conf.d/21-parse-prometheus.conf new file mode 100644 index 0000000000000000000000000000000000000000..b8323625f329af02f9ff33556e408b94ecf7e0b6 --- /dev/null +++ b/docker-compose/elk/logstash/conf.d/21-parse-prometheus.conf @@ -0,0 +1,15 @@ +filter { + if [program] == "prometheus" { + kv { } + mutate { + rename => { + "ts" => "timestamp" + "msg" => "message" + } + uppercase => [ "level" ] + } + date { + match => [ "timestamp", "ISO8601" ] + } + } +} diff --git a/docker-compose/elk/logstash/conf.d/22-parse-tango-rest.conf b/docker-compose/elk/logstash/conf.d/22-parse-tango-rest.conf new file mode 100644 index 0000000000000000000000000000000000000000..5df0cd92bd32625a1eb91220bf4e7a9827799523 --- /dev/null +++ b/docker-compose/elk/logstash/conf.d/22-parse-tango-rest.conf @@ -0,0 +1,14 @@ +filter { + if [program] == "tango-rest" { + grok { + match => { + "message" => "%{TIMESTAMP_ISO8601:timestamp} %{WORD:level} %{GREEDYDATA:message}" + } + "overwrite" => [ "timestamp", "level", "message" ] + } + date { + match => [ "timestamp", "YYYY-MM-dd HH:mm:ss,SSS" ] + timezone => "UTC" + } + } +} diff --git a/docker-compose/elk/logstash/conf.d/23-parse-maria-db.conf b/docker-compose/elk/logstash/conf.d/23-parse-maria-db.conf new file mode 100644 index 0000000000000000000000000000000000000000..0a23fddd078e5e967bc5f791e020faaa20ed632a --- /dev/null +++ b/docker-compose/elk/logstash/conf.d/23-parse-maria-db.conf @@ -0,0 +1,32 @@ +filter { + # mark all our mariadb instances + grok { + match => { + "program" => [ "archiver-maria-db", "tangodb" ] + } + add_tag => [ "mariadb" ] + } + + # parse mariadb output + if "mariadb" in [tags] { + grok { + match => { + "message" => [ + "%{TIMESTAMP_ISO8601:timestamp} .%{WORD:level}. %{GREEDYDATA:message}", + "%{TIMESTAMP_ISO8601:timestamp} 0 .%{WORD:level}. %{GREEDYDATA:message}" + ] + } + "overwrite" => [ "timestamp", "level", "message" ] + } + mutate { + gsub => [ + "level", "Note", "Info" + ] + uppercase => [ "level" ] + } + date { + match => [ "timestamp", "YYYY-MM-dd HH:mm:ssZZ", "YYYY-MM-dd HH:mm:ss", "YYYY-MM-dd H:mm:ss" ] + timezone => "UTC" + } + } +} diff --git a/docker-compose/grafana.yml b/docker-compose/grafana.yml index b9060c70a53ecfb4d4027ebe1e78d9fe658050f6..29c93c52c4dc05849aad10fabac12712c12dd4d7 100644 --- a/docker-compose/grafana.yml +++ b/docker-compose/grafana.yml @@ -23,4 +23,10 @@ services: # - grafana-configs:/etc/grafana ports: - "3000:3000" + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped diff --git a/docker-compose/grafana/Dockerfile b/docker-compose/grafana/Dockerfile index bc766bcd3b0d71f346fd70e34fa27dd91fc27b04..e51cce5eeaa0310c1ecd698d8d797e3163ce4457 100644 --- a/docker-compose/grafana/Dockerfile +++ b/docker-compose/grafana/Dockerfile @@ -1,5 +1,9 @@ FROM grafana/grafana +# Install some plugins +RUN grafana-cli plugins install briangann-datatable-panel +RUN grafana-cli plugins install ae3e-plotly-panel + COPY grafana.ini /etc/grafana/ # Add default configuration through provisioning (see https://grafana.com/docs/grafana/latest/administration/provisioning) diff --git a/docker-compose/grafana/dashboards/docker.json b/docker-compose/grafana/dashboards/docker.json index 0d486f65e35a9a1c4a5ca024d6a89b0a46991ff2..cc6680ee533d24c9a40a5df2e8020845e32575db 100644 --- a/docker-compose/grafana/dashboards/docker.json +++ b/docker-compose/grafana/dashboards/docker.json @@ -78,7 +78,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/docker/1\",name=~\".*_R\",name!=\"version_R\"}", + "expr": "device_attribute{device=\"stat/docker/1\",name=~\".*_R\",name!=\"version_R\"}", "instant": false, "interval": "", "legendFormat": "{{name}}", diff --git a/docker-compose/grafana/dashboards/home.json b/docker-compose/grafana/dashboards/home.json index 6d4641a656c20b40ceaa8a18d2b02da47b0b55ba..4ef59179fa14153bf814975ed74d55c2c92c2d10 100644 --- a/docker-compose/grafana/dashboards/home.json +++ b/docker-compose/grafana/dashboards/home.json @@ -22,7 +22,7 @@ "fiscalYearStartMonth": 0, "gnetId": null, "graphTooltip": 0, - "id": 6, + "id": 5, "links": [], "liveNow": false, "panels": [ @@ -96,7 +96,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/boot/1\",name=\"initialisation_progress_R\"}", + "expr": "device_attribute{device=\"stat/boot/1\",name=\"initialisation_progress_R\"}", "interval": "", "legendFormat": "", "refId": "A" @@ -191,7 +191,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{label=\"State\",device=~\"lts/.*/1\"}", + "expr": "device_attribute{label=\"State\",device=~\"stat/.*/1\"}", "instant": false, "interval": "", "legendFormat": "{{device}}", @@ -425,7 +425,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/boot/1\",name=\"initialisation_status_R\"}", + "expr": "device_attribute{device=\"stat/boot/1\",name=\"initialisation_status_R\"}", "instant": true, "interval": "", "legendFormat": "", @@ -449,7 +449,7 @@ "Time": true, "Value": true, "device": true, - "device_attribute{device=\"lts/boot/1\", dim_x=\"1\", dim_y=\"0\", instance=\"tango-prometheus-exporter:8000\", job=\"tango\", label=\"initialisation_status_R\", name=\"initialisation_status_R\", str_value=\"Initialisation completed\", type=\"string\", x=\"0\", y=\"0\"}": true, + "device_attribute{device=\"stat/boot/1\", dim_x=\"1\", dim_y=\"0\", instance=\"tango-prometheus-exporter:8000\", job=\"tango\", label=\"initialisation_status_R\", name=\"initialisation_status_R\", str_value=\"Initialisation completed\", type=\"string\", x=\"0\", y=\"0\"}": true, "dim_x": true, "dim_y": true, "instance": true, @@ -484,6 +484,196 @@ ], "type": "table" }, + { + "datasource": "ELK logs", + "description": "List of the errors in the selected timespan", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "@timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 149 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "level" + }, + "properties": [ + { + "id": "custom.width", + "value": 62 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "program" + }, + "properties": [ + { + "id": "custom.width", + "value": 287 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "extra.logger_name" + }, + "properties": [ + { + "id": "custom.width", + "value": 72 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "extra.lofar_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 196 + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 56, + "options": { + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.2.1", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "metrics": [ + { + "hide": false, + "id": "1", + "settings": { + "limit": "500" + }, + "type": "logs" + } + ], + "query": "level:(ERROR or CRIT or FATAL)", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Error Log", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "@version": true, + "_id": true, + "_index": true, + "_source": true, + "_type": true, + "extra.func_name": true, + "extra.interpreter": true, + "extra.interpreter_version": true, + "extra.line": true, + "extra.logger_name": true, + "extra.logstash_async_version": true, + "extra.path": true, + "extra.process_name": true, + "extra.software_version": true, + "extra.tango_device": true, + "extra.thread_name": true, + "highlight": true, + "host": true, + "logsource": true, + "pid": true, + "port": true, + "sort": true, + "tags": true, + "type": true + }, + "indexByName": { + "@timestamp": 0, + "@version": 5, + "_id": 6, + "_index": 7, + "_source": 8, + "_type": 9, + "extra.func_name": 10, + "extra.interpreter": 11, + "extra.interpreter_version": 12, + "extra.line": 13, + "extra.lofar_id": 4, + "extra.logger_name": 14, + "extra.logstash_async_version": 15, + "extra.path": 16, + "extra.process_name": 17, + "extra.software_version": 18, + "extra.tango_device": 19, + "extra.thread_name": 20, + "highlight": 21, + "host": 2, + "level": 1, + "logsource": 22, + "message": 23, + "pid": 24, + "port": 25, + "program": 3, + "sort": 26, + "tags": 27, + "type": 28 + }, + "renameByName": {} + } + } + ], + "type": "table" + }, { "collapsed": false, "datasource": null, @@ -491,7 +681,301 @@ "h": 1, "w": 24, "x": 0, - "y": 10 + "y": 15 + }, + "id": 49, + "panels": [], + "title": "APSCT & APSPU", + "type": "row" + }, + { + "datasource": "Prometheus", + "description": "State of APSCT", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 21, + "x": 0, + "y": 16 + }, + "id": 24, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "name" + }, + "pluginVersion": "8.2.1", + "targets": [ + { + "exemplar": true, + "expr": "1-device_attribute{device=\"stat/apsct/1\",name=\"APSCT_PWR_on_R\"}", + "interval": "", + "legendFormat": "Power", + "refId": "A" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/apsct/1\",name=\"APSCTTR_I2C_error_R\"}", + "hide": false, + "interval": "", + "legendFormat": "I2C", + "refId": "B" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/apsct/1\",name=\"APSCT_PLL_200MHz_error_R\"}", + "hide": false, + "interval": "", + "legendFormat": "PLL", + "refId": "C" + }, + { + "exemplar": true, + "expr": "1-device_attribute{device=\"stat/apsct/1\",name=\"APSCT_PLL_200MHz_locked_R\"}", + "hide": false, + "interval": "", + "legendFormat": "PLL Lock", + "refId": "D" + }, + { + "exemplar": true, + "expr": "1-device_attribute{device=\"stat/apsct/1\",name=\"APSCT_INPUT_10MHz_good_R\"}", + "hide": false, + "interval": "", + "legendFormat": "10MHz", + "refId": "E" + }, + { + "exemplar": true, + "expr": "1-device_attribute{device=\"stat/apsct/1\",name=\"APSCT_INPUT_PPS_good_R\"}", + "hide": false, + "interval": "", + "legendFormat": "PPS", + "refId": "F" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/apsct/1\",name=\"APSCT_PPS_ignore_R\"}", + "hide": false, + "interval": "", + "legendFormat": "PPS used", + "refId": "G" + } + ], + "title": "APS Clock State", + "type": "stat" + }, + { + "datasource": "Prometheus", + "description": "State of APSPU", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 16 + }, + "id": 50, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "name" + }, + "pluginVersion": "8.2.1", + "targets": [ + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/apspu/1\",name=\"APSPUTR_I2C_error_R\"}", + "hide": false, + "interval": "", + "legendFormat": "I2C", + "refId": "B" + } + ], + "title": "APS Power Unit State", + "type": "stat" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 53, + "panels": [], + "title": "UNB2", + "type": "row" + }, + { + "datasource": "Prometheus", + "description": "State of Unboard 2 I2C Bus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "green", + "value": 1 + }, + { + "color": "red", + "value": 2 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 54, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "name" + }, + "pluginVersion": "8.2.1", + "targets": [ + { + "exemplar": true, + "expr": "(1 + (device_attribute{device=\"stat/unb2/1\",name=\"UNB2TR_I2C_bus_error_R\"} != bool 0)) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", + "hide": false, + "interval": "", + "legendFormat": "I2C {{x}}", + "refId": "A" + }, + { + "exemplar": true, + "expr": "(1 + device_attribute{device=\"stat/unb2/1\",name=\"UNB2TR_I2C_bus_PS_error_R\"}) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", + "hide": false, + "interval": "", + "legendFormat": "PS {{x}}", + "refId": "B" + }, + { + "exemplar": true, + "expr": "(1 + sum by (x) (device_attribute{device=\"stat/unb2/1\",name=\"UNB2TR_I2C_bus_FPGA_PS_error_R\"})) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", + "hide": false, + "interval": "", + "legendFormat": "FPGA PS {{x}}", + "refId": "C" + }, + { + "exemplar": true, + "expr": "(1 + sum by (x) (device_attribute{device=\"stat/unb2/1\",name=\"UNB2TR_I2C_bus_DDR4_error_R\"})) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", + "hide": false, + "interval": "", + "legendFormat": "DDR {{x}}", + "refId": "D" + }, + { + "exemplar": true, + "expr": "(1 + sum by (x) (device_attribute{device=\"stat/unb2/1\",name=\"UNB2TR_I2C_bus_QSFP_error_R\"})) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", + "hide": false, + "interval": "", + "legendFormat": "QSFP {{x}}", + "refId": "E" + } + ], + "title": "UNB2 I2C State", + "type": "stat" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 }, "id": 17, "panels": [], @@ -530,12 +1014,12 @@ "h": 8, "w": 6, "x": 0, - "y": 11 + "y": 24 }, "id": 21, "options": { "colorMode": "background", - "graphMode": "area", + "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { @@ -552,13 +1036,14 @@ "targets": [ { "exemplar": true, - "expr": "sum by (x)(1 + (device_attribute{device=\"lts/recv/1\",name=\"RCU_ADC_lock_R\"} == bool 129)) * on(x) device_attribute{device=\"lts/recv/1\",name=\"RCU_mask_RW\"} - 3", + "expr": "sum by (x)(1 + (device_attribute{device=\"stat/recv/1\",name=\"RCU_ADC_locked_R\"})) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"} - 3", + "instant": false, "interval": "", "legendFormat": "{{y}}", "refId": "A" } ], - "title": "RCU ADC lock", + "title": "RCU Clock Lock", "type": "stat" }, { @@ -593,12 +1078,12 @@ "h": 8, "w": 6, "x": 6, - "y": 11 + "y": 24 }, "id": 25, "options": { "colorMode": "background", - "graphMode": "area", + "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { @@ -615,17 +1100,20 @@ "targets": [ { "exemplar": true, - "expr": "(2 - device_attribute{device=\"lts/recv/1\",name=\"RCU_I2C_STATUS_R\"}) * on(x) device_attribute{device=\"lts/recv/1\",name=\"RCU_mask_RW\"}", + "expr": "(1 + (device_attribute{device=\"stat/recv/1\",name=\"RECVTR_I2C_error_R\"} == bool 0)) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", + "hide": false, + "instant": false, "interval": "", "legendFormat": "{{y}}", "refId": "A" } ], - "title": "RCU I2C status", + "title": "RCU I2C State", "type": "stat" }, { "datasource": "Prometheus", + "description": "", "fieldConfig": { "defaults": { "color": { @@ -636,12 +1124,16 @@ "mode": "absolute", "steps": [ { - "color": "green", + "color": "transparent", "value": null }, { "color": "red", "value": 1 + }, + { + "color": "green", + "value": 2 } ] } @@ -649,12 +1141,12 @@ "overrides": [] }, "gridPos": { - "h": 5, - "w": 3, + "h": 8, + "w": 6, "x": 12, - "y": 11 + "y": 24 }, - "id": 24, + "id": 51, "options": { "colorMode": "background", "graphMode": "none", @@ -674,37 +1166,15 @@ "targets": [ { "exemplar": true, - "expr": "1-device_attribute{device=\"lts/apsct/1\",name=\"APSCT_PWR_on_R\"}", - "interval": "", - "legendFormat": "Power", - "refId": "A" - }, - { - "exemplar": true, - "expr": "device_attribute{device=\"lts/apsct/1\",name=\"APSCT_I2C_error_R\"}", - "hide": false, - "interval": "", - "legendFormat": "I2C", - "refId": "B" - }, - { - "exemplar": true, - "expr": "device_attribute{device=\"lts/apsct/1\",name=\"APSCT_PLL_200MHz_error_R\"}", - "hide": false, - "interval": "", - "legendFormat": "PLL", - "refId": "C" - }, - { - "exemplar": true, - "expr": "1-device_attribute{device=\"lts/apsct/1\",name=\"APSCT_PLL_200MHz_locked_R\"}", + "expr": "(1 + device_attribute{device=\"stat/recv/1\",name=\"RCU_PWR_good_R\"}) * on(x) device_attribute{device=\"stat/recv/1\",name=\"RCU_mask_RW\"}", "hide": false, + "instant": false, "interval": "", - "legendFormat": "PLL Lock", - "refId": "D" + "legendFormat": "{{y}}", + "refId": "A" } ], - "title": "Clock", + "title": "RCU Power good", "type": "stat" }, { @@ -714,7 +1184,7 @@ "h": 1, "w": 24, "x": 0, - "y": 19 + "y": 32 }, "id": 19, "panels": [], @@ -754,7 +1224,7 @@ "h": 8, "w": 5, "x": 0, - "y": 20 + "y": 33 }, "id": 11, "options": { @@ -776,7 +1246,7 @@ "targets": [ { "exemplar": true, - "expr": "(50+50*device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_communication_error_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}", + "expr": "(50+50*device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_communication_error_R\"}) * on(x) device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_mask_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -822,7 +1292,7 @@ "h": 8, "w": 5, "x": 5, - "y": 20 + "y": 33 }, "id": 9, "options": { @@ -844,7 +1314,7 @@ "targets": [ { "exemplar": true, - "expr": "(100-50*device_attribute{device=\"lts/sdp/1\",name=\"FPGA_processing_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}", + "expr": "(100-50*device_attribute{device=\"stat/sdp/1\",name=\"FPGA_processing_enable_R\"}) * on(x) device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_mask_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -896,7 +1366,7 @@ "h": 4, "w": 3, "x": 10, - "y": 20 + "y": 33 }, "id": 12, "options": { @@ -918,7 +1388,7 @@ "targets": [ { "exemplar": true, - "expr": "sum(sum by(x) (device_attribute{device=\"lts/sdp/1\",name=\"FPGA_wg_enable_RW\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"})", + "expr": "sum(sum by(x) (device_attribute{device=\"stat/sdp/1\",name=\"FPGA_wg_enable_RW\"}) * on(x) device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_mask_R\"})", "format": "time_series", "hide": false, "instant": false, @@ -938,7 +1408,7 @@ "h": 1, "w": 24, "x": 0, - "y": 28 + "y": 41 }, "id": 27, "panels": [], @@ -978,7 +1448,7 @@ "h": 8, "w": 5, "x": 0, - "y": 29 + "y": 42 }, "id": 28, "options": { @@ -1000,7 +1470,7 @@ "targets": [ { "exemplar": true, - "expr": "(100-50*device_attribute{device=\"lts/sst/1\",name=\"FPGA_sst_offload_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}", + "expr": "(100-50*device_attribute{device=\"stat/sst/1\",name=\"FPGA_sst_offload_enable_R\"}) * on(x) device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_mask_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -1076,7 +1546,7 @@ "h": 8, "w": 5, "x": 5, - "y": 29 + "y": 42 }, "id": 29, "options": { @@ -1093,7 +1563,7 @@ "targets": [ { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/sst/1\",name=\"nof_invalid_packets_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/sst/1\",name=\"nof_invalid_packets_R\"}[1m])", "format": "time_series", "hide": false, "instant": false, @@ -1103,7 +1573,7 @@ }, { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/sst/1\",name=\"nof_packets_dropped_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/sst/1\",name=\"nof_packets_dropped_R\"}[1m])", "hide": false, "interval": "", "legendFormat": "dropped", @@ -1111,7 +1581,7 @@ }, { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/sst/1\",name=\"nof_payload_errors_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/sst/1\",name=\"nof_payload_errors_R\"}[1m])", "hide": false, "interval": "", "legendFormat": "payload errors {{x}}", @@ -1185,7 +1655,7 @@ "h": 8, "w": 5, "x": 10, - "y": 29 + "y": 42 }, "id": 30, "options": { @@ -1202,7 +1672,7 @@ "targets": [ { "exemplar": true, - "expr": "sum(rate(device_attribute{device=\"lts/sst/1\",name=\"nof_bytes_received_R\"}[1m]))", + "expr": "sum(rate(device_attribute{device=\"stat/sst/1\",name=\"nof_bytes_received_R\"}[1m]))", "format": "time_series", "hide": false, "instant": false, @@ -1278,7 +1748,7 @@ "h": 8, "w": 5, "x": 15, - "y": 29 + "y": 42 }, "id": 33, "options": { @@ -1295,7 +1765,7 @@ "targets": [ { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/sst/1\",name=\"replicator_nof_bytes_sent_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/sst/1\",name=\"replicator_nof_bytes_sent_R\"}[1m])", "format": "time_series", "hide": false, "instant": false, @@ -1373,7 +1843,7 @@ "h": 8, "w": 3, "x": 20, - "y": 29 + "y": 42 }, "id": 34, "options": { @@ -1390,7 +1860,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/sst/1\",name=\"replicator_nof_tasks_pending_R\"}", + "expr": "device_attribute{device=\"stat/sst/1\",name=\"replicator_nof_tasks_pending_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -1410,7 +1880,7 @@ "h": 1, "w": 24, "x": 0, - "y": 37 + "y": 50 }, "id": 36, "panels": [], @@ -1447,10 +1917,10 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 4, "w": 5, "x": 0, - "y": 38 + "y": 51 }, "id": 37, "options": { @@ -1472,7 +1942,7 @@ "targets": [ { "exemplar": true, - "expr": "(100-50*device_attribute{device=\"lts/xst/1\",name=\"FPGA_xst_offload_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}", + "expr": "(100-50*device_attribute{device=\"stat/xst/1\",name=\"FPGA_xst_offload_enable_R\"}) * on(x) device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_mask_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -1548,7 +2018,7 @@ "h": 8, "w": 5, "x": 5, - "y": 38 + "y": 51 }, "id": 38, "options": { @@ -1565,7 +2035,7 @@ "targets": [ { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/xst/1\",name=\"nof_invalid_packets_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/xst/1\",name=\"nof_invalid_packets_R\"}[1m])", "format": "time_series", "hide": false, "instant": false, @@ -1575,7 +2045,7 @@ }, { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/xst/1\",name=\"nof_packets_dropped_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/xst/1\",name=\"nof_packets_dropped_R\"}[1m])", "hide": false, "interval": "", "legendFormat": "dropped", @@ -1583,7 +2053,7 @@ }, { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/xst/1\",name=\"nof_payload_errors_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/xst/1\",name=\"nof_payload_errors_R\"}[1m])", "hide": false, "interval": "", "legendFormat": "payload errors {{x}}", @@ -1657,7 +2127,7 @@ "h": 8, "w": 5, "x": 10, - "y": 38 + "y": 51 }, "id": 39, "options": { @@ -1674,7 +2144,7 @@ "targets": [ { "exemplar": true, - "expr": "sum(rate(device_attribute{device=\"lts/xst/1\",name=\"nof_bytes_received_R\"}[1m]))", + "expr": "sum(rate(device_attribute{device=\"stat/xst/1\",name=\"nof_bytes_received_R\"}[1m]))", "format": "time_series", "hide": false, "instant": false, @@ -1750,7 +2220,7 @@ "h": 8, "w": 5, "x": 15, - "y": 38 + "y": 51 }, "id": 40, "options": { @@ -1767,7 +2237,7 @@ "targets": [ { "exemplar": true, - "expr": "rate(device_attribute{device=\"lts/xst/1\",name=\"replicator_nof_bytes_sent_R\"}[1m])", + "expr": "rate(device_attribute{device=\"stat/xst/1\",name=\"replicator_nof_bytes_sent_R\"}[1m])", "format": "time_series", "hide": false, "instant": false, @@ -1845,7 +2315,7 @@ "h": 8, "w": 3, "x": 20, - "y": 38 + "y": 51 }, "id": 41, "options": { @@ -1862,7 +2332,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/xst/1\",name=\"replicator_nof_tasks_pending_R\"}", + "expr": "device_attribute{device=\"stat/xst/1\",name=\"replicator_nof_tasks_pending_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -1905,10 +2375,10 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 4, "w": 5, "x": 0, - "y": 46 + "y": 55 }, "id": 45, "options": { @@ -1930,7 +2400,7 @@ "targets": [ { "exemplar": true, - "expr": "(100-50*device_attribute{device=\"lts/xst/1\",name=\"FPGA_xst_processing_enable_R\"}) * on(x) device_attribute{device=\"lts/sdp/1\",name=\"TR_fpga_mask_R\"}", + "expr": "(100-50*device_attribute{device=\"stat/xst/1\",name=\"FPGA_xst_processing_enable_R\"}) * on(x) device_attribute{device=\"stat/sdp/1\",name=\"TR_fpga_mask_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -1959,5 +2429,5 @@ "timezone": "", "title": "Home", "uid": "nC8N_kO7k", - "version": 5 + "version": 6 } diff --git a/docker-compose/grafana/dashboards/sensors.json b/docker-compose/grafana/dashboards/sensors.json index 95e39f60d024ea355119a24d72cbd9bdd9c178fe..cbb6e6d0dab36965e0d744fd35ea1392de0c33d3 100644 --- a/docker-compose/grafana/dashboards/sensors.json +++ b/docker-compose/grafana/dashboards/sensors.json @@ -22,7 +22,6 @@ "fiscalYearStartMonth": 0, "gnetId": null, "graphTooltip": 0, - "id": 4, "links": [], "liveNow": false, "panels": [ @@ -75,7 +74,6 @@ } }, "mappings": [], - "min": 0, "thresholds": { "mode": "absolute", "steps": [ @@ -99,7 +97,7 @@ "x": 0, "y": 1 }, - "id": 2, + "id": 6, "options": { "legend": { "calcs": [], @@ -114,7 +112,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/recv/1\",name=\"RCU_temperature_R\"} - 273.15", + "expr": "device_attribute{device=\"stat/sdp/1\",name=\"FPGA_temp_R\"} != 0", "format": "time_series", "hide": false, "instant": false, @@ -123,13 +121,13 @@ "refId": "A" } ], - "title": "RCU temperatures", + "title": "FPGA Temperatures", "transformations": [], "type": "timeseries" }, { "datasource": "Prometheus", - "description": "Temperature sensors of each node on each board", + "description": "", "fieldConfig": { "defaults": { "color": { @@ -202,14 +200,14 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_CORE_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_CORE_TEMP_R\"} ", "interval": "", "legendFormat": "Core board {{x}} node {{y}}", "refId": "A" }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_TEMP_R\"} ", "hide": false, "interval": "", "legendFormat": "ERAM board {{x}} node {{y}}", @@ -217,7 +215,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_TEMP_R\"} ", "hide": false, "interval": "", "legendFormat": "TrRx board {{x}} node {{y}}", @@ -225,7 +223,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_TXGB_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_TXGB_TEMP_R\"} ", "hide": false, "interval": "", "legendFormat": "TrHx board {{x}} node {{y}}", @@ -233,23 +231,28 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_PGM_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_PGM_TEMP_R\"} ", "hide": false, "interval": "", "legendFormat": "IO board {{x}} node {{y}}", "refId": "E" }, { + "exemplar": true, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_HGXB_TEMP_R\"} ", "hide": false, + "interval": "", + "legendFormat": "HGXB board {{x}} node {{y}}", "refId": "F" } ], - "title": "Uniboard2 Node Temperatures", + "title": "Uniboard2 FPGA POL Temperatures", + "transformations": [], "type": "timeseries" }, { "datasource": "Prometheus", - "description": "Temperature sensors of the power supply on each board", + "description": "", "fieldConfig": { "defaults": { "color": { @@ -308,7 +311,7 @@ "x": 10, "y": 1 }, - "id": 8, + "id": 22, "options": { "legend": { "calcs": [], @@ -322,62 +325,287 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N01_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_QSFP_CAGE_TEMP_R\"}", "interval": "", - "legendFormat": "QSFP N01 board {{x}} ", + "legendFormat": "FPGA QSFP Cage {{x}}, {{y}} ", "refId": "A" + } + ], + "title": "Uniboard2 QSFP Cage Temperatures", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic", + "seriesBy": "max" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 85 + } + ] + }, + "unit": "celsius" }, - { - "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N23_TEMP_R\"}", - "hide": false, - "interval": "", - "legendFormat": "QSFP N23 board {{x}}", - "refId": "B" + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 5, + "x": 15, + "y": 1 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom" }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_TEMP_R\"}", - "hide": false, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_DDR4_SLOT_TEMP_R\"}", "interval": "", - "legendFormat": "Switch 1v2 board {{x}}", - "refId": "C" + "legendFormat": "FPGA QSFP Cage {{x}}, {{y}} ", + "refId": "A" + } + ], + "title": "Uniboard2 DDR4 Temperatures", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 5, + "x": 0, + "y": 9 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "pluginVersion": "8.1.2", + "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/recv/1\",name=\"RCU_TEMP_R\"}", + "format": "time_series", "hide": false, + "instant": false, "interval": "", - "legendFormat": "Switch PHY board {{x}}", - "refId": "D" + "legendFormat": "{{x}}", + "refId": "A" + } + ], + "title": "RCU Temperatures", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "Temperatures reported by APSCT and APSPU", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic", + "seriesBy": "max" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 85 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 5, + "x": 5, + "y": 9 + }, + "id": 24, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "bottom" }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_CLOCK_TEMP_R\"}", - "hide": false, + "expr": "device_attribute{device=\"stat/apsct/1\",name=~\"APSCT_TEMP_R\"}", "interval": "", - "legendFormat": "Clock PWR board {{x}}", - "refId": "E" + "legendFormat": "{{name}}", + "refId": "A" }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_DC_DC_48V_12V_TEMP_R\"}", + "expr": "device_attribute{device=\"stat/apspu/1\",name=~\"APSPU_.*_TEMP_R\"}", "hide": false, "interval": "", - "legendFormat": "DC-DC board {{x}}", - "refId": "F" + "legendFormat": "{{name}}", + "refId": "B" } ], - "title": "Uniboard2 Power Supply Temperatures", + "title": "APS Temperatures", "type": "timeseries" }, { "datasource": "Prometheus", - "description": "", + "description": "Temperature sensors of the power supply on each board", "fieldConfig": { "defaults": { "color": { - "mode": "palette-classic" + "mode": "palette-classic", + "seriesBy": "max" }, "custom": { "axisLabel": "", @@ -397,14 +625,14 @@ "scaleDistribution": { "type": "linear" }, - "showPoints": "auto", + "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { - "mode": "off" + "mode": "line" } }, "mappings": [], @@ -417,7 +645,7 @@ }, { "color": "red", - "value": 80 + "value": 85 } ] }, @@ -429,9 +657,9 @@ "h": 8, "w": 5, "x": 15, - "y": 1 + "y": 9 }, - "id": 6, + "id": 8, "options": { "legend": { "calcs": [], @@ -442,21 +670,56 @@ "mode": "single" } }, - "pluginVersion": "8.1.2", "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/sdp/1\",name=\"FPGA_temp_R\"}", - "format": "time_series", - "hide": false, - "instant": false, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_QSFP_N01_TEMP_R\"} ", "interval": "", - "legendFormat": "{{x}}", + "legendFormat": "QSFP N01 board {{x}}", "refId": "A" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_QSFP_N23_TEMP_R\"} ", + "hide": false, + "interval": "", + "legendFormat": "QSFP N23 board {{x}}", + "refId": "B" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_TEMP_R\"} ", + "hide": false, + "interval": "", + "legendFormat": "Switch 1v2 board {{x}}", + "refId": "C" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_TEMP_R\"} ", + "hide": false, + "interval": "", + "legendFormat": "Switch PHY board {{x}}", + "refId": "D" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_CLOCK_TEMP_R\"} ", + "hide": false, + "interval": "", + "legendFormat": "Clock PWR board {{x}}", + "refId": "E" + }, + { + "exemplar": true, + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_DC_DC_48V_12V_TEMP_R\"} ", + "hide": false, + "interval": "", + "legendFormat": "DC-DC board {{x}}", + "refId": "F" } ], - "title": "FPGA temperatures", - "transformations": [], + "title": "Uniboard2 Power Supply Temperatures", "type": "timeseries" }, { @@ -466,7 +729,7 @@ "h": 1, "w": 24, "x": 0, - "y": 9 + "y": 17 }, "id": 18, "panels": [], @@ -534,7 +797,7 @@ "h": 8, "w": 5, "x": 0, - "y": 10 + "y": 18 }, "id": 21, "options": { @@ -550,7 +813,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/apspu/1\",name=~\"APSPU_.*_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/apspu/1\",name=~\"APSPU_.*_VOUT_R\"}", "interval": "", "legendFormat": "{{name}} {{x}} ", "refId": "A" @@ -619,7 +882,7 @@ "h": 8, "w": 5, "x": 5, - "y": 10 + "y": 18 }, "id": 10, "options": { @@ -635,14 +898,14 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_CORE_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_CORE_VOUT_R\"}", "interval": "", "legendFormat": "Core board {{x}} node {{y}}", "refId": "A" }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_ERAM_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "ERAM board {{x}} node {{y}}", @@ -650,7 +913,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_RXGXB_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "TrRx board {{x}} node {{y}}", @@ -658,7 +921,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_TXGB_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_TXGB_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "TrHx board {{x}} node {{y}}", @@ -666,7 +929,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_FPGA_POL_PGM_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_FPGA_POL_PGM_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "IO board {{x}} node {{y}}", @@ -736,7 +999,7 @@ "h": 8, "w": 5, "x": 10, - "y": 10 + "y": 18 }, "id": 12, "options": { @@ -752,14 +1015,14 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N01_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_QSFP_N01_VOUT_R\"}", "interval": "", "legendFormat": "QSFP N01 board {{x}} ", "refId": "A" }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_QSFP_N23_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_QSFP_N23_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "QSFP N23 board {{x}}", @@ -767,7 +1030,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_SWITCH_1V2_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "Switch 1v2 board {{x}}", @@ -775,7 +1038,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_SWITCH_PHY_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "Switch PHY board {{x}}", @@ -783,7 +1046,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_POL_CLOCK_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_POL_CLOCK_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "Clock PWR board {{x}}", @@ -791,7 +1054,7 @@ }, { "exemplar": true, - "expr": "device_attribute{device=\"lts/unb2/1\",name=\"UNB2_DC_DC_48V_12V_VOUT_R\"}", + "expr": "device_attribute{device=\"stat/unb2/1\",name=\"UNB2_DC_DC_48V_12V_VOUT_R\"}", "hide": false, "interval": "", "legendFormat": "DC-DC board {{x}}", @@ -808,7 +1071,7 @@ "h": 1, "w": 24, "x": 0, - "y": 18 + "y": 26 }, "id": 20, "panels": [], @@ -878,7 +1141,7 @@ "h": 8, "w": 5, "x": 0, - "y": 19 + "y": 27 }, "id": 14, "options": { @@ -895,7 +1158,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/sdp/1\",name=\"TR_tod_pps_delta_R\"}", + "expr": "device_attribute{device=\"stat/sdp/1\",name=\"TR_tod_pps_delta_R\"}", "format": "time_series", "hide": false, "instant": false, @@ -923,5 +1186,5 @@ "timezone": "", "title": "Sensors", "uid": "KMRmQzd7z", - "version": 3 + "version": 1 } diff --git a/docker-compose/grafana/dashboards/version-information.json b/docker-compose/grafana/dashboards/version-information.json index 8b5e17bebd870d923d8944293a2bc66bddf79544..abd1f076841d0e4fd86dbd568226356f8270b697 100644 --- a/docker-compose/grafana/dashboards/version-information.json +++ b/docker-compose/grafana/dashboards/version-information.json @@ -229,7 +229,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/sdp/1\",name=\"FPGA_firmware_version_R\"}", + "expr": "device_attribute{device=\"stat/sdp/1\",name=\"FPGA_firmware_version_R\"}", "instant": true, "interval": "", "legendFormat": "", @@ -364,7 +364,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/sdp/1\",name=\"FPGA_hardware_version_R\"}", + "expr": "device_attribute{device=\"stat/sdp/1\",name=\"FPGA_hardware_version_R\"}", "instant": true, "interval": "", "legendFormat": "", @@ -487,7 +487,7 @@ "targets": [ { "exemplar": true, - "expr": "count(device_attribute{device=\"lts/sdp/1\",name=\"TR_software_version_R\"}) by (str_value)", + "expr": "count(device_attribute{device=\"stat/sdp/1\",name=\"TR_software_version_R\"}) by (str_value)", "instant": true, "interval": "", "legendFormat": "", @@ -601,7 +601,7 @@ "targets": [ { "exemplar": true, - "expr": "device_attribute{device=\"lts/recv/1\",name=\"RCU_version_R\"}", + "expr": "device_attribute{device=\"stat/recv/1\",name=\"RCU_version_R\"}", "instant": true, "interval": "", "legendFormat": "", diff --git a/docker-compose/integration-test.yml b/docker-compose/integration-test.yml index e0d1c6baf58948cdbee5a71ff2f859ab429dcd4b..defb45e3c3183516131795b283372ca784635d8c 100644 --- a/docker-compose/integration-test.yml +++ b/docker-compose/integration-test.yml @@ -15,11 +15,13 @@ services: container_name: ${CONTAINER_NAME_PREFIX}integration-test networks: - control + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw environment: - TANGO_HOST=${TANGO_HOST} - working_dir: /opt/lofar/tango/devices + working_dir: /opt/lofar/tango/tangostationcontrol entrypoint: - /usr/local/bin/wait-for-it.sh - ${TANGO_HOST} diff --git a/docker-compose/itango.yml b/docker-compose/itango.yml index 5b0874f2f3c936c1b57915580ac79be81b5edcb9..9b01c4ea25e2abc5849c9a98c29cc7601ba1115f 100644 --- a/docker-compose/itango.yml +++ b/docker-compose/itango.yml @@ -21,6 +21,8 @@ services: container_name: ${CONTAINER_NAME_PREFIX}itango networks: - control + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ..:/opt/lofar/tango:rw - ${HOME}:/hosthome diff --git a/docker-compose/itango/lofar-requirements.txt b/docker-compose/itango/lofar-requirements.txt index 1349c50ca993b51bb866a7880e3e7fb185049de8..b193887dbfdb59a4bc143ce6dd48a720ec5ad00c 100644 --- a/docker-compose/itango/lofar-requirements.txt +++ b/docker-compose/itango/lofar-requirements.txt @@ -1,8 +1,4 @@ +# Do not put tangostationcontrol dependencies here parso == 0.7.1 jedi == 0.17.2 -asyncua -astropy -python-logstash-async -gitpython -PyMySQL[rsa] -sqlalchemy +astropy diff --git a/docker-compose/jupyter/Dockerfile b/docker-compose/jupyter/Dockerfile index 8be3e9f3900b01e80893d38aedcb4f6397aa8fd0..5393cece6a74ff1de85e9c37ce6a8307e3a66cf5 100644 --- a/docker-compose/jupyter/Dockerfile +++ b/docker-compose/jupyter/Dockerfile @@ -25,6 +25,7 @@ RUN sudo pip3 install notebook-as-pdf # see https://github.com/jupyter/nbconvert/issues/1434 RUN sudo bash -c "echo DEFAULT_ARGS += [\\\"--no-sandbox\\\"] >> /usr/local/lib/python3.7/dist-packages/pyppeteer/launcher.py" +RUN sudo apt-get update -y RUN sudo apt-get install -y gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget libcairo-gobject2 libxinerama1 libgtk2.0-0 libpangoft2-1.0-0 libthai0 libpixman-1-0 libxcb-render0 libharfbuzz0b libdatrie1 libgraphite2-3 libgbm1 # Allow Download as -> PDF via LaTeX diff --git a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py index 05914fbf1bb3bbde3793c15f2f62b3e306bb022a..74692f10fff62684c21047eb373aebd70a876155 100644 --- a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py +++ b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py @@ -1,13 +1,13 @@ # Create shortcuts for our devices -apsct = DeviceProxy("LTS/APSCT/1") -apspu = DeviceProxy("LTS/APSPU/1") -recv = DeviceProxy("LTS/RECV/1") -sdp = DeviceProxy("LTS/SDP/1") -sst = DeviceProxy("LTS/SST/1") -xst = DeviceProxy("LTS/XST/1") -unb2 = DeviceProxy("LTS/UNB2/1") -boot = DeviceProxy("LTS/Boot/1") -docker = DeviceProxy("LTS/Docker/1") +apsct = DeviceProxy("STAT/APSCT/1") +apspu = DeviceProxy("STAT/APSPU/1") +recv = DeviceProxy("STAT/RECV/1") +sdp = DeviceProxy("STAT/SDP/1") +sst = DeviceProxy("STAT/SST/1") +xst = DeviceProxy("STAT/XST/1") +unb2 = DeviceProxy("STAT/UNB2/1") +boot = DeviceProxy("STAT/Boot/1") +docker = DeviceProxy("STAT/Docker/1") # Put them in a list in case one wants to iterate devices = [apsct, apspu, recv, sdp, sst, xst, unb2, boot, docker] diff --git a/docker-compose/lofar-device-base.yml b/docker-compose/lofar-device-base.yml index 22ecabca37c526867afe52461d7ce432964f8385..ce110ed85ba0cfb20b607ab7d08e70505d2392e8 100644 --- a/docker-compose/lofar-device-base.yml +++ b/docker-compose/lofar-device-base.yml @@ -20,5 +20,9 @@ services: args: SOURCE_IMAGE: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}-tango-itango:${TANGO_ITANGO_VERSION} container_name: ${CONTAINER_NAME_PREFIX}lofar-device-base + # These parameters are just visual queues, you have to define them again + # in derived docker-compose files! networks: - control + extra_hosts: + - "host.docker.internal:host-gateway" diff --git a/docker-compose/lofar-device-base/lofar-requirements.txt b/docker-compose/lofar-device-base/lofar-requirements.txt index 31b22c71689b481357cef56bf4940c1575a3b01d..10ad55d977c97793a352c13da323d84d3c826c0e 100644 --- a/docker-compose/lofar-device-base/lofar-requirements.txt +++ b/docker-compose/lofar-device-base/lofar-requirements.txt @@ -1,7 +1,5 @@ -asyncua +# Do not put tangostationcontrol dependencies here astropy -python-logstash-async -gitpython -PyMySQL[rsa] -sqlalchemy -docker + +# requirements to build tangocontrol +GitPython >= 3.1.24 # BSD diff --git a/docker-compose/prometheus.yml b/docker-compose/prometheus.yml index a0971c48fde4551809a936594aadcb6a79076712..604f4bf4bde93dd6d68aaf7f3b1da2fd3f884e83 100644 --- a/docker-compose/prometheus.yml +++ b/docker-compose/prometheus.yml @@ -16,4 +16,10 @@ services: - control ports: - "9090:9090" + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped diff --git a/docker-compose/rest.yml b/docker-compose/rest.yml index b76ed39c5319b10403a93db6736ce8d640380efc..467319399d6f3fec12a74068fea182195014b59e 100644 --- a/docker-compose/rest.yml +++ b/docker-compose/rest.yml @@ -33,3 +33,10 @@ services: - /usr/bin/supervisord - --configuration - /etc/supervisor/supervisord.conf + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" + restart: unless-stopped diff --git a/docker-compose/sdptr-sim/Dockerfile b/docker-compose/sdptr-sim/Dockerfile index fa23fe4d6458f4b7023c24b36774566cbac2163c..57fe98141f180a4d15a1e2d87c2c67be8f5894ff 100644 --- a/docker-compose/sdptr-sim/Dockerfile +++ b/docker-compose/sdptr-sim/Dockerfile @@ -16,5 +16,7 @@ RUN cd /sdptr && \ ./configure && \ bash -c "make -j `nproc` install" +COPY simulator.conf /sdptr/src/simulator.conf + WORKDIR /sdptr/src -CMD ["sdptr", "--type=LTS", "--configfile=uniboard.conf", "--nodaemon"] +CMD ["sdptr", "--type=simulator", "--configfile=simulator.conf", "--nodaemon"] diff --git a/docker-compose/sdptr-sim/simulator.conf b/docker-compose/sdptr-sim/simulator.conf new file mode 100644 index 0000000000000000000000000000000000000000..5ad69a8aed4807b815eeea18993d2b06e747b29f --- /dev/null +++ b/docker-compose/sdptr-sim/simulator.conf @@ -0,0 +1,19 @@ +# sdptr.conf +# configuration file for the SDP Translator. +# +# this config file holds settings for all [type]. +# +# # settings per type +# [LB_CORE] # [ant_band_station_type] +# n_fpgas = 16 # 8 or 16 +# first_pfga_nr = 0 # 0 for LB or 16 for HB +# ip_prefix = 10.99. # first part of ip (last part is hardware dependent) +# n_beamsets = 1 # 1 for 'LB', 'HB Remote' and 'HB International' and 2 for 'HB Core' + + +[simulator] +n_fpgas = 16 +first_fpga_nr = 0 +ip_prefix = 127.0. +n_beamsets = 1 + diff --git a/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter b/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter index 774d39a40ca19c9d979ad22565e57b4af3e9a831..dddb23ff587f6e9c837cdb77e7955e94272eca6f 160000 --- a/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter +++ b/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter @@ -1 +1 @@ -Subproject commit 774d39a40ca19c9d979ad22565e57b4af3e9a831 +Subproject commit dddb23ff587f6e9c837cdb77e7955e94272eca6f diff --git a/docker-compose/tango.yml b/docker-compose/tango.yml index 9fa0f5cde06f91b7cdc078f5c6481b013442e5ae..937cc5c8ecbe00b553d4692988e6cc2e5d7c51ef 100644 --- a/docker-compose/tango.yml +++ b/docker-compose/tango.yml @@ -28,6 +28,12 @@ services: - tangodb:/var/lib/mysql ports: - "3306:3306" + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped databaseds: @@ -55,4 +61,10 @@ services: - "2" - -ORBendPoint - giop:tcp::10000 + logging: + driver: syslog + options: + syslog-address: udp://${LOG_HOSTNAME}:1514 + syslog-format: rfc3164 + tag: "{{.Name}}" restart: unless-stopped diff --git a/docs/source/developer.rst b/docs/source/developer.rst index 517dfa324298e9451bfa5f9b25eef9726476686e..e2c36f83c2c458628038803506da62765b8f7004 100644 --- a/docs/source/developer.rst +++ b/docs/source/developer.rst @@ -48,7 +48,7 @@ Tango devices use CORBA, which require all servers to be able to reach each othe entrypoint: # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA # can't know about our Docker port forwarding - - python3 -u /opt/lofar/tango/devices/devices/sdp/sdp.py LTS -v -ORBendPoint giop:tcp:0:5701 -ORBendPointPublish giop:tcp:${HOSTNAME}:5701 + - python3 -u /opt/lofar/tango/devices/devices/sdp/sdp.py STAT -v -ORBendPoint giop:tcp:0:5701 -ORBendPointPublish giop:tcp:${HOSTNAME}:5701 Specifying the wrong ``$HOSTNAME`` or port can make your device unreachable, even if it is running. Note that ``$HOSTNAME`` is advertised as is, that is, it is resolved to an IP address by any client that wants to connect. This means the ``$HOSTNAME`` needs to be correct for both the other containers, and external clients. @@ -59,3 +59,40 @@ For more information, see: - https://huihoo.org/ace_tao/ACE-5.2+TAO-1.2/TAO/docs/ORBEndpoint.html - http://omniorb.sourceforge.net/omni42/omniNames.html - https://sourceforge.net/p/omniorb/svn/HEAD/tree/trunk/omniORB/src/lib/omniORB/orbcore/tcp/tcpEndpoint.cc + +Logging +------------------------- + +The ELK stack collects the logs from the containers, as well as any external processes that send theirs. It is the *Logstash* part of ELK that is responsible for this. The following interfaces are available for this purpose: + ++-------------+------------+-------------------------------------------------------------------------------------------------------------+ +| Interface | Port | Note | ++=============+============+=============================================================================================================+ +| Syslog | 1514/udp | Recommended over TCP, as the ELK stack might be down. | ++-------------+------------+-------------------------------------------------------------------------------------------------------------+ +| Syslog | 1514/tcp | | ++-------------+------------+-------------------------------------------------------------------------------------------------------------+ +| JSON | 5959/tcp | From python, recommended is the `LogStash Async <https://pypi.org/project/python-logstash-async/>`_ module. | ++-------------+------------+-------------------------------------------------------------------------------------------------------------+ +| Beats | 5044/tcp | Use `FileBeat <https://www.elastic.co/beats/filebeat>`_ to watch logs locally, and forward them to ELK. | ++-------------+------------+-------------------------------------------------------------------------------------------------------------+ + +We recommend making sure the contents of your log lines are parsed correctly, especially if logs are routed to the *Syslog* input. These configurations are stored in ``docker-compose/elk/logstash/conf.d``. An example: + +.. literalinclude:: ../../docker-compose/elk/logstash/conf.d/22-parse-tango-rest.conf + +Log from Python +````````````````` + +The ``common.lofar_logging`` module provides an easy way to log to the ELK stack from a Python Tango device. + +Log from Docker +````````````````` + +Not all Docker containers run our Python programs, and can forward the logs themselves. For those, we use the ``syslog`` log driver in Docker. Extend the ``docker compose`` files with: + +.. literalinclude:: ../../docker-compose/rest.yml + :start-at: logging: + :end-before: restart: + +Logs forwarded in this way are provided with the container name, their timestamp, and a log level guessed by Docker. It is thus wise to parse the message content further in Logstash (see above). diff --git a/docs/source/devices/boot.rst b/docs/source/devices/boot.rst index 53e2bab88d35f4a751c8e3809a24c1d3a0113f6b..45af638d95ac12ac7f3236a5f0b126a4777714ad 100644 --- a/docs/source/devices/boot.rst +++ b/docs/source/devices/boot.rst @@ -3,7 +3,7 @@ Boot ==================== -The ``boot == DeviceProxy("LTS/Boot/1")`` device is responsible for (re)starting and initialising the other devices. Devices which are not reachable, for example because their docker container is explicitly stopped, are skipped during initialisation. This device provides the following commands: +The ``boot == DeviceProxy("STAT/Boot/1")`` device is responsible for (re)starting and initialising the other devices. Devices which are not reachable, for example because their docker container is explicitly stopped, are skipped during initialisation. This device provides the following commands: :initialise_station(): Stop and start the other devices in the correct order, set their default values, and command them to initialise their hardware. This procedure runs asynchronously, causing this command to return immediately. Initialisation is aborted if an error is encountered. diff --git a/docs/source/devices/docker.rst b/docs/source/devices/docker.rst index df80cf64dc6be38f405688d9d11c7519c59079c3..6ac9d06d452b5c39a48d27687b225cd48c0af769 100644 --- a/docs/source/devices/docker.rst +++ b/docs/source/devices/docker.rst @@ -3,7 +3,7 @@ Docker ==================== -The ``docker == DeviceProxy("LTS/Docker/1")`` device controls the docker containers. It allows starting and stopping them, and querying whether they are running. Each container is represented by two attributes: +The ``docker == DeviceProxy("STAT/Docker/1")`` device controls the docker containers. It allows starting and stopping them, and querying whether they are running. Each container is represented by two attributes: :<container>_R: Returns whether the container is running. diff --git a/docs/source/devices/recv.rst b/docs/source/devices/recv.rst index d92ac6eca48eacc17667133b057bc9b127e5e08f..847f8bb51f7f52850e66b0d25c01269b9961e726 100644 --- a/docs/source/devices/recv.rst +++ b/docs/source/devices/recv.rst @@ -1,7 +1,7 @@ RECV ==================== -The ``recv == DeviceProxy("LTS/RECV/1")`` device controls the RCUs, the LBA antennas, and HBA tiles. Central to its operation are the masks (see also :ref:`attribute-masks`): +The ``recv == DeviceProxy("STAT/RECV/1")`` device controls the RCUs, the LBA antennas, and HBA tiles. Central to its operation are the masks (see also :ref:`attribute-masks`): :RCU_mask_RW: Controls which RCUs will actually be configured when attributes referring to RCUs are written. diff --git a/docs/source/devices/sdp.rst b/docs/source/devices/sdp.rst index b5f38ca5b2d8fe346a1ee90ec5a3a49c0b939af7..c4d4032f47e7e4988437adb54dc7778bd53dc4b1 100644 --- a/docs/source/devices/sdp.rst +++ b/docs/source/devices/sdp.rst @@ -1,7 +1,7 @@ SDP ==================== -The ``sdp == DeviceProxy("LTS/SDP/1")``` device controls the digital signal processing in SDP, performed by the firmware on the FPGAs on the Uniboards. Central to its operation is the mask (see also :ref:`attribute-masks`): +The ``sdp == DeviceProxy("STAT/SDP/1")``` device controls the digital signal processing in SDP, performed by the firmware on the FPGAs on the Uniboards. Central to its operation is the mask (see also :ref:`attribute-masks`): :TR_fpga_mask_RW: Controls which FPGAs will actually be configured when attributes referring to FPGAs are written. diff --git a/docs/source/devices/sst-xst.rst b/docs/source/devices/sst-xst.rst index b5c5c1c57cdd72da3f4b71c23110b75dc009fe6c..cdb689e457dc2d6abebcfc1391f057135f30b722 100644 --- a/docs/source/devices/sst-xst.rst +++ b/docs/source/devices/sst-xst.rst @@ -1,7 +1,7 @@ SST and XST ==================== -The ``sst == DeviceProxy("LTS/SST/1")`` and ``xst == DeviceProxy("LTS/XST/1")`` devices manages the SSTs (subband statistics) and XSTs (crosslet statistics), respectively. The statistics are emitted piece-wise through UDP packets by the FPGAs on the Uniboards in SDP. By default, each device configures the statistics to be streamed to itself (the device), from where the user can obtain them. +The ``sst == DeviceProxy("STAT/SST/1")`` and ``xst == DeviceProxy("STAT/XST/1")`` devices manages the SSTs (subband statistics) and XSTs (crosslet statistics), respectively. The statistics are emitted piece-wise through UDP packets by the FPGAs on the Uniboards in SDP. By default, each device configures the statistics to be streamed to itself (the device), from where the user can obtain them. The statistics are exposed in two ways, as: diff --git a/docs/source/devices/using.rst b/docs/source/devices/using.rst index 66760ebfd53de7df20fe4e58144c7d4b99dc3ecb..b5c41bd8089bc88d606ee0fe7bf8c442ff259475 100644 --- a/docs/source/devices/using.rst +++ b/docs/source/devices/using.rst @@ -84,7 +84,7 @@ Attributes The device can be operated in ``ON`` state, where it exposes *attributes* and *commands*. The attributes can be accessed as python properties, for example:: - recv = DeviceProxy("LTS/RECV/1") + recv = DeviceProxy("STAT/RECV/1") # turn on all LED0s recv.RCU_LED0_RW = [True] * 32 @@ -115,7 +115,7 @@ The masks only affect *writing* to attributes. Reading attributes (monitoring po For example, the ``RCU_mask_RW`` array is the RCU mask in the ``recv`` device. It behaves as follows, when we interact with the ``RCU_LED0_R(W)`` attributes:: - recv = DeviceProxy("LTS/RECV/1") + recv = DeviceProxy("STAT/RECV/1") # set mask to control all RCUs recv.RCU_mask_RW = [True] * 32 diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 8e35fceab3ec6ea07124e1181fccffdbe3cea679..1ed4fceacb85e6862c6f49d725fd4c53eb096081 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -66,7 +66,9 @@ SSTs/XSTs Some SSTs/XSTs packets do arrive, but not all, and/or the matrices remain zero? `````````````````````````````````````````````````````````````````````````````````````````````````````````````` -So ``sst.nof_packets_received`` / ``xst.nof_packets_received`` is increasing, telling you packets are arriving. But they're apparently dropped or contain zeroes. First, check the following settings: +So ``sst.nof_packets_received`` / ``xst.nof_packets_received`` is increasing, telling you packets are arriving. But they're apparently dropped or contain zeroes. + +The ``sdp.set_defaults()`` command, followed by ``sst.set_defaults()`` / ``xst.set_defaults()``, should reset that device to its default settings, which should result in a working system again. If not, or if the default configuration is not correct, check the following settings: - ``sdp.TR_fpga_mask_RW[x] == True``, to make sure we're actually configuring the FPGAs, - ``sdp.FPGA_wg_enable_RW[x] == False``, or the Waveform Generator might be replacing our the antenna data with zeroes, @@ -84,7 +86,7 @@ I am not receiving any XSTs and/or SSTs packets from SDP! Are you sure? If ``sst.nof_packets_received`` / ``xst.nof_packets_received`` is actually increasing, the packets are arriving, but are not parsable by the SST/XST device. If so, see the previous question. -Many settings need to be correct for the statistics emitted by the SDP FPGAs to reach our devices correctly. Here is a brief overview: +The ``sdp.set_defaults()`` command, followed by ``sst.set_defaults()`` / ``xst.set_defaults()``, should reset that device to its default settings, which should result in a working system again. If not, or if the default configuration is not correct, check the following settings: - ``sdp.TR_fpga_mask_RW[x] == True``, to make sure we're actually configuring the FPGAs, - ``sdp.FPGA_communication_error_R[x] == False``, to verify the FPGAs can be reached by SDP, diff --git a/docs/source/interfaces/control.rst b/docs/source/interfaces/control.rst index 3c514f11d7a3e5a4bbc1c7339bac3bed0820d70f..adb5775527f554b0ca130afe5c478b165e64ab65 100644 --- a/docs/source/interfaces/control.rst +++ b/docs/source/interfaces/control.rst @@ -38,8 +38,8 @@ Then, if we know what devices are available on the station, we can access them d os.environ["TANGO_HOST"] = "localhost:10000" # Construct a remote reference to a specific device. - # One can also use "tango://localhost:10000/LTS/Boot/1" if TANGO_HOST is not set - boot_device = tango.DeviceProxy("LTS/Boot/1") + # One can also use "tango://localhost:10000/STAT/Boot/1" if TANGO_HOST is not set + boot_device = tango.DeviceProxy("STAT/Boot/1") # Print the device's state. print(boot_device.state()) @@ -56,8 +56,8 @@ To obtain a list of all devices, we need to access the database:: db = tango.Database() # Retrieve the available devices, excluding any Tango-internal ones. - # This returns for example: ['LTS/Boot/1', 'LTS/Docker/1', ...] - devices = list(db.get_device_exported("LTS/*")) + # This returns for example: ['STAT/Boot/1', 'STAT/Docker/1', ...] + devices = list(db.get_device_exported("STAT/*")) # Connect to any of them. any_device = tango.DeviceProxy(devices[0]) @@ -77,7 +77,7 @@ We also provide a ReST API to allow the station to be controlled without needing - retrieving the device state, - and more. -For example, retrieving http://localhost:8080/tango/rest/v10/hosts/databaseds;port=10000/devices/LTS/SDP/1/state returns the following JSON document:: +For example, retrieving http://localhost:8080/tango/rest/v10/hosts/databaseds;port=10000/devices/STAT/SDP/1/state returns the following JSON document:: {"state":"ON","status":"The device is in ON state."} diff --git a/docs/source/interfaces/logs.rst b/docs/source/interfaces/logs.rst index 960efcd95b5306ab1904ffd8519e36af85099f0f..fa0d29765c5d228454222a8f4a8d3d8f935c46be 100644 --- a/docs/source/interfaces/logs.rst +++ b/docs/source/interfaces/logs.rst @@ -15,11 +15,11 @@ ELK To monitor the logs remotely, or to browse older logs, use the *ELK stack* that is included on the station, and served on http://localhost:5601. ELK, or ElasticSearch + Logstash + Kibana, is a popular log collection and querying system. Currently, the following logs are collected in our ELK installation: - Logs of all devices, -- Logs of the Jupyter notebook server. +- Logs of the Docker containers. If you browse to the ELK stack (actually, it is Kibana providing the GUI), your go-to is the *Discover* view at http://localhost:5601/app/discover. There, you can construct (and save, load) a dashboard that provides a custom view of the logs, based on the *index pattern* ``logstash-*``. There is a lot to take in, and there are excellent Kibana tutorials on the web. -To get going, use for example `this dashboard <http://localhost:5601/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-60m,to:now))&_a=(columns:!(extra.lofar_id,level,message),filters:!(),index:'1e8ca200-1be0-11ec-a85f-b97e4206c18b',interval:auto,query:(language:kuery,query:''),sort:!())>`_, which shows the logs of the last hour, with some useful columns added to the default timestamp and message columns. Expand the time range if no logs appear, to look further back. You should see something like: +To get going, use for example `this dashboard <http://localhost:5601/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))&_a=(columns:!(extra.lofar_id,program,level,message),filters:!(),index:'1e8ca200-1be0-11ec-a85f-b97e4206c18b',interval:auto,query:(language:kuery,query:'extra.lofar_id.keyword%20:%20*'),sort:!())>`_, which shows the logs of the last hour, with some useful columns added to the default timestamp and message columns. Expand the time range if no logs appear, to look further back. You should see something like: .. image:: elk_last_hour.png diff --git a/docs/source/interfaces/monitoring.rst b/docs/source/interfaces/monitoring.rst index 7d8a85fdf5bd7c103119a89a8dbae127040a5240..bb1ef494b320a40cd44aec789a0cf8d88653fa2a 100644 --- a/docs/source/interfaces/monitoring.rst +++ b/docs/source/interfaces/monitoring.rst @@ -36,7 +36,7 @@ Prometheus Prometheus stores attributes in the following format:: - device_attribute{device="lts/recv/1", + device_attribute{device="stat/recv/1", dim_x="32", dim_y="0", instance="tango-prometheus-exporter:8000", job="tango", diff --git a/jupyter-notebooks/.ipynb_checkpoints/test_device-checkpoint.ipynb b/jupyter-notebooks/.ipynb_checkpoints/test_device-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..16749ce8b9e2f50e6cae56615790b9e5f19211ef --- /dev/null +++ b/jupyter-notebooks/.ipynb_checkpoints/test_device-checkpoint.ipynb @@ -0,0 +1,163 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "id": "waiting-chance", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "moving-alexandria", + "metadata": {}, + "outputs": [ + { + "ename": "DevFailed", + "evalue": "DevFailed[\nDevError[\n desc = device lts/xst/1 not defined in the database !\n origin = DataBase::ImportDevice()\n reason = DB_DeviceNotDefined\nseverity = ERR]\n\nDevError[\n desc = Failed to execute command_inout on device sys/database/2, command DbImportDevice\n origin = Connection::command_inout()\n reason = API_CommandFailed\nseverity = ERR]\n\nDevError[\n desc = Can't connect to device lts/xst/1\n origin = DeviceProxy::DeviceProxy\n reason = API_DeviceNotDefined\nseverity = ERR]\n]", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mDevFailed\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/ipykernel_22/3496973635.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0md\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mDeviceProxy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"LTS/XST/1\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__init__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_executors\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mGreenMode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGevent\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'threadpool'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 206\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_executors\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mGreenMode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAsyncio\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'asyncio_executor'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 207\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mDeviceProxy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init_orig__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 208\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDevFailed\u001b[0m: DevFailed[\nDevError[\n desc = device lts/xst/1 not defined in the database !\n origin = DataBase::ImportDevice()\n reason = DB_DeviceNotDefined\nseverity = ERR]\n\nDevError[\n desc = Failed to execute command_inout on device sys/database/2, command DbImportDevice\n origin = Connection::command_inout()\n reason = API_CommandFailed\nseverity = ERR]\n\nDevError[\n desc = Can't connect to device lts/xst/1\n origin = DeviceProxy::DeviceProxy\n reason = API_DeviceNotDefined\nseverity = ERR]\n]" + ] + } + ], + "source": [ + "d=DeviceProxy(\"LTS/XST/1\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ranking-aluminum", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'd' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/ipykernel_22/3213548382.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mstate\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mstate\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"OFF\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minitialise\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'd' is not defined" + ] + } + ], + "source": [ + "state = str(d.state())\n", + "\n", + "if state == \"OFF\":\n", + " d.initialise()\n", + " time.sleep(1)\n", + "state = str(d.state())\n", + "if state == \"STANDBY\":\n", + " d.on()\n", + "state = str(d.state())\n", + "if state == \"ON\":\n", + " print(\"Device is now in on state\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "beneficial-evidence", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "packet_count_R [55]\n", + "last_packet_timestamp_R [1623249385]\n", + "queue_percentage_used_R [0.]\n", + "State <function __get_command_func.<locals>.f at 0x7fcb205fd0d0>\n", + "Status <function __get_command_func.<locals>.f at 0x7fcb205fd0d0>\n" + ] + } + ], + "source": [ + "attr_names = d.get_attribute_list()\n", + "\n", + "for i in attr_names:\n", + " exec(\"value = print(i, d.{})\".format(i))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "sporting-current", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.0" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.RCU_mask_RW = [False, False, False, False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False,]\n", + "time.sleep(1)\n", + "print(d.RCU_mask_RW)\n", + "\n", + "monitor_rate = d.RCU_monitor_rate_RW\n", + "print(\"current monitoring rate: {}, setting to {}\".format(monitor_rate, monitor_rate + 1))\n", + "monitor_rate = monitor_rate + 1\n", + "\n", + "time.sleep(1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "sharing-mechanics", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ruled-tracy", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "StationControl", + "language": "python", + "name": "stationcontrol" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/jupyter-notebooks/Archiving_load_test.ipynb b/jupyter-notebooks/Archiving_load_test.ipynb index afe61dacb2c9d01c17035ab641b4affadd31d7fa..64430c99049390ca89b18996ad518c5f0e59de37 100644 --- a/jupyter-notebooks/Archiving_load_test.ipynb +++ b/jupyter-notebooks/Archiving_load_test.ipynb @@ -187,7 +187,7 @@ } ], "source": [ - "device_name = 'LTS/RECV/1'\n", + "device_name = 'STAT/RECV/1'\n", "d=DeviceProxy(device_name) \n", "state = str(d.state())\n", "print(state)" @@ -548,7 +548,7 @@ ], "source": [ "# Update the archive time of an attribute\n", - "archiver.update_archiving_attribute('LTS/RECV/1/rcu_id_r',polling_period=1000,event_period=10000)" + "archiver.update_archiving_attribute('STAT/RECV/1/rcu_id_r',polling_period=1000,event_period=10000)" ] }, { @@ -720,7 +720,7 @@ ], "source": [ "# Add SDP attributes to load test\n", - "sdp_name = 'LTS/SDP/1'\n", + "sdp_name = 'STAT/SDP/1'\n", "d2=DeviceProxy(sdp_name) \n", "state = str(d2.state())\n", "print(state)\n", @@ -1217,7 +1217,7 @@ } ], "source": [ - "#archiver.remove_attribute_from_archiver('lts/recv/1/rcu_temperature_r')\n", + "#archiver.remove_attribute_from_archiver('STAT/recv/1/rcu_temperature_r')\n", "archiver.remove_attributes_in_error()" ] }, @@ -1262,4 +1262,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/Docker_notebook.ipynb b/jupyter-notebooks/Docker_notebook.ipynb index facc20c3e1e1d561504ef09b08e2e78296d0fb39..6df68c95bff37d25ccbb5ada0fabd4850b07386d 100644 --- a/jupyter-notebooks/Docker_notebook.ipynb +++ b/jupyter-notebooks/Docker_notebook.ipynb @@ -17,7 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "d=DeviceProxy(\"LTS/Docker/1\")" + "d=DeviceProxy(\"STAT/Docker/1\")" ] }, { @@ -136,4 +136,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/RECV_archive_all_attributes.ipynb b/jupyter-notebooks/RECV_archive_all_attributes.ipynb index 9941f00e3814827d3fddc73258bd5fedfc27b5c8..384d1522153c46ec6f1ebf96f0593830cecf75e7 100644 --- a/jupyter-notebooks/RECV_archive_all_attributes.ipynb +++ b/jupyter-notebooks/RECV_archive_all_attributes.ipynb @@ -96,7 +96,7 @@ } ], "source": [ - "device_name = 'LTS/RECV/1'\n", + "device_name = 'STAT/RECV/1'\n", "d=DeviceProxy(device_name) \n", "state = str(d.state())\n", "print(state)" @@ -379,4 +379,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/RECV_notebook.ipynb b/jupyter-notebooks/RECV_notebook.ipynb index 0f246c2bdd6f89e4bae6f06d46caef643091045c..6892f75ca7a91ef3e5bed866c0e3a6c3e9f2d1bb 100644 --- a/jupyter-notebooks/RECV_notebook.ipynb +++ b/jupyter-notebooks/RECV_notebook.ipynb @@ -17,7 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "d=DeviceProxy(\"LTS/RECV/1\")" + "d=DeviceProxy(\"STAT/RECV/1\")" ] }, { @@ -64,16 +64,16 @@ "evalue": "DevFailed[\nDevError[\n desc = Read value for attribute FPGA_mask_RW has not been updated\n origin = Device_3Impl::read_attributes_no_except\n reason = API_AttrValueNotSet\nseverity = ERR]\n\nDevError[\n desc = Failed to read_attribute on device lts/sdp/1, attribute FPGA_mask_RW\n origin = DeviceProxy::read_attribute()\n reason = API_AttributeFailed\nseverity = ERR]\n]", "output_type": "error", "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mDevFailed\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_22/2885399456.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m values = [\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_mask_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_mask_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_status_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_status_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__getattr\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 319\u001b[0m \u001b[0mattr_info\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__get_attr_cache\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname_l\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 320\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 321\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m__get_attribute_value\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 322\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mname_l\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__get_pipe_cache\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__get_attribute_value\u001b[0;34m(self, attr_info, name)\u001b[0m\n\u001b[1;32m 281\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__get_attribute_value\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 282\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0menum_class\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 283\u001b[0;31m \u001b[0mattr_value\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 284\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0menum_class\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 285\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0menum_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattr_value\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001b[0m in \u001b[0;36mgreener\u001b[0;34m(obj, *args, **kwargs)\u001b[0m\n\u001b[1;32m 193\u001b[0m \u001b[0mgreen_mode\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0maccess\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'green_mode'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 194\u001b[0m \u001b[0mexecutor\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_object_executor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgreen_mode\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 195\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mexecutor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwait\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 196\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 197\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mgreener\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, fn, args, kwargs, wait, timeout)\u001b[0m\n\u001b[1;32m 107\u001b[0m \u001b[0;31m# Sychronous (no delegation)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masynchronous\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0min_executor_context\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 109\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 110\u001b[0m \u001b[0;31m# Asynchronous delegation\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[0maccessor\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdelegate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__read_attribute\u001b[0;34m(self, value, extract_as)\u001b[0m\n\u001b[1;32m 439\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 440\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__DeviceProxy__read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mextract_as\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mExtractAs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNumpy\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 441\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m__check_read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mextract_as\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 442\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 443\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__check_read_attribute\u001b[0;34m(dev_attr)\u001b[0m\n\u001b[1;32m 155\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__check_read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdev_attr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 156\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdev_attr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhas_failed\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 157\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mDevFailed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdev_attr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_err_stack\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 158\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdev_attr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 159\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mDevFailed\u001b[0m: DevFailed[\nDevError[\n desc = Read value for attribute FPGA_mask_RW has not been updated\n origin = Device_3Impl::read_attributes_no_except\n reason = API_AttrValueNotSet\nseverity = ERR]\n\nDevError[\n desc = Failed to read_attribute on device lts/sdp/1, attribute FPGA_mask_RW\n origin = DeviceProxy::read_attribute()\n reason = API_AttributeFailed\nseverity = ERR]\n]" + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mDevFailed\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m/tmp/ipykernel_22/2885399456.py\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[1;32m 1\u001B[0m values = [\n\u001B[0;32m----> 2\u001B[0;31m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_mask_RW\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_mask_RW\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 3\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_scrap_R\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_scrap_R\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 4\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_scrap_RW\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_scrap_RW\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 5\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_status_R\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_status_R\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__DeviceProxy__getattr\u001B[0;34m(self, name)\u001B[0m\n\u001B[1;32m 319\u001B[0m \u001B[0mattr_info\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m__get_attr_cache\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mget\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname_l\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 320\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 321\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0m__get_attribute_value\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 322\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 323\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0mname_l\u001B[0m \u001B[0;32min\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m__get_pipe_cache\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__get_attribute_value\u001B[0;34m(self, attr_info, name)\u001B[0m\n\u001B[1;32m 281\u001B[0m \u001B[0;32mdef\u001B[0m \u001B[0m__get_attribute_value\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 282\u001B[0m \u001B[0m_\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0menum_class\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 283\u001B[0;31m \u001B[0mattr_value\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mread_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mvalue\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 284\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0menum_class\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 285\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0menum_class\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mattr_value\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001B[0m in \u001B[0;36mgreener\u001B[0;34m(obj, *args, **kwargs)\u001B[0m\n\u001B[1;32m 193\u001B[0m \u001B[0mgreen_mode\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0maccess\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m'green_mode'\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;32mNone\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 194\u001B[0m \u001B[0mexecutor\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mget_object_executor\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mobj\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mgreen_mode\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 195\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0mexecutor\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mrun\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mfn\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0margs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mkwargs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mwait\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mwait\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mtimeout\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mtimeout\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 196\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 197\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mgreener\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001B[0m in \u001B[0;36mrun\u001B[0;34m(self, fn, args, kwargs, wait, timeout)\u001B[0m\n\u001B[1;32m 107\u001B[0m \u001B[0;31m# Sychronous (no delegation)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 108\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0;32mnot\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0masynchronous\u001B[0m \u001B[0;32mor\u001B[0m \u001B[0;32mnot\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0min_executor_context\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 109\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0mfn\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m*\u001B[0m\u001B[0margs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 110\u001B[0m \u001B[0;31m# Asynchronous delegation\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 111\u001B[0m \u001B[0maccessor\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mdelegate\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mfn\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m*\u001B[0m\u001B[0margs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__DeviceProxy__read_attribute\u001B[0;34m(self, value, extract_as)\u001B[0m\n\u001B[1;32m 439\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 440\u001B[0m \u001B[0;32mdef\u001B[0m \u001B[0m__DeviceProxy__read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mvalue\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mextract_as\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mExtractAs\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mNumpy\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 441\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0m__check_read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mvalue\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mextract_as\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 442\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 443\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__check_read_attribute\u001B[0;34m(dev_attr)\u001B[0m\n\u001B[1;32m 155\u001B[0m \u001B[0;32mdef\u001B[0m \u001B[0m__check_read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mdev_attr\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 156\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0mdev_attr\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mhas_failed\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 157\u001B[0;31m \u001B[0;32mraise\u001B[0m \u001B[0mDevFailed\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m*\u001B[0m\u001B[0mdev_attr\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mget_err_stack\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 158\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mdev_attr\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 159\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;31mDevFailed\u001B[0m: DevFailed[\nDevError[\n desc = Read value for attribute FPGA_mask_RW has not been updated\n origin = Device_3Impl::read_attributes_no_except\n reason = API_AttrValueNotSet\nseverity = ERR]\n\nDevError[\n desc = Failed to read_attribute on device lts/sdp/1, attribute FPGA_mask_RW\n origin = DeviceProxy::read_attribute()\n reason = API_AttributeFailed\nseverity = ERR]\n]" ] } ], @@ -147,17 +147,17 @@ "evalue": "DevFailed[\nDevError[\n desc = Read value for attribute CLK_Enable_PWR_R has not been updated\n origin = Device_3Impl::read_attributes_no_except\n reason = API_AttrValueNotSet\nseverity = ERR]\n\nDevError[\n desc = Failed to read_attribute on device lts/recv/1, attribute CLK_Enable_PWR_R\n origin = DeviceProxy::read_attribute()\n reason = API_AttributeFailed\nseverity = ERR]\n]", "output_type": "error", "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mDevFailed\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_26/3093379163.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mattr_names\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mexec\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"value = print(i, d.{})\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m<string>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__getattr\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 319\u001b[0m \u001b[0mattr_info\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__get_attr_cache\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname_l\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 320\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 321\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m__get_attribute_value\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 322\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mname_l\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__get_pipe_cache\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__get_attribute_value\u001b[0;34m(self, attr_info, name)\u001b[0m\n\u001b[1;32m 281\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__get_attribute_value\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 282\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0menum_class\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mattr_info\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 283\u001b[0;31m \u001b[0mattr_value\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 284\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0menum_class\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 285\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0menum_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattr_value\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001b[0m in \u001b[0;36mgreener\u001b[0;34m(obj, *args, **kwargs)\u001b[0m\n\u001b[1;32m 193\u001b[0m \u001b[0mgreen_mode\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0maccess\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'green_mode'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 194\u001b[0m \u001b[0mexecutor\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_object_executor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgreen_mode\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 195\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mexecutor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwait\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 196\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 197\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mgreener\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, fn, args, kwargs, wait, timeout)\u001b[0m\n\u001b[1;32m 107\u001b[0m \u001b[0;31m# Sychronous (no delegation)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masynchronous\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0min_executor_context\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 109\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 110\u001b[0m \u001b[0;31m# Asynchronous delegation\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[0maccessor\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdelegate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__read_attribute\u001b[0;34m(self, value, extract_as)\u001b[0m\n\u001b[1;32m 439\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 440\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__DeviceProxy__read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mextract_as\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mExtractAs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNumpy\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 441\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m__check_read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mextract_as\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 442\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 443\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__check_read_attribute\u001b[0;34m(dev_attr)\u001b[0m\n\u001b[1;32m 155\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__check_read_attribute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdev_attr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 156\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdev_attr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhas_failed\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 157\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mDevFailed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdev_attr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_err_stack\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 158\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdev_attr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 159\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mDevFailed\u001b[0m: DevFailed[\nDevError[\n desc = Read value for attribute CLK_Enable_PWR_R has not been updated\n origin = Device_3Impl::read_attributes_no_except\n reason = API_AttrValueNotSet\nseverity = ERR]\n\nDevError[\n desc = Failed to read_attribute on device lts/recv/1, attribute CLK_Enable_PWR_R\n origin = DeviceProxy::read_attribute()\n reason = API_AttributeFailed\nseverity = ERR]\n]" + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mDevFailed\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m/tmp/ipykernel_26/3093379163.py\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[1;32m 3\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 4\u001B[0m \u001B[0;32mfor\u001B[0m \u001B[0mi\u001B[0m \u001B[0;32min\u001B[0m \u001B[0mattr_names\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m----> 5\u001B[0;31m \u001B[0mexec\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m\"value = print(i, d.{})\"\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mformat\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mi\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m", + "\u001B[0;32m<string>\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__DeviceProxy__getattr\u001B[0;34m(self, name)\u001B[0m\n\u001B[1;32m 319\u001B[0m \u001B[0mattr_info\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m__get_attr_cache\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mget\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname_l\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 320\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 321\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0m__get_attribute_value\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 322\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 323\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0mname_l\u001B[0m \u001B[0;32min\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m__get_pipe_cache\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__get_attribute_value\u001B[0;34m(self, attr_info, name)\u001B[0m\n\u001B[1;32m 281\u001B[0m \u001B[0;32mdef\u001B[0m \u001B[0m__get_attribute_value\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 282\u001B[0m \u001B[0m_\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0menum_class\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mattr_info\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 283\u001B[0;31m \u001B[0mattr_value\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mread_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mvalue\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 284\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0menum_class\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 285\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0menum_class\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mattr_value\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001B[0m in \u001B[0;36mgreener\u001B[0;34m(obj, *args, **kwargs)\u001B[0m\n\u001B[1;32m 193\u001B[0m \u001B[0mgreen_mode\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0maccess\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m'green_mode'\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;32mNone\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 194\u001B[0m \u001B[0mexecutor\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mget_object_executor\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mobj\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mgreen_mode\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 195\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0mexecutor\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mrun\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mfn\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0margs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mkwargs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mwait\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mwait\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mtimeout\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mtimeout\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 196\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 197\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mgreener\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/green.py\u001B[0m in \u001B[0;36mrun\u001B[0;34m(self, fn, args, kwargs, wait, timeout)\u001B[0m\n\u001B[1;32m 107\u001B[0m \u001B[0;31m# Sychronous (no delegation)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 108\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0;32mnot\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0masynchronous\u001B[0m \u001B[0;32mor\u001B[0m \u001B[0;32mnot\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0min_executor_context\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 109\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0mfn\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m*\u001B[0m\u001B[0margs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 110\u001B[0m \u001B[0;31m# Asynchronous delegation\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 111\u001B[0m \u001B[0maccessor\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mdelegate\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mfn\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m*\u001B[0m\u001B[0margs\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__DeviceProxy__read_attribute\u001B[0;34m(self, value, extract_as)\u001B[0m\n\u001B[1;32m 439\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 440\u001B[0m \u001B[0;32mdef\u001B[0m \u001B[0m__DeviceProxy__read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mvalue\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mextract_as\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mExtractAs\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mNumpy\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 441\u001B[0;31m \u001B[0;32mreturn\u001B[0m \u001B[0m__check_read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mvalue\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mextract_as\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 442\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 443\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__check_read_attribute\u001B[0;34m(dev_attr)\u001B[0m\n\u001B[1;32m 155\u001B[0m \u001B[0;32mdef\u001B[0m \u001B[0m__check_read_attribute\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mdev_attr\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 156\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0mdev_attr\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mhas_failed\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 157\u001B[0;31m \u001B[0;32mraise\u001B[0m \u001B[0mDevFailed\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m*\u001B[0m\u001B[0mdev_attr\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mget_err_stack\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 158\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mdev_attr\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 159\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;31mDevFailed\u001B[0m: DevFailed[\nDevError[\n desc = Read value for attribute CLK_Enable_PWR_R has not been updated\n origin = Device_3Impl::read_attributes_no_except\n reason = API_AttrValueNotSet\nseverity = ERR]\n\nDevError[\n desc = Failed to read_attribute on device lts/recv/1, attribute CLK_Enable_PWR_R\n origin = DeviceProxy::read_attribute()\n reason = API_AttributeFailed\nseverity = ERR]\n]" ] } ], @@ -191,4 +191,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/UNB2_notebook.ipynb b/jupyter-notebooks/UNB2_notebook.ipynb index d95aebef21b589d381ac137874282eaf579b8776..d3fcdc6794d746d2168f661ec4f3fc08f9550ebe 100644 --- a/jupyter-notebooks/UNB2_notebook.ipynb +++ b/jupyter-notebooks/UNB2_notebook.ipynb @@ -17,7 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "d=DeviceProxy(\"LTS/UNB2/1\")" + "d=DeviceProxy(\"STAT/UNB2/1\")" ] }, { @@ -240,12 +240,12 @@ "evalue": "FPGA_mask_RW", "output_type": "error", "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_22/2885399456.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m values = [\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_mask_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_mask_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_scrap_RW\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_scrap_RW\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFPGA_status_R\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"FPGA_status_R\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__getattr\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 353\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_pipe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 354\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 355\u001b[0;31m \u001b[0msix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_from\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 356\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 357\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/six.py\u001b[0m in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n", - "\u001b[0;31mAttributeError\u001b[0m: FPGA_mask_RW" + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mAttributeError\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m/tmp/ipykernel_22/2885399456.py\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[1;32m 1\u001B[0m values = [\n\u001B[0;32m----> 2\u001B[0;31m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_mask_RW\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_mask_RW\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 3\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_scrap_R\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_scrap_R\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 4\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_scrap_RW\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_scrap_RW\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 5\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mFPGA_status_R\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"FPGA_status_R\"\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__DeviceProxy__getattr\u001B[0;34m(self, name)\u001B[0m\n\u001B[1;32m 353\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mread_pipe\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 354\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 355\u001B[0;31m \u001B[0msix\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mraise_from\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mAttributeError\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mcause\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 356\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 357\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/six.py\u001B[0m in \u001B[0;36mraise_from\u001B[0;34m(value, from_value)\u001B[0m\n", + "\u001B[0;31mAttributeError\u001B[0m: FPGA_mask_RW" ] } ], @@ -476,4 +476,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/WG_test.ipynb b/jupyter-notebooks/WG_test.ipynb index fece6f9439e16869c958d6b68b77cf87c1cdad7c..5c68571046f886bded570ad37edec14e0a1a1fb0 100644 --- a/jupyter-notebooks/WG_test.ipynb +++ b/jupyter-notebooks/WG_test.ipynb @@ -18,8 +18,8 @@ } ], "source": [ - "#d=DeviceProxy(\"LTS/SST/1\")\n", - "#s=DeviceProxy(\"LTS/SDP/1\")\n", + "#d=DeviceProxy(\"STAT/SST/1\")\n", + "#s=DeviceProxy(\"STAT/SDP/1\")\n", "#d.off(),d.initialise(), d.on()\n", "s.initialise(), s.on()\n", "(d.state(), s.state())" @@ -111,12 +111,12 @@ "evalue": "set_defaults", "output_type": "error", "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_21/1160776047.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0md\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_defaults\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001b[0m in \u001b[0;36m__DeviceProxy__getattr\u001b[0;34m(self, name)\u001b[0m\n\u001b[1;32m 353\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_pipe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 354\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 355\u001b[0;31m \u001b[0msix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_from\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 356\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 357\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/six.py\u001b[0m in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n", - "\u001b[0;31mAttributeError\u001b[0m: set_defaults" + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mAttributeError\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m/tmp/ipykernel_21/1160776047.py\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[0;32m----> 1\u001B[0;31m \u001B[0md\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mset_defaults\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/tango/device_proxy.py\u001B[0m in \u001B[0;36m__DeviceProxy__getattr\u001B[0;34m(self, name)\u001B[0m\n\u001B[1;32m 353\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mread_pipe\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 354\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 355\u001B[0;31m \u001B[0msix\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mraise_from\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mAttributeError\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mname\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mcause\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 356\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 357\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m/usr/local/lib/python3.7/dist-packages/six.py\u001B[0m in \u001B[0;36mraise_from\u001B[0;34m(value, from_value)\u001B[0m\n", + "\u001B[0;31mAttributeError\u001B[0m: set_defaults" ] } ], @@ -1620,4 +1620,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/archiving_demo.ipynb b/jupyter-notebooks/archiving_demo.ipynb index 6ae2c3bc281d9e1269b9d0a5cab606bc11ef0553..7c63a8b215910525ae730d4a0521605eb57347c2 100644 --- a/jupyter-notebooks/archiving_demo.ipynb +++ b/jupyter-notebooks/archiving_demo.ipynb @@ -33,7 +33,7 @@ } ], "source": [ - "dev_rand = DeviceProxy(\"LTS/Random_Data/1\")\n", + "dev_rand = DeviceProxy(\"STAT/Random_Data/1\")\n", "dev_rand.get_attribute_list()" ] }, @@ -44,7 +44,7 @@ "metadata": {}, "outputs": [], "source": [ - "attr_fullname = 'lts/random_data/1/rnd4'\n", + "attr_fullname = 'stat/random_data/1/rnd4'\n", "archiver = Archiver()" ] }, @@ -155,7 +155,7 @@ "metadata": {}, "outputs": [], "source": [ - "attr_fullname = 'lts/random_data/1/rnd21'\n", + "attr_fullname = 'stat/random_data/1/rnd21'\n", "archiver.add_attribute_to_archiver(attr_fullname,polling_period=1000,event_period=1000)" ] }, @@ -1243,7 +1243,7 @@ "metadata": {}, "outputs": [], "source": [ - "d=DeviceProxy(\"LTS/RECV/1\")" + "d=DeviceProxy(\"STAT/RECV/1\")" ] }, { @@ -1328,7 +1328,7 @@ "metadata": {}, "outputs": [], "source": [ - "main_att = 'lts/recv/1/RCU_temperature_R'\n", + "main_att = 'stat/recv/1/RCU_temperature_R'\n", "archiver.add_attribute_to_archiver(main_att,polling_period=1000,event_period=1000)" ] }, @@ -1981,4 +1981,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/ini_device.ipynb b/jupyter-notebooks/ini_device.ipynb index ba365f263ca35e627b0430f26a02d53af059333a..a5b5e950e9cdf5dbffa58624523df2a7cca6b17f 100644 --- a/jupyter-notebooks/ini_device.ipynb +++ b/jupyter-notebooks/ini_device.ipynb @@ -18,7 +18,7 @@ "metadata": {}, "outputs": [], "source": [ - "d=DeviceProxy(\"LTS/ini_device/1\")" + "d=DeviceProxy(\"STAT/ini_device/1\")" ] }, { @@ -235,4 +235,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/jupyter-notebooks/test_device.ipynb b/jupyter-notebooks/test_device.ipynb index 7701f520937bcaf88b09f624c8b9e3a4ee752c85..3a718f2cc744d99d9cc7c96e295aaf30b3a371ca 100644 --- a/jupyter-notebooks/test_device.ipynb +++ b/jupyter-notebooks/test_device.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 61, + "execution_count": 15, "id": "waiting-chance", "metadata": {}, "outputs": [], @@ -13,17 +13,17 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 16, "id": "moving-alexandria", "metadata": {}, "outputs": [], "source": [ - "d=DeviceProxy(\"LTS/SST/1\")" + "d=DeviceProxy(\"STAT/SST/1\")" ] }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 17, "id": "ranking-aluminum", "metadata": {}, "outputs": [ @@ -46,12 +46,14 @@ " d.on()\n", "state = str(d.state())\n", "if state == \"ON\":\n", - " print(\"Device is now in on state\")\n" + " print(\"Device is now in on state\")\n", + "else:\n", + " print(f\"Device is now in {state} state\")" ] }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 18, "id": "beneficial-evidence", "metadata": {}, "outputs": [ @@ -59,64 +61,107 @@ "name": "stdout", "output_type": "stream", "text": [ - "packet_count_R [55]\n", - "last_packet_timestamp_R [1623249385]\n", - "queue_percentage_used_R [0.]\n", - "State <function __get_command_func.<locals>.f at 0x7fcb205fd0d0>\n", - "Status <function __get_command_func.<locals>.f at 0x7fcb205fd0d0>\n" + "['version_R', 'opcua_missing_attributes_R', 'UNB2TR_translator_busy_R', 'UNB2_DC_DC_48V_12V_IOUT_R', 'UNB2_DC_DC_48V_12V_TEMP_R', 'UNB2_DC_DC_48V_12V_VIN_R', 'UNB2_DC_DC_48V_12V_VOUT_R', 'UNB2_EEPROM_Serial_Number_R', 'UNB2_EEPROM_Unique_ID_R', 'UNB2_FPGA_DDR4_SLOT_TEMP_R', 'UNB2_FPGA_POL_CORE_IOUT_R', 'UNB2_FPGA_POL_CORE_TEMP_R', 'UNB2_FPGA_POL_CORE_VOUT_R', 'UNB2_FPGA_POL_ERAM_IOUT_R', 'UNB2_FPGA_POL_ERAM_TEMP_R', 'UNB2_FPGA_POL_ERAM_VOUT_R', 'UNB2_FPGA_POL_HGXB_IOUT_R', 'UNB2_FPGA_POL_HGXB_TEMP_R', 'UNB2_FPGA_POL_HGXB_VOUT_R', 'UNB2_FPGA_POL_PGM_IOUT_R', 'UNB2_FPGA_POL_PGM_TEMP_R', 'UNB2_FPGA_POL_PGM_VOUT_R', 'UNB2_FPGA_POL_RXGXB_IOUT_R', 'UNB2_FPGA_POL_RXGXB_TEMP_R', 'UNB2_FPGA_POL_RXGXB_VOUT_R', 'UNB2_FPGA_POL_TXGXB_IOUT_R', 'UNB2_FPGA_POL_TXGXB_TEMP_R', 'UNB2_FPGA_POL_TXGXB_VOUT_R', 'UNB2_FPGA_QSFP_CAGE_LOS_R', 'UNB2_FPGA_QSFP_CAGE_TEMP_R', 'UNB2_Front_Panel_LED_R', 'UNB2_Front_Panel_LED_RW', 'UNB2_I2C_bus_DDR4_error_R', 'UNB2_I2C_bus_error_R', 'UNB2_I2C_bus_FPGA_PS_error_R', 'UNB2_I2C_bus_PS_error_R', 'UNB2_I2C_bus_QSFP_error_R', 'UNB2_mask_RW', 'UNB2_POL_CLOCK_IOUT_R', 'UNB2_POL_CLOCK_TEMP_R', 'UNB2_POL_CLOCK_VOUT_R', 'UNB2_POL_QSFP_N01_IOUT_R', 'UNB2_POL_QSFP_N01_TEMP_R', 'UNB2_POL_QSFP_N01_VOUT_R', 'UNB2_POL_QSFP_N23_IOUT_R', 'UNB2_POL_QSFP_N23_TEMP_R', 'UNB2_POL_QSFP_N23_VOUT_R', 'UNB2_POL_SWITCH_1V2_IOUT_R', 'UNB2_POL_SWITCH_1V2_TEMP_R', 'UNB2_POL_SWITCH_1V2_VOUT_R', 'UNB2_POL_SWITCH_PHY_IOUT_R', 'UNB2_POL_SWITCH_PHY_TEMP_R', 'UNB2_POL_SWITCH_PHY_VOUT_R', 'UNB2_PWR_off_R', 'UNB2_PWR_off_RW', 'State', 'Status']\n", + "\r\n", + "Attributes:\n", + ">>>\t version_R\n", + ">>>\t opcua_missing_attributes_R\n", + ">>>\t UNB2TR_translator_busy_R\n", + ">>>\t UNB2_DC_DC_48V_12V_IOUT_R\n", + ">>>\t UNB2_DC_DC_48V_12V_TEMP_R\n", + ">>>\t UNB2_DC_DC_48V_12V_VIN_R\n", + ">>>\t UNB2_DC_DC_48V_12V_VOUT_R\n", + ">>>\t UNB2_EEPROM_Serial_Number_R\n", + ">>>\t UNB2_EEPROM_Unique_ID_R\n", + ">>>\t UNB2_FPGA_DDR4_SLOT_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_CORE_IOUT_R\n", + ">>>\t UNB2_FPGA_POL_CORE_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_CORE_VOUT_R\n", + ">>>\t UNB2_FPGA_POL_ERAM_IOUT_R\n", + ">>>\t UNB2_FPGA_POL_ERAM_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_ERAM_VOUT_R\n", + ">>>\t UNB2_FPGA_POL_HGXB_IOUT_R\n", + ">>>\t UNB2_FPGA_POL_HGXB_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_HGXB_VOUT_R\n", + ">>>\t UNB2_FPGA_POL_PGM_IOUT_R\n", + ">>>\t UNB2_FPGA_POL_PGM_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_PGM_VOUT_R\n", + ">>>\t UNB2_FPGA_POL_RXGXB_IOUT_R\n", + ">>>\t UNB2_FPGA_POL_RXGXB_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_RXGXB_VOUT_R\n", + ">>>\t UNB2_FPGA_POL_TXGXB_IOUT_R\n", + ">>>\t UNB2_FPGA_POL_TXGXB_TEMP_R\n", + ">>>\t UNB2_FPGA_POL_TXGXB_VOUT_R\n", + ">>>\t UNB2_FPGA_QSFP_CAGE_LOS_R\n", + ">>>\t UNB2_FPGA_QSFP_CAGE_TEMP_R\n", + ">>>\t UNB2_Front_Panel_LED_R\n", + ">>>\t UNB2_Front_Panel_LED_RW\n", + ">>>\t UNB2_I2C_bus_DDR4_error_R\n", + ">>>\t UNB2_I2C_bus_error_R\n", + ">>>\t UNB2_I2C_bus_FPGA_PS_error_R\n", + ">>>\t UNB2_I2C_bus_PS_error_R\n", + ">>>\t UNB2_I2C_bus_QSFP_error_R\n", + ">>>\t UNB2_mask_RW\n", + ">>>\t UNB2_POL_CLOCK_IOUT_R\n", + ">>>\t UNB2_POL_CLOCK_TEMP_R\n", + ">>>\t UNB2_POL_CLOCK_VOUT_R\n", + ">>>\t UNB2_POL_QSFP_N01_IOUT_R\n", + ">>>\t UNB2_POL_QSFP_N01_TEMP_R\n", + ">>>\t UNB2_POL_QSFP_N01_VOUT_R\n", + ">>>\t UNB2_POL_QSFP_N23_IOUT_R\n", + ">>>\t UNB2_POL_QSFP_N23_TEMP_R\n", + ">>>\t UNB2_POL_QSFP_N23_VOUT_R\n", + ">>>\t UNB2_POL_SWITCH_1V2_IOUT_R\n", + ">>>\t UNB2_POL_SWITCH_1V2_TEMP_R\n", + ">>>\t UNB2_POL_SWITCH_1V2_VOUT_R\n", + ">>>\t UNB2_POL_SWITCH_PHY_IOUT_R\n", + ">>>\t UNB2_POL_SWITCH_PHY_TEMP_R\n", + ">>>\t UNB2_POL_SWITCH_PHY_VOUT_R\n", + ">>>\t UNB2_PWR_off_R\n", + ">>>\t UNB2_PWR_off_RW\n", + ">>>\t State\n", + ">>>\t Status\n", + "Missing Attributes: \n", + " ('2:UNB2TR_translator_busy_R', '2:UNB2_EEPROM_Serial_Number_R', '2:UNB2_I2C_bus_DDR4_error_R', '2:UNB2_I2C_bus_error_R', '2:UNB2_I2C_bus_FPGA_PS_error_R', '2:UNB2_I2C_bus_PS_error_R', '2:UNB2_I2C_bus_QSFP_error_R', '2:UNB2_PWR_off_R', '2:UNB2_PWR_off_RW')\n" ] } ], "source": [ "attr_names = d.get_attribute_list()\n", + "print(attr_names)\n", "\n", + "print(\"\\r\\nAttributes:\")\n", "for i in attr_names:\n", - " exec(\"value = print(i, d.{})\".format(i))\n" + " print(\">>>\\t\",i)\n", + " #exec(\"value = print(i, d.{})\".format(i))\n", + "print(\"Missing Attributes: \\n\", d.opcua_missing_attributes_R)" ] }, { "cell_type": "code", - "execution_count": 39, - "id": "sporting-current", + "execution_count": 20, + "id": "252e49de", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "3.0" + "array([0., 0.])" ] }, - "execution_count": 39, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "d.RCU_mask_RW = [False, False, False, False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False,]\n", - "time.sleep(1)\n", - "print(d.RCU_mask_RW)\n", - "\n", - "monitor_rate = d.RCU_monitor_rate_RW\n", - "print(\"current monitoring rate: {}, setting to {}\".format(monitor_rate, monitor_rate + 1))\n", - "monitor_rate = monitor_rate + 1\n", - "\n", - "time.sleep(1)\n" + "d.UNB2_POL_QSFP_N23_TEMP_R" ] }, { "cell_type": "code", "execution_count": null, - "id": "sharing-mechanics", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ruled-tracy", + "id": "d348a3c6", "metadata": {}, "outputs": [], "source": [] @@ -143,4 +188,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/sbin/load_ConfigDb.sh b/sbin/load_ConfigDb.sh index 03ab449a026b5de41056f16de0d2e566a00adfbb..0fe57087a89dc08ebef51d4679a687ebbf6a144a 100755 --- a/sbin/load_ConfigDb.sh +++ b/sbin/load_ConfigDb.sh @@ -9,10 +9,10 @@ fi # copy file into container to read it from container, as the file's location # in the container won't be the same as on the host. -docker cp "${file}" dsconfig:/tmp/dsconfig-load-settings.json || exit 1 +docker cp "${file}" "${CONTAINER_NAME_PREFIX}"dsconfig:/tmp/dsconfig-update-settings.json || exit 1 -# write settings -docker exec -it dsconfig json2tango --write /tmp/dsconfig-load-settings.json +# update settings, Do not change -i into -it this will break integration tests in gitlab ci! +docker exec -i "${CONTAINER_NAME_PREFIX}"dsconfig json2tango --write /tmp/dsconfig-update-settings.json # somehow json2tango does not return 0 on success exit 0 diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh index 2175f2774e771ac31e9dcd1cb1ade68da51f923e..4e988f7fce03eaf4142193c8156ddbcf60ace0bf 100755 --- a/sbin/run_integration_test.sh +++ b/sbin/run_integration_test.sh @@ -9,16 +9,22 @@ if [ -z "$LOFAR20_DIR" ]; then LOFAR20_DIR=$(readlink -f "${LOFAR20_DIR_RELATIVE}") fi -# Start and stop sequence cd "$LOFAR20_DIR/docker-compose" || exit 1 + +# Make sure builds are recent, and use our building parameters. +make build + +# Start and stop sequence make stop device-sdp device-recv device-sst device-unb2 device-xst sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim -make start databaseds dsconfig jupyter elk +make start databaseds dsconfig elk # Give dsconfig and databaseds time to start -sleep 15 +sleep 60 # Update the dsconfig -"${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/integration_ConfigDb.json +# Do not remove `bash`, otherwise statement ignored by gitlab ci shell! +bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/LOFAR_ConfigDb.json +bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/stations/simulators_ConfigDb.json cd "$LOFAR20_DIR/docker-compose" || exit 1 make start sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim @@ -28,12 +34,16 @@ sleep 5 make start device-sdp device-recv device-sst device-unb2 device-xst -# Give the devices time to start -sleep 5 +# Give devices time to restart +# TODO(Corne Lukken): Use a nicer more reliable mechanism +sleep 60 # Start the integration test cd "$LOFAR20_DIR/docker-compose" || exit 1 make start integration-test +# Give devices time to restart +sleep 60 + # Run the integration test with the output displayed on stdout -docker start -a integration-test +docker start -a "${CONTAINER_NAME_PREFIX}"integration-test diff --git a/sbin/update_ConfigDb.sh b/sbin/update_ConfigDb.sh index 8d71c312fc94ba4dba45b17c05a966f62fa9ff34..1255f1ea141a75940f2cd858dfc2b40818bd6ec2 100755 --- a/sbin/update_ConfigDb.sh +++ b/sbin/update_ConfigDb.sh @@ -9,10 +9,10 @@ fi # copy file into container to read it from container, as the file's location # in the container won't be the same as on the host. -docker cp "${file}" dsconfig:/tmp/dsconfig-update-settings.json || exit 1 +docker cp "${file}" "${CONTAINER_NAME_PREFIX}"dsconfig:/tmp/dsconfig-update-settings.json || exit 1 -# update settings -docker exec -it dsconfig json2tango --write --update /tmp/dsconfig-update-settings.json +# update settings, Do not change -i into -it this will break integration tests in gitlab ci! +docker exec -i "${CONTAINER_NAME_PREFIX}"dsconfig json2tango --write --update /tmp/dsconfig-update-settings.json # somehow json2tango does not return 0 on success exit 0 diff --git a/tangostationcontrol/.stestr.conf b/tangostationcontrol/.stestr.conf new file mode 100644 index 0000000000000000000000000000000000000000..59b161cddad8a253059cf201b8872bc946f78c64 --- /dev/null +++ b/tangostationcontrol/.stestr.conf @@ -0,0 +1,3 @@ +[DEFAULT] +test_path=${TESTS_DIR:-./tangostationcontrol/test} +top_dir=./ diff --git a/devices/README.md b/tangostationcontrol/README.md similarity index 91% rename from devices/README.md rename to tangostationcontrol/README.md index 0604c3a4d1d90b7d99ab1f35cee1922c6ee99371..0fef1b58aa82065b03353315cdd63ded8e2a3cd2 100644 --- a/devices/README.md +++ b/tangostationcontrol/README.md @@ -3,7 +3,7 @@ This code provides an attribute_wrapper class in place of attributes for tango devices. the attribute wrappers contain additional code that moves a lot of the complexity and redundant code to the background. -The tango Device class is also abstracted further to a "hardware_device" class. This class wraps +The tango Device class is also abstracted further to a "lofar_device" class. This class wraps The only things required on the users part are to declare the attributes using the attribute_wrapper (see `example/example_device`), declare what client the attribute has to use in the initialisation and provide support for the used clients. diff --git a/tangostationcontrol/requirements.txt b/tangostationcontrol/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..b1620255b5a45c9e3f653661e65de6732fd93a07 --- /dev/null +++ b/tangostationcontrol/requirements.txt @@ -0,0 +1,13 @@ +# the order of packages is of significance, because pip processes them in the +# order of appearance. Changing the order has an impact on the overall +# integration process, which may cause wedges in the gate later. + +asyncua >= 0.9.90 # LGPLv3 +PyMySQL[rsa] >= 1.0.2 # MIT +sqlalchemy >= 1.4.26 #MIT +GitPython >= 3.1.24 # BSD +snmp >= 0.1.7 # GPL3 +h5py >= 3.5.0 # BSD +psutil >= 5.8.0 # BSD +docker >= 5.0.3 # Apache 2 +python-logstash-async >= 2.3.0 # MIT \ No newline at end of file diff --git a/tangostationcontrol/setup.cfg b/tangostationcontrol/setup.cfg new file mode 100644 index 0000000000000000000000000000000000000000..e6101c890893c961e1eff27ce3d3ab4e019ea312 --- /dev/null +++ b/tangostationcontrol/setup.cfg @@ -0,0 +1,58 @@ +[metadata] +name = tangostationcontrol +version = attr: tangostationcontrol.__version__ +summary = LOFAR 2.0 Station Control +description_file = + README.md +description_content_type = text/x-rst; charset=UTF-8 +author = ASTRON +home_page = https://astron.nl +project_urls = + Bug Tracker = https://support.astron.nl/jira/projects/L2SS/issues/ + Source Code = https://git.astron.nl/lofar2.0/tango +license = Apache-2 +classifier = + Environment :: Console + License :: Apache Software License + Operating System :: POSIX :: Linux + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + +[options] +package_dir= + =./ +packages=find: +python_requires = >=3.6 + +[options.packages.find] +where=./ + +[options.entry_points] +console_scripts = + l2ss-apsct = tangostationcontrol.devices.apsct:main + l2ss-apspu = tangostationcontrol.devices.apspu:main + l2ss-boot = tangostationcontrol.devices.boot:main + l2ss-docker-device = tangostationcontrol.devices.docker_device:main + l2ss-observation = tangostationcontrol.devices.observation:main + l2ss-observation-control = tangostationcontrol.devices.observation_control:main + l2ss-receiver = tangostationcontrol.devices.recv:main + l2ss-sdp = tangostationcontrol.devices.sdp.sdp:main + l2ss-sst = tangostationcontrol.devices.sdp.sst:main + l2ss-statistics-reader = tangostationcontrol.statistics_writer.statistics_reader:main + l2ss-statistics-writer = tangostationcontrol.statistics_writer.statistics_writer:main + l2ss-unb2 = tangostationcontrol.devices.unb2:main + l2ss-xst = tangostationcontrol.devices.sdp.xst:main + +# The following entry points should eventually be removed / replaced + l2ss-cold-start = tangostationcontrol.toolkit.lts_cold_start:main + l2ss-hardware-device-template = tangostationcontrol.examples.HW_device_template:main + l2ss-ini-device = tangostationcontrol.examples.load_from_disk.ini_device:main + l2ss-parse-statistics-packet = tangostationcontrol.devices.sdp.statistics_packet:main + l2ss-random-data = tangostationcontrol.test.devices.random_data:main + l2ss-snmp = tangostationcontrol.examples.snmp.snmp:main + l2ss-version = tangostationcontrol.common.lofar_version:main diff --git a/tangostationcontrol/setup.py b/tangostationcontrol/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..6356812fdc2951fff6af9659feca273df06efca3 --- /dev/null +++ b/tangostationcontrol/setup.py @@ -0,0 +1,7 @@ +import setuptools + +with open('requirements.txt') as f: + required = f.read().splitlines() + +# Requires: setup.cfg +setuptools.setup(install_requires=required) diff --git a/tangostationcontrol/tangostationcontrol/__init__.py b/tangostationcontrol/tangostationcontrol/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c6e48f3e8c0b11146b60c5fb7b8b2285fd7124d0 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/__init__.py @@ -0,0 +1,3 @@ +from tangostationcontrol.common.lofar_version import get_version + +__version__ = get_version() diff --git a/devices/clients/README.md b/tangostationcontrol/tangostationcontrol/clients/README.md similarity index 100% rename from devices/clients/README.md rename to tangostationcontrol/tangostationcontrol/clients/README.md diff --git a/devices/devices/__init__.py b/tangostationcontrol/tangostationcontrol/clients/__init__.py similarity index 100% rename from devices/devices/__init__.py rename to tangostationcontrol/tangostationcontrol/clients/__init__.py diff --git a/devices/clients/attribute_wrapper.py b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py similarity index 94% rename from devices/clients/attribute_wrapper.py rename to tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py index e55a662142cb89f62775fb7ac2189c063593df37..718ea431d6d24962ad7f437e3941e7609f89927f 100644 --- a/devices/clients/attribute_wrapper.py +++ b/tangostationcontrol/tangostationcontrol/clients/attribute_wrapper.py @@ -2,7 +2,7 @@ from tango.server import attribute from tango import AttrWriteType import numpy -from devices.device_decorators import only_when_on, fault_on_error +from tangostationcontrol.devices.device_decorators import only_when_on, fault_on_error import logging logger = logging.getLogger() @@ -154,7 +154,7 @@ class attribute_wrapper(attribute): try: self.read_function, self.write_function = client.setup_attribute(self.comms_annotation, self) except Exception as e: - raise Exception("Exception while setting %s attribute with annotation: '%s'", client.__class__.__name__, self.comms_annotation) from e + raise Exception(f"Exception while setting {client.__class__.__name__} attribute with annotation: '{self.comms_annotation}'") from e async def async_set_comm_client(self, client): """ @@ -163,7 +163,8 @@ class attribute_wrapper(attribute): try: self.read_function, self.write_function = await client.setup_attribute(self.comms_annotation, self) except Exception as e: - raise Exception("Exception while setting %s attribute with annotation: '%s'", client.__class__.__name__, self.comms_annotation) from e + raise Exception(f"Exception while setting {client.__class__.__name__} attribute with annotation: '{self.comms_annotation}'") from e + def set_pass_func(self): def pass_func(value=None): diff --git a/devices/clients/comms_client.py b/tangostationcontrol/tangostationcontrol/clients/comms_client.py similarity index 96% rename from devices/clients/comms_client.py rename to tangostationcontrol/tangostationcontrol/clients/comms_client.py index 31dfc99ce4092d8f1025bfe3b10fc8a9c561ebe8..2c28d2c70214935d32ffdcb21386ba841e7e5668 100644 --- a/devices/clients/comms_client.py +++ b/tangostationcontrol/tangostationcontrol/clients/comms_client.py @@ -48,13 +48,12 @@ class CommClient(AbstractCommClient, Thread): primitives. """ - def __init__(self, fault_func, streams, try_interval=2): + def __init__(self, fault_func, try_interval=2): """ """ self.fault_func = fault_func self.try_interval = try_interval - self.streams = streams self.stopping = False self.connected = False @@ -83,7 +82,7 @@ class CommClient(AbstractCommClient, Thread): try: self.connect() except Exception as e: - self.streams.error_stream("Fault condition in communication detected.", e) + logger.exception("Fault condition in communication detected.") self.fault_func() return @@ -93,7 +92,7 @@ class CommClient(AbstractCommClient, Thread): self.ping() time.sleep(self.try_interval) except Exception as e: - self.streams.error_stream("Fault condition in communication detected.", e) + logger.exception("Fault condition in communication detected.") # technically, we may not have dropped the connection, but encounter a different error. so explicitly disconnect. self.disconnect() @@ -266,3 +265,4 @@ class AsyncCommClient(object): future = asyncio.run_coroutine_threadsafe(self.stop(), self.event_loop) return future.result() + diff --git a/devices/clients/docker_client.py b/tangostationcontrol/tangostationcontrol/clients/docker_client.py similarity index 100% rename from devices/clients/docker_client.py rename to tangostationcontrol/tangostationcontrol/clients/docker_client.py diff --git a/devices/clients/opcua_client.py b/tangostationcontrol/tangostationcontrol/clients/opcua_client.py similarity index 82% rename from devices/clients/opcua_client.py rename to tangostationcontrol/tangostationcontrol/clients/opcua_client.py index bf68edd19318648f1c8313f349a63671000382c7..ce4447de3b9c8339bd36cc1e75a04ec6867b04de 100644 --- a/devices/clients/opcua_client.py +++ b/tangostationcontrol/tangostationcontrol/clients/opcua_client.py @@ -1,11 +1,10 @@ -from threading import Thread import socket import numpy import asyncua import asyncio from asyncua import Client -from clients.comms_client import AsyncCommClient +from tangostationcontrol.clients.comms_client import AsyncCommClient import logging logger = logging.getLogger() @@ -28,6 +27,20 @@ numpy_to_OPCua_dict = { numpy.str: asyncua.ua.VariantType.String } +def numpy_to_opcua(numpy_val): + """ Convert a numpy type to a corresponding opcua Variant type. """ + + numpy_type = type(numpy_val) + + assert numpy_type not in [list, numpy.array], "Converting arrays not yet supported." + + try: + ua_type = numpy_to_OPCua_dict[numpy_type] + except KeyError as e: + raise TypeError(f"Could not convert {numpy_val} (type {type(numpy_val).__name__}) to an OPC UA type.") from e + + return asyncua.ua.uatypes.Variant(Value=numpy_val, VariantType=ua_type) + class OPCUAConnection(AsyncCommClient): """ Connects to OPC-UA in the foreground or background, and sends HELLO @@ -86,7 +99,9 @@ class OPCUAConnection(AsyncCommClient): ping the client to make sure the connection with the client is still functional. """ try: - await self.client.send_hello() + # do a cheap call. NOTE: send_hello is not allowed after establishing a connection, + # so cannot be used here. see https://reference.opcfoundation.org/v104/Core/docs/Part6/7.1.3/ + _ = await self.client.get_namespace_array() except Exception as e: raise IOError("Lost connection to server %s: %s", self._servername(), e) @@ -116,7 +131,7 @@ class OPCUAConnection(AsyncCommClient): return path - async def setup_attribute(self, annotation, attribute): + async def setup_protocol_attribute(self, annotation, attribute): # process the annotation path = self.get_node_path(annotation) @@ -137,10 +152,15 @@ class OPCUAConnection(AsyncCommClient): try: # NOTE: debug statement tries to get the qualified name, this may not always work. in that case forgo the name and just print the path node_name = str(node.get_browse_name())[len("QualifiedName(2:"):] - self.streams.debug_stream("connected OPC ua node {} of type {} to attribute with dimensions: {} x {} ".format(str(node_name)[:len(node_name)-1], str(ua_type)[len("VariantType."):], dim_x, dim_y)) + logger.debug("connected OPC ua node {} of type {} to attribute with dimensions: {} x {} ".format(str(node_name)[:len(node_name)-1], str(ua_type)[len("VariantType."):], dim_x, dim_y)) except: pass + return prot_attr + + async def setup_attribute(self, annotation, attribute): + prot_attr = await self.setup_protocol_attribute(annotation, attribute) + # Tango will call these from a separate polling thread. def read_function(): return asyncio.run_coroutine_threadsafe(prot_attr.read_function(), self.event_loop).result() @@ -152,15 +172,24 @@ class OPCUAConnection(AsyncCommClient): return read_function, write_function - async def call_method(self, method_path, *args): - node = await self.obj.get_child(method_path[:-1]) - return await node.call_method(method_path[-1], *args) + async def _call_method(self, method_path, *args): + method_path = self.get_node_path(method_path) + # convert the arguments to OPC UA types + args = [numpy_to_opcua(arg) for arg in args] - def call_method(self, method_path, *args): - method_path = self.get_node_path(method_path) + try: + # call method in its parent node + node = await self.obj.get_child(method_path[:-1]) if len(method_path) > 1 else self.obj + result = await node.call_method(method_path[-1], *args) + except Exception as e: + raise Exception(f"Calling method {method_path} failed") from e + + return result - raise NotImplementedError + + def call_method(self, method_path, *args): + return asyncio.run_coroutine_threadsafe(self._call_method(method_path, *args), self.event_loop).result() class ProtocolAttribute: diff --git a/devices/clients/statistics_client.py b/tangostationcontrol/tangostationcontrol/clients/statistics_client.py similarity index 98% rename from devices/clients/statistics_client.py rename to tangostationcontrol/tangostationcontrol/clients/statistics_client.py index 3fd470fbf0319e45242abbc3a79362584628f844..2790197bdb90f2483d872f0dfd5978fa088d4980 100644 --- a/devices/clients/statistics_client.py +++ b/tangostationcontrol/tangostationcontrol/clients/statistics_client.py @@ -6,7 +6,7 @@ from .comms_client import AsyncCommClient from .tcp_replicator import TCPReplicator from .udp_receiver import UDPReceiver -from devices.sdp.statistics_collector import StatisticsConsumer +from tangostationcontrol.devices.sdp.statistics_collector import StatisticsConsumer logger = logging.getLogger() diff --git a/devices/clients/statistics_client_thread.py b/tangostationcontrol/tangostationcontrol/clients/statistics_client_thread.py similarity index 100% rename from devices/clients/statistics_client_thread.py rename to tangostationcontrol/tangostationcontrol/clients/statistics_client_thread.py diff --git a/devices/clients/tcp_replicator.py b/tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py similarity index 99% rename from devices/clients/tcp_replicator.py rename to tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py index 5ac6e492d977cf14452d4f97bd213c0d12af7cbb..8b820cc765daa193fe142f4a3f49ef7a3f643c76 100644 --- a/devices/clients/tcp_replicator.py +++ b/tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py @@ -6,7 +6,7 @@ from threading import Thread import asyncio import logging -from clients.statistics_client_thread import StatisticsClientThread +from tangostationcontrol.clients.statistics_client_thread import StatisticsClientThread logger = logging.getLogger() diff --git a/devices/clients/udp_receiver.py b/tangostationcontrol/tangostationcontrol/clients/udp_receiver.py similarity index 98% rename from devices/clients/udp_receiver.py rename to tangostationcontrol/tangostationcontrol/clients/udp_receiver.py index 8a9d1429945cdd5c41c47bf45edc5034c1cafa0c..2bda038a1fb0646af2d2e14082e10ca3d7866816 100644 --- a/devices/clients/udp_receiver.py +++ b/tangostationcontrol/tangostationcontrol/clients/udp_receiver.py @@ -7,7 +7,7 @@ import socket import time from typing import List # not needed for python3.9+, where we can use the type "list[Queue]" directly -from clients.statistics_client_thread import StatisticsClientThread +from tangostationcontrol.clients.statistics_client_thread import StatisticsClientThread logger = logging.getLogger() diff --git a/devices/devices/sdp/__init__.py b/tangostationcontrol/tangostationcontrol/common/__init__.py similarity index 100% rename from devices/devices/sdp/__init__.py rename to tangostationcontrol/tangostationcontrol/common/__init__.py diff --git a/devices/common/baselines.py b/tangostationcontrol/tangostationcontrol/common/baselines.py similarity index 100% rename from devices/common/baselines.py rename to tangostationcontrol/tangostationcontrol/common/baselines.py diff --git a/tangostationcontrol/tangostationcontrol/common/entrypoint.py b/tangostationcontrol/tangostationcontrol/common/entrypoint.py new file mode 100644 index 0000000000000000000000000000000000000000..d5b9d4952ee08180162b3bdca7417fff31f456f0 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/common/entrypoint.py @@ -0,0 +1,21 @@ +import sys + +from tango.server import run + +from tangostationcontrol.common.lofar_logging import configure_logger + + +def entry(Device, **kwargs): + """General device entrypoint""" + + # Remove first argument which is filename + args = sys.argv[1:] + + # Setup logging + configure_logger() + + # Start the device server + if type(Device) is tuple: + return run(Device, args=args, **kwargs) + else: + return run((Device,), args=args, **kwargs) diff --git a/devices/common/lofar_logging.py b/tangostationcontrol/tangostationcontrol/common/lofar_logging.py similarity index 98% rename from devices/common/lofar_logging.py rename to tangostationcontrol/tangostationcontrol/common/lofar_logging.py index 826e484e6e2bd321c343b814ccb734472e8bf73c..cfff61966f11a06c2fcf0e336da32eba24bfbfe2 100644 --- a/devices/common/lofar_logging.py +++ b/tangostationcontrol/tangostationcontrol/common/lofar_logging.py @@ -1,12 +1,11 @@ import logging from functools import wraps from tango.server import Device -import sys import traceback import socket import time -from .lofar_git import get_version +from .lofar_version import get_version class TangoLoggingHandler(logging.Handler): level_to_device_stream = { @@ -151,7 +150,7 @@ def configure_logger(logger: logging.Logger=None, log_extra=None, debug=False): from logstash_async.handler import AsynchronousLogstashHandler, LogstashFormatter # log to the tcp_input of logstash in our ELK stack - handler = AsynchronousLogstashHandler("elk", 5959, database_path='pending_log_messages.db') + handler = AsynchronousLogstashHandler("elk", 5959, database_path='/tmp/lofar_pending_log_messages.db') # configure log messages formatter = LogstashFormatter(extra=log_extra, tags=["python", "lofar"]) diff --git a/tangostationcontrol/tangostationcontrol/common/lofar_version.py b/tangostationcontrol/tangostationcontrol/common/lofar_version.py new file mode 100644 index 0000000000000000000000000000000000000000..89cb22f9fe6b76caf438984c673b21d00bc25645 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/common/lofar_version.py @@ -0,0 +1,103 @@ +import git +import os +import functools +import pkg_resources +import re + +def get_repo(starting_directory: str = os.path.dirname(os.path.abspath(__file__)), limit = 10) -> git.Repo: + """ Try finding the repository by traversing up the tree. + + By default, the repository containing this module is returned. + """ + + directory = starting_directory + + try: + return git.Repo(directory) + except git.InvalidGitRepositoryError: + pass + + # We now have to traverse up the tree up until limit diretories + for i in range(limit): + if directory == "/" or not os.path.exists(directory): + break + + directory = os.path.abspath(directory + os.path.sep + "..") + + try: + return git.Repo(directory) + except git.InvalidGitRepositoryError: + pass + + # Could not find a repo within the limit so return None + return None + + +@functools.lru_cache(maxsize=None) +def get_version(repo: git.Repo = None) -> str: + """ Return a version string for the current commit. + + There is a practical issue: the repository changes over time, f.e. switching branches with 'git checkout'. We want + to know the version that is running in memory, not the one that is on disk. + + As a work-around, we cache the version information, in that it is at least consistent. It is up to the caller + to request the version early enough. + + The version string is of the following pattern: + - ${MAJOR}.${MINOR}.${PATCH}[.${BRANCH}$.{COMMIT}][.dirty] + + For releases only ${MAJOR}.${MINOR}.${PATCH} should be set. Versioning is + achieved by tagging commits using the `v${MAJOR}.${MINOR}.${PATCH}` pattern. + The leading `v` is none optional! + + """ + + if repo is None: + repo = get_repo() + + # When we can't find a git repo anymore, we must be packaged. Extract the + # package version directly + if repo is None: + try: + return pkg_resources.require("tangostationcontrol")[0].version + except Exception: + pass + + # Filter all tags so that they must match vMAJOR.MINOR.PATCH or + # vMAJOR.MINOR.PATCH.BRANCHCOMMIT + reg = re.compile(r'^v[0-9](\.[0-9]){2}(\.[a-z]*[0-9]*)?') + + commit = repo.commit() + filtered_tags = [tag.name for tag in repo.tags if reg.search(tag.name)] + # Order tags from newest to oldest + tags = {tag.commit: tag for tag in reversed(repo.tags) if tag.name in filtered_tags} + + # Find closest tag for commit + closest_tag = type('',(object,),{"name": 'v0.0.0'})() + for item in commit.iter_items(repo, commit): + if item.type == 'commit' and item in tags: + closest_tag = tags[item] + break + + if commit in tags: + # a tag = production ready + commit_str = "{}".format(tags[commit].name[1:]) + elif repo.head.is_detached: + # no active branch + commit_str = "{}.{}".format(closest_tag.name[1:], commit) + else: + # HEAD of a branch + branch = repo.active_branch + commit_str = "{}.{}.{}".format(closest_tag.name[1:], branch, commit) + + return "{}{}".format(commit_str, ".dirty" if repo.is_dirty() else "") + +# at least cache the current repo version immediately +try: + _ = get_version() +except: + pass + + +def main(args=None, **kwargs): + print(get_version()) diff --git a/devices/examples/__init__.py b/tangostationcontrol/tangostationcontrol/devices/__init__.py similarity index 100% rename from devices/examples/__init__.py rename to tangostationcontrol/tangostationcontrol/devices/__init__.py diff --git a/devices/devices/abstract_device.py b/tangostationcontrol/tangostationcontrol/devices/abstract_device.py similarity index 86% rename from devices/devices/abstract_device.py rename to tangostationcontrol/tangostationcontrol/devices/abstract_device.py index 5b65c3a6c02fd487920e02efed2394de275f1a9d..8250e4e481dc9d27ec88654b6fef777d0e9bc4e4 100644 --- a/devices/devices/abstract_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/abstract_device.py @@ -20,7 +20,7 @@ logger = logging.getLogger() class AbstractDeviceMetas(DeviceMeta, ABCMeta): - """Collects meta classes to allow hardware_device to be both a Device and an ABC. """ + """Collects meta classes to allow lofar_device to be both a Device and an ABC. """ def __new__(mcs, name, bases, namespace, **kwargs): cls = ABCMeta.__new__(mcs, name, bases, namespace, **kwargs) diff --git a/devices/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py similarity index 72% rename from devices/devices/apsct.py rename to tangostationcontrol/tangostationcontrol/devices/apsct.py index c8b0cb0ad8843fc44fd6c3e298d3a6cfd15d6f5f..add4e146cdb5fb4282a49f9394c552465b088a26 100644 --- a/devices/devices/apsct.py +++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py @@ -11,31 +11,25 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports from tango import DebugIt from tango.server import run, command -from tango.server import device_property, attribute -from tango import AttrWriteType +from tango import AttrWriteType, DevState import numpy # Additional import -from device_decorators import * - -from clients.attribute_wrapper import attribute_wrapper -from devices.opcua_device import opcua_device -from common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.devices.device_decorators import * +from tangostationcontrol.devices.opcua_device import opcua_device import logging logger = logging.getLogger() __all__ = ["APSCT", "main"] + @device_logging_to_python() class APSCT(opcua_device): # ----------------- @@ -46,11 +40,14 @@ class APSCT(opcua_device): # Attributes # ---------- + APSCTTR_I2C_error_R = attribute_wrapper(comms_annotation=["APSCTTR_I2C_error_R" ],datatype=numpy.int64 ) + APSCTTR_monitor_rate_RW = attribute_wrapper(comms_annotation=["APSCTTR_monitor_rate_RW" ],datatype=numpy.int64 , access=AttrWriteType.READ_WRITE) APSCTTR_translator_busy_R = attribute_wrapper(comms_annotation=["APSCTTR_translator_busy_R" ],datatype=numpy.bool_ ) - APSCT_I2C_error_R = attribute_wrapper(comms_annotation=["APSCT_I2C_error_R" ],datatype=numpy.int64 ) - APSCT_ID_R = attribute_wrapper(comms_annotation=["APSCT_ID_R" ],datatype=numpy.int64 ) APSCT_INPUT_10MHz_good_R = attribute_wrapper(comms_annotation=["APSCT_INPUT_10MHz_good_R" ],datatype=numpy.bool_ ) APSCT_INPUT_PPS_good_R = attribute_wrapper(comms_annotation=["APSCT_INPUT_PPS_good_R" ],datatype=numpy.bool_ ) + APSCT_PCB_ID_R = attribute_wrapper(comms_annotation=["APSCT_PCB_ID_R" ],datatype=numpy.int64 ) + APSCT_PCB_number_R = attribute_wrapper(comms_annotation=["APSCT_PCB_number_R" ],datatype=numpy.str ) + APSCT_PCB_version_R = attribute_wrapper(comms_annotation=["APSCT_PCB_version_R" ],datatype=numpy.str ) APSCT_PLL_160MHz_error_R = attribute_wrapper(comms_annotation=["APSCT_PLL_160MHz_error_R" ],datatype=numpy.bool_ ) APSCT_PLL_160MHz_locked_R = attribute_wrapper(comms_annotation=["APSCT_PLL_160MHz_locked_R" ],datatype=numpy.bool_ ) APSCT_PLL_200MHz_error_R = attribute_wrapper(comms_annotation=["APSCT_PLL_200MHz_error_R" ],datatype=numpy.bool_ ) @@ -67,8 +64,7 @@ class APSCT(opcua_device): APSCT_PWR_PLL_200MHz_3V3_R = attribute_wrapper(comms_annotation=["APSCT_PWR_PLL_200MHz_3V3_R"],datatype=numpy.float64) APSCT_PWR_PLL_200MHz_on_R = attribute_wrapper(comms_annotation=["APSCT_PWR_PLL_200MHz_on_R" ],datatype=numpy.bool_ ) APSCT_PWR_PPSDIST_3V3_R = attribute_wrapper(comms_annotation=["APSCT_PWR_PPSDIST_3V3_R" ],datatype=numpy.float64) - APSCT_temperature_R = attribute_wrapper(comms_annotation=["APSCT_temperature_R" ],datatype=numpy.float64) - APSCT_version_R = attribute_wrapper(comms_annotation=["APSCT_version_R" ],datatype=numpy.str ) + APSCT_TEMP_R = attribute_wrapper(comms_annotation=["APSCT_TEMP_R" ],datatype=numpy.float64) # -------- # overloaded functions @@ -101,44 +97,27 @@ class APSCT(opcua_device): @command() @DebugIt() @only_when_on() - def CLK_off(self): + def APSCT_off(self): """ :return:None """ - self.opcua_connection.call_method(["CLK_off"]) + self.opcua_connection.call_method(["APSCT_off"]) @command() @DebugIt() @only_when_on() - def CLK_on(self): + def APSCT_on(self): """ :return:None """ - self.opcua_connection.call_method(["CLK_on"]) - - @command() - @DebugIt() - @only_when_on() - def CLK_PLL_setup(self): - """ + self.opcua_connection.call_method(["APSCT_on"]) - :return:None - """ - self.opcua_connection.call_method(["CLK_PLL_setup"]) # ---------- # Run server # ---------- -def main(args=None, **kwargs): - """Main function of the APSCT module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((APSCT,), args=args, **kwargs) - - -if __name__ == '__main__': - main() +def main(**kwargs): + """Main function of the ObservationControl module.""" + return entry(APSCT, **kwargs) diff --git a/devices/devices/apspu.py b/tangostationcontrol/tangostationcontrol/devices/apspu.py similarity index 55% rename from devices/devices/apspu.py rename to tangostationcontrol/tangostationcontrol/devices/apspu.py index cec9e56364a7c78d8938d0fb9241a840d1e0f95e..88a677fcb1cd743e1e59f8fe3aecbbb2a0992cba 100644 --- a/devices/devices/apspu.py +++ b/tangostationcontrol/tangostationcontrol/devices/apspu.py @@ -11,28 +11,20 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports -from tango import DebugIt -from tango.server import run, command -from tango.server import device_property, attribute from tango import AttrWriteType import numpy # Additional import -from device_decorators import * - -from clients.attribute_wrapper import attribute_wrapper -from devices.opcua_device import opcua_device -from common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.devices.device_decorators import * +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions __all__ = ["APSPU", "main"] + @device_logging_to_python() class APSPU(opcua_device): # ----------------- @@ -43,22 +35,24 @@ class APSPU(opcua_device): # Attributes # ---------- + APSPUTR_I2C_error_R = attribute_wrapper(comms_annotation=["APSPUTR_I2C_error_R" ],datatype=numpy.int64 ) + APSPUTR_monitor_rate_RW = attribute_wrapper(comms_annotation=["APSPUTR_monitor_rate_RW" ],datatype=numpy.int64 , access=AttrWriteType.READ_WRITE) APSPUTR_translator_busy_R = attribute_wrapper(comms_annotation=["APSPUTR_translator_busy_R" ],datatype=numpy.bool_ ) - APSPU_FAN1_RMS_R = attribute_wrapper(comms_annotation=["APSPU_FAN1_RMS_R" ],datatype=numpy.float64) - APSPU_FAN2_RMS_R = attribute_wrapper(comms_annotation=["APSPU_FAN2_RMS_R" ],datatype=numpy.float64) - APSPU_FAN3_RMS_R = attribute_wrapper(comms_annotation=["APSPU_FAN3_RMS_R" ],datatype=numpy.float64) - APSPU_I2C_error_R = attribute_wrapper(comms_annotation=["APSPU_I2C_error_R" ],datatype=numpy.int64 ) - APSPU_ID_R = attribute_wrapper(comms_annotation=["APSPU_ID_R" ],datatype=numpy.int64 ) + APSPU_FAN1_RPM_R = attribute_wrapper(comms_annotation=["APSPU_FAN1_RPM_R" ],datatype=numpy.float64) + APSPU_FAN2_RPM_R = attribute_wrapper(comms_annotation=["APSPU_FAN2_RPM_R" ],datatype=numpy.float64) + APSPU_FAN3_RPM_R = attribute_wrapper(comms_annotation=["APSPU_FAN3_RPM_R" ],datatype=numpy.float64) APSPU_LBA_IOUT_R = attribute_wrapper(comms_annotation=["APSPU_LBA_IOUT_R" ],datatype=numpy.float64) APSPU_LBA_TEMP_R = attribute_wrapper(comms_annotation=["APSPU_LBA_TEMP_R" ],datatype=numpy.float64) APSPU_LBA_VOUT_R = attribute_wrapper(comms_annotation=["APSPU_LBA_VOUT_R" ],datatype=numpy.float64) + APSPU_PCB_ID_R = attribute_wrapper(comms_annotation=["APSPU_PCB_ID_R" ],datatype=numpy.int64 ) + APSPU_PCB_number_R = attribute_wrapper(comms_annotation=["APSPU_PCB_number_R" ],datatype=numpy.str ) + APSPU_PCB_version_R = attribute_wrapper(comms_annotation=["APSPU_PCB_version_R" ],datatype=numpy.str ) APSPU_RCU2A_IOUT_R = attribute_wrapper(comms_annotation=["APSPU_RCU2A_IOUT_R" ],datatype=numpy.float64) APSPU_RCU2A_TEMP_R = attribute_wrapper(comms_annotation=["APSPU_RCU2A_TEMP_R" ],datatype=numpy.float64) APSPU_RCU2A_VOUT_R = attribute_wrapper(comms_annotation=["APSPU_RCU2A_VOUT_R" ],datatype=numpy.float64) APSPU_RCU2D_IOUT_R = attribute_wrapper(comms_annotation=["APSPU_RCU2D_IOUT_R" ],datatype=numpy.float64) APSPU_RCU2D_TEMP_R = attribute_wrapper(comms_annotation=["APSPU_RCU2D_TEMP_R" ],datatype=numpy.float64) APSPU_RCU2D_VOUT_R = attribute_wrapper(comms_annotation=["APSPU_RCU2D_VOUT_R" ],datatype=numpy.float64) - APSPU_version_R = attribute_wrapper(comms_annotation=["APSPU_version_R" ],datatype=numpy.str ) # -------- # overloaded functions @@ -69,17 +63,10 @@ class APSPU(opcua_device): # Commands # -------- + # ---------- # Run server # ---------- -def main(args=None, **kwargs): - """Main function of the APSPU module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((APSPU,), args=args, **kwargs) - - -if __name__ == '__main__': - main() +def main(**kwargs): + """Main function of the ObservationControl module.""" + return entry(APSPU, **kwargs) diff --git a/devices/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py similarity index 84% rename from devices/devices/boot.py rename to tangostationcontrol/tangostationcontrol/devices/boot.py index 5d9540aa52ffa1f177b3cd615110676f73466343..5b0acd2a587f6076e3a416151a30369a8a924478 100644 --- a/devices/devices/boot.py +++ b/tangostationcontrol/tangostationcontrol/devices/boot.py @@ -13,12 +13,6 @@ Boots the rest of the station software. """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports from tango import DebugIt from tango.server import run, command @@ -27,12 +21,11 @@ from tango import AttrWriteType, DeviceProxy, DevState # Additional import import numpy -from device_decorators import * +from tangostationcontrol.devices.device_decorators import * -from clients.attribute_wrapper import attribute_wrapper -from devices.hardware_device import hardware_device -from common.lofar_logging import device_logging_to_python, log_exceptions -from common.lofar_git import get_version +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.devices.lofar_device import lofar_device +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions import logging logger = logging.getLogger() @@ -191,7 +184,7 @@ class DevicesInitialiser(Thread): self.set_status(f"[restarting {device_name}] Succesfully started.") @device_logging_to_python() -class Boot(hardware_device): +class Boot(lofar_device): # ----------------- # Device Properties # ----------------- @@ -206,14 +199,14 @@ class Boot(hardware_device): Device_Names = device_property( dtype='DevVarStringArray', mandatory=False, - default_value=["LTS/Docker/1", # Docker controls the device containers, so it goes before anything else - "LTS/APSPU/1", # APS Power Units control other hardware we want to initialise - "LTS/APSCT/1", - "LTS/RECV/1", # RCUs are input for SDP, so initialise them first - "LTS/UNB2/1", # Uniboards host SDP, so initialise them first - "LTS/SDP/1", # SDP controls the mask for SST/XST/BST, so initialise it first - "LTS/SST/1", - "LTS/XST/1", + default_value=["STAT/Docker/1", # Docker controls the device containers, so it goes before anything else + "STAT/APSPU/1", # APS Power Units control other hardware we want to initialise + "STAT/APSCT/1", + "STAT/RECV/1", # RCUs are input for SDP, so initialise them first + "STAT/UNB2/1", # Uniboards host SDP, so initialise them first + "STAT/SDP/1", # SDP controls the mask for SST/XST/BST, so initialise it first + "STAT/SST/1", + "STAT/XST/1", ], ) @@ -242,10 +235,10 @@ class Boot(hardware_device): init_device method to be released. This method is called by the device destructor and by the device Init command (a Tango built-in). """ - self.debug_stream("Shutting down...") + logger.debug("Shutting down...") self.Off() - self.debug_stream("Shut down. Good bye.") + logger.debug("Shut down. Good bye.") # -------- # overloaded functions @@ -256,7 +249,7 @@ class Boot(hardware_device): try: self.initialiser.stop() except Exception as e: - self.warn_stream("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e)) + logger.warning("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e)) @log_exceptions() def configure_for_initialise(self): @@ -294,14 +287,6 @@ class Boot(hardware_device): # ---------- # Run server # ---------- -def main(args=None, **kwargs): - """Main function of the RECV module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((Boot,), args=args, **kwargs) - - -if __name__ == '__main__': - main() +def main(**kwargs): + """Main function of the Boot module.""" + return entry(Boot, **kwargs) diff --git a/devices/devices/device_decorators.py b/tangostationcontrol/tangostationcontrol/devices/device_decorators.py similarity index 82% rename from devices/devices/device_decorators.py rename to tangostationcontrol/tangostationcontrol/devices/device_decorators.py index 5300ba2a06380599a3457c1624344243b7f5db60..b3f203bfff1fec77efbc0b2d95d8c464a97dcb71 100644 --- a/devices/devices/device_decorators.py +++ b/tangostationcontrol/tangostationcontrol/devices/device_decorators.py @@ -2,6 +2,9 @@ from tango import DevState, Except from functools import wraps import traceback +import logging +logger = logging.getLogger() + __all__ = ["only_in_states", "only_when_on", "fault_on_error"] def only_in_states(allowed_states): @@ -15,7 +18,7 @@ def only_in_states(allowed_states): if self.get_state() in allowed_states: return func(self, *args, **kwargs) - self.warn_stream("Illegal command: Function %s can only be called in states %s. Current state: %s" % (func.__name__, allowed_states, self.get_state())) + logger.warning("Illegal command: Function %s can only be called in states %s. Current state: %s" % (func.__name__, allowed_states, self.get_state())) Except.throw_exception("IllegalCommand", "Function can only be called in states %s. Current state: %s" % (allowed_states, self.get_state()), func.__name__) return state_check_wrapper @@ -50,8 +53,10 @@ def fault_on_error(): try: return func(self, *args, **kwargs) except Exception as e: - self.error_stream("Function failed. Trace: %s", traceback.format_exc()) - self.Fault() + + logger.exception("Function failed.") + self.Fault(f"FAULT in {func.__name__}: {e.__class__.__name__}: {e}") + return None return error_wrapper diff --git a/devices/devices/docker_device.py b/tangostationcontrol/tangostationcontrol/devices/docker_device.py similarity index 88% rename from devices/devices/docker_device.py rename to tangostationcontrol/tangostationcontrol/devices/docker_device.py index f8a83dd41f9a81a217dcab9a2dc54201ecff1025..00f42ca816e1e8219cde06913ef633961a15366e 100644 --- a/devices/devices/docker_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/docker_device.py @@ -11,14 +11,7 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports -from tango import DebugIt from tango.server import run, command from tango.server import device_property, attribute from tango import AttrWriteType @@ -26,17 +19,22 @@ import numpy import asyncio # Additional import -from device_decorators import * +from tangostationcontrol.devices.device_decorators import * + +# Additional import +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.clients.docker_client import DockerClient +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.lofar_device import lofar_device +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions -from clients.docker_client import DockerClient -from clients.attribute_wrapper import attribute_wrapper -from devices.hardware_device import hardware_device -from common.lofar_logging import device_logging_to_python, log_exceptions +import logging +logger = logging.getLogger() __all__ = ["Docker", "main"] @device_logging_to_python() -class Docker(hardware_device): +class Docker(lofar_device): # ----------------- # Device Properties # ----------------- @@ -103,7 +101,7 @@ class Docker(hardware_device): try: self.docker_client.sync_stop() except Exception as e: - self.warn_stream("Exception while stopping docker client in configure_for_off function: {}. Exception ignored".format(e)) + logger.warning("Exception while stopping docker client in configure_for_off function: {}. Exception ignored".format(e)) @log_exceptions() def configure_for_initialise(self): @@ -131,14 +129,6 @@ class Docker(hardware_device): # ---------- # Run server # ---------- -def main(args=None, **kwargs): +def main(**kwargs): """Main function of the Docker module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((Docker,), args=args, **kwargs) - - -if __name__ == '__main__': - main() + return entry(Docker, **kwargs) diff --git a/devices/devices/hardware_device.py b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py similarity index 83% rename from devices/devices/hardware_device.py rename to tangostationcontrol/tangostationcontrol/devices/lofar_device.py index 7c7e6663cff7a68f8b0340d59f076bb946ea9ec5..8886abd8a40b38df1fa9ec181783d9f4a2ff08ae 100644 --- a/devices/devices/hardware_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py @@ -15,23 +15,24 @@ from abc import abstractmethod # PyTango imports from tango.server import Device, command, DeviceMeta, attribute -from tango import DevState, DebugIt, Attribute, DeviceProxy, AttrWriteType -# Additional import - -from clients.attribute_wrapper import attribute_wrapper -from common.lofar_logging import log_exceptions -from common.lofar_git import get_version -from devices.abstract_device import AbstractDeviceMetas -from devices.device_decorators import only_in_states, fault_on_error +from tango import AttrWriteType, DevState, DebugIt, Attribute, DeviceProxy import time import math -__all__ = ["hardware_device"] +# Additional import +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.common.lofar_logging import log_exceptions +from tangostationcontrol.common.lofar_version import get_version +from tangostationcontrol.devices.abstract_device import AbstractDeviceMetas +from tangostationcontrol.devices.device_decorators import only_in_states, fault_on_error + + +__all__ = ["lofar_device"] import logging logger = logging.getLogger() -class hardware_device(Device, metaclass=AbstractDeviceMetas): +class lofar_device(Device, metaclass=AbstractDeviceMetas): """ **Properties:** @@ -83,6 +84,16 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): Device.init_device(self) self.set_state(DevState.OFF) + self.set_status("Device is in the OFF state.") + + # register a proxy to ourselves, to interact with + # our attributes and commands as a client would. + # + # this is required to get/set attributes. + # + # we cannot write directly to our attribute, as that would not + # trigger a write_{name} call. See https://www.tango-controls.org/community/forum/c/development/c/accessing-own-deviceproxy-class/?page=1#post-2021 + self.proxy = DeviceProxy(self.get_name()) @log_exceptions() def delete_device(self): @@ -102,7 +113,7 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): # -------- @command() - @only_in_states([DevState.FAULT, DevState.OFF]) + @only_in_states([DevState.OFF]) @DebugIt() @fault_on_error() @log_exceptions() @@ -113,6 +124,8 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): :return:None """ self.set_state(DevState.INIT) + self.set_status("Device is in the INIT state.") + self.setup_value_dict() # reload our class & device properties from the Tango database @@ -121,6 +134,7 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): self.configure_for_initialise() self.set_state(DevState.STANDBY) + self.set_status("Device is in the STANDBY state.") @command() @only_in_states([DevState.STANDBY, DevState.ON]) @@ -139,7 +153,9 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): return self.configure_for_on() + self.set_state(DevState.ON) + self.set_status("Device is in the ON state.") @command() @DebugIt() @@ -156,23 +172,25 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): # Turn off self.set_state(DevState.OFF) + self.set_status("Device is in the OFF state.") self.configure_for_off() # Turn off again, in case of race conditions through reconnecting self.set_state(DevState.OFF) + self.set_status("Device is in the OFF state.") + @command() @only_in_states([DevState.ON, DevState.INIT, DevState.STANDBY, DevState.FAULT]) @DebugIt() @log_exceptions() - def Fault(self): + def Fault(self, new_status="Device is in the FAULT state."): """ - FAULT state is used to indicate our connection with the OPC-UA server is down. + FAULT state is used to indicate the device broke down, and partially or fully + stopped functioning. Remaining functionality is undefined. - This device will try to reconnect once, and transition to the ON state on success. - - If reconnecting fails, the user needs to call Initialise() to retry to restart this device. + new_status: The status to set when going to FAULT. :return:None """ @@ -181,8 +199,10 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): logger.warning("Requested to go to FAULT state, but am already in FAULT state.") return - self.configure_for_fault() self.set_state(DevState.FAULT) + self.set_status(new_status) + + self.configure_for_fault() # functions that can or must be overloaded def configure_for_fault(self): @@ -219,12 +239,6 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): 2) Any remaining default properties are set. """ - # we cannot write directly to our attribute, as that would not - # trigger a write_{name} call. See https://www.tango-controls.org/community/forum/c/development/c/accessing-own-deviceproxy-class/?page=1#post-2021 - - # obtain a proxy to myself, to write values - proxy = DeviceProxy(self.get_name()) - # collect all attributes for which defaults are provided attributes_with_defaults = [name for name in dir(self) # collect all attribute members @@ -241,8 +255,8 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): default_value = getattr(self, f"{name}_default") # set the attribute to the configured default - self.debug_stream(f"Setting attribute {name} to {default_value}") - proxy.write_attribute(name, default_value) + logger.debug(f"Setting attribute {name} to {default_value}") + self.proxy.write_attribute(name, default_value) except Exception as e: # log which attribute we're addressing raise Exception(f"Cannot assign default to attribute {name}") from e @@ -269,14 +283,11 @@ class hardware_device(Device, metaclass=AbstractDeviceMetas): pollperiod: how often to check the attribute, in seconds. """ - attr = getattr(self, attr_name) - # Poll every half a second for _ in range(math.ceil(timeout/pollperiod)): - if attr != value: + if getattr(self.proxy, attr_name) != value: return time.sleep(pollperiod) - raise Exception(f"{attr} != {value} after f{timeout} seconds still.") - + raise Exception(f"{attr_name} != {value} after {timeout} seconds still.") diff --git a/devices/devices/observation.py b/tangostationcontrol/tangostationcontrol/devices/observation.py similarity index 77% rename from devices/devices/observation.py rename to tangostationcontrol/tangostationcontrol/devices/observation.py index 0ac9cbc1837fdd8e7ded14bb6c8459226c223866..d43ecdf677d33ff942cdfb18d792b5b1a0609a22 100644 --- a/devices/devices/observation.py +++ b/tangostationcontrol/tangostationcontrol/devices/observation.py @@ -5,25 +5,22 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. - -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports from tango import server, Except, DevState, AttrWriteType, DevString, DebugIt from tango.server import Device, run, command, attribute import numpy from time import time -from devices.device_decorators import * -from common.lofar_logging import device_logging_to_python, log_exceptions -from common.lofar_git import get_version +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.common.lofar_version import get_version +from tangostationcontrol.devices.device_decorators import * from json import loads +import logging +logger = logging.getLogger() + __all__ = ["Observation", "main"] @device_logging_to_python() @@ -55,14 +52,14 @@ class Observation(Device): This method is called by the device destructor and by the device Init command (a Tango built-in). """ - self.debug_stream("Shutting down...") + logger.debug("Shutting down...") if self.get_state() != DevState.OFF: self.Off() - self.debug_stream("Shut down. Good bye.") + logger.debug("Shut down. Good bye.") # Lifecycle functions @command(dtype_in = DevString) - @only_in_states([DevState.FAULT, DevState.OFF]) + @only_in_states([DevState.OFF]) @log_exceptions() def Initialise(self, parameters: DevString = None): self.set_state(DevState.INIT) @@ -76,21 +73,21 @@ class Observation(Device): self._observation_id = int(self.observation_parameters.get("id")) self._stop_time = float(self.observation_parameters.get("stop_time")) self.set_state(DevState.STANDBY) - self.info_stream("The observation with ID={} is configured. It will begin as soon as On() is called and it is supposed to stop at {}.".format(self._observation_id, self._stop_time)) + logger.info("The observation with ID={} is configured. It will begin as soon as On() is called and it is supposed to stop at {}.".format(self._observation_id, self._stop_time)) @command() @only_in_states([DevState.STANDBY]) @log_exceptions() def On(self): self.set_state(DevState.ON) - self.info_stream("Started the observation with ID={}.".format(self._observation_id)) + logger.info("Started the observation with ID={}.".format(self._observation_id)) @command() @log_exceptions() def Off(self): self.stop_polling(True) self.set_state(DevState.OFF) - self.info_stream("Stopped the observation with ID={}.".format(self._observation_id)) + logger.info("Stopped the observation with ID={}.".format(self._observation_id)) @only_when_on() @fault_on_error() @@ -117,10 +114,6 @@ class Observation(Device): # ---------- # Run server # ---------- -def main(args = None, **kwargs): +def main(**kwargs): """Main function of the ObservationControl module.""" - return run((Observation,), args = args, **kwargs) - - -if __name__ == '__main__': - main() + return entry(Observation, **kwargs) diff --git a/devices/devices/observation_control.py b/tangostationcontrol/tangostationcontrol/devices/observation_control.py similarity index 85% rename from devices/devices/observation_control.py rename to tangostationcontrol/tangostationcontrol/devices/observation_control.py index 9b60f86bb983057d023483ebaa61164bdfba5bee..2bdae2e850a2b33955fcadc9512e4e6241d0452c 100644 --- a/devices/devices/observation_control.py +++ b/tangostationcontrol/tangostationcontrol/devices/observation_control.py @@ -5,13 +5,6 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. - -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports from tango import Except, DevFailed, DevState, AttrWriteType, DebugIt, DeviceProxy, Util, DevBoolean, DevString from tango.server import Device, run, command, device_property, attribute @@ -21,12 +14,14 @@ import numpy import time from json import loads -from devices.device_decorators import * -from common.lofar_logging import device_logging_to_python, log_exceptions -from common.lofar_git import get_version - -from observation import Observation +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.common.lofar_version import get_version +from tangostationcontrol.devices.device_decorators import * +from tangostationcontrol.devices.observation import Observation +import logging +logger = logging.getLogger() __all__ = ["ObservationControl", "main"] @@ -123,7 +118,7 @@ class ObservationControl(Device): # Lifecycle functions @command() - @only_in_states([DevState.FAULT, DevState.OFF]) + @only_in_states([DevState.OFF]) @log_exceptions() @DebugIt() def Initialise(self): @@ -158,7 +153,7 @@ class ObservationControl(Device): @log_exceptions() def read_running_observations_R(self): obs = [ key for key in self.running_observations ] - self.debug_stream("{}".format(obs)) + logger.debug("{}".format(obs)) return obs @log_exceptions() @@ -172,7 +167,7 @@ class ObservationControl(Device): """ if event.err: # Something is fishy with this event. - self.warn_stream("The Observation device {} sent an event but the event signals an error. It is advised to check the logs for any indication that something went wrong in that device. Event data={} ".format(event.device, event)) + logger.warning("The Observation device {} sent an event but the event signals an error. It is advised to check the logs for any indication that something went wrong in that device. Event data={} ".format(event.device, event)) return # Get the Observation ID from the sending device. @@ -182,7 +177,7 @@ class ObservationControl(Device): running_obs = self.running_observations.copy() if not running_obs: # No obs is running??? - self.warn_stream("Received an observation_running event for the observation with ID={}. According to the records in ObservationControl, this observation is not supposed to run. Please check previous logs, especially around the time an observation with this ID was started. Will continue and ignore this event.".format(obs_id)) + logger.warning("Received an observation_running event for the observation with ID={}. According to the records in ObservationControl, this observation is not supposed to run. Please check previous logs, especially around the time an observation with this ID was started. Will continue and ignore this event.".format(obs_id)) return if id in running_obs: @@ -213,7 +208,7 @@ class ObservationControl(Device): # Convert the input parameter to a dict. parameter_dict = loads(parameters) - self.debug_stream("incoming parameter_array = {}, parameter_dict = {}".format(parameters, parameter_dict)) + logger.debug("incoming parameter_array = {}, parameter_dict = {}".format(parameters, parameter_dict)) # Parameter check, do not execute an observation in case # the parameters are not sufficiently defined. @@ -245,10 +240,10 @@ class ObservationControl(Device): except DevFailed as ex: # It is OK if this fails. This likely means that the device did # never exist in the Tango DB. Still add a warning to the logs. - self.warn_stream("Something went wrong when it was attempted to remove the device {} from the Tango DB. You should better go and check the logs. Exception: {}".format(device_name, ex)) + logger.warning("Something went wrong when it was attempted to remove the device {} from the Tango DB. You should better go and check the logs. Exception: {}".format(device_name, ex)) pass else: - self.error_stream("Cannot delete a device from the Tango DB if the device's class name or the device name are not provided: class_name={}, device_name={}".format(class_name, device_name)) + logger.error("Cannot delete a device from the Tango DB if the device's class name or the device name are not provided: class_name={}, device_name={}".format(class_name, device_name)) def create_dynamic_device(self, class_name: str = None, device_name: str = None): """ @@ -261,7 +256,7 @@ class ObservationControl(Device): except DevFailed as ex: self.delete_dynamic_device(class_name, device_name) error_string = "Cannot start the device {} for the device class {}. Exception: {}".format(device_name, class_name, ex) - self.error_stream("{}, {}".format(error_string, ex)) + logger.exception(error_string) Except.re_throw_exception(ex, "DevFailed", error_string, __name__) # API @@ -288,7 +283,7 @@ class ObservationControl(Device): self.create_dynamic_device(class_name, device_name) except DevFailed as ex: error_string = "Cannot create the Observation device instance {} for ID={}. This means that the observation did not start.".format(device_name, obs_id) - self.error_stream(error_string) + logger.exception(error_string) Except.re_throw_exception(ex, "DevFailed", error_string, __name__) try: @@ -308,7 +303,7 @@ class ObservationControl(Device): # Remove the device again. self.delete_dynamic_device(class_name, device_name) error_string = "Cannot access the Observation device instance for observation ID={} with device class name={} and device instance name={}. This means that the observation likely did not start but certainly cannot be controlled and/or forcefully be stopped.".format(obs_id, class_name, device_name) - self.error_stream("{}, {}".format(error_string, ex)) + logger.exception(error_string) Except.re_throw_exception(ex, "DevFailed", error_string, __name__) try: @@ -338,11 +333,11 @@ class ObservationControl(Device): # Finally update the self.running_observation dict's entry of this # observation with the complete set of info. self.running_observations[obs_id] = observation - self.info_stream("Successfully started an observation with ID={}.".format(obs_id)) + logger.info("Successfully started an observation with ID={}.".format(obs_id)) except DevFailed as ex: self.delete_dynamic_device(class_name, device_name) error_string = "Cannot access the Observation device instance for observation ID={} with device class name={} and device instance name={}. This means that the observation cannot be controlled and/or forcefully be stopped.".format(obs_id, Observation.__name__, device_name) - self.error_stream("{}, {}".format(error_string, ex)) + logger.exception(error_string) Except.re_throw_exception(ex, "DevFailed", error_string, __name__) @command(dtype_in = numpy.int64) @@ -359,7 +354,7 @@ class ObservationControl(Device): error = "Cannot stop an observation with ID={}, because the observation is not running.".format(obs_id) Except.throw_exception("IllegalCommand", error, __name__) - self.info_stream("Stopping the observation with ID={}.".format(obs_id)) + logger.info("Stopping the observation with ID={}.".format(obs_id)) # Fetch the obs data and remove it from the dict of # currently running observations. observation = self.running_observations.pop(obs_id) @@ -369,7 +364,7 @@ class ObservationControl(Device): try: device_proxy.ping() except DevFailed: - self.warn_stream("The device for the Observation with ID={} has unexpectedly already disappeared. It is advised to check the logs up to 10s prior to this message to see what happened.".format(obs_id)) + logger.warning("The device for the Observation with ID={} has unexpectedly already disappeared. It is advised to check the logs up to 10s prior to this message to see what happened.".format(obs_id)) else: # Unsubscribe from the subscribed event. event_id = observation.pop("event_id") @@ -394,15 +389,15 @@ class ObservationControl(Device): remaining_wait_time = remaining_wait_time - sleep_time # Check if the observation object is really in OFF state. if stopped: - self.info_stream("Successfully stopped the observation with ID={}.".format(obs_id)) + logger.info("Successfully stopped the observation with ID={}.".format(obs_id)) else: - self.warn_stream("Could not shut down the Observation device (\"{}\") for observation ID={}. This means that there is a chance for a memory leak. Will continue anyway and forcefully delete the Observation object.".format(observation["device_name"], obs_id)) + logger.warning("Could not shut down the Observation device (\"{}\") for observation ID={}. This means that there is a chance for a memory leak. Will continue anyway and forcefully delete the Observation object.".format(observation["device_name"], obs_id)) # Finally remove the device object from the Tango DB. try: self.delete_dynamic_device(observation["class_name"], observation["device_name"]) except DevFailed: - self.warn_stream("Something went wrong when the device {} was removed from the Tango DB. There is nothing that can be done about this here at this moment but you should check the Tango DB yourself.".format(observation["device_name"])) + logger.warning("Something went wrong when the device {} was removed from the Tango DB. There is nothing that can be done about this here at this moment but you should check the Tango DB yourself.".format(observation["device_name"])) @command() @only_when_on() @@ -430,9 +425,9 @@ class ObservationControl(Device): observation = self.running_observations.get(obs_id) info = "An observation with ID={} is".format(obs_id) if observation is not None: - self.debug_stream("{} running.".format(info)) + logger.debug("{} running.".format(info)) return True - self.debug_stream("{} not running.".format(info)) + logger.debug("{} not running.".format(info)) return False @command(dtype_out = DevBoolean) @@ -445,10 +440,6 @@ class ObservationControl(Device): # ---------- # Run server # ---------- -def main(args = None, **kwargs): +def main(**kwargs): """Main function of the ObservationControl module.""" - return run((ObservationControl, Observation), verbose = True, args = args, **kwargs) - - -if __name__ == '__main__': - main() + return entry((ObservationControl, Observation), verbose=True, **kwargs) diff --git a/devices/devices/opcua_device.py b/tangostationcontrol/tangostationcontrol/devices/opcua_device.py similarity index 85% rename from devices/devices/opcua_device.py rename to tangostationcontrol/tangostationcontrol/devices/opcua_device.py index fd49b90f122868a0741ebe91ba69d71a434143d6..9f846533533e5211cbb7a5aa5018b87364f08463 100644 --- a/devices/devices/opcua_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/opcua_device.py @@ -25,15 +25,17 @@ import numpy import asyncio # Additional import -from devices.device_decorators import * +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.clients.opcua_client import OPCUAConnection +from tangostationcontrol.devices.device_decorators import * +from tangostationcontrol.devices.lofar_device import lofar_device -from clients.opcua_client import OPCUAConnection -from devices.hardware_device import hardware_device -from common.lofar_logging import device_logging_to_python, log_exceptions +import logging +logger = logging.getLogger() __all__ = ["opcua_device", "main"] -class opcua_device(hardware_device): +class opcua_device(lofar_device): """ **Properties:** @@ -117,7 +119,7 @@ class opcua_device(hardware_device): i.set_pass_func() self.opcua_missing_attributes.append(",".join(self.opcua_connection.get_node_path(i.comms_annotation))) - self.warn_stream("error while setting the attribute {} read/write function. {}".format(i, e)) + logger.warning("error while setting the attribute {} read/write function. {}".format(i, e)) @log_exceptions() def configure_for_off(self): @@ -126,4 +128,4 @@ class opcua_device(hardware_device): # disconnect self.opcua_connection.sync_stop() except Exception as e: - self.warn_stream("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e)) + logger.warning("Exception while stopping OPC ua connection in configure_for_off function: {}. Exception ignored".format(e)) diff --git a/devices/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py similarity index 74% rename from devices/devices/recv.py rename to tangostationcontrol/tangostationcontrol/devices/recv.py index d180e955a56ee583a7a2fbc1a732d933c27acced..4ac93d85abcf66d4c8dc25ab60a1fae89fbef794 100644 --- a/devices/devices/recv.py +++ b/tangostationcontrol/tangostationcontrol/devices/recv.py @@ -11,25 +11,19 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports from tango import DebugIt from tango.server import run, command from tango.server import device_property, attribute -from tango import AttrWriteType +from tango import AttrWriteType, DevState import numpy -# Additional import -from device_decorators import * - -from clients.attribute_wrapper import attribute_wrapper -from devices.opcua_device import opcua_device -from common.lofar_logging import device_logging_to_python, log_exceptions +# Additional import +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.device_decorators import * +from tangostationcontrol.devices.opcua_device import opcua_device import logging logger = logging.getLogger() @@ -63,11 +57,12 @@ class RECV(opcua_device): # ---------- # Attributes # ---------- - Ant_status_R = attribute(dtype=str, max_dim_x=3, max_dim_y=32) + ANT_status_R = attribute(dtype=(str,), max_dim_x=3, max_dim_y=32) + RCU_LED_colour_R = attribute(dtype=(numpy.uint32,), max_dim_x=32, fget=lambda self: (2 * self.proxy.RCU_LED_green_on_R + 4 * self.proxy.RCU_LED_red_on_R).astype(numpy.uint32)) ANT_mask_RW = attribute_wrapper(comms_annotation=["ANT_mask_RW" ],datatype=numpy.bool_ , dims=(3,32), access=AttrWriteType.READ_WRITE) - HBAT_beamformer_delays_R = attribute_wrapper(comms_annotation=["HBAT_beamformer_delays_R" ],datatype=numpy.int64 , dims=(32,96)) - HBAT_beamformer_delays_RW = attribute_wrapper(comms_annotation=["HBAT_beamformer_delays_RW" ],datatype=numpy.int64 , dims=(32,96), access=AttrWriteType.READ_WRITE) + HBAT_BF_delays_R = attribute_wrapper(comms_annotation=["HBAT_BF_delays_R" ],datatype=numpy.int64 , dims=(32,96)) + HBAT_BF_delays_RW = attribute_wrapper(comms_annotation=["HBAT_BF_delays_RW" ],datatype=numpy.int64 , dims=(32,96), access=AttrWriteType.READ_WRITE) HBAT_LED_on_R = attribute_wrapper(comms_annotation=["HBAT_LED_on_R" ],datatype=numpy.bool_ , dims=(32,96)) HBAT_LED_on_RW = attribute_wrapper(comms_annotation=["HBAT_LED_on_RW" ],datatype=numpy.bool_ , dims=(32,96), access=AttrWriteType.READ_WRITE) HBAT_PWR_LNA_on_R = attribute_wrapper(comms_annotation=["HBAT_PWR_LNA_on_R" ],datatype=numpy.bool_ , dims=(32,96)) @@ -82,14 +77,14 @@ class RECV(opcua_device): RCU_DTH_freq_R = attribute_wrapper(comms_annotation=["RCU_DTH_freq_R" ],datatype=numpy.int64 , dims=(3,32)) RCU_DTH_freq_RW = attribute_wrapper(comms_annotation=["RCU_DTH_freq_RW" ],datatype=numpy.int64 , dims=(3,32), access=AttrWriteType.READ_WRITE) RCU_DTH_on_R = attribute_wrapper(comms_annotation=["RCU_DTH_on_R" ],datatype=numpy.bool_ , dims=(3,32)) - RCU_DTH_shutdown_R = attribute_wrapper(comms_annotation=["RCU_DTH_shutdown_R" ],datatype=numpy.bool_ , dims=(3,32)) - RCU_I2C_error_R = attribute_wrapper(comms_annotation=["RCU_I2C_error_R" ],datatype=numpy.int64 , dims=(32,)) - RCU_ID_R = attribute_wrapper(comms_annotation=["RCU_ID_R" ],datatype=numpy.int64 , dims=(32,)) - RCU_LED_green_off_R = attribute_wrapper(comms_annotation=["RCU_LED_green_off_R" ],datatype=numpy.bool_ , dims=(32,)) - RCU_LED_green_off_RW = attribute_wrapper(comms_annotation=["RCU_LED_green_off_RW" ],datatype=numpy.bool_ , dims=(32,), access=AttrWriteType.READ_WRITE) - RCU_LED_red_off_R = attribute_wrapper(comms_annotation=["RCU_LED_red_off_R" ],datatype=numpy.bool_ , dims=(32,)) - RCU_LED_red_off_RW = attribute_wrapper(comms_annotation=["RCU_LED_red_off_RW" ],datatype=numpy.bool_ , dims=(32,), access=AttrWriteType.READ_WRITE) + RCU_LED_green_on_R = attribute_wrapper(comms_annotation=["RCU_LED_green_on_R" ],datatype=numpy.bool_ , dims=(32,)) + RCU_LED_green_on_RW = attribute_wrapper(comms_annotation=["RCU_LED_green_on_RW" ],datatype=numpy.bool_ , dims=(32,), access=AttrWriteType.READ_WRITE) + RCU_LED_red_on_R = attribute_wrapper(comms_annotation=["RCU_LED_red_on_R" ],datatype=numpy.bool_ , dims=(32,)) + RCU_LED_red_on_RW = attribute_wrapper(comms_annotation=["RCU_LED_red_on_RW" ],datatype=numpy.bool_ , dims=(32,), access=AttrWriteType.READ_WRITE) RCU_mask_RW = attribute_wrapper(comms_annotation=["RCU_mask_RW" ],datatype=numpy.bool_ , dims=(32,), access=AttrWriteType.READ_WRITE) + RCU_PCB_ID_R = attribute_wrapper(comms_annotation=["RCU_PCB_ID_R" ],datatype=numpy.int64 , dims=(32,)) + RCU_PCB_number_R = attribute_wrapper(comms_annotation=["RCU_PCB_number_R" ],datatype=numpy.str , dims=(32,)) + RCU_PCB_version_R = attribute_wrapper(comms_annotation=["RCU_PCB_version_R" ],datatype=numpy.str , dims=(32,)) RCU_PWR_1V8_R = attribute_wrapper(comms_annotation=["RCU_PWR_1V8_R" ],datatype=numpy.float64, dims=(32,)) RCU_PWR_2V5_R = attribute_wrapper(comms_annotation=["RCU_PWR_2V5_R" ],datatype=numpy.float64, dims=(32,)) RCU_PWR_3V3_R = attribute_wrapper(comms_annotation=["RCU_PWR_3V3_R" ],datatype=numpy.float64, dims=(32,)) @@ -101,8 +96,9 @@ class RECV(opcua_device): RCU_PWR_ANT_VOUT_R = attribute_wrapper(comms_annotation=["RCU_PWR_ANT_VOUT_R" ],datatype=numpy.float64, dims=(3,32)) RCU_PWR_DIGITAL_on_R = attribute_wrapper(comms_annotation=["RCU_PWR_DIGITAL_on_R" ],datatype=numpy.bool_ , dims=(32,)) RCU_PWR_good_R = attribute_wrapper(comms_annotation=["RCU_PWR_good_R" ],datatype=numpy.bool_ , dims=(32,)) - RCU_temperature_R = attribute_wrapper(comms_annotation=["RCU_temperature_R" ],datatype=numpy.float64, dims=(32,)) - RCU_version_R = attribute_wrapper(comms_annotation=["RCU_version_R" ],datatype=numpy.str , dims=(32,)) + RCU_TEMP_R = attribute_wrapper(comms_annotation=["RCU_TEMP_R" ],datatype=numpy.float64, dims=(32,)) + RECVTR_I2C_error_R = attribute_wrapper(comms_annotation=["RECVTR_I2C_error_R" ],datatype=numpy.int64 , dims=(32,)) + RECVTR_monitor_rate_RW = attribute_wrapper(comms_annotation=["RECVTR_monitor_rate_RW" ],datatype=numpy.int64 , access=AttrWriteType.READ_WRITE) RECVTR_translator_busy_R = attribute_wrapper(comms_annotation=["RECVTR_translator_busy_R" ],datatype=numpy.bool_ ) # -------- @@ -135,22 +131,22 @@ class RECV(opcua_device): @command() @DebugIt() @only_when_on() - def ADC_on(self): + def RCU_DTH_off(self): """ :return:None """ - self.opcua_connection.call_method(["ADC_on"]) + self.opcua_connection.call_method(["RCU_DTH_off"]) @command() @DebugIt() @only_when_on() - def RCU_update(self): + def RCU_DTH_on(self): """ :return:None """ - self.opcua_connection.call_method(["RCU_update"]) + self.opcua_connection.call_method(["RCU_DTH_on"]) def _initialise_hardware(self): """ Initialise the RCU hardware. """ @@ -174,8 +170,8 @@ class RECV(opcua_device): This function can be used as input to modify the RCU_mask_RW. """ - rcu_mask = self.RCU_mask_RW - i2c_errors = self.RCU_I2C_STATUS_R + rcu_mask = self.proxy.RCU_mask_RW + i2c_errors = self.proxy.RCU_I2C_STATUS_R nr_rcus = len(rcu_mask) rcu_status = [""] * nr_rcus @@ -191,7 +187,7 @@ class RECV(opcua_device): return rcu_status - def read_Ant_status_R(self): + def read_ANT_status_R(self): """ Returns a set of strings denoting the status of each antenna. An empty string means no problems were detected. A non-empty @@ -199,10 +195,10 @@ class RECV(opcua_device): This function can be used as input to modify the Ant_mask_RW. """ - ant_mask = self.Ant_mask_RW - rcu_mask = self.RCU_mask_RW - adc_lock = self.RCU_ADC_lock_R - i2c_errors = self.RCU_I2C_STATUS_R + ant_mask = self.proxy.ANT_mask_RW + rcu_mask = self.proxy.RCU_mask_RW + adc_lock = self.proxy.RCU_ADC_locked_R + i2c_errors = self.proxy.RCU_I2C_STATUS_R nr_rcus = len(ant_mask) nr_ants_per_rcu = len(ant_mask[0]) @@ -232,14 +228,6 @@ class RECV(opcua_device): # ---------- # Run server # ---------- -def main(args=None, **kwargs): +def main(**kwargs): """Main function of the RECV module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((RECV,), args=args, **kwargs) - - -if __name__ == '__main__': - main() + return entry(RECV, **kwargs) diff --git a/devices/integration_test/__init__.py b/tangostationcontrol/tangostationcontrol/devices/sdp/__init__.py similarity index 100% rename from devices/integration_test/__init__.py rename to tangostationcontrol/tangostationcontrol/devices/sdp/__init__.py diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py new file mode 100644 index 0000000000000000000000000000000000000000..ed970bc5681ec341a0bc62d0f37c82523f595f50 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# +# This file is part of the SDP project +# +# +# +# Distributed under the terms of the APACHE license. +# See LICENSE.txt for more info. + +""" SDP Device Server for LOFAR2.0 + +""" + +# PyTango imports +from tango.server import run +from tango.server import device_property, attribute +from tango import AttrWriteType + +# Additional import +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions + +import numpy + +__all__ = ["SDP", "main"] + + +@device_logging_to_python() +class SDP(opcua_device): + # ----------------- + # Device Properties + # ----------------- + + TR_fpga_mask_RW_default = device_property( + dtype='DevVarBooleanArray', + mandatory=False, + default_value=[True] * 16 + ) + + FPGA_processing_enable_RW_default = device_property( + dtype='DevVarBooleanArray', + mandatory=False, + default_value=[True] * 16 + ) + + FPGA_wg_enable_RW_default = device_property( + dtype='DevVarBooleanArray', + mandatory=False, + default_value=[[False] * 12] * 16 + ) + + # If we enable the waveform generator, we want some sane defaults. + + FPGA_wg_amplitude_RW = device_property( + dtype='DevVarDoubleArray', + mandatory=False, + default_value=[[0.1] * 12] * 16 + ) + + FPGA_wg_frequency_RW = device_property( + dtype='DevVarDoubleArray', + mandatory=False, + # Emit a signal on subband 102 + default_value=[[102 * 200e6/1024] * 12] * 16 + ) + + FPGA_wg_phase_RW = device_property( + dtype='DevVarDoubleArray', + mandatory=False, + default_value=[[0.0] * 12] * 16 + ) + + FPGA_sdp_info_station_id_RW_default = device_property( + dtype='DevVarULongArray', + mandatory=False, + default_value=[0] * 16 + ) + + FPGA_subband_weights_RW_default = device_property( + dtype='DevVarULongArray', + mandatory=False, + default_value=[[8192] * 12 * 512] * 16 + ) + + first_default_settings = [ + # set the masks first, as those filter any subsequent settings + 'TR_fpga_mask_RW' + ] + + # ---------- + # Attributes + # ---------- + + FPGA_beamlet_output_enable_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_enable_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_beamlet_output_enable_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_beamlet_output_hdr_eth_destination_mac_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_hdr_eth_destination_mac_R"], datatype=numpy.str, dims=(16,)) + FPGA_beamlet_output_hdr_eth_destination_mac_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_hdr_eth_destination_mac_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_beamlet_output_hdr_ip_destination_address_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_hdr_ip_destination_address_R"], datatype=numpy.str, dims=(16,)) + FPGA_beamlet_output_hdr_ip_destination_address_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_hdr_ip_destination_address_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_beamlet_output_hdr_udp_destination_port_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) + FPGA_beamlet_output_hdr_udp_destination_port_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_beamlet_output_scale_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_scale_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_beamlet_output_scale_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_scale_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_firmware_version_R = attribute_wrapper(comms_annotation=["FPGA_firmware_version_R"], datatype=numpy.str, dims=(16,)) + FPGA_global_node_index_R = attribute_wrapper(comms_annotation=["FPGA_global_node_index_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_hardware_version_R = attribute_wrapper(comms_annotation=["FPGA_hardware_version_R"], datatype=numpy.str, dims=(16,)) + FPGA_processing_enable_R = attribute_wrapper(comms_annotation=["FPGA_processing_enable_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_processing_enable_RW = attribute_wrapper(comms_annotation=["FPGA_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_scrap_R = attribute_wrapper(comms_annotation=["FPGA_scrap_R"], datatype=numpy.int32, dims=(8192,)) + FPGA_scrap_RW = attribute_wrapper(comms_annotation=["FPGA_scrap_RW"], datatype=numpy.int32, dims=(8192,), access=AttrWriteType.READ_WRITE) + FPGA_sdp_info_antenna_band_index_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_antenna_band_index_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_block_period_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_block_period_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_f_adc_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_f_adc_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_fsub_type_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_fsub_type_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_nyquist_sampling_zone_index_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_nyquist_sampling_zone_index_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_nyquist_sampling_zone_index_RW = attribute_wrapper(comms_annotation=["FPGA_sdp_info_nyquist_sampling_zone_index_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sdp_info_observation_id_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_observation_id_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_observation_id_RW = attribute_wrapper(comms_annotation=["FPGA_sdp_info_observation_id_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sdp_info_station_id_R = attribute_wrapper(comms_annotation=["FPGA_sdp_info_station_id_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_sdp_info_station_id_RW = attribute_wrapper(comms_annotation=["FPGA_sdp_info_station_id_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_subband_weights_R = attribute_wrapper(comms_annotation=["FPGA_subband_weights_R"], datatype=numpy.uint32, dims=(12 * 512, 16)) + FPGA_subband_weights_RW = attribute_wrapper(comms_annotation=["FPGA_subband_weights_RW"], datatype=numpy.uint32, dims=(12 * 512, 16), access=AttrWriteType.READ_WRITE) + FPGA_temp_R = attribute_wrapper(comms_annotation=["FPGA_temp_R"], datatype=numpy.float_, dims=(16,)) + FPGA_weights_R = attribute_wrapper(comms_annotation=["FPGA_weights_R"], datatype=numpy.int16, dims=(12 * 488 * 2, 16)) + FPGA_weights_RW = attribute_wrapper(comms_annotation=["FPGA_weights_RW"], datatype=numpy.int16, dims=(12 * 488 * 2, 16), access=AttrWriteType.READ_WRITE) + FPGA_wg_amplitude_R = attribute_wrapper(comms_annotation=["FPGA_wg_amplitude_R"], datatype=numpy.float_, dims=(12, 16)) + FPGA_wg_amplitude_RW = attribute_wrapper(comms_annotation=["FPGA_wg_amplitude_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE) + FPGA_wg_enable_R = attribute_wrapper(comms_annotation=["FPGA_wg_enable_R"], datatype=numpy.bool_, dims=(12, 16)) + FPGA_wg_enable_RW = attribute_wrapper(comms_annotation=["FPGA_wg_enable_RW"], datatype=numpy.bool_, dims=(12, 16), access=AttrWriteType.READ_WRITE) + FPGA_wg_frequency_R = attribute_wrapper(comms_annotation=["FPGA_wg_frequency_R"], datatype=numpy.float_, dims=(12, 16)) + FPGA_wg_frequency_RW = attribute_wrapper(comms_annotation=["FPGA_wg_frequency_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE) + FPGA_wg_phase_R = attribute_wrapper(comms_annotation=["FPGA_wg_phase_R"], datatype=numpy.float_, dims=(12, 16)) + FPGA_wg_phase_RW = attribute_wrapper(comms_annotation=["FPGA_wg_phase_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE) + TR_fpga_mask_R = attribute_wrapper(comms_annotation=["TR_fpga_mask_R"], datatype=numpy.bool_, dims=(16,)) + TR_fpga_mask_RW = attribute_wrapper(comms_annotation=["TR_fpga_mask_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + TR_fpga_communication_error_R = attribute_wrapper(comms_annotation=["TR_fpga_communication_error_R"], datatype=numpy.bool_, dims=(16,)) + TR_sdp_config_first_fpga_nr_R = attribute_wrapper(comms_annotation=["TR_sdp_config_first_fpga_nr_R"], datatype=numpy.uint32) + TR_sdp_config_nof_beamsets_R = attribute_wrapper(comms_annotation=["TR_sdp_config_nof_beamsets_R"], datatype=numpy.uint32) + TR_sdp_config_nof_fpgas_R = attribute_wrapper(comms_annotation=["TR_sdp_config_nof_fpgas_R"], datatype=numpy.uint32) + TR_software_version_R = attribute_wrapper(comms_annotation=["TR_software_version_R"], datatype=numpy.str) + TR_start_time_R = attribute_wrapper(comms_annotation=["TR_start_time_R"], datatype=numpy.int64) + TR_tod_R = attribute_wrapper(comms_annotation=["TR_tod_R"], datatype=numpy.int64, dims=(2,)) + TR_tod_pps_delta_R = attribute_wrapper(comms_annotation=["TR_tod_pps_delta_R"], datatype=numpy.double) + + S_pn = 12 # Number of ADC signal inputs per Processing Node (PN) FPGA. + N_pn = 16 # Number of FPGAs per antenna band that is controlled via the SC - SDP interface. + + # OPC-UA MP only points for AIT + FPGA_signal_input_mean_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_mean_R"], datatype=numpy.double , dims=(S_pn, N_pn)) + FPGA_signal_input_rms_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_rms_R"], datatype=numpy.double, dims=(S_pn, N_pn)) + + FPGA_jesd204b_csr_rbd_count_R = attribute_wrapper(comms_annotation=["FPGA_jesd204b_csr_rbd_count_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) + FPGA_jesd204b_csr_dev_syncn_R = attribute_wrapper(comms_annotation=["FPGA_jesd204b_csr_dev_syncn_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) + FPGA_jesd204b_rx_err0_R = attribute_wrapper(comms_annotation=["FPGA_jesd204b_rx_err0_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) + FPGA_jesd204b_rx_err1_R = attribute_wrapper(comms_annotation=["FPGA_jesd204b_rx_err1_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) + + FPGA_bsn_monitor_input_bsn_R = attribute_wrapper(comms_annotation=["FPGA_bsn_monitor_input_bsn_R"], datatype=numpy.int64, dims=(N_pn,)) + FPGA_bsn_monitor_input_nof_packets_R = attribute_wrapper(comms_annotation=["FPGA_bsn_monitor_input_nof_packets_R"], datatype=numpy.int32, dims=(N_pn,)) + FPGA_bsn_monitor_input_nof_valid_R = attribute_wrapper(comms_annotation=["FPGA_bsn_monitor_input_nof_valid_R"], datatype=numpy.int32, dims=(N_pn,)) + FPGA_bsn_monitor_input_nof_err_R = attribute_wrapper(comms_annotation=["FPGA_bsn_monitor_input_nof_err_R"], datatype=numpy.int32, dims=(N_pn,)) + + FPGA_signal_input_samples_delay_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_samples_delay_R"], datatype=numpy.uint32, dims=(S_pn, N_pn)) + FPGA_signal_input_samples_delay_RW = attribute_wrapper(comms_annotation=["FPGA_signal_input_samples_delay_RW"], datatype=numpy.uint32, dims=(S_pn, N_pn), access=AttrWriteType.READ_WRITE) + + + # -------- + # overloaded functions + # -------- + + # -------- + # Commands + # -------- + +# ---------- +# Run server +# ---------- +def main(**kwargs): + """Main function of the SDP module.""" + return entry(SDP, **kwargs) diff --git a/devices/devices/sdp/sst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py similarity index 66% rename from devices/devices/sdp/sst.py rename to tangostationcontrol/tangostationcontrol/devices/sdp/sst.py index 277714ab0b7ada6882a5ec1086690b3c29fb2382..18f000697b5351487ce4c75c0796e2cc81c28740 100644 --- a/devices/devices/sdp/sst.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py @@ -11,29 +11,24 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - # PyTango imports from tango.server import run from tango.server import device_property, attribute from tango import AttrWriteType # Additional import -from clients.attribute_wrapper import attribute_wrapper -from clients.statistics_client import StatisticsClient -from clients.opcua_client import OPCUAConnection -from devices.sdp.statistics import Statistics -from devices.sdp.statistics_collector import SSTCollector +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.clients.opcua_client import OPCUAConnection +from tangostationcontrol.clients.statistics_client import StatisticsClient +from tangostationcontrol.devices.sdp.statistics import Statistics +from tangostationcontrol.devices.sdp.statistics_collector import SSTCollector import numpy __all__ = ["SST", "main"] + class SST(Statistics): STATISTICS_COLLECTOR_CLASS = SSTCollector @@ -85,16 +80,16 @@ class SST(Statistics): # ---------- # FPGA control points for SSTs - FPGA_sst_offload_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sst_offload_enable_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_enable_R"], datatype=numpy.bool_, dims=(16,)) - FPGA_sst_offload_hdr_eth_destination_mac_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_eth_destination_mac_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sst_offload_hdr_eth_destination_mac_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_eth_destination_mac_R"], datatype=numpy.str, dims=(16,)) - FPGA_sst_offload_hdr_ip_destination_address_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_ip_destination_address_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sst_offload_hdr_ip_destination_address_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_ip_destination_address_R"], datatype=numpy.str, dims=(16,)) - FPGA_sst_offload_hdr_udp_destination_port_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sst_offload_hdr_udp_destination_port_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) - FPGA_sst_offload_weighted_subbands_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_weighted_subbands_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_sst_offload_weighted_subbands_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_sst_offload_weighted_subbands_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_sst_offload_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sst_offload_enable_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_enable_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_sst_offload_hdr_eth_destination_mac_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_hdr_eth_destination_mac_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sst_offload_hdr_eth_destination_mac_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_hdr_eth_destination_mac_R"], datatype=numpy.str, dims=(16,)) + FPGA_sst_offload_hdr_ip_destination_address_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_hdr_ip_destination_address_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sst_offload_hdr_ip_destination_address_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_hdr_ip_destination_address_R"], datatype=numpy.str, dims=(16,)) + FPGA_sst_offload_hdr_udp_destination_port_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sst_offload_hdr_udp_destination_port_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) + FPGA_sst_offload_weighted_subbands_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_weighted_subbands_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_sst_offload_weighted_subbands_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_sst_offload_weighted_subbands_R"], datatype=numpy.bool_, dims=(16,)) # number of packets with valid payloads nof_valid_payloads_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "nof_valid_payloads"}, dims=(SSTCollector.MAX_FPGAS,), datatype=numpy.uint64) @@ -120,14 +115,6 @@ class SST(Statistics): # ---------- # Run server # ---------- -def main(args=None, **kwargs): +def main(**kwargs): """Main function of the SST Device module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((SST,), args=args, **kwargs) - - -if __name__ == '__main__': - main() + return entry(SST, **kwargs) diff --git a/devices/devices/sdp/statistics.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py similarity index 90% rename from devices/devices/sdp/statistics.py rename to tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py index af1cf0201fd4dc244b8495730660b7c84398a518..4b03f2db7848cf37d1b2d8ccacfcf0ac81e928cc 100644 --- a/devices/devices/sdp/statistics.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py @@ -11,27 +11,20 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - from abc import ABCMeta, abstractmethod # PyTango imports from tango.server import device_property, attribute from tango import AttrWriteType + # Additional import import asyncio -from clients.statistics_client import StatisticsClient -from clients.attribute_wrapper import attribute_wrapper - -from devices.opcua_device import opcua_device +from tangostationcontrol.clients.statistics_client import StatisticsClient +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions -from common.lofar_logging import device_logging_to_python, log_exceptions import logging logger = logging.getLogger() @@ -142,7 +135,7 @@ class Statistics(opcua_device, metaclass=ABCMeta): except Exception as e: # use the pass function instead of setting read/write fails i.set_pass_func() - self.warn_stream("error while setting the sst attribute {} read/write function. {}. using pass function instead".format(i, e)) + logger.warning("error while setting the sst attribute {} read/write function. {}. using pass function instead".format(i, e)) await self.statistics_client.start() diff --git a/devices/devices/sdp/statistics_collector.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py similarity index 98% rename from devices/devices/sdp/statistics_collector.py rename to tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py index d9e5668b7e9b3db288a4b2360f4fa298594bbc1c..29503ca58ef25fcd3cb0b4ced4ff09ddaa62ecc6 100644 --- a/devices/devices/sdp/statistics_collector.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_collector.py @@ -4,8 +4,8 @@ import logging import numpy from .statistics_packet import SSTPacket, XSTPacket -from common.baselines import nr_baselines, baseline_index, baseline_from_index -from clients.statistics_client_thread import StatisticsClientThread +from tangostationcontrol.common.baselines import nr_baselines, baseline_index, baseline_from_index +from tangostationcontrol.clients.statistics_client_thread import StatisticsClientThread logger = logging.getLogger() @@ -184,6 +184,7 @@ class XSTCollector(StatisticsCollector): # process the packet self.parameters["nof_valid_payloads"][fields.gn_index] += numpy.uint64(1) + self.parameters["xst_blocks"][block_index][:fields.nof_statistics_per_packet] = fields.payload self.parameters["xst_timestamps"][block_index] = numpy.float64(fields.timestamp().timestamp()) self.parameters["xst_conjugated"][block_index] = conjugated diff --git a/devices/devices/sdp/statistics_packet.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_packet.py similarity index 99% rename from devices/devices/sdp/statistics_packet.py rename to tangostationcontrol/tangostationcontrol/devices/sdp/statistics_packet.py index 9bac227071dfbdec9ea0b0fd1fa63fa36176a8d9..c98ae9b5bdc604e8a55480cc5473e658b10cefa1 100644 --- a/devices/devices/sdp/statistics_packet.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics_packet.py @@ -1,6 +1,5 @@ import struct from datetime import datetime, timezone -from typing import Tuple import numpy __all__ = ["StatisticsPacket", "SSTPacket", "XSTPacket", "BSTPacket"] @@ -331,7 +330,7 @@ class BSTPacket(StatisticsPacket): return header -if __name__ == "__main__": +def main(args=None, **kwargs): # parse one packet from stdin import sys import pprint diff --git a/devices/devices/sdp/xst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py similarity index 69% rename from devices/devices/sdp/xst.py rename to tangostationcontrol/tangostationcontrol/devices/sdp/xst.py index c9883303b80425f0c142181994d43e477ec5431c..dcbda73c6570f6db966eaf5518e2129ecea41187 100644 --- a/devices/devices/sdp/xst.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py @@ -11,27 +11,19 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - # PyTango imports from tango.server import run from tango.server import device_property, attribute from tango import AttrWriteType -# Additional import -from clients.attribute_wrapper import attribute_wrapper -from clients.statistics_client import StatisticsClient -from clients.opcua_client import OPCUAConnection - -from common.lofar_logging import device_logging_to_python, log_exceptions +# Additional import +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.clients.opcua_client import OPCUAConnection +from tangostationcontrol.clients.statistics_client import StatisticsClient -from devices.sdp.statistics import Statistics -from devices.sdp.statistics_collector import XSTCollector +from tangostationcontrol.devices.sdp.statistics import Statistics +from tangostationcontrol.devices.sdp.statistics_collector import XSTCollector import numpy @@ -101,20 +93,20 @@ class XST(Statistics): # ---------- # FPGA control points for XSTs - FPGA_xst_integration_interval_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_integration_interval_RW"], datatype=numpy.double, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_xst_integration_interval_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_integration_interval_R"], datatype=numpy.double, dims=(16,)) - FPGA_xst_offload_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_xst_offload_enable_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_enable_R"], datatype=numpy.bool_, dims=(16,)) - FPGA_xst_offload_hdr_eth_destination_mac_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_hdr_eth_destination_mac_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_xst_offload_hdr_eth_destination_mac_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_hdr_eth_destination_mac_R"], datatype=numpy.str, dims=(16,)) - FPGA_xst_offload_hdr_ip_destination_address_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_hdr_ip_destination_address_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_xst_offload_hdr_ip_destination_address_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_hdr_ip_destination_address_R"], datatype=numpy.str, dims=(16,)) - FPGA_xst_offload_hdr_udp_destination_port_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_xst_offload_hdr_udp_destination_port_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) - FPGA_xst_processing_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) - FPGA_xst_processing_enable_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_processing_enable_R"], datatype=numpy.bool_, dims=(16,)) - FPGA_xst_subband_select_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_subband_select_RW"], datatype=numpy.uint32, dims=(8,16), access=AttrWriteType.READ_WRITE) - FPGA_xst_subband_select_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["2:FPGA_xst_subband_select_R"], datatype=numpy.uint32, dims=(8,16)) + FPGA_xst_integration_interval_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_integration_interval_RW"], datatype=numpy.double, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_integration_interval_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_integration_interval_R"], datatype=numpy.double, dims=(16,)) + FPGA_xst_offload_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_offload_enable_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_enable_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_xst_offload_hdr_eth_destination_mac_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_hdr_eth_destination_mac_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_offload_hdr_eth_destination_mac_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_hdr_eth_destination_mac_R"], datatype=numpy.str, dims=(16,)) + FPGA_xst_offload_hdr_ip_destination_address_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_hdr_ip_destination_address_RW"], datatype=numpy.str, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_offload_hdr_ip_destination_address_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_hdr_ip_destination_address_R"], datatype=numpy.str, dims=(16,)) + FPGA_xst_offload_hdr_udp_destination_port_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_offload_hdr_udp_destination_port_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) + FPGA_xst_processing_enable_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_processing_enable_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_processing_enable_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_xst_subband_select_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_subband_select_RW"], datatype=numpy.uint32, dims=(8,16), access=AttrWriteType.READ_WRITE) + FPGA_xst_subband_select_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_subband_select_R"], datatype=numpy.uint32, dims=(8,16)) # number of packets with valid payloads nof_valid_payloads_R = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "nof_valid_payloads"}, dims=(XSTCollector.MAX_FPGAS,), datatype=numpy.uint64) @@ -160,14 +152,6 @@ class XST(Statistics): # ---------- # Run server # ---------- -def main(args=None, **kwargs): +def main(**kwargs): """Main function of the XST Device module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((XST,), args=args, **kwargs) - - -if __name__ == '__main__': - main() + return entry(XST, **kwargs) diff --git a/devices/devices/unb2.py b/tangostationcontrol/tangostationcontrol/devices/unb2.py similarity index 71% rename from devices/devices/unb2.py rename to tangostationcontrol/tangostationcontrol/devices/unb2.py index bad1b1a324c9c838960d07cdfeb804b2789bbac6..c4f623c5df5846858dd8d0aa0ab5fd53dff56ac3 100644 --- a/devices/devices/unb2.py +++ b/tangostationcontrol/tangostationcontrol/devices/unb2.py @@ -11,22 +11,17 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports -from tango.server import run +from tango.server import run, command from tango.server import device_property, attribute -from tango import AttrWriteType +from tango import AttrWriteType, DebugIt, DevState # Additional import -from clients.attribute_wrapper import attribute_wrapper -from devices.opcua_device import opcua_device - -from common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.common.lofar_logging import device_logging_to_python, log_exceptions +from tangostationcontrol.devices.device_decorators import only_when_on import numpy @@ -64,42 +59,44 @@ class UNB2(opcua_device): 'UNB2_mask_RW' ] + UNB2TR_I2C_bus_DDR4_error_R = attribute_wrapper(comms_annotation=["UNB2TR_I2C_bus_DDR4_error_R"],datatype=numpy.int64 , dims=(4,2)) + UNB2TR_I2C_bus_error_R = attribute_wrapper(comms_annotation=["UNB2TR_I2C_bus_error_R" ],datatype=numpy.int64 , dims=(2,)) + UNB2TR_I2C_bus_FPGA_PS_error_R = attribute_wrapper(comms_annotation=["UNB2TR_I2C_bus_FPGA_PS_error_R"],datatype=numpy.int64 , dims=(4,2)) + UNB2TR_I2C_bus_PS_error_R = attribute_wrapper(comms_annotation=["UNB2TR_I2C_bus_PS_error_R" ],datatype=numpy.int64 , dims=(2,)) + UNB2TR_I2C_bus_QSFP_error_R = attribute_wrapper(comms_annotation=["UNB2TR_I2C_bus_QSFP_error_R"],datatype=numpy.int64 , dims=(24,2)) + UNB2TR_monitor_rate_RW = attribute_wrapper(comms_annotation=["UNB2TR_monitor_rate_RW" ],datatype=numpy.int64 , access=AttrWriteType.READ_WRITE) UNB2TR_translator_busy_R = attribute_wrapper(comms_annotation=["UNB2TR_translator_busy_R" ],datatype=numpy.bool_ ) UNB2_DC_DC_48V_12V_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_IOUT_R" ],datatype=numpy.float64, dims=(2,)) UNB2_DC_DC_48V_12V_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_TEMP_R" ],datatype=numpy.float64, dims=(2,)) UNB2_DC_DC_48V_12V_VIN_R = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_VIN_R" ],datatype=numpy.float64, dims=(2,)) UNB2_DC_DC_48V_12V_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_DC_DC_48V_12V_VOUT_R" ],datatype=numpy.float64, dims=(2,)) - UNB2_EEPROM_Serial_Number_R = attribute_wrapper(comms_annotation=["UNB2_EEPROM_Serial_Number_R"],datatype=numpy.str , dims=(2,)) - UNB2_EEPROM_Unique_ID_R = attribute_wrapper(comms_annotation=["UNB2_EEPROM_Unique_ID_R" ],datatype=numpy.int64 , dims=(2,)) - UNB2_FPGA_DDR4_SLOT_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_DDR4_SLOT_TEMP_R"],datatype=numpy.float64, dims=(16,)) - UNB2_FPGA_POL_CORE_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_IOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_CORE_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_TEMP_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_CORE_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_VOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_ERAM_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_IOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_ERAM_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_TEMP_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_ERAM_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_VOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_HGXB_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_IOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_HGXB_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_TEMP_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_HGXB_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_VOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_PGM_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_IOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_PGM_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_TEMP_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_PGM_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_VOUT_R" ],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_RXGXB_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_IOUT_R"],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_RXGXB_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_TEMP_R"],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_RXGXB_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_VOUT_R"],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_TXGXB_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_IOUT_R"],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_TXGXB_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_TEMP_R"],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_POL_TXGXB_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_VOUT_R"],datatype=numpy.float64, dims=(8,)) - UNB2_FPGA_QSFP_CAGE_LOS_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_QSFP_CAGE_LOS_R" ],datatype=numpy.int64 , dims=(48,)) - UNB2_FPGA_QSFP_CAGE_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_QSFP_CAGE_TEMP_R"],datatype=numpy.float64, dims=(48,)) - UNB2_Front_Panel_LED_R = attribute_wrapper(comms_annotation=["UNB2_Front_Panel_LED_R" ],datatype=numpy.int64 , dims=(2,)) - UNB2_Front_Panel_LED_RW = attribute_wrapper(comms_annotation=["UNB2_Front_Panel_LED_RW" ],datatype=numpy.int64 , dims=(2,), access=AttrWriteType.READ_WRITE) - UNB2_I2C_bus_DDR4_error_R = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_DDR4_error_R" ],datatype=numpy.int64 , dims=(8,)) - UNB2_I2C_bus_error_R = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_error_R" ],datatype=numpy.int64 , dims=(2,)) - UNB2_I2C_bus_FPGA_PS_error_R = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_FPGA_PS_error_R"],datatype=numpy.int64 , dims=(8,)) - UNB2_I2C_bus_PS_error_R = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_PS_error_R" ],datatype=numpy.int64 , dims=(2,)) - UNB2_I2C_bus_QSFP_error_R = attribute_wrapper(comms_annotation=["UNB2_I2C_bus_QSFP_error_R" ],datatype=numpy.int64 , dims=(48,)) + UNB2_FPGA_DDR4_SLOT_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_DDR4_SLOT_TEMP_R"],datatype=numpy.float64, dims=(8,2)) + UNB2_FPGA_POL_CORE_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_IOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_CORE_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_TEMP_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_CORE_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_CORE_VOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_ERAM_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_IOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_ERAM_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_TEMP_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_ERAM_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_ERAM_VOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_HGXB_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_IOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_HGXB_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_TEMP_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_HGXB_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_HGXB_VOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_PGM_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_IOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_PGM_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_TEMP_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_PGM_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_PGM_VOUT_R" ],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_RXGXB_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_IOUT_R"],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_RXGXB_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_TEMP_R"],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_RXGXB_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_RXGXB_VOUT_R"],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_TXGXB_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_IOUT_R"],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_TXGXB_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_TEMP_R"],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_POL_TXGXB_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_POL_TXGXB_VOUT_R"],datatype=numpy.float64, dims=(4,2)) + UNB2_FPGA_QSFP_CAGE_LOS_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_QSFP_CAGE_LOS_R" ],datatype=numpy.int64 , dims=(24,2)) + UNB2_FPGA_QSFP_CAGE_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_FPGA_QSFP_CAGE_TEMP_R"],datatype=numpy.float64, dims=(24,2)) + UNB2_Front_Panel_LED_colour_R = attribute_wrapper(comms_annotation=["UNB2_Front_Panel_LED_colour_R"],datatype=numpy.int64 , dims=(2,)) + UNB2_Front_Panel_LED_colour_RW = attribute_wrapper(comms_annotation=["UNB2_Front_Panel_LED_colour_RW"],datatype=numpy.int64 , dims=(2,), access=AttrWriteType.READ_WRITE) UNB2_mask_RW = attribute_wrapper(comms_annotation=["UNB2_mask_RW" ],datatype=numpy.bool_ , dims=(2,), access=AttrWriteType.READ_WRITE) + UNB2_PCB_ID_R = attribute_wrapper(comms_annotation=["UNB2_PCB_ID_R" ],datatype=numpy.int64 , dims=(2,)) + UNB2_PCB_number_R = attribute_wrapper(comms_annotation=["UNB2_PCB_number_R" ],datatype=numpy.str , dims=(2,)) + UNB2_PCB_version_R = attribute_wrapper(comms_annotation=["UNB2_PCB_version_R" ],datatype=numpy.str , dims=(2,)) UNB2_POL_CLOCK_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_POL_CLOCK_IOUT_R" ],datatype=numpy.float64, dims=(2,)) UNB2_POL_CLOCK_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_POL_CLOCK_TEMP_R" ],datatype=numpy.float64, dims=(2,)) UNB2_POL_CLOCK_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_POL_CLOCK_VOUT_R" ],datatype=numpy.float64, dims=(2,)) @@ -115,8 +112,7 @@ class UNB2(opcua_device): UNB2_POL_SWITCH_PHY_IOUT_R = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_PHY_IOUT_R"],datatype=numpy.float64, dims=(2,)) UNB2_POL_SWITCH_PHY_TEMP_R = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_PHY_TEMP_R"],datatype=numpy.float64, dims=(2,)) UNB2_POL_SWITCH_PHY_VOUT_R = attribute_wrapper(comms_annotation=["UNB2_POL_SWITCH_PHY_VOUT_R"],datatype=numpy.float64, dims=(2,)) - UNB2_PWR_off_R = attribute_wrapper(comms_annotation=["UNB2_PWR_off_R" ],datatype=numpy.bool_ , dims=(2,)) - UNB2_PWR_off_RW = attribute_wrapper(comms_annotation=["UNB2_PWR_off_RW" ],datatype=numpy.bool_ , dims=(2,), access=AttrWriteType.READ_WRITE) + UNB2_PWR_on_R = attribute_wrapper(comms_annotation=["UNB2_PWR_on_R" ],datatype=numpy.bool_ , dims=(2,)) # -------- # overloaded functions @@ -126,18 +122,29 @@ class UNB2(opcua_device): # Commands # -------- + @command() + @DebugIt() + @only_when_on() + def UNB2_off(self): + """ + + :return:None + """ + self.opcua_connection.call_method(["UNB2_off"]) + + @command() + @DebugIt() + @only_when_on() + def UNB2_on(self): + """ + + :return:None + """ + self.opcua_connection.call_method(["UNB2_on"]) + # ---------- # Run server # ---------- def main(args=None, **kwargs): """Main function of the UNB2 module.""" - - from common.lofar_logging import configure_logger - configure_logger() - - return run((UNB2,), args=args, **kwargs) - - -if __name__ == '__main__': - main() - + return entry(UNB2, **kwargs) diff --git a/devices/examples/HW_device_template.py b/tangostationcontrol/tangostationcontrol/examples/HW_device_template.py similarity index 79% rename from devices/examples/HW_device_template.py rename to tangostationcontrol/tangostationcontrol/examples/HW_device_template.py index 6059733023c5ee8448369a706ea2be5c8fa6b840..f7994ec1fea9892a3ae2ab44b57ff87a2b2f1958 100644 --- a/devices/examples/HW_device_template.py +++ b/tangostationcontrol/tangostationcontrol/examples/HW_device_template.py @@ -9,27 +9,21 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -sys.path.append(parentdir) - # PyTango imports from tango.server import run -from tango import AttrWriteType # Additional import -from clients.attribute_wrapper import attribute_wrapper -from devices.hardware_device import hardware_device +from tangostationcontrol.devices.lofar_device import lofar_device +import logging +logger = logging.getLogger() __all__ = ["HW_dev"] -class HW_dev(hardware_device): +class HW_dev(lofar_device): """ - This class is the minimal (read empty) implementation of a class using 'hardware_device' + This class is the minimal (read empty) implementation of a class using 'lofar_device' """ # ---------- @@ -54,10 +48,10 @@ class HW_dev(hardware_device): init_device method to be released. This method is called by the device destructor and by the device Init command (a Tango built-in). """ - self.debug_stream("Shutting down...") + logger.debug("Shutting down...") self.Off() - self.debug_stream("Shut down. Good bye.") + logger.debug("Shut down. Good bye.") # -------- # overloaded functions @@ -90,7 +84,3 @@ class HW_dev(hardware_device): def main(args=None, **kwargs): """Main function of the hardware device module.""" return run((HW_dev,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/devices/integration_test/client/__init__.py b/tangostationcontrol/tangostationcontrol/examples/__init__.py similarity index 100% rename from devices/integration_test/client/__init__.py rename to tangostationcontrol/tangostationcontrol/examples/__init__.py diff --git a/devices/integration_test/devices/__init__.py b/tangostationcontrol/tangostationcontrol/examples/load_from_disk/__init__.py similarity index 100% rename from devices/integration_test/devices/__init__.py rename to tangostationcontrol/tangostationcontrol/examples/load_from_disk/__init__.py diff --git a/devices/examples/load_from_disk/ini_client.py b/tangostationcontrol/tangostationcontrol/examples/load_from_disk/ini_client.py similarity index 94% rename from devices/examples/load_from_disk/ini_client.py rename to tangostationcontrol/tangostationcontrol/examples/load_from_disk/ini_client.py index cd227f23458c672c08b3acf08ba65fa9a48b581d..e5fbf03711fe220cfa56fa9327cbede7168b4e86 100644 --- a/devices/examples/load_from_disk/ini_client.py +++ b/tangostationcontrol/tangostationcontrol/examples/load_from_disk/ini_client.py @@ -1,7 +1,10 @@ -from clients.comms_client import CommClient +from tangostationcontrol.clients.comms_client import CommClient import configparser import numpy +import logging +logger = logging.getLogger() + __all__ = ["ini_client"] @@ -39,14 +42,14 @@ class ini_client(CommClient): def start(self): super().start() - def __init__(self, filename, fault_func, streams, try_interval=2): + def __init__(self, filename, fault_func, try_interval=2): """ initialises the class and tries to connect to the client. """ self.config = configparser.ConfigParser() self.filename = filename - super().__init__(fault_func, streams, try_interval) + super().__init__(fault_func, try_interval) # Explicitly connect if not self.connect(): @@ -62,7 +65,7 @@ class ini_client(CommClient): def disconnect(self): self.connected = False # always force a reconnect, regardless of a successful disconnect - self.streams.debug_stream("disconnected from the 'client' ") + logger.debug("disconnected from the 'client' ") def _setup_annotation(self, annotation): """ @@ -81,7 +84,7 @@ class ini_client(CommClient): """ # as this is an example, just print the annotation - self.streams.debug_stream("annotation: {}".format(annotation)) + logger.debug("annotation: {}".format(annotation)) name = annotation.get('name') if name is None: ValueError("ini client requires a variable `name` in the annotation to set/get") diff --git a/devices/examples/load_from_disk/ini_device.py b/tangostationcontrol/tangostationcontrol/examples/load_from_disk/ini_device.py similarity index 91% rename from devices/examples/load_from_disk/ini_device.py rename to tangostationcontrol/tangostationcontrol/examples/load_from_disk/ini_device.py index 07b2f419ab6b4cd5d78eb84a66c3906e169da99d..032c9b01b2a5447111d6245ffcba1bd610b3b655 100644 --- a/devices/examples/load_from_disk/ini_device.py +++ b/tangostationcontrol/tangostationcontrol/examples/load_from_disk/ini_device.py @@ -9,25 +9,20 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - # PyTango imports from tango.server import run from tango import AttrWriteType -# Additional import -from clients.attribute_wrapper import attribute_wrapper -from devices.hardware_device import hardware_device - import configparser import numpy -from ini_client import * +# Additional import +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.lofar_device import lofar_device +from tangostationcontrol.examples.load_from_disk.ini_client import * + +import logging +logger = logging.getLogger() __all__ = ["ini_device"] @@ -59,9 +54,9 @@ def write_ini_file(filename): -class ini_device(hardware_device): +class ini_device(lofar_device): """ - This class is the minimal (read empty) implementation of a class using 'hardware_device' + This class is the minimal (read empty) implementation of a class using 'lofar_device' """ # ---------- @@ -119,7 +114,7 @@ class ini_device(hardware_device): # use the pass function instead of setting read/write fails i.set_pass_func() - self.warn_stream("error while setting the ini attribute {} read/write function. {}".format(i, e)) + logger.warning("error while setting the ini attribute {} read/write function. {}".format(i, e)) self.ini_client.start() @@ -130,10 +125,5 @@ class ini_device(hardware_device): def main(args=None, **kwargs): write_ini_file("example.ini") - """Main function of the hardware device module.""" return run((ini_device,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/devices/test/__init__.py b/tangostationcontrol/tangostationcontrol/examples/snmp/__init__.py similarity index 100% rename from devices/test/__init__.py rename to tangostationcontrol/tangostationcontrol/examples/snmp/__init__.py diff --git a/devices/examples/snmp/snmp.py b/tangostationcontrol/tangostationcontrol/examples/snmp/snmp.py similarity index 81% rename from devices/examples/snmp/snmp.py rename to tangostationcontrol/tangostationcontrol/examples/snmp/snmp.py index 2a912ce1443bbd8e83b662d4ed9764627d947943..3c962da9911abf9a0b9cbb4d7ecd4ff19c6e95d5 100644 --- a/devices/examples/snmp/snmp.py +++ b/tangostationcontrol/tangostationcontrol/examples/snmp/snmp.py @@ -11,29 +11,25 @@ """ -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - # PyTango imports from tango.server import run from tango.server import device_property from tango import AttrWriteType # Additional import -from examples.snmp.snmp_client import SNMP_client -from clients.attribute_wrapper import attribute_wrapper -from devices.hardware_device import hardware_device +from tangostationcontrol.examples.snmp.snmp_client import SNMP_client +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper +from tangostationcontrol.devices.lofar_device import lofar_device import numpy +import logging +logger = logging.getLogger() + __all__ = ["SNMP", "main"] -class SNMP(hardware_device): +class SNMP(lofar_device): """ **Properties:** @@ -102,7 +98,7 @@ class SNMP(hardware_device): except Exception as e: # use the pass function instead of setting read/write fails i.set_pass_func() - self.warn_stream("error while setting the SNMP attribute {} read/write function. {}".format(i, e)) + logger.warning("error while setting the SNMP attribute {} read/write function. {}".format(i, e)) self.snmp_manager.start() @@ -118,12 +114,7 @@ class SNMP(hardware_device): def main(args=None, **kwargs): """Main function of the module.""" - from common.lofar_logging import configure_logger - import logging - configure_logger(logging.getLogger()) + from tangostationcontrol.common.lofar_logging import configure_logger + configure_logger() return run((SNMP,), args=args, **kwargs) - - -if __name__ == '__main__': - main() diff --git a/devices/examples/snmp/snmp_client.py b/tangostationcontrol/tangostationcontrol/examples/snmp/snmp_client.py similarity index 93% rename from devices/examples/snmp/snmp_client.py rename to tangostationcontrol/tangostationcontrol/examples/snmp/snmp_client.py index 96ac67140b9bdbdba7ab4d4fb8651b5e9674c219..7c18baa9a6954e03ab07eb85fe35b6e342867650 100644 --- a/devices/examples/snmp/snmp_client.py +++ b/tangostationcontrol/tangostationcontrol/examples/snmp/snmp_client.py @@ -1,10 +1,12 @@ -from clients.comms_client import CommClient +from tangostationcontrol.clients.comms_client import CommClient import snmp import numpy -import traceback +import logging + +logger = logging.getLogger() __all__ = ["SNMP_client"] @@ -38,11 +40,11 @@ class SNMP_client(CommClient): def start(self): super().start() - def __init__(self, community, host, timeout, fault_func, streams, try_interval=2): + def __init__(self, community, host, timeout, fault_func, try_interval=2): """ Create the SNMP and connect() to it """ - super().__init__(fault_func, streams, try_interval) + super().__init__(fault_func, try_interval) self.community = community self.host = host @@ -58,7 +60,7 @@ class SNMP_client(CommClient): """ Try to connect to the client """ - self.streams.debug_stream("Connecting to community: %s, host: %s", self.community, self.host) + logger.debug("Connecting to community: %s, host: %s", self.community, self.host) self.connected = True return True diff --git a/devices/integration_test/README.md b/tangostationcontrol/tangostationcontrol/integration_test/README.md similarity index 100% rename from devices/integration_test/README.md rename to tangostationcontrol/tangostationcontrol/integration_test/README.md diff --git a/devices/test/clients/__init__.py b/tangostationcontrol/tangostationcontrol/integration_test/__init__.py similarity index 100% rename from devices/test/clients/__init__.py rename to tangostationcontrol/tangostationcontrol/integration_test/__init__.py diff --git a/devices/integration_test/base.py b/tangostationcontrol/tangostationcontrol/integration_test/base.py similarity index 92% rename from devices/integration_test/base.py rename to tangostationcontrol/tangostationcontrol/integration_test/base.py index 241f0ecd409fd16484d81e31f1e1f83dc1b9d81b..ed1eb2239af74251e22b42adf8ea5e2596688076 100644 --- a/devices/integration_test/base.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/base.py @@ -7,7 +7,7 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -from common.lofar_logging import configure_logger +from tangostationcontrol.common.lofar_logging import configure_logger import unittest import asynctest diff --git a/devices/test/common/__init__.py b/tangostationcontrol/tangostationcontrol/integration_test/client/__init__.py similarity index 100% rename from devices/test/common/__init__.py rename to tangostationcontrol/tangostationcontrol/integration_test/client/__init__.py diff --git a/tangostationcontrol/tangostationcontrol/integration_test/client/test_opcua_client_against_server.py b/tangostationcontrol/tangostationcontrol/integration_test/client/test_opcua_client_against_server.py new file mode 100644 index 0000000000000000000000000000000000000000..bdd4e43b94b1a98596f339e220ee31116818fc37 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/integration_test/client/test_opcua_client_against_server.py @@ -0,0 +1,163 @@ +import asyncua +import numpy + +from tangostationcontrol.clients.opcua_client import OPCUAConnection + +from tangostationcontrol.integration_test import base + + +class TestClientServer(base.IntegrationAsyncTestCase): + """ Test the OPCUAConnection against an OPCUA server we instantiate ourselves. """ + + async def setup_server(self, port): + """ Setup a server on a dedicated port for the test, to allow + the tests to be run in parallel. """ + + # where we will run the server + self.endpoint = f"opc.tcp://127.0.0.1:{port}" + self.namespace = "http://example.com" + + # setup an OPC-UA server + self.server = asyncua.Server() + await self.server.init() + self.server.set_endpoint(self.endpoint) + self.server.set_server_name(f"Test server spawned by {__file__}") + + # create an interface + idx = await self.server.register_namespace(self.namespace) + obj = self.server.get_objects_node() + + # add double_R/double_RW + double_R = await obj.add_variable(idx, "double_R", 42.0) + double_RW = await obj.add_variable(idx, "double_RW", 42.0) + await double_RW.set_writable() + + # add methods + @asyncua.uamethod + def multiply(parent, x, y): + self.assertEqual(float, type(x)) + self.assertEqual(int, type(y)) + return x * y + + @asyncua.uamethod + def procedure(parent): + return + + @asyncua.uamethod + def throws(parent): + raise Exception("Expected test exception") + + multiply_method = await obj.add_method(idx, "multiply", multiply, [asyncua.ua.VariantType.Double, asyncua.ua.VariantType.Int64], [asyncua.ua.VariantType.Double]) + procedure_method = await obj.add_method(idx, "procedure", procedure, [], []) + throws_method = await obj.add_method(idx, "throws", throws, [], []) + + # run the server + await self.server.start() + + async def setUp(self): + self.server = None + + async def tearDown(self): + if self.server: + await self.server.stop() + + def fault_func(self): + raise Exception("FAULT") + + async def test_opcua_connection(self): + await self.setup_server(14840) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + finally: + await test_client.stop() + + async def test_read_attribute(self): + await self.setup_server(14841) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + + # setup the attribute + class attribute(object): + dim_x = 1 + dim_y = 0 + numpy_type = numpy.double + + prot_attr = await test_client.setup_protocol_attribute(["double_R"], attribute()) + + # read it from the server + self.assertEqual(42.0, await prot_attr.read_function()) + finally: + await test_client.stop() + + async def test_write_attribute(self): + await self.setup_server(14842) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + + # setup the attribute + class attribute(object): + dim_x = 1 + dim_y = 0 + numpy_type = numpy.double + + prot_attr = await test_client.setup_protocol_attribute(["double_RW"], attribute()) + + # write it to the server and read it back to verify + await prot_attr.write_function(123.0) + + self.assertEqual(123.0, await prot_attr.read_function()) + finally: + await test_client.stop() + + async def test_method_without_args(self): + await self.setup_server(14843) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + + self.assertEqual(None, await test_client._call_method(["procedure"])) + finally: + await test_client.stop() + + async def test_method_with_args(self): + await self.setup_server(14843) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + + self.assertEqual(21.0, await test_client._call_method(["multiply"], numpy.double(3.0), numpy.int64(7))) + finally: + await test_client.stop() + + async def test_method_with_wrong_arg_types(self): + await self.setup_server(14844) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + + with self.assertRaises(Exception): + # correct signature is multiply(double,int64) + _ = await test_client._call_method(["multiply"], numpy.double(3.0), numpy.double(7)) + finally: + await test_client.stop() + + async def test_errorring_method(self): + await self.setup_server(14845) + + test_client = OPCUAConnection(self.endpoint, self.namespace, 5, self.fault_func, self.loop) + try: + await test_client.start() + + with self.assertRaises(Exception): + await test_client._call_method(["throws"]) + finally: + await test_client.stop() diff --git a/devices/integration_test/client/test_sdptr_sim.py b/tangostationcontrol/tangostationcontrol/integration_test/client/test_sdptr_sim.py similarity index 92% rename from devices/integration_test/client/test_sdptr_sim.py rename to tangostationcontrol/tangostationcontrol/integration_test/client/test_sdptr_sim.py index ab9288b727e515c19b07c99d1fe8a233d7032055..a09f407e2982d7b873021f03b1eb9e78fe336e44 100644 --- a/devices/integration_test/client/test_sdptr_sim.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/client/test_sdptr_sim.py @@ -9,7 +9,7 @@ from asyncua import Client -from integration_test import base +from tangostationcontrol.integration_test import base class TestSDPTRSim(base.IntegrationAsyncTestCase): diff --git a/devices/integration_test/client/test_tcp_replicator.py b/tangostationcontrol/tangostationcontrol/integration_test/client/test_tcp_replicator.py similarity index 97% rename from devices/integration_test/client/test_tcp_replicator.py rename to tangostationcontrol/tangostationcontrol/integration_test/client/test_tcp_replicator.py index ca45c4c52ab7f5e379c484b964a05225950fc9e1..2467fd6dd8a7b24cc786c5b2cc10a25a610b88f1 100644 --- a/devices/integration_test/client/test_tcp_replicator.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/client/test_tcp_replicator.py @@ -7,18 +7,16 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -from asyncio import Queue - import logging import time import socket import sys -from clients.tcp_replicator import TCPReplicator +import timeout_decorator -from integration_test import base +from tangostationcontrol.clients.tcp_replicator import TCPReplicator -import timeout_decorator +from tangostationcontrol.integration_test import base logger = logging.getLogger() diff --git a/devices/integration_test/client/test_unb2_sim.py b/tangostationcontrol/tangostationcontrol/integration_test/client/test_unb2_sim.py similarity index 92% rename from devices/integration_test/client/test_unb2_sim.py rename to tangostationcontrol/tangostationcontrol/integration_test/client/test_unb2_sim.py index d934c06fb6dfb40dad1c8b54dc00a00715deedc8..261441901c589a26256b586dc571f7b063c08408 100644 --- a/devices/integration_test/client/test_unb2_sim.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/client/test_unb2_sim.py @@ -9,7 +9,7 @@ from asyncua import Client -from integration_test import base +from tangostationcontrol.integration_test import base class TestUNB2Sim(base.IntegrationAsyncTestCase): diff --git a/tangostationcontrol/tangostationcontrol/integration_test/device_proxy.py b/tangostationcontrol/tangostationcontrol/integration_test/device_proxy.py new file mode 100644 index 0000000000000000000000000000000000000000..00ba0904c7bd01fa2ce1453a4c6701d6a4246e14 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/integration_test/device_proxy.py @@ -0,0 +1,8 @@ +from tango import DeviceProxy + + +class TestDeviceProxy(DeviceProxy): + + def __init__(self, *args, **kwargs): + super(TestDeviceProxy, self).__init__(*args, **kwargs) + self.set_timeout_millis(10000) diff --git a/devices/test/devices/__init__.py b/tangostationcontrol/tangostationcontrol/integration_test/devices/__init__.py similarity index 100% rename from devices/test/devices/__init__.py rename to tangostationcontrol/tangostationcontrol/integration_test/devices/__init__.py diff --git a/devices/integration_test/devices/test_device_recv.py b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_recv.py similarity index 75% rename from devices/integration_test/devices/test_device_recv.py rename to tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_recv.py index 3a010a000c03d3c039f8f93a68c0f6437bc30db1..6d9353936537a116442409b9ce7c343fa4d803b1 100644 --- a/devices/integration_test/devices/test_device_recv.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_recv.py @@ -7,12 +7,10 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -import time - -from tango import DeviceProxy from tango._tango import DevState -from integration_test import base +from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy +from tangostationcontrol.integration_test import base class TestDeviceRECV(base.IntegrationTestCase): @@ -22,7 +20,7 @@ class TestDeviceRECV(base.IntegrationTestCase): def tearDown(self): """Turn device Off in teardown to prevent blocking tests""" - d = DeviceProxy("LTS/RECV/1") + d = TestDeviceProxy("STAT/RECV/1") try: d.Off() @@ -33,25 +31,25 @@ class TestDeviceRECV(base.IntegrationTestCase): def test_device_proxy_recv(self): """Test if we can successfully create a DeviceProxy and fetch state""" - d = DeviceProxy("LTS/RECV/1") + d = TestDeviceProxy("STAT/RECV/1") self.assertEqual(DevState.OFF, d.state()) def test_device_recv_initialize(self): """Test if we can transition to standby""" - d = DeviceProxy("LTS/RECV/1") + d = TestDeviceProxy("STAT/RECV/1") - d.initialise() + d.Initialise() self.assertEqual(DevState.STANDBY, d.state()) def test_device_recv_on(self): """Test if we can transition to on""" - d = DeviceProxy("LTS/RECV/1") + d = TestDeviceProxy("STAT/RECV/1") - d.initialise() + d.Initialise() d.on() diff --git a/devices/integration_test/devices/test_device_sdp.py b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_sdp.py similarity index 71% rename from devices/integration_test/devices/test_device_sdp.py rename to tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_sdp.py index 5f064128f858e0bd2c44768a4f13057e5dc20266..f12fc0ae4f9094c6c82a2dd9076f49cea7fd7ef1 100644 --- a/devices/integration_test/devices/test_device_sdp.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_sdp.py @@ -7,12 +7,11 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -import time - from tango import DeviceProxy from tango._tango import DevState -from integration_test import base +from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy +from tangostationcontrol.integration_test import base class TestDeviceSDP(base.IntegrationTestCase): @@ -23,7 +22,7 @@ class TestDeviceSDP(base.IntegrationTestCase): def tearDown(self): """Turn device Off in teardown to prevent blocking tests""" - d = DeviceProxy("LTS/SDP/1") + d = TestDeviceProxy("STAT/SDP/1") try: d.Off() @@ -34,25 +33,32 @@ class TestDeviceSDP(base.IntegrationTestCase): def test_device_proxy_sdp(self): """Test if we can successfully create a DeviceProxy and fetch state""" - d = DeviceProxy("LTS/SDP/1") + d = TestDeviceProxy("STAT/SDP/1") self.assertEqual(DevState.OFF, d.state()) + def test_device_sdp_ping(self): + """Test if we can successfully ping the device server""" + + d = TestDeviceProxy("STAT/SDP/1") + + self.assertGreater(d.ping(), 0) + def test_device_sdp_initialize(self): """Test if we can transition to standby""" - d = DeviceProxy("LTS/SDP/1") + d = TestDeviceProxy("STAT/SDP/1") - d.initialise() + d.Initialise() self.assertEqual(DevState.STANDBY, d.state()) def test_device_sdp_on(self): """Test if we can transition to on""" - d = DeviceProxy("LTS/SDP/1") + d = TestDeviceProxy("STAT/SDP/1") - d.initialise() + d.Initialise() d.on() @@ -61,7 +67,7 @@ class TestDeviceSDP(base.IntegrationTestCase): def test_device_sdp_read_attribute(self): """Test if we can read an attribute obtained over OPC-UA""" - d = DeviceProxy("LTS/SDP/1") + d = TestDeviceProxy("STAT/SDP/1") d.initialise() diff --git a/devices/integration_test/devices/test_device_sst.py b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_sst.py similarity index 89% rename from devices/integration_test/devices/test_device_sst.py rename to tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_sst.py index a6b71d328305f2dafed46f9e4f3ea9209df9601d..210dc93defc98c51f9fb9a2b0497a52e5547e5a7 100644 --- a/devices/integration_test/devices/test_device_sst.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_sst.py @@ -10,10 +10,10 @@ import socket import sys import time -from tango import DeviceProxy from tango._tango import DevState -from integration_test import base +from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy +from tangostationcontrol.integration_test import base class TestDeviceSST(base.IntegrationTestCase): @@ -24,7 +24,7 @@ class TestDeviceSST(base.IntegrationTestCase): def tearDown(self): """Turn device Off in teardown to prevent blocking tests""" - d = DeviceProxy("LTS/SST/1") + d = TestDeviceProxy("STAT/SST/1") try: d.Off() @@ -35,14 +35,14 @@ class TestDeviceSST(base.IntegrationTestCase): def test_device_proxy_sst(self): """Test if we can successfully create a DeviceProxy and fetch state""" - d = DeviceProxy("LTS/SST/1") + d = TestDeviceProxy("STAT/SST/1") self.assertEqual(DevState.OFF, d.state()) def test_device_sst_initialize(self): """Test if we can transition to standby""" - d = DeviceProxy("LTS/SST/1") + d = TestDeviceProxy("STAT/SST/1") d.initialise() @@ -53,7 +53,7 @@ class TestDeviceSST(base.IntegrationTestCase): port_property = {"Statistics_Client_TCP_Port": "4999"} - d = DeviceProxy("LTS/SST/1") + d = TestDeviceProxy("STAT/SST/1") self.assertEqual(DevState.OFF, d.state(), "Prerequisite could not be met " @@ -72,7 +72,7 @@ class TestDeviceSST(base.IntegrationTestCase): def test_device_sst_send_udp(self): port_property = {"Statistics_Client_TCP_Port": "4998"} - d = DeviceProxy("LTS/SST/1") + d = TestDeviceProxy("STAT/SST/1") self.assertEqual(DevState.OFF, d.state(), "Prerequisite could not be met " @@ -101,7 +101,7 @@ class TestDeviceSST(base.IntegrationTestCase): m_data = "Hello World!".encode("UTF-8") - d = DeviceProxy("LTS/SST/1") + d = TestDeviceProxy("STAT/SST/1") self.assertEqual(DevState.OFF, d.state(), "Prerequisite could not be met " diff --git a/devices/integration_test/devices/test_device_unb2.py b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_unb2.py similarity index 79% rename from devices/integration_test/devices/test_device_unb2.py rename to tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_unb2.py index d796e586cd5165b0e3fb7cd09c1c3acf5cdd747c..4a0382f2aea7c370562ff4d23e37c85c7963a436 100644 --- a/devices/integration_test/devices/test_device_unb2.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_device_unb2.py @@ -7,12 +7,10 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -import time - -from tango import DeviceProxy from tango._tango import DevState -from integration_test import base +from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy +from tangostationcontrol.integration_test import base class TestDeviceUNB2(base.IntegrationTestCase): @@ -23,7 +21,7 @@ class TestDeviceUNB2(base.IntegrationTestCase): def tearDown(self): """Turn device Off in teardown to prevent blocking tests""" - d = DeviceProxy("LTS/UNB2/1") + d = TestDeviceProxy("STAT/UNB2/1") try: d.Off() @@ -34,14 +32,14 @@ class TestDeviceUNB2(base.IntegrationTestCase): def test_device_proxy_unb2(self): """Test if we can successfully create a DeviceProxy and fetch state""" - d = DeviceProxy("LTS/UNB2/1") + d = TestDeviceProxy("STAT/UNB2/1") self.assertEqual(DevState.OFF, d.state()) def test_device_unb2_initialize(self): """Test if we can transition to standby""" - d = DeviceProxy("LTS/UNB2/1") + d = TestDeviceProxy("STAT/UNB2/1") d.initialise() @@ -50,7 +48,7 @@ class TestDeviceUNB2(base.IntegrationTestCase): def test_device_unb2_on(self): """Test if we can transition to on""" - d = DeviceProxy("LTS/UNB2/1") + d = TestDeviceProxy("STAT/UNB2/1") d.initialise() diff --git a/tangostationcontrol/tangostationcontrol/integration_test/devices/test_tango_database.py b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_tango_database.py new file mode 100644 index 0000000000000000000000000000000000000000..b14cc363f24b3ea8e77ecd59e1184500fe40e0d4 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/integration_test/devices/test_tango_database.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# +# This file is part of the LOFAR 2.0 Station Software +# +# +# +# Distributed under the terms of the APACHE license. +# See LICENSE.txt for more info. + +import time + +from tango import Database +from tango._tango import DevState + +from tangostationcontrol.integration_test import base + + +class TestTangoDatabase(base.IntegrationTestCase): + + def setUp(self): + """Intentionally recreate the device object in each test""" + super(TestTangoDatabase, self).setUp() + + def test_database_servers(self): + """Connect to the database and find at least 3 servers + + One for SDP, RECV and the databaseds itself. + """ + + d = Database() + + # Ensure this value is close to actual amount of servers defined by + # integration_ConfigDb.json + self.assertGreater(len(d.get_server_list()), 16, msg=f"Servers: {d.get_server_list()}") diff --git a/devices/statistics_writer/README.md b/tangostationcontrol/tangostationcontrol/statistics_writer/README.md similarity index 100% rename from devices/statistics_writer/README.md rename to tangostationcontrol/tangostationcontrol/statistics_writer/README.md diff --git a/devices/statistics_writer/SST_2021-10-04-07-36-52.h5 b/tangostationcontrol/tangostationcontrol/statistics_writer/SST_2021-10-04-07-36-52.h5 similarity index 100% rename from devices/statistics_writer/SST_2021-10-04-07-36-52.h5 rename to tangostationcontrol/tangostationcontrol/statistics_writer/SST_2021-10-04-07-36-52.h5 diff --git a/tangostationcontrol/tangostationcontrol/statistics_writer/__init__.py b/tangostationcontrol/tangostationcontrol/statistics_writer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/statistics_writer/hdf5_writer.py b/tangostationcontrol/tangostationcontrol/statistics_writer/hdf5_writer.py similarity index 98% rename from devices/statistics_writer/hdf5_writer.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/hdf5_writer.py index 6715dd870608a0202610ea52c417695844f0d1c9..eb7fa643bd9c8d74b1e946f468532c4852ecaba5 100644 --- a/devices/statistics_writer/hdf5_writer.py +++ b/tangostationcontrol/tangostationcontrol/statistics_writer/hdf5_writer.py @@ -11,8 +11,8 @@ import logging # import statistics classes with workaround import sys sys.path.append("..") -from devices.sdp.statistics_packet import SSTPacket, XSTPacket, BSTPacket, StatisticsPacket -import devices.sdp.statistics_collector as statistics_collector +from tangostationcontrol.devices.sdp.statistics_packet import SSTPacket, XSTPacket, BSTPacket, StatisticsPacket +import tangostationcontrol.devices.sdp.statistics_collector as statistics_collector logger = logging.getLogger("statistics_writer") diff --git a/devices/statistics_writer/receiver.py b/tangostationcontrol/tangostationcontrol/statistics_writer/receiver.py similarity index 96% rename from devices/statistics_writer/receiver.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/receiver.py index 92d0d6d34bfc69f8f89f306c86b906c68956e47b..cd6c0af4cd5d4a1f8cdc3c2e37d86f6bd655db53 100644 --- a/devices/statistics_writer/receiver.py +++ b/tangostationcontrol/tangostationcontrol/statistics_writer/receiver.py @@ -2,7 +2,7 @@ import socket import sys sys.path.append("..") -from devices.sdp.statistics_packet import StatisticsPacket +from tangostationcontrol.devices.sdp.statistics_packet import StatisticsPacket import os class receiver: diff --git a/devices/statistics_writer/statistics_reader.py b/tangostationcontrol/tangostationcontrol/statistics_writer/statistics_reader.py similarity index 93% rename from devices/statistics_writer/statistics_reader.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/statistics_reader.py index f0906e7d4122b2f1d0d8d864d8c6a47ad793c0f4..67ff6377cdf90326d7a9fa33a015c1ac5861064d 100644 --- a/devices/statistics_writer/statistics_reader.py +++ b/tangostationcontrol/tangostationcontrol/statistics_writer/statistics_reader.py @@ -5,16 +5,9 @@ import argparse import os import psutil import pytz -import time process = psutil.Process(os.getpid()) -parser = argparse.ArgumentParser(description='Select a file to explore') -parser.add_argument('--files', type=str, nargs="+", help='the name and path of the files, takes one or more files') -parser.add_argument('--start_time', type=str, help='lowest timestamp to process (uses isoformat, ex: 2021-10-04T07:50:08.937+00:00)') -parser.add_argument('--end_time', type=str, help='highest timestamp to process (uses isoformat, ex: 2021-10-04T07:50:08.937+00:00)') - - import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger("hdf5_explorer") @@ -219,7 +212,20 @@ class statistics_data: self.values = numpy.array(file.get(f"{group_key}/values")) -if __name__ == "__main__": +def main(): + parser = argparse.ArgumentParser(description='Select a file to explore') + parser.add_argument( + '--files', type=str, nargs="+", required=True, + help='the name and path of the files, takes one or more files') + parser.add_argument( + '--start_time', type=str, required=True, + help='lowest timestamp to process (uses isoformat, ex: 2021-10-04T07:50' + ':08.937+00:00)') + parser.add_argument( + '--end_time', type=str, required=True, + help='highest timestamp to process (usesisoformat, ex: 2021-10-04T07:50' + ':08.937+00:00)') + args = parser.parse_args() files = args.files end_time = args.end_time diff --git a/devices/statistics_writer/statistics_writer.py b/tangostationcontrol/tangostationcontrol/statistics_writer/statistics_writer.py similarity index 56% rename from devices/statistics_writer/statistics_writer.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/statistics_writer.py index 8bf8fa64fbba9626f60abec0bb6cacb7e7288c51..1a1ecb671159e1b3ca143ecbf860000d6cdbe0c5 100644 --- a/devices/statistics_writer/statistics_writer.py +++ b/tangostationcontrol/tangostationcontrol/statistics_writer/statistics_writer.py @@ -1,32 +1,49 @@ import argparse -from receiver import tcp_receiver, file_receiver -from hdf5_writer import hdf5_writer - import time -from datetime import datetime - import sys -import signal + +from tangostationcontrol.statistics_writer.receiver import tcp_receiver, file_receiver +from tangostationcontrol.statistics_writer.hdf5_writer import hdf5_writer import logging logging.basicConfig(level=logging.INFO, format = '%(asctime)s:%(levelname)s: %(message)s') logger = logging.getLogger("statistics_writer") +def main(): + parser = argparse.ArgumentParser( + description='Converts a stream of statistics packets into HDF5 files.') + parser.add_argument( + '-a', '--host', type=str, required=True, help='the host to connect to') + parser.add_argument( + '-p', '--port', type=int, default=0, + help='the port to connect to, or 0 to use default port for the ' + 'selected mode (default: %(default)s)') + parser.add_argument( + '-f', '--file', type=str, required=True, help='the file to read from') + parser.add_argument( + '-m', '--mode', type=str, choices=['SST', 'XST', 'BST'], default='SST', + help='sets the statistics type to be decoded options (default: ' + '%(default)s)') + parser.add_argument( + '-i', '--interval', type=float, default=3600, nargs="?", + help='The time between creating new files in seconds (default: ' + '%(default)s)') + parser.add_argument( + '-o', '--output_dir', type=str, default=".", nargs="?", + help='specifies the folder to write all the files (default: ' + '%(default)s)') + parser.add_argument( + '-v', '--debug', dest='debug', action='store_true', default=False, + help='increase log output') + parser.add_argument( + '-d', '--decimation', type=int, default=1, + help='Configure the writer to only store one every n samples. Saves ' + 'storage space') + parser.add_argument( + '-r', '--reconnect', dest='reconnect', action='store_true', default=False, + help='Set the writer to keep trying to reconnect whenever connection ' + 'is lost. (default: %(default)s)') -parser = argparse.ArgumentParser(description='Converts a stream of statistics packets into HDF5 files.') -parser.add_argument('-a', '--host', type=str, help='The host to connect to.') -parser.add_argument('-p', '--port', type=int, default=0, help='The port to connect to, or 0 to use default port for the selected mode. (default: %(default)s)') -parser.add_argument('-f', '--file', type=str, help='The file to read from. (will ignore --host and --port)') - -parser.add_argument('-m', '--mode', type=str, choices=['SST', 'XST', 'BST'], default='SST', help='Sets the statistics type to be decoded options. (default: %(default)s)') -parser.add_argument('-i', '--interval', type=float, default=3600, nargs="?", help='The time between creating new files in seconds. (default: %(default)s)') -parser.add_argument('-o', '--output_dir', type=str, default=".", nargs="?", help='Specifies the folder to write all the files. (default: %(default)s)') -parser.add_argument('-d', '--decimation', type=int, default=1, help='Configure the writer to only store one every n samples. Saves storage space.') -parser.add_argument('-v', '--debug', dest='debug', action='store_true', default=False, help='Increase log output.') -parser.add_argument('-r', '--reconnect', dest='reconnect', action='store_true', default=False, help='Set the writer to keep trying to reconnect whenever connection is lost. (default: %(default)s)') - - -if __name__ == "__main__": args = parser.parse_args() # argparse arguments diff --git a/devices/statistics_writer/test/SST_10m_test_1.h5 b/tangostationcontrol/tangostationcontrol/statistics_writer/test/SST_10m_test_1.h5 similarity index 100% rename from devices/statistics_writer/test/SST_10m_test_1.h5 rename to tangostationcontrol/tangostationcontrol/statistics_writer/test/SST_10m_test_1.h5 diff --git a/devices/statistics_writer/test/SST_10m_test_2.h5 b/tangostationcontrol/tangostationcontrol/statistics_writer/test/SST_10m_test_2.h5 similarity index 100% rename from devices/statistics_writer/test/SST_10m_test_2.h5 rename to tangostationcontrol/tangostationcontrol/statistics_writer/test/SST_10m_test_2.h5 diff --git a/devices/statistics_writer/test/SST_10m_test_3.h5 b/tangostationcontrol/tangostationcontrol/statistics_writer/test/SST_10m_test_3.h5 similarity index 100% rename from devices/statistics_writer/test/SST_10m_test_3.h5 rename to tangostationcontrol/tangostationcontrol/statistics_writer/test/SST_10m_test_3.h5 diff --git a/tangostationcontrol/tangostationcontrol/statistics_writer/test/__init__.py b/tangostationcontrol/tangostationcontrol/statistics_writer/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/statistics_writer/test/devices_test_SDP_SST_statistics_packets.bin b/tangostationcontrol/tangostationcontrol/statistics_writer/test/devices_test_SDP_SST_statistics_packets.bin similarity index 100% rename from devices/statistics_writer/test/devices_test_SDP_SST_statistics_packets.bin rename to tangostationcontrol/tangostationcontrol/statistics_writer/test/devices_test_SDP_SST_statistics_packets.bin diff --git a/devices/statistics_writer/test/test_server.py b/tangostationcontrol/tangostationcontrol/statistics_writer/test/test_server.py similarity index 100% rename from devices/statistics_writer/test/test_server.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/test/test_server.py diff --git a/tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/__init__.py b/tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/statistics_writer/udp_dev/udp_client.py b/tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/udp_client.py similarity index 100% rename from devices/statistics_writer/udp_dev/udp_client.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/udp_client.py diff --git a/devices/statistics_writer/udp_dev/udp_server.py b/tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/udp_server.py similarity index 100% rename from devices/statistics_writer/udp_dev/udp_server.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/udp_server.py diff --git a/devices/statistics_writer/udp_dev/udp_write_manager.py b/tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/udp_write_manager.py similarity index 100% rename from devices/statistics_writer/udp_dev/udp_write_manager.py rename to tangostationcontrol/tangostationcontrol/statistics_writer/udp_dev/udp_write_manager.py diff --git a/devices/test/README.md b/tangostationcontrol/tangostationcontrol/test/README.md similarity index 100% rename from devices/test/README.md rename to tangostationcontrol/tangostationcontrol/test/README.md diff --git a/devices/test/SDP_SST_statistics_packet.bin b/tangostationcontrol/tangostationcontrol/test/SDP_SST_statistics_packet.bin similarity index 100% rename from devices/test/SDP_SST_statistics_packet.bin rename to tangostationcontrol/tangostationcontrol/test/SDP_SST_statistics_packet.bin diff --git a/devices/test/SDP_SST_statistics_packets.bin b/tangostationcontrol/tangostationcontrol/test/SDP_SST_statistics_packets.bin similarity index 100% rename from devices/test/SDP_SST_statistics_packets.bin rename to tangostationcontrol/tangostationcontrol/test/SDP_SST_statistics_packets.bin diff --git a/devices/test/SDP_XST_statistics_packets.bin b/tangostationcontrol/tangostationcontrol/test/SDP_XST_statistics_packets.bin similarity index 100% rename from devices/test/SDP_XST_statistics_packets.bin rename to tangostationcontrol/tangostationcontrol/test/SDP_XST_statistics_packets.bin diff --git a/tangostationcontrol/tangostationcontrol/test/__init__.py b/tangostationcontrol/tangostationcontrol/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/test/base.py b/tangostationcontrol/tangostationcontrol/test/base.py similarity index 91% rename from devices/test/base.py rename to tangostationcontrol/tangostationcontrol/test/base.py index 1c2eff09be8e6a4034a476173944c8ec2a1fe61c..7cf3af7f8becb1f92cde139290394ea540f5d8d6 100644 --- a/devices/test/base.py +++ b/tangostationcontrol/tangostationcontrol/test/base.py @@ -7,7 +7,7 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -from common.lofar_logging import configure_logger +from tangostationcontrol.common.lofar_logging import configure_logger import unittest import testscenarios diff --git a/tangostationcontrol/tangostationcontrol/test/clients/__init__.py b/tangostationcontrol/tangostationcontrol/test/clients/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/test/clients/test_attr_wrapper.py b/tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py similarity index 92% rename from devices/test/clients/test_attr_wrapper.py rename to tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py index 8711d989a67730667c10aed91de7c9929c500fcb..24ba5f506023f4260a35958cba568936cb2ad76f 100644 --- a/devices/test/clients/test_attr_wrapper.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py @@ -10,15 +10,17 @@ from tango import DevState # Internal imports -from test.clients.test_client import test_client -from clients.attribute_wrapper import * -from devices.hardware_device import * +from tangostationcontrol.test.clients.test_client import test_client +from tangostationcontrol.clients.attribute_wrapper import * +from tangostationcontrol.devices.lofar_device import * +import tangostationcontrol.devices.lofar_device # Test imports from tango.test_context import DeviceTestContext -from test import base +from tangostationcontrol.test import base import asyncio +import mock scalar_dims = (1,) spectrum_dims = (4,) @@ -31,260 +33,265 @@ str_image_val = [['1','1'],['1','1'],['1','1']] def dev_init(device): device.set_state(DevState.INIT) - device.test_client = test_client(device.Fault, device) + device.test_client = test_client(device.Fault) for i in device.attr_list(): asyncio.run(i.async_set_comm_client(device.test_client)) device.test_client.start() class TestAttributeTypes(base.TestCase): + def setUp(self): + # Avoid the device trying to access itself as a client + self.deviceproxy_patch = mock.patch.object(tangostationcontrol.devices.lofar_device,'DeviceProxy') + self.deviceproxy_patch.start() + self.addCleanup(self.deviceproxy_patch.stop) - class str_scalar_device(hardware_device): + class str_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="str_scalar_R", datatype=numpy.str) scalar_RW = attribute_wrapper(comms_annotation="str_scalar_RW", datatype=numpy.str, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class bool_scalar_device(hardware_device): + class bool_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="bool_scalar_R", datatype=numpy.bool_) scalar_RW = attribute_wrapper(comms_annotation="bool_scalar_RW", datatype=numpy.bool_, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class float32_scalar_device(hardware_device): + class float32_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="float32_scalar_R", datatype=numpy.float32) scalar_RW = attribute_wrapper(comms_annotation="float32_scalar_RW", datatype=numpy.float32, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class float64_scalar_device(hardware_device): + class float64_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="float64_scalar_R", datatype=numpy.float64) scalar_RW = attribute_wrapper(comms_annotation="float64_scalar_RW", datatype=numpy.float64, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class double_scalar_device(hardware_device): + class double_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="double_scalar_R", datatype=numpy.double) scalar_RW = attribute_wrapper(comms_annotation="double_scalar_RW", datatype=numpy.double, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class uint8_scalar_device(hardware_device): + class uint8_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="uint8_scalar_R", datatype=numpy.uint8) scalar_RW = attribute_wrapper(comms_annotation="uint8_scalar_RW", datatype=numpy.uint8, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class uint16_scalar_device(hardware_device): + class uint16_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="uint16_scalar_R", datatype=numpy.uint16) scalar_RW = attribute_wrapper(comms_annotation="uint16_scalar_RW", datatype=numpy.uint16, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class uint32_scalar_device(hardware_device): + class uint32_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="uint32_scalar_R", datatype=numpy.uint32) scalar_RW = attribute_wrapper(comms_annotation="uint32_scalar_RW", datatype=numpy.uint32, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class uint64_scalar_device(hardware_device): + class uint64_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="uint64_scalar_R", datatype=numpy.uint64) scalar_RW = attribute_wrapper(comms_annotation="uint64_scalar_RW", datatype=numpy.uint64, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class int16_scalar_device(hardware_device): + class int16_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="int16_scalar_R", datatype=numpy.int16) scalar_RW = attribute_wrapper(comms_annotation="int16_scalar_RW", datatype=numpy.int16, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class int32_scalar_device(hardware_device): + class int32_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="int32_scalar_R", datatype=numpy.int32) scalar_RW = attribute_wrapper(comms_annotation="int32_scalar_RW", datatype=numpy.int32, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class int64_scalar_device(hardware_device): + class int64_scalar_device(lofar_device): scalar_R = attribute_wrapper(comms_annotation="int64_scalar_R", datatype=numpy.int64) scalar_RW = attribute_wrapper(comms_annotation="int64_scalar_RW", datatype=numpy.int64, access=AttrWriteType.READ_WRITE) def configure_for_initialise(self): dev_init(self) - class str_spectrum_device(hardware_device): + class str_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="str_spectrum_R", datatype=numpy.str, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="str_spectrum_RW", datatype=numpy.str, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class bool_spectrum_device(hardware_device): + class bool_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="bool_spectrum_R", datatype=numpy.bool_, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="bool_spectrum_RW", datatype=numpy.bool_, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class float32_spectrum_device(hardware_device): + class float32_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="float32_spectrum_R", datatype=numpy.float32, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="float32_spectrum_RW", datatype=numpy.float32, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class float64_spectrum_device(hardware_device): + class float64_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="float64_spectrum_R", datatype=numpy.float64, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="float64_spectrum_RW", datatype=numpy.float64, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class double_spectrum_device(hardware_device): + class double_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="double_spectrum_R", datatype=numpy.double, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="double_spectrum_RW", datatype=numpy.double, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class uint8_spectrum_device(hardware_device): + class uint8_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="uint8_spectrum_R", datatype=numpy.uint8, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="uint8_spectrum_RW", datatype=numpy.uint8, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class uint16_spectrum_device(hardware_device): + class uint16_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="uint16_spectrum_R", datatype=numpy.uint16, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="uint16_spectrum_RW", datatype=numpy.uint16, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class uint32_spectrum_device(hardware_device): + class uint32_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="uint32_spectrum_R", datatype=numpy.uint32, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="uint32_spectrum_RW", datatype=numpy.uint32, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class uint64_spectrum_device(hardware_device): + class uint64_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="uint64_spectrum_R", datatype=numpy.uint64, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="uint64_spectrum_RW", datatype=numpy.uint64, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class int16_spectrum_device(hardware_device): + class int16_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="int16_spectrum_R", datatype=numpy.int16, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="int16_spectrum_RW", datatype=numpy.int16, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class int32_spectrum_device(hardware_device): + class int32_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="int32_spectrum_R", datatype=numpy.int32, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="int32_spectrum_RW", datatype=numpy.int32, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class int64_spectrum_device(hardware_device): + class int64_spectrum_device(lofar_device): spectrum_R = attribute_wrapper(comms_annotation="int64_spectrum_R", datatype=numpy.int64, dims=spectrum_dims) spectrum_RW = attribute_wrapper(comms_annotation="int64_spectrum_RW", datatype=numpy.int64, access=AttrWriteType.READ_WRITE, dims=spectrum_dims) def configure_for_initialise(self): dev_init(self) - class str_image_device(hardware_device): + class str_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="str_image_R", datatype=numpy.str, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="str_image_RW", datatype=numpy.str, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class bool_image_device(hardware_device): + class bool_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="bool_image_R", datatype=numpy.bool_, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="bool_image_RW", datatype=numpy.bool_, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class float32_image_device(hardware_device): + class float32_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="float32_image_R", datatype=numpy.float32, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="float32_image_RW", datatype=numpy.float32, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class float64_image_device(hardware_device): + class float64_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="float64_image_R", datatype=numpy.float64, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="float64_image_RW", datatype=numpy.float64, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class double_image_device(hardware_device): + class double_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="double_image_R", datatype=numpy.double, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="double_image_RW", datatype=numpy.double, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class uint8_image_device(hardware_device): + class uint8_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="uint8_image_R", datatype=numpy.uint8, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="uint8_image_RW", datatype=numpy.uint8, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class uint16_image_device(hardware_device): + class uint16_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="uint16_image_R", datatype=numpy.uint16, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="uint16_image_RW", datatype=numpy.uint16, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class uint32_image_device(hardware_device): + class uint32_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="uint32_image_R", datatype=numpy.uint32, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="uint32_image_RW", datatype=numpy.uint32, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class uint64_image_device(hardware_device): + class uint64_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="uint64_image_R", datatype=numpy.uint64, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="uint64_image_RW", datatype=numpy.uint64, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class int16_image_device(hardware_device): + class int16_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="int16_image_R", datatype=numpy.int16, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="int16_image_RW", datatype=numpy.int16, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class int32_image_device(hardware_device): + class int32_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="int32_image_R", datatype=numpy.int32, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="int32_image_RW", datatype=numpy.int32, access=AttrWriteType.READ_WRITE, dims=(2,3)) def configure_for_initialise(self): dev_init(self) - class int64_image_device(hardware_device): + class int64_image_device(lofar_device): image_R = attribute_wrapper(comms_annotation="int64_image_R", datatype=numpy.int64, dims=(2,3)) image_RW = attribute_wrapper(comms_annotation="int64_image_RW", datatype=numpy.int64, access=AttrWriteType.READ_WRITE, dims=(2,3)) diff --git a/devices/test/clients/test_client.py b/tangostationcontrol/tangostationcontrol/test/clients/test_client.py similarity index 80% rename from devices/test/clients/test_client.py rename to tangostationcontrol/tangostationcontrol/test/clients/test_client.py index 7e002c3ad28a531b0ba16f12a22e782d4ba3bb01..ea03e850d4021d0d4c40e82a60d4fd1f0a9d67ea 100644 --- a/devices/test/clients/test_client.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_client.py @@ -3,8 +3,10 @@ import numpy # Test imports -from clients.comms_client import CommClient +from tangostationcontrol.clients.comms_client import CommClient +import logging +logger = logging.getLogger() class test_client(CommClient): """ @@ -15,11 +17,11 @@ class test_client(CommClient): def start(self): super().start() - def __init__(self, fault_func, streams, try_interval=2): + def __init__(self, fault_func, try_interval=2): """ initialises the class and tries to connect to the client. """ - super().__init__(fault_func, streams, try_interval) + super().__init__(fault_func, try_interval) # Explicitly connect self.connect() @@ -28,13 +30,13 @@ class test_client(CommClient): """ this function provides a location for the code neccecary to connect to the client """ - self.streams.debug_stream("the example client doesn't actually connect to anything silly") + logger.debug("the example client doesn't actually connect to anything silly") self.connected = True # set connected to true def disconnect(self): self.connected = False # always force a reconnect, regardless of a successful disconnect - self.streams.debug_stream("disconnected from the 'client' ") + logger.debug("disconnected from the 'client' ") def _setup_annotation(self, annotation): """ @@ -50,7 +52,7 @@ class test_client(CommClient): """ # as this is an example, just print the annotation - self.streams.debug_stream("annotation: {}".format(annotation)) + logger.debug("annotation: {}".format(annotation)) def _setup_value_conversion(self, attribute): """ @@ -75,16 +77,16 @@ class test_client(CommClient): self.value = numpy.zeros(dims, dtype) def read_function(): - self.streams.debug_stream("from read_function, reading {} array of type {}".format(dims, dtype)) + logger.debug("from read_function, reading {} array of type {}".format(dims, dtype)) return self.value def write_function(write_value): - self.streams.debug_stream("from write_function, writing {} array of type {}".format(dims, dtype)) + logger.debug("from write_function, writing {} array of type {}".format(dims, dtype)) self.value = write_value return - self.streams.debug_stream("created and bound example_client read/write functions to attribute_wrapper object") + logger.debug("created and bound example_client read/write functions to attribute_wrapper object") return read_function, write_function async def setup_attribute(self, annotation=None, attribute=None): diff --git a/devices/test/clients/test_opcua_client.py b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py similarity index 98% rename from devices/test/clients/test_opcua_client.py rename to tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py index bc13dc5e1d1d04c800e35f113825015b38779cd9..c1c29ee04279bab3c943ccc35d4e3a5071345607 100644 --- a/devices/test/clients/test_opcua_client.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py @@ -1,16 +1,15 @@ import numpy -from clients.opcua_client import OPCUAConnection -from clients import opcua_client - import asyncua import io -import asyncio +import asynctest from unittest import mock -import unittest -from test import base -import asynctest + +from tangostationcontrol.clients.opcua_client import OPCUAConnection +from tangostationcontrol.clients import opcua_client + +from tangostationcontrol.test import base class attr_props: diff --git a/devices/test/clients/test_statistics_client_thread.py b/tangostationcontrol/tangostationcontrol/test/clients/test_statistics_client_thread.py similarity index 86% rename from devices/test/clients/test_statistics_client_thread.py rename to tangostationcontrol/tangostationcontrol/test/clients/test_statistics_client_thread.py index fd7ce0701f9d792863909b9f8ee4a9d39a2b1fd1..17f866871bd682b3f289364c16a55e5ee2010a7c 100644 --- a/devices/test/clients/test_statistics_client_thread.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_statistics_client_thread.py @@ -10,9 +10,10 @@ import logging from unittest import mock -from clients.statistics_client_thread import StatisticsClientThread +from tangostationcontrol.clients.statistics_client_thread import \ + StatisticsClientThread -from test import base +from tangostationcontrol.test import base logger = logging.getLogger() diff --git a/devices/test/clients/test_tcp_replicator.py b/tangostationcontrol/tangostationcontrol/test/clients/test_tcp_replicator.py similarity index 97% rename from devices/test/clients/test_tcp_replicator.py rename to tangostationcontrol/tangostationcontrol/test/clients/test_tcp_replicator.py index a9babed0eb7af7a58544b3ff7535c3113ed12ca3..04c87f1d5a15705f7d0b8ce1460141255cb02b27 100644 --- a/devices/test/clients/test_tcp_replicator.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_tcp_replicator.py @@ -9,15 +9,14 @@ import logging import time -from queue import Queue from unittest import mock -from clients.tcp_replicator import TCPReplicator -from clients import tcp_replicator +import timeout_decorator -from test import base +from tangostationcontrol.clients.tcp_replicator import TCPReplicator +from tangostationcontrol.clients import tcp_replicator -import timeout_decorator +from tangostationcontrol.test import base logger = logging.getLogger() diff --git a/tangostationcontrol/tangostationcontrol/test/common/__init__.py b/tangostationcontrol/tangostationcontrol/test/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/test/common/test_baselines.py b/tangostationcontrol/tangostationcontrol/test/common/test_baselines.py similarity index 91% rename from devices/test/common/test_baselines.py rename to tangostationcontrol/tangostationcontrol/test/common/test_baselines.py index 206b4ca0eccefe1012519c8236d158e52f1cdc38..25eb5d1dfffa2fca8748d74020893edfb17c2037 100644 --- a/devices/test/common/test_baselines.py +++ b/tangostationcontrol/tangostationcontrol/test/common/test_baselines.py @@ -7,9 +7,9 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -from common import baselines +from tangostationcontrol.common import baselines -from test import base +from tangostationcontrol.test import base class TestBaselines(base.TestCase): diff --git a/devices/test/common/test_lofar_logging.py b/tangostationcontrol/tangostationcontrol/test/common/test_lofar_logging.py similarity index 97% rename from devices/test/common/test_lofar_logging.py rename to tangostationcontrol/tangostationcontrol/test/common/test_lofar_logging.py index c1030b28f3b9b7861e6eec9d25b4ca6ef22a0c22..5140d05e58ca370509a080211ca96f2df21fe399 100644 --- a/devices/test/common/test_lofar_logging.py +++ b/tangostationcontrol/tangostationcontrol/test/common/test_lofar_logging.py @@ -7,16 +7,16 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -import git from unittest import mock - -from common import lofar_logging import logging + from tango.server import Device from tango import device_server from tango.test_context import DeviceTestContext -from test import base +from tangostationcontrol.common import lofar_logging + +from tangostationcontrol.test import base class TestLofarLogging(base.TestCase): diff --git a/tangostationcontrol/tangostationcontrol/test/common/test_lofar_version.py b/tangostationcontrol/tangostationcontrol/test/common/test_lofar_version.py new file mode 100644 index 0000000000000000000000000000000000000000..89ac894d9388d3939671c43239033ce1147fef30 --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/test/common/test_lofar_version.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +# +# This file is part of the LOFAR 2.0 Station Software +# +# +# +# Distributed under the terms of the APACHE license. +# See LICENSE.txt for more info. + +import git +from unittest import mock + +from tangostationcontrol.common import lofar_version + +from tangostationcontrol.test import base + + +class TestLofarVersion(base.TestCase): + + def setUp(self): + super(TestLofarVersion, self).setUp() + + # Clear the cache as this function of lofar_version uses LRU decorator + # This is a good demonstration of how unit tests in Python can have + # permanent effects, typically fixtures are needed to restore these. + lofar_version.get_version.cache_clear() + + def test_get_version(self): + """Test if attributes of get_repo are correctly used by get_version""" + + with mock.patch.object(lofar_version, 'get_repo') as m_get_repo: + m_commit = mock.Mock() + m_commit.return_value.__str__ = mock.Mock(return_value="123456") + m_commit.return_value.iter_items.return_value = [] + + m_is_dirty = mock.Mock() + m_is_dirty.return_value = False + + m_head = mock.Mock(is_detached=False) + + m_get_repo.return_value = mock.Mock( + active_branch="main", commit=m_commit, tags=[], + is_dirty=m_is_dirty, head=m_head) + + # No need for special string equal in Python + self.assertEqual("0.0.0.main.123456", lofar_version.get_version()) + + def test_get_version_tag(self): + """Test if get_version determines production_ready for tagged commit""" + + with mock.patch.object(lofar_version, 'get_repo') as m_get_repo: + m_commit = mock.Mock() + m_commit.return_value.__str__ = mock.Mock(return_value="123456") + m_commit.return_value.iter_items.return_value = [] + + m_is_dirty = mock.Mock() + m_is_dirty.return_value = False + + m_head = mock.Mock(is_detached=False) + + m_tag_commit = mock.Mock(type="commit") + m_tag_commit.__str__ = mock.Mock(return_value="123456") + + m_tag = mock.Mock(commit=m_tag_commit) + m_tag.name = "v0.0.3" + m_tag.__str__ = mock.Mock(return_value= "v0.0.3") + + m_commit.return_value = m_tag_commit + m_commit.return_value.iter_items.return_value = [m_tag_commit] + + m_get_repo.return_value = mock.Mock( + active_branch="main", commit=m_commit, + tags=[m_tag], is_dirty=m_is_dirty, head=m_head) + + self.assertEqual("0.0.3", lofar_version.get_version()) + + @mock.patch.object(lofar_version, 'get_repo') + def test_get_version_tag_dirty(self, m_get_repo): + + """Test if get_version determines dirty tagged commit""" + m_commit = mock.Mock() + m_commit.return_value.__str__ = mock.Mock(return_value="123456") + m_commit.return_value.iter_items.return_value = [] + + m_is_dirty = mock.Mock() + m_is_dirty.return_value = True + + m_head = mock.Mock(is_detached=False) + + m_get_repo.return_value = mock.Mock( + active_branch="main", commit=m_commit, tags=[], + is_dirty=m_is_dirty, head=m_head) + + # No need for special string equal in Python + self.assertEqual("0.0.0.main.123456.dirty", lofar_version.get_version()) + + def test_catch_repo_error(self): + """Test if invalid git directories will raise error""" + + with mock.patch.object(lofar_version, 'get_repo') as m_get_repo: + + # Configure lofar_version.get_repo to raise InvalidGitRepositoryError + m_get_repo.side_effect = git.InvalidGitRepositoryError + + # Test that error is raised by get_version + self.assertRaises( + git.InvalidGitRepositoryError, lofar_version.get_version) diff --git a/tangostationcontrol/tangostationcontrol/test/devices/__init__.py b/tangostationcontrol/tangostationcontrol/test/devices/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/test/devices/random_data.py b/tangostationcontrol/tangostationcontrol/test/devices/random_data.py similarity index 97% rename from devices/test/devices/random_data.py rename to tangostationcontrol/tangostationcontrol/test/devices/random_data.py index 43e1a037624a516f88d05d644fd86e23fab6baa8..51d7b269f99c814cb340dc9f0e8feb44f3393f94 100644 --- a/devices/test/devices/random_data.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/random_data.py @@ -7,13 +7,6 @@ # Distributed under the terms of the APACHE license. # See LICENSE.txt for more info. -# TODO(Corne): Remove sys.path.append hack once packaging is in place! -import os, sys -currentdir = os.path.dirname(os.path.realpath(__file__)) -parentdir = os.path.dirname(currentdir) -parentdir = os.path.dirname(parentdir) -sys.path.append(parentdir) - # PyTango imports from tango import DevState from tango.server import run, Device, attribute, command @@ -497,6 +490,3 @@ def main(args = None, **kwargs): Main function of the RandomData module. """ return run((Random_Data,), args = args, **kwargs) - -if __name__ == '__main__': - main() diff --git a/devices/test/devices/test_abstract_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_abstract_device.py similarity index 95% rename from devices/test/devices/test_abstract_device.py rename to tangostationcontrol/tangostationcontrol/test/devices/test_abstract_device.py index f54383c9a1b85f5c9e442f51d7f04d061951f772..469ea19fa970cf48c2de9c4c6b5648bd7b756040 100644 --- a/devices/test/devices/test_abstract_device.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/test_abstract_device.py @@ -16,9 +16,9 @@ from tango.server import attribute from tango.test_context import DeviceTestContext -from devices.abstract_device import AbstractDeviceMetas +from tangostationcontrol.devices.abstract_device import AbstractDeviceMetas -from test import base +from tangostationcontrol.test import base class TestAbstractDevice(base.TestCase): diff --git a/devices/test/devices/test_statistics_collector.py b/tangostationcontrol/tangostationcontrol/test/devices/test_statistics_collector.py similarity index 96% rename from devices/test/devices/test_statistics_collector.py rename to tangostationcontrol/tangostationcontrol/test/devices/test_statistics_collector.py index 5fe4e24dabbf169664b19250cba13f19b8020327..4b58141c06d9b09d68dba295b007b41081ca3618 100644 --- a/devices/test/devices/test_statistics_collector.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/test_statistics_collector.py @@ -1,7 +1,7 @@ -from devices.sdp.statistics_collector import XSTCollector -from devices.sdp.statistics_packet import XSTPacket +from tangostationcontrol.devices.sdp.statistics_collector import XSTCollector +from tangostationcontrol.devices.sdp.statistics_packet import XSTPacket -from test import base +from tangostationcontrol.test import base class TestXSTCollector(base.TestCase): def test_valid_packet(self): diff --git a/devices/toolkit/README.md b/tangostationcontrol/tangostationcontrol/toolkit/README.md similarity index 100% rename from devices/toolkit/README.md rename to tangostationcontrol/tangostationcontrol/toolkit/README.md diff --git a/tangostationcontrol/tangostationcontrol/toolkit/__init__.py b/tangostationcontrol/tangostationcontrol/toolkit/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/devices/toolkit/archiver.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py similarity index 98% rename from devices/toolkit/archiver.py rename to tangostationcontrol/tangostationcontrol/toolkit/archiver.py index 622e444753993eb010b25b28b21798118e53d2a1..a938b41156eb25f706ddfe6cb939a3dc28a57dbf 100644 --- a/devices/toolkit/archiver.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py @@ -3,7 +3,9 @@ #from logging import raiseExceptions import logging import traceback -from clients.attribute_wrapper import attribute_wrapper + +from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper + from tango import DeviceProxy, AttributeProxy from datetime import datetime, timedelta @@ -335,7 +337,7 @@ class AttributeFormatException(Exception): """ Exception that handles wrong attribute naming """ - def __init__(self, message="Wrong Tango attribute format! Try: domain/family/member/attribute (e.g. LTS/RECV/1/temperature)"): + def __init__(self, message="Wrong Tango attribute format! Try: domain/family/member/attribute (e.g. STAT/RECV/1/temperature)"): self.message = message super().__init__(self.message) @@ -405,7 +407,7 @@ class Retriever(): try: [domain, family, member] = device_fqname.split('/') except: - raise AttributeFormatException(f"Could not parse device name {device_fqname}. Please provide FQDN, e.g. LTS/Device/1") + raise AttributeFormatException(f"Could not parse device name {device_fqname}. Please provide FQDN, e.g. STAT/Device/1") attrs = self.session.query(Attribute).filter(and_(Attribute.domain == domain, Attribute.family == family, \ Attribute.member == member)).all() # Returns the representation as set in __repr__ method of the mapper class @@ -418,7 +420,7 @@ class Retriever(): try: [domain, family, member, name] = attribute_fqname.split('/') except: - raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. LTS/Device/1/Attribute") + raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. STAT/Device/1/Attribute") try: result = self.session.query(Attribute.att_conf_id).filter(and_(Attribute.domain == domain, Attribute.family == family, \ Attribute.member == member, Attribute.name == name)).one() @@ -437,7 +439,7 @@ class Retriever(): try: [domain, family, member, name] = attribute_fqname.split('/') except: - raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. LTS/Device/1/Attribute") + raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. STAT/Device/1/Attribute") try: result = self.session.query(DataType.data_type).join(Attribute,Attribute.att_conf_data_type_id==DataType.att_conf_data_type_id).\ filter(and_(Attribute.domain == domain, Attribute.family == family, Attribute.member == member, Attribute.name == name)).one() diff --git a/devices/toolkit/archiver_base.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base.py similarity index 100% rename from devices/toolkit/archiver_base.py rename to tangostationcontrol/tangostationcontrol/toolkit/archiver_base.py diff --git a/devices/toolkit/archiver_config/lofar2.json b/tangostationcontrol/tangostationcontrol/toolkit/archiver_config/lofar2.json similarity index 87% rename from devices/toolkit/archiver_config/lofar2.json rename to tangostationcontrol/tangostationcontrol/toolkit/archiver_config/lofar2.json index 914fe15b7b26c3d6fae1a6486220282e9f10f59d..71539d81e4d09b3771354b94e013ea6ab8bf2b77 100644 --- a/devices/toolkit/archiver_config/lofar2.json +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_config/lofar2.json @@ -4,27 +4,27 @@ "development_archive_time": "60000" }, "devices":{ - "LTS/RECV/1": { + "STAT/RECV/1": { "environment": "development", "include": [], "exclude": ["CLK_Enable_PWR_R","CLK_I2C_STATUS_R","CLK_PLL_error_R","CLK_PLL_locked_R","CLK_translator_busy_R"] }, - "LTS/SDP/1": { + "STAT/SDP/1": { "environment": "development", "include": ["FPGA_temp_R","TR_fpga_mask_R"], "exclude": [] }, - "LTS/SST/1": { + "STAT/SST/1": { "environment": "development", "include": [], "exclude": [] }, - "LTS/XST/1": { + "STAT/XST/1": { "environment": "development", "include": [], "exclude": [] }, - "LTS/UNB2/1": { + "STAT/UNB2/1": { "environment": "development", "include": [], "exclude": [] diff --git a/devices/toolkit/get_internal_attribute_history.py b/tangostationcontrol/tangostationcontrol/toolkit/get_internal_attribute_history.py similarity index 99% rename from devices/toolkit/get_internal_attribute_history.py rename to tangostationcontrol/tangostationcontrol/toolkit/get_internal_attribute_history.py index 735be01613611d73f39678f6b0ed5fb1f1c56a70..8b6b4254f6c10dc8207232b16fd5e22d44e7c556 100644 --- a/devices/toolkit/get_internal_attribute_history.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/get_internal_attribute_history.py @@ -1,10 +1,8 @@ #! /usr/bin/env python3 - from tango import DeviceProxy from numpy import array, transpose - def get_internal_attribute_history(device: DeviceProxy, attribute_name: str, depth: int = 10): try: history = array(device.attribute_history(attr_name = attribute_name, depth = depth)) diff --git a/devices/toolkit/lofar2_config.py b/tangostationcontrol/tangostationcontrol/toolkit/lofar2_config.py similarity index 99% rename from devices/toolkit/lofar2_config.py rename to tangostationcontrol/tangostationcontrol/toolkit/lofar2_config.py index 581eea4f73a4d276613123ec9bf86bdb7e97a0ea..811f4f27abbbac832c6de6811a223a27229e9032 100644 --- a/devices/toolkit/lofar2_config.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/lofar2_config.py @@ -2,7 +2,6 @@ import logging - def configure_logging(): # Always also log the hostname because it makes the origin of the log clear. import socket diff --git a/devices/toolkit/udp_simulator.py b/tangostationcontrol/tangostationcontrol/toolkit/udp_simulator.py similarity index 100% rename from devices/toolkit/udp_simulator.py rename to tangostationcontrol/tangostationcontrol/toolkit/udp_simulator.py diff --git a/devices/test-requirements.txt b/tangostationcontrol/test-requirements.txt similarity index 100% rename from devices/test-requirements.txt rename to tangostationcontrol/test-requirements.txt diff --git a/devices/tox.ini b/tangostationcontrol/tox.ini similarity index 95% rename from devices/tox.ini rename to tangostationcontrol/tox.ini index 59d2347f3ff42ccb084033aea67d478fd63513cb..69782d5e33c1ab14ce9abcd50253e0db9eabdf9a 100644 --- a/devices/tox.ini +++ b/tangostationcontrol/tox.ini @@ -22,7 +22,7 @@ commands = stestr run {posargs} ; Warning running integration tests will make changes to your docker system! ; These tests should only be run by the integration-test docker container. passenv = TANGO_HOST -setenv = TESTS_DIR=./integration_test +setenv = TESTS_DIR=./tangostationcontrol/integration_test commands = stestr run --serial {posargs}