32 #include <libnova/julian_day.h>
33 #include <libnova/ln_types.h>
34 #include <libnova/precession.h>
49 static std::string regex_replace_compat(
const std::string &input,
const std::string &pattern,
const std::string &replace)
52 std::regex_replace(std::ostreambuf_iterator<char>(s), input.begin(), input.end(), std::regex(pattern), replace);
58 const char *
DSP_TAB =
"Signal Processing";
61 m_Name(name), m_Label(label), m_Type(
type)
65 sprintf(activatestrname,
"DSP_ACTIVATE_%s",
m_Name);
66 sprintf(activatestrlabel,
"%s",
m_Label);
74 BufferSizes =
nullptr;
170 bool Interface::ISNewBLOB(
const char *dev,
const char *name,
int sizes[],
int blobsizes[],
char *blobs[],
char *formats[],
171 char *names[],
int n)
196 bool success =
false;
204 if (sendCapture || saveCapture)
214 for (len = 1, i = 0; i < BufferSizesQty; len *= BufferSizes[i++]);
217 if (!strcmp(captureExtention,
"fits"))
219 success = sendFITS(buffer, sendCapture, saveCapture);
223 success = uploadFile(buffer, len, sendCapture, saveCapture, captureExtention);
247 void Interface::addFITSKeywords(fitsfile *fptr)
252 char *orig = setlocale(LC_NUMERIC,
"C");
258 fits_update_key_s(fptr, TSTRING,
"TELESCOP", fitsString,
"Telescope name", &status);
262 fits_update_key_s(fptr, TSTRING,
"OBSERVER", fitsString,
"Observer name", &status);
266 fits_update_key_s(fptr, TSTRING,
"OBJECT", fitsString,
"Object name", &status);
271 double Lat = nv[0].getValue();
272 double Lon = nv[1].getValue();
273 double El = nv[2].getValue();
278 fs_sexa(lat_str, Lat, 2, 360000);
279 fs_sexa(lon_str, Lon, 2, 360000);
281 fits_update_key_s(fptr, TSTRING,
"LATITUDE", lat_str,
"Location Latitude", &status);
282 fits_update_key_s(fptr, TSTRING,
"LONGITUDE", lon_str,
"Location Longitude", &status);
283 fits_update_key_s(fptr, TSTRING,
"ELEVATION", el_str,
"Location Elevation", &status);
289 double RA = nv[0].getValue();
290 double Dec = nv[1].getValue();
294 epochPos.declination = Dec;
300 double raJ2000 = J2000Pos.rightascension;
301 double decJ2000 = J2000Pos.declination;
302 char ra_str[32], de_str[32];
304 fs_sexa(ra_str, raJ2000, 2, 360000);
305 fs_sexa(de_str, decJ2000, 2, 360000);
307 char *raPtr = ra_str, *dePtr = de_str;
308 while (*raPtr !=
'\0')
314 while (*dePtr !=
'\0')
321 fits_update_key_s(fptr, TSTRING,
"OBJCTRA", ra_str,
"Object RA", &status);
322 fits_update_key_s(fptr, TSTRING,
"OBJCTDEC", de_str,
"Object DEC", &status);
327 fits_update_key_s(fptr, TINT,
"EQUINOX", &epoch,
"Equinox", &status);
330 fits_update_key_s(fptr, TSTRING,
"DATE-OBS", exp_start,
"UTC start date of observation", &status);
331 fits_write_comment(fptr,
"Generated by INDI", &status);
333 setlocale(LC_NUMERIC, orig);
336 void Interface::fits_update_key_s(fitsfile *fptr,
int type, std::string name,
void *p, std::string explanation,
340 fits_update_key(fptr,
type, name.c_str(), p,
const_cast<char *
>(explanation.c_str()), status);
347 sprintf(filename,
"INDI_DSP_INTERFACE_XXXXXX");
348 int fd = mkstemp(filename);
351 int written = write(
fd, buffer, len);
359 loaded_stream = stream_arr[channels];
360 for (
int c = 0; c < channels; c++)
369 return loaded_stream;
372 bool Interface::sendFITS(uint8_t *buf,
bool sendCapture,
bool saveCapture)
374 int img_type = USHORT_IMG;
375 int byte_type = TUSHORT;
376 std::string bit_depth =
"16 bits per sample";
382 bit_depth =
"8 bits per sample";
387 img_type = USHORT_IMG;
388 bit_depth =
"16 bits per pixel";
393 img_type = ULONG_IMG;
394 bit_depth =
"32 bits per sample";
399 img_type = ULONG_IMG;
400 bit_depth =
"64 bits double per sample";
405 img_type = FLOAT_IMG;
406 bit_depth =
"32 bits double per sample";
411 img_type = DOUBLE_IMG;
412 bit_depth =
"64 bits double per sample";
420 fitsfile *fptr =
nullptr;
424 int naxis =
static_cast<int>(BufferSizesQty);
425 long *naxes =
static_cast<long*
>(malloc(
sizeof(
long) * BufferSizesQty));
428 for (uint32_t i = 0; i < BufferSizesQty; nelements *= static_cast<long>(BufferSizes[i++]))
429 naxes[i] = BufferSizes[i];
434 memptr = malloc(memsize);
437 LOGF_ERROR(
"Error: failed to allocate memory: %lu", memsize);
441 fits_create_memfile(&fptr, &memptr, &memsize, 2880, realloc, &status);
445 fits_report_error(stderr, status);
446 fits_get_errstatus(status, error_status);
447 fits_close_file(fptr, &status);
453 fits_create_img(fptr, img_type, naxis, naxes, &status);
457 fits_report_error(stderr, status);
458 fits_get_errstatus(status, error_status);
459 fits_close_file(fptr, &status);
465 addFITSKeywords(fptr);
467 fits_write_img(fptr, byte_type, 1, nelements, buf, &status);
471 fits_report_error(stderr, status);
472 fits_get_errstatus(status, error_status);
473 fits_close_file(fptr, &status);
478 fits_close_file(fptr, &status);
480 uploadFile(memptr, memsize, sendCapture, saveCapture, captureExtention);
486 bool Interface::uploadFile(
const void *fitsData,
size_t totalBytes,
bool sendCapture,
bool saveCapture,
const char* format)
490 format, totalBytes, sendCapture ?
"Yes" :
"No", saveCapture ?
"Yes" :
"No");
492 FitsB.blob =
const_cast<void*
>(fitsData);
493 FitsB.bloblen =
static_cast<int>(totalBytes);
494 FitsB.size = totalBytes;
523 strftime(ts,
sizeof(ts),
"%Y-%m-%dT%H-%M-%S", tp);
524 std::string filets(ts);
525 prefix = std::regex_replace(prefix, std::regex(
"ISO8601"), filets);
528 snprintf(indexString, 8,
"%03d", maxIndex);
529 std::string prefixIndex = indexString;
531 prefix = std::regex_replace(prefix, std::regex(
"XXX"), prefixIndex);
539 fp = fopen(processedFileName,
"w");
547 for (
int nr = 0; nr < static_cast<int>(
FitsB.bloblen); nr += n)
548 n = fwrite((
static_cast<char *
>(
FitsB.blob) + nr), 1,
FitsB.bloblen - nr, fp);
551 LOGF_INFO(
"File saved in %s.", processedFileName);
557 auto start = std::chrono::high_resolution_clock::now();
559 auto end = std::chrono::high_resolution_clock::now();
560 std::chrono::duration<double> diff = end - start;
561 LOGF_DEBUG(
"BLOB transfer took %g seconds", diff.count());
571 int Interface::getFileIndex(
const char *dir,
const char *prefix,
const char *ext)
576 struct dirent *epdf =
nullptr;
577 std::vector<std::string> files = std::vector<std::string>();
579 std::string prefixIndex = prefix;
580 prefixIndex = regex_replace_compat(prefixIndex,
"_ISO8601",
"");
581 prefixIndex = regex_replace_compat(prefixIndex,
"_XXX",
"");
586 if (stat(dir, &st) == -1)
596 while ((epdf = readdir(dpdf)))
598 if (strstr(epdf->d_name, prefixIndex.c_str()))
599 files.push_back(epdf->d_name);
608 for (
unsigned long i = 0; i < static_cast<unsigned long>(files.size()); i++)
612 std::string file = files.at(i);
613 std::size_t start = file.find_last_of(
"_");
614 std::size_t end = file.find_last_of(
".");
615 if (start != std::string::npos)
617 index = atoi(file.substr(start + 1, end).c_str());
618 if (index > maxIndex)
623 return (maxIndex + 1);
634 for(uint32_t dim = 0; dim < dims; dim++)
637 switch (bits_per_sample)
667 if(
stream ==
nullptr)
return false;
668 if(dims != (uint32_t)
stream->
dims)
return false;
669 for(uint32_t d = 0; d < dims; d++)
675 switch (bits_per_sample)
705 if(
stream ==
nullptr)
return false;
706 if(dims != (uint32_t)
stream->
dims)
return false;
707 for(uint32_t d = 0; d < dims; d++)
713 switch (bits_per_sample)
743 if(
stream ==
nullptr)
return false;
744 if(dims != (uint32_t)
stream->
dims)
return false;
745 for(uint32_t d = 0; d < dims; d++)
751 switch (bits_per_sample)
779 if(
stream ==
nullptr)
return false;
780 if(dims != (uint32_t)
stream->
dims)
return false;
781 for(uint32_t d = 0; d < dims; d++)
787 switch (bits_per_sample)
843 return static_cast<uint8_t *
>(
buffer);
873 return static_cast<uint8_t *
>(
buffer);
904 *sizes = (
int*)malloc(
sizeof(
int) * in->
dims);
905 for(
int d = 0; d < in->
dims; d++)
906 *sizes[d] = in->
sizes[d];
907 return static_cast<uint8_t *
>(
buffer);
bool setImaginary(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
Interface(INDI::DefaultDevice *dev, Type type=DSP_NONE, const char *name="DSP_PLUGIN", const char *label="DSP Plugin")
const char * getDeviceName()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
virtual void ISGetProperties(const char *dev)
virtual void Activated()
Activated Called after activation from client application.
ISwitchVectorProperty ActivateSP
void setCaptureFileExtension(const char *ext)
setIntegrationFileExtension Set the returned file extension.
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
int getBPS()
getBPS Get the returned file bit depth/sample size.
virtual bool updateProperties()
virtual bool saveConfigItems(FILE *fp)
virtual bool processBLOB(uint8_t *buf, uint32_t ndims, int *dims, int bits_per_sample)
processBLOB Propagate to Callback and generate BLOBs for parent device.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
bool setReal(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
void setSizes(uint32_t num, int *sizes)
setSizes Set the returned file dimensions and corresponding sizes.
IBLOBVectorProperty FitsBP
bool setStream(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
INDI::DefaultDevice * m_Device
dsp_stream_p loadFITS(char *buf, int len)
loadFITS Converts FITS data into a dsp_stream structure pointer.
void setBPS(int bps)
setBPS Set the returned file bit depth/sample size.
bool setMagnitude(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
virtual uint8_t * Callback(uint8_t *buf, uint32_t ndims, int *dims, int bits_per_sample)
Callback Called by processBLOB.
uint8_t * getBuffer(dsp_stream_p in, uint32_t *dims, int **sizes)
bool setPhase(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
virtual void Deactivated()
Deactivated Called after deactivation from client application.
INDI::PropertyNumber getNumber(const char *name) const
const char * getDeviceName() const
INDI::PropertySwitch getSwitch(const char *name) const
INDI::PropertyText getText(const char *name) const
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
INDI::PropertyViewText * getText() const
struct dsp_stream_t * phase
Fourier transform phase.
int * sizes
Sizes of each dimension.
dsp_complex dft
Fourier transform.
double * buf
Linear double array containing complex numbers.
struct dsp_stream_t * magnitude
Fourier transform magnitude.
int dims
Number of dimensions of the buffers.
int len
The buffers length.
#define dsp_buffer_copy(in, out, len)
Fill the output buffer with the values of the elements of the input stream by casting them to the out...
#define dsp_buffer_copy_stepping(in, out, inlen, outlen, instep, outstep)
Fill the output buffer with the values of the elements of the input stream by casting them to the out...
#define dsp_buffer_set(buf, len, _val)
Fill the buffer with the passed value.
DLL_EXPORT void dsp_stream_free(dsp_stream_p stream)
Free the DSP stream passed as argument.
DLL_EXPORT dsp_stream_p dsp_stream_copy(dsp_stream_p stream)
Create a copy of the DSP stream passed as argument.
DLL_EXPORT dsp_stream_p dsp_stream_new(void)
Allocate a new DSP stream type.
DLL_EXPORT void dsp_stream_add_dim(dsp_stream_p stream, int len)
Add a dimension with length len to a DSP stream.
DLL_EXPORT void dsp_stream_alloc_buffer(dsp_stream_p stream, int len)
Allocate a buffer with length len on the stream passed as argument.
DLL_EXPORT void dsp_stream_free_buffer(dsp_stream_p stream)
Free the buffer of the DSP Stream passed as argument.
DLL_EXPORT dsp_stream_p * dsp_file_read_fits(const char *filename, int *channels, int stretch)
Read a FITS file and fill a dsp_stream_p with its content.
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string. sprint the variable a in sexagesimal format into out[].
Implementations for common driver routines.
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 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.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
void IDSetBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
#define LOGF_INFO(fmt,...)
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)
#define DEBUGF(priority, msg,...)
std::vector< uint8_t > buffer
The DSP Namespace adds signal processing to INDI drivers. Primarily written for sensors and detectors...
void ObservedToJ2000(IEquatorialCoordinates *observed, double jd, IEquatorialCoordinates *J2000pos)
ObservedToJ2000 converts an observed position to a J2000 catalogue position removes aberration,...
int mkpath(std::string s, mode_t mode)
Holds the connection type.
Contains a set of informations and data relative to a buffer and how to use it.