View Javadoc

1   /*
2   Copyright (C) 2007 Dirk Huenniger
3   
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8   
9   This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Lesser General Public License for more details.
13  
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17   */
18  
19  package org.indi.examples;
20  
21  import java.io.IOException;
22  
23  import org.indi.clientmessages.GetProperties;
24  import org.indi.objects.Blob;
25  import org.indi.objects.BlobVector;
26  import org.indi.objects.Number;
27  import org.indi.objects.NumberVector;
28  import org.indi.objects.Permission;
29  import org.indi.objects.State;
30  import org.indi.objects.Switch;
31  import org.indi.objects.SwitchRule;
32  import org.indi.objects.SwitchVector;
33  import org.indi.reactor.TimerCallback;
34  import org.indi.server.BasicDevice;
35  import org.indi.server.IndiServer;
36  
37  /**
38   * A simple CCD simulator. A .fits file is transferred after the given
39   * exposuretime has been expired.
40   * 
41   * @author Dirk Hünniger
42   * 
43   */
44  public class SimpleCCDSimulator extends BasicDevice implements TimerCallback {
45      /**
46       * the vector containing the switch to connect /disconnect the device
47       */
48      private final SwitchVector powerswitch;
49      /**
50       * the name of the powerswitch
51       */
52      private final String powervectorname = "CONNECTION";
53      /**
54       * the name of the only group contained in this device
55       */
56      private final String groupname = "Main Control";
57      /**
58       * the connectswitch used ti connect diconnect the device.
59       */
60      private Switch connectswitch = null;
61      /**
62       * the indivector hosting the temperature property
63       */
64      private NumberVector temperaturevector = null;
65      /**
66       * the temperature of the CCD
67       */
68      private Number temperature = null;
69      /**
70       * the number Vector hosting the exposuretime
71       */
72      private NumberVector exposuretimevector = null;
73      /**
74       * the exposuretime
75       */
76      private Number exposuretime = null;
77      /**
78       * the blobvector hosting the blob to carry the image
79       */
80      private BlobVector imagevector = null;
81      /**
82       * the time between onTimer callbacks in miliseconds
83       */
84      private final long timeout = 1000;
85      /**
86       * the Blob to carry the image to the client after the exposurtime has
87       * expired
88       */
89      private Blob image = null;
90      /**
91       * the requested temperature of the ccd
92       */
93      private double targetTemperature = 0;
94      /**
95       * the name of this device
96       */
97      private final String name = "Simple CCD Simulator";
98  
99      /**
100      * class constructor
101      * 
102      * @param server
103      *                the indi server to host the device
104      */
105     public SimpleCCDSimulator(IndiServer server) {
106 	super(server);
107 	this.powerswitch = new SwitchVector(this.name, this.powervectorname,
108 		"Connection", this.groupname, State.Idle, Permission.ReadWrite,
109 		SwitchRule.OneOfMany, 0);
110 	this.connectswitch = new Switch("CONNECT", "Connect", Switch.State.Off);
111 	this.powerswitch.add(this.connectswitch);
112 	this.powerswitch.add(new Switch("DISCONNECT", "Disconnect",
113 		Switch.State.On));
114 	this.exposuretimevector = new NumberVector(this.name,
115 		"EXPOSE_DURATION", "Expose", this.groupname, State.Idle,
116 		Permission.ReadWrite, 60);
117 	this.exposuretime = new Number("EXPOSE_S", "Duration (s)", "%5.2f", 0.,
118 		36000., .5, 1.);
119 	this.exposuretimevector.add(this.exposuretime);
120 	this.temperaturevector = new NumberVector(this.name, "CCD_TEMPERATURE",
121 		"Temperature (C)", this.groupname, State.Idle,
122 		Permission.ReadWrite, 60);
123 	this.temperature = new Number("TEMPERATURE", "Temperature", "%+06.2f",
124 		-30., 40., 1., 0.);
125 	this.temperaturevector.add(this.temperature);
126 	this.imagevector = new BlobVector(this.name, "Video", "Video",
127 		this.groupname, State.Idle, Permission.ReadOnly, 0);
128 	this.image = new Blob("CCD1", "Feed");
129 	this.imagevector.add(this.image);
130 	timer(this.timeout);
131     }
132 
133     /**
134      * Starts an indi server hosting a ccd simulator and a telescope (mount)
135      * simulator
136      * 
137      * @param args
138      *                Command line parameters (ignored)
139      * @throws IOException
140      */
141     public static void main(String[] args) throws IOException {
142 	IndiServer s = new IndiServer();
143 	new SimpleCCDSimulator(s);
144 	new SimpleTelescopeSimulator(s);
145 	while (true) {
146 	    s.reactor.handleEvents(10);
147 	}
148     }
149 
150     @Override
151     public void onGetProperties(GetProperties o) {
152 	def(this.powerswitch);
153 	def(this.exposuretimevector);
154 	def(this.temperaturevector);
155 	def(this.imagevector);
156     }
157 
158     @Override
159     public void onNew(SwitchVector vector) {
160 	if (!((this.powervectorname.equals(vector.getName())) && (this.name
161 		.equals(vector.getDevice())))) {
162 	    return;
163 	}
164 	this.powerswitch.update(vector);
165 	switch (this.connectswitch.getState()) {
166 	case On:
167 	    this.powerswitch.setState(State.Ok);
168 	    set(this.powerswitch,
169 		    "Connection to Simple CCD Simulator is successful.");
170 	    break;
171 	case Off:
172 	    this.powerswitch.setState(State.Idle);
173 	    set(this.powerswitch, "Simple CCD Simulator has been disconneced.");
174 	    break;
175 	}
176     }
177 
178     @Override
179     public void onNew(NumberVector vector) {
180 	if (!(this.name.equals(this.name))) {
181 	    return;
182 	}
183 	if (vector.getName().equals(this.exposuretimevector.getName())) {
184 	    if (this.connectswitch.getState() == Switch.State.Off) {
185 		this.exposuretimevector.setState(State.Idle);
186 		msg("CCD Simulator is offline");
187 		set(this.exposuretimevector);
188 	    } else {
189 		this.exposuretimevector.setState(State.Busy);
190 		this.exposuretimevector.update(vector);
191 	    }
192 	}
193 	if (vector.getName().equals(this.temperaturevector.getName())) {
194 	    if (this.connectswitch.getState() == Switch.State.Off) {
195 		this.temperaturevector.setState(State.Idle);
196 		msg("CCD Simulator is offline");
197 	    } else {
198 		for (Number n : vector.getChlidren()) {
199 		    if (n.getName().equals(this.temperature.getName())) {
200 			this.targetTemperature = n.getDouble();
201 		    }
202 		}
203 		if (this.targetTemperature == this.temperature.getDouble()) {
204 		    this.temperaturevector.setState(State.Ok);
205 		} else {
206 		    this.temperaturevector.setState(State.Busy);
207 		    msg("Setting CCD temperature to "
208 			    + String.valueOf(this.targetTemperature));
209 		}
210 		set(this.temperaturevector);
211 	    }
212 	}
213     }
214 
215     @Override
216     public void onTimer() {
217 	switch (this.exposuretimevector.getState()) {
218 	case Busy:
219 	    this.exposuretime.subtractDouble(1.0);
220 	    if (this.exposuretime.getDouble() <= 0) {
221 		/* Let's set the state of OK and report that to the client */
222 		this.exposuretimevector.setState(State.Ok);
223 		/* Upload a sample FITS file */
224 		this.image.setValue(Thread.currentThread()
225 			.getContextClassLoader().getResourceAsStream(
226 				"org/indi/examples/Test.fits"), "fits");
227 		set(this.imagevector);
228 	    }
229 	    set(this.exposuretimevector);
230 	    break;
231 	}
232 	switch (this.temperaturevector.getState()) {
233 	case Busy:
234 	    if (this.temperature.getDouble() < this.targetTemperature - 1.0) {
235 		this.temperature.addDouble(1.0);
236 		set(this.temperaturevector);
237 	    } else if (this.temperature.getDouble() > this.targetTemperature + 1.0) {
238 		this.temperature.subtractDouble(1.0);
239 		set(this.temperaturevector);
240 	    } else {
241 		this.temperaturevector.setState(State.Ok);
242 		this.temperature.setDouble(this.targetTemperature);
243 		set(this.temperaturevector, "Target Temperature reached");
244 	    }
245 	    break;
246 	}
247 	timer(this.timeout);
248     }
249 }