From 92b68f9cf4bca092dca8fc578e09558e96a19e92 Mon Sep 17 00:00:00 2001 From: gscalamera <graziano.scalamera@elettra.eu> Date: Fri, 19 Aug 2016 11:53:04 +0200 Subject: [PATCH] added dynamic attributes for alarms with quality and exceptions --- src/Alarm.cpp | 448 ++++++++++++++++++++++++++++++++------ src/Alarm.h | 20 +- src/Alarm.xmi | 10 +- src/AlarmClass.h | 17 ++ src/AlarmDynAttrUtils.cpp | 158 ++++++++++++++ src/AlarmStateMachine.cpp | 16 ++ src/alarm_table.cpp | 47 +++- src/alarm_table.h | 171 ++++++++++++++- src/event_table.cpp | 9 +- src/event_table.h | 10 + 10 files changed, 821 insertions(+), 85 deletions(-) create mode 100644 src/AlarmDynAttrUtils.cpp diff --git a/src/Alarm.cpp b/src/Alarm.cpp index 6a4648d..2d7c109 100644 --- a/src/Alarm.cpp +++ b/src/Alarm.cpp @@ -302,7 +302,7 @@ void Alarm::init_device() alarmedlock = new(ReadersWritersLock); internallock = new(ReadersWritersLock); dslock = new(ReadersWritersLock); - + alarms.set_dev(this); /*----- PROTECTED REGION END -----*/ // Alarm::init_device_before @@ -1086,6 +1086,72 @@ void Alarm::read_alarm(Tango::Attribute &attr) /*----- PROTECTED REGION END -----*/ // Alarm::read_alarm } +//-------------------------------------------------------- +/** + * Read attribute AlarmState related method + * Description: + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void Alarm::read_AlarmState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "Alarm::read_AlarmState(Tango::Attribute &attr) entering... " << endl; + Tango::DevBoolean *att_value = get_AlarmState_data_ptr(attr.get_name()); + /*----- PROTECTED REGION ID(Alarm::read_AlarmState) ENABLED START -----*/ + string reason(""); + string desc(""); + string origin(""); + int quality = Tango::ATTR_VALID; +#ifndef _RW_LOCK + alarms.lock(); +#else + alarms.vlock->readerIn(); +#endif + alarm_container_t::iterator it; + for(it = alarms.v_alarm.begin(); it != alarms.v_alarm.end(); it++) + { + if(it->second.attr_name == attr.get_name()) + { + + break; + } + } + if(it != alarms.v_alarm.end()) + { + reason = it->second.ex_reason; + desc = it->second.ex_desc; + origin = it->second.ex_origin; + quality = it->second.quality; + } + DEBUG_STREAM << "Alarm::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl; +#ifndef _RW_LOCK + alarms.unlock(); +#else + alarms.vlock->readerOut(); +#endif + if(desc.length() > 0) + { + Tango::Except::throw_exception( + reason, + desc, + origin, Tango::ERR); + } + // Set the attribute value + if(quality != Tango::ATTR_VALID) + { + timeval now; + gettimeofday(&now, NULL); + attr.set_value_date_quality(att_value, now/*TODO timestamp*/, (Tango::AttrQuality)quality); + } + else + { + attr.set_value(att_value); + } + + /*----- PROTECTED REGION END -----*/ // Alarm::read_AlarmState +} //-------------------------------------------------------- /** * Method : Alarm::add_dynamic_attributes() @@ -1095,9 +1161,34 @@ void Alarm::read_alarm(Tango::Attribute &attr) //-------------------------------------------------------- void Alarm::add_dynamic_attributes() { + // Example to add dynamic attribute: + // Copy inside the following protected area to create instance(s) at startup. + // add_AlarmState_dynamic_attribute("MyAlarmStateAttribute"); + /*----- PROTECTED REGION ID(Alarm::add_dynamic_attributes) ENABLED START -----*/ // Add your own code to create and add dynamic attributes if any +#ifndef _RW_LOCK + alarms.lock(); +#else + alarms.vlock->readerIn(); +#endif + if (alarms.v_alarm.empty() == false) + { + for (alarm_container_t::iterator i = alarms.v_alarm.begin(); \ + i != alarms.v_alarm.end(); i++) + { + add_AlarmState_dynamic_attribute(i->second.attr_name); + Tango::DevBoolean *attr_value = get_AlarmState_data_ptr(i->second.attr_name); + i->second.attr_value = attr_value; + } + } +#ifndef _RW_LOCK + alarms.unlock(); +#else + alarms.vlock->readerOut(); +#endif + /*----- PROTECTED REGION END -----*/ // Alarm::add_dynamic_attributes } @@ -1427,12 +1518,12 @@ void Alarm::load(Tango::DevString argin) if(alm.to_be_evaluated) //TODO: remove this evaluation of the formula that is not necessary { DEBUG_STREAM << "Alarm::load(): Evaluating formula=" << alm.formula << endl; - try { - double res; + try { + struct formula_res_t res; string attr_values; res = eval_formula(alm.formula_tree, attr_values); - DEBUG_STREAM << "Parsing succeeded of "<< alm.formula << "; result=" << res << endl; - alarms.update(alm.name, gettime(), (int)res, attr_values, alm.grp2str(), alm.msg, alm.formula); //pass "now" as timestamp in this case + DEBUG_STREAM << "Parsing succeeded of "<< alm.formula << "; result=" << res.value << " quality=" << res.quality << endl; + alarms.update(alm.name, gettime(), res, attr_values, alm.grp2str(), alm.msg, alm.formula); //pass "now" as timestamp in this case } catch(std::out_of_range& e) { @@ -1839,6 +1930,11 @@ void Alarm::modify(Tango::DevString argin) alarm_t alm; alarm_parse al_gr(alm); // Construct Spirit grammar alm.name.clear(); + alm.attr_name.clear(); + alm.quality = Tango::ATTR_VALID; + alm.ex_reason.clear(); + alm.ex_desc.clear(); + alm.ex_origin.clear(); alm.formula.clear(); alm.msg.clear(); alm.lev.clear(); @@ -2130,6 +2226,11 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn) DEBUG_STREAM << "Alarm::load_alarm(): Creating Spirit Parser..." << endl; alarm_parse al_gr(alm); // Construct Spirit grammar alm.name.clear(); + alm.attr_name.clear(); + alm.quality = Tango::ATTR_VALID; + alm.ex_reason.clear(); + alm.ex_desc.clear(); + alm.ex_origin.clear(); alm.formula.clear(); alm.msg.clear(); alm.lev.clear(); @@ -2160,6 +2261,19 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn) if (alm.formula_tree.full) { std::transform(alm.name.begin(), alm.name.end(), alm.name.begin(), (int(*)(int))tolower); //transform to lowercase + //replace / with __ + if(!alm.name.empty()) + { + alm.attr_name = alm.name; + size_t start_pos = 0; + string from("/"); + string to("__"); + while((start_pos = alm.attr_name.find(from, start_pos)) != std::string::npos) + { + alm.attr_name.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } + } //std::transform(alm.formula.begin(), alm.formula.end(), alm.formula.begin(), (int(*)(int))tolower); //transform to lowercase: incorrect, state has to be written uppercase std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase @@ -2219,6 +2333,7 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn) } alm.ts = gettime(); DEBUG_STREAM << "Alarm::load_alarm(): name = '" << alm.name << "'" << endl; + DEBUG_STREAM << " attr_name = '" << alm.attr_name << "'" << endl; DEBUG_STREAM << " formula = '" << alm.formula << "'" << endl; DEBUG_STREAM << " time_threshold = '" << alm.time_threshold << "'" << endl; DEBUG_STREAM << " msg = '" << alm.msg << "'" << endl; @@ -2247,7 +2362,9 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn) (const char*)"", \ (const char*)"Alarm::load_alarm()", Tango::ERR); } - + add_AlarmState_dynamic_attribute(alm.attr_name); + Tango::DevBoolean *attr_value = get_AlarmState_data_ptr(alm.attr_name); + alm.attr_value = attr_value; if (alarms.exist(alm.name)) { ostringstream o; o << "Alarm::load_alarm(): alarm '" << alm.name << "' already exist" << ends; @@ -2500,8 +2617,10 @@ void Alarm::subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn) void Alarm::do_alarm(bei_t& e) { bool changed=true; + int num_changed=0; //if (e.name == INTERNAL_ERROR) { - if(e.type == TYPE_TANGO_ERR) { + if(e.type == TYPE_TANGO_ERR || e.type == TYPE_GENERIC_ERR) + { ostringstream o; o << e.msg << endl; WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl; @@ -2550,20 +2669,61 @@ void Alarm::do_alarm(bei_t& e) { found_ev->err_counter++; if(found_ev->err_counter >= errThreshold) - set_internal_alarm(e.ev_name, gettime(), o.str(), errThreshold); + { + set_internal_alarm(e.ev_name, gettime(), o.str(), errThreshold); + } + if(e.type == TYPE_TANGO_ERR) + found_ev->ex_reason = string("Event_ERROR"); + else + found_ev->ex_reason = string("Alarm_ERROR"); + found_ev->ex_desc = o.str(); + found_ev->ex_origin = e.ev_name; + //LOOP ALARMS IN WHICH THIS EVENT IS USED + vector<string>::iterator j = found_ev->m_alarm.begin(); + while (j != found_ev->m_alarm.end()) + { +#ifndef _RW_LOCK + alarms.lock(); +#else + alarms.vlock->readerIn(); +#endif + alarm_container_t::iterator it = alarms.v_alarm.find(*j); + if(it != alarms.v_alarm.end()) + { + try + { + if(e.type == TYPE_TANGO_ERR) + it->second.ex_reason = found_ev->ex_reason; + else + it->second.ex_reason = found_ev->ex_reason; + it->second.ex_desc = found_ev->ex_desc; + it->second.ex_origin = found_ev->ex_origin; + Tango::DevErrorList errors(1); + errors.length(1); + 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); + DEBUG_STREAM << "PUSHING EXCEPTION FOR " << it->second.attr_name << " " << it->second.ex_desc << "-" << it->second.ex_reason << "-" << it->second.ex_origin << endl; + push_change_event(it->second.attr_name, &except); + push_archive_event(it->second.attr_name, &except); + }catch(Tango::DevFailed &ex) + {} + } +#ifndef _RW_LOCK + alarms.unlock(); +#else + alarms.vlock->readerOut(); +#endif + j++; + } } return; - } - else if(e.type == TYPE_GENERIC_ERR) { - ostringstream o; - o << e.msg << endl; - WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl; - set_internal_alarm(e.ev_name, gettime(), o.str()); - return; } DEBUG_STREAM << "Alarm::do_alarm(): arrived event=" << e.ev_name << endl; - double res; + formula_res_t res; vector<event>::iterator found = \ find(events->v_event.begin(), events->v_event.end(), e.ev_name); if (found == events->v_event.end()) @@ -2608,6 +2768,11 @@ void Alarm::do_alarm(bei_t& e) if (found != events->v_event.end()) { found->value = e.value; + found->quality = e.quality; + //found->errors = e.errors; + found->ex_reason = e.ex_reason; + found->ex_desc = e.ex_desc; + found->ex_origin = e.ex_origin; found->valid = true; found->ts = e.ts; found->type = e.type; @@ -2628,14 +2793,43 @@ void Alarm::do_alarm(bei_t& e) try { string attr_values; res = eval_formula(it->second.formula_tree, attr_values); - DEBUG_STREAM << "Alarm::do_alarm(): Evaluation of " << it->second.formula << "; result=" << res << endl; + DEBUG_STREAM << "Alarm::do_alarm(): Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl; #ifndef _RW_LOCK alarms.unlock(); #else alarms.vlock->readerOut(); #endif - changed = alarms.update(tmpname, found->ts, (int)res, attr_values, it->second.grp2str(), it->second.msg, it->second.formula); //update internal structure and log to db - } catch(std::out_of_range& e) + changed = alarms.update(tmpname, found->ts, res, attr_values, it->second.grp2str(), it->second.msg, it->second.formula); //update internal structure and log to db + if(changed) + num_changed++; + Tango::DevBoolean *attr_value = get_AlarmState_data_ptr(it->second.attr_name); + *attr_value = (it->second.stat == S_ALARM); + try + { //DevFailed for push events + if(it->second.ex_reason.length() == 0) + { + timeval now; + gettimeofday(&now, NULL); + push_change_event(it->second.attr_name,(Tango::DevBoolean *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false); + push_archive_event(it->second.attr_name,(Tango::DevBoolean *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false); + } + else + { + Tango::DevErrorList errors(1); + errors.length(1); + 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); + push_change_event(it->second.attr_name, &except); + push_archive_event(it->second.attr_name, &except); + } + } catch(Tango::DevFailed & ex) + { + WARN_STREAM << "Alarm::do_alarm(): EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; + } + } catch(std::out_of_range& ex) { #ifndef _RW_LOCK alarms.unlock(); @@ -2645,8 +2839,26 @@ void Alarm::do_alarm(bei_t& e) ostringstream o; o << tmpname << ": in formula array index out of range!" << ends; WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl; - set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); - } catch(string & e) + set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); + try + { //DevFailed for push events + Tango::DevErrorList errors(1); + errors.length(1); + it->second.ex_reason = string("OUT_OF_RANGE"); + it->second.ex_desc = e.ev_name + ": " + o.str(); + it->second.ex_origin = e.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); + push_change_event(it->second.attr_name, &except); + push_archive_event(it->second.attr_name, &except); + } catch(Tango::DevFailed & ex) + { + WARN_STREAM << "Alarm::do_alarm(): EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; + } + } catch(string & ex) { #ifndef _RW_LOCK alarms.unlock(); @@ -2654,9 +2866,27 @@ void Alarm::do_alarm(bei_t& e) alarms.vlock->readerOut(); #endif ostringstream o; - o << tmpname << ": in formula err=" << e << ends; + o << tmpname << ": in formula err=" << ex << ends; WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl; - set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); + set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); + try + { //DevFailed for push events + Tango::DevErrorList errors(1); + errors.length(1); + it->second.ex_reason = string("FORMULA_ERROR"); + it->second.ex_desc = e.ev_name + ": " + o.str(); + it->second.ex_origin = e.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); + push_change_event(it->second.attr_name, &except); + push_archive_event(it->second.attr_name, &except); + } catch(Tango::DevFailed & ex) + { + WARN_STREAM << "Alarm::do_alarm(): EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; + } } } else @@ -2670,14 +2900,31 @@ void Alarm::do_alarm(bei_t& e) //o << j->first << ": not found formula in alarm table" << ends; o << (*j) << ": not found formula in alarm table" << ends; WARN_STREAM << "Alarm::do_alarm(): " << o.str() << endl; - set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); + set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); + try + { //DevFailed for push events + Tango::DevErrorList errors(1); + errors.length(1); + it->second.ex_reason = string("NOT_FOUND"); + it->second.ex_desc = e.ev_name + ": " + o.str(); + it->second.ex_origin = e.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); + push_change_event(it->second.attr_name, &except); + push_archive_event(it->second.attr_name, &except); + } catch(Tango::DevFailed & ex) + { + WARN_STREAM << "Alarm::do_alarm(): EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; + } } j++; } - //TODO: push_change_event HERE! prepare_alarm_attr(); - if(!changed) + if(num_changed==0) return; if(ds_num == 0) { @@ -2704,7 +2951,19 @@ void Alarm::timer_update() ostringstream o; o << "Error checking time thresholds and updating alarm status=" << e << ends; WARN_STREAM << "Alarm::timer_update(): " << o.str() << endl; - set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); + set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); +/* Tango::DevErrorList errors(1); + errors.length(1); + it->second.ex_reason = string("INTERNAL_ERROR"); + it->second.ex_desc = o.str(); + it->second.ex_origin = string("Alarm::timer_update"); + 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); + push_change_event(it->second.attr_name, &except); + push_archive_event(it->second.attr_name, &except);*/ } prepare_alarm_attr(); @@ -2805,13 +3064,14 @@ bool Alarm::remove_alarm(string& s) throw(string&) i->second.dp_n = NULL; /* * remove this alarm from alarm table - */ + */ + remove_AlarmState_dynamic_attribute(i->second.attr_name); + alarms.erase(i); #ifndef _RW_LOCK alarms.unlock(); #else alarms.vlock->writerOut(); #endif - alarms.erase(i); return true; } #ifndef _RW_LOCK @@ -2949,12 +3209,12 @@ void Alarm::set_internal_alarm(string name, Tango::TimeVal t, string msg, unsign //============================================================== //------------------- AST evaluation methods ------------------- //============================================================== -double Alarm::eval_formula(tree_parse_info_t tree, string &attr_values) +formula_res_t Alarm::eval_formula(tree_parse_info_t tree, string &attr_values) { return eval_expression(tree.trees.begin(), attr_values); } -double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range +formula_res_t Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range { ostringstream err; @@ -2969,8 +3229,10 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) throw err.str(); } string val_d(i->value.begin(), i->value.end()); - DEBUG_STREAM << " node value real = " << val_d << endl; - return strtod(val_d.c_str(), 0); + formula_res_t res; + res.value = strtod(val_d.c_str(), 0); + DEBUG_STREAM << " node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl; + return res; } else if (i->value.id() == formula_grammar::val_hID) { @@ -2981,7 +3243,9 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) } string val_d(i->value.begin(), i->value.end()); DEBUG_STREAM << " node value hex = " << val_d << endl; - return strtod(val_d.c_str(), 0); + formula_res_t res; + res.value = strtod(val_d.c_str(), 0); + return res; } else if (i->value.id() == formula_grammar::val_stID) { @@ -3025,7 +3289,9 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) double st = i->value.value(); //get value directly from node saved with access_node_d #endif //_ACCESS_NODE_D DEBUG_STREAM << " node value state : " << val_st << "=" << st << endl; - return st; + formula_res_t res; + res.value = st; + return res; } else if (i->value.id() == formula_grammar::unary_exprID) { @@ -3035,12 +3301,15 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; throw err.str(); } + formula_res_t res; + res = eval_expression(i->children.begin(), attr_values); if (*i->value.begin() == '+') - return + eval_expression(i->children.begin(), attr_values); + res.value = + res.value; if (*i->value.begin() == '-') - return - eval_expression(i->children.begin(), attr_values); + res.value = - res.value; if (*i->value.begin() == '!') - return ! eval_expression(i->children.begin(), attr_values); + res.value = ! res.value; + return res; } else if (i->value.id() == formula_grammar::mult_exprID) { @@ -3093,20 +3362,20 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) else if (i->value.id() == formula_grammar::event_ID) { DEBUG_STREAM << " node event" << string(i->value.begin(), i->value.end()) << endl; - int ind; + formula_res_t ind; if(i->children.size() != 2) { err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends;; throw err.str(); - } + } if((i->children.begin()+1)->value.id() == formula_grammar::indexID) - ind = (int)eval_expression(i->children.begin()+1, attr_values); //array index + ind = eval_expression(i->children.begin()+1, attr_values); //array index else { 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()) << ends;; throw err.str(); - } - return eval_expression(i->children.begin(), attr_values ,ind); + } + return eval_expression(i->children.begin(), attr_values, (int)ind.value); } else if (i->value.id() == formula_grammar::nameID) { @@ -3135,8 +3404,14 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) ostringstream temp_attr_val; temp_attr_val << it->name << "[" << ev_ind << "]=" <<it->value.at(ev_ind) << ";"; attr_values += temp_attr_val.str(); - DEBUG_STREAM << " node name -> " << temp_attr_val.str() << endl; - return it->value.at(ev_ind); //throw std::out_of_range + formula_res_t res; + res.quality = it->quality; + res.ex_reason = it->ex_reason; + res.ex_desc = it->ex_desc; + res.ex_origin = it->ex_origin; + DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl; + res.value = it->value.at(ev_ind); //throw std::out_of_range + return res; } else { @@ -3153,7 +3428,9 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) } string val_d(i->value.begin(), i->value.end()); DEBUG_STREAM << " node index = " << val_d << endl; - return strtod(val_d.c_str(), 0); + formula_res_t res; + res.value = strtod(val_d.c_str(), 0); + return res; } else if (i->value.id() == formula_grammar::logical_exprID) { @@ -3187,28 +3464,46 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) err << "in node bitwise_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; throw err.str(); } - double val_d1=eval_expression(i->children.begin(), attr_values), - val_d2=eval_expression(i->children.begin()+1, 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; string err2("ERROR: non-int value in bitwise operation!"); - val_l1 = (long)trunc(val_d1); //transform to long - val_l2 = (long)trunc(val_d2); //transform to long + val_l1 = (long)trunc(res_1.value); //transform to long + val_l2 = (long)trunc(res_2.value); //transform to long - if((val_l1 != val_d1) || (val_l2 != val_d2)) //if different, lost something with truncf + if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf throw err2; if (*i->value.begin() == '&') - { - return (double)(val_l1 & val_l2); + { + 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); + return res; } else if (*i->value.begin() == '|') { - return (double)(val_l1 | val_l2); + 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); + return res; } else if (*i->value.begin() == '^') - { - return (double)(val_l1 ^ val_l2); + { + 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); + return res; } else { @@ -3224,24 +3519,36 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) err << "in node shift_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; throw err.str(); } - double val_d1=eval_expression(i->children.begin(), attr_values), - val_d2=eval_expression(i->children.begin()+1, 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; string err2("ERROR: non-int value in bitwise operation!"); - val_l1 = (long)trunc(val_d1); //transform to long - val_l2 = (long)trunc(val_d2); //transform to long + val_l1 = (long)trunc(res_1.value); //transform to long + val_l2 = (long)trunc(res_2.value); //transform to long - if((val_l1 != val_d1) || (val_l2 != val_d2)) //if different, lost something with truncf + if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf throw err2; if (string(i->value.begin(), i->value.end()) == string("<<")) - { - return (double)(val_l1 << val_l2); + { + 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); + return res; } else if (string(i->value.begin(), i->value.end()) == string(">>")) - { - return (double)(val_l1 >> val_l2); + { + 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); + return res; } else { @@ -3314,8 +3621,11 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) { err << "in node funcID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; throw err.str(); - } - return fabs(eval_expression(i->children.begin(), attr_values)); //now handled only abs as function + } + formula_res_t res; + res = eval_expression(i->children.begin(), attr_values); + res.value = fabs(res.value); + return res; //now handled only abs as function } else { @@ -3325,7 +3635,9 @@ double Alarm::eval_expression(iter_t const& i, string &attr_values, int ev_ind) throw err.str(); } } - return 0; + formula_res_t res; + res.value = 0; + return res; } void Alarm::find_event_formula(tree_parse_info_t tree, vector<string> & ev) diff --git a/src/Alarm.h b/src/Alarm.h index dd9c4d7..681eb2d 100644 --- a/src/Alarm.h +++ b/src/Alarm.h @@ -183,6 +183,22 @@ public: virtual void read_alarm(Tango::Attribute &attr); virtual bool is_alarm_allowed(Tango::AttReqType type); +// Dynamic attribute methods +public: + + /** + * Attribute AlarmState related methods + * Description: + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_AlarmState(Tango::Attribute &attr); + virtual bool is_AlarmState_allowed(Tango::AttReqType type); + void add_AlarmState_dynamic_attribute(string attname); + void remove_AlarmState_dynamic_attribute(string attname); + Tango::DevBoolean *get_AlarmState_data_ptr(string &name); + map<string,Tango::DevBoolean> AlarmState_data; //-------------------------------------------------------- /** @@ -303,10 +319,10 @@ private: void load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn); - double eval_formula(tree_parse_info_t tree, string &attr_values); + formula_res_t eval_formula(tree_parse_info_t tree, string &attr_values); void find_event_formula(tree_parse_info_t tree, vector<string> &); - double 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, int ev_ind=0); //recursive tree node evaluation 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 diff --git a/src/Alarm.xmi b/src/Alarm.xmi index e7e5428..1623e05 100644 --- a/src/Alarm.xmi +++ b/src/Alarm.xmi @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="ASCII"?> <pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl"> <classes name="Alarm" pogoRevision="9.1"> - <description description="Elettra alarm device server" title="Elettra alarm device server" sourcePath="/home/graziano/workspace/git/alarm/src" language="Cpp" filestogenerate="XMI file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false"> + <description description="Elettra alarm device server" title="Elettra alarm device server" sourcePath="/home/graziano/workspace/git/alarm/src" language="Cpp" filestogenerate="XMI file,Code files,Protected Regions,Eclipse Project" license="GPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false"> <inheritances classname="Device_4Impl" sourcePath=""/> <identification contact="at elettra.eu - graziano.scalamera" author="graziano.scalamera" emailDomain="elettra.eu" classFamily="SoftwareSystem" siteSpecific="" platform="Unix Like" bus="Not Applicable" manufacturer="" reference=""/> </description> @@ -129,6 +129,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> + <dynamicAttributes name="AlarmState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <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=""/> + </dynamicAttributes> <preferences docHome="./doc_html" makefileHome="/usr/local/tango-8.1.2.c/share/pogo/preferences"/> </classes> </pogoDsl:PogoSystem> diff --git a/src/AlarmClass.h b/src/AlarmClass.h index df66071..e215eb1 100644 --- a/src/AlarmClass.h +++ b/src/AlarmClass.h @@ -72,6 +72,23 @@ public: }; +//========================================= +// Define classes for dynamic attributes +//========================================= +// Attribute AlarmState class definition +class AlarmStateAttrib: public Tango::Attr +{ +public: + AlarmStateAttrib(const string &att_name):Attr(att_name.c_str(), + Tango::DEV_BOOLEAN, Tango::READ) {}; + ~AlarmStateAttrib() {}; + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<Alarm *>(dev))->read_AlarmState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<Alarm *>(dev))->is_AlarmState_allowed(ty);} +}; + + //========================================= // Define classes for commands //========================================= diff --git a/src/AlarmDynAttrUtils.cpp b/src/AlarmDynAttrUtils.cpp new file mode 100644 index 0000000..122abfe --- /dev/null +++ b/src/AlarmDynAttrUtils.cpp @@ -0,0 +1,158 @@ +/*----- PROTECTED REGION ID(Alarm::DynAttrUtils.cpp) ENABLED START -----*/ +static const char *RcsId = "$Id: $"; +//============================================================================= +// +// file : AlarmDynAttrUtils.cpp +// +// description : Dynamic attributes utilities file for the Alarm class +// +// project : Elettra alarm device server +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Tango is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// $Author: $ +// +// $Revision: $ +// $Date: $ +// +// $HeadURL: $ +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + + +#include <Alarm.h> +#include <AlarmClass.h> + +/*----- PROTECTED REGION END -----*/ // Alarm::DynAttrUtils.cpp + +//================================================================ +// Attributes managed is: +//================================================================ +// AlarmState | Tango::DevBoolean Scalar +//================================================================ + +// For compatibility reason, this file (AlarmDynAttrUtils) +// manage also the dynamic command utilities. +//================================================================ +// The following table gives the correspondence +// between command and method names. +// +// Command name | Method name +//================================================================ +//================================================================ + +namespace Alarm_ns +{ +//============================================================= +// Add/Remove dynamic attribute methods +//============================================================= + +//-------------------------------------------------------- +/** + * Add a AlarmState dynamic attribute. + * + * parameter attname: attribute name to be cretated and added. + */ +//-------------------------------------------------------- +void Alarm::add_AlarmState_dynamic_attribute(string attname) +{ + // Attribute : AlarmState + AlarmStateAttrib *alarmstate = new AlarmStateAttrib(attname); + Tango::UserDefaultAttrProp alarmstate_prop; + // description not set for AlarmState + // label not set for AlarmState + // unit not set for AlarmState + // standard_unit not set for AlarmState + // display_unit not set for AlarmState + // format not set for AlarmState + // max_value not set for AlarmState + // min_value not set for AlarmState + // max_alarm not set for AlarmState + // min_alarm not set for AlarmState + // max_warning not set for AlarmState + // min_warning not set for AlarmState + // delta_t not set for AlarmState + // delta_val not set for AlarmState + + /*----- PROTECTED REGION ID(Alarm::att_AlarmState_dynamic_attribute) ENABLED START -----*/ + DEBUG_STREAM << __func__<<": entering name="<<attname; + + /*----- PROTECTED REGION END -----*/ // Alarm::att_AlarmState_dynamic_attribute + alarmstate->set_default_properties(alarmstate_prop); + // Not Polled + alarmstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + alarmstate->set_change_event(true, true); + alarmstate->set_archive_event(true, true); + AlarmState_data.insert(make_pair(attname, false)); + add_attribute(alarmstate); +} +//-------------------------------------------------------- +/** + * remove a AlarmState dynamic attribute. + * + * parameter attname: attribute name to be removed. + */ +//-------------------------------------------------------- +void Alarm::remove_AlarmState_dynamic_attribute(string attname) +{ + remove_attribute(attname, true); + map<string,Tango::DevBoolean>::iterator ite; + if ((ite=AlarmState_data.find(attname))!=AlarmState_data.end()) + { + /*----- PROTECTED REGION ID(Alarm::remove_AlarmState_dynamic_attribute) ENABLED START -----*/ + DEBUG_STREAM << __func__<<": entering name="<<attname; + /*----- PROTECTED REGION END -----*/ // Alarm::remove_AlarmState_dynamic_attribute + AlarmState_data.erase(ite); + } +} + + +//============================================================ +// Tool methods to get pointer on attribute data buffer +//============================================================ +//-------------------------------------------------------- +/** + * Return a pointer on AlarmState data. + * + * parameter attname: the specified attribute name. + */ +//-------------------------------------------------------- +Tango::DevBoolean *Alarm::get_AlarmState_data_ptr(string &name) +{ + map<string,Tango::DevBoolean>::iterator ite; + if ((ite=AlarmState_data.find(name))==AlarmState_data.end()) + { + TangoSys_OMemStream tms; + tms << "Dynamic attribute " << name << " has not been created"; + Tango::Except::throw_exception( + (const char *)"ATTRIBUTE_NOT_FOUND", + tms.str().c_str(), + (const char *)"Alarm::get_AlarmState_data_ptr()"); + } + return &(ite->second); +} + + +//============================================================= +// Add/Remove dynamic command methods +//============================================================= + + +} // namespace diff --git a/src/AlarmStateMachine.cpp b/src/AlarmStateMachine.cpp index 5f703cc..558ee6f 100644 --- a/src/AlarmStateMachine.cpp +++ b/src/AlarmStateMachine.cpp @@ -66,6 +66,22 @@ bool Alarm::is_alarm_allowed(TANGO_UNUSED(Tango::AttReqType type)) return true; } +//-------------------------------------------------------- +/** + * Method : Alarm::is_AlarmState_allowed() + * Description : Execution allowed for AlarmState attribute + */ +//-------------------------------------------------------- +bool Alarm::is_AlarmState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for AlarmState attribute in read access. + /*----- PROTECTED REGION ID(Alarm::AlarmStateStateAllowed_READ) ENABLED START -----*/ + + /*----- PROTECTED REGION END -----*/ // Alarm::AlarmStateStateAllowed_READ + return true; +} + //================================================= // Commands Allowed Methods diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp index fa6b4ce..d017c15 100644 --- a/src/alarm_table.cpp +++ b/src/alarm_table.cpp @@ -341,7 +341,7 @@ void alarm_table::stored(vector<alarm_t>& a) #endif } -bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, int res, string &attr_values, string grp, string msg, string formula) +bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_t res, string &attr_values, string grp, string msg, string formula) { bool ret_changed=false; //Tango::TimeVal now = gettime(); @@ -366,34 +366,37 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, int res, str else found->second.silenced = 0; } - + found->second.quality = res.quality; + found->second.ex_reason = res.ex_reason; + found->second.ex_desc = res.ex_desc; + found->second.ex_origin = res.ex_origin; bool status_time_threshold; if(found->second.time_threshold > 0) //if enabled time threshold - status_time_threshold = (res) && (found->second.counter >= 1) && ((ts.tv_sec - found->second.time_threshold) > found->second.ts_time_threshold.tv_sec); //formula gives true and time threshold is passed + status_time_threshold = ((int)res.value) && (found->second.counter >= 1) && ((ts.tv_sec - found->second.time_threshold) > found->second.ts_time_threshold.tv_sec); //formula gives true and time threshold is passed else - status_time_threshold = res; + status_time_threshold = (int)res.value; //if status changed: // - from S_NORMAL to S_ALARM considering also time threshold //or // - from S_ALARM to S_NORMAL - if((status_time_threshold && (found->second.stat == S_NORMAL)) || (!res && (found->second.stat == S_ALARM))) + if((status_time_threshold && (found->second.stat == S_NORMAL)) || (!(int)res.value && (found->second.stat == S_ALARM))) { ret_changed=true; a.type_log = TYPE_LOG_STATUS; a.name = alm_name; a.time_s = ts.tv_sec; a.time_us = ts.tv_usec; - a.status = res ? S_ALARM : S_NORMAL; + a.status = (int)res.value ? S_ALARM : S_NORMAL; //a.level = found->second.lev; - if(res) + if((int)res.value) found->second.ack = NOT_ACK; //if changing from NORMAL to ALARM -> NACK a.ack = found->second.ack; a.values = attr_values; //a.grp = found->second.grp2str(); - //a.msg = res ? found->second.msg : ""; + //a.msg = (int)res.value ? found->second.msg : ""; logloop->log_alarm_db(a); found->second.ts = ts; /* store event timestamp into alarm timestamp */ //here update ts only if status changed - if(res) + if((int)res.value) { found->second.is_new = 1; //here set this alarm as new, read attribute set it to 0 //12-06-08: StopNew command set it to 0 if(found->second.dp_a && ((ts.tv_sec - startup_complete.tv_sec) > 10)) //action from S_NORMAL to S_ALARM @@ -491,7 +494,7 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, int res, str found->second.stat = S_ALARM; //found->second.ack = NOT_ACK; } - if(res) { + if((int)res.value) { found->second.counter++; } else { found->second.stat = S_NORMAL; @@ -611,6 +614,30 @@ bool alarm_table::timer_update() arg.arg_b = i->second.send_arg_a; cmdloop->list.push_back(arg); } + *(i->second.attr_value) = true; + try + { + if(i->second.ex_reason.length() == 0) + { + timeval now; + gettimeofday(&now, NULL); + mydev->push_change_event(i->second.attr_name,(Tango::DevBoolean *)i->second.attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false); + mydev->push_archive_event(i->second.attr_name,(Tango::DevBoolean *)i->second.attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false); + } + else + { + Tango::DevErrorList errors(1); + errors.length(1); + errors[0].desc = CORBA::string_dup(i->second.ex_desc.c_str()); + errors[0].severity = Tango::ERR; + errors[0].reason = CORBA::string_dup(i->second.ex_reason.c_str()); + errors[0].origin = CORBA::string_dup(i->second.ex_origin.c_str()); + Tango::DevFailed except(errors); + mydev->push_change_event(i->second.attr_name, &except); + mydev->push_archive_event(i->second.attr_name, &except); + } + } catch(Tango::DevFailed &e) + {} } if (status_time_threshold) { i->second.stat = S_ALARM; diff --git a/src/alarm_table.h b/src/alarm_table.h index ee82694..818a7e4 100644 --- a/src/alarm_table.h +++ b/src/alarm_table.h @@ -102,6 +102,166 @@ class alarm_table; class log_thread; class cmd_thread; + +struct formula_res_t +{ + formula_res_t(){value=0;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");} + double value; + int quality; + Tango::DevErrorList errors; //TODO: error stack + string ex_reason; + string ex_desc; + string ex_origin; + int combine_quality(int quality1, int quality2) + { + int res; + if(quality1 == Tango::ATTR_INVALID || quality2 == Tango::ATTR_INVALID) + res = Tango::ATTR_INVALID; + else if(quality1 == Tango::ATTR_ALARM || quality2 == Tango::ATTR_ALARM) + res = Tango::ATTR_ALARM; + else if(quality1 == Tango::ATTR_WARNING || quality2 == Tango::ATTR_WARNING) + res = Tango::ATTR_WARNING; + else if(quality1 == Tango::ATTR_CHANGING || quality2 == Tango::ATTR_CHANGING) + res = Tango::ATTR_CHANGING; + else + res = (quality1 > quality2) ? quality1 : quality2; //TODO: decide priority in enum AttrQuality { ATTR_VALID, ATTR_INVALID, ATTR_ALARM, ATTR_CHANGING, ATTR_WARNING /*, __max_AttrQuality=0xffffffff */ }; + return res; + } + string combine_exception(string ex_1, string ex_2) + { + if(ex_1.length() > 0) + return ex_1; + else + return ex_2; + } + formula_res_t operator==(const formula_res_t& e) + { + formula_res_t res; + res.value = value == e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator!=(const formula_res_t& e) + { + formula_res_t res; + res.value = value != e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator<=(const formula_res_t& e) + { + formula_res_t res; + res.value = value <= e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator>=(const formula_res_t& e) + { + formula_res_t res; + res.value = value >= e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator<(const formula_res_t& e) + { + formula_res_t res; + res.value = value < e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator>(const formula_res_t& e) + { + formula_res_t res; + res.value = value > e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator||(const formula_res_t& e) + { + formula_res_t res; + res.value = value || e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator&&(const formula_res_t& e) + { + formula_res_t res; + res.value = value && e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator+(const formula_res_t& e) + { + formula_res_t res; + res.value = value + e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator-(const formula_res_t& e) + { + formula_res_t res; + res.value = value - e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator*(const formula_res_t& e) + { + formula_res_t res; + res.value = value * e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + formula_res_t operator/(const formula_res_t& e) + { + formula_res_t res; + res.value = value / e.value; + res.quality = combine_quality(quality, e.quality); + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + return res; + } + /*string operator<<(const formula_res_t& e) + { + stringstream res; + res << "value="<<e.value<<" quality="<<e.quality<<" EX reason="<<e.ex_reason<<" desc="<<e.ex_desc<<" origin="<<e.ex_origin; + return res.str(); + }*/ +}; + /* * store the alarm-name/alarm-formula pair */ @@ -109,6 +269,12 @@ class alarm_t { public: string name, formula; + string attr_name; + Tango::DevBoolean *attr_value; + int quality; + string ex_reason; + string ex_desc; + string ex_origin; Tango::TimeVal ts; string stat, ack; @@ -171,6 +337,7 @@ class alarm_table { public: alarm_table() {} ~alarm_table() {} + void set_dev(Tango::DeviceImpl* devImpl) {mydev=devImpl;} //void init(vector<string>& avs); //void init(vector<string>& avs, vector<string> &evn, map< string,vector<string> > &alarm_event); @@ -179,7 +346,7 @@ class alarm_table { unsigned int size(void); alarm_container_t& get(void); void stored(vector<alarm_t>& a); - bool update(const string& alm_name, Tango::TimeVal ts, int res, string &attr_values, string grp, string msg, string formula); + bool update(const string& alm_name, Tango::TimeVal ts, formula_res_t res, string &attr_values, string grp, string msg, string formula); bool timer_update(); void erase(alarm_container_t::iterator i); bool exist(string& s); @@ -203,7 +370,7 @@ class alarm_table { protected: private: - + Tango::DeviceImpl* mydev; log_thread *logloop; cmd_thread *cmdloop; }; diff --git a/src/event_table.cpp b/src/event_table.cpp index 846e5cb..da0c2cc 100644 --- a/src/event_table.cpp +++ b/src/event_table.cpp @@ -377,10 +377,15 @@ void EventCallBack::push_event(Tango::EventData* ev) { string temp_name; bei_t e; - + e.ex_reason = string(""); + e.ex_desc = string(""); + e.ex_origin = string(""); try { + //e.errors = ev->errors; + e.quality = Tango::ATTR_VALID; + //cout << "EVENT="<<ev->attr_name<<" quality="<<e.quality<<endl; if (!ev->err) { - + e.quality = (int)ev->attr_value->get_quality(); #if 0//TANGO_VER >= 711 string ev_name_str(ev->attr_name); string::size_type pos = ev_name_str.find("tango://"); diff --git a/src/event_table.h b/src/event_table.h index 395c9ec..8e2b5cb 100644 --- a/src/event_table.h +++ b/src/event_table.h @@ -45,6 +45,11 @@ class event { device, /* device name */ attribute; /* attribute name */ value_t value; /* event value */ + int quality; + //Tango::DevErrorList errors; + string ex_reason; + string ex_desc; + string ex_origin; Tango::TimeVal ts; /* event timestamp */ int type, /* attribute data type */ counter, /* molteplicita' */ @@ -76,6 +81,11 @@ class event { typedef struct basic_event_info_s { string ev_name; value_t value; + int quality; + //Tango::DevErrorList errors; + string ex_reason; + string ex_desc; + string ex_origin; int type; Tango::TimeVal ts; string msg; -- GitLab