11#include "clientmanager.h"
12#include "driverinfo.h"
13#include "deviceinfo.h"
14#include "imageviewer.h"
15#include "indi_debug.h"
17#include "kstarsdata.h"
21#include "indilistener.h"
23#include "indicamera.h"
24#include "indiguider.h"
25#include "indifocuser.h"
26#include "indifilterwheel.h"
29#include "indiweather.h"
30#include "indiadaptiveoptics.h"
31#include "indidustcap.h"
32#include "indilightbox.h"
33#include "indidetector.h"
34#include "indirotator.h"
35#include "indispectrograph.h"
36#include "indicorrelator.h"
37#include "indiauxiliary.h"
39#include "genericdeviceadaptor.h"
41#include <QImageReader>
47GDSetCommand::GDSetCommand(INDI_PROPERTY_TYPE inPropertyType,
const QString &inProperty,
const QString &inElement,
49 :
QObject(parent), propType(inPropertyType), indiProperty((inProperty)), indiElement(inElement), elementValue(qValue)
53uint8_t GenericDevice::m_ID = 1;
57 new GenericDeviceAdaptor(
this);
61 m_DriverInfo = idv.getDriverInfo();
62 m_BaseDevice = idv.getBaseDevice();
65 Q_ASSERT_X(m_BaseDevice, __FUNCTION__,
"Base device is invalid.");
66 Q_ASSERT_X(m_ClientManager, __FUNCTION__,
"Client manager is invalid.");
68 m_Name = m_BaseDevice.getDeviceName();
70 setObjectName(m_Name);
72 m_DriverInterface = m_BaseDevice.getDriverInterface();
73 m_DriverVersion = m_BaseDevice.getDriverVersion();
80 if (Options::useTimeUpdate() && Options::timeSource() ==
"KStars")
84 auto tvp = m_BaseDevice.getText(
"TIME_UTC");
85 if (tvp && tvp.getPermission() != IP_RO)
91 m_ReadyTimer =
new QTimer(
this);
92 m_ReadyTimer->setInterval(250);
93 m_ReadyTimer->setSingleShot(
true);
96 m_TimeUpdateTimer =
new QTimer(
this);
97 m_TimeUpdateTimer->setInterval(5000);
98 m_TimeUpdateTimer->setSingleShot(
true);
101 m_LocationUpdateTimer =
new QTimer(
this);
102 m_LocationUpdateTimer->setInterval(5000);
103 m_LocationUpdateTimer->setSingleShot(
true);
108GenericDevice::~GenericDevice()
110 for (
auto &metadata : streamFileMetadata)
111 metadata.file->close();
114void GenericDevice::handleTimeout()
127void GenericDevice::checkTimeUpdate()
132 auto timeTP = tvp.getText();
134 if (timeTP && timeTP->getPermission() != IP_RO && timeTP->getState() == IPS_IDLE)
140void GenericDevice::checkLocationUpdate()
145 auto locationNP = nvp.getNumber();
147 if (locationNP && locationNP->getPermission() != IP_RO && locationNP->getState() == IPS_IDLE)
152void GenericDevice::registerDBusType()
155 static bool isRegistered =
false;
157 if (isRegistered ==
false)
159 qRegisterMetaType<ISD::ParkStatus>(
"ISD::ParkStatus");
160 qDBusRegisterMetaType<ISD::ParkStatus>();
166const QString &GenericDevice::getDeviceName()
const
171void GenericDevice::registerProperty(INDI::Property prop)
173 if (!prop.getRegistered())
176 m_ReadyTimer->start();
181 if (name ==
"CONNECTION")
183 auto svp = prop.getSwitch();
186 if (!svp || svp->getState() == IPS_BUSY)
189 auto conSP = svp->findWidgetByName(
"CONNECT");
194 if (m_Connected ==
false && svp->getState() == IPS_OK && conSP->getState() == ISS_ON)
200 else if (m_Connected && conSP->getState() == ISS_OFF)
206 m_Ready = (svp->s == IPS_OK && conSP->s == ISS_ON);
208 else if (name ==
"DRIVER_INFO")
210 auto tvp = prop.getText();
213 auto tp = tvp->findWidgetByName(
"DRIVER_INTERFACE");
216 m_DriverInterface =
static_cast<uint32_t
>(atoi(tp->getText()));
217 emit interfaceDefined();
220 tp = tvp->findWidgetByName(
"DRIVER_VERSION");
223 m_DriverVersion =
QString(tp->getText());
227 else if (name ==
"SYSTEM_PORTS")
231 auto svp = prop.getSwitch();
232 auto port = m_BaseDevice.getText(
"DEVICE_PORT");
235 for (
const auto &it : *svp)
237 if (it.isNameMatch(port.at(0)->getText()))
239 emit systemPortDetected();
245 else if (name ==
"TIME_UTC" && Options::useTimeUpdate())
247 const auto &tvp = prop.getText();
251 if (Options::timeSource() ==
"KStars" && tvp->getPermission() != IP_RO)
254 m_TimeUpdateTimer->start();
257 else if (name ==
"GEOGRAPHIC_COORD" && Options::useGeographicUpdate())
259 if (Options::locationSource() ==
"KStars" && prop.getPermission() != IP_RO)
262 m_LocationUpdateTimer->start();
264 else if (name ==
"WATCHDOG_HEARTBEAT")
266 if (watchDogTimer ==
nullptr)
268 watchDogTimer =
new QTimer(
this);
269 connect(watchDogTimer, SIGNAL(timeout()),
this, SLOT(resetWatchdog()));
272 if (m_Connected && prop.getNumber()->at(0)->getValue() > 0)
275 m_ClientManager->sendNewProperty(prop);
279 emit propertyDefined(prop);
282void GenericDevice::updateProperty(INDI::Property prop)
284 switch (prop.getType())
306void GenericDevice::removeProperty(INDI::Property prop)
308 emit propertyDeleted(prop);
311void GenericDevice::processSwitch(INDI::Property prop)
313 if (prop.isNameMatch(
"CONNECTION"))
316 if (prop.getState() == IPS_BUSY)
319 auto connectionOn = prop.getSwitch()->findWidgetByName(
"CONNECT");
320 if (m_Connected ==
false && prop.getState() == IPS_OK && connectionOn->getState() == ISS_ON)
329 if (watchDogTimer !=
nullptr)
331 auto nvp = m_BaseDevice.getNumber(
"WATCHDOG_HEARTBEAT");
332 if (nvp && nvp.at(0)->getValue() > 0)
335 m_ClientManager->sendNewProperty(nvp);
339 m_ReadyTimer->start();
341 else if (m_Connected && connectionOn->getState() == ISS_OFF)
343 disconnect(m_ReadyTimer, &
QTimer::timeout,
this, &GenericDevice::handleTimeout);
349 m_Ready = (prop.getState() == IPS_OK && connectionOn->getState() == ISS_ON);
352 emit propertyUpdated(prop);
355void GenericDevice::processNumber(INDI::Property prop)
357 QString deviceName = getDeviceName();
358 auto nvp = prop.getNumber();
360 if (prop.isNameMatch(
"GEOGRAPHIC_COORD") && prop.getState() == IPS_OK && Options::locationSource() == deviceName)
366 auto np = nvp->findWidgetByName(
"LONG");
374 lng.
setD(np->value - 360.0);
376 np = nvp->findWidgetByName(
"LAT");
385 qCWarning(KSTARS_INDI) <<
"Ignoring invalid device coordinates.";
389 np = nvp->findWidgetByName(
"ELEV");
394 for (
auto &oneDevice : INDIListener::devices())
397 if (oneDevice->getDeviceName() == getDeviceName())
404 std::unique_ptr<GeoLocation> tempGeo;
407 if (getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
408 newLocationName =
i18n(
"GPS Location");
410 newLocationName =
i18n(
"Mount Location");
412 if (
geo->name() != newLocationName)
414 double TZ0 =
geo->TZ0();
416 tempGeo.reset(
new GeoLocation(lng, lat, newLocationName,
"",
"", TZ0, rule, elev));
425 qCInfo(KSTARS_INDI) <<
"Setting location from device:" << deviceName <<
"Longitude:" << lng.
toDMSString() <<
"Latitude:" <<
430 else if (nvp->isNameMatch(
"WATCHDOG_HEARTBEAT"))
432 if (watchDogTimer ==
nullptr)
434 watchDogTimer =
new QTimer(
this);
438 auto value = nvp->at(0)->getValue();
439 if (m_Connected && value > 0)
443 double nextMS = qMax(100.0, (value - 5) * 1000);
444 watchDogTimer->start(nextMS);
447 watchDogTimer->stop();
450 emit propertyUpdated(prop);
453void GenericDevice::processText(INDI::Property prop)
455 auto tvp = prop.getText();
457 if (tvp->isNameMatch(
"DRIVER_INFO"))
459 auto tp = tvp->findWidgetByName(
"DRIVER_INTERFACE");
462 m_DriverInterface =
static_cast<uint32_t
>(atoi(tp->getText()));
463 emit interfaceDefined();
467 if (m_ConcreteDevices.isEmpty() ==
false)
470 if (generateDevices())
475 tp = tvp->findWidgetByName(
"DRIVER_VERSION");
478 m_DriverVersion =
QString(tp->text);
483 else if (tvp->isNameMatch(
"TIME_UTC") && tvp->s == IPS_OK && Options::timeSource() == getDeviceName())
485 int d, m, y, min, sec, hour;
490 auto tp = tvp->findWidgetByName(
"UTC");
494 qCWarning(KSTARS_INDI) <<
"UTC property missing from TIME_UTC";
498 sscanf(tp->getText(),
"%d%*[^0-9]%d%*[^0-9]%dT%d%*[^0-9]%d%*[^0-9]%d", &y, &m, &d, &hour, &min, &sec);
500 indiTime.
setHMS(hour, min, sec);
504 tp = tvp->findWidgetByName(
"OFFSET");
508 qCWarning(KSTARS_INDI) <<
"Offset property missing from TIME_UTC";
512 sscanf(tp->getText(),
"%f", &utcOffset);
515 for (
auto &oneDevice : INDIListener::devices())
518 if (oneDevice->getDeviceName() == getDeviceName())
521 oneDevice->updateTime(tvp->tp[0].text, tvp->tp[1].text);
524 qCInfo(KSTARS_INDI) <<
"Setting UTC time from device:" << getDeviceName() << indiDateTime.toString();
531 utcOffset -=
geo->tzrule()->deltaTZ();
535 geo->setTZ0(utcOffset);
538 emit propertyUpdated(prop);
541void GenericDevice::processLight(INDI::Property prop)
543 emit propertyUpdated(prop);
546void GenericDevice::processMessage(
int messageID)
548 emit messageUpdated(messageID);
551bool GenericDevice::processBLOB(INDI::Property prop)
554 if (prop.getPermission() == IP_WO)
557 auto bvp = prop.getBLOB();
558 auto bp = bvp->at(0);
561 for (
auto &oneConcreteDevice : m_ConcreteDevices)
563 if (!oneConcreteDevice.isNull() && oneConcreteDevice->processBLOB(prop))
567 INDIDataTypes dataType;
569 if (!strcmp(bp->getFormat(),
".ascii"))
570 dataType = DATA_ASCII;
572 dataType = DATA_OTHER;
574 QString currentDir = Options::fitsDir();
578 currentDir.
truncate(
sizeof(currentDir) - 1);
580 QString filename(currentDir +
'/');
587 if (dataType == DATA_ASCII)
591 auto it = std::find_if(streamFileMetadata.begin(), streamFileMetadata.end(), [bvp, bp](
const StreamFileMetadata & data)
593 return (bvp->getDeviceName() == data.device && bvp->getName() == data.property && bp->getName() == data.element);
596 QFile *streamDatafile =
nullptr;
599 if (it == streamFileMetadata.end())
601 StreamFileMetadata metadata;
602 metadata.device = bvp->getDeviceName();
603 metadata.property = bvp->getName();
604 metadata.element = bp->getName();
608 streamDatafile =
new QFile(
this);
609 metadata.file = streamDatafile;
611 streamFileMetadata.append(metadata);
614 streamDatafile = (*it).file;
619 for (nr = 0; nr < bp->getSize(); nr += n)
620 n = out.
writeRawData(
static_cast<char *
>(bp->getBlob()) + nr, bp->getSize() - nr);
623 streamDatafile->
flush();
628 QFile fits_temp_file(filename);
631 qCCritical(KSTARS_INDI) <<
"GenericDevice Error: Unable to open " << fits_temp_file.
fileName();
637 for (nr = 0; nr < bp->getSize(); nr += n)
638 n = out.
writeRawData(
static_cast<char *
>(bp->getBlob()) + nr, bp->getSize() - nr);
640 fits_temp_file.
flush();
641 fits_temp_file.
close();
654 if (dataType == DATA_OTHER)
657 emit propertyUpdated(prop);
661bool GenericDevice::setConfig(INDIConfig tConfig)
663 auto svp = m_BaseDevice.getSwitch(
"CONFIG_PROCESS");
668 const char *strConfig =
nullptr;
672 case LOAD_LAST_CONFIG:
673 strConfig =
"CONFIG_LOAD";
677 strConfig =
"CONFIG_SAVE";
680 case LOAD_DEFAULT_CONFIG:
681 strConfig =
"CONFIG_DEFAULT";
685 strConfig =
"CONFIG_PURGE";
692 auto sp = svp.findWidgetByName(strConfig);
695 sp->setState(ISS_ON);
698 m_ClientManager->sendNewProperty(svp);
703void GenericDevice::createDeviceInit()
705 if (Options::showINDIMessages())
714void GenericDevice::updateTime(
const QString &iso8601,
const QString &utcOffset)
717 auto timeUTC = m_BaseDevice.getText(
"TIME_UTC");
734 auto timeEle = timeUTC.findWidgetByName(
"UTC");
738 auto offsetEle = timeUTC.findWidgetByName(
"OFFSET");
742 if (timeEle && offsetEle)
744 qCInfo(KSTARS_INDI) <<
"Updating" << getDeviceName() <<
"Time UTC:" << isoTS <<
"Offset:" << offset;
745 m_ClientManager->sendNewProperty(timeUTC);
752void GenericDevice::updateLocation(
double longitude,
double latitude,
double elevation)
754 auto nvp = m_BaseDevice.getNumber(
"GEOGRAPHIC_COORD");
761 double longitude_degrees, latitude_degrees, elevation_meters;
763 if (longitude == -1 && latitude == -1 && elevation == -1)
765 longitude_degrees =
geo->lng()->Degrees();
766 latitude_degrees =
geo->lat()->Degrees();
767 elevation_meters =
geo->elevation();
771 longitude_degrees = longitude;
772 latitude_degrees = latitude;
773 elevation_meters = elevation;
776 if (longitude_degrees < 0)
777 longitude_degrees =
dms(longitude_degrees + 360.0).
Degrees();
779 auto np = nvp.findWidgetByName(
"LONG");
784 np->setValue(longitude_degrees);
786 np = nvp.findWidgetByName(
"LAT");
790 np->setValue(latitude_degrees);
792 np = nvp.findWidgetByName(
"ELEV");
796 np->setValue(elevation_meters);
798 qCInfo(KSTARS_INDI) <<
"Updating" << getDeviceName() <<
"Location Longitude:" << longitude_degrees <<
"Latitude:" <<
799 latitude_degrees <<
"Elevation:" << elevation_meters;
801 m_ClientManager->sendNewProperty(nvp);
804void GenericDevice::Connect()
806 m_ClientManager->connectDevice(m_Name.toLatin1().constData());
809void GenericDevice::Disconnect()
811 m_ClientManager->disconnectDevice(m_Name.toLatin1().constData());
814bool GenericDevice::setProperty(
QObject *setPropCommand)
816 GDSetCommand *indiCommand =
static_cast<GDSetCommand *
>(setPropCommand);
820 auto prop = m_BaseDevice.getProperty(indiCommand->indiProperty.toLatin1().constData());
825 switch (indiCommand->propType)
829 auto svp = prop.getSwitch();
834 auto sp = svp->findWidgetByName(indiCommand->indiElement.toLatin1().constData());
839 if (svp->getRule() == ISR_1OFMANY || svp->getRule() == ISR_ATMOST1)
842 sp->setState(indiCommand->elementValue.toInt() == 0 ? ISS_OFF : ISS_ON);
845 m_ClientManager->sendNewProperty(svp);
852 auto nvp = prop.getNumber();
857 auto np = nvp->findWidgetByName(indiCommand->indiElement.toLatin1().constData());
862 double value = indiCommand->elementValue.toDouble();
864 if (value == np->getValue())
870 m_ClientManager->sendNewProperty(nvp);
881bool GenericDevice::getMinMaxStep(
const QString &propName,
const QString &elementName,
double *min,
double *max,
884 auto nvp = m_BaseDevice.getNumber(propName.
toLatin1());
889 auto np = nvp.findWidgetByName(elementName.
toLatin1());
896 *step = np->getStep();
901IPState GenericDevice::getState(
const QString &propName)
906IPerm GenericDevice::getPermission(
const QString &propName)
911INDI::Property GenericDevice::getProperty(
const QString &propName)
916bool GenericDevice::setJSONProperty(
const QString &propName,
const QJsonArray &propElements)
918 for (
auto &oneProp : * (m_BaseDevice.getProperties()))
920 if (propName ==
QString(oneProp.getName()))
922 switch (oneProp.getType())
926 auto svp = oneProp.getSwitch();
927 if (svp->getRule() == ISR_1OFMANY || svp->getRule() == ISR_ATMOST1)
930 for (
auto oneElement : propElements)
932 QJsonObject oneElementObject = oneElement.toObject();
933 auto sp = svp->findWidgetByName(oneElementObject[
"name"].
toString().toLatin1().constData());
936 sp->setState(
static_cast<ISState
>(oneElementObject[
"state"].toInt()));
940 m_ClientManager->sendNewProperty(svp);
946 auto nvp = oneProp.getNumber();
947 for (
const auto &oneElement : propElements)
949 QJsonObject oneElementObject = oneElement.toObject();
950 auto np = nvp->findWidgetByName(oneElementObject[
"name"].
toString().toLatin1().constData());
953 double newValue = oneElementObject[
"value"].toDouble(std::numeric_limits<double>::quiet_NaN());
954 if (std::isnan(newValue))
956 f_scansexa(oneElementObject[
"value"].
toString().toLatin1().constData(), &newValue);
958 np->setValue(newValue);
962 m_ClientManager->sendNewProperty(nvp);
968 auto tvp = oneProp.getText();
969 for (
const auto &oneElement : propElements)
971 QJsonObject oneElementObject = oneElement.toObject();
972 auto tp = tvp->findWidgetByName(oneElementObject[
"name"].
toString().toLatin1().constData());
974 tp->setText(oneElementObject[
"text"].
toString().toLatin1().constData());
977 m_ClientManager->sendNewProperty(tvp);
994bool GenericDevice::getJSONProperty(
const QString &propName,
QJsonObject &propObject,
bool compact)
996 for (
auto oneProp : m_BaseDevice.getProperties())
998 if (propName == oneProp.getName())
1000 switch (oneProp.getType())
1003 switchToJson(oneProp, propObject, compact);
1007 numberToJson(oneProp, propObject, compact);
1011 textToJson(oneProp, propObject, compact);
1015 lightToJson(oneProp, propObject, compact);
1034 if (!blobProperty.isValid())
1037 auto oneBLOB = blobProperty.getBLOB()->findWidgetByName(elementName.
toLatin1().
constData());
1045 blobObject.
insert(
"property", propName);
1046 blobObject.
insert(
"element", elementName);
1048 blobObject.
insert(
"data", encoded);
1053void GenericDevice::resetWatchdog()
1055 auto nvp = m_BaseDevice.getNumber(
"WATCHDOG_HEARTBEAT");
1059 m_ClientManager->sendNewProperty(nvp);
1064 if (m_ConcreteDevices.contains(interface))
1066 device = m_ConcreteDevices[interface];
1074 if (m_ConcreteDevices.contains(INDI::BaseDevice::TELESCOPE_INTERFACE))
1075 return dynamic_cast<ISD::Mount*
>(m_ConcreteDevices[INDI::BaseDevice::TELESCOPE_INTERFACE].get());
1081 if (m_ConcreteDevices.contains(INDI::BaseDevice::CCD_INTERFACE))
1082 return dynamic_cast<ISD::Camera*
>(m_ConcreteDevices[INDI::BaseDevice::CCD_INTERFACE].get());
1086ISD::Guider *GenericDevice::getGuider()
1088 if (m_ConcreteDevices.contains(INDI::BaseDevice::GUIDER_INTERFACE))
1089 return dynamic_cast<ISD::Guider*
>(m_ConcreteDevices[INDI::BaseDevice::GUIDER_INTERFACE].get());
1095 if (m_ConcreteDevices.contains(INDI::BaseDevice::FOCUSER_INTERFACE))
1096 return dynamic_cast<ISD::Focuser*
>(m_ConcreteDevices[INDI::BaseDevice::FOCUSER_INTERFACE].get());
1100ISD::FilterWheel *GenericDevice::getFilterWheel()
1102 if (m_ConcreteDevices.contains(INDI::BaseDevice::FILTER_INTERFACE))
1103 return dynamic_cast<ISD::FilterWheel*
>(m_ConcreteDevices[INDI::BaseDevice::FILTER_INTERFACE].get());
1109 if (m_ConcreteDevices.contains(INDI::BaseDevice::DOME_INTERFACE))
1110 return dynamic_cast<ISD::Dome*
>(m_ConcreteDevices[INDI::BaseDevice::DOME_INTERFACE].get());
1114ISD::GPS *GenericDevice::getGPS()
1116 if (m_ConcreteDevices.contains(INDI::BaseDevice::GPS_INTERFACE))
1117 return dynamic_cast<ISD::GPS*
>(m_ConcreteDevices[INDI::BaseDevice::GPS_INTERFACE].get());
1123 if (m_ConcreteDevices.contains(INDI::BaseDevice::WEATHER_INTERFACE))
1124 return dynamic_cast<ISD::Weather*
>(m_ConcreteDevices[INDI::BaseDevice::WEATHER_INTERFACE].get());
1130 if (m_ConcreteDevices.contains(INDI::BaseDevice::AO_INTERFACE))
1131 return dynamic_cast<ISD::AdaptiveOptics*
>(m_ConcreteDevices[INDI::BaseDevice::AO_INTERFACE].get());
1137 if (m_ConcreteDevices.contains(INDI::BaseDevice::DUSTCAP_INTERFACE))
1138 return dynamic_cast<ISD::DustCap*
>(m_ConcreteDevices[INDI::BaseDevice::DUSTCAP_INTERFACE].get());
1144 if (m_ConcreteDevices.contains(INDI::BaseDevice::LIGHTBOX_INTERFACE))
1145 return dynamic_cast<ISD::LightBox*
>(m_ConcreteDevices[INDI::BaseDevice::LIGHTBOX_INTERFACE].get());
1151 if (m_ConcreteDevices.contains(INDI::BaseDevice::DETECTOR_INTERFACE))
1152 return dynamic_cast<ISD::Detector*
>(m_ConcreteDevices[INDI::BaseDevice::DETECTOR_INTERFACE].get());
1158 if (m_ConcreteDevices.contains(INDI::BaseDevice::ROTATOR_INTERFACE))
1159 return dynamic_cast<ISD::Rotator*
>(m_ConcreteDevices[INDI::BaseDevice::ROTATOR_INTERFACE].get());
1165 if (m_ConcreteDevices.contains(INDI::BaseDevice::SPECTROGRAPH_INTERFACE))
1166 return dynamic_cast<ISD::Spectrograph*
>(m_ConcreteDevices[INDI::BaseDevice::SPECTROGRAPH_INTERFACE].get());
1172 if (m_ConcreteDevices.contains(INDI::BaseDevice::CORRELATOR_INTERFACE))
1173 return dynamic_cast<ISD::Correlator*
>(m_ConcreteDevices[INDI::BaseDevice::CORRELATOR_INTERFACE].get());
1179 if (m_ConcreteDevices.contains(INDI::BaseDevice::AUX_INTERFACE))
1180 return dynamic_cast<ISD::Auxiliary*
>(m_ConcreteDevices[INDI::BaseDevice::AUX_INTERFACE].get());
1184bool GenericDevice::generateDevices()
1186 auto generated =
false;
1188 if (m_DriverInterface & INDI::BaseDevice::TELESCOPE_INTERFACE &&
1189 m_ConcreteDevices[INDI::BaseDevice::TELESCOPE_INTERFACE].isNull())
1194 m_ConcreteDevices[INDI::BaseDevice::TELESCOPE_INTERFACE].reset(mount);
1195 mount->registeProperties();
1198 mount->processProperties();
1200 emit newMount(mount);
1204 connect(mount, &ISD::ConcreteDevice::ready,
this, [
this, mount]()
1209 emit newMount(mount);
1216 if (m_DriverInterface & INDI::BaseDevice::CCD_INTERFACE &&
1217 m_ConcreteDevices[INDI::BaseDevice::CCD_INTERFACE].isNull())
1220 camera->setObjectName(
"Camera:" + objectName());
1222 m_ConcreteDevices[INDI::BaseDevice::CCD_INTERFACE].reset(camera);
1223 camera->registeProperties();
1226 camera->processProperties();
1227 camera->setProperty(
"dispatched",
true);
1228 emit newCamera(camera);
1233 connect(camera, &ISD::ConcreteDevice::ready,
this, [
this, camera]()
1235 if (!camera->property(
"dispatched").isValid())
1237 camera->setProperty(
"dispatched",
true);
1238 emit newCamera(camera);
1245 if (m_DriverInterface & INDI::BaseDevice::GUIDER_INTERFACE &&
1246 m_ConcreteDevices[INDI::BaseDevice::GUIDER_INTERFACE].isNull())
1248 auto guider =
new ISD::Guider(
this);
1249 guider->setObjectName(
"Guider:" + objectName());
1251 m_ConcreteDevices[INDI::BaseDevice::GUIDER_INTERFACE].reset(guider);
1252 guider->registeProperties();
1255 guider->processProperties();
1256 guider->setProperty(
"dispatched",
true);
1257 emit newGuider(guider);
1261 connect(guider, &ISD::ConcreteDevice::ready,
this, [
this, guider]()
1263 if (!guider->property(
"dispatched").isValid())
1265 guider->setProperty(
"dispatched",
true);
1266 emit newGuider(guider);
1273 if (m_DriverInterface & INDI::BaseDevice::FOCUSER_INTERFACE &&
1274 m_ConcreteDevices[INDI::BaseDevice::FOCUSER_INTERFACE].isNull())
1277 focuser->setObjectName(
"Focuser:" + objectName());
1279 m_ConcreteDevices[INDI::BaseDevice::FOCUSER_INTERFACE].reset(focuser);
1280 focuser->registeProperties();
1283 focuser->processProperties();
1284 focuser->setProperty(
"dispatched",
true);
1285 emit newFocuser(focuser);
1289 connect(focuser, &ISD::ConcreteDevice::ready,
this, [
this, focuser]()
1291 if (!focuser->property(
"dispatched").isValid())
1293 focuser->setProperty(
"dispatched",
true);
1294 emit newFocuser(focuser);
1301 if (m_DriverInterface & INDI::BaseDevice::FILTER_INTERFACE &&
1302 m_ConcreteDevices[INDI::BaseDevice::FILTER_INTERFACE].isNull())
1304 auto filterWheel =
new ISD::FilterWheel(
this);
1305 filterWheel->setObjectName(
"FilterWheel:" + objectName());
1307 m_ConcreteDevices[INDI::BaseDevice::FILTER_INTERFACE].reset(filterWheel);
1308 filterWheel->registeProperties();
1311 filterWheel->processProperties();
1312 filterWheel->setProperty(
"dispatched",
true);
1313 emit newFilterWheel(filterWheel);
1317 connect(filterWheel, &ISD::ConcreteDevice::ready,
this, [
this, filterWheel]()
1319 if (!filterWheel->property(
"dispatched").isValid())
1321 filterWheel->setProperty(
"dispatched",
true);
1322 emit newFilterWheel(filterWheel);
1329 if (m_DriverInterface & INDI::BaseDevice::DOME_INTERFACE &&
1330 m_ConcreteDevices[INDI::BaseDevice::DOME_INTERFACE].isNull())
1333 dome->setObjectName(
"Dome:" + objectName());
1335 m_ConcreteDevices[INDI::BaseDevice::DOME_INTERFACE].reset(dome);
1336 dome->registeProperties();
1339 dome->processProperties();
1340 dome->setProperty(
"dispatched",
true);
1345 connect(dome, &ISD::ConcreteDevice::ready,
this, [
this, dome]()
1347 if (!dome->property(
"dispatched").isValid())
1349 dome->setProperty(
"dispatched",
true);
1357 if (m_DriverInterface & INDI::BaseDevice::GPS_INTERFACE &&
1358 m_ConcreteDevices[INDI::BaseDevice::GPS_INTERFACE].isNull())
1360 auto gps =
new ISD::GPS(
this);
1361 gps->setObjectName(
"GPS:" + objectName());
1363 m_ConcreteDevices[INDI::BaseDevice::GPS_INTERFACE].reset(gps);
1364 gps->registeProperties();
1367 gps->processProperties();
1368 gps->setProperty(
"dispatched",
true);
1373 connect(gps, &ISD::ConcreteDevice::ready,
this, [
this, gps]()
1375 if (!gps->property(
"dispatched").isValid())
1377 gps->setProperty(
"dispatched",
true);
1385 if (m_DriverInterface & INDI::BaseDevice::WEATHER_INTERFACE &&
1386 m_ConcreteDevices[INDI::BaseDevice::WEATHER_INTERFACE].isNull())
1389 weather->setObjectName(
"Weather:" + objectName());
1391 m_ConcreteDevices[INDI::BaseDevice::WEATHER_INTERFACE].reset(weather);
1392 weather->registeProperties();
1395 weather->processProperties();
1396 weather->setProperty(
"dispatched",
true);
1397 emit newWeather(weather);
1401 connect(weather, &ISD::ConcreteDevice::ready,
this, [
this, weather]()
1403 if (!weather->property(
"dispatched").isValid())
1405 weather->setProperty(
"dispatched",
true);
1406 emit newWeather(weather);
1413 if (m_DriverInterface & INDI::BaseDevice::AO_INTERFACE &&
1414 m_ConcreteDevices[INDI::BaseDevice::AO_INTERFACE].isNull())
1417 ao->setObjectName(
"AdaptiveOptics:" + objectName());
1419 m_ConcreteDevices[INDI::BaseDevice::AO_INTERFACE].reset(ao);
1420 ao->registeProperties();
1423 ao->processProperties();
1424 ao->setProperty(
"dispatched",
true);
1425 emit newAdaptiveOptics(ao);
1429 connect(ao, &ISD::ConcreteDevice::ready,
this, [
this, ao]()
1431 if (!ao->property(
"dispatched").isValid())
1433 ao->setProperty(
"dispatched",
true);
1434 emit newAdaptiveOptics(ao);
1441 if (m_DriverInterface & INDI::BaseDevice::DUSTCAP_INTERFACE &&
1442 m_ConcreteDevices[INDI::BaseDevice::DUSTCAP_INTERFACE].isNull())
1445 dustCap->setObjectName(
"DustCap:" + objectName());
1447 m_ConcreteDevices[INDI::BaseDevice::DUSTCAP_INTERFACE].reset(dustCap);
1448 dustCap->registeProperties();
1451 dustCap->processProperties();
1452 dustCap->setProperty(
"dispatched",
true);
1453 emit newDustCap(dustCap);
1457 connect(dustCap, &ISD::ConcreteDevice::ready,
this, [
this, dustCap]()
1459 if (!dustCap->property(
"dispatched").isValid())
1461 dustCap->setProperty(
"dispatched",
true);
1462 emit newDustCap(dustCap);
1469 if (m_DriverInterface & INDI::BaseDevice::LIGHTBOX_INTERFACE &&
1470 m_ConcreteDevices[INDI::BaseDevice::LIGHTBOX_INTERFACE].isNull())
1473 lightBox->setObjectName(
"LightBox:" + objectName());
1475 m_ConcreteDevices[INDI::BaseDevice::LIGHTBOX_INTERFACE].reset(lightBox);
1476 lightBox->registeProperties();
1479 lightBox->processProperties();
1480 lightBox->setProperty(
"dispatched",
true);
1481 emit newLightBox(lightBox);
1485 connect(lightBox, &ISD::ConcreteDevice::ready,
this, [
this, lightBox]()
1487 if (!lightBox->property(
"dispatched").isValid())
1489 lightBox->setProperty(
"dispatched",
true);
1490 emit newLightBox(lightBox);
1497 if (m_DriverInterface & INDI::BaseDevice::ROTATOR_INTERFACE &&
1498 m_ConcreteDevices[INDI::BaseDevice::ROTATOR_INTERFACE].isNull())
1501 rotator->setObjectName(
"Rotator:" + objectName());
1503 m_ConcreteDevices[INDI::BaseDevice::ROTATOR_INTERFACE].reset(rotator);
1504 rotator->registeProperties();
1507 rotator->processProperties();
1508 rotator->setProperty(
"dispatched",
true);
1509 emit newRotator(rotator);
1513 connect(rotator, &ISD::ConcreteDevice::ready,
this, [
this, rotator]()
1515 if (!rotator->property(
"dispatched").isValid())
1517 rotator->setProperty(
"dispatched",
true);
1518 emit newRotator(rotator);
1525 if (m_DriverInterface & INDI::BaseDevice::DETECTOR_INTERFACE &&
1526 m_ConcreteDevices[INDI::BaseDevice::DETECTOR_INTERFACE].isNull())
1529 detector->setObjectName(
"Detector:" + objectName());
1531 m_ConcreteDevices[INDI::BaseDevice::DETECTOR_INTERFACE].reset(detector);
1532 detector->registeProperties();
1535 detector->processProperties();
1536 detector->setProperty(
"dispatched",
true);
1537 emit newDetector(detector);
1541 connect(detector, &ISD::ConcreteDevice::ready,
this, [
this, detector]()
1543 if (!detector->property(
"dispatched").isValid())
1545 detector->setProperty(
"dispatched",
true);
1546 emit newDetector(detector);
1553 if (m_DriverInterface & INDI::BaseDevice::SPECTROGRAPH_INTERFACE &&
1554 m_ConcreteDevices[INDI::BaseDevice::SPECTROGRAPH_INTERFACE].isNull())
1557 spectrograph->setObjectName(
"Spectrograph:" + objectName());
1559 m_ConcreteDevices[INDI::BaseDevice::SPECTROGRAPH_INTERFACE].reset(spectrograph);
1560 spectrograph->registeProperties();
1563 spectrograph->processProperties();
1564 spectrograph->setProperty(
"dispatched",
true);
1565 emit newSpectrograph(spectrograph);
1569 connect(spectrograph, &ISD::ConcreteDevice::ready,
this, [
this, spectrograph]()
1571 if (!spectrograph->property(
"dispatched").isValid())
1573 spectrograph->setProperty(
"dispatched",
true);
1574 emit newSpectrograph(spectrograph);
1581 if (m_DriverInterface & INDI::BaseDevice::CORRELATOR_INTERFACE &&
1582 m_ConcreteDevices[INDI::BaseDevice::CORRELATOR_INTERFACE].isNull())
1585 correlator->setObjectName(
"Correlator:" + objectName());
1587 m_ConcreteDevices[INDI::BaseDevice::CORRELATOR_INTERFACE].reset(correlator);
1588 correlator->registeProperties();
1591 correlator->processProperties();
1592 correlator->setProperty(
"dispatched",
true);
1593 emit newCorrelator(correlator);
1597 connect(correlator, &ISD::ConcreteDevice::ready,
this, [
this, correlator]()
1599 if (!correlator->property(
"dispatched").isValid())
1601 correlator->setProperty(
"dispatched",
true);
1602 emit newCorrelator(correlator);
1609 if (m_DriverInterface & INDI::BaseDevice::AUX_INTERFACE &&
1610 m_ConcreteDevices[INDI::BaseDevice::AUX_INTERFACE].isNull())
1613 aux->setObjectName(
"Auxiliary:" + objectName());
1615 m_ConcreteDevices[INDI::BaseDevice::AUX_INTERFACE].reset(aux);
1616 aux->registeProperties();
1619 aux->processProperties();
1620 aux->setProperty(
"dispatched",
true);
1621 emit newAuxiliary(aux);
1625 connect(aux, &ISD::ConcreteDevice::ready,
this, [
this, aux]()
1627 if (!aux->property(
"dispatched").isValid())
1629 aux->setProperty(
"dispatched",
true);
1630 emit newAuxiliary(aux);
1639void GenericDevice::sendNewProperty(INDI::Property prop)
1644void switchToJson(INDI::Property prop,
QJsonObject &propObject,
bool compact)
1646 auto svp = prop.getSwitch();
1648 for (
int i = 0; i < svp->count(); i++)
1650 QJsonObject oneSwitch = {{
"name", svp->at(i)->getName()}, {
"state", svp->at(i)->getState()}};
1652 oneSwitch.
insert(
"label", svp->at(i)->getLabel());
1653 switches.
append(oneSwitch);
1656 propObject = {{
"device", svp->getDeviceName()}, {
"name", svp->getName()}, {
"state", svp->getState()}, {
"switches", switches}};
1659 propObject.
insert(
"label", svp->getLabel());
1660 propObject.
insert(
"group", svp->getGroupName());
1661 propObject.
insert(
"perm", svp->getPermission());
1662 propObject.
insert(
"rule", svp->getRule());
1666void numberToJson(INDI::Property prop,
QJsonObject &propObject,
bool compact)
1668 auto nvp = prop.getNumber();
1670 for (
int i = 0; i < nvp->count(); i++)
1672 QJsonObject oneNumber = {{
"name", nvp->at(i)->getName()}, {
"value", nvp->at(i)->getValue()}};
1675 oneNumber.
insert(
"label", nvp->at(i)->getLabel());
1676 oneNumber.
insert(
"min", nvp->at(i)->getMin());
1677 oneNumber.
insert(
"max", nvp->at(i)->getMax());
1678 oneNumber.
insert(
"step", nvp->at(i)->getStep());
1679 oneNumber.
insert(
"format", nvp->at(i)->getFormat());
1681 numbers.
append(oneNumber);
1684 propObject = {{
"device", nvp->getDeviceName()}, {
"name", nvp->getName()}, {
"state", nvp->getState()}, {
"numbers", numbers}};
1687 propObject.
insert(
"label", nvp->getLabel());
1688 propObject.
insert(
"group", nvp->getGroupName());
1689 propObject.
insert(
"perm", nvp->getPermission());
1693void textToJson(INDI::Property prop,
QJsonObject &propObject,
bool compact)
1695 auto tvp = prop.getText();
1697 for (
int i = 0; i < tvp->count(); i++)
1699 QJsonObject oneText = {{
"name", tvp->at(i)->getName()}, {
"text", tvp->at(i)->getText()}};
1702 oneText.
insert(
"label", tvp->at(i)->getLabel());
1707 propObject = {{
"device", tvp->getDeviceName()}, {
"name", tvp->getName()}, {
"state", tvp->getState()}, {
"texts", Texts}};
1710 propObject.
insert(
"label", tvp->getLabel());
1711 propObject.
insert(
"group", tvp->getGroupName());
1712 propObject.
insert(
"perm", tvp->getPermission());
1716void lightToJson(INDI::Property prop,
QJsonObject &propObject,
bool compact)
1718 auto lvp = prop.getLight();
1720 for (
int i = 0; i < lvp->count(); i++)
1722 QJsonObject oneLight = {{
"name", lvp->at(i)->getName()}, {
"state", lvp->at(i)->getState()}};
1725 oneLight.
insert(
"label", lvp->at(i)->getLabel());
1730 propObject = {{
"device", lvp->getDeviceName()}, {
"name", lvp->getName()}, {
"state", lvp->getState()}, {
"lights", Lights}};
1733 propObject.
insert(
"label", lvp->getLabel());
1734 propObject.
insert(
"group", lvp->getGroupName());
1738void propertyToJson(INDI::Property prop,
QJsonObject &propObject,
bool compact)
1740 switch (prop.getType())
1743 switchToJson(prop, propObject, compact);
1746 textToJson(prop, propObject, compact);
1749 numberToJson(prop, propObject, compact);
1752 lightToJson(prop, propObject, compact);
1764 argument << static_cast<int>(source);
1775 dest =
static_cast<ISD::ParkStatus
>(a);
ClientManager manages connection to INDI server, creation of devices, and receiving/sending propertie...
DeviceInfo is simple class to hold DriverInfo and INDI::BaseDevice associated with a particular devic...
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
AdaptiveOptics class handles control of INDI AdaptiveOptics devices.
Auxiliary class handles control of INDI Auxiliary devices.
Camera class controls an INDI Camera device.
void sendNewProperty(INDI::Property prop)
Send new property command to server.
Correlator class handles control of INDI Correlator devices.
Detector class handles control of INDI Detector devices.
Class handles control of INDI dome devices.
Handles operation of a remotely controlled dust cover cap.
Focuser class handles control of INDI focuser devices.
Handles operation of a remotely controlled light box.
device handle controlling Mounts.
Rotator class handles control of INDI Rotator devices.
Spectrograph class handles control of INDI Spectrograph devices.
Focuser class handles control of INDI Weather devices.
void setLocation(const GeoLocation &l)
Set the GeoLocation according to the argument.
void changeDateTime(const KStarsDateTime &newDate)
Change the current simulation date/time to the KStarsDateTime argument.
void syncLST()
Sync the LST with the simulation clock.
const KStarsDateTime & ut() const
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
static KStars * Instance()
KStarsData * data() const
void timeChanged()
The time has changed (emitted by setUTC() )
void forceUpdateNow()
Convenience function; simply calls forceUpdate(true).
This class provides the information needed to determine whether Daylight Savings Time (DST; a....
An angle, stored as degrees, but expressible in many ways.
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
virtual void setD(const double &x)
Sets floating-point value of angle, in degrees.
const double & Degrees() const
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
ISD is a collection of INDI Standard Devices.
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
GeoCoordinates geo(const QVariant &location)
QString name(StandardAction id)
QDebug operator<<(QDebug dbg, const PerceptualColor::MultiSpinBoxSection &value)
QCA_EXPORT QVariant getProperty(const QString &name)
const char * constData() const const
QByteArray fromRawData(const char *data, qsizetype size)
QByteArray toBase64(Base64Options options) const const
int writeRawData(const char *s, int len)
bool setDate(int year, int month, int day)
QDateTime currentDateTime()
QString toString(QStringView format, QCalendar cal) const const
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
virtual QString fileName() const const override
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
virtual void close() override
void append(const QJsonValue &value)
iterator insert(QLatin1StringView key, const QJsonValue &value)
QStatusBar * statusBar() const const
QVariant property(const char *name) const const
void setObjectName(QAnyStringView name)
bool setProperty(const char *name, QVariant &&value)
void showMessage(const QString &message, int timeout)
QString arg(Args &&... args) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & setNum(double n, char format, int precision)
qsizetype size() const const
QByteArray toLatin1() const const
QString toLower() const const
QByteArray toUtf8() const const
QString trimmed() const const
void truncate(qsizetype position)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool setHMS(int h, int m, int s, int ms)
void setScheme(const QString &scheme)
bool isValid() const const