add client/server (not tested yet)

This commit is contained in:
Edward Emelianov 2022-03-17 18:06:18 +03:00
parent bd70ff5bc8
commit ebf6a53d63
19 changed files with 2269 additions and 510 deletions

View File

@ -19,7 +19,7 @@ add_definitions(-D_XOPEN_SOURCE=1234 -D_DEFAULT_SOURCE -D_GNU_SOURCE -DLOCALEDIR
set(CMAKE_COLOR_MAKEFILE ON) set(CMAKE_COLOR_MAKEFILE ON)
set(SOURCES main.c cmdlnopts.c ccdfunc.c) set(SOURCES main.c cmdlnopts.c ccdfunc.c socket.c server.c client.c)
# cmake -DDEBUG=yes -> debugging # cmake -DDEBUG=yes -> debugging
if(DEFINED DEBUG AND DEBUG STREQUAL "yes") if(DEFINED DEBUG AND DEBUG STREQUAL "yes")

View File

@ -25,7 +25,7 @@
#include <unistd.h> #include <unistd.h>
#include <usefull_macros.h> #include <usefull_macros.h>
#include "ccdfunc.h" #include "basestructs.h"
extern Camera camera; extern Camera camera;
extern Focuser focuser; extern Focuser focuser;

View File

@ -21,7 +21,7 @@
#include <string.h> #include <string.h>
#include <usefull_macros.h> #include <usefull_macros.h>
#include "ccdfunc.h" #include "basestructs.h"
extern Camera camera; extern Camera camera;
extern Focuser focuser; extern Focuser focuser;

View File

@ -26,7 +26,7 @@
#include <usefull_macros.h> #include <usefull_macros.h>
#include <ASICamera2.h> #include <ASICamera2.h>
#include "ccdfunc.h" #include "basestructs.h"
extern Camera camera; extern Camera camera;
extern Focuser focuser; extern Focuser focuser;
@ -47,6 +47,7 @@ static struct{
float mingain; float mingain;
float maxbright; float maxbright;
float minbright; float minbright;
int maxbin;
} extrvalues = {0}; // extremal values } extrvalues = {0}; // extremal values
static double starttime = 0.; // time when exposure started static double starttime = 0.; // time when exposure started
@ -69,6 +70,7 @@ static int zwo_getfloat(float *f, ASI_CONTROL_TYPE t){
long val; ASI_BOOL aut = ASI_FALSE; long val; ASI_BOOL aut = ASI_FALSE;
if(ASI_SUCCESS != ASIGetControlValue(caminfo.CameraID, t, &val, &aut)) if(ASI_SUCCESS != ASIGetControlValue(caminfo.CameraID, t, &val, &aut))
return FALSE; return FALSE;
if(aut) DBG("VALUE IS AUTO!!!");
*f = (float) val; *f = (float) val;
return TRUE; return TRUE;
} }
@ -142,6 +144,7 @@ static int startcapt(){
static void asi_closecam(){ static void asi_closecam(){
FNAME(); FNAME();
if(caminfo.CameraID){ if(caminfo.CameraID){
camcancel();
ASICloseCamera(caminfo.CameraID); ASICloseCamera(caminfo.CameraID);
caminfo.CameraID = 0; caminfo.CameraID = 0;
} }
@ -154,12 +157,10 @@ static int setdevno(int n){
DBG("Camera #%d, name: %s, ID: %d", n, caminfo.Name, caminfo.CameraID); DBG("Camera #%d, name: %s, ID: %d", n, caminfo.Name, caminfo.CameraID);
DBG("WxH: %ldx%ld, %s", caminfo.MaxWidth, caminfo.MaxHeight, caminfo.IsColorCam == ASI_TRUE ? "color" : "monochrome"); DBG("WxH: %ldx%ld, %s", caminfo.MaxWidth, caminfo.MaxHeight, caminfo.IsColorCam == ASI_TRUE ? "color" : "monochrome");
DBG("Pixel size: %1.1f mkm; gain: %1.2f e/ADU", caminfo.PixelSize, caminfo.ElecPerADU); DBG("Pixel size: %1.1f mkm; gain: %1.2f e/ADU", caminfo.PixelSize, caminfo.ElecPerADU);
#ifdef EBUG
int *sup = caminfo.SupportedBins; int *sup = caminfo.SupportedBins;
while(*sup){ while(*sup){
green("Supported bin: %d\n", *sup++); extrvalues.maxbin = *sup++;
} }
#endif
camera.pixX = camera.pixY = (float)caminfo.PixelSize / 1e6; // um -> m camera.pixX = camera.pixY = (float)caminfo.PixelSize / 1e6; // um -> m
camera.array = (frameformat){.w = caminfo.MaxWidth, .h = caminfo.MaxHeight, .xoff = 0, .yoff = 0}; camera.array = (frameformat){.w = caminfo.MaxWidth, .h = caminfo.MaxHeight, .xoff = 0, .yoff = 0};
camera.field = camera.array; // initial setup (will update later) camera.field = camera.array; // initial setup (will update later)
@ -217,7 +218,10 @@ static int setdevno(int n){
} }
static int camsetbrig(float b){ static int camsetbrig(float b){
if(b < extrvalues.minbright || b > extrvalues.maxbright) return FALSE; if(b < extrvalues.minbright || b > extrvalues.maxbright){
WARNX(_("Brightness should be from %g to %g"), extrvalues.minbright, extrvalues.maxbright);
return FALSE;
}
return zwo_setfloat(b, ASI_BRIGHTNESS); return zwo_setfloat(b, ASI_BRIGHTNESS);
} }
@ -233,7 +237,10 @@ static int camsetexp(float t){
} }
static int camsetgain(float g){ static int camsetgain(float g){
if(g < extrvalues.mingain || g > extrvalues.maxgain) return FALSE; if(g < extrvalues.mingain || g > extrvalues.maxgain){
WARNX(_("Gain should be from %g to %g"), extrvalues.mingain, extrvalues.maxgain);
return FALSE;
}
return zwo_setfloat(g, ASI_GAIN); return zwo_setfloat(g, ASI_GAIN);
} }
@ -243,6 +250,10 @@ static int camgetgain(float *g){
} }
static int camsett(float t){ static int camsett(float t){
if(caminfo.IsCoolerCam == ASI_FALSE){
DBG("Cooling unsupported");
return FALSE;
}
if(!zwo_setfloat(1., ASI_FAN_ON)){ if(!zwo_setfloat(1., ASI_FAN_ON)){
DBG("Can't set fan on"); DBG("Can't set fan on");
return FALSE; return FALSE;
@ -251,6 +262,10 @@ static int camsett(float t){
if(zwo_getfloat(&f, ASI_FAN_ON)){ if(zwo_getfloat(&f, ASI_FAN_ON)){
DBG("FAN: %g", f); DBG("FAN: %g", f);
} }
if(!zwo_setfloat(1., ASI_COOLER_ON)){
DBG("Can't set cooler on");
return FALSE;
}
if(!zwo_setfloat(t, ASI_TARGET_TEMP)){ if(!zwo_setfloat(t, ASI_TARGET_TEMP)){
DBG("Can't set target temperature"); DBG("Can't set target temperature");
return FALSE; return FALSE;
@ -258,30 +273,25 @@ static int camsett(float t){
if(zwo_getfloat(&f, ASI_TARGET_TEMP)){ if(zwo_getfloat(&f, ASI_TARGET_TEMP)){
DBG("Ttarg = %g", f); DBG("Ttarg = %g", f);
} }
if(!zwo_setfloat(1., ASI_COOLER_ON)){
DBG("Can't set cooler on");
return FALSE;
}
if(!zwo_getfloat(&f, ASI_COOLER_ON)) return FALSE; if(!zwo_getfloat(&f, ASI_COOLER_ON)) return FALSE;
DBG("COOLERON = %g", f); DBG("COOLERON = %g", f);
usleep(100000); #ifdef EBUG
double t0 = dtime(); double t0 = dtime();
float c, p, tn; float c, p, tn;
while(dtime() - t0 < 10.){ while(dtime() - t0 < 1200.){
green("%.1f", dtime()-t0); usleep(100000); // without this first ASI_FAN_ON will show false data
green("%.1f ", dtime()-t0);
zwo_getfloat(&f, ASI_FAN_ON); zwo_getfloat(&f, ASI_FAN_ON);
zwo_getfloat(&t, ASI_TARGET_TEMP); zwo_getfloat(&t, ASI_TARGET_TEMP);
zwo_getfloat(&c, ASI_COOLER_ON); zwo_getfloat(&c, ASI_COOLER_ON);
zwo_getfloat(&tn, ASI_TEMPERATURE); zwo_getfloat(&tn, ASI_TEMPERATURE);
zwo_getfloat(&p, ASI_COOLER_POWER_PERC); zwo_getfloat(&p, ASI_COOLER_POWER_PERC);
printf("fan: %g, t: %g, cooler: %g, perc: %g, tnow: %g\n", f, t, c, p, tn/10.); printf("fan: %g, t: %g, cooler: %g, perc: %g, tnow: %g\n", f, t, c, p, tn/10.);
if(f > 0.) break;
usleep(100000);
} }
#endif
return TRUE; return TRUE;
} }
static int camgett(float *t){ static int camgett(float *t){
if(!t) return FALSE; if(!t) return FALSE;
float curt; float curt;
@ -295,7 +305,13 @@ static int gett(_U_ float *t){
} }
static int camsetbin(int h, int v){ static int camsetbin(int h, int v){
if(h != v) return FALSE; if(h != v){
WARNX(_("BinX and BinY should be equal"));
return FALSE;
}
if(h > extrvalues.maxbin){
WARNX(_("Maximal binning value is %d"), extrvalues.maxbin);
}
if(zwo_setfloat(1., ASI_HARDWARE_BIN)){ if(zwo_setfloat(1., ASI_HARDWARE_BIN)){
curbin = h; curbin = h;
return TRUE; return TRUE;
@ -322,8 +338,9 @@ static int camsetgeom(frameformat *f){ // w,h, xoff, yoff
DBG(_("Can't get geometry")); DBG(_("Can't get geometry"));
return FALSE; return FALSE;
} }
DBG("curformat: w=%d, h=%d, bin=%d", f->w, f->h, curbin);
DBG("w=%d, h=%d, bin=%d", f->w, f->h, curbin); DBG("w=%d, h=%d, bin=%d", f->w, f->h, curbin);
if(ASI_SUCCESS != ASISetStartPos(caminfo.CameraID, f->xoff, f->yoff)){ if(ASI_SUCCESS != ASISetStartPos(caminfo.CameraID, f->xoff/curbin, f->yoff/curbin)){
DBG("Can't set start pos"); DBG("Can't set start pos");
return FALSE; return FALSE;
} }
@ -331,6 +348,7 @@ static int camsetgeom(frameformat *f){ // w,h, xoff, yoff
DBG("Can't get start pos"); DBG("Can't get start pos");
return FALSE; return FALSE;
} }
DBG("curstartpos: x=%d, y=%d", f->xoff, f->yoff);
camera.geometry = *f; camera.geometry = *f;
return TRUE; return TRUE;
} }
@ -373,7 +391,20 @@ static int camgetio(_U_ int *io){ // not supported
return FALSE; return FALSE;
} }
static int camfan(_U_ fan_speed spd){ // not supported static int camfan(_U_ fan_speed spd){ // not supported, just turn it on/off
switch(spd){
case FAN_OFF:
if(!zwo_setfloat(0., ASI_FAN_ON)){
DBG("Can't set fan off");
return FALSE;
}
break;
default: // turn ON
if(!zwo_setfloat(1., ASI_FAN_ON)){
DBG("Can't set fan on");
return FALSE;
}
}
return TRUE; return TRUE;
} }

138
basestructs.h Normal file
View File

@ -0,0 +1,138 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef BASESTRUCTS_H__
#define BASESTRUCTS_H__
#include <stdint.h>
typedef struct{
uint16_t *data; // image data
int w, h; // image size
uint16_t max, min; // min/max values
float avr, std; // statistics
} IMG;
// format of single frame
typedef struct{
int w; int h; // width & height
int xoff; int yoff; // X and Y offset
} frameformat;
typedef enum{
SHUTTER_OPEN, // open shutter now
SHUTTER_CLOSE, // close shutter now
SHUTTER_OPENATLOW, // ext. expose control @low
SHUTTER_OPENATHIGH, // -//- @high
SHUTTER_AMOUNT, // amount of entries
} shutter_op;
typedef enum{
CAPTURE_NO, // no capture initiated
CAPTURE_PROCESS, // in progress
CAPTURE_CANTSTART, // can't start
CAPTURE_ABORTED, // some error - aborted
CAPTURE_READY, // ready - user can read image
} capture_status;
typedef enum{
FAN_OFF,
FAN_LOW,
FAN_MID,
FAN_HIGH,
} fan_speed;
// all setters and getters of Camera, Focuser and Wheel should return TRUE if success or FALSE if failed or unsupported
// camera
typedef struct{
int (*check)(); // check if the device is available, connect and init
int Ndevices; // amount of devices found
void (*close)(); // disconnect & close device
int (*startexposition)(); // start exposition
int (*pollcapture)(capture_status *st, float *remain);// start or poll capture process, `remain` - time remain (s)
int (*capture)(IMG *ima); // capture an image, struct `ima` should be prepared before
void (*cancel)(); // cancel exposition
// setters:
int (*setDevNo)(int n); // set active device number
int (*setbrightness)(float b);
int (*setexp)(float e);
int (*setgain)(float g);
int (*setT)(float t);
int (*setbin)(int binh, int binv); // binning
int (*setnflushes)(int N); // flushes amount
int (*shuttercmd)(shutter_op s); // work with shutter
int (*confio)(int s); // configure IO-port
int (*setio)(int s); // set IO-port to given state
int (*setframetype)(int l); // set frametype: 1 - light, 0 - dark
int (*setbitdepth)(int h); // set bit depth: 1 - high, 0 - low
int (*setfastspeed)(int s); // set readout speed: 1 - fast, 0 - low
// geometry (if TRUE, all args are changed to suitable values)
int (*setgeometry)(frameformat *fmt); // set geometry in UNBINNED coordinates
int (*setfanspeed)(fan_speed spd); // set fan speed
// getters:
int (*getbrightness)(float *b);// get brightnes level
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getgain)(float *g); // get gain value
int (*getmaxgain)(float *g);// get max available gain value
// get limits of geometry: maximal values and steps
int (*getgeomlimits)(frameformat *max, frameformat *step);
int (*getTcold)(float *t); // cold-side T
int (*getThot)(float *t); // hot-side T
int (*getTbody)(float *t); // body T
int (*getbin)(int *binh, int *binv);
int (*getio)(int *s); // get IO-port state
float pixX, pixY; // pixel size in um
frameformat field; // max field of view
frameformat array; // array format
frameformat geometry; // current geometry settings (as in setgeometry)
} Camera;
// focuser
typedef struct{
int (*check)(); // check if the device is available
int Ndevices;
void (*close)();
// setters:
int (*setDevNo)(int n); // set active device number
int (*setAbsPos)(int async, float n);// set absolute position (in millimeters!!!)
int (*home)(int async); // home device
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getTbody)(float *t); // body T
int (*getPos)(float *p); // current position number (starting from zero)
int (*getMaxPos)(float *p); // max position
int (*getMinPos)(float *p); // min position
} Focuser;
// wheel
typedef struct{
int (*check)(); // check if the device is available
int Ndevices;
void (*close)();
// setters:
int (*setDevNo)(int n); // set active device number
int (*setPos)(int n); // set absolute position (starting from 0)
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getTbody)(float *t); // body T
int (*getPos)(int *p); // current position number (starting from zero)
int (*getMaxPos)(int *p); // amount of positions
} Wheel;
#endif // BASESTRUCTS_H__

253
ccdfunc.c
View File

@ -41,9 +41,10 @@ static int fitserror = 0;
#define TRYFITS(f, ...) \ #define TRYFITS(f, ...) \
do{ int status = 0; \ do{ int status = 0; \
f(__VA_ARGS__, &status); \ f(__VA_ARGS__, &status); \
if(status){ \ if(status){ \
fits_report_error(stderr, status); \ fits_report_error(stderr, status); \
fitserror = status;} \ LOGERR("Fits error %d", status); \
fitserror = status;} \
}while(0) }while(0)
#define WRITEKEY(...) \ #define WRITEKEY(...) \
do{ int status = 0; \ do{ int status = 0; \
@ -105,16 +106,16 @@ static size_t curtime(char *s_time){ // current date/time
return strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm)); return strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm));
}*/ }*/
static int check_filename(char *buff, char *outfile, char *ext){ // check if I can create file prefix_XXXX.fits
struct stat filestat; static int check_filenameprefix(char *buff, int buflen){
int num; for(int num = 1; num < 10000; num++){
for(num = 1; num < 10000; num++){ if(snprintf(buff, buflen-1, "%s_%04d.fits", GP->outfileprefix, num) < 1)
if(snprintf(buff, PATH_MAX, "%s_%04d.%s", outfile, num, ext) < 1) return FALSE;
return 0; struct stat filestat;
if(stat(buff, &filestat)) // no such file or can't stat() if(stat(buff, &filestat)) // no such file or can't stat()
return 1; return TRUE;
} }
return 0; return FALSE;
} }
/** /**
@ -144,21 +145,37 @@ static void addrec(fitsfile *f, char *filename){
} }
} }
void saveFITS(IMG *img, char *filename){ // save FITS file `img` into GP->outfile or GP->outfileprefix_XXXX.fits
void saveFITS(IMG *img){
if(!camera){ if(!camera){
LOGERR("Can't save image: no camera device");
WARNX(_("Camera device unknown")); WARNX(_("Camera device unknown"));
return; return;
} }
char buff[PATH_MAX], fnam[PATH_MAX]; char buff[PATH_MAX], fnam[PATH_MAX];
if(filename == NULL) return; if(!GP->outfile && !GP->outfileprefix){
fitserror = 0; LOGERR("Can't save image: neither filename nor filename prefix pointed");
if(!check_filename(fnam, filename, "fits") && !GP->rewrite){ WARNX(_("Neither filename nor filename prefix pointed!"));
// îÅ ÍÏÇÕ ÓÏÈÒÁÎÉÔØ ÆÁÊÌ return;
WARNX(_("Can't save file")); }
}else{ if(GP->outfile){ // pointed specific output file name like "file.fits", check it
if(GP->rewrite){ struct stat filestat;
DBG("REW"); int s = stat(GP->outfile, &filestat);
snprintf(fnam, PATH_MAX, "!%s.fits", filename); if(s){ // not exists
snprintf(fnam, PATH_MAX-1, "%s", GP->outfile);
}else{ // exists
if(!GP->rewrite){
LOGERR("Can't save image: file %s exists", GP->outfile);
WARNX("File %s exists!", GP->outfile);
return;
}
snprintf(fnam, PATH_MAX-1, "!%s", GP->outfile);
}
}else{ // user pointed output file prefix
if(!check_filenameprefix(fnam, PATH_MAX)){
// îÅ ÍÏÇÕ ÓÏÈÒÁÎÉÔØ ÆÁÊÌ
WARNX(_("Can't save file with prefix %s"), GP->outfileprefix);
LOGERR("Can't save image with prefix %s", GP->outfileprefix);
} }
} }
int width = img->w, height = img->h; int width = img->w, height = img->h;
@ -171,12 +188,13 @@ void saveFITS(IMG *img, char *filename){
char bufc[FLEN_CARD]; char bufc[FLEN_CARD];
time_t savetime = time(NULL); time_t savetime = time(NULL);
fitsfile *fp; fitsfile *fp;
fitserror = 0;
TRYFITS(fits_create_file, &fp, fnam); TRYFITS(fits_create_file, &fp, fnam);
if(fitserror) goto cloerr; if(fitserror) goto cloerr;
TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes); TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
if(fitserror) goto cloerr; if(fitserror) goto cloerr;
// FILE / Input file original name // FILE / Input file original name
WRITEKEY(fp, TSTRING, "FILE", filename, "Input file original name"); WRITEKEY(fp, TSTRING, "FILE", fnam, "Input file original name");
// ORIGIN / organization responsible for the data // ORIGIN / organization responsible for the data
WRITEKEY(fp, TSTRING, "ORIGIN", "SAO RAS", "organization responsible for the data"); WRITEKEY(fp, TSTRING, "ORIGIN", "SAO RAS", "organization responsible for the data");
// OBSERVAT / Observatory name // OBSERVAT / Observatory name
@ -200,8 +218,8 @@ void saveFITS(IMG *img, char *filename){
camera->array.xoff + camera->array.w, camera->array.yoff + camera->array.h); camera->array.xoff + camera->array.w, camera->array.yoff + camera->array.h);
WRITEKEY(fp, TSTRING, "ARRAYFLD", bufc, "Camera full array size"); WRITEKEY(fp, TSTRING, "ARRAYFLD", bufc, "Camera full array size");
// CRVAL1, CRVAL2 / Offset in X, Y // CRVAL1, CRVAL2 / Offset in X, Y
if(GP->X0 > -1) WRITEKEY(fp, TINT, "X0", &GP->X0, "Subframe left border"); if(GP->X0 > -1) WRITEKEY(fp, TINT, "X0", &GP->X0, "Subframe left border without binning");
if(GP->Y0 > -1) WRITEKEY(fp, TINT, "Y0", &GP->Y0, "Subframe upper border"); if(GP->Y0 > -1) WRITEKEY(fp, TINT, "Y0", &GP->Y0, "Subframe upper border without binning");
if(GP->objtype) strncpy(bufc, GP->objtype, FLEN_CARD-1); if(GP->objtype) strncpy(bufc, GP->objtype, FLEN_CARD-1);
else if(GP->dark) sprintf(bufc, "dark"); else if(GP->dark) sprintf(bufc, "dark");
else sprintf(bufc, "light"); else sprintf(bufc, "light");
@ -221,7 +239,7 @@ void saveFITS(IMG *img, char *filename){
WRITEKEY(fp, TFLOAT, "STATAVR", &tmpf, "Average data value"); WRITEKEY(fp, TFLOAT, "STATAVR", &tmpf, "Average data value");
tmpf = img->std; tmpf = img->std;
WRITEKEY(fp, TFLOAT, "STATSTD", &tmpf, "Std. of data value"); WRITEKEY(fp, TFLOAT, "STATSTD", &tmpf, "Std. of data value");
WRITEKEY(fp, TFLOAT, "CAMTEMP0", &GP->temperature, "Camera temperature at exp. start, degr C"); // WRITEKEY(fp, TFLOAT, "CAMTEMP0", &GP->temperature, "Camera temperature at exp. start, degr C");
if(camera->getTcold(&tmpf)) if(camera->getTcold(&tmpf))
WRITEKEY(fp, TFLOAT, "CAMTEMP", &tmpf, "Camera temperature at exp. end, degr C"); WRITEKEY(fp, TFLOAT, "CAMTEMP", &tmpf, "Camera temperature at exp. end, degr C");
if(camera->getTbody(&tmpf)) if(camera->getTbody(&tmpf))
@ -231,6 +249,12 @@ void saveFITS(IMG *img, char *filename){
// EXPTIME / actual exposition time (sec) // EXPTIME / actual exposition time (sec)
tmpd = GP->exptime; tmpd = GP->exptime;
WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmpd, "Actual exposition time (sec)"); WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmpd, "Actual exposition time (sec)");
if(camera->getgain(&tmpf)){
WRITEKEY(fp, TFLOAT, "CAMGAIN", &tmpf, "CMOS gain value");
}
if(camera->getbrightness(&tmpf)){
WRITEKEY(fp, TFLOAT, "CAMBRIGH", &tmpf, "CMOS brightness value");
}
// DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC) // DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC)
strftime(bufc, FLEN_VALUE, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime)); strftime(bufc, FLEN_VALUE, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime));
WRITEKEY(fp, TSTRING, "DATE", bufc, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)"); WRITEKEY(fp, TSTRING, "DATE", bufc, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)");
@ -301,14 +325,16 @@ void saveFITS(IMG *img, char *filename){
TRYFITS(fits_close_file, fp); TRYFITS(fits_close_file, fp);
cloerr: cloerr:
if(fitserror == 0){ if(fitserror == 0){
LOGMSG("Save file '%s'", fnam);
verbose(1, _("File saved as '%s'"), fnam); verbose(1, _("File saved as '%s'"), fnam);
}else{ }else{
LOGERR("Can't save %s", fnam);
WARNX(_("Error saving file")); WARNX(_("Error saving file"));
fitserror = 0; fitserror = 0;
} }
} }
static void calculate_stat(IMG *image){ void calculate_stat(IMG *image){
uint64_t Noverld = 0L, size = image->h*image->w; uint64_t Noverld = 0L, size = image->h*image->w;
double sum = 0., sum2 = 0.; double sum = 0., sum2 = 0.;
uint16_t max = 0, min = 65535; uint16_t max = 0, min = 65535;
@ -340,6 +366,7 @@ static void calculate_stat(IMG *image){
double avr = sum/sz; double avr = sum/sz;
image->avr = avr; image->avr = avr;
image->std = sqrt(fabs(sum2/sz - avr*avr)); image->std = sqrt(fabs(sum2/sz - avr*avr));
image->max = max; image->min = min;
if(GP->verbose){ if(GP->verbose){
printf(_("Image stat:\n")); printf(_("Image stat:\n"));
printf("avr = %.1f, std = %.1f, Noverload = %ld\n", avr, image->std, Noverld); printf("avr = %.1f, std = %.1f, Noverload = %ld\n", avr, image->std, Noverld);
@ -347,32 +374,45 @@ static void calculate_stat(IMG *image){
} }
} }
int startFocuser(void **dlh){
if(!GP->focuserdev && !GP->commondev){
verbose(3, _("Focuser device not pointed"));
return FALSE;
}else{
char *plugin = GP->commondev ? GP->commondev : GP->focuserdev;
if(!(*dlh = init_focuser(plugin))) return FALSE;
}
if(!focuser->check()){
verbose(3, _("No focusers found"));
focuser = NULL;
return FALSE;
}
return TRUE;
}
void focclose(void *dlh){
focuser->close();
dlclose(dlh);
focuser = NULL;
}
/* /*
* Find focusers and work with each of them * Find focusers and work with each of them
*/ */
void focusers(){ void focusers(){
FNAME(); FNAME();
void *dlh = NULL; void *dlh = NULL;
if(!GP->focuserdev && !GP->commondev){ if(!startFocuser(&dlh)) return;
verbose(3, _("Focuser device not pointed"));
return;
}else{
char *plugin = GP->commondev ? GP->commondev : GP->focuserdev;
if(!(dlh = init_focuser(plugin))) return;
}
if(!focuser->check()){
verbose(3, _("No focusers found"));
focuser = NULL;
return;
}
if(GP->listdevices){ if(GP->listdevices){
for(int i = 0; i < focuser->Ndevices; ++i){ for(int i = 0; i < focuser->Ndevices; ++i){
if(!focuser->setDevNo(i)) continue;
char modname[256]; char modname[256];
focuser->getModelName(modname, 255); focuser->getModelName(modname, 255);
printf("Found focuser #%d: %s\n", i, modname); printf("Found focuser #%d: %s\n", i, modname);
} }
} }
int num = GP->focdevno; int num = GP->focdevno;
if(num < 0) num = 0;
if(num > focuser->Ndevices - 1){ if(num > focuser->Ndevices - 1){
WARNX(_("Found %d focusers, you point number %d"), focuser->Ndevices, num); WARNX(_("Found %d focusers, you point number %d"), focuser->Ndevices, num);
goto retn; goto retn;
@ -422,9 +462,29 @@ void focusers(){
if(!focuser->setAbsPos(GP->async, tagpos)) WARNX(_("Can't set position %g"), tagpos); if(!focuser->setAbsPos(GP->async, tagpos)) WARNX(_("Can't set position %g"), tagpos);
} }
retn: retn:
focuser->close(); focclose(dlh);
}
int startWheel(void **dlh){
if(!GP->wheeldev && !GP->commondev){
verbose(3, _("Wheel device not pointed"));
return FALSE;
}else{
char *plugin = GP->commondev ? GP->commondev : GP->wheeldev;
if(!(*dlh = init_wheel(plugin))) return FALSE;
}
if(!wheel->check()){
verbose(3, _("No wheels found"));
wheel = NULL;
return FALSE;
}
return TRUE;
}
void closewheel(void *dlh){
wheel->close();
dlclose(dlh); dlclose(dlh);
focuser = NULL; wheel = NULL;
} }
/* /*
@ -433,26 +493,17 @@ retn:
void wheels(){ void wheels(){
FNAME(); FNAME();
void *dlh = NULL; void *dlh = NULL;
if(!GP->wheeldev && !GP->commondev){ if(!startWheel(&dlh)) return;
verbose(3, _("Wheel device not pointed"));
return;
}else{
char *plugin = GP->commondev ? GP->commondev : GP->wheeldev;
if(!(dlh = init_wheel(plugin))) return;
}
if(!wheel->check()){
verbose(3, _("No wheels found"));
wheel = NULL;
return;
}
if(GP->listdevices){ if(GP->listdevices){
for(int i = 0; i < wheel->Ndevices; ++i){ for(int i = 0; i < wheel->Ndevices; ++i){
if(!wheel->setDevNo(i)) continue;
char modname[256]; char modname[256];
wheel->getModelName(modname, 255); wheel->getModelName(modname, 255);
printf("Found wheel #%d: %s\n", i, modname); printf("Found wheel #%d: %s\n", i, modname);
} }
} }
int num = GP->whldevno; int num = GP->whldevno;
if(num < 0) num = 0;
if(num > wheel->Ndevices - 1){ if(num > wheel->Ndevices - 1){
WARNX(_("Found %d wheels, you point number %d"), wheel->Ndevices, num); WARNX(_("Found %d wheels, you point number %d"), wheel->Ndevices, num);
goto retn; goto retn;
@ -487,9 +538,7 @@ void wheels(){
if(!wheel->setPos(pos)) if(!wheel->setPos(pos))
WARNX(_("Can't set wheel position %d"), pos); WARNX(_("Can't set wheel position %d"), pos);
retn: retn:
wheel->close(); closewheel(dlh);
dlclose(dlh);
wheel = NULL;
} }
/* /*
static void closeall(){ static void closeall(){
@ -500,22 +549,47 @@ static void closeall(){
static capture_status capt(){ static capture_status capt(){
capture_status cs; capture_status cs;
float tleave, tmpf; float tremain, tmpf;
while(camera->pollcapture(&cs, &tleave)){ while(camera->pollcapture(&cs, &tremain)){
if(cs != CAPTURE_PROCESS) break; if(cs != CAPTURE_PROCESS) break;
if(tleave > 0.1){ if(tremain > 0.1){
verbose(2, _("%.1f seconds till exposition ends"), tleave); verbose(2, _("%.1f seconds till exposition ends"), tremain);
if(camera->getTcold(&tmpf)) verbose(1, "CCDTEMP=%.1f", tmpf); if(camera->getTcold(&tmpf)) verbose(1, "CCDTEMP=%.1f", tmpf);
if(camera->getTbody(&tmpf)) verbose(1, "BODYTEMP=%.1f", tmpf); if(camera->getTbody(&tmpf)) verbose(1, "BODYTEMP=%.1f", tmpf);
} }
if(tleave > 6.) sleep(5); if(tremain > 6.) sleep(5);
else if(tleave > 0.9) sleep((int)(tleave+0.99)); else if(tremain > 0.9) sleep((int)(tremain+0.99));
else usleep((int)(1e6*tleave) + 100000); else usleep((int)(1e6*tremain) + 100000);
if(!camera) return CAPTURE_ABORTED; if(!camera) return CAPTURE_ABORTED;
} }
return cs; return cs;
} }
int startCCD(void **dlh){
if(!GP->cameradev && !GP->commondev){
verbose(3, _("Camera device not pointed"));
return FALSE;
}else{
char *plugin = GP->commondev ? GP->commondev : GP->cameradev;
if(!(*dlh = init_camera(plugin))) return FALSE;
}
if(!camera->check()){
verbose(3, _("No cameras found"));
LOGWARN(_("No cameras found"));
return FALSE;
}
return TRUE;
}
void closecam(void *dlh){
if(!dlh) return;
DBG("Close cam");
camera->close();
DBG("close dlh");
dlclose(dlh);
camera = NULL;
}
/* /*
* Find CCDs and work with each of them * Find CCDs and work with each of them
*/ */
@ -524,25 +598,17 @@ void ccds(){
float tmpf; float tmpf;
int tmpi; int tmpi;
void *dlh = NULL; void *dlh = NULL;
if(!GP->cameradev && !GP->commondev){ if(!startCCD(&dlh)) return;
verbose(3, _("Camera device not pointed"));
return;
}else{
char *plugin = GP->commondev ? GP->commondev : GP->cameradev;
if(!(dlh = init_camera(plugin))) return;
}
if(!camera->check()){
verbose(3, _("No cameras found"));
return;
}
if(GP->listdevices){ if(GP->listdevices){
for(int i = 0; i < camera->Ndevices; ++i){ for(int i = 0; i < camera->Ndevices; ++i){
if(!camera->setDevNo(i)) continue;
char modname[256]; char modname[256];
camera->getModelName(modname, 255); camera->getModelName(modname, 255);
printf("Found camera #%d: %s\n", i, modname); printf("Found camera #%d: %s\n", i, modname);
} }
} }
int num = GP->camdevno; int num = GP->camdevno;
if(num < 0) num = 0;
if(num > camera->Ndevices - 1){ if(num > camera->Ndevices - 1){
WARNX(_("Found %d cameras, you point number %d"), camera->Ndevices, num); WARNX(_("Found %d cameras, you point number %d"), camera->Ndevices, num);
goto retn; goto retn;
@ -571,7 +637,7 @@ void ccds(){
snprintf(buf, BUFSIZ, "(%d, %d)(%d, %d)", camera->field.xoff, camera->field.yoff, snprintf(buf, BUFSIZ, "(%d, %d)(%d, %d)", camera->field.xoff, camera->field.yoff,
camera->field.xoff + camera->field.w, camera->field.yoff + camera->field.h); camera->field.xoff + camera->field.w, camera->field.yoff + camera->field.h);
verbose(2, _("Field of view: %s"), buf); verbose(2, _("Field of view: %s"), buf);
if(GP->temperature < 40.){ if(!isnan(GP->temperature)){
if(!camera->setT((float)GP->temperature)) if(!camera->setT((float)GP->temperature))
WARNX(_("Can't set T to %g degC"), GP->temperature); WARNX(_("Can't set T to %g degC"), GP->temperature);
verbose(3, "SetT=%.1f", GP->temperature); verbose(3, "SetT=%.1f", GP->temperature);
@ -603,29 +669,40 @@ void ccds(){
WARNX(_("Can't set IOport")); WARNX(_("Can't set IOport"));
} }
if(GP->exptime < 0.) goto retn; if(GP->exptime < 0.) goto retn;
if(!isnan(GP->gain)){
DBG("Change gain to %g", GP->gain);
if(camera->setgain(GP->gain)){
camera->getgain(&GP->gain);
verbose(1, _("Set gain to %g"), GP->gain);
}else WARNX(_("Can't set gain to %g"), GP->gain);
}
if(!isnan(GP->brightness)){
if(camera->setbrightness(GP->brightness)){
camera->getbrightness(&GP->brightness);
verbose(1, _("Set brightness to %g"), GP->brightness);
}else WARNX(_("Can't set brightness to %g"), GP->brightness);
}
/*********************** expose control ***********************/ /*********************** expose control ***********************/
// cancel previous exp // cancel previous exp
camera->cancel(); camera->cancel();
if(!camera->setbin(GP->hbin, GP->vbin)) if(!camera->setbin(GP->hbin, GP->vbin))
WARNX(_("Can't set binning %dx%d"), GP->hbin, GP->vbin); WARNX(_("Can't set binning %dx%d"), GP->hbin, GP->vbin);
if(GP->fullframe){ if(GP->X0 < 0) GP->X0 = x0; // default values
DBG("FULLFRAME"); if(GP->Y0 < 0) GP->Y0 = y0;
GP->X0 = x0; GP->Y0 = y0; GP->X1 = x1; GP->Y1 = y1; if(GP->X1 < 0) GP->X1 = x1;
}
if(GP->X0 == -1) GP->X0 = x0; // default values
if(GP->Y0 == -1) GP->Y0 = y0;
if(GP->X1 == -1) GP->X1 = x1;
else if(GP->X1 > x1) GP->X1 = x1; else if(GP->X1 > x1) GP->X1 = x1;
if(GP->Y1 == -1) GP->Y1 = y1; if(GP->Y1 < 0) GP->Y1 = y1;
else if(GP->Y1 > y1) GP->Y1 = y1; else if(GP->Y1 > y1) GP->Y1 = y1;
frameformat fmt = {.w = GP->X1 - GP->X0, .h = GP->Y1 - GP->Y0, .xoff = GP->X0, .yoff = GP->Y0}; frameformat fmt = {.w = GP->X1 - GP->X0, .h = GP->Y1 - GP->Y0, .xoff = GP->X0, .yoff = GP->Y0};
int raw_width = fmt.w / GP->hbin, raw_height = fmt.h / GP->vbin; int raw_width = fmt.w / GP->hbin, raw_height = fmt.h / GP->vbin;
if(!camera->setgeometry(&fmt)) if(!camera->setgeometry(&fmt))
WARNX(_("Can't set given geometry")); WARNX(_("Can't set given geometry"));
verbose(3, "Geometry: off=%d/%d, wh=%d/%d", fmt.xoff, fmt.yoff, fmt.w, fmt.h); verbose(3, "Geometry: off=%d/%d, wh=%d/%d", fmt.xoff, fmt.yoff, fmt.w, fmt.h);
if(!camera->setnflushes(GP->nflushes)) if(GP->nflushes > 0){
WARNX(_("Can't set %d flushes"), GP->nflushes); if(!camera->setnflushes(GP->nflushes))
verbose(3, "Nflushes=%d", GP->nflushes); WARNX(_("Can't set %d flushes"), GP->nflushes);
else verbose(3, "Nflushes=%d", GP->nflushes);
}
if(!camera->setexp(GP->exptime)) if(!camera->setexp(GP->exptime))
WARNX(_("Can't set exposure time to %f seconds"), GP->exptime); WARNX(_("Can't set exposure time to %f seconds"), GP->exptime);
tmpi = (GP->dark) ? 0 : 1; tmpi = (GP->dark) ? 0 : 1;
@ -675,7 +752,7 @@ void ccds(){
break; break;
} }
calculate_stat(&ima); calculate_stat(&ima);
saveFITS(&ima, GP->outfile); saveFITS(&ima);
#ifdef IMAGEVIEW #ifdef IMAGEVIEW
if(GP->showimage){ // display image if(GP->showimage){ // display image
if((mainwin = getWin())){ if((mainwin = getWin())){
@ -748,11 +825,7 @@ void ccds(){
DBG("FREE img"); DBG("FREE img");
FREE(img); FREE(img);
retn: retn:
DBG("Close cam"); closecam(dlh);
camera->close();
DBG("close dlh");
dlclose(dlh);
camera = NULL;
} }
void cancel(){ void cancel(){

127
ccdfunc.h
View File

@ -20,125 +20,24 @@
#ifndef CCDFUNC_H__ #ifndef CCDFUNC_H__
#define CCDFUNC_H__ #define CCDFUNC_H__
#include <stdint.h> #include "basestructs.h"
typedef struct{ extern Camera *camera;
uint16_t *data; // image data extern Focuser *focuser;
int w, h; // image size extern Wheel *wheel;
uint16_t max, min; // min/max values
float avr, std; // statistics
} IMG;
// format of single frame void calculate_stat(IMG *image);
typedef struct{ void saveFITS(IMG *img); // for imageview module
int w; int h; // width & height
int xoff; int yoff; // X and Y offset
} frameformat;
typedef enum{
SHUTTER_OPEN, // open shutter now
SHUTTER_CLOSE, // close shutter now
SHUTTER_OPENATLOW, // ext. expose control @low
SHUTTER_OPENATHIGH, // -//- @high
SHUTTER_AMOUNT, // amount of entries
} shutter_op;
typedef enum{
CAPTURE_NO, // no capture initiated
CAPTURE_PROCESS, // in progress
CAPTURE_CANTSTART, // can't start
CAPTURE_ABORTED, // some error - aborted
CAPTURE_READY, // ready - user can read image
} capture_status;
typedef enum{
FAN_OFF,
FAN_LOW,
FAN_MID,
FAN_HIGH,
} fan_speed;
// all setters and getters of Camera, Focuser and Wheel should return TRUE if success or FALSE if failed or unsupported
// camera
typedef struct{
int (*check)(); // check if the device is available, connect and init
int Ndevices; // amount of devices found
void (*close)(); // disconnect & close device
int (*startexposition)(); // start exposition
int (*pollcapture)(capture_status *st, float *remain);// start or poll capture process, `remain` - time remain (s)
int (*capture)(IMG *ima); // capture an image, struct `ima` should be prepared before
void (*cancel)(); // cancel exposition
// setters:
int (*setDevNo)(int n); // set active device number
int (*setbrightness)(float b);
int (*setexp)(float e);
int (*setgain)(float g);
int (*setT)(float t);
int (*setbin)(int binh, int binv); // binning
int (*setnflushes)(int N); // flushes amount
int (*shuttercmd)(shutter_op s); // work with shutter
int (*confio)(int s); // configure IO-port
int (*setio)(int s); // set IO-port to given state
int (*setframetype)(int l); // set frametype: 1 - light, 0 - dark
int (*setbitdepth)(int h); // set bit depth: 1 - high, 0 - low
int (*setfastspeed)(int s); // set readout speed: 1 - fast, 0 - low
// geometry (if TRUE, all args are changed to suitable values)
int (*setgeometry)(frameformat *fmt); // set geometry in UNBINNED coordinates
int (*setfanspeed)(fan_speed spd); // set fan speed
// getters:
int (*getbrightness)(float *b);// get brightnes level
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getgain)(float *g); // get gain value
int (*getmaxgain)(float *g);// get max available gain value
// get limits of geometry: maximal values and steps
int (*getgeomlimits)(frameformat *max, frameformat *step);
int (*getTcold)(float *t); // cold-side T
int (*getThot)(float *t); // hot-side T
int (*getTbody)(float *t); // body T
int (*getbin)(int *binh, int *binv);
int (*getio)(int *s); // get IO-port state
float pixX, pixY; // pixel size in um
frameformat field; // max field of view
frameformat array; // array format
frameformat geometry; // current geometry settings (as in setgeometry)
} Camera;
// focuser
typedef struct{
int (*check)(); // check if the device is available
int Ndevices;
void (*close)();
// setters:
int (*setDevNo)(int n); // set active device number
int (*setAbsPos)(int async, float n);// set absolute position (in millimeters!!!)
int (*home)(int async); // home device
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getTbody)(float *t); // body T
int (*getPos)(float *p); // current position number (starting from zero)
int (*getMaxPos)(float *p); // max position
int (*getMinPos)(float *p); // min position
} Focuser;
// wheel
typedef struct{
int (*check)(); // check if the device is available
int Ndevices;
void (*close)();
// setters:
int (*setDevNo)(int n); // set active device number
int (*setPos)(int n); // set absolute position (starting from 0)
// getters:
int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes)
int (*getTbody)(float *t); // body T
int (*getPos)(int *p); // current position number (starting from zero)
int (*getMaxPos)(int *p); // amount of positions
} Wheel;
void saveFITS(IMG *img, char *filename); // for imageview module
void focusers(); void focusers();
void wheels(); void wheels();
void ccds(); void ccds();
void cancel(); void cancel();
int startCCD(void **dlh);
int startWheel(void **dlh);
int startFocuser(void **dlh);
void focclose(void *dlh);
void closewheel(void *dlh);
void closecam(void *dlh);
#endif // CCDFUNC_H__ #endif // CCDFUNC_H__

176
client.c Normal file
View File

@ -0,0 +1,176 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// client-side functions
#include <math.h> // isnan
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <usefull_macros.h>
#include "client.h"
#include "cmdlnopts.h"
#include "server.h" // for common commands names
#include "socket.h"
static char sendbuf[BUFSIZ];
#define SENDMSG(...) do{snprintf(sendbuf, BUFSIZ-1, __VA_ARGS__); verbose(2, "%s", sendbuf); sendstrmessage(sock, sendbuf); getans(sock);}while(0)
/**
* check data from fd (polling function for client)
* @param fd - file descriptor
* @return 0 in case of timeout, 1 in case of fd have data, -1 if error
*/
static int canberead(int fd){
fd_set fds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100;
FD_ZERO(&fds);
FD_SET(fd, &fds);
do{
int rc = select(fd+1, &fds, NULL, NULL, &timeout);
if(rc < 0){
if(errno != EINTR){
LOGWARN("select()");
WARN("select()");
return -1;
}
continue;
}
break;
}while(1);
if(FD_ISSET(fd, &fds)){
return 1;
}
return 0;
}
static char *getans(int sock){
static char buf[BUFSIZ];
double t0 = dtime();
char *ans = NULL;
while(dtime() - t0 < ANSWER_TIMEOUT){
if(1 != canberead(sock)) continue;
int n = read(sock, buf, BUFSIZ-1);
if(n == 0){
WARNX("Server disconnected");
signals(1);
}
ans = buf;
buf[n] = 0;
DBG("Got from server: %s", buf);
verbose(1, "%s", buf);
}
return ans;
}
static char *makeabspath(const char *path){
static char buf[PATH_MAX];
if(!path) return NULL;
char *ret = NULL;
int unl = 0;
FILE *f = fopen(path, "r");
if(!f){
f = fopen(path, "a");
if(!f){
ERR("Can't create %s", path);
return NULL;
}
unl = 1;
}
if(!realpath(path, buf)){
ERR("realpath()");
}else ret = buf;
fclose(f);
if(unl) unlink(path);
return ret;
}
/**
* @brief processData - process here some actions and make messages for server
*/
static void process_data(int sock){
// focuser
if(GP->listdevices) SENDMSG(CMD_FOCLIST);
if(GP->focdevno > -1) SENDMSG(CMD_FDEVNO "=%d", GP->focdevno);
if(!isnan(GP->gotopos)){
SENDMSG(CMD_FGOTO "=%g", GP->gotopos);
}
// wheel
if(GP->listdevices) SENDMSG(CMD_WLIST);
if(GP->whldevno > -1) SENDMSG(CMD_WDEVNO "=%d", GP->whldevno);
if(GP->setwheel > -1) SENDMSG(CMD_WPOS "=%d", GP->setwheel);
// CCD/CMOS
if(GP->cancelexpose) SENDMSG(CMD_EXPSTATE "=%d", CAMERA_IDLE);
if(GP->listdevices) SENDMSG(CMD_CAMLIST);
if(GP->camdevno > -1) SENDMSG(CMD_CAMDEVNO "=%d", GP->camdevno);
if(GP->hbin) SENDMSG(CMD_HBIN "=%d", GP->hbin);
if(GP->vbin) SENDMSG(CMD_VBIN "=%d", GP->vbin);
if(!isnan(GP->temperature)) SENDMSG(CMD_CAMTEMPER "=%g", GP->temperature);
if(GP->shtr_cmd > -1) SENDMSG(CMD_SHUTTER "=%d", GP->shtr_cmd);
if(GP->confio > -1) SENDMSG(CMD_CONFIO "=%d", GP->confio);
if(GP->setio > -1) SENDMSG(CMD_IO "=%d", GP->setio);\
if(!isnan(GP->gain)) SENDMSG(CMD_GAIN "=%g", GP->gain);
if(!isnan(GP->brightness)) SENDMSG(CMD_BRIGHTNESS "=%g", GP->brightness);
if(GP->nflushes > 0) SENDMSG(CMD_NFLUSHES "=%d", GP->nflushes);
if(GP->rewrite) SENDMSG(CMD_REWRITE "=1");
else SENDMSG(CMD_REWRITE "=0");
if(GP->outfile) SENDMSG(CMD_FILENAME "=%s", makeabspath(GP->outfile));
if(GP->outfileprefix) SENDMSG(CMD_FILENAMEPREFIX "=%s", makeabspath(GP->outfileprefix));
// if client gives filename and exptime, make exposition
if(GP->exptime > -DBL_EPSILON){
SENDMSG(CMD_EXPOSITION "=%g", GP->exptime);
if(GP->outfile || GP->outfileprefix) SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE);
}
// common information
SENDMSG(CMD_INFO);
}
void client(int sock){
process_data(sock);
if(!GP->waitexpend) return;
double t0 = dtime(), tw = t0;
while(dtime() - t0 < CLIENT_TIMEOUT){
if(GP->waitexpend && dtime() - tw > WAIT_TIMEOUT){
SENDMSG(CMD_TREMAIN); // get remained time
tw = dtime();
sprintf(sendbuf, "%s", CMD_EXPSTATE);
verbose(2, "%s", sendbuf);
sendstrmessage(sock, sendbuf);
}
char *ans = getans(sock);
if(ans){
t0 = dtime();
char *val = get_keyval(ans);
if(val && 0 == strcmp(ans, CMD_EXPSTATE)){
int state = atoi(val);
if(state == CAMERA_ERROR){
WARNX(_("Can't make exposition"));
return;
}
if(state != CAMERA_CAPTURE){
verbose(2, "Frame ready!");
return;
}
}
}
}
WARNX(_("Server timeout"));
DBG("Timeout");
}

33
client.h Normal file
View File

@ -0,0 +1,33 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef CLIENT_H__
#define CLIENT_H__
// waiting for answer timeout
#define ANSWER_TIMEOUT 1.0
// wait for exposition ends (between subsequent check calls)
#define WAIT_TIMEOUT 2.0
// client will disconnect after this time from last server message
#define CLIENT_TIMEOUT 10.0
// client-side functions
void client(int fd);
#endif // CLIENT_H__

View File

@ -9,24 +9,30 @@
#include "cmdlnopts.h" #include "cmdlnopts.h"
#define DEFAULT_PID_FILE "/tmp/CCD_Capture.pid"
static int help; static int help;
glob_pars *GP = NULL; glob_pars *GP = NULL;
// DEFAULTS // DEFAULTS
// default global parameters // default global parameters
static glob_pars G = { static glob_pars G = {
.instrument = "direct imaging", .instrument = NULL,
.exptime = -1, .exptime = -1.,
.nframes = 1, .nframes = 1,
.hbin = 1, .vbin = 1, .hbin = 1, .vbin = 1,
.X0 = -1, .Y0 = -1, .X0 = -1, .Y0 = -1,
.X1 = -1, .Y1 = -1, .X1 = -1, .Y1 = -1,
.temperature = 1e6, .focdevno = -1,
.camdevno = -1,
.whldevno = -1,
.temperature = NAN,
.shtr_cmd = -1, .shtr_cmd = -1,
.confio = -1, .setio = -1, .confio = -1, .setio = -1,
.gotopos = NAN, .addsteps = NAN, .gotopos = NAN, .addsteps = NAN,
.pidfile = DEFAULT_PID_FILE,
.brightness = NAN, .gain = NAN,
.setwheel = -1, .setwheel = -1,
.fanspeed = -1, .fanspeed = -1,
.nflushes = 1
}; };
/* /*
@ -47,7 +53,7 @@ myoption cmdlnopts[] = {
{"verbose", NO_ARGS, NULL, 'V', arg_none, APTR(&G.verbose), N_("verbose level (each -v increase it)")}, {"verbose", NO_ARGS, NULL, 'V', arg_none, APTR(&G.verbose), N_("verbose level (each -v increase it)")},
{"dark", NO_ARGS, NULL, 'd', arg_int, APTR(&G.dark), N_("not open shutter, when exposing (\"dark frames\")")}, {"dark", NO_ARGS, NULL, 'd', arg_int, APTR(&G.dark), N_("not open shutter, when exposing (\"dark frames\")")},
{"8bit", NO_ARGS, NULL, '8', arg_int, APTR(&G._8bit), N_("run in 8-bit mode")}, {"8bit", NO_ARGS, NULL, '8', arg_int, APTR(&G._8bit), N_("run in 8-bit mode")},
{"fast", NO_ARGS, NULL, 'f', arg_none, APTR(&G.fast), N_("fast (8MHz) readout mode")}, {"fast", NO_ARGS, NULL, 'f', arg_none, APTR(&G.fast), N_("fast readout mode")},
{"set-temp",NEED_ARG, NULL, 't', arg_double, APTR(&G.temperature),N_("set CCD temperature to given value (degr C)")}, {"set-temp",NEED_ARG, NULL, 't', arg_double, APTR(&G.temperature),N_("set CCD temperature to given value (degr C)")},
{"set-fan", NEED_ARG, NULL, 0, arg_int, APTR(&G.fanspeed), N_("set fan speed (0 - off, 1 - low, 2 - high)")}, {"set-fan", NEED_ARG, NULL, 0, arg_int, APTR(&G.fanspeed), N_("set fan speed (0 - off, 1 - low, 2 - high)")},
@ -58,6 +64,8 @@ myoption cmdlnopts[] = {
{"obsname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.observers), N_("observers' names")}, {"obsname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.observers), N_("observers' names")},
{"prog-id", NEED_ARG, NULL, 'P', arg_string, APTR(&G.prog_id), N_("observing program name")}, {"prog-id", NEED_ARG, NULL, 'P', arg_string, APTR(&G.prog_id), N_("observing program name")},
{"addrec", MULT_PAR, NULL, 'r', arg_string, APTR(&G.addhdr), N_("add records to header from given file[s]")}, {"addrec", MULT_PAR, NULL, 'r', arg_string, APTR(&G.addhdr), N_("add records to header from given file[s]")},
{"outfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.outfile), N_("output file name")},
{"wait", NO_ARGS, &G.waitexpend,1,arg_none, NULL, N_("wait while exposition ends")},
{"nflushes",NEED_ARG, NULL, 'l', arg_int, APTR(&G.nflushes), N_("N flushes before exposing (default: 1)")}, {"nflushes",NEED_ARG, NULL, 'l', arg_int, APTR(&G.nflushes), N_("N flushes before exposing (default: 1)")},
{"hbin", NEED_ARG, NULL, 'h', arg_int, APTR(&G.hbin), N_("horizontal binning to N pixels")}, {"hbin", NEED_ARG, NULL, 'h', arg_int, APTR(&G.hbin), N_("horizontal binning to N pixels")},
@ -65,11 +73,11 @@ myoption cmdlnopts[] = {
{"nframes", NEED_ARG, NULL, 'n', arg_int, APTR(&G.nframes), N_("make series of N frames")}, {"nframes", NEED_ARG, NULL, 'n', arg_int, APTR(&G.nframes), N_("make series of N frames")},
{"pause", NEED_ARG, NULL, 'p', arg_int, APTR(&G.pause_len), N_("make pause for N seconds between expositions")}, {"pause", NEED_ARG, NULL, 'p', arg_int, APTR(&G.pause_len), N_("make pause for N seconds between expositions")},
{"exptime", NEED_ARG, NULL, 'x', arg_double, APTR(&G.exptime), N_("set exposure time to given value (seconds!)")}, {"exptime", NEED_ARG, NULL, 'x', arg_double, APTR(&G.exptime), N_("set exposure time to given value (seconds!)")},
{"X0", NEED_ARG, NULL, 0, arg_int, APTR(&G.X0), N_("frame X0 coordinate (-1 - all with overscan)")}, {"cancel", NO_ARGS, &G.cancelexpose, 1,arg_none, NULL, N_("cancel current exposition")},
{"Y0", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y0), N_("frame Y0 coordinate (-1 - all with overscan)")}, {"X0", NEED_ARG, NULL, 0, arg_int, APTR(&G.X0), N_("absolute (not divided by binning!) frame X0 coordinate (-1 - all with overscan)")},
{"X1", NEED_ARG, NULL, 0, arg_int, APTR(&G.X1), N_("frame X1 coordinate (-1 - all with overscan)")}, {"Y0", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y0), N_("absolute frame Y0 coordinate (-1 - all with overscan)")},
{"Y1", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y1), N_("frame Y1 coordinate (-1 - all with overscan)")}, {"X1", NEED_ARG, NULL, 0, arg_int, APTR(&G.X1), N_("absolute frame X1 coordinate (-1 - all with overscan)")},
{"fullframe",NO_ARGS, NULL, 0, arg_int, APTR(&G.fullframe), N_("grab full frame (with overscans)")}, {"Y1", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y1), N_("absolute frame Y1 coordinate (-1 - all with overscan)")},
{"open-shutter",NO_ARGS,&G.shtr_cmd, SHUTTER_OPEN,arg_none,NULL, N_("open shutter")}, {"open-shutter",NO_ARGS,&G.shtr_cmd, SHUTTER_OPEN,arg_none,NULL, N_("open shutter")},
{"close-shutter",NO_ARGS,&G.shtr_cmd, SHUTTER_CLOSE,arg_none,NULL, N_("close shutter")}, {"close-shutter",NO_ARGS,&G.shtr_cmd, SHUTTER_CLOSE,arg_none,NULL, N_("close shutter")},
@ -86,6 +94,14 @@ myoption cmdlnopts[] = {
{"wheel-set",NEED_ARG, NULL, 'w', arg_int, APTR(&G.setwheel), N_("set wheel position")}, {"wheel-set",NEED_ARG, NULL, 'w', arg_int, APTR(&G.setwheel), N_("set wheel position")},
{"gain", NEED_ARG, NULL, 0, arg_float, APTR(&G.gain), N_("CMOS gain level")},
{"brightness",NEED_ARG, NULL, 0, arg_float, APTR(&G.brightness),N_("CMOS brightness level")},
{"logfile", NEED_ARG, NULL, 0, arg_string, APTR(&G.logfile), N_("logging file name (if run as server)")},
{"path", NEED_ARG, NULL, 0, arg_string, APTR(&G.path), N_("UNIX socket name")},
{"port", NEED_ARG, NULL, 0, arg_string, APTR(&G.port), N_("local INET socket port")},
{"pidfile", NEED_ARG, NULL, 0, arg_string, APTR(&G.pidfile), N_("PID file (default: " DEFAULT_PID_FILE ")")},
#ifdef IMAGEVIEW #ifdef IMAGEVIEW
{"display", NO_ARGS, NULL, 'D', arg_int, APTR(&G.showimage), N_("Display image in OpenGL window")}, {"display", NO_ARGS, NULL, 'D', arg_int, APTR(&G.showimage), N_("Display image in OpenGL window")},
#endif #endif
@ -94,7 +110,6 @@ myoption cmdlnopts[] = {
end_option end_option
}; };
/** /**
* Parse command line options and return dynamically allocated structure * Parse command line options and return dynamically allocated structure
* to global parameters * to global parameters
@ -104,12 +119,12 @@ myoption cmdlnopts[] = {
*/ */
glob_pars *parse_args(int argc, char **argv){ glob_pars *parse_args(int argc, char **argv){
// format of help: "Usage: progname [args]\n" // format of help: "Usage: progname [args]\n"
change_helpstring("Usage: %s [args] <output file prefix>\n\n\tWhere args are:\n"); change_helpstring("Usage: %s [args] [output file prefix]\n\n\tWhere args are:\n");
// parse arguments // parse arguments
parseargs(&argc, &argv, cmdlnopts); parseargs(&argc, &argv, cmdlnopts);
if(help) showhelp(-1, cmdlnopts); if(help) showhelp(-1, cmdlnopts);
if(argc > 0){ if(argc > 0){
G.outfile = strdup(argv[0]); G.outfileprefix = strdup(argv[0]);
if(argc > 1){ if(argc > 1){
WARNX("%d unused parameters:\n", argc - 1); WARNX("%d unused parameters:\n", argc - 1);
for(int i = 1; i < argc; ++i) for(int i = 1; i < argc; ++i)

View File

@ -32,24 +32,32 @@ typedef struct{
char *focuserdev; // focuser ... char *focuserdev; // focuser ...
char *wheeldev; // wheel ... char *wheeldev; // wheel ...
char *objname; // object's name char *objname; // object's name
char *outfile; // output filename prefix char *outfile; // output filename
char *outfileprefix;// output filename prefix
char *objtype; // type of object (dark/obj/bias) char *objtype; // type of object (dark/obj/bias)
char *instrument; // instrument's name char *instrument; // instrument's name
char *observers; // observers' names char *observers; // observers' names
char *prog_id; // programm identificator char *prog_id; // programm identificator
char *author; // programm author char *author; // programm author
char *logfile; // when run as server log here
char *path; // UNIX socket name
char *port; // local INET socket port
char *pidfile; // PID file (default: /tmp/CCD_Capture.pid)
char **addhdr; // list of files from which to add header records
int waitexpend; // wait while exposition ends
int cancelexpose; // cancel exp
int client; // run as client
int listdevices; // list connected devices int listdevices; // list connected devices
int fanspeed; // fan speed: 0-2 int fanspeed; // fan speed: 0-2
int noflush; // turn off bg flushing int noflush; // turn off bg flushing
int camdevno; // camera number (0, 1, 2 etc) int camdevno; // camera number (0, 1, 2 etc)
int focdevno; int focdevno; // focuser -//-
int whldevno; int whldevno; // wheel -//-
int dark; // dark frame int dark; // dark frame
int nframes; // amount of frames to take int nframes; // amount of frames to take
int hbin; int vbin; // binning int hbin; int vbin; // binning
int X0; int Y0; // top left corner coordinate (-1 - all, including overscan) int X0; int Y0; // top left corner coordinate (-1 - all, including overscan)
int X1; int Y1; // bottom right corner coordinate int X1; int Y1; // bottom right corner coordinate
int fullframe; // grab full frame (with overscans)
int nflushes; // amount of flushes int nflushes; // amount of flushes
int pause_len; // pause (in seconds) between expositions int pause_len; // pause (in seconds) between expositions
int shtr_cmd; // shutter command (flishutter_t) int shtr_cmd; // shutter command (flishutter_t)
@ -58,16 +66,17 @@ typedef struct{
int getio; // get value of ioport int getio; // get value of ioport
int setio; // set value of ioport int setio; // set value of ioport
int confio; // configure ioport int confio; // configure ioport
double exptime; // time of exposition in seconds
double temperature; // temperature of CCD
double gotopos; // move stepper motor of focuser to absolute position
double addsteps; // move stepper motor of focuser to relative position
int setwheel; // set wheel position int setwheel; // set wheel position
int async; // asynchronous moving int async; // asynchronous moving
int verbose; // each '-V' increases it int verbose; // each '-V' increases it
int rewrite; // rewrite file int rewrite; // rewrite file
int showimage; // show image preview int showimage; // show image preview
char **addhdr; // list of files from which to add header records float gain; // gain level (only for CMOS)
float brightness; // brightness (only for CMOS)
double exptime; // time of exposition in seconds
double temperature; // temperature of CCD
double gotopos; // move stepper motor of focuser to absolute position
double addsteps; // move stepper motor of focuser to relative position
} glob_pars; } glob_pars;

View File

@ -489,7 +489,7 @@ void* image_thread(_U_ void *data){
if(win && win->winevt){ if(win && win->winevt){
if(win->winevt & WINEVT_SAVEIMAGE){ // save image if(win->winevt & WINEVT_SAVEIMAGE){ // save image
verbose(2, "Make screenshot\n"); verbose(2, "Make screenshot\n");
saveFITS(img, "ScreenShot"); saveFITS(img);
win->winevt &= ~WINEVT_SAVEIMAGE; win->winevt &= ~WINEVT_SAVEIMAGE;
} }
if(win->winevt & WINEVT_ROLLCOLORFUN){ if(win->winevt & WINEVT_ROLLCOLORFUN){

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-03-01 20:35+0300\n" "POT-Creation-Date: 2022-03-17 18:04+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,472 +17,543 @@ msgstr ""
"Content-Type: text/plain; charset=koi8-r\n" "Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: cmdlnopts.c:37 #: cmdlnopts.c:43
msgid "common device plugin (e.g devfli.so)" msgid "common device plugin (e.g devfli.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:38 #: cmdlnopts.c:44
msgid "camera device plugin (e.g. devfli.so)" msgid "camera device plugin (e.g. devfli.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:39 #: cmdlnopts.c:45
msgid "focuser device plugin (e.g. devzwo.so)" msgid "focuser device plugin (e.g. devzwo.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:40 #: cmdlnopts.c:46
msgid "wheel device plugin (e.g. devdummy.so)" msgid "wheel device plugin (e.g. devdummy.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:41 #: cmdlnopts.c:47
msgid "list connected devices" msgid "list connected devices"
msgstr "" msgstr ""
#: cmdlnopts.c:42 #: cmdlnopts.c:48
msgid "camera device number (if many: 0, 1, 2 etc)" msgid "camera device number (if many: 0, 1, 2 etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:43 #: cmdlnopts.c:49
msgid "filter wheel device number (if many: 0, 1, 2 etc)" msgid "filter wheel device number (if many: 0, 1, 2 etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:44 #: cmdlnopts.c:50
msgid "focuser device number (if many: 0, 1, 2 etc)" msgid "focuser device number (if many: 0, 1, 2 etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:45 #: cmdlnopts.c:51
msgid "show this help" msgid "show this help"
msgstr "" msgstr ""
#: cmdlnopts.c:46 #: cmdlnopts.c:52
msgid "rewrite output file if exists" msgid "rewrite output file if exists"
msgstr "" msgstr ""
#: cmdlnopts.c:47 #: cmdlnopts.c:53
msgid "verbose level (each -v increase it)" msgid "verbose level (each -v increase it)"
msgstr "" msgstr ""
#: cmdlnopts.c:48 #: cmdlnopts.c:54
msgid "not open shutter, when exposing (\"dark frames\")" msgid "not open shutter, when exposing (\"dark frames\")"
msgstr "" msgstr ""
#: cmdlnopts.c:49 #: cmdlnopts.c:55
msgid "run in 8-bit mode" msgid "run in 8-bit mode"
msgstr "" msgstr ""
#: cmdlnopts.c:50
msgid "fast (8MHz) readout mode"
msgstr ""
#: cmdlnopts.c:51
msgid "set CCD temperature to given value (degr C)"
msgstr ""
#: cmdlnopts.c:52
msgid "set fan speed (0 - off, 1 - low, 2 - high)"
msgstr ""
#: cmdlnopts.c:54
msgid "program author"
msgstr ""
#: cmdlnopts.c:55
msgid "object type (neon, object, flat etc)"
msgstr ""
#: cmdlnopts.c:56 #: cmdlnopts.c:56
msgid "instrument name" msgid "fast readout mode"
msgstr "" msgstr ""
#: cmdlnopts.c:57 #: cmdlnopts.c:57
msgid "object name" msgid "set CCD temperature to given value (degr C)"
msgstr "" msgstr ""
#: cmdlnopts.c:58 #: cmdlnopts.c:58
msgid "observers' names" msgid "set fan speed (0 - off, 1 - low, 2 - high)"
msgstr ""
#: cmdlnopts.c:59
msgid "observing program name"
msgstr "" msgstr ""
#: cmdlnopts.c:60 #: cmdlnopts.c:60
msgid "add records to header from given file[s]" msgid "program author"
msgstr ""
#: cmdlnopts.c:61
msgid "object type (neon, object, flat etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:62 #: cmdlnopts.c:62
msgid "N flushes before exposing (default: 1)" msgid "instrument name"
msgstr "" msgstr ""
#: cmdlnopts.c:63 #: cmdlnopts.c:63
msgid "horizontal binning to N pixels" msgid "object name"
msgstr "" msgstr ""
#: cmdlnopts.c:64 #: cmdlnopts.c:64
msgid "vertical binning to N pixels" msgid "observers' names"
msgstr "" msgstr ""
#: cmdlnopts.c:65 #: cmdlnopts.c:65
msgid "make series of N frames" msgid "observing program name"
msgstr "" msgstr ""
#: cmdlnopts.c:66 #: cmdlnopts.c:66
msgid "make pause for N seconds between expositions" msgid "add records to header from given file[s]"
msgstr "" msgstr ""
#: cmdlnopts.c:67 #: cmdlnopts.c:67
msgid "set exposure time to given value (seconds!)" msgid "output file name"
msgstr "" msgstr ""
#: cmdlnopts.c:68 #: cmdlnopts.c:68
msgid "frame X0 coordinate (-1 - all with overscan)" msgid "wait while exposition ends"
msgstr ""
#: cmdlnopts.c:69
msgid "frame Y0 coordinate (-1 - all with overscan)"
msgstr "" msgstr ""
#: cmdlnopts.c:70 #: cmdlnopts.c:70
msgid "frame X1 coordinate (-1 - all with overscan)" msgid "N flushes before exposing (default: 1)"
msgstr "" msgstr ""
#: cmdlnopts.c:71 #: cmdlnopts.c:71
msgid "frame Y1 coordinate (-1 - all with overscan)" msgid "horizontal binning to N pixels"
msgstr "" msgstr ""
#: cmdlnopts.c:72 #: cmdlnopts.c:72
msgid "grab full frame (with overscans)" msgid "vertical binning to N pixels"
msgstr ""
#: cmdlnopts.c:73
msgid "make series of N frames"
msgstr "" msgstr ""
#: cmdlnopts.c:74 #: cmdlnopts.c:74
msgid "open shutter" msgid "make pause for N seconds between expositions"
msgstr "" msgstr ""
#: cmdlnopts.c:75 #: cmdlnopts.c:75
msgid "close shutter" msgid "set exposure time to given value (seconds!)"
msgstr "" msgstr ""
#: cmdlnopts.c:76 #: cmdlnopts.c:76
msgid "run exposition on LOW @ pin5 I/O port" msgid "cancel current exposition"
msgstr "" msgstr ""
#: cmdlnopts.c:77 #: cmdlnopts.c:77
msgid "run exposition on HIGH @ pin5 I/O port" msgid ""
"absolute (not divided by binning!) frame X0 coordinate (-1 - all with "
"overscan)"
msgstr "" msgstr ""
#: cmdlnopts.c:78 #: cmdlnopts.c:78
msgid "get value of I/O port pins" msgid "absolute frame Y0 coordinate (-1 - all with overscan)"
msgstr "" msgstr ""
#: cmdlnopts.c:79 #: cmdlnopts.c:79
msgid "move stepper motor asynchronous" msgid "absolute frame X1 coordinate (-1 - all with overscan)"
msgstr "" msgstr ""
#: cmdlnopts.c:81 #: cmdlnopts.c:80
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)" msgid "absolute frame Y1 coordinate (-1 - all with overscan)"
msgstr "" msgstr ""
#: cmdlnopts.c:82 #: cmdlnopts.c:82
msgid "open shutter"
msgstr ""
#: cmdlnopts.c:83
msgid "close shutter"
msgstr ""
#: cmdlnopts.c:84
msgid "run exposition on LOW @ pin5 I/O port"
msgstr ""
#: cmdlnopts.c:85
msgid "run exposition on HIGH @ pin5 I/O port"
msgstr ""
#: cmdlnopts.c:86
msgid "get value of I/O port pins"
msgstr ""
#: cmdlnopts.c:87
msgid "move stepper motor asynchronous"
msgstr ""
#: cmdlnopts.c:89
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
msgstr ""
#: cmdlnopts.c:90
msgid "" msgid ""
"configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == " "configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == "
"output, 0 == input)" "output, 0 == input)"
msgstr "" msgstr ""
#: cmdlnopts.c:84 #: cmdlnopts.c:92
msgid "move focuser to absolute position, mm" msgid "move focuser to absolute position, mm"
msgstr "" msgstr ""
#: cmdlnopts.c:85 #: cmdlnopts.c:93
msgid "move focuser to relative position, mm" msgid "move focuser to relative position, mm"
msgstr "" msgstr ""
#: cmdlnopts.c:87 #: cmdlnopts.c:95
msgid "set wheel position" msgid "set wheel position"
msgstr "" msgstr ""
#: cmdlnopts.c:90 #: cmdlnopts.c:97
msgid "CMOS gain level"
msgstr ""
#: cmdlnopts.c:98
msgid "CMOS brightness level"
msgstr ""
#: cmdlnopts.c:100
msgid "logging file name (if run as server)"
msgstr ""
#: cmdlnopts.c:101
msgid "UNIX socket name"
msgstr ""
#: cmdlnopts.c:102
msgid "local INET socket port"
msgstr ""
#: cmdlnopts.c:103
msgid "PID file (default: "
msgstr ""
#: cmdlnopts.c:106
msgid "Display image in OpenGL window" msgid "Display image in OpenGL window"
msgstr "" msgstr ""
#: ccdfunc.c:62 #: ccdfunc.c:63
#, c-format #, c-format
msgid "Can't find plugin %s: %s" msgid "Can't find plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:74 #: ccdfunc.c:75
#, c-format #, c-format
msgid "Can't find focuser in plugin %s: %s" msgid "Can't find focuser in plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:85 #: ccdfunc.c:86
#, c-format #, c-format
msgid "Can't find camera in plugin %s: %s" msgid "Can't find camera in plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:96 #: ccdfunc.c:97
#, c-format #, c-format
msgid "Can't find wheel in plugin %s: %s" msgid "Can't find wheel in plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:149 #: ccdfunc.c:152
msgid "Camera device unknown" msgid "Camera device unknown"
msgstr "" msgstr ""
#. Не могу сохранить файл #: ccdfunc.c:158
#: ccdfunc.c:157 msgid "Neither filename nor filename prefix pointed!"
msgid "Can't save file"
msgstr "" msgstr ""
#: ccdfunc.c:304 #. Не могу сохранить файл
#: ccdfunc.c:177
#, c-format
msgid "Can't save file with prefix %s"
msgstr ""
#: ccdfunc.c:329
#, c-format #, c-format
msgid "File saved as '%s'" msgid "File saved as '%s'"
msgstr "" msgstr ""
#: ccdfunc.c:306 #: ccdfunc.c:332
msgid "Error saving file" msgid "Error saving file"
msgstr "" msgstr ""
#: ccdfunc.c:344 #: ccdfunc.c:371
#, c-format #, c-format
msgid "Image stat:\n" msgid "Image stat:\n"
msgstr "" msgstr ""
#: ccdfunc.c:357 #: ccdfunc.c:379
msgid "Focuser device not pointed" msgid "Focuser device not pointed"
msgstr "" msgstr ""
#: ccdfunc.c:364 #: ccdfunc.c:386
msgid "No focusers found" msgid "No focusers found"
msgstr "" msgstr ""
#: ccdfunc.c:377 #: ccdfunc.c:417
#, c-format #, c-format
msgid "Found %d focusers, you point number %d" msgid "Found %d focusers, you point number %d"
msgstr "" msgstr ""
#: ccdfunc.c:381 #: ccdfunc.c:421
msgid "Can't set active focuser number" msgid "Can't set active focuser number"
msgstr "" msgstr ""
#: ccdfunc.c:395 #: ccdfunc.c:435
msgid "Can't get focuser limit positions" msgid "Can't get focuser limit positions"
msgstr "" msgstr ""
#: ccdfunc.c:402 #: ccdfunc.c:442
msgid "Can't get current focuser position" msgid "Can't get current focuser position"
msgstr "" msgstr ""
#: ccdfunc.c:416 #: ccdfunc.c:456
#, c-format #, c-format
msgid "Can't set position %g: out of limits [%g, %g]" msgid "Can't set position %g: out of limits [%g, %g]"
msgstr "" msgstr ""
#: ccdfunc.c:420 #: ccdfunc.c:460
msgid "Can't home focuser" msgid "Can't home focuser"
msgstr "" msgstr ""
#: ccdfunc.c:422 #: ccdfunc.c:462
#, c-format #, c-format
msgid "Can't set position %g" msgid "Can't set position %g"
msgstr "" msgstr ""
#: ccdfunc.c:437 #: ccdfunc.c:470
msgid "Wheel device not pointed" msgid "Wheel device not pointed"
msgstr "" msgstr ""
#: ccdfunc.c:444 #: ccdfunc.c:477
msgid "No wheels found" msgid "No wheels found"
msgstr "" msgstr ""
#: ccdfunc.c:457 #: ccdfunc.c:508
#, c-format #, c-format
msgid "Found %d wheels, you point number %d" msgid "Found %d wheels, you point number %d"
msgstr "" msgstr ""
#: ccdfunc.c:461 #: ccdfunc.c:512
msgid "Can't set active wheel number" msgid "Can't set active wheel number"
msgstr "" msgstr ""
#: ccdfunc.c:477 #: ccdfunc.c:528
msgid "Can't get max wheel position" msgid "Can't get max wheel position"
msgstr "" msgstr ""
#: ccdfunc.c:484 #: ccdfunc.c:535
#, c-format #, c-format
msgid "Wheel position should be from 0 to %d" msgid "Wheel position should be from 0 to %d"
msgstr "" msgstr ""
#: ccdfunc.c:488 #: ccdfunc.c:539
#, c-format #, c-format
msgid "Can't set wheel position %d" msgid "Can't set wheel position %d"
msgstr "" msgstr ""
#: ccdfunc.c:507 #: ccdfunc.c:556
#, c-format #, c-format
msgid "%.1f seconds till exposition ends" msgid "%.1f seconds till exposition ends"
msgstr "" msgstr ""
#: ccdfunc.c:528 #: ccdfunc.c:570
msgid "Camera device not pointed" msgid "Camera device not pointed"
msgstr "" msgstr ""
#: ccdfunc.c:535 #: ccdfunc.c:577 ccdfunc.c:578
msgid "No cameras found" msgid "No cameras found"
msgstr "" msgstr ""
#: ccdfunc.c:547 #: ccdfunc.c:613
#, c-format #, c-format
msgid "Found %d cameras, you point number %d" msgid "Found %d cameras, you point number %d"
msgstr "" msgstr ""
#: ccdfunc.c:551 #: ccdfunc.c:617
msgid "Can't set active camera number" msgid "Can't set active camera number"
msgstr "" msgstr ""
#: ccdfunc.c:557 #: ccdfunc.c:623
msgid "Can't set fan speed" msgid "Can't set fan speed"
msgstr "" msgstr ""
#: ccdfunc.c:558 #: ccdfunc.c:624
#, c-format #, c-format
msgid "Set fan speed to %d" msgid "Set fan speed to %d"
msgstr "" msgstr ""
#: ccdfunc.c:563 #: ccdfunc.c:629
#, c-format #, c-format
msgid "Camera model: %s" msgid "Camera model: %s"
msgstr "" msgstr ""
#: ccdfunc.c:564 #: ccdfunc.c:630
#, c-format #, c-format
msgid "Pixel size: %g x %g" msgid "Pixel size: %g x %g"
msgstr "" msgstr ""
#: ccdfunc.c:570 #: ccdfunc.c:636
#, c-format #, c-format
msgid "Full array: %s" msgid "Full array: %s"
msgstr "" msgstr ""
#: ccdfunc.c:573 #: ccdfunc.c:639
#, c-format #, c-format
msgid "Field of view: %s" msgid "Field of view: %s"
msgstr "" msgstr ""
#: ccdfunc.c:576 #: ccdfunc.c:642
#, c-format #, c-format
msgid "Can't set T to %g degC" msgid "Can't set T to %g degC"
msgstr "" msgstr ""
#: ccdfunc.c:583 #: ccdfunc.c:649
#, c-format #, c-format
msgid "Shutter command: %s\n" msgid "Shutter command: %s\n"
msgstr "" msgstr ""
#: ccdfunc.c:585 #: ccdfunc.c:651
#, c-format #, c-format
msgid "Can't run shutter command %s (unsupported?)" msgid "Can't run shutter command %s (unsupported?)"
msgstr "" msgstr ""
#. "Попытка сконфигурировать порт I/O как %d\n" #. "Попытка сконфигурировать порт I/O как %d\n"
#: ccdfunc.c:589 #: ccdfunc.c:655
#, c-format #, c-format
msgid "Try to configure I/O port as %d" msgid "Try to configure I/O port as %d"
msgstr "" msgstr ""
#: ccdfunc.c:591 #: ccdfunc.c:657
msgid "Can't configure (unsupported?)" msgid "Can't configure (unsupported?)"
msgstr "" msgstr ""
#: ccdfunc.c:597 #: ccdfunc.c:663
msgid "Can't get IOport state (unsupported?)" msgid "Can't get IOport state (unsupported?)"
msgstr "" msgstr ""
#. "Попытка записи %d в порт I/O\n" #. "Попытка записи %d в порт I/O\n"
#: ccdfunc.c:601 #: ccdfunc.c:667
#, c-format #, c-format
msgid "Try to write %d to I/O port" msgid "Try to write %d to I/O port"
msgstr "" msgstr ""
#: ccdfunc.c:603 #: ccdfunc.c:669
msgid "Can't set IOport" msgid "Can't set IOport"
msgstr "" msgstr ""
#: ccdfunc.c:610 #: ccdfunc.c:676
#, c-format
msgid "Set gain to %g"
msgstr ""
#: ccdfunc.c:677
#, c-format
msgid "Can't set gain to %g"
msgstr ""
#: ccdfunc.c:682
#, c-format
msgid "Set brightness to %g"
msgstr ""
#: ccdfunc.c:683
#, c-format
msgid "Can't set brightness to %g"
msgstr ""
#: ccdfunc.c:689
#, c-format #, c-format
msgid "Can't set binning %dx%d" msgid "Can't set binning %dx%d"
msgstr "" msgstr ""
#: ccdfunc.c:624 #: ccdfunc.c:699
msgid "Can't set given geometry" msgid "Can't set given geometry"
msgstr "" msgstr ""
#: ccdfunc.c:627 #: ccdfunc.c:703
#, c-format #, c-format
msgid "Can't set %d flushes" msgid "Can't set %d flushes"
msgstr "" msgstr ""
#: ccdfunc.c:630 #: ccdfunc.c:707
#, c-format #, c-format
msgid "Can't set exposure time to %f seconds" msgid "Can't set exposure time to %f seconds"
msgstr "" msgstr ""
#: ccdfunc.c:633 #: ccdfunc.c:710
msgid "Can't change frame type" msgid "Can't change frame type"
msgstr "" msgstr ""
#: ccdfunc.c:636 #: ccdfunc.c:713
msgid "Can't set bit depth" msgid "Can't set bit depth"
msgstr "" msgstr ""
#: ccdfunc.c:638 #: ccdfunc.c:715
msgid "Can't set readout speed" msgid "Can't set readout speed"
msgstr "" msgstr ""
#: ccdfunc.c:639 #: ccdfunc.c:716
#, c-format #, c-format
msgid "Readout mode: %s" msgid "Readout mode: %s"
msgstr "" msgstr ""
#: ccdfunc.c:640 #: ccdfunc.c:717
msgid "Only show statistics" msgid "Only show statistics"
msgstr "" msgstr ""
#. GET binning should be AFTER setgeometry! #. GET binning should be AFTER setgeometry!
#: ccdfunc.c:642 #: ccdfunc.c:719
msgid "Can't get current binning" msgid "Can't get current binning"
msgstr "" msgstr ""
#: ccdfunc.c:655 #: ccdfunc.c:732
msgid "Can't open OpenGL window, image preview will be inaccessible" msgid "Can't open OpenGL window, image preview will be inaccessible"
msgstr "" msgstr ""
#. Захват кадра %d\n #. Захват кадра %d\n
#: ccdfunc.c:662 #: ccdfunc.c:739
#, c-format #, c-format
msgid "Capture frame %d" msgid "Capture frame %d"
msgstr "" msgstr ""
#: ccdfunc.c:664 #: ccdfunc.c:741 server.c:64
msgid "Can't start exposition" msgid "Can't start exposition"
msgstr "" msgstr ""
#: ccdfunc.c:668 ccdfunc.c:690 ccdfunc.c:731 #: ccdfunc.c:745 ccdfunc.c:767 ccdfunc.c:808
msgid "Can't capture image" msgid "Can't capture image"
msgstr "" msgstr ""
#: ccdfunc.c:671 #: ccdfunc.c:748
msgid "Read grabbed image" msgid "Read grabbed image"
msgstr "" msgstr ""
#: ccdfunc.c:674 ccdfunc.c:694 ccdfunc.c:735 #: ccdfunc.c:751 ccdfunc.c:771 ccdfunc.c:812
msgid "Can't grab image" msgid "Can't grab image"
msgstr "" msgstr ""
#. %d секунд до окончания паузы\n #. %d секунд до окончания паузы\n
#: ccdfunc.c:711 #: ccdfunc.c:788
#, c-format #, c-format
msgid "%d seconds till pause ends\n" msgid "%d seconds till pause ends\n"
msgstr "" msgstr ""
#: server.c:89
msgid "No camera device"
msgstr ""
#: client.c:164
msgid "Can't make exposition"
msgstr ""
#: client.c:174
msgid "Server timeout"
msgstr ""
#: imageview.c:264 #: imageview.c:264
msgid "Can't init mutex!" msgid "Can't init mutex!"
msgstr "" msgstr ""

View File

@ -7,7 +7,7 @@
msgid "" msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n" msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-03-01 20:27+0300\n" "POT-Creation-Date: 2022-03-17 18:04+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -16,13 +16,13 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Content-Type: text/plain; charset=koi8-r\n" "Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: ccdfunc.c:507 #: ccdfunc.c:556
#, c-format #, c-format
msgid "%.1f seconds till exposition ends" msgid "%.1f seconds till exposition ends"
msgstr "" msgstr ""
#. %d секунд до окончания паузы\n #. %d секунд до окончания паузы\n
#: ccdfunc.c:711 #: ccdfunc.c:788
#, c-format #, c-format
msgid "%d seconds till pause ends\n" msgid "%d seconds till pause ends\n"
msgstr "" msgstr ""
@ -31,77 +31,85 @@ msgstr ""
msgid "Already initialized!" msgid "Already initialized!"
msgstr "" msgstr ""
#: ccdfunc.c:528 #: cmdlnopts.c:98
msgid "CMOS brightness level"
msgstr ""
#: cmdlnopts.c:97
msgid "CMOS gain level"
msgstr ""
#: ccdfunc.c:570
msgid "Camera device not pointed" msgid "Camera device not pointed"
msgstr "" msgstr ""
#: ccdfunc.c:149 #: ccdfunc.c:152
msgid "Camera device unknown" msgid "Camera device unknown"
msgstr "" msgstr ""
#: ccdfunc.c:563 #: ccdfunc.c:629
#, c-format #, c-format
msgid "Camera model: %s" msgid "Camera model: %s"
msgstr "" msgstr ""
#: ccdfunc.c:668 ccdfunc.c:690 ccdfunc.c:731 #: ccdfunc.c:745 ccdfunc.c:767 ccdfunc.c:808
msgid "Can't capture image" msgid "Can't capture image"
msgstr "" msgstr ""
#: ccdfunc.c:633 #: ccdfunc.c:710
msgid "Can't change frame type" msgid "Can't change frame type"
msgstr "" msgstr ""
#: ccdfunc.c:591 #: ccdfunc.c:657
msgid "Can't configure (unsupported?)" msgid "Can't configure (unsupported?)"
msgstr "" msgstr ""
#: ccdfunc.c:85 #: ccdfunc.c:86
#, c-format #, c-format
msgid "Can't find camera in plugin %s: %s" msgid "Can't find camera in plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:74 #: ccdfunc.c:75
#, c-format #, c-format
msgid "Can't find focuser in plugin %s: %s" msgid "Can't find focuser in plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:62 #: ccdfunc.c:63
#, c-format #, c-format
msgid "Can't find plugin %s: %s" msgid "Can't find plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:96 #: ccdfunc.c:97
#, c-format #, c-format
msgid "Can't find wheel in plugin %s: %s" msgid "Can't find wheel in plugin %s: %s"
msgstr "" msgstr ""
#: ccdfunc.c:597 #: ccdfunc.c:663
msgid "Can't get IOport state (unsupported?)" msgid "Can't get IOport state (unsupported?)"
msgstr "" msgstr ""
#. GET binning should be AFTER setgeometry! #. GET binning should be AFTER setgeometry!
#: ccdfunc.c:642 #: ccdfunc.c:719
msgid "Can't get current binning" msgid "Can't get current binning"
msgstr "" msgstr ""
#: ccdfunc.c:402 #: ccdfunc.c:442
msgid "Can't get current focuser position" msgid "Can't get current focuser position"
msgstr "" msgstr ""
#: ccdfunc.c:395 #: ccdfunc.c:435
msgid "Can't get focuser limit positions" msgid "Can't get focuser limit positions"
msgstr "" msgstr ""
#: ccdfunc.c:477 #: ccdfunc.c:528
msgid "Can't get max wheel position" msgid "Can't get max wheel position"
msgstr "" msgstr ""
#: ccdfunc.c:674 ccdfunc.c:694 ccdfunc.c:735 #: ccdfunc.c:751 ccdfunc.c:771 ccdfunc.c:812
msgid "Can't grab image" msgid "Can't grab image"
msgstr "" msgstr ""
#: ccdfunc.c:420 #: ccdfunc.c:460
msgid "Can't home focuser" msgid "Can't home focuser"
msgstr "" msgstr ""
@ -109,98 +117,113 @@ msgstr ""
msgid "Can't init mutex!" msgid "Can't init mutex!"
msgstr "" msgstr ""
#: ccdfunc.c:655 #: client.c:164
msgid "Can't make exposition"
msgstr ""
#: ccdfunc.c:732
msgid "Can't open OpenGL window, image preview will be inaccessible" msgid "Can't open OpenGL window, image preview will be inaccessible"
msgstr "" msgstr ""
#: ccdfunc.c:585 #: ccdfunc.c:651
#, c-format #, c-format
msgid "Can't run shutter command %s (unsupported?)" msgid "Can't run shutter command %s (unsupported?)"
msgstr "" msgstr ""
#. Не могу сохранить файл #. Не могу сохранить файл
#: ccdfunc.c:157 #: ccdfunc.c:177
msgid "Can't save file" #, c-format
msgid "Can't save file with prefix %s"
msgstr "" msgstr ""
#: ccdfunc.c:627 #: ccdfunc.c:703
#, c-format #, c-format
msgid "Can't set %d flushes" msgid "Can't set %d flushes"
msgstr "" msgstr ""
#: ccdfunc.c:603 #: ccdfunc.c:669
msgid "Can't set IOport" msgid "Can't set IOport"
msgstr "" msgstr ""
#: ccdfunc.c:576 #: ccdfunc.c:642
#, c-format #, c-format
msgid "Can't set T to %g degC" msgid "Can't set T to %g degC"
msgstr "" msgstr ""
#: ccdfunc.c:551 #: ccdfunc.c:617
msgid "Can't set active camera number" msgid "Can't set active camera number"
msgstr "" msgstr ""
#: ccdfunc.c:381 #: ccdfunc.c:421
msgid "Can't set active focuser number" msgid "Can't set active focuser number"
msgstr "" msgstr ""
#: ccdfunc.c:461 #: ccdfunc.c:512
msgid "Can't set active wheel number" msgid "Can't set active wheel number"
msgstr "" msgstr ""
#: ccdfunc.c:610 #: ccdfunc.c:689
#, c-format #, c-format
msgid "Can't set binning %dx%d" msgid "Can't set binning %dx%d"
msgstr "" msgstr ""
#: ccdfunc.c:636 #: ccdfunc.c:713
msgid "Can't set bit depth" msgid "Can't set bit depth"
msgstr "" msgstr ""
#: ccdfunc.c:630 #: ccdfunc.c:683
#, c-format
msgid "Can't set brightness to %g"
msgstr ""
#: ccdfunc.c:707
#, c-format #, c-format
msgid "Can't set exposure time to %f seconds" msgid "Can't set exposure time to %f seconds"
msgstr "" msgstr ""
#: ccdfunc.c:557 #: ccdfunc.c:623
msgid "Can't set fan speed" msgid "Can't set fan speed"
msgstr "" msgstr ""
#: ccdfunc.c:624 #: ccdfunc.c:677
#, c-format
msgid "Can't set gain to %g"
msgstr ""
#: ccdfunc.c:699
msgid "Can't set given geometry" msgid "Can't set given geometry"
msgstr "" msgstr ""
#: ccdfunc.c:422 #: ccdfunc.c:462
#, c-format #, c-format
msgid "Can't set position %g" msgid "Can't set position %g"
msgstr "" msgstr ""
#: ccdfunc.c:416 #: ccdfunc.c:456
#, c-format #, c-format
msgid "Can't set position %g: out of limits [%g, %g]" msgid "Can't set position %g: out of limits [%g, %g]"
msgstr "" msgstr ""
#: ccdfunc.c:638 #: ccdfunc.c:715
msgid "Can't set readout speed" msgid "Can't set readout speed"
msgstr "" msgstr ""
#: ccdfunc.c:488 #: ccdfunc.c:539
#, c-format #, c-format
msgid "Can't set wheel position %d" msgid "Can't set wheel position %d"
msgstr "" msgstr ""
#: ccdfunc.c:664 #: ccdfunc.c:741 server.c:64
msgid "Can't start exposition" msgid "Can't start exposition"
msgstr "" msgstr ""
#. Захват кадра %d\n #. Захват кадра %d\n
#: ccdfunc.c:662 #: ccdfunc.c:739
#, c-format #, c-format
msgid "Capture frame %d" msgid "Capture frame %d"
msgstr "" msgstr ""
#: cmdlnopts.c:90 #: cmdlnopts.c:106
msgid "Display image in OpenGL window" msgid "Display image in OpenGL window"
msgstr "" msgstr ""
@ -209,40 +232,40 @@ msgstr ""
msgid "Equalization of histogram: %s" msgid "Equalization of histogram: %s"
msgstr "" msgstr ""
#: ccdfunc.c:306 #: ccdfunc.c:332
msgid "Error saving file" msgid "Error saving file"
msgstr "" msgstr ""
#: ccdfunc.c:573 #: ccdfunc.c:639
#, c-format #, c-format
msgid "Field of view: %s" msgid "Field of view: %s"
msgstr "" msgstr ""
#: ccdfunc.c:304 #: ccdfunc.c:329
#, c-format #, c-format
msgid "File saved as '%s'" msgid "File saved as '%s'"
msgstr "" msgstr ""
#: ccdfunc.c:357 #: ccdfunc.c:379
msgid "Focuser device not pointed" msgid "Focuser device not pointed"
msgstr "" msgstr ""
#: ccdfunc.c:547 #: ccdfunc.c:613
#, c-format #, c-format
msgid "Found %d cameras, you point number %d" msgid "Found %d cameras, you point number %d"
msgstr "" msgstr ""
#: ccdfunc.c:377 #: ccdfunc.c:417
#, c-format #, c-format
msgid "Found %d focusers, you point number %d" msgid "Found %d focusers, you point number %d"
msgstr "" msgstr ""
#: ccdfunc.c:457 #: ccdfunc.c:508
#, c-format #, c-format
msgid "Found %d wheels, you point number %d" msgid "Found %d wheels, you point number %d"
msgstr "" msgstr ""
#: ccdfunc.c:570 #: ccdfunc.c:636
#, c-format #, c-format
msgid "Full array: %s" msgid "Full array: %s"
msgstr "" msgstr ""
@ -252,190 +275,229 @@ msgstr ""
msgid "Histogram conversion: %s" msgid "Histogram conversion: %s"
msgstr "" msgstr ""
#: ccdfunc.c:344 #: ccdfunc.c:371
#, c-format #, c-format
msgid "Image stat:\n" msgid "Image stat:\n"
msgstr "" msgstr ""
#: cmdlnopts.c:62 #: cmdlnopts.c:70
msgid "N flushes before exposing (default: 1)" msgid "N flushes before exposing (default: 1)"
msgstr "" msgstr ""
#: ccdfunc.c:535 #: ccdfunc.c:158
msgid "Neither filename nor filename prefix pointed!"
msgstr ""
#: server.c:89
msgid "No camera device"
msgstr ""
#: ccdfunc.c:577 ccdfunc.c:578
msgid "No cameras found" msgid "No cameras found"
msgstr "" msgstr ""
#: ccdfunc.c:364 #: ccdfunc.c:386
msgid "No focusers found" msgid "No focusers found"
msgstr "" msgstr ""
#: ccdfunc.c:444 #: ccdfunc.c:477
msgid "No wheels found" msgid "No wheels found"
msgstr "" msgstr ""
#: ccdfunc.c:640 #: ccdfunc.c:717
msgid "Only show statistics" msgid "Only show statistics"
msgstr "" msgstr ""
#: ccdfunc.c:564 #: cmdlnopts.c:103
msgid "PID file (default: "
msgstr ""
#: ccdfunc.c:630
#, c-format #, c-format
msgid "Pixel size: %g x %g" msgid "Pixel size: %g x %g"
msgstr "" msgstr ""
#: ccdfunc.c:671 #: ccdfunc.c:748
msgid "Read grabbed image" msgid "Read grabbed image"
msgstr "" msgstr ""
#: ccdfunc.c:639 #: ccdfunc.c:716
#, c-format #, c-format
msgid "Readout mode: %s" msgid "Readout mode: %s"
msgstr "" msgstr ""
#: ccdfunc.c:558 #: client.c:174
msgid "Server timeout"
msgstr ""
#: ccdfunc.c:682
#, c-format
msgid "Set brightness to %g"
msgstr ""
#: ccdfunc.c:624
#, c-format #, c-format
msgid "Set fan speed to %d" msgid "Set fan speed to %d"
msgstr "" msgstr ""
#: ccdfunc.c:583 #: ccdfunc.c:676
#, c-format
msgid "Set gain to %g"
msgstr ""
#: ccdfunc.c:649
#, c-format #, c-format
msgid "Shutter command: %s\n" msgid "Shutter command: %s\n"
msgstr "" msgstr ""
#. "Попытка сконфигурировать порт I/O как %d\n" #. "Попытка сконфигурировать порт I/O как %d\n"
#: ccdfunc.c:589 #: ccdfunc.c:655
#, c-format #, c-format
msgid "Try to configure I/O port as %d" msgid "Try to configure I/O port as %d"
msgstr "" msgstr ""
#. "Попытка записи %d в порт I/O\n" #. "Попытка записи %d в порт I/O\n"
#: ccdfunc.c:601 #: ccdfunc.c:667
#, c-format #, c-format
msgid "Try to write %d to I/O port" msgid "Try to write %d to I/O port"
msgstr "" msgstr ""
#: ccdfunc.c:437 #: cmdlnopts.c:101
msgid "UNIX socket name"
msgstr ""
#: ccdfunc.c:470
msgid "Wheel device not pointed" msgid "Wheel device not pointed"
msgstr "" msgstr ""
#: ccdfunc.c:484 #: ccdfunc.c:535
#, c-format #, c-format
msgid "Wheel position should be from 0 to %d" msgid "Wheel position should be from 0 to %d"
msgstr "" msgstr ""
#: cmdlnopts.c:60 #: cmdlnopts.c:77
msgid "absolute (not divided by binning!) frame X0 coordinate (-1 - all "
"with overscan)"
msgstr ""
#: cmdlnopts.c:79
msgid "absolute frame X1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:78
msgid "absolute frame Y0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:80
msgid "absolute frame Y1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:66
msgid "add records to header from given file[s]" msgid "add records to header from given file[s]"
msgstr "" msgstr ""
#: cmdlnopts.c:42 #: cmdlnopts.c:48
msgid "camera device number (if many: 0, 1, 2 etc)" msgid "camera device number (if many: 0, 1, 2 etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:38 #: cmdlnopts.c:44
msgid "camera device plugin (e.g. devfli.so)" msgid "camera device plugin (e.g. devfli.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:75 #: cmdlnopts.c:76
msgid "cancel current exposition"
msgstr ""
#: cmdlnopts.c:83
msgid "close shutter" msgid "close shutter"
msgstr "" msgstr ""
#: cmdlnopts.c:37 #: cmdlnopts.c:43
msgid "common device plugin (e.g devfli.so)" msgid "common device plugin (e.g devfli.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:82 #: cmdlnopts.c:90
msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, " msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, "
"1 == output, 0 == input)" "1 == output, 0 == input)"
msgstr "" msgstr ""
#: cmdlnopts.c:50 #: cmdlnopts.c:56
msgid "fast (8MHz) readout mode" msgid "fast readout mode"
msgstr "" msgstr ""
#: cmdlnopts.c:43 #: cmdlnopts.c:49
msgid "filter wheel device number (if many: 0, 1, 2 etc)" msgid "filter wheel device number (if many: 0, 1, 2 etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:44 #: cmdlnopts.c:50
msgid "focuser device number (if many: 0, 1, 2 etc)" msgid "focuser device number (if many: 0, 1, 2 etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:39 #: cmdlnopts.c:45
msgid "focuser device plugin (e.g. devzwo.so)" msgid "focuser device plugin (e.g. devzwo.so)"
msgstr "" msgstr ""
#: cmdlnopts.c:68 #: cmdlnopts.c:86
msgid "frame X0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:70
msgid "frame X1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:69
msgid "frame Y0 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:71
msgid "frame Y1 coordinate (-1 - all with overscan)"
msgstr ""
#: cmdlnopts.c:78
msgid "get value of I/O port pins" msgid "get value of I/O port pins"
msgstr "" msgstr ""
#: cmdlnopts.c:72 #: cmdlnopts.c:71
msgid "grab full frame (with overscans)"
msgstr ""
#: cmdlnopts.c:63
msgid "horizontal binning to N pixels" msgid "horizontal binning to N pixels"
msgstr "" msgstr ""
#: cmdlnopts.c:56 #: cmdlnopts.c:62
msgid "instrument name" msgid "instrument name"
msgstr "" msgstr ""
#: cmdlnopts.c:41 #: cmdlnopts.c:47
msgid "list connected devices" msgid "list connected devices"
msgstr "" msgstr ""
#: cmdlnopts.c:66 #: cmdlnopts.c:102
msgid "local INET socket port"
msgstr ""
#: cmdlnopts.c:100
msgid "logging file name (if run as server)"
msgstr ""
#: cmdlnopts.c:74
msgid "make pause for N seconds between expositions" msgid "make pause for N seconds between expositions"
msgstr "" msgstr ""
#: cmdlnopts.c:65 #: cmdlnopts.c:73
msgid "make series of N frames" msgid "make series of N frames"
msgstr "" msgstr ""
#: cmdlnopts.c:84 #: cmdlnopts.c:92
msgid "move focuser to absolute position, mm" msgid "move focuser to absolute position, mm"
msgstr "" msgstr ""
#: cmdlnopts.c:85 #: cmdlnopts.c:93
msgid "move focuser to relative position, mm" msgid "move focuser to relative position, mm"
msgstr "" msgstr ""
#: cmdlnopts.c:79 #: cmdlnopts.c:87
msgid "move stepper motor asynchronous" msgid "move stepper motor asynchronous"
msgstr "" msgstr ""
#: cmdlnopts.c:48 #: cmdlnopts.c:54
msgid "not open shutter, when exposing (\"dark frames\")" msgid "not open shutter, when exposing (\"dark frames\")"
msgstr "" msgstr ""
#: cmdlnopts.c:57 #: cmdlnopts.c:63
msgid "object name" msgid "object name"
msgstr "" msgstr ""
#: cmdlnopts.c:55 #: cmdlnopts.c:61
msgid "object type (neon, object, flat etc)" msgid "object type (neon, object, flat etc)"
msgstr "" msgstr ""
#: cmdlnopts.c:58 #: cmdlnopts.c:64
msgid "observers' names" msgid "observers' names"
msgstr "" msgstr ""
#: cmdlnopts.c:59 #: cmdlnopts.c:65
msgid "observing program name" msgid "observing program name"
msgstr "" msgstr ""
@ -447,62 +509,70 @@ msgstr ""
msgid "on" msgid "on"
msgstr "" msgstr ""
#: cmdlnopts.c:74 #: cmdlnopts.c:82
msgid "open shutter" msgid "open shutter"
msgstr "" msgstr ""
#: cmdlnopts.c:54 #: cmdlnopts.c:67
msgid "output file name"
msgstr ""
#: cmdlnopts.c:60
msgid "program author" msgid "program author"
msgstr "" msgstr ""
#: cmdlnopts.c:46 #: cmdlnopts.c:52
msgid "rewrite output file if exists" msgid "rewrite output file if exists"
msgstr "" msgstr ""
#: cmdlnopts.c:77 #: cmdlnopts.c:85
msgid "run exposition on HIGH @ pin5 I/O port" msgid "run exposition on HIGH @ pin5 I/O port"
msgstr "" msgstr ""
#: cmdlnopts.c:76 #: cmdlnopts.c:84
msgid "run exposition on LOW @ pin5 I/O port" msgid "run exposition on LOW @ pin5 I/O port"
msgstr "" msgstr ""
#: cmdlnopts.c:49 #: cmdlnopts.c:55
msgid "run in 8-bit mode" msgid "run in 8-bit mode"
msgstr "" msgstr ""
#: cmdlnopts.c:51 #: cmdlnopts.c:57
msgid "set CCD temperature to given value (degr C)" msgid "set CCD temperature to given value (degr C)"
msgstr "" msgstr ""
#: cmdlnopts.c:81 #: cmdlnopts.c:89
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)" msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
msgstr "" msgstr ""
#: cmdlnopts.c:67 #: cmdlnopts.c:75
msgid "set exposure time to given value (seconds!)" msgid "set exposure time to given value (seconds!)"
msgstr "" msgstr ""
#: cmdlnopts.c:52 #: cmdlnopts.c:58
msgid "set fan speed (0 - off, 1 - low, 2 - high)" msgid "set fan speed (0 - off, 1 - low, 2 - high)"
msgstr "" msgstr ""
#: cmdlnopts.c:87 #: cmdlnopts.c:95
msgid "set wheel position" msgid "set wheel position"
msgstr "" msgstr ""
#: cmdlnopts.c:45 #: cmdlnopts.c:51
msgid "show this help" msgid "show this help"
msgstr "" msgstr ""
#: cmdlnopts.c:47 #: cmdlnopts.c:53
msgid "verbose level (each -v increase it)" msgid "verbose level (each -v increase it)"
msgstr "" msgstr ""
#: cmdlnopts.c:64 #: cmdlnopts.c:72
msgid "vertical binning to N pixels" msgid "vertical binning to N pixels"
msgstr "" msgstr ""
#: cmdlnopts.c:40 #: cmdlnopts.c:68
msgid "wait while exposition ends"
msgstr ""
#: cmdlnopts.c:46
msgid "wheel device plugin (e.g. devdummy.so)" msgid "wheel device plugin (e.g. devdummy.so)"
msgstr "" msgstr ""

85
main.c
View File

@ -15,12 +15,15 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <omp.h> #include <omp.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/prctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <usefull_macros.h> #include <usefull_macros.h>
@ -31,8 +34,22 @@
#include "imageview.h" #include "imageview.h"
#endif #endif
#include "omp.h" #include "omp.h"
#include "socket.h"
static int isserver = FALSE;
static pid_t childpid = 0;
void signals(int signo){ void signals(int signo){
if(childpid){ // master process
DBG("Master killed with sig=%d", signo);
LOGWARN("Master killed with sig=%d", signo);
if(!GP->client){
DBG("Unlink pid file");
unlink(GP->pidfile);
}
exit(signo);
}
// slave: cancel exposition
WARNX("Get signal %d - exit", signo); WARNX("Get signal %d - exit", signo);
DBG("Cancel capturing"); DBG("Cancel capturing");
cancel(); cancel();
@ -45,6 +62,7 @@ void signals(int signo){
} }
int main(int argc, char **argv){ int main(int argc, char **argv){
char *self = strdup(argv[0]);
initial_setup(); initial_setup();
/* /*
int cpunumber = sysconf(_SC_NPROCESSORS_ONLN); int cpunumber = sysconf(_SC_NPROCESSORS_ONLN);
@ -52,13 +70,70 @@ int main(int argc, char **argv){
omp_set_num_threads(cpunumber); omp_set_num_threads(cpunumber);
*/ */
parse_args(argc, argv); parse_args(argc, argv);
if(GP->outfile && GP->outfileprefix) ERRX("Can't use outfile name and prefix together");
if(GP->outfile && !GP->rewrite){
struct stat filestat;
if(0 == stat(GP->outfile, &filestat)) ERRX("File %s exists!", GP->outfile);
}
if(GP->port || GP->path){
if(GP->path){
WARNX("Options `port` and `path` can't be used together! Point `port` for TCP socket or `path` for UNIX.");
return 1;
}
int port = atoi(GP->port);
if(port < PORTN_MIN || port > PORTN_MAX){
WARNX("Wrong port value: %d", port);
return 1;
}
if(!GP->client) isserver = TRUE;
}
if(GP->logfile){
int lvl = LOGLEVEL_WARN + GP->verbose;
DBG("level = %d", lvl);
if(lvl > LOGLEVEL_ANY) lvl = LOGLEVEL_ANY;
verbose(1, "Log file %s @ level %d\n", GP->logfile, lvl);
OPENLOG(GP->logfile, lvl, 1);
if(!globlog) WARNX("Can't create log file");
}
signal(SIGINT, signals); signal(SIGINT, signals);
signal(SIGQUIT, signals); signal(SIGQUIT, signals);
signal(SIGABRT, signals); signal(SIGABRT, signals);
signal(SIGTERM, signals); signal(SIGTERM, signals);
focusers(); signal(SIGHUP, SIG_IGN);
wheels(); signal(SIGTSTP, SIG_IGN);
ccds(); // check for another running process in server and standalone mode
return 0; if(!GP->client) check4running(self, GP->pidfile);
if(!isserver && !GP->client){ // standalone mode
focusers();
wheels();
ccds();
return 0;
}
LOGMSG("Started");
#ifndef EBUG
if(isserver){
unsigned int pause = 5;
while(1){
childpid = fork();
if(childpid){ // master
double t0 = dtime();
LOGMSG("Created child with pid %d", childpid);
wait(NULL);
LOGWARN("Child %d died", childpid);
if(dtime() - t0 < 1.) pause += 5;
else pause = 1;
if(pause > 900) pause = 900;
sleep(pause); // wait a little before respawn
}else{ // slave
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
break;
}
}
}
#endif
if(GP->path) return start_socket(isserver, GP->path, FALSE);
if(GP->port) return start_socket(isserver, GP->port, TRUE);
} }

808
server.c Normal file
View File

@ -0,0 +1,808 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdatomic.h>
#include <netdb.h>
#include <pthread.h>
#include <poll.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <usefull_macros.h>
#include "ccdfunc.h"
#include "cmdlnopts.h"
#include "server.h"
#include "socket.h"
static atomic_int camdevno = 0, wheeldevno = 0, focdevno = 0; // current devices numbers
static _Atomic camera_state camstate = CAMERA_IDLE;
#define FLAG_STARTCAPTURE (1<<0)
#define FLAG_CANCEL (1<<1)
static atomic_int camflags = 0, camfanspd = 0, confio = 0, nflushes;
static char *outfile = NULL;
static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions
static frameformat frmformatmax = {0}, curformat = {0}; // maximal format
static void *camdev = NULL, *focdev = NULL, *wheeldev = NULL;
static float focmaxpos = 0., focminpos = 0.; // focuser extremal positions
static int wmaxpos = 0.; // wheel max pos
static float tremain = 0.; // time when capture done
static IMG ima = {0};
static void fixima(){
FREE(ima.data);
int raw_width = curformat.w / GP->hbin, raw_height = curformat.h / GP->vbin;
ima.h = curformat.h;
ima.w = curformat.w;
ima.data = MALLOC(uint16_t, raw_width * raw_height);
}
// functions for processCAM finite state machine
static inline void cameraidlestate(){ // idle - wait for capture commands
if(camflags & FLAG_STARTCAPTURE){ // start capturing
camflags &= ~FLAG_STARTCAPTURE;
camstate = CAMERA_CAPTURE;
camera->cancel();
if(!camera->startexposition()){
LOGERR("Can't start exposition");
WARNX(_("Can't start exposition"));
camstate = CAMERA_ERROR;
return;
}
}
}
static inline void cameracapturestate(){ // capturing - wait for exposition ends
if(camflags & FLAG_CANCEL){ // cancel all expositions
camflags &= ~FLAG_CANCEL;
camera->cancel();
camstate = CAMERA_IDLE;
return;
}
capture_status cs;
if(camera->pollcapture(&cs, &tremain)){
if(cs != CAPTURE_PROCESS){
tremain = 0.;
camstate = CAMERA_FRAMERDY;
return;
}
}
}
// base camera thread
static void* processCAM(_U_ void *d){
if(!camera) ERRX(_("No camera device"));
camera_state curstate = camstate;
double logt = dtime();
while(1){
// log
if(dtime() - logt > TLOG_PAUSE){
logt = dtime();
float t;
if(camera->getTcold(&t)){
LOGMSG("CCDTEMP=%f", t);
}
if(camera->getThot(&t)){
LOGMSG("HOTTEMP=%f", t);
}
if(camera->getTbody(&t)){
LOGMSG("BODYTEMP=%f", t);
}
}
switch(curstate){
case CAMERA_IDLE:
cameraidlestate();
break;
case CAMERA_CAPTURE:
cameracapturestate();
break;
case CAMERA_FRAMERDY:
// do nothing: when `server` got this state it sends "expstate=2" to all clients and changes state to IDLE
break;
case CAMERA_ERROR:
// do nothing: when `server` got this state it sends "expstate=3" to all clients and changes state to IDLE
break;
}
}
return NULL;
}
// functions running @ each devno change
static int camdevini(int n){
if(!camera) return FALSE;
pthread_mutex_lock(&locmutex);
if(!camera->setDevNo(n)){
LOGERR("Can't set active camera number");
pthread_mutex_unlock(&locmutex);
return FALSE;
}
camdevno = n;
LOGMSG("Set camera device number to %d", camdevno);
frameformat step;
camera->getgeomlimits(&frmformatmax, &step);
curformat = frmformatmax;
if(GP->hbin < 1) GP->hbin = 1;
if(GP->vbin < 1) GP->vbin = 1;
fixima();
pthread_mutex_unlock(&locmutex);
return TRUE;
}
static int focdevini(int n){
if(!focuser) return FALSE;
pthread_mutex_lock(&locmutex);
if(!focuser->setDevNo(n)){
LOGERR("Can't set active focuser number");
pthread_mutex_unlock(&locmutex);
return FALSE;
}
focdevno = n;
LOGMSG("Set focuser device number to %d", focdevno);
focuser->getMaxPos(&focmaxpos);
focuser->getMinPos(&focminpos);
pthread_mutex_unlock(&locmutex);
return TRUE;
}
static int wheeldevini(int n){
if(!wheel) return FALSE;
pthread_mutex_unlock(&locmutex);
if(!wheel->setDevNo(n)){
LOGERR("Can't set active wheel number");
pthread_mutex_unlock(&locmutex);
return FALSE;
}
wheeldevno = n;
LOGMSG("Set wheel device number to %d", wheeldevno);
wheel->getMaxPos(&wmaxpos);
pthread_mutex_unlock(&locmutex);
return TRUE;
}
/*******************************************************************************
*************************** CCD/CMOS handlers *********************************
******************************************************************************/
static hresult camlisthandler(int fd, _U_ const char *key, _U_ const char *val){
char buf[BUFSIZ], modname[256];
pthread_mutex_lock(&locmutex);
for(int i = 0; i < camera->Ndevices; ++i){
if(!camera->setDevNo(i)) continue;
camera->getModelName(modname, 255);
snprintf(buf, BUFSIZ-1, CMD_CAMLIST "='%s'", modname);
sendstrmessage(fd, buf);
}
if(camdevno > -1) camera->setDevNo(camdevno);
pthread_mutex_unlock(&locmutex);
return RESULT_SILENCE;
}
static hresult camsetNhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
if(val){
int num = atoi(val);
if(num > camera->Ndevices - 1 || num < 0){
return RESULT_BADVAL;
}
if(!camdevini(num)) return RESULT_FAIL;
}
snprintf(buf, 63, CMD_CAMDEVNO "=%d", camdevno);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
// exposition time setter/getter
static hresult exphandler(int fd, _U_ const char *key, const char *val){
char buf[64];
if(val){
double v = atof(val);
if(v < DBL_EPSILON) return RESULT_BADVAL;
if(camstate != CAMERA_CAPTURE){
pthread_mutex_lock(&locmutex);
if(camera->setexp(v)){
GP->exptime = v;
}else LOGWARN("Can't set exptime to %g", v);
pthread_mutex_unlock(&locmutex);
}
}
snprintf(buf, 63, CMD_EXPOSITION "=%g", GP->exptime);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
// filename setter/getter
static hresult namehandler(int fd, _U_ const char *key, const char *val){
char buf[64];
if(val){
pthread_mutex_lock(&locmutex);
FREE(outfile);
outfile = strdup(val);
GP->outfile = outfile;
GP->outfileprefix = NULL;
pthread_mutex_unlock(&locmutex);
}
if(!GP->outfile) return RESULT_FAIL;
snprintf(buf, 63, CMD_FILENAME "=%s", GP->outfile);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
// filename prefix
static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *val){
char buf[64];
if(val){
pthread_mutex_lock(&locmutex);
FREE(outfile);
outfile = strdup(val);
GP->outfileprefix = outfile;
GP->outfile = NULL;
pthread_mutex_unlock(&locmutex);
}
if(!GP->outfileprefix) return RESULT_FAIL;
snprintf(buf, 63, CMD_FILENAMEPREFIX "=%s", GP->outfileprefix);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
// rewrite
static hresult rewritefilehandler(_U_ int fd, _U_ const char *key, const char *val){
char buf[64];
if(val){
int n = atoi(val);
if(n < 0 || n > 1) return RESULT_BADVAL;
pthread_mutex_lock(&locmutex);
GP->rewrite = n;
pthread_mutex_unlock(&locmutex);
}
snprintf(buf, 63, CMD_REWRITE "=%d", GP->rewrite);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult binhandler(_U_ int fd, const char *key, const char *val){
char buf[64];
if(val){
int b = atoi(val);
if(b < 1) return RESULT_BADVAL;
if(0 == strcmp(key, CMD_HBIN)) GP->hbin = b;
else GP->vbin = b;
pthread_mutex_lock(&locmutex);
if(!camera->setbin(GP->hbin, GP->vbin)){
pthread_mutex_unlock(&locmutex);
return RESULT_BADVAL;
}
fixima();
}
pthread_mutex_lock(&locmutex);
int r = camera->getbin(&GP->hbin, &GP->vbin);
pthread_mutex_unlock(&locmutex);
if(r){
if(0 == strcmp(key, CMD_HBIN)) snprintf(buf, 63, "%s=%d", key, GP->hbin);
else snprintf(buf, 63, "%s=%d", key, GP->vbin);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
return RESULT_FAIL;
}
static hresult temphandler(_U_ int fd, _U_ const char *key, const char *val){
float f;
char buf[64];
if(val){
f = atof(val);
pthread_mutex_lock(&locmutex);
if(!camera->setT((float)f)){
pthread_mutex_unlock(&locmutex);
LOGWARN("Can't set camera T to %.1f", f);
return RESULT_FAIL;
}
LOGMSG("Set camera T to %.1f", f);
}
pthread_mutex_lock(&locmutex);
int r = camera->getTcold(&f);
pthread_mutex_unlock(&locmutex);
if(r){
snprintf(buf, 63, CMD_CAMTEMPER "=%.1f", f);
sendstrmessage(fd, buf);
pthread_mutex_lock(&locmutex);
r = camera->getTbody(&f);
pthread_mutex_unlock(&locmutex);
if(r){
snprintf(buf, 63, "tbody=%.1f", f);
sendstrmessage(fd, buf);
}
pthread_mutex_lock(&locmutex);
r = camera->getThot(&f);
pthread_mutex_unlock(&locmutex);
if(r){
snprintf(buf, 63, "thot=%.1f", f);
sendstrmessage(fd, buf);
}
return RESULT_SILENCE;
}else return RESULT_FAIL;
}
static hresult camfanhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
if(val){
int spd = atoi(val);
if(spd < 0) return RESULT_BADVAL;
if(spd > FAN_HIGH) spd = FAN_HIGH;
pthread_mutex_lock(&locmutex);
int r = camera->setfanspeed((fan_speed)spd);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
camfanspd = spd;
}
snprintf(buf, 63, CMD_CAMFANSPD "=%d", camfanspd);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
const char *shutterstr[] = {"open", "close", "expose @high", "expose @low"};
static hresult shutterhandler(_U_ int fd, _U_ const char *key, const char *val){
if(val){
int x = atoi(val);
if(x < 0 || x >= SHUTTER_AMOUNT) return RESULT_BADVAL;
pthread_mutex_lock(&locmutex);
int r = camera->shuttercmd((shutter_op)x);
pthread_mutex_unlock(&locmutex);
if(r){
LOGMSG("Shutter command '%s'", shutterstr[x]);
}else{
LOGWARN("Can't run shutter command '%s'", shutterstr[x]);
return RESULT_FAIL;
}
}
return RESULT_OK;
}
static hresult confiohandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
if(val){
int io = atoi(val);
pthread_mutex_lock(&locmutex);
int r = camera->confio(io);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
confio = io;
}
snprintf(buf, 63, CMD_CONFIO "=%d", confio);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult iohandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
int io;
if(val){
io = atoi(val);
pthread_mutex_lock(&locmutex);
int r = camera->setio(io);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
}
pthread_mutex_lock(&locmutex);
int r = camera->getio(&io);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
snprintf(buf, 63, CMD_IO "=%d", io);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult gainhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
float f;
if(val){
f = atof(val);
pthread_mutex_lock(&locmutex);
int r = camera->setgain(f);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
}
pthread_mutex_lock(&locmutex);
int r = camera->getgain(&f);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
snprintf(buf, 63, CMD_GAIN "=%.1f", f);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult brightnesshandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
float b;
if(val){
b = atof(val);
pthread_mutex_lock(&locmutex);
int r = camera->setbrightness(b);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
}
pthread_mutex_lock(&locmutex);
int r = camera->getbrightness(&b);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
snprintf(buf, 63, CMD_BRIGHTNESS "=%.1f", b);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
// set format: `format=X0,X1,Y0,Y1`
// get geomlimits: `maxformat=X0,X1,Y0,Y1`
static hresult formathandler(int fd, const char *key, const char *val){
char buf[64];
frameformat fmt;
if(val){
if(strcmp(key, CMD_FRAMEFORMAT)) return RESULT_BADKEY; // can't set maxformat
if(4 != sscanf(val, "%d,%d,%d,%d", &fmt.xoff, &fmt.yoff, &fmt.w, &fmt.h)) return RESULT_BADVAL;
fmt.w -= fmt.xoff; fmt.h -= fmt.yoff;
pthread_mutex_lock(&locmutex);
int r = camera->setgeometry(&fmt);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
curformat = fmt;
fixima();
}
if(strcmp(key, CMD_FRAMEMAX)) snprintf(buf, 63, CMD_FRAMEMAX "=%d,%d,%d,%d",
frmformatmax.xoff, frmformatmax.yoff, frmformatmax.xoff+frmformatmax.w, frmformatmax.yoff+frmformatmax.w);
else snprintf(buf, 63, CMD_FRAMEFORMAT "=%d,%d,%d,%d",
camera->array.xoff, camera->array.yoff, camera->array.xoff+camera->array.w, camera->array.yoff+camera->array.w);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult nflusheshandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
if(val){
int n = atoi(val);
if(n < 1) return RESULT_BADVAL;
pthread_mutex_lock(&locmutex);
if(!camera->setnflushes(n)){
pthread_mutex_unlock(&locmutex);
return RESULT_FAIL;
}
nflushes = n;
pthread_mutex_unlock(&locmutex);
}
snprintf(buf, 63, CMD_NFLUSHES "=%d", nflushes);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult expstatehandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
if(val){
int n = atoi(val);
if(n == CAMERA_IDLE){ // cancel expositions
camflags |= FLAG_CANCEL;
return RESULT_OK;
}
else if(n == CAMERA_CAPTURE){ // start exposition
camflags |= FLAG_STARTCAPTURE;
return RESULT_OK;
}
else return RESULT_BADVAL;
}
snprintf(buf, 63, CMD_EXPSTATE "=%d", camstate);
sendstrmessage(fd, buf);
snprintf(buf, 63, "camflags=%d", camflags);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult tremainhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
snprintf(buf, 63, CMD_TREMAIN "=%g", tremain);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
/*
static hresult handler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
return RESULT_SILENCE;
}
*/
/*******************************************************************************
***************************** Wheel handlers **********************************
******************************************************************************/
static hresult wlisthandler(int fd, _U_ const char *key, _U_ const char *val){
if(wheel->Ndevices < 1) return RESULT_FAIL;
pthread_mutex_lock(&locmutex);
for(int i = 0; i < wheel->Ndevices; ++i){
if(!wheel->setDevNo(i)) continue;
char modname[256], buf[BUFSIZ];
wheel->getModelName(modname, 255);
snprintf(buf, BUFSIZ-1, CMD_WLIST "='%s'", modname);
sendstrmessage(fd, buf);
}
if(wheeldevno > -1) wheel->setDevNo(wheeldevno);
pthread_mutex_unlock(&locmutex);
return RESULT_SILENCE;
}
static hresult wsetNhandler(int fd, _U_ const char *key, const char *val){
char buf[64];
if(val){
int num = atoi(val);
if(num > wheel->Ndevices - 1 || num < 0){
return RESULT_BADVAL;
}
if(!wheeldevini(num)) return RESULT_FAIL;
}
snprintf(buf, 63, CMD_WDEVNO "=%d", wheeldevno);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult wgotohandler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
int pos;
if(val){
pos = atoi(val);
pthread_mutex_lock(&locmutex);
int r = wheel->setPos(pos);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_BADVAL;
}
pthread_mutex_lock(&locmutex);
int r = wheel->getPos(&pos);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
snprintf(buf, 63, CMD_WPOS "=%d", pos);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
/*******************************************************************************
**************************** Focuser handlers *********************************
******************************************************************************/
static hresult foclisthandler(int fd, _U_ const char *key, _U_ const char *val){
if(focuser->Ndevices < 1) return RESULT_FAIL;
pthread_mutex_lock(&locmutex);
for(int i = 0; i < focuser->Ndevices; ++i){
char modname[256], buf[BUFSIZ];
if(!focuser->setDevNo(i)) continue;
focuser->getModelName(modname, 255);
snprintf(buf, BUFSIZ-1, CMD_FOCLIST "='%s'", modname);
sendstrmessage(fd, buf);
}
if(focdevno > -1) focuser->setDevNo(focdevno);
pthread_mutex_unlock(&locmutex);
return RESULT_SILENCE;
}
static hresult fsetNhandler(int fd, _U_ const char *key, const char *val){
char buf[64];
if(val){
int num = atoi(val);
if(num > focuser->Ndevices - 1 || num < 0){
return RESULT_BADVAL;
}
if(!focdevini(num)) return RESULT_FAIL;
}
snprintf(buf, 63, CMD_FDEVNO "=%d", focdevno);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
static hresult fgotohandler(int fd, _U_ const char *key, const char *val){
char buf[64];
float f;
int r;
if(val){
f = atof(val);
if(f < focminpos || f > focmaxpos) return RESULT_BADVAL;
pthread_mutex_lock(&locmutex);
if(f - focminpos < __FLT_EPSILON__){
r = focuser->home(1);
}else{
r = focuser->setAbsPos(1, f);
}
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
}
pthread_mutex_lock(&locmutex);
r = focuser->getPos(&f);
pthread_mutex_unlock(&locmutex);
if(!r) return RESULT_FAIL;
snprintf(buf, 63, "FOCPOS=%g", f);
sendstrmessage(fd, buf);
return RESULT_SILENCE;
}
/*
static hresult handler(_U_ int fd, _U_ const char *key, _U_ const char *val){
char buf[64];
return RESULT_SILENCE;
}
*/
// information about everything
static hresult infohandler(int fd, _U_ const char *key, _U_ const char *val){
char buf[BUFSIZ], buf1[256];
float f;
int i;
if(camera){
if(camera->getModelName(buf1, 255)){
snprintf(buf, BUFSIZ-1, CMD_CAMLIST "='%s'", buf1);
sendstrmessage(fd, buf);
}
namehandler(fd, CMD_FILENAME, NULL);
binhandler(fd, CMD_HBIN, NULL);
binhandler(fd, CMD_VBIN, NULL);
temphandler(fd, CMD_CAMTEMPER, NULL);
exphandler(fd, CMD_EXPOSITION, NULL);
}
if(wheel){
if(wheel->getModelName(buf1, 255)){
snprintf(buf, BUFSIZ-1, CMD_WLIST "='%s'", buf1);
sendstrmessage(fd, buf);
}
if(wheel->getTbody(&f)){
snprintf(buf, BUFSIZ-1, "WHEELTEMP=%.1f", f);
sendstrmessage(fd, buf);
}
if(wheel->getPos(&i)){
snprintf(buf, BUFSIZ-1, "WHEELPOS=%d", i);
sendstrmessage(fd, buf);
}
snprintf(buf, BUFSIZ-1, "WHEELMAXPOS=%d", wmaxpos);
sendstrmessage(fd, buf);
}
if(focuser){
if(focuser->getModelName(buf1, 255)){
snprintf(buf, BUFSIZ-1, CMD_FOCLIST "='%s'", buf1);
sendstrmessage(fd, buf);
}
if(focuser->getTbody(&f)){
snprintf(buf, BUFSIZ-1, "FOCTEMP=%.1f", f);
sendstrmessage(fd, buf);
}
snprintf(buf, BUFSIZ-1, "FOCMINPOS=%g", focminpos);
sendstrmessage(fd, buf);
snprintf(buf, BUFSIZ-1, "FOCMAXPOS=%g", focmaxpos);
sendstrmessage(fd, buf);
if(focuser->getPos(&f)){
snprintf(buf, BUFSIZ-1, "FOCPOS=%g", f);
sendstrmessage(fd, buf);
}
}
return RESULT_SILENCE;
}
// for setters: do nothing when camera not in idle state
static int CAMbusy(){
if(camera && camstate != CAMERA_IDLE) return TRUE;
return TRUE;
}
static int chktrue(_U_ char *val){
return TRUE;
}
static int chkcam(char *val){
if(val && CAMbusy()) return RESULT_BUSY;
if(camera) return TRUE;
return FALSE;
}
static int chkwheel(char *val){
if(val && CAMbusy()) return RESULT_BUSY;
if(wheel) return TRUE;
return FALSE;
}
static int chkfoc(char *val){
if(val && CAMbusy()) return RESULT_BUSY;
if(focuser) return TRUE;
return FALSE;
}
static handleritem items[] = {
{chktrue, infohandler, CMD_INFO},
{chkcam, camlisthandler, CMD_CAMLIST},
{chkcam, camsetNhandler, CMD_CAMDEVNO},
{chkcam, camfanhandler, CMD_CAMFANSPD},
{chkcam, exphandler, CMD_EXPOSITION},
{chkcam, namehandler, CMD_FILENAME},
{chkcam, binhandler, CMD_HBIN},
{chkcam, binhandler, CMD_VBIN},
{chkcam, temphandler, CMD_CAMTEMPER},
{chkcam, shutterhandler, CMD_SHUTTER},
{chkcam, confiohandler, CMD_CONFIO},
{chkcam, iohandler, CMD_IO},
{chkcam, gainhandler, CMD_GAIN},
{chkcam, brightnesshandler, CMD_BRIGHTNESS},
{chkcam, formathandler, CMD_FRAMEFORMAT},
{chkcam, formathandler, CMD_FRAMEMAX},
{chkcam, nflusheshandler, CMD_NFLUSHES},
{chkcam, expstatehandler, CMD_EXPSTATE},
{chkcam, nameprefixhandler, CMD_FILENAMEPREFIX},
{chkcam, rewritefilehandler, CMD_REWRITE},
{chktrue, tremainhandler, CMD_TREMAIN},
{chkfoc, foclisthandler, CMD_FOCLIST},
{chkfoc, fsetNhandler, CMD_FDEVNO},
{chkfoc, fgotohandler, CMD_FGOTO},
{chkwheel, wlisthandler, CMD_WLIST},
{chkwheel, wsetNhandler, CMD_WDEVNO},
{chkwheel, wgotohandler, CMD_WPOS},
{NULL, NULL, NULL},
};
#define CLBUFSZ BUFSIZ
void server(int sock){
// init everything
startCCD(&camdev);
camdevini(0);
startFocuser(&focdev);
focdevini(0);
startWheel(&wheeldev);
wheeldevini(0);
if(listen(sock, MAXCLIENTS) == -1){
WARN("listen");
LOGWARN("listen");
return;
}
// start camera thread
pthread_t camthread;
if(camera){
if(pthread_create(&camthread, NULL, processCAM, NULL)) ERR("pthread_create()");
}
int nfd = 1; // only one socket @start
struct pollfd poll_set[MAXCLIENTS+1];
char buffers[MAXCLIENTS][CLBUFSZ]; // buffers for data reading
bzero(poll_set, sizeof(poll_set));
// ZERO - listening server socket
poll_set[0].fd = sock;
poll_set[0].events = POLLIN;
while(1){
poll(poll_set, nfd, 1); // max timeout - 1ms
if(poll_set[0].revents & POLLIN){ // check main for accept()
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
int client = accept(sock, (struct sockaddr*)&addr, &len);
DBG("New connection");
LOGMSG("SERVER got connection, fd=%d", client);
if(nfd == MAXCLIENTS + 1){
LOGWARN("Max amount of connections, disconnect fd=%d", client);
WARNX("Limit of connections reached");
close(client);
}else{
memset(&poll_set[nfd], 0, sizeof(struct pollfd));
poll_set[nfd].fd = client;
poll_set[nfd].events = POLLIN;
++nfd;
}
}
// process some data & send messages to ALL
if(camstate == CAMERA_FRAMERDY || camstate == CAMERA_ERROR){
char buff[32];
int l = 0;
snprintf(buff, 31, CMD_EXPSTATE "=%d", camstate);
DBG("Send %s to %d clients", buff, nfd - 1);
for(int i = 1; i < nfd; ++i)
sendmessage(poll_set[i].fd, buff, l);
if(camstate == CAMERA_FRAMERDY){ // save frame
if(!ima.data) LOGERR("Can't save image: not initialized");
else{
if(!camera->capture(&ima)) LOGERR("Can't capture image");
else{
calculate_stat(&ima);
saveFITS(&ima);
}
}
}
camstate = CAMERA_IDLE;
}
// scan connections
for(int fdidx = 1; fdidx < nfd; ++fdidx){
if((poll_set[fdidx].revents & POLLIN) == 0) continue;
int fd = poll_set[fdidx].fd;
if(!processData(fd, items, buffers[fdidx-1], CLBUFSZ)){ // socket closed
DBG("Client fd=%d disconnected", fd);
LOGMSG("SERVER client fd=%d disconnected", fd);
buffers[fdidx-1][0] = 0; // clear rest of data in buffer
close(fd);
// move last FD to current position
poll_set[fdidx] = poll_set[nfd - 1];
--nfd;
}
}
}
focclose(focdev);
closewheel(wheeldev);
closecam(camdev);
}

73
server.h Normal file
View File

@ -0,0 +1,73 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef SERVER_H__
#define SERVER_H__
typedef enum{
CAMERA_IDLE, // idle state, client send this to cancel capture
CAMERA_CAPTURE, // capturing frame, client send this to start capture
CAMERA_FRAMERDY, // frame ready to be saved
CAMERA_ERROR // can't do exposition
} camera_state;
// pause (seconds) between temperature logging
#define TLOG_PAUSE 60.
// server-side functions
void server(int fd);
// common information about everything
#define CMD_INFO "info"
// CCD/CMOS
#define CMD_CAMLIST "camlist"
#define CMD_CAMDEVNO "camdevno"
#define CMD_EXPOSITION "exptime"
#define CMD_FILENAME "filename"
#define CMD_FILENAMEPREFIX "filenameprefix"
// rewrite=1 will rewrite files, =0 - not (only for `filename`)
#define CMD_REWRITE "rewrite"
#define CMD_HBIN "hbin"
#define CMD_VBIN "vbin"
#define CMD_CAMTEMPER "tcold"
#define CMD_CAMFANSPD "ccdfanspeed"
#define CMD_SHUTTER "shutter"
#define CMD_CONFIO "confio"
#define CMD_IO "io"
#define CMD_GAIN "gain"
#define CMD_BRIGHTNESS "brightness"
#define CMD_FRAMEFORMAT "format"
#define CMD_FRAMEMAX "maxformat"
#define CMD_NFLUSHES "nflushes"
// expstate=CAMERA_CAPTURE will start exposition, CAMERA_IDLE - cancel
#define CMD_EXPSTATE "expstate"
#define CMD_TREMAIN "tremain"
// focuser
#define CMD_FOCLIST "foclist"
#define CMD_FDEVNO "focdevno"
#define CMD_FGOTO "focgoto"
// wheel
#define CMD_WLIST "wlist"
#define CMD_WDEVNO "wdevno"
#define CMD_WPOS "wpos"
#endif // SERVER_H__

229
socket.c Normal file
View File

@ -0,0 +1,229 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h> // isspace
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/un.h> // unix socket
#include <usefull_macros.h>
#include "cmdlnopts.h"
#include "client.h"
#include "server.h"
#include "socket.h"
/**
* @brief start_socket - create socket and run client or server
* @param isserver - TRUE for server, FALSE for client
* @param path - UNIX-socket path or local INET socket port
* @param isnet - TRUE for INET socket, FALSE for UNIX
* @return 0 if OK
*/
int start_socket(int isserver, char *path, int isnet){
if(!path) return 1;
DBG("path/port: %s", path);
int sock = -1;
struct addrinfo hints = {0}, *res;
struct sockaddr_un unaddr = {0};
if(isnet){
DBG("Network socket");
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if(getaddrinfo("127.0.0.1", path, &hints, &res) != 0){
ERR("getaddrinfo");
}
}else{
DBG("UNIX socket");
char apath[128];
if(*path == 0){
DBG("convert name");
apath[0] = 0;
strncpy(apath+1, path+1, 126);
}else if(strncmp("\\0", path, 2) == 0){
DBG("convert name");
apath[0] = 0;
strncpy(apath+1, path+2, 126);
}else strcpy(apath, path);
unaddr.sun_family = AF_UNIX;
hints.ai_addr = (struct sockaddr*) &unaddr;
hints.ai_addrlen = sizeof(unaddr);
memcpy(unaddr.sun_path, apath, 106); // if sun_path[0] == 0 we don't create a file
hints.ai_family = AF_UNIX;
hints.ai_socktype = SOCK_SEQPACKET;
res = &hints;
}
for(struct addrinfo *p = res; p; p = p->ai_next){
if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0){ // or SOCK_STREAM?
LOGWARN("socket()");
WARN("socket()");
continue;
}
if(isserver){
int reuseaddr = 1;
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){
LOGWARN("setsockopt()");
WARN("setsockopt()");
close(sock); sock = -1;
continue;
}
if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){
LOGWARN("bind()");
WARN("bind()");
close(sock); sock = -1;
continue;
}
int enable = 1;
if(ioctl(sock, FIONBIO, (void *)&enable) < 0){ // make socket nonblocking
LOGERR("Can't make socket nonblocking");
ERRX("ioctl()");
}
}else{
if(connect(sock, p->ai_addr, p->ai_addrlen) == -1){
LOGWARN("connect()");
WARN("connect()");
close(sock); sock = -1;
}
}
break;
}
if(sock < 0){
LOGERR("Can't open socket");
ERRX("Can't open socket");
}
if(isnet) freeaddrinfo(res);
if(isserver) server(sock);
else client(sock);
close(sock);
signals(0);
return 0;
}
// simple wrapper over write: add missed newline and log data
void sendmessage(int fd, const char *msg, int l){
if(fd < 1 || !msg || l < 1) return;
DBG("send to fd %d: %s [%d]", fd, msg, l);
char *tmpbuf = MALLOC(char, l+1);
memcpy(tmpbuf, msg, l);
if(msg[l-1] != '\n') tmpbuf[l++] = '\n';
if(l != write(fd, tmpbuf, l)){
LOGWARN("write()");
WARN("write()");
}else{
if(globlog){ // logging turned ON
tmpbuf[l-1] = 0; // remove trailing '\n' for logging
LOGMSG("SEND '%s'", tmpbuf);
}
}
FREE(tmpbuf);
}
void sendstrmessage(int fd, const char *msg){
if(fd < 1 || !msg) return;
int l = strlen(msg);
sendmessage(fd, msg, l);
}
// text messages for `hresult`
static const char *resmessages[] = {
[RESULT_OK] = "OK",
[RESULT_BUSY] = "BUSY",
[RESULT_FAIL] = "FAIL",
[RESULT_BADKEY] = "BADKEY",
[RESULT_BADVAL] = "BADVAL",
[RESULT_SILENCE] = "",
};
const char *hresult2str(hresult r){
if(r >= RESULT_NUM) return "BADRESULT";
return resmessages[r];
}
/**
* @brief get_keyval - get value of `key = val`
* @param keyval (io) - pair `key = val`, return `key`
* @return `val`
*/
char *get_keyval(char *keyval){
DBG("Got string %s", keyval);
// remove starting spaces in key
while(isspace(*keyval)) ++keyval;
char *val = strchr(keyval, '=');
if(val){ // got value: remove starting spaces in val
*val++ = 0;
while(isspace(*val)) ++val;
}
// remove trailing spaces in key
char *e = keyval + strlen(keyval) - 1; // last key symbol
while(isspace(*e) && e > keyval) --e;
e[1] = 0;
// now we have key (`str`) and val (or NULL)
DBG("key=%s, val=%s", keyval, val);
return val;
}
// parse string of data (command or key=val)
// the CONTENT of buffer `str` WILL BE BROKEN!
static void parsestring(int fd, handleritem *handlers, char *str){
if(fd < 1 || !handlers || !handlers->key || !str || !*str) return;
char *val = get_keyval(str);
if(val) LOGMSG("RECEIVE '%s=%s'", str, val);
else LOGMSG("RECEIVE '%s'", str);
for(handleritem *h = handlers; h->key; ++h){
if(strcmp(str, h->key) == 0){ // found command
if(h->chkfunction && !h->chkfunction(val)) sendstrmessage(fd, resmessages[RESULT_FAIL]);
else{
if(h->handler){
hresult r = h->handler(fd, str, val);
sendstrmessage(fd, hresult2str(r));
}else sendstrmessage(fd, resmessages[RESULT_FAIL]);
}
return;
}
}
sendstrmessage(fd, resmessages[RESULT_BADKEY]);
}
/**
* @brief processData - read (if available) data from fd and run processing, sending to fd messages for each command
* @param fd - socket file descriptor
* @param handlers - NULL-terminated array of handlers
* @param buf (io) - zero-terminated buffer for storing rest of data (without newline), its content will be changed
* @param buflen - its length
* @return FALSE if client closed (nothing to read)
*/
int processData(int fd, handleritem *handlers, char *buf, int buflen){
int curlen = strlen(buf);
if(curlen == buflen-1) curlen = 0; // buffer overflow - clear old content
ssize_t rd = read(fd, buf + curlen, buflen-1 - curlen);
if(rd <= 0) return FALSE;
DBG("got %s[%zd] from %d", buf, rd, fd);
char *restofdata = buf, *eptr = buf + curlen + rd;
*eptr = 0;
do{
char *nl = strchr(restofdata, '\n');
if(!nl) break;
*nl++ = 0;
parsestring(fd, handlers, restofdata);
restofdata = nl;
DBG("rest of data: %s", restofdata);
}while(1);
if(restofdata != buf) memmove(buf, restofdata, eptr - restofdata + 1);
return TRUE;
}

59
socket.h Normal file
View File

@ -0,0 +1,59 @@
/*
* This file is part of the CCD_Capture project.
* Copyright 2022 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef SERSOCK_H__
#define SERSOCK_H__
// max & min TCP socket port number
#define PORTN_MAX (65535)
#define PORTN_MIN (1024)
#define BUFLEN (1024)
// Max amount of connections
#define MAXCLIENTS (30)
typedef enum{
RESULT_OK, // all OK
RESULT_BUSY, // camera busy and no setters can be done
RESULT_FAIL, // failed running command
RESULT_BADVAL, // bad key's value
RESULT_BADKEY, // bad key
RESULT_SILENCE, // send nothing to client
RESULT_NUM
} hresult;
const char *hresult2str(hresult r);
// fd - socket fd to send private messages, key, val - key and its value
typedef hresult (*mesghandler)(int fd, const char *key, const char *val);
typedef struct{
int (*chkfunction)(char *val); // function to check device is ready
mesghandler handler; // handler function
const char *key; // keyword
} handleritem;
int start_socket(int server, char *path, int isnet);
void sendmessage(int fd, const char *msg, int l);
void sendstrmessage(int fd, const char *msg);
char *get_keyval(char *keyval);
int processData(int fd, handleritem *handlers, char *buf, int buflen);
#endif // SERSOCK_H__