Telescope.cpp   Telescope.cpp 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA.
*/ */
#include "Telescope.hpp" #include "Telescope.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
#include "StelTranslator.hpp" #include "StelTranslator.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include <sstream> #include <cmath>
#include <iomanip>
#include <math.h>
#include <QTextStream>
#include <QString>
#include <QStringList>
#include <QRegExp>
#include <QDebug> #include <QDebug>
#include <QHostAddress>
#include <QHostInfo>
#include <QRegExp>
#include <QString>
#include <QTcpSocket>
#include <QTextStream>
#ifdef WIN32 #ifdef Q_OS_WIN
#include <windows.h> // GetSystemTimeAsFileTime #include <windows.h> // GetSystemTimeAsFileTime()
#include <winsock2.h>
#define ERRNO WSAGetLastError()
#define STRERROR(x) x
#undef EAGAIN
#define EAGAIN WSAEWOULDBLOCK
#undef EINTR
#define EINTR WSAEINTR
#undef EINPROGRESS
#define EINPROGRESS WSAEINPROGRESS
static u_long ioctlsocket_arg = 1;
#define SET_NONBLOCKING_MODE(s) ioctlsocket(s,FIONBIO,&ioctlsocket_a
rg)
#define SOCKLEN_T int
#define close closesocket
#define IS_INVALID_SOCKET(fd) (fd==INVALID_SOCKET)
#else #else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h> // strerror
#define ERRNO errno
#define STRERROR(x) strerror(x)
#define SET_NONBLOCKING_MODE(s) fcntl(s,F_SETFL,O_NONBLOCK)
#define SOCKLEN_T socklen_t
#define SOCKET int
#define IS_INVALID_SOCKET(fd) (fd<0)
#define INVALID_SOCKET (-1)
#endif #endif
using namespace std; //! Example Telescope class. A physical telescope does not exist.
//! This can be used as a starting point for implementing a derived
struct PrintRaDec //! Telescope class.
{
PrintRaDec(const unsigned int ra_int,const int dec_int) : ra_int(ra_
int),dec_int(dec_int) {}
const unsigned int ra_int;
const int dec_int;
};
template<class T>
T &operator<<(T &o,const PrintRaDec &x)
{
unsigned int h = x.ra_int;
int d = (int)floor(0.5+x.dec_int*(360*3600*1000/4294967296.0));
char dec_sign;
if (d >= 0)
{
if (d > 90*3600*1000)
{
d = 180*3600*1000 - d;
h += 0x80000000;
}
dec_sign = '+';
}
else
{
if (d < -90*3600*1000)
{
d = -180*3600*1000 - d;
h += 0x80000000;
}
d = -d;
dec_sign = '-';
}
h = (unsigned int)floor(0.5+h*(24*3600*10000/4294967296.0));
const int ra_ms = h % 10000;
h /= 10000;
const int ra_s = h % 60;
h /= 60;
const int ra_m = h % 60;
h /= 60;
h %= 24;
const int dec_ms = d % 1000;
d /= 1000;
const int dec_s = d % 60;
d /= 60;
const int dec_m = d % 60;
d /= 60;
o << "ra = "
<< setfill(' ') << setw(2) << h << 'h'
<< setfill('0') << setw(2) << ra_m << 'm'
<< setfill('0') << setw(2) << ra_s << '.'
<< setfill('0') << setw(4) << ra_ms
<< " dec = "
<< ((d<10)?" ":"") << dec_sign << d << 'd'
<< setfill('0') << setw(2) << dec_m << 'm'
<< setfill('0') << setw(2) << dec_s << '.'
<< setfill('0') << setw(3) << dec_ms
<< setfill(' ');
return o;
}
class TelescopeDummy : public Telescope class TelescopeDummy : public Telescope
{ {
//! example Telescope class. A physical telescope does not exist.
//! This can be used as a starting point for implementing a derived
//! Telescope class.
public: public:
TelescopeDummy(const QString &name,const QString &params) : Telescop e(name) TelescopeDummy(const QString &name,const QString &params) : Telescop e(name)
{ {
desired_pos[0] = XYZ[0] = 1.0; desired_pos[0] = XYZ[0] = 1.0;
desired_pos[1] = XYZ[1] = 0.0; desired_pos[1] = XYZ[1] = 0.0;
desired_pos[2] = XYZ[2] = 0.0; desired_pos[2] = XYZ[2] = 0.0;
} }
private: private:
bool isConnected(void) const bool isConnected(void) const
{ {
return true; return true;
} }
bool hasKnownPosition(void) const bool hasKnownPosition(void) const
{ {
return true; return true;
} }
Vec3d getJ2000EquatorialPos(const StelNavigator *nav=0) const Vec3d getJ2000EquatorialPos(const StelNavigator *nav=0) const
{ {
return XYZ; return XYZ;
} }
void prepareSelectFds(fd_set&,fd_set&,int&) bool prepareCommunication()
{ {
XYZ = XYZ*31.0+desired_pos; XYZ = XYZ*31.0+desired_pos;
const double lq = XYZ.lengthSquared(); const double lq = XYZ.lengthSquared();
if (lq > 0.0) XYZ *= (1.0/sqrt(lq)); if (lq > 0.0) XYZ *= (1.0/sqrt(lq));
else XYZ = desired_pos; else XYZ = desired_pos;
return true;
} }
void telescopeGoto(const Vec3d &j2000Pos) void telescopeGoto(const Vec3d &j2000Pos)
{ {
desired_pos = j2000Pos; desired_pos = j2000Pos;
desired_pos.normalize(); desired_pos.normalize();
} }
Vec3d XYZ; // j2000 position Vec3d XYZ; // j2000 position
Vec3d desired_pos; Vec3d desired_pos;
}; };
class TelescopeTcp : public Telescope
{
//! This Telescope class can controll a telescope by communicating
//! to a server process ("telescope server") via
//! the "Stellarium telescope control protocol" over TCP/IP.
//! The "Stellarium telescope control protocol" is specified in a seperat
e
//! document along with the telescope server software.
public:
TelescopeTcp(const QString &name,const QString &params);
~TelescopeTcp(void)
{
hangup();
}
private:
bool isConnected(void) const
{
return (!IS_INVALID_SOCKET(fd) && !wait_for_connection_estab
lishment);
}
Vec3d getJ2000EquatorialPos(const StelNavigator *nav=0) const;
void prepareSelectFds(fd_set &read_fds,fd_set &write_fds,int &fd_max
);
void handleSelectFds(const fd_set &read_fds,const fd_set &write_fds)
;
void telescopeGoto(const Vec3d &j2000Pos);
bool isInitialized(void) const
{
return (ntohs(address.sin_port)!=0);
}
void performReading(void);
void performWriting(void);
private:
void hangup(void);
struct sockaddr_in address;
SOCKET fd;
bool wait_for_connection_establishment;
long long int end_of_timeout;
char read_buff[120];
char *read_buff_end;
char write_buff[120];
char *write_buff_end;
int time_delay;
struct Position
{
long long int server_micros;
long long int client_micros;
Vec3d pos;
int status;
};
Position positions[16];
Position *position_pointer;
Position *const end_position;
virtual bool hasKnownPosition(void) const
{
return (position_pointer->client_micros!=0x7FFFFFFFFFFFFFFFL
L);
}
};
Telescope *Telescope::create(const QString &url) Telescope *Telescope::create(const QString &url)
{ {
// example url: My_first_telescope:TCP:localhost:10000:500000 // example url: My_first_telescope:TCP:localhost:10000:500000
// split to: // split to:
// name = My_first_telescope // name = My_first_telescope
// type = TCP // type = TCP
// params = localhost:10000:500000 // params = localhost:10000:500000
// //
// The params part is optional. We will use QRegExp to validate // The params part is optional. We will use QRegExp to validate
// the url and extact the components. // the url and extact the components.
skipping to change at line 256 skipping to change at line 112
params = recRx.capturedTexts().at(4).trimmed(); params = recRx.capturedTexts().at(4).trimmed();
} }
else else
{ {
qWarning() << "WARNING - telescope definition" << url << "no t recognised"; qWarning() << "WARNING - telescope definition" << url << "no t recognised";
return NULL; return NULL;
} }
qDebug() << "Creating telescope" << url << "; name/type/params:" << name << type << params; qDebug() << "Creating telescope" << url << "; name/type/params:" << name << type << params;
Telescope *rval = 0; Telescope * newTelescope = 0;
if (type == "Dummy") if (type == "Dummy")
{ {
rval = new TelescopeDummy(name,params); newTelescope = new TelescopeDummy(name,params);
} }
else if (type == "TCP") else if (type == "TCP")
{ {
rval = new TelescopeTcp(name,params); newTelescope = new TelescopeTcp(name,params);
} }
else else
{ {
qWarning() << "WARNING - unknown telescope type" << type << "- not creating a telescope object for url" << url; qWarning() << "WARNING - unknown telescope type" << type << "- not creating a telescope object for url" << url;
} }
if (rval && !rval->isInitialized()) if (newTelescope && !newTelescope->isInitialized())
{ {
delete rval; delete newTelescope;
rval = 0; newTelescope = 0;
} }
return rval; return newTelescope;
} }
Telescope::Telescope(const QString &name) : name(name) Telescope::Telescope(const QString &name) : name(name)
{ {
nameI18n = name; nameI18n = name;
} }
QString Telescope::getInfoString(const StelCore* core, const InfoStringGrou p& flags) const QString Telescope::getInfoString(const StelCore* core, const InfoStringGrou p& flags) const
{ {
QString str; QString str;
skipping to change at line 298 skipping to change at line 154
oss << "<h2>" << nameI18n << "</h2>"; oss << "<h2>" << nameI18n << "</h2>";
} }
oss << getPositionInfoString(core, flags); oss << getPositionInfoString(core, flags);
postProcessInfoString(str, flags); postProcessInfoString(str, flags);
return str; return str;
} }
long long int GetNow(void) //! returns the current system time in microseconds since the Epoch
qint64 getNow(void)
{ {
#ifdef WIN32 // At the moment this can't be done in a platform-independent way with Qt
// (QDateTime and QTime don't support microsecond precision)
#ifdef Q_OS_WIN
FILETIME file_time; FILETIME file_time;
GetSystemTimeAsFileTime(&file_time); GetSystemTimeAsFileTime(&file_time);
return (*((__int64*)(&file_time))/10) - 86400000000LL*134774; return (*((__int64*)(&file_time))/10) - 86400000000LL*134774;
#else #else
struct timeval tv; struct timeval tv;
gettimeofday(&tv,0); gettimeofday(&tv,0);
return tv.tv_sec * 1000000LL + tv.tv_usec; return tv.tv_sec * 1000000LL + tv.tv_usec;
#endif #endif
} }
TelescopeTcp::TelescopeTcp(const QString &name,const QString &params) : Tel escope(name),fd(INVALID_SOCKET), TelescopeTcp::TelescopeTcp(const QString &name,const QString &params) : Tel escope(name), tcpSocket(new QTcpSocket()),
end_position(positions+(sizeof(positions)/sizeof(positions[0 ]))) end_position(positions+(sizeof(positions)/sizeof(positions[0 ])))
{ {
hangup(); hangup();
address.sin_port = htons(0);
// Example params: // Example params:
// localhost:10000:500000 // localhost:10000:500000
// split into: // split into:
// host = localhost // host = localhost
// port = 10000 (int) // port = 10000 (int)
// time_delay = 500000 (int) // time_delay = 500000 (int)
QRegExp paramRx("^([^:]*):(\\d+):(\\d+)$"); QRegExp paramRx("^([^:]*):(\\d+):(\\d+)$");
QString host; QString host;
int port;
if (paramRx.exactMatch(params)) if (paramRx.exactMatch(params))
{ {
// I will not use the ok param to toInt as the // I will not use the ok param to toInt as the
// QRegExp only matches valid integers. // QRegExp only matches valid integers.
host = paramRx.capturedTexts().at(1).trimmed(); host = paramRx.capturedTexts().at(1).trimmed();
port = paramRx.capturedTexts().at(2).toInt(); port = paramRx.capturedTexts().at(2).toInt();
time_delay = paramRx.capturedTexts().at(3).toInt(); time_delay = paramRx.capturedTexts().at(3).toInt();
} }
else else
{ {
qWarning() << "WARNING - incorrect TelescopeTcp parameters"; qWarning() << "WARNING - incorrect TelescopeTcp parameters";
return; return;
} }
qDebug() << "TelescopeTcp paramaters host, port, time_delay:" << hos t << port << time_delay; qDebug() << "TelescopeTcp paramaters host, port, time_delay:" << hos t << port << time_delay;
if (port<=0 || port>0xFFFF) if (port <= 0 || port > 0xFFFF)
{ {
qWarning() << "ERROR creating TelescopeTcp - port not valid (should be less than 32767)"; qWarning() << "ERROR creating TelescopeTcp - port not valid (should be less than 32767)";
return; return;
} }
if (time_delay<=0 || time_delay>10000000)
if (time_delay <= 0 || time_delay > 10000000)
{ {
qWarning() << "ERROR creating TelescopeTcp - time_delay not valid (should be less than 10000000)"; qWarning() << "ERROR creating TelescopeTcp - time_delay not valid (should be less than 10000000)";
return; return;
} }
struct hostent *hep = gethostbyname(host.toLocal8Bit());
if (hep == 0) //BM: TODO: This may cause some delay when there are more telescopes
{ QHostInfo info = QHostInfo::fromName(host);
qDebug() << "ERROR creating TelescopeTcp - unknown host" << if (info.error())
host;
return;
}
if (hep->h_length != 4)
{ {
qDebug() << "ERROR creating TelescopeTcp - host address is n ot IPv4"; qDebug() << "ERROR creating TelescopeTcp: error looking up h ost " << host << ":\n" << info.errorString();
return; return;
} }
memset(&address,0,sizeof(struct sockaddr_in)); //BM: is info.addresses().isEmpty() if there's no error?
memcpy(&(address.sin_addr),hep->h_addr,4); address = info.addresses().first();
address.sin_port = htons(port);
address.sin_family = AF_INET;
end_of_timeout = -0x8000000000000000LL; end_of_timeout = -0x8000000000000000LL;
for (position_pointer = positions; position_pointer < end_position; resetPositions();
position_pointer++)
{ connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this
position_pointer->server_micros = 0x7FFFFFFFFFFFFFFFLL; , SLOT(socketFailed(QAbstractSocket::SocketError)));
position_pointer->client_micros = 0x7FFFFFFFFFFFFFFFLL;
position_pointer->pos[0] = 0.0;
position_pointer->pos[1] = 0.0;
position_pointer->pos[2] = 0.0;
position_pointer->status = 0;
}
position_pointer = positions;
} }
void TelescopeTcp::hangup(void) void TelescopeTcp::hangup(void)
{ {
if (!IS_INVALID_SOCKET(fd)) if (tcpSocket->isValid())
{ {
close(fd); tcpSocket->abort();// Or maybe tcpSocket->close()?
fd = INVALID_SOCKET;
} }
read_buff_end = read_buff;
write_buff_end = write_buff; readBufferEnd = readBuffer;
writeBufferEnd = writeBuffer;
wait_for_connection_establishment = false; wait_for_connection_establishment = false;
resetPositions();
}
//! resets/initializes the array of positions kept for position interpolati
on
void TelescopeTcp::resetPositions()
{
for (position_pointer = positions; position_pointer < end_position; position_pointer++) for (position_pointer = positions; position_pointer < end_position; position_pointer++)
{ {
position_pointer->server_micros = 0x7FFFFFFFFFFFFFFFLL; position_pointer->server_micros = 0x7FFFFFFFFFFFFFFFLL;
position_pointer->client_micros = 0x7FFFFFFFFFFFFFFFLL; position_pointer->client_micros = 0x7FFFFFFFFFFFFFFFLL;
position_pointer->pos[0] = 0.0; position_pointer->pos[0] = 0.0;
position_pointer->pos[1] = 0.0; position_pointer->pos[1] = 0.0;
position_pointer->pos[2] = 0.0; position_pointer->pos[2] = 0.0;
position_pointer->status = 0; position_pointer->status = 0;
} }
position_pointer = positions; position_pointer = positions;
} }
//! queues a GOTO command with the specified position to the write buffer.
//! For the data format of the command see the
//! "Stellarium telescope control protocol" text file
void TelescopeTcp::telescopeGoto(const Vec3d &j2000Pos) void TelescopeTcp::telescopeGoto(const Vec3d &j2000Pos)
{ {
//! queues a GOTO command with the specified position to the write buffer
.
//! for the data format of the command see the
//! "Stellarium telescope control protocol"
if (isConnected()) if (isConnected())
{ {
if (write_buff_end-write_buff+20 < (int)sizeof(write_buff)) if (writeBufferEnd - writeBuffer + 20 < (int)sizeof(writeBuf fer))
{ {
const double ra = atan2(j2000Pos[1],j2000Pos[0]); const double ra = atan2(j2000Pos[1], j2000Pos[0]);
const double dec = atan2(j2000Pos[2], sqrt(j2000Pos[ 0]*j2000Pos[0]+j2000Pos[1]*j2000Pos[1])); const double dec = atan2(j2000Pos[2], sqrt(j2000Pos[ 0]*j2000Pos[0]+j2000Pos[1]*j2000Pos[1]));
unsigned int ra_int = (unsigned int)floor(0.5 + ra* (((unsigned int)0x80000000)/M_PI)); unsigned int ra_int = (unsigned int)floor(0.5 + ra*( ((unsigned int)0x80000000)/M_PI));
int dec_int = (int)floor(0.5 + dec*(((unsigned int)0 x80000000)/M_PI)); int dec_int = (int)floor(0.5 + dec*(((unsigned int)0 x80000000)/M_PI));
// qDebug() << "TelescopeTcp(" << name << ")::telescopeGoto: "
// "queuing packet: " << PrintRaDec(ra_int,dec_int);
// length of packet: // length of packet:
*write_buff_end++ = 20; *writeBufferEnd++ = 20;
*write_buff_end++ = 0; *writeBufferEnd++ = 0;
// type of packet: // type of packet:
*write_buff_end++ = 0; *writeBufferEnd++ = 0;
*write_buff_end++ = 0; *writeBufferEnd++ = 0;
// client_micros: // client_micros:
long long int now = GetNow(); qint64 now = getNow();
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
now>>=8; now>>=8;
*write_buff_end++ = now; *writeBufferEnd++ = now;
// ra: // ra:
*write_buff_end++ = ra_int; *writeBufferEnd++ = ra_int;
ra_int>>=8; ra_int>>=8;
*write_buff_end++ = ra_int; *writeBufferEnd++ = ra_int;
ra_int>>=8; ra_int>>=8;
*write_buff_end++ = ra_int; *writeBufferEnd++ = ra_int;
ra_int>>=8; ra_int>>=8;
*write_buff_end++ = ra_int; *writeBufferEnd++ = ra_int;
// dec: // dec:
*write_buff_end++ = dec_int; *writeBufferEnd++ = dec_int;
dec_int>>=8; dec_int>>=8;
*write_buff_end++ = dec_int; *writeBufferEnd++ = dec_int;
dec_int>>=8; dec_int>>=8;
*write_buff_end++ = dec_int; *writeBufferEnd++ = dec_int;
dec_int>>=8; dec_int>>=8;
*write_buff_end++ = dec_int; *writeBufferEnd++ = dec_int;
} }
else else
{ {
qDebug() << "TelescopeTcp(" << name << ")::telescope Goto: "<< "communication is too slow, I will ignore this command"; qDebug() << "TelescopeTcp(" << name << ")::telescope Goto: "<< "communication is too slow, I will ignore this command";
} }
} }
} }
void TelescopeTcp::performWriting(void) void TelescopeTcp::performWriting(void)
{ {
const int to_write = write_buff_end - write_buff; const int to_write = writeBufferEnd - writeBuffer;
const int rc = send(fd,write_buff,to_write,0); const int rc = tcpSocket->write(writeBuffer, to_write);
if (rc < 0) if (rc < 0)
{ {
if (ERRNO != EINTR && ERRNO != EAGAIN) //TODO: Better error message. See the Qt documentation.
{ qDebug() << "TelescopeTcp(" << name << ")::performWriting: "
qDebug() << "TelescopeTcp(" << name << ")::performWr << "write failed: " << tcpSocket->errorString();
iting: " hangup();
<< "send failed: " << STRERROR(ERRNO);
hangup();
}
} }
else if (rc > 0) else if (rc > 0)
{ {
if (rc >= to_write) if (rc >= to_write)
{ {
// everything written // everything written
write_buff_end = write_buff; writeBufferEnd = writeBuffer;
} }
else else
{ {
// partly written // partly written
memmove(write_buff,write_buff+rc,to_write-rc); memmove(writeBuffer, writeBuffer + rc, to_write - rc
write_buff_end -= rc; );
writeBufferEnd -= rc;
} }
} }
} }
//! try to read some data from the telescope server
void TelescopeTcp::performReading(void) void TelescopeTcp::performReading(void)
{ {
//! try to read some data from the telescope server const int to_read = readBuffer + sizeof(readBuffer) - readBufferEnd;
const int to_read = read_buff + sizeof(read_buff) - read_buff_end; const int rc = tcpSocket->read(readBufferEnd, to_read);
const int rc = recv(fd,read_buff_end,to_read,0);
if (rc < 0) if (rc < 0)
{ {
if (ERRNO != EINTR && ERRNO != EAGAIN) //TODO: Better error warning. See the Qt documentation.
{ qDebug() << "TelescopeTcp(" << name << ")::performReading: "
qDebug() << "TelescopeTcp(" << name << ")::performRe << "read failed: " << tcpSocket->errorString();
ading: " << "recv failed: " << STRERROR(ERRNO); hangup();
hangup();
}
} }
else if (rc == 0) else if (rc == 0)
{ {
qDebug() << "TelescopeTcp(" << name << ")::performReading: " << "server has closed the connection"; qDebug() << "TelescopeTcp(" << name << ")::performReading: " << "server has closed the connection";
hangup(); hangup();
} }
else else
{ {
read_buff_end += rc; readBufferEnd += rc;
char *p = read_buff; char *p = readBuffer;
// parse the data in the read buffer: // parse the data in the read buffer:
while (read_buff_end-p >= 2) while (readBufferEnd - p >= 2)
{ {
const int size = (int)(((unsigned char)(p[0])) | ((( unsigned int)(unsigned char)(p[1])) << 8)); const int size = (int)(((unsigned char)(p[0])) | ((( unsigned int)(unsigned char)(p[1])) << 8));
if (size > (int)sizeof(read_buff) || size < 4) if (size > (int)sizeof(readBuffer) || size < 4)
{ {
qDebug() << "TelescopeTcp(" << name << ")::p erformReading: " << "bad packet size: " << size; qDebug() << "TelescopeTcp(" << name << ")::p erformReading: " << "bad packet size: " << size;
hangup(); hangup();
return; return;
} }
if (size > read_buff_end-p) if (size > readBufferEnd - p)
{ {
// wait for complete packet // wait for complete packet
break; break;
} }
const int type = (int)(((unsigned char)(p[2])) | ((( unsigned int)(unsigned char)(p[3])) << 8)); const int type = (int)(((unsigned char)(p[2])) | ((( unsigned int)(unsigned char)(p[3])) << 8));
// dispatch: // dispatch:
switch (type) switch (type)
{ {
case 0: case 0:
{
// We have received position information.
// For the data format of the message see the
// "Stellarium telescope control protocol"
if (size < 24)
{ {
qDebug() << "TelescopeTcp(" << name // We have received position information.
<< ")::performReading: " << "type 0: bad packet size: " << size; // For the data format of the message see th
hangup(); e
return; // "Stellarium telescope control protocol"
if (size < 24)
{
qDebug() << "TelescopeTcp("
<< name << ")::performReading: " << "type 0: bad packet size: " << size;
hangup();
return;
}
const qint64 server_micros = (qint64
)
(((quint64)(unsigned char)(p
[ 4])) |
(((quint64)(unsigned char)(p
[ 5])) << 8) |
(((quint64)(unsigned char)(p
[ 6])) << 16) |
(((quint64)(unsigned char)(p
[ 7])) << 24) |
(((quint64)(unsigned char)(p
[ 8])) << 32) |
(((quint64)(unsigned char)(p
[ 9])) << 40) |
(((quint64)(unsigned char)(p
[10])) << 48) |
(((quint64)(unsigned char)(p
[11])) << 56));
const unsigned int ra_int =
((unsigned int)(unsigned cha
r)(p[12])) |
(((unsigned int)(unsigned ch
ar)(p[13])) << 8) |
(((unsigned int)(unsigned ch
ar)(p[14])) << 16) |
(((unsigned int)(unsigned ch
ar)(p[15])) << 24);
const int dec_int =
(int)(((unsigned int)(unsign
ed char)(p[16])) |
(((unsigned int)(un
signed char)(p[17])) << 8) |
(((unsigned int)(un
signed char)(p[18])) << 16) |
(((unsigned int)(un
signed char)(p[19])) << 24));
const int status =
(int)(((unsigned int)(unsign
ed char)(p[20])) |
(((unsigned int)(un
signed char)(p[21])) << 8) |
(((unsigned int)(un
signed char)(p[22])) << 16) |
(((unsigned int)(un
signed char)(p[23])) << 24));
// remember the time and received po
sition so that later we
// will know where the telescope is
pointing to:
position_pointer++;
if (position_pointer >= end_position
)
position_pointer = positions
;
position_pointer->server_micros = se
rver_micros;
position_pointer->client_micros = ge
tNow();
const double ra = ra_int * (M_PI/(
unsigned int)0x80000000);
const double dec = dec_int * (M_PI/(
unsigned int)0x80000000);
const double cdec = cos(dec);
position_pointer->pos[0] = cos(ra)*c
dec;
position_pointer->pos[1] = sin(ra)*c
dec;
position_pointer->pos[2] = sin(dec);
position_pointer->status = status;
} }
const long long int server_micros = (long lo break;
ng int) default:
(((unsigned long long int)(unsigned qDebug() << "TelescopeTcp(" << name
char)(p[ 4])) | << ")::performReading: " << "ignoring unknown packet, type: " << type;
(((unsigned long long int)(unsigned
char)(p[ 5])) << 8) |
(((unsigned long long int)(unsigned
char)(p[ 6])) << 16) |
(((unsigned long long int)(unsigned
char)(p[ 7])) << 24) |
(((unsigned long long int)(unsigned
char)(p[ 8])) << 32) |
(((unsigned long long int)(unsigned
char)(p[ 9])) << 40) |
(((unsigned long long int)(unsigned
char)(p[10])) << 48) |
(((unsigned long long int)(unsigned
char)(p[11])) << 56));
const unsigned int ra_int =
((unsigned int)(unsigned char)(p[12])) |
(((unsigned int)(unsigned char)(p[13]))
<< 8) |
(((unsigned int)(unsigned char)(p[14]))
<< 16) |
(((unsigned int)(unsigned char)(p[15]))
<< 24);
const int dec_int =
(int)(((unsigned int)(unsigned char)
(p[16])) |
(((unsigned int)(unsigned char)(p[17
])) << 8) |
(((unsigned int)(unsigned char)(p[18
])) << 16) |
(((unsigned int)(unsigned char)(p[19
])) << 24));
const int status =
(int)(((unsigned int)(unsigned char)(p[2
0])) |
(((unsigned int)(unsigned char)(p[21
])) << 8) |
(((unsigned int)(unsigned char)(p[22
])) << 16) |
(((unsigned int)(unsigned char)(p[23
])) << 24));
// remember the time and received position
so that later we
// will know where the telescope is pointi
ng to:
position_pointer++;
if (position_pointer >= end_position)
position_pointer = positions;
position_pointer->server_micros = server_mic
ros;
position_pointer->client_micros = GetNow();
const double ra = ra_int * (M_PI/(unsigned
int)0x80000000);
const double dec = dec_int * (M_PI/(unsigned
int)0x80000000);
const double cdec = cos(dec);
position_pointer->pos[0] = cos(ra)*cdec;
position_pointer->pos[1] = sin(ra)*cdec;
position_pointer->pos[2] = sin(dec);
position_pointer->status = status;
// qDebug() << "TelescopeTcp(" << name << ")::performReading: "
//// "Server Time: " << server_micros
// << PrintRaDec(ra_int,dec_int)
// ;
}
break;
default:
qDebug() << "TelescopeTcp(" << name << ")::p
erformReading: " << "ignoring unknown packet, type: " << type;
break; break;
} }
p += size; p += size;
} }
if (p >= read_buff_end) if (p >= readBufferEnd)
{ {
// everything handled // everything handled
read_buff_end = read_buff; readBufferEnd = readBuffer;
} }
else else
{ {
// partly handled // partly handled
memmove(read_buff,p,read_buff_end-p); memmove(readBuffer, p, readBufferEnd - p);
read_buff_end -= (p-read_buff); readBufferEnd -= (p - readBuffer);
} }
} }
} }
//! estimates where the telescope is by interpolation in the stored
//! telescope positions:
Vec3d TelescopeTcp::getJ2000EquatorialPos(const StelNavigator*) const Vec3d TelescopeTcp::getJ2000EquatorialPos(const StelNavigator*) const
{ {
// estimate wher the telescope is by interpolation in the stored
// telescope positions:
if (position_pointer->client_micros == 0x7FFFFFFFFFFFFFFFLL) if (position_pointer->client_micros == 0x7FFFFFFFFFFFFFFFLL)
{ {
return Vec3d(0,0,0); return Vec3d(0,0,0);
} }
const long long int now = GetNow() - time_delay; const qint64 now = getNow() - time_delay;
const Position *p = position_pointer; const Position *p = position_pointer;
do do
{ {
const Position *pp = p; const Position *pp = p;
if (pp == positions) pp = end_position; if (pp == positions) pp = end_position;
pp--; pp--;
if (pp->client_micros == 0x7FFFFFFFFFFFFFFFLL) break; if (pp->client_micros == 0x7FFFFFFFFFFFFFFFLL) break;
if (pp->client_micros <= now && now <= p->client_micros) if (pp->client_micros <= now && now <= p->client_micros)
{ {
if (pp->client_micros != p->client_micros) if (pp->client_micros != p->client_micros)
skipping to change at line 644 skipping to change at line 488
double f = rval.lengthSquared(); double f = rval.lengthSquared();
if (f > 0.0) if (f > 0.0)
{ {
return (1.0/sqrt(f))*rval; return (1.0/sqrt(f))*rval;
} }
} }
break; break;
} }
p = pp; p = pp;
} }
while (p != position_pointer); while (p != position_pointer);//BM: WTF?
return p->pos; return p->pos;
} }
void TelescopeTcp::prepareSelectFds(fd_set &read_fds,fd_set &write_fds, int //! checks if the socket is connected, tries to connect if it is not
&fd_max) //@return true if the socket is connected
bool TelescopeTcp::prepareCommunication()
{ {
// just plain TCP/IP programming if(tcpSocket->state() == QAbstractSocket::ConnectedState)
if (IS_INVALID_SOCKET(fd))
{ {
// try reconnecting if(wait_for_connection_establishment)
const long long int now = GetNow();
if (now < end_of_timeout) return;
end_of_timeout = now + 5000000;
fd = socket(AF_INET,SOCK_STREAM,0);
if (IS_INVALID_SOCKET(fd))
{ {
qDebug() << "TelescopeTcp(" << name << ")::prepareSe wait_for_connection_establishment = false;
lectFds: "<< "socket() failed: " << STRERROR(ERRNO); qDebug() << "TelescopeTcp(" << name << ")::prepareCo
return; mmunication: " << "connection established";
} }
if (SET_NONBLOCKING_MODE(fd) != 0) return true;
}
else if(wait_for_connection_establishment)
{
const qint64 now = getNow();
if (now > end_of_timeout)
{ {
qDebug() << "TelescopeTcp(" << name << ")::prepareSe end_of_timeout = now + 1000000;
lectFds: " << "could not set nonblocking mode: " << STRERROR(ERRNO); qDebug() << "TelescopeTcp(" << name << ")::prepareCo
mmunication: " << "connect timeout";
hangup(); hangup();
return;
}
if (connect(fd,(struct sockaddr*)(&address),sizeof(address))
!= 0)
{
if (ERRNO != EINPROGRESS && ERRNO != EAGAIN)
{
qDebug() << "TelescopeTcp(" << name << ")::p
repareSelectFds: " << "connect() failed: " << STRERROR(ERRNO);
hangup();
return;
}
wait_for_connection_establishment = true;
// qDebug() << "TelescopeTcp(" << name << ")::prepareSelectFds: "
// << "waiting for connection establishment";
}
else
{
wait_for_connection_establishment = false;
qDebug() << "TelescopeTcp(" << name << ")::prepareSe
lectFds: " << "connection established";
// connection established, wait for next call of pre
pareSelectFds
} }
} }
else else
{ {
// socked is already connected const qint64 now = getNow();
if (fd_max < (int)fd) fd_max = (int)fd; if (now < end_of_timeout)
if (wait_for_connection_establishment) return false; //Don't try to reconnect for some time
{ end_of_timeout = now + 5000000;
const long long int now = GetNow(); tcpSocket->connectToHost(address, port);
if (now > end_of_timeout) wait_for_connection_establishment = true;
{
end_of_timeout = now + 1000000;
qDebug() << "TelescopeTcp(" << name << ")::p
repareSelectFds: " << "connect timeout";
hangup();
return;
}
FD_SET(fd,&write_fds);
}
else
{
if (write_buff_end > write_buff) FD_SET(fd,&write_fd
s);
FD_SET(fd,&read_fds);
}
} }
return false;
} }
void TelescopeTcp::handleSelectFds(const fd_set &read_fds, const fd_set &wr ite_fds) void TelescopeTcp::performCommunication()
{ {
// just plain TCP/IP programming if (tcpSocket->state() == QAbstractSocket::ConnectedState)
if (!IS_INVALID_SOCKET(fd))
{ {
if (wait_for_connection_establishment) performWriting();
{
if (FD_ISSET(fd,const_cast<fd_set *>(&write_fds))) if (tcpSocket->bytesAvailable() > 0)
{
wait_for_connection_establishment = false;
int err = 0;
SOCKLEN_T length = sizeof(err);
if (getsockopt(fd,SOL_SOCKET,SO_ERROR,(char*
)(&err),&length) != 0)
{
qDebug() << "TelescopeTcp(" << name
<< ")::handleSelectFds: " << "getsockopt failed";
hangup();
}
else
{
if (err != 0)
{
qDebug() << "TelescopeTcp("
<< name << ")::handleSelectFds: " << "connect failed: " << STRERROR(err);
hangup();
}
else
{
qDebug() << "TelescopeTcp("
<< name << ")::handleSelectFds: " << "connection established";
}
}
}
}
else // connection already established
{ {
if (FD_ISSET(fd,const_cast<fd_set *>(&write_fds))) //If performReading() is called when there are no by
{ tes to read,
performWriting(); //it closes the connection
} performReading();
if (!IS_INVALID_SOCKET(fd) && FD_ISSET(fd,const_cast
<fd_set *>(&read_fds)))
{
performReading();
}
} }
} }
} }
//TODO: More informative error messages?
void TelescopeTcp::socketFailed(QAbstractSocket::SocketError socketError)
{
qDebug() << "TelescopeTcp(" << name << "): TCP socket error:\n" << t
cpSocket->errorString();
}
 End of changes. 91 change blocks. 
463 lines changed or deleted 236 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/