33 #include <libnova/julian_day.h>
34 #include <libnova/ln_types.h>
35 #include <libnova/precession.h>
70 Buffer =
static_cast<uint8_t *
>(malloc(
sizeof(uint8_t)));
134 DSP->updateProperties();
149 DSP->ISGetProperties(dev);
225 Streamer->ISNewText(dev, name, texts, names, n);
228 DSP->ISNewText(dev, name, texts, names, n);
239 if (!strcmp(name,
"SENSOR_INTEGRATION"))
293 Streamer->ISNewNumber(dev, name, values, names, n);
296 DSP->ISNewNumber(dev, name, values, names, n);
364 Streamer->ISNewSwitch(dev, name, states, names, n);
367 DSP->ISNewSwitch(dev, name, states, names, n);
373 char *formats[],
char *names[],
int n)
376 DSP->ISNewBLOB(dev, name, sizes, blobsizes, blobs, formats, names, n);
456 IUFillNumber(&
EqN[1],
"DEC",
"DEC (dd:mm:ss)",
"%010.6m", -90, 90, 0, 0);
483 return callHandshake();
493 return callHandshake();
536 if (nbuf == BufferSize)
550 DSP->setSizes(1,
new int[1] { BufferSize * 8 /
getBPS() });
552 if (allocMem ==
false)
555 Buffer =
static_cast<uint8_t *
>(realloc(Buffer, nbuf *
sizeof(uint8_t)));
574 integrationTime = duration;
578 startIntegrationTime =
time_ns();
583 static char iso8601[32];
585 time_t t = (time_t)startIntegrationTime;
588 strftime(iso8601,
sizeof(iso8601),
"%Y-%m-%dT%H:%M:%S", tp);
612 DSP->setCaptureFileExtension(ext);
632 double integrationTime;
634 char *orig = setlocale(LC_NUMERIC,
"C");
640 fits_update_key_s(fptr, TSTRING,
"INSTRUME", fitsString,
"Sensor Name", &status);
644 fits_update_key_s(fptr, TSTRING,
"TELESCOP", fitsString,
"Telescope name", &status);
648 fits_update_key_s(fptr, TSTRING,
"OBSERVER", fitsString,
"Observer name", &status);
658 snprintf(timestamp, 32,
"%lf", startIntegrationTime);
660 fits_update_key_s(fptr, TDOUBLE,
"EXPTIME", &(integrationTime),
"Total Integration Time (s)", &status);
669 double min_val, max_val;
670 getMinMax(&min_val, &max_val, buf, len,
getBPS());
696 fits_update_key_s(fptr, TSTRING,
"SITELAT", lat_str,
"Location Latitude", &status);
697 fits_update_key_s(fptr, TSTRING,
"SITELONG", lon_str,
"Location Longitude", &status);
698 fits_update_key_s(fptr, TSTRING,
"SITEELEV", el_str,
"Location Elevation", &status);
700 if (
RA != -1000 &&
Dec != -1000)
704 epochPos.declination =
Dec;
710 double raJ2000 = J2000Pos.rightascension;
711 double decJ2000 = J2000Pos.declination;
712 char ra_str[32], de_str[32];
714 fs_sexa(ra_str, raJ2000, 2, 360000);
715 fs_sexa(de_str, decJ2000, 2, 360000);
717 char *raPtr = ra_str, *dePtr = de_str;
718 while (*raPtr !=
'\0')
724 while (*dePtr !=
'\0')
740 fits_update_key_s(fptr, TSTRING,
"EPOCH", timestamp,
"Unix Epoch of start of integration", &status);
742 fits_update_key_s(fptr, TSTRING,
"DATE-OBS", exp_start,
"UTC start date of observation", &status);
744 fits_write_comment(fptr,
"Generated by INDI", &status);
746 setlocale(LC_NUMERIC, orig);
753 fits_update_key(fptr,
type, name.c_str(), p,
const_cast<char *
>(explanation.c_str()), status);
756 void* SensorInterface::sendFITS(uint8_t *buf,
int len)
760 fitsfile *fptr =
nullptr;
769 std::string bit_depth;
776 bit_depth =
"8 bits per sample";
781 img_type = USHORT_IMG;
782 bit_depth =
"16 bits per sample";
788 bit_depth =
"32 bits per sample";
792 byte_type = TLONGLONG;
793 img_type = LONGLONG_IMG;
794 bit_depth =
"64 bits double per sample";
799 img_type = FLOAT_IMG;
800 bit_depth =
"32 bits double per sample";
805 img_type = DOUBLE_IMG;
806 bit_depth =
"64 bits double per sample";
814 naxes[0] = naxes[0] < 1 ? 1 : naxes[0];
816 nelements = naxes[0];
823 memptr = malloc(memsize);
829 fits_create_memfile(&fptr, &memptr, &memsize, 2880, realloc, &status);
833 fits_report_error(stderr, status);
834 fits_get_errstatus(status, error_status);
836 if(memptr !=
nullptr)
841 fits_create_img(fptr, img_type, naxis, naxes, &status);
845 fits_report_error(stderr, status);
846 fits_get_errstatus(status, error_status);
848 if(memptr !=
nullptr)
855 fits_write_img(fptr, byte_type, 1, nelements, buf, &status);
859 fits_report_error(stderr, status);
860 fits_get_errstatus(status, error_status);
862 if(memptr !=
nullptr)
867 fits_close_file(fptr, &status);
869 uploadFile(memptr, memsize, sendIntegration, saveIntegration);
887 std::thread(&SensorInterface::IntegrationCompletePrivate,
this).detach();
892 bool SensorInterface::IntegrationCompletePrivate()
896 bool autoLoop =
false;
898 if (sendIntegration || saveIntegration)
900 void* blob =
nullptr;
942 bool saveIntegration)
948 FitsB.blob =
const_cast<void *
>(fitsData);
949 FitsB.bloblen = totalBytes;
955 char integrationFileName[
MAXRBUF];
975 strftime(ts,
sizeof(ts),
"%Y-%m-%dT%H-%M-%S", tp);
976 std::string filets(ts);
977 prefix = std::regex_replace(prefix, std::regex(
"ISO8601"), filets);
980 snprintf(indexString, 8,
"%03d", maxIndex);
981 std::string prefixIndex = indexString;
983 prefix = std::regex_replace(prefix, std::regex(
"XXX"), prefixIndex);
988 fp = fopen(integrationFileName,
"w");
996 for (
int nr = 0; nr < static_cast<int>(
FitsB.bloblen); nr += n)
997 n = fwrite((
static_cast<char *
>(
FitsB.blob) + nr), 1,
FitsB.bloblen - nr, fp);
1009 FitsB.size = totalBytes;
1019 LOG_ERROR(
"Streaming is not supported.");
1025 LOG_ERROR(
"Streaming is not supported.");
1049 DSP->saveConfigItems(fp);
1054 void SensorInterface::getMinMax(
double *
min,
double *
max, uint8_t *buf,
int len,
int bpp)
1057 int integrationHeight = 1;
1058 int integrationWidth = len;
1059 double lmin = 0, lmax = 0;
1065 uint8_t *integrationBuffer =
static_cast<uint8_t *
>(buf);
1066 lmin = lmax = integrationBuffer[0];
1068 for (i = 0; i < integrationHeight; i++)
1069 for (j = 0; j < integrationWidth; j++)
1071 ind = (i * integrationWidth) + j;
1072 if (integrationBuffer[ind] < lmin)
1073 lmin = integrationBuffer[ind];
1074 else if (integrationBuffer[ind] > lmax)
1075 lmax = integrationBuffer[ind];
1082 uint16_t *integrationBuffer =
reinterpret_cast<uint16_t *
>(buf);
1083 lmin = lmax = integrationBuffer[0];
1085 for (i = 0; i < integrationHeight; i++)
1086 for (j = 0; j < integrationWidth; j++)
1088 ind = (i * integrationWidth) + j;
1089 if (integrationBuffer[ind] < lmin)
1090 lmin = integrationBuffer[ind];
1091 else if (integrationBuffer[ind] > lmax)
1092 lmax = integrationBuffer[ind];
1099 uint32_t *integrationBuffer =
reinterpret_cast<uint32_t *
>(buf);
1100 lmin = lmax = integrationBuffer[0];
1102 for (i = 0; i < integrationHeight; i++)
1103 for (j = 0; j < integrationWidth; j++)
1105 ind = (i * integrationWidth) + j;
1106 if (integrationBuffer[ind] < lmin)
1107 lmin = integrationBuffer[ind];
1108 else if (integrationBuffer[ind] > lmax)
1109 lmax = integrationBuffer[ind];
1116 unsigned long *integrationBuffer =
reinterpret_cast<unsigned long *
>(buf);
1117 lmin = lmax = integrationBuffer[0];
1119 for (i = 0; i < integrationHeight; i++)
1120 for (j = 0; j < integrationWidth; j++)
1122 ind = (i * integrationWidth) + j;
1123 if (integrationBuffer[ind] < lmin)
1124 lmin = integrationBuffer[ind];
1125 else if (integrationBuffer[ind] > lmax)
1126 lmax = integrationBuffer[ind];
1133 double *integrationBuffer =
reinterpret_cast<double *
>(buf);
1134 lmin = lmax = integrationBuffer[0];
1136 for (i = 0; i < integrationHeight; i++)
1137 for (j = 0; j < integrationWidth; j++)
1139 ind = (i * integrationWidth) + j;
1140 if (integrationBuffer[ind] < lmin)
1141 lmin = integrationBuffer[ind];
1142 else if (integrationBuffer[ind] > lmax)
1143 lmax = integrationBuffer[ind];
1150 double *integrationBuffer =
reinterpret_cast<double *
>(buf);
1151 lmin = lmax = integrationBuffer[0];
1153 for (i = 0; i < integrationHeight; i++)
1154 for (j = 0; j < integrationWidth; j++)
1156 ind = (i * integrationWidth) + j;
1157 if (integrationBuffer[ind] < lmin)
1158 lmin = integrationBuffer[ind];
1159 else if (integrationBuffer[ind] > lmax)
1160 lmax = integrationBuffer[ind];
1171 std::stringstream s;
1172 std::regex_replace(std::ostreambuf_iterator<char>(s), input.begin(), input.end(), std::regex(pattern), replace);
1176 int SensorInterface::getFileIndex(
const char *dir,
const char *prefix,
const char *ext)
1180 DIR *dpdf =
nullptr;
1181 struct dirent *epdf =
nullptr;
1182 std::vector<std::string> files = std::vector<std::string>();
1184 std::string prefixIndex = prefix;
1191 if (stat(dir, &st) == -1)
1198 dpdf = opendir(dir);
1199 if (dpdf !=
nullptr)
1201 while ((epdf = readdir(dpdf)))
1203 if (strstr(epdf->d_name, prefixIndex.c_str()))
1204 files.push_back(epdf->d_name);
1213 for (
int i = 0; i < static_cast<int>(files.size()); i++)
1217 std::string file = files.at(i);
1218 std::size_t start = file.find_last_of(
"_");
1219 std::size_t end = file.find_last_of(
".");
1220 if (start != std::string::npos)
1222 index = atoi(file.substr(start + 1, end).c_str());
1223 if (index > maxIndex)
1228 return (maxIndex + 1);
1250 bool SensorInterface::callHandshake()
1252 if (sensorConnection > 0)
1267 if (value == 0 || (mask & value) == 0)
1273 sensorConnection = value;
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
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 successfull connectio...
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...
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()
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.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
Connection::Interface * getActiveConnection()
uint16_t getDriverInterface() const
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)
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 * getBuffer()
getBuffer Get raw 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
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. Dervied classes should class this functio...
ISwitchVectorProperty TelescopeTypeSP
void processProperties(const char *dev)
bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
char * getIntegrationFileExtension()
bool initProperties()
Initilize 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)
int getBPS() const
getBPS Get Sensor depth (bits per sample).
void setIntegrationFileExtension(const char *ext)
setIntegrationExtension Set integration exntension
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
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.
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
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.
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)
Number vector property descriptor.
char device[MAXINDIDEVICE]
void uploadFile(const char *filename)