Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cs/ds/alarm-handler
  • francesco.tripaldi/alarm-handler
2 results
Show changes
Commits on Source (51)
Showing
with 1884 additions and 359 deletions
......@@ -28,6 +28,7 @@
*.out
*.app
bin/
build/
.nse_depinfo
......
image:
name: harbor.skao.int/production/ska-tango-images-tango-dsconfig:1.5.5
stages:
- build
- test
build_job:
stage: build
tags:
- docker
before_script:
- sudo apt update && sudo apt -y --no-install-recommends install build-essential cmake pkg-config libboost-thread-dev
script:
- mkdir build && cd build
- cmake -DBUILD_TESTS=ON ..
- make
artifacts:
paths:
- build/alarm-handler-srv
- build/bin/testdevice-srv
expire_in: 1 week
test_load_job:
stage: test
tags:
- docker
before_script:
- sudo apt update && sudo apt -y --no-install-recommends install libboost-thread-dev
script:
- sleep 10
- /usr/local/bin/DataBaseds 2 -ORBendPoint giop:tcp::10000 &
- sleep 10
- exit_code=2
- json2tango -w -a -u ./test/ah_config.json || exit_code=$?
- if [ ${exit_code} -ne 2 ]; then echo "Tango DB configuration failed!" ; else echo "Tango DB configuration succedeed!"; fi
- ./build/alarm-handler-srv 01 &
- ./build/bin/testdevice-srv 01 &
- sleep 5
- python ./test/load-alarm-conf.py --device=alarm/handler/01 --load="tag=test0;formula=(alarm/test/01/condition == 1);on_delay=0;off_delay=0;priority=high;shlvd_time=0;group=gr_test;message=Test alarm;url=;on_command=;off_command=;enabled=1"
- sleep 1
- python ./test/check-alarm-conf.py --device=alarm/handler/01 --alarm="tag=test0;formula=(alarm/test/01/condition == 1);on_delay=0;off_delay=0;priority=high;shlvd_time=0;group=gr_test;message=Test alarm;url=;on_command=;off_command=;enabled=1"
needs: ["build_job"]
services:
- name: harbor.skao.int/production/ska-tango-images-tango-db:10.4.16
alias: tangodb
image:
name: harbor.skao.int/production/ska-tango-images-tango-dsconfig:1.5.5
# The following variables are automatically passed down to the tangodb container
# as well as the tangodatabaseds container and available within each.
variables:
MYSQL_ROOT_PASSWORD: "secret"
MYSQL_DATABASE: "tango"
MYSQL_USER: "tango"
MYSQL_PASSWORD: "tango"
MYSQL_HOST: "tangodb"
TANGO_HOST: "localhost:10000"
stages:
- build
- conf
- test
services:
- name: harbor.skao.int/production/ska-tango-images-tango-db
alias: tangodb
# - name: harbor.skao.int/production/ska-tango-images-tango-cpp
# alias: tangodatabaseds
# entrypoint: ["/usr/local/bin/DataBaseds"]
# command: ["2","-ORBendPoint giop:tcp::10000"]
build_job:
stage: build
before_script:
#TODO: remove procps use for ps
- sudo apt update && sudo apt -y --no-install-recommends install build-essential cmake pkg-config libboost-thread-dev procps
script:
#- make
- mkdir build && cd build
- cmake ..
- make
artifacts:
paths:
- build/alarm-handler-srv
expire_in: 1 week
# # depending on your build setup it's most likely a good idea to cache outputs to reduce the build time
# cache:
# paths:
# - build/CMakeFiles/
configure_and_run_job:
stage: conf
script:
- sleep 10
- /usr/local/bin/DataBaseds 2 -ORBendPoint giop:tcp::10000 &
- sleep 10
- exit_code=2
- json2tango -w -a -u ./test/ah_config.json || exit_code=$?
# json2tango returns 2 if values written to DB
- if [ ${exit_code} -ne 2 ]; then echo "Tango DB configuration failed!" ; else echo "Tango DB configuration succedeed!"; fi
- sleep 5
artifacts:
paths:
- build/alarm-handler-srv
expire_in: 1 week
needs: ["build_job"]
#services:
# - name: harbor.skao.int/production/ska-tango-images-tango-db
# alias: tangodb
test_job:
stage: test
before_script:
#TODO: remove procps use for ps
- sudo apt update && sudo apt -y --no-install-recommends install libboost-thread-dev procps
script:
- /usr/local/bin/DataBaseds 2 -ORBendPoint giop:tcp::10000 &
- sleep 10
- ./build/alarm-handler-srv 01 &
- sleep 10
- ps -ef | grep alarm-handler-srv | grep -v grep
- sleep 5
needs: ["configure_and_run_job"]
# Functions and Pre-build -----------------------------------
# Stop messy in source builds
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES OFF)
if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()
# Start Build Config -----------------------------------
cmake_minimum_required(VERSION 3.8)
set(CMAKE_SKIP_RPATH true)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Output name for the final binary
set(AH_NAME "alarm-handler-srv")
# Versioning
set(VERSION_MAJOR "1")
set(VERSION_MINOR "0")
set(VERSION_PATCH "0")
set(VERSION_METADATA "")
set(VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
# Add any include paths from the command line
list(APPEND INCLUDE_PATHS ${CMAKE_INCLUDE_PATH})
list(APPEND INCLUDE_PATHS ${CMAKE_SOURCE_DIR})
list(APPEND LIBRARY_PATHS ${CMAKE_LIBRARY_PATH})
# Start the project
project(alarm_handler VERSION ${VERSION_STRING} LANGUAGES CXX)
# Build options
option(ENABLE_CLANG "Enable clang code and layout analysis" OFF)
option(BUILD_TESTS "Build tests" OFF)
# arch install definitions
include(GNUInstallDirs)
message(STATUS "Searching for libraries...")
# Variable to contain a list of all the libs we depend on
set(AH_LIBRARIES)
# allow pkg-config to search the CMAKE_PREFIX_PATH
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON)
list(APPEND CMAKE_PREFIX_PATH "/usr")
# Find Dependencies -----------------------------------
# Find tango if it has not already been found. Returns an interface library
# called TangoInterfaceLibrary
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(Tango)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.65.0 COMPONENTS thread)
# Code Analysis -----------------------------------
if(ENABLE_CLANG)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# To find clang, find_program will search your PATH environment variable.
# Ensure if you have a non-standard clang install, that it has been added
# to your path.
find_program(CLANG_TIDY_EXE
NAMES "clang-tidy"
DOC "Path to clang-tidy executable")
if(NOT CLANG_TIDY_EXE)
message(STATUS "clang-tidy not found.")
else(NOT CLANG_TIDY_EXE)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}")
endif(NOT CLANG_TIDY_EXE)
endif(ENABLE_CLANG)
# Source -----------------------------------
add_subdirectory(src)
# Build Targets -----------------------------------
# Executable --------
add_executable(alarm_handler ${SRC_FILES})
target_link_libraries(alarm_handler
PRIVATE
TangoInterfaceLibrary
${Boost_LIBRARIES}
)
target_include_directories(alarm_handler
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
${INCLUDE_PATHS}
"${PROJECT_BINARY_DIR}"
${Boost_INCLUDE_DIRS})
if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set_target_properties(alarm_handler
PROPERTIES
OUTPUT_NAME ${AH_NAME}
LINK_FLAGS "-Wl,--no-undefined"
CXX_STANDARD 17)
else()
set_target_properties(alarm_handler
PROPERTIES
OUTPUT_NAME ${AH_NAME}
LINK_FLAGS ""
CXX_STANDARD 17)
endif()
if(DO_CLANG_TIDY)
set_target_properties(alarm_handler
PROPERTIES
CXX_CLANG_TIDY ${DO_CLANG_TIDY})
endif(DO_CLANG_TIDY)
target_compile_options(alarm_handler
PRIVATE "$<$<CONFIG:DEBUG>:-g>")
# Install Config -----------------------------------
install(
TARGETS alarm_handler
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
message(STATUS "Configured alarm-handler project")
# Tests -----------------------------------
if(BUILD_TESTS)
add_subdirectory(test)
endif(BUILD_TESTS)
# alarm
# Alarm-handler
Elettra alarm-handler Tango device
## building
git clone http://github.com/ELETTRA-SincrotroneTrieste/makefiles.git
## Building and Installation
git clone http://github.com/ELETTRA-SincrotroneTrieste/alarm-handler.git
In its simplest form, clone the repository and assuming a standard install for all dependencies:
cd alarm-handler
```
mkdir build
cd build
cmake ../
make
make install
```
### pkg-config Settings
The build system uses pkg-config to find some dependencies, for example Tango. If Tango is not installed to a standard location, set PKG_CONFIG_PATH, i.e.
```bash
export PKG_CONFIG_PATH=/non/standard/tango/install/location
...
cmake ../
...
```
The pkg-config path can also be set with the cmake argument CMAKE_PREFIX_PATH. This can be set on the command line at configuration time, i.e.:
```bash
...
cmake -DCMAKE_PREFIX_PATH=/non/standard/tango/install/location ../
...
```
### Project Flags
| Flag | Setting | Default | Description |
|------|-----|-----|-----|
| BUILD_TESTS | ON/OFF | OFF | Build test devices under test directory |
### Standard CMake Flags
The build system is CMake therefore standard CMake flags can be used to influence the build and installation process. The following is a list of common useful CMake flags and their use:
| Flag | Use |
|------|-----|
| CMAKE_INSTALL_PREFIX | Standard CMake flag to modify the install prefix. |
| CMAKE_INCLUDE_PATH | Standard CMake flag to add include paths to the search path. |
| CMAKE_LIBRARY_PATH | Standard CMake flag to add paths to the library search path |
## Legacy Building
Using Elettra makefiles, clone both alarm-handler and makefile repositories, then call make:
```bash
git clone http://gitlab.elettra.eu/cd/ds/makefiles.git
git clone http://gitlab.elettra.eu/cs/ds/alarm-handler.git
cd alarm-handler
make
```
include(CMakeParseArguments)
function(find_libraries)
# Parse the parameters
set(MULTIVALUEARGS LIBRARIES SEARCH_PATHS)
cmake_parse_arguments(FIND_LIBRARIES "" "" "${MULTIVALUEARGS}" ${ARGN})
# Clear the found libraries
unset(FOUND_LIBRARIES PARENT_SCOPE)
foreach(LIB ${FIND_LIBRARIES_LIBRARIES})
# try the user provided paths first
find_library(FOUND_LIB_${LIB} ${LIB} PATHS ${FIND_LIBRARIES_SEARCH_PATHS} NO_DEFAULT_PATH)
# if we could not find it, drop to the system paths
if(NOT FOUND_LIB_${LIB})
find_library(FOUND_LIB_${LIB} ${LIB})
endif(NOT FOUND_LIB_${LIB})
if(FOUND_LIB_${LIB})
message(STATUS "Found " ${LIB} " at: " ${FOUND_LIB_${LIB}})
list(APPEND FOUND_LIBRARIES ${FOUND_LIB_${LIB}})
else()
message(FATAL "Could not find " ${LIB})
endif(FOUND_LIB_${LIB})
endforeach(LIB ${LIBRARIES})
set(FOUND_LIBRARIES ${FOUND_LIBRARIES} PARENT_SCOPE)
endfunction(find_libraries)
\ No newline at end of file
if(NOT TARGET TangoInterfaceLibrary)
# Ensure pkg-config is installed
find_package(PkgConfig REQUIRED)
# Now search for the tango.pc file, this is a required dependency
message(STATUS "Search for TANGO package config...")
pkg_search_module(TANGO REQUIRED tango>=9.2.5)
message(STATUS "Found tango version ${TANGO_VERSION} at ${TANGO_PREFIX}")
include(FindLibraries)
find_libraries(LIBRARIES ${TANGO_LIBRARIES} SEARCH_PATHS ${TANGO_LIBRARY_DIRS})
# Create an interface library to represent the tango linkage
add_library(TangoInterfaceLibrary INTERFACE)
set_target_properties(TangoInterfaceLibrary
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${TANGO_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${FOUND_LIBRARIES}"
INTERFACE_COMPILE_OPTIONS "${TANGO_CFLAGS}")
message(STATUS "Configured Tango Interface for TANGO version ${TANGO_VERSION}")
endif(NOT TARGET TangoInterfaceLibrary)
\ No newline at end of file
File added
# Formula syntax
The formula is an expression with operators, operands and functions. Operands can be variables, constant values, or other expression optionally enclosed by parentheses.
## Operands
### Variables
- Attributes names with or without fqdn (e.g. ```tango://host:port/name/of/dev/attr```, ```name/of/dev/attr```)
- attribute properties ```.quality```, ```.alarm```, ```.normal``` so that
- ```name/of/dev/attr.quality``` returns the Tango quality (the integer value) of the attribute
- ```name/of/dev/attr.alarm``` returns true if the attribute ==UNACK or ==ACK
- ```name/of/dev/attr.normal``` returns true if the attribute ==NORM or ==RTNUN
### Constants
- Real numbers (e.g. ```name/of/dev/attr >= 35```, ```name/of/dev/attr < -23.5```)
- Hexadecimal numbers (e.g. ```name/of/dev/attr != 0xaf```, ```name/of/dev/attr & 0x1A```)
- Strings as any character between an opening and a closing ' (e.g. ```name/of/dev/status == 'The device is in ON state.'```)
- Tango states enum labels (*ON, OFF, CLOSE, OPEN, INSERT, EXTRACT, MOVING, STANDBY, FAULT, INIT, RUNNING, ALARM, DISABLE, UNKNOWN*) (e.g. ```name/of/dev/state == FAULT```)
- Tango quality enum labels (*ATTR_VALID, ATTR_INVALID, ATTR_WARNING, ATTR_ALARM, ATTR_CHANGING*) (e.g. ```name/of/dev/attr.quality == ATTR_ALARM```)
- Alarm state enum labels (*NORM, UNACK, ACKED, RTNUN, SHLVD, DSUPR, OOSRV*) (e.g. ```name/of/dev/alarm_attr != NORM```)
### Expressions
- A combination of operands and operators enclosed by parentheses
## Operators
### Binary Math
- Multiplication ```*```
- Division ```/```
- Addition ```+```
- Subtraction ```-```
### Binary Comparison
- Equal ```==```
- Not equal ```!=```
- Greater than ```>```
- Greater than or equal to ```>=```
- Less than ```<```
- Less than or equal to ```<=```
### Binary Logical
- Logical AND ```&&```
- Logical OR ```||```
### Binary Bitwise
- Left shift ```<<```
- Right shift ```>>```
- Bitwise AND ```&```
- Bitwise OR ```|```
- Bitwise XOR ```^```
### Unary Math
- Minus ```-```
### Unary Logical
- Logical NOT ```!```
### Binary operators order of precedence
```
*, /, +, -, <<, >>, <=, >=, >, <, ==, !=, &, |, ^, &&, ||
```
## Functions
### Unary Functions
- Absolute value of X ```abs(X)```
- Sine of X ```sin(X)```
- Cosine of X ```cos(X)```
### Binary Functions
- Minimum between two values X and Y ```min(X,Y)```
- Maximum between two values X and Y ```max(X,Y)```
- Power: X raised to the power of Y ```pow(X,Y)```
### Ternary Functions
- Conditional operator: if X then Y else Z ```X ? Y : Z```
### Reduce Functions
- Reduce OR: reduce array X applying logical OR to each element ```OR(X)```
- Reduce AND: reduce array X applying logical AND to each element ```OR(X)```
# Attributes types
The following types of attribute are supported:
```
Scalar, Spectrum, Image
```
with data types:
```
DevBoolean, DevUChar, DevShort, DevUShort, DevLong, DevULong, DevLong64, DevULong64, DevFloat, DevDouble, DevString, DevState, DevEnum
```
```DevEncoded``` is not supported.
The read part of every attribute is internally extracted in a vector of double with the ```extract_read``` method of the ```DeviceAttribute``` class. In this ways operations between attribute with different data types and sizes can be performed with the following constraints:
- DevString attributes can only be compared with 'equal' or 'not equal' operators to DevString attributes or string constants
- Binary operators can operate on arrays if both operands have the same size, or one of the two has size equal to one.
# Operation on arrays
## Indexes to access elements
- A single element of a one-dimensional array attribute (Spectrum) can be extracted with a single index between square brackets (e.g. ```name/of/dev/attr[ind]```).
- A single element of a two-dimensional array attribute (Image) can be extracted with two indexes between square brackets (e.g. ```name/of/dev/attr[ind_row][ind_column]```).
- A one-dimensional array can be extracted from a two-dimensional array attribute (Image) with a single index between square brackets (e.g. ```name/of/dev/attr[ind_row]```).
## Lists and ranges of indexes to slice arrays
Indexes can be specified as a comma separated list and/or hyphen-separated range (e.g. ```[i0,i1-i2,...]```).
In this way:
- A slice can be extracted from a one-dimensional array with a list and/or range of indexes between square brackets (e.g. ```name/of/dev/1Dattr[i0,i1-i2,...]```).
- A subset of rows can be extracted from a two-dimensional array with a list and/or range of indexes for the first dimension (e.g. ```name/of/dev/2Dattr[i0,i1-i2,...]```).
- A single column slice can be extracted from a two-dimensional array with a list and/or range of indexes for the first dimension and a single index for the second dimension (e.g. ```name/of/dev/2Dattr[i0,i1-i2,...][i3]```).
- A single row slice can be extracted from a two-dimensional array with a single index for the first dimension and list/range of indexes for the second dimension (e.g. ```name/of/dev/2Dattr[i0][i1-i2,i3,...]```).
- An array slice can be extracted from a two-dimensional array with a list and/or range of indexes for both the first and second dimensions (e.g. ```name/of/dev/2Dattr[i0-i1,...][i2,i3,...]```).
- To specify all elements of one dimension index -1 can be used (e.g. Column 3 of all rows of 2D array ```name/of/dev/2Dattr[-1][3]```).
If any index exceeds actual dimensions of the array, the formula is evaluated to ERROR with an out of bounds exception.
No check is done on the order and uniqueness of indexes, so it is allowed to concatenate duplicated and out of order elements/rows/columns (e.g. ```name/of/dev/2Dattr[0-2,1,0,..]``` evaluates to an array with rows 0,1,2,1,0 of 2Dattr)
## Limitations
- It is not possible to specify array constants (e.g. ```name/of/dev/attr > [val1,val2]```).
- It is not possible to use indexes on expressions (e.g. ```(any_expression)[ind]```).
## Unary operators and functions
Unary operators and functions are applied to every element of the array
## Binary operators and functions
- If both operands have the same size, operators are applied element by element. Result is an array with the same size.
- If one operand has size one, operators apply it to every element of the other operand. Result is an array with the same size.
- Otherwise an exception is raised and the formula is evaluated to the *ERROR* state with the Reason, Descrption and Origin DevFailed fields properly filled.
## Ternary Function
- Conditional operator: if X then Y else Z. X is implicitly reduced with *OR* to have a boolean value, then Y or Z are evaluated depending on the result
# Formula result
Every formula produce a boolean result in the following way:
1. each element of the array is tested as not equal to zero in order to have an array of booleans
2. the array of boolean is reduced with OR (i.e. if at least one element of the array is TRUE, the result is TRUE)
# Errors
If a formula cannot be evaluated, the corresponding alarm is set to the *ERROR* value with the Reason, Description and Origin DevFailed fields properly filled.
Possible errors are:
- Errors coming from the event system for one or more attributes involved in the formula
- Errors coming from evaluation of array with different sizes
- Errors coming from indexes out of bound while extracting elements from arrays
- Unexpected errors while evaluating formulas
File added
File added
File added
File added
File added
File added
......@@ -37,6 +37,7 @@
#include <AlarmHandler.h>
#include <AlarmHandlerClass.h>
#include <ctype.h> //for tolower
#include <numeric> //for std::accumulate
#include "alarm-thread.h"
#include "alarm_grammar.h"
......@@ -130,6 +131,7 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $";
// alarmSummary | Tango::DevString Spectrum ( max = 10000)
// eventList | Tango::DevString Spectrum ( max = 10000)
// eventSummary | Tango::DevString Spectrum ( max = 10000)
// alarmDisabled | Tango::DevString Spectrum ( max = 10000)
//================================================================
namespace AlarmHandler_ns
......@@ -342,6 +344,7 @@ void AlarmHandler::delete_device()
delete[] attr_alarmSummary_read;
delete[] attr_eventList_read;
delete[] attr_eventSummary_read;
delete[] attr_alarmDisabled_read;
}
//--------------------------------------------------------
......@@ -370,7 +373,7 @@ void AlarmHandler::init_device()
if(instanceCounter > 1)
{
ERROR_STREAM << "More than one instance in the same executable of Alarm Server is not allowed!!" << endl;
cout << "ERROR: second instance of Alarm Server, exiting..." << endl;
TANGO_LOG << "ERROR: second instance of Alarm Server, exiting..." << endl;
exit(-1);
} //-------------------------------------------
alarmedlock = new(ReadersWritersLock);
......@@ -399,6 +402,7 @@ void AlarmHandler::init_device()
attr_alarmSummary_read = new Tango::DevString[10000];
attr_eventList_read = new Tango::DevString[10000];
attr_eventSummary_read = new Tango::DevString[10000];
attr_alarmDisabled_read = new Tango::DevString[10000];
/*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/
/* for(size_t i=0; i<MAX_ALARMS; i++)
{
......@@ -412,6 +416,7 @@ void AlarmHandler::init_device()
alarmSummary_read[i].resize(MAX_ATTR_SUMMARY);
}*/
// Initialize device
alarms.set_al_qual(setAlarmQuality);
alarms.set_err_delay(errorDelay);
thread->period = subscribeRetryPeriod;
......@@ -486,6 +491,8 @@ void AlarmHandler::init_device()
rule_names[formula_grammar::val_qualityID] = "ValQuality";
rule_names[formula_grammar::val_alarm_enum_stID] = "ValAlarmEnumStatus";
rule_names[formula_grammar::propertyID] = "EventProperty";
rule_names[formula_grammar::index_rangeID] = "RangeIndex";
rule_names[formula_grammar::index_listID] = "ListIndex";
/*
* get device attribute properties and initialize internal
......@@ -520,7 +527,7 @@ void AlarmHandler::init_device()
} catch(string & e)
{
ERROR_STREAM << "AlarmHandler::init_device(): " << e << endl;
cout << "Error: " << e << ". Exiting..." << endl;
TANGO_LOG << "Error: " << e << ". Exiting..." << endl;
exit(-4);
}
......@@ -629,6 +636,8 @@ void AlarmHandler::init_device()
for(alarm_container_t::iterator i = alarms.v_alarm.begin(); \
i!=alarms.v_alarm.end(); i++)
{
if(!i->second.enabled)
i->second.ts_time_silenced = gettime(); //TODO: save time when alarm was disabled
if(i->second.cmd_name_a.length() > 0)
{
try {
......@@ -748,7 +757,7 @@ void AlarmHandler::init_device()
}
}
set_change_event("alarm",true,false);
set_change_event("alarm",true,true);
/*
* create alarm processing thread
*/
......@@ -821,6 +830,7 @@ void AlarmHandler::get_device_property()
dev_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
dev_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));
dev_prop.push_back(Tango::DbDatum("ErrorDelay"));
dev_prop.push_back(Tango::DbDatum("SetAlarmQuality"));
// is there at least one property to be read ?
if (dev_prop.size()>0)
......@@ -879,6 +889,17 @@ void AlarmHandler::get_device_property()
// And try to extract ErrorDelay value from database
if (dev_prop[i].is_empty()==false) dev_prop[i] >> errorDelay;
// Try to initialize SetAlarmQuality from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty()==false) cl_prop >> setAlarmQuality;
else {
// Try to initialize SetAlarmQuality from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty()==false) def_prop >> setAlarmQuality;
}
// And try to extract SetAlarmQuality value from database
if (dev_prop[i].is_empty()==false) dev_prop[i] >> setAlarmQuality;
}
/*----- PROTECTED REGION ID(AlarmHandler::get_device_property_after) ENABLED START -----*/
......@@ -979,11 +1000,13 @@ void AlarmHandler::read_alarm(Tango::Attribute &attr)
//DEBUG_STREAM << "AlarmHandler::read_alarm(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_alarm) ENABLED START -----*/
// Add your own code here
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
attr.set_value(ds, ds_num, 0, false);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarm
......@@ -1206,6 +1229,24 @@ void AlarmHandler::read_eventSummary(Tango::Attribute &attr)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_eventSummary
}
//--------------------------------------------------------
/**
* Read attribute alarmDisabled related method
* Description: List of alarms in out of service or shelved state
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
//--------------------------------------------------------
void AlarmHandler::read_alarmDisabled(Tango::Attribute &attr)
{
//DEBUG_STREAM << "AlarmHandler::read_alarmDisabled(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_alarmDisabled) ENABLED START -----*/
// Set the attribute value
attr.set_value(attr_alarmDisabled_read, alarmDisabled_sz);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarmDisabled
}
//--------------------------------------------------------
/**
......@@ -1234,7 +1275,10 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
break;
}
}
bool error;
bool error=false;
bool enabled=true;
bool shelved=false;
int silenced=0;
if(it != alarms.v_alarm.end())
{
reason = it->second.ex_reason;
......@@ -1242,10 +1286,13 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
origin = it->second.ex_origin;
quality = it->second.quality;
error = it->second.error;
enabled = it->second.enabled;
shelved = it->second.shelved;
silenced = it->second.silenced;
}
DEBUG_STREAM << "AlarmHandler::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl;
alarms.vlock->readerOut();
if(error) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used
if(error && enabled && !(shelved && silenced >0)) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used
//if(desc.length() > 0)
{
Tango::Except::throw_exception(
......@@ -1254,7 +1301,7 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
origin, Tango::ERR);
}
// Set the attribute value
if(quality != Tango::ATTR_VALID)
if(quality != Tango::ATTR_VALID && setAlarmQuality)
{
timeval now;
gettimeofday(&now, NULL);
......@@ -1375,7 +1422,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
localalarmed = *found; //NOTE: copy before updating ack
localv_alarm = i->second;
//update alarm ack in alarmed table
found->ack = ACK;
alarmedlock->readerOut();
alarms.vlock->readerOut();
......@@ -1397,12 +1444,20 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
*attr_value = _RTNUN;
try
{ //DevFailed for push events
if(localv_alarm.ex_reason.empty())
if(!localv_alarm.error || !localv_alarm.enabled || (localv_alarm.shelved && localv_alarm.silenced > 0))
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
}
}
else
{
......@@ -1454,6 +1509,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -1462,6 +1518,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -1476,7 +1533,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -1487,7 +1545,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0],alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
......@@ -1690,7 +1749,7 @@ void AlarmHandler::load(Tango::DevString argin)
alarms.vlock->readerOut();
#if 0//TODO
#if 1//TODO
prepare_alarm_attr();
try
{
......@@ -1778,6 +1837,7 @@ void AlarmHandler::remove(Tango::DevString argin)
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -1786,6 +1846,7 @@ void AlarmHandler::remove(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -1800,7 +1861,8 @@ void AlarmHandler::remove(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -1811,7 +1873,8 @@ void AlarmHandler::remove(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -1862,13 +1925,13 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}*/
start_pos = filter.find("*", start_pos);
if(start_pos != std::string::npos && start_pos == filter.size()-1) //* is the only character or at the end of the filter
if(start_pos != std::string::npos && start_pos == filter.size()-1) // * is the only character or at the end of the filter
{
filter.replace(start_pos, 1, "");
filter_begin = filter;
DEBUG_STREAM << __func__ << ": updated filter to: " << filter_begin;
}
/*else if(start_pos != std::string::npos) //* is in the middle of the filter
/*else if(start_pos != std::string::npos) // * is in the middle of the filter
{
string filter_begin=filter.substr(0,start_pos);
string filter_end=filter.substr(start_pos+1);
......@@ -1896,9 +1959,9 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
{
ostringstream os;
os.clear();
os << ai->second.ts.tv_sec << SEP << KEY(NAME_KEY) << ai->second.name << SEP << KEY(FORMULA_KEY) << ai->second.formula << SEP << KEY(ONDELAY_KEY) << ai->second.on_delay << SEP << KEY(OFFDELAY_KEY) << ai->second.off_delay <<
os << KEY(NAME_KEY) << ai->second.name << SEP << KEY(FORMULA_KEY) << ai->second.formula << SEP << KEY(ONDELAY_KEY) << ai->second.on_delay << SEP << KEY(OFFDELAY_KEY) << ai->second.off_delay <<
SEP << KEY(LEVEL_KEY) << ai->second.lev << SEP << KEY(SILENT_TIME_KEY) << ai->second.silent_time << SEP << KEY(GROUP_KEY) << ai->second.grp2str() << SEP << KEY(MESSAGE_KEY) << ai->second.msg << SEP << KEY(URL_KEY) << ai->second.url <<
SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0");
SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(RECEIVERS_KEY) << ai->second.receivers << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0");
alarm_filtered.push_back(os.str());
}
} /* for */
......@@ -1939,6 +2002,7 @@ void AlarmHandler::stop_audible()
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -1947,6 +2011,7 @@ void AlarmHandler::stop_audible()
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -1961,7 +2026,8 @@ void AlarmHandler::stop_audible()
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -1972,7 +2038,8 @@ void AlarmHandler::stop_audible()
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2006,6 +2073,16 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
alarm_container_t::iterator i = alarms.v_alarm.find(*si);
if(i != alarms.v_alarm.end())
{
if(!i->second.enabled)
{
ostringstream err;
err << *si << " is not enabled";
alarms.vlock->readerOut();
Tango::Except::throw_exception( \
(const char*)"NOT_ENABLED", \
(const char*)err.str().c_str(), \
(const char*)__func__, Tango::ERR);
}
if(i->second.silenced > 0)
{
Tango::TimeVal now = gettime();
......@@ -2077,6 +2154,7 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -2085,6 +2163,7 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -2099,7 +2178,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2110,7 +2190,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2120,7 +2201,6 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::silence
}
//--------------------------------------------------------
/**
* Command Modify related method
......@@ -2179,6 +2259,7 @@ void AlarmHandler::modify(Tango::DevString argin)
i->second.cmd_dp_n = alm.cmd_dp_n;
i->second.cmd_action_n = alm.cmd_action_n;
//i->second.send_arg_n = alm.send_arg_n;
i->second.receivers = alm.receivers;
i->second.enabled = alm.enabled;
//update attribute properties
......@@ -2276,10 +2357,11 @@ void AlarmHandler::modify(Tango::DevString argin)
//4: load modified alarm
//------------------------------
load(argin);
usleep(150000);//wait some time before updating attributes with prepare_alarm_attr so that event are subscribed and first evaluation done
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -2288,6 +2370,7 @@ void AlarmHandler::modify(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -2302,7 +2385,8 @@ void AlarmHandler::modify(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2313,7 +2397,8 @@ void AlarmHandler::modify(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2436,13 +2521,24 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
*attr_value = _SHLVD;
try
{ //DevFailed for push events
if(alm.ex_reason.empty())
#if 0//do not store errors for disabled alarms
if(!alm.error)
#endif
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#if 0//do not store errors for disabled alarms
else
{
Tango::DevErrorList errors(1);
......@@ -2455,6 +2551,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}
#endif
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -2465,6 +2562,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -2473,6 +2571,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -2485,7 +2584,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2494,7 +2594,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2551,12 +2652,20 @@ void AlarmHandler::enable(Tango::DevString argin)
*attr_value = _RTNUN;
try
{ //DevFailed for push events
if(alm.ex_reason.empty())
if(!alm.error)
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
else
{
......@@ -2578,6 +2687,7 @@ void AlarmHandler::enable(Tango::DevString argin)
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -2586,6 +2696,7 @@ void AlarmHandler::enable(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -2598,7 +2709,8 @@ void AlarmHandler::enable(Tango::DevString argin)
push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2607,7 +2719,8 @@ void AlarmHandler::enable(Tango::DevString argin)
push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2649,6 +2762,7 @@ void AlarmHandler::disable(Tango::DevString argin)
i->second.enabled = false;
i->second.ts_time_silenced = gettime();
i->second.silenced = (i->second.silent_time > 0) ? 0 : -1; //0: can be silenced, -1: cannot be silenced
i->second.shelved = false;
alarm_t alm = i->second;
......@@ -2658,13 +2772,24 @@ void AlarmHandler::disable(Tango::DevString argin)
*attr_value = _OOSRV;
try
{ //DevFailed for push events
if(alm.ex_reason.empty())
#if 0 //do not store errors for disabled alarms
if(!alm.error)
#endif
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#if 0 //do not store errors for disabled alarms
else
{
Tango::DevErrorList errors(1);
......@@ -2677,6 +2802,7 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}
#endif
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -2703,6 +2829,7 @@ void AlarmHandler::disable(Tango::DevString argin)
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -2711,6 +2838,7 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -2725,7 +2853,8 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2736,7 +2865,8 @@ void AlarmHandler::disable(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2797,6 +2927,7 @@ void AlarmHandler::stop_new()
prepare_alarm_attr();
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -2805,6 +2936,7 @@ void AlarmHandler::stop_new()
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -2819,7 +2951,8 @@ void AlarmHandler::stop_new()
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read);
push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -2830,7 +2963,8 @@ void AlarmHandler::stop_new()
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read);
push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -2897,11 +3031,23 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
ostringstream tmp_ex;
tmp_ex.str("");
ostringstream tmp;
tmp.str("");
tmp << "\"" << it->second.msg << "\"";
if(it->second.error)
{
tmp_ex << "{\"Reason\":\"" << it->second.ex_reason << "\",\"Desc\":\"" << it->second.ex_desc << "\",\"Origin\":\"" << it->second.ex_origin << "\"}";
info.insert(make_pair(VALUE_KEY,string("ERROR")));
complete.push_back(KEY(VALUE_KEY)+string("ERROR"));
string almstate(tmp_val.str());
if(almstate != "SHLVD" && almstate != "OOSRV")
{
almstate = S_ERROR;
}
info.insert(make_pair(VALUE_KEY,almstate));
complete.push_back(KEY(VALUE_KEY)+almstate);
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(FORMULA_KEY,it->second.formula));
complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
info.insert(make_pair(ATTR_VALUES_KEY,tmp_ex.str()));
......@@ -2911,13 +3057,26 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
{
info.insert(make_pair(VALUE_KEY,tmp_val.str()));
complete.push_back(KEY(VALUE_KEY)+tmp_val.str());
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(FORMULA_KEY,it->second.formula));
complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
info.insert(make_pair(ATTR_VALUES_KEY,it->second.attr_values));
complete.push_back(KEY(ATTR_VALUES_KEY)+it->second.attr_values);
}
tm time_tm;
time_t time_sec= it->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
ostringstream time_s;
time_s << time_buf << "." << it->second.ts.tv_usec;
info.insert(make_pair(ALARM_TIME_KEY,time_s.str()));
complete.push_back(KEY(ALARM_TIME_KEY)+time_s.str());
ostringstream tmp_qual;
try
......@@ -2929,7 +3088,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
}
info.insert(make_pair(QUALITY_KEY,tmp_qual.str()));
complete.push_back(KEY(QUALITY_KEY)+tmp_qual.str());
ostringstream tmp;
//#if 0
tmp.str("");
tmp << (it->second.enabled ? "1" : "0");
......@@ -2944,6 +3103,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
info.insert(make_pair(ACKNOWLEDGED_KEY,tmp.str())); //TODO: redundant, information already in attr_value
complete.push_back(KEY(ACKNOWLEDGED_KEY)+tmp.str()); //TODO: redundant, information already in attr_value
//#endif
tmp.str("");
tmp << (it->second.is_new ? "1" : "0");
info.insert(make_pair(AUDIBLE_KEY,tmp.str()));
......@@ -2984,17 +3144,12 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
complete.push_back(KEY(SILENT_TIME_REMAINING_KEY)+tmp.str());
info.insert(make_pair(GROUP_KEY,it->second.grp2str()));
complete.push_back(KEY(GROUP_KEY)+it->second.grp2str());
tmp.str("");
tmp << "\"" << it->second.msg << "\"";
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(ON_COMMAND_KEY,it->second.cmd_name_a));
complete.push_back(KEY(ON_COMMAND_KEY)+it->second.cmd_name_a);
info.insert(make_pair(OFF_COMMAND_KEY,it->second.cmd_name_n));
complete.push_back(KEY(OFF_COMMAND_KEY)+it->second.cmd_name_n);
info.insert(make_pair(RECEIVERS_KEY,it->second.receivers));
complete.push_back(KEY(RECEIVERS_KEY)+it->second.receivers);
alarms.vlock->readerOut();
argout = new Tango::DevVarStringArray();
if(argin->length() == 1)
......@@ -3124,6 +3279,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
alm.send_arg_n = false;
alm.dp_n = NULL;
alm.enabled = 1;
alm.receivers.clear();
evn.clear();
alm.formula_tree =
......@@ -3144,6 +3300,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase
alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.receivers = std::regex_replace(alm.receivers, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
if(alm.cmd_name_a.length() > 0)
{
const char *c = alm.cmd_name_a.c_str();
......@@ -3208,6 +3365,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
DEBUG_STREAM << " lev = '" << alm.lev << "'" << endl;
DEBUG_STREAM << " action_a = '" << alm.cmd_name_a << "'" << endl;
DEBUG_STREAM << " action_n = '" << alm.cmd_name_n << "'" << endl;
DEBUG_STREAM << " receivers = '" << alm.receivers << "'" << endl;
DEBUG_STREAM << " enabled = '" << (alm.enabled ? "1" : "0") << "'" << endl;
if ((alm.name.empty() == false) && \
(alm.formula.empty() == false) && \
......@@ -3294,7 +3452,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting)
{
alarms.push_back(a); //take and release writer vlock
DEBUG_STREAM << "AlarmHandler::add_alarm(): added alarm '" \
<< a.name << "'" << endl;
<< a.name << "' starting=" << (int)starting << endl;
if(!starting)
{
alarms.vlock->readerIn();
......@@ -3314,7 +3472,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting)
}
}
void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&)
void AlarmHandler::add_event(alarm_t& a, vector<string> &evn)
{
DEBUG_STREAM << "AlarmHandler::add_event(): formula '" << a.formula << "' found " << evn.size() << " events" << endl;
/*
......@@ -3430,6 +3588,7 @@ void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&)
}
}
} //for (vector<string>::iterator j = evn.begin(); ...
thread->signal(); //wake up subscibe thread if not waked by events->add
for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
{
......@@ -3456,7 +3615,7 @@ void AlarmHandler::do_alarm(bei_t& e)
{
ostringstream o;
o << e.msg;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << e.ev_name << ": " << o.str() << endl;
events->veclock.readerIn();
vector<event>::iterator found_ev = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name);
......@@ -3501,6 +3660,7 @@ void AlarmHandler::do_alarm(bei_t& e)
}
if(found_ev != events->v_event.end())
{
found_ev->valid = false;
Tango::TimeVal ts = gettime();
found_ev->err_counter++;
if(e.type == TYPE_TANGO_ERR)
......@@ -3519,15 +3679,19 @@ void AlarmHandler::do_alarm(bei_t& e)
list<string>::iterator j = m_alarm.begin();
while (j != m_alarm.end())
{
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": before do_alarm_eval name=" << *j << " ev=" << e.ev_name << " err=" << found_ev_ex_desc << endl;
changed = do_alarm_eval(*j, e.ev_name, ts);
//if(!changed)
// continue; //TODO: check if OK
alarms.vlock->readerIn();
alarm_container_t::iterator it = alarms.v_alarm.find(*j);
if(it != alarms.v_alarm.end())
{
#if 0 //already done in alarm_table::update called by do_alarm_eval
it->second.err_counter++;
//if first error, reset ACK
if(it->second.ex_reason.empty() && it->second.ex_desc.empty() && it->second.ex_origin.empty())
{
it->second.ack = NOT_ACK;
it->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay
}
if(e.type == TYPE_TANGO_ERR)
......@@ -3541,32 +3705,69 @@ void AlarmHandler::do_alarm(bei_t& e)
if((ts.tv_sec - errorDelay) > it->second.ts_err_delay.tv_sec) //error is present and err delay has passed
{
if(!it->second.error)
{
it->second.is_new = 1;
it->second.ack = NOT_ACK;//if first error, reset ACK
}
it->second.error = true;
}
}
else
{
if(!it->second.error)
{
it->second.is_new = 1;
it->second.ack = NOT_ACK;//if first error, reset ACK
}
it->second.error = true;
}
#endif
alarm_t alm = it->second;
alarms.vlock->readerOut();
try
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": after do_alarm_eval name=" << *j << " error=" << (int)alm.error << " enabled=" << alm.enabled << endl;
#if 0 //TODO: already pushed in do_alarm_eval, not necessary here ?
if(alm.error && alm.enabled && !(alm.shelved && alm.silenced > 0))
{
Tango::DevErrorList errors(1);
errors.length(1);
errors[0].desc = CORBA::string_dup(alm.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(alm.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(alm.ex_origin.c_str());
Tango::DevFailed except(errors);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << alm.attr_name << " " << alm.ex_desc << "-" << alm.ex_reason << "-" << alm.ex_origin << endl;
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}catch(Tango::DevFailed &ex)
{}
try
{
Tango::DevErrorList errors(1);
errors.length(1);
errors[0].desc = CORBA::string_dup(alm.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(alm.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(alm.ex_origin.c_str());
Tango::DevFailed except(errors);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << alm.attr_name << " " << alm.ex_desc << "-" << alm.ex_reason << "-" << alm.ex_origin << endl;
push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except);
}catch(Tango::DevFailed &ex)
{}
}
else if(alm.error) //TODO: or if(changed) ?
{
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(alm.attr_name);
if(!alm.enabled)
{
*attr_value = _OOSRV;
}
else if(alm.shelved && alm.silenced > 0)
{
*attr_value = _SHLVD;
}
if(setAlarmQuality)
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,static_cast<Tango::AttrQuality>(alm.quality), 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,static_cast<Tango::AttrQuality>(alm.quality), 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#endif
}
else
{
......@@ -3575,6 +3776,7 @@ void AlarmHandler::do_alarm(bei_t& e)
j++;
}
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -3583,6 +3785,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -3598,6 +3801,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -3609,11 +3813,16 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
}
else
{
events->veclock.readerOut();
}
return;
}
}
//here not event error
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl;
formula_res_t res;
events->veclock.readerIn();
vector<event>::iterator found = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name);
......@@ -3657,9 +3866,12 @@ void AlarmHandler::do_alarm(bei_t& e)
}
}
if (found != events->v_event.end())
{
{
found->value = e.value;
found->value_string = e.value_string;
found->read_size = e.read_size;
found->dim_x = e.dim_x;
found->dim_y = e.dim_y;
found->quality = e.quality;
//found->errors = e.errors;
found->ex_reason = e.ex_reason;
......@@ -3701,6 +3913,7 @@ void AlarmHandler::do_alarm(bei_t& e)
return;
}
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -3709,6 +3922,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -3724,6 +3938,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -3735,9 +3950,11 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
}
else
{
events->veclock.readerOut();
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl;
}
} /* do_alarm() */
......@@ -3777,10 +3994,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
it->second.to_be_evaluated = false;
it->second.attr_values.erase(it->second.attr_values.size()-1);
it->second.attr_values += string("}");
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl;
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << print_array(res.value,res.dim_x,res.dim_y) << " quality=" << res.quality << " valid=" << (int)res.valid << endl;
changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); //update internal structure and log to db
changed = changed || prev_error;
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << endl;
changed = changed || (prev_error && res.valid);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << " error=" << (int)it->second.error << endl;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
if(!it->second.enabled)
*attr_value = _OOSRV;
......@@ -3801,12 +4018,20 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
try
{ //DevFailed for push events
if(!it->second.error)
if(!it->second.error || !it->second.enabled || (it->second.shelved && it->second.silenced > 0))
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
if(setAlarmQuality)
{
push_change_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
}
else
{
push_change_event(attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value);
}
}
else
{
......@@ -3826,7 +4051,8 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
}
} catch(std::out_of_range& ex)
{
changed = !prev_error;
events->veclock.readerOut(); //readerIn called in eval_expression
changed = true;//force update attributes in case of modify/load alarm with out_of_range exception
it->second.to_be_evaluated = true;
ostringstream o;
o << tmpname << ": in formula array index out of range!";
......@@ -3837,16 +4063,29 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = string("OUT_OF_RANGE");
it->second.ex_desc = ev_name + ": " + o.str();
it->second.ex_desc = o.str();
it->second.ex_origin = ev_name;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -3856,7 +4095,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
changed = !prev_error;
it->second.to_be_evaluated = true;
ostringstream o;
o << tmpname << ": in formula err=" << ex;
o << ex;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
try
......@@ -3864,16 +4103,70 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = string("FORMULA_ERROR");
it->second.ex_desc = ev_name + ": " + o.str();
it->second.ex_desc = o.str();
it->second.ex_origin = ev_name;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
}
}
catch(Tango::DevFailed & ex)
{
changed = !prev_error;
it->second.to_be_evaluated = true;
ostringstream o;
o << ex.errors[0].desc;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
try
{ //DevFailed for push events
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = ex.errors[0].reason;
it->second.ex_desc = ex.errors[0].desc;
it->second.ex_origin = ex.errors[0].origin;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
......@@ -3882,6 +4175,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
}
else
{
alarms.vlock->readerOut();
ostringstream o;
//o << j->first << ": not found formula in alarm table" << ends;
o << (alm_name) << ": not found formula in alarm table";
......@@ -3942,9 +4236,11 @@ void AlarmHandler::timer_update()
{
return;
}
DEBUG_STREAM << "AlarmHandler::timer_update(): changed -> prepare_alarm_attr" << endl;
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
try
{
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
......@@ -3953,6 +4249,7 @@ void AlarmHandler::timer_update()
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
}
else
#endif
{
//attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false);
......@@ -3968,6 +4265,7 @@ void AlarmHandler::timer_update()
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
......@@ -3979,6 +4277,7 @@ void AlarmHandler::timer_update()
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
} catch(Tango::DevFailed& e)
{
ostringstream err;
......@@ -3987,7 +4286,7 @@ void AlarmHandler::timer_update()
}
}
bool AlarmHandler::remove_alarm(string& s) throw(string&)
bool AlarmHandler::remove_alarm(string& s)
{
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": entering alm name=" << s << endl;
alarms.vlock->writerIn();
......@@ -4097,7 +4396,7 @@ bool AlarmHandler::remove_alarm(string& s) throw(string&)
} /* remove_alarm() */
/*void AlarmHandler::add_to_database(alarm_t& a) throw(string&)
/*void AlarmHandler::add_to_database(alarm_t& a)
{
Tango::DbDatum alarm("alarm");
Tango::DbData db_data;
......@@ -4222,14 +4521,59 @@ void AlarmHandler::set_internal_alarm(string name, Tango::TimeVal t, string msg,
//==============================================================
formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_values)
{
return eval_expression(tree.trees.begin(), attr_values);
formula_res_t res = eval_expression(tree.trees.begin(), attr_values);
res.extract_result(); //from Array res.value to Scalar res.value
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << __func__ << ": finally value=" << print_array(res.value,res.dim_x,res.dim_y) << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"' quality=" << res.quality << endl;
#endif
if(res.valid)
{
res.ex_reason.clear();
res.ex_desc.clear();
res.ex_origin.clear();
res.error.clear();
}
return res;
}
void AlarmHandler::eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind)
{
if(i->value.id() == formula_grammar::index_rangeID || i->value.id() == formula_grammar::indexID)
{
if(i->children.size() == 0)
{
std::string val_s(i->value.begin(), i->value.end());
long value = strtol(val_s.c_str(), NULL, 10);
if(value>=0)
{
ind.push_back(value);
}
else if(value == -1)
{
ind = {(double)(value)};
}
}
else if(i->children.size() == 2)
{
iter_t child = i->children.begin();
string val_s1(child->value.begin(), child->value.end());
long ind_start = strtol(val_s1.c_str(), NULL, 10);
string val_s2((child+1)->value.begin(), (child+1)->value.end());
long ind_end = strtol(val_s2.c_str(), NULL, 10);
if(ind_start>=0 && ind_end>=ind_start)
{
for(int ind_range=ind_start; ind_range<=ind_end; ind_range++)
ind.push_back((double)ind_range);
}
}
}
}
formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range
formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind)
{
ostringstream err;
err << "Evaluating formula: ";
err << "";
//iter_t it = i->children.begin();
if (i->value.id() == formula_grammar::val_rID)
......@@ -4241,9 +4585,12 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
string val_d(i->value.begin(), i->value.end());
formula_res_t res;
res.value = strtod(val_d.c_str(), 0);
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl;
DEBUG_STREAM << " node value real = " << val_d << "(value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<<")" << endl;
#endif
return res;
}
......@@ -4259,7 +4606,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value hex = " << val_d << endl;
#endif
formula_res_t res;
res.value = strtod(val_d.c_str(), 0);
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::val_stID)
......@@ -4275,7 +4625,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value state : " << val_st << "=" << st << endl;
#endif
formula_res_t res;
res.value = st;
res.value = {(double)st};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::val_alarm_enum_stID)
......@@ -4291,7 +4644,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value alarm enum state : " << val_st << "=" << st << endl;
#endif
formula_res_t res;
res.value = st;
res.value = {(double)st};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::val_qualityID)
......@@ -4308,7 +4664,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value quality : " << val_quality << "=" << quality << endl;
#endif
formula_res_t res;
res.value = quality;
res.value = {(double)quality};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res;
}
else if (i->value.id() == formula_grammar::unary_exprID)
......@@ -4321,26 +4680,23 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
throw err.str();
}
formula_res_t res;
res = eval_expression(i->children.begin(), attr_values);
if (*i->value.begin() == '+')
{
res.value = + res.value;
return eval_expression(i->children.begin(), attr_values);
}
else if (*i->value.begin() == '-')
{
res.value = - res.value;
return -eval_expression(i->children.begin(), attr_values);
}
else if (*i->value.begin() == '!')
{
res.value = ! res.value;
return !eval_expression(i->children.begin(), attr_values);
}
else
{
err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
throw err.str();
}
return res;
}
else if (i->value.id() == formula_grammar::mult_exprID)
{
......@@ -4400,49 +4756,104 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node event" << string(i->value.begin(), i->value.end()) << endl;
#endif
formula_res_t ind;
if(i->children.size() != 2)
if(i->children.size() < 2)
{
err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();;
throw err.str();
}
if((i->children.begin()+1)->value.id() == formula_grammar::indexID)
ind = eval_expression(i->children.begin()+1, attr_values); //array index
else if((i->children.begin()+1)->value.id() == formula_grammar::propertyID)
vector<vector<double> > indexes;
iter_t child = i->children.begin();
if(child->value.id() != formula_grammar::nameID)
{
err << "in node "<< rule_names[i->value.id()]<<"(" << string(i->value.begin(), i->value.end()) << ") expecting " << rule_names[formula_grammar::nameID] << " as first child";
throw err.str();
}
child++;
while(child != i->children.end() && child->value.id() != formula_grammar::propertyID) //eval indexes
{
if(child->value.id() == formula_grammar::index_rangeID || child->value.id() == formula_grammar::indexID)
{
vector<double> ind_range;
eval_index_range(child, attr_values, ind_range);
if(!ind_range.empty())
indexes.push_back(ind_range);
}
else if(child->value.id() == formula_grammar::index_listID)
{
vector<double> ind_list;
iter_t granchild = child->children.begin();
while(granchild != child->children.end() && granchild->value.id() == formula_grammar::index_rangeID) //eval indexes
{
eval_index_range(granchild, attr_values, ind_list);
granchild++;
}
if(!ind_list.empty())
indexes.push_back(ind_list);
}
child++;
}
if(child - i->children.begin() == (long int)i->children.size() -1 && child->value.id() == formula_grammar::propertyID)
{
if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".quality")
if(string(child->value.begin(), child->value.end()) == ".quality")
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = res.quality;
formula_res_t res;
res = eval_expression(i->children.begin(), attr_values);
res.value = {(double)res.quality};
res.dim_x=1;
res.dim_y=0;
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.quality -> " << res.value << endl;
DEBUG_STREAM << " node event.quality -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
#endif
return res;
}
else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".alarm")
else if(string(child->value.begin(), child->value.end()) == ".alarm")
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = (res.value == _UNACK) || (res.value == _ACKED);
formula_res_t res;
if(!indexes.empty())
res = eval_expression(i->children.begin(), attr_values, indexes);
else
res = eval_expression(i->children.begin(), attr_values);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return (double)((n == _UNACK) || (n == _ACKED)); });
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.alarm -> " << res.value << endl;
DEBUG_STREAM << " node event.alarm -> " << print_array(res.value,res.dim_x,res.dim_y)<< endl;
#endif
return res;
}
else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".normal")
else if(string(child->value.begin(), child->value.end()) == ".normal")
{
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value);
res.value = (res.value == _NORM) || (res.value == _RTNUN);
formula_res_t res;
if(!indexes.empty())
res = eval_expression(i->children.begin(), attr_values, indexes);
else
res = eval_expression(i->children.begin(), attr_values);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return (double)((n == _NORM) || (n == _RTNUN)); });
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.normal -> " << res.value << endl;
DEBUG_STREAM << " node event.normal -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
#endif
return res;
}
}
else
else if(child - i->children.begin() < (long int)i->children.size() -1)//unsupported more indexes/qualities
{
err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children2 is not an index ->" << string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end());
err << "expecting indexes or properties after attribute name, found instead: "<< string(child->value.begin(), child->value.end());
throw err.str();
}
return eval_expression(i->children.begin(), attr_values, (int)ind.value);
if(!indexes.empty())
return eval_expression(i->children.begin(), attr_values, indexes);
else
return eval_expression(i->children.begin(), attr_values);
}
else if (i->value.id() == formula_grammar::nameID)
{
......@@ -4462,37 +4873,412 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if(!it->valid)
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
err << it->ex_desc << "";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!";
err << "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula";
formula_res_t res;
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
res.error = err.str();
res.attr_name = it->name;
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":{\"Reason\":\"" << res.ex_reason << "\",\"Desc\":\"" << res.ex_desc << "\",\"Origin\":\"" << res.ex_origin << "\"},";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << " quality=" << res.quality << endl;
#endif
events->veclock.readerOut();
throw err.str();
//throw err.str();
return res;
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
err << it->ex_desc << "";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!";
err << "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula";
formula_res_t res;
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
res.error = err.str();
res.attr_name = it->name;
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":{\"Reason\":\"" << res.ex_reason << "\",\"Desc\":\"" << res.ex_desc << "\",\"Origin\":\"" << res.ex_origin << "\"},";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << " quality=" << res.quality << endl;
#endif
events->veclock.readerOut();
throw err.str();
}
ostringstream temp_attr_val;
if(it->value.size() > 1)
temp_attr_val << "\"" << it->name << "[" << ev_ind << "]\":" <<it->value.at(ev_ind) << ",";//throw std::out_of_range
else
temp_attr_val << "\"" << it->name << "\":" <<it->value.at(ev_ind) << ",";//throw std::out_of_range
attr_values += temp_attr_val.str();
//throw err.str();
return res;
}
formula_res_t res;
res.valid = true;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
res.attr_name = it->name;
ostringstream temp_attr_val;
if(it->value.size() > 0)
{
if(!ev_ind.empty())
{
temp_attr_val << "\"" << it->name;
for(auto vei : ev_ind)
{
if(!vei.empty())
{
temp_attr_val << "[" << print_vector(vei) << "]";
}
}
temp_attr_val << "\":";
if(it->dim_y <=1)//1D array
{
if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1)//single element of 1D array (e.g. [0])
{
res.dim_x = 1;
res.dim_y = 0;
if(ev_ind[0][0] >= it->value.size())
{
err << "Requested element " << ev_ind[0][0] << " is out of bounds with dim=" << it->value.size();
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value = {it->value.at(ev_ind[0][0])};//throw std::out_of_range
temp_attr_val << "[" << res.value[0] << "],";
}
else if(ev_ind.size() ==1 && ev_ind[0].size() > 1)//multiple elements of 1D array (e.g. [0,1,2])
{
res.dim_y = 0;
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->value.size())
{
err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
else
{
res.value.push_back(it->value.at(ei0));//throw std::out_of_range
}
}
res.dim_x = res.value.size();
temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) << ",";
}
else if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0]==-1)//all elements of 1D array (e.g. [-1])
{
res.dim_y = 0;
res.value = it->value;
res.dim_x = it->dim_x;
temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) <<",";
}
else
{
err << "UNSUPPORTED additional indexes in 1D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else if(it->dim_y > 1)//2D array
{
//single row of 2D array (e.g. [0] or [0][-1])
if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() == 1 && ev_ind[0][0] != -1) // and first index not -1
{
res.dim_y = 0;
if(ev_ind[0][0] >= it->dim_y)
{
err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(ev_ind[0][0] * (it->dim_x)));
advance(vend,(int)(ev_ind[0][0]+1) * it->dim_x);
res.value = value_t(vstart,vend);
temp_attr_val << "" << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() > 1)//multiple rows of 2D array (e.g. [0,1,2] or [0,1,2][-1])
{
res.dim_x = it->dim_x;
res.dim_y = ev_ind[0].size();
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->value.size())
{
err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
else
{
auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(ei0 * (it->dim_x)));
advance(vend,(int)(ei0+1) * it->dim_x);
value_t row = value_t(vstart,vend);
res.value.insert(
res.value.end(),
std::make_move_iterator(row.begin()),
std::make_move_iterator(row.end())
);
}
}
temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() == 1 && ev_ind[0][0] == -1)//all rows of 2D array (e.g. [-1] or [-1][-1])
{
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.value = it->value;
temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single element of 2D array (e.g. [0][1])
{
res.dim_x = 1;
res.dim_y = 0;
if(ev_ind[0][0] >= it->dim_y)
{
err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
if(ev_ind[1][0] >= it->dim_x)
{
err << "Requested column " << ev_ind[1][0] << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value = {it->value.at(ev_ind[0][0]*it->dim_x + ev_ind[1][0])};//throw std::out_of_range
temp_attr_val << "[" <<res.value[0] << "],";//throw std::out_of_range
}
else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column slice of 2D array (e.g. [0,1,2][3])
{
res.dim_x = 1;
long ei1 = ev_ind[1][0];
if(ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_y = ev_ind[0].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column of 2D array (e.g. [-1][3])
{
res.dim_x = 1;
long ei1 = ev_ind[1][0];
if(ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(long ei0 = 0; ei0 < it->dim_y; ei0++)
{
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_y = it->dim_y;
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() > 1)//single row slice of 2D array (e.g. [0][1,2,3])
{
res.dim_y = 0;
long ei0 = ev_ind[0][0];
if(ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_x = ev_ind[1].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [0,1][2,3])
{
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
}
res.dim_x = ev_ind[1].size();
res.dim_y = ev_ind[0].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [-1][2,3])
{
for(long ei0 = 0; ei0 < it->dim_y; ei0++)
{
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
}
res.dim_x = ev_ind[1].size();
res.dim_y = it->dim_y;
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else //ev_ind.size() > 2
{
err << "UNSUPPORTED additional indexes in 2D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else //TODO N-DIMENSIONAL arrays
{
err << "UNSUPPORTED array indexes: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else
{
res.value = it->value;
temp_attr_val << "\"" << it->name << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
}
}
else
temp_attr_val << "\"" << it->name << "\":[],";
attr_values += temp_attr_val.str();
events->veclock.readerOut();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
#endif
res.value = it->value.at(ev_ind); //throw std::out_of_range
events->veclock.readerOut();
#endif
return res;
}
else
......@@ -4514,7 +5300,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node index = " << val_d << endl;
#endif
formula_res_t res;
res.value = strtod(val_d.c_str(), 0);
res.valid = true;
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
return res;
}
else if (i->value.id() == formula_grammar::logical_exprID)
......@@ -4555,43 +5344,72 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values);
long val_l1,val_l2;
vector<long> val_l1(res_1.value.size()),val_l2(res_2.value.size());
bool valid = res_1.valid && res_2.valid;
string err2("ERROR: non-int value in bitwise operation!");
val_l1 = (long)trunc(res_1.value); //transform to long
val_l2 = (long)trunc(res_2.value); //transform to long
if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf
throw err2;
string err2("Non int value in bitwise operation");
std::transform(res_1.value.begin(), res_1.value.end(), val_l1.begin(),
[](double n) { return (long)trunc(n); });//transform to long
std::transform(res_2.value.begin(), res_2.value.end(), val_l2.begin(),
[](double n) { return (long)trunc(n); });//transform to long
size_t ii;
for(ii=0; ii<res_1.value.size(); ii++)
{
if(val_l1[ii] != res_1.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
for(ii=0; ii<res_2.value.size(); ii++)
{
if(val_l2[ii] != res_2.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
if (*i->value.begin() == '&')
{
formula_res_t res;
res.value = (double)(val_l1 & val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y,val_l2,res_2.dim_x,res_2.dim_y,res.value,res.dim_x,res.dim_y, "Bitwise &", vectorUtils::fBitAnd);
return res;
}
else if (*i->value.begin() == '|')
{
formula_res_t res;
res.value = (double)(val_l1 | val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise |", vectorUtils::fBitOr);
return res;
}
else if (*i->value.begin() == '^')
{
formula_res_t res;
res.value = (double)(val_l1 ^ val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise ^", vectorUtils::fBitXor);
return res;
}
else
......@@ -4612,33 +5430,59 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values);
long val_l1,val_l2;
vector<long> val_l1(res_1.value.size()),val_l2(res_2.value.size());
bool valid = res_1.valid && res_2.valid;
string err2("ERROR: non-int value in bitwise operation!");
val_l1 = (long)trunc(res_1.value); //transform to long
val_l2 = (long)trunc(res_2.value); //transform to long
if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf
throw err2;
string err2("Non int value in bitwise operation");
std::transform(res_1.value.begin(), res_1.value.end(), val_l1.begin(),
[](double n) { return (long)trunc(n); });//transform to long
std::transform(res_2.value.begin(), res_2.value.end(), val_l2.begin(),
[](double n) { return (long)trunc(n); });//transform to long
bool non_int_error=false;
size_t ii;
for(ii=0; ii<res_1.value.size(); ii++)
{
if(val_l1[ii] != res_1.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception(//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
for(ii=0; ii<res_2.value.size(); ii++)
{
if(val_l2[ii] != res_2.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception(//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
if (string(i->value.begin(), i->value.end()) == string("<<"))
{
formula_res_t res;
res.value = (double)(val_l1 << val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_2.dim_x,res_2.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise <<", vectorUtils::fBitShiftL);
return res;
}
else if (string(i->value.begin(), i->value.end()) == string(">>"))
{
formula_res_t res;
res.value = (double)(val_l1 >> val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
res.valid = valid;
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise >>", vectorUtils::fBitShiftR);
return res;
}
else
......@@ -4684,20 +5528,45 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
err << "in node equality_exprID -> nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not valid!";
if(it->ex_desc.length() > 0)
err << " EX: '" << it->ex_desc << "'";
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
events->veclock.readerOut();
throw err.str();
/*Tango::Except::throw_exception( //throw exception to have error not delayed
it->ex_reason,//or Event_ERROR
it->ex_desc,
it->ex_origin);*/
return res;
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
err << "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not initialized!!";
if(it->ex_desc.length() > 0)
err << " EX: '" << it->ex_desc << "'";
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
events->veclock.readerOut();
throw err.str();
/*Tango::Except::throw_exception( //throw exception to have error not delayed
it->ex_reason,//or Event_ERROR
it->ex_desc,
it->ex_origin);*/
return res;
}
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\",";
attr_values += temp_attr_val.str();
res.valid = true;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
......@@ -4720,12 +5589,16 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if (string(i->value.begin(), i->value.end()) == string("!="))
{
res.value = attr_val != val_string;
res.value = {(double)(attr_val != val_string)};
res.dim_x=1;
res.dim_y=0;
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("=="))
{
res.value = attr_val == val_string;
res.value = {(double)(attr_val == val_string)};
res.dim_x=1;
res.dim_y=0;
return res;
}
else
......@@ -4786,7 +5659,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
else
{
err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
err << "in node compare_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
throw err.str();
}
}
......@@ -4805,109 +5678,49 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if (string(i->value.begin(), i->value.end()) == string("abs"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = fabs(res.value);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return fabs(n); });
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("cos"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = cos(res.value);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return cos(n); });
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("sin"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = sin(res.value);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return sin(n); });
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("quality"))
{
res = eval_expression(i->children.begin(), attr_values);
res.value = res.quality;
res.value = {(double)res.quality};//ignore values and keep quality as result
res.dim_x=1;
res.dim_y=0;
return res;
}
else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")) && i->children.begin()->value.id() == formula_grammar::nameID)
else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")))
{
events->veclock.readerIn();
vector<event>::iterator it = events->v_event.begin();
string s(i->children.begin()->value.begin(), i->children.begin()->value.end());
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " -> " << string(i->value.begin(), i->value.end()) << "(" << s << ")" << endl;
#endif
while ((it != events->v_event.end()) && (it->name != s))
it++;
if (it != events->v_event.end())
res = eval_expression(i->children.begin(), attr_values);
res.dim_x=1;
res.dim_y=0;
if(string(i->value.begin(), i->value.end()) == string("AND"))
{
if(!it->valid)
{
err << "in node funcID(" << string(i->value.begin(), i->value.end()) << "), (" << s << ") value not valid!" << ends;
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!";
events->veclock.readerOut();
throw err.str();
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!";
events->veclock.readerOut();
throw err.str();
}
ostringstream temp_attr_val;
bool result;
if (string(i->value.begin(), i->value.end()) == string("AND"))
result = true;
else if (string(i->value.begin(), i->value.end()) == string("OR"))
result = false;
temp_attr_val << "\"" << it->name << "\":";
if(it->read_size > 1)
temp_attr_val << "[";
for(int att_ind = 0; att_ind < it->read_size && att_ind < it->value.size(); att_ind++)
{
temp_attr_val << it->value.at(att_ind);
if (string(i->value.begin(), i->value.end()) == string("AND"))
{
result = result && (bool)it->value.at(att_ind);
if(!result) //comment to have all array values in attr_values
break; //comment to have all array values in attr_values
}
else if (string(i->value.begin(), i->value.end()) == string("OR"))
{
result = result || (bool)it->value.at(att_ind);
if(result) //comment to have all array values in attr_values
break; //comment to have all array values in attr_values
}
if(att_ind < it->read_size-1 && att_ind < it->value.size()-1)
temp_attr_val << ",";
}
if(it->read_size > 1)
temp_attr_val << "]";
temp_attr_val << ",";
attr_values += temp_attr_val.str();
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
#endif
res.value = result;
events->veclock.readerOut();
return res;
res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)true, [](bool acc, double n) { return (bool)(acc && (bool)(n));})};
}
else
else if(string(i->value.begin(), i->value.end()) == string("OR"))
{
events->veclock.readerOut();
err << "in function " << string(i->value.begin(), i->value.end()) << " event (" << s << ") not found in event table" << ends;
throw err.str();
res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)false, [](bool acc, double n) { return (bool)(acc || (bool)(n));})};
}
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node funcID("<<string(i->value.begin(), i->value.end())<<") value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<< endl;
#endif
return res;
}
else
{
......@@ -4927,34 +5740,47 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values);
bool valid = res_1.valid && res_2.valid;
if (string(i->value.begin(), i->value.end()) == string("min"))
{
formula_res_t res;
res.value = min(res_1.value, res_2.value);
vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fMin);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("max"))
{
formula_res_t res;
res.value = max(res_1.value, res_2.value);
vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fMax);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
return res;
}
else if (string(i->value.begin(), i->value.end()) == string("pow"))
{
formula_res_t res;
res.value = pow(res_1.value, res_2.value);
vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fPow);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
if(!res.valid)
{
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason);
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc);
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin);
}
return res;
}
else
......@@ -4974,7 +5800,15 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
throw err.str();
}
formula_res_t res_1=eval_expression(i->children.begin(), attr_values);
if(res_1.value)
if(!res_1.valid || res_1.value.empty())
{
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node ternary_if expression: returning Error=" << res_1.ex_desc << endl;
#endif
return res_1;
}
res_1.extract_result();
if(res_1.value[0])
{
formula_res_t res = eval_expression(i->children.begin()+1, attr_values);
return res;
......@@ -4996,7 +5830,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
}
}
formula_res_t res;
res.value = 0;
res.value = {(double)0.0};
res.dim_x=1;
res.dim_y=0;
res.valid = false;
return res;
}
......@@ -5029,7 +5866,7 @@ void AlarmHandler::eval_node_event(iter_t const& i, vector<string> & ev)
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase
ev.push_back(s);
}
//cout << endl;
//TANGO_LOG << endl;
//iter_t it = i->children.begin();
for(iter_t it = i->children.begin(); it != i->children.end(); it++)
eval_node_event(it, ev);
......@@ -5053,6 +5890,7 @@ void AlarmHandler::prepare_alarm_attr()
silencedAlarms_sz=0;
listAlarms_sz=0;
alarmSummary_sz=0;
alarmDisabled_sz=0;
string almstate;
for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
......@@ -5064,6 +5902,7 @@ void AlarmHandler::prepare_alarm_attr()
string alm_summary;
alm_summary += KEY(NAME_KEY) + ai->first + SEP;
#endif
stringstream alm_disabled;
if(ai->second.enabled == false)
{
outOfServiceAlarms_read[outOfServiceAlarms_sz] = ai->second.name;
......@@ -5086,7 +5925,7 @@ void AlarmHandler::prepare_alarm_attr()
}
else
{
if(ai->second.stat == S_ALARM && ai->second.ack == ACK)
if(ai->second.stat == S_ALARM && ai->second.ack == ACK && !ai->second.error)
{
acknowledgedAlarms_read[acknowledgedAlarms_sz] = ai->second.name;
attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str());
......@@ -5096,7 +5935,7 @@ void AlarmHandler::prepare_alarm_attr()
acknowledgedAlarms_sz++;
almstate = "ACKED";
}
else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK)
else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK && !ai->second.error)
{
unacknowledgedAlarms_read[unacknowledgedAlarms_sz] = ai->second.name;
attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str());
......@@ -5106,7 +5945,7 @@ void AlarmHandler::prepare_alarm_attr()
unacknowledgedAlarms_sz++;
almstate = "UNACK";
}
else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK)
else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK && !ai->second.error)
{
unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz] = ai->second.name;
attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str());
......@@ -5116,7 +5955,7 @@ void AlarmHandler::prepare_alarm_attr()
unacknowledgedNormalAlarms_sz++;
almstate = "RTNUN";
}
else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK)
else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK && !ai->second.error)
{
normalAlarms_read[normalAlarms_sz] = ai->second.name;
attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str());
......@@ -5137,6 +5976,38 @@ void AlarmHandler::prepare_alarm_attr()
}
}
tm time_tm;
time_t time_sec= ai->second.ts_time_silenced.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
if(almstate == "OOSRV" || almstate == "SHLVD")
{
//TANGO_LOG << __func__ << ": " << ai->first << " silenced="<< ai->second.silenced << endl;
#if 0
alm_disabled << KEY(ALARM_TIME_KEY) << time_buf << "." << ai->second.ts.tv_usec << SEP;
alm_disabled << KEY(NAME_KEY) << ai->first << SEP;
alm_disabled << KEY(VALUE_KEY) << almstate << SEP; //TODO: string or enum value?
alm_disabled << KEY(SILENT_TIME_REMAINING_KEY) << ai->second.silenced << SEP;
alm_disabled << KEY(MESSAGE_KEY) << ai->second.msg; //TODO: escape ';'
#else
alm_disabled << ai->second.ts.tv_sec << "\t";
alm_disabled << ai->second.ts.tv_usec << "\t";
alm_disabled << ai->first << "\t";
alm_disabled << almstate << "\t"; //TODO: string or enum value?
alm_disabled << ai->second.ack << "\t";
alm_disabled << ai->second.lev << "\t";
alm_disabled << ai->second.silenced << "\t";
alm_disabled << ai->second.grp2str() << "\t";
alm_disabled << ai->second.msg << "\t"; //TODO: escape ';'
#endif
alarmDisabled_read[alarmDisabled_sz] = alm_disabled.str();
attr_alarmDisabled_read[alarmDisabled_sz] = const_cast<char*>(alarmDisabled_read[alarmDisabled_sz].c_str());
alarmDisabled_sz++;
}
ostringstream tmp_ex;
//tmp_ex.str("");
if(ai->second.error)
......@@ -5149,11 +6020,9 @@ void AlarmHandler::prepare_alarm_attr()
}
}
tm time_tm;
time_t time_sec= ai->second.ts.tv_sec;
time_sec= ai->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
#ifndef ALM_SUM_STR
......@@ -5251,17 +6120,18 @@ void AlarmHandler::prepare_alarm_attr()
* found, change stat only if switching from
* S_NORMAL or S_ALARM status to S_ERROR
*/
//cout << "read_attr(): S_ERROR: found: " << aid->name << endl;
//TANGO_LOG << "read_attr(): S_ERROR: found: " << aid->name << endl;
if (aid->stat != S_ERROR) {
aid->stat = S_ERROR;
aid->ack = NOT_ACK;
aid->ts = ai->second.ts;
aid->msg = it->second.ex_desc;//tmp_ex.str();//ai->second.msg;
aid->msg = ai->second.ex_desc;//tmp_ex.str();//ai->second.msg;
aid->url = ai->second.url;
}
aid->grp = ai->second.grp;
aid->lev = ai->second.lev;
aid->is_new = ai->second.is_new; //copy is_new state
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
#ifdef _CNT_ATOMIC
aid->on_counter.store(ai->second.on_counter);
......@@ -5276,7 +6146,7 @@ void AlarmHandler::prepare_alarm_attr()
} else {
alarm_t at = ai->second;
at.stat = S_ERROR;
at.msg = it->second.ex_desc;//tmp_ex.str();//ai->second.msg;
at.msg = ai->second.ex_desc;//tmp_ex.str();//ai->second.msg;
/*
* not found: new "alarmed" item
*/
......@@ -5301,7 +6171,7 @@ void AlarmHandler::prepare_alarm_attr()
* found, change stat only if switching from
* S_NORMAL to S_ALARM status
*/
//cout << "read_attr(): S_ALARM: found: " << aid->name << endl;
//TANGO_LOG << "read_attr(): S_ALARM: found: " << aid->name << endl;
if (aid->stat == S_NORMAL || aid->stat == S_ERROR) {
aid->stat = S_ALARM;
aid->ack = NOT_ACK;
......@@ -5312,6 +6182,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->grp = ai->second.grp;
aid->lev = ai->second.lev;
aid->is_new = ai->second.is_new; //copy is_new state
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
#ifdef _CNT_ATOMIC
aid->on_counter.store(ai->second.on_counter);
......@@ -5366,6 +6237,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->is_new = ai->second.is_new; //copy is_new state
aid->silenced = ai->second.silenced; //update silenced from alarm table (maybe not necessary)
aid->silent_time = ai->second.silent_time; //if already alarmed and not saved correctly in properties needed to update
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
if (aid->ack == ACK) {
//if (aid->done) //TODO: done seems useless
......@@ -5438,7 +6310,7 @@ void AlarmHandler::prepare_alarm_attr()
is_new = (aid->is_new && aid->silenced <= 0) ? "NEW" : " ";
os << aid->ts.tv_sec << "\t" << aid->ts.tv_usec << "\t" \
<< aid->name << "\t" << aid->stat << "\t" << aid->ack \
<< "\t" << aid->on_counter << "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new;
<< "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new;
tmp_alarm_table.push_back(os.str());
}
}
......@@ -5465,18 +6337,20 @@ void AlarmHandler::prepare_alarm_attr()
strncpy(dss[i],tmp_alarm_table[i].c_str(), len);
dss[i][len]=0;
}
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0)
{
ostringstream os1;
ds_num++;
os1.clear();
os1 << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << -1 << "\t" << 0 << "\t" << 0 << "\t ";
os1 << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << -1 << "\t" << 0 << "\t" << 0 << "\t ";
//ds[0] = CORBA::string_dup(os1.str().c_str());
size_t len=os1.str().length();
if(len >= 10124) len = 10124-1;
strncpy(dss[i],os1.str().c_str(), len);
dss[i][len]=0;
}
#endif
dslock->writerOut();
}
......@@ -5566,7 +6440,7 @@ void AlarmHandler::put_signal_property()
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled,
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.silent_time);
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.receivers,it.second.silent_time);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": SAVED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
//alarms.vlock->readerOut();//TODO: avoid keeping lock
......@@ -5589,7 +6463,7 @@ void AlarmHandler::put_signal_property()
itmap->second = conf_string;
savedlock->readerOut();
alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled,
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.silent_time);
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.receivers,it.second.silent_time);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": UPDATED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
}
......@@ -5600,8 +6474,13 @@ void AlarmHandler::put_signal_property()
}
}
// Identify the alarms that need to be removed.
// The alarms that have been identified to be removed have their tag
// stored in a std::vector. The vector is later iterated over in a second
// step when the alarms get removed.
savedlock->readerIn();
map<string, string>::iterator it2=saved_alarms.begin();
vector< string > alarms_to_be_erased;
while(it2 != saved_alarms.end())
{
if(!it2->first.empty())//TODO: should not be needed, bug if it happens
......@@ -5609,25 +6488,30 @@ void AlarmHandler::put_signal_property()
auto found = local_alarms.find(it2->first);
if (found == local_alarms.end())
{
DEBUG_STREAM << __func__<<": DELETING '" << it2->first << "'" << endl;
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.delete_alarm_conf_db(it2->first);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": DELETED '" <<it2->first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
//savedlock->readerOut();//TODO: with boost shared lock to be released to take exclusive
savedlock->writerIn();
saved_alarms.erase(it2);
savedlock->writerOut();
//savedlock->readerIn();
alarms_to_be_erased.push_back(it2->first);
}
}
if(it2 != saved_alarms.end())
it2++;
}
savedlock->readerOut();
// Now remove the alarms from the property in the TangoDB and saved_alarms.
if(!alarms_to_be_erased.empty())
{
savedlock->writerIn();
for(auto iter{alarms_to_be_erased.begin()}; iter != alarms_to_be_erased.end(); ++iter)
{
DEBUG_STREAM << __func__<<": DELETING '" << *iter << "' saved_alarms.size=" << saved_alarms.size() << endl;
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.delete_alarm_conf_db(*iter);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": DELETED '" << *iter << "' in " << ELAPSED(t0, t1) << " ms saved_alarms.size=" << saved_alarms.size() << endl;
saved_alarms.erase(saved_alarms.find(*iter));
}
savedlock->writerOut();
}
Tango::DbData data;
data.push_back(Tango::DbDatum("AlarmList"));
......@@ -5738,6 +6622,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm)
alm.dp_n = NULL;
alm.enabled=true;
alm.shelved=false;
alm.receivers.clear();
alm.formula_tree =
//boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp =
......@@ -5761,6 +6646,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm)
std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase
alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.receivers = std::regex_replace(alm.receivers, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
if(alm.cmd_name_a.length() > 0)
{
const char *c = alm.cmd_name_a.c_str();
......
......@@ -33,7 +33,7 @@
#ifndef AlarmHandler_H
#define AlarmHandler_H
#include <tango.h>
#include <tango/tango.h>
#include <boost/version.hpp>
#if BOOST_VERSION >= 103600
......@@ -61,7 +61,15 @@ class update_thread;
# define ELAPSED(before, after) \
1000.0*(after.tv_sec-before.tv_sec) + \
((double)after.tv_usec-before.tv_usec) / 1000
#ifndef TANGO_LOG
#define TANGO_LOG cout
#endif
#ifndef TANGO_LOG_INFO
#define TANGO_LOG_INFO cout2
#endif
#ifndef TANGO_LOG_DEBUG
#define TANGO_LOG_DEBUG cout4
#endif
/*----- PROTECTED REGION END -----*/ // AlarmHandler.h
......@@ -100,10 +108,6 @@ class AlarmHandler : public TANGO_BASE_CLASS
public:
bool compare_without_domain(string str1, string str2);
string remove_domain(string str);
//TODO: real attributes
Tango::DevLong attr_AttributeStartedNumber_read;
Tango::DevLong attr_AttributePausedNumber_read;
Tango::DevLong attr_AttributeStoppedNumber_read;
Tango::DevLong attr_AttributeNumber_read;
string normalAlarms_read[MAX_ALARMS];
......@@ -117,6 +121,7 @@ public:
string alarmSummary_read[MAX_ALARMS];
string eventList_read[MAX_ATTR_SUMMARY];
string eventSummary_read[MAX_ATTR_SUMMARY];
string alarmDisabled_read[MAX_ALARMS];
/* char c_normalAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
char c_unacknowledgedAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
......@@ -140,6 +145,7 @@ public:
size_t alarmSummary_sz;
size_t eventList_sz;
size_t eventSummary_sz;
size_t alarmDisabled_sz;
double last_statistics_reset_time;
......@@ -157,6 +163,8 @@ public:
vector<Tango::DevLong> statisticsTimeWindow;
// ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received.
Tango::DevULong errorDelay;
// SetAlarmQuality: Set alarm attribute quality as computed using quality of attributes in the formula
Tango::DevBoolean setAlarmQuality;
// Attribute data members
public:
......@@ -175,6 +183,7 @@ public:
Tango::DevString *attr_alarmSummary_read;
Tango::DevString *attr_eventList_read;
Tango::DevString *attr_eventSummary_read;
Tango::DevString *attr_alarmDisabled_read;
// Constructors and destructors
public:
......@@ -371,6 +380,15 @@ public:
*/
virtual void read_eventSummary(Tango::Attribute &attr);
virtual bool is_eventSummary_allowed(Tango::AttReqType type);
/**
* Attribute alarmDisabled related methods
* Description: List of alarms in out of service or shelved state
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
virtual void read_alarmDisabled(Tango::Attribute &attr);
virtual bool is_alarmDisabled_allowed(Tango::AttReqType type);
// Dynamic attribute methods
public:
......@@ -575,13 +593,13 @@ private:
void init_alarms(map< string,vector<string> > &alarm_events);
#endif
void add_alarm(alarm_t& a, bool starting=false);
void add_event(alarm_t& a, vector<string> &evn) throw(string&);
void add_event(alarm_t& a, vector<string> &evn);
#if 0
void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn) throw(string&);
void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn);
#endif
// void do_alarm(bei_t& e); //gcc 4 problem??
bool remove_alarm(string& s) throw(string&);
//void add_to_database(alarm_t& a) throw(string&);
bool remove_alarm(string& s);
//void add_to_database(alarm_t& a);
void set_internal_alarm(string name, Tango::TimeVal t, string msg, unsigned int count=1);
void load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn);
......@@ -589,7 +607,8 @@ private:
formula_res_t eval_formula(tree_parse_info_t tree, string &attr_values);
void find_event_formula(tree_parse_info_t tree, vector<string> &);
formula_res_t eval_expression(iter_t const& i, string &attr_values, int ev_ind=0); //recursive tree node evaluation
formula_res_t eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind={}); //recursive tree node evaluation
void eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind);
void eval_node_event(iter_t const& i, vector<string> & ev); //recursive tree node evaluation
void prepare_alarm_attr(); //for read attribute alarm and push_change_event
......
......@@ -24,6 +24,11 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>30</DefaultPropValue>
</classProperties>
<classProperties name="SetAlarmQuality" description="Set alarm attribute quality as computed using quality of attributes in the formula">
<type xsi:type="pogoDsl:BooleanType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>false</DefaultPropValue>
</classProperties>
<deviceProperties name="GroupNames" description="Labels for Group mask, first is for mask 0x00">
<type xsi:type="pogoDsl:StringVectorType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
......@@ -43,6 +48,11 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>30</DefaultPropValue>
</deviceProperties>
<deviceProperties name="SetAlarmQuality" description="Set alarm attribute quality as computed using quality of attributes in the formula">
<type xsi:type="pogoDsl:BooleanType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>false</DefaultPropValue>
</deviceProperties>
<commands name="State" description="This command gets the device state (stored in its &lt;i>device_state&lt;/i> data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
<argin description="none.">
<type xsi:type="pogoDsl:VoidType"/>
......@@ -189,8 +199,8 @@
</commands>
<attributes name="alarmAudible" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:BooleanType"/>
<changeEvent fire="true" libCheckCriteria="false"/>
<archiveEvent fire="true" libCheckCriteria="false"/>
<changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="True if there is at least one alarm that needs audible indication on the GUI" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
......@@ -306,6 +316,14 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<attributes name="alarmDisabled" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="10000" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="List of alarms in out of service or shelved state" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<dynamicAttributes name="AlarmState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
<dataType xsi:type="pogoDsl:EnumType"/>
<changeEvent fire="true" libCheckCriteria="true"/>
......@@ -324,8 +342,8 @@
</dynamicAttributes>
<dynamicAttributes name="AlarmFormula" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="true" libCheckCriteria="false"/>
<archiveEvent fire="true" libCheckCriteria="false"/>
<changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
......
/*----- PROTECTED REGION ID(AlarmHandlerClass.cpp) ENABLED START -----*/
static const char *RcsId = "$Id: $";
static const char *TagName = "$Name: $";
static const char *CvsPath = "$Source: $";
static const char *SvnPath = "$HeadURL: $";
static const char *HttpServer = "http://www.esrf.eu/computing/cs/tango/tango_doc/ds_doc/";
//=============================================================================
//
// file : AlarmHandlerClass.cpp
......@@ -78,7 +73,7 @@ AlarmHandlerClass *AlarmHandlerClass::_instance = NULL;
//--------------------------------------------------------
AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s)
{
cout2 << "Entering AlarmHandlerClass constructor" << endl;
TANGO_LOG_INFO << "Entering AlarmHandlerClass constructor" << endl;
set_default_property();
get_class_property();
write_class_property();
......@@ -87,7 +82,7 @@ AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s)
/*----- PROTECTED REGION END -----*/ // AlarmHandlerClass::constructor
cout2 << "Leaving AlarmHandlerClass constructor" << endl;
TANGO_LOG_INFO << "Leaving AlarmHandlerClass constructor" << endl;
}
//--------------------------------------------------------
......@@ -167,7 +162,7 @@ AlarmHandlerClass *AlarmHandlerClass::instance()
//--------------------------------------------------------
CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "AckClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "AckClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->ack(argin));
......@@ -187,7 +182,7 @@ CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_an
//--------------------------------------------------------
CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "LoadClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "LoadClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->load(argin));
......@@ -207,7 +202,7 @@ CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_a
//--------------------------------------------------------
CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "RemoveClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "RemoveClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->remove(argin));
......@@ -227,7 +222,7 @@ CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "SearchAlarmClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "SearchAlarmClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
return insert((static_cast<AlarmHandler *>(device))->search_alarm(argin));
......@@ -246,7 +241,7 @@ CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::An
//--------------------------------------------------------
CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "StopAudibleClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "StopAudibleClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->stop_audible());
return new CORBA::Any();
}
......@@ -264,7 +259,7 @@ CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(co
//--------------------------------------------------------
CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "SilenceClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "SilenceClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->silence(argin));
......@@ -284,7 +279,7 @@ CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i
//--------------------------------------------------------
CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "ModifyClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ModifyClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->modify(argin));
......@@ -304,7 +299,7 @@ CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "ShelveClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ShelveClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->shelve(argin));
......@@ -324,7 +319,7 @@ CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "EnableClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "EnableClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->enable(argin));
......@@ -344,7 +339,7 @@ CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//--------------------------------------------------------
CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "DisableClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "DisableClass::execute(): arrived" << endl;
Tango::DevString argin;
extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->disable(argin));
......@@ -364,7 +359,7 @@ CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i
//--------------------------------------------------------
CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "ResetStatisticsClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ResetStatisticsClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->reset_statistics());
return new CORBA::Any();
}
......@@ -382,7 +377,7 @@ CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSE
//--------------------------------------------------------
CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "StopNewClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "StopNewClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->stop_new());
return new CORBA::Any();
}
......@@ -400,7 +395,7 @@ CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const
//--------------------------------------------------------
CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{
cout2 << "GetAlarmInfoClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "GetAlarmInfoClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin;
extract(in_any, argin);
return insert((static_cast<AlarmHandler *>(device))->get_alarm_info(argin));
......@@ -419,7 +414,7 @@ CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::A
//--------------------------------------------------------
CORBA::Any *ReLoadAllClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{
cout2 << "ReLoadAllClass::execute(): arrived" << endl;
TANGO_LOG_INFO << "ReLoadAllClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->re_load_all());
return new CORBA::Any();
}
......@@ -491,6 +486,7 @@ void AlarmHandlerClass::get_class_property()
cl_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
cl_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));
cl_prop.push_back(Tango::DbDatum("ErrorDelay"));
cl_prop.push_back(Tango::DbDatum("SetAlarmQuality"));
// Call database and extract values
if (Tango::Util::instance()->_UseDb==true)
......@@ -546,6 +542,18 @@ void AlarmHandlerClass::get_class_property()
cl_prop[i] << errorDelay;
}
}
// Try to extract SetAlarmQuality value
if (cl_prop[++i].is_empty()==false) cl_prop[i] >> setAlarmQuality;
else
{
// Check default value for SetAlarmQuality
def_prop = get_default_class_property(cl_prop[i].name);
if (def_prop.is_empty()==false)
{
def_prop >> setAlarmQuality;
cl_prop[i] << setAlarmQuality;
}
}
/*----- PROTECTED REGION ID(AlarmHandlerClass::get_class_property_after) ENABLED START -----*/
// Check class property data members init
......@@ -624,6 +632,20 @@ void AlarmHandlerClass::set_default_property()
cl_def_prop.push_back(data);
add_wiz_class_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_class_prop(prop_name, prop_desc);
prop_name = "SetAlarmQuality";
prop_desc = "Set alarm attribute quality as computed using quality of attributes in the formula";
prop_def = "false";
vect_data.clear();
vect_data.push_back("false");
if (prop_def.length()>0)
{
Tango::DbDatum data(prop_name);
data << vect_data ;
cl_def_prop.push_back(data);
add_wiz_class_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_class_prop(prop_name, prop_desc);
......@@ -683,6 +705,20 @@ void AlarmHandlerClass::set_default_property()
}
else
add_wiz_dev_prop(prop_name, prop_desc);
prop_name = "SetAlarmQuality";
prop_desc = "Set alarm attribute quality as computed using quality of attributes in the formula";
prop_def = "false";
vect_data.clear();
vect_data.push_back("false");
if (prop_def.length()>0)
{
Tango::DbDatum data(prop_name);
data << vect_data ;
dev_def_prop.push_back(data);
add_wiz_dev_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_dev_prop(prop_name, prop_desc);
}
//--------------------------------------------------------
......@@ -748,7 +784,7 @@ void AlarmHandlerClass::device_factory(const Tango::DevVarStringArray *devlist_p
// Create devices and add it into the device list
for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
{
cout4 << "Device name : " << (*devlist_ptr)[i].in() << endl;
TANGO_LOG_DEBUG << "Device name : " << (*devlist_ptr)[i].in() << endl;
device_list.push_back(new AlarmHandler(this, (*devlist_ptr)[i]));
}
......@@ -811,8 +847,8 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled
alarmaudible->set_disp_level(Tango::OPERATOR);
// Not Memorized
alarmaudible->set_change_event(true, false);
alarmaudible->set_archive_event(true, false);
alarmaudible->set_change_event(true, true);
alarmaudible->set_archive_event(true, true);
att_list.push_back(alarmaudible);
// Attribute : StatisticsResetTime
......@@ -1145,8 +1181,6 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled
eventlist->set_disp_level(Tango::OPERATOR);
// Not Memorized
//eventlist->set_change_event(true, true);
//eventlist->set_archive_event(true, true);
att_list.push_back(eventlist);
// Attribute : eventSummary
......@@ -1171,10 +1205,34 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled
eventsummary->set_disp_level(Tango::OPERATOR);
// Not Memorized
//eventsummary->set_change_event(true, true);
//eventsummary->set_archive_event(true, true);
att_list.push_back(eventsummary);
// Attribute : alarmDisabled
alarmDisabledAttrib *alarmdisabled = new alarmDisabledAttrib();
Tango::UserDefaultAttrProp alarmdisabled_prop;
alarmdisabled_prop.set_description("List of alarms in out of service or shelved state");
// label not set for alarmDisabled
// unit not set for alarmDisabled
// standard_unit not set for alarmDisabled
// display_unit not set for alarmDisabled
// format not set for alarmDisabled
// max_value not set for alarmDisabled
// min_value not set for alarmDisabled
// max_alarm not set for alarmDisabled
// min_alarm not set for alarmDisabled
// max_warning not set for alarmDisabled
// min_warning not set for alarmDisabled
// delta_t not set for alarmDisabled
// delta_val not set for alarmDisabled
alarmdisabled->set_default_properties(alarmdisabled_prop);
// Not Polled
alarmdisabled->set_disp_level(Tango::OPERATOR);
// Not Memorized
alarmdisabled->set_change_event(true, true);
alarmdisabled->set_archive_event(true, true);
att_list.push_back(alarmdisabled);
// Create a list of static attributes
create_static_attribute_list(get_class_attr()->get_attr_list());
......@@ -1374,7 +1432,7 @@ void AlarmHandlerClass::create_static_attribute_list(vector<Tango::Attr *> &att_
defaultAttList.push_back(att_name);
}
cout2 << defaultAttList.size() << " attributes in default list" << endl;
TANGO_LOG_INFO << defaultAttList.size() << " attributes in default list" << endl;
/*----- PROTECTED REGION ID(AlarmHandlerClass::create_static_att_list) ENABLED START -----*/
......@@ -1410,7 +1468,7 @@ void AlarmHandlerClass::erase_dynamic_attributes(const Tango::DevVarStringArray
vector<string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name);
if (ite_str == defaultAttList.end())
{
cout2 << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl;
TANGO_LOG_INFO << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl;
Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str());
dev->remove_attribute(att_list[att.get_attr_idx()], true, false);
--ite_att;
......
......@@ -37,7 +37,7 @@
#ifndef AlarmHandlerClass_H
#define AlarmHandlerClass_H
#include <tango.h>
#include <tango/tango.h>
#include <AlarmHandler.h>
......@@ -249,6 +249,19 @@ public:
{return (static_cast<AlarmHandler *>(dev))->is_eventSummary_allowed(ty);}
};
// Attribute alarmDisabled class definition
class alarmDisabledAttrib: public Tango::SpectrumAttr
{
public:
alarmDisabledAttrib():SpectrumAttr("alarmDisabled",
Tango::DEV_STRING, Tango::READ, 10000) {};
~alarmDisabledAttrib() {};
virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
{(static_cast<AlarmHandler *>(dev))->read_alarmDisabled(att);}
virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
{return (static_cast<AlarmHandler *>(dev))->is_alarmDisabled_allowed(ty);}
};
//=========================================
// Define classes for dynamic attributes
......@@ -633,6 +646,8 @@ class AlarmHandlerClass : public Tango::DeviceClass
vector<Tango::DevLong> statisticsTimeWindow;
// ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received.
Tango::DevULong errorDelay;
// SetAlarmQuality: Set alarm attribute quality as computed using quality of attributes in the formula
Tango::DevBoolean setAlarmQuality;
public:
// write class properties data members
Tango::DbData cl_prop;
......