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);
+