diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b73c4eaedd173a1e099cb136bc75dcc37e0cb119..5dfcfcc0838b8ceb5543457286c36b296c3f6aaf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -459,6 +459,10 @@ integration_test_docker: - name: docker:dind variables: DOCKER_TLS_CERTDIR: "/certs" + artifacts: + when: always + paths: + - log/ before_script: - | if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" && -z "$CI_COMMIT_TAG" ]]; then @@ -477,20 +481,23 @@ integration_test_docker: - 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 docker image script to execute -# - chmod u+x $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh # Do not remove 'bash' or statement will be ignored by primitive docker shell - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh pull $tag -## 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 + - bash -e $CI_PROJECT_DIR/sbin/run_integration_test.sh + after_script: +# Collect output of all containers + - | + mkdir -p log + for container in $(docker ps -a --format "{{.Names}}") + do + echo "Saving log for container $container" + docker logs "${container}" >& "log/${container}.log" + done wheel_packaging: stage: packaging artifacts: diff --git a/.gitmodules b/.gitmodules index 295ed3b37fc8ff4b3674422af3b799f3041f45ed..3f1cb3e31f5ff75ccc1292eada306c6bcc551630 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,4 @@ branch = station-control [submodule "tangostationcontrol/tangostationcontrol/toolkit/libhdbpp-python"] path = tangostationcontrol/tangostationcontrol/toolkit/libhdbpp-python - url = https://gitlab.com/tango-controls/hdbpp/libhdbpp-python + url = https://gitlab.com/tango-controls/hdbpp/libhdbpp-python.git diff --git a/CDB/integration_ConfigDb.json b/CDB/integration_ConfigDb.json deleted file mode 100644 index 7cfbd82751791d7968315923edfc2ba971480308..0000000000000000000000000000000000000000 --- a/CDB/integration_ConfigDb.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "servers": { - "APSCT": { - "STAT": { - "APSCT": { - "STAT/APSCT/1": { - "properties": { - "OPC_Server_Name": [ - "apsct-sim" - ], - "OPC_Server_Port": [ - "4843" - ], - "OPC_Time_Out": [ - "5.0" - ] - } - } - } - } - }, - "APSPU": { - "STAT": { - "APSPU": { - "STAT/APSPU/1": { - "properties": { - "OPC_Server_Name": [ - "apspu-sim" - ], - "OPC_Server_Port": [ - "4843" - ], - "OPC_Time_Out": [ - "5.0" - ] - } - } - } - } - }, - "RECV": { - "STAT": { - "RECV": { - "STAT/RECV/1": { - "properties": { - "OPC_Server_Name": [ - "recv-sim" - ], - "OPC_Server_Port": [ - "4840" - ], - "OPC_Time_Out": [ - "5.0" - ] - } - } - } - } - }, - "SDP": { - "STAT": { - "SDP": { - "STAT/SDP/1": { - "properties": { - "OPC_Server_Name": [ - "sdptr-sim" - ], - "OPC_Server_Port": [ - "4840" - ], - "OPC_Time_Out": [ - "5.0" - ], - "FPGA_sdp_info_station_id_RW_default": [ - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901", - "901" - ], - "polled_attr": [ - "fpga_temp_r", - "1000", - "state", - "1000", - "status", - "1000", - "fpga_mask_rw", - "1000", - "fpga_scrap_r", - "1000", - "fpga_scrap_rw", - "1000", - "fpga_status_r", - "1000", - "fpga_version_r", - "1000", - "fpga_weights_r", - "1000", - "fpga_weights_rw", - "1000", - "tr_busy_r", - "1000", - "tr_reload_rw", - "1000", - "tr_tod_r", - "1000", - "tr_uptime_r", - "1000" - ] - } - } - } - } - }, - "SST": { - "STAT": { - "SST": { - "STAT/SST/1": { - "properties": { - "Statistics_Client_UDP_Port": [ - "5001" - ], - "Statistics_Client_TCP_Port": [ - "5101" - ], - "OPC_Server_Name": [ - "sdptr-sim" - ], - "OPC_Server_Port": [ - "4840" - ], - "OPC_Time_Out": [ - "5.0" - ], - "FPGA_sst_offload_hdr_eth_destination_mac_RW_default": [ - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd" - ], - "FPGA_sst_offload_hdr_ip_destination_address_RW_default": [ - "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" - ], - "FPGA_sst_offload_hdr_udp_destination_port_RW_default": [ - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001", - "5001" - ] - } - } - } - } - }, - "XST": { - "STAT": { - "XST": { - "STAT/XST/1": { - "properties": { - "Statistics_Client_UDP_Port": [ - "5002" - ], - "Statistics_Client_TCP_Port": [ - "5102" - ], - "OPC_Server_Name": [ - "sdptr-sim" - ], - "OPC_Server_Port": [ - "4840" - ], - "OPC_Time_Out": [ - "5.0" - ], - "FPGA_xst_offload_hdr_eth_destination_mac_RW_default": [ - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd", - "6c:2b:59:97:be:dd" - ], - "FPGA_xst_offload_hdr_ip_destination_address_RW_default": [ - "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" - ], - "FPGA_xst_offload_hdr_udp_destination_port_RW_default": [ - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002", - "5002" - ] - } - } - } - } - }, - "UNB2": { - "STAT": { - "UNB2": { - "STAT/UNB2/1": { - "properties": { - "OPC_Server_Name": [ - "unb2-sim" - ], - "OPC_Server_Port": [ - "4841" - ], - "OPC_Time_Out": [ - "5.0" - ] - } - } - } - } - } - } -} diff --git a/CDB/integrations/recvcluster_ConfigDb.json b/CDB/integrations/recvcluster_ConfigDb.json new file mode 100644 index 0000000000000000000000000000000000000000..1b27092a198f26f2916e27a3043c8d5528e064a1 --- /dev/null +++ b/CDB/integrations/recvcluster_ConfigDb.json @@ -0,0 +1,2278 @@ +{ + "servers": { + "TileBeam": { + "STAT": { + "TileBeam": { + "STAT/TileBeam/2": {}, + "STAT/TileBeam/3": {}, + "STAT/TileBeam/4": {} + } + } + }, + "RECV": { + "STAT": { + "RECV": { + "STAT/RECV/2": { + "attribute_properties": { + "Ant_mask_RW": { + "archive_period": [ + "600000" + ] + }, + "CLK_Enable_PWR_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_I2C_STATUS_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "CLK_PLL_error_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_PLL_locked_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_monitor_rate_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "CLK_translator_busy_R": { + "archive_period": [ + "600000" + ] + }, + "HBA_element_LNA_pwr_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_LNA_pwr_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_beamformer_delays_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_beamformer_delays_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_led_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_led_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_pwr_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_pwr_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_ADC_lock_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_I2C_STATUS_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_ID_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_LED0_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED0_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED1_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED1_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_Pwr_dig_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_attenuator_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_attenuator_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_band_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_band_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_mask_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_monitor_rate_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1.0", + "1.0" + ], + "rel_change": [ + "-1.0", + "1.0" + ] + }, + "RCU_temperature_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1.0", + "1.0" + ], + "rel_change": [ + "-1.0", + "1.0" + ] + }, + "RCU_translator_busy_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_version_R": { + "archive_period": [ + "600000" + ] + }, + "State": { + "archive_period": [ + "600000" + ], + "event_period": [ + "0" + ] + }, + "Status": { + "archive_period": [ + "600000" + ], + "event_period": [ + "0" + ] + } + }, + "properties": { + "HBAT_reference_itrf": [ + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786" + ], + "HBAT_antenna_itrf_offsets": [ + "-1.847", + "-1.180", + " 1.493", + "-1.581", + " 0.003", + " 1.186", + "-1.315", + " 1.185", + " 0.880", + "-1.049", + " 2.367", + " 0.573", + "-0.882", + "-1.575", + " 0.804", + "-0.616", + "-0.393", + " 0.498", + "-0.350", + " 0.789", + " 0.191", + "-0.083", + " 1.971", + "-0.116", + " 0.083", + "-1.971", + " 0.116", + " 0.350", + "-0.789", + "-0.191", + " 0.616", + " 0.393", + "-0.498", + " 0.882", + " 1.575", + "-0.804", + " 1.049", + "-2.367", + "-0.573", + " 1.315", + "-1.185", + "-0.880", + " 1.581", + "-0.003", + "-1.186", + " 1.847", + " 1.180", + "-1.493" + ], + "OPC_Server_Name": [ + "recv-sim" + ], + "OPC_Server_Port": [ + "4840" + ], + "OPC_Time_Out": [ + "5.0" + ], + "polled_attr": [ + "state", + "1000", + "status", + "1000", + "ant_mask_rw", + "1000", + "rcu_adc_lock_r", + "1000", + "rcu_attenuator_r", + "1000", + "rcu_attenuator_rw", + "1000", + "rcu_band_r", + "1000", + "rcu_band_rw", + "1000", + "rcu_id_r", + "1000", + "rcu_led0_r", + "1000", + "rcu_led0_rw", + "1000", + "rcu_mask_rw", + "1000", + "rcu_monitor_rate_rw", + "1000", + "rcu_pwr_dig_r", + "1000", + "rcu_temperature_r", + "1000", + "rcu_version_r", + "1000", + "hba_element_beamformer_delays_r", + "1000", + "hba_element_beamformer_delays_rw", + "1000", + "hba_element_led_r", + "1000", + "hba_element_led_rw", + "1000", + "hba_element_pwr_r", + "1000", + "hba_element_pwr_rw", + "1000", + "clk_enable_pwr_r", + "1000", + "clk_i2c_status_r", + "1000", + "clk_monitor_rate_rw", + "1000", + "clk_pll_error_r", + "1000", + "clk_pll_locked_r", + "1000", + "clk_translator_busy_r", + "1000", + "hba_element_lna_pwr_r", + "1000", + "hba_element_lna_pwr_rw", + "1000", + "rcu_i2c_status_r", + "1000", + "rcu_led1_r", + "1000", + "rcu_led1_rw", + "1000", + "rcu_translator_busy_r", + "1000" + ] + } + }, + "STAT/RECV/3": { + "attribute_properties": { + "Ant_mask_RW": { + "archive_period": [ + "600000" + ] + }, + "CLK_Enable_PWR_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_I2C_STATUS_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "CLK_PLL_error_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_PLL_locked_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_monitor_rate_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "CLK_translator_busy_R": { + "archive_period": [ + "600000" + ] + }, + "HBA_element_LNA_pwr_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_LNA_pwr_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_beamformer_delays_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_beamformer_delays_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_led_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_led_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_pwr_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_pwr_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_ADC_lock_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_I2C_STATUS_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_ID_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_LED0_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED0_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED1_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED1_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_Pwr_dig_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_attenuator_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_attenuator_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_band_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_band_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_mask_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_monitor_rate_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1.0", + "1.0" + ], + "rel_change": [ + "-1.0", + "1.0" + ] + }, + "RCU_temperature_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1.0", + "1.0" + ], + "rel_change": [ + "-1.0", + "1.0" + ] + }, + "RCU_translator_busy_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_version_R": { + "archive_period": [ + "600000" + ] + }, + "State": { + "archive_period": [ + "600000" + ], + "event_period": [ + "0" + ] + }, + "Status": { + "archive_period": [ + "600000" + ], + "event_period": [ + "0" + ] + } + }, + "properties": { + "HBAT_reference_itrf": [ + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786" + ], + "HBAT_antenna_itrf_offsets": [ + "-1.847", + "-1.180", + " 1.493", + "-1.581", + " 0.003", + " 1.186", + "-1.315", + " 1.185", + " 0.880", + "-1.049", + " 2.367", + " 0.573", + "-0.882", + "-1.575", + " 0.804", + "-0.616", + "-0.393", + " 0.498", + "-0.350", + " 0.789", + " 0.191", + "-0.083", + " 1.971", + "-0.116", + " 0.083", + "-1.971", + " 0.116", + " 0.350", + "-0.789", + "-0.191", + " 0.616", + " 0.393", + "-0.498", + " 0.882", + " 1.575", + "-0.804", + " 1.049", + "-2.367", + "-0.573", + " 1.315", + "-1.185", + "-0.880", + " 1.581", + "-0.003", + "-1.186", + " 1.847", + " 1.180", + "-1.493" + ], + "OPC_Server_Name": [ + "recv-sim" + ], + "OPC_Server_Port": [ + "4840" + ], + "OPC_Time_Out": [ + "5.0" + ], + "polled_attr": [ + "state", + "1000", + "status", + "1000", + "ant_mask_rw", + "1000", + "rcu_adc_lock_r", + "1000", + "rcu_attenuator_r", + "1000", + "rcu_attenuator_rw", + "1000", + "rcu_band_r", + "1000", + "rcu_band_rw", + "1000", + "rcu_id_r", + "1000", + "rcu_led0_r", + "1000", + "rcu_led0_rw", + "1000", + "rcu_mask_rw", + "1000", + "rcu_monitor_rate_rw", + "1000", + "rcu_pwr_dig_r", + "1000", + "rcu_temperature_r", + "1000", + "rcu_version_r", + "1000", + "hba_element_beamformer_delays_r", + "1000", + "hba_element_beamformer_delays_rw", + "1000", + "hba_element_led_r", + "1000", + "hba_element_led_rw", + "1000", + "hba_element_pwr_r", + "1000", + "hba_element_pwr_rw", + "1000", + "clk_enable_pwr_r", + "1000", + "clk_i2c_status_r", + "1000", + "clk_monitor_rate_rw", + "1000", + "clk_pll_error_r", + "1000", + "clk_pll_locked_r", + "1000", + "clk_translator_busy_r", + "1000", + "hba_element_lna_pwr_r", + "1000", + "hba_element_lna_pwr_rw", + "1000", + "rcu_i2c_status_r", + "1000", + "rcu_led1_r", + "1000", + "rcu_led1_rw", + "1000", + "rcu_translator_busy_r", + "1000" + ] + } + }, + "STAT/RECV/4": { + "attribute_properties": { + "Ant_mask_RW": { + "archive_period": [ + "600000" + ] + }, + "CLK_Enable_PWR_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_I2C_STATUS_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "CLK_PLL_error_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_PLL_locked_R": { + "archive_period": [ + "600000" + ] + }, + "CLK_monitor_rate_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "CLK_translator_busy_R": { + "archive_period": [ + "600000" + ] + }, + "HBA_element_LNA_pwr_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_LNA_pwr_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_beamformer_delays_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_beamformer_delays_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_led_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_led_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_pwr_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "HBA_element_pwr_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_ADC_lock_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_I2C_STATUS_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_ID_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_LED0_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED0_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED1_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_LED1_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_Pwr_dig_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_attenuator_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_attenuator_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_band_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_band_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1", + "1" + ], + "rel_change": [ + "-1", + "1" + ] + }, + "RCU_mask_RW": { + "archive_period": [ + "600000" + ] + }, + "RCU_monitor_rate_RW": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1.0", + "1.0" + ], + "rel_change": [ + "-1.0", + "1.0" + ] + }, + "RCU_temperature_R": { + "archive_period": [ + "600000" + ], + "archive_rel_change": [ + "-1.0", + "1.0" + ], + "rel_change": [ + "-1.0", + "1.0" + ] + }, + "RCU_translator_busy_R": { + "archive_period": [ + "600000" + ] + }, + "RCU_version_R": { + "archive_period": [ + "600000" + ] + }, + "State": { + "archive_period": [ + "600000" + ], + "event_period": [ + "0" + ] + }, + "Status": { + "archive_period": [ + "600000" + ], + "event_period": [ + "0" + ] + } + }, + "properties": { + "HBAT_reference_itrf": [ + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786", + "3826577.066", + "461022.948", + "5064892.786" + ], + "HBAT_antenna_itrf_offsets": [ + "-1.847", + "-1.180", + " 1.493", + "-1.581", + " 0.003", + " 1.186", + "-1.315", + " 1.185", + " 0.880", + "-1.049", + " 2.367", + " 0.573", + "-0.882", + "-1.575", + " 0.804", + "-0.616", + "-0.393", + " 0.498", + "-0.350", + " 0.789", + " 0.191", + "-0.083", + " 1.971", + "-0.116", + " 0.083", + "-1.971", + " 0.116", + " 0.350", + "-0.789", + "-0.191", + " 0.616", + " 0.393", + "-0.498", + " 0.882", + " 1.575", + "-0.804", + " 1.049", + "-2.367", + "-0.573", + " 1.315", + "-1.185", + "-0.880", + " 1.581", + "-0.003", + "-1.186", + " 1.847", + " 1.180", + "-1.493" + ], + "OPC_Server_Name": [ + "recv-sim" + ], + "OPC_Server_Port": [ + "4840" + ], + "OPC_Time_Out": [ + "5.0" + ], + "polled_attr": [ + "state", + "1000", + "status", + "1000", + "ant_mask_rw", + "1000", + "rcu_adc_lock_r", + "1000", + "rcu_attenuator_r", + "1000", + "rcu_attenuator_rw", + "1000", + "rcu_band_r", + "1000", + "rcu_band_rw", + "1000", + "rcu_id_r", + "1000", + "rcu_led0_r", + "1000", + "rcu_led0_rw", + "1000", + "rcu_mask_rw", + "1000", + "rcu_monitor_rate_rw", + "1000", + "rcu_pwr_dig_r", + "1000", + "rcu_temperature_r", + "1000", + "rcu_version_r", + "1000", + "hba_element_beamformer_delays_r", + "1000", + "hba_element_beamformer_delays_rw", + "1000", + "hba_element_led_r", + "1000", + "hba_element_led_rw", + "1000", + "hba_element_pwr_r", + "1000", + "hba_element_pwr_rw", + "1000", + "clk_enable_pwr_r", + "1000", + "clk_i2c_status_r", + "1000", + "clk_monitor_rate_rw", + "1000", + "clk_pll_error_r", + "1000", + "clk_pll_locked_r", + "1000", + "clk_translator_busy_r", + "1000", + "hba_element_lna_pwr_r", + "1000", + "hba_element_lna_pwr_rw", + "1000", + "rcu_i2c_status_r", + "1000", + "rcu_led1_r", + "1000", + "rcu_led1_rw", + "1000", + "rcu_translator_busy_r", + "1000" + ] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/CDB/stations/dummy_positions_ConfigDb.json b/CDB/stations/dummy_positions_ConfigDb.json index 926145a0c6a2f652c637ae4ab409b57b07c655d7..460f49d2e5c9af9d968c11be32f11819a4ab943e 100644 --- a/CDB/stations/dummy_positions_ConfigDb.json +++ b/CDB/stations/dummy_positions_ConfigDb.json @@ -5,6 +5,9 @@ "RECV": { "STAT/RECV/1": { "properties": { + "Antenna_Field_Reference_ETRS": [ + "3826896.631", "460979.131", "5064657.943" + ], "HBAT_reference_ETRS": [ "3826886.142", "460980.772", "5064665.668", "3826887.237", "460985.643", "5064664.406", diff --git a/bin/wait-for-it.sh b/bin/wait-for-it.sh new file mode 100755 index 0000000000000000000000000000000000000000..0bd0c104de461817575aafc4962fcc5ee786945e --- /dev/null +++ b/bin/wait-for-it.sh @@ -0,0 +1,165 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2086,SC2064,SC2206,SC2124 +# Use this script to test if a given TCP host/port are available +# +# Source: https://github.com/vishnubob/wait-for-it +# License: MIT + +cmdname=$(basename $0) + +echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $TIMEOUT -gt 0 ]]; then + echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" + else + echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" + fi + start_ts=$(date +%s) + while : + do + (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 + result=$? + if [[ $result -eq 0 ]]; then + end_ts=$(date +%s) + echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" + break + fi + sleep 1 + done + return $result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $QUIET -eq 1 ]]; then + timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + else + timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + fi + PID=$! + trap "kill -INT -$PID" INT + wait $PID + RESULT=$? + if [[ $RESULT -ne 0 ]]; then + echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" + fi + return $RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + hostport=(${1//:/ }) + HOST=${hostport[0]} + PORT=${hostport[1]} + shift 1 + ;; + --child) + CHILD=1 + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -s | --strict) + STRICT=1 + shift 1 + ;; + -h) + HOST="$2" + if [[ $HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + HOST="${1#*=}" + shift 1 + ;; + -p) + PORT="$2" + if [[ $PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + PORT="${1#*=}" + shift 1 + ;; + -t) + TIMEOUT="$2" + if [[ $TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + CLI="$@" + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$HOST" == "" || "$PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +TIMEOUT=${TIMEOUT:-15} +STRICT=${STRICT:-0} +CHILD=${CHILD:-0} +QUIET=${QUIET:-0} + +if [[ $CHILD -gt 0 ]]; then + wait_for + RESULT=$? + exit $RESULT +else + if [[ $TIMEOUT -gt 0 ]]; then + wait_for_wrapper + RESULT=$? + else + wait_for + RESULT=$? + fi +fi + +if [[ $CLI != "" ]]; then + if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then + echoerr "$cmdname: strict mode, refusing to execute subprocess" + exit $RESULT + fi + exec $CLI +else + exit $RESULT +fi diff --git a/docker-compose/Makefile b/docker-compose/Makefile index 5aa715b84f64f4038ce946aa2cd9c33f9c53ba23..d329b9bbb5bd6cbaff6cd0d06f9bf1f93ed47ae5 100644 --- a/docker-compose/Makefile +++ b/docker-compose/Makefile @@ -114,7 +114,9 @@ ifeq ($(NETWORK_MODE),host) MYSQL_HOST := $(shell hostname):3306 else ifeq ($(TANGO_HOST),) - TANGO_HOST := $(CONTAINER_NAME_PREFIX)databaseds:10000 + # Use FQDN for TANGO_HOST to avoid confusion in the archiver, which also + # adds the domain. + TANGO_HOST := $(CONTAINER_NAME_PREFIX)databaseds.$(NETWORK_MODE):10000 else TANGO_HOST := $(TANGO_HOST) endif @@ -181,6 +183,7 @@ bootstrap: pull build # first start, initialise from scratch $(MAKE) start dsconfig # boot up containers to load configurations sleep 5 # wait for dsconfig container to come up ../sbin/update_ConfigDb.sh ../CDB/LOFAR_ConfigDb.json # load default configuration + ../sbin/update_ConfigDb.sh ../CDB/tango-archiver-data/archiver-devices.json # load default archive configuration ../sbin/update_ConfigDb.sh ../CDB/stations/simulators_ConfigDb.json # by default, use simulators start: up ## start a service (usage: make start <servicename>) diff --git a/docker-compose/alerta-web/Dockerfile b/docker-compose/alerta-web/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..8a1845a7a3b9aed0a20cf30505be1cd3218bf729 --- /dev/null +++ b/docker-compose/alerta-web/Dockerfile @@ -0,0 +1,3 @@ +FROM alerta/alerta-web + +RUN pip install git+https://github.com/alerta/alerta-contrib.git#subdirectory=plugins/slack diff --git a/docker-compose/alerta.yml b/docker-compose/alerta.yml new file mode 100644 index 0000000000000000000000000000000000000000..5465fe19fe10a563df8527bc8cc64c4d93ee2895 --- /dev/null +++ b/docker-compose/alerta.yml @@ -0,0 +1,36 @@ +version: '2.1' + +volumes: + alerta-postgres-data: {} + +services: + alerta-web: + build: alerta-web + container_name: alerta-web + networks: + - control + ports: + - "8081:8080" + depends_on: + - alerta-db + environment: + - DEBUG=1 # remove this line to turn DEBUG off + - DATABASE_URL=postgres://postgres:postgres@alerta-db:5432/monitoring + - AUTH_REQUIRED=True + - ADMIN_USERS=admin #default password: alerta + - ADMIN_KEY=demo-key + - PLUGINS=reject,blackout,normalise,enhance + restart: always + + alerta-db: + image: postgres + container_name: alerta-db + networks: + - control + volumes: + - alerta-postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_DB: monitoring + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + restart: always diff --git a/docker-compose/grafana/alerting.json b/docker-compose/grafana/alerting.json new file mode 100644 index 0000000000000000000000000000000000000000..1a08e2cebfe5ebb77b22afbca6a0f70dd86ff4e5 --- /dev/null +++ b/docker-compose/grafana/alerting.json @@ -0,0 +1,26 @@ +{ + "template_files": {}, + "alertmanager_config": { + "route": { + "receiver": "Alerta" + }, + "templates": null, + "receivers": [ + { + "name": "Alerta", + "grafana_managed_receiver_configs": [ + { + "uid": "ROaAvQEnz", + "name": "Alerta", + "type": "webhook", + "disableResolveMessage": false, + "settings": { + "url": "http://alerta-web:8080/api/webhooks/prometheus?api-key=demo-key" + }, + "secureFields": {} + } + ] + } + ] + } +} diff --git a/docker-compose/tango-archiver-ts/Dockerfile b/docker-compose/tango-archiver-ts/Dockerfile index 98c3190c0ade4fb0b7457e6a983fc675e5eb8c3c..0d8b5e0c0ee0fe3efc174771b4556001c34a1789 100644 --- a/docker-compose/tango-archiver-ts/Dockerfile +++ b/docker-compose/tango-archiver-ts/Dockerfile @@ -29,8 +29,11 @@ RUN echo "deb http://deb.debian.org/debian buster-backports main contrib non-fre libpqxx-6.2 \ libpq-dev \ libpqxx-dev - -RUN git clone -b v2.0.0 https://github.com/Diego91RA/libhdbpp.git + + +# ----------- LIBHDB++ ----------------------------- + +RUN git clone -b master https://gitlab.com/tango-controls/hdbpp/donotusebadimport/libhdbpp.git RUN cd libhdbpp \ && mkdir build \ @@ -59,8 +62,11 @@ RUN cd libhdbpp/build \ --requires="libzmq5,libomniorb4-2,libcos4-2,libomnithread4" \ make install -RUN git clone -b master --recurse-submodules https://github.com/Diego91RA/libhdbpp-timescale.git -RUN cd libhdbpp-timescale && git checkout 85c03657d4518e876869b322d6a50c46875a1300 + +# ----------- LIBHDB++ TIMESCALE --------------- + +#RUN git clone -b image_support --recurse-submodules https://github.com/tango-controls-hdbpp/libhdbpp-timescale.git +RUN git clone -b image_support_lofar_fixes --recurse-submodules https://git.astron.nl/lofar2.0/libhdbpp-timescale.git RUN cd libhdbpp-timescale \ && mkdir -p build \ @@ -89,7 +95,10 @@ RUN cd libhdbpp-timescale/build \ --requires="libpq5" \ make install -RUN git clone -b v2.0.0 https://github.com/Diego91RA/hdbpp-cm.git + +# ----------- HDB++ CONFIGURATION MANAGER --------------- + +RUN git clone -b master https://github.com/tango-controls-hdbpp/hdbpp-cm.git RUN cd hdbpp-cm \ && mkdir -p build \ @@ -118,8 +127,10 @@ RUN cd hdbpp-cm/build \ --requires="libzmq5,libomniorb4-2,libcos4-2,libomnithread4" \ make install -RUN git clone -b master https://github.com/Diego91RA/hdbpp-es.git -RUN cd hdbpp-es && git checkout 473cbfbd7af76851bbf6ca2fcf5e4880e9f8e437 + +# ----------- HDB++ EVENT SUBSCRIBER --------------- + +RUN git clone -b master https://github.com/tango-controls-hdbpp/hdbpp-es.git RUN cd hdbpp-es \ && mkdir -p build \ diff --git a/docker-compose/tango.yml b/docker-compose/tango.yml index 166891b51f9a1ac59d3fcf837c3486f3199ad798..5a6839f44a356113ae1fc525a0ff6e3290e777cd 100644 --- a/docker-compose/tango.yml +++ b/docker-compose/tango.yml @@ -80,12 +80,10 @@ services: - TANGO_HOST=${TANGO_HOST} command: > sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict -- - json2tango -w -a -u /tango-archiver-data/archiver-devices.json && sleep infinity" volumes: - ..:/opt/lofar/tango:rw - ${HOME}:/hosthome - - ../CDB/tango-archiver-data:/tango-archiver-data logging: driver: syslog options: diff --git a/docker-compose/timescaledb/Dockerfile b/docker-compose/timescaledb/Dockerfile index 88e81b1ba2a3ffbb98f1016cfdcdfc255daec575..656d2ef661a13a5e84eadf7eda2ff6b27684d23c 100644 --- a/docker-compose/timescaledb/Dockerfile +++ b/docker-compose/timescaledb/Dockerfile @@ -4,22 +4,23 @@ FROM timescale/timescaledb:latest-pg12 COPY resources/01_admin.sh docker-entrypoint-initdb.d/002_admin.sh # Create DB schema (tables, indexes, etc.) COPY resources/02_hdb_schema.sql docker-entrypoint-initdb.d/003_hdb_schema.sql +COPY resources/03_hdb_images.sql docker-entrypoint-initdb.d/004_hdb_images.sql # Create DB roles -COPY resources/03_hdb_roles.sql docker-entrypoint-initdb.d/004_hdb_roles.sql +COPY resources/04_hdb_roles.sql docker-entrypoint-initdb.d/005_hdb_roles.sql # Create further roles -COPY resources/04_hdb_ext_users.sql docker-entrypoint-initdb.d/005_hdb_ext_users.sql +COPY resources/05_hdb_ext_users.sql docker-entrypoint-initdb.d/006_hdb_ext_users.sql # Add further functions -COPY resources/05_hdb_ext_import.sql docker-entrypoint-initdb.d/006_hdb_ext_import.sql +COPY resources/06_hdb_ext_import.sql docker-entrypoint-initdb.d/007_hdb_ext_import.sql # Create timescaledb aggregates -COPY resources/06_hdb_ext_aggregates.sql docker-entrypoint-initdb.d/007_hdb_ext_aggregates.sql -COPY resources/07_hdb_ext_arrays_aggregates_helper.sql docker-entrypoint-initdb.d/008_hdb_ext_arrays_aggregates_helper.sql -COPY resources/08_hdb_ext_arrays_aggregates.sql docker-entrypoint-initdb.d/009_hdb_ext_arrays_aggregates.sql +COPY resources/07_hdb_ext_aggregates.sql docker-entrypoint-initdb.d/008_hdb_ext_aggregates.sql +COPY resources/08_hdb_ext_arrays_aggregates_helper.sql docker-entrypoint-initdb.d/009_hdb_ext_arrays_aggregates_helper.sql +COPY resources/09_hdb_ext_arrays_aggregates.sql docker-entrypoint-initdb.d/010_hdb_ext_arrays_aggregates.sql # Add compress policy -COPY resources/09_hdb_ext_compress_policy.sql docker-entrypoint-initdb.d/010_hdb_ext_compress_policy.sql +COPY resources/10_hdb_ext_compress_policy.sql docker-entrypoint-initdb.d/011_hdb_ext_compress_policy.sql # Add reorder policy -COPY resources/10_hdb_ext_reorder_policy.sql docker-entrypoint-initdb.d/011_hdb_ext_reorder_policy.sql +COPY resources/11_hdb_ext_reorder_policy.sql docker-entrypoint-initdb.d/012_hdb_ext_reorder_policy.sql # Add LOFAR functions and views -COPY resources/11_lofar_func.sh docker-entrypoint-initdb.d/012_lofar_func.sh -COPY resources/12_lofar_views.sql docker-entrypoint-initdb.d/013_lofar_views.sql +COPY resources/12_lofar_func.sh docker-entrypoint-initdb.d/013_lofar_func.sh +COPY resources/13_lofar_views.sql docker-entrypoint-initdb.d/014_lofar_views.sql # Cleanup admin role -COPY resources/13_cleanup.sql docker-entrypoint-initdb.d/014_cleanup.sql +COPY resources/14_cleanup.sql docker-entrypoint-initdb.d/015_cleanup.sql diff --git a/docker-compose/timescaledb/resources/03_hdb_images.sql b/docker-compose/timescaledb/resources/03_hdb_images.sql new file mode 100644 index 0000000000000000000000000000000000000000..7eb58950bade5cf9af0551a6484f809b4bf7f3a8 --- /dev/null +++ b/docker-compose/timescaledb/resources/03_hdb_images.sql @@ -0,0 +1,298 @@ +-- ----------------------------------------------------------------------------- +-- This file is part of the hdbpp-timescale-project +-- +-- Copyright (C) : 2014-2019 +-- European Synchrotron Radiation Facility +-- BP 220, Grenoble 38043, FRANCE +-- +-- libhdb++timescale is free software: you can redistribute it and/or modify +-- it under the terms of the Lesser GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- libhdb++timescale is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser +-- GNU General Public License for more details. +-- +-- You should have received a copy of the Lesser GNU General Public License +-- along with libhdb++timescale. If not, see <http://www.gnu.org/licenses/>. +-- ----------------------------------------------------------------------------- + +\c hdb + +CREATE TABLE IF NOT EXISTS att_image_devboolean ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r boolean[][], + value_w boolean[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devboolean IS 'Array Boolean Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devboolean_att_conf_id_idx ON att_array_devboolean (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devboolean_att_conf_id_data_time_idx ON att_array_devboolean (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devboolean', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devuchar ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r uchar[][], + value_w uchar[][], + quality smallint, + details json, + att_error_desc_id integer, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devuchar IS 'Array UChar Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devuchar_att_conf_id_idx ON att_array_devuchar (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devuchar_att_conf_id_data_time_idx ON att_array_devuchar (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devuchar', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devshort ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r smallint[][], + value_w smallint[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devshort IS 'Array Short Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devshort_att_conf_id_idx ON att_array_devshort (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devshort_att_conf_id_data_time_idx ON att_array_devshort (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devshort', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devushort ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r ushort[][], + value_w ushort[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devushort IS 'Array UShort Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devushort_att_conf_id_idx ON att_array_devushort (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devushort_att_conf_id_data_time_idx ON att_array_devushort (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devushort', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devlong ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r integer[][], + value_w integer[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devlong IS 'Array Long Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devlong_att_conf_id_idx ON att_array_devlong (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devlong_att_conf_id_data_time_idx ON att_array_devlong (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devlong', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devulong ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r ulong[][], + value_w ulong[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devulong IS 'Array ULong Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devulong_att_conf_id_idx ON att_array_devulong (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devulong_att_conf_id_data_time_idx ON att_array_devulong (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devulong', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devlong64 ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r bigint[][], + value_w bigint[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devlong64 IS 'Array Long64 Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devlong64_att_conf_id_idx ON att_array_devlong64 (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devlong64_att_conf_id_data_time_idx ON att_array_devlong64 (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devlong64', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devulong64 ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r ulong64[][], + value_w ulong64[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devulong64 IS 'Array ULong64 Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devulong64_att_conf_id_idx ON att_array_devulong64 (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devulong64_att_conf_id_data_time_idx ON att_array_devulong64 (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devulong64', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devfloat ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r real[][], + value_w real[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devfloat IS 'Array Float Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devfloat_att_conf_id_idx ON att_array_devfloat (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devfloat_att_conf_id_data_time_idx ON att_array_devfloat (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devfloat', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devdouble ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r double precision[][], + value_w double precision[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devdouble IS 'Array Double Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devdouble_att_conf_id_idx ON att_array_devdouble (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devdouble_att_conf_id_data_time_idx ON att_array_devdouble (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devdouble', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devstring ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r text[][], + value_w text[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devstring IS 'Array String Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devstring_att_conf_id_idx ON att_array_devstring (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devstring_att_conf_id_data_time_idx ON att_array_devstring (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devstring', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devstate ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r integer[][], + value_w integer[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devstate IS 'Array State Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devstate_att_conf_id_idx ON att_array_devstate (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devstate_att_conf_id_data_time_idx ON att_array_devstate (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devstate', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devencoded ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r bytea[][], + value_w bytea[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); +COMMENT ON TABLE att_image_devencoded IS 'Array DevEncoded Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devencoded_att_conf_id_idx ON att_array_devencoded (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devencoded_att_conf_id_data_time_idx ON att_array_devencoded (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devencoded', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +CREATE TABLE IF NOT EXISTS att_image_devenum ( + att_conf_id integer NOT NULL, + data_time timestamp WITH TIME ZONE NOT NULL, + value_r_label text[][], + value_r smallint[][], + value_w_label text[][], + value_w smallint[][], + quality smallint, + att_error_desc_id integer, + details json, + PRIMARY KEY (att_conf_id, data_time), + FOREIGN KEY (att_conf_id) REFERENCES att_conf (att_conf_id), + FOREIGN KEY (att_error_desc_id) REFERENCES att_error_desc (att_error_desc_id) +); + +COMMENT ON TABLE att_image_devenum IS 'Array Enum Values Table'; +CREATE INDEX IF NOT EXISTS att_image_devenum_att_conf_id_idx ON att_array_devenum (att_conf_id); +CREATE INDEX IF NOT EXISTS att_image_devenum_att_conf_id_data_time_idx ON att_array_devenum (att_conf_id,data_time DESC); +SELECT create_hypertable('att_image_devenum', 'data_time', chunk_time_interval => interval '28 day', create_default_indexes => FALSE); + +-- Trigger to set the enum_labels +CREATE OR REPLACE FUNCTION set_enum_label_array() RETURNS TRIGGER AS $$ +DECLARE +BEGIN + IF NEW.value_r IS NOT NULL THEN + WITH enum_labels AS ( + SELECT enum_labels FROM att_parameter WHERE att_conf_id=NEW.att_conf_id ORDER BY recv_time DESC limit 1 + ) + SELECT array_agg(res) FROM (SELECT enum_labels[UNNEST(NEW.value_r)+ 1] FROM enum_labels) as res INTO NEW.value_r_label; + END IF; + IF NEW.value_w IS NOT NULL THEN + WITH enum_labels AS ( + SELECT enum_labels FROM att_parameter WHERE att_conf_id=NEW.att_conf_id ORDER BY recv_time DESC limit 1 + ) + SELECT array_agg(res) FROM (SELECT enum_labels[UNNEST(NEW.value_w)+ 1] FROM enum_labels) as res INTO NEW.value_w_label; + END IF; + RETURN NEW; +END +$$ LANGUAGE plpgsql; + +CREATE TRIGGER enum_label_trigger BEFORE INSERT ON att_image_devenum FOR EACH ROW EXECUTE PROCEDURE set_enum_label_array(); + diff --git a/docker-compose/timescaledb/resources/03_hdb_roles.sql b/docker-compose/timescaledb/resources/04_hdb_roles.sql similarity index 100% rename from docker-compose/timescaledb/resources/03_hdb_roles.sql rename to docker-compose/timescaledb/resources/04_hdb_roles.sql diff --git a/docker-compose/timescaledb/resources/04_hdb_ext_users.sql b/docker-compose/timescaledb/resources/05_hdb_ext_users.sql similarity index 100% rename from docker-compose/timescaledb/resources/04_hdb_ext_users.sql rename to docker-compose/timescaledb/resources/05_hdb_ext_users.sql diff --git a/docker-compose/timescaledb/resources/05_hdb_ext_import.sql b/docker-compose/timescaledb/resources/06_hdb_ext_import.sql similarity index 100% rename from docker-compose/timescaledb/resources/05_hdb_ext_import.sql rename to docker-compose/timescaledb/resources/06_hdb_ext_import.sql diff --git a/docker-compose/timescaledb/resources/06_hdb_ext_aggregates.sql b/docker-compose/timescaledb/resources/07_hdb_ext_aggregates.sql similarity index 100% rename from docker-compose/timescaledb/resources/06_hdb_ext_aggregates.sql rename to docker-compose/timescaledb/resources/07_hdb_ext_aggregates.sql diff --git a/docker-compose/timescaledb/resources/07_hdb_ext_arrays_aggregates_helper.sql b/docker-compose/timescaledb/resources/08_hdb_ext_arrays_aggregates_helper.sql similarity index 100% rename from docker-compose/timescaledb/resources/07_hdb_ext_arrays_aggregates_helper.sql rename to docker-compose/timescaledb/resources/08_hdb_ext_arrays_aggregates_helper.sql diff --git a/docker-compose/timescaledb/resources/08_hdb_ext_arrays_aggregates.sql b/docker-compose/timescaledb/resources/09_hdb_ext_arrays_aggregates.sql similarity index 100% rename from docker-compose/timescaledb/resources/08_hdb_ext_arrays_aggregates.sql rename to docker-compose/timescaledb/resources/09_hdb_ext_arrays_aggregates.sql diff --git a/docker-compose/timescaledb/resources/09_hdb_ext_compress_policy.sql b/docker-compose/timescaledb/resources/10_hdb_ext_compress_policy.sql similarity index 100% rename from docker-compose/timescaledb/resources/09_hdb_ext_compress_policy.sql rename to docker-compose/timescaledb/resources/10_hdb_ext_compress_policy.sql diff --git a/docker-compose/timescaledb/resources/10_lofar_views.sh b/docker-compose/timescaledb/resources/10_lofar_views.sh new file mode 100644 index 0000000000000000000000000000000000000000..7d7fb8cec25bd53f017fd1086636cec1be769755 --- /dev/null +++ b/docker-compose/timescaledb/resources/10_lofar_views.sh @@ -0,0 +1,427 @@ +#!/bin/bash +psql << EOF +\c hdb + +-- NOTE: We concatenate domain/family/member here, which means we can't index +-- the resulting column. However, queries also supply the attribute name, +-- which we can index. The scan on the device name is then limited to +-- entries which have the same attribute name across devices. + +CREATE OR REPLACE VIEW lofar_scalar_double AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + 0 AS x, + value_r as value + FROM att_scalar_devdouble att + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devboolean AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devboolean att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devuchar AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devuchar att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devshort AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devshort att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devushort AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devushort att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devlong AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devlong att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devulong AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devulong att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devlong64 AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devlong64 att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devulong64 AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devulong64 att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devfloat AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devfloat att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devdouble AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devdouble att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devstring AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devstring att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devstate AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devstate att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devencoded AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devencoded att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_array_devenum AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + array_element.idx - 1 AS x, + array_element.val as value + FROM att_array_devenum att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devboolean AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devboolean att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devuchar AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devuchar att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devshort AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devshort att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devushort AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devushort att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devlong AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devlong att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devulong AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devulong att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devlong64 AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devlong64 att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devulong64 AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devulong64 att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devfloat AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devfloat att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devdouble AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devdouble att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devstring AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devstring att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devstate AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devstate att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devencoded AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devencoded att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; + +CREATE OR REPLACE VIEW lofar_image_devenum AS + SELECT + att.data_time AS data_time, + CONCAT_WS('/', domain, family, member) AS device, + ac.name AS name, + (array_element.idx - 1) / ARRAY_LENGTH(att.value_r, 1) AS x, + (array_element.idx - 1) % ARRAY_LENGTH(att.value_r, 1) AS y, + array_element.val as value + FROM att_image_devenum att + -- add array values, and their index + JOIN LATERAL UNNEST(att.value_r) WITH ORDINALITY AS array_element(val,idx) ON TRUE + -- add the device information + JOIN att_conf ac ON att.att_conf_id = ac.att_conf_id + WHERE att.value_r IS NOT NULL; +EOF diff --git a/docker-compose/timescaledb/resources/10_hdb_ext_reorder_policy.sql b/docker-compose/timescaledb/resources/11_hdb_ext_reorder_policy.sql similarity index 100% rename from docker-compose/timescaledb/resources/10_hdb_ext_reorder_policy.sql rename to docker-compose/timescaledb/resources/11_hdb_ext_reorder_policy.sql diff --git a/docker-compose/timescaledb/resources/11_lofar_func.sh b/docker-compose/timescaledb/resources/12_lofar_func.sh similarity index 100% rename from docker-compose/timescaledb/resources/11_lofar_func.sh rename to docker-compose/timescaledb/resources/12_lofar_func.sh diff --git a/docker-compose/timescaledb/resources/12_lofar_views.sql b/docker-compose/timescaledb/resources/13_lofar_views.sql similarity index 100% rename from docker-compose/timescaledb/resources/12_lofar_views.sql rename to docker-compose/timescaledb/resources/13_lofar_views.sql diff --git a/docker-compose/timescaledb/resources/13_cleanup.sql b/docker-compose/timescaledb/resources/14_cleanup.sql similarity index 100% rename from docker-compose/timescaledb/resources/13_cleanup.sql rename to docker-compose/timescaledb/resources/14_cleanup.sql diff --git a/jupyter-notebooks/archiving_demo.ipynb b/jupyter-notebooks/archiving_demo.ipynb index ae6e656b319177a31f5bc052d80dbb0e60ba306d..d478c20c71ce35a7c4d017a180bdd404d0b06c2d 100644 --- a/jupyter-notebooks/archiving_demo.ipynb +++ b/jupyter-notebooks/archiving_demo.ipynb @@ -11,6 +11,7 @@ "import numpy as np\n", "sys.path.append('/hosthome/tango/tangostationcontrol/tangostationcontrol/')\n", "from toolkit.archiver_util import *\n", + "from toolkit.archiver_configurator import *\n", "from toolkit.archiver import *\n", "from toolkit.retriever import *\n", "from matplotlib import pyplot as plt" @@ -30,16 +31,43 @@ { "cell_type": "code", "execution_count": null, - "id": "c1eedafb", + "id": "b3748c34", "metadata": {}, "outputs": [], + "source": [ + "# Safety cleanup\n", + "DeviceProxy(archiver.get_subscribers()[0]).delete_property('AttributeList')\n", + "DeviceProxy(archiver.get_subscribers()[0]).delete_property('__SubDevices')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1eedafb", + "metadata": { + "scrolled": true + }, + "outputs": [], "source": [ "# Apply the chosen JSON configuration file in directory toolkit/archiver_config/\n", "config_dict = archiver.get_configuration()\n", - "print(config_dict)\n", + "#print(config_dict)\n", "archiver.apply_configuration(config_dict)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "76e9656f", + "metadata": {}, + "outputs": [], + "source": [ + "# Print max loads\n", + "# print(DATATYPES_SIZE_DICT)\n", + "print(archiver.get_maximum_device_load('STAT/SDP/1'))\n", + "print(archiver.get_maximum_device_load('STAT/RECV/1'))" + ] + }, { "cell_type": "code", "execution_count": null, @@ -49,8 +77,9 @@ "source": [ "# RECV device\n", "device_name = 'STAT/RECV/1'\n", + "#device_name = 'STAT/UNB2/1'\n", "d=DeviceProxy(device_name) \n", - "d.set_timeout_millis(10000)\n", + "d.set_timeout_millis(30000)\n", "state = str(d.state())\n", "print(device_name + ' : ' + state)" ] @@ -118,17 +147,6 @@ " print(f\"Device {device_name} is now in ON state\")" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "6fad043c", - "metadata": {}, - "outputs": [], - "source": [ - "# Optional\n", - "archiver.remove_attributes_in_error()" - ] - }, { "cell_type": "code", "execution_count": null, @@ -137,38 +155,41 @@ "outputs": [], "source": [ "# Add boolean scalar attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/RECVTR_translator_busy_R', polling_period=1000, event_period=5000)\n", + "archiver.add_attribute_to_archiver('stat/recv/1/RECVTR_translator_busy_R', polling_period=1000, archive_event_period=5000)\n", "# Add boolean array attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/rcu_mask_rw', polling_period=1000, event_period=5000)\n", + "archiver.add_attribute_to_archiver('stat/recv/1/rcu_mask_rw', polling_period=1000, archive_event_period=5000)\n", + "# Add boolean image attribute\n", + "archiver.add_attribute_to_archiver('stat/recv/1/ANT_mask_RW', polling_period=1000, archive_event_period=5000)\n", "\n", "# Add double scalar attribute\n", - "archiver.add_attribute_to_archiver('stat/sdp/1/TR_tod_pps_delta_R', polling_period=1000, event_period=5000)\n", + "archiver.add_attribute_to_archiver('stat/sdp/1/TR_tod_pps_delta_R', polling_period=1000, archive_event_period=5000)\n", "# Add double array attribute\n", - "archiver.add_attribute_to_archiver('stat/sdp/1/fpga_temp_r', polling_period=1000, event_period=5000)\n", - "\n", - "# Add ushort array attribute\n", - "archiver.add_attribute_to_archiver('stat/sdp/1/FPGA_beamlet_output_hdr_udp_destination_port_R', polling_period=1000, event_period=5000)\n", + "archiver.add_attribute_to_archiver('stat/sdp/1/fpga_temp_r', polling_period=1000, archive_event_period=5000)\n", + "# Add double image attribute\n", + "archiver.add_attribute_to_archiver('stat/recv/1/HBAT_antenna_ITRF_offsets_R', polling_period=1000, archive_event_period=5000)\n", "\n", "# Add long array attribute\n", - "archiver.add_attribute_to_archiver('stat/sdp/1/FPGA_bsn_monitor_input_nof_err_R', polling_period=1000, event_period=5000)\n", + "#archiver.add_attribute_to_archiver('stat/sdp/1/FPGA_bsn_monitor_input_nof_err_R', polling_period=1000, archive_event_period=5000)\n", "\n", "# Add ulong scalar attribute\n", - "archiver.add_attribute_to_archiver('stat/sdp/1/TR_sdp_config_first_fpga_nr_R', polling_period=1000, event_period=5000)\n", + "#archiver.add_attribute_to_archiver('stat/sdp/1/TR_sdp_config_first_fpga_nr_R', polling_period=1000, archive_event_period=5000)\n", "# Add ulong array attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/RCU_LED_colour_R', polling_period=1000, event_period=5000)\n", + "#archiver.add_attribute_to_archiver('stat/recv/1/RCU_LED_colour_R', polling_period=1000, archive_event_period=5000)\n", "\n", "# Add long64 scalar attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/RECVTR_monitor_rate_RW', polling_period=1000, event_period=5000)\n", + "archiver.add_attribute_to_archiver('stat/recv/1/RECVTR_monitor_rate_RW', polling_period=1000, archive_event_period=5000)\n", "# Add long64 array attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/RCU_PCB_ID_R', polling_period=1000, event_period=5000)\n", + "archiver.add_attribute_to_archiver('stat/recv/1/RCU_PCB_ID_R', polling_period=1000, archive_event_period=5000)\n", + "# Add long64 image attribute\n", + "archiver.add_attribute_to_archiver('stat/recv/1/HBAT_BF_delay_steps_R', polling_period=1000, archive_event_period=5000)\n", "\n", "# Add string scalar attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/status', polling_period=1000, event_period=5000)\n", + "#archiver.add_attribute_to_archiver('stat/recv/1/status', polling_period=1000, archive_event_period=5000)\n", "# Add string array attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/opcua_missing_attributes_R', polling_period=1000, event_period=5000)\n", + "#archiver.add_attribute_to_archiver('stat/recv/1/opcua_missing_attributes_R', polling_period=1000, archive_event_period=5000)\n", "\n", "# Add state scalar attribute\n", - "archiver.add_attribute_to_archiver('stat/recv/1/state', polling_period=1000, event_period=5000)" + "#archiver.add_attribute_to_archiver('stat/recv/1/state', polling_period=1000, archive_event_period=5000)" ] }, { @@ -220,16 +241,6 @@ "values = [float(item.value_r) for item in records]" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "3dcab007", - "metadata": {}, - "outputs": [], - "source": [ - "values" - ] - }, { "cell_type": "code", "execution_count": null, @@ -267,6 +278,53 @@ "views_records = retriever.get_lofar_attribute('stat/sdp/1/fpga_temp_r')\n", "views_records" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7a624b0", + "metadata": {}, + "outputs": [], + "source": [ + "d.off()\n", + "d2.off()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e08fc4a", + "metadata": {}, + "outputs": [], + "source": [ + "# Retrieve boolean image attributes\n", + "attr_name = 'stat/recv/1/ant_mask_rw'\n", + "records = retriever.get_attribute_value_by_hours(attr_name,1.5)\n", + "print(np.array(records[0].value_r).shape)\n", + "#records[0].value_r" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb2f36f6", + "metadata": {}, + "outputs": [], + "source": [ + "# Retrieve numeric image attributes\n", + "attr_name = 'stat/recv/1/HBAT_antenna_ITRF_offsets_R'.lower()\n", + "records = retriever.get_attribute_value_by_hours(attr_name,0.5)\n", + "print(np.array(records[0].value_r).shape)\n", + "#records[0].value_r" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a53be0f9", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh index a044d46c9eba08e7d503a135cd911b634482cbfd..192592858526d0c9f446836e96bd5919bc7eb46a 100755 --- a/sbin/run_integration_test.sh +++ b/sbin/run_integration_test.sh @@ -11,34 +11,48 @@ fi cd "$LOFAR20_DIR/docker-compose" || exit 1 +# Start the database server first +make build databaseds dsconfig +make start databaseds dsconfig + +# Give dsconfig and databaseds time to start +sleep 1 # dsconfig container must be up and running... +# shellcheck disable=SC2016 +echo '/usr/local/bin/wait-for-it.sh ${TANGO_HOST} --strict --timeout=300 -- true' | make run dsconfig bash - + +DEVICES="device-boot device-apsct device-apspu device-sdp device-recv device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-antennafield" +SIMULATORS="sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim" + # Build only the required images, please do not build everything that makes CI # take really long to finish, especially grafana / jupyter / prometheus. # jupyter is physically large > 2.5gb and overlayfs is really slow. -make build device-sdp device-recv device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-antennafield -make build sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim -make build databaseds dsconfig elk integration-test +# shellcheck disable=SC2086 +make build $DEVICES $SIMULATORS +make build elk integration-test make build archiver-timescale hdbppts-cm hdbppts-es # Start and stop sequence -make stop device-boot device-docker device-apsct device-apspu device-sdp device-recv device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-antennafield device-tilebeam sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim hdbppts-es hdbppts-cm archiver-timescale -make start databaseds dsconfig elk - -# Give dsconfig and databaseds time to start -sleep 60 +# shellcheck disable=SC2086 +make stop $DEVICES $SIMULATORS hdbppts-es hdbppts-cm archiver-timescale +make stop device-docker # this one does not test well in docker-in-docker +make start elk # Update the dsconfig # 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/tango-archiver-data/archiver-devices.json bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/stations/simulators_ConfigDb.json bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/stations/dummy_positions_ConfigDb.json cd "$LOFAR20_DIR/docker-compose" || exit 1 -make start sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim +# shellcheck disable=SC2086 +make start $SIMULATORS # Give the simulators time to start sleep 5 -make start device-boot device-apsct device-apspu device-sdp device-recv device-sst device-unb2 device-xst device-tilebeam device-beamlet device-digitalbeam device-antennafield +# shellcheck disable=SC2086 +make start $DEVICES # Archive devices -> starting order is important make start archiver-timescale hdbppts-cm hdbppts-es @@ -46,9 +60,20 @@ make start archiver-timescale hdbppts-cm hdbppts-es # TODO(Corne Lukken): Use a nicer more reliable mechanism sleep 60 +# Give archiver-timescale time to start +# shellcheck disable=SC2016 +echo '/usr/local/bin/wait-for-it.sh archiver-timescale:5432 --strict --timeout=300 -- true' | make run dsconfig bash - + # Start the integration test cd "$LOFAR20_DIR/docker-compose" || exit 1 make up integration-test # Run the default integration tests make run integration-test default + +# Configure integration test for recv_cluster module +bash "${LOFAR20_DIR}"/sbin/update_ConfigDb.sh "${LOFAR20_DIR}"/CDB/integrations/recvcluster_ConfigDb.json +make restart device-recv device-tilebeam +sleep 5 + +make run integration-test recv_cluster diff --git a/tangostationcontrol/docs/source/installation.rst b/tangostationcontrol/docs/source/installation.rst index 2699d1baa5198cc4757b49da7cd7fa360c3ee2f1..fd01fe45e0b27de2170c23341ab04e1c6b97f900 100644 --- a/tangostationcontrol/docs/source/installation.rst +++ b/tangostationcontrol/docs/source/installation.rst @@ -72,3 +72,19 @@ The ELK stack requires some kernel settings to be tuned, before it will start. A make restart elk after reboot, or configure your system to set ``sysctl -w vm.max_map_count=262144`` (or higher) as root during boot. + +Configuration +--------------------------- + +These sections are optional, to configure specific functionality you may or may not want to use. + +Alerta +```````` + +If you want Grafana alerts to appear in Alerta, you need to manually configure Grafana to forward them. Import the alert settings manually: + +- Go to Grafana (http://localhost:3000) and sign in with an administration account (default: admin/admin), +- Go to ``Alerting`` and select ``Admin`` in the left menu bar, +- Copy/paste the following information, and press ``Save``: + +.. literalinclude:: ../../../docker-compose/grafana/alerting.json diff --git a/tangostationcontrol/docs/source/interfaces/overview.rst b/tangostationcontrol/docs/source/interfaces/overview.rst index a00ab5710ad863b4f10d1bb0ee93ab3f547826d5..e077c73dde0f7467807cbbf0c7f8d8abe797a205 100644 --- a/tangostationcontrol/docs/source/interfaces/overview.rst +++ b/tangostationcontrol/docs/source/interfaces/overview.rst @@ -10,6 +10,8 @@ The station provides the following interfaces accessible through your browser (a +---------------------+---------+----------------------+-------------------+ | :doc:`monitoring` |Grafana |http://localhost:3000 |admin/admin | +---------------------+---------+----------------------+-------------------+ +| Alerting |Alerta |http://localhost:8081 |admin/alerta | ++---------------------+---------+----------------------+-------------------+ | :doc:`logs` |Kibana |http://localhost:5601 | | +---------------------+---------+----------------------+-------------------+ diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py index dd8bd1c2a7698d2c2481dbb52d60e99541f7e43b..75ef8f612b3bfd44735444fba95d8927226fe55a 100644 --- a/tangostationcontrol/tangostationcontrol/devices/apsct.py +++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py @@ -14,7 +14,7 @@ # PyTango imports from tango import DebugIt from tango.server import command, attribute, device_property -from tango import AttrWriteType, DevState +from tango import AttrWriteType import numpy # Additional import @@ -23,6 +23,7 @@ from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.common.lofar_logging import device_logging_to_python from tangostationcontrol.devices.device_decorators import * from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.devices.lofar_device import lofar_device import logging logger = logging.getLogger() @@ -138,7 +139,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def APSCT_off(self): """ @@ -148,7 +149,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def APSCT_200MHz_on(self): """ @@ -158,7 +159,7 @@ class APSCT(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def APSCT_160MHz_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/devices/beam_device.py b/tangostationcontrol/tangostationcontrol/devices/beam_device.py new file mode 100644 index 0000000000000000000000000000000000000000..0b436d89b2191b33f059094a89740d66382d927b --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/devices/beam_device.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# +# Distributed under the terms of the APACHE license. +# See LICENSE.txt for more info. + +"""Beam Abstract Device Server for LOFAR2.0 + +""" +# PyTango imports +from tango.server import attribute, command +from tango import AttrWriteType, DebugIt + +# Additional import +from tangostationcontrol.common.entrypoint import entry +from tangostationcontrol.common.measures import get_measures_directory, get_available_measures_directories, download_measures, use_measures_directory, restart_python +from tangostationcontrol.common.lofar_logging import log_exceptions +from tangostationcontrol.devices.lofar_device import lofar_device + +__all__ = ["beam_device", "main"] + +import logging +logger = logging.getLogger() + + +class beam_device(lofar_device): + + # ---------- + # Attributes + # ---------- + + # Directory where the casacore measures that we use, reside. We configure ~/.casarc to + # use the symlink /opt/IERS/current, which we switch to the actual set of files to use. + measures_directory_R = attribute(dtype=str, access=AttrWriteType.READ, fget = lambda self: get_measures_directory()) + + # List of dowloaded measures (the latest 64, anyway) + measures_directories_available_R = attribute(dtype=(str,), max_dim_x=64, access=AttrWriteType.READ, fget = lambda self: sorted(get_available_measures_directories())[-64:]) + + # -------- + # Commands + # -------- + + @command(dtype_out=str, doc_out="Name of newly installed measures directory") + @DebugIt() + @log_exceptions() + def download_measures(self): + """ Download new measures tables into /opt/IERS, but do not activate them. + + NOTE: This may take a while to complete. You are advised to increase + the timeout of the proxy using `my_device.set_timeout_millis(10000)`. """ + + return download_measures() + + @command(dtype_in=str, doc_in="Measures directory to activate") + @DebugIt() + @log_exceptions() + def use_measures(self, newdir): + """ Activate a downloaded set of measures tables. + + NOTE: This will turn off and restart this device!! """ + + # switch to requested measures + use_measures_directory(newdir) + logger.info(f"Switched measures table to {newdir}") + + # turn off our device, to prepare for a python restart + self.Off() + + # restart this program to force casacore to adopt + # the new tables + logger.warning("Restarting device to activate new measures tables") + restart_python() + +# ---------- +# Run server +# ---------- +def main(**kwargs): + """Main function of the Docker module.""" + return entry(beam_device, **kwargs) diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py index beefe5b8f91516de4a4f2f911df8383e9980b50f..edce4de96d049d223664cc8ca4428cd743591306 100644 --- a/tangostationcontrol/tangostationcontrol/devices/boot.py +++ b/tangostationcontrol/tangostationcontrol/devices/boot.py @@ -50,7 +50,7 @@ class DevicesInitialiser(object): the start() method, and progress can be followed by inspecting the members progress (0-100), status (string), and is_running() (bool). """ - def __init__(self, device_names, reboot=False, initialise_hardware=True, proxy_timeout=10.0): + def __init__(self, device_names, reboot=False, initialise_hardware=True, proxy_timeout=60.0): self.reboot = reboot self.initialise_hardware = initialise_hardware @@ -153,7 +153,7 @@ class DevicesInitialiser(object): continue if self.is_available(device): - if self.reboot or self.devices[device].state() not in [DevState.ON, DevState.ALARM]: + if self.reboot or self.devices[device].state() not in lofar_device.OPERATIONAL_STATES: self.stop_device(device) self.boot_device(device) @@ -204,7 +204,7 @@ class DevicesInitialiser(object): else: proxy.warm_boot() - if proxy.state() not in [DevState.ON, DevState.ALARM]: # ALARM still means booting was succesful + if proxy.state() not in lofar_device.OPERATIONAL_STATES: raise InitialisationException(f"Could not boot device {device_name}. It reports status: {proxy.status()}") self.set_status(f"[restarting {device_name}] Succesfully booted.") @@ -218,7 +218,7 @@ class Boot(lofar_device): DeviceProxy_Time_Out = device_property( dtype='DevDouble', mandatory=False, - default_value=30.0, + default_value=60.0, ) # Initialise the hardware when initialising a station. Can end badly when using simulators. @@ -314,14 +314,14 @@ class Boot(lofar_device): @command() @DebugIt() - @only_in_states([DevState.ON]) + @only_in_states(lofar_device.OPERATIONAL_STATES) @log_exceptions() def boot(self): self._boot(reboot=False, initialise_hardware=self.Initialise_Hardware) @command() @DebugIt() - @only_in_states([DevState.ON]) + @only_in_states(lofar_device.OPERATIONAL_STATES) @log_exceptions() def reboot(self): self._boot(reboot=True, initialise_hardware=self.Initialise_Hardware) diff --git a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py index 740d45626ae02dcb62b1ff2a00d5b30b31be91ab..cc276428d962fa006d2ef0619790b65c1f2ba270 100644 --- a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py @@ -41,6 +41,7 @@ class lofar_device(Device, metaclass=DeviceMeta): INIT = Device is initialising. STANDBY = Device is initialised, but pends external configuration and an explicit turning on, ON = Device is fully configured, functional, controls the hardware, and is possibly actively running, + ALARM = Device is operating but one of its attributes is out of range, FAULT = Device detected an unrecoverable error, and is thus malfunctional, OFF = Device is turned off, drops connection to the hardware, @@ -49,6 +50,7 @@ class lofar_device(Device, metaclass=DeviceMeta): OFF -> INIT: Triggered by device. Device will initialise (connect to hardware, other devices), INIT -> STANDBY: Triggered by device. Device is initialised, and is ready for additional configuration by the user, STANDBY -> ON: Triggered by user. Device reports to be functional, + ON -> ALARM: Triggered by tango. Device has attribute(s) with value(s) exceeding their alarm treshold, * -> FAULT: Triggered by device. Device has degraded to malfunctional, for example because the connection to the hardware is lost, * -> FAULT: Triggered by user. Emulate a forced malfunction for integration testing purposes, * -> OFF: Triggered by user. Device is turned off. Triggered by the Off() command, @@ -57,6 +59,17 @@ class lofar_device(Device, metaclass=DeviceMeta): The user triggers their transitions by the commands reflecting the target state (Initialise(), On(), Fault()). """ + # The Device states in which we consider our device operational, + # and thus allow interaction. + OPERATIONAL_STATES = [DevState.ON, DevState.ALARM] + + # States in which Initialise() has happened, and the hardware + # can thus be configured or otherwise interacted with. + INITIALISED_STATES = OPERATIONAL_STATES + [DevState.STANDBY] + + # States in which most commands are allowed + DEFAULT_COMMAND_STATES = INITIALISED_STATES + # ---------- # Attributes # ---------- @@ -159,7 +172,7 @@ class lofar_device(Device, metaclass=DeviceMeta): self.set_status("Device is in the STANDBY state.") @command() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(INITIALISED_STATES) @DebugIt() @fault_on_error() @log_exceptions() @@ -204,7 +217,6 @@ class lofar_device(Device, metaclass=DeviceMeta): @command() - @only_in_states([DevState.ON, DevState.INIT, DevState.STANDBY, DevState.FAULT]) @DebugIt() @log_exceptions() def Fault(self, new_status="Device is in the FAULT state."): @@ -216,6 +228,9 @@ class lofar_device(Device, metaclass=DeviceMeta): :return:None """ + if self.get_state() == DevState.OFF: + raise Exception("IllegalCommand: Cannot go from FAULT -> OFF") + if self.get_state() == DevState.FAULT: # Already faulting. Don't complain. logger.warning("Requested to go to FAULT state, but am already in FAULT state.") @@ -228,15 +243,19 @@ class lofar_device(Device, metaclass=DeviceMeta): # functions that can or must be overloaded def configure_for_fault(self): + """Overloadable function called in Fault after state is set to FAULT""" pass def configure_for_off(self): + """Overloadable function called in Off after state is set to OFF""" pass def configure_for_on(self): + """Overloadable function called in On BEFORE state is set to ON""" pass def configure_for_initialise(self): + """Overloadable function called in initialise with state INIT, STANDBY after call""" pass def always_executed_hook(self): @@ -268,7 +287,7 @@ class lofar_device(Device, metaclass=DeviceMeta): pass @command() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @DebugIt() @log_exceptions() def set_defaults(self): @@ -298,7 +317,7 @@ class lofar_device(Device, metaclass=DeviceMeta): self._set_defaults(attributes_to_set) - @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @fault_on_error() @command() def set_translator_defaults(self): @@ -307,25 +326,27 @@ class lofar_device(Device, metaclass=DeviceMeta): # This is just the command version of _set_translator_defaults(). self._set_translator_defaults() - @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @fault_on_error() @command() + @DebugIt() def prepare_hardware(self): """ Load firmware required before configuring anything. """ # This is just the command version of _prepare_hardware(). self._prepare_hardware() - @only_in_states([DevState.STANDBY, DevState.INIT, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @fault_on_error() @command() + @DebugIt() def initialise_hardware(self): """ Initialise the hardware after configuring it. """ # This is just the command version of _initialise_hardware(). self._initialise_hardware() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(DEFAULT_COMMAND_STATES) @command(dtype_out = DevDouble) def max_archiving_load(self): """ Return the maximum archiving load for the device attributes """ diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py index 787a51df3e62ed35071cd97e66ffc1851819f74a..ddac029a61102834374baa6d38745d59a0769739 100644 --- a/tangostationcontrol/tangostationcontrol/devices/recv.py +++ b/tangostationcontrol/tangostationcontrol/devices/recv.py @@ -16,7 +16,7 @@ from functools import partial from tango import DebugIt from tango.server import command from tango.server import device_property, attribute -from tango import AttrWriteType, DevState, DevVarFloatArray +from tango import AttrWriteType, DevVarFloatArray import numpy from math import pi @@ -29,6 +29,7 @@ from tangostationcontrol.common.lofar_logging import device_logging_to_python from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.devices.device_decorators import * from tangostationcontrol.devices.opcua_device import opcua_device +from tangostationcontrol.devices.lofar_device import lofar_device import logging logger = logging.getLogger() @@ -126,6 +127,18 @@ class RECV(opcua_device): # ----- Position information + Antenna_Field_Reference_ITRF = device_property( + doc="ITRF position (XYZ) of each antenna field", + dtype='DevVarFloatArray', + mandatory=False + ) + + Antenna_Field_Reference_ETRS = device_property( + doc="ETRS position (XYZ) of each antenna field", + dtype='DevVarFloatArray', + mandatory=False + ) + HBAT_reference_ITRF = device_property( doc="ITRF position (XYZ) of each HBAT (leave empty to auto-derive from ETRS)", dtype='DevVarFloatArray', @@ -218,6 +231,10 @@ class RECV(opcua_device): # ----- Position information + Antenna_Field_Reference_ITRF_R = attribute(access=AttrWriteType.READ, + doc='Absolute reference position of antenna field, in ITRF', + dtype=(numpy.float,), max_dim_x=3) + HBAT_antenna_ITRF_offsets_R = attribute(access=AttrWriteType.READ, doc='Offsets of the antennas within a tile, in ITRF ("iHBADeltas"). True shape: 96x16x3.', dtype=((numpy.float,),), max_dim_x=48, max_dim_y=96) @@ -226,6 +243,15 @@ class RECV(opcua_device): doc='Absolute reference position of each tile, in ITRF', dtype=((numpy.float,),), max_dim_x=3, max_dim_y=96) + def read_Antenna_Field_Reference_ITRF_R(self): + # provide ITRF field coordinates if they were configured + if self.Antenna_Field_Reference_ITRF: + return numpy.array(self.Antenna_Field_Reference_ITRF).reshape(3) + + # calculate them from ETRS coordinates if not, using the configured ITRF reference + ETRS_coordinates = numpy.array(self.Antenna_Field_Reference_ETRS).reshape(3) + return ETRS_to_ITRF(ETRS_coordinates, self.ITRF_Reference_Frame, self.ITRF_Reference_Epoch) + def read_HBAT_antenna_ITRF_offsets_R(self): base_antenna_offsets = numpy.array(self.HBAT_base_antenna_offsets).reshape(16,3) PQR_to_ETRS_rotation_matrix = numpy.array(self.HBAT_PQR_to_ETRS_rotation_matrix).reshape(3,3) @@ -252,7 +278,7 @@ class RECV(opcua_device): # ---------- # Summarising Attributes # ---------- - RCU_LED_colour_R = attribute(dtype=(numpy.uint32,), max_dim_x=32) + RCU_LED_colour_R = attribute(dtype=(numpy.uint32,), max_dim_x=32, fisallowed="is_attribute_wrapper_allowed") def read_RCU_LED_colour_R(self): return (2 * self.read_attribute("RCU_LED_green_on_R") + 4 * self.read_attribute("RCU_LED_red_on_R")).astype(numpy.uint32) @@ -347,7 +373,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_off(self): """ @@ -357,7 +383,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_on(self): """ @@ -367,7 +393,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_DTH_off(self): """ @@ -377,7 +403,7 @@ class RECV(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def RCU_DTH_on(self): """ @@ -394,10 +420,6 @@ class RECV(opcua_device): self.RCU_on() self.wait_attribute("RECVTR_translator_busy_R", False, self.RCU_On_Off_timeout) - # Turn off DTH by default - self.RCU_DTH_off() - self.wait_attribute("RECVTR_translator_busy_R", False, self.RCU_DTH_On_Off_timeout) - # ---------- # Run server # ---------- diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py b/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py index 36ac75f4ed8b6ba94035c495e9729b61f2a7536f..ae61d77bd51299d8dba44e77422d09d324d1ec53 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py @@ -8,10 +8,10 @@ """ # PyTango imports -from tango.server import device_property -from tango import AttrWriteType -# Additional import +from tango.server import device_property, command +from tango import AttrWriteType, DevVarFloatArray, DevVarULongArray +# Additional import from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper from tangostationcontrol.devices.opcua_device import opcua_device @@ -24,6 +24,14 @@ __all__ = ["Beamlet", "main"] class Beamlet(opcua_device): + # List of OPC-UA CP for BF beamlets + S_pn = SDP.S_pn + N_pn = SDP.N_pn + A_pn = 6 + N_pol = 2 + N_beamlets_ctrl = 488 + N_pol_bf = 2 + # ----------------- # Device Properties # ----------------- @@ -55,12 +63,18 @@ class Beamlet(opcua_device): default_value=[1.0] * 16 ) + FPGA_bf_weights_xy_yx_RW_default = device_property( + dtype='DevVarULongArray', + mandatory=False, + default_value = [[0] * A_pn * N_pol * N_beamlets_ctrl] * N_pn + ) + first_default_settings = [ 'FPGA_beamlet_output_hdr_eth_destination_mac_RW', 'FPGA_beamlet_output_hdr_ip_destination_address_RW', 'FPGA_beamlet_output_hdr_udp_destination_port_RW', - - 'FPGA_beamlet_output_enable_RW' + 'FPGA_beamlet_output_enable_RW', + 'FPGA_bf_weights_xy_yx_RW' ] # ---------- @@ -78,43 +92,45 @@ class Beamlet(opcua_device): FPGA_beamlet_output_scale_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_scale_R"], datatype=numpy.double, dims=(16,)) FPGA_beamlet_output_scale_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_scale_RW"], datatype=numpy.double, dims=(16,), access=AttrWriteType.READ_WRITE) - # List of OPC-UA CP for BF beamlets - S_pn = SDP.S_pn - N_pn = SDP.N_pn - A_pn = 6 - N_pol = 2 - N_beamlets_ctrl = 488 - N_pol_bf = 2 + FPGA_beamlet_output_nof_packets_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_nof_packets_R"], datatype=numpy.int32, dims=(N_beamlets_ctrl, N_pn)) + FPGA_beamlet_output_nof_valid_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_output_nof_valid_R"], datatype=numpy.int32, dims=(N_beamlets_ctrl, N_pn)) + + # uint16[N_pn][A_pn][N_pol][N_beamlets_ctrl] + # Select subband per dual-polarisation beamlet. + # 0 for antenna polarization X in beamlet polarization X, + # 1 for antenna polarization Y in beamlet polarization Y. + FPGA_beamlet_subband_select_R = attribute_wrapper(comms_annotation=["FPGA_beamlet_subband_select_R"], datatype=numpy.uint16, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn)) + FPGA_beamlet_subband_select_RW = attribute_wrapper(comms_annotation=["FPGA_beamlet_subband_select_RW"], datatype=numpy.uint16, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) # cint16[N_pn][A_pn][N_pol][N_beamlets_ctrl] # Co-polarization BF weights. The N_pol = 2 parameter index is: # 0 for antenna polarization X in beamlet polarization X, # 1 for antenna polarization Y in beamlet polarization Y. - FPGA_bf_weights_xx_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_yy_R"], datatype=numpy.int16, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_xx_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_yy_RW"], datatype=numpy.int16, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_xx_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_yy_R"], datatype=numpy.uint32, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_xx_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_yy_RW"], datatype=numpy.uint32, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) # cint16[N_pn][A_pn][N_pol][N_beamlets_ctrl] # Cross-polarization BF weights. The N_pol = 2 parameter index is (note that index pol in range 0:N_pol-1 is the antenna polarization, so index !pol is the beamlet polarization): # 0 for antenna polarization X in beamlet polarization Y, # 1 for antenna polarization Y in beamlet polarization X. - FPGA_bf_weights_xy_yx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_yx_R"], datatype=numpy.int16, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_xy_yx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_yx_RW"], datatype=numpy.int16, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_xy_yx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_yx_R"], datatype=numpy.uint32, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_xy_yx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_yx_RW"], datatype=numpy.uint32, dims=(A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) # cint16[N_pn][N_pol_bf][A_pn][N_pol][N_beamlets_ctrl] # Full Jones matrix of BF weights. - FPGA_bf_weights_xx_xy_yx_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_xy_yx_yy_R"], datatype=numpy.int16, dims=(N_pol_bf * A_pn * N_pol * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_xx_xy_yx_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_xy_yx_yy_RW"], datatype=numpy.int16, dims=(N_pol_bf * A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_xx_xy_yx_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_xy_yx_yy_R"], datatype=numpy.uint32, dims=(N_pol_bf * A_pn * N_pol * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_xx_xy_yx_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_xy_yx_yy_RW"], datatype=numpy.uint32, dims=(N_pol_bf * A_pn * N_pol * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) # cint16[N_pn][A_pn][N_beamlets_ctrl] # BF weights for separate access to respectively w_xx, w_xy, w_yx, and w_yy. - FPGA_bf_weights_xx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_R"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_xx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_RW"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) - FPGA_bf_weights_xy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_R"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_xy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_RW"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) - FPGA_bf_weights_yx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yx_R"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_yx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yx_RW"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) - FPGA_bf_weights_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yy_R"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn)) - FPGA_bf_weights_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yy_RW"], datatype=numpy.int16, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_xx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_R"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_xx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xx_RW"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_xy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_R"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_xy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_xy_RW"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_yx_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yx_R"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_yx_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yx_RW"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) + FPGA_bf_weights_yy_R = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yy_R"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn)) + FPGA_bf_weights_yy_RW = attribute_wrapper(comms_annotation=["FPGA_bf_weights_yy_RW"], datatype=numpy.uint32, dims=(A_pn * N_beamlets_ctrl, N_pn), access=AttrWriteType.READ_WRITE) # ---------- # Summarising Attributes @@ -124,9 +140,33 @@ class Beamlet(opcua_device): # Overloaded functions # -------- + # -------- + # internal functions + # -------- + def _calculate_bf_weights(self, phases: numpy.ndarray): + """ Helper function that converts a difference in phase (in radiants) + to a FPGA weight (in complex number) """ + + # Convert array values in complex numbers + unit = numpy.power(2,14) + real = numpy.array(unit * numpy.cos(phases), dtype=numpy.short) + imag = numpy.array(unit * numpy.sin(phases), dtype=numpy.short) + # join 16 bits of imaginary part (MSB) with 16 bits of real part (LSB) + bf_weights = numpy.array( numpy.frombuffer( b''.join([imag,real]), dtype=numpy.uint32 ) ) + + return bf_weights + # -------- # Commands # -------- + @command(dtype_in=DevVarFloatArray, dtype_out=DevVarULongArray) + def calculate_bf_weights(self, phases: numpy.ndarray): + """ converts a difference in phase (in radiants) to a FPGA weight (in complex number) """ + + # Calculate the FPGA weight array + bf_weights = self._calculate_bf_weights(phases) + + return bf_weights # ---------- # Run server diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py b/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py index 147b0a6237d14b70683f778f220f304ffb2e3b86..256bd5b2cccd8531b2e9ff9aeedcc1acf25cd425 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/digitalbeam.py @@ -14,14 +14,14 @@ from tangostationcontrol.common.entrypoint import entry #from tangostationcontrol.clients.attribute_wrapper import attribute_wrapper -from tangostationcontrol.devices.lofar_device import lofar_device +from tangostationcontrol.devices.beam_device import beam_device #import numpy __all__ = ["DigitalBeam", "main"] -class DigitalBeam(lofar_device): +class DigitalBeam(beam_device): pass # ----------------- # Device Properties diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py index c4dc14a165f69ce471e7c416fef14dd0771b54cb..dd4179e47840488b1033d9612a4a5015f0ec2a49 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py @@ -108,6 +108,14 @@ class SDP(opcua_device): FPGA_pps_expected_cnt_RW = attribute_wrapper(comms_annotation=["FPGA_pps_expected_cnt_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) 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_ring_node_offset_R = attribute_wrapper(comms_annotation=["FPGA_ring_node_offset_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_ring_node_offset_RW = attribute_wrapper(comms_annotation=["FPGA_ring_node_offset_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_ring_nof_nodes_R = attribute_wrapper(comms_annotation=["FPGA_ring_nof_nodes_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_ring_nof_nodes_RW = attribute_wrapper(comms_annotation=["FPGA_ring_nof_nodes_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_ring_use_cable_to_next_rn_R = attribute_wrapper(comms_annotation=["FPGA_ring_use_cable_to_next_rn_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_ring_use_cable_to_next_rn_RW = attribute_wrapper(comms_annotation=["FPGA_ring_use_cable_to_next_rn_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_ring_use_cable_to_previous_rn_R = attribute_wrapper(comms_annotation=["FPGA_ring_use_cable_to_previous_rn_R"], datatype=numpy.bool_, dims=(16,)) + FPGA_ring_use_cable_to_previous_rn_RW = attribute_wrapper(comms_annotation=["FPGA_ring_use_cable_to_previous_rn_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,)) @@ -122,7 +130,7 @@ class SDP(opcua_device): 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_time_since_last_pps_R = attribute_wrapper(comms_annotation=["FPGA_time_since_last_pps_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_time_since_last_pps_R = attribute_wrapper(comms_annotation=["FPGA_time_since_last_pps_R"], datatype=numpy.float_, dims=(16,)) FPGA_temp_R = attribute_wrapper(comms_annotation=["FPGA_temp_R"], datatype=numpy.float_, dims=(16,)) 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) @@ -156,10 +164,9 @@ class SDP(opcua_device): 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_bsn_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_bsn_R"], datatype=numpy.int64, dims=(N_pn,)) + FPGA_signal_input_nof_blocks_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_nof_blocks_R"], datatype=numpy.int32, dims=(N_pn,)) + FPGA_signal_input_nof_samples_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_nof_samples_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) @@ -194,17 +201,14 @@ class SDP(opcua_device): # -------- def _prepare_hardware(self): - # FPGA firmware loading disabled, as it causes SDPTR to crash, - # see https://support.astron.nl/jira/browse/L2SDP-670 - """ - # FPGAs need the correct firmware loaded - self.FPGA_boot_image_RW = [1] * self.N_pn - - # wait for the firmware to be loaded (ignoring masked out elements) - mask = self.proxy.TR_fpga_mask_RW - self.wait_attribute("FPGA_boot_image_R", lambda attr: ((attr == 1) | ~mask).all(), 10) - """ - pass + # FPGAs that are actually reachable and we care about + wait_for = ~(self.read_attribute("TR_fpga_communication_error_R")) & self.read_attribute("TR_fpga_mask_R") + + # Order the correct firmare to be loaded + self.proxy.FPGA_boot_image_RW = [1] * self.N_pn + + # Wait for the firmware to be loaded (ignoring masked out elements) + self.wait_attribute("FPGA_boot_image_R", lambda attr: ((attr == 1) | ~wait_for).all(), 60) # -------- # Commands diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py index c7e9c95844b93768caa3622488ea2520244b38d9..1228cdc99d6ab8037f7c8bfe4ec859b5185cdd9e 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py @@ -90,6 +90,9 @@ class SST(Statistics): 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,)) + FPGA_sst_offload_nof_packets_R = attribute_wrapper(comms_annotation=["FPGA_sst_offload_nof_packets_R"], datatype=numpy.int32, dims=(16,)) + FPGA_sst_offload_nof_valid_R = attribute_wrapper(comms_annotation=["FPGA_sst_offload_nof_valid_R"], datatype=numpy.int32, 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) # number of packets with invalid payloads diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py index 8be9cdb483ef4f21818791009a19e8fbc2b91cb9..73a5d85bb742f06bf5412926cadefe4db0455716 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py @@ -110,6 +110,11 @@ class XST(Statistics): FPGA_xst_offload_nof_crosslets_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_nof_crosslets_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) FPGA_xst_offload_nof_crosslets_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_offload_nof_crosslets_R"], datatype=numpy.uint32, dims=(16,)) + FPGA_xst_ring_nof_transport_hops_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_ring_nof_transport_hops_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE) + FPGA_xst_ring_nof_transport_hops_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_xst_ring_nof_transport_hops_R"], datatype=numpy.uint32, dims=(16,)) + + FPGA_xst_offload_nof_packets_R = attribute_wrapper(comms_annotation=["FPGA_xst_offload_nof_packets_R"], datatype=numpy.int32, dims=(16,)) + FPGA_xst_offload_nof_valid_R = attribute_wrapper(comms_annotation=["FPGA_xst_offload_nof_valid_R"], datatype=numpy.int32, 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=(XSTCollector.MAX_FPGAS,), datatype=numpy.uint64) diff --git a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py index 948a3657279bf489039bd372b1a096052d3556ec..7adee9e269bf24d340175d1704448ded674c3684 100644 --- a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py +++ b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py @@ -11,17 +11,17 @@ import numpy import datetime from json import loads -from tango.server import attribute, command, device_property -from tango import AttrWriteType, DebugIt, DevState, DeviceProxy, DevVarStringArray, DevVarDoubleArray, DevString, DevSource from threading import Thread, Lock, Condition +from tango import AttrWriteType, DebugIt, DeviceProxy, DevVarStringArray, DevVarDoubleArray, DevString, DevSource +from tango.server import attribute, command, device_property +from tango import Util # Additional import 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 -from tangostationcontrol.common.measures import get_measures_directory, use_measures_directory, download_measures, restart_python, get_available_measures_directories from tangostationcontrol.beam.delays import delay_calculator from tangostationcontrol.devices.device_decorators import * +from tangostationcontrol.devices.beam_device import beam_device import logging logger = logging.getLogger() @@ -31,7 +31,7 @@ logger = logging.getLogger() __all__ = ["TileBeam", "main", "BeamTracker"] @device_logging_to_python() -class TileBeam(lofar_device): +class TileBeam(beam_device): # ----------------- # Device Properties @@ -58,7 +58,7 @@ class TileBeam(lofar_device): HBAT_pointing_direction_R = attribute(access=AttrWriteType.READ, dtype=((numpy.str,),), max_dim_x=3, max_dim_y=96, fget=lambda self: self._hbat_pointing_direction_r) - + HBAT_pointing_direction_RW = attribute(access=AttrWriteType.READ_WRITE, dtype=((numpy.str,),), max_dim_x=3, max_dim_y=96, fget=lambda self: self._hbat_pointing_direction_rw) @@ -77,13 +77,6 @@ class TileBeam(lofar_device): dtype=numpy.bool, fget=lambda self: self._hbat_tracking_enabled_rw) - # Directory where the casacore measures that we use, reside. We configure ~/.casarc to - # use the symlink /opt/IERS/current, which we switch to the actual set of files to use. - measures_directory_R = attribute(dtype=str, access=AttrWriteType.READ, fget = lambda self: get_measures_directory()) - - # List of dowloaded measures (the latest 64, anyway) - measures_directories_available_R = attribute(dtype=(str,), max_dim_x=64, access=AttrWriteType.READ, fget = lambda self: sorted(get_available_measures_directories())[-64:]) - # -------- # overloaded functions # -------- @@ -106,8 +99,11 @@ class TileBeam(lofar_device): # Initialise tracking control self._hbat_tracking_enabled_rw = True - # Set a reference of RECV device - self.recv_proxy = DeviceProxy("STAT/RECV/1") + # Set a reference of RECV device that is correlated to this BEAM device + util = Util.instance() + instance_number = self.get_name().split('/')[2] + self.recv_proxy = DeviceProxy( + f"{util.get_ds_inst_name()}/RECV/{instance_number}") self.recv_proxy.set_source(DevSource.DEV) # Retrieve positions from RECV device @@ -130,7 +126,7 @@ class TileBeam(lofar_device): # Start beam tracking thread if self._hbat_tracking_enabled_rw: self.HBAT_beam_tracker.start() - + @log_exceptions() def configure_for_off(self): if self.HBAT_beam_tracker: @@ -219,42 +215,11 @@ class TileBeam(lofar_device): # -------- # Commands # -------- - - @command(dtype_out=str, doc_out="Name of newly installed measures directory") - @DebugIt() - @log_exceptions() - def download_measures(self): - """ Download new measures tables into /opt/IERS, but do not activate them. - - NOTE: This may take a while to complete. You are advised to increase - the timeout of the proxy using `my_device.set_timeout_millis(10000)`. """ - - return download_measures() - - @command(dtype_in=str, doc_in="Measures directory to activate") - @DebugIt() - @log_exceptions() - def use_measures(self, newdir): - """ Activate a downloaded set of measures tables. - - NOTE: This will turn off and restart this device!! """ - - # switch to requested measures - use_measures_directory(newdir) - logger.info(f"Switched measures table to {newdir}") - - # turn off our device, to prepare for a python restart - self.Off() - - # restart this program to force casacore to adopt - # the new tables - logger.warning("Restarting device to activate new measures tables") - restart_python() @command(dtype_in=DevVarStringArray, dtype_out=DevVarDoubleArray) @DebugIt() @log_exceptions() - @only_in_states([DevState.ON]) + @only_in_states(beam_device.DEFAULT_COMMAND_STATES) def HBAT_delays(self, pointing_direction: numpy.array, timestamp: datetime.datetime = None): """ Calculate the delays (in seconds) based on the pointing list and the timestamp @@ -275,7 +240,7 @@ class TileBeam(lofar_device): @command(dtype_in=DevVarStringArray) @DebugIt() @log_exceptions() - @only_in_states([DevState.ON]) + @only_in_states(beam_device.DEFAULT_COMMAND_STATES) def HBAT_set_pointing(self, pointing_direction: list, timestamp: datetime.datetime = None): """ Uploads beam weights based on a given pointing direction 2D array (96 tiles x 3 parameters) @@ -293,7 +258,7 @@ class TileBeam(lofar_device): @command(dtype_in = DevString) @DebugIt() - @only_in_states([DevState.ON]) + @only_in_states(beam_device.DEFAULT_COMMAND_STATES) def HBAT_set_pointing_for_specific_time(self, parameters: DevString = None): """ Uploads beam weights based on a given pointing direction 2D array (96 tiles x 3 parameters) @@ -330,7 +295,7 @@ class BeamTracker(): DISCONNECT_TIMEOUT = 3.0 """ Object that encapsulates a Thread, resposible for beam tracking operations """ - def __init__(self, device: lofar_device): + def __init__(self, device: beam_device): self.thread = None self.device = device @@ -361,9 +326,9 @@ class BeamTracker(): """ Force the pointing to be updated. """ self.stale_pointing = True - self.unlock_thread() + self.notify_thread() - def unlock_thread(self): + def notify_thread(self): # inform the thread to stop waiting with self.update_lock: self.update_condition.notify() @@ -413,7 +378,7 @@ class BeamTracker(): def _update_HBAT_pointing_direction(self): """ Updates the beam weights using a fixed interval of time """ - # Check if flag beamtracking is true + # Check if flag beamtracking is true with self.update_lock: while not self.done: self.stale_pointing = False diff --git a/tangostationcontrol/tangostationcontrol/devices/unb2.py b/tangostationcontrol/tangostationcontrol/devices/unb2.py index 614055a716ce8a527197aaad159273ebfda220ef..a255cd7a25358e38ed8d807476b5786596acd773 100644 --- a/tangostationcontrol/tangostationcontrol/devices/unb2.py +++ b/tangostationcontrol/tangostationcontrol/devices/unb2.py @@ -13,12 +13,13 @@ # PyTango imports from tango.server import command, attribute, device_property -from tango import AttrWriteType, DebugIt, DevState +from tango import AttrWriteType, DebugIt # Additional 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.devices.lofar_device import lofar_device from tangostationcontrol.common.lofar_logging import device_logging_to_python from tangostationcontrol.devices.device_decorators import only_in_states @@ -203,7 +204,7 @@ class UNB2(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def UNB2_off(self): """ @@ -213,7 +214,7 @@ class UNB2(opcua_device): @command() @DebugIt() - @only_in_states([DevState.STANDBY, DevState.ON]) + @only_in_states(lofar_device.DEFAULT_COMMAND_STATES) def UNB2_on(self): """ diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py index 4948dd7f70a1d1c122dcd3a3c50cda6184bb44d3..c6935e256caa035611d508922fd8dcde2937ac4a 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py @@ -67,6 +67,7 @@ class TestDeviceTileBeam(AbstractTestBases.TestDeviceBase): # Verify writing operation does not lead to errors self.proxy.HBAT_set_pointing(self.pointing_direction) # write values to RECV HBAT_delays_r2 = numpy.array(recv_proxy.read_attribute('HBAT_BF_delay_steps_RW').value) + self.assertIsNotNone(HBAT_delays_r2) # Verify delays changed (to be discussed) diff --git a/tangostationcontrol/tangostationcontrol/integration_test/devices/test_lofar_device.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py similarity index 99% rename from tangostationcontrol/tangostationcontrol/integration_test/devices/test_lofar_device.py rename to tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py index d5a935eb537a9031ee67b2252ba1b1cfd1eb6687..3a420bbd3c3f03b34d4664f39d631de154c69bd0 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/devices/test_lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py @@ -13,6 +13,7 @@ from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy from tangostationcontrol.integration_test import base + class TestProxyAttributeAccess(base.IntegrationTestCase): """ Test whether DeviceProxy's can always access attributes immediately after turning them on. """ diff --git a/tangostationcontrol/tangostationcontrol/integration_test/toolkit/__init__.py b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/__init__.py similarity index 100% rename from tangostationcontrol/tangostationcontrol/integration_test/toolkit/__init__.py rename to tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/__init__.py diff --git a/tangostationcontrol/tangostationcontrol/integration_test/toolkit/test_archiver.py b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver.py similarity index 98% rename from tangostationcontrol/tangostationcontrol/integration_test/toolkit/test_archiver.py rename to tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver.py index a6c361435cd953616bbd5cdf9514b2550a9e824a..1ead9d257645eeb3934b57052cd3cbd89bce39d6 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/toolkit/test_archiver.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver.py @@ -16,6 +16,7 @@ from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy import time from datetime import datetime + class TestArchiver(BaseIntegrationTestCase): def setUp(self): @@ -54,10 +55,12 @@ class TestArchiver(BaseIntegrationTestCase): recv_proxy.set_defaults() recv_proxy.on() self.assertEqual(DevState.ON, recv_proxy.state()) - + + """ # Safety operation that prevents event subscriber to go in Fault state self.archiver.remove_attributes_in_error() time.sleep(3) + """ attr_fullname = 'stat/recv/1/recvtr_translator_busy_r' # boolean self.archiver.add_attribute_to_archiver(attr_fullname, polling_period=1000, archive_event_period=3000) time.sleep(3) @@ -75,11 +78,13 @@ class TestArchiver(BaseIntegrationTestCase): self.assertEqual(datetime,type(item.data_time)) # column datetime self.assertEqual(bool,type(item.value)) # column value + """ # Remove attribute at the end of the test self.archiver.remove_attribute_from_archiver(attr_fullname) time.sleep(3) # Test if the attribute has been correctly removed self.assertFalse(self.archiver.is_attribute_archived(attribute_fqdn(attr_fullname))) + """ recv_proxy.off() def test_archive_array_attribute(self): @@ -95,9 +100,11 @@ class TestArchiver(BaseIntegrationTestCase): sdp_proxy.on() self.assertEqual(DevState.ON, sdp_proxy.state()) + """ # Safety operation that prevents event subscriber to go in Fault state self.archiver.remove_attributes_in_error() time.sleep(3) + """ attr_fullname = 'stat/sdp/1/fpga_temp_r' # double self.archiver.add_attribute_to_archiver(attr_fullname, polling_period=1000, archive_event_period=3000) time.sleep(3) @@ -116,11 +123,13 @@ class TestArchiver(BaseIntegrationTestCase): self.assertEqual(int,type(item.x)) # column index self.assertEqual(float,type(item.value)) # column value + """ # Remove attribute at the end of the test self.archiver.remove_attribute_from_archiver(attr_fullname) time.sleep(3) # Test if the attribute has been correctly removed self.assertFalse(self.archiver.is_attribute_archived(attribute_fqdn(attr_fullname))) + """ sdp_proxy.off() def test_get_maximum_device_load(self): diff --git a/tangostationcontrol/tangostationcontrol/integration_test/toolkit/test_archiver_util.py b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py similarity index 99% rename from tangostationcontrol/tangostationcontrol/integration_test/toolkit/test_archiver_util.py rename to tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py index ad4595951d43c5cacdf26459e9cb982c1e32e142..952e665674d2bcb79e8a393a33c62a6144ec9125 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/toolkit/test_archiver_util.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py @@ -14,6 +14,7 @@ from tango import DevState import json import pkg_resources + class TestArchiverUtil(BaseIntegrationTestCase): def setUp(self): diff --git a/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_demo.py b/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_demo.py deleted file mode 100644 index 78ea0de074ee4f5336820a4fa91e88d3ef4a73c5..0000000000000000000000000000000000000000 --- a/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_demo.py +++ /dev/null @@ -1,28 +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 logging - -from tangostationcontrol.integration_test import base - -logger = logging.getLogger() - - -class TestDemo(base.IntegrationTestCase): - """ This test will not be run until L2SS-484 is merged. - It serves as a trivial example of test exclusion since the unit tests pass - even though assertTrue(False) can trivially be determined to never succeed. - """ - - def setUp(self): - - super(TestDemo, self).setUp() - - def test_fail(self): - self.assertTrue(False) diff --git a/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py b/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py new file mode 100644 index 0000000000000000000000000000000000000000..898ca83892593852472387b9a489a4a51cc0204c --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py @@ -0,0 +1,67 @@ +# -*- 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 +import numpy +import logging +import statistics + +from tango import DevState + +from tangostationcontrol.integration_test import base +from tangostationcontrol.integration_test.device_proxy import TestDeviceProxy + +logger = logging.getLogger() + + +class TestRecvCluster(base.IntegrationTestCase): + + pointing_direction = numpy.array([["J2000", "0deg", "0deg"]] * 96).flatten() + + def setUp(self): + + super(TestRecvCluster, self).setUp() + + def test_recv_cluster_performance(self): + beam_proxies = [] + recv_proxies = [] + + # Beam / Recv 1,2,3,4 + for i in range(1, 5): + recv_proxies.append(TestDeviceProxy(f"STAT/RECV/{i}")) + beam_proxies.append(TestDeviceProxy(f"STAT/TileBeam/{i}")) + + # Recv devices must be ready before TileBeam + for proxy in recv_proxies: + proxy.off() + self.assertTrue(proxy.state() is DevState.OFF) + proxy.initialise() + self.assertTrue(proxy.state() is DevState.STANDBY) + proxy.set_defaults() + proxy.on() + self.assertTrue(proxy.state() is DevState.ON) + + for proxy in beam_proxies: + proxy.off() + self.assertTrue(proxy.state() is DevState.OFF) + proxy.initialise() + self.assertTrue(proxy.state() is DevState.STANDBY) + proxy.on() + self.assertTrue(proxy.state() is DevState.ON) + + results = [] + for _i in range(25): + start_time = time.monotonic_ns() + for proxy in beam_proxies: + proxy.HBAT_set_pointing(self.pointing_direction) + stop_time = time.monotonic_ns() + results.append(stop_time - start_time) + + logging.error(f"Median {statistics.median(results) / 1.e9} Stdev " + f"{statistics.stdev(results) / 1.e9}") diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py index 1fde8856cf55a79a03aaec2cc53ba34a4ad818f0..49de70bd5aecc1faab3bf7402f7adad059bd3823 100644 --- a/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py @@ -19,7 +19,8 @@ from tangostationcontrol.test import base class TestRecvDevice(base.TestCase): # some dummy values for mandatory properties - recv_properties = {'OPC_Server_Name': 'example.com', 'OPC_Server_Port': 4840, 'OPC_Time_Out': 5.0} + recv_properties = {'OPC_Server_Name': 'example.com', 'OPC_Server_Port': 4840, 'OPC_Time_Out': 5.0, + 'Antenna_Field_Reference_ITRF' : [3.0, 3.0, 3.0], 'Antenna_Field_Reference_ETRS' : [7.0, 7.0, 7.0]} def setUp(self): super(TestRecvDevice, self).setUp() @@ -31,11 +32,20 @@ class TestRecvDevice(base.TestCase): device, 'DeviceProxy') proxy_patcher.start() self.addCleanup(proxy_patcher.stop) - - + def test_calculate_HBAT_bf_delay_steps(self): """Verify HBAT beamforming calculations are correctly executed""" with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True) as proxy: delays = numpy.random.rand(96,16).flatten() HBAT_bf_delay_steps = proxy.calculate_HBAT_bf_delay_steps(delays) self.assertEqual(3072, len(HBAT_bf_delay_steps)) # 96x32=3072 + + def test_read_Antenna_Field_Reference(self): + """Verify if Antenna coordinates are correctly provided""" + # Device uses ITRF coordinates by default + with DeviceTestContext(recv.RECV, properties=self.recv_properties, process=True) as proxy: + self.assertEqual(3.0, proxy.Antenna_Field_Reference_ITRF_R[0]) + # Device derives coordinates from ETRS if ITRF ones are not found + recv_properties_v2 = {'OPC_Server_Name': 'example.com', 'OPC_Server_Port': 4840, 'OPC_Time_Out': 5.0, 'Antenna_Field_Reference_ETRS' : [7.0, 7.0, 7.0]} + with DeviceTestContext(recv.RECV, properties=recv_properties_v2, process=True) as proxy: + self.assertNotEqual(3.0, proxy.Antenna_Field_Reference_ITRF_R[0]) # value = 6.948998835785814 diff --git a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py index 4265c277554adb9d4e92c8491f392bffaddb3084..842aff8367ab78a30ba55eb31bd48fcb29193d8e 100644 --- a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py +++ b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py @@ -22,12 +22,12 @@ class TestArchiverUtil(base.TestCase): def test_device_fqdn(self): """Test if a device name is correctly converted in a Tango FQDN""" - self.assertEqual(f"tango://databaseds:10000/{self.device_name}".lower(), device_fqdn(self.device_name)) + self.assertEqual(f"tango://databaseds:10000/{self.device_name}".lower(), device_fqdn(self.device_name, "databaseds:10000")) def test_attribute_fqdn(self): """Test if an attribute name is correctly converted in a Tango FQDN""" self.assertEqual(f"tango://databaseds:10000/{self.device_name}/{self.attribute_name}".lower(), - attribute_fqdn(f"{self.device_name}/{self.attribute_name}")) + attribute_fqdn(f"{self.device_name}/{self.attribute_name}", "databaseds:10000")) self.assertRaises(ValueError, lambda: attribute_fqdn(self.attribute_name)) def test_split_tango_name(self): diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py index 2c002f1cf866c98738c13203fbf8e0cd864edabd..2e178083d2428d1b0706e283ded68e7ee0c5ea46 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py @@ -25,8 +25,8 @@ def warn_if_attribute_not_found(): try: return func(self, attribute_name, *args, **kwargs) except DevFailed as e: - if e.args[0].reason == 'Attribute not found': - logger.warning(f"Attribute {attribute_name} not found!") + if e.args[0].reason in ['Attribute not found', 'BadSignalName']: + logger.warning(f"Attribute {attribute_name} not found: {e.args[0].desc}") else: raise @@ -59,7 +59,7 @@ class Archiver(): self.cm = DeviceProxy(cm_name) try: if self.cm.state() == DevState.FAULT: - raise Exception(f"Configuration Manager {cm_name} is in FAULT state") + raise Exception(f"Configuration Manager {cm_name} is in FAULT state: {self.cm.status()}") except Exception as e: raise Exception(f"Connection failed with Configuration Manager {cm_name}") from e self.es_list = [es_name for es_name in self.get_subscribers(from_db=False)] @@ -145,7 +145,8 @@ class Archiver(): dev_polling_time, dev_archive_abs_change, dev_archive_rel_change, dev_archive_period, dev_event_period, dev_strategy = get_global_env_parameters(config_dict, environment) # Attributes to be included in archiving stategy include_att_list = get_include_attribute_list(device, config_dict, environment) - self.remove_attributes_by_device(device, exclude=include_att_list) + # TODO Cleanup the subscriber + # self.remove_attributes_by_device(device, exclude=include_att_list) # Include attributes by custom configuration try: for att in include_att_list: @@ -168,8 +169,8 @@ class Archiver(): environment = 'production' # Retrieve global parameters prod_polling_time, prod_archive_abs_change, prod_archive_rel_change, prod_archive_period, prod_event_period, prod_strategy = get_global_env_parameters(config_dict, environment) - # Cleanup the subscriber - self.remove_attributes_by_device(device) + # TODO Cleanup the subscriber + # self.remove_attributes_by_device(device) attribute_list = DeviceProxy(device).get_attribute_list() try: # Add attributes in 'suffixes' and 'infixes' list which have different parameters @@ -214,6 +215,7 @@ class Archiver(): else: raise + @warn_if_attribute_not_found() def add_attribute_to_archiver(self, attribute_name: str, polling_period: int, archive_event_period: int, strategy: str = 'RUN', abs_change: int = 1, rel_change: int = None, es_name:str=None): """ @@ -280,6 +282,10 @@ class Archiver(): """ Stops the data archiving of the attribute passed as input, and remove it from the subscriber's list. """ + + # Removal of attributes leads to hdbpp-es freezing up, see https://github.com/tango-controls-hdbpp/hdbpp-es/issues/25 + raise NotImplementedError("Removing attributes is not supported yet") + attribute_name = attribute_fqdn(attribute_name) self.cm.AttributeStop(attribute_name) self.cm.AttributeRemove(attribute_name) @@ -340,6 +346,7 @@ class Archiver(): Starts the archiving of the attribute passed as input. The attribute must be already present in the subscriber's list """ + attribute_name = attribute_fqdn(attribute_name) self.cm.AttributeStart(attribute_name) @warn_if_attribute_not_found() @@ -348,6 +355,7 @@ class Archiver(): Stops the archiving of the attribute passed as input. The attribute must be already present in the subscriber's list """ + attribute_name = attribute_fqdn(attribute_name) self.cm.AttributeStop(attribute_name) def is_attribute_archived(self, attribute_name:str): diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py index 45119bfeb213b667f1eb53f4fee778f05dd062ae..fd6f8f7aa0f39d52f79798e89923e75c60de0b5e 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py @@ -418,6 +418,19 @@ class Array_Boolean(Array): def __repr__(self): return f"<Array_Boolean(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Boolean(Array): + """ + Class that represents a Tango Boolean Image mapped to table 'att_image_devboolean' + """ + __tablename__ = 'att_image_devboolean' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(Boolean)) + value_w = Column(ARRAY(Boolean)) + + def __repr__(self): + return f"<Image_Boolean(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + + class Array_Double(Array): """ Class that represents a Tango Double Array mapped to table 'att_array_devdouble' @@ -430,6 +443,18 @@ class Array_Double(Array): def __repr__(self): return f"<Array_Double(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Double(Array): + """ + Class that represents a Tango Double Image mapped to table 'att_image_devdouble' + """ + __tablename__ = 'att_image_devdouble' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(FLOAT)) + value_w = Column(ARRAY(FLOAT)) + + def __repr__(self): + return f"<Image_Double(att_conf_id='{self.att_conf_id}', data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_Encoded(Array): """ Class that represents a Tango Encoded Array mapped to table 'att_array_devencoded' @@ -442,6 +467,18 @@ class Array_Encoded(Array): def __repr__(self): return f"<Array_Encoded(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Encoded(Array): + """ + Class that represents a Tango Encoded Array mapped to table 'att_image_devencoded' + """ + __tablename__ = 'att_image_devencoded' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(BYTEA)) + value_w = Column(ARRAY(BYTEA)) + + def __repr__(self): + return f"<Image_Encoded(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_Enum(Array): """ Class that represents a Tango Enum Array mapped to table 'att_array_devenum' @@ -456,6 +493,20 @@ class Array_Enum(Array): def __repr__(self): return f"<Array_Enum(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r_label='{self.value_r_label}',value_r='{self.value_r}',value_w_label='{self.value_w_label}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Enum(Array): + """ + Class that represents a Tango Enum Array mapped to table 'att_image_devenum' + """ + __tablename__ = 'att_image_devenum' + __table_args__ = {'extend_existing': True} + value_r_label = Column(ARRAY(TEXT)) + value_r = Column(ARRAY(INTEGER)) + value_w_label = Column(ARRAY(TEXT)) + value_w = Column(ARRAY(INTEGER)) + + def __repr__(self): + return f"<Image_Enum(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r_label='{self.value_r_label}',value_r='{self.value_r}',value_w_label='{self.value_w_label}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_Float(Array): """ Class that represents a Tango Float Array mapped to table 'att_array_devfloat' @@ -468,6 +519,18 @@ class Array_Float(Array): def __repr__(self): return f"<Array_Float(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Float(Array): + """ + Class that represents a Tango Float Array mapped to table 'att_image_devfloat' + """ + __tablename__ = 'att_image_devfloat' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(FLOAT)) + value_w = Column(ARRAY(FLOAT)) + + def __repr__(self): + return f"<Image_Float(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_Long(Array): """ Class that represents a Tango Long Array mapped to table 'att_array_devlong' @@ -480,6 +543,18 @@ class Array_Long(Array): def __repr__(self): return f"<Array_Long(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Long(Array): + """ + Class that represents a Tango Long Array mapped to table 'att_image_devlong' + """ + __tablename__ = 'att_image_devlong' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INT4RANGE)) + value_w = Column(ARRAY(INT4RANGE)) + + def __repr__(self): + return f"<Image_Long(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_Long64(Array): """ Class that represents a Tango Long64 Array mapped to table 'att_array_devlong64' @@ -492,6 +567,18 @@ class Array_Long64(Array): def __repr__(self): return f"<Array_Long64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Long64(Array): + """ + Class that represents a Tango Long64 Array mapped to table 'att_image_devlong64' + """ + __tablename__ = 'att_image_devlong64' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INT8RANGE)) + value_w = Column(ARRAY(INT8RANGE)) + + def __repr__(self): + return f"<Image_Long64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_Short(Array): """ Class that represents a Tango Short Array mapped to table 'att_array_devshort' @@ -504,6 +591,18 @@ class Array_Short(Array): def __repr__(self): return f"<Array_Short(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_Short(Array): + """ + Class that represents a Tango Short Array mapped to table 'att_image_devshort' + """ + __tablename__ = 'att_image_devshort' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INTEGER)) + value_w = Column(ARRAY(INTEGER)) + + def __repr__(self): + return f"<Image_Short(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_State(Array): """ Class that represents a Tango State Array mapped to table 'att_array_devstate' @@ -516,6 +615,18 @@ class Array_State(Array): def __repr__(self): return f"<Array_State(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_State(Array): + """ + Class that represents a Tango State Array mapped to table 'att_image_devstate' + """ + __tablename__ = 'att_image_devstate' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INT4RANGE)) + value_w = Column(ARRAY(INT4RANGE)) + + def __repr__(self): + return f"<Image_State(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_String(Array): """ Class that represents a Tango String Array mapped to table 'att_array_devstring' @@ -528,6 +639,18 @@ class Array_String(Array): def __repr__(self): return f"<Array_String(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_String(Array): + """ + Class that represents a Tango String Array mapped to table 'att_image_devstring' + """ + __tablename__ = 'att_image_devstring' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(TEXT)) + value_w = Column(ARRAY(TEXT)) + + def __repr__(self): + return f"<Image_String(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_UChar(Array): """ Class that represents a Tango UChar Array mapped to table 'att_array_devuchar' @@ -540,6 +663,18 @@ class Array_UChar(Array): def __repr__(self): return f"<Array_UChar(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_UChar(Array): + """ + Class that represents a Tango UChar Array mapped to table 'att_image_devuchar' + """ + __tablename__ = 'att_image_devuchar' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INTEGER)) + value_w = Column(ARRAY(INTEGER)) + + def __repr__(self): + return f"<Image_UChar(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_ULong(Array): """ Class that represents a Tango ULong Array mapped to table 'att_array_devulong' @@ -552,6 +687,18 @@ class Array_ULong(Array): def __repr__(self): return f"<Array_ULong(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_ULong(Array): + """ + Class that represents a Tango ULong Array mapped to table 'att_image_devulong' + """ + __tablename__ = 'att_image_devulong' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INTEGER)) + value_w = Column(ARRAY(INTEGER)) + + def __repr__(self): + return f"<Image_ULong(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_ULong64(Array): """ Class that represents a Tango ULong64 Array mapped to table 'att_array_devulong64' @@ -564,6 +711,18 @@ class Array_ULong64(Array): def __repr__(self): return f"<Array_ULong64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_ULong64(Array): + """ + Class that represents a Tango ULong64 Array mapped to table 'att_image_devulong64' + """ + __tablename__ = 'att_image_devulong64' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INTEGER)) + value_w = Column(ARRAY(INTEGER)) + + def __repr__(self): + return f"<Image_ULong64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + class Array_UShort(Array): """ Class that represents a Tango UShort Array mapped to table 'att_array_devushort' @@ -576,6 +735,18 @@ class Array_UShort(Array): def __repr__(self): return f"<Array_UShort(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" +class Image_UShort(Array): + """ + Class that represents a Tango UShort Array mapped to table 'att_image_devushort' + """ + __tablename__ = 'att_image_devushort' + __table_args__ = {'extend_existing': True} + value_r = Column(ARRAY(INTEGER)) + value_w = Column(ARRAY(INTEGER)) + + def __repr__(self): + return f"<Image_UShort(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w}',quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>" + def get_class_by_tablename(tablename: str): """ Returns class reference mapped to a table. diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver_util.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_util.py index 0d5e8f4d992170016bae7405c204b785c8cb8573..c797c5267a517dbe00c566297b94cc176f9a9574 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/archiver_util.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_util.py @@ -6,6 +6,7 @@ from tango import DeviceProxy, CmdArgType import re +import os """ A dictionary whose keys are the Tango datatypes mapping, and the values are the relative byte size @@ -21,6 +22,8 @@ DATATYPES_SIZE_DICT = {CmdArgType.DevBoolean:1, CmdArgType.DevShort:2, CmdArgTyp CmdArgType.DevULong64:8,CmdArgType.DevVarLong64Array:None,CmdArgType.DevVarULong64Array:None, CmdArgType.DevInt:4,CmdArgType.DevEncoded:None, CmdArgType.DevEnum:None, CmdArgType.DevPipeBlob:None} +TANGO_HOST = os.environ.get("TANGO_HOST", None) + def get_db_config(device_name:str) -> dict: """ Retrieve the DB credentials from the Tango properties of Configuration Manager or EventSubscribers @@ -46,7 +49,7 @@ def get_attribute_from_fqdn(attribute_name:str): return attribute_name -def device_fqdn(device_name:str, tango_host:str = 'databaseds:10000'): +def device_fqdn(device_name:str, tango_host:str = TANGO_HOST): """ For some operations Tango devices must be transformed from the form 'domain/family/name' to 'tango://db:port/domain/family/name' @@ -59,7 +62,7 @@ def device_fqdn(device_name:str, tango_host:str = 'databaseds:10000'): return f"tango://{tango_host}/{device_name}".lower() -def attribute_fqdn(attribute_name:str, tango_host:str = 'databaseds:10000'): +def attribute_fqdn(attribute_name:str, tango_host:str = TANGO_HOST): """ For some operations Tango devices must be transformed from the form 'domain/family/name/attribute' to 'tango://db:port/domain/family/name/attribute' diff --git a/tangostationcontrol/tox.ini b/tangostationcontrol/tox.ini index 9a7799463c22c24e85236c4e780a57e951502964..40f6e5cf38bace12fc00a2ccba1c0515678906c3 100644 --- a/tangostationcontrol/tox.ini +++ b/tangostationcontrol/tox.ini @@ -31,7 +31,7 @@ commands = {envpython} -m stestr run {posargs} passenv = TANGO_HOST setenv = TESTS_DIR=./tangostationcontrol/integration_test/{posargs} commands = - {envpython} -m stestr run --serial + {envpython} -m stestr run --serial {posargs} [testenv:cover] ; stestr does not natively support generating coverage reports use