View Javadoc
1   /**
2    * Copyright (C) 2010-14 pvmanager developers. See COPYRIGHT.TXT
3    * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4    */
5   package org.epics.pvmanager.sim;
6   
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.concurrent.ScheduledExecutorService;
11  import java.util.concurrent.ScheduledFuture;
12  import java.util.concurrent.TimeUnit;
13  import java.util.logging.Level;
14  import java.util.logging.Logger;
15  import org.epics.pvmanager.ChannelWriteCallback;
16  import org.epics.pvmanager.MultiplexedChannelHandler;
17  import org.epics.pvmanager.util.FunctionParser;
18  import org.epics.vtype.AlarmSeverity;
19  import org.epics.vtype.VType;
20  import static org.epics.vtype.ValueFactory.*;
21  
22  /**
23   *
24   * @author carcassi
25   */
26  class IntermittentChannelHandler extends MultiplexedChannelHandler<Object, Object> {
27      
28      private final Object value;
29      private final double delayInSeconds;
30      private final ScheduledExecutorService exec;
31      private final Runnable task = new Runnable() {
32  
33          @Override
34          public void run() {
35              // Protect the timer thread for possible problems.
36              try {
37                  boolean toConnect = !isConnected();
38                  
39                  if (toConnect) {
40                      processConnection(new Object());
41                      processMessage(toVTypeChecked(value));
42                  } else {
43                      processMessage(toVTypeChecked(value, newAlarm(AlarmSeverity.UNDEFINED, "Disconnected"), timeNow(), displayNone()));
44                      processConnection(null);
45                  }
46              } catch (Exception ex) {
47                  log.log(Level.WARNING, "Data simulation problem", ex);
48              }
49          }
50      };
51      private static final Logger log = Logger.getLogger(SimulationChannelHandler.class.getName());
52      private ScheduledFuture<?> taskFuture;
53  
54      IntermittentChannelHandler(String channelName, ScheduledExecutorService exec) {
55          super(channelName);
56          String errorMessage = "Incorrect syntax. Must match intermittentChannel(delayInSeconds, value)";
57          List<Object> tokens = FunctionParser.parseFunctionAnyParameter(channelName);
58          if (tokens == null || tokens.size() <= 1) {
59              throw new IllegalArgumentException(errorMessage);
60          }
61          if (tokens.size() == 2) {
62              value = "Initial Value";
63          } else {
64              value = FunctionParser.asScalarOrList(tokens.subList(2, tokens.size()));
65              if (value == null) {
66                  throw new IllegalArgumentException(errorMessage);
67              }
68          }
69          delayInSeconds = (Double) tokens.get(1);
70          if (delayInSeconds < 0.001) {
71              throw new IllegalArgumentException("Delay must be at least 0.001");
72          }
73          this.exec = exec;
74      }
75  
76      @Override
77      public void connect() {
78          taskFuture = exec.scheduleWithFixedDelay(task, 0, (long) (delayInSeconds * 1000), TimeUnit.MILLISECONDS);
79      }
80  
81      @Override
82      public void disconnect() {
83          taskFuture.cancel(false);
84          processConnection(null);
85      }
86  
87      @Override
88      public Map<String, Object> getProperties() {
89          Map<String, Object> result = new HashMap<>();
90          result.put("delayInSeconds", delayInSeconds);
91          result.put("value", value);
92          return result;
93      }
94  
95      @Override
96      protected boolean isConnected(Object payload) {
97          return payload != null;
98      }
99      
100     @Override
101     public void write(Object newValue, ChannelWriteCallback callback) {
102         throw new UnsupportedOperationException("Can't write to simulation channel.");
103     }
104     
105 }