From 62f41e9bafc5919b9a3e8b4236f7adacde39f8eb Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Sat, 22 Feb 2020 18:02:23 +0300 Subject: [PATCH] Add saving FITS-header template to 10micron daemon --- Daemons/10micron_stellarium/Makefile | 5 +- Daemons/10micron_stellarium/cmdlnopts.c | 2 + Daemons/10micron_stellarium/cmdlnopts.h | 1 + Daemons/10micron_stellarium/main.c | 31 ++-- Daemons/10micron_stellarium/main.h | 14 +- Daemons/10micron_stellarium/telescope.c | 203 +++++++++++++++++++++--- Daemons/10micron_stellarium/telescope.h | 6 +- Docs/Alignment/Readme.md | 1 + 8 files changed, 220 insertions(+), 43 deletions(-) diff --git a/Daemons/10micron_stellarium/Makefile b/Daemons/10micron_stellarium/Makefile index 309c12d..732f767 100644 --- a/Daemons/10micron_stellarium/Makefile +++ b/Daemons/10micron_stellarium/Makefile @@ -1,10 +1,9 @@ PROGRAM = stellariumdaemon -LDFLAGS = -lsofa_c +LDFLAGS = -lsofa_c -pthread SRCS = $(wildcard *.c) CC = gcc DEFINES = -D_GNU_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=1111 -DEFINES += -DCOM_SPD=B9600 -#DEFINES += -DEBUG +DEFINES += -DEBUG CXX = gcc CFLAGS = -Wall -Werror -Wextra -Wno-trampolines $(DEFINES) OBJS = $(SRCS:.c=.o) diff --git a/Daemons/10micron_stellarium/cmdlnopts.c b/Daemons/10micron_stellarium/cmdlnopts.c index ce12256..2b12075 100644 --- a/Daemons/10micron_stellarium/cmdlnopts.c +++ b/Daemons/10micron_stellarium/cmdlnopts.c @@ -46,6 +46,7 @@ glob_pars const Gdefault = { .device = DEFAULT_COMDEV, .port = DEFAULT_PORT, .pidfile = DEFAULT_PIDFILE, + .crdsfile = "/tmp/10micron.fitsheader", .emulation = 0, .logfile = NULL // don't save logs }; @@ -61,6 +62,7 @@ myoption cmdlnopts[] = { {"emulation",NO_ARGS, NULL, 'e', arg_int, APTR(&G.emulation), _("run in emulation mode")}, //{"hostname",NEED_ARG, NULL, 'H', arg_string, APTR(&G.hostname), _("hostname to connect (default: localhost)")}, {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("file to save logs")}, + {"hdrfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.crdsfile), _("file to save FITS-header with coordinates and time")}, {"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")}, {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("port to connect (default: " DEFAULT_PORT ")")}, end_option diff --git a/Daemons/10micron_stellarium/cmdlnopts.h b/Daemons/10micron_stellarium/cmdlnopts.h index cfcafee..696f76c 100644 --- a/Daemons/10micron_stellarium/cmdlnopts.h +++ b/Daemons/10micron_stellarium/cmdlnopts.h @@ -33,6 +33,7 @@ typedef struct{ char *port; // port to connect char *pidfile; // name of PID file char *logfile; // logging to this file + char *crdsfile; // file where FITS-header should be written int emulation; // run in emulation mode int rest_pars_num; // number of rest parameters char** rest_pars; // the rest parameters: array of char* diff --git a/Daemons/10micron_stellarium/main.c b/Daemons/10micron_stellarium/main.c index 3732426..ff10da7 100644 --- a/Daemons/10micron_stellarium/main.c +++ b/Daemons/10micron_stellarium/main.c @@ -20,29 +20,21 @@ */ #include -#include #include -#include -#include #include #include #include #include -#include -#include -#include #include #include #include #include #include -#include -#include "cmdlnopts.h" #include "emulation.h" #include "libsofa.h" +#include "main.h" #include "telescope.h" -#include "usefull_macros.h" // daemon.c extern void check4running(char *self, char *pidfilename, void (*iffound)(pid_t pid)); @@ -311,14 +303,26 @@ void handle_socket(int sock){ close(sock); } +static void *hdrthread(_U_ void *buf){ + // write FITS-header at most once per second + do{ + wrhdr(); + usleep(1000); // give a chanse to write/read for others + }while(1); + return NULL; +} + static inline void main_proc(){ int sock; int reuseaddr = 1; + pthread_t hthrd; // connect to telescope if(!GP->emulation){ - if(!connect_telescope(GP->device)){ + if(!connect_telescope(GP->device, GP->crdsfile)){ ERRX(_("Can't connect to telescope device")); } + if(pthread_create(&hthrd, NULL, hdrthread, NULL)) + ERR(_("Can't create writing thread")); } // open socket struct addrinfo hints, *res, *p; @@ -384,6 +388,8 @@ static inline void main_proc(){ }*/ handle_socket(newsock); } + pthread_cancel(hthrd); // cancel steppers' thread + pthread_join(hthrd, NULL); close(sock); } @@ -400,6 +406,11 @@ int main(int argc, char **argv){ signal(SIGQUIT, signals); // ctrl+\ - quit signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z + int fd; + if((fd = open(GP->crdsfile, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) // test FITS-header file for writing + ERR(_("Can't open %s for writing"), GP->crdsfile); + close(fd); + printf(_("Start socket\n")); putlog("Starting, master PID=%d", getpid()); #ifndef EBUG // daemonize only in release mode diff --git a/Daemons/10micron_stellarium/main.h b/Daemons/10micron_stellarium/main.h index ec6d9c1..3d595aa 100644 --- a/Daemons/10micron_stellarium/main.h +++ b/Daemons/10micron_stellarium/main.h @@ -22,16 +22,16 @@ #ifndef __MAIN_H__ #define __MAIN_H__ -#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include "cmdlnopts.h" #include "usefull_macros.h" diff --git a/Daemons/10micron_stellarium/telescope.c b/Daemons/10micron_stellarium/telescope.c index 3180d22..c2ac3e4 100644 --- a/Daemons/10micron_stellarium/telescope.c +++ b/Daemons/10micron_stellarium/telescope.c @@ -20,20 +20,25 @@ * MA 02110-1301, USA. * */ +#include + #include "telescope.h" #include "usefull_macros.h" // polling timeout for answer from mount #ifndef T_POLLING_TMOUT -#define T_POLLING_TMOUT (1.5) +#define T_POLLING_TMOUT (0.5) #endif +// wait for '\n' after last data read #ifndef WAIT_TMOUT -#define WAIT_TMOUT (0.5) +#define WAIT_TMOUT (0.01) #endif #define BUFLEN 80 +static char *hdname = NULL; + /** * read strings from terminal (ending with '\n') with timeout * @return NULL if nothing was read or pointer to static buffer @@ -69,10 +74,12 @@ static char *read_string(){ } /** - * write command + * write command, thread-safe * @return answer or NULL if error occured (or no answer) */ static char *write_cmd(const char *cmd){ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&mutex); DBG("Write %s", cmd); if(write_tty(cmd, strlen(cmd))) return NULL; double t0 = dtime(); @@ -80,32 +87,51 @@ static char *write_cmd(const char *cmd){ while(dtime() - t0 < T_POLLING_TMOUT){ // read answer if((ans = read_string())){ // parse new data DBG("got answer: %s", ans); + pthread_mutex_unlock(&mutex); return ans; } } + pthread_mutex_unlock(&mutex); return NULL; } + +int chkconn(){ + char tmpbuf[4096]; + read_tty(tmpbuf, 4096); // clear rbuf + write_cmd("#"); // clear cmd buffer + if(!write_cmd(":SB0#")) return 0; // 115200 + //if(!write_cmd(":GR#")) return 0; + return 1; +} + /** * connect telescope device - * @param dev (i) - device name to connect + * @param dev (i) - device name to connect + * @param hdrname (i) - output file with FITS-headers * @return 1 if all OK */ -int connect_telescope(char *dev){ +int connect_telescope(char *dev, char *hdrname){ if(!dev) return 0; + tcflag_t spds[] = {B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, 0}, *speeds = spds; DBG("Connection to device %s...", dev); putlog("Try to connect to device %s...", dev); - char tmpbuf[4096]; - fflush(stdout); - #ifndef COM_SPEED - #define COM_SPEED B9600 - #endif - tty_init(dev, COM_SPEED); - read_tty(tmpbuf, 4096); // clear rbuf + while(*speeds){ + DBG("Try %d", *speeds); + tty_init(dev, *speeds); + if(chkconn()) break; + ++speeds; + } + if(!*speeds) return 0; + if(*speeds != B115200){ + restore_tty(); + tty_init(dev, B115200); + if(!chkconn()) return 0; + } write_cmd(":U2#"); write_cmd(":U2#"); -// if(!write_cmd(":GR#")) return 0; - putlog("connected", dev); + putlog("connected to %s@115200, will write FITS-header into %s", dev, hdrname); + hdname = strdup(hdrname); DBG("connected"); return 1; } @@ -193,19 +219,47 @@ static int str2coord(char *str, double *val){ return 1; } +/** + * @brief printhdr - write FITS record into output file + * @param fd - fd to write + * @param key - key + * @param val - value + * @param cmnt - comment + * @return 0 if all OK + */ +static int printhdr(int fd, const char *key, const char *val, const char *cmnt){ + char tmp[81]; + char tk[9]; + if(strlen(key) > 8){ + snprintf(tk, 9, "%s", key); + key = tk; + } + if(cmnt){ + snprintf(tmp, 81, "%-8s= %-21s / %s", key, val, cmnt); + }else{ + snprintf(tmp, 81, "%-8s= %s", key, val); + } + size_t l = strlen(tmp); + tmp[l] = '\n'; + ++l; + if(write(fd, tmp, l) != (ssize_t)l){ + WARN("write()"); + return 1; + } + return 0; +} + + +static double r = 0., d = 0.; // RA/DEC from wrhdr +static time_t tlast = 0; // last time coordinates were refreshed /** * get coordinates + * @param ra (o) - right ascension (hours) + * @param decl (o) - declination (degrees) * @return 1 if all OK */ int get_telescope_coords(double *ra, double *decl){ - double r, d; - char *ans; - // :GR# -> 11:05:26.16# - ans = write_cmd(":GR#"); - if(!str2coord(ans, &r)) return 0; - // :GD# -> +44:14:10.7# - ans = write_cmd(":GD#"); - if(!str2coord(ans, &d)) return 0; + if(time(NULL) - tlast > COORDS_TOO_OLD_TIME) return 0; // coordinates are too old if(ra) *ra = r; if(decl) *decl = d; return 1; @@ -217,3 +271,108 @@ void stop_telescope(){ } putlog("Can't send command STOP"); } + +// site characteristics +static char + *elevation = NULL, + *longitude = NULL, + *latitude = NULL; + +// make duplicate of buf without trailing `#` +// if astr == 1, surround content with '' +static char *dups(const char *buf, int astr){ + if(!buf) return NULL; + char *newbuf = malloc(strlen(buf)+5), *bptr = newbuf+1; + if(!newbuf) return NULL; + strcpy(bptr, buf); + char *sharp = strrchr(bptr, '#'); + if(sharp) *sharp = 0; + if(astr){ + bptr = newbuf; + *bptr = '\''; + int l = strlen(newbuf); + newbuf[l] = '\''; + newbuf[l+1] = 0; + } + char *d = strdup(bptr); + free(newbuf); + return d; +} + +static void getplace(){ + char *ans; + if(!elevation){ + ans = write_cmd(":Gev#"); + elevation = dups(ans, 0); + } + if(!longitude){ + ans = write_cmd(":Gg#"); + longitude = dups(ans, 1); + } + if(!latitude){ + ans = write_cmd(":Gt#"); + latitude = dups(ans, 1); + } +} + + +/** + * @brief wrhdr - try to write into header file + */ +void wrhdr(){ + char *ans = NULL, *jd = NULL, *lst = NULL, *date = NULL; + // get coordinates for writing to file & sending to stellarium client + ans = write_cmd(":GR#"); + if(!str2coord(ans, &r)) return; + ans = write_cmd(":GD#"); + if(!str2coord(ans, &d)) return; + tlast = time(NULL); + if(!hdname) return; + if(!elevation || !longitude || !latitude) getplace(); + ans = write_cmd(":GJD#"); jd = dups(ans, 0); + ans = write_cmd(":GS#"); lst = dups(ans, 1); + ans = write_cmd(":GUDT#"); + if(ans){ + char *comma = strchr(ans, ','); + if(comma){ + *comma = 'T'; + date = dups(ans, 1); + } + } +#define WRHDR(k, v, c) do{if(printhdr(hdrfd, k, v, c)){close(hdrfd); return;}}while(0) + char val[22]; + if(unlink(hdname)){ + WARN("unlink(%s)", hdname); + return; + } + int hdrfd = open(hdname, O_WRONLY | O_TRUNC | O_CREAT, 0644); + if(hdrfd < 0){ + WARN("Can't open %s", hdname); + return; + } + WRHDR("TIMESYS", "'UTC'", "Time system"); + WRHDR("ORIGIN", "'SAO RAS'", "Organization responsible for the data"); + WRHDR("TELESCOP", "'Astrosib-500'", "Telescope name"); + snprintf(val, 22, "%.10f", r*15.); // convert RA to degrees + WRHDR("RA", val, "Right ascension, current epoch"); + snprintf(val, 22, "%.10f", d); + WRHDR("DEC", val, "Declination, current epoch"); + if(elevation) WRHDR("ELEVAT", elevation, "Elevation of site over the sea level"); + if(longitude) WRHDR("LONGITUD", longitude, "Geo longitude of site (east negative)"); + if(latitude) WRHDR("LATITUDE", latitude, "Geo latitude of site (south negative)"); + if(jd) WRHDR("MJD-END", jd, "Julian date of observations end"); + if(lst) WRHDR("LSTEND", lst, "Local sidereal time of observations end"); + if(date) WRHDR("DATE-END", date, "Date (UTC) of observations end"); + FREE(jd); + FREE(lst); + FREE(date); + // WRHDR("", , ""); + //ans = write_cmd(":GC#"); + //char *ans1 = write_cmd(":GC#"); +#undef WRHDR + close(hdrfd); +} + +// LSTSTART - sid time +// MJD-END + diff --git a/Daemons/10micron_stellarium/telescope.h b/Daemons/10micron_stellarium/telescope.h index 38956fb..efabb74 100644 --- a/Daemons/10micron_stellarium/telescope.h +++ b/Daemons/10micron_stellarium/telescope.h @@ -24,9 +24,13 @@ #ifndef __TELESCOPE_H__ #define __TELESCOPE_H__ -int connect_telescope(char *dev); +// max time after last coordinates reading +#define COORDS_TOO_OLD_TIME (5) + +int connect_telescope(char *dev, char *hdrname); int point_telescope(double ra, double decl); int get_telescope_coords(double *ra, double *decl); void stop_telescope(); +void wrhdr(); #endif // __TELESCOPE_H__ diff --git a/Docs/Alignment/Readme.md b/Docs/Alignment/Readme.md index 400b1e8..dda9580 100644 --- a/Docs/Alignment/Readme.md +++ b/Docs/Alignment/Readme.md @@ -10,3 +10,4 @@ Alignment procedure: - enter data into telescope mount You should store parameters RA2000, DEC2000 and SidTime of each FITS-file. +Also you will need telescope position data for each file - it's side of pier! \ No newline at end of file