diff --git a/Makefile b/Makefile index 1999ee1..65668bc 100644 --- a/Makefile +++ b/Makefile @@ -2,16 +2,18 @@ LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all LDFLAGS += -lm -pthread SRCS := $(wildcard *.c) -DEFINES := $(DEF) -D_XOPEN_SOURCE=1111 -DEFINES += -DEBUG -#OBJDIR := mk -CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines -std=gnu99 -#OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) -#DEPS := $(OBJS:.o=.d) +#GCC_GE_4_9_3 := $(shell g++ -dumpversion | gawk '{print $$1>=4.9.3?"1":"0"}') +DEFINES := $(DEF) -D_XOPEN_SOURCE=1111 +#ifeq ($(GCC_GE_4_9_3),1) + DEFINES += -D_DEFAULT_SOURCE +#else +# DEFINES += -D_BSD_SOURCE +#endif +#DEFINES += -DEBUG +CFLAGS += -Wall -Wextra -O2 -std=gnu99 CC = gcc all : sbig340 daemon client -# $(OBJDIR) sbig340 : $(SRCS) @echo -e "\t\tLD sbig340" @@ -25,27 +27,11 @@ client : $(SRCS) @echo -e "\t\tLD client" $(CC) -DCLIENT $(CFLAGS) $(DEFINES) $(LDFLAGS) $(shell pkg-config --libs cfitsio) -ltiff $(SRCS) -o client -#$(OBJDIR): -# mkdir $(OBJDIR) - -#ifneq ($(MAKECMDGOALS),clean) -#-include $(DEPS) -#endif - -#$(OBJDIR)/%.o: %.c -# @echo -e "\t\tCC $<" -# $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< - -#clean: -# @echo -e "\t\tCLEAN" -# @rm -f $(OBJS) $(DEPS) -# @rmdir $(OBJDIR) 2>/dev/null || true - -#xclean: clean -# @rm -f $(PROGRAM) +clean: + @echo -e "\t\tCLEAN" + @rm -f sbig340 daemon client gentags: CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null -.PHONY: gentags -#clean xclean +.PHONY: gentags clean diff --git a/Readme.md b/README.md similarity index 100% rename from Readme.md rename to README.md diff --git a/cmdlnopts.c b/cmdlnopts.c index a18dc99..9e0a365 100644 --- a/cmdlnopts.c +++ b/cmdlnopts.c @@ -53,8 +53,10 @@ glob_pars const Gdefault = { .imformat = NULL, .imstoretype = NULL, .outpfname = "output.tiff", - .hostname = "localhost", - .port = "4444" + .hostname = NULL, + .port = "4444", + .once = 0, + .timestamp = 0, }; /* @@ -93,6 +95,8 @@ myoption cmdlnopts[] = { #if defined DAEMON || defined CLIENT #ifndef DAEMON {"hostname",NEED_ARG, NULL, 'H', arg_string, APTR(&G.hostname), _("hostname to connect (default: localhost)")}, + {"once", NO_ARGS, NULL, '1', arg_int, APTR(&G.once), _("run client just once")}, + {"timestamp",NO_ARGS, NULL, 't', arg_int, APTR(&G.timestamp), _("add timestamp to filename")}, #endif {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("port to connect (default: 4444)")}, #endif diff --git a/cmdlnopts.h b/cmdlnopts.h index b4d0224..6b3543a 100644 --- a/cmdlnopts.h +++ b/cmdlnopts.h @@ -35,6 +35,8 @@ typedef struct{ int rest_pars_num; // number of rest parameters heater_cmd heater; // turn heater on/off/leave unchanged int splist; // list speeds available + int once; // run once (client) + int timestamp; // add timestamp int newspeed; // change speed int speed; // connect @ this speed char *shutter_cmd; // shutter command: 'o' for open, 'c' for close, 'k' for de-energize diff --git a/imfunctions.c b/imfunctions.c index cdafbc9..b6eac90 100644 --- a/imfunctions.c +++ b/imfunctions.c @@ -25,10 +25,12 @@ #include "imfunctions.h" #include "term.h" #include // strncasecmp -#include // save tiff #include // sqrt #include // time, gmtime etc +#ifndef DAEMON #include // save fits +#include // save tiff +#endif #include // basename #include // utimensat #include // AT_... @@ -38,7 +40,8 @@ double exp_calculated = -1.; // optimal exposition, calculated in histogram save * All image-storing functions modify ctime of saved files to be the time of * exposition start! */ - +#ifndef DAEMON +#include void modifytimestamp(char *filename, imstorage *img){ if(!filename) return; struct timespec times[2]; @@ -58,9 +61,19 @@ void modifytimestamp(char *filename, imstorage *img){ * make filename for given name, suffix and storage type * @return filename or NULL if can't create it */ -static char *make_filename(const char *outfile, const char *suff, store_type st){ +static char *make_filename(imstorage *img, const char *suff){ struct stat filestat; static char buff[FILENAME_MAX]; + store_type st = img->st; + char fnbuf[FILENAME_MAX], *outfile = img->imname; + if(img->timestamp){ + struct tm *stm = localtime(&img->exposetime); + // add timestamp as YYYY-MM-DD_hh:mm:ss + snprintf(fnbuf, FILENAME_MAX, "%s_%04d-%02d-%02d_%02d:%02d:%02d", outfile, + 1900+stm->tm_year, 1+stm->tm_mon, stm->tm_mday, + stm->tm_hour, stm->tm_min, stm->tm_sec); + outfile = fnbuf; + } if(st == STORE_NORMAL || st == STORE_REWRITE){ snprintf(buff, FILENAME_MAX, "%s.%s", outfile, suff); if(stat(buff, &filestat)){ @@ -143,18 +156,20 @@ imstorage *chk_storeimg(char *filename, char* store, char *format){ #define FMTSZ (3) image_format formats[FMTSZ] = {FORMAT_FITS, FORMAT_TIFF, FORMAT_RAW}; const char *suffixes[FMTSZ] = {SUFFIX_FITS, SUFFIX_TIFF, SUFFIX_RAW}; - for(size_t i = 0; i < FMTSZ; ++i){ - if(!(formats[i] & fmt)) continue; - if(!make_filename(nm, suffixes[i], st)){ - WARNX(_("Can't create output file (is it exists?)")); - free(nm); - return NULL; - } - } imstorage *ist = MALLOC(imstorage, 1); ist->st = st; ist->imformat = fmt; ist->imname = strdup(nm); + for(size_t i = 0; i < FMTSZ; ++i){ + if(!(formats[i] & fmt)) continue; + if(!make_filename(ist, suffixes[i])){ + WARNX(_("Can't create output file (is it exists?)")); + free(nm); + free(ist->imname); + free(ist); + return NULL; + } + } return ist; } @@ -165,7 +180,7 @@ imstorage *chk_storeimg(char *filename, char* store, char *format){ int writetiff(imstorage *img){ int H = img->H, W = img->W, y; uint16_t *data = img->imdata; - char *name = make_filename(img->imname, SUFFIX_TIFF, img->st); + char *name = make_filename(img, SUFFIX_TIFF); TIFF *image = NULL; if(!name || !(image = TIFFOpen(name, "w"))){ WARN("Can't save tiff file"); @@ -195,6 +210,7 @@ int writetiff(imstorage *img){ modifytimestamp(name, img); return 0; } +#endif /** * Calculate image statistics: print it on screen and save for `writefits` @@ -243,6 +259,7 @@ void print_stat(imstorage *img){ printf("At 3sigma: Noverload = %ld, avr = %.3f, std = %.3f\n", Noverld, avr, std); } +#ifndef DAEMON #define TRYFITS(f, ...) \ do{ int status = 0; \ f(__VA_ARGS__, &status); \ @@ -260,7 +277,7 @@ int writefits(imstorage *img){ long naxes[2] = {img->W, img->H}; char buf[80]; fitsfile *fp; - char *filename = make_filename(img->imname, SUFFIX_FITS, img->st); + char *filename = make_filename(img, SUFFIX_FITS); TRYFITS(fits_create_file, &fp, filename); TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes); // FILE / Input file original name @@ -293,9 +310,9 @@ int writefits(imstorage *img){ WRITEKEY(TSTRING, "IMAGETYP", buf, "Image type"); // DATAMAX, DATAMIN / Max,min pixel value uint16_t val = UINT16_MAX; - WRITEKEY(TUSHORT, "DATAMAX", &val, "Max pixel value"); + WRITEKEY(TUSHORT, "DATAMAX", &val, "Max possible pixel value"); val = 0; - WRITEKEY(TUSHORT, "DATAMIN", &val, "Min pixel value"); + WRITEKEY(TUSHORT, "DATAMIN", &val, "Min possible pixel value"); // statistical values WRITEKEY(TUSHORT, "STATMAX", &glob_max, "Max pixel value"); WRITEKEY(TUSHORT, "STATMIN", &glob_min, "Min pixel value"); @@ -335,6 +352,7 @@ int writefits(imstorage *img){ green(_("Image %s saved\n"), filename); return 0; } +#endif #ifndef CLIENT /** @@ -406,8 +424,9 @@ int save_histo(FILE *f, imstorage *img){ return 0; } +#ifndef DAEMON int writedump(imstorage *img){ - char *name = make_filename(img->imname, SUFFIX_RAW, img->st); + char *name = make_filename(img, SUFFIX_RAW); if(!name) return 1; int f = open(name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(f){ @@ -423,7 +442,7 @@ int writedump(imstorage *img){ return 3; } modifytimestamp(name, img); - name = make_filename(img->imname, "histogram.txt", img->st); + name = make_filename(img, "histogram.txt"); if(!name) return 4; FILE *h = fopen(name, "w"); if(!h) return 5; @@ -466,3 +485,4 @@ int store_image(imstorage *img){ } return status; } +#endif diff --git a/imfunctions.h b/imfunctions.h index dc9af0d..fd122d1 100644 --- a/imfunctions.h +++ b/imfunctions.h @@ -66,6 +66,8 @@ typedef struct{ size_t W, H; // image size uint16_t *imdata; // image data itself time_t exposetime; // time of exposition start + int timestamp; // add timestamp to filename + int once; // get only one image } imstorage; extern double exp_calculated; diff --git a/main.c b/main.c index a59b2ef..72decc4 100644 --- a/main.c +++ b/main.c @@ -111,6 +111,10 @@ int main(int argc, char **argv){ run_terminal(); // non-echo terminal mode } #endif // !defined DAEMON && !defined CLIENT +#ifdef CLIENT + img->once = G->once; + img->timestamp = G->timestamp; +#endif #if defined CLIENT || defined DAEMON daemonize(img, G->hostname, G->port); #endif diff --git a/socket.c b/socket.c index 0aaad61..947a8a1 100644 --- a/socket.c +++ b/socket.c @@ -31,6 +31,9 @@ #include #include // INT_xxx #include // pthread_kill +#include // daemon +#include // wait +#include //prctl #define BUFLEN (10240) #define BUFLEN10 (1048576) @@ -396,6 +399,7 @@ static void client_(imstorage *img, int sock){ if(store_image(img)) WARNX(_("Error storing image")); } + if(img->once) break; } } #endif @@ -405,8 +409,9 @@ static void client_(imstorage *img, int sock){ */ void daemonize(imstorage *img, char *hostname, char *port){ FNAME(); - green("Daemonize\n"); #ifndef EBUG + if(!img->once){ + green("Daemonize\n"); if(daemon(1, 0)){ ERR("daemon()"); } @@ -421,7 +426,7 @@ void daemonize(imstorage *img, char *hostname, char *port){ prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies break; // go out to normal functional } - } + }} #endif int sock = -1; struct addrinfo hints, *res, *p; diff --git a/term.h b/term.h index e15908a..46fe622 100644 --- a/term.h +++ b/term.h @@ -41,7 +41,7 @@ typedef enum{ } heater_cmd; // terminal timeout (seconds) -#define WAIT_TMOUT (0.1) +#define WAIT_TMOUT (0.2) // timeout waitint 'D' #define EXP_DONE_TMOUT (5.0) // dataportion transfer timeout diff --git a/usefull_macros.c b/usefull_macros.c index fbac349..4f5ee6b 100644 --- a/usefull_macros.c +++ b/usefull_macros.c @@ -333,7 +333,7 @@ size_t read_tty(uint8_t *buff, size_t length){ int retval; FD_ZERO(&rfds); FD_SET(comfd, &rfds); - tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms + tv.tv_sec = 0; tv.tv_usec = 500000; // wait for 500ms max retval = select(comfd + 1, &rfds, NULL, NULL, &tv); if (!retval) return 0; if(FD_ISSET(comfd, &rfds)){