29 #define DOWNLOAD_TAB "Download images"
30 #define IMAGE_NAME "%s/%s_%d_%03d%s"
31 #define IMAGE_PREFIX "_TMP_"
34 #define GROUP_PREFIX "GROUP_"
35 #define GROUP_PREFIX_LEN 6
48 std::generate(groups.begin(), groups.end(), [
this, &i] { return std::make_shared<Group>(i++, this); });
51 bool Imager::isRunning()
56 bool Imager::isCCDConnected()
58 return StatusL[0].s ==
IPS_OK;
61 bool Imager::isFilterConnected()
63 return StatusL[1].s ==
IPS_OK;
66 std::shared_ptr<Group> Imager::getGroup(
int index)
const
68 if(index > -1 && index <= maxGroup)
73 std::shared_ptr<Group> Imager::currentGroup()
const
75 return getGroup(group - 1);
80 std::shared_ptr<Group> Imager::nextGroup()
const
82 return getGroup(group);
85 void Imager::initiateNextFilter()
90 if (group > 0 && image > 0 && group <= maxGroup && image <= maxImage)
92 int filterSlot = currentGroup()->filterSlot();
94 if (!isFilterConnected())
99 IDSetNumber(&ProgressNP,
"Filter wheel is not connected");
104 initiateNextCapture();
107 else if (filterSlot != 0 && FilterSlotN[0].value != filterSlot)
109 FilterSlotN[0].value = filterSlot;
111 LOGF_DEBUG(
"Group %d of %d, image %d of %d, filer %d, filter set initiated on %s",
112 group, maxGroup, image, maxImage, (
int)FilterSlotN[0].value, FilterSlotNP.
device);
116 initiateNextCapture();
121 void Imager::initiateNextCapture()
125 if (group > 0 && image > 0 && group <= maxGroup && image <= maxImage)
127 if (!isCCDConnected())
133 CCDImageBinN[0].value = currentGroup()->binning();
134 CCDImageBinN[1].value = currentGroup()->binning();
136 CCDImageExposureN[0].value = currentGroup()->exposure();
138 IUSaveText(&CCDUploadSettingsT[0], ImageNameT[0].text);
142 LOGF_DEBUG(
"Group %d of %d, image %d of %d, duration %.1fs, binning %d, capture initiated on %s", group,
143 maxGroup, image, maxImage, CCDImageExposureN[0].value, (
int)CCDImageBinN[0].value,
144 CCDImageExposureNP.
device);
149 void Imager::startBatch()
152 ProgressN[0].value = group = 1;
153 ProgressN[1].value = image = 1;
154 maxImage = currentGroup()->count();
157 initiateNextFilter();
160 void Imager::abortBatch()
166 void Imager::batchDone()
172 void Imager::initiateDownload()
174 int group = (int)DownloadN[0].value;
175 int image = (int)DownloadN[1].value;
176 char name[128] = {0};
179 if (group == 0 || image == 0)
182 sprintf(name,
IMAGE_NAME, ImageNameT[0].text, ImageNameT[1].text, group, image, format);
183 file.open(name, std::ios::in | std::ios::binary | std::ios::ate);
184 DownloadN[0].value = 0;
185 DownloadN[1].value = 0;
188 long size = file.tellg();
189 char *data =
new char[size];
191 file.seekg(0, std::ios::beg);
192 file.read(data, size);
195 LOGF_DEBUG(
"Group %d, image %d, download initiated", group, image);
199 FitsB[0].blob = data;
200 FitsB[0].bloblen = FitsB[0].size = size;
210 LOGF_DEBUG(
"Group %d, image %d, upload failed", group, image);
231 IUFillText(&ControlledDeviceT[0],
"CCD",
"CCD",
"CCD Simulator");
232 IUFillText(&ControlledDeviceT[1],
"FILTER",
"Filter wheel",
"Filter Simulator");
235 controlledCCD = ControlledDeviceT[0].text;
236 controlledFilterWheel = ControlledDeviceT[1].text;
243 IUFillNumber(&ProgressN[1],
"IMAGE",
"Current image",
"%3.0f", 1, 100, 1, 0);
244 IUFillNumber(&ProgressN[2],
"REMAINING_TIME",
"Remaining time",
"%5.2f", 0, 36000, 0, 0.0);
253 IUFillText(&ImageNameT[0],
"IMAGE_FOLDER",
"Image folder",
"/tmp");
254 IUFillText(&ImageNameT[1],
"IMAGE_PREFIX",
"Image prefix",
"IMG");
259 IUFillNumber(&DownloadN[1],
"IMAGE",
"Image",
"%3.0f", 1, 100, 1, 1);
270 for (
int i = 0; i < GroupCountN[0].value; i++)
272 groups[i]->defineProperties();
275 IUFillNumber(&CCDImageExposureN[0],
"CCD_EXPOSURE_VALUE",
"Duration (s)",
"%5.2f", 0, 36000, 0, 1.0);
276 IUFillNumberVector(&CCDImageExposureNP, CCDImageExposureN, 1, ControlledDeviceT[0].text,
"CCD_EXPOSURE",
"Expose",
279 IUFillNumber(&CCDImageBinN[0],
"HOR_BIN",
"X",
"%2.0f", 1, 4, 1, 1);
280 IUFillNumber(&CCDImageBinN[1],
"VER_BIN",
"Y",
"%2.0f", 1, 4, 1, 1);
281 IUFillNumberVector(&CCDImageBinNP, CCDImageBinN, 2, ControlledDeviceT[0].text,
"CCD_BINNING",
"Binning",
290 IUFillText(&CCDUploadSettingsT[0],
"UPLOAD_DIR",
"Dir",
"");
292 IUFillTextVector(&CCDUploadSettingsTP, CCDUploadSettingsT, 2, ControlledDeviceT[0].text,
"UPLOAD_SETTINGS",
295 IUFillNumber(&FilterSlotN[0],
"FILTER_SLOT_VALUE",
"Filter",
"%3.0f", 1.0, 12.0, 1.0, 1.0);
296 IUFillNumberVector(&FilterSlotNP, FilterSlotN, 1, ControlledDeviceT[1].text,
"FILTER_SLOT",
"Filter Slot",
307 ProgressN[0].value = group = 0;
308 ProgressN[1].value = image = 0;
313 DownloadN[0].value = 0;
314 DownloadN[1].value = 0;
340 if (std::string{name} == std::string{GroupCountNP.
name})
342 for (
int i = 0; i < maxGroup; i++)
343 groups[i]->deleteProperties();
345 maxGroup = (int)GroupCountN[0].value;
348 for (
int i = 0; i < maxGroup; i++)
349 groups[i]->defineProperties();
354 if (std::string{name} == std::string{DownloadNP.
name})
362 for (
int i = 0; i < GroupCountN[0].value; i++)
363 if (groups[i]->
ISNewNumber(dev, name, values, names, n))
377 if (std::string{name} == std::string{BatchSP.
name})
379 for (
int i = 0; i < n; i++)
381 if (strcmp(names[i], BatchS[0].name) == 0 && states[i] ==
ISS_ON)
386 if (strcmp(names[i], BatchS[1].name) == 0 && states[i] ==
ISS_ON)
404 if (std::string{name} == std::string{ControlledDeviceTP.
name})
408 strncpy(StatusL[0].label, ControlledDeviceT[0].text,
sizeof(StatusL[0].label));
409 strncpy(CCDImageExposureNP.
device, ControlledDeviceT[0].text,
sizeof(CCDImageExposureNP.
device));
410 strncpy(CCDImageBinNP.
device, ControlledDeviceT[0].text,
sizeof(CCDImageBinNP.
device));
411 strncpy(StatusL[1].label, ControlledDeviceT[1].text,
sizeof(StatusL[1].label));
412 strncpy(FilterSlotNP.
device, ControlledDeviceT[1].text,
sizeof(FilterSlotNP.
device));
415 if (std::string{name} == std::string{ImageNameTP.
name})
425 bool Imager::ISNewBLOB(
const char *dev,
const char *name,
int sizes[],
int blobsizes[],
char *blobs[],
char *formats[],
426 char *names[],
int n)
439 BaseClient::watchDevice(controlledCCD);
440 BaseClient::watchDevice(controlledFilterWheel);
469 LOGF_DEBUG(
"Device %s detected", deviceName.c_str());
470 if (deviceName == controlledCCD)
472 if (deviceName == controlledFilterWheel)
480 std::string deviceName{
property.getDeviceName()};
485 if (deviceName == controlledCCD)
497 if (deviceName == controlledFilterWheel)
506 LOGF_DEBUG(
"Connecting %s", controlledFilterWheel);
515 std::string deviceName{
property.getDeviceName()};
523 char name[128] = {0};
526 strncpy(format, bp.getFormat(), 16);
527 sprintf(name,
IMAGE_NAME, ImageNameT[0].text, ImageNameT[1].text, group, image, format);
528 file.open(name, std::ios::out | std::ios::binary | std::ios::trunc);
529 file.write(
static_cast<char *
>(bp.getBlob()), bp.getBlobLen());
531 LOGF_DEBUG(
"Group %d of %d, image %d of %d, saved to %s", group, maxGroup, image, maxImage,
533 if (image == maxImage)
535 if (group == maxGroup)
541 maxImage = nextGroup()->count();
542 ProgressN[0].value = group = group + 1;
543 ProgressN[1].value = image = 1;
545 initiateNextFilter();
550 ProgressN[1].value = image = image + 1;
552 initiateNextFilter();
564 if (deviceName == controlledCCD)
569 if (deviceName == controlledFilterWheel)
577 if (deviceName == controlledCCD && property.
isNameMatch(
"CCD_EXPOSURE"))
580 ProgressN[2].value = propertyNumber[0].getValue();
585 if (deviceName == controlledFilterWheel && property.
isNameMatch(
"FILTER_SLOT"))
588 FilterSlotN[0].value = propertyNumber[0].getValue();
590 initiateNextCapture();
594 if (deviceName == controlledCCD && property.
isNameMatch(
"CCD_FILE_PATH"))
597 char name[128] = {0};
599 strncpy(format, strrchr(propertyText[0].
getText(),
'.'),
sizeof(format));
600 sprintf(name,
IMAGE_NAME, ImageNameT[0].text, ImageNameT[1].text, group, image, format);
601 rename(propertyText[0].
getText(), name);
602 LOGF_DEBUG(
"Group %d of %d, image %d of %d, saved to %s", group, maxGroup, image,
604 if (image == maxImage)
606 if (group == maxGroup)
612 maxImage = nextGroup()->count();
613 ProgressN[0].value = group = group + 1;
614 ProgressN[1].value = image = 1;
616 initiateNextFilter();
621 ProgressN[1].value = image = image + 1;
623 initiateNextFilter();
std::shared_ptr< Imager > imager(new Imager())
void setServer(const char *hostname, unsigned int port)
Set the server host name and port.
void sendNewSwitch(INDI::Property pp)
Send new Switch command to server.
void setBLOBMode(BLOBHandling blobH, const char *dev, const char *prop=nullptr)
Set Binary Large Object policy mode.
void connectDevice(const char *deviceName)
Disconnect INDI driver.
void sendNewNumber(INDI::Property pp)
Send new Number command to server.
void sendNewText(INDI::Property pp)
Send new Text command to server.
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.
Class to provide basic INDI device functionality.
const char * getDeviceName() const
INDI::PropertyText getText(const char *name) const
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Process the client newBLOB command.
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
Provides generic container for INDI properties.
bool isNameMatch(const char *otherName) const
INDI_PROPERTY_TYPE getType() const
virtual void updateProperty(INDI::Property property) override
Emmited when a new property value arrives from INDI server.
static const std::string DEVICE_NAME
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual const char * getDefaultName() override
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual void serverConnected() override
Emmited when the server is connected.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual void newDevice(INDI::BaseDevice baseDevice) override
Emmited when a new device is created from INDI server.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool Disconnect() override
Disconnect from device.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual void serverDisconnected(int exit_code) override
Emmited when the server gets disconnected.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISSnoopDevice(XMLEle *root) override
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
virtual void newProperty(INDI::Property property) override
Emmited when a new property is created for an INDI driver.
virtual bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) override
Process the client newBLOB command.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
void ISGetProperties(const char *dev)
Get Device Properties.
void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
void IUFillBLOBVector(IBLOBVectorProperty *bvp, IBLOB *bp, int nbp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a BLOB vector property. The vector's auxiliary elements will be set to NULL.
void IUFillBLOB(IBLOB *bp, const char *name, const char *label, const char *format)
Assign attributes for a BLOB property. The BLOB's data and auxiliary elements will be set to NULL.
void IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
void IDSetBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define LOGF_DEBUG(fmt,...)
const char * CONNECTION
Connect to and disconnect from device.
char device[MAXINDIDEVICE]