1 /*
2 * CelestronTelescope.java
3 *
4 * Copyright (c) 2003, Raben Systems, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * Neither the name of Raben Systems, Inc. nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 package com.raben.telescope.comm;
35 import java.awt.geom.Point2D;
36 import java.io.IOException;
37 import java.util.TimeZone;
38 import java.util.Calendar;
39 import java.util.GregorianCalendar;
40 import java.util.Properties;
41
42 /***
43 * Implementation of the TelescopeInterface for telescopes
44 * manufactured by Celestron (tm)
45 * @author Vern Raben
46 * @version $Revision: 1.2 $
47 *
48 * NOTE - this only hardware this has been tested on at present is
49 * Nexstar 11 GPS, Hand Control Version 2.2 and 2.3 using MS Windows XP
50 * and J2SDK 1.4.1
51 *
52 */
53 public class CelestronTelescope implements TelescopeInterface {
54
55 /*** Serial connection to telescope */
56 private SerialConnection serialConnection = new SerialConnection();
57
58 /*** True character */
59 private static final char TRUE_CHAR = (char) 1;
60
61 /*** Telescope model */
62 private TelescopeModel telescopeModel =
63 TelescopeModel.CELESTRON_NEXSTAR_GPS;
64
65 /*** Standard Celestron commands */
66 private CelestronCommand command = new CelestronCommand();
67
68 /*** Auxiallary Celestron commands */
69 private CelestronAuxillaryCommand auxCommand = null;
70
71 /*** Connection timeout */
72 private long timeOut = 30000L;
73
74 /*** UTC TimeZone */
75 private static final TimeZone TZ = TimeZone.getTimeZone("UTC");
76
77 /*** Conversion from angle to RA */
78 private static final double ANGLE_TO_RA = 360.0 / 24.0;
79
80 /*** Conversion from RA to angle */
81 private static final double RA_TO_ANGLE = 24.0 / 360.0;
82
83 /*** Tracking mode 0=off, 1= azimuth, 2= equ-n, 3=eq-S */
84 private static int trackingMode = 1;
85
86 /*** Creates a new instance of CelestronTelescope */
87 public CelestronTelescope() {
88 }
89
90 /***
91 * Cancel goto command
92 * @exception IOException may occur
93 */
94 public void cancelGoTo() throws IOException {
95 serialConnection.sendString(command.cancelGoTo());
96 serialConnection.receiveString();
97 }
98
99 /***
100 * Get right ascension and declination
101 * @return Point2D May return NaN if coordinate not received
102 * @exception IOException may occur
103 */
104 public Point2D getRightAscensionDeclination() throws IOException {
105 Point2D raDec = new Point2D.Double(Double.NaN, Double.NaN);
106 serialConnection.sendString(command.getRightAscensionDeclination());
107 String response = serialConnection.receiveString();
108 command.decodeHexadecimal(response, raDec);
109 double decl = raDec.getY();
110
111 if (decl > 180.0) {
112 decl -= 360.0;
113 }
114
115 raDec.setLocation(raDec.getX() * RA_TO_ANGLE, decl);
116 return raDec;
117 }
118
119
120 /***
121 * Go to specificied azimuth/altitude coordinate
122 * @param coordinate Point2D
123 * @exception IOException may be thrown
124 */
125 public void goToAzimuthAltitude(Point2D coordinate) throws IOException {
126
127 double azm = coordinate.getX();
128 double alt = coordinate.getY();
129
130 if (alt < 0.0) {
131 alt += 360.0;
132 }
133
134 sendCommand(command.goToAzimuthAltitude(azm, alt));
135 serialConnection.receiveString(); // ISSUE - do all models ack with #
136 }
137
138 /***
139 * Go to specified right ascension/declination coordinate
140 * @param coordinate Point2D
141 * @exception IOException may occur
142 */
143 public void goToRightAscensionDeclination(Point2D coordinate)
144 throws IOException {
145 sendCommand(command.goToRightAscensionDeclination(
146 (coordinate.getX() * ANGLE_TO_RA), coordinate.getY()));
147 serialConnection.receiveString(); // ISSUE - do all models ack with #
148 }
149
150 /***
151 * Send command to the communications port
152 * @param cmd The command string
153 * @exception IOException may occur
154 */
155 private void sendCommand(String cmd) throws IOException {
156
157 if ((cmd != null) && (cmd.length() > 0)) {
158
159 if ((TelescopeModel.CELESTRON_NEXSTAR_OGT.equals(telescopeModel))
160 || (TelescopeModel.CELESTRON_NEXSTAR_5_8.equals(
161 telescopeModel))) {
162 sendInitializeCommand();
163 serialConnection.sendString(cmd);
164 } else {
165 serialConnection.sendString(cmd);
166 }
167 }
168
169 }
170
171 /***
172 * Send command to the communication port
173 * @param cmd Character array containing command
174 * @exception IOException may occur
175 */
176 private void sendCommand(char[] cmd) throws IOException {
177 if ((cmd != null) && (cmd.length > 0)) {
178 serialConnection.sendChars(cmd);
179 }
180 }
181
182
183
184 /***
185 * Get azimuth and altitude coordinate
186 * @return Current azimuth altitude coordinate
187 * @exception IOException may occur
188 */
189 public Point2D getAzimuthAltitude() throws IOException {
190 sendCommand(command.getAzimuthAltitude());
191 Point2D azmAlt = new Point2D.Double(Double.NaN, Double.NaN);
192 String response = serialConnection.receiveString();
193 command.decodeHexadecimal(response, azmAlt);
194
195 if (azmAlt.getY() > 180.0) {
196 azmAlt.setLocation(azmAlt.getX(), azmAlt.getY() - 360.0);
197 }
198
199 return azmAlt;
200 }
201
202 /***
203 * Check whether or not telescope is aligned
204 * @return true if aligned, false otherwise
205 * @exception IOException may occur
206 */
207 public boolean isAligned() throws IOException {
208 boolean aligned = false;
209 sendCommand(command.alignmentComplete());
210 char[] response = serialConnection.receiveChars();
211
212 if ((response != null) && (response.length == 2)) {
213
214 if (response[0] == TRUE_CHAR) {
215 aligned = true;
216 } else {
217 aligned = false;
218 }
219
220 }
221
222 return aligned;
223 }
224
225 /***
226 * Check if communication with telescope is established
227 * @return true if communicating, false otherwise
228 * @exception IOException may occur
229 */
230 public boolean isCommunicating() throws IOException {
231 boolean communicating = false;
232
233 if ((serialConnection != null) && (serialConnection.isOpen())) {
234 serialConnection.sendString("Kx");
235 String response = serialConnection.receiveString();
236
237 if ("x#".equals(response)) {
238 communicating = true;
239 }
240 }
241
242 return communicating;
243 }
244
245 /***
246 * Check whether telescope is slewing to new coordinate
247 * @return true if telescope is slewing, false otherwise
248 * @exception IOException may occur
249 */
250 public boolean isSlewing() throws IOException {
251 boolean slewing = false;
252
253 serialConnection.sendString("L");
254 char[] response = serialConnection.receiveChars();
255
256 if ((response != null) && (response.length == 2)) {
257 if (response[0] == '1') {
258 slewing = true;
259 }
260 }
261
262 return slewing;
263 }
264
265 /***
266 * Close connection to telescope
267 */
268 public void close() {
269
270 if (serialConnection != null) {
271 serialConnection.closeConnection();
272 }
273 }
274
275
276 /***
277 * Get control unit version
278 * @return version
279 * @exception IOException may occur
280 */
281 public String getHandControlVersion() throws IOException {
282
283 int versionVal = 0;
284 serialConnection.sendString("V");
285 String response = serialConnection.receiveString();
286
287 if (response.length() > 0) {
288 for (int i = response.length() - 2; i >= 0; i--) {
289
290 switch(i) {
291 case 1: versionVal += 10 * (int) response.charAt(i);
292 break;
293 case 0: versionVal += (int) response.charAt(i);
294 break;
295 }
296
297 }
298 }
299
300 return String.valueOf(versionVal);
301 }
302
303 /***
304 * Initialize connection to telescope
305 * @exception IOException may be thrown
306 */
307 public void connect() throws IOException {
308 serialConnection.openConnection();
309 }
310
311 /***
312 * Check if connection is open
313 * @return True if connection is open
314 */
315 public boolean isConnected() {
316 return serialConnection.isOpen();
317 }
318
319 /***
320 * Set tracking mode
321 * Must be aligned to switch from off to alt-az*
322 * @param mode (0=tracking off,1=Alt-Az tracking,2=Eq-North,3=Eq-South
323 * @exception IOException may be thrown
324 */
325 public void setTrackingMode(int mode) throws IOException {
326 String cmd = command.trackingMode(mode);
327
328 if ((cmd != null) && (cmd.length() > 0)) {
329 setDebug(true);
330 serialConnection.sendString(cmd);
331 serialConnection.receiveString();
332 }
333 }
334
335
336 /***
337 * Get telescope geographic coordinate from GPS interface
338 * @return Geographic coordinate of telescope in degrees
339 * @exception IOException may occur
340 */
341 public Point2D getGpsCoordinate() throws IOException {
342 double longitude = Double.NaN;
343 double latitude = Double.NaN;
344
345 if (auxCommand != null) {
346 sendCommand(auxCommand.gpsLongitudeCommand());
347 char[] retVal = serialConnection.receiveChars();
348 longitude = auxCommand.decodeGpsCoordinate(retVal);
349 sendCommand(auxCommand.gpsLatitudeCommand());
350 retVal = serialConnection.receiveChars();
351 latitude = auxCommand.decodeGpsCoordinate(retVal);
352 }
353
354 return new Point2D.Double(longitude, latitude);
355 }
356
357
358 /***
359 * Get Date and Time from GPS interface
360 * @return Calendar set to GPS date/time
361 * @exception IOException may occur
362 */
363 public Calendar getGpsDateTime() throws IOException {
364 int mo = 0;
365 int da = 0;
366 int yr = 0;
367 int hr = 0;
368 int min = 0;
369 int sec = 0;
370 Calendar cal = new GregorianCalendar(TZ);
371
372 if (auxCommand != null) {
373
374 // Get year
375 sendCommand(auxCommand.gpsYearCommand());
376 char[] retVal = serialConnection.receiveChars();
377
378 if ((retVal != null) && (retVal.length == 3)) {
379 yr = (retVal[0] << 8) | (retVal[1]);
380 }
381
382 // Get mo and day
383 sendCommand(auxCommand.gpsDateCommand());
384 retVal = serialConnection.receiveChars();
385
386 if ((retVal != null) && (retVal.length == 3)) {
387 mo = (int) (retVal[0]) - 1;
388 da = (int) retVal[1];
389 }
390
391 // Get hr, min, sec
392 sendCommand(auxCommand.gpsTimeCommand());
393 retVal = serialConnection.receiveChars();
394
395 if ((retVal != null) && (retVal.length == 4)) {
396 hr = retVal[0];
397 min = retVal[1];
398 sec = retVal[2];
399 }
400 }
401
402 cal.set(yr, mo, da, hr, min, sec);
403 return cal;
404 }
405
406
407 /***
408 * Check if GPS is linked
409 * @return True if GPS is linked, false otherwise
410 * @exception IOException may occur
411 */
412 public boolean isGpsLinked() throws IOException {
413 boolean linked = false;
414
415 if (auxCommand != null) {
416 sendCommand(auxCommand.gpsLinkedCommand());
417
418 char[] chars = serialConnection.receiveChars();
419
420 if ((chars != null) && (chars.length == 2)) {
421 if (chars[0] == TRUE_CHAR) {
422 linked = true;
423 } else {
424 linked = false;
425 }
426 }
427 }
428
429 return linked;
430 }
431
432
433 /***
434 * Set azimuth tracking rate
435 * Note - tracking will return to default in approximately 20 seconds
436 * unless tracking is turned off @see setTrackingMode
437 * @param trackRate in arc-sec/sec
438 * @exception IOException may occur
439 */
440 public void setAzimuthTrackingRate(int trackRate) throws IOException {
441 if (auxCommand != null) {
442 sendCommand(auxCommand.azimuthTrackingRateCommand(trackRate));
443 String retVal = serialConnection.receiveString();
444 }
445 }
446
447 /*** Set altitude tracking rate
448 * Note - tracking will return to default in approximately 20 seconds
449 * unless tracking is turned off @see setTrackingMode
450 * @param trackRate in arc-sec/sec
451 * @exception IOException may occur
452 */
453 public void setAltitudeTrackingRate(int trackRate) throws IOException {
454 if (auxCommand != null) {
455 sendCommand(auxCommand.altitudeTrackingRateCommand(trackRate));
456 String retVal = serialConnection.receiveString();
457 }
458 }
459
460 /***
461 * Get port being used
462 * @return String (default is COM1)
463 */
464 private String getPortName() {
465 return serialConnection.getPortName();
466 }
467
468 /***
469 * Set port to use for connection
470 * @param portName Name of port (default is COM1)
471 *
472 */
473 private void setPortName(String portName) {
474 serialConnection.setPortName(portName);
475 }
476
477 /***
478 * Send an initialize command and wait for 1/4 second
479 * Used by original Nexstar GT, Nexstar 5/8
480 * @exception IOException may occur
481 */
482 private void sendInitializeCommand() throws IOException {
483 serialConnection.sendString("?");
484
485 try {
486 Thread.sleep(250L);
487 } catch (InterruptedException e) {
488 // ignore
489 }
490 }
491
492
493 /***
494 * Get telescope model
495 * @return TelescopeModel
496 */
497 public TelescopeModel getTelescopeModel() {
498 return command.getTelescopeModel();
499 }
500
501
502 /***
503 * Set the telescope model
504 * @param model of telescope @see TelescopeModel
505 * ISSUE - Generic Celestron telescope not yet implemented
506 */
507 public void setTelescopeModel(TelescopeModel model) {
508
509 if (model != null) {
510
511 if (TelescopeModel.CELESTRON.equals(model)) {
512 model = determineTelescopeModel();
513 }
514
515 command.setTelescopeModel(model);
516
517 // Enable auxillary commands if capable
518 if ((TelescopeModel.CELESTRON_ASC.equals(model))
519 || (TelescopeModel.CELESTRON_CGE.equals(model))
520 || (TelescopeModel.CELESTRON_NEXSTAR_GPS.equals(model))) {
521
522 // ISSUE - should probably check version first
523 auxCommand = new CelestronAuxillaryCommand();
524 }
525 }
526
527 }
528
529 /***
530 * Send commands to scope to determine specific model
531 * @return TelescopeModel
532 * ISSUE - not yet implemented
533 */
534 private TelescopeModel determineTelescopeModel() {
535 return TelescopeModel.CELESTRON_NEXSTAR_GPS;
536 }
537
538 /***
539 * String describing telescope
540 * @return String
541 */
542 public String toString() {
543 StringBuffer buf = new StringBuffer(getClass().getName());
544 buf.append("[");
545 buf.append("telescopeModel=");
546 buf.append(telescopeModel.toString());
547 buf.append("]");
548 return buf.toString();
549 }
550
551 /***
552 * Get telescope properties
553 * @return Telescope properties
554 */
555 public java.util.Properties getProperties() {
556 Properties props = new Properties();
557 props.setProperty(ScopeKey.MODEL, telescopeModel.toString());
558 props.setProperty(ScopeKey.PORT, serialConnection.getPortName());
559 props.setProperty(ScopeKey.DEBUG, String.valueOf(isDebug()));
560 return props;
561 }
562
563 /***
564 * Set telescope properties
565 * @param props Properties for setting up telescope such as comm port,
566 * and debug. Supported keys are
567 * com.raben.telescope.port
568 * com.raben.telescope.debug
569 */
570 public void setProperties(java.util.Properties props) {
571 String port = props.getProperty(ScopeKey.PORT, "COM1");
572 setPortName(port);
573 String debugStr = props.getProperty(ScopeKey.DEBUG);
574
575 if (debugStr != null) {
576 if ("true".equals(debugStr)) {
577 serialConnection.setDebug(true);
578 } else {
579 serialConnection.setDebug(false);
580 }
581 }
582 }
583
584 /*** Get debug flag
585 * @return True if in debug mode, false otherwise
586 */
587 public boolean isDebug() {
588 return serialConnection.isDebug();
589 }
590
591 /*** Set debug flag
592 * @param debug flag
593 */
594 public void setDebug(boolean debug) {
595 serialConnection.setDebug(debug);
596 }
597
598 public void moveInAzimuth(boolean direction, int rate) throws IOException {
599 System.out.println("moveInAzimuth direction = "+direction+" rate="+rate);
600 sendCommand(auxCommand.azimuthMoveCommand(direction, rate));
601 }
602
603 public void moveInAltitude(boolean direction, int rate) throws IOException {
604 System.out.println("moveInAltitude");
605 char[] cmd = auxCommand.altitudeMoveCommand(direction, rate);
606
607 if (cmd != null) {
608 System.out.println(SerialConnection.displayCharArrayAsHexString(cmd));
609 }
610 else {
611 System.out.println("cmd is null");
612 }
613
614 sendCommand(auxCommand.altitudeMoveCommand(direction, rate));
615 }
616
617 }
618
This page was automatically generated by Maven