33#include <libnova/julian_day.h>
34#include <libnova/ln_types.h>
35#include <libnova/precession.h>
70 Continuum =
static_cast<uint8_t *
>(malloc(
sizeof(uint8_t)));
71 Real =
static_cast<uint8_t *
>(malloc(
sizeof(uint8_t)));
72 Imaginary =
static_cast<uint8_t *
>(malloc(
sizeof(uint8_t)));
73 Magnitude =
static_cast<uint8_t *
>(malloc(
sizeof(uint8_t)));
74 Phase =
static_cast<uint8_t *
>(malloc(
sizeof(uint8_t)));
146 DSP->updateProperties();
161 DSP->ISGetProperties(dev);
237 Streamer->ISNewText(dev, name, texts, names, n);
240 DSP->ISNewText(dev, name, texts, names, n);
251 if (!strcmp(name,
"SENSOR_INTEGRATION"))
305 Streamer->ISNewNumber(dev, name, values, names, n);
308 DSP->ISNewNumber(dev, name, values, names, n);
376 Streamer->ISNewSwitch(dev, name, states, names, n);
379 DSP->ISNewSwitch(dev, name, states, names, n);
385 char *formats[],
char *names[],
int n)
388 DSP->ISNewBLOB(dev, name, sizes, blobsizes, blobs, formats, names, n);
472 IUFillNumber(&
EqN[1],
"DEC",
"DEC (dd:mm:ss)",
"%010.6m", -90, 90, 0, 0);
499 return callHandshake();
509 return callHandshake();
552 if (nbuf == BufferSize)
566 DSP->setSizes(1,
new int[1] { BufferSize * 8 /
getBPS() });
568 if (allocMem ==
false)
571 Continuum =
static_cast<uint8_t *
>(realloc(Continuum, nbuf *
sizeof(uint8_t)));
572 Real =
static_cast<uint8_t *
>(realloc(Real, nbuf *
sizeof(uint8_t)));
573 Imaginary =
static_cast<uint8_t *
>(realloc(Imaginary, nbuf *
sizeof(uint8_t)));
574 Magnitude =
static_cast<uint8_t *
>(realloc(Magnitude, nbuf *
sizeof(uint8_t)));
575 Phase =
static_cast<uint8_t *
>(realloc(Phase, nbuf *
sizeof(uint8_t)));
594 integrationTime = duration;
598 startIntegrationTime =
time_ns();
603 static char iso8601[32];
605 time_t t = (time_t)startIntegrationTime;
608 strftime(iso8601,
sizeof(iso8601),
"%Y-%m-%dT%H:%M:%S", tp);
632 DSP->setCaptureFileExtension(ext);
652 double integrationTime;
654 char *orig = setlocale(LC_NUMERIC,
"C");
660 fits_update_key_s(fptr, TSTRING,
"INSTRUME", fitsString,
"Sensor Name", &status);
664 fits_update_key_s(fptr, TSTRING,
"TELESCOP", fitsString,
"Telescope name", &status);
668 fits_update_key_s(fptr, TSTRING,
"OBSERVER", fitsString,
"Observer name", &status);
678 snprintf(timestamp, 32,
"%lf", startIntegrationTime);
680 fits_update_key_s(fptr, TDOUBLE,
"EXPTIME", &(integrationTime),
"Total Integration Time (s)", &status);
689 double min_val, max_val;
690 getMinMax(&min_val, &max_val, buf, len,
getBPS());
716 fits_update_key_s(fptr, TSTRING,
"SITELAT", lat_str,
"Location Latitude", &status);
717 fits_update_key_s(fptr, TSTRING,
"SITELONG", lon_str,
"Location Longitude", &status);
718 fits_update_key_s(fptr, TSTRING,
"SITEELEV", el_str,
"Location Elevation", &status);
720 if (
RA != -1000 &&
Dec != -1000)
724 epochPos.declination =
Dec;
730 double raJ2000 = J2000Pos.rightascension;
731 double decJ2000 = J2000Pos.declination;
732 char ra_str[32], de_str[32];
734 fs_sexa(ra_str, raJ2000, 2, 360000);
735 fs_sexa(de_str, decJ2000, 2, 360000);
737 char *raPtr = ra_str, *dePtr = de_str;
738 while (*raPtr !=
'\0')
744 while (*dePtr !=
'\0')
760 fits_update_key_s(fptr, TSTRING,
"EPOCH", timestamp,
"Unix Epoch of start of integration", &status);
762 fits_update_key_s(fptr, TSTRING,
"DATE-OBS", exp_start,
"UTC start date of observation", &status);
764 fits_write_comment(fptr,
"Generated by INDI", &status);
766 setlocale(LC_NUMERIC, orig);
773 fits_update_key(fptr,
type, name.c_str(), p,
const_cast<char *
>(explanation.c_str()), status);
776void* SensorInterface::sendFITS(uint8_t *buf,
int len,
IBLOB blob)
780 fitsfile *fptr =
nullptr;
789 std::string bit_depth;
796 bit_depth =
"8 bits per sample";
801 img_type = USHORT_IMG;
802 bit_depth =
"16 bits per sample";
808 bit_depth =
"32 bits per sample";
812 byte_type = TLONGLONG;
813 img_type = LONGLONG_IMG;
814 bit_depth =
"64 bits double per sample";
819 img_type = FLOAT_IMG;
820 bit_depth =
"32 bits double per sample";
825 img_type = DOUBLE_IMG;
826 bit_depth =
"64 bits double per sample";
834 naxes[0] = naxes[0] < 1 ? 1 : naxes[0];
836 nelements = naxes[0];
843 memptr = malloc(memsize);
849 fits_create_memfile(&fptr, &memptr, &memsize, 2880, realloc, &status);
853 fits_report_error(stderr, status);
854 fits_get_errstatus(status, error_status);
856 if(memptr !=
nullptr)
861 fits_create_img(fptr, img_type, naxis, naxes, &status);
865 fits_report_error(stderr, status);
866 fits_get_errstatus(status, error_status);
868 if(memptr !=
nullptr)
875 fits_write_img(fptr, byte_type, 1, nelements, buf, &status);
879 fits_report_error(stderr, status);
880 fits_get_errstatus(status, error_status);
882 if(memptr !=
nullptr)
887 fits_close_file(fptr, &status);
889 uploadFile(memptr, memsize, blob, sendIntegration, saveIntegration);
907 std::thread(&SensorInterface::IntegrationCompletePrivate,
this).detach();
912bool SensorInterface::IntegrationCompletePrivate()
916 bool autoLoop =
false;
918 if (sendIntegration || saveIntegration)
920 void* blob =
nullptr;
921 void* magnitude =
nullptr;
922 void* phase =
nullptr;
923 void* real =
nullptr;
924 void* imaginary =
nullptr;
986bool SensorInterface::uploadFile(
const void *fitsData,
size_t totalBytes,
IBLOB blob,
bool sendIntegration,
987 bool saveIntegration)
993 blob.blob =
const_cast<void *
>(fitsData);
994 blob.bloblen = totalBytes;
1000 char integrationFileName[
MAXRBUF];
1020 strftime(ts,
sizeof(ts),
"%Y-%m-%dT%H-%M-%S", tp);
1021 std::string filets(ts);
1022 prefix = std::regex_replace(prefix, std::regex(
"ISO8601"), filets);
1024 char indexString[8];
1025 snprintf(indexString, 8,
"%03d", maxIndex);
1026 std::string prefixIndex = indexString;
1028 prefix = std::regex_replace(prefix, std::regex(
"XXX"), prefixIndex);
1033 fp = fopen(integrationFileName,
"w");
1041 for (
int nr = 0; nr < static_cast<int>(blob.bloblen); nr += n)
1042 n = fwrite((
static_cast<char *
>(blob.blob) + nr), 1, blob.bloblen - nr, fp);
1054 blob.size = totalBytes;
1063 LOG_ERROR(
"Streaming is not supported.");
1069 LOG_ERROR(
"Streaming is not supported.");
1093 DSP->saveConfigItems(fp);
1098void SensorInterface::getMinMax(
double *
min,
double *
max, uint8_t *buf,
int len,
int bpp)
1101 int integrationHeight = 1;
1102 int integrationWidth = len;
1103 double lmin = 0, lmax = 0;
1109 uint8_t *integrationBuffer =
static_cast<uint8_t *
>(buf);
1110 lmin = lmax = integrationBuffer[0];
1112 for (i = 0; i < integrationHeight; i++)
1113 for (j = 0; j < integrationWidth; j++)
1115 ind = (i * integrationWidth) + j;
1116 if (integrationBuffer[ind] < lmin)
1117 lmin = integrationBuffer[ind];
1118 else if (integrationBuffer[ind] > lmax)
1119 lmax = integrationBuffer[ind];
1126 uint16_t *integrationBuffer =
reinterpret_cast<uint16_t *
>(buf);
1127 lmin = lmax = integrationBuffer[0];
1129 for (i = 0; i < integrationHeight; i++)
1130 for (j = 0; j < integrationWidth; j++)
1132 ind = (i * integrationWidth) + j;
1133 if (integrationBuffer[ind] < lmin)
1134 lmin = integrationBuffer[ind];
1135 else if (integrationBuffer[ind] > lmax)
1136 lmax = integrationBuffer[ind];
1143 uint32_t *integrationBuffer =
reinterpret_cast<uint32_t *
>(buf);
1144 lmin = lmax = integrationBuffer[0];
1146 for (i = 0; i < integrationHeight; i++)
1147 for (j = 0; j < integrationWidth; j++)
1149 ind = (i * integrationWidth) + j;
1150 if (integrationBuffer[ind] < lmin)
1151 lmin = integrationBuffer[ind];
1152 else if (integrationBuffer[ind] > lmax)
1153 lmax = integrationBuffer[ind];
1160 unsigned long *integrationBuffer =
reinterpret_cast<unsigned long *
>(buf);
1161 lmin = lmax = integrationBuffer[0];
1163 for (i = 0; i < integrationHeight; i++)
1164 for (j = 0; j < integrationWidth; j++)
1166 ind = (i * integrationWidth) + j;
1167 if (integrationBuffer[ind] < lmin)
1168 lmin = integrationBuffer[ind];
1169 else if (integrationBuffer[ind] > lmax)
1170 lmax = integrationBuffer[ind];
1177 double *integrationBuffer =
reinterpret_cast<double *
>(buf);
1178 lmin = lmax = integrationBuffer[0];
1180 for (i = 0; i < integrationHeight; i++)
1181 for (j = 0; j < integrationWidth; j++)
1183 ind = (i * integrationWidth) + j;
1184 if (integrationBuffer[ind] < lmin)
1185 lmin = integrationBuffer[ind];
1186 else if (integrationBuffer[ind] > lmax)
1187 lmax = integrationBuffer[ind];
1194 double *integrationBuffer =
reinterpret_cast<double *
>(buf);
1195 lmin = lmax = integrationBuffer[0];
1197 for (i = 0; i < integrationHeight; i++)
1198 for (j = 0; j < integrationWidth; j++)
1200 ind = (i * integrationWidth) + j;
1201 if (integrationBuffer[ind] < lmin)
1202 lmin = integrationBuffer[ind];
1203 else if (integrationBuffer[ind] > lmax)
1204 lmax = integrationBuffer[ind];
1215 std::stringstream s;
1216 std::regex_replace(std::ostreambuf_iterator<char>(s), input.begin(), input.end(), std::regex(pattern), replace);
1220int SensorInterface::getFileIndex(
const char *dir,
const char *prefix,
const char *ext)
1224 DIR *dpdf =
nullptr;
1225 struct dirent *epdf =
nullptr;
1226 std::vector<std::string> files = std::vector<std::string>();
1228 std::string prefixIndex = prefix;
1235 if (stat(dir, &st) == -1)
1242 dpdf = opendir(dir);
1243 if (dpdf !=
nullptr)
1245 while ((epdf = readdir(dpdf)))
1247 if (strstr(epdf->d_name, prefixIndex.c_str()))
1248 files.push_back(epdf->d_name);
1257 for (
int i = 0; i < static_cast<int>(files.size()); i++)
1261 std::string file = files.at(i);
1262 std::size_t start = file.find_last_of(
"_");
1263 std::size_t end = file.find_last_of(
".");
1264 if (start != std::string::npos)
1266 index = atoi(file.substr(start + 1, end).c_str());
1267 if (index > maxIndex)
1272 return (maxIndex + 1);
1295bool SensorInterface::callHandshake()
1297 if (sensorConnection > 0)
1312 if (value == 0 || (mask & value) == 0)
1318 sensorConnection = value;
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
The TCP class manages connection with devices over the network via TCP/IP. Upon successful connection...
const char * getDeviceName() const
void setCurrentPollingPeriod(uint32_t msec)
setCurrentPollingPeriod Change the current polling period to call TimerHit() function in the driver.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
uint32_t getPollingPeriod() const
getPollingPeriod Return the polling period.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
uint32_t getDriverInterface() const
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.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
Connection::Interface * getActiveConnection()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
void setIntegrationFailed()
setIntegrationFailed Alert the client that the Integration failed.
ITextVectorProperty FileNameTP
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
void SetCapability(uint32_t cap)
SetCapability Set the Sensor capabilities. Al fields must be initialized.
ITextVectorProperty FITSHeaderTP
ISwitch AbortIntegrationS[1]
virtual bool StartStreaming()
StartStreaming Start live video streaming.
virtual bool StopStreaming()
StopStreaming Stop live video streaming.
ITextVectorProperty UploadSettingsTP
INumberVectorProperty LocationNP
bool processSwitch(const char *dev, const char *name, ISState states[], char *names[], int n)
uint8_t * getReal()
getBuffer Get real buffer of the stream of the Sensor device.
void setBPS(int bps)
setBPP Set depth of Sensor device.
INumber FramedIntegrationN[1]
INumberVectorProperty EqNP
void setBufferSize(int nbuf, bool allocMem=true)
setBufferSize Set desired buffer size. The function will allocate memory accordingly....
double primaryFocalLength
void setNAxis(int value)
setNAxis Set FITS number of axis
void setSensorConnection(const uint8_t &value)
setSensorConnection Set Sensor connection mode. Child class should call this in the constructor befor...
void setIntegrationLeft(double duration)
setIntegrationLeft Update Integration time left. Inform the client of the new Integration time left v...
ITextVectorProperty ActiveDeviceTP
IBLOBVectorProperty FitsBP
virtual bool AbortIntegration()
Abort ongoing Integration.
uint8_t * getImaginary()
getBuffer Get imaginary buffer of the stream of the Sensor device.
std::unique_ptr< StreamManager > Streamer
void setIntegrationTime(double duration)
setIntegrationTime Set desired Sensor frame Integration duration for next Integration....
int PortFD
For Serial & TCP connections.
bool processText(const char *dev, const char *name, char *texts[], char *names[], int n)
virtual void setMinMaxStep(const char *property, const char *element, double min, double max, double step, bool sendToClient=true)
setMinMaxStep for a number property element
virtual void addFITSKeywords(fitsfile *fptr, uint8_t *buf, int len)
Add FITS keywords to a fits file.
int getBufferSize() const
getContinuumBufferSize Get allocated continuum buffer size to hold the Sensor integrationd stream.
bool processBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
INumberVectorProperty TemperatureNP
void fits_update_key_s(fitsfile *fptr, int type, std::string name, void *p, std::string explanation, int *status)
INumber ScopeParametersN[4]
const char * getIntegrationStartTime()
getIntegrationStartTime
INumberVectorProperty FramedIntegrationNP
ISwitchVectorProperty AbortIntegrationSP
uint8_t * getMagnitude()
getBuffer Get magnitude buffer of the stream of the Sensor device.
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save configuration items in XML file.
virtual bool IntegrationComplete()
Uploads target Device exposed buffer as FITS to the client. Derived classes should class this functio...
ISwitchVectorProperty TelescopeTypeSP
void processProperties(const char *dev)
uint8_t * getBuffer()
getBuffer Get continuum buffer of the stream of the Sensor device.
bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
ISwitchVectorProperty UploadSP
virtual bool Handshake()
perform handshake with device to check communication
Connection::TCP * tcpConnection
bool processSnoopDevice(XMLEle *root)
char * getIntegrationFileExtension()
int getBPS() const
getBPS Get Sensor depth (bits per sample).
void setIntegrationFileExtension(const char *ext)
setIntegrationExtension Set integration extension
Connection::Serial * serialConnection
virtual void activeDevicesUpdated()
activeDevicesUpdated Inform children that ActiveDevices property was updated so they can snoop on the...
double getIntegrationTime() const
getIntegrationTime Get requested Integration duration for the Sensor device in seconds.
INumberVectorProperty ScopeParametersNP
uint8_t * getPhase()
getBuffer Get phase buffer of the stream of the Sensor device.
virtual int SetTemperature(double temperature)
Set Sensor temperature.
virtual bool StartIntegration(double duration)
Start integration from the Sensor device.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * INFO_TAB
INFO_TAB Where all the properties for general information are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
double time_ns()
Get a unix timestamp with nanosecond precision.
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 IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
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.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
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.
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
int IUSnoopNumber(XMLEle *root, INumberVectorProperty *nvp)
Update a snooped number vector property from the given XML root element.
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 IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
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 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.
void IDSnoopDevice(const char *snooped_device, const char *snooped_property)
Function a Driver calls to snoop on another Device. Snooped messages will then arrive via ISSnoopDevi...
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
void IDSetBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
void IDSetText(const ITextVectorProperty *tvp, const char *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 LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
#define DEBUGF(priority, msg,...)
The DSP Namespace adds signal processing to INDI drivers. Primarily written for sensors and detectors...
Namespace to encapsulate INDI client, drivers, and mediator classes.
std::string regex_replace_compat2(const std::string &input, const std::string &pattern, const std::string &replace)
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)
One Blob (Binary Large Object) descriptor.
Number vector property descriptor.
char device[MAXINDIDEVICE]
void uploadFile(const char *filename)