From bd09ecef906ca68fc6fdadb13cbdeec98834fc33 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 25 Feb 2020 17:52:48 +0300 Subject: [PATCH] add tool for pointing telescope from CLI --- Daemons/10micron_stellarium/libsofa.c | 8 +- Daemons/10micron_stellarium/main.c | 29 ++- Daemons/10micron_stellarium/telescope.c | 71 ++++-- Daemons/Readme.md | 7 +- Daemons/astrosib/HWoff | 0 Daemons/astrosib/HWon | 0 Daemons/astrosib/STARTobs | 0 Daemons/astrosib/STOPobs | 0 Daemons/netsocket/HWpoweroff | 0 Daemons/netsocket/HWpoweron | 0 Daemons/netsocket/MOUNTpoweronoff | 0 Daemons/send_coordinates/Makefile | 43 ++++ Daemons/send_coordinates/Readme | 1 + Daemons/send_coordinates/SendCoords.config | 2 + Daemons/send_coordinates/SendCoords.creator | 1 + .../send_coordinates/SendCoords.creator.user | 167 ++++++++++++++ Daemons/send_coordinates/SendCoords.files | 5 + Daemons/send_coordinates/SendCoords.includes | 1 + Daemons/send_coordinates/cmdlnopts.c | 92 ++++++++ Daemons/send_coordinates/cmdlnopts.h | 42 ++++ Daemons/send_coordinates/main.c | 79 +++++++ Daemons/send_coordinates/stelldaemon.c | 215 ++++++++++++++++++ Daemons/send_coordinates/stelldaemon.h | 53 +++++ Daemons/teldaemon/teldaemon | Bin Docs/Alignment/makelist | 0 Docs/focus | 0 26 files changed, 779 insertions(+), 37 deletions(-) mode change 100755 => 100644 Daemons/astrosib/HWoff mode change 100755 => 100644 Daemons/astrosib/HWon mode change 100755 => 100644 Daemons/astrosib/STARTobs mode change 100755 => 100644 Daemons/astrosib/STOPobs mode change 100644 => 100755 Daemons/netsocket/HWpoweroff mode change 100644 => 100755 Daemons/netsocket/HWpoweron mode change 100644 => 100755 Daemons/netsocket/MOUNTpoweronoff create mode 100644 Daemons/send_coordinates/Makefile create mode 100644 Daemons/send_coordinates/Readme create mode 100644 Daemons/send_coordinates/SendCoords.config create mode 100644 Daemons/send_coordinates/SendCoords.creator create mode 100644 Daemons/send_coordinates/SendCoords.creator.user create mode 100644 Daemons/send_coordinates/SendCoords.files create mode 100644 Daemons/send_coordinates/SendCoords.includes create mode 100644 Daemons/send_coordinates/cmdlnopts.c create mode 100644 Daemons/send_coordinates/cmdlnopts.h create mode 100644 Daemons/send_coordinates/main.c create mode 100644 Daemons/send_coordinates/stelldaemon.c create mode 100644 Daemons/send_coordinates/stelldaemon.h mode change 100644 => 100755 Daemons/teldaemon/teldaemon mode change 100644 => 100755 Docs/Alignment/makelist mode change 100644 => 100755 Docs/focus diff --git a/Daemons/10micron_stellarium/libsofa.c b/Daemons/10micron_stellarium/libsofa.c index b6f4b62..0015fbe 100644 --- a/Daemons/10micron_stellarium/libsofa.c +++ b/Daemons/10micron_stellarium/libsofa.c @@ -82,7 +82,7 @@ int get_MJDt(struct timeval *tval, sMJD *MJD){ struct tm tms; double tSeconds; if(!tval){ - DBG("MJD for current time"); + //DBG("MJD for current time"); struct timeval currentTime; gettimeofday(¤tTime, NULL); gmtime_r(¤tTime.tv_sec, &tms); @@ -102,11 +102,11 @@ int get_MJDt(struct timeval *tval, sMJD *MJD){ MJD->MJD = utc1 - 2400000.5 + utc2; MJD->utc1 = utc1; MJD->utc2 = utc2; - DBG("UTC(m): %g, %.8f\n", utc1 - 2400000.5, utc2); + //DBG("UTC(m): %g, %.8f\n", utc1 - 2400000.5, utc2); if(iauUtctai(utc1, utc2, &MJD->tai1, &MJD->tai2)) return -1; - DBG("TAI"); + //DBG("TAI"); if(iauTaitt(MJD->tai1, MJD->tai2, &MJD->tt1, &MJD->tt2)) return -1; - DBG("TT"); + //DBG("TT"); return 0; } diff --git a/Daemons/10micron_stellarium/main.c b/Daemons/10micron_stellarium/main.c index 349cead..b0a9776 100644 --- a/Daemons/10micron_stellarium/main.c +++ b/Daemons/10micron_stellarium/main.c @@ -257,28 +257,29 @@ int proc_data(uint8_t *data, ssize_t len){ /** * main socket service procedure */ -void handle_socket(int sock){ +void *handle_socket(void *sockd){ FNAME(); - if(global_quit) return; + if(global_quit) return NULL; ssize_t rd; outdata dout; + int sock = *(int*)sockd; dout.len = htole16(sizeof(outdata)); dout.type = 0; - dout.status = 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(!getcoords(&RA, &Decl)){ + if((dout.status = getcoords(&RA, &Decl)) < 0){ WARNX("Error: can't get coordinates"); - // continue; + sleep(1); + continue; } - DBG("got : %g/%g", RA, Decl); + //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)); + //DBG("sent ra = %g, dec = %g", RA2HRS(dout.ra), DEC2DEG(dout.dec)); fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); @@ -307,6 +308,7 @@ void handle_socket(int sock){ else dout.status = 0; } close(sock); + return NULL; } static void *hdrthread(_U_ void *buf){ @@ -392,9 +394,18 @@ static inline void main_proc(){ close(newsock); continue; }*/ - handle_socket(newsock); + //handle_socket(newsock); + pthread_t rthrd; + if(pthread_create(&rthrd, NULL, handle_socket, (void*)&newsock)){ + putlog("Error creating listen thread"); + ERR(_("Can't create socket thread")); + }else{ + DBG("Thread created, detouch"); + pthread_detach(rthrd); // don't care about thread state + + } } - pthread_cancel(hthrd); // cancel steppers' thread + pthread_cancel(hthrd); // cancel reading thread pthread_join(hthrd, NULL); close(sock); } diff --git a/Daemons/10micron_stellarium/telescope.c b/Daemons/10micron_stellarium/telescope.c index 3822e71..88539c2 100644 --- a/Daemons/10micron_stellarium/telescope.c +++ b/Daemons/10micron_stellarium/telescope.c @@ -83,13 +83,13 @@ static char *read_string(){ static char *write_cmd(const char *cmd){ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); - DBG("Write %s", cmd); + //DBG("Write %s", cmd); if(write_tty(cmd, strlen(cmd))) return NULL; double t0 = dtime(); static char *ans; while(dtime() - t0 < T_POLLING_TMOUT){ // read answer if((ans = read_string())){ // parse new data - DBG("got answer: %s", ans); + // DBG("got answer: %s", ans); pthread_mutex_unlock(&mutex); return ans; } @@ -101,10 +101,8 @@ static char *write_cmd(const char *cmd){ // write to telescope mount corrections: datetime, pressure and temperature static void makecorr(){ // write current date&time - char buf[64], *ans; -#ifdef EBUG - write_cmd(":GUDT#"); -#endif + char buf[64], *ans; + DBG("curtime: %s", write_cmd(":GUDT#")); write_cmd(":gT#"); // correct time by GPS ans = write_cmd(":gtg#"); if(!ans || *ans != '1'){ @@ -113,16 +111,15 @@ static void makecorr(){ 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, stm->tm_mday, + 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); if(!ans || *ans != '1'){ WARNX("Can't write current date/time"); putlog("Can't set system time"); }else putlog("Set system time by command %s", buf); -#ifdef EBUG - write_cmd(":GUDT#"); -#endif + DBG("curtime: %s", write_cmd(":GUDT#")); } placeWeather w; if(getWeath(&w)) putlog("Can't determine weather data"); @@ -226,10 +223,11 @@ int point_telescope(double ra, double dec){ err = 2; goto ret; } + DBG("Move"); ans = write_cmd(":MS#"); if(!ans || *ans != '0'){ putlog("move error, answer: %s", ans); - err = 2; + err = 3; goto ret; } ret: @@ -299,28 +297,26 @@ static int printhdr(int fd, const char *key, const char *val, const char *cmnt){ static double r = 0., d = 0.; // RA/DEC from wrhdr +static int mountstatus = 0; // return of :Gstat# static time_t tlast = 0; // last time coordinates were refreshed /** * get coordinates * @param ra (o) - right ascension (hours) * @param decl (o) - declination (degrees) - * @return 1 if all OK + * @return telescope status or -1 if coordinates are too old */ int get_telescope_coords(double *ra, double *decl){ - if(time(NULL) - tlast > COORDS_TOO_OLD_TIME) return 0; // coordinates are too old + 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 1; + return mountstatus; } void stop_telescope(){ - for(int i = 0; i < 3; ++i){ - if(write_cmd(":STOP#")){ - Target = 0; - return; - } - } - putlog("Can't send command STOP"); + write_cmd(":RT9#"); // stop tracking + write_cmd(":STOP#"); // halt moving + Target = 0; } // site characteristics @@ -366,6 +362,33 @@ static void getplace(){ } } +static const char *statuses[12] = { + [0] = "'Tracking'", + [1] = "'Going to stop'", + [2] = "'Slewing to park'", + [3] = "'Unparking'", + [4] = "'Slewing to home'", + [5] = "'Parked'", + [6] = "'Slewing or going to stop'", + [7] = "'Stopped'", + [8] = "'Motors inhibited, T too low'", + [9] = "'Outside tracking limit'", + [10]= "'Following satellite'", + [11]= "'Data inconsistency'" +}; + +/** + * @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 < (int)(sizeof(statuses)/sizeof(char*)-1)) return statuses[status]; + if(status == 99) return "'Error'"; + return "'Unknown status'"; +} + /** * @brief wrhdr - try to write into header file */ @@ -411,6 +434,11 @@ void wrhdr(){ } } ans = write_cmd(":pS#"); pS = dups(ans, 1); + ans = write_cmd(":Gstat#"); + if(ans){ + mountstatus = atoi(ans); + //DBG("Status: %d", mountstatus); + } #define WRHDR(k, v, c) do{if(printhdr(hdrfd, k, v, c)){close(hdrfd); return;}}while(0) char val[22]; if(unlink(hdname)){ @@ -437,6 +465,7 @@ void wrhdr(){ WRHDR("RA", val, "Telescope right ascension, current epoch"); snprintf(val, 22, "%.10f", d); WRHDR("DEC", val, "Telescope declination, current epoch"); + WRHDR("TELSTAT", strstatus(mountstatus), "Telescope mount status"); sMJD mjd; if(!get_MJDt(NULL, &mjd)){ snprintf(val, 22, "%.10f", 2000.+(mjd.MJD-MJD2000)/365.25); // calculate EPOCH/EQUINOX diff --git a/Daemons/Readme.md b/Daemons/Readme.md index 234d752..ad871f3 100644 --- a/Daemons/Readme.md +++ b/Daemons/Readme.md @@ -1,8 +1,9 @@ -Different daemons -================= +Different daemons @ tools +========================= - *10micron_stellarium* - simple daemon for 10-micron mount management from stellarium interface - *domedaemon* - open/close dome by network query - *netdaemon* - template for net-daemons -- *teldaemon* - open/close Astrosib-500 scope covers by network query - *netsocket* - scripts for management of network 220V-socket +- *send_coordinates* - get/send coordinates to 10-micron mount through stellarium daemon +- *teldaemon* - open/close Astrosib-500 scope covers by network query diff --git a/Daemons/astrosib/HWoff b/Daemons/astrosib/HWoff old mode 100755 new mode 100644 diff --git a/Daemons/astrosib/HWon b/Daemons/astrosib/HWon old mode 100755 new mode 100644 diff --git a/Daemons/astrosib/STARTobs b/Daemons/astrosib/STARTobs old mode 100755 new mode 100644 diff --git a/Daemons/astrosib/STOPobs b/Daemons/astrosib/STOPobs old mode 100755 new mode 100644 diff --git a/Daemons/netsocket/HWpoweroff b/Daemons/netsocket/HWpoweroff old mode 100644 new mode 100755 diff --git a/Daemons/netsocket/HWpoweron b/Daemons/netsocket/HWpoweron old mode 100644 new mode 100755 diff --git a/Daemons/netsocket/MOUNTpoweronoff b/Daemons/netsocket/MOUNTpoweronoff old mode 100644 new mode 100755 diff --git a/Daemons/send_coordinates/Makefile b/Daemons/send_coordinates/Makefile new file mode 100644 index 0000000..e41fd9c --- /dev/null +++ b/Daemons/send_coordinates/Makefile @@ -0,0 +1,43 @@ +# run `make DEF=...` to add extra defines +PROGRAM := send_coords +LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all +LDFLAGS += -lusefull_macros +SRCS := $(wildcard *.c) +DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +OBJDIR := mk +CFLAGS += -O2 -Wno-trampolines -std=gnu99 +OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) +DEPS := $(OBJS:.o=.d) +CC = gcc +#CXX = g++ + + +all : $(OBJDIR) $(PROGRAM) + +debug: CFLAGS += -DEBUG -Werror -Wall -Wextra -W +debug: all + +$(PROGRAM) : $(OBJS) + @echo -e "\t\tLD $(PROGRAM)" + $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) + +$(OBJDIR): + mkdir $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + +$(OBJDIR)/%.o: %.c + @echo -e "\t\tCC $<" + $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< + +clean: + @echo -e "\t\tCLEAN" + @rm -f $(OBJS) $(DEPS) + @rmdir $(OBJDIR) 2>/dev/null || true + +xclean: clean + @rm -f $(PROGRAM) + +.PHONY: clean xclean diff --git a/Daemons/send_coordinates/Readme b/Daemons/send_coordinates/Readme new file mode 100644 index 0000000..0f1b925 --- /dev/null +++ b/Daemons/send_coordinates/Readme @@ -0,0 +1 @@ +A simple tool to send/receive coordinates from telescope diff --git a/Daemons/send_coordinates/SendCoords.config b/Daemons/send_coordinates/SendCoords.config new file mode 100644 index 0000000..e0284f4 --- /dev/null +++ b/Daemons/send_coordinates/SendCoords.config @@ -0,0 +1,2 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 diff --git a/Daemons/send_coordinates/SendCoords.creator b/Daemons/send_coordinates/SendCoords.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/Daemons/send_coordinates/SendCoords.creator @@ -0,0 +1 @@ +[General] diff --git a/Daemons/send_coordinates/SendCoords.creator.user b/Daemons/send_coordinates/SendCoords.creator.user new file mode 100644 index 0000000..075bf79 --- /dev/null +++ b/Daemons/send_coordinates/SendCoords.creator.user @@ -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/send_coordinates + + + + 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/send_coordinates/SendCoords.files b/Daemons/send_coordinates/SendCoords.files new file mode 100644 index 0000000..9b614da --- /dev/null +++ b/Daemons/send_coordinates/SendCoords.files @@ -0,0 +1,5 @@ +cmdlnopts.c +cmdlnopts.h +main.c +stelldaemon.c +stelldaemon.h diff --git a/Daemons/send_coordinates/SendCoords.includes b/Daemons/send_coordinates/SendCoords.includes new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/Daemons/send_coordinates/SendCoords.includes @@ -0,0 +1 @@ +. diff --git a/Daemons/send_coordinates/cmdlnopts.c b/Daemons/send_coordinates/cmdlnopts.c new file mode 100644 index 0000000..4ada3fa --- /dev/null +++ b/Daemons/send_coordinates/cmdlnopts.c @@ -0,0 +1,92 @@ +/* + * This file is part of the SendCoords 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 +#include + +#include "cmdlnopts.h" +#include "usefull_macros.h" + +/* + * here are global parameters initialisation + */ +static int help; +static glob_pars G; + +#define DEFAULT_PIDFILE "/tmp/sendcoords.pid" +#define DEFAULT_PORT "10000" +#define DEFAULT_HOST "localhost" + +// DEFAULTS +// default global parameters +static glob_pars const Gdefault = { + .pidfile = DEFAULT_PIDFILE, + .port = DEFAULT_PORT, + .host = DEFAULT_HOST, +}; + +/* + * Define command line options by filling structure: + * name has_arg flag val type argptr help +*/ +static myoption cmdlnopts[] = { +// common options + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, + {"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 ")")}, + {"host", NEED_ARG, NULL, 'H', arg_string, APTR(&G.host), _("host to connect (default: " DEFAULT_HOST ")")}, + {"ra", NEED_ARG, NULL, 'r', arg_string, APTR(&G.ra), _("target RA: HH:MM:SS.SS")}, + {"dec", NEED_ARG, NULL, 'd', arg_string, APTR(&G.dec), _("target DEC: [+-]DD:MM:SS.SS")}, + {"quiet", NO_ARGS, NULL, 'q', arg_none, APTR(&G.quiet), _("suppress all messages to stdout")}, + {"monitor", NO_ARGS, NULL, 'm', arg_none, APTR(&G.monitor), _("monitor coordinates")}, + 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" + change_helpstring(helpstring); + // parse arguments + parseargs(&argc, &argv, cmdlnopts); + if(help) showhelp(-1, cmdlnopts); + if(argc > 0){ + fprintf(stderr, "Undefined extra parameters!\n"); + showhelp(-1, cmdlnopts); + G.rest_pars_num = argc; + G.rest_pars = MALLOC(char *, argc); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; +} + diff --git a/Daemons/send_coordinates/cmdlnopts.h b/Daemons/send_coordinates/cmdlnopts.h new file mode 100644 index 0000000..241bac0 --- /dev/null +++ b/Daemons/send_coordinates/cmdlnopts.h @@ -0,0 +1,42 @@ +/* + * This file is part of the SendCoords 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 +#ifndef CMDLNOPTS_H__ +#define CMDLNOPTS_H__ + +/* + * here are some typedef's for global data + */ +typedef struct{ + char *pidfile; // name of PID file + char *port; // port to connect + char *host; // hostname + char *ra; // RA in string form + char *dec; // DEC in string form + int rest_pars_num; // number of rest parameters + int quiet; // don't show anything + int monitor; // monitor status + char** rest_pars; // the rest parameters: array of char* +} glob_pars; + + +glob_pars *parse_args(int argc, char **argv); + +#endif // CMDLNOPTS_H__ diff --git a/Daemons/send_coordinates/main.c b/Daemons/send_coordinates/main.c new file mode 100644 index 0000000..a8935f6 --- /dev/null +++ b/Daemons/send_coordinates/main.c @@ -0,0 +1,79 @@ +/* + * This file is part of the SendCoords 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 // signal +#include // printf +#include // exit, free +#include // strdup +#include // sleep +#include + +#include "cmdlnopts.h" +#include "stelldaemon.h" + +glob_pars *GP = NULL; // for GP->pidfile need in `signals` + +/** + * We REDEFINE the default WEAK function of signal processing + */ +void signals(int sig){ + if(sig){ + signal(sig, SIG_IGN); + DBG("Get signal %d, quit.\n", sig); + } + WARNX("Exit with status %d", sig); + if(GP->pidfile) // remove unnesessary PID file + unlink(GP->pidfile); + restore_console(); + exit(sig); +} + +void iffound_default(pid_t pid){ + ERRX("Another copy of this process found, pid=%d. Exit.", pid); +} + +int main(int argc, char *argv[]){ + initial_setup(); + char *self = strdup(argv[0]); + GP = parse_args(argc, argv); + if(GP->rest_pars_num){ + printf("%d extra options:\n", GP->rest_pars_num); + for(int i = 0; i < GP->rest_pars_num; ++i) + printf("%s\n", GP->rest_pars[i]); + } + if((GP->ra && !GP->dec) || (!GP->ra && GP->dec)) + ERRX("You should point both coordinates"); + check4running(self, GP->pidfile); + free(self); + signal(SIGTERM, signals); // kill (-15) - 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 + setup_con(); + /* + if(GP->rest_pars_num){ + for(int i = 0; i < GP->rest_pars_num; ++i) + printf("Extra argument: %s\n", GP->rest_pars[i]); + }*/ + mk_connection(); + // clean everything + signals(0); + return 0; +} + diff --git a/Daemons/send_coordinates/stelldaemon.c b/Daemons/send_coordinates/stelldaemon.c new file mode 100644 index 0000000..85726c0 --- /dev/null +++ b/Daemons/send_coordinates/stelldaemon.c @@ -0,0 +1,215 @@ +/* + * This file is part of the SendCoords 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 // inet_ntop +#include // NAN +#include //getaddrinfo +#include +#include +#include +#include // getaddrinfo, connect, socket +#include // getaddrinfo & socket types +#include +#include + +#include "cmdlnopts.h" +#include "stelldaemon.h" + +extern glob_pars *GP; + +/** + * convert RA/DEC to string in forman RA: HH:MM:SS.SS, DEC: DD:MM:SS.S + */ +static 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, "RA=%02d:%02d:%05.2f, DEC=%c%02d:%02d:%04.1f", h,m,ra, sign,d,dm,dec); + return buf; +} + +/** + * @brief print_coords - print received coordinates @ terminal + * @param idat (i) - received data + */ +static void print_coords(indata *dat){ + uint16_t len, type; + uint32_t ra; + int32_t dec, status; +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + len = le16toh(dat->len); type = le16toh(dat->type); + //tim = le64toh(dat->time); + ra = le32toh(dat->ra); + dec = (int32_t)le32toh((uint32_t)dat->dec); + status = (int32_t)le32toh((uint32_t)dat->status); +#else + len = dat->len; + type = dat->type; + //tim = dat->time; + ra = dat->ra; + dec = dat->dec; + status = dat->status; +#endif + DBG("len=%d, type=%d, ra=%d, dec=%d, status=%d\n", + len, type, ra, dec, status); + if(len != sizeof(indata)){ + WARNX("Field `size` of input data not equal to %d", sizeof(indata)); + return; + } + double tagRA = RA2HRS(ra), tagDec = DEC2DEG(dec); +// DBG("RA: %g, DEC: %g, STATUS: %d", tagRA, tagDec, status); + printf("%s, STATUS: %d\n", radec2str(tagRA, tagDec), status); +} + +static int waittoread(int sock){ + fd_set fds; + struct timeval timeout; + int rc; + timeout.tv_sec = 5; // wait not more than 1 second + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(sock, &fds); + rc = select(sock+1, &fds, NULL, NULL, &timeout); + if(rc < 0){ + WARN("select()"); + return 0; + } + if(rc > 0 && FD_ISSET(sock, &fds)) return 1; + return 0; +} + +/** + * @brief str2ha - convert string with angle/hour HH:MM:SS or DD:MM:SS into double value + * @param str (i) - input string + * @param ha (o) - value + * @return 0 if all OK + */ +static int str2ha(const char *str, double *ha){ + if(!str || !ha) return 1; + int hd, m, sign = 1; // hours/degrees, minutes + float s; // seconds + if(3 != sscanf(str, "%d:%d:%f", &hd, &m, &s)){ + return 1; + } + if(hd < 0){sign = -1; hd = -hd;} + *ha = sign * (hd + m/60. + s/3600.); + return 0; +} + +void mk_connection(){ + int sockfd = 0; + int pointing = FALSE; // ==1 if telescope is pointing + uint8_t recvBuff[64]; + double ra = FP_NAN, dec = FP_NAN; + if(GP->ra && GP->dec){ + DBG("Point to %s %s", GP->ra, GP->dec); + if(str2ha(GP->ra, &ra)){ + WARNX("Wrong RA: %s", GP->ra); + return; + } + if(ra < 0. || ra > 24.){ + WARNX("RA should be in range 0..24h"); + return; + } + if(str2ha(GP->dec, &dec)){ + WARNX("Wrong DEC: %s", GP->dec); + return; + } + if(dec < -90. || dec > 90.){ + WARNX("DEC should be in range -90..90degr"); + return; + } + pointing = TRUE; + DBG("RA: %g, DEC: %g", ra, dec); + } + struct addrinfo h, *r, *p; + memset(&h, 0, sizeof(h)); + h.ai_family = AF_INET; + h.ai_socktype = SOCK_STREAM; + h.ai_flags = AI_CANONNAME; + if(!GP) ERRX("Command line arguments not defined!"); + if(getaddrinfo(GP->host, GP->port, &h, &r)){WARN("getaddrinfo()"); return;} + struct sockaddr_in *ia = (struct sockaddr_in*)r->ai_addr; +#ifdef EBUG + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN); + printf("canonname: %s, port: %u, addr: %s\n", r->ai_canonname, ntohs(ia->sin_port), str); +#endif + for(p = r; 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){ + close(sockfd); + WARN("connect()"); + continue; + } + break; // if we get here, we must have connected successfully + } + if(p == NULL){ + // looped off the end of the list with no connection + WARNX("Failed to connect to socket\n"); + return; + } + freeaddrinfo(r); + + if(pointing){ + outdata dat; + dat.len = htole16(sizeof(outdata)); + dat.type = 0; + dat.ra = htole32(HRS2RA(ra)); + dat.dec = (int32_t)htole32(DEG2DEC(dec)); + if(send(sockfd, &dat, sizeof(outdata), 0) != sizeof(outdata)) + WARN("send()"); + sleep(1); + } + int tstart = time(NULL); + while(waittoread(sockfd)){ + int n = read(sockfd, recvBuff, sizeof(recvBuff)-1); + DBG("got %d bytes", n); + if(n < 1) break; + if(n == sizeof (indata)){ + indata *idat = (indata*)recvBuff; + if(!GP->quiet) print_coords(idat); + if(GP->monitor) continue; + if(!pointing) break; + if(idat->status == _10U_STATUS_TRACKING && time(NULL) - tstart > 3) break; // start tracking (+3s pause) + if(idat->status != _10U_STATUS_SLEWING){ + if(time(NULL) - tstart > 5) signals(idat->status); // exit with error code after 5 seconds waiting + }else tstart = time(NULL); // reset time if status is slewing + } + } + close(sockfd); + DBG("End"); + //FREE(msg); +} diff --git a/Daemons/send_coordinates/stelldaemon.h b/Daemons/send_coordinates/stelldaemon.h new file mode 100644 index 0000000..f01a080 --- /dev/null +++ b/Daemons/send_coordinates/stelldaemon.h @@ -0,0 +1,53 @@ +/* + * This file is part of the SendCoords 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 +#ifndef STELLDAEMON_H__ + +#include + +// some statuses +#define _10U_STATUS_TRACKING (0) +#define _10U_STATUS_SLEWING (6) + +#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; +} outdata; + +typedef struct __attribute__((__packed__)){ + uint16_t len; + uint16_t type; + uint64_t time; + uint32_t ra; + int32_t dec; + int32_t status; +} indata; + +void mk_connection(); + +#define STELLDAEMON_H__ +#endif // STELLDAEMON_H__ diff --git a/Daemons/teldaemon/teldaemon b/Daemons/teldaemon/teldaemon old mode 100644 new mode 100755 diff --git a/Docs/Alignment/makelist b/Docs/Alignment/makelist old mode 100644 new mode 100755 diff --git a/Docs/focus b/Docs/focus old mode 100644 new mode 100755