mirror of
https://github.com/eddyem/small_tel.git
synced 2025-12-06 02:35:14 +03:00
add weather processing to 10micron stellarium
This commit is contained in:
parent
6bfcc8730c
commit
b25c15cbfc
@ -9,7 +9,9 @@ main.c
|
||||
main.h
|
||||
parseargs.c
|
||||
parseargs.h
|
||||
socket.c
|
||||
socket.h
|
||||
telescope.c
|
||||
telescope.h
|
||||
usefull_macros.c
|
||||
usefull_macros.h
|
||||
usefull_macro.c
|
||||
usefull_macro.h
|
||||
|
||||
@ -24,20 +24,23 @@
|
||||
#include <strings.h>
|
||||
#include <math.h>
|
||||
#include "cmdlnopts.h"
|
||||
#include "usefull_macros.h"
|
||||
#include "parseargs.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
/*
|
||||
* here are global parameters initialisation
|
||||
*/
|
||||
int help;
|
||||
glob_pars G;
|
||||
glob_pars *GP = NULL;
|
||||
|
||||
#define DEFAULT_COMDEV "/dev/ttyUSB0"
|
||||
// port for connections
|
||||
#define DEFAULT_PORT "10000"
|
||||
#define DEFAULT_DBGPORT "10001"
|
||||
// accept only local connections
|
||||
//#define ACCEPT_IP "192.168.3.225"
|
||||
// weather server port and name
|
||||
#define DEFAULT_WSPORT (12345)
|
||||
#define DEFAULT_WSNAME "robotel1.sao.ru"
|
||||
// default PID filename:
|
||||
#define DEFAULT_PIDFILE "/tmp/stellariumdaemon.pid"
|
||||
// default file with headers
|
||||
@ -52,6 +55,8 @@ glob_pars const Gdefault = {
|
||||
.pidfile = DEFAULT_PIDFILE,
|
||||
.crdsfile = DEFAULT_FITSHDR,
|
||||
.emulation = 0,
|
||||
.weathserver = DEFAULT_WSNAME,
|
||||
.weathport = DEFAULT_WSPORT,
|
||||
.logfile = NULL // don't save logs
|
||||
};
|
||||
|
||||
@ -70,6 +75,8 @@ myoption cmdlnopts[] = {
|
||||
{"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")},
|
||||
{"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("port to connect (default: " DEFAULT_PORT ")")},
|
||||
{"dbgport", NEED_ARG, NULL, 'D', arg_string, APTR(&G.dbgport), _("port to connect for debug console (default: " DEFAULT_DBGPORT ")")},
|
||||
{"wport", NEED_ARG, NULL, 'w', arg_int, APTR(&G.weathport), _("weather server port")},
|
||||
{"wname", NEED_ARG, NULL, 'W', arg_string, APTR(&G.weathserver),_("weather server address")},
|
||||
end_option
|
||||
};
|
||||
|
||||
|
||||
@ -23,8 +23,6 @@
|
||||
#ifndef __CMDLNOPTS_H__
|
||||
#define __CMDLNOPTS_H__
|
||||
|
||||
#include "parseargs.h"
|
||||
|
||||
/*
|
||||
* here are some typedef's for global data
|
||||
*/
|
||||
@ -35,11 +33,15 @@ typedef struct{
|
||||
char *pidfile; // name of PID file
|
||||
char *logfile; // logging to this file
|
||||
char *crdsfile; // file where FITS-header should be written
|
||||
char *weathserver; // weather server name
|
||||
int emulation; // run in emulation mode
|
||||
int rest_pars_num; // number of rest parameters
|
||||
int weathport; // weather server port
|
||||
char** rest_pars; // the rest parameters: array of char*
|
||||
} glob_pars;
|
||||
|
||||
// global parameters
|
||||
extern glob_pars *GP;
|
||||
|
||||
glob_pars *parse_args(int argc, char **argv);
|
||||
#endif // __CMDLNOPTS_H__
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
#include "math.h"
|
||||
#include "emulation.h"
|
||||
#include "usefull_macros.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
// emulation speed over RA & DEC (0.5 degr per sec)
|
||||
#define RA_SPEED (0.033)
|
||||
|
||||
@ -19,7 +19,8 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "libsofa.h"
|
||||
#include "usefull_macros.h"
|
||||
#include "socket.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
#ifdef EBUG
|
||||
void reprd(char* s, double ra, double dc){
|
||||
@ -45,31 +46,73 @@ void radtodeg(double r){
|
||||
#define REP(a,b,c)
|
||||
#endif
|
||||
|
||||
// temporal stubs for weather/place/DUT1 data; return 0 if all OK
|
||||
int getPlace(placeData *p){
|
||||
if(!p) return 0;
|
||||
/* Site longitude, latitude (radians) and height above the geoid (m). */
|
||||
p->slong = 0.7232763200;
|
||||
p->slat = 0.7618977414;
|
||||
/*
|
||||
iauAf2a('+', 41, 26, 26.45, &p->slong); // longitude
|
||||
iauAf2a('+', 43, 39, 12.69, &p->slat); // latitude
|
||||
*/
|
||||
p->salt = 2070.0; // altitude
|
||||
//DBG("long: %.10f, lat: %.10f", p->slong, p->slat);
|
||||
return 0;
|
||||
// temporal stubs for weather/place/DUT1 data; user can change values of these variables
|
||||
static placeData place = {.slong = 0.7232763200, .slat = 0.7618977414, .salt = 2070.};
|
||||
placeData *getPlace(){
|
||||
return &place;
|
||||
}
|
||||
int getWeath(placeWeather *w){
|
||||
if(!w) return 0;
|
||||
w->relhum = 0.7;
|
||||
w->tc = 1.;
|
||||
w->php = 780.;
|
||||
return 0;
|
||||
|
||||
static localWeather weather = {0};
|
||||
typedef struct{
|
||||
const char *name;
|
||||
double *valptr;
|
||||
} weathpars;
|
||||
#define WPCOUNT (7)
|
||||
static weathpars WPars[WPCOUNT] = {
|
||||
{"BTAHumid", &weather.relhum},
|
||||
{"BTAPres", &weather.pres},
|
||||
{"Exttemp", &weather.tc},
|
||||
{"Rain", &weather.rain},
|
||||
{"Clouds", &weather.clouds},
|
||||
{"Wind", &weather.wind},
|
||||
{"Time", &weather.time}
|
||||
};
|
||||
|
||||
localWeather *getWeath(){
|
||||
//DBG("DT=%zd", time(NULL) - (time_t)weather.time);
|
||||
char *w = getweathbuffer();
|
||||
//DBG("w=%s", w);
|
||||
if(w){ // get new data - check it
|
||||
int ctr = 0;
|
||||
for(int i = 0; i < WPCOUNT; ++i){
|
||||
if(getparval(WPars[i].name, w, WPars[i].valptr)) ++ctr;
|
||||
}
|
||||
if(ctr != WPCOUNT) WARN("Not full set of parameters in %s", w);
|
||||
FREE(w);
|
||||
}
|
||||
if((time_t)weather.time == 0 || time(NULL) - (time_t)weather.time > 3600) return NULL;
|
||||
return &weather;
|
||||
}
|
||||
int getDUT(almDut *a){
|
||||
if(!a) return 0;
|
||||
a->px = a->py = a->DUT1 = 0.;
|
||||
return 0;
|
||||
static almDut dut1 = {0};
|
||||
almDut *getDUT(){
|
||||
// check DUT1 data HERE once per some time
|
||||
return &dut1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief r2sHMS - convert angle in radians into string "'HH:MM:SS.SS'"
|
||||
* @param radians - angle
|
||||
* @param hms (o) - string
|
||||
* @param len - length of hms
|
||||
*/
|
||||
void r2sHMS(double radians, char *hms, int len){
|
||||
char pm;
|
||||
int i[4];
|
||||
iauA2tf(2, radians, &pm, i);
|
||||
snprintf(hms, len, "'%c%02d:%02d:%02d.%02d'", pm, i[0],i[1],i[2],i[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief r2sDMS - convert angle in radians into string "'DD:MM:SS.S'"
|
||||
* @param radians - angle
|
||||
* @param dms (o) - string
|
||||
* @param len - length of hms
|
||||
*/
|
||||
void r2sDMS(double radians, char *dms, int len){
|
||||
char pm;
|
||||
int i[4];
|
||||
iauA2af(1, radians, &pm, i);
|
||||
snprintf(dms, len, "'%c%02d:%02d:%02d.%d'", pm, i[0],i[1],i[2],i[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,15 +153,89 @@ int get_MJDt(struct timeval *tval, sMJD *MJD){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_LST - calculate local siderial time
|
||||
* @param mjd (i) - date/time for LST (utc1 & tt used)
|
||||
* @param dUT1 - (UT1-UTC)
|
||||
* @param slong - site longitude (radians)
|
||||
* @param LST (o) - local sidereal time (radians)
|
||||
* @return 0 if all OK
|
||||
*/
|
||||
int get_LST(sMJD *mjd, double dUT1, double slong, double *LST){
|
||||
double ut11, ut12;
|
||||
sMJD Mjd;
|
||||
if(!mjd){
|
||||
if(get_MJDt(NULL, &Mjd)) return 1;
|
||||
}else memcpy(&Mjd, mjd, sizeof(sMJD));
|
||||
if(iauUtcut1(Mjd.utc1, Mjd.utc2, dUT1, &ut11, &ut12)) return 2;
|
||||
/*double era = iauEra00(ut11, ut12) + slong;
|
||||
double eo = iauEe06a(mjd->tt1, mjd->tt2);
|
||||
printf("ERA = %s; ", radtohrs(era));
|
||||
printf("ERA-eo = %s\n", radtohrs(era-eo));*/
|
||||
if(!LST) return 0;
|
||||
double ST = iauGst06a(ut11, ut12, Mjd.tt1, Mjd.tt2);
|
||||
ST += slong;
|
||||
if(ST > D2PI) ST -= D2PI;
|
||||
else if(ST < 0.) ST += D2PI;
|
||||
*LST = ST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief hor2eq - convert horizontal coordinates to polar
|
||||
* @param h (i) - horizontal coordinates
|
||||
* @param pc (o) - polar coordinates
|
||||
* @param sidTime - sidereal time
|
||||
*/
|
||||
void hor2eq(horizCrds *h, polarCrds *pc, double sidTime){
|
||||
if(!h || !pc) return;
|
||||
placeData *p = getPlace();
|
||||
iauAe2hd(h->az, DPI/2. - h->zd, p->slat, &pc->ha, &pc->dec); // A,H -> HA,DEC; phi - site latitude
|
||||
pc->ra = sidTime - pc->ha;
|
||||
pc->eo = 0.;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief eq2horH - convert polar coordinates to horizontal
|
||||
* @param pc (i) - polar coordinates (only HA used)
|
||||
* @param h (o) - horizontal coordinates
|
||||
* @param sidTime - sidereal time
|
||||
*/
|
||||
void eq2horH(polarCrds *pc, horizCrds *h){
|
||||
if(!h || !pc) return;
|
||||
placeData *p = getPlace();
|
||||
double alt;
|
||||
iauHd2ae(pc->ha, pc->dec, p->slat, &h->az, &alt);
|
||||
h->zd = DPI/2. - alt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief eq2hor - convert polar coordinates to horizontal
|
||||
* @param pc (i) - polar coordinates (only RA used)
|
||||
* @param h (o) - horizontal coordinates
|
||||
* @param sidTime - sidereal time
|
||||
*/
|
||||
void eq2hor(polarCrds *pc, horizCrds *h, double sidTime){
|
||||
if(!h || !pc) return;
|
||||
double ha = sidTime - pc->ra + pc->eo;
|
||||
placeData *p = getPlace();
|
||||
double alt;
|
||||
iauHd2ae(ha, pc->dec, p->slat, &h->az, &alt);
|
||||
h->zd = DPI/2. - alt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief get_ObsPlace - calculate observed place (without PM etc) for given date @550nm
|
||||
* @param tval (i) - time
|
||||
* @param p2000 (i) - polar coordinates for J2000 (only ra/dec used), ICRS (catalog)
|
||||
* @param weath (i) - weather data (relhum, temp, press) or NULL if none
|
||||
* @param pnow (o) - polar coordinates for given epoch (or NULL)
|
||||
* @param hnow (o) - horizontal coordinates for given epoch (or NULL)
|
||||
* @return 0 if all OK
|
||||
*/
|
||||
int get_ObsPlace(struct timeval *tval, polarCrds *p2000, polarCrds *pnow, horizCrds *hnow){
|
||||
int get_ObsPlace(struct timeval *tval, polarCrds *p2000, localWeather *weath, polarCrds *pnow, horizCrds *hnow){
|
||||
double pr = 0.0; // RA proper motion (radians/year; Note 2)
|
||||
double pd = 0.0; // Dec proper motion (radians/year)
|
||||
double px = 0.0; // parallax (arcsec)
|
||||
@ -126,28 +243,26 @@ int get_ObsPlace(struct timeval *tval, polarCrds *p2000, polarCrds *pnow, horizC
|
||||
sMJD MJD;
|
||||
if(get_MJDt(tval, &MJD)) return -1;
|
||||
if(!p2000) return -1;
|
||||
placeData p;
|
||||
placeWeather w;
|
||||
almDut d;
|
||||
if(getPlace(&p)) return -1;
|
||||
if(getWeath(&w)) return -1;
|
||||
if(getDUT(&d)) return -1;
|
||||
/* Effective wavelength (microns) */
|
||||
double wl = 0.55;
|
||||
/* ICRS to observed. */
|
||||
double aob, zob, hob, dob, rob, eo;
|
||||
/*
|
||||
DBG("iauAtco13(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)",
|
||||
p2000->ra, p2000->dec, pr, pd, px, rv, MJD.utc1, MJD.utc2, d.DUT1, p.slong, p.slat, p.salt,
|
||||
d.px, d.py, w.php, w.tc, w.relhum, wl);
|
||||
*/
|
||||
double p = 0., t = 0., h = 0.;
|
||||
if(weath){
|
||||
p = weath->pres; t = weath->tc; h = weath->relhum;
|
||||
}
|
||||
/*
|
||||
DBG("iauAtco13(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)",
|
||||
p2000->ra, p2000->dec, pr, pd, px, rv, MJD.utc1, MJD.utc2, d.DUT1, p.slong, p.slat, p.salt,
|
||||
d.px, d.py, p, t, h, wl);
|
||||
*/
|
||||
if(iauAtco13(p2000->ra, p2000->dec,
|
||||
pr, pd, px, rv,
|
||||
MJD.utc1, MJD.utc2,
|
||||
d.DUT1,
|
||||
p.slong, p.slat, p.salt,
|
||||
d.px, d.py,
|
||||
w.php, w.tc, w.relhum,
|
||||
dut1.DUT1,
|
||||
place.slong, place.slat, place.salt,
|
||||
dut1.px, dut1.py,
|
||||
p, t, h,
|
||||
wl,
|
||||
&aob, &zob,
|
||||
&hob, &dob, &rob, &eo)) return -1;
|
||||
|
||||
@ -56,10 +56,14 @@ typedef struct{
|
||||
|
||||
// place weather data
|
||||
typedef struct{
|
||||
double relhum; // rel. humidity, 0..1
|
||||
double php; // atm. pressure (hectopascales)
|
||||
double relhum; // rel. humidity, 0..100%
|
||||
double pres; // atm. pressure (mmHg)
|
||||
double tc; // temperature, degrC
|
||||
} placeWeather;
|
||||
double rain; // rain value (0..1)
|
||||
double clouds; // clouds (0 - bad, >2500 - good)
|
||||
double wind; // wind speed, m/s
|
||||
double time; // measurements time
|
||||
} localWeather;
|
||||
|
||||
// DUT/polar almanach data
|
||||
typedef struct{
|
||||
@ -68,9 +72,15 @@ typedef struct{
|
||||
double py;
|
||||
} almDut;
|
||||
|
||||
void r2sHMS(double radians, char *hms, int len);
|
||||
void r2sDMS(double radians, char *hms, int len);
|
||||
void hor2eq(horizCrds *h, polarCrds *pc, double sidTime);
|
||||
void eq2horH(polarCrds *pc, horizCrds *h);
|
||||
void eq2hor(polarCrds *pc, horizCrds *h, double sidTime);
|
||||
int get_MJDt(struct timeval *tval, sMJD *MJD);
|
||||
int get_ObsPlace(struct timeval *tval, polarCrds *p2000, polarCrds *pnow, horizCrds *hnow);
|
||||
int getDUT(almDut *a);
|
||||
int getWeath(placeWeather *w);
|
||||
int getPlace(placeData *p);
|
||||
int get_LST(sMJD *mjd, double dUT1, double slong, double *LST);
|
||||
int get_ObsPlace(struct timeval *tval, polarCrds *p2000, localWeather *weath, polarCrds *pnow, horizCrds *hnow);
|
||||
almDut *getDUT();
|
||||
localWeather *getWeath();
|
||||
placeData *getPlace();
|
||||
#endif // LIBSOFA_H__
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "emulation.h"
|
||||
#include "libsofa.h"
|
||||
#include "main.h"
|
||||
#include "socket.h"
|
||||
#include "telescope.h"
|
||||
|
||||
// daemon.c
|
||||
@ -45,9 +46,6 @@ extern void check4running(char *self, char *pidfilename, void (*iffound)(pid_t p
|
||||
// pause for incoming message waiting (out coordinates sent after that timeout)
|
||||
#define SOCK_TMOUT (1)
|
||||
|
||||
// global parameters
|
||||
static glob_pars *GP = NULL;
|
||||
|
||||
static pid_t childpid = 1; // PID of child process
|
||||
volatile int global_quit = 0;
|
||||
// quit by signal
|
||||
@ -56,12 +54,13 @@ void signals(int sig){
|
||||
if(childpid){ // parent process
|
||||
restore_tty(); // restore all parameters
|
||||
unlink(GP->pidfile); // and remove pidfile
|
||||
}
|
||||
weatherserver_disconnect();
|
||||
}
|
||||
DBG("Get signal %d, quit.\n", sig);
|
||||
global_quit = 1;
|
||||
sleep(1);
|
||||
if(childpid) putlog("PID %d exit with status %d after child's %d death", getpid(), sig, childpid);
|
||||
else WARNX("Child %d died with %d", getpid(), sig);
|
||||
sleep(1);
|
||||
exit(sig);
|
||||
}
|
||||
|
||||
@ -228,30 +227,33 @@ int proc_data(uint8_t *data, ssize_t len){
|
||||
double tagRA = RA2HRS(ra), tagDec = DEC2DEG(dec);
|
||||
DBG("RA: %u (%g), DEC: %d (%g)", ra, tagRA, dec, tagDec);
|
||||
// check RA/DEC
|
||||
horizCrds h;
|
||||
polarCrds p;
|
||||
p.ra = tagRA/12. * M_PI;
|
||||
p.dec = tagDec * DD2R;
|
||||
if(get_ObsPlace(NULL, &p, NULL, &h)){
|
||||
WARNX("Can't convert coordinates to horiz");
|
||||
horizCrds hnow; // without refraction
|
||||
polarCrds p2000, pnow;
|
||||
p2000.ra = tagRA/12. * M_PI;
|
||||
p2000.dec = tagDec * DD2R;
|
||||
// now J2000 obs Jnow
|
||||
if(get_ObsPlace(NULL, &p2000, NULL, &pnow, &hnow)){
|
||||
WARNX("Can't convert coordinates to Jnow");
|
||||
return 0;
|
||||
}
|
||||
#ifdef EBUG
|
||||
int i[4], j[4]; char pm, pm1;
|
||||
iauA2af(2, h.az, &pm, i);
|
||||
iauA2af(2, h.zd, &pm1, j);
|
||||
iauA2af(2, hnow.az, &pm, i);
|
||||
iauA2af(2, hnow.zd, &pm1, j);
|
||||
DBG("az: %c%02d %02d %02d.%2.d, zd: %c%02d %02d %02d.%2.d",
|
||||
pm, i[0],i[1],i[2],i[3],
|
||||
pm1,j[0],j[1],j[2],j[3]);
|
||||
iauA2af(2, M_PI_2 - h.zd, &pm, i);
|
||||
iauA2af(2, M_PI_2 - hnow.zd, &pm, i);
|
||||
DBG("h: %c%02d %02d %02d.%2.d", pm, i[0],i[1],i[2],i[3]);
|
||||
#endif
|
||||
if(h.zd > 80.*DD2R){
|
||||
if(hnow.zd > 80.*DD2R){
|
||||
WARNX("Z > 80degr, stop telescope");
|
||||
putlog("Z>80 - stop!");
|
||||
stop_telescope();
|
||||
return 0;
|
||||
}
|
||||
tagRA = (pnow.ra - pnow.eo) / M_PI * 12.;
|
||||
tagDec = pnow.dec / DD2R;
|
||||
if(!setCoords(tagRA, tagDec)) return 0;
|
||||
return 1;
|
||||
}
|
||||
@ -318,7 +320,7 @@ static void *hdrthread(_U_ void *buf){
|
||||
// write FITS-header at most once per second
|
||||
while(!global_quit){
|
||||
wrhdr();
|
||||
usleep(1000); // give a chance to write/read for others
|
||||
usleep(100000); // give a chance to write/read for others
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -446,6 +448,10 @@ static inline void main_proc(){
|
||||
if(pthread_create(&termthrd, NULL, termthread, NULL))
|
||||
ERR(_("Can't create terminal thread"));
|
||||
}
|
||||
// connect to weather daemon
|
||||
if(!weatherserver_connect()){
|
||||
DBG("Can't connect to weather server, will try later");
|
||||
}
|
||||
// open socket
|
||||
int sock = opensocket(GP->port);
|
||||
if(sock < 0){
|
||||
@ -488,6 +494,7 @@ int main(int argc, char **argv){
|
||||
if(GP->logfile) openlogfile(GP->logfile);
|
||||
putlog("Starting, master PID=%d", getpid());
|
||||
|
||||
#ifndef EBUG
|
||||
while(1){
|
||||
childpid = fork();
|
||||
if(childpid < 0){
|
||||
@ -506,6 +513,9 @@ int main(int argc, char **argv){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
main_proc();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "usefull_macros.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
// global parameters
|
||||
extern glob_pars *Global_parameters;
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
#include <libintl.h>// gettext
|
||||
#include <ctype.h> // isalpha
|
||||
#include "parseargs.h"
|
||||
#include "usefull_macros.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
char *helpstring = "%s\n";
|
||||
|
||||
|
||||
208
Daemons/10micron_stellarium/socket.c
Normal file
208
Daemons/10micron_stellarium/socket.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* This file is part of the StelD project.
|
||||
* Copyright 2021 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 <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "socket.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
// max time to wait answer from server
|
||||
#define WAITANSTIME (1.0)
|
||||
|
||||
static int sockfd = -1; // server file descriptor
|
||||
static pthread_t sock_thread;
|
||||
static char buf[BUFSIZ]; // buffer for messages
|
||||
static int Nread; // amount of bytes in buf
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void *getmessages(_U_ void *par);
|
||||
|
||||
/**
|
||||
* @brief weatherserver_connect - connect to a weather server
|
||||
* @return FALSE if failed
|
||||
*/
|
||||
int weatherserver_connect(){
|
||||
if(sockfd > 0) return TRUE;
|
||||
DBG("connect to %s:%d", GP->weathserver, GP->weathport);
|
||||
char port[10];
|
||||
snprintf(port, 10, "%d", GP->weathport);
|
||||
struct addrinfo hints = {0}, *res, *p;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if(getaddrinfo(GP->weathserver, port, &hints, &res) != 0){
|
||||
WARN("getaddrinfo()");
|
||||
return FALSE;
|
||||
}
|
||||
// loop through all the results and connect to the first we can
|
||||
for(p = res; p; p = p->ai_next){
|
||||
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
|
||||
WARN("socket");
|
||||
continue;
|
||||
}
|
||||
if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1){
|
||||
WARN("connect()");
|
||||
close(sockfd);
|
||||
continue;
|
||||
}
|
||||
break; // if we get here, we have a successfull connection
|
||||
}
|
||||
if(!p){
|
||||
WARNX("Can't connect to socket");
|
||||
sockfd = -1;
|
||||
return FALSE;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
if(pthread_create(&sock_thread, NULL, getmessages, NULL)){
|
||||
WARN("pthread_create()");
|
||||
weatherserver_disconnect();
|
||||
return FALSE;
|
||||
}
|
||||
DBG("connected, fd=%d", sockfd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void weatherserver_disconnect(){
|
||||
if(sockfd > -1){
|
||||
pthread_kill(sock_thread, 9);
|
||||
pthread_join(sock_thread, NULL);
|
||||
close(sockfd);
|
||||
}
|
||||
sockfd = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getparval - return value of parameter
|
||||
* @param par (i) - parameter value
|
||||
* @param ansbuf (i) - buffer with server answer
|
||||
* @param val (o) - value of parameter
|
||||
* @return TRUE if parameter found and set `val` to its value
|
||||
*/
|
||||
int getparval(const char *par, const char *ansbuf, double *val){
|
||||
if(!par || !ansbuf) return FALSE;
|
||||
int ret = FALSE;
|
||||
char *b = strdup(ansbuf);
|
||||
char *parval = NULL, *token = strtok(b, "\n");
|
||||
int l = strlen(par);
|
||||
if(!token) goto rtn;
|
||||
while(token){
|
||||
if(strncmp(token, par, l) == 0){ // found
|
||||
//DBG("token: '%s'", token);
|
||||
parval = strchr(token, '=');
|
||||
if(!parval) goto rtn;
|
||||
++parval; while(*parval == ' ' || *parval == '\t') ++parval;
|
||||
//DBG("parval: '%s'", parval);
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
token = strtok(NULL, "\n");
|
||||
}
|
||||
if(parval && val){
|
||||
*val = atof(parval);
|
||||
//DBG("Set %s to %g", par, *val);
|
||||
}
|
||||
rtn:
|
||||
FREE(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* wait for answer from socket
|
||||
* @return FALSE in case of error or timeout, TRUE if socket is ready
|
||||
*/
|
||||
static int canread(){
|
||||
if(sockfd < 0) return FALSE;
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
int rc;
|
||||
// wait not more than 10ms
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10000;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sockfd, &fds);
|
||||
do{
|
||||
rc = select(sockfd+1, &fds, NULL, NULL, &timeout);
|
||||
if(rc < 0){
|
||||
if(errno != EINTR){
|
||||
WARN("select()");
|
||||
return FALSE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}while(1);
|
||||
if(FD_ISSET(sockfd, &fds)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getmessages - continuosly read data from server and fill buffer
|
||||
*/
|
||||
static void *getmessages(_U_ void *par){
|
||||
write(sockfd, "get\n", 4);
|
||||
while(sockfd > 0){
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(Nread == 0){
|
||||
double t0 = dtime();
|
||||
while(dtime() - t0 < WAITANSTIME && Nread < BUFSIZ){
|
||||
if(!canread()) continue;
|
||||
int n = read(sockfd, buf+Nread, BUFSIZ-Nread);
|
||||
if(n == 0) break;
|
||||
if(n < 0){
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
return NULL;
|
||||
}
|
||||
Nread += n;
|
||||
}
|
||||
if(Nread){
|
||||
buf[Nread] = 0;
|
||||
//DBG("got %d: %s", Nread, buf);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if(Nread == 0){
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getweathbuffer - read whole buffer with data and set Nread to zero
|
||||
* @return NULL if no data or buffer (allocated here)
|
||||
*/
|
||||
char *getweathbuffer(){
|
||||
if(!weatherserver_connect()) return NULL; // not connected & can't connect
|
||||
char *ret = NULL;
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(Nread){
|
||||
ret = strdup(buf);
|
||||
Nread = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return ret;
|
||||
}
|
||||
28
Daemons/10micron_stellarium/socket.h
Normal file
28
Daemons/10micron_stellarium/socket.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of the StelD project.
|
||||
* Copyright 2021 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 SOCKET_H__
|
||||
#define SOCKET_H__
|
||||
|
||||
void weatherserver_disconnect();
|
||||
int weatherserver_connect();
|
||||
int getparval(const char *par, const char *ansbuf, double *val);
|
||||
char *getweathbuffer();
|
||||
|
||||
#endif // SOCKET_H__
|
||||
@ -28,7 +28,7 @@
|
||||
#include "libsofa.h"
|
||||
#include "main.h" // global_quit
|
||||
#include "telescope.h"
|
||||
#include "usefull_macros.h"
|
||||
#include "usefull_macro.h"
|
||||
|
||||
// polling timeout for answer from mount
|
||||
#ifndef T_POLLING_TMOUT
|
||||
@ -45,6 +45,12 @@ static char *hdname = NULL;
|
||||
static double ptRAdeg, ptDECdeg; // target RA/DEC J2000
|
||||
static int Target = 0; // target coordinates entered
|
||||
|
||||
static double r = 0., d = 0.; // RA/DEC from wrhdr
|
||||
static int mountstatus = 0; // return of :Gstat#
|
||||
static time_t tlast = 0; // last time coordinates were refreshed
|
||||
|
||||
static int pause_communication = 0; // ==1 to prevent writing to port outside of terminal thread
|
||||
|
||||
/**
|
||||
* read strings from terminal (ending with '\n') with timeout
|
||||
* @return NULL if nothing was read or pointer to static buffer
|
||||
@ -96,7 +102,7 @@ static char *write_cmd(const char *cmd, char *buff){
|
||||
char *ans;
|
||||
while(dtime() - t0 < T_POLLING_TMOUT){ // read answer
|
||||
if((ans = read_string())){ // parse new data
|
||||
// DBG("got answer: %s", ans);
|
||||
//DBG("got answer: %s", ans);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if(!buff) return NULL;
|
||||
strncpy(buff, ans, BUFLEN-1);
|
||||
@ -108,22 +114,24 @@ static char *write_cmd(const char *cmd, char *buff){
|
||||
}
|
||||
|
||||
// write to telescope mount corrections: datetime, pressure and temperature
|
||||
// @return 1 if time was corrected
|
||||
// @return 1 if time and weather was corrected
|
||||
static int makecorr(){
|
||||
int ret = 0;
|
||||
if(pause_communication) return 0;
|
||||
int ret = 1;
|
||||
// write current date&time
|
||||
char buf[64], ibuff[BUFLEN], *ans;
|
||||
DBG("curtime: %s", write_cmd(":GUDT#", ibuff));
|
||||
ans = write_cmd(":Gstat#", ibuff);
|
||||
if(ans){
|
||||
mountstatus = atoi(ans);
|
||||
// if system is in tracking or unknown state - don't update data!
|
||||
if(mountstatus == TEL_SLEWING || mountstatus == TEL_TRACKING) return 0;
|
||||
}
|
||||
/*
|
||||
* there's no GPS on this mount and there's no need for it!
|
||||
write_cmd(":gT#", NULL); // correct time by GPS
|
||||
ans = write_cmd(":gtg#", ibuff);
|
||||
*/
|
||||
|
||||
if(!ans || *ans == '0'){ // system is in tracking or unknown state - don't update data!
|
||||
return 0;
|
||||
}
|
||||
WARNX("Refresh datetime");
|
||||
time_t t = time(NULL);
|
||||
struct tm *stm = localtime(&t);
|
||||
@ -136,27 +144,33 @@ static int makecorr(){
|
||||
if(!ans || *ans != '1'){
|
||||
WARNX("Can't write current date/time");
|
||||
putlog("Can't set system time");
|
||||
ret = 0;
|
||||
}else{
|
||||
putlog("Set system time by command %s", buf);
|
||||
ret = 1;
|
||||
}
|
||||
DBG("curtime: %s", write_cmd(":GUDT#", ibuff));
|
||||
sprintf(buf, ":SREF0#"); // turn off 2-coord guiding & refraction
|
||||
write_cmd(buf, ibuff);
|
||||
sprintf(buf, ":Sdat0#"); // turn off dual-axis tracking
|
||||
write_cmd(buf, ibuff);
|
||||
/*placeWeather w;
|
||||
if(getWeath(&w)) putlog("Can't determine weather data");
|
||||
else{ // set refraction model data
|
||||
snprintf(buf, 64, ":SRPRS%.1f#", w.php);
|
||||
localWeather *w = getWeath();
|
||||
if(!w){
|
||||
ret = 0;
|
||||
putlog("Can't determine weather data");
|
||||
}else{ // set refraction model data
|
||||
snprintf(buf, 64, ":SRPRS%.1f#", w->pres*1013./760.);
|
||||
ans = write_cmd(buf, ibuff);
|
||||
if(!ans || *ans != '1') putlog("Can't set pressure data of refraction model");
|
||||
else putlog("Correct pressure to %g", w.php);
|
||||
snprintf(buf, 64, ":SRTMP%.1f#", w.tc);
|
||||
if(!ans || *ans != '1'){
|
||||
ret = 0;
|
||||
putlog("Can't set pressure data of refraction model");
|
||||
}else putlog("Correct pressure to %gmmHg", w->pres);
|
||||
snprintf(buf, 64, ":SRTMP%.1f#", w->tc);
|
||||
ans = write_cmd(buf, ibuff);
|
||||
if(!ans || *ans != '1') putlog("Can't set temperature data of refraction model");
|
||||
else putlog("Correct temperature to %g", w.tc);
|
||||
}*/
|
||||
if(!ans || *ans != '1'){
|
||||
ret = 0;
|
||||
putlog("Can't set temperature data of refraction model");
|
||||
}else putlog("Correct temperature to %g", w->tc);
|
||||
}
|
||||
sprintf(buf, ":SREF1#"); // turn on refraction correction
|
||||
write_cmd(buf, ibuff);
|
||||
sprintf(buf, ":Sdat1#"); // turn on dual-axis tracking
|
||||
write_cmd(buf, ibuff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -201,7 +215,8 @@ int connect_telescope(char *dev, char *hdrname){
|
||||
hdname = strdup(hdrname);
|
||||
DBG("connected");
|
||||
Target = 0;
|
||||
write_cmd(":gT#", NULL); // correct time by GPS
|
||||
getWeath(); getPlace(); getDUT(); // determine starting values
|
||||
//write_cmd(":gT#", NULL); // correct time by GPS
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -212,11 +227,15 @@ int connect_telescope(char *dev, char *hdrname){
|
||||
*/
|
||||
/**
|
||||
* send coordinates to telescope
|
||||
* @param ra - right ascention (hours)
|
||||
* @param dec - declination (degrees)
|
||||
* @param ra - right ascention (hours), Jnow without refraction
|
||||
* @param dec - declination (degrees), Jnow without refraction
|
||||
* @return 1 if all OK
|
||||
*/
|
||||
int point_telescope(double ra, double dec){
|
||||
if(pause_communication){
|
||||
putlog("Can't point telescope in paused mode");
|
||||
return 0;
|
||||
}
|
||||
DBG("try to send ra=%g, decl=%g", ra, dec);
|
||||
ptRAdeg = ra * 15.;
|
||||
ptDECdeg = dec;
|
||||
@ -322,10 +341,6 @@ static int printhdr(int fd, const char *key, const char *val, const char *cmnt){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static double r = 0., d = 0.; // RA/DEC from wrhdr
|
||||
static int mountstatus = 0; // return of :Gstat#
|
||||
static time_t tlast = 0; // last time coordinates were refreshed
|
||||
/**
|
||||
* get coordinates
|
||||
* @param ra (o) - right ascension (hours)
|
||||
@ -340,11 +355,15 @@ int get_telescope_coords(double *ra, double *decl){
|
||||
return mountstatus;
|
||||
}
|
||||
|
||||
void stop_telescope(){
|
||||
void stop_telescope(){ // work even in paused mode if moving!
|
||||
Target = 0;
|
||||
if(pause_communication){
|
||||
if(mountstatus == TEL_PARKED || mountstatus == TEL_STOPPED || mountstatus == TEL_INHIBITED
|
||||
|| mountstatus == TEL_OUTLIMIT) return;
|
||||
}
|
||||
write_cmd(":RT9#", NULL); // stop tracking
|
||||
write_cmd(":AL#", NULL); // stop tracking
|
||||
write_cmd(":STOP#", NULL); // halt moving
|
||||
Target = 0;
|
||||
}
|
||||
|
||||
// site characteristics
|
||||
@ -391,18 +410,18 @@ static void getplace(){
|
||||
}
|
||||
|
||||
static const char *statuses[12] = {
|
||||
[0] = "'Tracking'",
|
||||
[1] = "'Stopped or homing'",
|
||||
[2] = "'Slewing to park'",
|
||||
[3] = "'Unparking'",
|
||||
[4] = "'Slewing to home'",
|
||||
[5] = "'Parked'",
|
||||
[6] = "'Slewing or going to stop'",
|
||||
[7] = "'Stopped'",
|
||||
[8] = "'Motors inhibited, T too low'",
|
||||
[9] = "'Outside tracking limit'",
|
||||
[10]= "'Following satellite'",
|
||||
[11]= "'Data inconsistency'"
|
||||
[TEL_TRACKING] = "'Tracking'",
|
||||
[TEL_STOPHOM] = "'Stopped or homing'",
|
||||
[TEL_PARKING] = "'Slewing to park'",
|
||||
[TEL_UNPARKING] = "'Unparking'",
|
||||
[TEL_HOMING] = "'Slewing to home'",
|
||||
[TEL_PARKED] = "'Parked'",
|
||||
[TEL_SLEWING] = "'Slewing or going to stop'",
|
||||
[TEL_STOPPED] = "'Stopped'",
|
||||
[TEL_INHIBITED] = "'Motors inhibited, T too low'",
|
||||
[TEL_OUTLIMIT] = "'Outside tracking limit'",
|
||||
[TEL_FOLSAT]= "'Following satellite'",
|
||||
[TEL_DATINCOSIST]= "'Data inconsistency'"
|
||||
};
|
||||
|
||||
/**
|
||||
@ -412,7 +431,7 @@ static const char *statuses[12] = {
|
||||
*/
|
||||
static const char* strstatus(int status){
|
||||
if(status < 0) return "'Signal lost'";
|
||||
if(status < (int)(sizeof(statuses)/sizeof(char*)-1)) return statuses[status];
|
||||
if(status < TEL_MAXSTATUS) return statuses[status];
|
||||
if(status == 99) return "'Error'";
|
||||
return "'Unknown status'";
|
||||
}
|
||||
@ -421,9 +440,21 @@ static const char* strstatus(int status){
|
||||
* @brief wrhdr - try to write into header file
|
||||
*/
|
||||
void wrhdr(){
|
||||
static time_t commWasPaused = 0;
|
||||
if(pause_communication){ // don't allow pauses more for 15 minutes!
|
||||
if(commWasPaused == 0){
|
||||
commWasPaused = time(NULL);
|
||||
return;
|
||||
}else{
|
||||
if(time(NULL) - commWasPaused > 15*60){
|
||||
putlog("Clear communication pause after 15 minutes");
|
||||
pause_communication = 0;
|
||||
}else return;
|
||||
}
|
||||
}
|
||||
static int failcounter = 0;
|
||||
static time_t lastcorr = 0; // last time of corrections made
|
||||
if(time(NULL) - lastcorr > CORRECTIONS_TIMEDIFF){
|
||||
if(time(NULL) - lastcorr > CORRECTIONS_TIMEDIFF){ // make correction once per hour
|
||||
if(makecorr()) lastcorr = time(NULL);
|
||||
else lastcorr += 30; // failed -> check 30s later
|
||||
}
|
||||
@ -437,6 +468,7 @@ void wrhdr(){
|
||||
DBG("Can't get RA!");
|
||||
signals(9);
|
||||
}
|
||||
DBG("Failed");
|
||||
return;
|
||||
}
|
||||
ans = write_cmd(":GD#", ibuff);
|
||||
@ -446,8 +478,43 @@ void wrhdr(){
|
||||
DBG("Can't get DEC!");
|
||||
signals(9);
|
||||
}
|
||||
DBG("Failed");
|
||||
return;
|
||||
}
|
||||
almDut *dut = getDUT();
|
||||
localWeather *weather = getWeath();
|
||||
double LST = 0; // local sidereal time IN RADIANS!
|
||||
|
||||
placeData *place = getPlace();
|
||||
if(get_LST(NULL, dut->DUT1, place->slong, &LST)){
|
||||
DBG("Can't calculate coordinates, get from mount");
|
||||
ans = write_cmd(":GS#", ibuff);
|
||||
lst = dups(ans, 1);
|
||||
if(!str2coord(ans, &LST)){
|
||||
if(++failcounter == 10){
|
||||
putlog("Lost connection with mount");
|
||||
DBG("Can't get LST!");
|
||||
signals(9);
|
||||
}
|
||||
DBG("Failed");
|
||||
return;
|
||||
}
|
||||
LST *= 15.*DD2R; // convert hours to radians
|
||||
}else{
|
||||
lst = MALLOC(char, 32);
|
||||
r2sHMS(LST, lst, 32);
|
||||
}
|
||||
sMJD mjd;
|
||||
if(get_MJDt(NULL, &mjd)){
|
||||
ans = write_cmd(":GJD1#", ibuff);
|
||||
jd = dups(ans, 0);
|
||||
}else{
|
||||
jd = MALLOC(char, 32);
|
||||
snprintf(jd, 32, "%.10f", mjd.MJD);
|
||||
}
|
||||
polarCrds pNow = {.ra = r*15.*DD2R, .dec = d*DD2R}; // coordinates now
|
||||
horizCrds hNow;
|
||||
eq2hor(&pNow, &hNow, LST);
|
||||
failcounter = 0;
|
||||
tlast = time(NULL);
|
||||
// check it here, not in the beginning of function - to check connection with mount first
|
||||
@ -456,8 +523,6 @@ void wrhdr(){
|
||||
return;
|
||||
}
|
||||
if(!elevation || !longitude || !latitude) getplace();
|
||||
ans = write_cmd(":GJD1#", ibuff); jd = dups(ans, 0);
|
||||
ans = write_cmd(":GS#", ibuff); lst = dups(ans, 1);
|
||||
ans = write_cmd(":GUDT#", ibuff);
|
||||
if(ans){
|
||||
char *comma = strchr(ans, ',');
|
||||
@ -487,7 +552,13 @@ void wrhdr(){
|
||||
#define WRHDR(k, v, c) do{if(printhdr(fd, k, v, c)){goto returning;}}while(0)
|
||||
WRHDR("TIMESYS", "'UTC'", "Time system");
|
||||
WRHDR("ORIGIN", "'SAO RAS'", "Organization responsible for the data");
|
||||
WRHDR("TELESCOP", "'Astrosib-500'", "Telescope name");
|
||||
WRHDR("TELESCOP", TELESCOPE_NAME, "Telescope name");
|
||||
snprintf(val, 22, "%.10f", dut->px);
|
||||
WRHDR("POLARX", val, "IERS pole X coordinate, arcsec");
|
||||
snprintf(val, 22, "%.10f", dut->py);
|
||||
WRHDR("POLARY", val, "IERS pole Y coordinate, arcsec");
|
||||
snprintf(val, 22, "%.10f", dut->py);
|
||||
WRHDR("DUT1", val, "IERS `UT1-UTC`, sec");
|
||||
if(Target){ // target coordinates entered - store them @header
|
||||
snprintf(val, 22, "%.10f", ptRAdeg);
|
||||
WRHDR("TAGRA", val, "Target RA (J2000), degrees");
|
||||
@ -495,24 +566,47 @@ void wrhdr(){
|
||||
WRHDR("TAGDEC", val, "Target DEC (J2000), degrees");
|
||||
}
|
||||
snprintf(val, 22, "%.10f", r*15.); // convert RA to degrees
|
||||
WRHDR("RA", val, "Telescope right ascension, current epoch");
|
||||
WRHDR("RA", val, "Telescope right ascension, current epoch, deg");
|
||||
snprintf(val, 22, "%.10f", d);
|
||||
WRHDR("DEC", val, "Telescope declination, current epoch");
|
||||
WRHDR("DEC", val, "Telescope declination, current epoch, deg");
|
||||
snprintf(val, 22, "%.10f", hNow.az * DR2D);
|
||||
WRHDR("AZ", val, "Telescope azimuth, current epoch, deg");
|
||||
snprintf(val, 22, "%.10f", hNow.zd * DR2D);
|
||||
WRHDR("ZD", val, "Telescope zenith distance, current epoch, deg");
|
||||
WRHDR("TELSTAT", strstatus(mountstatus), "Telescope mount status");
|
||||
sMJD mjd;
|
||||
if(!get_MJDt(NULL, &mjd)){
|
||||
snprintf(val, 22, "%.10f", 2000.+(mjd.MJD-MJD2000)/365.25); // calculate EPOCH/EQUINOX
|
||||
WRHDR("EQUINOX", val, "Equinox of celestial coordinate system");
|
||||
snprintf(val, 22, "%.10f", mjd.MJD);
|
||||
WRHDR("MJD-END", val, "Modified julian date of observations end");
|
||||
snprintf(val, 22, "%.10f", 2000.+(mjd.MJD-MJD2000)/365.25); // calculate EPOCH/EQUINOX
|
||||
WRHDR("EQUINOX", val, "Equinox of celestial coordinate system");
|
||||
if(!jd){
|
||||
snprintf(val, 22, "%.10f", mjd.MJD);
|
||||
WRHDR("MJD-END", val, "Modified julian date of observations end");
|
||||
}
|
||||
}
|
||||
if(jd){
|
||||
WRHDR("MJD-END", jd, "Modified julian date of observations end");
|
||||
}
|
||||
if(jd) WRHDR("JD-END", jd, "Julian date of observations end");
|
||||
if(pS) WRHDR("PIERSIDE", pS, "Pier side of telescope mount");
|
||||
if(elevation) WRHDR("ELEVAT", elevation, "Elevation of site over the sea level");
|
||||
if(longitude) WRHDR("LONGITUD", longitude, "Geo longitude of site (east negative)");
|
||||
if(latitude) WRHDR("LATITUDE", latitude, "Geo latitude of site (south negative)");
|
||||
if(lst) WRHDR("LSTEND", lst, "Local sidereal time of observations end");
|
||||
if(date) WRHDR("DATE-END", date, "Date (UTC) of observations end");
|
||||
if(weather){
|
||||
snprintf(val, 22, "%.1f", weather->relhum);
|
||||
WRHDR("HUMIDITY", val, "Relative humidity, %%");
|
||||
snprintf(val, 22, "%.1f", weather->pres);
|
||||
WRHDR("PRESSURE", val, "Atmospheric pressure, mmHg");
|
||||
snprintf(val, 22, "%.1f", weather->tc);
|
||||
WRHDR("EXTTEMP", val, "External temperature, degrC");
|
||||
snprintf(val, 22, "%.0f", weather->rain);
|
||||
WRHDR("RAIN", val, "Rain conditions");
|
||||
snprintf(val, 22, "%.1f", weather->clouds);
|
||||
WRHDR("SKYQUAL", val, "Sky quality (0 - wery bad, >2500 - good)");
|
||||
snprintf(val, 22, "%.1f", weather->wind);
|
||||
WRHDR("WINDSPD", val, "Wind speed (m/s)");
|
||||
snprintf(val, 22, "%.0f", weather->time);
|
||||
WRHDR("WEATTIME", val, "Unix time of weather measurements");
|
||||
}
|
||||
// WRHDR("", , "");
|
||||
#undef WRHDR
|
||||
returning:
|
||||
@ -543,9 +637,22 @@ void *term_thread(void *sockd){
|
||||
char *ch = strchr(buff, '\n');
|
||||
if(ch) *ch = 0;
|
||||
if(!buff[0]) continue; // empty string
|
||||
DBG("%s COMMAND: %s", peerIP, buff);
|
||||
if(strcasecmp(buff, "pause") == 0){
|
||||
DBG("PAUSED");
|
||||
putlog("Port writing outside terminal thread is paused");
|
||||
pause_communication = 1;
|
||||
continue;
|
||||
}
|
||||
if(strcasecmp(buff, "continue") == 0){
|
||||
DBG("CONTINUED");
|
||||
putlog("Port writing outside terminal thread is restored by user");
|
||||
pause_communication = 0;
|
||||
continue;
|
||||
}
|
||||
char *ans = write_cmd(buff, ibuff);
|
||||
putlog("%s COMMAND %s ANSWER %s", peerIP, buff, ibuff);
|
||||
DBG("%s COMMAND: %s ANSWER: %s", peerIP, buff, ibuff);
|
||||
DBG("ANSWER: %s", ibuff);
|
||||
if(ans){
|
||||
ssize_t l = (ssize_t)strlen(ans);
|
||||
if(l++){
|
||||
|
||||
@ -29,6 +29,25 @@
|
||||
// make datetime/pressure/temperature corrections each CORRECTIONS_TIMEDIFF seconds
|
||||
#define CORRECTIONS_TIMEDIFF (3600)
|
||||
|
||||
#define TELESCOPE_NAME "'Astrosib-500 (1)'"
|
||||
|
||||
// telescope statuses
|
||||
typedef enum{
|
||||
TEL_TRACKING = 0,
|
||||
TEL_STOPHOM = 1,
|
||||
TEL_PARKING = 2,
|
||||
TEL_UNPARKING = 3,
|
||||
TEL_HOMING = 4,
|
||||
TEL_PARKED = 5,
|
||||
TEL_SLEWING = 6,
|
||||
TEL_STOPPED = 7,
|
||||
TEL_INHIBITED = 8,
|
||||
TEL_OUTLIMIT = 9,
|
||||
TEL_FOLSAT = 10,
|
||||
TEL_DATINCOSIST = 11,
|
||||
TEL_MAXSTATUS = 12 // number of statuses
|
||||
} tel_status;
|
||||
|
||||
int connect_telescope(char *dev, char *hdrname);
|
||||
int point_telescope(double ra, double decl);
|
||||
int get_telescope_coords(double *ra, double *decl);
|
||||
|
||||
@ -19,8 +19,9 @@
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usefull_macros.h"
|
||||
#include "usefull_macro.h"
|
||||
#include <linux/limits.h> // PATH_MAX
|
||||
#include <pthread.h>
|
||||
|
||||
/**
|
||||
* function for different purposes that need to know time intervals
|
||||
@ -393,49 +394,52 @@ int str2double(double *num, const char *str){
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static FILE *Flog = NULL; // log file descriptor
|
||||
static char *logname = NULL;
|
||||
// static time_t log_open_time = 0;
|
||||
/**
|
||||
* Try to open log file
|
||||
* if failed show warning message
|
||||
*/
|
||||
void openlogfile(char *name){
|
||||
if(!name){
|
||||
WARNX(_("Need filename for log file"));
|
||||
return;
|
||||
}
|
||||
green(_("Try to open log file %s in append mode\n"), name);
|
||||
fflush(stdout);
|
||||
if(!(Flog = fopen(name, "a"))){
|
||||
WARN(_("Can't open log file"));
|
||||
return;
|
||||
}
|
||||
// log_open_time = time(NULL);
|
||||
logname = name;
|
||||
}
|
||||
static pthread_mutex_t logmutex;
|
||||
|
||||
/**
|
||||
* Save message to log file, rotate logs every 24 hours
|
||||
* @brief openlogfile - create log file: init mutex, test file open ability
|
||||
* @param log - log structure
|
||||
* @return 0 if all OK
|
||||
*/
|
||||
int openlogfile(char *name){
|
||||
FREE(logname);
|
||||
pthread_mutex_destroy(&logmutex);
|
||||
FILE *logfd = fopen(name, "a");
|
||||
if(!logfd){
|
||||
WARN("Can't open log file");
|
||||
return 2;
|
||||
}
|
||||
fclose(logfd);
|
||||
if(pthread_mutex_init(&logmutex, NULL)){
|
||||
WARN("Can't init log mutes");
|
||||
return 3;
|
||||
}
|
||||
logname = strdup(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int putlog(const char *fmt, ...){
|
||||
if(!Flog) return 0;
|
||||
time_t t_now = time(NULL);
|
||||
/*if(t_now - log_open_time > 86400){ // rotate log
|
||||
fprintf(Flog, "\n\t\t%sRotate log\n", ctime(&t_now));
|
||||
fclose(Flog);
|
||||
char newname[PATH_MAX];
|
||||
snprintf(newname, PATH_MAX, "%s.old", logname);
|
||||
if(rename(logname, newname)) WARN("rename()");
|
||||
openlogfile(logname);
|
||||
if(!Flog) return 0;
|
||||
}*/
|
||||
int i = fprintf(Flog, "\n\t\t%s", ctime(&t_now));
|
||||
if(!logname) return 0;
|
||||
if(pthread_mutex_lock(&logmutex)){
|
||||
WARN("Can't lock log mutex");
|
||||
return 0;
|
||||
}
|
||||
int i = 0;
|
||||
FILE *logfd = fopen(logname, "a");
|
||||
if(!logfd) goto rtn;
|
||||
char strtm[128];
|
||||
time_t t = time(NULL);
|
||||
struct tm *curtm = localtime(&t);
|
||||
strftime(strtm, 128, "%Y/%m/%d-%H:%M:%S", curtm);
|
||||
i = fprintf(logfd, "%s\t", strtm);
|
||||
va_list ar;
|
||||
va_start(ar, fmt);
|
||||
i = vfprintf(Flog, fmt, ar);
|
||||
i += vfprintf(logfd, fmt, ar);
|
||||
va_end(ar);
|
||||
fprintf(Flog, "\n");
|
||||
fflush(Flog);
|
||||
i += fprintf(logfd, "\n");
|
||||
fclose(logfd);
|
||||
rtn:
|
||||
pthread_mutex_unlock(&logmutex);
|
||||
return i;
|
||||
}
|
||||
@ -138,7 +138,7 @@ int write_tty(const char *buff, size_t length);
|
||||
|
||||
int str2double(double *num, const char *str);
|
||||
|
||||
void openlogfile(char *name);
|
||||
int openlogfile(char *name);
|
||||
int putlog(const char *fmt, ...);
|
||||
|
||||
#endif // __USEFULL_MACROS_H__
|
||||
Loading…
x
Reference in New Issue
Block a user