add logging, heater period, max exptime

This commit is contained in:
eddyem 2017-04-24 12:06:41 +03:00
parent a8c4255f33
commit 5ac8803ca3
11 changed files with 205 additions and 29 deletions

View File

@ -1,33 +1,56 @@
# run `make DEF=...` to add extra defines
# run `make DEF=...` to add extra defines,
# conditional compile flags:
# NOLIBRAW=1 - not use libraw & libgd
# NOTIFF - not use libtiff
# NOCFITSIO - not use cfitsio
#
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
LDFLAGS += -lm -pthread
LDIMG := $(shell pkg-config --libs libraw) -lgd $(shell pkg-config --libs cfitsio) -ltiff
LDIMG :=
SRCS := $(wildcard *.c)
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
#DEFINES += -DEBUG
DEFINES += -DEBUG
CFLAGS += -Wall -Wextra -O2
CFLAGS += $(shell pkg-config --cflags libraw)
OBJS := $(SRCS:%.c=%.o)
CC = gcc
CPP = g++
all : sbig340_standalone sbig340_daemon sbig340_client
TARGETS := sbig340_daemon
ifndef NOLIBRAW
LDIMG += $(shell pkg-config --libs libraw) -lgd
CFLAGS += $(shell pkg-config --cflags libraw)
DEBAYER := debayer.o
DEFINES += -DLIBRAW
endif
ifndef NOTIFF
LDIMG += -ltiff
DEFINES += -DLIBTIFF
endif
ifndef NOCFITSIO
LDIMG += $(shell pkg-config --libs cfitsio)
DEFINES += -DLIBCFITSIO
endif
all : sbig340_daemon sbig340_standalone sbig340_client
debayer.o : debayer.cpp
@echo -e "\t\tG++ debayer"
$(CPP) $(CFLAGS) $(DEFINES) debayer.cpp -c
sbig340_standalone : $(SRCS) debayer.o
sbig340_standalone : $(SRCS) $(DEBAYER)
@echo -e "\t\tBuild standalone"
$(CC) $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(LDIMG) $(SRCS) debayer.o -o $@
$(CC) $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(LDIMG) $(SRCS) $(DEBAYER) -o $@
sbig340_daemon : $(SRCS)
@echo -e "\t\tBuild daemon"
$(CC) -DDAEMON $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(SRCS) -o $@
sbig340_client : $(SRCS) debayer.o
sbig340_client : $(SRCS) $(DEBAYER)
@echo -e "\t\tBuild client"
$(CC) -DCLIENT $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(LDIMG) $(SRCS) debayer.o -o $@
$(CC) -DCLIENT $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(LDIMG) $(SRCS) $(DEBAYER) -o $@
clean:
@echo -e "\t\tCLEAN"

View File

@ -59,6 +59,8 @@ glob_pars const Gdefault = {
.timestamp = 0,
.dark_interval = 1800,
.min_dark_exp = 30,
.max_exptime = -1,
.htrperiod = 0
};
/*
@ -82,6 +84,8 @@ myoption cmdlnopts[] = {
#endif
// not client options
#ifndef CLIENT
{"exptime-max",NEED_ARG,NULL, 0, arg_double, APTR(&G.max_exptime),_("maximal exposition time (seconds)")},
{"heaterperiod", NEED_ARG,NULL, 0, arg_int, APTR(&G.htrperiod), _("change heater ON time (0..3599 seconds)")},
{"device", NEED_ARG, NULL, 'i', arg_string, APTR(&G.device), _("serial device name (default: " DEFAULT_COMDEV ")")},
{"heater-on",NO_ARGS, APTR(&G.heater),HEATER_ON, arg_none, NULL, _("turn heater on")},
{"heater-off",NO_ARGS, APTR(&G.heater),HEATER_OFF, arg_none, NULL, _("turn heater off")},

View File

@ -52,6 +52,8 @@ typedef struct{
char *port; // port to connect
double dark_interval; // time interval (in seconds) between dark images taken
double min_dark_exp; // minimal exposition (in seconds) @ which darks would be taken
double max_exptime; // maximal exposition time
int htrperiod; // new value for heater ON time (0..3599 seconds)
char** rest_pars; // the rest parameters: array of char*
} glob_pars;

View File

@ -401,6 +401,11 @@ uint16_t *get_imdata(imstorage *img){
}
#endif // CLIENT
static double max_exptime = 180.;
void set_max_exptime(double t){
if(t > 30. && t < 300.) max_exptime = t;
}
/**
* save truncated to 256 levels histogram of `img` into file `f`
* @return 0 if all OK
@ -447,7 +452,7 @@ int save_histo(FILE *f, imstorage *img){
if(mul > mulmax) mul = mulmax;
double E = img->exptime * mul;
if(E < 5e-5) E = 5e-5; // too short exposition
else if(E > 180.) E = 180.; // no need to do expositions larger than 3 minutes
else if(E > max_exptime) E = max_exptime; // no need to do expositions larger than max_exptime
green("Recommended exposition time: %g seconds\n", E);
exp_calculated = E;
return 0;
@ -523,6 +528,7 @@ int store_image(imstorage *img){
if(write_debayer(img, (uint16_t)lowval)) status |= 8; // and save colour image
}
#endif
putlog("Save image, status=%d", status);
return status;
}
#endif // !DAEMON

View File

@ -78,6 +78,8 @@ extern double exp_calculated;
#define SUFFIX_TIFF "tiff"
#define SUFFIX_JPEG "jpg"
void set_max_exptime(double t);
char *make_filename(imstorage *img, const char *suff);
imstorage *chk_storeimg(imstorage *img, char* store, char *format);
int store_image(imstorage *filename);

36
main.c
View File

@ -41,6 +41,7 @@ void signals(int signo){
restore_console();
restore_tty();
#endif
putlog("Exit with status %d", signo);
exit(signo);
}
@ -52,10 +53,13 @@ int main(int argc, char **argv){
signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
glob_pars *G = parse_args(argc, argv);
if(G->rest_pars_num)
openlogfile(G->rest_pars[0]);
imstorage *img = NULL;
imsubframe *F = NULL;
#ifndef CLIENT
if(G->htrperiod) set_heater_period(G->htrperiod);
if(G->max_exptime) set_max_exptime(G->max_exptime);
if(G->splist){
list_speeds();
return 0;
@ -65,18 +69,20 @@ int main(int argc, char **argv){
#if defined DAEMON || defined CLIENT
if(!G->once){
#ifndef EBUG
green("Daemonize");
printf("\n");
putlog("Daemonize");
fflush(stdout);
if(daemon(1, 0)){
putlog("Can't daemonize");
ERR("daemon()");
}
#endif // EBUG
while(1){ // guard for dead processes
pid_t childpid = fork();
if(childpid){
DBG("Created child with PID %d\n", childpid);
putlog("Create child with PID %d\n", childpid);
DBG("Create child with PID %d\n", childpid);
wait(NULL);
putlog("Child %d died\n", childpid);
WARNX("Child %d died\n", childpid);
sleep(1);
}else{
@ -88,23 +94,31 @@ int main(int argc, char **argv){
#endif // DAEMON || CLIENT
#ifndef CLIENT
if(!try_connect(G->device, G->speed)){
putlog("device not answer");
WARNX(_("Check power and connection: device not answer!"));
return 1;
}
char *fw = get_firmvare_version();
if(fw) printf(_("Firmware version: %s\n"), fw);
if(G->newspeed && term_setspeed(G->newspeed))
if(G->newspeed && term_setspeed(G->newspeed)){
putlog("Can't change speed to %d", G->newspeed);
ERRX(_("Can't change speed to %d"), G->newspeed);
if(G->shutter_cmd && shutter_command(G->shutter_cmd))
}
if(G->shutter_cmd && shutter_command(G->shutter_cmd)){
putlog("Can't send shutter command: %s", G->shutter_cmd);
WARNX(_("Can't send shutter command: %s"), G->shutter_cmd);
if(G->heater != HEATER_LEAVE)
}
if(G->heater != HEATER_LEAVE){
heater(G->heater); // turn on/off heater
}
#ifndef DAEMON
if(G->takeimg){
#endif // DAEMON
if(G->subframe){
if(!(F = define_subframe(G->subframe)))
if(!(F = define_subframe(G->subframe))){
putlog("Error defining subframe");
ERRX(_("Error defining subframe"));
}
G->binning = 0xff; // take subframe
}
#endif // !CLIENT
@ -126,14 +140,18 @@ int main(int argc, char **argv){
img->binning = G->binning;
if(start_exposition(img, G->imtype)){ // start test exposition even in daemon
putlog("Error starting exposition");
ERRX(_("Error starting exposition"));
}else{
if(!get_imdata(img)){
putlog("Error image transfer");
WARNX(_("Error image transfer"));
}else{
#ifndef DAEMON
if(store_image(img))
if(store_image(img)){
putlog("Error storing image");
WARNX(_("Error storing image"));
}
#endif // !DAEMON
}
}

View File

@ -79,7 +79,7 @@ static uint8_t *findpar(uint8_t *str, char *par){
* get integer & double `parameter` value from string `str`, put value to `ret`
* @return 1 if all OK
*/
static long getintpar(uint8_t *str, char *parameter, long *ret){
static int getintpar(uint8_t *str, char *parameter, long *ret){
long tmp;
char *endptr;
if(!(str = findpar(str, parameter))) return 0;
@ -90,6 +90,7 @@ static long getintpar(uint8_t *str, char *parameter, long *ret){
DBG("get par: %s = %ld", parameter, tmp);
return 1;
}
#ifdef CLIENT
static int getdpar(uint8_t *str, char *parameter, double *ret){
double tmp;
char *endptr;
@ -101,6 +102,7 @@ static int getdpar(uint8_t *str, char *parameter, double *ret){
DBG("get par: %s = %g", parameter, tmp);
return 1;
}
#endif // CLIENT
/**************** CLIENT/SERVER FUNCTIONS ****************/
#ifdef DAEMON
@ -201,6 +203,7 @@ int send_ima(int sock, int webquery){
WARN("write()");
return 0;
}
putlog("send image to client");
return 1;
}
@ -243,6 +246,7 @@ void *handle_socket(void *asock){
}
_read = read(sock, buff, BUFLEN);
if(_read < 1){ // error or disconnect
putlog("Client disconnected");
DBG("Nothing to read from fd %d (ret: %zd)", sock, _read);
break;
}
@ -259,9 +263,15 @@ void *handle_socket(void *asock){
}
// here we can process user data
printf("user send: %s\n", found);
long ii; double dd;
if(getdpar((uint8_t*)found, "exptime", &dd)) printf("exptime: %g\n", dd);
if(getintpar((uint8_t*)found, "somepar", &ii)) printf("somepar: %ld\n", ii);
long htr;
// double dd;
//if(getdpar((uint8_t*)found, "exptime", &dd)) printf("exptime: %g\n", dd);
if(getintpar((uint8_t*)found, "heater", &htr)){
putlog("got command: heater=%ld", htr);
if(htr == 0) heater_off();
else heater_on();
break; // disconnect after command receiving
}
}
close(sock);
//DBG("closed");
@ -286,6 +296,7 @@ void *server(void *asock){
WARN("accept()");
continue;
}
putlog("Got connection from %s\n", inet_ntoa(their_addr.sin_addr));
pthread_t handler_thread;
if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock))
WARN("pthread_create()");
@ -307,6 +318,7 @@ static void daemon_(imstorage *img, int sock){
do{
if(pthread_kill(sock_thread, 0) == ESRCH){ // died
WARNX("Sockets thread died");
putlog("Sockets thread died");
pthread_join(sock_thread, NULL);
if(pthread_create(&sock_thread, NULL, server, (void*) &sock))
ERR("pthread_create()");
@ -322,12 +334,14 @@ static void daemon_(imstorage *img, int sock){
}
}
if(start_exposition(img, NULL)){
putlog("Error starting exposition, try later");
WARNX(_("Error starting exposition, try later"));
++errcntr;
}else{
FREE(img->imdata);
if(!get_imdata(img)){
++errcntr;
putlog("Error image transfer");
WARNX(_("Error image transfer"));
}else{
errcntr = 0;
@ -341,6 +355,7 @@ static void daemon_(imstorage *img, int sock){
}
}
if(errcntr >= 33){
putlog("Unrecoverable error, errcntr=%d. Exit", errcntr);
ERRX(_("Unrecoverable error"));
}
}while(1);
@ -383,8 +398,6 @@ static void client_(imstorage *img, int sock){
size_t Bufsiz = BUFLEN10;
uint8_t *recvBuff = MALLOC(uint8_t, Bufsiz);
while(1){
//size_t L = strlen(msg);
//if(send(sock, msg, L, 0) != L){ WARN("send"); continue;}
if(!waittoread(sock)) continue;
size_t offset = 0;
do{
@ -398,21 +411,30 @@ static void client_(imstorage *img, int sock){
DBG("Buffer reallocated, new size: %zd\n", Bufsiz);
}
ssize_t n = read(sock, &recvBuff[offset], Bufsiz - offset);
if(!n) break;
if(!n){
putlog("Socket closed");
break;
}
if(n < 0){
putlog("error in read()");
WARN("read");
break;
}
offset += n;
}while(waittoread(sock));
if(!offset){
putlog("Socket closed");
WARN("Socket closed\n");
return;
}
DBG("read %zd bytes\n", offset);
if(get_imstorage(img, recvBuff, offset)){
if(store_image(img))
if(store_image(img)){
putlog("Error storing image");
WARNX(_("Error storing image"));
}else{
putlog("Image saved");
}
}
if(img->once) break;
}
@ -438,6 +460,7 @@ void daemonize(imstorage *img, char *hostname, char *port){
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN);
DBG("canonname: %s, port: %u, addr: %s\n", res->ai_canonname, ntohs(ia->sin_port), str);
putlog("connect to %s:%s", hostname, port);
// loop through all the results and bind to the first we can
for(p = res; p != NULL; p = p->ai_next){
if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
@ -465,6 +488,7 @@ void daemonize(imstorage *img, char *hostname, char *port){
}
if(p == NULL){
// looped off the end of the list with no successful bind
putlog("failed to bind socket");
ERRX("failed to bind socket");
}
freeaddrinfo(res);
@ -473,6 +497,7 @@ void daemonize(imstorage *img, char *hostname, char *port){
#else
daemon_(img, sock);
#endif
putlog("Close socket");
close(sock);
signals(0);
}

41
term.c
View File

@ -48,6 +48,22 @@ static int speeds[] = {
460800
};
// values changed by heater_on() and heater_off() for indirect heater commands
static int set_heater_on = 0, set_heater_off = 0;
static time_t heater_period = 600; // default value for heater ON - 10 minutes
// change value of heater_period
void set_heater_period(int p){
if(p > 0 && p < 3600) heater_period = (time_t) p;
}
void heater_on(){
set_heater_on = 1;
set_heater_off = 0;
}
void heater_off(){
set_heater_off = 1;
set_heater_on = 0;
}
void list_speeds(){
green(_("Speeds available:\n"));
for(int i = 0; i < speedssize; ++i)
@ -126,6 +142,7 @@ static int download_in_progress = 0; // == 1 when image downloading runs
* Used only on exit, so don't check commands status
*/
void abort_image(){
putlog("Abort image exposition");
uint8_t tmpbuf[4096];
if(download_in_progress){
read_tty(tmpbuf, 4096);
@ -235,9 +252,11 @@ int try_connect(char *device, int speed){
}
if(TRANS_SUCCEED != st || l != 1 || *rd != ANS_COMM_TEST) continue;
DBG("Got it!");
putlog("Connection established at B%d", speeds[curspd]);
green(_("Connection established at B%d.\n"), speeds[curspd]);
return speeds[curspd];
}
putlog("No connection!");
red(_("No connection!\n"));
return 0;
}
@ -338,6 +357,7 @@ void heater(heater_cmd cmd){
trans_status st = TRANS_TIMEOUT;
if(i < 10) st = wait_checksum();
if(i == 10 || st != TRANS_SUCCEED){
putlog("Can't send heater command");
WARNX(_("Can't send heater command: %s"), (st==TRANS_TIMEOUT) ? _("no answer") : _("bad checksum"));
}
}
@ -464,7 +484,7 @@ imsubframe *define_subframe(char *parm){
}
/**
* Send command to start exposition
* Send command to start exposition & turn heater on/off if got command to do it
* @param binning - binning to expose
* @param exptime - exposition time
* @param imtype - autodark, light or dark
@ -472,6 +492,23 @@ imsubframe *define_subframe(char *parm){
*/
int start_exposition(imstorage *im, char *imtype){
FNAME();
// check heater commands
static time_t htr_on_time = 0;
if(htr_on_time && time(NULL) - htr_on_time > heater_period){
set_heater_off = 0;
set_heater_on = 0;
heater(HEATER_OFF);
htr_on_time = 0;
}
if(set_heater_off){
set_heater_off = 0;
heater(HEATER_OFF);
htr_on_time = 0;
}else if(set_heater_on){
set_heater_on = 0;
heater(HEATER_ON);
htr_on_time = time(NULL);
}
double exptime = im->exptime;
uint64_t exp100us = exptime * 10000.;
static uint8_t cmd[6] = {CMD_TAKE_IMAGE}; // `static` to save all data after first call
@ -545,6 +582,7 @@ int start_exposition(imstorage *im, char *imtype){
WARNX(_("Didn't get the respond"));
return 8;
}
putlog("start exposition, exptime=%gs", exptime);
im->imtype = it;
size_t W, H;
switch(im->binning){ // set image size
@ -699,6 +737,7 @@ uint16_t *get_image(imstorage *img){
bptr = ptr;
}while(rest);
printf("\b Done!\n");
putlog("got image data");
DBG("Got full data packet, capture time: %.1f seconds", dtime() - tstart);
download_in_progress = 0;
return buff;

6
term.h
View File

@ -85,6 +85,11 @@ int open_serial(char *dev);
int get_curspeed();
int try_connect(char *device, int speed);
void heater(heater_cmd cmd);
// setters for indirect heater using
void heater_on();
void heater_off();
void set_heater_period(int p);
void list_speeds();
void abort_image();
int term_setspeed(int speed);
@ -94,5 +99,6 @@ imsubframe *define_subframe(char *parm);
int start_exposition(imstorage *im, char *imtype);
int wait4image();
uint16_t *get_image(imstorage *img);
void set_heater_period(int p);
#endif // __TERM_H__

View File

@ -20,6 +20,7 @@
*/
#include "usefull_macros.h"
#include <linux/limits.h> // PATH_MAX
/**
* function for different purposes that need to know time intervals
@ -383,3 +384,49 @@ int str2double(double *num, const char *str){
if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number
return TRUE;
}
FILE *Flog = NULL; // log file descriptor
char *logname = NULL;
time_t log_open_time = 0;
/**
* Try to open log file
* if failed show warning message
*/
void openlogfile(char *name){
if(!name){
WARNX(_("Need filename"));
return;
}
green(_("Try to open log file %s in append mode\n"), name);
if(!(Flog = fopen(name, "a"))){
WARN(_("Can't open log file"));
return;
}
log_open_time = time(NULL);
logname = name;
}
/**
* Save message to log file, rotate logs every 24 hours
*/
int putlog(const char *fmt, ...){
if(!Flog) return 0;
time_t t_now = time(NULL);
if(t_now - log_open_time > 86400){ // rotate log
fprintf(Flog, "\n\t\t%sRotate log\n", ctime(&t_now));
fclose(Flog);
char newname[PATH_MAX];
snprintf(newname, PATH_MAX, "%s.old", logname);
if(rename(logname, newname)) WARN("rename()");
openlogfile(logname);
if(!Flog) return 0;
}
int i = fprintf(Flog, "\n\t\t%s", ctime(&t_now));
va_list ar;
va_start(ar, fmt);
i = vfprintf(Flog, fmt, ar);
va_end(ar);
fprintf(Flog, "\n");
fflush(Flog);
return i;
}

View File

@ -49,6 +49,7 @@
#include <termios.h>
#include <termio.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <stdint.h>
@ -137,4 +138,7 @@ int write_tty(const uint8_t *buff, size_t length);
int str2double(double *num, const char *str);
void openlogfile(char *name);
int putlog(const char *fmt, ...);
#endif // __USEFULL_MACROS_H__