Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TC plugin: add Alpaca #4148

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 131 additions & 31 deletions plugins/TelescopeControl/src/ASCOM/ASCOMDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,57 +18,135 @@

#include "ASCOMDevice.hpp"
#include <comdef.h>
#include <QTimer>
//#include <qwaitcondition.h>
#include <QMessageBox>
#include "StelTranslator.hpp"

ASCOMDevice::ASCOMDevice(QObject* parent, QString ascomDeviceId) : QObject(parent),
mAscomDeviceId(ascomDeviceId)
{}
mAscomDeviceId(ascomDeviceId),
connectionRetries(0)
{
}

bool ASCOMDevice::connect()
// FIXME! ASCOM7 deprecates writing to the LConnected property. One shall use methods Connect()/Disconnect() instead,
// and detect the state per "Connecting" property.
void ASCOMDevice::connect()
{
if (mConnected) return true;
if (mConnected) return; // true;

BOOL initResult = OleInit(COINIT_APARTMENTTHREADED);
HRESULT hResult = OleCreateInstance(reinterpret_cast<const wchar_t*>(mAscomDeviceId.toStdWString().c_str()), &pTelescopeDispatch);

if (!initResult || FAILED(hResult))
{
qDebug() << "Initialization failed for device: " << mAscomDeviceId;
return false;
qCritical() << "Initialization failed for device: " << mAscomDeviceId;
QMessageBox::critical(nullptr, q_("ERROR!"), q_("Initialization failed for device: ")+mAscomDeviceId);

return;
}

VARIANT v1 = OleBoolToVariant(TRUE);
// Initiate asynchronous Connect() according to ASCOM7
hResult = OleMethodCall(pTelescopeDispatch, nullptr, const_cast<wchar_t*>(LConnect), 0);
if (FAILED(hResult))
{
qCritical() << "Could not send Connect signal to device: " << mAscomDeviceId;
QMessageBox::critical(nullptr, q_("ERROR!"), q_("Could not send Connect signal to device: ")+mAscomDeviceId);
return;
}
connectionRetries=10;
QObject::connect(&connectionTimer, &QTimer::timeout, this, &ASCOMDevice::tryFinishConnect);
connectionTimer.start(250); // 1/4 s interval
}

hResult = OlePropertyPut(pTelescopeDispatch, nullptr, const_cast<wchar_t*>(LConnected), 1, v1);
void ASCOMDevice::tryFinishConnect()
{
qDebug() << "ASCOMDevice::tryFinishConnect()";

if (FAILED(hResult))
if (isConnecting())
{
qDebug() << "Could not connect to device: " << mAscomDeviceId;
return false;
if (--connectionRetries <= 0)
{
// Give up connecting!
connectionTimer.stop();
QObject::disconnect(&connectionTimer, &QTimer::timeout, this, &ASCOMDevice::tryFinishConnect);
qCritical() << "Could not establish connection to device: " << mAscomDeviceId;
QMessageBox::critical(nullptr, q_("ERROR!"), q_("Could not establish connection to device: ")+mAscomDeviceId);
}
}
else // connection has probably been established. Read value for certainty.
{
connectionTimer.stop();
QObject::disconnect(&connectionTimer, &QTimer::timeout, this, &ASCOMDevice::tryFinishConnect);
mConnected=isDeviceConnected();
}

mConnected = true;
return true;
}

bool ASCOMDevice::disconnect()
void ASCOMDevice::tryFinishDisconnect()
{
if (!mConnected) return true;
qDebug() << "ASCOMDevice::tryFinishDisconnect()";
if (isConnecting())
{
if (--connectionRetries <= 0)
{
// Give up disconnecting! Is that at all useful?
connectionTimer.stop();
QObject::disconnect(&connectionTimer, &QTimer::timeout, this, &ASCOMDevice::tryFinishDisconnect);
qCritical() << "Could not send Disconnect signal to device: " << mAscomDeviceId;
// TODO: Show a screen panel?
QMessageBox::critical(nullptr, q_("ERROR!"), q_("Could not cleanly disconnect from device: ")+mAscomDeviceId);
}
}
else // disconnection has been successful. Read value for certainty.
{
connectionTimer.stop();
QObject::disconnect(&connectionTimer, &QTimer::timeout, this, &ASCOMDevice::tryFinishDisconnect);
mConnected=false;
pTelescopeDispatch->Release();
}
}


VARIANT v1 = OleBoolToVariant(FALSE);
HRESULT hResult = OlePropertyPut(pTelescopeDispatch, nullptr, const_cast<wchar_t*>(LConnected), 1, v1);

//void ASCOMDevice::disconnect()
//{
// if (!mConnected) return; // true;
//
// VARIANT v1 = OleBoolToVariant(FALSE);
// HRESULT hResult = OlePropertyPut(pTelescopeDispatch, nullptr, const_cast<wchar_t*>(LConnected), 1, v1);
//
// if (FAILED(hResult))
// {
// qDebug() << "Could not disconnect device: " << mAscomDeviceId;
// return; // false;
// }
//
// pTelescopeDispatch->Release(); // TODO: Move that to tryFinishDisconnect
//
// mConnected = false;
// return; // true;
//}


void ASCOMDevice::disconnect()
{
if (mConnected) return; // true;


// Initiate asynchronous Disconnect() according to ASCOM7
HRESULT hResult = OleMethodCall(pTelescopeDispatch, nullptr, const_cast<wchar_t*>(LDisconnect), 0);
if (FAILED(hResult))
{
qDebug() << "Could not disconnect device: " << mAscomDeviceId;
return false;
qCritical() << "Could not send Disconnect signal to device: " << mAscomDeviceId;
// TODO: Show a screen panel?
return;
}

pTelescopeDispatch->Release();

mConnected = false;
return true;
connectionRetries=10;
QObject::connect(&connectionTimer, &QTimer::timeout, this, &ASCOMDevice::tryFinishDisconnect);
connectionTimer.start(250); // 1/4 s interval
}


ASCOMDevice::ASCOMCoordinates ASCOMDevice::position() const
{
return mCoordinates;
Expand Down Expand Up @@ -114,6 +192,11 @@ void ASCOMDevice::abortSlew()
}
}

bool ASCOMDevice::isConnected() const
{
return mConnected;
}

bool ASCOMDevice::isDeviceConnected() const
{
if (!mConnected) return false;
Expand All @@ -127,7 +210,21 @@ bool ASCOMDevice::isDeviceConnected() const
return false;
}

return v1.boolVal == -1;
return v1.boolVal == VARIANT_TRUE;
}

bool ASCOMDevice::isConnecting() const
{
VARIANT v1;
HRESULT hResult = OlePropertyGet(pTelescopeDispatch, &v1, const_cast<wchar_t*>(LConnecting));

if (FAILED(hResult))
{
qDebug() << "Could not get connecting state for device: " << mAscomDeviceId;
return false;
}

return v1.boolVal == VARIANT_TRUE;
}

bool ASCOMDevice::isParked() const
Expand All @@ -143,7 +240,7 @@ bool ASCOMDevice::isParked() const
return false;
}

return v1.boolVal == -1;
return v1.boolVal == VARIANT_TRUE;
}


Expand Down Expand Up @@ -176,7 +273,7 @@ bool ASCOMDevice::doesRefraction()
return false;
}

return v1.boolVal == -1;
return v1.boolVal == VARIANT_TRUE;
}


Expand Down Expand Up @@ -228,9 +325,12 @@ QString ASCOMDevice::showDeviceChooser(QString previousDeviceId)

const wchar_t* ASCOMDevice::LSlewToCoordinatesAsync = L"SlewToCoordinatesAsync";
const wchar_t* ASCOMDevice::LSyncToCoordinates = L"SyncToCoordinates";
const wchar_t* ASCOMDevice::LAbortSlew = L"AbortSlew";
const wchar_t* ASCOMDevice::LConnected = L"Connected";
const wchar_t* ASCOMDevice::LAtPark = L"AtPark";
const wchar_t* ASCOMDevice::LAbortSlew = L"AbortSlew";
const wchar_t* ASCOMDevice::LConnected = L"Connected";
const wchar_t* ASCOMDevice::LConnecting = L"Connecting";
const wchar_t* ASCOMDevice::LConnect = L"Connect";
const wchar_t* ASCOMDevice::LDisconnect = L"Disconnect";
const wchar_t* ASCOMDevice::LAtPark = L"AtPark";
const wchar_t* ASCOMDevice::LEquatorialSystem = L"EquatorialSystem";
const wchar_t* ASCOMDevice::LDoesRefraction = L"DoesRefraction";
const wchar_t* ASCOMDevice::LRightAscension = L"RightAscension";
Expand Down
17 changes: 14 additions & 3 deletions plugins/TelescopeControl/src/ASCOM/ASCOMDevice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <QObject>
#include <QStringList>
#include <QTimer>
#include "../common/OLE.hpp"

class ASCOMDevice final : public QObject
Expand All @@ -43,10 +44,14 @@ class ASCOMDevice final : public QObject

ASCOMDevice(QObject* parent = nullptr, QString ascomDeviceId = nullptr);

bool isDeviceConnected() const;
bool isConnected() const; // just return mConnected, i.e., connection has been etablished previously so that this device is said "active".
bool isDeviceConnected() const; // Thorough test if connection to actual telescope is still present. Slow!
bool isParked() const;
bool connect();
bool disconnect();
void connect(); // initiate connection.
void disconnect(); // initiate disconnection.
bool isConnecting() const; // According to ASCOM7 protocol standards.
void tryFinishConnect(); // finalize connection or give up after some time.
void tryFinishDisconnect();
ASCOMCoordinates position() const;
void slewToCoordinates(ASCOMCoordinates coords);
void syncToCoordinates(ASCOMCoordinates coords);
Expand All @@ -56,6 +61,7 @@ class ASCOMDevice final : public QObject
ASCOMCoordinates getCoordinates();

signals:
// TODO: These signals are empty definitions and are not connected and never emitted!
void deviceConnected();
void deviceDisconnected();

Expand All @@ -64,10 +70,15 @@ class ASCOMDevice final : public QObject
bool mConnected = false;
ASCOMCoordinates mCoordinates;
QString mAscomDeviceId;
QTimer connectionTimer;
int connectionRetries;
static const wchar_t* LSlewToCoordinatesAsync;
static const wchar_t* LSyncToCoordinates;
static const wchar_t* LAbortSlew;
static const wchar_t* LConnected;
static const wchar_t* LConnecting;
static const wchar_t* LConnect;
static const wchar_t* LDisconnect;
static const wchar_t* LAtPark;
static const wchar_t* LEquatorialSystem;
static const wchar_t* LDoesRefraction;
Expand Down
6 changes: 3 additions & 3 deletions plugins/TelescopeControl/src/ASCOM/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Due to incomprehensible errors between ASCOM and Qt6OpenGL!QOpenGL2PaintEngineEx::setState(), we must disable ASCOM in QT6-based builds.
# Due to incomprehensible errors between ASCOM and Qt6OpenGL!QOpenGL2PaintEngineEx::setState(), we temporarily had to disable ASCOM in QT6-based builds.
# No other code change related to Qt6 has been done so far, only the ASCOM selector has been greyed out.
# Rather sooner than later ASCOM must be replaced by Alpaca.
if(WIN32 AND (${QT_VERSION_MAJOR} EQUAL "5"))
if(WIN32)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
Expand Down Expand Up @@ -43,4 +43,4 @@ ENDIF(ENABLE_TESTING)

SET_TARGET_PROPERTIES(TelescopeControl_ASCOM PROPERTIES FOLDER "plugins/TelescopeControl")

ENDIF(WIN32 AND (${QT_VERSION_MAJOR} EQUAL "5"))
ENDIF(WIN32)
5 changes: 4 additions & 1 deletion plugins/TelescopeControl/src/ASCOM/TelescopeClientASCOM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ TelescopeClientASCOM::TelescopeClientASCOM(const QString& name, const QString& p

mAscomDevice = new ASCOMDevice(this, mAscomDeviceId);
mAscomDevice->connect();
// TODO: Wait for actual confirmation of connection...
mDoesRefraction = mAscomDevice->doesRefraction();
mCoordinateType = mAscomDevice->getEquatorialCoordinateType();
}
Expand Down Expand Up @@ -167,7 +168,9 @@ void TelescopeClientASCOM::telescopeAbortSlew()

bool TelescopeClientASCOM::isConnected() const
{
return mAscomDevice->isDeviceConnected();
//return mAscomDevice->isDeviceConnected();
// Called every frame, we should only see if we have been connected before...
return mAscomDevice->isConnected();
}

bool TelescopeClientASCOM::hasKnownPosition() const
Expand Down
Loading
Loading