mirror of
https://github.com/eddyem/eddys_snippets.git
synced 2025-12-06 02:35:12 +03:00
Add short list to HSFV_manage
This commit is contained in:
parent
bf4ea0c493
commit
b73587a5e4
@ -23,18 +23,16 @@ given turret.
|
|||||||
|
|
||||||
## Usage examples
|
## Usage examples
|
||||||
|
|
||||||
#### List all devices connected
|
#### Short list of connected devices (wheel ID, turret serial and current position):
|
||||||
Свойства подключенного колеса
|
HSFW_manage
|
||||||
Wheel ID 'A', name 'UBVRI', serial '00000563', 5 filters:
|
'B' '00000563' 1
|
||||||
1: 'U'
|
'A' '00000532' 1
|
||||||
2: 'B'
|
|
||||||
3: 'V'
|
|
||||||
4: 'R'
|
|
||||||
5: 'I'
|
|
||||||
current position: 1
|
|
||||||
|
|
||||||
Свойства подключенного колеса
|
#### List all devices connected
|
||||||
Wheel ID 'B', name 'Sloan', serial '00000532', 5 filters:
|
HSFW_manage --list
|
||||||
|
|
||||||
|
Connected wheel properties
|
||||||
|
Wheel ID 'B' , name 'Sloan', serial '00000563' , 5 filters:
|
||||||
1: '1'
|
1: '1'
|
||||||
2: '2'
|
2: '2'
|
||||||
3: '3'
|
3: '3'
|
||||||
@ -42,6 +40,15 @@ given turret.
|
|||||||
5: '5'
|
5: '5'
|
||||||
current position: 1
|
current position: 1
|
||||||
|
|
||||||
|
Connected wheel properties
|
||||||
|
Wheel ID 'A' , name 'UBVRI', serial '00000532' , 5 filters:
|
||||||
|
1: 'U'
|
||||||
|
2: 'B'
|
||||||
|
3: 'V'
|
||||||
|
4: 'R'
|
||||||
|
5: 'I'
|
||||||
|
current position: 1
|
||||||
|
|
||||||
#### Move wheel by turret's serial and position number
|
#### Move wheel by turret's serial and position number
|
||||||
HSFW_manage -s 00000563 -p 3
|
HSFW_manage -s 00000563 -p 3
|
||||||
|
|
||||||
|
|||||||
@ -36,54 +36,54 @@
|
|||||||
int help;
|
int help;
|
||||||
glob_pars G;
|
glob_pars G;
|
||||||
|
|
||||||
int listNms = 0 // list names
|
int listNms = LIST_NONE // list names
|
||||||
,gohome = 0 // first go home
|
,gohome = 0 // first go home
|
||||||
,reName = 0 // rename wheels/positions
|
,reName = 0 // rename wheels/positions
|
||||||
,showpos = 0 // show current position (if none args)
|
,showpos = 0 // show current position (if none args)
|
||||||
,setdef = 0 // reset all names to default values
|
,setdef = 0 // reset all names to default values
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
// DEFAULTS
|
// DEFAULTS
|
||||||
// default global parameters
|
// default global parameters
|
||||||
glob_pars const Gdefault = {
|
glob_pars const Gdefault = {
|
||||||
NULL // wheelID
|
NULL // wheelID
|
||||||
,NULL // wheelName
|
,NULL // wheelName
|
||||||
,NULL // serial
|
,NULL // serial
|
||||||
,0 // filterPos ( 0 - get current position)
|
,0 // filterPos ( 0 - get current position)
|
||||||
,NULL // filterName
|
,NULL // filterName
|
||||||
,NULL // filterId
|
,NULL // filterId
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define command line options by filling structure:
|
* Define command line options by filling structure:
|
||||||
* name has_arg flag val type argptr help
|
* name has_arg flag val type argptr help
|
||||||
*/
|
*/
|
||||||
myoption cmdlnopts[] = {
|
myoption cmdlnopts[] = {
|
||||||
/// "ÏÔÏÂÒÁÚÉÔØ ÜÔÕ ÓÐÒÁ×ËÕ"
|
/// "ÏÔÏÂÒÁÚÉÔØ ÜÔÕ ÓÐÒÁ×ËÕ"
|
||||||
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), N_("show this help")},
|
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), N_("show this help")},
|
||||||
/// "ÂÕË×ÅÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ËÏÌÅÓÁ"
|
/// "ÂÕË×ÅÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ËÏÌÅÓÁ"
|
||||||
{"wheel-id",NEED_ARG, NULL, 'W', arg_string, APTR(&G.wheelID), N_("letter wheel identificator")},
|
{"wheel-id",NEED_ARG, NULL, 'W', arg_string, APTR(&G.wheelID), N_("letter wheel identificator")},
|
||||||
/// "ÎÁÚ×ÁÎÉÅ ËÏÌÅÓÁ"
|
/// "ÎÁÚ×ÁÎÉÅ ËÏÌÅÓÁ"
|
||||||
{"wheel-name",NEED_ARG, NULL, 'N', arg_string, APTR(&G.wheelName), N_("wheel name")},
|
{"wheel-name",NEED_ARG, NULL, 'N', arg_string, APTR(&G.wheelName), N_("wheel name")},
|
||||||
/// "ÓÅÒÉÊÎÙÊ ÎÏÍÅÒ ÔÕÒÅÌÉ (Ó ÎÁÞÁÌØÎÙÍÉ ÎÕÌÑÍÉ)"
|
/// "ÓÅÒÉÊÎÙÊ ÎÏÍÅÒ ÔÕÒÅÌÉ (Ó ÎÁÞÁÌØÎÙÍÉ ÎÕÌÑÍÉ)"
|
||||||
{"serial", NEED_ARG, NULL, 's', arg_string, APTR(&G.serial), N_("turret serial (with leading zeros)")},
|
{"serial", NEED_ARG, NULL, 's', arg_string, APTR(&G.serial), N_("turret serial (with leading zeros)")},
|
||||||
/// "ÎÏÍÅÒ ÐÏÚÉÃÉÉ ÆÉÌØÔÒÁ"
|
/// "ÎÏÍÅÒ ÐÏÚÉÃÉÉ ÆÉÌØÔÒÁ"
|
||||||
{"f-position",NEED_ARG, NULL, 'p', arg_int, APTR(&G.filterPos), N_("filter position number")},
|
{"f-position",NEED_ARG, NULL, 'p', arg_int, APTR(&G.filterPos), N_("filter position number")},
|
||||||
/// "ÎÁÚ×ÁÎÉÅ ÆÉÌØÔÒÁ"
|
/// "ÎÁÚ×ÁÎÉÅ ÆÉÌØÔÒÁ"
|
||||||
{"filter-name",NEED_ARG,NULL, 'n', arg_string, APTR(&G.filterName),N_("filter name")},
|
{"filter-name",NEED_ARG,NULL, 'n', arg_string, APTR(&G.filterName),N_("filter name")},
|
||||||
/// "ÉÄÅÎÔÉÆÉËÁÔÏÒ ÆÉÌØÔÒÁ, ÎÁÐÒÉÍÅÒ, \"A3\""
|
/// "ÉÄÅÎÔÉÆÉËÁÔÏÒ ÆÉÌØÔÒÁ, ÎÁÐÒÉÍÅÒ, \"A3\""
|
||||||
{"filter-id",NEED_ARG, NULL, 'i', arg_string, APTR(&G.filterId), N_("filter identificator like \"A3\"")},
|
{"filter-id",NEED_ARG, NULL, 'i', arg_string, APTR(&G.filterId), N_("filter identificator like \"A3\"")},
|
||||||
/// "ÓÐÉÓÏË ×ÓÅÈ ÓÏÈÒÁÎÅÎÎÙÈ ÉÍÅÎ"
|
/// "ÓÐÉÓÏË ×ÓÅÈ ÓÏÈÒÁÎÅÎÎÙÈ ÉÍÅÎ"
|
||||||
{"list-all",NO_ARGS, &listNms,LIST_ALL,arg_none, NULL, N_("list all stored names")},
|
{"list-all",NO_ARGS, &listNms,LIST_ALL,arg_none, NULL, N_("list all stored names")},
|
||||||
/// "ÓÐÉÓÏË ÉÍÅÎ ÔÏÌØËÏ ÐÒÉÓÕÔÓÔ×ÕÀÝÉÈ ÕÓÔÒÏÊÓÔ×"
|
/// "ÓÐÉÓÏË ÉÍÅÎ ÔÏÌØËÏ ÐÒÉÓÕÔÓÔ×ÕÀÝÉÈ ÕÓÔÒÏÊÓÔ×"
|
||||||
{"list", NO_ARGS, &listNms,LIST_PRES,arg_none,NULL, N_("list only present devices' names")},
|
{"list", NO_ARGS, &listNms,LIST_PRES,arg_none,NULL, N_("list only present devices' names")},
|
||||||
/// "ÐÅÒÅÍÅÓÔÉÔØÓÑ × ÓÔÁÒÔÏ×ÕÀ ÐÏÚÉÃÉÀ"
|
/// "ÐÅÒÅÍÅÓÔÉÔØÓÑ × ÓÔÁÒÔÏ×ÕÀ ÐÏÚÉÃÉÀ"
|
||||||
{"home", NO_ARGS, NULL, 'H', arg_none, &gohome, N_("move to home position")},
|
{"home", NO_ARGS, NULL, 'H', arg_none, &gohome, N_("move to home position")},
|
||||||
/// "ÐÅÒÅÉÍÅÎÏ×ÁÔØ ÓÏÈÒÁÎÅÎÎÙÅ ÉÍÅÎÁ ËÏÌÅÓ/ÆÉÌØÔÒÏ×"
|
/// "ÐÅÒÅÉÍÅÎÏ×ÁÔØ ÓÏÈÒÁÎÅÎÎÙÅ ÉÍÅÎÁ ËÏÌÅÓ/ÆÉÌØÔÒÏ×"
|
||||||
{"rename", NO_ARGS, &reName,1, arg_none, NULL, N_("rename stored wheels/filters names")},
|
{"rename", NO_ARGS, &reName,1, arg_none, NULL, N_("rename stored wheels/filters names")},
|
||||||
{"resetnames",NO_ARGS, &setdef,1, arg_none, NULL, N_("reset all names to default values")},
|
{"resetnames",NO_ARGS, &setdef,1, arg_none, NULL, N_("reset all names to default values")},
|
||||||
end_option
|
end_option
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,45 +94,46 @@ myoption cmdlnopts[] = {
|
|||||||
* @return TRUE if success
|
* @return TRUE if success
|
||||||
*/
|
*/
|
||||||
bool myatod(double *num, const char *str){
|
bool myatod(double *num, const char *str){
|
||||||
double res;
|
double res;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
assert(str);
|
assert(str);
|
||||||
res = strtod(str, &endptr);
|
res = strtod(str, &endptr);
|
||||||
if(endptr == str || *str == '\0' || *endptr != '\0'){
|
if(endptr == str || *str == '\0' || *endptr != '\0'){
|
||||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ double!"
|
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ double!"
|
||||||
WARNX(_("Wrong double number format!"));
|
WARNX(_("Wrong double number format!"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
*num = res;
|
*num = res;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse command line options and return dynamically allocated structure
|
* Parse command line options and return dynamically allocated structure
|
||||||
* to global parameters
|
* to global parameters
|
||||||
* @param argc - copy of argc from main
|
* @param argc - copy of argc from main
|
||||||
* @param argv - copy of argv from main
|
* @param argv - copy of argv from main
|
||||||
* @return allocated structure with global parameters
|
* @return allocated structure with global parameters
|
||||||
*/
|
*/
|
||||||
glob_pars *parse_args(int argc, char **argv){
|
glob_pars *parse_args(int argc, char **argv){
|
||||||
int i, oldargc = argc - 1;
|
int i, oldargc = argc - 1;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr);
|
ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr);
|
||||||
/// "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s [ÁÒÇÕÍÅÎÔÙ] [ÐÒÅÆÉËÓ ×ÙÈÏÄÎÏÇÏ ÆÁÊÌÁ]\n\n\tçÄÅ [ÁÒÇÕÍÅÎÔÙ]:\n"
|
/// "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s [ÁÒÇÕÍÅÎÔÙ] [ÐÒÅÆÉËÓ ×ÙÈÏÄÎÏÇÏ ÆÁÊÌÁ]\n\n\tçÄÅ [ÁÒÇÕÍÅÎÔÙ]:\n"
|
||||||
//change_helpstring(_("Usage: %s [args] [outfile prefix] [file list for group operations]\n\n\tWhere args are:\n"));
|
//change_helpstring(_("Usage: %s [args] [outfile prefix] [file list for group operations]\n\n\tWhere args are:\n"));
|
||||||
// parse arguments
|
// parse arguments
|
||||||
parseargs(&argc, &argv, cmdlnopts);
|
parseargs(&argc, &argv, cmdlnopts);
|
||||||
if(help) showhelp(-1, cmdlnopts);
|
if(help) showhelp(-1, cmdlnopts);
|
||||||
if(argc > 0){
|
if(argc > 0){
|
||||||
/// "éÇÎÏÒÉÒÕÀÔÓÑ ÐÁÒÁÍÅÔÒÙ: "
|
/// "éÇÎÏÒÉÒÕÀÔÓÑ ÐÁÒÁÍÅÔÒÙ: "
|
||||||
WARNX(_("Ignore parameters:"));
|
WARNX(_("Ignore parameters:"));
|
||||||
for (i = 0; i < argc; i++){
|
for (i = 0; i < argc; i++){
|
||||||
printf("%s\n", argv[i]);
|
printf("%s\n", argv[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(argc == oldargc){ // no parameters given or given only wrong parameters
|
if(argc == oldargc){ // no parameters given or given only wrong parameters
|
||||||
showpos = 1;
|
//showpos = 1;
|
||||||
}
|
listNms = LIST_SHORT; // short list of turrets present
|
||||||
return &G;
|
}
|
||||||
|
return &G;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,17 +29,21 @@
|
|||||||
* here are some typedef's for global data
|
* here are some typedef's for global data
|
||||||
*/
|
*/
|
||||||
typedef struct{
|
typedef struct{
|
||||||
char *wheelID; // ID of wheel to work with
|
char *wheelID; // ID of wheel to work with
|
||||||
char *wheelName; // and/or its name
|
char *wheelName; // and/or its name
|
||||||
char *serial; // turret's serial (string description)
|
char *serial; // turret's serial (string description)
|
||||||
int filterPos; // position of filter
|
int filterPos; // position of filter
|
||||||
char *filterName; // and/or its name
|
char *filterName; // and/or its name
|
||||||
char *filterId; // or full ID like "A2"
|
char *filterId; // or full ID like "A2"
|
||||||
} glob_pars;
|
} glob_pars;
|
||||||
|
|
||||||
// ids for "list all" & "list present"
|
// ids for "list all", "list present", "list short"
|
||||||
#define LIST_ALL (1)
|
typedef enum{
|
||||||
#define LIST_PRES (2)
|
LIST_NONE = 0,
|
||||||
|
LIST_ALL,
|
||||||
|
LIST_PRES,
|
||||||
|
LIST_SHORT
|
||||||
|
} listopts;
|
||||||
|
|
||||||
// default & global parameters
|
// default & global parameters
|
||||||
extern glob_pars const Gdefault;
|
extern glob_pars const Gdefault;
|
||||||
|
|||||||
@ -66,9 +66,10 @@ void set_cur_wheel(int idx){
|
|||||||
* Check command line arguments, find filters/wheels by name, find max positions & so on
|
* Check command line arguments, find filters/wheels by name, find max positions & so on
|
||||||
*/
|
*/
|
||||||
void check_args(){
|
void check_args(){
|
||||||
|
FNAME();
|
||||||
// here we fill value of wheel_id if no given and present only one turret
|
// here we fill value of wheel_id if no given and present only one turret
|
||||||
list_hw(listNms); // also exit if no HW found
|
list_hw(listNms); // also exit if no HW found
|
||||||
if(listNms) return;
|
if(listNms != LIST_NONE) return;
|
||||||
int i;
|
int i;
|
||||||
// add wheel ID to global parameters if there was nothing
|
// add wheel ID to global parameters if there was nothing
|
||||||
if(G.serial){ // HW given by its serial
|
if(G.serial){ // HW given by its serial
|
||||||
@ -170,6 +171,7 @@ void check_args(){
|
|||||||
/// "<22>牧挝吓 讼膛酉 闻 下瘟艺峙蜗!"
|
/// "<22>牧挝吓 讼膛酉 闻 下瘟艺峙蜗!"
|
||||||
ERRX(_("Given wheel not found!"));
|
ERRX(_("Given wheel not found!"));
|
||||||
}
|
}
|
||||||
|
DBG("listNms = %d", listNms);
|
||||||
if(reName && !G.wheelID){
|
if(reName && !G.wheelID){
|
||||||
G.wheelID = calloc(2, 1);
|
G.wheelID = calloc(2, 1);
|
||||||
*G.wheelID = wheel_id;
|
*G.wheelID = wheel_id;
|
||||||
@ -286,7 +288,7 @@ int poll_regstatus(int fd, int msg){
|
|||||||
ERRX(_("Error ocured, repeat again"));
|
ERRX(_("Error ocured, repeat again"));
|
||||||
}
|
}
|
||||||
usleep(50000);
|
usleep(50000);
|
||||||
if(msg) printf("."); fflush(stdout);
|
if(msg){printf("."); fflush(stdout);}
|
||||||
}
|
}
|
||||||
if(msg) printf("\n");
|
if(msg) printf("\n");
|
||||||
return buf[4];
|
return buf[4];
|
||||||
@ -339,6 +341,7 @@ void list_props(int verblevl, wheel_descr *wheel){
|
|||||||
wheel->ID = buf[5];
|
wheel->ID = buf[5];
|
||||||
wheel->maxpos = buf[4];
|
wheel->maxpos = buf[4];
|
||||||
DBG("Wheel with id '%c' and maxpos %d", wheel->ID, wheel->maxpos);
|
DBG("Wheel with id '%c' and maxpos %d", wheel->ID, wheel->maxpos);
|
||||||
|
DBG("Verblevl = %d", verblevl);
|
||||||
char *getwname(int id){
|
char *getwname(int id){
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
buf[0] = REG_NAME;
|
buf[0] = REG_NAME;
|
||||||
@ -353,33 +356,40 @@ void list_props(int verblevl, wheel_descr *wheel){
|
|||||||
}
|
}
|
||||||
else return NULL;
|
else return NULL;
|
||||||
}
|
}
|
||||||
if(verblevl == LIST_PRES || !verblevl){ // list only presented devices or not list
|
if(verblevl == LIST_PRES || verblevl == LIST_SHORT || verblevl == LIST_NONE){ // list only presented devices or not list
|
||||||
char *nm;
|
char *nm;
|
||||||
/// "\n笞鲜釉琢 邢乃汤夼挝锨<E68C9D> 讼膛恿\n"
|
/// "\n笞鲜釉琢 邢乃汤夼挝锨<E68C9D> 讼膛恿\n"
|
||||||
if(verblevl) green(_("\nConnected wheel properties\n"));
|
if(verblevl != LIST_NONE){
|
||||||
if(verblevl) printf("Wheel ID '%c'", wheel->ID);
|
if(verblevl == LIST_PRES){
|
||||||
|
green(_("\nConnected wheel properties\n"));
|
||||||
|
printf("Wheel ID ");
|
||||||
|
}
|
||||||
|
printf("'%c' ", wheel->ID);
|
||||||
|
}
|
||||||
nm = getwname(wheel->ID);
|
nm = getwname(wheel->ID);
|
||||||
if(nm){
|
if(nm){
|
||||||
strncpy(wheel->name, nm, 9);
|
strncpy(wheel->name, nm, 9);
|
||||||
if(verblevl) printf(", name '%s'", wheel->name);
|
if(verblevl == LIST_PRES) printf(", name '%s'", wheel->name);
|
||||||
DBG("Wheel name: %s", wheel->name);
|
DBG("Wheel name: %s", wheel->name);
|
||||||
}
|
}
|
||||||
if(wheel->serial && verblevl){
|
if(wheel->serial && verblevl != LIST_NONE){
|
||||||
printf(", serial '%s'", wheel->serial);
|
if(verblevl == LIST_PRES) printf(", serial ");
|
||||||
|
printf("'%s' ", wheel->serial);
|
||||||
}
|
}
|
||||||
if(verblevl) printf(", %d filters:\n", wheel->maxpos);
|
if(verblevl == LIST_NONE) return;
|
||||||
else return;
|
if(verblevl == LIST_PRES){
|
||||||
int i, m = wheel->maxpos + 1;
|
printf(", %d filters:\n", wheel->maxpos);
|
||||||
// now get filter names
|
int i, m = wheel->maxpos + 1;
|
||||||
for(i = 1; i < m; ++i){
|
// now get filter names
|
||||||
nm = get_filter_name(wheel, i);
|
for(i = 1; i < m; ++i){
|
||||||
printf("\t%d", i);
|
nm = get_filter_name(wheel, i);
|
||||||
if(nm) printf(": '%s'", nm);
|
printf("\t%d", i);
|
||||||
printf("\n");
|
if(nm) printf(": '%s'", nm);
|
||||||
}
|
printf("\n");
|
||||||
if(verblevl){
|
}
|
||||||
printf("current position: %d\n", poll_regstatus(wheel->fd, 0));
|
printf("current position: ");
|
||||||
}
|
}
|
||||||
|
printf("%d\n", poll_regstatus(wheel->fd, 0));
|
||||||
}
|
}
|
||||||
if(verblevl != LIST_ALL) return;
|
if(verblevl != LIST_ALL) return;
|
||||||
// now list all things stored in memory of turret driver
|
// now list all things stored in memory of turret driver
|
||||||
|
|||||||
6
astrosib/CMakeLists.txt
Normal file
6
astrosib/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
########## Tutorial two ##############
|
||||||
|
add_executable(astrosib astrosib.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(astrosib indidriver)
|
||||||
|
|
||||||
|
|
||||||
6
astrosib/Readme.md
Normal file
6
astrosib/Readme.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
INDI driver for ASTROSIB telescopes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*Write at level upper to CMakeLists.txt:*
|
||||||
|
add_subdirectory(astrosib)
|
||||||
481
astrosib/astrosib.cpp
Normal file
481
astrosib/astrosib.cpp
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* astrosib.cpp
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
INDI Developers Manual
|
||||||
|
Tutorial #2
|
||||||
|
|
||||||
|
"Simple Telescope Driver"
|
||||||
|
|
||||||
|
We develop a simple telescope simulator.
|
||||||
|
|
||||||
|
Refer to README, which contains instruction on how to build this driver, and use it
|
||||||
|
with an INDI-compatible client.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file simplescope.cpp
|
||||||
|
\brief Construct a basic INDI telescope device that simulates GOTO commands.
|
||||||
|
\author Jasem Mutlaq
|
||||||
|
|
||||||
|
\example simplescope.cpp
|
||||||
|
A simple GOTO telescope that simulator slewing operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "astrosib.h"
|
||||||
|
|
||||||
|
#include "indicom.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// timer polling time
|
||||||
|
#define POLLMS 1000
|
||||||
|
|
||||||
|
static const char *FOCUSER_TAB = "Focuser management";
|
||||||
|
static const char *COOLER_TAB = "Cooler management";
|
||||||
|
static const char *HEATER_TAB = "Heater management";
|
||||||
|
|
||||||
|
std::unique_ptr<AstroSib> aSib(new AstroSib());
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Return properties of device.
|
||||||
|
***************************************************************************************/
|
||||||
|
void ISGetProperties(const char *dev){
|
||||||
|
aSib->ISGetProperties(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Process new switch from client
|
||||||
|
***************************************************************************************/
|
||||||
|
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n){
|
||||||
|
aSib->ISNewSwitch(dev, name, states, names, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Process new text from client
|
||||||
|
***************************************************************************************/
|
||||||
|
void ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n){
|
||||||
|
aSib->ISNewText(dev, name, texts, names, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Process new number from client
|
||||||
|
***************************************************************************************/
|
||||||
|
void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n){
|
||||||
|
aSib->ISNewNumber(dev, name, values, names, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Process new blob from client
|
||||||
|
***************************************************************************************/
|
||||||
|
void ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[],
|
||||||
|
char *names[], int n){
|
||||||
|
aSib->ISNewBLOB(dev, name, sizes, blobsizes, blobs, formats, names, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Process snooped property from another driver
|
||||||
|
***************************************************************************************/
|
||||||
|
void ISSnoopDevice(XMLEle *root){
|
||||||
|
INDI_UNUSED(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstroSib::AstroSib(){
|
||||||
|
/* code should be here */
|
||||||
|
//DBG_LEVEL = INDI::Logger::getInstance().addDebugLevel("Astrosib Verbose", "SCOPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
AstroSib::~AstroSib(){
|
||||||
|
/* code should be here */
|
||||||
|
if (isConnected()) AstroSib::Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** We init our properties here. The only thing we want to init are the Debug controls
|
||||||
|
***************************************************************************************/
|
||||||
|
bool AstroSib::initProperties(){
|
||||||
|
// ALWAYS call initProperties() of parent first
|
||||||
|
INDI::DefaultDevice::initProperties();
|
||||||
|
|
||||||
|
// Shutter leaves
|
||||||
|
IUFillSwitch(&ShtrsS[SHTR_OPENED], "SHTR_OPENED", "Open Scope", ISS_OFF);
|
||||||
|
IUFillSwitch(&ShtrsS[SHTR_CLOSED], "SHTR_CLOSED", "Close Scope", ISS_ON);
|
||||||
|
IUFillSwitchVector(&ShtrsSP, ShtrsS, 2, getDeviceName(), "SHTR_CONTROL", "Shutter Control",
|
||||||
|
MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 1, IPS_OK);
|
||||||
|
|
||||||
|
// Mirror and ambient temperature
|
||||||
|
IUFillNumber(&TempN[0], "MIRROR_TEMP", "Mirror temperature", "%.1f", -100., 100., 0.1, 0.);
|
||||||
|
IUFillNumber(&TempN[1], "AMBIENT_TEMP", "Ambient temperature", "%.1f", -100., 100., 0.1, 0.);
|
||||||
|
IUFillNumber(&TempN[2], "FOCUSER_TEMP", "Focuser temperature", "%.1f", -100., 100., 0.1, 0.);
|
||||||
|
IUFillNumberVector(&TempNP, TempN, 3, getDeviceName(), "TEMPERATURE", "Temperature",
|
||||||
|
MAIN_CONTROL_TAB, IP_RO, 1, IPS_IDLE);
|
||||||
|
|
||||||
|
// Focuser: current, relative and absolute position
|
||||||
|
IUFillNumber(&FocuserN[0], "FOC_CUR", "Current focuser position", "%.0f", 0, 65536, 1, 0);
|
||||||
|
IUFillNumber(&FocuserN[1], "FOC_REL", "Relative focuser position", "%.0f", -65536, 65536, 1, 0);
|
||||||
|
IUFillNumber(&FocuserN[2], "FOC_ABS", "Absolute focuser position", "%.0f", 0, 65536, 1, 0);
|
||||||
|
IUFillNumberVector(&FocuserNPcur, FocuserN, 1, getDeviceName(), "FOCUS_CUR", "Focuser current",
|
||||||
|
FOCUSER_TAB, IP_RO, 1, IPS_IDLE);
|
||||||
|
FocuserNPcur.s = IPS_OK;
|
||||||
|
IUFillNumberVector(&FocuserNP, &FocuserN[1], 2, getDeviceName(), "FOCUS_SET", "Focuser set",
|
||||||
|
FOCUSER_TAB, IP_RW, 1, IPS_IDLE);
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "FOCINIT, cur: %g, rel: %g, abs: %g", FocuserN[0].value, FocuserN[1].value, FocuserN[2].value);
|
||||||
|
// Mirror cooler ON/OFF
|
||||||
|
IUFillSwitch(&CoolerS[_ON], "COOLER_ON", "Cooler ON", ISS_OFF);
|
||||||
|
IUFillSwitch(&CoolerS[_OFF], "COOLER_OFF", "Cooler OFF", ISS_ON);
|
||||||
|
IUFillSwitchVector(&CoolerSP, CoolerS, 2, getDeviceName(), "COOLER_CONTROL", "Cooler Control",
|
||||||
|
COOLER_TAB, IP_RW, ISR_1OFMANY, 1, IPS_IDLE);
|
||||||
|
IUFillSwitch(&ACoolerS[_ON], "ACOOLER_ON", "Cooler auto ON", ISS_OFF);
|
||||||
|
IUFillSwitch(&ACoolerS[_OFF], "ACOOLER_OFF", "Cooler auto OFF", ISS_ON);
|
||||||
|
IUFillSwitchVector(&ACoolerSP, ACoolerS, 2, getDeviceName(), "ACOOLER_CONTROL", "Auto Cooler Control",
|
||||||
|
COOLER_TAB, IP_RW, ISR_1OFMANY, 1, IPS_IDLE);
|
||||||
|
// Secondary mirror / Primary focus corrector Heater
|
||||||
|
IUFillSwitch(&AHeaterS[_ON], "HTR_ON", "Auto Heater ON", ISS_OFF);
|
||||||
|
IUFillSwitch(&AHeaterS[_OFF], "HTR_OFF", "Auto Heater OFF", ISS_ON);
|
||||||
|
IUFillSwitchVector(&AHeaterSP, AHeaterS, 2, getDeviceName(), "HEATER_CONTROL", "Heater Control",
|
||||||
|
HEATER_TAB, IP_RW, ISR_1OFMANY, 1, IPS_IDLE);
|
||||||
|
IUFillNumber(&PHeaterN, "PHTR", "Set heater power", "%.0f", 0, 100, 1, 0);
|
||||||
|
IUFillNumberVector(&PHeaterNP, &PHeaterN, 1, getDeviceName(), "PHTR_CTRL", "Heater power",
|
||||||
|
HEATER_TAB, IP_RW, 1, IPS_IDLE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::updateProperties(){
|
||||||
|
// We must ALWAYS call the parent class updateProperties() first
|
||||||
|
DefaultDevice::updateProperties();
|
||||||
|
|
||||||
|
// If we are connected, we define the property to the client.
|
||||||
|
if (isConnected()){
|
||||||
|
defineSwitch(&ShtrsSP);
|
||||||
|
defineNumber(&TempNP);
|
||||||
|
defineNumber(&FocuserNPcur);
|
||||||
|
defineNumber(&FocuserNP);
|
||||||
|
defineSwitch(&CoolerSP);
|
||||||
|
defineSwitch(&ACoolerSP);
|
||||||
|
defineSwitch(&AHeaterSP);
|
||||||
|
defineNumber(&PHeaterNP);
|
||||||
|
SetTimer(POLLMS);
|
||||||
|
// Otherwise, we delete the property from the client
|
||||||
|
}else{
|
||||||
|
deleteProperty(ShtrsSP.name);
|
||||||
|
deleteProperty(TempNP.name);
|
||||||
|
deleteProperty(FocuserNPcur.name);
|
||||||
|
deleteProperty(FocuserNP.name);
|
||||||
|
deleteProperty(CoolerSP.name);
|
||||||
|
deleteProperty(ACoolerSP.name);
|
||||||
|
deleteProperty(AHeaterSP.name);
|
||||||
|
deleteProperty(PHeaterNP.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Process new switch from client
|
||||||
|
***************************************************************************************/
|
||||||
|
bool AstroSib::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n){
|
||||||
|
// Mak sure the call is for our device
|
||||||
|
if(!strcmp(dev,getDeviceName())){
|
||||||
|
// Check if the call for shutters
|
||||||
|
if (!strcmp(name, ShtrsSP.name)){
|
||||||
|
// Find out which state is requested by the client
|
||||||
|
const char *actionName = IUFindOnSwitchName(states, names, n);
|
||||||
|
// If door is the same state as actionName, then we do nothing. i.e. if actionName is SHTR_OPENED and our shutter is already open, we return
|
||||||
|
int currentIndex = IUFindOnSwitchIndex(&ShtrsSP);
|
||||||
|
if (!strcmp(actionName, ShtrsS[currentIndex].name)){
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Shutter is already %s", ShtrsS[currentIndex].label);
|
||||||
|
ShtrsSP.s = IPS_OK;
|
||||||
|
IDSetSwitch(&ShtrsSP, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Otherwise, let us update the switch state
|
||||||
|
IUUpdateSwitch(&ShtrsSP, states, names, n);
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Shutter is going to %s", ShtrsS[currentIndex].label);
|
||||||
|
ShtrsSP.s = IPS_BUSY;
|
||||||
|
IDSetSwitch(&ShtrsSP, NULL);
|
||||||
|
return ShutterSetState(currentIndex);
|
||||||
|
}else if (!strcmp(name, CoolerSP.name)){
|
||||||
|
// Find out which state is requested by the client
|
||||||
|
const char *actionName = IUFindOnSwitchName(states, names, n);
|
||||||
|
int currentIndex = IUFindOnSwitchIndex(&CoolerSP);
|
||||||
|
CoolerSP.s = IPS_OK;
|
||||||
|
if (!strcmp(actionName, CoolerS[currentIndex].name)){
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Cooler is already %s", CoolerS[currentIndex].label);
|
||||||
|
IDSetSwitch(&CoolerSP, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IUUpdateSwitch(&CoolerSP, states, names, n);
|
||||||
|
currentIndex = IUFindOnSwitchIndex(&CoolerSP);
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Cooler is now %s", CoolerS[currentIndex].label);
|
||||||
|
IDSetSwitch(&CoolerSP, NULL);
|
||||||
|
return CoolerSetState(currentIndex);
|
||||||
|
}else if (!strcmp(name, ACoolerSP.name)){
|
||||||
|
// Find out which state is requested by the client
|
||||||
|
const char *actionName = IUFindOnSwitchName(states, names, n);
|
||||||
|
int currentIndex = IUFindOnSwitchIndex(&ACoolerSP);
|
||||||
|
ACoolerSP.s = IPS_OK;
|
||||||
|
if (!strcmp(actionName, ACoolerS[currentIndex].name)){
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Auto Cooler is already %s", ACoolerS[currentIndex].label);
|
||||||
|
IDSetSwitch(&ACoolerSP, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IUUpdateSwitch(&ACoolerSP, states, names, n);
|
||||||
|
currentIndex = IUFindOnSwitchIndex(&ACoolerSP);
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Auto Cooler is now %s", ACoolerS[currentIndex].label);
|
||||||
|
IDSetSwitch(&ACoolerSP, NULL);
|
||||||
|
return ACoolerSetState(currentIndex);
|
||||||
|
}else if (!strcmp(name, AHeaterSP.name)){
|
||||||
|
// Find out which state is requested by the client
|
||||||
|
const char *actionName = IUFindOnSwitchName(states, names, n);
|
||||||
|
int currentIndex = IUFindOnSwitchIndex(&AHeaterSP);
|
||||||
|
AHeaterSP.s = IPS_OK;
|
||||||
|
if (!strcmp(actionName, AHeaterS[currentIndex].name)){
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Auto Heater is already %s", AHeaterS[currentIndex].label);
|
||||||
|
IDSetSwitch(&AHeaterSP, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IUUpdateSwitch(&AHeaterSP, states, names, n);
|
||||||
|
currentIndex = IUFindOnSwitchIndex(&AHeaterSP);
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "Auto Heater is now %s", AHeaterS[currentIndex].label);
|
||||||
|
IDSetSwitch(&AHeaterSP, NULL);
|
||||||
|
return AHeaterSetState(currentIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we did not process the switch, let us pass it to the parent class to process it
|
||||||
|
return INDI::DefaultDevice::ISNewSwitch(dev, name, states, names, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
|
||||||
|
{
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "NEW NUM, name: %s, value=%g, names = %s, n: %d", name, values[0], names[0], n);
|
||||||
|
if (dev != nullptr && strcmp(dev, getDeviceName()) == 0){
|
||||||
|
if(strcmp(name, FocuserNP.name) == 0){
|
||||||
|
if(FocInProgress){ // Already moving
|
||||||
|
DEBUG(INDI::Logger::DBG_ERROR, "Wait still focus moving ends");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(IUUpdateNumber(&FocuserNP, values, names, n)){
|
||||||
|
DEBUG(INDI::Logger::DBG_ERROR, "Can't set focuser value");
|
||||||
|
FocuserN[1].value = 0;
|
||||||
|
FocuserN[2].value = focabs;
|
||||||
|
FocuserNP.s = IPS_ALERT;
|
||||||
|
IDSetNumber(&FocuserNP, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DEBUGF(INDI::Logger::DBG_SESSION, "NEW NUMBER, rel: %g, abs: %g", FocuserN[1].value, FocuserN[2].value);
|
||||||
|
if(FocuserN[1].value){ // relative
|
||||||
|
focabs = foccur + FocuserN[1].value;
|
||||||
|
}else if(FocuserN[2].value){ // absolute
|
||||||
|
focabs = FocuserN[2].value;
|
||||||
|
}
|
||||||
|
if(focabs < 0){
|
||||||
|
DEBUG(INDI::Logger::DBG_ERROR, "Can't move focuser to negative values");
|
||||||
|
focabs = foccur;
|
||||||
|
FocuserNP.s = IPS_ALERT;
|
||||||
|
IDSetNumber(&FocuserNP, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FocInProgress = true;
|
||||||
|
FocuserNP.s = IPS_BUSY;
|
||||||
|
FocuserN[1].value = focabs - foccur;
|
||||||
|
FocuserN[2].value = focabs;
|
||||||
|
IDSetNumber(&FocuserNP, nullptr);
|
||||||
|
return FocuserSetVal(focabs);
|
||||||
|
}else if(strcmp(name, PHeaterNP.name) == 0){
|
||||||
|
float oldval = PHeaterN.value;
|
||||||
|
if(IUUpdateNumber(&PHeaterNP, values, names, n)){
|
||||||
|
DEBUG(INDI::Logger::DBG_ERROR, "Can't set heater power value");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool stat = HeaterSetPower(*values);
|
||||||
|
if(!stat) PHeaterN.value = oldval;
|
||||||
|
PHeaterNP.s = (stat) ? IPS_OK : IPS_ALERT;
|
||||||
|
IDSetNumber(&PHeaterNP, nullptr);
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** INDI is asking us for our default device name
|
||||||
|
***************************************************************************************/
|
||||||
|
const char *AstroSib::getDefaultName(){
|
||||||
|
return "AstroSib telescope";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Timer events
|
||||||
|
void AstroSib::TimerHit(){
|
||||||
|
static int tensecond = 0;
|
||||||
|
++tensecond;
|
||||||
|
if (isConnected()){
|
||||||
|
// once per 10 seconds check cooler & heater status
|
||||||
|
if(tensecond == 10){
|
||||||
|
CoolerChk();
|
||||||
|
HeaterChk();
|
||||||
|
tensecond = 0;
|
||||||
|
}
|
||||||
|
// check shutter if(ShtrInProgress)
|
||||||
|
if(ShtrInProgress){
|
||||||
|
ShutterChk();
|
||||||
|
}
|
||||||
|
// once per second check temperatures
|
||||||
|
TemperatureChk();
|
||||||
|
// check focuser if(FocInProgress)
|
||||||
|
if(FocInProgress){
|
||||||
|
FocuserChk();
|
||||||
|
}
|
||||||
|
SetTimer(POLLMS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private functions working with RS-232
|
||||||
|
*/
|
||||||
|
void AstroSib::FocuserChk(){
|
||||||
|
if(!FocInProgress){
|
||||||
|
int cur = foccur, abs = focabs, del = cur - abs;
|
||||||
|
if(del){
|
||||||
|
if(cur > abs){
|
||||||
|
cur -= 10;
|
||||||
|
if(cur < abs) cur = abs;
|
||||||
|
}else{
|
||||||
|
cur += 10;
|
||||||
|
if(cur > abs) cur = abs;
|
||||||
|
}
|
||||||
|
foccur = cur;
|
||||||
|
focabs = abs;
|
||||||
|
//DEBUGF(INDI::Logger::DBG_SESSION, "move, cur: %d, abs: %d", foccur, focabs);
|
||||||
|
}
|
||||||
|
if(foccur == focabs){
|
||||||
|
FocInProgress = false;
|
||||||
|
FocuserNP.s = IPS_IDLE;
|
||||||
|
IDSetNumber(&FocuserNPcur, "Position reached");
|
||||||
|
}else FocuserNP.s = IPS_BUSY;
|
||||||
|
}else{
|
||||||
|
FocuserNP.s = IPS_IDLE;
|
||||||
|
}
|
||||||
|
FocuserNPcur.s = IPS_OK;
|
||||||
|
FocuserN[0].value = foccur;
|
||||||
|
FocuserN[1].value = focabs - foccur;
|
||||||
|
FocuserN[2].value = focabs;
|
||||||
|
IDSetNumber(&FocuserNPcur, nullptr);
|
||||||
|
IDSetNumber(&FocuserNP, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstroSib::TemperatureChk(){
|
||||||
|
mirrtemp += 0.01; if(mirrtemp > 20.) mirrtemp = -20.;
|
||||||
|
ambtemp += 0.05; if(ambtemp > 20.) ambtemp = -20;
|
||||||
|
TempN[0].value = mirrtemp;
|
||||||
|
TempN[1].value = ambtemp;
|
||||||
|
TempN[2].value = focusert;
|
||||||
|
TempNP.s = IPS_OK;
|
||||||
|
IDSetNumber(&TempNP, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstroSib::ShutterChk(){
|
||||||
|
if(ShtrInProgress){
|
||||||
|
static bool closed = false;
|
||||||
|
if(closed){
|
||||||
|
ShtrsS[SHTR_OPENED].s = ISS_OFF;
|
||||||
|
ShtrsS[SHTR_CLOSED].s = ISS_ON;
|
||||||
|
}else{
|
||||||
|
ShtrsS[SHTR_OPENED].s = ISS_ON;
|
||||||
|
ShtrsS[SHTR_CLOSED].s = ISS_OFF;
|
||||||
|
}
|
||||||
|
closed = !closed;
|
||||||
|
}
|
||||||
|
ShtrInProgress = false;
|
||||||
|
ShtrsSP.s = IPS_OK;
|
||||||
|
IDSetSwitch(&ShtrsSP, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstroSib::CoolerChk(){
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstroSib::HeaterChk(){
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::ShutterSetState(int newstate){
|
||||||
|
(void) newstate;
|
||||||
|
ShtrInProgress = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::CoolerSetState(int newstate){
|
||||||
|
(void) newstate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::ACoolerSetState(int newstate){
|
||||||
|
(void) newstate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::AHeaterSetState(int newstate){
|
||||||
|
(void) newstate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::AstroSib::FocuserSetVal(int focval){
|
||||||
|
(void) focval;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstroSib::HeaterSetPower(int pwr){
|
||||||
|
(void) pwr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Client is asking us to establish connection to the device
|
||||||
|
***************************************************************************************/
|
||||||
|
bool AstroSib::Connect(){
|
||||||
|
/* code should be here */
|
||||||
|
IDMessage(getDeviceName(), "Astrosib telescope connected successfully!");
|
||||||
|
SetTimer(POLLMS);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** Client is asking us to terminate connection to the device
|
||||||
|
***************************************************************************************/
|
||||||
|
bool AstroSib::Disconnect(){
|
||||||
|
/* code should be here */
|
||||||
|
IDMessage(getDeviceName(), "Astrosib telescope disconnected successfully!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************
|
||||||
|
** INDI is asking us to check communication with the device via a handshake
|
||||||
|
***************************************************************************************/
|
||||||
|
bool AstroSib::Handshake(){
|
||||||
|
// When communicating with a real scope, we check here if commands are receieved
|
||||||
|
// and acknolowedged by the mount.
|
||||||
|
/* code should be here */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
103
astrosib/astrosib.h
Normal file
103
astrosib/astrosib.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* astrosib.h
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
INDI Developers Manual
|
||||||
|
Tutorial #2
|
||||||
|
|
||||||
|
"Simple Telescope Driver"
|
||||||
|
|
||||||
|
We develop a simple telescope simulator.
|
||||||
|
|
||||||
|
Refer to README, which contains instruction on how to build this driver, and use it
|
||||||
|
with an INDI-compatible client.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file simplescope.h
|
||||||
|
\brief Construct a basic INDI telescope device that simulates GOTO commands.
|
||||||
|
\author Jasem Mutlaq
|
||||||
|
|
||||||
|
\example simplescope.h
|
||||||
|
A simple GOTO telescope that simulator slewing operation.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "inditelescope.h"
|
||||||
|
|
||||||
|
class AstroSib : public INDI::DefaultDevice{
|
||||||
|
public:
|
||||||
|
AstroSib();
|
||||||
|
~AstroSib();
|
||||||
|
bool ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
|
||||||
|
bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n);
|
||||||
|
void TimerHit();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool Connect();
|
||||||
|
bool Disconnect();
|
||||||
|
|
||||||
|
bool Handshake();
|
||||||
|
const char *getDefaultName();
|
||||||
|
bool initProperties();
|
||||||
|
bool updateProperties();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum {_ON, _OFF};
|
||||||
|
// last ambient & mirror temperature values
|
||||||
|
float ambtemp {0}, mirrtemp {0}, focusert{0};
|
||||||
|
INumber TempN[3]; // mirror, ambient and focuser
|
||||||
|
INumberVectorProperty TempNP;
|
||||||
|
void TemperatureChk();
|
||||||
|
// shutter leaves state
|
||||||
|
enum {SHTR_OPENED, SHTR_CLOSED};
|
||||||
|
bool ShtrInProgress{false};
|
||||||
|
ISwitch ShtrsS[2]; // roof shutters switch
|
||||||
|
ISwitchVectorProperty ShtrsSP;
|
||||||
|
bool ShutterSetState(int newstate);
|
||||||
|
void ShutterChk();
|
||||||
|
// focuser current/relative/absolute position
|
||||||
|
bool FocInProgress{false};
|
||||||
|
int foccur{0}, focabs{0};
|
||||||
|
INumber FocuserN[3];
|
||||||
|
INumberVectorProperty FocuserNP, FocuserNPcur;
|
||||||
|
bool FocuserSetVal(int focval);
|
||||||
|
void FocuserChk();
|
||||||
|
// mirror cooler
|
||||||
|
ISwitch CoolerS[2];
|
||||||
|
ISwitchVectorProperty CoolerSP;
|
||||||
|
// cooler auto
|
||||||
|
ISwitch ACoolerS[2];
|
||||||
|
ISwitchVectorProperty ACoolerSP;
|
||||||
|
bool CoolerSetState(int newstate);
|
||||||
|
bool ACoolerSetState(int newstate);
|
||||||
|
void CoolerChk();
|
||||||
|
// heater
|
||||||
|
ISwitch AHeaterS[2];
|
||||||
|
ISwitchVectorProperty AHeaterSP;
|
||||||
|
INumber PHeaterN;
|
||||||
|
INumberVectorProperty PHeaterNP;
|
||||||
|
bool AHeaterSetState(int newstate);
|
||||||
|
bool HeaterSetPower(int pwr);
|
||||||
|
void HeaterChk();
|
||||||
|
};
|
||||||
@ -8,7 +8,7 @@ set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
|||||||
message("VER: ${VERSION}")
|
message("VER: ${VERSION}")
|
||||||
|
|
||||||
# default flags
|
# default flags
|
||||||
set(CFLAGS -O2 -Wextra -Wall -Werror -W -std=gnu99)
|
set(CFLAGS -O2 -std=gnu99)
|
||||||
|
|
||||||
set(CMAKE_COLOR_MAKEFILE ON)
|
set(CMAKE_COLOR_MAKEFILE ON)
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
|
|||||||
|
|
||||||
# cmake -DEBUG=1 -> debugging
|
# cmake -DEBUG=1 -> debugging
|
||||||
if(DEFINED EBUG)
|
if(DEFINED EBUG)
|
||||||
|
set(CFLAGS ${CFLAGS} -Wextra -Wall -Werror -W)
|
||||||
add_definitions(-DEBUG)
|
add_definitions(-DEBUG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ add_custom_command(
|
|||||||
COMMAND enconv ${PO_FILE}
|
COMMAND enconv ${PO_FILE}
|
||||||
DEPENDS ${SOURCES}
|
DEPENDS ${SOURCES}
|
||||||
)
|
)
|
||||||
# we need this to prewent ru.po from deleting by make clean
|
# we need this to prevent ru.po from deleting by make clean
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
RU_FILE
|
RU_FILE
|
||||||
COMMAND [ -f ${RU_FILE} ] && ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} || cp ${PO_FILE} ${RU_FILE}
|
COMMAND [ -f ${RU_FILE} ] && ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} || cp ${PO_FILE} ${RU_FILE}
|
||||||
|
|||||||
140
cmakelists_/CMakeLists_regular_02.txt
Normal file
140
cmakelists_/CMakeLists_regular_02.txt
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
set(PROJ fitsread)
|
||||||
|
set(MINOR_VERSION "1")
|
||||||
|
set(MID_VERSION "0")
|
||||||
|
set(MAJOR_VERSION "0")
|
||||||
|
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||||
|
|
||||||
|
enable_language(C)
|
||||||
|
|
||||||
|
message("VER: ${VERSION}")
|
||||||
|
# threads number definition
|
||||||
|
if(NOT DEFINED PROCESSOR_COUNT)
|
||||||
|
set(PROCESSOR_COUNT 2) # by default 2 cores
|
||||||
|
set(cpuinfo_file "/proc/cpuinfo")
|
||||||
|
if(EXISTS "${cpuinfo_file}")
|
||||||
|
file(STRINGS "${cpuinfo_file}" procs REGEX "^processor.: [0-9]+$")
|
||||||
|
list(LENGTH procs PROCESSOR_COUNT)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
add_definitions(-DTHREAD_NUMBER=${PROCESSOR_COUNT})
|
||||||
|
message("In multithreaded operations will use ${PROCESSOR_COUNT} threads")
|
||||||
|
|
||||||
|
# default flags
|
||||||
|
set(CFLAGS -O2 -Wextra -Wall -Werror -W -Wno-trampolines -std=gnu99)
|
||||||
|
|
||||||
|
set(CMAKE_COLOR_MAKEFILE ON)
|
||||||
|
|
||||||
|
# here is one of two variants: all .c in directory or .c files in list
|
||||||
|
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
|
||||||
|
|
||||||
|
# cmake -DDEBUG=1 -> debugging
|
||||||
|
if(DEFINED DEBUG)
|
||||||
|
add_definitions(-DEBUG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# directory should contain dir locale/ru for gettext translations
|
||||||
|
set(LCPATH ${CMAKE_SOURCE_DIR}/locale/ru)
|
||||||
|
|
||||||
|
if(NOT DEFINED LOCALEDIR)
|
||||||
|
if(DEFINED DEBUG)
|
||||||
|
set(LOCALEDIR ${CMAKE_CURRENT_SOURCE_DIR}/locale)
|
||||||
|
else()
|
||||||
|
set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###### pkgconfig ######
|
||||||
|
# pkg-config modules (for pkg-check-modules)
|
||||||
|
set(MODULES cfitsio fftw3)
|
||||||
|
|
||||||
|
# find packages:
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
pkg_check_modules(${PROJ} REQUIRED ${MODULES})
|
||||||
|
|
||||||
|
# external modules like OpenMP:
|
||||||
|
include(FindOpenMP)
|
||||||
|
if(OPENMP_FOUND)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
|
||||||
|
add_definitions(-DOMP_FOUND)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###### additional flags ######
|
||||||
|
list(APPEND ${PROJ}_LIBRARIES "-lfftw3_threads")
|
||||||
|
|
||||||
|
project(${PROJ})
|
||||||
|
# change wrong behaviour with install prefix
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND CMAKE_INSTALL_PREFIX MATCHES "/usr/local")
|
||||||
|
message("Change default install path to /usr")
|
||||||
|
set(CMAKE_INSTALL_PREFIX "/usr")
|
||||||
|
endif()
|
||||||
|
message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||||
|
|
||||||
|
# gettext files
|
||||||
|
set(PO_FILE ${LCPATH}/messages.po)
|
||||||
|
set(MO_FILE ${LCPATH}/LC_MESSAGES/${PROJ}.mo)
|
||||||
|
set(RU_FILE ${LCPATH}/ru.po)
|
||||||
|
set(CTAGS_FILE ${CMAKE_SOURCE_DIR}/${PROJ}.c.tags)
|
||||||
|
|
||||||
|
# exe file
|
||||||
|
add_executable(${PROJ} ${SOURCES})
|
||||||
|
# -I
|
||||||
|
include_directories(${${PROJ}_INCLUDE_DIRS})
|
||||||
|
# -L
|
||||||
|
link_directories(${${PROJ}_LIBRARY_DIRS})
|
||||||
|
# -D
|
||||||
|
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
|
||||||
|
-DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\"
|
||||||
|
-DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\"
|
||||||
|
-DMAJOR_VERSION=\"${MAJOR_VESION}\")
|
||||||
|
|
||||||
|
# -l
|
||||||
|
target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} -lm)
|
||||||
|
|
||||||
|
# Installation of the program
|
||||||
|
INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES")
|
||||||
|
#PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
|
||||||
|
INSTALL(TARGETS ${PROJ} DESTINATION "bin")
|
||||||
|
|
||||||
|
###### gettext & ctags ######
|
||||||
|
if(DEFINED EBUG)
|
||||||
|
message("Generate locale & tags files")
|
||||||
|
find_package(Gettext REQUIRED)
|
||||||
|
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
|
||||||
|
if(NOT GETTEXT_XGETTEXT_EXECUTABLE OR NOT GETTEXT_MSGFMT_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR "xgettext not found")
|
||||||
|
endif()
|
||||||
|
file(MAKE_DIRECTORY ${LCPATH})
|
||||||
|
file(MAKE_DIRECTORY ${LCPATH}/LC_MESSAGES)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${PO_FILE}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=utf-8 ${SOURCES} -c -k_ -kN_ -o ${PO_FILE}
|
||||||
|
COMMAND sed -i 's/charset=.*\\\\n/charset=koi8-r\\\\n/' ${PO_FILE}
|
||||||
|
COMMAND enconv ${PO_FILE}
|
||||||
|
DEPENDS ${SOURCES}
|
||||||
|
)
|
||||||
|
# we need this to prevent ru.po & .mo from deleting by make clean
|
||||||
|
add_custom_target(
|
||||||
|
RU_FILE
|
||||||
|
COMMAND [ -f ${RU_FILE} ] && ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} || cp ${PO_FILE} ${RU_FILE}
|
||||||
|
DEPENDS ${PO_FILE} ${SOURCES}
|
||||||
|
)
|
||||||
|
add_custom_target(
|
||||||
|
MO_FILE
|
||||||
|
COMMAND make RU_FILE && ${GETTEXT_MSGFMT_EXECUTABLE} ${RU_FILE} -o ${MO_FILE}
|
||||||
|
DEPENDS ${SOURCES}
|
||||||
|
)
|
||||||
|
add_dependencies(${PROJ} MO_FILE)
|
||||||
|
|
||||||
|
set(CFLAGS_A CFLAGS=${CFLAGS})
|
||||||
|
add_custom_target(ctags
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND CFLAGS=-DEBUG geany -g ${CTAGS_FILE} ${SOURCES}
|
||||||
|
DEPENDS ${SOURCES}
|
||||||
|
)
|
||||||
|
add_dependencies(${PROJ} ctags)
|
||||||
|
endif()
|
||||||
1
cmakelists_/get_proc_count
Normal file
1
cmakelists_/get_proc_count
Normal file
@ -0,0 +1 @@
|
|||||||
|
getconf _NPROCESSORS_ONLN
|
||||||
14
get_avail_mem.c
Normal file
14
get_avail_mem.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static unsigned long long get_available_mem(){
|
||||||
|
return sysconf(_SC_AVPHYS_PAGES) * (unsigned long long) sysconf(_SC_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
unsigned long long m = get_available_mem();
|
||||||
|
printf("MEM: %llu == %lluGB\n", m, m/1024/1024/1024);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never allocate memory by big pieces with malloc! Only mmap with MAP_POPULATE!!!!!!!!!11111111111
|
||||||
2
image_view_module/README
Normal file
2
image_view_module/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
GLUT -> GLFW
|
||||||
|
For GUI: look for analog of GLUI
|
||||||
@ -202,7 +202,7 @@ mmapbuf *My_mmap(char *filename){
|
|||||||
void My_munmap(mmapbuf *b){
|
void My_munmap(mmapbuf *b){
|
||||||
if(munmap(b->data, b->len)){
|
if(munmap(b->data, b->len)){
|
||||||
/// "îÅ ÍÏÇÕ munmap"
|
/// "îÅ ÍÏÇÕ munmap"
|
||||||
ERR(_("Can't munmap"));
|
WARN(_("Can't munmap"));
|
||||||
}
|
}
|
||||||
FREE(b);
|
FREE(b);
|
||||||
}
|
}
|
||||||
@ -291,8 +291,6 @@ void tty_init(char *comdev){
|
|||||||
DBG("\nOpen port...\n");
|
DBG("\nOpen port...\n");
|
||||||
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
|
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
|
||||||
WARN("Can't use port %s\n",comdev);
|
WARN("Can't use port %s\n",comdev);
|
||||||
ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
|
|
||||||
close(comfd);
|
|
||||||
signals(0); // quit?
|
signals(0); // quit?
|
||||||
}
|
}
|
||||||
DBG(" OK\nGet current settings... ");
|
DBG(" OK\nGet current settings... ");
|
||||||
|
|||||||
@ -56,6 +56,9 @@
|
|||||||
// unused arguments with -Wall -Werror
|
// unused arguments with -Wall -Werror
|
||||||
#define _U_ __attribute__((__unused__))
|
#define _U_ __attribute__((__unused__))
|
||||||
|
|
||||||
|
#define ASTRING(MACRO) #MACRO
|
||||||
|
#define STRING(MACRO) ASTRING(MACRO)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Coloured messages output
|
* Coloured messages output
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user