1 /*
2  * Stellarium Telescope Control Plug-in
3  *
4  * Copyright (C) 2006 Johannes Gajdosik
5  * Copyright (C) 2009 Bogdan Marinov
6  *
7  * This module was originally written by Johannes Gajdosik in 2006
8  * as a core module of Stellarium. In 2009 it was significantly extended with
9  * GUI features and later split as an external plug-in module by Bogdan Marinov.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
24  */
25 
26 #ifndef TELESCOPECLIENT_HPP
27 #define TELESCOPECLIENT_HPP
28 
29 #include <QHostAddress>
30 #include <QHostInfo>
31 #include <QList>
32 #include <QString>
33 #include <QTcpSocket>
34 #include <QObject>
35 
36 #include "StelApp.hpp"
37 #include "StelObject.hpp"
38 #include "common/InterpolatedPosition.hpp"
39 
40 class StelCore;
41 
42 qint64 getNow(void);
43 
44 enum Equinox {
45 	EquinoxJ2000,
46 	EquinoxJNow
47 };
48 
49 //! An abstract base class that should never be used directly, only inherited.
50 //! This class used to be called Telescope, but it has been renamed
51 //! to TelescopeClient in order to resolve a compiler/linker conflict
52 //! with the identically named Telescope class in Stellarium's main code.
53 class TelescopeClient : public QObject, public StelObject
54 {
55 	Q_OBJECT
56 public:
57 	static const QString TELESCOPECLIENT_TYPE;
58 	static TelescopeClient *create(const QString &url);
~TelescopeClient(void)59 	virtual ~TelescopeClient(void) Q_DECL_OVERRIDE {}
60 
61 	// Method inherited from StelObject
getEnglishName(void) const62 	QString getEnglishName(void) const Q_DECL_OVERRIDE {return name;}
getNameI18n(void) const63 	QString getNameI18n(void) const Q_DECL_OVERRIDE {return nameI18n;}
getInfoColor(void) const64 	Vec3f getInfoColor(void) const Q_DECL_OVERRIDE
65 	{
66 		return Vec3f(1.f, 1.f, 1.f);
67 	}
68 	//! TelescopeClient supports the following InfoStringGroup flags:
69 	//! - Name
70 	//! - RaDecJ2000
71 	//! - RaDec
72 	//! - PlainText
73 	//! @param core the StelCore object
74 	//! @param flags a set of InfoStringGroup items to include in the return value.
75 	//! @return a QString containing an HMTL encoded description of the Telescope.
76 	QString getInfoString(const StelCore* core, const InfoStringGroup& flags) const Q_DECL_OVERRIDE;
getType(void) const77 	QString getType(void) const Q_DECL_OVERRIDE {return TELESCOPECLIENT_TYPE;}
getID() const78 	QString getID() const Q_DECL_OVERRIDE {return name;}
getAngularSize(const StelCore *) const79 	virtual double getAngularSize(const StelCore*) const Q_DECL_OVERRIDE {Q_ASSERT(0); return 0;}	// TODO
80 
81 	// Methods specific to telescope
82 	virtual void telescopeGoto(const Vec3d &j2000Pos, StelObjectP selectObject) = 0;
83 	virtual void telescopeSync(const Vec3d &j2000Pos, StelObjectP selectObject) = 0;
telescopeAbortSlew()84 	virtual void telescopeAbortSlew() {}
85 
86 	//!
87 	//! \brief move
88 	//! \param angle [0,360)
89 	//! \param speed [0,1]
90 	//!
91 	virtual void move(double angle, double speed);
92 	virtual bool isConnected(void) const = 0;
93 	virtual bool hasKnownPosition(void) const = 0;
addOcular(double fov)94 	void addOcular(double fov) {if (fov>=0.0) oculars.push_back(fov);}
getOculars(void) const95 	const QList<double> &getOculars(void) const {return oculars;}
96 
prepareCommunication()97 	virtual bool prepareCommunication() {return false;}
performCommunication()98 	virtual void performCommunication() {}
99 
createControlWidget(QSharedPointer<TelescopeClient> telescope,QWidget * parent=Q_NULLPTR) const100 	virtual QWidget* createControlWidget(QSharedPointer<TelescopeClient> telescope, QWidget* parent = Q_NULLPTR) const { Q_UNUSED(telescope) Q_UNUSED(parent) return Q_NULLPTR; }
101 
102 protected:
103 	TelescopeClient(const QString &name);
104 	QString nameI18n;
105 	const QString name;
106 
getTelescopeInfoString(const StelCore * core,const InfoStringGroup & flags) const107 	virtual QString getTelescopeInfoString(const StelCore* core, const InfoStringGroup& flags) const
108 	{
109 		Q_UNUSED(core)
110 		Q_UNUSED(flags)
111 		return QString();
112 	}
113 private:
isInitialized(void) const114 	virtual bool isInitialized(void) const {return true;}
getSelectPriority(const StelCore * core) const115 	float getSelectPriority(const StelCore* core) const Q_DECL_OVERRIDE {Q_UNUSED(core); return -10.f;}
116 private:
117 	QList<double> oculars; // fov of the oculars
118 };
119 
120 //! Example Telescope class. A physical telescope does not exist.
121 //! This can be used as a starting point for implementing a derived
122 //! Telescope class.
123 //! This class used to be called TelescopeDummy, but it had to be renamed
124 //! in order to resolve a compiler/linker conflict with the identically named
125 //! TelescopeDummy class in Stellarium's main code.
126 class TelescopeClientDummy : public TelescopeClient
127 {
128 public:
TelescopeClientDummy(const QString & name,const QString &)129 	TelescopeClientDummy(const QString &name, const QString &) : TelescopeClient(name)
130 	{
131 		desired_pos[0] = XYZ[0] = 1.0;
132 		desired_pos[1] = XYZ[1] = 0.0;
133 		desired_pos[2] = XYZ[2] = 0.0;
134 	}
~TelescopeClientDummy(void)135 	~TelescopeClientDummy(void) Q_DECL_OVERRIDE {}
isConnected(void) const136 	bool isConnected(void) const Q_DECL_OVERRIDE
137 	{
138 		return true;
139 	}
prepareCommunication(void)140 	bool prepareCommunication(void) Q_DECL_OVERRIDE
141 	{
142 		XYZ = XYZ * 31.0 + desired_pos;
143 		const double lq = XYZ.lengthSquared();
144 		if (lq > 0.0)
145 			XYZ *= (1.0/std::sqrt(lq));
146 		else
147 			XYZ = desired_pos;
148 		return true;
149 	}
telescopeGoto(const Vec3d & j2000Pos,StelObjectP selectObject)150 	void telescopeGoto(const Vec3d &j2000Pos, StelObjectP selectObject) Q_DECL_OVERRIDE
151 	{
152 		Q_UNUSED(selectObject)
153 		desired_pos = j2000Pos;
154 		desired_pos.normalize();
155 	}
telescopeSync(const Vec3d & j2000Pos,StelObjectP selectObject)156 	void telescopeSync(const Vec3d &j2000Pos, StelObjectP selectObject) Q_DECL_OVERRIDE
157 	{
158 		Q_UNUSED(selectObject)
159 		Q_UNUSED(j2000Pos)
160 	}
hasKnownPosition(void) const161 	bool hasKnownPosition(void) const Q_DECL_OVERRIDE
162 	{
163 		return true;
164 	}
getJ2000EquatorialPos(const StelCore *) const165 	Vec3d getJ2000EquatorialPos(const StelCore*) const Q_DECL_OVERRIDE
166 	{
167 		return XYZ;
168 	}
169 
170 private:
171 	Vec3d XYZ; // j2000 position
172 	Vec3d desired_pos;
173 };
174 
175 //! This TelescopeClient class can control a telescope by communicating
176 //! to a server process ("telescope server") via
177 //! the "Stellarium telescope control protocol" over TCP/IP.
178 //! The "Stellarium telescope control protocol" is specified in a separate
179 //! document along with the telescope server software.
180 class TelescopeTCP : public TelescopeClient
181 {
182 	Q_OBJECT
183 public:
184 	TelescopeTCP(const QString &name, const QString &params, Equinox eq = EquinoxJ2000);
~TelescopeTCP(void)185 	~TelescopeTCP(void) Q_DECL_OVERRIDE
186 	{
187 		hangup();
188 	}
isConnected(void) const189 	bool isConnected(void) const Q_DECL_OVERRIDE
190 	{
191 		//return (tcpSocket->isValid() && !wait_for_connection_establishment);
192 		return (tcpSocket->state() == QAbstractSocket::ConnectedState);
193 	}
194 
195 private:
196 	Vec3d getJ2000EquatorialPos(const StelCore* core=Q_NULLPTR) const Q_DECL_OVERRIDE;
197 	bool prepareCommunication() Q_DECL_OVERRIDE;
198 	void performCommunication() Q_DECL_OVERRIDE;
199 	void telescopeGoto(const Vec3d &j2000Pos, StelObjectP selectObject) Q_DECL_OVERRIDE;
200 	void telescopeSync(const Vec3d &j2000Pos, StelObjectP selectObject) Q_DECL_OVERRIDE;
isInitialized(void) const201 	bool isInitialized(void) const Q_DECL_OVERRIDE
202 	{
203 		return (!address.isNull());
204 	}
205 	void performReading(void);
206 	void performWriting(void);
207 
208 private:
209 	void hangup(void);
210 	QHostAddress address;
211 	quint16 port;
212 	QTcpSocket * tcpSocket;
213 	bool wait_for_connection_establishment;
214 	qint64 end_of_timeout;
215 	char readBuffer[120];
216 	char *readBufferEnd;
217 	char writeBuffer[120];
218 	char *writeBufferEnd;
219 	int time_delay;
220 
221 	InterpolatedPosition interpolatedPosition;
hasKnownPosition(void) const222 	virtual bool hasKnownPosition(void) const Q_DECL_OVERRIDE
223 	{
224 		return interpolatedPosition.isKnown();
225 	}
226 
227 	Equinox equinox;
228 
229 private slots:
230 	void socketConnected(void);
231 	void socketFailed(QAbstractSocket::SocketError socketError);
232 };
233 
234 #endif // TELESCOPECLIENT_HPP
235