diff --git a/.gitignore b/.gitignore index a931c4f..37d1ff0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,13 @@ !Makefile ![Rr][Ee][Aa][Dd][Mm][Ee] +# build dirs +mk/ +build/ +.qtc_clangd +.qtcreator + + # Prerequisites *.d @@ -30,9 +37,6 @@ *.so *.so.* -# build dirs -mk/ -build/ # diff .qtcreator/ diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/10micron_readme.koi8-r b/Daemons/deprecated/10micron_stellarium.deprecated/10micron_readme.koi8-r new file mode 100644 index 0000000..d6bf479 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/10micron_readme.koi8-r @@ -0,0 +1,58 @@ +# - очистить принимающий буфер + +:shutdown# - выключить монтировку + +:U2# - установить наивысшую точность + +Состояние гидирования (ACK): команда 0x06, ответ L/P - вкл/выкл +:AL# - выключить ведение (без ответа) +:AP# - включить + +GPS: +:gtg# - возвращает 1, если часы синхронизированы с GPS + +наведение на цель +:MS# - двигаться на цель, возврат: 0, если все в порядке, либо текст с ошибкой +:SrHH:MM:SS.SS# - установить RA цели (возврат 1 если ОК) +:SdsDD*MM:SS.S# - установить DECL цели (возврат 1 если ОК) +:D# - статус наведения, возврат: 0x7f, если в процессе, либо # +:NUDGEsXXX,sYYY# - скорректировать положение по RA/DEC на N угловых секунд +:STOP# - останов (:AP# - для возобновления гидирования) + +:Gstat# - состояние монтировки +:GT# - частота для гидирования (60.1643377745 по звездам) +:AL# - выкл. гидирование +:AP# - вкл +:Gpgc# - состояние гидирования +:GSC# - коррекция скорости гидирования на косинус h +:GTTRK# - возможно ли наведение на текущий объект +:pS# - с какой стороны монтировки телескоп (для перекладывания?) +:FLIP# - переложить монтировку + +:GVP# - название монтировки +:GTMP@# (@ - номер датчика) - температура датчика +:GREF# - состояние коррекции на рефракцию + +:GA# - высота телескопа над горизонтом +:GZ# - азимут +:GC# - дата +:GD# - склонение +:GR# - восхождение + +:GJD# - юлианская дата (GJD1 - с наивысшей точностью) +:GLDT# - местные дата и время +:GS# - звездное время + +парковка: стр. 20 + +ехать: +:Q# - прекратить наведение (а еще :Qe# - east и пр.) +:D# - состояние наведения +:NUDGEsXXXX,sYYYY# - коррекция положения на XXX/YYY секунд (RA/Dec) +:MA# - по введенным горизонтальным координатам цели +:MS# - ехать на цель +:Me$=#, :Mw#, :Mn#, :Ms# - движение в данную сторону +:MeXXX#, :MnXXX# и др. стороны - коррекция на XXX миллисекунд скорости гида + +модель наведения - стр. 44 +после определения центра изображения ввести его командами :Sr# и :Sd# и добавить точку командой :CMS# diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.cflags b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.cflags new file mode 100644 index 0000000..68d5165 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.config b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.config new file mode 100644 index 0000000..e3e2368 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.config @@ -0,0 +1,3 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define EBUG 1 diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator @@ -0,0 +1 @@ +[General] diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user new file mode 100644 index 0000000..1eea4a5 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user @@ -0,0 +1,220 @@ + + + + + + EnvironmentId + {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + true + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + true + 0 + 80 + true + true + 1 + 0 + false + false + false + 1 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + true + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 4 + true + + + + true + + 0 + + + + ProjectExplorer.Project.Target.0 + + Desktop + true + Desktop + Desktop + {91347f2c-5221-46a7-80b1-0a054ca02f79} + 0 + 0 + 0 + + /home/eddy/Docs/SAO/10micron/C-sources/10micron_stellarium.deprecated + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Default + GenericProjectManager.GenericBuildConfiguration + 0 + 0 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + + true + true + %{RunConfig:Executable:Path} + + 1 + + 1 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + + true + true + %{RunConfig:Executable:Path} + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + Version + 22 + + diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user.7bd84e3.22 b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user.7bd84e3.22 new file mode 100644 index 0000000..c61e2e6 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user.7bd84e3.22 @@ -0,0 +1,165 @@ + + + + + + EnvironmentId + {7bd84e39-ca37-46d3-be9d-99ebea85bc0d} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + false + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + /tmp/astrosib/Doc/C-sources/10micron_stellarium + + + + all + + false + + + false + true + п║п╠п╬я─п╨п╟ + + GenericProjectManager.GenericMakeStep + + 1 + п║п╠п╬я─п╨п╟ + + ProjectExplorer.BuildSteps.Build + + + + + clean + + false + + + false + true + п║п╠п╬я─п╨п╟ + + GenericProjectManager.GenericMakeStep + + 1 + п·я┤п╦я│я┌п╨п╟ + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + п÷п╬ я┐п╪п╬п╩я┤п╟п╫п╦я▌ + п÷п╬ я┐п╪п╬п╩я┤п╟п╫п╦я▌ + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + п═п╟п╥п╡я▒я─я┌я▀п╡п╟п╫п╦п╣ + + ProjectExplorer.BuildSteps.Deploy + + 1 + п п╬п╫я└п╦пЁя┐я─п╟я├п╦я▐ я─п╟п╥п╡я▒я─я┌я▀п╡п╟п╫п╦я▐ + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + + п·я│п╬п╠п╟я▐ п©я─п╬пЁя─п╟п╪п╪п╟ + + ProjectExplorer.CustomExecutableRunConfiguration + + 3768 + false + true + false + false + true + + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user.cf63021.4.9-pre1 b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user.cf63021.4.9-pre1 new file mode 100644 index 0000000..0781e9a --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.creator.user.cf63021.4.9-pre1 @@ -0,0 +1,167 @@ + + + + + + EnvironmentId + {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + false + false + 1 + true + true + 0 + 8 + true + 2 + true + true + true + true + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {91347f2c-5221-46a7-80b1-0a054ca02f79} + 0 + 0 + 0 + + /tmp/as/Doc/C-sources/10micron_stellarium + + + + all + + false + + + false + true + п║п╠п╬я─п╨п╟ + + GenericProjectManager.GenericMakeStep + + 1 + п║п╠п╬я─п╨п╟ + + ProjectExplorer.BuildSteps.Build + + + + + clean + + false + + + false + true + п║п╠п╬я─п╨п╟ + + GenericProjectManager.GenericMakeStep + + 1 + п·я┤п╦я│я┌п╨п╟ + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + п÷п╬ я┐п╪п╬п╩я┤п╟п╫п╦я▌ + п÷п╬ я┐п╪п╬п╩я┤п╟п╫п╦я▌ + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + пёя│я┌п╟п╫п╬п╡п╨п╟ + + ProjectExplorer.BuildSteps.Deploy + + 1 + п п╬п╫я└п╦пЁя┐я─п╟я├п╦я▐ я┐я│я┌п╟п╫п╬п╡п╨п╦ + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + 2 + + + п·я│п╬п╠п╟я▐ п©я─п╬пЁя─п╟п╪п╪п╟ + + ProjectExplorer.CustomExecutableRunConfiguration + + 3768 + false + true + false + false + true + + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 20 + + + Version + 20 + + diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.cxxflags b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.files b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.files new file mode 100644 index 0000000..8528303 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.files @@ -0,0 +1,14 @@ +cmdlnopts.c +cmdlnopts.h +daemon.c +emulation.c +emulation.h +libsofa.c +libsofa.h +main.c +main.h +socket.c +socket.h +telescope.c +telescope.h +usefull_macro.c diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/StelD.includes b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.includes new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/StelD.includes @@ -0,0 +1 @@ +. diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/cmdlnopts.c b/Daemons/deprecated/10micron_stellarium.deprecated/cmdlnopts.c new file mode 100644 index 0000000..ba847cc --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/cmdlnopts.c @@ -0,0 +1,110 @@ +/* geany_encoding=koi8-r + * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include + +#include "cmdlnopts.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" +// weather server port and name +#define DEFAULT_WSPORT (12345) +#define DEFAULT_WSNAME "robometeo.sao.ru" +// default PID filename: +#define DEFAULT_PIDFILE "/tmp/stellariumdaemon.pid" +// default file with headers +#define DEFAULT_FITSHDR "/tmp/10micron.fitsheader" + +// DEFAULTS +// default global parameters +glob_pars const Gdefault = { + .device = DEFAULT_COMDEV, + .port = DEFAULT_PORT, + .dbgport = DEFAULT_DBGPORT, + .pidfile = DEFAULT_PIDFILE, + .crdsfile = DEFAULT_FITSHDR, + .emulation = 0, + .weathserver = DEFAULT_WSNAME, + .weathport = DEFAULT_WSPORT, + .logfile = NULL // don't save logs +}; + +/* + * Define command line options by filling structure: + * name has_arg flag val type argptr help +*/ +sl_option_t cmdlnopts[] = { +// common options + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, + {"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), _("serial device name (default: " DEFAULT_COMDEV ")")}, + {"emulation",NO_ARGS, NULL, 'e', arg_int, APTR(&G.emulation), _("run in emulation mode")}, + //{"hostname",NEED_ARG, NULL, 'H', arg_string, APTR(&G.hostname), _("hostname to connect (default: localhost)")}, + {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("file to save logs")}, + {"hdrfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.crdsfile), _("file to save FITS-header with coordinates and time")}, + {"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")}, + {"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("port to connect (default: " DEFAULT_PORT ")")}, + {"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 +}; + +/** + * Parse command line options and return dynamically allocated structure + * to global parameters + * @param argc - copy of argc from main + * @param argv - copy of argv from main + * @return allocated structure with global parameters + */ +glob_pars *parse_args(int argc, char **argv){ + int i; + void *ptr; + ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); + size_t hlen = 1024; + char helpstring[1024], *hptr = helpstring; + snprintf(hptr, hlen, "Usage: %%s [args]\n\n\tWhere args are:\n"); + // format of help: "Usage: progname [args]\n" + sl_helpstring(helpstring); + // parse arguments + sl_parseargs(&argc, &argv, cmdlnopts); + if(help) sl_showhelp(-1, cmdlnopts); + if(argc > 0){ + G.rest_pars_num = argc; + G.rest_pars = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; +} + diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/cmdlnopts.h b/Daemons/deprecated/10micron_stellarium.deprecated/cmdlnopts.h new file mode 100644 index 0000000..b4a6abd --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/cmdlnopts.h @@ -0,0 +1,44 @@ +/* geany_encoding=koi8-r + * cmdlnopts.h - comand line options for parceargs + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once + +/* + * here are some typedef's for global data + */ +typedef struct{ + char *device; // serial device name + char *port; // port to connect + char *dbgport; // port for debug console + 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); diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/daemon.c b/Daemons/deprecated/10micron_stellarium.deprecated/daemon.c new file mode 100644 index 0000000..fbb6200 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/daemon.c @@ -0,0 +1,144 @@ +/* + * daemon.c - functions for running in background like a daemon + * + * Copyright 2013 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#define PROC_BASE "/proc" + +#include // printf, fopen, ... +#include // getpid +#include // perror +#include // opendir +#include // opendir +#include // stat +#include // fcntl +#include // exit +#include // memset + +/** + * read process name from /proc/PID/cmdline + * @param pid - PID of interesting process + * @return filename or NULL if not found + * don't use this function twice for different names without copying + * its returning by strdup, because `name` contains in static array + */ +char *readname(pid_t pid){ + static char name[256]; + char *pp = name, byte, path[256]; + FILE *file; + int cntr = 0; + size_t sz; + snprintf (path, 255, PROC_BASE "/%d/cmdline", pid); + file = fopen(path, "r"); + if(!file) return NULL; // there's no such file + do{ // read basename + sz = fread(&byte, 1, 1, file); + if(sz != 1) break; + if(byte != '/') *pp++ = byte; + else{ + pp = name; + cntr = 0; + } + }while(byte && cntr++ < 255); + name[cntr] = 0; + fclose(file); + return name; +} + +void iffound_default(pid_t pid){ + fprintf(stderr, "\nFound running process (pid=%d), exit.\n", pid); + exit(0); +} + +/** + * check wether there is a same running process + * exit if there is a running process or error + * Checking have 3 steps: + * 1) lock executable file + * 2) check pidfile (if you run a copy?) + * 3) check /proc for executables with the same name (no/wrong pidfile) + * @param selfname - argv[0] or NULL for non-locking + * @param pidfilename - name of pidfile or NULL if none + * @param iffound - action to run if file found or NULL for exit(0) + */ +void check4running(char *selfname, char *pidfilename, void (*iffound)(pid_t pid)){ + DIR *dir; + FILE *pidfile, *fself; + struct dirent *de; + struct stat s_buf; + pid_t pid = 0, self; + struct flock fl; + char *name, *myname; + if(!iffound) iffound = iffound_default; + if(selfname){ // block self + fself = fopen(selfname, "r"); // open self binary to lock + if(!fself){ + perror("fopen"); + goto selfpid; + } + memset(&fl, 0, sizeof(struct flock)); + fl.l_type = F_WRLCK; + if(fcntl(fileno(fself), F_GETLK, &fl) == -1){ // check locking + perror("fcntl"); + goto selfpid; + } + if(fl.l_type != F_UNLCK){ // file is locking - exit + printf("Found locker, PID = %d!\n", fl.l_pid); + exit(1); + } + fl.l_type = F_RDLCK; + if(fcntl(fileno(fself), F_SETLKW, &fl) == -1){ + perror("fcntl"); + } + } + selfpid: + self = getpid(); // get self PID + if(!(dir = opendir(PROC_BASE))){ // open /proc directory + perror(PROC_BASE); + } + if(!(name = readname(self))){ // error reading self name + perror("Can't read self name"); + exit(1); + } + myname = strdup(name); + if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists + pidfile = fopen(pidfilename, "r"); + if(pidfile){ + if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process + if((name = readname(pid)) && strncmp(name, myname, 255) == 0) + iffound(pid); + } + fclose(pidfile); + } + } + // There is no pidfile or it consists a wrong record + while((de = readdir(dir))){ // scan /proc + if(!(pid = (pid_t)atoi(de->d_name)) || pid == self) // pass non-PID files and self + continue; + if((name = readname(pid)) && strncmp(name, myname, 255) == 0) + iffound(pid); + } + closedir(dir); + if(pidfilename){ + pidfile = fopen(pidfilename, "w"); + fprintf(pidfile, "%d\n", self); // write self PID to pidfile + fclose(pidfile); + } + free(myname); +} diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/emulation.c b/Daemons/deprecated/10micron_stellarium.deprecated/emulation.c new file mode 100644 index 0000000..3be9bbe --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/emulation.c @@ -0,0 +1,106 @@ +/* + * geany_encoding=koi8-r + * emulation.c + * + * Copyright 2018 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include + +#include "math.h" +#include "emulation.h" + + +// emulation speed over RA & DEC (0.5 degr per sec) +#define RA_SPEED (0.033) +#define DECL_SPEED (0.5) + +// current coordinates +static double RA = 0., DECL = 0.; +// target coordinates +static double RAtarg = 0., DECLtarg = 0.; +// coordinates @ guiding start +static double RA0 = 0., DECL0 = 0.; +static double raspeed = 0.; +// ==1 if pointing +static int pointing = 0; +// pointing start time +static double tstart = -1.; + +/** + * send coordinates to telescope emulation + * @param ra - right ascention (hours) + * @param decl - declination (degrees) + * @return 1 if all OK + */ +int point_emulation(double ra, double decl){ + DBG("(emul) Send ra=%g, decl=%g", ra, decl); + LOGMSG("(emul) Send ra=%g, decl=%g", ra, decl); + RAtarg = ra; DECLtarg = decl; + RA0 = RA; DECL0 = DECL; + raspeed = (RAtarg > RA) ? RA_SPEED : -RA_SPEED; + if(fabs(RAtarg - RA) > 12.){ // go to opposite direction + raspeed = -raspeed; + } + tstart = sl_dtime(); + pointing = 1; + return 0; +} + +static double getradiff(){ + double diff = RAtarg - RA; + if(raspeed < 0.) diff = -diff; + if(diff > 12.) diff -= 24.; + else if(diff < -12.) diff += 24.; + return fabs(diff); +} + +/** + * get coordinates (emulation) + * @return 1 if all OK + */ +int get_emul_coords(double *ra, double *decl){ + if(pointing){ + DBG("RA/DEC: targ: %g/%g, cur: %g/%g, start: %g/%g", RAtarg, DECLtarg, RA, DECL, RA0, DECL0); + // diff < speed? stop + if((fabs(RAtarg - RA) < RA_SPEED && fabs(DECLtarg - DECL) < DECL_SPEED)){ + RA = RAtarg; + DECL = DECLtarg; + pointing = 0; // guiding + DBG("@ target"); + }else{ // calculate new coordinates + double radiff = getradiff(), decldiff = fabs(DECLtarg - DECL); + double tdiff = sl_dtime() - tstart; + RA = RA0 + raspeed * tdiff; + DBG("RA=%g", RA); + if(getradiff() > radiff) RA = RAtarg; + DBG("RA=%g", RA); + if(RA < 0.) RA += 24.; + else if(RA > 24.) RA -= 24.; + DBG("RA=%g", RA); + double sign = (DECLtarg > DECL) ? 1. : -1.; + DECL = DECL0 + sign * DECL_SPEED * tdiff; + if(fabs(DECLtarg - DECL) > decldiff) DECL = DECLtarg; + DBG("RA/DEC: targ: %g/%g, cur: %g/%g, start: %g/%g", RAtarg, DECLtarg, RA, DECL, RA0, DECL0); + } + } + if(ra) *ra = RA; + if(decl) *decl = DECL; + return 1; +} diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/emulation.h b/Daemons/deprecated/10micron_stellarium.deprecated/emulation.h new file mode 100644 index 0000000..16a45d1 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/emulation.h @@ -0,0 +1,28 @@ +/* + * geany_encoding=koi8-r + * emulation.h + * + * Copyright 2018 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once + + +int point_emulation(double ra, double decl); +int get_emul_coords(double *ra, double *decl); + diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/libsofa.c b/Daemons/deprecated/10micron_stellarium.deprecated/libsofa.c new file mode 100644 index 0000000..b9c3913 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/libsofa.c @@ -0,0 +1,383 @@ +/* + * This file is part of the StelD project. + * Copyright 2020 Edward V. Emelianov . + * + * 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 . + */ + +#include +#include +#include + +#include "libsofa.h" +#include "socket.h" + + +#ifdef EBUG +void reprd(char* s, double ra, double dc){ + char pm; + int i[4]; + printf ( "%s:", s ); + eraA2tf ( 7, ra, &pm, i ); + printf ( " %2.2d %2.2d %2.2d.%7.7d", i[0],i[1],i[2],i[3] ); + eraA2af ( 6, dc, &pm, i ); + printf ( " %c%2.2d %2.2d %2.2d.%6.6d\n", pm, i[0],i[1],i[2],i[3] ); +} +void radtodeg(double r){ + int i[4]; char pm; + int rem = (int)(r / ERFA_D2PI); + if(rem) r -= ERFA_D2PI * rem; + if(r > ERFA_DPI) r -= ERFA_D2PI; + else if(r < -ERFA_DPI) r += ERFA_D2PI; + eraA2af (2, r, &pm, i); + printf("%c%02d %02d %02d.%2.d", pm, i[0],i[1],i[2],i[3]); +} +#define REP(a,b,c) reprd(a,b,c) +#else +#define REP(a,b,c) +#endif + +// 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; +} + +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; +} +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]; + eraA2tf(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]; + eraA2af(1, radians, &pm, i); + snprintf(dms, len, "'%c%02d:%02d:%02d.%d'", pm, i[0],i[1],i[2],i[3]); +} + +/** + * @brief get_MJDt - calculate MJD of date from argument + * @param tval (i) - given date (or NULL for current) + * @param MJD (o) - time (or NULL just to check) + * @return 0 if all OK + */ +int get_MJDt(struct timeval *tval, sMJD *MJD){ + struct tm tms; + double tSeconds; + if(!tval){ + //DBG("MJD for current time"); + struct timeval currentTime; + gettimeofday(¤tTime, NULL); + gmtime_r(¤tTime.tv_sec, &tms); + tSeconds = tms.tm_sec + ((double)currentTime.tv_usec)/1e6; + }else{ + gmtime_r(&tval->tv_sec, &tms); + tSeconds = tms.tm_sec + ((double)tval->tv_usec)/1e6; + } + int y, m, d; + y = 1900 + tms.tm_year; + m = tms.tm_mon + 1; + d = tms.tm_mday; + double utc1, utc2; + /* UTC date. */ + if(eraDtf2d("UTC", y, m, d, tms.tm_hour, tms.tm_min, tSeconds, &utc1, &utc2) < 0) return -1; + if(!MJD) return 0; + MJD->MJD = utc1 - 2400000.5 + utc2; + MJD->utc1 = utc1; + MJD->utc2 = utc2; + //DBG("UTC(m): %g, %.8f\n", utc1 - 2400000.5, utc2); + if(eraUtctai(utc1, utc2, &MJD->tai1, &MJD->tai2)) return -1; + //DBG("TAI"); + if(eraTaitt(MJD->tai1, MJD->tai2, &MJD->tt1, &MJD->tt2)) return -1; + //DBG("TT"); + 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(eraUtcut1(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 = eraGst06a(ut11, ut12, Mjd.tt1, Mjd.tt2); + ST += slong; + if(ST > ERFA_D2PI) ST -= ERFA_D2PI; + else if(ST < 0.) ST += ERFA_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(); + eraAe2hd(h->az, ERFA_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; + eraHd2ae(pc->ha, pc->dec, p->slat, &h->az, &alt); + h->zd = ERFA_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; + eraHd2ae(ha, pc->dec, p->slat, &h->az, &alt); + h->zd = ERFA_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, 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) + double rv = 0.0; // radial velocity (km/s, positive if receding) + sMJD MJD; + if(get_MJDt(tval, &MJD)) return -1; + if(!p2000) return -1; + /* Effective wavelength (microns) */ + double wl = 0.55; + /* ICRS to observed. */ + double aob, zob, hob, dob, rob, eo; + 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(eraAtco13(p2000->ra, p2000->dec, + pr, pd, px, rv, + MJD.utc1, MJD.utc2, + dut1.DUT1, + place.slong, place.slat, place.salt, + dut1.px, dut1.py, + p, t, h, + wl, + &aob, &zob, + &hob, &dob, &rob, &eo)) return -1; + REP("ICRS->observed", rob, dob); + if(pnow){ + pnow->eo = eo; + pnow->ha = hob; + pnow->ra = rob; + pnow->dec = dob; + } + if(hnow){ + hnow->az = aob; + hnow->zd = zob; + } +#ifdef EBUG + printf("A(bta)/Z: "); + radtodeg(aob); + printf("("); radtodeg(ERFA_DPI-aob); + printf(")/"); radtodeg(zob); + printf("\n"); +#endif + return 0; +} + +// azimuth: north=zero, east=90deg + +// parallactic angle: iauHd2pa ( ha, dec, phi ); + +// refraction coefficients: iauRefco + +// iauAe2hd ( az, el, phi, &ha, &dec ); A,H -> HA,DEC; phi - site latitude +// iauHd2ae ( ha, dec, phi, &az, &el ); HA,DEC -> A,H + +// iauAtoc13 - obs->ICRS(catalog) +// iauAtoi13 - obs->CIRS + +// iauAtio13 - CIRS->observed + +#if 0 +/** + * convert geocentric coordinates (nowadays, CIRS) to mean (JD2000, ICRS) + * appRA, appDecl in seconds + * r, d in seconds + */ +void JnowtoJ2000(double appRA, double appDecl, double *r, double *dc){ + double ra=0., dec=0., utc1, utc2, tai1, tai2, tt1, tt2, fd, eo, ri; + int y, m, d, H, M; + DBG("appRa: %g'', appDecl'': %g", appRA, appDecl); + appRA *= DS2R; + appDecl *= DAS2R; +#define SOFA(f, ...) do{if(f(__VA_ARGS__)){WARNX("Error in " #f); goto rtn;}}while(0) + // 1. convert system JDate to UTC + SOFA(iauJd2cal, JDate, 0., &y, &m, &d, &fd); + fd *= 24.; + H = (int)fd; + fd = (fd - H)*60.; + M = (int)fd; + fd = (fd - M)*60.; + SOFA(iauDtf2d, "UTC", y, m, d, H, M, fd, &utc1, &utc2); + SOFA(iauUtctai, utc1, utc2, &tai1, &tai2); + SOFA(iauTaitt, tai1, tai2, &tt1, &tt2); + iauAtic13(appRA, appDecl, tt1, tt2, &ri, &dec, &eo); + ra = iauAnp(ri + eo); + ra *= DR2S; + dec *= DR2AS; + DBG("SOFA: r=%g'', d=%g''", ra, dec); +#undef SOFA +rtn: + if(r) *r = ra; + if(dc) *dc = dec; +} + +/** + * @brief J2000toJnow - convert ra/dec between epochs + * @param in - J2000 (degrees) + * @param out - Jnow (degrees) + * @return + */ +int J2000toJnow(const polar *in, polar *out){ + if(!out) return 1; + double utc1, utc2; + time_t tsec; + struct tm *ts; + tsec = time(0); // number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) + ts = gmtime(&tsec); + int result = 0; + result = iauDtf2d ( "UTC", ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, &utc1, &utc2 ); + if (result != 0) { + fprintf(stderr, "iauDtf2d call failed\n"); + return 1; + } + // Make TT julian date for Atci13 call + double tai1, tai2; + double tt1, tt2; + result = iauUtctai(utc1, utc2, &tai1, &tai2); + if(result){ + fprintf(stderr, "iauUtctai call failed\n"); + return 1; + } + result = iauTaitt(tai1, tai2, &tt1, &tt2); + if(result){ + fprintf(stderr, "iauTaitt call failed\n"); + return 1; + } + 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) + double rv = 0.0; // radial velocity (km/s, positive if receding) + double rc = DD2R * in->ra, dc = DD2R * in->dec; // convert into radians + double ri, di, eo; + iauAtci13(rc, dc, pr, pd, px, rv, tt1, tt2, &ri, &di, &eo); + out->ra = iauAnp(ri - eo) * DR2D; + out->dec = di * DR2D; + return 0; +} +#endif diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/libsofa.h b/Daemons/deprecated/10micron_stellarium.deprecated/libsofa.h new file mode 100644 index 0000000..ff659b0 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/libsofa.h @@ -0,0 +1,84 @@ +/* + * This file is part of the StelD project. + * Copyright 2020 Edward V. Emelianov . + * + * 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 . + */ +#pragma once + +#include +#include +#include + +// JD2451544.5 == 2000.0 +#define MJD2000 (51544) + +typedef struct{ + double utc1; double utc2; // UTC JD, commonly used MJD = utc1+utc2-2400000.5 + double MJD; + double tai1; double tai2; // TAI JD + double tt1; double tt2; // TT JD +} sMJD; + +// polar coordinates & equation of origins (all in radians) +typedef struct{ + double ha; // hour angle + double dec; // declination + double ra; // right ascension + double eo; // equation of origins +} polarCrds; + +// horizontal coordinates (all in radians) +typedef struct{ + double az; // azimuth, 0 @ south, positive clockwise + double zd; // zenith distance +} horizCrds; + +// observational place coordinates and altitude; all coordinates are in radians! +typedef struct{ + double slong; // longitude + double slat; // lattitude + double salt; // altitude, m +} placeData; + +// place weather data +typedef struct{ + double relhum; // rel. humidity, 0..100% + double pres; // atm. pressure (mmHg) + double tc; // temperature, degrC + 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{ + double DUT1; // UT1-UTC, sec + double px; // polar coordinates, arcsec + 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_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(); + diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/main.c b/Daemons/deprecated/10micron_stellarium.deprecated/main.c new file mode 100644 index 0000000..80556ab --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/main.c @@ -0,0 +1,522 @@ +/* + * main.c + * + * Copyright 2014 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "emulation.h" +#include "libsofa.h" +#include "main.h" +#include "socket.h" +#include "telescope.h" + +// daemon.c +extern void check4running(char *self, char *pidfilename, void (*iffound)(pid_t pid)); + +// Max amount of connections +#define BACKLOG (10) +#define BUFLEN (1024) +// pause for incoming message waiting (out coordinates sent after that timeout) +#define SOCK_TMOUT (1) + +static pid_t childpid = 1; // PID of child process +volatile int global_quit = 0; +// quit by signal +void signals(int sig){ + signal(sig, SIG_IGN); + if(!childpid){ // child process + stop_telescope(); + disconnect_telescope(); + unlink(GP->pidfile); // and remove pidfile + weatherserver_disconnect(); + } + DBG("Get signal %d, quit.\n", sig); + global_quit = 1; + if(childpid) LOGERR("PID %d exit with status %d after child's %d death", getpid(), sig, childpid); + else LOGWARN("Child %d died with %d", getpid(), sig); + sleep(1); + exit(sig); +} + +// search a first word after needle without spaces +char* stringscan(char *str, char *needle){ + char *a, *e; + char *end = str + strlen(str); + a = strstr(str, needle); + if(!a) return NULL; + a += strlen(needle); + while (a < end && (*a == ' ' || *a == '\r' || *a == '\t')) a++; + if(a >= end) return NULL; + e = strchr(a, ' '); + if(e) *e = 0; + return a; +} + +/** + * Send data to user + * @param data - data to send + * @param dlen - data length + * @param sockfd - socket fd for sending data + * @return 0 if failed + */ +int send_data(uint8_t *data, size_t dlen, int sockfd){ + size_t sent = write(sockfd, data, dlen); + if(sent != dlen){ + WARN("write()"); + return 0; + } + return 1; +} + +//read: 0x14 0x0 0x0 0x0 0x5b 0x5a 0x2e 0xc6 0x8c 0x23 0x5 0x0 0x23 0x9 0xe5 0xaf 0x23 0x2e 0x34 0xed +// command: goto 16h29 24.45 -26d25 55.62 +/* + LITTLE-ENDIAN!!! + from client: +LENGTH (2 bytes, integer): length of the message +TYPE (2 bytes, integer): 0 +TIME (8 bytes, integer): current time on the server computer in microseconds + since 1970.01.01 UT. Currently unused. +RA (4 bytes, unsigned integer): right ascension of the telescope (J2000) + a value of 0x100000000 = 0x0 means 24h=0h, + a value of 0x80000000 means 12h +DEC (4 bytes, signed integer): declination of the telescope (J2000) + a value of -0x40000000 means -90degrees, + a value of 0x0 means 0degrees, + a value of 0x40000000 means 90degrees + +to client: +LENGTH (2 bytes, integer): length of the message +TYPE (2 bytes, integer): 0 +TIME (8 bytes, integer): current time on the server computer in microseconds + since 1970.01.01 UT. Currently unused. +RA (4 bytes, unsigned integer): right ascension of the telescope (J2000) + a value of 0x100000000 = 0x0 means 24h=0h, + a value of 0x80000000 means 12h +DEC (4 bytes, signed integer): declination of the telescope (J2000) + a value of -0x40000000 means -90degrees, + a value of 0x0 means 0degrees, + a value of 0x40000000 means 90degrees +STATUS (4 bytes, signed integer): status of the telescope, currently unused. + status=0 means ok, status<0 means some error +*/ + +#define DEG2DEC(degr) ((int32_t)(degr / 90. * ((double)0x40000000))) +#define HRS2RA(hrs) ((uint32_t)(hrs / 12. * ((double)0x80000000))) +#define DEC2DEG(i32) (((double)i32)*90./((double)0x40000000)) +#define RA2HRS(u32) (((double)u32)*12. /((double)0x80000000)) + +typedef struct __attribute__((__packed__)){ + uint16_t len; + uint16_t type; + uint64_t time; + uint32_t ra; + int32_t dec; +} indata; + +typedef struct __attribute__((__packed__)){ + uint16_t len; + uint16_t type; + uint64_t time; + uint32_t ra; + int32_t dec; + int32_t status; +} outdata; + +/** + * convert RA/DEC to string in forman RA: HH:MM:SS.SS, DEC: DD:MM:SS.S + */ +char *radec2str(double ra, double dec){ + static char buf[1024]; + char sign = '+'; + if(dec < 0){ + sign = '-'; + dec = -dec; + } + + int h = (int)ra; + ra -= h; ra *= 60.; + int m = (int)ra; + ra -= m; ra *= 60.; + + int d = (int) dec; + dec -= d; dec *= 60.; + int dm = (int)dec; + dec -= dm; dec *= 60.; + snprintf(buf, 1024, "%d:%d:%.2f %c%d:%d:%.1f", h,m,ra, sign,d,dm,dec); + return buf; +} + +/** + * send input RA/Decl (j2000!) coordinates to tel + * ra in hours (0..24), decl in degrees (-90..90) + * @return 1 if all OK + */ +int setCoords(double ra, double dec){ + char *radec = radec2str(ra, dec); + DBG("Set RA/Decl to %s", radec); + LOGDBG("Try to set RA/Decl to %s", radec); + int (*pointfunction)(double, double) = point_telescope; + if(GP->emulation) pointfunction = point_emulation; + return pointfunction(ra, dec); +} + +/** + * @brief proc_data - process data received from Stellarium + * @param data - raw data + * @param len - its length + * @return 1 if all OK + */ +int proc_data(uint8_t *data, ssize_t len){ + FNAME(); + if(len != sizeof(indata)){ + WARNX("Bad data size: got %zd instead of %zd!", len, sizeof(indata)); + return 0; + } + indata *dat = (indata*)data; + uint16_t L, T; + //uint64_t tim; + uint32_t ra; + int32_t dec; +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + L = le16toh(dat->len); T = le16toh(dat->type); + //tim = le64toh(dat->time); + ra = le32toh(dat->ra); + dec = (int32_t)le32toh((uint32_t)dat->dec); +#else + L = dat->len; T = dat->type; + //tim = dat->time; + ra = dat->ra; dec = dat->dec; +#endif + DBG("got message with len %u & type %u", L, T); + if(L != len){ + WARNX("Length of message != msg->len"); + return 0; + } + if(T){ + WARNX("Wrong message type"); + return 0; + } + // convert RA/DEC to hours/degrees + double tagRA = RA2HRS(ra), tagDec = DEC2DEG(dec); + DBG("RA: %u (%g), DEC: %d (%g)", ra, tagRA, dec, tagDec); + // check RA/DEC + horizCrds hnow; // without refraction + polarCrds p2000, pnow; + p2000.ra = tagRA/12. * M_PI; + p2000.dec = tagDec * ERFA_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; + eraA2af(2, hnow.az, &pm, i); + eraA2af(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]); + eraA2af(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(hnow.zd > 80.*ERFA_DD2R){ + WARNX("Z > 80degr, stop telescope"); + LOGWARN("Z>80 - stop!"); + stop_telescope(); + return 0; + } + tagRA = (pnow.ra - pnow.eo) / M_PI * 12.; + tagDec = pnow.dec / ERFA_DD2R; + if(!setCoords(tagRA, tagDec)) return 0; + return 1; +} + +/** + * main socket service procedure + */ +void *handle_socket(void *sockd){ + FNAME(); + if(global_quit) return NULL; + outdata dout; + int sock = *(int*)sockd; + dout.len = htole16(sizeof(outdata)); + dout.type = 0; + int (*getcoords)(double*, double*) = get_telescope_coords; + if(GP->emulation) getcoords = get_emul_coords; + while(!global_quit){ + // get coordinates + double RA = 0., Decl = 0.; + if((dout.status = getcoords(&RA, &Decl)) < 0){ + WARNX("Error: can't get coordinates"); + sleep(1); + continue; + } + //DBG("got : %g/%g", RA, Decl); + dout.ra = htole32(HRS2RA(RA)); + dout.dec = (int32_t)htole32(DEG2DEC(Decl)); + if(!send_data((uint8_t*)&dout, sizeof(outdata), sock)) break; + //DBG("sent ra = %g, dec = %g", RA2HRS(dout.ra), DEC2DEG(dout.dec)); + fd_set readfds; + struct timeval timeout; + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + timeout.tv_sec = SOCK_TMOUT; // wait not more than SOCK_TMOUT second + timeout.tv_usec = 0; + int sel = select(sock + 1 , &readfds , NULL , NULL , &timeout); + if(sel < 0){ + if(errno != EINTR) + WARN("select()"); + continue; + } + if(!(FD_ISSET(sock, &readfds))) continue; + // fill incoming buffer + uint8_t buff[BUFLEN+1]; + ssize_t rd = read(sock, buff, BUFLEN); + buff[rd] = 0; + DBG("read %zd (%s)", rd, buff); + if(rd <= 0){ // error or disconnect + DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); + break; + } + /************************************** + * DO SOMETHING WITH DATA * + **************************************/ + if(!proc_data(buff, rd)) dout.status = -1; + else dout.status = 0; + } + close(sock); + return NULL; +} + +// thread writing FITS-header file +static void *hdrthread(_U_ void *buf){ + // write FITS-header at most once per second + while(!global_quit){ + wrhdr(); + usleep(100000); // give a chance to write/read for others + } + return NULL; +} + +/** + * @brief opensocket - open socket to port `port` + * @return socket fd or <0 if failed + */ +static int opensocket(char *port){ + if(!port) return -1; + int reuseaddr = 1; + int sock; + struct addrinfo hints, *res, *p; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + DBG("try to open port %s", port); + if(getaddrinfo(NULL, port, &hints, &res) != 0){ + WARN("getaddrinfo()"); + return 0; + } + /* + struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); + */ + // loop through all the results and bind to the first we can + for(p = res; p != NULL; p = p->ai_next){ + if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ + WARN("socket()"); + continue; + } + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ + WARN("setsockopt()"); + close(sock); + continue; + } + if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ + WARN("bind()"); + close(sock); + continue; + } + break; // if we get here, we must have connected successfully + } + freeaddrinfo(res); + // Listen + if(listen(sock, BACKLOG) == -1){ + WARN("listen"); + LOGWARN("listen() error"); + } + DBG("listen at %s", port); + LOGDBG("listen at %s", port); + return sock; +} + +/** + * @brief waitconn + * @param sock - socket fd to accept() + * @param connthread - thread which to run when connection accepted (it's parameter - socket fd) + */ +static void waitconn(int sock, void *(*connthread)(void*)){ + // Main loop + while(!global_quit){ + socklen_t size = sizeof(struct sockaddr_in); + struct sockaddr_in myaddr; + int newsock; + newsock = accept(sock, (struct sockaddr*)&myaddr, &size); + if(newsock <= 0){ + WARN("accept()"); + sleep(1); + continue; + } + struct sockaddr_in peer; + socklen_t peer_len = sizeof(peer); + if(getpeername(newsock, (struct sockaddr*)&peer, &peer_len) == -1){ + WARN("getpeername()"); + close(newsock); + continue; + } + int sockport = -1; + if(getsockname(newsock, (struct sockaddr*)&peer, &peer_len) == 0){ + sockport = ntohs(peer.sin_port); + } + char *peerIP = inet_ntoa(peer.sin_addr); + LOGMSG("Got connection from %s @ %d", peerIP, sockport); + DBG("Peer's IP address is: %s (@port %d)\n", peerIP, sockport); + /*if(strcmp(peerIP, ACCEPT_IP) && strcmp(peerIP, "127.0.0.1")){ + WARNX("Wrong IP"); + close(newsock); + continue; + }*/ + pthread_t rthrd; + if(pthread_create(&rthrd, NULL, connthread, (void*)&newsock)){ + LOGERR("Error creating listen thread"); + ERR(_("Can't create socket thread")); + }else{ + DBG("Thread created, detouch"); + pthread_detach(rthrd); // don't care about thread state + } + } + close(sock); +} + +// thread working with terminal +static void *termthread(_U_ void *buf){ + int sock = opensocket(GP->dbgport); + if(sock < 0){ + LOGERR("Can't open debugging socket @ port %s", GP->dbgport); + ERRX("Can't open debug socket"); + } + waitconn(sock, term_thread); + return NULL; +} + +static inline void main_proc(){ + pthread_t hthrd, termthrd; + // connect to telescope + if(!GP->emulation){ + if(!connect_telescope(GP->device, GP->crdsfile)){ + ERRX(_("Can't connect to telescope device")); + } + if(pthread_create(&hthrd, NULL, hdrthread, NULL)) + ERR(_("Can't create writing thread")); + 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){ + LOGERR("Can't open socket @ port %s", GP->port); + ERRX("Can't open stellarium socket"); + } + waitconn(sock, handle_socket); + usleep(10000); + pthread_cancel(hthrd); // cancel reading thread + pthread_cancel(termthrd); + pthread_join(hthrd, NULL); + pthread_join(termthrd, NULL); +} + +int main(int argc, char **argv){ + GP = parse_args(argc, argv); + sl_init(); + + signal(SIGTERM, signals); // kill (-15) - quit + signal(SIGKILL, signals); // kill (-9) - quit + signal(SIGHUP, SIG_IGN); // hup - ignore + signal(SIGINT, signals); // ctrl+C - quit + signal(SIGQUIT, signals); // ctrl+\ - quit + signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z + + int fd; + if((fd = open(GP->crdsfile, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) // test FITS-header file for writing + ERR(_("Can't open %s for writing"), GP->crdsfile); + close(fd); + + printf("Daemonize\n"); +#ifndef EBUG // daemonize only in release mode + if(daemon(1, 0)){ + LOGERR("Err: daemon()"); + ERR("daemon()"); + } +#endif // EBUG + check4running((char*)__progname, GP->pidfile, NULL); + if(GP->logfile) OPENLOG(GP->logfile, LOGLEVEL_ANY, 1); + LOGMSG("Starting, master PID=%d", getpid()); + +#ifndef EBUG + while(1){ + childpid = fork(); + if(childpid < 0){ + LOGERR("fork() error"); + ERR("ERROR on fork"); + } + if(childpid){ + LOGMSG("Created child with PID %d\n", childpid); + DBG("Created child with PID %d\n", childpid); + wait(NULL); + LOGWARN("Child %d died\n", childpid); + DBG("Child %d died\n", childpid); + }else{ + prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies + main_proc(); + return 0; + } + } +#else + main_proc(); +#endif + + return 0; +} diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/main.h b/Daemons/deprecated/10micron_stellarium.deprecated/main.h new file mode 100644 index 0000000..c05624a --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/main.h @@ -0,0 +1,40 @@ +/* + * main.h + * + * Copyright 2014 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdlnopts.h" + +// global parameters +extern glob_pars *Global_parameters; +// global quit flag +extern volatile int global_quit; diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/socket.c b/Daemons/deprecated/10micron_stellarium.deprecated/socket.c new file mode 100644 index 0000000..9da4d2c --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/socket.c @@ -0,0 +1,208 @@ +/* + * This file is part of the StelD project. + * Copyright 2021 Edward V. Emelianov . + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdlnopts.h" +#include "socket.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 = sl_dtime(); + while(sl_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; +} diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/socket.h b/Daemons/deprecated/10micron_stellarium.deprecated/socket.h new file mode 100644 index 0000000..407be59 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/socket.h @@ -0,0 +1,25 @@ +/* + * This file is part of the StelD project. + * Copyright 2021 Edward V. Emelianov . + * + * 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 . + */ + +#pragma once + + +void weatherserver_disconnect(); +int weatherserver_connect(); +int getparval(const char *par, const char *ansbuf, double *val); +char *getweathbuffer(); diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/telescope.c b/Daemons/deprecated/10micron_stellarium.deprecated/telescope.c new file mode 100644 index 0000000..1caa991 --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/telescope.c @@ -0,0 +1,718 @@ +/* + * geany_encoding=koi8-r + * telescope.c + * + * Copyright 2018 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include // ntoa +#include +#include // ntoa +#include +#include +#include // getpeername +#include + +#include "libsofa.h" +#include "main.h" // global_quit +#include "telescope.h" + + +// polling timeout for answer from mount +#ifndef T_POLLING_TMOUT +#define T_POLLING_TMOUT (0.5) +#endif +// wait for '\n' after last data read +#ifndef WAIT_TMOUT +#define WAIT_TMOUT (0.01) +#endif + +#define BUFLEN 80 + +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 + +static sl_tty_t *TTY = NULL; + + +/** + * read strings from terminal (ending with '\n') with timeout + * @return NULL if nothing was read or pointer to static buffer + * THREAD UNSAFE! + */ +static char *read_string(){ + static char buf[BUFLEN]; + if(!TTY){ + DBG("TTY not ready"); + return NULL; + } + int r = 0, l; + int LL = BUFLEN - 1; + char *ptr = NULL; + static char *optr = NULL; + if(optr && *optr){ + ptr = optr; + optr = strchr(optr, '\n'); + if(optr) *(optr++) = 0; + return ptr; + } + ptr = buf; + double d0 = sl_dtime(); + do{ + if((l = sl_tty_read(TTY)) > 0){ + DBG("Got %d bytes: '%s'", l, TTY->buf); + if(l > LL) l = LL; + memcpy(ptr, TTY->buf, l); + r += l; LL -= l; ptr += l; + *ptr = 0; + if(ptr[-1] == '\n'){ + ptr[-1] = 0; + break; + } + d0 = sl_dtime(); + } + }while(sl_dtime() - d0 < WAIT_TMOUT && LL); + if(r){ + buf[r] = 0; + optr = strchr(buf, '\n'); + if(optr) *(optr++) = 0; + return buf; + } + return NULL; +} + +/** + * write command, thread-safe + * @param cmd (i) - command to write + * @param buff (o) - buffer (WHICH SIZE = BUFLEN!!!) to which write data (or NULL if don't need) + * @return answer or NULL if error occured (or no answer) + * WARNING!!! data returned is allocated by strdup! You MUST free it when don't need + */ +static char *write_cmd(const char *cmd, char *buff){ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&mutex); + DBG("Write %s", cmd); + if(sl_tty_write(TTY->comfd, cmd, strlen(cmd))) return NULL; + double t0 = sl_dtime(); + char *ans; + while(sl_dtime() - t0 < T_POLLING_TMOUT){ // read answer + //DBG("%gs after start", sl_dtime() - t0); + if((ans = read_string())){ // parse new data + DBG("got answer: %s", ans); + pthread_mutex_unlock(&mutex); + if(!buff) return NULL; + strncpy(buff, ans, BUFLEN-1); + return buff; + } + } + pthread_mutex_unlock(&mutex); + return NULL; +} + +// write to telescope mount corrections: datetime, pressure and temperature +// @return 1 if time and weather was corrected +static int makecorr(){ + 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); + */ + WARNX("Refresh datetime"); + time_t t = time(NULL); + struct tm *stm = localtime(&t); + struct timeval tv; + gettimeofday(&tv,NULL); + snprintf(buf, 64, ":SLDT%04d-%02d-%02d,%02d:%02d:%02d.%02ld#", 1900+stm->tm_year, stm->tm_mon+1, stm->tm_mday, + stm->tm_hour, stm->tm_min, stm->tm_sec, tv.tv_usec/10000); + DBG("write: %s", buf); + ans = write_cmd(buf, ibuff); + if(!ans || *ans != '1'){ + WARNX("Can't write current date/time"); + LOGWARN("Can't set system time"); + ret = 0; + }else{ + LOGMSG("Set system time by command %s", buf); + } + DBG("curtime: %s", write_cmd(":GUDT#", ibuff)); + localWeather *w = getWeath(); + if(!w){ + ret = 0; + LOGWARN("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'){ + ret = 0; + LOGWARN("Can't set pressure data of refraction model"); + }else LOGMSG("Correct pressure to %gmmHg", w->pres); + snprintf(buf, 64, ":SRTMP%.1f#", w->tc); + ans = write_cmd(buf, ibuff); + if(!ans || *ans != '1'){ + ret = 0; + LOGWARN("Can't set temperature data of refraction model"); + }else LOGMSG("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; +} + + +int chkconn(){ + char tmpbuf[4096]; + if(!TTY){ + DBG("TTY not opened"); + return 0; + } + sl_tty_read(TTY); // clear rbuf + DBG("Clear, try to ask 115200"); + //write_cmd("#", NULL); // clear cmd buffer + write_cmd(":GA#", tmpbuf); + write_cmd(":GR#", tmpbuf); + if(!write_cmd(":SB0#", tmpbuf)) return 0; // 115200 + if(*tmpbuf == '1'){ + DBG("OK, found!"); + //if(!write_cmd(":GR#")) return 0; + return 1; + } + return 0; +} + +/** + * connect telescope device + * @param dev (i) - device name to connect + * @param hdrname (i) - output file with FITS-headers + * @return 1 if all OK + */ +int connect_telescope(char *dev, char *hdrname){ + if(!dev) return 0; + tcflag_t spds[] = {9600, 19200, 38400, 57600, 115200, 4800, 2400, 1200, 0}, *speeds = spds; + DBG("Connection to device %s...", dev); + sl_tty_tmout(10000.); + while(*speeds){ + DBG("Try %d", *speeds); + TTY = sl_tty_new(dev, *speeds, BUFSIZ); + if(TTY){ + DBG("try to open %s", dev); + TTY = sl_tty_open(TTY, 1); + } + if(TTY && chkconn()) break; + sl_tty_close(&TTY); + ++speeds; + } + if(!*speeds){ + DBG("Not found"); + return 0; + } + if(*speeds != B115200){ + DBG("change to 115200"); + sl_tty_close(&TTY); + TTY = sl_tty_new(dev, *speeds, BUFSIZ); + if(TTY) TTY = sl_tty_open(TTY, 1); + if(!TTY || !chkconn()){ + DBG("not found"); + return 0; + } + } + write_cmd("#", NULL); // clear previous buffer + write_cmd(":STOP#", NULL); // stop tracking after poweron + write_cmd(":U2#", NULL); // set high precision + write_cmd(":So10#", NULL); // set minimum altitude to 10 degrees + LOGMSG("Connected to %s@115200, will write FITS-header into %s", dev, hdrname); + FREE(hdname); + hdname = strdup(hdrname); + DBG("connected"); + Target = 0; + getWeath(); getPlace(); getDUT(); // determine starting values + //write_cmd(":gT#", NULL); // correct time by GPS + return 1; +} + +/* +:MS# - move to target, return: 0 if all OK or text with error +:SrHH:MM:SS.SS# - set target RA (return 1 if all OK) +:SdsDD*MM:SS.S# - set target DECL (return 1 if all OK) +*/ +/** + * send coordinates to telescope + * @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){ + LOGWARN("Can't point telescope in paused mode"); + return 0; + } + DBG("try to send ra=%g, decl=%g", ra, dec); + ptRAdeg = ra * 15.; + ptDECdeg = dec; + Target = 0; + int err = 0; + char buf[80], ibuff[BUFLEN]; + char sign = '+'; + if(dec < 0){ + sign = '-'; + dec = -dec; + } + + int h = (int)ra; + ra -= h; ra *= 60.; + int m = (int)ra; + ra -= m; ra *= 60.; + + int d = (int) dec; + dec -= d; dec *= 60.; + int dm = (int)dec; + dec -= dm; dec *= 60.; + snprintf(buf, 80, ":Sr%d:%d:%.2f#", h,m,ra); + char *ans = write_cmd(buf, ibuff); + if(!ans || *ans != '1'){ + err = 1; + goto ret; + } + snprintf(buf, 80, ":Sd%c%d:%d:%.1f#", sign,d,dm,dec); + ans = write_cmd(buf, ibuff); + if(!ans || *ans != '1'){ + err = 2; + goto ret; + } + DBG("Move"); + ans = write_cmd(":MS#", ibuff); + if(!ans || *ans != '0'){ + LOGWARN("move error, answer: %s", ans); + err = 3; + goto ret; + } + ret: + if(err){ + LOGWARN("error sending coordinates (err = %d: RA/DEC/MOVE)!", err); + return 0; + }else{ + Target = 1; + LOGMSG("Send ra=%g degr, dec=%g degr", ptRAdeg, ptDECdeg); + } + return 1; +} + +/** + * convert str into RA/DEC coordinate + * @param str (i) - string with angle + * @param val (o) - output angle value + * @return 1 if all OK + */ +static int str2coord(char *str, double *val){ + if(!str || !val) return 0; + int d, m; + float s; + int sign = 1; + if(*str == '+') ++str; + else if(*str == '-'){ + sign = -1; + ++str; + } + int n = sscanf(str, "%d:%d:%f#", &d, &m, &s); + if(n != 3) return 0; + double ang = d + ((double)m)/60. + s/3600.; + if(sign == -1) *val = -ang; + else *val = ang; + return 1; +} + +/** + * @brief printhdr - write FITS record into output file + * @param fd - fd to write + * @param key - key + * @param val - value + * @param cmnt - comment + * @return 0 if all OK + */ +static int printhdr(int fd, const char *key, const char *val, const char *cmnt){ + char tmp[81]; + char tk[9]; + if(strlen(key) > 8){ + snprintf(tk, 9, "%s", key); + key = tk; + } + if(cmnt){ + snprintf(tmp, 81, "%-8s= %-21s / %s", key, val, cmnt); + }else{ + snprintf(tmp, 81, "%-8s= %s", key, val); + } + size_t l = strlen(tmp); + tmp[l] = '\n'; + ++l; + if(write(fd, tmp, l) != (ssize_t)l){ + WARN("write()"); + return 1; + } + return 0; +} + +/** + * get coordinates + * @param ra (o) - right ascension (hours) + * @param decl (o) - declination (degrees) + * @return telescope status or -1 if coordinates are too old + */ +int get_telescope_coords(double *ra, double *decl){ + if(!tlast) tlast = time(NULL); + if(time(NULL) - tlast > COORDS_TOO_OLD_TIME) return -1; // coordinates are too old + if(ra) *ra = r; + if(decl) *decl = d; + return mountstatus; +} + +void disconnect_telescope(){ + if(TTY) sl_tty_close(&TTY); +} + +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 +} + +// site characteristics +static char + *elevation = NULL, + *longitude = NULL, + *latitude = NULL; + +// make duplicate of buf without trailing `#` +// if astr == 1, surround content with '' +static char *dups(const char *buf, int astr){ + if(!buf) return NULL; + char *newbuf = malloc(strlen(buf)+5), *bptr = newbuf+1; + if(!newbuf) return NULL; + strcpy(bptr, buf); + char *sharp = strrchr(bptr, '#'); + if(sharp) *sharp = 0; + if(astr){ + bptr = newbuf; + *bptr = '\''; + int l = strlen(newbuf); + newbuf[l] = '\''; + newbuf[l+1] = 0; + } + char *d = strdup(bptr); + free(newbuf); + return d; +} + +static void getplace(){ + char *ans, ibuff[BUFLEN]; + if(!elevation){ + ans = write_cmd(":Gev#", ibuff); + elevation = dups(ans, 0); + } + if(!longitude){ + ans = write_cmd(":Gg#", ibuff); + longitude = dups(ans, 1); + } + if(!latitude){ + ans = write_cmd(":Gt#", ibuff); + latitude = dups(ans, 1); + } +} + +static const char *statuses[12] = { + [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'" +}; + +/** + * @brief strstatus - return string explanation of mount status + * @param status - integer status code + * @return statically allocated string with explanation + */ +static const char* strstatus(int status){ + if(status < 0) return "'Signal lost'"; + if(status < TEL_MAXSTATUS) return statuses[status]; + if(status == 99) return "'Error'"; + return "'Unknown 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){ + LOGMSG("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){ // make correction once per hour + if(makecorr()) lastcorr = time(NULL); + else lastcorr += 30; // failed -> check 30s later + } + char *ans = NULL, *jd = NULL, *lst = NULL, *date = NULL, *pS = NULL; + char ibuff[BUFLEN]; + // get coordinates for writing to file & sending to stellarium client + ans = write_cmd(":GR#", ibuff); + if(!str2coord(ans, &r)){ + if(++failcounter == 10){ + LOGERR("Lost connection with mount: can't get RA!"); + DBG("Can't get RA!"); + signals(9); + } + DBG("Failed"); + return; + } + ans = write_cmd(":GD#", ibuff); + if(!str2coord(ans, &d)){ + if(++failcounter == 10){ + LOGERR("Lost connection with mount: can't get DEC!"); + 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){ + LOGERR("Lost connection with mount: can't get LST!"); + DBG("Can't get LST!"); + signals(9); + } + DBG("Failed"); + return; + } + LST *= 15.*ERFA_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.*ERFA_DD2R, .dec = d*ERFA_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 + if(!hdname){ + DBG("hdname not given!"); + return; + } + if(!elevation || !longitude || !latitude) getplace(); + ans = write_cmd(":GUDT#", ibuff); + if(ans){ + char *comma = strchr(ans, ','); + if(comma){ + *comma = 'T'; + date = dups(ans, 1); + } + } + ans = write_cmd(":pS#", ibuff); pS = dups(ans, 1); + ans = write_cmd(":Gstat#", ibuff); + if(ans){ + mountstatus = atoi(ans); + //DBG("Status: %d", mountstatus); + } + int l = strlen(hdname) + 7; + char *aname = MALLOC(char, l); + snprintf(aname, l, "%sXXXXXX", hdname); + int fd = mkstemp(aname); + if(fd < 0){ + WARN("Can't write header file: mkstemp()"); + FREE(aname); + FREE(jd); FREE(lst); FREE(date); FREE(pS); + return; + } + fchmod(fd, 0644); + char val[22]; +#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", 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"); + snprintf(val, 22, "%.10f", ptDECdeg); + 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, deg"); + snprintf(val, 22, "%.10f", d); + WRHDR("DEC", val, "Telescope declination, current epoch, deg"); + snprintf(val, 22, "%.10f", hNow.az * ERFA_DR2D); + WRHDR("AZ", val, "Telescope azimuth, current epoch, deg"); + snprintf(val, 22, "%.10f", hNow.zd * ERFA_DR2D); + WRHDR("ZD", val, "Telescope zenith distance, current epoch, deg"); + WRHDR("TELSTAT", strstatus(mountstatus), "Telescope mount status"); + 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"); + 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(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: + FREE(jd); FREE(lst); FREE(date); FREE(pS); + close(fd); + rename(aname, hdname); + FREE(aname); +} + +// terminal thread: allows to work with terminal through socket +void *term_thread(void *sockd){ + int sock = *(int*)sockd; + char buff[BUFLEN+1], ibuff[BUFLEN+2]; + // get client IP from socket fd - for logging + struct sockaddr_in peer; + socklen_t peer_len = sizeof(peer); + char *peerIP = NULL; + if(getpeername(sock, (struct sockaddr*)&peer, &peer_len) == 0){ + peerIP = inet_ntoa(peer.sin_addr); + } + while(!global_quit){ // blocking read + ssize_t rd = read(sock, buff, BUFLEN); + if(rd <= 0){ // error or disconnect + DBG("Nothing to read from fd %d (ret: %zd)", sock, rd); + break; + } + buff[rd] = 0; + 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"); + LOGMSG("Port writing outside terminal thread is paused"); + pause_communication = 1; + continue; + } + if(strcasecmp(buff, "continue") == 0){ + DBG("CONTINUED"); + LOGMSG("Port writing outside terminal thread is restored by user"); + pause_communication = 0; + continue; + } + char *ans = write_cmd(buff, ibuff); + LOGMSG("%s COMMAND %s ANSWER %s", peerIP, buff, ibuff); + DBG("ANSWER: %s", ibuff); + if(ans){ + ssize_t l = (ssize_t)strlen(ans); + if(l++){ + ans[l-1] = '\n'; + ans[l] = 0; + if(l != write(sock, ans, l)){ + WARN("term_thread, write()"); + break; + } + } + } + } + close(sock); + return NULL; +} diff --git a/Daemons/deprecated/10micron_stellarium.deprecated/telescope.h b/Daemons/deprecated/10micron_stellarium.deprecated/telescope.h new file mode 100644 index 0000000..614f46e --- /dev/null +++ b/Daemons/deprecated/10micron_stellarium.deprecated/telescope.h @@ -0,0 +1,56 @@ +/* + * geany_encoding=koi8-r + * telescope.h + * + * Copyright 2018 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once + +// max time after last coordinates reading +#define COORDS_TOO_OLD_TIME (5) +// 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); +void stop_telescope(); +void disconnect_telescope(); +void wrhdr(); +void *term_thread(void *sockd); +