From 95d047d0f46d5d0764d98756a10b945e923208f4 Mon Sep 17 00:00:00 2001 From: Simon Ebner Date: Tue, 21 May 2013 16:01:05 +0200 Subject: [PATCH] Added regex wait condition for string values ... --- .../main/java/ch/psi/fda/aq/Acquisition.java | 40 +++++ .../actions/ChannelAccessConditionRegex.java | 149 ++++++++++++++++++ .../actions/ChannelAccessConditionTest.java | 17 +- 3 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessConditionRegex.java diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/aq/Acquisition.java b/ch.psi.fda/src/main/java/ch/psi/fda/aq/Acquisition.java index 3cdfb25..4e78ad1 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/aq/Acquisition.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/aq/Acquisition.java @@ -42,6 +42,9 @@ import ch.psi.fda.core.Actor; import ch.psi.fda.core.EngineConfiguration; import ch.psi.fda.core.Sensor; import ch.psi.fda.core.actions.ChannelAccessCondition; +import ch.psi.fda.core.actions.ChannelAccessConditionAnd; +import ch.psi.fda.core.actions.ChannelAccessConditionOr; +import ch.psi.fda.core.actions.ChannelAccessConditionRegex; import ch.psi.fda.core.actions.ChannelAccessPut; import ch.psi.fda.core.actions.Delay; import ch.psi.fda.core.actors.ChannelAccessFunctionActuator; @@ -567,6 +570,43 @@ public class Acquisition { alist.add(new ChannelAccessCondition(ca.getChannel(), new Double(ca.getValue()), timeout)); } } + else if(operation.equals("waitREGEX")){ + Long timeout = null ; // Default timeout = wait forever + if(ca.getTimeout()!=null){ + timeout = Math.round(ca.getTimeout()*1000); + } + if(type.equals("String")){ + alist.add(new ChannelAccessConditionRegex(ca.getChannel(), ca.getValue(), timeout)); + } + else{ + logger.warning("Operation "+operation+" wity type "+type+" for action is not supported"); + } + } + else if(operation.equals("waitOR")){ + Long timeout = null ; // Default timeout = wait forever + if(ca.getTimeout()!=null){ + timeout = Math.round(ca.getTimeout()*1000); + } + + if(type.equals("Integer")){ + alist.add(new ChannelAccessConditionOr(ca.getChannel(), new Integer(ca.getValue()), timeout)); + } + else{ + logger.warning("Operation "+operation+" wity type "+type+" for action is not supported"); + } + } + else if(operation.equals("waitAND")){ + Long timeout = null ; // Default timeout = wait forever + if(ca.getTimeout()!=null){ + timeout = Math.round(ca.getTimeout()*1000); + } + if(type.equals("Integer")){ + alist.add(new ChannelAccessConditionAnd(ca.getChannel(), new Integer(ca.getValue()), timeout)); + } + else { + logger.warning("Operation "+operation+" wity type "+type+" for action is not supported"); + } + } else{ // Operation not supported logger.warning("Operation "+operation+" for action is not supported"); diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessConditionRegex.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessConditionRegex.java new file mode 100644 index 0000000..a904ab4 --- /dev/null +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessConditionRegex.java @@ -0,0 +1,149 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code 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. + * + * This code 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 this code. If not, see . + * + */ + +package ch.psi.fda.core.actions; + +import java.util.Comparator; +import java.util.logging.Logger; + +import gov.aps.jca.CAException; +import ch.psi.fda.core.Action; +import ch.psi.jcae.ChannelBean; +import ch.psi.jcae.ChannelBeanFactory; + +/** + * Perform a put on the specified Channel Access channel. The put can be done synchronous or + * asynchronously. + * @author ebner + * + */ +public class ChannelAccessConditionRegex implements Action { + + // Get Logger + private static Logger logger = Logger.getLogger(ChannelAccessConditionRegex.class.getName()); + + /** + * Channel to set + */ + private final ChannelBean channel; + /** + * Value to wait for + */ + private final E expectedValue; + + private final Long timeout; + + private volatile boolean abort = false; + private volatile Thread waitT = null; + + /** + * Constructor + * @param channelName Name of the channel to set the value + * @param expectedValue Value to wait for + * @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout) + * + * @throws IllegalArgumentException Unable to initialize channel, + * Timeout specified is not >=0 + */ + @SuppressWarnings("unchecked") + public ChannelAccessConditionRegex(String channelName, E expectedValue, Long timeout){ + + if(timeout !=null && timeout<=0){ + throw new IllegalArgumentException("Timeout must be > 0"); + } + + try { + this.channel = (ChannelBean) ChannelBeanFactory.getFactory().createChannelBean( (Class) expectedValue.getClass(), channelName, false); + } catch (CAException e) { + // Convert Exception into unchecked RuntimeException + throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e); + } catch (InterruptedException e) { + throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e); + } + + this.expectedValue = expectedValue; + + if(timeout==null){ + this.timeout = channel.getWaitTimeout(); + } + else{ + this.timeout = timeout; + } + } + + + /* (non-Javadoc) + * @see ch.psi.fda.core.Action#execute() + */ + /** + * @throws InterruptedException + * @throws RuntimeException Channel value did not reach expected value (within the specified timeout period) + */ + @Override + public void execute() throws InterruptedException { + abort=false; + logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" ); + try{ + waitT = Thread.currentThread(); + channel.waitForValue(expectedValue, new Comparator() { + + @Override + public int compare(E o1, E o2) { + return o1.matches(o2) ? 0:1; + } + }, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value + } catch (CAException e) { + throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e); + } catch(InterruptedException e){ + if(!abort){ + throw e; + } + } + finally{ + waitT=null; + } + } + + /* (non-Javadoc) + * @see ch.psi.fda.core.Action#abort() + */ + @Override + public void abort() { + abort=true; + if(waitT!=null){ + waitT.interrupt(); + } + } + + + /* (non-Javadoc) + * @see ch.psi.fda.core.Action#destroy() + */ + @Override + public void destroy() { + // Destroy channel + try { + logger.finest("Destroy action channel: "+channel.getName()); + channel.destroy(); + } catch (CAException e) { + throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e); + } + } + +} diff --git a/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java b/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java index acf1ed4..d1c8ab7 100644 --- a/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java +++ b/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java @@ -59,10 +59,23 @@ public class ChannelAccessConditionTest { /** * Test method for {@link ch.psi.fda.core.actions.ChannelAccessStringCondition#ChannelAccessStringCondition(java.lang.String, java.lang.String, long)}. + * @throws InterruptedException + * @throws CAException */ @Test - public void testChannelAccessStringCondition() { - new ChannelAccessCondition(TestChannels.STRING_OUT, "SomeValue", 1000l); + public void testChannelAccessStringCondition() throws InterruptedException, CAException { + final ChannelBean channel = ChannelBeanFactory.getFactory().createChannelBean(String.class, TestChannels.STRING_OUT, false); + channel.setValue("SomeValue"); + ChannelAccessCondition c = new ChannelAccessCondition(TestChannels.STRING_OUT, "SomeValue", 1000l); + c.execute(); + } + + @Test + public void testChannelAccessStringConditionRegex() throws InterruptedException, CAException { + final ChannelBean channel = ChannelBeanFactory.getFactory().createChannelBean(String.class, TestChannels.STRING_OUT, false); + channel.setValue("SomeValue"); + ChannelAccessConditionRegex c = new ChannelAccessConditionRegex(TestChannels.STRING_OUT, "Some.*", 1000l); + c.execute(); } /**