Instrument Neutral Distributed Interface INDI  2.0.2
baseclientqt.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2016 Jasem Mutlaq. All rights reserved.
3 
4  INDI Qt Client
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2 as published by the Free Software Foundation.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 *******************************************************************************/
20 
21 #include "baseclientqt.h"
22 #include "baseclientqt_p.h"
23 
24 #include "abstractbaseclient.h"
25 #include "abstractbaseclient_p.h"
26 namespace INDI
27 {
28 
29 // BaseClientQtPrivate
30 
33 { }
34 
35 ssize_t BaseClientQtPrivate::sendData(const void *data, size_t size)
36 {
37  return clientSocket.write(static_cast<const char *>(data), size);
38 }
39 
41 {
42  char msg[MAXRBUF];
43 
44  if (sConnected == false)
45  return;
46 
47  while (clientSocket.bytesAvailable() > 0)
48  {
49  const QByteArray data = clientSocket.readAll();
50 
51  auto documents = xmlParser.parseChunk(data.constData(), data.size());
52 
53  if (documents.size() == 0)
54  {
56  {
57  IDLog("Bad XML from %s/%d: %s\n%.*s\n", cServer.c_str(), cPort, xmlParser.errorMessage(), data.size(), data.constData());
58  }
59  break;
60  }
61 
62  for (const auto &doc: documents)
63  {
64  LilXmlElement root = doc.root();
65 
66  if (verbose)
67  root.print(stderr, 0);
68 
69  int err_code = dispatchCommand(root, msg);
70 
71  if (err_code < 0)
72  {
73  // Silenty ignore property duplication errors
74  if (err_code != INDI_PROPERTY_DUPLICATED)
75  {
76  IDLog("Dispatch command error(%d): %s\n", err_code, msg);
77  root.print(stderr, 0);
78  }
79  }
80  }
81  }
82 }
83 
84 // BaseClientQt
85 
87  : QObject(parent)
89 {
90  D_PTR(BaseClientQt);
91  connect(&d->clientSocket, &QTcpSocket::readyRead, this, [d]()
92  {
93  d->listenINDI();
94  });
95 
96 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
97  connect(&d->clientSocket, &QTcpSocket::errorOccurred, this, [d, this](QAbstractSocket::SocketError socketError)
98 #else
99  connect(&d->clientSocket, qOverload<QAbstractSocket::SocketError>(&QTcpSocket::error), this, [d, this](QAbstractSocket::SocketError socketError)
100 #endif
101  {
102  if (d->sConnected == false)
103  return;
104 
105  // TODO Handle what happens on socket failure!
106  INDI_UNUSED(socketError);
107  IDLog("Socket Error: %s\n", d->clientSocket.errorString().toLatin1().constData());
108  fprintf(stderr, "INDI server %s/%d disconnected.\n", d->cServer.c_str(), d->cPort);
109  d->clientSocket.close();
110  // Let client handle server disconnection
111  serverDisconnected(-1);
112  });
113 }
114 
116 {
117  D_PTR(BaseClientQt);
118  d->clear();
119 }
120 
122 {
123  D_PTR(BaseClientQt);
124  d->clientSocket.connectToHost(d->cServer.c_str(), d->cPort);
125 
126  if (d->clientSocket.waitForConnected(d->timeout_sec * 1000) == false)
127  {
128  d->sConnected = false;
129  return false;
130  }
131 
132  d->clear();
133 
134  d->sConnected = true;
135 
136  serverConnected();
137 
138  d->userIoGetProperties();
139 
140  return true;
141 }
142 
144 {
145  D_PTR(BaseClientQt);
146 
147  if (d->sConnected == false)
148  return true;
149 
150  d->sConnected = false;
151 
152  d->clientSocket.close();
153 
154  d->clear();
155 
156  d->watchDevice.unwatchDevices();
157 
158  serverDisconnected(exit_code);
159 
160  return true;
161 }
162 
163 }
int dispatchCommand(const INDI::LilXmlElement &root, char *errmsg)
Dispatch command received from INDI server to respective devices handled by the client.
ssize_t sendData(const void *data, size_t size) override
BaseClientQtPrivate(BaseClientQt *parent)
Class to provide basic client functionality based on Qt5 toolkit and is therefore suitable for cross-...
Definition: baseclientqt.h:48
bool disconnectServer(int exit_code=0) override
Disconnect from INDI server. Any devices previously created will be deleted and memory cleared.
bool connectServer() override
Connect to INDI server.
BaseClientQt(QObject *parent=Q_NULLPTR)
virtual void serverDisconnected(int exit_code)
Emmited when the server gets disconnected.
Definition: indibase.cpp:36
virtual void serverConnected()
Emmited when the server is connected.
Definition: indibase.cpp:33
void print(FILE *f, int level=0) const
Definition: indililxml.h:430
const char * errorMessage() const
Definition: indililxml.h:505
bool hasErrorMessage() const
Definition: indililxml.h:500
std::list< LilXmlDocument > parseChunk(const char *data, size_t size)
Definition: indililxml.h:485
@ INDI_PROPERTY_DUPLICATED
Definition: indibasetypes.h:65
void IDLog(const char *fmt,...)
Definition: indicom.c:316
#define MAXRBUF
Definition: indiserver.cpp:102
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: json.h:4973