
org.tango.server.events.ChangeEventTrigger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of JTangoServer Show documentation
Show all versions of JTangoServer Show documentation
Library for Tango Server (ie. Tango Device) in Java
The newest version!
/**
* Copyright (C) : 2012
*
* Synchrotron Soleil
* L'Orme des merisiers
* Saint Aubin
* BP48
* 91192 GIF-SUR-YVETTE CEDEX
*
* This file is part of Tango.
*
* Tango is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Tango. If not, see .
*/
package org.tango.server.events;
import java.lang.reflect.Array;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
import org.tango.server.Constants;
import org.tango.server.ExceptionMessages;
import org.tango.server.attribute.AttributeImpl;
import org.tango.server.attribute.AttributeValue;
import org.tango.utils.ArrayUtils;
import org.tango.utils.DevFailedUtils;
import fr.esrf.Tango.DevEncoded;
import fr.esrf.Tango.DevFailed;
import fr.esrf.Tango.DevState;
import fr.esrf.Tango.EventProperties;
/**
* manage trigger for {@link EventType#CHANGE_EVENT}
*
* @author ABEILLE
*
*/
public class ChangeEventTrigger implements IEventTrigger {
private final Logger logger = LoggerFactory.getLogger(ChangeEventTrigger.class);
private final XLogger xlogger = XLoggerFactory.getXLogger(ChangeEventTrigger.class);
private final AttributeImpl attribute;
private AttributeValue previousValue;
private AttributeValue value;
private double absolute;
private boolean checkAbsolute;
private double relative;
private boolean checkRelative;
private DevFailed error;
private DevFailed previousError;
private boolean previousInitialized = false;
private final QualityEventTrigger qualityTrigger;
/**
* Ctr
*
* @param attribute The attribute that send event
* @param absolute The absolute change delta
* @param relative The relative change delta
*/
public ChangeEventTrigger(final AttributeImpl attribute, final String absolute, final String relative) {
this.attribute = attribute;
value = attribute.getReadValue();
qualityTrigger = new QualityEventTrigger(attribute);
setCriteria(absolute, relative);
}
public void setCriteria(final String absolute, final String relative) {
try {
this.absolute = Double.parseDouble(absolute);
checkAbsolute = true;
} catch (final NumberFormatException e) {
checkAbsolute = false;
}
try {
this.relative = Double.parseDouble(relative);
checkRelative = true;
} catch (final NumberFormatException e) {
checkRelative = false;
}
}
@Override
public boolean isSendEvent() throws DevFailed {
xlogger.entry();
boolean hasChanged = qualityTrigger.isSendEvent();
if (!hasChanged) {
value = attribute.getReadValue();
// Check if first call
if (!previousInitialized) {
previousError = error;
previousValue = value;
previousInitialized = true;
hasChanged = true;
} else {
if (previousError != null && error == null) {
// there was an error before
hasChanged = true;
} else if (previousError == null && error != null) {
// an error has just occured
hasChanged = true;
} else if (previousError != null && error != null) {
if (!DevFailedUtils.toString(previousError).equals(DevFailedUtils.toString(error))) {
// the error msg has changed
hasChanged = true;
}
} else if (value.getValue() == null && previousValue.getValue() == null) {
hasChanged = false;
} else if (value.getValue() == null && previousValue.getValue() != null) {
hasChanged = true;
} else if (value.getValue() != null && previousValue.getValue() == null) {
hasChanged = true;
} else if (attribute.isScalar()) {
if (attribute.isNumber()) {
hasChanged = hasScalarNumberChanged();
} else if (attribute.isState()) {
hasChanged = hasStateChanged();
} else if (attribute.isDevEncoded()) {
hasChanged = hasDevEncodedChanged();
} else {
// string or boolean
hasChanged = hasScalarStringChanged();
}
} else {
if (attribute.isNumber()) {
hasChanged = hasArrayNumberChanged();
} else if (attribute.isState()) {
hasChanged = hasStateArrayChanged();
} else {
// string or boolean
hasChanged = hasArrayStringChanged();
}
}
if (hasChanged) {
previousValue = value;
}
}
}
logger.debug("CHANGE event for {} must send: {}", attribute.getName(), hasChanged);
xlogger.exit();
return hasChanged;
}
@Override
public void setError(final DevFailed error) {
previousError = this.error;
this.error = error;
}
private boolean hasScalarNumberChanged() {
boolean hasChanged = false;
final double val = Double.parseDouble(value.getValue().toString());
final double previousVal = Double.parseDouble(previousValue.getValue().toString());
// absolute change
if (checkAbsolute) {
final double delta = val - previousVal;
hasChanged = Math.abs(delta) >= absolute;
}
// relative change
if (!hasChanged && checkRelative) {
final double delta;
if (previousVal == 0) {
if (val == 0) {
delta = 0;
} else {
delta = 100;
}
} else {
delta = (val - previousVal) / previousVal * 100.0;
}
hasChanged = Math.abs(delta) >= relative;
}
return hasChanged;
}
private boolean hasDevEncodedChanged() {
final DevEncoded val = (DevEncoded) value.getValue();
final DevEncoded previousVal = (DevEncoded) previousValue.getValue();
return !Arrays.equals(val.encoded_data, previousVal.encoded_data);
}
private boolean hasScalarStringChanged() {
final String val = value.getValue().toString();
final String previousVal = previousValue.getValue().toString();
return !val.equals(previousVal);
}
private boolean hasArrayNumberChanged() {
boolean hasChanged = false;
if (Array.getLength(value.getValue()) != Array.getLength(previousValue.getValue())) {
hasChanged = true;
} else {
final String[] val = ArrayUtils.toStringArray(value.getValue());
final String[] previousVal = ArrayUtils.toStringArray(previousValue.getValue());
for (int i = 0; i < previousVal.length; i++) {
final double valD = Double.parseDouble(val[i]);
final double previousValD = Double.parseDouble(previousVal[i]);
// absolute change
if (checkAbsolute) {
final double delta = valD - previousValD;
hasChanged = Math.abs(delta) >= absolute;
}
// relative change
if (!hasChanged && checkRelative) {
final double delta;
if (previousValD == 0) {
if (valD == 0) {
delta = 0;
} else {
delta = 100;
}
} else {
delta = valD - previousValD * 100.0 / previousValD;
}
hasChanged = Math.abs(delta) >= relative;
}
if (hasChanged) {
break;
}
}
}
return hasChanged;
}
private boolean hasArrayStringChanged() {
boolean hasChanged = false;
if (Array.getLength(value.getValue()) != Array.getLength(previousValue.getValue())) {
hasChanged = true;
} else {
final String[] val;
final String[] previousVal;
if (value.getValue() instanceof String[]) {
val = (String[]) value.getValue();
previousVal = (String[]) previousValue.getValue();
} else {
val = ArrayUtils.toStringArray(value.getValue());
previousVal = ArrayUtils.toStringArray(previousValue.getValue());
}
if (!Arrays.equals(val, previousVal)) {
hasChanged = true;
}
}
return hasChanged;
}
private boolean hasStateChanged() {
final DevState state = (DevState) value.getValue();
final DevState previousState = (DevState) previousValue.getValue();
return state != previousState;
}
private boolean hasStateArrayChanged() {
boolean hasChanged = false;
final DevState[] state = (DevState[]) value.getValue();
final DevState[] previousState = (DevState[]) previousValue.getValue();
if (state.length != previousState.length) {
hasChanged = true;
} else {
for (int i = 0; i < previousState.length; i++) {
if (!state[i].equals(previousState[i])) {
hasChanged = true;
break;
}
}
}
return hasChanged;
}
/**
* Check if event criteria are set for specified events
*
* @param attribute the specified attribute
* @throws DevFailed if no event criteria is set for specified attribute.
*/
static void checkEventCriteria(final AttributeImpl attribute) throws DevFailed {
// Check if value is not numerical (always true for State and String)
if (attribute.isState() || attribute.isString() || attribute.isBoolean()) {
return;
}
// Else check criteria
final EventProperties props = attribute.getProperties().getEventProp();
if (props.ch_event.abs_change.equals(Constants.NOT_SPECIFIED)
&& props.ch_event.rel_change.equals(Constants.NOT_SPECIFIED)) {
DevFailedUtils
.throwDevFailed(ExceptionMessages.EVENT_CRITERIA_NOT_SET,
"Event properties (abs_change or rel_change) for attribute " + attribute.getName()
+ " are not set");
}
}
@Override
public void updateProperties() throws DevFailed {
final EventProperties props = attribute.getProperties().getEventProp();
setCriteria(props.ch_event.abs_change, props.ch_event.rel_change);
}
@Override
public boolean doCheck() {
return attribute.isPushChangeEvent() ? attribute.isCheckChangeEvent() : true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy